summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Macnak <natsu@google.com>2023-09-27 12:54:16 -0700
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2023-09-28 17:11:53 +0000
commitfe5c2c01714a5f328003a35e674304262c787ff4 (patch)
tree26b1467f525b85e1fc16a183068eadff761a10f4
parentbb30e856312fb239b5a6cb4c4ec77a578ca61c25 (diff)
downloadminigbm-fe5c2c01714a5f328003a35e674304262c787ff4.tar.gz
gralloc: Upstream AIDL allocator, stablec mapper, and sepolicy
... from various developments in AOSP. Bug: b/225198076 Test: n/a Change-Id: I65c340cfee4a3ad3c6545f365ca60249fd338a5f Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/minigbm/+/4897925 Reviewed-by: Yiwei Zhang <zzyiwei@chromium.org> Tested-by: Jason Macnak <natsu@google.com> Commit-Queue: Jason Macnak <natsu@google.com>
-rw-r--r--cros_gralloc/aidl/.clang-format19
-rw-r--r--cros_gralloc/aidl/Allocator.cpp242
-rw-r--r--cros_gralloc/aidl/Allocator.h57
-rw-r--r--cros_gralloc/aidl/Android.bp51
-rw-r--r--cros_gralloc/aidl/Main.cpp44
-rw-r--r--cros_gralloc/aidl/allocator.rc7
-rw-r--r--cros_gralloc/aidl/allocator.xml10
-rw-r--r--cros_gralloc/mapper_stablec/.clang-format19
-rw-r--r--cros_gralloc/mapper_stablec/Android.bp44
-rw-r--r--cros_gralloc/mapper_stablec/Mapper.cpp745
-rw-r--r--cros_gralloc/mapper_stablec/mapper.minigbm.xml9
-rw-r--r--cros_gralloc/sepolicy/cameraserver.te3
-rw-r--r--cros_gralloc/sepolicy/mediaswcodec.te3
-rw-r--r--cros_gralloc/sepolicy/system_server.te3
14 files changed, 1256 insertions, 0 deletions
diff --git a/cros_gralloc/aidl/.clang-format b/cros_gralloc/aidl/.clang-format
new file mode 100644
index 0000000..e5e7076
--- /dev/null
+++ b/cros_gralloc/aidl/.clang-format
@@ -0,0 +1,19 @@
+# Copyright 2022 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# This directory is formatted to match the format of the interfaces implemented.
+
+BasedOnStyle: Google
+Standard: Cpp11
+AccessModifierOffset: -2
+AllowShortFunctionsOnASingleLine: Inline
+ColumnLimit: 100
+CommentPragmas: NOLINT:.*
+DerivePointerAlignment: false
+IncludeBlocks: Preserve
+IndentWidth: 4
+ContinuationIndentWidth: 8
+PointerAlignment: Left
+TabWidth: 4
+UseTab: Never \ No newline at end of file
diff --git a/cros_gralloc/aidl/Allocator.cpp b/cros_gralloc/aidl/Allocator.cpp
new file mode 100644
index 0000000..2ea5a0d
--- /dev/null
+++ b/cros_gralloc/aidl/Allocator.cpp
@@ -0,0 +1,242 @@
+/*
+ * Copyright 2022 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Allocator.h"
+
+#include <aidl/android/hardware/graphics/allocator/AllocationError.h>
+#include <aidlcommonsupport/NativeHandle.h>
+#include <android-base/logging.h>
+#include <android/binder_ibinder_platform.h>
+#include <gralloctypes/Gralloc4.h>
+#include <log/log.h>
+
+#include "cros_gralloc/gralloc4/CrosGralloc4Utils.h"
+
+using aidl::android::hardware::common::NativeHandle;
+using BufferDescriptorInfoV4 =
+ android::hardware::graphics::mapper::V4_0::IMapper::BufferDescriptorInfo;
+
+namespace aidl::android::hardware::graphics::allocator::impl {
+namespace {
+
+inline ndk::ScopedAStatus ToBinderStatus(AllocationError error) {
+ return ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(error));
+}
+
+} // namespace
+
+bool Allocator::init() {
+ mDriver = cros_gralloc_driver::get_instance();
+ return mDriver != nullptr;
+}
+
+// TODO(natsu): deduplicate with CrosGralloc4Allocator after the T release.
+ndk::ScopedAStatus Allocator::initializeMetadata(
+ cros_gralloc_handle_t crosHandle,
+ const struct cros_gralloc_buffer_descriptor& crosDescriptor) {
+ if (!mDriver) {
+ ALOGE("Failed to initializeMetadata. Driver is uninitialized.\n");
+ return ToBinderStatus(AllocationError::NO_RESOURCES);
+ }
+
+ if (!crosHandle) {
+ ALOGE("Failed to initializeMetadata. Invalid handle.\n");
+ return ToBinderStatus(AllocationError::NO_RESOURCES);
+ }
+
+ void* addr;
+ uint64_t size;
+ int ret = mDriver->get_reserved_region(crosHandle, &addr, &size);
+ if (ret) {
+ ALOGE("Failed to getReservedRegion.\n");
+ return ToBinderStatus(AllocationError::NO_RESOURCES);
+ }
+
+ CrosGralloc4Metadata* crosMetadata = reinterpret_cast<CrosGralloc4Metadata*>(addr);
+
+ snprintf(crosMetadata->name, CROS_GRALLOC4_METADATA_MAX_NAME_SIZE, "%s",
+ crosDescriptor.name.c_str());
+ crosMetadata->dataspace = common::Dataspace::UNKNOWN;
+ crosMetadata->blendMode = common::BlendMode::INVALID;
+
+ return ndk::ScopedAStatus::ok();
+}
+
+void Allocator::releaseBufferAndHandle(native_handle_t* handle) {
+ mDriver->release(handle);
+ native_handle_close(handle);
+ native_handle_delete(handle);
+}
+
+ndk::ScopedAStatus Allocator::allocate(const std::vector<uint8_t>& descriptor, int32_t count,
+ allocator::AllocationResult* outResult) {
+ if (!mDriver) {
+ ALOGE("Failed to allocate. Driver is uninitialized.\n");
+ return ToBinderStatus(AllocationError::NO_RESOURCES);
+ }
+
+ BufferDescriptorInfoV4 description;
+
+ int ret = ::android::gralloc4::decodeBufferDescriptorInfo(descriptor, &description);
+ if (ret) {
+ ALOGE("Failed to allocate. Failed to decode buffer descriptor: %d.\n", ret);
+ return ToBinderStatus(AllocationError::BAD_DESCRIPTOR);
+ }
+
+ std::vector<native_handle_t*> handles;
+ handles.resize(count, nullptr);
+
+ for (int32_t i = 0; i < count; i++) {
+ ndk::ScopedAStatus status = allocate(description, &outResult->stride, &handles[i]);
+ if (!status.isOk()) {
+ for (int32_t j = 0; j < i; j++) {
+ releaseBufferAndHandle(handles[j]);
+ }
+ return status;
+ }
+ }
+
+ outResult->buffers.resize(count);
+ for (int32_t i = 0; i < count; i++) {
+ auto handle = handles[i];
+ outResult->buffers[i] = ::android::dupToAidl(handle);
+ releaseBufferAndHandle(handle);
+ }
+
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Allocator::allocate(const BufferDescriptorInfoV4& descriptor, int32_t* outStride,
+ native_handle_t** outHandle) {
+ if (!mDriver) {
+ ALOGE("Failed to allocate. Driver is uninitialized.\n");
+ return ToBinderStatus(AllocationError::NO_RESOURCES);
+ }
+
+ struct cros_gralloc_buffer_descriptor crosDescriptor;
+ if (convertToCrosDescriptor(descriptor, &crosDescriptor)) {
+ return ToBinderStatus(AllocationError::UNSUPPORTED);
+ }
+
+ crosDescriptor.reserved_region_size += sizeof(CrosGralloc4Metadata);
+
+ if (!mDriver->is_supported(&crosDescriptor)) {
+ const std::string drmFormatString = get_drm_format_string(crosDescriptor.drm_format);
+ const std::string pixelFormatString = getPixelFormatString(descriptor.format);
+ const std::string usageString = getUsageString(descriptor.usage);
+ ALOGE("Failed to allocate. Unsupported combination: pixel format:%s, drm format:%s, "
+ "usage:%s\n",
+ pixelFormatString.c_str(), drmFormatString.c_str(), usageString.c_str());
+ return ToBinderStatus(AllocationError::UNSUPPORTED);
+ }
+
+ native_handle_t* handle;
+ int ret = mDriver->allocate(&crosDescriptor, &handle);
+ if (ret) {
+ return ToBinderStatus(AllocationError::NO_RESOURCES);
+ }
+
+ cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(handle);
+
+ auto status = initializeMetadata(crosHandle, crosDescriptor);
+ if (!status.isOk()) {
+ ALOGE("Failed to allocate. Failed to initialize gralloc buffer metadata.");
+ releaseBufferAndHandle(handle);
+ return status;
+ }
+
+ *outStride = static_cast<int32_t>(crosHandle->pixel_stride);
+ *outHandle = handle;
+
+ return ndk::ScopedAStatus::ok();
+}
+
+static BufferDescriptorInfoV4 convertAidlToIMapperV4Descriptor(const BufferDescriptorInfo& info) {
+ return BufferDescriptorInfoV4 {
+ .name{reinterpret_cast<const char*>(info.name.data())},
+ .width = static_cast<uint32_t>(info.width),
+ .height = static_cast<uint32_t>(info.height),
+ .layerCount = static_cast<uint32_t>(info.layerCount),
+ .format = static_cast<::android::hardware::graphics::common::V1_2::PixelFormat>(info.format),
+ .usage = static_cast<uint64_t>(info.usage),
+ .reservedSize = 0,
+ };
+}
+
+ndk::ScopedAStatus Allocator::allocate2(const BufferDescriptorInfo& descriptor, int32_t count,
+ allocator::AllocationResult* outResult) {
+ if (!mDriver) {
+ ALOGE("Failed to allocate. Driver is uninitialized.\n");
+ return ToBinderStatus(AllocationError::NO_RESOURCES);
+ }
+
+ if (!descriptor.additionalOptions.empty()) {
+ return ToBinderStatus(AllocationError::UNSUPPORTED);
+ }
+
+ BufferDescriptorInfoV4 descriptionV4 = convertAidlToIMapperV4Descriptor(descriptor);
+
+ std::vector<native_handle_t*> handles;
+ handles.resize(count, nullptr);
+
+ for (int32_t i = 0; i < count; i++) {
+ ndk::ScopedAStatus status = allocate(descriptionV4, &outResult->stride, &handles[i]);
+ if (!status.isOk()) {
+ for (int32_t j = 0; j < i; j++) {
+ releaseBufferAndHandle(handles[j]);
+ }
+ return status;
+ }
+ }
+
+ outResult->buffers.resize(count);
+ for (int32_t i = 0; i < count; i++) {
+ auto handle = handles[i];
+ outResult->buffers[i] = ::android::dupToAidl(handle);
+ releaseBufferAndHandle(handle);
+ }
+
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Allocator::isSupported(const BufferDescriptorInfo& descriptor,
+ bool* outResult) {
+ if (!mDriver) {
+ ALOGE("Failed to allocate. Driver is uninitialized.\n");
+ return ToBinderStatus(AllocationError::NO_RESOURCES);
+ }
+
+ if (!descriptor.additionalOptions.empty()) {
+ *outResult = false;
+ return ndk::ScopedAStatus::ok();
+ }
+
+ struct cros_gralloc_buffer_descriptor crosDescriptor;
+ if (convertToCrosDescriptor(convertAidlToIMapperV4Descriptor(descriptor), &crosDescriptor)) {
+ // Failing to convert the descriptor means the layer count, pixel format, or usage is
+ // unsupported, thus isSupported() = false
+ *outResult = false;
+ return ndk::ScopedAStatus::ok();
+ }
+
+ crosDescriptor.reserved_region_size += sizeof(CrosGralloc4Metadata);
+
+ *outResult = mDriver->is_supported(&crosDescriptor);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Allocator::getIMapperLibrarySuffix(std::string* outResult) {
+ *outResult = "minigbm";
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::SpAIBinder Allocator::createBinder() {
+ auto binder = BnAllocator::createBinder();
+ AIBinder_setInheritRt(binder.get(), true);
+ return binder;
+}
+
+} // namespace aidl::android::hardware::graphics::allocator::impl \ No newline at end of file
diff --git a/cros_gralloc/aidl/Allocator.h b/cros_gralloc/aidl/Allocator.h
new file mode 100644
index 0000000..5c12308
--- /dev/null
+++ b/cros_gralloc/aidl/Allocator.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2022 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef MINIGBM_CROSGRALLOC_AIDL_ALLOCATOR_H_
+#define MINIGBM_CROSGRALLOC_AIDL_ALLOCATOR_H_
+
+#include <aidl/android/hardware/graphics/allocator/AllocationResult.h>
+#include <aidl/android/hardware/graphics/allocator/BnAllocator.h>
+#include <android/hardware/graphics/mapper/4.0/IMapper.h>
+
+#include "cros_gralloc/cros_gralloc_driver.h"
+#include "cros_gralloc/cros_gralloc_helpers.h"
+#include "cros_gralloc/gralloc4/CrosGralloc4Metadata.h"
+
+namespace aidl::android::hardware::graphics::allocator::impl {
+
+class Allocator : public BnAllocator {
+ public:
+ Allocator() = default;
+
+ bool init();
+
+ ndk::ScopedAStatus allocate(const std::vector<uint8_t>& descriptor, int32_t count,
+ allocator::AllocationResult* outResult) override;
+
+ ndk::ScopedAStatus allocate2(const BufferDescriptorInfo& descriptor, int32_t count,
+ allocator::AllocationResult* outResult) override;
+
+ ndk::ScopedAStatus isSupported(const BufferDescriptorInfo& descriptor,
+ bool* outResult) override;
+
+ ndk::ScopedAStatus getIMapperLibrarySuffix(std::string* outResult) override;
+
+ protected:
+ ndk::SpAIBinder createBinder() override;
+
+ private:
+ ndk::ScopedAStatus allocate(
+ const ::android::hardware::graphics::mapper::V4_0::IMapper::BufferDescriptorInfo&
+ descriptor,
+ int32_t* outStride, native_handle_t** outHandle);
+
+ ndk::ScopedAStatus initializeMetadata(
+ cros_gralloc_handle_t crosHandle,
+ const struct cros_gralloc_buffer_descriptor& crosDescriptor);
+
+ void releaseBufferAndHandle(native_handle_t* handle);
+
+ cros_gralloc_driver* mDriver = nullptr;
+};
+
+} // namespace aidl::android::hardware::graphics::allocator::impl
+
+#endif \ No newline at end of file
diff --git a/cros_gralloc/aidl/Android.bp b/cros_gralloc/aidl/Android.bp
new file mode 100644
index 0000000..da8f670
--- /dev/null
+++ b/cros_gralloc/aidl/Android.bp
@@ -0,0 +1,51 @@
+//
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "external_minigbm_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-BSD
+ default_applicable_licenses: ["external_minigbm_license"],
+}
+
+cc_binary {
+ name: "android.hardware.graphics.allocator-service.minigbm",
+ defaults: ["minigbm_cros_gralloc_defaults"],
+ relative_install_path: "hw",
+ init_rc: ["allocator.rc"],
+ vintf_fragments: ["allocator.xml"],
+ vendor: true,
+ shared_libs: [
+ "android.hardware.graphics.allocator-V2-ndk",
+ "android.hardware.graphics.mapper@4.0",
+ "libbase",
+ "libbinder_ndk",
+ "libgralloctypes",
+ "libhidlbase",
+ "liblog",
+ "libminigbm_gralloc",
+ "libminigbm_gralloc4_utils",
+ ],
+ static_libs: [
+ "libaidlcommonsupport",
+ ],
+ srcs: [
+ "Allocator.cpp",
+ "Main.cpp",
+ ],
+}
diff --git a/cros_gralloc/aidl/Main.cpp b/cros_gralloc/aidl/Main.cpp
new file mode 100644
index 0000000..c2c4c5c
--- /dev/null
+++ b/cros_gralloc/aidl/Main.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2022 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Allocator.h"
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <log/log.h>
+
+using aidl::android::hardware::graphics::allocator::impl::Allocator;
+
+int main(int /*argc*/, char** /*argv*/) {
+ ALOGI("Minigbm AIDL allocator starting up...");
+
+ // same as SF main thread
+ struct sched_param param = {0};
+ param.sched_priority = 2;
+ if (sched_setscheduler(0, SCHED_FIFO | SCHED_RESET_ON_FORK, &param) != 0) {
+ ALOGI("%s: failed to set priority: %s", __FUNCTION__, strerror(errno));
+ }
+
+ auto allocator = ndk::SharedRefBase::make<Allocator>();
+ CHECK(allocator != nullptr);
+
+ if (!allocator->init()) {
+ ALOGE("Failed to initialize Minigbm AIDL allocator.");
+ return EXIT_FAILURE;
+ }
+
+ const std::string instance = std::string() + Allocator::descriptor + "/default";
+ binder_status_t status =
+ AServiceManager_addService(allocator->asBinder().get(), instance.c_str());
+ CHECK_EQ(status, STATUS_OK);
+
+ ABinderProcess_setThreadPoolMaxThreadCount(4);
+ ABinderProcess_startThreadPool();
+ ABinderProcess_joinThreadPool();
+
+ return EXIT_FAILURE;
+} \ No newline at end of file
diff --git a/cros_gralloc/aidl/allocator.rc b/cros_gralloc/aidl/allocator.rc
new file mode 100644
index 0000000..24a7c45
--- /dev/null
+++ b/cros_gralloc/aidl/allocator.rc
@@ -0,0 +1,7 @@
+service vendor.graphics.allocator /vendor/bin/hw/android.hardware.graphics.allocator-service.minigbm
+ class hal animation
+ user system
+ group graphics drmrpc
+ capabilities SYS_NICE
+ onrestart restart surfaceflinger
+ task_profiles ServiceCapacityLow \ No newline at end of file
diff --git a/cros_gralloc/aidl/allocator.xml b/cros_gralloc/aidl/allocator.xml
new file mode 100644
index 0000000..4d375b3
--- /dev/null
+++ b/cros_gralloc/aidl/allocator.xml
@@ -0,0 +1,10 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.graphics.allocator</name>
+ <version>2</version>
+ <interface>
+ <name>IAllocator</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+</manifest> \ No newline at end of file
diff --git a/cros_gralloc/mapper_stablec/.clang-format b/cros_gralloc/mapper_stablec/.clang-format
new file mode 100644
index 0000000..e5e7076
--- /dev/null
+++ b/cros_gralloc/mapper_stablec/.clang-format
@@ -0,0 +1,19 @@
+# Copyright 2022 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# This directory is formatted to match the format of the interfaces implemented.
+
+BasedOnStyle: Google
+Standard: Cpp11
+AccessModifierOffset: -2
+AllowShortFunctionsOnASingleLine: Inline
+ColumnLimit: 100
+CommentPragmas: NOLINT:.*
+DerivePointerAlignment: false
+IncludeBlocks: Preserve
+IndentWidth: 4
+ContinuationIndentWidth: 8
+PointerAlignment: Left
+TabWidth: 4
+UseTab: Never \ No newline at end of file
diff --git a/cros_gralloc/mapper_stablec/Android.bp b/cros_gralloc/mapper_stablec/Android.bp
new file mode 100644
index 0000000..b25be17
--- /dev/null
+++ b/cros_gralloc/mapper_stablec/Android.bp
@@ -0,0 +1,44 @@
+//
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "external_minigbm_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-BSD
+ default_applicable_licenses: ["external_minigbm_license"],
+}
+
+cc_library_shared {
+ name: "mapper.minigbm",
+ defaults: ["minigbm_gralloc4_common_defaults"],
+ vintf_fragments: ["mapper.minigbm.xml"],
+ shared_libs: [
+ "android.hardware.graphics.allocator-V2-ndk",
+ "libminigbm_gralloc",
+ ],
+ header_libs: [
+ "libbase_headers",
+ "libimapper_stablec",
+ "libimapper_providerutils",
+ ],
+ srcs: [
+ ":minigbm_gralloc4_mapper_files",
+ "Mapper.cpp",
+ ],
+ cpp_std: "c++20",
+}
diff --git a/cros_gralloc/mapper_stablec/Mapper.cpp b/cros_gralloc/mapper_stablec/Mapper.cpp
new file mode 100644
index 0000000..6c4ac86
--- /dev/null
+++ b/cros_gralloc/mapper_stablec/Mapper.cpp
@@ -0,0 +1,745 @@
+/*
+ * Copyright 2022 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <aidl/android/hardware/graphics/allocator/BufferDescriptorInfo.h>
+#include <aidl/android/hardware/graphics/common/BufferUsage.h>
+#include <aidl/android/hardware/graphics/common/PixelFormat.h>
+#include <aidl/android/hardware/graphics/common/StandardMetadataType.h>
+#include <android-base/unique_fd.h>
+#include <android/hardware/graphics/mapper/IMapper.h>
+#include <android/hardware/graphics/mapper/utils/IMapperMetadataTypes.h>
+#include <android/hardware/graphics/mapper/utils/IMapperProvider.h>
+#include <cutils/native_handle.h>
+#include <gralloctypes/Gralloc4.h>
+
+#include "cros_gralloc/cros_gralloc_driver.h"
+#include "cros_gralloc/cros_gralloc_handle.h"
+#include "cros_gralloc/gralloc4/CrosGralloc4Metadata.h"
+#include "cros_gralloc/gralloc4/CrosGralloc4Utils.h"
+
+using namespace ::aidl::android::hardware::graphics::common;
+using namespace ::android::hardware::graphics::mapper;
+using ::aidl::android::hardware::graphics::allocator::BufferDescriptorInfo;
+using ::android::base::unique_fd;
+
+#define REQUIRE_DRIVER() \
+ if (!mDriver) { \
+ ALOGE("Failed to %s. Driver is uninitialized.", __func__); \
+ return AIMAPPER_ERROR_NO_RESOURCES; \
+ }
+
+#define VALIDATE_BUFFER_HANDLE(bufferHandle) \
+ if (!(bufferHandle)) { \
+ ALOGE("Failed to %s. Null buffer_handle_t.", __func__); \
+ return AIMAPPER_ERROR_BAD_BUFFER; \
+ }
+
+#define VALIDATE_DRIVER_AND_BUFFER_HANDLE(bufferHandle) \
+ REQUIRE_DRIVER() \
+ VALIDATE_BUFFER_HANDLE(bufferHandle)
+
+static_assert(CROS_GRALLOC4_METADATA_MAX_NAME_SIZE >=
+ decltype(std::declval<BufferDescriptorInfo>().name){}.size(),
+ "Metadata name storage too small to fit a BufferDescriptorInfo::name");
+
+constexpr const char* STANDARD_METADATA_NAME =
+ "android.hardware.graphics.common.StandardMetadataType";
+
+static bool isStandardMetadata(AIMapper_MetadataType metadataType) {
+ return strcmp(STANDARD_METADATA_NAME, metadataType.name) == 0;
+}
+
+class CrosGrallocMapperV5 final : public vendor::mapper::IMapperV5Impl {
+ private:
+ cros_gralloc_driver* mDriver = cros_gralloc_driver::get_instance();
+
+ public:
+ explicit CrosGrallocMapperV5() = default;
+ ~CrosGrallocMapperV5() override = default;
+
+ AIMapper_Error importBuffer(const native_handle_t* _Nonnull handle,
+ buffer_handle_t _Nullable* _Nonnull outBufferHandle) override;
+
+ AIMapper_Error freeBuffer(buffer_handle_t _Nonnull buffer) override;
+
+ AIMapper_Error getTransportSize(buffer_handle_t _Nonnull buffer, uint32_t* _Nonnull outNumFds,
+ uint32_t* _Nonnull outNumInts) override;
+
+ AIMapper_Error lock(buffer_handle_t _Nonnull buffer, uint64_t cpuUsage, ARect accessRegion,
+ int acquireFence, void* _Nullable* _Nonnull outData) override;
+
+ AIMapper_Error unlock(buffer_handle_t _Nonnull buffer, int* _Nonnull releaseFence) override;
+
+ AIMapper_Error flushLockedBuffer(buffer_handle_t _Nonnull buffer) override;
+
+ AIMapper_Error rereadLockedBuffer(buffer_handle_t _Nonnull buffer) override;
+
+ int32_t getMetadata(buffer_handle_t _Nonnull buffer, AIMapper_MetadataType metadataType,
+ void* _Nonnull outData, size_t outDataSize) override;
+
+ int32_t getStandardMetadata(buffer_handle_t _Nonnull buffer, int64_t standardMetadataType,
+ void* _Nonnull outData, size_t outDataSize) override;
+
+ AIMapper_Error setMetadata(buffer_handle_t _Nonnull buffer, AIMapper_MetadataType metadataType,
+ const void* _Nonnull metadata, size_t metadataSize) override;
+
+ AIMapper_Error setStandardMetadata(buffer_handle_t _Nonnull buffer,
+ int64_t standardMetadataType, const void* _Nonnull metadata,
+ size_t metadataSize) override;
+
+ AIMapper_Error listSupportedMetadataTypes(
+ const AIMapper_MetadataTypeDescription* _Nullable* _Nonnull outDescriptionList,
+ size_t* _Nonnull outNumberOfDescriptions) override;
+
+ AIMapper_Error dumpBuffer(buffer_handle_t _Nonnull bufferHandle,
+ AIMapper_DumpBufferCallback _Nonnull dumpBufferCallback,
+ void* _Null_unspecified context) override;
+
+ AIMapper_Error dumpAllBuffers(AIMapper_BeginDumpBufferCallback _Nonnull beginDumpBufferCallback,
+ AIMapper_DumpBufferCallback _Nonnull dumpBufferCallback,
+ void* _Null_unspecified context) override;
+
+ AIMapper_Error getReservedRegion(buffer_handle_t _Nonnull buffer,
+ void* _Nullable* _Nonnull outReservedRegion,
+ uint64_t* _Nonnull outReservedSize) override;
+
+ private:
+ enum class ReservedRegionArea {
+ /* CrosGralloc4Metadata */
+ MAPPER4_METADATA,
+
+ /* External user metadata */
+ USER_METADATA,
+ };
+
+ AIMapper_Error getReservedRegionArea(const cros_gralloc_buffer* crosBuffer,
+ ReservedRegionArea area, void** outAddr,
+ uint64_t* outSize);
+
+ AIMapper_Error getCrosMetadata(const cros_gralloc_buffer* crosBuffer,
+ const CrosGralloc4Metadata** outMetadata);
+
+ AIMapper_Error getMutableCrosMetadata(cros_gralloc_buffer* crosBuffer,
+ CrosGralloc4Metadata** outMetadata);
+
+ template <typename F, StandardMetadataType TYPE>
+ int32_t getStandardMetadata(const cros_gralloc_buffer* crosBuffer, F&& provide,
+ StandardMetadata<TYPE>);
+
+ template <StandardMetadataType TYPE>
+ AIMapper_Error setStandardMetadata(CrosGralloc4Metadata* crosMetadata,
+ typename StandardMetadata<TYPE>::value_type&& value);
+
+ void dumpBuffer(
+ const cros_gralloc_buffer* crosBuffer,
+ std::function<void(AIMapper_MetadataType, const std::vector<uint8_t>&)> callback);
+};
+
+AIMapper_Error CrosGrallocMapperV5::importBuffer(
+ const native_handle_t* _Nonnull bufferHandle,
+ buffer_handle_t _Nullable* _Nonnull outBufferHandle) {
+ REQUIRE_DRIVER()
+
+ if (!bufferHandle || bufferHandle->numFds == 0) {
+ ALOGE("Failed to importBuffer. Bad handle.");
+ return AIMAPPER_ERROR_BAD_BUFFER;
+ }
+
+ native_handle_t* importedBufferHandle = native_handle_clone(bufferHandle);
+ if (!importedBufferHandle) {
+ ALOGE("Failed to importBuffer. Handle clone failed: %s.", strerror(errno));
+ return AIMAPPER_ERROR_NO_RESOURCES;
+ }
+
+ int ret = mDriver->retain(importedBufferHandle);
+ if (ret) {
+ native_handle_close(importedBufferHandle);
+ native_handle_delete(importedBufferHandle);
+ return AIMAPPER_ERROR_NO_RESOURCES;
+ }
+
+ *outBufferHandle = importedBufferHandle;
+ return AIMAPPER_ERROR_NONE;
+}
+
+AIMapper_Error CrosGrallocMapperV5::freeBuffer(buffer_handle_t _Nonnull buffer) {
+ VALIDATE_DRIVER_AND_BUFFER_HANDLE(buffer)
+
+ int ret = mDriver->release(buffer);
+ if (ret) {
+ return AIMAPPER_ERROR_BAD_BUFFER;
+ }
+
+ native_handle_close(buffer);
+ native_handle_delete(const_cast<native_handle_t*>(buffer));
+ return AIMAPPER_ERROR_NONE;
+}
+
+AIMapper_Error CrosGrallocMapperV5::getTransportSize(buffer_handle_t _Nonnull bufferHandle,
+ uint32_t* _Nonnull outNumFds,
+ uint32_t* _Nonnull outNumInts) {
+ VALIDATE_DRIVER_AND_BUFFER_HANDLE(bufferHandle)
+
+ // No local process data is currently stored on the native handle.
+ *outNumFds = bufferHandle->numFds;
+ *outNumInts = bufferHandle->numInts;
+ return AIMAPPER_ERROR_NONE;
+}
+
+AIMapper_Error CrosGrallocMapperV5::lock(buffer_handle_t _Nonnull bufferHandle, uint64_t cpuUsage,
+ ARect region, int acquireFenceRawFd,
+ void* _Nullable* _Nonnull outData) {
+ // We take ownership of the FD in all cases, even for errors
+ unique_fd acquireFence(acquireFenceRawFd);
+ VALIDATE_DRIVER_AND_BUFFER_HANDLE(bufferHandle)
+ if (cpuUsage == 0) {
+ ALOGE("Failed to lock. Bad cpu usage: %" PRIu64 ".", cpuUsage);
+ return AIMAPPER_ERROR_BAD_VALUE;
+ }
+
+ uint32_t mapUsage = cros_gralloc_convert_map_usage(cpuUsage);
+
+ cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(bufferHandle);
+ if (crosHandle == nullptr) {
+ ALOGE("Failed to lock. Invalid handle.");
+ return AIMAPPER_ERROR_BAD_VALUE;
+ }
+
+ struct rectangle rect;
+
+ // An access region of all zeros means the entire buffer.
+ if (region.left == 0 && region.top == 0 && region.right == 0 && region.bottom == 0) {
+ rect = {0, 0, crosHandle->width, crosHandle->height};
+ } else {
+ if (region.left < 0 || region.top < 0 || region.right <= region.left ||
+ region.bottom <= region.top) {
+ ALOGE("Failed to lock. Invalid accessRegion: [%d, %d, %d, %d]", region.left, region.top,
+ region.right, region.bottom);
+ return AIMAPPER_ERROR_BAD_VALUE;
+ }
+
+ if (region.right > crosHandle->width) {
+ ALOGE("Failed to lock. Invalid region: width greater than buffer width (%d vs %d).",
+ region.right, crosHandle->width);
+ return AIMAPPER_ERROR_BAD_VALUE;
+ }
+
+ if (region.bottom > crosHandle->height) {
+ ALOGE("Failed to lock. Invalid region: height greater than buffer height (%d vs "
+ "%d).",
+ region.bottom, crosHandle->height);
+ return AIMAPPER_ERROR_BAD_VALUE;
+ }
+
+ rect = {static_cast<uint32_t>(region.left), static_cast<uint32_t>(region.top),
+ static_cast<uint32_t>(region.right - region.left),
+ static_cast<uint32_t>(region.bottom - region.top)};
+ }
+
+ uint8_t* addr[DRV_MAX_PLANES];
+ int32_t status = mDriver->lock(bufferHandle, acquireFence.get(),
+ /*close_acquire_fence=*/false, &rect, mapUsage, addr);
+ if (status) {
+ return AIMAPPER_ERROR_BAD_VALUE;
+ }
+
+ *outData = addr[0];
+ return AIMAPPER_ERROR_NONE;
+}
+
+AIMapper_Error CrosGrallocMapperV5::unlock(buffer_handle_t _Nonnull buffer,
+ int* _Nonnull releaseFence) {
+ VALIDATE_DRIVER_AND_BUFFER_HANDLE(buffer)
+ int ret = mDriver->unlock(buffer, releaseFence);
+ if (ret) {
+ ALOGE("Failed to unlock.");
+ return AIMAPPER_ERROR_BAD_BUFFER;
+ }
+ return AIMAPPER_ERROR_NONE;
+}
+
+AIMapper_Error CrosGrallocMapperV5::flushLockedBuffer(buffer_handle_t _Nonnull buffer) {
+ VALIDATE_DRIVER_AND_BUFFER_HANDLE(buffer)
+ int ret = mDriver->flush(buffer);
+ if (ret) {
+ ALOGE("Failed to flushLockedBuffer. Flush failed.");
+ return AIMAPPER_ERROR_BAD_BUFFER;
+ }
+ return AIMAPPER_ERROR_NONE;
+}
+
+AIMapper_Error CrosGrallocMapperV5::rereadLockedBuffer(buffer_handle_t _Nonnull buffer) {
+ VALIDATE_DRIVER_AND_BUFFER_HANDLE(buffer)
+ int ret = mDriver->invalidate(buffer);
+ if (ret) {
+ ALOGE("Failed to rereadLockedBuffer. Failed to invalidate.");
+ return AIMAPPER_ERROR_BAD_BUFFER;
+ }
+
+ return AIMAPPER_ERROR_NONE;
+}
+
+int32_t CrosGrallocMapperV5::getMetadata(buffer_handle_t _Nonnull buffer,
+ AIMapper_MetadataType metadataType, void* _Nonnull outData,
+ size_t outDataSize) {
+ // We don't have any vendor-specific metadata, so divert to getStandardMetadata after validating
+ // that this is a standard metadata request
+ if (isStandardMetadata(metadataType)) {
+ return getStandardMetadata(buffer, metadataType.value, outData, outDataSize);
+ }
+ return -AIMAPPER_ERROR_UNSUPPORTED;
+}
+
+int32_t CrosGrallocMapperV5::getStandardMetadata(buffer_handle_t _Nonnull bufferHandle,
+ int64_t standardType, void* _Nonnull outData,
+ size_t outDataSize) {
+ // Can't use VALIDATE_DRIVER_AND_BUFFER_HANDLE because we need to negate the error
+ // for this call
+ if (!mDriver) {
+ ALOGE("Failed to %s. Driver is uninitialized.", __func__);
+ return -AIMAPPER_ERROR_NO_RESOURCES;
+ }
+ if (!(bufferHandle)) {
+ ALOGE("Failed to %s. Null buffer_handle_t.", __func__);
+ return -AIMAPPER_ERROR_BAD_BUFFER;
+ }
+
+ cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(bufferHandle);
+ if (!crosHandle) {
+ ALOGE("Failed to get. Invalid handle.");
+ return -AIMAPPER_ERROR_BAD_BUFFER;
+ }
+
+ int32_t retValue = -AIMAPPER_ERROR_UNSUPPORTED;
+ mDriver->with_buffer(crosHandle, [&](cros_gralloc_buffer* crosBuffer) {
+ auto provider = [&]<StandardMetadataType T>(auto&& provide) -> int32_t {
+ return getStandardMetadata(crosBuffer, provide, StandardMetadata<T>{});
+ };
+ retValue = provideStandardMetadata(static_cast<StandardMetadataType>(standardType), outData,
+ outDataSize, provider);
+ });
+ return retValue;
+}
+
+template <typename F, StandardMetadataType metadataType>
+int32_t CrosGrallocMapperV5::getStandardMetadata(const cros_gralloc_buffer* crosBuffer, F&& provide,
+ StandardMetadata<metadataType>) {
+ const CrosGralloc4Metadata* crosMetadata = nullptr;
+ if constexpr (metadataType == StandardMetadataType::BLEND_MODE ||
+ metadataType == StandardMetadataType::CTA861_3 ||
+ metadataType == StandardMetadataType::DATASPACE ||
+ metadataType == StandardMetadataType::NAME ||
+ metadataType == StandardMetadataType::SMPTE2086) {
+ AIMapper_Error error = getCrosMetadata(crosBuffer, &crosMetadata);
+ if (error != AIMAPPER_ERROR_NONE) {
+ ALOGE("Failed to get. Failed to get buffer metadata.");
+ return -AIMAPPER_ERROR_NO_RESOURCES;
+ }
+ }
+ if constexpr (metadataType == StandardMetadataType::BUFFER_ID) {
+ return provide(crosBuffer->get_id());
+ }
+ if constexpr (metadataType == StandardMetadataType::NAME) {
+ return provide(crosMetadata->name);
+ }
+ if constexpr (metadataType == StandardMetadataType::WIDTH) {
+ return provide(crosBuffer->get_width());
+ }
+ if constexpr (metadataType == StandardMetadataType::STRIDE) {
+ return provide(crosBuffer->get_pixel_stride());
+ }
+ if constexpr (metadataType == StandardMetadataType::HEIGHT) {
+ return provide(crosBuffer->get_height());
+ }
+ if constexpr (metadataType == StandardMetadataType::LAYER_COUNT) {
+ return provide(1);
+ }
+ if constexpr (metadataType == StandardMetadataType::PIXEL_FORMAT_REQUESTED) {
+ return provide(static_cast<PixelFormat>(crosBuffer->get_android_format()));
+ }
+ if constexpr (metadataType == StandardMetadataType::PIXEL_FORMAT_FOURCC) {
+ return provide(drv_get_standard_fourcc(crosBuffer->get_format()));
+ }
+ if constexpr (metadataType == StandardMetadataType::PIXEL_FORMAT_MODIFIER) {
+ return provide(crosBuffer->get_format_modifier());
+ }
+ if constexpr (metadataType == StandardMetadataType::USAGE) {
+ return provide(static_cast<BufferUsage>(crosBuffer->get_android_usage()));
+ }
+ if constexpr (metadataType == StandardMetadataType::ALLOCATION_SIZE) {
+ return provide(crosBuffer->get_total_size());
+ }
+ if constexpr (metadataType == StandardMetadataType::PROTECTED_CONTENT) {
+ uint64_t hasProtectedContent =
+ crosBuffer->get_android_usage() & static_cast<int64_t>(BufferUsage::PROTECTED) ? 1
+ : 0;
+ return provide(hasProtectedContent);
+ }
+ if constexpr (metadataType == StandardMetadataType::COMPRESSION) {
+ return provide(android::gralloc4::Compression_None);
+ }
+ if constexpr (metadataType == StandardMetadataType::INTERLACED) {
+ return provide(android::gralloc4::Interlaced_None);
+ }
+ if constexpr (metadataType == StandardMetadataType::CHROMA_SITING) {
+ return provide(android::gralloc4::ChromaSiting_None);
+ }
+ if constexpr (metadataType == StandardMetadataType::PLANE_LAYOUTS) {
+ std::vector<PlaneLayout> planeLayouts;
+ getPlaneLayouts(crosBuffer->get_format(), &planeLayouts);
+
+ for (size_t plane = 0; plane < planeLayouts.size(); plane++) {
+ PlaneLayout& planeLayout = planeLayouts[plane];
+ planeLayout.offsetInBytes = crosBuffer->get_plane_offset(plane);
+ planeLayout.strideInBytes = crosBuffer->get_plane_stride(plane);
+ planeLayout.totalSizeInBytes = crosBuffer->get_plane_size(plane);
+ planeLayout.widthInSamples =
+ crosBuffer->get_width() / planeLayout.horizontalSubsampling;
+ planeLayout.heightInSamples =
+ crosBuffer->get_height() / planeLayout.verticalSubsampling;
+ }
+
+ return provide(planeLayouts);
+ }
+ if constexpr (metadataType == StandardMetadataType::CROP) {
+ const uint32_t numPlanes = crosBuffer->get_num_planes();
+ const uint32_t w = crosBuffer->get_width();
+ const uint32_t h = crosBuffer->get_height();
+ std::vector<aidl::android::hardware::graphics::common::Rect> crops;
+ for (uint32_t plane = 0; plane < numPlanes; plane++) {
+ aidl::android::hardware::graphics::common::Rect crop;
+ crop.left = 0;
+ crop.top = 0;
+ crop.right = w;
+ crop.bottom = h;
+ crops.push_back(crop);
+ }
+
+ return provide(crops);
+ }
+ if constexpr (metadataType == StandardMetadataType::DATASPACE) {
+ return provide(crosMetadata->dataspace);
+ }
+ if constexpr (metadataType == StandardMetadataType::BLEND_MODE) {
+ return provide(crosMetadata->blendMode);
+ }
+ if constexpr (metadataType == StandardMetadataType::SMPTE2086) {
+ return crosMetadata->smpte2086 ? provide(*crosMetadata->smpte2086) : 0;
+ }
+ if constexpr (metadataType == StandardMetadataType::CTA861_3) {
+ return crosMetadata->cta861_3 ? provide(*crosMetadata->cta861_3) : 0;
+ }
+ return -AIMAPPER_ERROR_UNSUPPORTED;
+}
+
+AIMapper_Error CrosGrallocMapperV5::setMetadata(buffer_handle_t _Nonnull buffer,
+ AIMapper_MetadataType metadataType,
+ const void* _Nonnull metadata,
+ size_t metadataSize) {
+ // We don't have any vendor-specific metadata, so divert to setStandardMetadata after validating
+ // that this is a standard metadata request
+ if (isStandardMetadata(metadataType)) {
+ return setStandardMetadata(buffer, metadataType.value, metadata, metadataSize);
+ }
+ return AIMAPPER_ERROR_UNSUPPORTED;
+}
+
+AIMapper_Error CrosGrallocMapperV5::setStandardMetadata(buffer_handle_t _Nonnull bufferHandle,
+ int64_t standardTypeRaw,
+ const void* _Nonnull metadata,
+ size_t metadataSize) {
+ VALIDATE_DRIVER_AND_BUFFER_HANDLE(bufferHandle)
+
+ cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(bufferHandle);
+ if (!crosHandle) {
+ ALOGE("Failed to get. Invalid handle.");
+ return AIMAPPER_ERROR_BAD_BUFFER;
+ }
+
+ auto standardType = static_cast<StandardMetadataType>(standardTypeRaw);
+
+ switch (standardType) {
+ // Read-only values
+ case StandardMetadataType::BUFFER_ID:
+ case StandardMetadataType::NAME:
+ case StandardMetadataType::WIDTH:
+ case StandardMetadataType::HEIGHT:
+ case StandardMetadataType::LAYER_COUNT:
+ case StandardMetadataType::PIXEL_FORMAT_REQUESTED:
+ case StandardMetadataType::USAGE:
+ return AIMAPPER_ERROR_BAD_VALUE;
+
+ // Supported to set
+ case StandardMetadataType::BLEND_MODE:
+ case StandardMetadataType::CTA861_3:
+ case StandardMetadataType::DATASPACE:
+ case StandardMetadataType::SMPTE2086:
+ break;
+
+ // Everything else unsupported
+ default:
+ return AIMAPPER_ERROR_UNSUPPORTED;
+ }
+
+ AIMapper_Error status = AIMAPPER_ERROR_UNSUPPORTED;
+ mDriver->with_buffer(crosHandle, [&](cros_gralloc_buffer* crosBuffer) {
+ CrosGralloc4Metadata* crosMetadata = nullptr;
+ status = getMutableCrosMetadata(crosBuffer, &crosMetadata);
+ if (status != AIMAPPER_ERROR_NONE) {
+ return;
+ }
+
+ auto applier = [&]<StandardMetadataType T>(auto&& value) -> AIMapper_Error {
+ return setStandardMetadata<T>(crosMetadata, std::forward<decltype(value)>(value));
+ };
+
+ status = applyStandardMetadata(standardType, metadata, metadataSize, applier);
+ });
+ return status;
+}
+
+template <StandardMetadataType TYPE>
+AIMapper_Error CrosGrallocMapperV5::setStandardMetadata(
+ CrosGralloc4Metadata* crosMetadata, typename StandardMetadata<TYPE>::value_type&& value) {
+ if constexpr (TYPE == StandardMetadataType::BLEND_MODE) {
+ crosMetadata->blendMode = value;
+ }
+ if constexpr (TYPE == StandardMetadataType::CTA861_3) {
+ crosMetadata->cta861_3 = value;
+ }
+ if constexpr (TYPE == StandardMetadataType::DATASPACE) {
+ crosMetadata->dataspace = value;
+ }
+ if constexpr (TYPE == StandardMetadataType::SMPTE2086) {
+ crosMetadata->smpte2086 = value;
+ }
+ // Unsupported metadatas were already filtered before we reached this point
+ return AIMAPPER_ERROR_NONE;
+}
+
+constexpr AIMapper_MetadataTypeDescription describeStandard(StandardMetadataType type,
+ bool isGettable, bool isSettable) {
+ return {{STANDARD_METADATA_NAME, static_cast<int64_t>(type)},
+ nullptr,
+ isGettable,
+ isSettable,
+ {0}};
+}
+
+AIMapper_Error CrosGrallocMapperV5::listSupportedMetadataTypes(
+ const AIMapper_MetadataTypeDescription* _Nullable* _Nonnull outDescriptionList,
+ size_t* _Nonnull outNumberOfDescriptions) {
+ static constexpr std::array<AIMapper_MetadataTypeDescription, 22> sSupportedMetadaTypes{
+ describeStandard(StandardMetadataType::BUFFER_ID, true, false),
+ describeStandard(StandardMetadataType::NAME, true, false),
+ describeStandard(StandardMetadataType::WIDTH, true, false),
+ describeStandard(StandardMetadataType::HEIGHT, true, false),
+ describeStandard(StandardMetadataType::LAYER_COUNT, true, false),
+ describeStandard(StandardMetadataType::PIXEL_FORMAT_REQUESTED, true, false),
+ describeStandard(StandardMetadataType::PIXEL_FORMAT_FOURCC, true, false),
+ describeStandard(StandardMetadataType::PIXEL_FORMAT_MODIFIER, true, false),
+ describeStandard(StandardMetadataType::USAGE, true, false),
+ describeStandard(StandardMetadataType::ALLOCATION_SIZE, true, false),
+ describeStandard(StandardMetadataType::PROTECTED_CONTENT, true, false),
+ describeStandard(StandardMetadataType::COMPRESSION, true, false),
+ describeStandard(StandardMetadataType::INTERLACED, true, false),
+ describeStandard(StandardMetadataType::CHROMA_SITING, true, false),
+ describeStandard(StandardMetadataType::PLANE_LAYOUTS, true, false),
+ describeStandard(StandardMetadataType::CROP, true, false),
+ describeStandard(StandardMetadataType::DATASPACE, true, true),
+ describeStandard(StandardMetadataType::COMPRESSION, true, false),
+ describeStandard(StandardMetadataType::BLEND_MODE, true, true),
+ describeStandard(StandardMetadataType::SMPTE2086, true, true),
+ describeStandard(StandardMetadataType::CTA861_3, true, true),
+ describeStandard(StandardMetadataType::STRIDE, true, false),
+ };
+ *outDescriptionList = sSupportedMetadaTypes.data();
+ *outNumberOfDescriptions = sSupportedMetadaTypes.size();
+ return AIMAPPER_ERROR_NONE;
+}
+
+void CrosGrallocMapperV5::dumpBuffer(
+ const cros_gralloc_buffer* crosBuffer,
+ std::function<void(AIMapper_MetadataType, const std::vector<uint8_t>&)> callback) {
+ // Temp buffer of ~10kb, should be large enough for any of the metadata we want to dump
+ std::vector<uint8_t> tempBuffer;
+ tempBuffer.resize(10000);
+ AIMapper_MetadataType metadataType;
+ metadataType.name = STANDARD_METADATA_NAME;
+
+ // Take an instance of the empty StandardMetadat<T> class just to allow auto-deduction
+ // to happen as explicit template invocation on lambdas is ugly
+ auto dump = [&]<StandardMetadataType T>(StandardMetadata<T>) {
+ // Nested templated lambdas! Woo! But the cleanness of the result is worth it
+ // The outer lambda exists basically just to capture the StandardMetadataType that's
+ // being dumped, as the `provider` parameter of getStandardMetadata only knows
+ // the value_type that the enum maps to but not the enum value itself, which we need to
+ // construct the `AIMapper_MetadataType` to pass to the dump callback
+ auto dumpInner = [&](const typename StandardMetadata<T>::value_type& value) -> int32_t {
+ int32_t size =
+ StandardMetadata<T>::value::encode(value, tempBuffer.data(), tempBuffer.size());
+ // The initial size should always be large enough, but just in case...
+ if (size > tempBuffer.size()) {
+ tempBuffer.resize(size * 2);
+ size = StandardMetadata<T>::value::encode(value, tempBuffer.data(),
+ tempBuffer.size());
+ }
+ // If the first resize failed _somehow_, just give up. Also don't notify if any
+ // errors occurred during encoding.
+ if (size >= 0 && size <= tempBuffer.size()) {
+ metadataType.value = static_cast<int64_t>(T);
+ callback(metadataType, tempBuffer);
+ }
+ // We don't actually care about the return value in this case, but why not use the
+ // real value anyway
+ return size;
+ };
+ getStandardMetadata(crosBuffer, dumpInner, StandardMetadata<T>{});
+ };
+
+ // So clean. So pretty.
+ dump(StandardMetadata<StandardMetadataType::BUFFER_ID>{});
+ dump(StandardMetadata<StandardMetadataType::NAME>{});
+ dump(StandardMetadata<StandardMetadataType::WIDTH>{});
+ dump(StandardMetadata<StandardMetadataType::HEIGHT>{});
+ dump(StandardMetadata<StandardMetadataType::LAYER_COUNT>{});
+ dump(StandardMetadata<StandardMetadataType::PIXEL_FORMAT_REQUESTED>{});
+ dump(StandardMetadata<StandardMetadataType::PIXEL_FORMAT_FOURCC>{});
+ dump(StandardMetadata<StandardMetadataType::PIXEL_FORMAT_MODIFIER>{});
+ dump(StandardMetadata<StandardMetadataType::USAGE>{});
+ dump(StandardMetadata<StandardMetadataType::ALLOCATION_SIZE>{});
+ dump(StandardMetadata<StandardMetadataType::PROTECTED_CONTENT>{});
+ dump(StandardMetadata<StandardMetadataType::COMPRESSION>{});
+ dump(StandardMetadata<StandardMetadataType::INTERLACED>{});
+ dump(StandardMetadata<StandardMetadataType::CHROMA_SITING>{});
+ dump(StandardMetadata<StandardMetadataType::PLANE_LAYOUTS>{});
+ dump(StandardMetadata<StandardMetadataType::DATASPACE>{});
+ dump(StandardMetadata<StandardMetadataType::BLEND_MODE>{});
+}
+
+AIMapper_Error CrosGrallocMapperV5::dumpBuffer(
+ buffer_handle_t _Nonnull bufferHandle,
+ AIMapper_DumpBufferCallback _Nonnull dumpBufferCallback, void* _Null_unspecified context) {
+ VALIDATE_DRIVER_AND_BUFFER_HANDLE(bufferHandle)
+ cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(bufferHandle);
+ if (!crosHandle) {
+ ALOGE("Failed to get. Invalid handle.");
+ return AIMAPPER_ERROR_BAD_BUFFER;
+ }
+ auto callback = [&](AIMapper_MetadataType type, const std::vector<uint8_t>& buffer) {
+ dumpBufferCallback(context, type, buffer.data(), buffer.size());
+ };
+ mDriver->with_buffer(
+ crosHandle, [&](cros_gralloc_buffer* crosBuffer) { dumpBuffer(crosBuffer, callback); });
+ return AIMAPPER_ERROR_NONE;
+}
+
+AIMapper_Error CrosGrallocMapperV5::dumpAllBuffers(
+ AIMapper_BeginDumpBufferCallback _Nonnull beginDumpBufferCallback,
+ AIMapper_DumpBufferCallback _Nonnull dumpBufferCallback, void* _Null_unspecified context) {
+ REQUIRE_DRIVER()
+ auto callback = [&](AIMapper_MetadataType type, const std::vector<uint8_t>& buffer) {
+ dumpBufferCallback(context, type, buffer.data(), buffer.size());
+ };
+ mDriver->with_each_buffer([&](cros_gralloc_buffer* crosBuffer) {
+ beginDumpBufferCallback(context);
+ dumpBuffer(crosBuffer, callback);
+ });
+ return AIMAPPER_ERROR_NONE;
+}
+
+AIMapper_Error CrosGrallocMapperV5::getReservedRegion(buffer_handle_t _Nonnull buffer,
+ void* _Nullable* _Nonnull outReservedRegion,
+ uint64_t* _Nonnull outReservedSize) {
+ VALIDATE_DRIVER_AND_BUFFER_HANDLE(buffer)
+ cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(buffer);
+ if (!crosHandle) {
+ ALOGE("Failed to getReservedRegion. Invalid handle.");
+ return AIMAPPER_ERROR_BAD_BUFFER;
+ }
+
+ void* reservedRegionAddr = nullptr;
+ uint64_t reservedRegionSize = 0;
+
+ AIMapper_Error error = AIMAPPER_ERROR_NONE;
+ mDriver->with_buffer(crosHandle, [&, this](cros_gralloc_buffer* crosBuffer) {
+ error = getReservedRegionArea(crosBuffer, ReservedRegionArea::USER_METADATA,
+ &reservedRegionAddr, &reservedRegionSize);
+ });
+
+ if (error != AIMAPPER_ERROR_NONE) {
+ ALOGE("Failed to getReservedRegion. Failed to getReservedRegionArea.");
+ return AIMAPPER_ERROR_BAD_BUFFER;
+ }
+
+ return AIMAPPER_ERROR_NONE;
+}
+
+AIMapper_Error CrosGrallocMapperV5::getReservedRegionArea(const cros_gralloc_buffer* crosBuffer,
+ ReservedRegionArea area, void** outAddr,
+ uint64_t* outSize) {
+ int ret = crosBuffer->get_reserved_region(outAddr, outSize);
+ if (ret) {
+ ALOGE("Failed to getReservedRegionArea.");
+ *outAddr = nullptr;
+ *outSize = 0;
+ return AIMAPPER_ERROR_NO_RESOURCES;
+ }
+
+ switch (area) {
+ case ReservedRegionArea::MAPPER4_METADATA: {
+ // CrosGralloc4Metadata resides at the beginning reserved region.
+ *outSize = sizeof(CrosGralloc4Metadata);
+ break;
+ }
+ case ReservedRegionArea::USER_METADATA: {
+ // User metadata resides after the CrosGralloc4Metadata.
+ *outAddr = reinterpret_cast<void*>(reinterpret_cast<char*>(*outAddr) +
+ sizeof(CrosGralloc4Metadata));
+ *outSize = *outSize - sizeof(CrosGralloc4Metadata);
+ break;
+ }
+ }
+
+ return AIMAPPER_ERROR_NONE;
+}
+
+AIMapper_Error CrosGrallocMapperV5::getCrosMetadata(const cros_gralloc_buffer* crosBuffer,
+ const CrosGralloc4Metadata** outMetadata) {
+ void* addr = nullptr;
+ uint64_t size;
+
+ auto error =
+ getReservedRegionArea(crosBuffer, ReservedRegionArea::MAPPER4_METADATA, &addr, &size);
+ if (error != AIMAPPER_ERROR_NONE) {
+ return error;
+ }
+
+ *outMetadata = reinterpret_cast<const CrosGralloc4Metadata*>(addr);
+ return AIMAPPER_ERROR_NONE;
+}
+
+AIMapper_Error CrosGrallocMapperV5::getMutableCrosMetadata(cros_gralloc_buffer* crosBuffer,
+ CrosGralloc4Metadata** outMetadata) {
+ void* addr = nullptr;
+ uint64_t size;
+
+ auto error =
+ getReservedRegionArea(crosBuffer, ReservedRegionArea::MAPPER4_METADATA, &addr, &size);
+ if (error != AIMAPPER_ERROR_NONE) {
+ return error;
+ }
+
+ *outMetadata = reinterpret_cast<CrosGralloc4Metadata*>(addr);
+ return AIMAPPER_ERROR_NONE;
+}
+
+extern "C" uint32_t ANDROID_HAL_MAPPER_VERSION = AIMAPPER_VERSION_5;
+
+extern "C" AIMapper_Error AIMapper_loadIMapper(AIMapper* _Nullable* _Nonnull outImplementation) {
+ static vendor::mapper::IMapperProvider<CrosGrallocMapperV5> provider;
+ return provider.load(outImplementation);
+} \ No newline at end of file
diff --git a/cros_gralloc/mapper_stablec/mapper.minigbm.xml b/cros_gralloc/mapper_stablec/mapper.minigbm.xml
new file mode 100644
index 0000000..282f7c8
--- /dev/null
+++ b/cros_gralloc/mapper_stablec/mapper.minigbm.xml
@@ -0,0 +1,9 @@
+<manifest version="1.0" type="device">
+ <hal format="native">
+ <name>mapper</name>
+ <version>5.0</version>
+ <interface>
+ <instance>minigbm</instance>
+ </interface>
+ </hal>
+</manifest>
diff --git a/cros_gralloc/sepolicy/cameraserver.te b/cros_gralloc/sepolicy/cameraserver.te
new file mode 100644
index 0000000..654c6bb
--- /dev/null
+++ b/cros_gralloc/sepolicy/cameraserver.te
@@ -0,0 +1,3 @@
+# Suppress warnings for minigbm trying to read vendor.minigbm.debug
+# property for the devices which do not use this property.
+dontaudit cameraserver vendor_default_prop:file read;
diff --git a/cros_gralloc/sepolicy/mediaswcodec.te b/cros_gralloc/sepolicy/mediaswcodec.te
new file mode 100644
index 0000000..a39fd73
--- /dev/null
+++ b/cros_gralloc/sepolicy/mediaswcodec.te
@@ -0,0 +1,3 @@
+# Suppress warnings for minigbm trying to read vendor.minigbm.debug
+# property for the devices which do not use this property.
+dontaudit mediaswcodec vendor_default_prop:file read;
diff --git a/cros_gralloc/sepolicy/system_server.te b/cros_gralloc/sepolicy/system_server.te
new file mode 100644
index 0000000..402dea6
--- /dev/null
+++ b/cros_gralloc/sepolicy/system_server.te
@@ -0,0 +1,3 @@
+# Suppress warnings for minigbm trying to read vendor.minigbm.debug
+# property for the devices which do not use this property.
+dontaudit system_server vendor_default_prop:file read;