| /* |
| * 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 <unistd.h> |
| #include <chrono> |
| #include <thread> |
| #include <vector> |
| |
| #include <aidl/android/hardware/graphics/common/PlaneLayoutComponentType.h> |
| |
| #include <android-base/logging.h> |
| #include <android-base/unique_fd.h> |
| #include <android/sync.h> |
| #include <gralloctypes/Gralloc4.h> |
| #include <gtest/gtest.h> |
| #include <hidl/GtestPrinter.h> |
| #include <hidl/ServiceManagement.h> |
| #include <mapper-vts/4.0/MapperVts.h> |
| #include <system/graphics.h> |
| |
| 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<void(const IMapper::BufferDescriptorInfo& descriptorInfo, |
| const hidl_vec<uint8_t>& vec)>; |
| |
| struct YCbCr { |
| android_ycbcr yCbCr; |
| int64_t horizontalSubSampling; |
| int64_t verticalSubSampling; |
| }; |
| |
| class GraphicsMapperHidlTest |
| : public ::testing::TestWithParam<std::tuple<std::string, std::string>> { |
| protected: |
| void SetUp() override { |
| ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>(std::get<0>(GetParam()), |
| std::get<1>(GetParam()))); |
| ASSERT_NE(nullptr, mGralloc->getAllocator().get()); |
| 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<uint64_t>(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<uint8_t> 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<uint8_t>& 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<uint8_t> vec; |
| ASSERT_EQ(Error::NONE, mGralloc->get(bufferHandle, metadataType, &vec)); |
| |
| ASSERT_NO_FATAL_FAILURE(decode(descriptorInfo, vec)); |
| } |
| |
| void verifyRGBA8888PlaneLayouts(const std::vector<PlaneLayout>& 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<StandardMetadataType> foundMetadataTypes; |
| |
| const std::vector<IMapper::MetadataDump> 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<uint8_t> 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<uint8_t> vec; |
| ASSERT_EQ(Error::NONE, |
| mGralloc->get(bufferHandle, gralloc4::MetadataType_PlaneLayouts, &vec)); |
| std::vector<PlaneLayout> 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<PlaneLayoutComponentType>(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<uint8_t> vec; |
| EXPECT_EQ(Error::NONE, |
| mGralloc->get(bufferHandle, gralloc4::MetadataType_PlaneLayouts, &vec)); |
| std::vector<PlaneLayout> 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<PlaneLayoutComponentType>(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<uint8_t> vec; |
| ASSERT_EQ(Error::NONE, |
| mGralloc->get(bufferHandle, gralloc4::MetadataType_PlaneLayouts, &vec)); |
| std::vector<PlaneLayout> 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<uint8_t>(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<void(uint8_t*, uint8_t)> traverseFuncion) { |
| auto yData = static_cast<uint8_t*>(yCbCr.y); |
| auto cbData = static_cast<uint8_t*>(yCbCr.cb); |
| auto crData = static_cast<uint8_t*>(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<uint8_t>(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<uint8_t>(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<Gralloc> mGralloc; |
| IMapper::BufferDescriptorInfo mDummyDescriptorInfo{}; |
| static const std::set<StandardMetadataType> sRequiredMetadataTypes; |
| }; |
| |
| const std::set<StandardMetadataType> 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<const native_handle_t*> 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->getAllocator()->allocate(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<bool> timeUp(false); |
| std::atomic<uint64_t> allocationCount(0); |
| auto threadLoop = [&]() { |
| while (!timeUp) { |
| mGralloc->getAllocator()->allocate( |
| descriptor, 1, |
| [&](const auto&, const auto&, const auto&) { allocationCount++; }); |
| } |
| }; |
| |
| std::vector<std::thread> 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<native_handle_t*>(buffer); |
| }); |
| |
| // free the imported handle with another mapper |
| std::unique_ptr<Gralloc> anotherGralloc; |
| ASSERT_NO_FATAL_FAILURE(anotherGralloc = std::make_unique<Gralloc>(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(invalidHandle); |
| 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<int32_t>(info.width), |
| static_cast<int32_t>(info.height)}; |
| unique_fd fence; |
| uint8_t* data; |
| ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(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<uint8_t*>(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<int32_t>(info.width), |
| static_cast<int32_t>(info.height)}; |
| unique_fd fence; |
| uint8_t* data; |
| |
| ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(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<uint8_t*>(yCbCr.cb); |
| auto crData = static_cast<uint8_t*>(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<uint8_t*>(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<int32_t>(info.width), |
| static_cast<int32_t>(info.height)}; |
| unique_fd fence; |
| ASSERT_NO_FATAL_FAILURE(mGralloc->lock(bufferHandle, info.usage, region, fence.release())); |
| |
| hidl_vec<uint8_t> vec; |
| ASSERT_EQ(Error::NONE, mGralloc->get(bufferHandle, gralloc4::MetadataType_PlaneLayouts, &vec)); |
| std::vector<PlaneLayout> 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<int32_t>(info.width), |
| static_cast<int32_t>(info.height)}; |
| unique_fd fence; |
| uint8_t* data; |
| |
| ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(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<uint8_t*>(yCbCr.cb); |
| auto crData = static_cast<uint8_t*>(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<uint8_t*>(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<int32_t>(info.width), |
| static_cast<int32_t>(info.height)}; |
| unique_fd fence; |
| uint8_t* data; |
| |
| ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(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<uint8_t*>(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<int32_t>(info.width), |
| static_cast<int32_t>(info.height)}; |
| unique_fd fence; |
| |
| ASSERT_NO_FATAL_FAILURE(mGralloc->lock(bufferHandle, info.usage, region, fence.release())); |
| |
| hidl_vec<uint8_t> vec; |
| ASSERT_EQ(Error::NONE, mGralloc->get(bufferHandle, gralloc4::MetadataType_PlaneLayouts, &vec)); |
| std::vector<PlaneLayout> 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<PlaneLayoutComponentType>(planeLayoutComponent.type.value)); |
| EXPECT_EQ(0, planeLayoutComponent.offsetInBits % 8); |
| EXPECT_EQ(-1, planeLayoutComponent.sizeInBits); |
| |
| 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<int32_t>(info.width), |
| static_cast<int32_t>(info.height)}; |
| unique_fd fence; |
| |
| ASSERT_NO_FATAL_FAILURE(mGralloc->lock(bufferHandle, info.usage, region, fence.release())); |
| |
| hidl_vec<uint8_t> vec; |
| ASSERT_EQ(Error::NONE, mGralloc->get(bufferHandle, gralloc4::MetadataType_PlaneLayouts, &vec)); |
| std::vector<PlaneLayout> 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<PlaneLayoutComponentType>(planeLayoutComponent.type.value)); |
| EXPECT_EQ(0, planeLayoutComponent.offsetInBits % 8); |
| EXPECT_EQ(-1, planeLayoutComponent.sizeInBits); |
| |
| ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle))); |
| } |
| |
| TEST_P(GraphicsMapperHidlTest, Lock_YCBCR_P010) { |
| auto info = mDummyDescriptorInfo; |
| info.format = PixelFormat::YCBCR_P010; |
| |
| 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<int32_t>(info.width), |
| static_cast<int32_t>(info.height)}; |
| unique_fd fence; |
| uint8_t* data; |
| |
| ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(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<int32_t>(info.width * 2), |
| static_cast<int32_t>(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<native_handle_t*>(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<native_handle_t*>( |
| 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<native_handle_t*>( |
| 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<int32_t>(info.width), |
| static_cast<int32_t>(info.height)}; |
| uint8_t* writeData; |
| ASSERT_NO_FATAL_FAILURE( |
| writeData = static_cast<uint8_t*>(mGralloc->lock( |
| writeBufferHandle, static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN), region, |
| -1))); |
| |
| uint8_t* readData; |
| ASSERT_NO_FATAL_FAILURE( |
| readData = static_cast<uint8_t*>(mGralloc->lock( |
| readBufferHandle, static_cast<uint64_t>(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::get(BufferId) |
| */ |
| TEST_P(GraphicsMapperHidlTest, GetBufferId) { |
| testGet(mDummyDescriptorInfo, gralloc4::MetadataType_BufferId, |
| [](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& 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<uint8_t>& 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<uint8_t>& 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<uint8_t>& 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<uint8_t>& 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<uint8_t>& 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<uint8_t>& 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<uint8_t>& 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<uint8_t>& 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<uint8_t>& 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<uint8_t> 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<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN); |
| |
| testGet(info, gralloc4::MetadataType_Compression, |
| [](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& 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<uint8_t>& 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<uint8_t>& 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<uint8_t> vec; |
| ASSERT_EQ(Error::NONE, mGralloc->get(bufferHandle, gralloc4::MetadataType_PlaneLayouts, &vec)); |
| |
| std::vector<PlaneLayout> 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<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN); |
| |
| testGet(info, gralloc4::MetadataType_Crop, |
| [](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& vec) { |
| std::vector<aidl::android::hardware::graphics::common::Rect> 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<uint8_t>& 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<uint8_t>& 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<uint8_t>& vec) { |
| std::optional<Smpte2086> 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<uint8_t>& vec) { |
| std::optional<Cta861_3> 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<uint8_t>& vec) { |
| std::optional<std::vector<uint8_t>> 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<uint8_t>& vec) { |
| std::optional<std::vector<uint8_t>> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> vec; |
| ASSERT_EQ(NO_ERROR, gralloc4::encodePixelFormatFourCC(pixelFormatFourCC, &vec)); |
| |
| testSet(mDummyDescriptorInfo, gralloc4::MetadataType_PixelFormatFourCC, vec, |
| [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& 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<uint8_t> vec; |
| ASSERT_EQ(NO_ERROR, gralloc4::encodePixelFormatModifier(pixelFormatModifier, &vec)); |
| |
| testSet(mDummyDescriptorInfo, gralloc4::MetadataType_PixelFormatModifier, vec, |
| [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& 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<uint8_t> vec; |
| ASSERT_EQ(NO_ERROR, gralloc4::encodeAllocationSize(allocationSize, &vec)); |
| |
| testSet(mDummyDescriptorInfo, gralloc4::MetadataType_AllocationSize, vec, |
| [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& 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<uint8_t> 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<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN); |
| |
| ExtendableType compression = gralloc4::Compression_DisplayStreamCompression; |
| hidl_vec<uint8_t> vec; |
| ASSERT_EQ(NO_ERROR, gralloc4::encodeCompression(compression, &vec)); |
| |
| testSet(info, gralloc4::MetadataType_Compression, vec, |
| [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& 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<uint8_t> vec; |
| ASSERT_EQ(NO_ERROR, gralloc4::encodeInterlaced(interlaced, &vec)); |
| |
| testSet(mDummyDescriptorInfo, gralloc4::MetadataType_Interlaced, vec, |
| [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& 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<uint8_t> vec; |
| ASSERT_EQ(NO_ERROR, gralloc4::encodeChromaSiting(chromaSiting, &vec)); |
| |
| testSet(mDummyDescriptorInfo, gralloc4::MetadataType_ChromaSiting, vec, |
| [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& 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<PlaneLayout> 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<uint8_t> 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<PlaneLayout> 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<aidl::android::hardware::graphics::common::Rect> crops{{0, 0, 32, 32}}; |
| hidl_vec<uint8_t> vec; |
| ASSERT_EQ(NO_ERROR, gralloc4::encodeCrop(crops, &vec)); |
| |
| testSet(mDummyDescriptorInfo, gralloc4::MetadataType_Crop, vec, |
| [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& vec) { |
| std::vector<aidl::android::hardware::graphics::common::Rect> 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<uint8_t> vec; |
| ASSERT_EQ(NO_ERROR, gralloc4::encodeDataspace(dataspace, &vec)); |
| |
| testSet(mDummyDescriptorInfo, gralloc4::MetadataType_Dataspace, vec, |
| [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& 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<uint8_t> vec; |
| ASSERT_EQ(NO_ERROR, gralloc4::encodeBlendMode(blendMode, &vec)); |
| |
| testSet(mDummyDescriptorInfo, gralloc4::MetadataType_BlendMode, vec, |
| [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& 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<uint8_t> vec; |
| ASSERT_EQ(NO_ERROR, gralloc4::encodeSmpte2086(smpte2086, &vec)); |
| |
| testSet(mDummyDescriptorInfo, gralloc4::MetadataType_Smpte2086, vec, |
| [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& vec) { |
| std::optional<Smpte2086> 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<uint8_t> 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<uint8_t>& vec) { |
| std::optional<Cta861_3> 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<uint8_t> vec; |
| |
| testSet(mDummyDescriptorInfo, gralloc4::MetadataType_Smpte2094_40, vec, |
| [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& vec) { |
| std::optional<std::vector<uint8_t>> 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<uint8_t> vec; |
| |
| testSet(mDummyDescriptorInfo, gralloc4::MetadataType_Smpte2094_10, vec, |
| [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& vec) { |
| std::optional<std::vector<uint8_t>> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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)); |
| 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<uint8_t> vec; |
| ASSERT_EQ(Error::UNSUPPORTED, |
| mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo, |
| gralloc4::MetadataType_BufferId, &vec)); |
| } |
| |
| /** |
| * Test IMapper::getFromBufferDescriptorInfo(Name) |
| */ |
| TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoName) { |
| hidl_vec<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN); |
| |
| hidl_vec<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> vec; |
| const auto ret = mGralloc->getFromBufferDescriptorInfo( |
| mDummyDescriptorInfo, gralloc4::MetadataType_PlaneLayouts, &vec); |
| if (ret == Error::NONE) { |
| std::vector<PlaneLayout> 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<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN); |
| |
| hidl_vec<uint8_t> 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<aidl::android::hardware::graphics::common::Rect> crops; |
| ASSERT_EQ(NO_ERROR, gralloc4::decodeCrop(vec, &crops)); |
| EXPECT_EQ(1, crops.size()); |
| } |
| |
| /** |
| * Test IMapper::getFromBufferDescriptorInfo(Dataspace) |
| */ |
| TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoDataspace) { |
| hidl_vec<uint8_t> 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<uint8_t> 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<uint8_t> 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> 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<uint8_t> 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> 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<uint8_t> 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<std::vector<uint8_t>> 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<uint8_t> 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<std::vector<uint8_t>> 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<uint8_t> 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<uint8_t> vec; |
| ASSERT_EQ(Error::UNSUPPORTED, |
| mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo, metadataTypeFake, &vec)); |
| ASSERT_EQ(0, vec.size()); |
| } |
| |
| /** |
| * Test IMapper::listSupportedMetadataTypes() |
| */ |
| TEST_P(GraphicsMapperHidlTest, ListSupportedMetadataTypes) { |
| hidl_vec<IMapper::MetadataTypeDescription> descriptions; |
| mGralloc->getMapper()->listSupportedMetadataTypes( |
| [&](const auto& tmpError, const auto& tmpDescriptions) { |
| ASSERT_EQ(Error::NONE, tmpError); |
| descriptions = tmpDescriptions; |
| }); |
| |
| std::set<StandardMetadataType> foundMetadataTypes; |
| |
| std::set<StandardMetadataType> 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<native_handle_t*>(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<native_handle_t*>(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<IMapper::BufferDump> 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<uint64_t> requestedReservedSizes{1, 10, 333, static_cast<uint64_t>(pageSize) / 2, |
| static_cast<uint64_t>(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<uint8_t*>(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<uint64_t> requestedReservedSizes{static_cast<uint64_t>(pageSize) * 2, |
| static_cast<uint64_t>(pageSize) * 10, |
| static_cast<uint64_t>(pageSize) * 1000}; |
| |
| for (auto requestedReservedSize : requestedReservedSizes) { |
| info.reservedSize = requestedReservedSize; |
| |
| BufferDescriptor descriptor; |
| ASSERT_NO_FATAL_FAILURE(descriptor = mGralloc->createDescriptor(info)); |
| |
| Error err; |
| mGralloc->getAllocator()->allocate( |
| 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<Gralloc> anotherGralloc; |
| ASSERT_NO_FATAL_FAILURE(anotherGralloc = std::make_unique<Gralloc>(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); |
| INSTANTIATE_TEST_CASE_P( |
| PerInstance, GraphicsMapperHidlTest, |
| testing::Combine( |
| testing::ValuesIn( |
| android::hardware::getAllHalInstanceNames(IAllocator::descriptor)), |
| testing::ValuesIn(android::hardware::getAllHalInstanceNames(IMapper::descriptor))), |
| android::hardware::PrintInstanceTupleNameToString<>); |
| |
| } // namespace |
| } // namespace vts |
| } // namespace V4_0 |
| } // namespace mapper |
| } // namespace graphics |
| } // namespace hardware |
| } // namespace android |