Home | History | Annotate | Download | only in functional
      1 /*
      2  * Copyright 2018 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #define LOG_TAG "VtsHalGraphicsMapperV3_0TargetTest"
     18 
     19 #include <chrono>
     20 #include <thread>
     21 #include <vector>
     22 
     23 #include <VtsHalHidlTargetTestBase.h>
     24 #include <android-base/logging.h>
     25 #include <mapper-vts/3.0/MapperVts.h>
     26 
     27 namespace android {
     28 namespace hardware {
     29 namespace graphics {
     30 namespace mapper {
     31 namespace V3_0 {
     32 namespace vts {
     33 namespace {
     34 
     35 using android::hardware::graphics::common::V1_2::BufferUsage;
     36 using android::hardware::graphics::common::V1_2::PixelFormat;
     37 
     38 // Test environment for graphics.mapper.
     39 class GraphicsMapperHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
     40    public:
     41     // get the test environment singleton
     42     static GraphicsMapperHidlEnvironment* Instance() {
     43         static GraphicsMapperHidlEnvironment* instance = new GraphicsMapperHidlEnvironment;
     44         return instance;
     45     }
     46 
     47     virtual void registerTestServices() override {
     48         registerTestService<IAllocator>();
     49         registerTestService<IMapper>();
     50     }
     51 };
     52 
     53 class GraphicsMapperHidlTest : public ::testing::VtsHalHidlTargetTestBase {
     54    protected:
     55     void SetUp() override {
     56         ASSERT_NO_FATAL_FAILURE(
     57             mGralloc = std::make_unique<Gralloc>(
     58                 GraphicsMapperHidlEnvironment::Instance()->getServiceName<IAllocator>(),
     59                 GraphicsMapperHidlEnvironment::Instance()->getServiceName<IMapper>()));
     60 
     61         mDummyDescriptorInfo.width = 64;
     62         mDummyDescriptorInfo.height = 64;
     63         mDummyDescriptorInfo.layerCount = 1;
     64         mDummyDescriptorInfo.format = PixelFormat::RGBA_8888;
     65         mDummyDescriptorInfo.usage =
     66             static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN);
     67     }
     68 
     69     void TearDown() override {}
     70 
     71     std::unique_ptr<Gralloc> mGralloc;
     72     IMapper::BufferDescriptorInfo mDummyDescriptorInfo{};
     73 };
     74 
     75 /**
     76  * Test IAllocator::dumpDebugInfo by calling it.
     77  */
     78 TEST_F(GraphicsMapperHidlTest, AllocatorDumpDebugInfo) {
     79     mGralloc->dumpDebugInfo();
     80 }
     81 
     82 /**
     83  * Test IAllocator::allocate with valid buffer descriptors.
     84  */
     85 TEST_F(GraphicsMapperHidlTest, AllocatorAllocate) {
     86     BufferDescriptor descriptor;
     87     ASSERT_NO_FATAL_FAILURE(descriptor = mGralloc->createDescriptor(mDummyDescriptorInfo));
     88 
     89     for (uint32_t count = 0; count < 5; count++) {
     90         std::vector<const native_handle_t*> bufferHandles;
     91         uint32_t stride;
     92         ASSERT_NO_FATAL_FAILURE(bufferHandles =
     93                                     mGralloc->allocate(descriptor, count, false, &stride));
     94 
     95         if (count >= 1) {
     96             EXPECT_LE(mDummyDescriptorInfo.width, stride) << "invalid buffer stride";
     97         }
     98 
     99         for (auto bufferHandle : bufferHandles) {
    100             mGralloc->freeBuffer(bufferHandle);
    101         }
    102     }
    103 }
    104 
    105 /**
    106  * Test IAllocator::allocate with invalid buffer descriptors.
    107  */
    108 TEST_F(GraphicsMapperHidlTest, AllocatorAllocateNegative) {
    109     // this assumes any valid descriptor is non-empty
    110     BufferDescriptor descriptor;
    111     mGralloc->getAllocator()->allocate(descriptor, 1,
    112                                        [&](const auto& tmpError, const auto&, const auto&) {
    113                                            EXPECT_EQ(Error::BAD_DESCRIPTOR, tmpError);
    114                                        });
    115 }
    116 
    117 /**
    118  * Test IAllocator::allocate does not leak.
    119  */
    120 TEST_F(GraphicsMapperHidlTest, AllocatorAllocateNoLeak) {
    121     auto info = mDummyDescriptorInfo;
    122     info.width = 1024;
    123     info.height = 1024;
    124 
    125     for (int i = 0; i < 2048; i++) {
    126         auto bufferHandle = mGralloc->allocate(info, false);
    127         mGralloc->freeBuffer(bufferHandle);
    128     }
    129 }
    130 
    131 /**
    132  * Test that IAllocator::allocate is thread-safe.
    133  */
    134 TEST_F(GraphicsMapperHidlTest, AllocatorAllocateThreaded) {
    135     BufferDescriptor descriptor;
    136     ASSERT_NO_FATAL_FAILURE(descriptor = mGralloc->createDescriptor(mDummyDescriptorInfo));
    137 
    138     std::atomic<bool> timeUp(false);
    139     std::atomic<uint64_t> allocationCount(0);
    140     auto threadLoop = [&]() {
    141         while (!timeUp) {
    142             mGralloc->getAllocator()->allocate(
    143                 descriptor, 1, [&](const auto&, const auto&, const auto&) { allocationCount++; });
    144         }
    145     };
    146 
    147     std::vector<std::thread> threads;
    148     for (int i = 0; i < 8; i++) {
    149         threads.push_back(std::thread(threadLoop));
    150     }
    151 
    152     std::this_thread::sleep_for(std::chrono::seconds(3));
    153     timeUp = true;
    154     LOG(VERBOSE) << "Made " << allocationCount << " threaded allocations";
    155 
    156     for (auto& thread : threads) {
    157         thread.join();
    158     }
    159 }
    160 
    161 /**
    162  * Test IMapper::createDescriptor with valid descriptor info.
    163  */
    164 TEST_F(GraphicsMapperHidlTest, CreateDescriptorBasic) {
    165     ASSERT_NO_FATAL_FAILURE(mGralloc->createDescriptor(mDummyDescriptorInfo));
    166 }
    167 
    168 /**
    169  * Test IMapper::createDescriptor with invalid descriptor info.
    170  */
    171 TEST_F(GraphicsMapperHidlTest, CreateDescriptorNegative) {
    172     auto info = mDummyDescriptorInfo;
    173     info.width = 0;
    174     mGralloc->getMapper()->createDescriptor(info, [&](const auto& tmpError, const auto&) {
    175         EXPECT_EQ(Error::BAD_VALUE, tmpError) << "createDescriptor did not fail with BAD_VALUE";
    176     });
    177 }
    178 
    179 /**
    180  * Test IMapper::importBuffer and IMapper::freeBuffer with allocated buffers.
    181  */
    182 TEST_F(GraphicsMapperHidlTest, ImportFreeBufferBasic) {
    183     const native_handle_t* bufferHandle;
    184     ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(mDummyDescriptorInfo, true));
    185     ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(bufferHandle));
    186 }
    187 
    188 /**
    189  * Test IMapper::importBuffer and IMapper::freeBuffer with cloned buffers.
    190  */
    191 TEST_F(GraphicsMapperHidlTest, ImportFreeBufferClone) {
    192     const native_handle_t* clonedBufferHandle;
    193     ASSERT_NO_FATAL_FAILURE(clonedBufferHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
    194 
    195     // A cloned handle is a raw handle. Check that we can import it multiple
    196     // times.
    197     const native_handle_t* importedBufferHandles[2];
    198     ASSERT_NO_FATAL_FAILURE(importedBufferHandles[0] = mGralloc->importBuffer(clonedBufferHandle));
    199     ASSERT_NO_FATAL_FAILURE(importedBufferHandles[1] = mGralloc->importBuffer(clonedBufferHandle));
    200     ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(importedBufferHandles[0]));
    201     ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(importedBufferHandles[1]));
    202 
    203     ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(clonedBufferHandle));
    204 }
    205 
    206 /**
    207  * Test IMapper::importBuffer and IMapper::freeBuffer cross mapper instances.
    208  */
    209 TEST_F(GraphicsMapperHidlTest, ImportFreeBufferSingleton) {
    210     const native_handle_t* rawHandle;
    211     ASSERT_NO_FATAL_FAILURE(rawHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
    212 
    213     native_handle_t* importedHandle = nullptr;
    214     mGralloc->getMapper()->importBuffer(rawHandle, [&](const auto& tmpError, const auto& buffer) {
    215         ASSERT_EQ(Error::NONE, tmpError);
    216         importedHandle = static_cast<native_handle_t*>(buffer);
    217     });
    218 
    219     // free the imported handle with another mapper
    220     std::unique_ptr<Gralloc> anotherGralloc;
    221     ASSERT_NO_FATAL_FAILURE(
    222         anotherGralloc = std::make_unique<Gralloc>(
    223             GraphicsMapperHidlEnvironment::Instance()->getServiceName<IAllocator>(),
    224             GraphicsMapperHidlEnvironment::Instance()->getServiceName<IMapper>()));
    225     Error error = mGralloc->getMapper()->freeBuffer(importedHandle);
    226     ASSERT_EQ(Error::NONE, error);
    227 
    228     ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(rawHandle));
    229 }
    230 
    231 /**
    232  * Test IMapper::importBuffer and IMapper::freeBuffer do not leak.
    233  */
    234 TEST_F(GraphicsMapperHidlTest, ImportFreeBufferNoLeak) {
    235     auto info = mDummyDescriptorInfo;
    236     info.width = 1024;
    237     info.height = 1024;
    238 
    239     for (int i = 0; i < 2048; i++) {
    240         auto bufferHandle = mGralloc->allocate(info, true);
    241         mGralloc->freeBuffer(bufferHandle);
    242     }
    243 }
    244 
    245 /**
    246  * Test IMapper::importBuffer with invalid buffers.
    247  */
    248 TEST_F(GraphicsMapperHidlTest, ImportBufferNegative) {
    249     native_handle_t* invalidHandle = nullptr;
    250     mGralloc->getMapper()->importBuffer(invalidHandle, [&](const auto& tmpError, const auto&) {
    251         EXPECT_EQ(Error::BAD_BUFFER, tmpError)
    252             << "importBuffer with nullptr did not fail with BAD_BUFFER";
    253     });
    254 
    255     invalidHandle = native_handle_create(0, 0);
    256     mGralloc->getMapper()->importBuffer(invalidHandle, [&](const auto& tmpError, const auto&) {
    257         EXPECT_EQ(Error::BAD_BUFFER, tmpError)
    258             << "importBuffer with invalid handle did not fail with BAD_BUFFER";
    259     });
    260     native_handle_delete(invalidHandle);
    261 }
    262 
    263 /**
    264  * Test IMapper::freeBuffer with invalid buffers.
    265  */
    266 TEST_F(GraphicsMapperHidlTest, FreeBufferNegative) {
    267     native_handle_t* invalidHandle = nullptr;
    268     Error error = mGralloc->getMapper()->freeBuffer(invalidHandle);
    269     EXPECT_EQ(Error::BAD_BUFFER, error) << "freeBuffer with nullptr did not fail with BAD_BUFFER";
    270 
    271     invalidHandle = native_handle_create(0, 0);
    272     error = mGralloc->getMapper()->freeBuffer(invalidHandle);
    273     EXPECT_EQ(Error::BAD_BUFFER, error)
    274         << "freeBuffer with invalid handle did not fail with BAD_BUFFER";
    275     native_handle_delete(invalidHandle);
    276 
    277     const native_handle_t* clonedBufferHandle;
    278     ASSERT_NO_FATAL_FAILURE(clonedBufferHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
    279     error = mGralloc->getMapper()->freeBuffer(invalidHandle);
    280     EXPECT_EQ(Error::BAD_BUFFER, error)
    281         << "freeBuffer with un-imported handle did not fail with BAD_BUFFER";
    282 
    283     mGralloc->freeBuffer(clonedBufferHandle);
    284 }
    285 
    286 /**
    287  * Test IMapper::lock and IMapper::unlock.
    288  */
    289 TEST_F(GraphicsMapperHidlTest, LockUnlockBasic) {
    290     const auto& info = mDummyDescriptorInfo;
    291 
    292     const native_handle_t* bufferHandle;
    293     uint32_t stride;
    294     ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(info, true, &stride));
    295 
    296     // lock buffer for writing
    297     const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
    298                                static_cast<int32_t>(info.height)};
    299     int fence = -1;
    300     uint8_t* data;
    301     int32_t bytesPerPixel = -1;
    302     int32_t bytesPerStride = -1;
    303     ASSERT_NO_FATAL_FAILURE(
    304             data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage, region, fence,
    305                                                         &bytesPerPixel, &bytesPerStride)));
    306 
    307     // Valid return values are -1 for unsupported or the number bytes for supported which is >=0
    308     EXPECT_GT(bytesPerPixel, -1);
    309     EXPECT_GT(bytesPerStride, -1);
    310 
    311     // RGBA_8888
    312     size_t strideInBytes = stride * 4;
    313     size_t writeInBytes = info.width * 4;
    314 
    315     for (uint32_t y = 0; y < info.height; y++) {
    316         memset(data, y, writeInBytes);
    317         data += strideInBytes;
    318     }
    319 
    320     ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
    321 
    322     bytesPerPixel = -1;
    323     bytesPerStride = -1;
    324 
    325     // lock again for reading
    326     ASSERT_NO_FATAL_FAILURE(
    327             data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage, region, fence,
    328                                                         &bytesPerPixel, &bytesPerStride)));
    329     for (uint32_t y = 0; y < info.height; y++) {
    330         for (size_t i = 0; i < writeInBytes; i++) {
    331             EXPECT_EQ(static_cast<uint8_t>(y), data[i]);
    332         }
    333         data += strideInBytes;
    334     }
    335 
    336     EXPECT_GT(bytesPerPixel, -1);
    337     EXPECT_GT(bytesPerStride, -1);
    338 
    339     ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
    340     if (fence >= 0) {
    341         close(fence);
    342     }
    343 }
    344 
    345 /**
    346  * Test IMapper::lockYCbCr.  This locks a YV12 buffer, and makes sure we can
    347  * write to and read from it.
    348  */
    349 TEST_F(GraphicsMapperHidlTest, LockYCbCrBasic) {
    350     auto info = mDummyDescriptorInfo;
    351     info.format = PixelFormat::YV12;
    352 
    353     const native_handle_t* bufferHandle;
    354     uint32_t stride;
    355     ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(info, true, &stride));
    356 
    357     // lock buffer for writing
    358     const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
    359                                static_cast<int32_t>(info.height)};
    360     int fence = -1;
    361     YCbCrLayout layout;
    362     ASSERT_NO_FATAL_FAILURE(layout = mGralloc->lockYCbCr(bufferHandle, info.usage, region, fence));
    363 
    364     auto yData = static_cast<uint8_t*>(layout.y);
    365     auto cbData = static_cast<uint8_t*>(layout.cb);
    366     auto crData = static_cast<uint8_t*>(layout.cr);
    367     for (uint32_t y = 0; y < info.height; y++) {
    368         for (uint32_t x = 0; x < info.width; x++) {
    369             auto val = static_cast<uint8_t>(info.height * y + x);
    370 
    371             yData[layout.yStride * y + x] = val;
    372             if (y % 2 == 0 && x % 2 == 0) {
    373                 cbData[layout.cStride * y / 2 + x / 2] = val;
    374                 crData[layout.cStride * y / 2 + x / 2] = val;
    375             }
    376         }
    377     }
    378 
    379     ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
    380 
    381     // lock again for reading
    382     ASSERT_NO_FATAL_FAILURE(layout = mGralloc->lockYCbCr(bufferHandle, info.usage, region, fence));
    383 
    384     yData = static_cast<uint8_t*>(layout.y);
    385     cbData = static_cast<uint8_t*>(layout.cb);
    386     crData = static_cast<uint8_t*>(layout.cr);
    387     for (uint32_t y = 0; y < info.height; y++) {
    388         for (uint32_t x = 0; x < info.width; x++) {
    389             auto val = static_cast<uint8_t>(info.height * y + x);
    390 
    391             EXPECT_EQ(val, yData[layout.yStride * y + x]);
    392             if (y % 2 == 0 && x % 2 == 0) {
    393                 EXPECT_EQ(val, cbData[layout.cStride * y / 2 + x / 2]);
    394                 EXPECT_EQ(val, crData[layout.cStride * y / 2 + x / 2]);
    395             }
    396         }
    397     }
    398 
    399     ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
    400     if (fence >= 0) {
    401         close(fence);
    402     }
    403 }
    404 
    405 /**
    406  * Test IMapper::unlock with invalid buffers.
    407  */
    408 TEST_F(GraphicsMapperHidlTest, UnlockNegative) {
    409     native_handle_t* invalidHandle = nullptr;
    410     mGralloc->getMapper()->unlock(invalidHandle, [&](const auto& tmpError, const auto&) {
    411         EXPECT_EQ(Error::BAD_BUFFER, tmpError)
    412             << "unlock with nullptr did not fail with BAD_BUFFER";
    413     });
    414 
    415     invalidHandle = native_handle_create(0, 0);
    416     mGralloc->getMapper()->unlock(invalidHandle, [&](const auto& tmpError, const auto&) {
    417         EXPECT_EQ(Error::BAD_BUFFER, tmpError)
    418             << "unlock with invalid handle did not fail with BAD_BUFFER";
    419     });
    420     native_handle_delete(invalidHandle);
    421 
    422     ASSERT_NO_FATAL_FAILURE(invalidHandle = const_cast<native_handle_t*>(
    423                                 mGralloc->allocate(mDummyDescriptorInfo, false)));
    424     mGralloc->getMapper()->unlock(invalidHandle, [&](const auto& tmpError, const auto&) {
    425         EXPECT_EQ(Error::BAD_BUFFER, tmpError)
    426             << "unlock with un-imported handle did not fail with BAD_BUFFER";
    427     });
    428     mGralloc->freeBuffer(invalidHandle);
    429 
    430 // disabled as it fails on many existing drivers
    431 #if 0
    432   ASSERT_NO_FATAL_FAILURE(invalidHandle = const_cast<native_handle_t*>(
    433                               mGralloc->allocate(mDummyDescriptorInfo, true)));
    434   mGralloc->getMapper()->unlock(
    435       invalidHandle, [&](const auto& tmpError, const auto&) {
    436         EXPECT_EQ(Error::BAD_BUFFER, tmpError)
    437             << "unlock with unlocked handle did not fail with BAD_BUFFER";
    438       });
    439   mGralloc->freeBuffer(invalidHandle);
    440 #endif
    441 }
    442 
    443 /**
    444  * Test IMapper::isSupported with required format RGBA_8888
    445  */
    446 TEST_F(GraphicsMapperHidlTest, IsSupportedRGBA8888) {
    447     const auto& info = mDummyDescriptorInfo;
    448     bool supported = false;
    449 
    450     ASSERT_NO_FATAL_FAILURE(supported = mGralloc->isSupported(info));
    451     ASSERT_TRUE(supported);
    452 }
    453 
    454 /**
    455  * Test IMapper::isSupported with required format YV12
    456  */
    457 TEST_F(GraphicsMapperHidlTest, IsSupportedYV12) {
    458     auto info = mDummyDescriptorInfo;
    459     info.format = PixelFormat::YV12;
    460     bool supported = false;
    461 
    462     ASSERT_NO_FATAL_FAILURE(supported = mGralloc->isSupported(info));
    463     ASSERT_TRUE(supported);
    464 }
    465 
    466 /**
    467  * Test IMapper::isSupported with optional format Y16
    468  */
    469 TEST_F(GraphicsMapperHidlTest, IsSupportedY16) {
    470     auto info = mDummyDescriptorInfo;
    471     info.format = PixelFormat::Y16;
    472     bool supported = false;
    473 
    474     ASSERT_NO_FATAL_FAILURE(supported = mGralloc->isSupported(info));
    475 }
    476 
    477 }  // namespace
    478 }  // namespace vts
    479 }  // namespace V3_0
    480 }  // namespace mapper
    481 }  // namespace graphics
    482 }  // namespace hardware
    483 }  // namespace android
    484 
    485 int main(int argc, char** argv) {
    486     using android::hardware::graphics::mapper::V3_0::vts::GraphicsMapperHidlEnvironment;
    487     ::testing::AddGlobalTestEnvironment(GraphicsMapperHidlEnvironment::Instance());
    488     ::testing::InitGoogleTest(&argc, argv);
    489     GraphicsMapperHidlEnvironment::Instance()->init(&argc, argv);
    490     int status = RUN_ALL_TESTS();
    491     LOG(INFO) << "Test result = " << status;
    492     return status;
    493 }
    494