Files
hardware_interfaces/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
Jason Macnak 3f4276f4a9 Update Mapper4 SetBadMetadata VTS test for optional metadata
The common decode function for optional gralloc4 metadata
`android::gralloc4::decodeOptionalMetadata()` treats an empty
input `hidl_vec<uint8_t>` as `std::nullopt` and not a bad
value. aosp/1907915 previously tried to update the encoding
and decoding of optional metadata in order to distinguish
this case but the change broke GRF. Instead, let's update the
SetBadMetadata test to use some actual incorrect data for the
optional metadata tests instead of an empty vec.

Bug: b/207388558
Test: cvd start
Test: VtsHalGraphicsMapperV4_0TargetTest
Change-Id: I87c20930cb701e87c89489bd0359cce0522cfe44
2022-05-11 21:56:30 +00:00

2616 lines
101 KiB
C++

/*
* 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)>;
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;
ASSERT_EQ(Error::NONE, mGralloc->get(bufferHandle, metadataType, &vec));
ASSERT_NO_FATAL_FAILURE(decode(descriptorInfo, vec));
}
void testSet(const IMapper::BufferDescriptorInfo& descriptorInfo,
const MetadataType& metadataType, const hidl_vec<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 + (planeLayoutComponent.offsetInBits / 8);
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);
}
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 traverseYCbCr888Data(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 fillYCbCr888Data(const android_ycbcr& yCbCr, int32_t width, int32_t height,
int64_t hSubsampling, int64_t vSubsampling) {
traverseYCbCr888Data(yCbCr, width, height, hSubsampling, vSubsampling,
[](auto address, auto fillingData) { *address = fillingData; });
}
void verifyYCbCr888Data(const android_ycbcr& yCbCr, int32_t width, int32_t height,
int64_t hSubsampling, int64_t vSubsampling) {
traverseYCbCr888Data(
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; }
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);
fillYCbCr888Data(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));
verifyYCbCr888Data(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);
fillYCbCr888Data(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));
verifyYCbCr888Data(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);
fillYCbCr888Data(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));
verifyYCbCr888Data(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 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(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());
}
/**
* 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(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));
}
/**
* 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));
// Keep optional metadata types below and populate the encoded metadata vec
// with some arbitrary different metadata because the common gralloc4::decode*()
// functions do not distinguish between an empty vec and bad value.
ASSERT_EQ(NO_ERROR, gralloc4::encodeDataspace(Dataspace::SRGB_LINEAR, &vec));
ASSERT_EQ(Error::UNSUPPORTED,
mGralloc->set(bufferHandle, gralloc4::MetadataType_Smpte2086, vec));
ASSERT_EQ(Error::UNSUPPORTED,
mGralloc->set(bufferHandle, gralloc4::MetadataType_Cta861_3, vec));
}
/**
* Test IMapper::getFromBufferDescriptorInfo(BufferId)
*/
TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoBufferId) {
hidl_vec<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(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