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