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