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