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