/* * Copyright 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "VtsHalGraphicsMapperV4_0TargetTest" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace android { namespace hardware { namespace graphics { namespace mapper { namespace V4_0 { namespace vts { namespace { using ::android::base::unique_fd; using android::hardware::graphics::common::V1_2::BufferUsage; using android::hardware::graphics::common::V1_2::PixelFormat; using Tolerance = ::android::hardware::graphics::mapper::V4_0::vts::Gralloc::Tolerance; using MetadataType = android::hardware::graphics::mapper::V4_0::IMapper::MetadataType; using aidl::android::hardware::graphics::common::BlendMode; using aidl::android::hardware::graphics::common::Cta861_3; 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 aidl::android::hardware::graphics::common::PlaneLayoutComponentType; using aidl::android::hardware::graphics::common::Smpte2086; using aidl::android::hardware::graphics::common::StandardMetadataType; using DecodeFunction = std::function& vec)>; struct YCbCr { android_ycbcr yCbCr; int64_t horizontalSubSampling; int64_t verticalSubSampling; }; class GraphicsMapperHidlTest : public ::testing::TestWithParam> { protected: void SetUp() override { ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique(std::get<0>(GetParam()), std::get<1>(GetParam()))); ASSERT_TRUE(mGralloc->hasAllocator()); ASSERT_NE(nullptr, mGralloc->getMapper().get()); mDummyDescriptorInfo.name = "dummy"; mDummyDescriptorInfo.width = 64; mDummyDescriptorInfo.height = 64; mDummyDescriptorInfo.layerCount = 1; mDummyDescriptorInfo.format = PixelFormat::RGBA_8888; mDummyDescriptorInfo.usage = static_cast(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN); mDummyDescriptorInfo.reservedSize = 0; } 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; const auto result = mGralloc->get(bufferHandle, metadataType, &vec); if (metadataType == gralloc4::MetadataType_Smpte2094_10 && result == Error::UNSUPPORTED) { GTEST_SKIP() << "getting metadata for Smpte2094-10 is unsupported"; } ASSERT_EQ(Error::NONE, result); 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"; return; } 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 verifyRGBA8888PlaneLayouts(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) { if (!gralloc4::isStandardPlaneLayoutComponentType(component.type)) { continue; } 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(32, 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); } void verifyBufferDump(const IMapper::BufferDump& bufferDump, const native_handle_t* bufferHandle = nullptr) { std::set foundMetadataTypes; const std::vector metadataDump = bufferDump.metadataDump; for (const auto& dump : metadataDump) { const auto& metadataType = dump.metadataType; const auto& metadata = dump.metadata; if (!gralloc4::isStandardMetadataType(metadataType)) { continue; } StandardMetadataType type = gralloc4::getStandardMetadataTypeValue(metadataType); if (sRequiredMetadataTypes.find(type) == sRequiredMetadataTypes.end()) { continue; } ASSERT_EQ(foundMetadataTypes.find(type), foundMetadataTypes.end()); foundMetadataTypes.insert(type); if (!bufferHandle) { continue; } hidl_vec metadataFromGet; ASSERT_EQ(Error::NONE, mGralloc->get(bufferHandle, metadataType, &metadataFromGet)); ASSERT_EQ(metadataFromGet, metadata); } EXPECT_EQ(sRequiredMetadataTypes, foundMetadataTypes); } void getAndroidYCbCr(const native_handle_t* bufferHandle, uint8_t* data, android_ycbcr* outYCbCr, int64_t* hSubsampling, int64_t* vSubsampling) { 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)); outYCbCr->y = nullptr; outYCbCr->cb = nullptr; outYCbCr->cr = nullptr; outYCbCr->ystride = 0; outYCbCr->cstride = 0; outYCbCr->chroma_step = 0; for (const auto& planeLayout : planeLayouts) { for (const auto& planeLayoutComponent : planeLayout.components) { if (!gralloc4::isStandardPlaneLayoutComponentType(planeLayoutComponent.type)) { continue; } ASSERT_EQ(0, planeLayoutComponent.offsetInBits % 8); uint8_t* tmpData = data + planeLayout.offsetInBytes + bitsToBytes(planeLayoutComponent.offsetInBits); uint64_t sampleIncrementInBytes; auto type = static_cast(planeLayoutComponent.type.value); switch (type) { case PlaneLayoutComponentType::Y: ASSERT_EQ(nullptr, outYCbCr->y); ASSERT_EQ(8, planeLayoutComponent.sizeInBits); ASSERT_EQ(8, planeLayout.sampleIncrementInBits); outYCbCr->y = tmpData; outYCbCr->ystride = planeLayout.strideInBytes; break; case PlaneLayoutComponentType::CB: case PlaneLayoutComponentType::CR: ASSERT_EQ(0, planeLayout.sampleIncrementInBits % 8); sampleIncrementInBytes = planeLayout.sampleIncrementInBits / 8; ASSERT_TRUE(sampleIncrementInBytes == 1 || sampleIncrementInBytes == 2); if (outYCbCr->cstride == 0 && outYCbCr->chroma_step == 0) { outYCbCr->cstride = planeLayout.strideInBytes; outYCbCr->chroma_step = sampleIncrementInBytes; } else { ASSERT_EQ(outYCbCr->cstride, planeLayout.strideInBytes); ASSERT_EQ(outYCbCr->chroma_step, sampleIncrementInBytes); } if (*hSubsampling == 0 && *vSubsampling == 0) { *hSubsampling = planeLayout.horizontalSubsampling; *vSubsampling = planeLayout.verticalSubsampling; } else { ASSERT_EQ(*hSubsampling, planeLayout.horizontalSubsampling); ASSERT_EQ(*vSubsampling, planeLayout.verticalSubsampling); } if (type == PlaneLayoutComponentType::CB) { ASSERT_EQ(nullptr, outYCbCr->cb); outYCbCr->cb = tmpData; } else { ASSERT_EQ(nullptr, outYCbCr->cr); outYCbCr->cr = tmpData; } break; default: break; }; } } ASSERT_NE(nullptr, outYCbCr->y); ASSERT_NE(nullptr, outYCbCr->cb); ASSERT_NE(nullptr, outYCbCr->cr); } YCbCr getAndroidYCbCr_P010(const native_handle_t* bufferHandle, uint8_t* data) { YCbCr yCbCr_P010; hidl_vec vec; EXPECT_EQ(Error::NONE, mGralloc->get(bufferHandle, gralloc4::MetadataType_PlaneLayouts, &vec)); std::vector planeLayouts; EXPECT_EQ(NO_ERROR, gralloc4::decodePlaneLayouts(vec, &planeLayouts)); EXPECT_EQ(2, planeLayouts.size()); EXPECT_EQ(1, planeLayouts[0].components.size()); EXPECT_EQ(2, planeLayouts[1].components.size()); yCbCr_P010.yCbCr.y = nullptr; yCbCr_P010.yCbCr.cb = nullptr; yCbCr_P010.yCbCr.cr = nullptr; yCbCr_P010.yCbCr.ystride = 0; yCbCr_P010.yCbCr.cstride = 0; yCbCr_P010.yCbCr.chroma_step = 0; int64_t cb_offset = 0; int64_t cr_offset = 0; for (const auto& planeLayout : planeLayouts) { for (const auto& planeLayoutComponent : planeLayout.components) { if (!gralloc4::isStandardPlaneLayoutComponentType(planeLayoutComponent.type)) { continue; } uint8_t* tmpData = data + planeLayout.offsetInBytes + bitsToBytes(planeLayoutComponent.offsetInBits); uint64_t sampleIncrementInBytes = 0; auto type = static_cast(planeLayoutComponent.type.value); switch (type) { case PlaneLayoutComponentType::Y: // For specs refer: // https://docs.microsoft.com/en-us/windows/win32/medfound/10-bit-and-16-bit-yuv-video-formats EXPECT_EQ(6, planeLayoutComponent.offsetInBits); EXPECT_EQ(nullptr, yCbCr_P010.yCbCr.y); EXPECT_EQ(10, planeLayoutComponent.sizeInBits); EXPECT_EQ(16, planeLayout.sampleIncrementInBits); yCbCr_P010.yCbCr.y = tmpData; yCbCr_P010.yCbCr.ystride = planeLayout.strideInBytes; break; case PlaneLayoutComponentType::CB: case PlaneLayoutComponentType::CR: sampleIncrementInBytes = bitsToBytes(planeLayout.sampleIncrementInBits); EXPECT_EQ(4, sampleIncrementInBytes); if (yCbCr_P010.yCbCr.cstride == 0 && yCbCr_P010.yCbCr.chroma_step == 0) { yCbCr_P010.yCbCr.cstride = planeLayout.strideInBytes; yCbCr_P010.yCbCr.chroma_step = sampleIncrementInBytes; } else { EXPECT_EQ(yCbCr_P010.yCbCr.cstride, planeLayout.strideInBytes); EXPECT_EQ(yCbCr_P010.yCbCr.chroma_step, sampleIncrementInBytes); } if (yCbCr_P010.horizontalSubSampling == 0 && yCbCr_P010.verticalSubSampling == 0) { yCbCr_P010.horizontalSubSampling = planeLayout.horizontalSubsampling; yCbCr_P010.verticalSubSampling = planeLayout.verticalSubsampling; } else { EXPECT_EQ(yCbCr_P010.horizontalSubSampling, planeLayout.horizontalSubsampling); EXPECT_EQ(yCbCr_P010.verticalSubSampling, planeLayout.verticalSubsampling); } if (type == PlaneLayoutComponentType::CB) { EXPECT_EQ(nullptr, yCbCr_P010.yCbCr.cb); yCbCr_P010.yCbCr.cb = tmpData; cb_offset = planeLayoutComponent.offsetInBits; } else { EXPECT_EQ(nullptr, yCbCr_P010.yCbCr.cr); yCbCr_P010.yCbCr.cr = tmpData; cr_offset = planeLayoutComponent.offsetInBits; } break; default: break; }; } } EXPECT_EQ(cb_offset + bytesToBits(2), cr_offset); EXPECT_NE(nullptr, yCbCr_P010.yCbCr.y); EXPECT_NE(nullptr, yCbCr_P010.yCbCr.cb); EXPECT_NE(nullptr, yCbCr_P010.yCbCr.cr); return yCbCr_P010; } void fillRGBA8888(uint8_t* data, uint32_t height, size_t strideInBytes, size_t widthInBytes, uint32_t seed = 0) { for (uint32_t y = 0; y < height; y++) { memset(data, y + seed, widthInBytes); data += strideInBytes; } } void verifyRGBA8888(const native_handle_t* bufferHandle, const uint8_t* data, uint32_t height, size_t strideInBytes, size_t widthInBytes, uint32_t seed = 0) { 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)); verifyRGBA8888PlaneLayouts(planeLayouts); for (uint32_t y = 0; y < height; y++) { for (size_t i = 0; i < widthInBytes; i++) { EXPECT_EQ(static_cast(y + seed), data[i]); } data += strideInBytes; } } void traverseYCbCrData(const android_ycbcr& yCbCr, int32_t width, int32_t height, int64_t hSubsampling, int64_t vSubsampling, std::function traverseFuncion) { auto yData = static_cast(yCbCr.y); auto cbData = static_cast(yCbCr.cb); auto crData = static_cast(yCbCr.cr); auto yStride = yCbCr.ystride; auto cStride = yCbCr.cstride; auto chromaStep = yCbCr.chroma_step; for (uint32_t y = 0; y < height; y++) { for (uint32_t x = 0; x < width; x++) { auto val = static_cast(height * y + x); traverseFuncion(yData + yStride * y + x, val); if (y % vSubsampling == 0 && x % hSubsampling == 0) { uint32_t subSampleX = x / hSubsampling; uint32_t subSampleY = y / vSubsampling; const auto subSampleOffset = cStride * subSampleY + chromaStep * subSampleX; const auto subSampleVal = static_cast(height * subSampleY + subSampleX); traverseFuncion(cbData + subSampleOffset, subSampleVal); traverseFuncion(crData + subSampleOffset, subSampleVal + 1); } } } } void fillYCbCrData(const android_ycbcr& yCbCr, int32_t width, int32_t height, int64_t hSubsampling, int64_t vSubsampling) { traverseYCbCrData(yCbCr, width, height, hSubsampling, vSubsampling, [](auto address, auto fillingData) { *address = fillingData; }); } void verifyYCbCrData(const android_ycbcr& yCbCr, int32_t width, int32_t height, int64_t hSubsampling, int64_t vSubsampling) { traverseYCbCrData( yCbCr, width, height, hSubsampling, vSubsampling, [](auto address, auto expectedData) { EXPECT_EQ(*address, expectedData); }); } bool isEqual(float a, float b) { return abs(a - b) < 0.0001; } uint64_t bitsToBytes(int64_t bits) { return bits / 8; } uint64_t bytesToBits(int64_t bytes) { return bytes * 8; } std::unique_ptr mGralloc; IMapper::BufferDescriptorInfo mDummyDescriptorInfo{}; static const std::set sRequiredMetadataTypes; }; const std::set GraphicsMapperHidlTest::sRequiredMetadataTypes{ StandardMetadataType::BUFFER_ID, StandardMetadataType::NAME, StandardMetadataType::WIDTH, StandardMetadataType::HEIGHT, StandardMetadataType::LAYER_COUNT, StandardMetadataType::PIXEL_FORMAT_REQUESTED, StandardMetadataType::PIXEL_FORMAT_FOURCC, StandardMetadataType::PIXEL_FORMAT_MODIFIER, StandardMetadataType::USAGE, StandardMetadataType::ALLOCATION_SIZE, StandardMetadataType::PROTECTED_CONTENT, StandardMetadataType::COMPRESSION, StandardMetadataType::INTERLACED, StandardMetadataType::CHROMA_SITING, StandardMetadataType::PLANE_LAYOUTS, StandardMetadataType::DATASPACE, StandardMetadataType::BLEND_MODE, }; /** * Test IAllocator::allocate with valid buffer descriptors. */ TEST_P(GraphicsMapperHidlTest, AllocatorAllocate) { BufferDescriptor descriptor; ASSERT_NO_FATAL_FAILURE(descriptor = mGralloc->createDescriptor(mDummyDescriptorInfo)); for (uint32_t count = 0; count < 5; count++) { std::vector bufferHandles; uint32_t stride; ASSERT_NO_FATAL_FAILURE(bufferHandles = mGralloc->allocate(descriptor, count, false, Tolerance::kToleranceStrict, &stride)); if (count >= 1) { EXPECT_LE(mDummyDescriptorInfo.width, stride) << "invalid buffer stride"; } for (auto bufferHandle : bufferHandles) { mGralloc->freeBuffer(bufferHandle); } } } /** * Test IAllocator::allocate with invalid buffer descriptors. */ TEST_P(GraphicsMapperHidlTest, AllocatorAllocateNegative) { // this assumes any valid descriptor is non-empty BufferDescriptor descriptor; mGralloc->rawAllocate(descriptor, 1, [&](const auto& tmpError, const auto&, const auto&) { EXPECT_EQ(Error::BAD_DESCRIPTOR, tmpError); }); } /** * Test IAllocator::allocate does not leak. */ TEST_P(GraphicsMapperHidlTest, AllocatorAllocateNoLeak) { auto info = mDummyDescriptorInfo; info.width = 1024; info.height = 1024; for (int i = 0; i < 2048; i++) { auto bufferHandle = mGralloc->allocate(info, false); mGralloc->freeBuffer(bufferHandle); } } /** * Test that IAllocator::allocate is thread-safe. */ TEST_P(GraphicsMapperHidlTest, AllocatorAllocateThreaded) { BufferDescriptor descriptor; ASSERT_NO_FATAL_FAILURE(descriptor = mGralloc->createDescriptor(mDummyDescriptorInfo)); std::atomic timeUp(false); std::atomic allocationCount(0); auto threadLoop = [&]() { while (!timeUp) { mGralloc->rawAllocate(descriptor, 1, [&](const auto&, const auto&, const auto&) { allocationCount++; }); } }; std::vector threads; for (int i = 0; i < 8; i++) { threads.push_back(std::thread(threadLoop)); } std::this_thread::sleep_for(std::chrono::seconds(3)); timeUp = true; LOG(VERBOSE) << "Made " << allocationCount << " threaded allocations"; for (auto& thread : threads) { thread.join(); } } /** * Test IMapper::createDescriptor with valid descriptor info. */ TEST_P(GraphicsMapperHidlTest, CreateDescriptorBasic) { ASSERT_NO_FATAL_FAILURE(mGralloc->createDescriptor(mDummyDescriptorInfo)); } /** * Test IMapper::createDescriptor with invalid descriptor info. */ TEST_P(GraphicsMapperHidlTest, CreateDescriptorNegative) { auto info = mDummyDescriptorInfo; info.width = 0; mGralloc->getMapper()->createDescriptor(info, [&](const auto& tmpError, const auto&) { EXPECT_EQ(Error::BAD_VALUE, tmpError) << "createDescriptor did not fail with BAD_VALUE"; }); } /** * Test IMapper::importBuffer and IMapper::freeBuffer with allocated buffers. */ TEST_P(GraphicsMapperHidlTest, ImportFreeBufferBasic) { const native_handle_t* bufferHandle; ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(mDummyDescriptorInfo, true)); ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(bufferHandle)); } /** * Test IMapper::importBuffer and IMapper::freeBuffer with cloned buffers. */ TEST_P(GraphicsMapperHidlTest, ImportFreeBufferClone) { const native_handle_t* clonedBufferHandle; ASSERT_NO_FATAL_FAILURE(clonedBufferHandle = mGralloc->allocate(mDummyDescriptorInfo, false)); // A cloned handle is a raw handle. Check that we can import it multiple // times. const native_handle_t* importedBufferHandles[2]; ASSERT_NO_FATAL_FAILURE(importedBufferHandles[0] = mGralloc->importBuffer(clonedBufferHandle)); ASSERT_NO_FATAL_FAILURE(importedBufferHandles[1] = mGralloc->importBuffer(clonedBufferHandle)); ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(importedBufferHandles[0])); ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(importedBufferHandles[1])); ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(clonedBufferHandle)); } /** * Test IMapper::importBuffer and IMapper::freeBuffer cross mapper instances. */ TEST_P(GraphicsMapperHidlTest, ImportFreeBufferSingleton) { const native_handle_t* rawHandle; ASSERT_NO_FATAL_FAILURE(rawHandle = mGralloc->allocate(mDummyDescriptorInfo, false)); native_handle_t* importedHandle = nullptr; mGralloc->getMapper()->importBuffer(rawHandle, [&](const auto& tmpError, const auto& buffer) { ASSERT_EQ(Error::NONE, tmpError); importedHandle = static_cast(buffer); }); // free the imported handle with another mapper std::unique_ptr anotherGralloc; ASSERT_NO_FATAL_FAILURE(anotherGralloc = std::make_unique(std::get<0>(GetParam()), std::get<1>(GetParam()))); Error error = mGralloc->getMapper()->freeBuffer(importedHandle); ASSERT_EQ(Error::NONE, error); ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(rawHandle)); } /** * Test IMapper::importBuffer and IMapper::freeBuffer do not leak. */ TEST_P(GraphicsMapperHidlTest, ImportFreeBufferNoLeak) { auto info = mDummyDescriptorInfo; info.width = 1024; info.height = 1024; for (int i = 0; i < 2048; i++) { auto bufferHandle = mGralloc->allocate(info, true); mGralloc->freeBuffer(bufferHandle); } } /** * Test IMapper::importBuffer with invalid buffers. */ TEST_P(GraphicsMapperHidlTest, ImportBufferNegative) { native_handle_t* invalidHandle = nullptr; mGralloc->getMapper()->importBuffer(invalidHandle, [&](const auto& tmpError, const auto&) { EXPECT_EQ(Error::BAD_BUFFER, tmpError) << "importBuffer with nullptr did not fail with BAD_BUFFER"; }); invalidHandle = native_handle_create(0, 0); mGralloc->getMapper()->importBuffer(invalidHandle, [&](const auto& tmpError, const auto&) { EXPECT_EQ(Error::BAD_BUFFER, tmpError) << "importBuffer with invalid handle did not fail with BAD_BUFFER"; }); native_handle_delete(invalidHandle); } /** * Test IMapper::freeBuffer with invalid buffers. */ TEST_P(GraphicsMapperHidlTest, FreeBufferNegative) { native_handle_t* invalidHandle = nullptr; Error error = mGralloc->getMapper()->freeBuffer(invalidHandle); EXPECT_EQ(Error::BAD_BUFFER, error) << "freeBuffer with nullptr did not fail with BAD_BUFFER"; invalidHandle = native_handle_create(0, 0); error = mGralloc->getMapper()->freeBuffer(invalidHandle); EXPECT_EQ(Error::BAD_BUFFER, error) << "freeBuffer with invalid handle did not fail with BAD_BUFFER"; native_handle_delete(invalidHandle); const native_handle_t* clonedBufferHandle; ASSERT_NO_FATAL_FAILURE(clonedBufferHandle = mGralloc->allocate(mDummyDescriptorInfo, false)); error = mGralloc->getMapper()->freeBuffer(const_cast(clonedBufferHandle)); EXPECT_EQ(Error::BAD_BUFFER, error) << "freeBuffer with un-imported handle did not fail with BAD_BUFFER"; mGralloc->freeBuffer(clonedBufferHandle); } /** * Test IMapper::lock and IMapper::unlock. */ TEST_P(GraphicsMapperHidlTest, LockUnlockBasic) { const auto& info = mDummyDescriptorInfo; const native_handle_t* bufferHandle; uint32_t stride; ASSERT_NO_FATAL_FAILURE( bufferHandle = mGralloc->allocate(info, true, Tolerance::kToleranceStrict, &stride)); // lock buffer for writing const IMapper::Rect region{0, 0, static_cast(info.width), static_cast(info.height)}; unique_fd fence; uint8_t* data; ASSERT_NO_FATAL_FAILURE(data = static_cast(mGralloc->lock(bufferHandle, info.usage, region, fence.release()))); // RGBA_8888 fillRGBA8888(data, info.height, stride * 4, info.width * 4); ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle))); // lock again for reading ASSERT_NO_FATAL_FAILURE(data = static_cast(mGralloc->lock(bufferHandle, info.usage, region, fence.release()))); ASSERT_NO_FATAL_FAILURE( verifyRGBA8888(bufferHandle, data, info.height, stride * 4, info.width * 4)); ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle))); } /** * Test multiple operations associated with different color formats */ TEST_P(GraphicsMapperHidlTest, Lock_YCRCB_420_SP) { auto info = mDummyDescriptorInfo; info.format = PixelFormat::YCRCB_420_SP; const native_handle_t* bufferHandle; uint32_t stride; ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate( info, true, Tolerance::kToleranceUnSupported, &stride)); if (bufferHandle == nullptr) { GTEST_SUCCEED() << "YCRCB_420_SP format is unsupported"; return; } // lock buffer for writing const IMapper::Rect region{0, 0, static_cast(info.width), static_cast(info.height)}; unique_fd fence; uint8_t* data; ASSERT_NO_FATAL_FAILURE(data = static_cast(mGralloc->lock(bufferHandle, info.usage, region, fence.release()))); android_ycbcr yCbCr; int64_t hSubsampling = 0; int64_t vSubsampling = 0; ASSERT_NO_FATAL_FAILURE( getAndroidYCbCr(bufferHandle, data, &yCbCr, &hSubsampling, &vSubsampling)); constexpr uint32_t kCbCrSubSampleFactor = 2; ASSERT_EQ(kCbCrSubSampleFactor, hSubsampling); ASSERT_EQ(kCbCrSubSampleFactor, vSubsampling); auto cbData = static_cast(yCbCr.cb); auto crData = static_cast(yCbCr.cr); ASSERT_EQ(crData + 1, cbData); ASSERT_EQ(2, yCbCr.chroma_step); fillYCbCrData(yCbCr, info.width, info.height, hSubsampling, vSubsampling); ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle))); // lock again for reading ASSERT_NO_FATAL_FAILURE(data = static_cast(mGralloc->lock(bufferHandle, info.usage, region, fence.release()))); ASSERT_NO_FATAL_FAILURE( getAndroidYCbCr(bufferHandle, data, &yCbCr, &hSubsampling, &vSubsampling)); verifyYCbCrData(yCbCr, info.width, info.height, hSubsampling, vSubsampling); ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle))); } TEST_P(GraphicsMapperHidlTest, YV12SubsampleMetadata) { auto info = mDummyDescriptorInfo; info.format = PixelFormat::YV12; const native_handle_t* bufferHandle; uint32_t stride; ASSERT_NO_FATAL_FAILURE( bufferHandle = mGralloc->allocate(info, true, Tolerance::kToleranceStrict, &stride)); const IMapper::Rect region{0, 0, static_cast(info.width), static_cast(info.height)}; unique_fd fence; ASSERT_NO_FATAL_FAILURE(mGralloc->lock(bufferHandle, info.usage, region, fence.release())); 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_EQ(3, planeLayouts.size()); auto yPlane = planeLayouts[0]; auto crPlane = planeLayouts[1]; auto cbPlane = planeLayouts[2]; constexpr uint32_t kCbCrSubSampleFactor = 2; EXPECT_EQ(kCbCrSubSampleFactor, crPlane.horizontalSubsampling); EXPECT_EQ(kCbCrSubSampleFactor, crPlane.verticalSubsampling); EXPECT_EQ(kCbCrSubSampleFactor, cbPlane.horizontalSubsampling); EXPECT_EQ(kCbCrSubSampleFactor, cbPlane.verticalSubsampling); const long chromaSampleWidth = info.width / kCbCrSubSampleFactor; const long chromaSampleHeight = info.height / kCbCrSubSampleFactor; EXPECT_EQ(info.width, yPlane.widthInSamples); EXPECT_EQ(info.height, yPlane.heightInSamples); EXPECT_EQ(chromaSampleWidth, crPlane.widthInSamples); EXPECT_EQ(chromaSampleHeight, crPlane.heightInSamples); EXPECT_EQ(chromaSampleWidth, cbPlane.widthInSamples); EXPECT_EQ(chromaSampleHeight, cbPlane.heightInSamples); EXPECT_LE(crPlane.widthInSamples, crPlane.strideInBytes); EXPECT_LE(cbPlane.widthInSamples, cbPlane.strideInBytes); ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle))); } TEST_P(GraphicsMapperHidlTest, Lock_YV12) { auto info = mDummyDescriptorInfo; info.format = PixelFormat::YV12; const native_handle_t* bufferHandle; uint32_t stride; ASSERT_NO_FATAL_FAILURE( bufferHandle = mGralloc->allocate(info, true, Tolerance::kToleranceStrict, &stride)); // lock buffer for writing const IMapper::Rect region{0, 0, static_cast(info.width), static_cast(info.height)}; unique_fd fence; uint8_t* data; ASSERT_NO_FATAL_FAILURE(data = static_cast(mGralloc->lock(bufferHandle, info.usage, region, fence.release()))); android_ycbcr yCbCr; int64_t hSubsampling = 0; int64_t vSubsampling = 0; ASSERT_NO_FATAL_FAILURE( getAndroidYCbCr(bufferHandle, data, &yCbCr, &hSubsampling, &vSubsampling)); constexpr uint32_t kCbCrSubSampleFactor = 2; ASSERT_EQ(kCbCrSubSampleFactor, hSubsampling); ASSERT_EQ(kCbCrSubSampleFactor, vSubsampling); auto cbData = static_cast(yCbCr.cb); auto crData = static_cast(yCbCr.cr); ASSERT_EQ(crData + yCbCr.cstride * info.height / vSubsampling, cbData); ASSERT_EQ(1, yCbCr.chroma_step); fillYCbCrData(yCbCr, info.width, info.height, hSubsampling, vSubsampling); ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle))); // lock again for reading ASSERT_NO_FATAL_FAILURE(data = static_cast(mGralloc->lock(bufferHandle, info.usage, region, fence.release()))); ASSERT_NO_FATAL_FAILURE( getAndroidYCbCr(bufferHandle, data, &yCbCr, &hSubsampling, &vSubsampling)); verifyYCbCrData(yCbCr, info.width, info.height, hSubsampling, vSubsampling); ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle))); } TEST_P(GraphicsMapperHidlTest, Lock_YCBCR_420_888) { auto info = mDummyDescriptorInfo; info.format = PixelFormat::YCBCR_420_888; const native_handle_t* bufferHandle; uint32_t stride; ASSERT_NO_FATAL_FAILURE( bufferHandle = mGralloc->allocate(info, true, Tolerance::kToleranceStrict, &stride)); // lock buffer for writing const IMapper::Rect region{0, 0, static_cast(info.width), static_cast(info.height)}; unique_fd fence; uint8_t* data; ASSERT_NO_FATAL_FAILURE(data = static_cast(mGralloc->lock(bufferHandle, info.usage, region, fence.release()))); android_ycbcr yCbCr; int64_t hSubsampling = 0; int64_t vSubsampling = 0; ASSERT_NO_FATAL_FAILURE( getAndroidYCbCr(bufferHandle, data, &yCbCr, &hSubsampling, &vSubsampling)); constexpr uint32_t kCbCrSubSampleFactor = 2; ASSERT_EQ(kCbCrSubSampleFactor, hSubsampling); ASSERT_EQ(kCbCrSubSampleFactor, vSubsampling); fillYCbCrData(yCbCr, info.width, info.height, hSubsampling, vSubsampling); ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle))); // lock again for reading ASSERT_NO_FATAL_FAILURE(data = static_cast(mGralloc->lock(bufferHandle, info.usage, region, fence.release()))); ASSERT_NO_FATAL_FAILURE( getAndroidYCbCr(bufferHandle, data, &yCbCr, &hSubsampling, &vSubsampling)); verifyYCbCrData(yCbCr, info.width, info.height, hSubsampling, vSubsampling); ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle))); } TEST_P(GraphicsMapperHidlTest, Lock_RAW10) { auto info = mDummyDescriptorInfo; info.format = PixelFormat::RAW10; const native_handle_t* bufferHandle; uint32_t stride; ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate( info, true, Tolerance::kToleranceUnSupported, &stride)); if (bufferHandle == nullptr) { GTEST_SUCCEED() << "RAW10 format is unsupported"; return; } const IMapper::Rect region{0, 0, static_cast(info.width), static_cast(info.height)}; unique_fd fence; ASSERT_NO_FATAL_FAILURE(mGralloc->lock(bufferHandle, info.usage, region, fence.release())); 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_EQ(1, planeLayouts.size()); auto planeLayout = planeLayouts[0]; EXPECT_EQ(0, planeLayout.sampleIncrementInBits); EXPECT_EQ(1, planeLayout.horizontalSubsampling); EXPECT_EQ(1, planeLayout.verticalSubsampling); ASSERT_EQ(1, planeLayout.components.size()); auto planeLayoutComponent = planeLayout.components[0]; EXPECT_EQ(PlaneLayoutComponentType::RAW, static_cast(planeLayoutComponent.type.value)); EXPECT_EQ(0, planeLayoutComponent.offsetInBits % 8); ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle))); } TEST_P(GraphicsMapperHidlTest, Lock_RAW12) { auto info = mDummyDescriptorInfo; info.format = PixelFormat::RAW12; const native_handle_t* bufferHandle; uint32_t stride; ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate( info, true, Tolerance::kToleranceUnSupported, &stride)); if (bufferHandle == nullptr) { GTEST_SUCCEED() << "RAW12 format is unsupported"; return; } const IMapper::Rect region{0, 0, static_cast(info.width), static_cast(info.height)}; unique_fd fence; ASSERT_NO_FATAL_FAILURE(mGralloc->lock(bufferHandle, info.usage, region, fence.release())); 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_EQ(1, planeLayouts.size()); auto planeLayout = planeLayouts[0]; EXPECT_EQ(0, planeLayout.sampleIncrementInBits); EXPECT_EQ(1, planeLayout.horizontalSubsampling); EXPECT_EQ(1, planeLayout.verticalSubsampling); ASSERT_EQ(1, planeLayout.components.size()); auto planeLayoutComponent = planeLayout.components[0]; EXPECT_EQ(PlaneLayoutComponentType::RAW, static_cast(planeLayoutComponent.type.value)); EXPECT_EQ(0, planeLayoutComponent.offsetInBits % 8); ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle))); } TEST_P(GraphicsMapperHidlTest, Lock_YCBCR_P010) { if (base::GetIntProperty("ro.vendor.api_level", __ANDROID_API_FUTURE__) < __ANDROID_API_T__) { GTEST_SKIP() << "Old vendor grallocs may not support P010"; } auto info = mDummyDescriptorInfo; info.format = PixelFormat::YCBCR_P010; uint32_t stride; const native_handle_t* bufferHandle = mGralloc->allocate(info, true, Tolerance::kToleranceStrict, &stride); if (::testing::Test::IsSkipped()) { GTEST_SKIP(); } const IMapper::Rect region{0, 0, static_cast(info.width), static_cast(info.height)}; unique_fd fence; uint8_t* data; ASSERT_NO_FATAL_FAILURE(data = static_cast(mGralloc->lock(bufferHandle, info.usage, region, fence.release()))); YCbCr yCbCr; ASSERT_NO_FATAL_FAILURE(yCbCr = getAndroidYCbCr_P010(bufferHandle, data)); constexpr uint32_t kCbCrSubSampleFactor = 2; ASSERT_EQ(kCbCrSubSampleFactor, yCbCr.horizontalSubSampling); ASSERT_EQ(kCbCrSubSampleFactor, yCbCr.verticalSubSampling); ASSERT_EQ(0, info.height % 2); // fill the data fillYCbCrData(yCbCr.yCbCr, info.width, info.height, yCbCr.horizontalSubSampling, yCbCr.verticalSubSampling); // verify the YCbCr data verifyYCbCrData(yCbCr.yCbCr, info.width, info.height, yCbCr.horizontalSubSampling, yCbCr.verticalSubSampling); ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle))); } /** * Test IMapper::unlock with bad access region */ TEST_P(GraphicsMapperHidlTest, LockBadAccessRegion) { const auto& info = mDummyDescriptorInfo; const native_handle_t* bufferHandle; ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(info, true)); const IMapper::Rect accessRegion{0, 0, static_cast(info.width * 2), static_cast(info.height * 2)}; int acquireFence = -1; NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0); hidl_handle acquireFenceHandle; if (acquireFence >= 0) { auto h = native_handle_init(acquireFenceStorage, 1, 0); h->data[0] = acquireFence; acquireFenceHandle = h; } auto buffer = const_cast(bufferHandle); mGralloc->getMapper()->lock(buffer, info.usage, accessRegion, acquireFenceHandle, [&](const auto& tmpError, const auto& /*tmpData*/) { EXPECT_EQ(Error::BAD_VALUE, tmpError) << "locking with a bad access region should fail"; }); if (::testing::Test::HasFailure()) { if (acquireFence >= 0) { close(acquireFence); } int releaseFence = -1; ASSERT_NO_FATAL_FAILURE(releaseFence = mGralloc->unlock(bufferHandle)); if (releaseFence >= 0) { close(releaseFence); } } } /** * Test IMapper::unlock with invalid buffers. */ TEST_P(GraphicsMapperHidlTest, UnlockNegative) { native_handle_t* invalidHandle = nullptr; mGralloc->getMapper()->unlock(invalidHandle, [&](const auto& tmpError, const auto&) { EXPECT_EQ(Error::BAD_BUFFER, tmpError) << "unlock with nullptr did not fail with BAD_BUFFER"; }); invalidHandle = native_handle_create(0, 0); mGralloc->getMapper()->unlock(invalidHandle, [&](const auto& tmpError, const auto&) { EXPECT_EQ(Error::BAD_BUFFER, tmpError) << "unlock with invalid handle did not fail with BAD_BUFFER"; }); native_handle_delete(invalidHandle); ASSERT_NO_FATAL_FAILURE(invalidHandle = const_cast( mGralloc->allocate(mDummyDescriptorInfo, false))); mGralloc->getMapper()->unlock(invalidHandle, [&](const auto& tmpError, const auto&) { EXPECT_EQ(Error::BAD_BUFFER, tmpError) << "unlock with un-imported handle did not fail with BAD_BUFFER"; }); mGralloc->freeBuffer(invalidHandle); // disabled as it fails on many existing drivers #if 0 ASSERT_NO_FATAL_FAILURE(invalidHandle = const_cast( mGralloc->allocate(mDummyDescriptorInfo, true))); mGralloc->getMapper()->unlock( invalidHandle, [&](const auto& tmpError, const auto&) { EXPECT_EQ(Error::BAD_BUFFER, tmpError) << "unlock with unlocked handle did not fail with BAD_BUFFER"; }); mGralloc->freeBuffer(invalidHandle); #endif } /** * Test IMapper::flush and IMapper::reread. */ TEST_P(GraphicsMapperHidlTest, FlushRereadBasic) { const auto& info = mDummyDescriptorInfo; const native_handle_t* rawHandle; uint32_t stride; ASSERT_NO_FATAL_FAILURE(rawHandle = mGralloc->allocate(mDummyDescriptorInfo, false, Tolerance::kToleranceStrict, &stride)); const native_handle_t* writeBufferHandle; const native_handle_t* readBufferHandle; ASSERT_NO_FATAL_FAILURE(writeBufferHandle = mGralloc->importBuffer(rawHandle)); ASSERT_NO_FATAL_FAILURE(readBufferHandle = mGralloc->importBuffer(rawHandle)); // lock buffer for writing const IMapper::Rect region{0, 0, static_cast(info.width), static_cast(info.height)}; uint8_t* writeData; ASSERT_NO_FATAL_FAILURE( writeData = static_cast(mGralloc->lock( writeBufferHandle, static_cast(BufferUsage::CPU_WRITE_OFTEN), region, -1))); uint8_t* readData; ASSERT_NO_FATAL_FAILURE( readData = static_cast(mGralloc->lock( readBufferHandle, static_cast(BufferUsage::CPU_READ_OFTEN), region, -1))); fillRGBA8888(writeData, info.height, stride * 4, info.width * 4); unique_fd fence; ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->flushLockedBuffer(writeBufferHandle))); if (fence >= 0) { ASSERT_EQ(0, sync_wait(fence, 3500)); } ASSERT_NO_FATAL_FAILURE(mGralloc->rereadLockedBuffer(readBufferHandle)); ASSERT_NO_FATAL_FAILURE( verifyRGBA8888(readBufferHandle, readData, info.height, stride * 4, info.width * 4)); ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(readBufferHandle))); ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(writeBufferHandle))); } /** * Test IMapper::flushLockedBuffer with bad buffer */ TEST_P(GraphicsMapperHidlTest, FlushLockedBufferBadBuffer) { ASSERT_NO_FATAL_FAILURE(mGralloc->getMapper()->flushLockedBuffer( nullptr, [&](const auto& tmpError, const auto& /*tmpReleaseFence*/) { ASSERT_EQ(Error::BAD_BUFFER, tmpError); })); } /** * Test IMapper::rereadLockedBuffer with bad buffer */ TEST_P(GraphicsMapperHidlTest, RereadLockedBufferBadBuffer) { ASSERT_EQ(Error::BAD_BUFFER, mGralloc->getMapper()->rereadLockedBuffer(nullptr)); } /** * Test IMapper::isSupported with required format RGBA_8888 */ TEST_P(GraphicsMapperHidlTest, IsSupportedRGBA8888) { const auto& info = mDummyDescriptorInfo; bool supported = false; ASSERT_NO_FATAL_FAILURE(supported = mGralloc->isSupported(info)); ASSERT_TRUE(supported); } /** * Test IMapper::isSupported with required format YV12 */ TEST_P(GraphicsMapperHidlTest, IsSupportedYV12) { auto info = mDummyDescriptorInfo; info.format = PixelFormat::YV12; bool supported = false; ASSERT_NO_FATAL_FAILURE(supported = mGralloc->isSupported(info)); ASSERT_TRUE(supported); } /** * Test IMapper::isSupported with optional format Y16 */ TEST_P(GraphicsMapperHidlTest, IsSupportedY16) { auto info = mDummyDescriptorInfo; info.format = PixelFormat::Y16; bool supported = false; ASSERT_NO_FATAL_FAILURE(supported = mGralloc->isSupported(info)); } /** * Test IMapper::isSupported with optional format R_8 */ TEST_P(GraphicsMapperHidlTest, IsSupportedR8) { auto info = mDummyDescriptorInfo; info.format = static_cast( aidl::android::hardware::graphics::common::PixelFormat::R_8); bool supported = false; supported = mGralloc->isSupportedNoFailure(info); if (!supported) { GTEST_SUCCEED() << "R_8 is optional; unsupported so skipping allocation test"; return; } BufferDescriptor descriptor; ASSERT_NO_FATAL_FAILURE(descriptor = mGralloc->createDescriptor(info)); constexpr uint32_t count = 1; std::vector bufferHandles; uint32_t stride; ASSERT_NO_FATAL_FAILURE(bufferHandles = mGralloc->allocate(descriptor, count, false, Tolerance::kToleranceStrict, &stride)); EXPECT_LE(info.width, stride) << "invalid buffer stride"; EXPECT_EQ(1u, bufferHandles.size()); for (auto bufferHandle : bufferHandles) { mGralloc->freeBuffer(bufferHandle); } } /** * Test IMapper::get(BufferId) */ TEST_P(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_P(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_P(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_P(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_P(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_P(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_P(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_P(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_P(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_P(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_P(GraphicsMapperHidlTest, GetProtectedContent) { auto info = mDummyDescriptorInfo; info.usage = BufferUsage::PROTECTED | BufferUsage::COMPOSER_OVERLAY; const native_handle_t* bufferHandle = nullptr; bufferHandle = mGralloc->allocate(info, true, Tolerance::kToleranceAllErrors); if (!bufferHandle) { GTEST_SUCCEED() << "unable to allocate protected content"; return; } 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_P(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_P(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_P(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_P(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(verifyRGBA8888PlaneLayouts(planeLayouts)); } /** * Test IMapper::get(Crop) */ TEST_P(GraphicsMapperHidlTest, GetCrop) { auto info = mDummyDescriptorInfo; info.format = PixelFormat::RGBA_8888; info.usage = static_cast(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN); testGet(info, gralloc4::MetadataType_Crop, [](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec& vec) { std::vector crops; ASSERT_EQ(NO_ERROR, gralloc4::decodeCrop(vec, &crops)); EXPECT_EQ(1, crops.size()); }); } /** * Test IMapper::get(Dataspace) */ TEST_P(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_P(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(Smpte2086) */ TEST_P(GraphicsMapperHidlTest, GetSmpte2086) { testGet(mDummyDescriptorInfo, gralloc4::MetadataType_Smpte2086, [](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec& vec) { std::optional smpte2086; ASSERT_EQ(NO_ERROR, gralloc4::decodeSmpte2086(vec, &smpte2086)); EXPECT_FALSE(smpte2086.has_value()); }); } /** * Test IMapper::get(Cta861_3) */ TEST_P(GraphicsMapperHidlTest, GetCta861_3) { testGet(mDummyDescriptorInfo, gralloc4::MetadataType_Cta861_3, [](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec& vec) { std::optional cta861_3; ASSERT_EQ(NO_ERROR, gralloc4::decodeCta861_3(vec, &cta861_3)); EXPECT_FALSE(cta861_3.has_value()); }); } /** * Test IMapper::get(Smpte2094_40) */ TEST_P(GraphicsMapperHidlTest, GetSmpte2094_40) { testGet(mDummyDescriptorInfo, gralloc4::MetadataType_Smpte2094_40, [](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec& vec) { std::optional> smpte2094_40; ASSERT_EQ(NO_ERROR, gralloc4::decodeSmpte2094_40(vec, &smpte2094_40)); EXPECT_FALSE(smpte2094_40.has_value()); }); } /** * Test IMapper::get(Smpte2094_10) */ TEST_P(GraphicsMapperHidlTest, GetSmpte2094_10) { testGet(mDummyDescriptorInfo, gralloc4::MetadataType_Smpte2094_10, [](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec& vec) { std::optional> smpte2094_10; ASSERT_EQ(NO_ERROR, gralloc4::decodeSmpte2094_10(vec, &smpte2094_10)); EXPECT_FALSE(smpte2094_10.has_value()); }); } /** * Test IMapper::get(metadata) with a bad buffer */ TEST_P(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_Crop, &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()); ASSERT_EQ(Error::BAD_BUFFER, mGralloc->get(bufferHandle, gralloc4::MetadataType_Smpte2086, &vec)); ASSERT_EQ(0, vec.size()); ASSERT_EQ(Error::BAD_BUFFER, mGralloc->get(bufferHandle, gralloc4::MetadataType_Cta861_3, &vec)); ASSERT_EQ(0, vec.size()); ASSERT_EQ(Error::BAD_BUFFER, mGralloc->get(bufferHandle, gralloc4::MetadataType_Smpte2094_40, &vec)); ASSERT_EQ(0, vec.size()); ASSERT_EQ(Error::BAD_BUFFER, mGralloc->get(bufferHandle, gralloc4::MetadataType_Smpte2094_10, &vec)); ASSERT_EQ(0, vec.size()); } /** * Test IMapper::get(metadata) for unsupported metadata */ TEST_P(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_P(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_P(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_P(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(AllocationSize) */ TEST_P(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_P(GraphicsMapperHidlTest, SetProtectedContent) { const native_handle_t* bufferHandle = nullptr; auto info = mDummyDescriptorInfo; info.usage = BufferUsage::PROTECTED | BufferUsage::COMPOSER_OVERLAY; bufferHandle = mGralloc->allocate(info, true, Tolerance::kToleranceAllErrors); if (!bufferHandle) { GTEST_SUCCEED() << "unable to allocate protected content"; return; } 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_P(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_P(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_P(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_P(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; 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 = 24; 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; 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"; return; } 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); 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(Crop) */ TEST_P(GraphicsMapperHidlTest, SetCrop) { std::vector crops{{0, 0, 32, 32}}; hidl_vec vec; ASSERT_EQ(NO_ERROR, gralloc4::encodeCrop(crops, &vec)); testSet(mDummyDescriptorInfo, gralloc4::MetadataType_Crop, vec, [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec& vec) { std::vector realCrops; ASSERT_EQ(NO_ERROR, gralloc4::decodeCrop(vec, &realCrops)); ASSERT_EQ(1, realCrops.size()); ASSERT_EQ(crops.front().left, realCrops.front().left); ASSERT_EQ(crops.front().top, realCrops.front().top); ASSERT_EQ(crops.front().right, realCrops.front().right); ASSERT_EQ(crops.front().bottom, realCrops.front().bottom); }); } /** * Test IMapper::set(Dataspace) */ TEST_P(GraphicsMapperHidlTest, SetDataspace) { Dataspace dataspace = Dataspace::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_P(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(Smpte2086) */ TEST_P(GraphicsMapperHidlTest, SetSmpte2086) { /** * DISPLAY_P3 is a color space that uses the DCI_P3 primaries, * the D65 white point and the SRGB transfer functions. * Rendering Intent: Colorimetric * Primaries: * x y * green 0.265 0.690 * blue 0.150 0.060 * red 0.680 0.320 * white (D65) 0.3127 0.3290 */ Smpte2086 smpte2086; smpte2086.primaryRed.x = 0.680; smpte2086.primaryRed.y = 0.320; smpte2086.primaryGreen.x = 0.265; smpte2086.primaryGreen.y = 0.690; smpte2086.primaryBlue.x = 0.150; smpte2086.primaryBlue.y = 0.060; smpte2086.whitePoint.x = 0.3127; smpte2086.whitePoint.y = 0.3290; smpte2086.maxLuminance = 100.0; smpte2086.minLuminance = 0.1; hidl_vec vec; ASSERT_EQ(NO_ERROR, gralloc4::encodeSmpte2086(smpte2086, &vec)); testSet(mDummyDescriptorInfo, gralloc4::MetadataType_Smpte2086, vec, [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec& vec) { std::optional realSmpte2086; ASSERT_EQ(NO_ERROR, gralloc4::decodeSmpte2086(vec, &realSmpte2086)); ASSERT_TRUE(realSmpte2086.has_value()); EXPECT_TRUE(isEqual(smpte2086.primaryRed.x, realSmpte2086->primaryRed.x)); EXPECT_TRUE(isEqual(smpte2086.primaryRed.y, realSmpte2086->primaryRed.y)); EXPECT_TRUE(isEqual(smpte2086.primaryGreen.x, realSmpte2086->primaryGreen.x)); EXPECT_TRUE(isEqual(smpte2086.primaryGreen.y, realSmpte2086->primaryGreen.y)); EXPECT_TRUE(isEqual(smpte2086.primaryBlue.x, realSmpte2086->primaryBlue.x)); EXPECT_TRUE(isEqual(smpte2086.primaryBlue.y, realSmpte2086->primaryBlue.y)); EXPECT_TRUE(isEqual(smpte2086.whitePoint.x, realSmpte2086->whitePoint.x)); EXPECT_TRUE(isEqual(smpte2086.whitePoint.y, realSmpte2086->whitePoint.y)); EXPECT_TRUE(isEqual(smpte2086.maxLuminance, realSmpte2086->maxLuminance)); EXPECT_TRUE(isEqual(smpte2086.minLuminance, realSmpte2086->minLuminance)); }); } /** * Test IMapper::set(Cta8613) */ TEST_P(GraphicsMapperHidlTest, SetCta861_3) { Cta861_3 cta861_3; cta861_3.maxContentLightLevel = 78.0; cta861_3.maxFrameAverageLightLevel = 62.0; hidl_vec vec; ASSERT_EQ(NO_ERROR, gralloc4::encodeCta861_3(cta861_3, &vec)); testSet(mDummyDescriptorInfo, gralloc4::MetadataType_Cta861_3, vec, [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec& vec) { std::optional realCta861_3; ASSERT_EQ(NO_ERROR, gralloc4::decodeCta861_3(vec, &realCta861_3)); ASSERT_TRUE(realCta861_3.has_value()); EXPECT_TRUE( isEqual(cta861_3.maxContentLightLevel, realCta861_3->maxContentLightLevel)); EXPECT_TRUE(isEqual(cta861_3.maxFrameAverageLightLevel, realCta861_3->maxFrameAverageLightLevel)); }); } /** * Test IMapper::set(Smpte2094_40) */ TEST_P(GraphicsMapperHidlTest, SetSmpte2094_40) { hidl_vec vec; testSet(mDummyDescriptorInfo, gralloc4::MetadataType_Smpte2094_40, vec, [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec& vec) { std::optional> realSmpte2094_40; ASSERT_EQ(NO_ERROR, gralloc4::decodeSmpte2094_40(vec, &realSmpte2094_40)); EXPECT_FALSE(realSmpte2094_40.has_value()); }); } /** * Test IMapper::set(Smpte2094_10) */ TEST_P(GraphicsMapperHidlTest, SetSmpte2094_10) { hidl_vec vec; testSet(mDummyDescriptorInfo, gralloc4::MetadataType_Smpte2094_10, vec, [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec& vec) { std::optional> realSmpte2094_10; ASSERT_EQ(NO_ERROR, gralloc4::decodeSmpte2094_10(vec, &realSmpte2094_10)); EXPECT_FALSE(realSmpte2094_10.has_value()); }); } /** * Test IMapper::set(metadata) with a bad buffer */ TEST_P(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_Crop, 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)); ASSERT_EQ(Error::BAD_BUFFER, mGralloc->set(bufferHandle, gralloc4::MetadataType_Smpte2086, vec)); ASSERT_EQ(Error::BAD_BUFFER, mGralloc->set(bufferHandle, gralloc4::MetadataType_Cta861_3, vec)); ASSERT_EQ(Error::BAD_BUFFER, mGralloc->set(bufferHandle, gralloc4::MetadataType_Smpte2094_40, vec)); ASSERT_EQ(Error::BAD_BUFFER, mGralloc->set(bufferHandle, gralloc4::MetadataType_Smpte2094_10, vec)); } /** * Test get::metadata with cloned native_handle */ TEST_P(GraphicsMapperHidlTest, GetMetadataClonedHandle) { const native_handle_t* bufferHandle = nullptr; ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(mDummyDescriptorInfo, true)); const auto dataspace = Dataspace::SRGB_LINEAR; { hidl_vec metadata; ASSERT_EQ(NO_ERROR, gralloc4::encodeDataspace(dataspace, &metadata)); Error err = mGralloc->set(bufferHandle, gralloc4::MetadataType_Dataspace, metadata); if (err == Error::UNSUPPORTED) { GTEST_SUCCEED() << "setting this metadata is unsupported"; return; } ASSERT_EQ(Error::NONE, err); } const native_handle_t* importedHandle; { auto clonedHandle = native_handle_clone(bufferHandle); ASSERT_NO_FATAL_FAILURE(importedHandle = mGralloc->importBuffer(clonedHandle)); native_handle_close(clonedHandle); native_handle_delete(clonedHandle); } Dataspace realSpace = Dataspace::UNKNOWN; { hidl_vec metadata; ASSERT_EQ(Error::NONE, mGralloc->get(importedHandle, gralloc4::MetadataType_Dataspace, &metadata)); ASSERT_NO_FATAL_FAILURE(gralloc4::decodeDataspace(metadata, &realSpace)); } EXPECT_EQ(dataspace, realSpace); } /** * Test set::metadata with cloned native_handle */ TEST_P(GraphicsMapperHidlTest, SetMetadataClonedHandle) { const native_handle_t* bufferHandle = nullptr; ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(mDummyDescriptorInfo, true)); const native_handle_t* importedHandle; { auto clonedHandle = native_handle_clone(bufferHandle); ASSERT_NO_FATAL_FAILURE(importedHandle = mGralloc->importBuffer(clonedHandle)); native_handle_close(clonedHandle); native_handle_delete(clonedHandle); } const auto dataspace = Dataspace::SRGB_LINEAR; { hidl_vec metadata; ASSERT_EQ(NO_ERROR, gralloc4::encodeDataspace(dataspace, &metadata)); Error err = mGralloc->set(importedHandle, gralloc4::MetadataType_Dataspace, metadata); if (err == Error::UNSUPPORTED) { GTEST_SUCCEED() << "setting this metadata is unsupported"; return; } ASSERT_EQ(Error::NONE, err); } Dataspace realSpace = Dataspace::UNKNOWN; { hidl_vec metadata; ASSERT_EQ(Error::NONE, mGralloc->get(bufferHandle, gralloc4::MetadataType_Dataspace, &metadata)); ASSERT_NO_FATAL_FAILURE(gralloc4::decodeDataspace(metadata, &realSpace)); } EXPECT_EQ(dataspace, realSpace); } /** * Test IMapper::set(metadata) for constant metadata */ TEST_P(GraphicsMapperHidlTest, SetConstantMetadata) { const native_handle_t* bufferHandle = nullptr; ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(mDummyDescriptorInfo, true)); uint64_t bufferId = 2; hidl_vec bufferIdVec; ASSERT_EQ(NO_ERROR, gralloc4::encodeBufferId(bufferId, &bufferIdVec)); ASSERT_EQ(Error::BAD_VALUE, mGralloc->set(bufferHandle, gralloc4::MetadataType_BufferId, bufferIdVec)); std::string name{"new name"}; hidl_vec nameVec; ASSERT_EQ(NO_ERROR, gralloc4::encodeName(name, &nameVec)); ASSERT_EQ(Error::BAD_VALUE, mGralloc->set(bufferHandle, gralloc4::MetadataType_Name, nameVec)); uint64_t width = 32; hidl_vec widthVec; ASSERT_EQ(NO_ERROR, gralloc4::encodeWidth(width, &widthVec)); ASSERT_EQ(Error::BAD_VALUE, mGralloc->set(bufferHandle, gralloc4::MetadataType_Width, widthVec)); uint64_t height = 32; hidl_vec heightVec; ASSERT_EQ(NO_ERROR, gralloc4::encodeHeight(height, &heightVec)); ASSERT_EQ(Error::BAD_VALUE, mGralloc->set(bufferHandle, gralloc4::MetadataType_Height, heightVec)); uint64_t layerCount = 2; hidl_vec layerCountVec; ASSERT_EQ(NO_ERROR, gralloc4::encodeLayerCount(layerCount, &layerCountVec)); ASSERT_EQ(Error::BAD_VALUE, mGralloc->set(bufferHandle, gralloc4::MetadataType_LayerCount, layerCountVec)); hardware::graphics::common::V1_2::PixelFormat pixelFormatRequested = PixelFormat::BLOB; hidl_vec pixelFormatRequestedVec; ASSERT_EQ(NO_ERROR, gralloc4::encodePixelFormatRequested(pixelFormatRequested, &pixelFormatRequestedVec)); ASSERT_EQ(Error::BAD_VALUE, mGralloc->set(bufferHandle, gralloc4::MetadataType_PixelFormatRequested, pixelFormatRequestedVec)); uint64_t usage = 0; hidl_vec usageVec; ASSERT_EQ(NO_ERROR, gralloc4::encodeUsage(usage, &usageVec)); ASSERT_EQ(Error::BAD_VALUE, mGralloc->set(bufferHandle, gralloc4::MetadataType_Usage, usageVec)); } /** * Test IMapper::set(metadata) for bad metadata */ TEST_P(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_PixelFormatFourCC, vec)); ASSERT_EQ(Error::UNSUPPORTED, mGralloc->set(bufferHandle, gralloc4::MetadataType_PixelFormatModifier, 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_Crop, vec)); ASSERT_EQ(Error::UNSUPPORTED, mGralloc->set(bufferHandle, gralloc4::MetadataType_Dataspace, vec)); ASSERT_EQ(Error::UNSUPPORTED, mGralloc->set(bufferHandle, gralloc4::MetadataType_BlendMode, vec)); // Keep optional metadata types below and populate the encoded metadata vec // with some arbitrary different metadata because the common gralloc4::decode*() // functions do not distinguish between an empty vec and bad value. if (base::GetIntProperty("ro.vendor.api_level", __ANDROID_API_FUTURE__) >= __ANDROID_API_T__) { // Some old grallocs shipped with broken validation. ASSERT_EQ(NO_ERROR, gralloc4::encodeDataspace(Dataspace::SRGB_LINEAR, &vec)); ASSERT_EQ(Error::UNSUPPORTED, mGralloc->set(bufferHandle, gralloc4::MetadataType_Smpte2086, vec)); ASSERT_EQ(Error::UNSUPPORTED, mGralloc->set(bufferHandle, gralloc4::MetadataType_Cta861_3, vec)); } } /** * Test IMapper::getFromBufferDescriptorInfo(BufferId) */ TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoBufferId) { hidl_vec vec; ASSERT_EQ(Error::UNSUPPORTED, mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo, gralloc4::MetadataType_BufferId, &vec)); } /** * Test IMapper::getFromBufferDescriptorInfo(Name) */ TEST_P(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_P(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_P(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_P(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_P(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"; return; } ASSERT_EQ(err, Error::NONE); uint32_t pixelFormatFourCC = 0; ASSERT_EQ(NO_ERROR, gralloc4::decodePixelFormatFourCC(vec, &pixelFormatFourCC)); } /** * Test IMapper::getFromBufferDescriptorInfo(PixelFormatModifier) */ TEST_P(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"; return; } ASSERT_EQ(err, Error::NONE); uint64_t pixelFormatModifier = 0; ASSERT_EQ(NO_ERROR, gralloc4::decodePixelFormatModifier(vec, &pixelFormatModifier)); } /** * Test IMapper::getFromBufferDescriptorInfo(Usage) */ TEST_P(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_P(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"; return; } ASSERT_EQ(err, Error::NONE); uint64_t allocationSize = 0; ASSERT_EQ(NO_ERROR, gralloc4::decodeAllocationSize(vec, &allocationSize)); } /** * Test IMapper::getFromBufferDescriptorInfo(ProtectedContent) */ TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoProtectedContent) { auto info = mDummyDescriptorInfo; info.usage = BufferUsage::PROTECTED | BufferUsage::COMPOSER_OVERLAY; hidl_vec vec; auto err = mGralloc->getFromBufferDescriptorInfo(info, gralloc4::MetadataType_ProtectedContent, &vec); if (err == Error::UNSUPPORTED) { GTEST_SUCCEED() << "setting this metadata is unsupported"; return; } ASSERT_EQ(err, Error::NONE); uint64_t protectedContent = 0; ASSERT_EQ(NO_ERROR, gralloc4::decodeProtectedContent(vec, &protectedContent)); EXPECT_EQ(1, protectedContent); } /** * Test IMapper::getFromBufferDescriptorInfo(Compression) */ TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoCompression) { auto info = mDummyDescriptorInfo; info.usage = static_cast(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN); hidl_vec vec; auto err = mGralloc->getFromBufferDescriptorInfo(info, gralloc4::MetadataType_Compression, &vec); if (err == Error::UNSUPPORTED) { GTEST_SUCCEED() << "setting this metadata is unsupported"; return; } ASSERT_EQ(err, Error::NONE); 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_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoInterlaced) { hidl_vec vec; auto err = mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo, gralloc4::MetadataType_Interlaced, &vec); if (err == Error::UNSUPPORTED) { GTEST_SUCCEED() << "setting this metadata is unsupported"; return; } ASSERT_EQ(err, Error::NONE); 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_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoChromaSiting) { hidl_vec vec; auto err = mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo, gralloc4::MetadataType_ChromaSiting, &vec); if (err == Error::UNSUPPORTED) { GTEST_SUCCEED() << "setting this metadata is unsupported"; return; } ASSERT_EQ(err, Error::NONE); 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_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoPlaneLayouts) { hidl_vec vec; const auto ret = mGralloc->getFromBufferDescriptorInfo( mDummyDescriptorInfo, gralloc4::MetadataType_PlaneLayouts, &vec); if (ret == Error::NONE) { std::vector planeLayouts; ASSERT_EQ(NO_ERROR, gralloc4::decodePlaneLayouts(vec, &planeLayouts)); ASSERT_NO_FATAL_FAILURE(verifyRGBA8888PlaneLayouts(planeLayouts)); } else { ASSERT_EQ(Error::UNSUPPORTED, ret); } } /** * Test IMapper::getFromBufferDescriptorInfo(Crop) */ TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoCrop) { auto info = mDummyDescriptorInfo; info.format = PixelFormat::RGBA_8888; info.usage = static_cast(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN); hidl_vec vec; auto err = mGralloc->getFromBufferDescriptorInfo(info, gralloc4::MetadataType_Crop, &vec); if (err == Error::UNSUPPORTED) { GTEST_SUCCEED() << "setting this metadata is unsupported"; return; } ASSERT_EQ(err, Error::NONE); std::vector crops; ASSERT_EQ(NO_ERROR, gralloc4::decodeCrop(vec, &crops)); EXPECT_EQ(1, crops.size()); } /** * Test IMapper::getFromBufferDescriptorInfo(Dataspace) */ TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoDataspace) { hidl_vec vec; auto err = mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo, gralloc4::MetadataType_Dataspace, &vec); if (err == Error::UNSUPPORTED) { GTEST_SUCCEED() << "setting this metadata is unsupported"; return; } ASSERT_EQ(err, Error::NONE); Dataspace dataspace = Dataspace::DISPLAY_P3; ASSERT_EQ(NO_ERROR, gralloc4::decodeDataspace(vec, &dataspace)); EXPECT_EQ(Dataspace::UNKNOWN, dataspace); } /** * Test IMapper::getFromBufferDescriptorInfo(BlendMode) */ TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoBlendMode) { hidl_vec vec; auto err = mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo, gralloc4::MetadataType_BlendMode, &vec); if (err == Error::UNSUPPORTED) { GTEST_SUCCEED() << "setting this metadata is unsupported"; return; } ASSERT_EQ(err, Error::NONE); BlendMode blendMode = BlendMode::COVERAGE; ASSERT_EQ(NO_ERROR, gralloc4::decodeBlendMode(vec, &blendMode)); EXPECT_EQ(BlendMode::INVALID, blendMode); } /** * Test IMapper::getFromBufferDescriptorInfo(Smpte2086) */ TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoSmpte2086) { hidl_vec vec; auto err = mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo, gralloc4::MetadataType_Smpte2086, &vec); if (err == Error::UNSUPPORTED) { GTEST_SUCCEED() << "setting this metadata is unsupported"; return; } ASSERT_EQ(err, Error::NONE); std::optional smpte2086; ASSERT_EQ(NO_ERROR, gralloc4::decodeSmpte2086(vec, &smpte2086)); EXPECT_FALSE(smpte2086.has_value()); } /** * Test IMapper::getFromBufferDescriptorInfo(Cta861_3) */ TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoCta861_3) { hidl_vec vec; auto err = mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo, gralloc4::MetadataType_Cta861_3, &vec); if (err == Error::UNSUPPORTED) { GTEST_SUCCEED() << "setting this metadata is unsupported"; return; } ASSERT_EQ(err, Error::NONE); std::optional cta861_3; ASSERT_EQ(NO_ERROR, gralloc4::decodeCta861_3(vec, &cta861_3)); EXPECT_FALSE(cta861_3.has_value()); } /** * Test IMapper::getFromBufferDescriptorInfo(Smpte2094_40) */ TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoSmpte2094_40) { hidl_vec vec; auto err = mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo, gralloc4::MetadataType_Smpte2094_40, &vec); if (err == Error::UNSUPPORTED) { GTEST_SUCCEED() << "setting this metadata is unsupported"; return; } ASSERT_EQ(err, Error::NONE); std::optional> smpte2094_40; ASSERT_EQ(NO_ERROR, gralloc4::decodeSmpte2094_40(vec, &smpte2094_40)); EXPECT_FALSE(smpte2094_40.has_value()); } /** * Test IMapper::getFromBufferDescriptorInfo(Smpte2094_10) */ TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoSmpte2094_10) { hidl_vec vec; auto err = mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo, gralloc4::MetadataType_Smpte2094_10, &vec); if (err == Error::UNSUPPORTED) { GTEST_SUCCEED() << "setting this metadata is unsupported"; return; } ASSERT_EQ(err, Error::NONE); std::optional> smpte2094_10; ASSERT_EQ(NO_ERROR, gralloc4::decodeSmpte2094_10(vec, &smpte2094_10)); EXPECT_FALSE(smpte2094_10.has_value()); } /** * Test IMapper::getFromBufferDescriptorInfo(metadata) for unsupported metadata */ TEST_P(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_P(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()); } /** * Test IMapper::listSupportedMetadataTypes() */ TEST_P(GraphicsMapperHidlTest, ListSupportedMetadataTypes) { hidl_vec descriptions; mGralloc->getMapper()->listSupportedMetadataTypes( [&](const auto& tmpError, const auto& tmpDescriptions) { ASSERT_EQ(Error::NONE, tmpError); descriptions = tmpDescriptions; }); std::set foundMetadataTypes; std::set notSettableMetadataTypes{ StandardMetadataType::BUFFER_ID, StandardMetadataType::NAME, StandardMetadataType::WIDTH, StandardMetadataType::HEIGHT, StandardMetadataType::LAYER_COUNT, StandardMetadataType::PIXEL_FORMAT_REQUESTED, StandardMetadataType::USAGE}; ASSERT_LE(sRequiredMetadataTypes.size(), descriptions.size()); for (const auto& description : descriptions) { const auto& metadataType = description.metadataType; if (!gralloc4::isStandardMetadataType(metadataType)) { EXPECT_GT(description.description.size(), 0); continue; } StandardMetadataType type = gralloc4::getStandardMetadataTypeValue(metadataType); if (sRequiredMetadataTypes.find(type) == sRequiredMetadataTypes.end()) { continue; } ASSERT_EQ(foundMetadataTypes.find(type), foundMetadataTypes.end()); foundMetadataTypes.insert(type); ASSERT_TRUE(description.isGettable); if (notSettableMetadataTypes.find(type) != notSettableMetadataTypes.end()) { ASSERT_FALSE(description.isSettable); } } ASSERT_EQ(sRequiredMetadataTypes, foundMetadataTypes); } /** * Test IMapper::dumpBuffer() */ TEST_P(GraphicsMapperHidlTest, DumpBuffer) { const native_handle_t* bufferHandle = nullptr; ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(mDummyDescriptorInfo, true)); auto buffer = const_cast(bufferHandle); IMapper::BufferDump bufferDump; mGralloc->getMapper()->dumpBuffer(buffer, [&](const auto& tmpError, const auto& tmpBufferDump) { ASSERT_EQ(Error::NONE, tmpError); bufferDump = tmpBufferDump; }); ASSERT_NO_FATAL_FAILURE(verifyBufferDump(bufferDump, buffer)); } /** * Test IMapper::dumpBuffer() with an invalid buffer */ TEST_P(GraphicsMapperHidlTest, DumpBufferNullBuffer) { native_handle_t* bufferHandle = nullptr; auto buffer = const_cast(bufferHandle); mGralloc->getMapper()->dumpBuffer(buffer, [&](const auto& tmpError, const auto& /*tmpBufferDump*/) { ASSERT_EQ(Error::BAD_BUFFER, tmpError); }); } /** * Test IMapper::dumpBuffer() multiple */ TEST_P(GraphicsMapperHidlTest, DumpBuffers) { size_t bufferCount = 10; for (int i = 0; i < bufferCount; i++) { ASSERT_NO_FATAL_FAILURE(mGralloc->allocate(mDummyDescriptorInfo, true)); } hidl_vec bufferDump; mGralloc->getMapper()->dumpBuffers([&](const auto& tmpError, const auto& tmpBufferDump) { ASSERT_EQ(Error::NONE, tmpError); bufferDump = tmpBufferDump; }); ASSERT_EQ(bufferCount, bufferDump.size()); for (const auto& dump : bufferDump) { ASSERT_NO_FATAL_FAILURE(verifyBufferDump(dump)); } } /** * Test IMapper::getReservedRegion() */ TEST_P(GraphicsMapperHidlTest, GetReservedRegion) { const native_handle_t* bufferHandle = nullptr; auto info = mDummyDescriptorInfo; const int pageSize = getpagesize(); ASSERT_GE(pageSize, 0); std::vector requestedReservedSizes{1, 10, 333, static_cast(pageSize) / 2, static_cast(pageSize)}; for (auto requestedReservedSize : requestedReservedSizes) { info.reservedSize = requestedReservedSize; ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(info, true)); void* reservedRegion = nullptr; uint64_t reservedSize = 0; ASSERT_EQ(Error::NONE, mGralloc->getReservedRegion(bufferHandle, &reservedRegion, &reservedSize)); ASSERT_NE(nullptr, reservedRegion); ASSERT_EQ(requestedReservedSize, reservedSize); uint8_t testValue = 1; memset(reservedRegion, testValue, reservedSize); for (uint64_t i = 0; i < reservedSize; i++) { ASSERT_EQ(testValue, static_cast(reservedRegion)[i]); } } } /** * Test IMapper::getReservedRegion() request over a page */ TEST_P(GraphicsMapperHidlTest, GetLargeReservedRegion) { const native_handle_t* bufferHandle = nullptr; auto info = mDummyDescriptorInfo; const int pageSize = getpagesize(); ASSERT_GE(pageSize, 0); std::vector requestedReservedSizes{static_cast(pageSize) * 2, static_cast(pageSize) * 10, static_cast(pageSize) * 1000}; for (auto requestedReservedSize : requestedReservedSizes) { info.reservedSize = requestedReservedSize; BufferDescriptor descriptor; ASSERT_NO_FATAL_FAILURE(descriptor = mGralloc->createDescriptor(info)); Error err = Error::NONE; mGralloc->rawAllocate( descriptor, 1, [&](const auto& tmpError, const auto&, const auto& tmpBuffers) { err = tmpError; if (err == Error::NONE) { ASSERT_EQ(1, tmpBuffers.size()); ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->importBuffer(tmpBuffers[0])); } }); if (err == Error::UNSUPPORTED) { continue; } ASSERT_EQ(Error::NONE, err); void* reservedRegion = nullptr; uint64_t reservedSize = 0; err = mGralloc->getReservedRegion(bufferHandle, &reservedRegion, &reservedSize); ASSERT_EQ(Error::NONE, err); ASSERT_NE(nullptr, reservedRegion); ASSERT_EQ(requestedReservedSize, reservedSize); } } /** * Test IMapper::getReservedRegion() across multiple mappers */ TEST_P(GraphicsMapperHidlTest, GetReservedRegionMultiple) { const native_handle_t* bufferHandle = nullptr; auto info = mDummyDescriptorInfo; const int pageSize = getpagesize(); ASSERT_GE(pageSize, 0); info.reservedSize = pageSize; ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(info, true)); void* reservedRegion1 = nullptr; uint64_t reservedSize1 = 0; ASSERT_EQ(Error::NONE, mGralloc->getReservedRegion(bufferHandle, &reservedRegion1, &reservedSize1)); ASSERT_NE(nullptr, reservedRegion1); ASSERT_EQ(info.reservedSize, reservedSize1); std::unique_ptr anotherGralloc; ASSERT_NO_FATAL_FAILURE(anotherGralloc = std::make_unique(std::get<0>(GetParam()), std::get<1>(GetParam()))); void* reservedRegion2 = nullptr; uint64_t reservedSize2 = 0; ASSERT_EQ(Error::NONE, mGralloc->getReservedRegion(bufferHandle, &reservedRegion2, &reservedSize2)); ASSERT_EQ(reservedRegion1, reservedRegion2); ASSERT_EQ(reservedSize1, reservedSize2); } /** * Test IMapper::getReservedRegion() with a bad buffer */ TEST_P(GraphicsMapperHidlTest, GetReservedRegionBadBuffer) { const native_handle_t* bufferHandle = nullptr; void* reservedRegion = nullptr; uint64_t reservedSize = 0; ASSERT_EQ(Error::BAD_BUFFER, mGralloc->getReservedRegion(bufferHandle, &reservedRegion, &reservedSize)); ASSERT_EQ(nullptr, reservedRegion); ASSERT_EQ(0, reservedSize); } GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsMapperHidlTest); namespace { std::vector getAllocatorInstances() { std::vector instances; for (auto halInstance : android::hardware::getAllHalInstanceNames(IAllocator::descriptor)) { instances.emplace_back(std::move(halInstance)); } for (auto aidlInstance : getAidlHalInstanceNames( aidl::android::hardware::graphics::allocator::IAllocator::descriptor)) { instances.emplace_back(std::move(aidlInstance)); } return instances; } } // namespace INSTANTIATE_TEST_CASE_P( PerInstance, GraphicsMapperHidlTest, testing::Combine( testing::ValuesIn(getAllocatorInstances()), testing::ValuesIn(android::hardware::getAllHalInstanceNames(IMapper::descriptor))), android::hardware::PrintInstanceTupleNameToString<>); } // namespace } // namespace vts } // namespace V4_0 } // namespace mapper } // namespace graphics } // namespace hardware } // namespace android