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