• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
Instance()42     static GraphicsMapperHidlEnvironment* Instance() {
43         static GraphicsMapperHidlEnvironment* instance = new GraphicsMapperHidlEnvironment;
44         return instance;
45     }
46 
registerTestServices()47     virtual void registerTestServices() override {
48         registerTestService<IAllocator>();
49         registerTestService<IMapper>();
50     }
51 };
52 
53 class GraphicsMapperHidlTest : public ::testing::VtsHalHidlTargetTestBase {
54    protected:
SetUp()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 
TearDown()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  */
TEST_F(GraphicsMapperHidlTest,AllocatorDumpDebugInfo)78 TEST_F(GraphicsMapperHidlTest, AllocatorDumpDebugInfo) {
79     mGralloc->dumpDebugInfo();
80 }
81 
82 /**
83  * Test IAllocator::allocate with valid buffer descriptors.
84  */
TEST_F(GraphicsMapperHidlTest,AllocatorAllocate)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  */
TEST_F(GraphicsMapperHidlTest,AllocatorAllocateNegative)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  */
TEST_F(GraphicsMapperHidlTest,AllocatorAllocateNoLeak)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  */
TEST_F(GraphicsMapperHidlTest,AllocatorAllocateThreaded)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  */
TEST_F(GraphicsMapperHidlTest,CreateDescriptorBasic)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  */
TEST_F(GraphicsMapperHidlTest,CreateDescriptorNegative)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  */
TEST_F(GraphicsMapperHidlTest,ImportFreeBufferBasic)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  */
TEST_F(GraphicsMapperHidlTest,ImportFreeBufferClone)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  */
TEST_F(GraphicsMapperHidlTest,ImportFreeBufferSingleton)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  */
TEST_F(GraphicsMapperHidlTest,ImportFreeBufferNoLeak)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  */
TEST_F(GraphicsMapperHidlTest,ImportBufferNegative)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  */
TEST_F(GraphicsMapperHidlTest,FreeBufferNegative)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  */
TEST_F(GraphicsMapperHidlTest,LockUnlockBasic)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  */
TEST_F(GraphicsMapperHidlTest,LockYCbCrBasic)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  */
TEST_F(GraphicsMapperHidlTest,UnlockNegative)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  */
TEST_F(GraphicsMapperHidlTest,IsSupportedRGBA8888)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  */
TEST_F(GraphicsMapperHidlTest,IsSupportedYV12)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  */
TEST_F(GraphicsMapperHidlTest,IsSupportedY16)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 
main(int argc,char ** argv)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