diff options
author | Jason Macnak <natsu@google.com> | 2023-09-27 12:54:16 -0700 |
---|---|---|
committer | Chromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2023-09-28 17:11:53 +0000 |
commit | fe5c2c01714a5f328003a35e674304262c787ff4 (patch) | |
tree | 26b1467f525b85e1fc16a183068eadff761a10f4 | |
parent | bb30e856312fb239b5a6cb4c4ec77a578ca61c25 (diff) | |
download | minigbm-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-format | 19 | ||||
-rw-r--r-- | cros_gralloc/aidl/Allocator.cpp | 242 | ||||
-rw-r--r-- | cros_gralloc/aidl/Allocator.h | 57 | ||||
-rw-r--r-- | cros_gralloc/aidl/Android.bp | 51 | ||||
-rw-r--r-- | cros_gralloc/aidl/Main.cpp | 44 | ||||
-rw-r--r-- | cros_gralloc/aidl/allocator.rc | 7 | ||||
-rw-r--r-- | cros_gralloc/aidl/allocator.xml | 10 | ||||
-rw-r--r-- | cros_gralloc/mapper_stablec/.clang-format | 19 | ||||
-rw-r--r-- | cros_gralloc/mapper_stablec/Android.bp | 44 | ||||
-rw-r--r-- | cros_gralloc/mapper_stablec/Mapper.cpp | 745 | ||||
-rw-r--r-- | cros_gralloc/mapper_stablec/mapper.minigbm.xml | 9 | ||||
-rw-r--r-- | cros_gralloc/sepolicy/cameraserver.te | 3 | ||||
-rw-r--r-- | cros_gralloc/sepolicy/mediaswcodec.te | 3 | ||||
-rw-r--r-- | cros_gralloc/sepolicy/system_server.te | 3 |
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, ¶m) != 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; |