From d36e12776fadfb4249c86eff4c3314773c35a358 Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Tue, 26 Nov 2019 11:33:32 -0800 Subject: [PATCH] gralloc: add reserved region This patch adds a reserved region of shared memory to every gralloc native_handle_t. The reserved region of memory will allow future versions of Android to add new buffer features without requiring gralloc upgrades. Bug: 145232031 Test: VtsHalGraphicsMapperV4_0TargetTest Change-Id: I1bdfec0a6ef85097096035d3d38e5c9e7fcc32f2 --- graphics/mapper/4.0/IMapper.hal | 43 ++++++- graphics/mapper/4.0/utils/vts/MapperVts.cpp | 13 ++ .../vts/include/mapper-vts/4.0/MapperVts.h | 3 + .../VtsHalGraphicsMapperV4_0TargetTest.cpp | 120 ++++++++++++++++++ 4 files changed, 176 insertions(+), 3 deletions(-) diff --git a/graphics/mapper/4.0/IMapper.hal b/graphics/mapper/4.0/IMapper.hal index 298f31ed56..89d4128518 100644 --- a/graphics/mapper/4.0/IMapper.hal +++ b/graphics/mapper/4.0/IMapper.hal @@ -56,6 +56,12 @@ interface IMapper { * BufferUsage. */ bitfield usage; + + /** + * The size in bytes of the reserved region associated with the buffer. + * See getReservedRegion for more information. + */ + uint64_t reservedSize; }; struct Rect { @@ -71,9 +77,10 @@ interface IMapper { * * Since the buffer descriptor fully describes a buffer, any device * dependent or device independent checks must be performed here whenever - * possible. Specifically, when layered buffers are not supported, this - * function must return `UNSUPPORTED` if `description.layers` is great than - * 1. + * possible. When layered buffers are not supported, this function must + * return `UNSUPPORTED` if `description.layers` is great than 1. This + * function may return `UNSUPPORTED` if `description.reservedSize` is + * larger than a page. * * @param description Attributes of the descriptor. * @return error Error status of the call, which may be @@ -560,5 +567,35 @@ interface IMapper { */ dumpBuffers() generates (Error error, vec bufferDumps); + + /** + * Returns the region of shared memory associated with the buffer that is + * reserved for client use. + * + * The shared memory may be allocated from any shared memory allocator. + * The shared memory must be CPU-accessible and virtually contiguous. The + * starting address must be word-aligned. + * + * This function may only be called after importBuffer() has been called by the + * client. The reserved region must remain accessible until freeBuffer() has + * been called. After freeBuffer() has been called, the client must not access + * the reserved region. + * + * This reserved memory may be used in future versions of Android to + * help clients implement backwards compatible features without requiring + * IAllocator/IMapper updates. + * + * @param buffer Imported buffer handle. + * @return error Error status of the call, which may be + * - `NONE` upon success. + * - `BAD_BUFFER` if the buffer is invalid. + * @return reservedRegion CPU-accessible pointer to the reserved region + * @return reservedSize the size of the reservedRegion that was requested + * in the BufferDescriptorInfo. + */ + getReservedRegion(pointer buffer) + generates (Error error, + pointer reservedRegion, + uint64_t reservedSize); }; diff --git a/graphics/mapper/4.0/utils/vts/MapperVts.cpp b/graphics/mapper/4.0/utils/vts/MapperVts.cpp index 8073e6924c..1dafd4a455 100644 --- a/graphics/mapper/4.0/utils/vts/MapperVts.cpp +++ b/graphics/mapper/4.0/utils/vts/MapperVts.cpp @@ -310,6 +310,19 @@ Error Gralloc::getFromBufferDescriptorInfo(const IMapper::BufferDescriptorInfo& return err; } +Error Gralloc::getReservedRegion(const native_handle_t* bufferHandle, void** outReservedRegion, + uint64_t* outReservedSize) { + Error err; + mMapper->getReservedRegion( + const_cast(bufferHandle), + [&](const auto& tmpError, const auto& tmpReservedRegion, const auto& tmpReservedSize) { + err = tmpError; + *outReservedRegion = tmpReservedRegion; + *outReservedSize = tmpReservedSize; + }); + return err; +} + } // namespace vts } // namespace V4_0 } // namespace mapper diff --git a/graphics/mapper/4.0/utils/vts/include/mapper-vts/4.0/MapperVts.h b/graphics/mapper/4.0/utils/vts/include/mapper-vts/4.0/MapperVts.h index 6251e6649c..de77e1ff59 100644 --- a/graphics/mapper/4.0/utils/vts/include/mapper-vts/4.0/MapperVts.h +++ b/graphics/mapper/4.0/utils/vts/include/mapper-vts/4.0/MapperVts.h @@ -90,6 +90,9 @@ class Gralloc { const IMapper::MetadataType& metadataType, hidl_vec* outVec); + Error getReservedRegion(const native_handle_t* bufferHandle, void** outReservedRegion, + uint64_t* outReservedSize); + private: void init(const std::string& allocatorServiceName, const std::string& mapperServiceName); diff --git a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp index d63b078d1b..f5c0617cd7 100644 --- a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp +++ b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp @@ -16,6 +16,7 @@ #define LOG_TAG "VtsHalGraphicsMapperV4_0TargetTest" +#include #include #include #include @@ -82,6 +83,7 @@ class GraphicsMapperHidlTest : public ::testing::VtsHalHidlTargetTestBase { mDummyDescriptorInfo.format = PixelFormat::RGBA_8888; mDummyDescriptorInfo.usage = static_cast(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN); + mDummyDescriptorInfo.reservedSize = 0; } void TearDown() override {} @@ -1821,6 +1823,124 @@ TEST_F(GraphicsMapperHidlTest, DumpBuffers) { } } +/** + * Test IMapper::getReservedRegion() + */ +TEST_F(GraphicsMapperHidlTest, GetReservedRegion) { + const native_handle_t* bufferHandle = nullptr; + auto info = mDummyDescriptorInfo; + + const int pageSize = getpagesize(); + ASSERT_GE(0, pageSize); + std::vector requestedReservedSizes{1, 10, 333, static_cast(pageSize) / 2, + static_cast(pageSize)}; + + for (auto requestedReservedSize : requestedReservedSizes) { + info.reservedSize = requestedReservedSize; + + ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(info, true)); + + void* reservedRegion = nullptr; + uint64_t reservedSize = 0; + ASSERT_EQ(Error::NONE, + mGralloc->getReservedRegion(bufferHandle, &reservedRegion, &reservedSize)); + ASSERT_NE(nullptr, reservedRegion); + ASSERT_EQ(requestedReservedSize, reservedSize); + + uint8_t testValue = 1; + memset(reservedRegion, testValue, reservedSize); + for (uint64_t i = 0; i < reservedSize; i++) { + ASSERT_EQ(testValue, static_cast(reservedRegion)[i]); + } + } +} + +/** + * Test IMapper::getReservedRegion() request over a page + */ +TEST_F(GraphicsMapperHidlTest, GetLargeReservedRegion) { + const native_handle_t* bufferHandle = nullptr; + auto info = mDummyDescriptorInfo; + + const int pageSize = getpagesize(); + ASSERT_GE(0, pageSize); + std::vector requestedReservedSizes{static_cast(pageSize) * 2, + static_cast(pageSize) * 10, + static_cast(pageSize) * 1000}; + + for (auto requestedReservedSize : requestedReservedSizes) { + info.reservedSize = requestedReservedSize; + + BufferDescriptor descriptor; + ASSERT_NO_FATAL_FAILURE(descriptor = mGralloc->createDescriptor(info)); + + Error err; + mGralloc->getAllocator()->allocate( + descriptor, 1, + [&](const auto& tmpError, const auto&, const auto&) { err = tmpError; }); + 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_F(GraphicsMapperHidlTest, GetReservedRegionMultiple) { + const native_handle_t* bufferHandle = nullptr; + auto info = mDummyDescriptorInfo; + + const int pageSize = getpagesize(); + ASSERT_GE(0, pageSize); + info.reservedSize = pageSize; + + ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(info, true)); + + void* reservedRegion1 = nullptr; + uint64_t reservedSize1 = 0; + ASSERT_EQ(Error::NONE, + mGralloc->getReservedRegion(bufferHandle, &reservedRegion1, &reservedSize1)); + ASSERT_NE(nullptr, reservedRegion1); + ASSERT_EQ(info.reservedSize, reservedSize1); + + std::unique_ptr anotherGralloc; + ASSERT_NO_FATAL_FAILURE( + anotherGralloc = std::make_unique( + GraphicsMapperHidlEnvironment::Instance()->getServiceName(), + GraphicsMapperHidlEnvironment::Instance()->getServiceName())); + + 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_F(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); +} + } // namespace } // namespace vts } // namespace V4_0