blob: 529fb1817a05d6d9431e1a4104c1cceaab4599f8 [file] [log] [blame]
/*
* 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.get())));
// 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.get())));
ASSERT_NO_FATAL_FAILURE(
verifyRGBA8888(bufferHandle, data, info.height, stride * 4, info.width * 4));
ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
}
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.get())));
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.get())));
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_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.get())));
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.get())));
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.get())));
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.get())));
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 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 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(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);
}
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