From 88d87faec908588db0dcf8fe9705ac72516ea82a Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Tue, 5 Nov 2019 14:57:51 -0800 Subject: [PATCH] gralloc: add get and set BufferMetadata support Add get and set functions that allow buffer metadata to be set on the buffer. This patch has been reviewed by vendors on AOSP. It is a combination of the following patches. They have been squashed (and updated) to make them easier to review. Two of the patches are proposals by ARM that have been incorporated into this patch. https://android-review.googlesource.com/c/platform/hardware/interfaces/+/1107574 https://android-review.googlesource.com/c/platform/hardware/interfaces/+/1109946 https://android-review.googlesource.com/c/platform/hardware/interfaces/+/1124857 https://android-review.googlesource.com/c/platform/hardware/interfaces/+/1126861 Bug: 141632767, 141631993 Test: VtsHalGraphicsMapperV4_0TargetTest Change-Id: I0e79d73a7687f2f5b51828a7454888e6d8ff9460 --- graphics/common/aidl/Android.bp | 1 + graphics/mapper/4.0/IMapper.hal | 222 +++- graphics/mapper/4.0/utils/vts/Android.bp | 3 + graphics/mapper/4.0/utils/vts/MapperVts.cpp | 88 +- .../vts/include/mapper-vts/4.0/MapperVts.h | 16 +- graphics/mapper/4.0/vts/functional/Android.bp | 6 +- .../VtsHalGraphicsMapperV4_0TargetTest.cpp | 1080 ++++++++++++++++- 7 files changed, 1381 insertions(+), 35 deletions(-) diff --git a/graphics/common/aidl/Android.bp b/graphics/common/aidl/Android.bp index 497c0f824d..e0c7674bba 100644 --- a/graphics/common/aidl/Android.bp +++ b/graphics/common/aidl/Android.bp @@ -1,5 +1,6 @@ aidl_interface { name: "vintf-graphics-common", + host_supported: true, vendor_available: true, vndk: { enabled: true, diff --git a/graphics/mapper/4.0/IMapper.hal b/graphics/mapper/4.0/IMapper.hal index 640539fcee..a5413826ce 100644 --- a/graphics/mapper/4.0/IMapper.hal +++ b/graphics/mapper/4.0/IMapper.hal @@ -35,18 +35,20 @@ interface IMapper { */ uint32_t width; - /** - * The height specifies how many rows of pixels must be in the - * allocated buffer. - */ + /** + * The height specifies how many rows of pixels must be in the + * allocated buffer. + */ uint32_t height; - /** - * The number of image layers that must be in the allocated buffer. - */ + /** + * The number of image layers that must be in the allocated buffer. + */ uint32_t layerCount; - /** Buffer pixel format. */ + /** + * Buffer pixel format. + */ PixelFormat format; /** @@ -309,5 +311,209 @@ interface IMapper { generates (Error error, bool supported); + + /** + * Description for get(...), set(...) and getFromBufferDescriptorInfo(...) + * + * ------------ Overview ----------------------------------- + * Gralloc 4 adds support for getting and setting buffer metadata on a buffer. + * + * To get buffer metadata, the client passes in a buffer handle and a token that + * represents the type of buffer metadata they would like to get. IMapper returns + * a byte stream that contains the buffer metadata. To set the buffer metadata, the + * client passes in a buffer handle and a token that represents the type of buffer + * metadata they would like to set and a byte stream that contains the buffer metadata + * they are setting. + * + * Buffer metadata is global for a buffer. When the metadata is set on the buffer + * in a process, the updated metadata should be available to all other processes. + * Please see "Storing and Propagating Metadata" below for more details. + * + * The getter and setter functions have been optimized for easy vendor extension. + * They do not require a formal HIDL extension to add support for getting and setting + * vendor defined buffer metadata. In order to allow easy extension, the types used + * here are not typical HIDL types. See "Buffer Metadata Token" and + * "Buffer Metadata Stream" below for more details. + * + * ------------ Storing and Propagating Metadata ----------- + * Buffer metadata must be global. Any changes to the metadata must be propagated + * to all other processes immediately. Vendors may chose how they would like support + * this functionality. + * + * We recommend supporting this functionality by allocating an extra page of shared + * memory and storing it in the buffer's native_handle_t. The buffer metadata can + * be stored in the extra page of shared memory. Set operations are automatically + * propagated to all other processes. + * + * ------------ Buffer Metadata Synchronization ------------ + * There are no explicit buffer metadata synchronization primitives. Many devices + * before gralloc 4 already support getting and setting of global buffer metadata + * with no explicit synchronization primitives. Adding synchronization primitives + * would just add unnecessary complexity. + * + * The general rule is if a process has permission to write to a buffer, they + * have permission to write to the buffer's metadata. If a process has permission + * to read from a buffer, they have permission to read the buffer's metadata. + * + * There is one exception to this rule. Fences CANNOT be used to protect a buffer's + * metadata. A process should finish writing to a buffer's metadata before sending + * sending the buffer to another process that will read or write to the buffer. + * This exception is needed because sometimes userspace needs to read the + * buffer's metadata before the buffer's contents are ready. + * + * As a simple example: an app renders to a buffer and then displays the buffer. + * In this example when the app renders to the buffer, both the buffer and its + * metadata need to be updated. The app's process queues up its work on the GPU + * and gets back an acquire fence. The app's process must update the buffer's + * metadata before enqueuing the buffer to SurfaceFlinger. The app process CANNOT + * update the buffer's metadata after enqueuing the buffer. When HardwareComposer + * receives the buffer, it is immediately safe to read the buffer's metadata + * and use it to program the display driver. To read the buffer's contents, + * display driver must still wait on the acquire fence. + * + * ------------ Buffer Metadata Token ---------------------- + * In order to allow arbitrary vendor defined metadata, we could not use a + * HIDL enum as the buffer metadata token. Extending a HIDL enum requires a full + * HIDL extension. We also could not use a simple non-HIDL enum because vendor + * defined enums from different vendors could collide. Instead we have defined + * a struct that has a string representing the enum type and an int that + * represents the enum value. The string protects different enum values from + * colliding. + * + * The token struct (MetadataType) is defined as a HIDL struct since it + * is passed into a HIDL function. The standard buffer metadata types are NOT + * defined as a HIDL enum because it would have required a new IMapper version + * just to add future standard buffer metadata types. By putting the enum in the + * stable AIDL (hardware/interfaces/graphics/common/aidl/android/hardware/ + * graphics/common/StandardMetadataType.aidl), vendors will be able to optionally + * choose to support future standard buffer metadata types without upgrading + * HIDL versions. For more information see the description of "struct MetadataType". + * + * ------------ Buffer Metadata Stream --------------------- + * The buffer metadata is get and set as a byte stream (vec). By getting + * and setting buffer metadata as a byte stream, vendors can use the standard + * getters and setter functions defined here. Vendors do NOT need to add their own + * getters and setter functions for each new type of buffer metadata. + * + * Converting buffer metadata into a byte stream can be non-trivial. For the standard + * buffer metadata types defined in StandardMetadataType.aidl, there are also + * support functions that will encode the buffer metadata into a byte stream + * and decode the buffer metadata from a byte stream. We STRONGLY recommend using + * these support functions. The framework will use them when getting and setting + * metadata. The support functions are defined in + * frameworks/native/libs/gralloc/types/include/gralloctypes/Gralloc4.h. + */ + + /** + * MetadataType represents the different types of buffer metadata that could be + * associated with a buffer. It is used by IMapper to help get and set buffer metadata + * on the buffer's native handle. + * + * Standard buffer metadata will have the name field set to + * "android.hardware.graphics.common.StandardMetadataType" and will contain values + * from StandardMetadataType.aidl. + * + * This struct should be "extended" by devices that use a proprietary or non-standard + * buffer metadata. To extend the struct, first create a custom @VendorStability vendor + * AIDL interface that defines the new type(s) you would like to support. Set the + * struct's name field to the custom aidl interface's name + * (eg. "vendor.mycompanyname.graphics.common.MetadataType"). Set the struct's value + * field to the custom @VendorStabilty vendor AIDL interface. + * + * Each company should create their own StandardMetadataType.aidl extension. The name + * field prevents values from different companies from colliding. + */ + struct MetadataType { + string name; + int64_t value; + }; + + /** + * Gets the buffer metadata for a given MetadataType. + * + * Buffer metadata can be changed after allocation so clients should avoid "caching" + * the buffer metadata. For example, if the video resolution changes and the buffers + * are not reallocated, several buffer metadata values may change without warning. + * Clients should not expect the values to be constant. They should requery them every + * frame. The only exception is buffer metadata that is determined at allocation + * time. For StandardMetadataType values, only BUFFER_ID, NAME, WIDTH, + * HEIGHT, LAYER_COUNT, PIXEL_FORMAT_REQUESTED and USAGE are safe to cache because + * they are determined at allocation time. + * + * @param buffer Buffer containing desired metadata + * @param metadataType MetadataType for the metadata value being queried + * @return error Error status of the call, which may be + * - `NONE` upon success. + * - `BAD_BUFFER` if the raw handle is invalid. + * - `NO_RESOURCES` if the get cannot be fullfilled due to unavailability of + * resources. + * - `UNSUPPORTED` when metadataType is unknown/unsupported. + * IMapper must support getting all StandardMetadataType.aidl values defined + * at the time the device first launches. + * @return metadata Vector of bytes representing the buffer metadata associated with + * the MetadataType. + */ + get(pointer buffer, MetadataType metadataType) + generates (Error error, + vec metadata); + + /** + * Sets the global value for a given MetadataType. + * + * Metadata fields are not required to be settable. This function can + * return Error::UNSUPPORTED whenever it doesn't support setting a + * particular Metadata field. + * + * The framework may attempt to set the following StandardMetadataType + * values: DATASPACE, PER_FRAME_METADATA, PER_FRAME_METADATA_BLOB and BLEND_MODE. + * We strongly encourage everyone to support setting as many of those fields as + * possible. If a device's Composer implementation supports a field, it should be + * supported here. Over time these metadata fields will be moved out of + * Composer/BufferQueue/etc. and into the buffer's Metadata fields. + * If a device's IMapper doesn't support setting those Metadata fields, + * eventually the device may not longer be able to support these fields. + * + * @param buffer Buffer receiving desired metadata + * @param metadataType MetadataType for the metadata value being set + * @param metadata Vector of bytes representing the value associated with + * @return error Error status of the call, which may be + * - `NONE` upon success. + * - `BAD_BUFFER` if the raw handle is invalid. + * - `BAD_VALUE` when the field is constant and can never be set (such as + * BUFFER_ID, NAME, WIDTH, HEIGHT, LAYER_COUNT, PIXEL_FORMAT_REQUESTED and + * USAGE) + * - `NO_RESOURCES` if the set cannot be fullfilled due to unavailability of + * resources. + * - `UNSUPPORTED` when metadataType is unknown/unsupported or setting + * it is unsupported. Unsupported should also be returned if the metadata + * is malformed. + */ + set(pointer buffer, MetadataType metadataType, vec metadata) + generates (Error error); + + /** + * Given a BufferDescriptorInfo, gets the starting value of a given + * MetadataType. This can be used to query basic information about a buffer + * before the buffer is allocated. + * + * @param description Attributes of the descriptor. + * @param metadataType MetadataType for the metadata value being queried + * @return error Error status of the call, which may be + * - `NONE` upon success. + * - `BAD_VALUE` if any of the specified BufferDescriptorInfo attributes + * are invalid. + * - `NO_RESOURCES` if the get cannot be fullfilled due to unavailability of + * resources. + * - `UNSUPPORTED` when any of the description attributes are unsupported or + * if the metadataType is unknown/unsupported. This should also be + * returned if the requested metadata is not defined until a buffer has been + * allocated. + * @return metadata Vector of bytes representing the value associated with + * the MetadataType value. + */ + getFromBufferDescriptorInfo(BufferDescriptorInfo description, + MetadataType metadataType) + generates (Error error, + vec metadata); }; diff --git a/graphics/mapper/4.0/utils/vts/Android.bp b/graphics/mapper/4.0/utils/vts/Android.bp index e451584958..56ff116a43 100644 --- a/graphics/mapper/4.0/utils/vts/Android.bp +++ b/graphics/mapper/4.0/utils/vts/Android.bp @@ -26,6 +26,9 @@ cc_library_static { "android.hardware.graphics.allocator@4.0", "android.hardware.graphics.mapper@4.0", ], + shared_libs: [ + "libgralloctypes", + ], export_static_lib_headers: [ "android.hardware.graphics.allocator@4.0", "android.hardware.graphics.mapper@4.0", diff --git a/graphics/mapper/4.0/utils/vts/MapperVts.cpp b/graphics/mapper/4.0/utils/vts/MapperVts.cpp index 056b7c9da4..531f31131c 100644 --- a/graphics/mapper/4.0/utils/vts/MapperVts.cpp +++ b/graphics/mapper/4.0/utils/vts/MapperVts.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include #include #include @@ -92,28 +93,39 @@ const native_handle_t* Gralloc::cloneBuffer(const hidl_handle& rawHandle) { std::vector Gralloc::allocate(const BufferDescriptor& descriptor, uint32_t count, bool import, - uint32_t* outStride) { + bool allowFailure, uint32_t* outStride) { std::vector bufferHandles; bufferHandles.reserve(count); - mAllocator->allocate(descriptor, count, - [&](const auto& tmpError, const auto& tmpStride, const auto& tmpBuffers) { - ASSERT_EQ(Error::NONE, tmpError) << "failed to allocate buffers"; - ASSERT_EQ(count, tmpBuffers.size()) << "invalid buffer array"; + mAllocator->allocate( + descriptor, count, + [&](const auto& tmpError, const auto& tmpStride, const auto& tmpBuffers) { + ASSERT_EQ(Error::NONE, tmpError) << "failed to allocate buffers"; + ASSERT_EQ(count, tmpBuffers.size()) << "invalid buffer array"; - for (uint32_t i = 0; i < count; i++) { - if (import) { - ASSERT_NO_FATAL_FAILURE( - bufferHandles.push_back(importBuffer(tmpBuffers[i]))); - } else { - ASSERT_NO_FATAL_FAILURE( - bufferHandles.push_back(cloneBuffer(tmpBuffers[i]))); - } - } + for (uint32_t i = 0; i < count; i++) { + const native_handle_t* bufferHandle = nullptr; + if (import) { + if (allowFailure) { + bufferHandle = importBuffer(tmpBuffers[i]); + } else { + ASSERT_NO_FATAL_FAILURE(bufferHandle = importBuffer(tmpBuffers[i])); + } + } else { + if (allowFailure) { + bufferHandle = cloneBuffer(tmpBuffers[i]); + } else { + ASSERT_NO_FATAL_FAILURE(bufferHandle = cloneBuffer(tmpBuffers[i])); + } + } + if (bufferHandle) { + bufferHandles.push_back(bufferHandle); + } + } - if (outStride) { - *outStride = tmpStride; - } - }); + if (outStride) { + *outStride = tmpStride; + } + }); if (::testing::Test::HasFatalFailure()) { bufferHandles.clear(); @@ -123,17 +135,20 @@ std::vector Gralloc::allocate(const BufferDescriptor& de } const native_handle_t* Gralloc::allocate(const IMapper::BufferDescriptorInfo& descriptorInfo, - bool import, uint32_t* outStride) { + bool import, bool allowFailure, uint32_t* outStride) { BufferDescriptor descriptor = createDescriptor(descriptorInfo); if (::testing::Test::HasFatalFailure()) { return nullptr; } - auto buffers = allocate(descriptor, 1, import, outStride); + auto buffers = allocate(descriptor, 1, import, allowFailure, outStride); if (::testing::Test::HasFatalFailure()) { return nullptr; } + if (buffers.size() != 1) { + return nullptr; + } return buffers[0]; } @@ -167,6 +182,10 @@ const native_handle_t* Gralloc::importBuffer(const hidl_handle& rawHandle) { } void Gralloc::freeBuffer(const native_handle_t* bufferHandle) { + if (bufferHandle == nullptr) { + return; + } + auto buffer = const_cast(bufferHandle); if (mImportedBuffers.erase(bufferHandle)) { @@ -296,6 +315,35 @@ bool Gralloc::isSupported(const IMapper::BufferDescriptorInfo& descriptorInfo) { return supported; } +Error Gralloc::get(const native_handle_t* bufferHandle, const IMapper::MetadataType& metadataType, + hidl_vec* outVec) { + Error err; + mMapper->get(const_cast(bufferHandle), metadataType, + [&](const auto& tmpError, const hidl_vec& tmpVec) { + err = tmpError; + *outVec = tmpVec; + }); + return err; +} + +Error Gralloc::set(const native_handle_t* bufferHandle, const IMapper::MetadataType& metadataType, + const hidl_vec& vec) { + return mMapper->set(const_cast(bufferHandle), metadataType, vec); +} + +Error Gralloc::getFromBufferDescriptorInfo(const IMapper::BufferDescriptorInfo& descriptorInfo, + const IMapper::MetadataType& metadataType, + hidl_vec* outVec) { + Error err; + mMapper->getFromBufferDescriptorInfo( + descriptorInfo, metadataType, + [&](const auto& tmpError, const hidl_vec& tmpVec) { + err = tmpError; + *outVec = tmpVec; + }); + return err; +} + } // namespace vts } // namespace V4_0 } // namespace mapper diff --git a/graphics/mapper/4.0/utils/vts/include/mapper-vts/4.0/MapperVts.h b/graphics/mapper/4.0/utils/vts/include/mapper-vts/4.0/MapperVts.h index 03ce764d8b..28555fa05d 100644 --- a/graphics/mapper/4.0/utils/vts/include/mapper-vts/4.0/MapperVts.h +++ b/graphics/mapper/4.0/utils/vts/include/mapper-vts/4.0/MapperVts.h @@ -51,9 +51,11 @@ class Gralloc { // // Either case, the returned buffers must be freed with freeBuffer. std::vector allocate(const BufferDescriptor& descriptor, uint32_t count, - bool import = true, uint32_t* outStride = nullptr); + bool import = true, bool allowFailure = false, + uint32_t* outStride = nullptr); const native_handle_t* allocate(const IMapper::BufferDescriptorInfo& descriptorInfo, - bool import = true, uint32_t* outStride = nullptr); + bool import = true, bool allowFailure = false, + uint32_t* outStride = nullptr); // IMapper methods @@ -81,6 +83,16 @@ class Gralloc { bool isSupported(const IMapper::BufferDescriptorInfo& descriptorInfo); + Error get(const native_handle_t* bufferHandle, const IMapper::MetadataType& metadataType, + hidl_vec* outVec); + + Error set(const native_handle_t* bufferHandle, const IMapper::MetadataType& metadataType, + const hidl_vec& vec); + + Error getFromBufferDescriptorInfo(const IMapper::BufferDescriptorInfo& descriptorInfo, + const IMapper::MetadataType& metadataType, + hidl_vec* outVec); + private: void init(const std::string& allocatorServiceName, const std::string& mapperServiceName); diff --git a/graphics/mapper/4.0/vts/functional/Android.bp b/graphics/mapper/4.0/vts/functional/Android.bp index a90ee0ca1c..5a7548a4f8 100644 --- a/graphics/mapper/4.0/vts/functional/Android.bp +++ b/graphics/mapper/4.0/vts/functional/Android.bp @@ -19,12 +19,16 @@ cc_test { defaults: ["VtsHalTargetTestDefaults"], srcs: ["VtsHalGraphicsMapperV4_0TargetTest.cpp"], static_libs: [ + "android.hardware.graphics.mapper@4.0-vts", + ], + shared_libs: [ "android.hardware.graphics.allocator@4.0", "android.hardware.graphics.common@1.0", "android.hardware.graphics.common@1.1", "android.hardware.graphics.common@1.2", "android.hardware.graphics.mapper@4.0", - "android.hardware.graphics.mapper@4.0-vts", + "libgralloctypes", + "vintf-graphics-common-ndk_platform", ], test_suites: ["general-tests"], } diff --git a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp index 62ff6134ff..1e8ec01e33 100644 --- a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp +++ b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp @@ -22,6 +22,7 @@ #include #include +#include #include namespace android { @@ -34,6 +35,15 @@ namespace { using android::hardware::graphics::common::V1_2::BufferUsage; using android::hardware::graphics::common::V1_2::PixelFormat; +using MetadataType = android::hardware::graphics::mapper::V4_0::IMapper::MetadataType; +using aidl::android::hardware::graphics::common::BlendMode; +using aidl::android::hardware::graphics::common::Dataspace; +using aidl::android::hardware::graphics::common::ExtendableType; +using aidl::android::hardware::graphics::common::PlaneLayout; +using aidl::android::hardware::graphics::common::PlaneLayoutComponent; + +using DecodeFunction = std::function& vec)>; // Test environment for graphics.mapper. class GraphicsMapperHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase { @@ -57,6 +67,8 @@ class GraphicsMapperHidlTest : public ::testing::VtsHalHidlTargetTestBase { mGralloc = std::make_unique( GraphicsMapperHidlEnvironment::Instance()->getServiceName(), GraphicsMapperHidlEnvironment::Instance()->getServiceName())); + ASSERT_NE(nullptr, mGralloc->getAllocator().get()); + ASSERT_NE(nullptr, mGralloc->getMapper().get()); mDummyDescriptorInfo.name = "dummy"; mDummyDescriptorInfo.width = 64; @@ -69,6 +81,85 @@ class GraphicsMapperHidlTest : public ::testing::VtsHalHidlTargetTestBase { void TearDown() override {} + void testGet(const IMapper::BufferDescriptorInfo& descriptorInfo, + const MetadataType& metadataType, DecodeFunction decode) { + const native_handle_t* bufferHandle = nullptr; + ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(descriptorInfo, true)); + + hidl_vec vec; + ASSERT_EQ(Error::NONE, mGralloc->get(bufferHandle, metadataType, &vec)); + + ASSERT_NO_FATAL_FAILURE(decode(descriptorInfo, vec)); + } + + void testSet(const IMapper::BufferDescriptorInfo& descriptorInfo, + const MetadataType& metadataType, const hidl_vec& metadata, + DecodeFunction decode) { + const native_handle_t* bufferHandle = nullptr; + ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(descriptorInfo, true)); + + Error err = mGralloc->set(bufferHandle, metadataType, metadata); + if (err == Error::UNSUPPORTED) { + GTEST_SUCCEED() << "setting this metadata is unsupported"; + } + ASSERT_EQ(err, Error::NONE); + + hidl_vec vec; + ASSERT_EQ(Error::NONE, mGralloc->get(bufferHandle, metadataType, &vec)); + + ASSERT_NO_FATAL_FAILURE(decode(descriptorInfo, vec)); + } + + void verifyDummyDescriptorInfoPlaneLayouts(const std::vector& planeLayouts) { + ASSERT_EQ(1, planeLayouts.size()); + + const auto& planeLayout = planeLayouts.front(); + + ASSERT_EQ(4, planeLayout.components.size()); + + int64_t offsetInBitsR = -1; + int64_t offsetInBitsG = -1; + int64_t offsetInBitsB = -1; + int64_t offsetInBitsA = -1; + + for (const auto& component : planeLayout.components) { + EXPECT_EQ(GRALLOC4_PLANE_LAYOUT_COMPONENT_TYPE, component.type.name); + EXPECT_EQ(8, component.sizeInBits); + if (component.type.value == gralloc4::PlaneLayoutComponentType_R.value) { + offsetInBitsR = component.offsetInBits; + } + if (component.type.value == gralloc4::PlaneLayoutComponentType_G.value) { + offsetInBitsG = component.offsetInBits; + } + if (component.type.value == gralloc4::PlaneLayoutComponentType_B.value) { + offsetInBitsB = component.offsetInBits; + } + if (component.type.value == gralloc4::PlaneLayoutComponentType_A.value) { + offsetInBitsA = component.offsetInBits; + } + } + + EXPECT_EQ(0, offsetInBitsR); + EXPECT_EQ(8, offsetInBitsG); + EXPECT_EQ(16, offsetInBitsB); + EXPECT_EQ(24, offsetInBitsA); + + EXPECT_EQ(0, planeLayout.offsetInBytes); + EXPECT_EQ(8, planeLayout.sampleIncrementInBits); + // Skip testing stride because any stride is valid + EXPECT_EQ(mDummyDescriptorInfo.width, planeLayout.widthInSamples); + EXPECT_EQ(mDummyDescriptorInfo.height, planeLayout.heightInSamples); + EXPECT_LE(planeLayout.widthInSamples * planeLayout.heightInSamples * 4, + planeLayout.totalSizeInBytes); + EXPECT_EQ(1, planeLayout.horizontalSubsampling); + EXPECT_EQ(1, planeLayout.verticalSubsampling); + + EXPECT_EQ(0, planeLayout.crop.left); + EXPECT_EQ(0, planeLayout.crop.top); + EXPECT_EQ(planeLayout.widthInSamples, planeLayout.crop.right); + EXPECT_EQ(planeLayout.heightInSamples, planeLayout.crop.bottom); + } + std::unique_ptr mGralloc; IMapper::BufferDescriptorInfo mDummyDescriptorInfo{}; }; @@ -90,8 +181,8 @@ TEST_F(GraphicsMapperHidlTest, AllocatorAllocate) { for (uint32_t count = 0; count < 5; count++) { std::vector bufferHandles; uint32_t stride; - ASSERT_NO_FATAL_FAILURE(bufferHandles = - mGralloc->allocate(descriptor, count, false, &stride)); + ASSERT_NO_FATAL_FAILURE( + bufferHandles = mGralloc->allocate(descriptor, count, false, false, &stride)); if (count >= 1) { EXPECT_LE(mDummyDescriptorInfo.width, stride) << "invalid buffer stride"; @@ -293,7 +384,7 @@ TEST_F(GraphicsMapperHidlTest, LockUnlockBasic) { const native_handle_t* bufferHandle; uint32_t stride; - ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(info, true, &stride)); + ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(info, true, false, &stride)); // lock buffer for writing const IMapper::Rect region{0, 0, static_cast(info.width), @@ -354,7 +445,7 @@ TEST_F(GraphicsMapperHidlTest, LockYCbCrBasic) { const native_handle_t* bufferHandle; uint32_t stride; - ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(info, true, &stride)); + ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(info, true, false, &stride)); // lock buffer for writing const IMapper::Rect region{0, 0, static_cast(info.width), @@ -519,6 +610,987 @@ TEST_F(GraphicsMapperHidlTest, IsSupportedY16) { ASSERT_NO_FATAL_FAILURE(supported = mGralloc->isSupported(info)); } +/** + * Test IMapper::get(BufferId) + */ +TEST_F(GraphicsMapperHidlTest, GetBufferId) { + testGet(mDummyDescriptorInfo, gralloc4::MetadataType_BufferId, + [](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec& vec) { + uint64_t bufferId = 0; + ASSERT_EQ(NO_ERROR, gralloc4::decodeBufferId(vec, &bufferId)); + }); +} + +/** + * Test IMapper::get(Name) + */ +TEST_F(GraphicsMapperHidlTest, GetName) { + testGet(mDummyDescriptorInfo, gralloc4::MetadataType_Name, + [](const IMapper::BufferDescriptorInfo& info, const hidl_vec& vec) { + std::string name; + ASSERT_EQ(NO_ERROR, gralloc4::decodeName(vec, &name)); + EXPECT_EQ(info.name, name); + }); +} + +/** + * Test IMapper::get(Width) + */ +TEST_F(GraphicsMapperHidlTest, GetWidth) { + testGet(mDummyDescriptorInfo, gralloc4::MetadataType_Width, + [](const IMapper::BufferDescriptorInfo& info, const hidl_vec& vec) { + uint64_t width = 0; + ASSERT_EQ(NO_ERROR, gralloc4::decodeWidth(vec, &width)); + EXPECT_EQ(info.width, width); + }); +} + +/** + * Test IMapper::get(Height) + */ +TEST_F(GraphicsMapperHidlTest, GetHeight) { + testGet(mDummyDescriptorInfo, gralloc4::MetadataType_Height, + [](const IMapper::BufferDescriptorInfo& info, const hidl_vec& vec) { + uint64_t height = 0; + ASSERT_EQ(NO_ERROR, gralloc4::decodeHeight(vec, &height)); + EXPECT_EQ(info.height, height); + }); +} + +/** + * Test IMapper::get(LayerCount) + */ +TEST_F(GraphicsMapperHidlTest, GetLayerCount) { + testGet(mDummyDescriptorInfo, gralloc4::MetadataType_LayerCount, + [](const IMapper::BufferDescriptorInfo& info, const hidl_vec& vec) { + uint64_t layerCount = 0; + ASSERT_EQ(NO_ERROR, gralloc4::decodeLayerCount(vec, &layerCount)); + EXPECT_EQ(info.layerCount, layerCount); + }); +} + +/** + * Test IMapper::get(PixelFormatRequested) + */ +TEST_F(GraphicsMapperHidlTest, GetPixelFormatRequested) { + testGet(mDummyDescriptorInfo, gralloc4::MetadataType_PixelFormatRequested, + [](const IMapper::BufferDescriptorInfo& info, const hidl_vec& vec) { + PixelFormat pixelFormatRequested = PixelFormat::BLOB; + ASSERT_EQ(NO_ERROR, + gralloc4::decodePixelFormatRequested(vec, &pixelFormatRequested)); + EXPECT_EQ(info.format, pixelFormatRequested); + }); +} + +/** + * Test IMapper::get(PixelFormatFourCC) + */ +TEST_F(GraphicsMapperHidlTest, GetPixelFormatFourCC) { + testGet(mDummyDescriptorInfo, gralloc4::MetadataType_PixelFormatFourCC, + [](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec& vec) { + uint32_t pixelFormatFourCC = 0; + ASSERT_EQ(NO_ERROR, gralloc4::decodePixelFormatFourCC(vec, &pixelFormatFourCC)); + }); +} + +/** + * Test IMapper::get(PixelFormatModifier) + */ +TEST_F(GraphicsMapperHidlTest, GetPixelFormatModifier) { + testGet(mDummyDescriptorInfo, gralloc4::MetadataType_PixelFormatModifier, + [](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec& vec) { + uint64_t pixelFormatModifier = 0; + ASSERT_EQ(NO_ERROR, gralloc4::decodePixelFormatModifier(vec, &pixelFormatModifier)); + }); +} + +/** + * Test IMapper::get(Usage) + */ +TEST_F(GraphicsMapperHidlTest, GetUsage) { + testGet(mDummyDescriptorInfo, gralloc4::MetadataType_Usage, + [](const IMapper::BufferDescriptorInfo& info, const hidl_vec& vec) { + uint64_t usage = 0; + ASSERT_EQ(NO_ERROR, gralloc4::decodeUsage(vec, &usage)); + EXPECT_EQ(info.usage, usage); + }); +} + +/** + * Test IMapper::get(AllocationSize) + */ +TEST_F(GraphicsMapperHidlTest, GetAllocationSize) { + testGet(mDummyDescriptorInfo, gralloc4::MetadataType_AllocationSize, + [](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec& vec) { + uint64_t allocationSize = 0; + ASSERT_EQ(NO_ERROR, gralloc4::decodeAllocationSize(vec, &allocationSize)); + }); +} + +/** + * Test IMapper::get(ProtectedContent) + */ +TEST_F(GraphicsMapperHidlTest, GetProtectedContent) { + auto info = mDummyDescriptorInfo; + info.usage = BufferUsage::PROTECTED | BufferUsage::COMPOSER_OVERLAY; + + const native_handle_t* bufferHandle = nullptr; + bufferHandle = mGralloc->allocate(info, true, true); + if (bufferHandle) { + GTEST_SUCCEED() << "unable to allocate protected content"; + } + + hidl_vec vec; + ASSERT_EQ(Error::NONE, + mGralloc->get(bufferHandle, gralloc4::MetadataType_ProtectedContent, &vec)); + + uint64_t protectedContent = 0; + ASSERT_EQ(NO_ERROR, gralloc4::decodeProtectedContent(vec, &protectedContent)); + EXPECT_EQ(1, protectedContent); +} + +/** + * Test IMapper::get(Compression) + */ +TEST_F(GraphicsMapperHidlTest, GetCompression) { + auto info = mDummyDescriptorInfo; + info.usage = static_cast(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN); + + testGet(info, gralloc4::MetadataType_Compression, + [](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec& vec) { + ExtendableType compression = gralloc4::Compression_DisplayStreamCompression; + ASSERT_EQ(NO_ERROR, gralloc4::decodeCompression(vec, &compression)); + + EXPECT_EQ(gralloc4::Compression_None.name, compression.name); + EXPECT_EQ(gralloc4::Compression_None.value, compression.value); + }); +} + +/** + * Test IMapper::get(Interlaced) + */ +TEST_F(GraphicsMapperHidlTest, GetInterlaced) { + testGet(mDummyDescriptorInfo, gralloc4::MetadataType_Interlaced, + [](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec& vec) { + ExtendableType interlaced = gralloc4::Interlaced_TopBottom; + ASSERT_EQ(NO_ERROR, gralloc4::decodeInterlaced(vec, &interlaced)); + + EXPECT_EQ(gralloc4::Interlaced_None.name, interlaced.name); + EXPECT_EQ(gralloc4::Interlaced_None.value, interlaced.value); + }); +} + +/** + * Test IMapper::get(ChromaSiting) + */ +TEST_F(GraphicsMapperHidlTest, GetChromaSiting) { + testGet(mDummyDescriptorInfo, gralloc4::MetadataType_ChromaSiting, + [](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec& vec) { + ExtendableType chromaSiting = gralloc4::ChromaSiting_Unknown; + ASSERT_EQ(NO_ERROR, gralloc4::decodeChromaSiting(vec, &chromaSiting)); + + EXPECT_EQ(gralloc4::ChromaSiting_None.name, chromaSiting.name); + EXPECT_EQ(gralloc4::ChromaSiting_None.value, chromaSiting.value); + }); +} + +/** + * Test IMapper::get(PlaneLayouts) + */ +TEST_F(GraphicsMapperHidlTest, GetPlaneLayouts) { + const native_handle_t* bufferHandle = nullptr; + ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(mDummyDescriptorInfo, true)); + + hidl_vec vec; + ASSERT_EQ(Error::NONE, mGralloc->get(bufferHandle, gralloc4::MetadataType_PlaneLayouts, &vec)); + + std::vector planeLayouts; + ASSERT_EQ(NO_ERROR, gralloc4::decodePlaneLayouts(vec, &planeLayouts)); + + ASSERT_NO_FATAL_FAILURE(verifyDummyDescriptorInfoPlaneLayouts(planeLayouts)); +} + +/** + * Test IMapper::get(Dataspace) + */ +TEST_F(GraphicsMapperHidlTest, GetDataspace) { + testGet(mDummyDescriptorInfo, gralloc4::MetadataType_Dataspace, + [](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec& vec) { + Dataspace dataspace = Dataspace::DISPLAY_P3; + ASSERT_EQ(NO_ERROR, gralloc4::decodeDataspace(vec, &dataspace)); + EXPECT_EQ(Dataspace::UNKNOWN, dataspace); + }); +} + +/** + * Test IMapper::get(BlendMode) + */ +TEST_F(GraphicsMapperHidlTest, GetBlendMode) { + testGet(mDummyDescriptorInfo, gralloc4::MetadataType_BlendMode, + [](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec& vec) { + BlendMode blendMode = BlendMode::NONE; + ASSERT_EQ(NO_ERROR, gralloc4::decodeBlendMode(vec, &blendMode)); + EXPECT_EQ(BlendMode::INVALID, blendMode); + }); +} + +/** + * Test IMapper::get(metadata) with a bad buffer + */ +TEST_F(GraphicsMapperHidlTest, GetMetadataBadValue) { + const native_handle_t* bufferHandle = nullptr; + hidl_vec vec; + ASSERT_EQ(Error::BAD_BUFFER, + mGralloc->get(bufferHandle, gralloc4::MetadataType_BufferId, &vec)); + ASSERT_EQ(0, vec.size()); + ASSERT_EQ(Error::BAD_BUFFER, mGralloc->get(bufferHandle, gralloc4::MetadataType_Name, &vec)); + ASSERT_EQ(0, vec.size()); + ASSERT_EQ(Error::BAD_BUFFER, mGralloc->get(bufferHandle, gralloc4::MetadataType_Width, &vec)); + ASSERT_EQ(0, vec.size()); + ASSERT_EQ(Error::BAD_BUFFER, mGralloc->get(bufferHandle, gralloc4::MetadataType_Height, &vec)); + ASSERT_EQ(0, vec.size()); + ASSERT_EQ(Error::BAD_BUFFER, + mGralloc->get(bufferHandle, gralloc4::MetadataType_LayerCount, &vec)); + ASSERT_EQ(0, vec.size()); + ASSERT_EQ(Error::BAD_BUFFER, + mGralloc->get(bufferHandle, gralloc4::MetadataType_PixelFormatRequested, &vec)); + ASSERT_EQ(0, vec.size()); + ASSERT_EQ(Error::BAD_BUFFER, + mGralloc->get(bufferHandle, gralloc4::MetadataType_PixelFormatFourCC, &vec)); + ASSERT_EQ(0, vec.size()); + ASSERT_EQ(Error::BAD_BUFFER, + mGralloc->get(bufferHandle, gralloc4::MetadataType_PixelFormatModifier, &vec)); + ASSERT_EQ(0, vec.size()); + ASSERT_EQ(Error::BAD_BUFFER, mGralloc->get(bufferHandle, gralloc4::MetadataType_Usage, &vec)); + ASSERT_EQ(0, vec.size()); + ASSERT_EQ(Error::BAD_BUFFER, + mGralloc->get(bufferHandle, gralloc4::MetadataType_AllocationSize, &vec)); + ASSERT_EQ(0, vec.size()); + ASSERT_EQ(Error::BAD_BUFFER, + mGralloc->get(bufferHandle, gralloc4::MetadataType_ProtectedContent, &vec)); + ASSERT_EQ(0, vec.size()); + ASSERT_EQ(Error::BAD_BUFFER, + mGralloc->get(bufferHandle, gralloc4::MetadataType_Compression, &vec)); + ASSERT_EQ(0, vec.size()); + ASSERT_EQ(Error::BAD_BUFFER, + mGralloc->get(bufferHandle, gralloc4::MetadataType_Interlaced, &vec)); + ASSERT_EQ(0, vec.size()); + ASSERT_EQ(Error::BAD_BUFFER, + mGralloc->get(bufferHandle, gralloc4::MetadataType_ChromaSiting, &vec)); + ASSERT_EQ(0, vec.size()); + ASSERT_EQ(Error::BAD_BUFFER, + mGralloc->get(bufferHandle, gralloc4::MetadataType_PlaneLayouts, &vec)); + ASSERT_EQ(0, vec.size()); + ASSERT_EQ(Error::BAD_BUFFER, + mGralloc->get(bufferHandle, gralloc4::MetadataType_Dataspace, &vec)); + ASSERT_EQ(0, vec.size()); + ASSERT_EQ(Error::BAD_BUFFER, + mGralloc->get(bufferHandle, gralloc4::MetadataType_BlendMode, &vec)); + ASSERT_EQ(0, vec.size()); +} + +/** + * Test IMapper::get(metadata) for unsupported metadata + */ +TEST_F(GraphicsMapperHidlTest, GetUnsupportedMetadata) { + const native_handle_t* bufferHandle = nullptr; + ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(mDummyDescriptorInfo, true)); + + MetadataType metadataTypeFake = {"FAKE", 1}; + + hidl_vec vec; + ASSERT_EQ(Error::UNSUPPORTED, mGralloc->get(bufferHandle, metadataTypeFake, &vec)); + ASSERT_EQ(0, vec.size()); +} + +/** + * Test IMapper::get(metadata) for unsupported standard metadata + */ +TEST_F(GraphicsMapperHidlTest, GetUnsupportedStandardMetadata) { + const native_handle_t* bufferHandle = nullptr; + ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(mDummyDescriptorInfo, true)); + + MetadataType metadataTypeFake = {GRALLOC4_STANDARD_METADATA_TYPE, 9999}; + + hidl_vec vec; + ASSERT_EQ(Error::UNSUPPORTED, mGralloc->get(bufferHandle, metadataTypeFake, &vec)); + ASSERT_EQ(0, vec.size()); +} + +/** + * Test IMapper::set(PixelFormatFourCC) + */ +TEST_F(GraphicsMapperHidlTest, SetPixelFormatFourCC) { + uint32_t pixelFormatFourCC = 0x34324142; // DRM_FORMAT_BGRA8888 + hidl_vec vec; + ASSERT_EQ(NO_ERROR, gralloc4::encodePixelFormatFourCC(pixelFormatFourCC, &vec)); + + testSet(mDummyDescriptorInfo, gralloc4::MetadataType_PixelFormatFourCC, vec, + [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec& vec) { + uint32_t realPixelFormatFourCC = 0; + ASSERT_EQ(NO_ERROR, gralloc4::decodePixelFormatFourCC(vec, &realPixelFormatFourCC)); + EXPECT_EQ(pixelFormatFourCC, realPixelFormatFourCC); + }); +} + +/** + * Test IMapper::set(PixelFormatModifier) + */ +TEST_F(GraphicsMapperHidlTest, SetPixelFormatModifier) { + uint64_t pixelFormatModifier = 10; + hidl_vec vec; + ASSERT_EQ(NO_ERROR, gralloc4::encodePixelFormatModifier(pixelFormatModifier, &vec)); + + testSet(mDummyDescriptorInfo, gralloc4::MetadataType_PixelFormatModifier, vec, + [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec& vec) { + uint64_t realPixelFormatModifier = 0; + ASSERT_EQ(NO_ERROR, + gralloc4::decodePixelFormatModifier(vec, &realPixelFormatModifier)); + EXPECT_EQ(pixelFormatModifier, realPixelFormatModifier); + }); +} + +/** + * Test IMapper::set(Usage) remove flag + */ +TEST_F(GraphicsMapperHidlTest, SetUsageRemoveBit) { + uint64_t usage = static_cast(BufferUsage::CPU_WRITE_OFTEN); + hidl_vec vec; + ASSERT_EQ(NO_ERROR, gralloc4::encodeUsage(usage, &vec)); + + testSet(mDummyDescriptorInfo, gralloc4::MetadataType_Usage, vec, + [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec& vec) { + uint64_t realUsage = 0; + ASSERT_EQ(NO_ERROR, gralloc4::decodeUsage(vec, &realUsage)); + EXPECT_EQ(usage, realUsage); + }); +} +/** + * Test IMapper::set(Usage) add flag + */ +TEST_F(GraphicsMapperHidlTest, SetUsageAddBit) { + uint64_t usage = mDummyDescriptorInfo.usage | static_cast(BufferUsage::GPU_TEXTURE); + hidl_vec vec; + ASSERT_EQ(NO_ERROR, gralloc4::encodeUsage(usage, &vec)); + + testSet(mDummyDescriptorInfo, gralloc4::MetadataType_Usage, vec, + [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec& vec) { + uint64_t realUsage = 0; + ASSERT_EQ(NO_ERROR, gralloc4::decodeUsage(vec, &realUsage)); + EXPECT_EQ(usage, realUsage); + }); +} + +/** + * Test IMapper::set(Usage) to test protected content + */ +TEST_F(GraphicsMapperHidlTest, SetUsageProtected) { + const native_handle_t* bufferHandle = nullptr; + auto info = mDummyDescriptorInfo; + info.usage = BufferUsage::PROTECTED | BufferUsage::COMPOSER_OVERLAY; + + bufferHandle = mGralloc->allocate(info, true, true); + if (bufferHandle) { + GTEST_SUCCEED() << "unable to allocate protected content"; + } + + uint64_t usage = static_cast(BufferUsage::COMPOSER_OVERLAY); + hidl_vec vec; + ASSERT_EQ(NO_ERROR, gralloc4::encodeUsage(usage, &vec)); + + Error err = mGralloc->set(bufferHandle, gralloc4::MetadataType_Usage, vec); + ASSERT_EQ(err, Error::UNSUPPORTED); + vec.resize(0); + + uint64_t realUsage = 0; + ASSERT_EQ(Error::NONE, mGralloc->get(bufferHandle, gralloc4::MetadataType_Usage, &vec)); + ASSERT_EQ(NO_ERROR, gralloc4::decodeUsage(vec, &realUsage)); + EXPECT_EQ(info.usage, realUsage); +} + +/** + * Test IMapper::set(AllocationSize) + */ +TEST_F(GraphicsMapperHidlTest, SetAllocationSize) { + uint64_t allocationSize = 1000000; + hidl_vec vec; + ASSERT_EQ(NO_ERROR, gralloc4::encodeAllocationSize(allocationSize, &vec)); + + testSet(mDummyDescriptorInfo, gralloc4::MetadataType_AllocationSize, vec, + [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec& vec) { + uint64_t realAllocationSize = 0; + ASSERT_EQ(NO_ERROR, gralloc4::decodeAllocationSize(vec, &realAllocationSize)); + EXPECT_EQ(allocationSize, realAllocationSize); + }); +} + +/** + * Test IMapper::set(ProtectedContent) + */ +TEST_F(GraphicsMapperHidlTest, SetProtectedContent) { + const native_handle_t* bufferHandle = nullptr; + auto info = mDummyDescriptorInfo; + info.usage = BufferUsage::PROTECTED | BufferUsage::COMPOSER_OVERLAY; + + bufferHandle = mGralloc->allocate(info, true, true); + if (bufferHandle) { + GTEST_SUCCEED() << "unable to allocate protected content"; + } + + uint64_t protectedContent = 0; + hidl_vec vec; + ASSERT_EQ(NO_ERROR, gralloc4::encodeProtectedContent(protectedContent, &vec)); + + Error err = mGralloc->set(bufferHandle, gralloc4::MetadataType_ProtectedContent, vec); + ASSERT_EQ(err, Error::UNSUPPORTED); + vec.resize(0); + + uint64_t realProtectedContent = 0; + ASSERT_EQ(Error::NONE, + mGralloc->get(bufferHandle, gralloc4::MetadataType_ProtectedContent, &vec)); + ASSERT_EQ(NO_ERROR, gralloc4::decodeProtectedContent(vec, &realProtectedContent)); + EXPECT_EQ(1, realProtectedContent); +} + +/** + * Test IMapper::set(Compression) + */ +TEST_F(GraphicsMapperHidlTest, SetCompression) { + auto info = mDummyDescriptorInfo; + info.usage = static_cast(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN); + + ExtendableType compression = gralloc4::Compression_DisplayStreamCompression; + hidl_vec vec; + ASSERT_EQ(NO_ERROR, gralloc4::encodeCompression(compression, &vec)); + + testSet(info, gralloc4::MetadataType_Compression, vec, + [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec& vec) { + ExtendableType realCompression = gralloc4::Compression_None; + ASSERT_EQ(NO_ERROR, gralloc4::decodeCompression(vec, &realCompression)); + + EXPECT_EQ(compression.name, realCompression.name); + EXPECT_EQ(compression.value, realCompression.value); + }); +} + +/** + * Test IMapper::set(Interlaced) + */ +TEST_F(GraphicsMapperHidlTest, SetInterlaced) { + ExtendableType interlaced = gralloc4::Interlaced_RightLeft; + hidl_vec vec; + ASSERT_EQ(NO_ERROR, gralloc4::encodeInterlaced(interlaced, &vec)); + + testSet(mDummyDescriptorInfo, gralloc4::MetadataType_Interlaced, vec, + [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec& vec) { + ExtendableType realInterlaced = gralloc4::Interlaced_None; + ASSERT_EQ(NO_ERROR, gralloc4::decodeInterlaced(vec, &realInterlaced)); + + EXPECT_EQ(interlaced.name, realInterlaced.name); + EXPECT_EQ(interlaced.value, realInterlaced.value); + }); +} + +/** + * Test IMapper::set(ChromaSiting) + */ +TEST_F(GraphicsMapperHidlTest, SetChromaSiting) { + ExtendableType chromaSiting = gralloc4::ChromaSiting_SitedInterstitial; + hidl_vec vec; + ASSERT_EQ(NO_ERROR, gralloc4::encodeChromaSiting(chromaSiting, &vec)); + + testSet(mDummyDescriptorInfo, gralloc4::MetadataType_ChromaSiting, vec, + [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec& vec) { + ExtendableType realChromaSiting = gralloc4::ChromaSiting_None; + ASSERT_EQ(NO_ERROR, gralloc4::decodeChromaSiting(vec, &realChromaSiting)); + + EXPECT_EQ(chromaSiting.name, realChromaSiting.name); + EXPECT_EQ(chromaSiting.value, realChromaSiting.value); + }); +} + +/** + * Test IMapper::set(PlaneLayouts) + */ +TEST_F(GraphicsMapperHidlTest, SetPlaneLayouts) { + const native_handle_t* bufferHandle = nullptr; + auto info = mDummyDescriptorInfo; + ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(info, true)); + + std::vector planeLayouts; + PlaneLayout planeLayoutA; + PlaneLayout planeLayoutRGB; + PlaneLayoutComponent component; + + planeLayoutA.offsetInBytes = 0; + planeLayoutA.sampleIncrementInBits = 8; + planeLayoutA.strideInBytes = info.width + 20; + planeLayoutA.widthInSamples = info.width; + planeLayoutA.heightInSamples = info.height; + planeLayoutA.totalSizeInBytes = planeLayoutA.strideInBytes * info.height; + planeLayoutA.horizontalSubsampling = 1; + planeLayoutA.verticalSubsampling = 1; + planeLayoutA.crop.left = 0; + planeLayoutA.crop.top = 0; + planeLayoutA.crop.right = info.width; + planeLayoutA.crop.bottom = info.height; + + component.type = gralloc4::PlaneLayoutComponentType_A; + component.offsetInBits = 0; + component.sizeInBits = 8; + planeLayoutA.components.push_back(component); + + planeLayouts.push_back(planeLayoutA); + + planeLayoutRGB.offsetInBytes = 0; + planeLayoutRGB.sampleIncrementInBits = 32; + planeLayoutRGB.strideInBytes = info.width + 20; + planeLayoutRGB.widthInSamples = info.width; + planeLayoutRGB.heightInSamples = info.height; + planeLayoutRGB.totalSizeInBytes = planeLayoutRGB.strideInBytes * info.height; + planeLayoutRGB.horizontalSubsampling = 1; + planeLayoutRGB.verticalSubsampling = 1; + planeLayoutRGB.crop.left = 0; + planeLayoutRGB.crop.top = 0; + planeLayoutRGB.crop.right = info.width; + planeLayoutRGB.crop.bottom = info.height; + + component.type = gralloc4::PlaneLayoutComponentType_R; + planeLayoutRGB.components.push_back(component); + component.type = gralloc4::PlaneLayoutComponentType_G; + planeLayoutRGB.components.push_back(component); + component.type = gralloc4::PlaneLayoutComponentType_B; + planeLayoutRGB.components.push_back(component); + + planeLayouts.push_back(planeLayoutRGB); + + hidl_vec vec; + ASSERT_EQ(NO_ERROR, gralloc4::encodePlaneLayouts(planeLayouts, &vec)); + + Error err = mGralloc->set(bufferHandle, gralloc4::MetadataType_PlaneLayouts, vec); + if (err == Error::UNSUPPORTED) { + GTEST_SUCCEED() << "setting this metadata is unsupported"; + } + ASSERT_EQ(err, Error::NONE); + + std::vector realPlaneLayouts; + ASSERT_EQ(NO_ERROR, gralloc4::decodePlaneLayouts(vec, &realPlaneLayouts)); + + ASSERT_EQ(planeLayouts.size(), realPlaneLayouts.size()); + + for (int i = 0; i < realPlaneLayouts.size(); i++) { + const auto& planeLayout = planeLayouts[i]; + const auto& realPlaneLayout = realPlaneLayouts[i]; + + EXPECT_EQ(planeLayout.offsetInBytes, realPlaneLayout.offsetInBytes); + EXPECT_EQ(planeLayout.sampleIncrementInBits, realPlaneLayout.sampleIncrementInBits); + EXPECT_EQ(planeLayout.strideInBytes, realPlaneLayout.strideInBytes); + EXPECT_EQ(planeLayout.widthInSamples, realPlaneLayout.widthInSamples); + EXPECT_EQ(planeLayout.heightInSamples, realPlaneLayout.heightInSamples); + EXPECT_LE(planeLayout.totalSizeInBytes, realPlaneLayout.totalSizeInBytes); + EXPECT_EQ(planeLayout.horizontalSubsampling, realPlaneLayout.horizontalSubsampling); + EXPECT_EQ(planeLayout.verticalSubsampling, realPlaneLayout.verticalSubsampling); + + EXPECT_EQ(planeLayout.crop.left, realPlaneLayout.crop.left); + EXPECT_EQ(planeLayout.crop.top, realPlaneLayout.crop.top); + EXPECT_EQ(planeLayout.crop.right, realPlaneLayout.crop.right); + EXPECT_EQ(planeLayout.crop.bottom, realPlaneLayout.crop.bottom); + + ASSERT_EQ(planeLayout.components.size(), realPlaneLayout.components.size()); + + for (int j = 0; j < realPlaneLayout.components.size(); j++) { + const auto& component = planeLayout.components[j]; + const auto& realComponent = realPlaneLayout.components[j]; + + EXPECT_EQ(component.type.name, realComponent.type.name); + EXPECT_EQ(component.type.value, realComponent.type.value); + EXPECT_EQ(component.sizeInBits, realComponent.sizeInBits); + EXPECT_EQ(component.offsetInBits, realComponent.offsetInBits); + } + } +} + +/** + * Test IMapper::set(Dataspace) + */ +TEST_F(GraphicsMapperHidlTest, SetDataspace) { + Dataspace dataspace = Dataspace::V0_SRGB_LINEAR; + hidl_vec vec; + ASSERT_EQ(NO_ERROR, gralloc4::encodeDataspace(dataspace, &vec)); + + testSet(mDummyDescriptorInfo, gralloc4::MetadataType_Dataspace, vec, + [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec& vec) { + Dataspace realDataspace = Dataspace::UNKNOWN; + ASSERT_EQ(NO_ERROR, gralloc4::decodeDataspace(vec, &realDataspace)); + EXPECT_EQ(dataspace, realDataspace); + }); +} + +/** + * Test IMapper::set(BlendMode) + */ +TEST_F(GraphicsMapperHidlTest, SetBlendMode) { + BlendMode blendMode = BlendMode::PREMULTIPLIED; + hidl_vec vec; + ASSERT_EQ(NO_ERROR, gralloc4::encodeBlendMode(blendMode, &vec)); + + testSet(mDummyDescriptorInfo, gralloc4::MetadataType_BlendMode, vec, + [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec& vec) { + BlendMode realBlendMode = BlendMode::INVALID; + ASSERT_EQ(NO_ERROR, gralloc4::decodeBlendMode(vec, &realBlendMode)); + EXPECT_EQ(blendMode, realBlendMode); + }); +} + +/** + * Test IMapper::set(metadata) with a bad buffer + */ +TEST_F(GraphicsMapperHidlTest, SetMetadataNullBuffer) { + const native_handle_t* bufferHandle = nullptr; + hidl_vec vec; + ASSERT_EQ(Error::BAD_BUFFER, mGralloc->set(bufferHandle, gralloc4::MetadataType_BufferId, vec)); + ASSERT_EQ(Error::BAD_BUFFER, mGralloc->set(bufferHandle, gralloc4::MetadataType_Name, vec)); + ASSERT_EQ(Error::BAD_BUFFER, mGralloc->set(bufferHandle, gralloc4::MetadataType_Width, vec)); + ASSERT_EQ(Error::BAD_BUFFER, mGralloc->set(bufferHandle, gralloc4::MetadataType_Height, vec)); + ASSERT_EQ(Error::BAD_BUFFER, + mGralloc->set(bufferHandle, gralloc4::MetadataType_LayerCount, vec)); + ASSERT_EQ(Error::BAD_BUFFER, + mGralloc->set(bufferHandle, gralloc4::MetadataType_PixelFormatRequested, vec)); + ASSERT_EQ(Error::BAD_BUFFER, + mGralloc->set(bufferHandle, gralloc4::MetadataType_PixelFormatFourCC, vec)); + ASSERT_EQ(Error::BAD_BUFFER, + mGralloc->set(bufferHandle, gralloc4::MetadataType_PixelFormatModifier, vec)); + ASSERT_EQ(Error::BAD_BUFFER, mGralloc->set(bufferHandle, gralloc4::MetadataType_Usage, vec)); + ASSERT_EQ(Error::BAD_BUFFER, + mGralloc->set(bufferHandle, gralloc4::MetadataType_AllocationSize, vec)); + ASSERT_EQ(Error::BAD_BUFFER, + mGralloc->set(bufferHandle, gralloc4::MetadataType_ProtectedContent, vec)); + ASSERT_EQ(Error::BAD_BUFFER, + mGralloc->set(bufferHandle, gralloc4::MetadataType_Compression, vec)); + ASSERT_EQ(Error::BAD_BUFFER, + mGralloc->set(bufferHandle, gralloc4::MetadataType_Interlaced, vec)); + ASSERT_EQ(Error::BAD_BUFFER, + mGralloc->set(bufferHandle, gralloc4::MetadataType_ChromaSiting, vec)); + ASSERT_EQ(Error::BAD_BUFFER, + mGralloc->set(bufferHandle, gralloc4::MetadataType_PlaneLayouts, vec)); + ASSERT_EQ(Error::BAD_BUFFER, + mGralloc->set(bufferHandle, gralloc4::MetadataType_Dataspace, vec)); + ASSERT_EQ(Error::BAD_BUFFER, + mGralloc->set(bufferHandle, gralloc4::MetadataType_BlendMode, vec)); +} + +/** + * Test IMapper::set(metadata) for constant metadata + */ +TEST_F(GraphicsMapperHidlTest, SetConstantMetadata) { + const native_handle_t* bufferHandle = nullptr; + ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(mDummyDescriptorInfo, true)); + + hidl_vec vec; + ASSERT_EQ(Error::BAD_VALUE, mGralloc->set(bufferHandle, gralloc4::MetadataType_BufferId, vec)); + ASSERT_EQ(Error::BAD_VALUE, mGralloc->set(bufferHandle, gralloc4::MetadataType_Name, vec)); + ASSERT_EQ(Error::BAD_VALUE, mGralloc->set(bufferHandle, gralloc4::MetadataType_Width, vec)); + ASSERT_EQ(Error::BAD_VALUE, mGralloc->set(bufferHandle, gralloc4::MetadataType_Height, vec)); + ASSERT_EQ(Error::BAD_VALUE, + mGralloc->set(bufferHandle, gralloc4::MetadataType_LayerCount, vec)); + ASSERT_EQ(Error::BAD_VALUE, + mGralloc->set(bufferHandle, gralloc4::MetadataType_PixelFormatRequested, vec)); + ASSERT_EQ(Error::BAD_VALUE, mGralloc->set(bufferHandle, gralloc4::MetadataType_Usage, vec)); +} + +/** + * Test IMapper::set(metadata) for bad metadata + */ +TEST_F(GraphicsMapperHidlTest, SetBadMetadata) { + const native_handle_t* bufferHandle = nullptr; + ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(mDummyDescriptorInfo, true)); + + hidl_vec vec; + ASSERT_EQ(Error::UNSUPPORTED, + mGralloc->set(bufferHandle, gralloc4::MetadataType_BufferId, vec)); + ASSERT_EQ(Error::UNSUPPORTED, mGralloc->set(bufferHandle, gralloc4::MetadataType_Name, vec)); + ASSERT_EQ(Error::UNSUPPORTED, mGralloc->set(bufferHandle, gralloc4::MetadataType_Width, vec)); + ASSERT_EQ(Error::UNSUPPORTED, mGralloc->set(bufferHandle, gralloc4::MetadataType_Height, vec)); + ASSERT_EQ(Error::UNSUPPORTED, + mGralloc->set(bufferHandle, gralloc4::MetadataType_LayerCount, vec)); + ASSERT_EQ(Error::UNSUPPORTED, + mGralloc->set(bufferHandle, gralloc4::MetadataType_PixelFormatRequested, vec)); + ASSERT_EQ(Error::UNSUPPORTED, + mGralloc->set(bufferHandle, gralloc4::MetadataType_PixelFormatFourCC, vec)); + ASSERT_EQ(Error::UNSUPPORTED, + mGralloc->set(bufferHandle, gralloc4::MetadataType_PixelFormatModifier, vec)); + ASSERT_EQ(Error::UNSUPPORTED, mGralloc->set(bufferHandle, gralloc4::MetadataType_Usage, vec)); + ASSERT_EQ(Error::UNSUPPORTED, + mGralloc->set(bufferHandle, gralloc4::MetadataType_AllocationSize, vec)); + ASSERT_EQ(Error::UNSUPPORTED, + mGralloc->set(bufferHandle, gralloc4::MetadataType_ProtectedContent, vec)); + ASSERT_EQ(Error::UNSUPPORTED, + mGralloc->set(bufferHandle, gralloc4::MetadataType_Compression, vec)); + ASSERT_EQ(Error::UNSUPPORTED, + mGralloc->set(bufferHandle, gralloc4::MetadataType_Interlaced, vec)); + ASSERT_EQ(Error::UNSUPPORTED, + mGralloc->set(bufferHandle, gralloc4::MetadataType_ChromaSiting, vec)); + ASSERT_EQ(Error::UNSUPPORTED, + mGralloc->set(bufferHandle, gralloc4::MetadataType_PlaneLayouts, vec)); + ASSERT_EQ(Error::UNSUPPORTED, + mGralloc->set(bufferHandle, gralloc4::MetadataType_Dataspace, vec)); + ASSERT_EQ(Error::UNSUPPORTED, + mGralloc->set(bufferHandle, gralloc4::MetadataType_BlendMode, vec)); +} + +/** + * Test IMapper::getFromBufferDescriptorInfo(BufferId) + */ +TEST_F(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoBufferId) { + hidl_vec vec; + ASSERT_EQ(Error::UNSUPPORTED, + mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo, + gralloc4::MetadataType_BufferId, &vec)); +} + +/** + * Test IMapper::getFromBufferDescriptorInfo(Name) + */ +TEST_F(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoName) { + hidl_vec vec; + ASSERT_EQ(Error::NONE, mGralloc->getFromBufferDescriptorInfo( + mDummyDescriptorInfo, gralloc4::MetadataType_Name, &vec)); + + std::string name; + ASSERT_EQ(NO_ERROR, gralloc4::decodeName(vec, &name)); + EXPECT_EQ(mDummyDescriptorInfo.name, name); +} + +/** + * Test IMapper::getFromBufferDescriptorInfo(Width) + */ +TEST_F(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoWidth) { + hidl_vec vec; + ASSERT_EQ(Error::NONE, mGralloc->getFromBufferDescriptorInfo( + mDummyDescriptorInfo, gralloc4::MetadataType_Width, &vec)); + + uint64_t width = 0; + ASSERT_EQ(NO_ERROR, gralloc4::decodeWidth(vec, &width)); + EXPECT_EQ(mDummyDescriptorInfo.width, width); +} + +/** + * Test IMapper::getFromBufferDescriptorInfo(Height) + */ +TEST_F(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoHeight) { + hidl_vec vec; + ASSERT_EQ(Error::NONE, mGralloc->getFromBufferDescriptorInfo( + mDummyDescriptorInfo, gralloc4::MetadataType_Height, &vec)); + + uint64_t height = 0; + ASSERT_EQ(NO_ERROR, gralloc4::decodeHeight(vec, &height)); + EXPECT_EQ(mDummyDescriptorInfo.height, height); +} + +/** + * Test IMapper::getFromBufferDescriptorInfo(PixelFormatRequested) + */ +TEST_F(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoPixelFormatRequested) { + hidl_vec vec; + ASSERT_EQ(Error::NONE, + mGralloc->getFromBufferDescriptorInfo( + mDummyDescriptorInfo, gralloc4::MetadataType_PixelFormatRequested, &vec)); + + PixelFormat pixelFormatRequested = PixelFormat::BLOB; + ASSERT_EQ(NO_ERROR, gralloc4::decodePixelFormatRequested(vec, &pixelFormatRequested)); + EXPECT_EQ(mDummyDescriptorInfo.format, pixelFormatRequested); +} + +/** + * Test IMapper::getFromBufferDescriptorInfo(PixelFormatFourCC) + */ +TEST_F(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoPixelFormatFourCC) { + hidl_vec vec; + Error err = mGralloc->getFromBufferDescriptorInfo( + mDummyDescriptorInfo, gralloc4::MetadataType_PixelFormatFourCC, &vec); + if (err == Error::UNSUPPORTED) { + GTEST_SUCCEED() << "setting this metadata is unsupported"; + } + ASSERT_EQ(err, Error::NONE); + + uint32_t pixelFormatFourCC = 0; + ASSERT_EQ(NO_ERROR, gralloc4::decodePixelFormatFourCC(vec, &pixelFormatFourCC)); +} + +/** + * Test IMapper::getFromBufferDescriptorInfo(PixelFormatModifier) + */ +TEST_F(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoPixelFormatModifier) { + hidl_vec vec; + Error err = mGralloc->getFromBufferDescriptorInfo( + mDummyDescriptorInfo, gralloc4::MetadataType_PixelFormatModifier, &vec); + if (err == Error::UNSUPPORTED) { + GTEST_SUCCEED() << "setting this metadata is unsupported"; + } + ASSERT_EQ(err, Error::NONE); + + uint64_t pixelFormatModifier = 0; + ASSERT_EQ(NO_ERROR, gralloc4::decodePixelFormatModifier(vec, &pixelFormatModifier)); +} + +/** + * Test IMapper::getFromBufferDescriptorInfo(Usage) + */ +TEST_F(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoUsage) { + hidl_vec vec; + ASSERT_EQ(Error::NONE, mGralloc->getFromBufferDescriptorInfo( + mDummyDescriptorInfo, gralloc4::MetadataType_Usage, &vec)); + + uint64_t usage = 0; + ASSERT_EQ(NO_ERROR, gralloc4::decodeUsage(vec, &usage)); + EXPECT_EQ(mDummyDescriptorInfo.usage, usage); +} + +/** + * Test IMapper::getFromBufferDescriptorInfo(AllocationSize) + */ +TEST_F(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoAllocationSize) { + hidl_vec vec; + Error err = mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo, + gralloc4::MetadataType_AllocationSize, &vec); + if (err == Error::UNSUPPORTED) { + GTEST_SUCCEED() << "setting this metadata is unsupported"; + } + ASSERT_EQ(err, Error::NONE); + + uint64_t allocationSize = 0; + ASSERT_EQ(NO_ERROR, gralloc4::decodeAllocationSize(vec, &allocationSize)); +} + +/** + * Test IMapper::getFromBufferDescriptorInfo(ProtectedContent) + */ +TEST_F(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoProtectedContent) { + auto info = mDummyDescriptorInfo; + info.usage = BufferUsage::PROTECTED | BufferUsage::COMPOSER_OVERLAY; + + hidl_vec vec; + ASSERT_EQ(Error::NONE, mGralloc->getFromBufferDescriptorInfo( + info, gralloc4::MetadataType_ProtectedContent, &vec)); + + uint64_t protectedContent = 0; + ASSERT_EQ(NO_ERROR, gralloc4::decodeProtectedContent(vec, &protectedContent)); + EXPECT_EQ(1, protectedContent); +} + +/** + * Test IMapper::getFromBufferDescriptorInfo(Compression) + */ +TEST_F(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoCompression) { + auto info = mDummyDescriptorInfo; + info.usage = static_cast(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN); + + hidl_vec vec; + ASSERT_EQ(Error::NONE, mGralloc->getFromBufferDescriptorInfo( + info, gralloc4::MetadataType_Compression, &vec)); + + ExtendableType compression = gralloc4::Compression_DisplayStreamCompression; + ASSERT_EQ(NO_ERROR, gralloc4::decodeCompression(vec, &compression)); + + EXPECT_EQ(gralloc4::Compression_None.name, compression.name); + EXPECT_EQ(gralloc4::Compression_None.value, compression.value); +} + +/** + * Test IMapper::getFromBufferDescriptorInfo(Interlaced) + */ +TEST_F(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoInterlaced) { + hidl_vec vec; + ASSERT_EQ(Error::NONE, mGralloc->getFromBufferDescriptorInfo( + mDummyDescriptorInfo, gralloc4::MetadataType_Interlaced, &vec)); + + ExtendableType interlaced = gralloc4::Interlaced_TopBottom; + ASSERT_EQ(NO_ERROR, gralloc4::decodeInterlaced(vec, &interlaced)); + + EXPECT_EQ(gralloc4::Interlaced_None.name, interlaced.name); + EXPECT_EQ(gralloc4::Interlaced_None.value, interlaced.value); +} + +/** + * Test IMapper::getFromBufferDescriptorInfo(ChromaSiting) + */ +TEST_F(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoChromaSiting) { + hidl_vec vec; + ASSERT_EQ(Error::NONE, + mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo, + gralloc4::MetadataType_ChromaSiting, &vec)); + + ExtendableType chromaSiting = gralloc4::ChromaSiting_CositedHorizontal; + ASSERT_EQ(NO_ERROR, gralloc4::decodeChromaSiting(vec, &chromaSiting)); + + EXPECT_EQ(gralloc4::ChromaSiting_None.name, chromaSiting.name); + EXPECT_EQ(gralloc4::ChromaSiting_None.value, chromaSiting.value); +} + +/** + * Test IMapper::getFromBufferDescriptorInfo(PlaneLayouts) + */ +TEST_F(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoPlaneLayouts) { + hidl_vec vec; + ASSERT_EQ(Error::NONE, + mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo, + gralloc4::MetadataType_PlaneLayouts, &vec)); + + std::vector planeLayouts; + ASSERT_EQ(NO_ERROR, gralloc4::decodePlaneLayouts(vec, &planeLayouts)); + ASSERT_NO_FATAL_FAILURE(verifyDummyDescriptorInfoPlaneLayouts(planeLayouts)); +} + +/** + * Test IMapper::getFromBufferDescriptorInfo(Dataspace) + */ +TEST_F(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoDataspace) { + hidl_vec vec; + ASSERT_EQ(Error::NONE, mGralloc->getFromBufferDescriptorInfo( + mDummyDescriptorInfo, gralloc4::MetadataType_Dataspace, &vec)); + + Dataspace dataspace = Dataspace::DISPLAY_P3; + ASSERT_EQ(NO_ERROR, gralloc4::decodeDataspace(vec, &dataspace)); + EXPECT_EQ(Dataspace::UNKNOWN, dataspace); +} + +/** + * Test IMapper::getFromBufferDescriptorInfo(BlendMode) + */ +TEST_F(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoBlendMode) { + hidl_vec vec; + ASSERT_EQ(Error::NONE, mGralloc->getFromBufferDescriptorInfo( + mDummyDescriptorInfo, gralloc4::MetadataType_BlendMode, &vec)); + + BlendMode blendMode = BlendMode::COVERAGE; + ASSERT_EQ(NO_ERROR, gralloc4::decodeBlendMode(vec, &blendMode)); + EXPECT_EQ(BlendMode::INVALID, blendMode); +} + +/** + * Test IMapper::getFromBufferDescriptorInfo(metadata) for unsupported metadata + */ +TEST_F(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoUnsupportedMetadata) { + MetadataType metadataTypeFake = {"FAKE", 1}; + + hidl_vec vec; + ASSERT_EQ(Error::UNSUPPORTED, + mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo, metadataTypeFake, &vec)); + ASSERT_EQ(0, vec.size()); +} + +/** + * Test IMapper::getFromBufferDescriptorInfo(metadata) for unsupported standard metadata + */ +TEST_F(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoUnsupportedStandardMetadata) { + MetadataType metadataTypeFake = {GRALLOC4_STANDARD_METADATA_TYPE, 9999}; + + hidl_vec vec; + ASSERT_EQ(Error::UNSUPPORTED, + mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo, metadataTypeFake, &vec)); + ASSERT_EQ(0, vec.size()); +} + } // namespace } // namespace vts } // namespace V4_0