1 /*
2  * Copyright (C) 2016 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 "VtsHalGraphicsMapperV2_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/2.0/MapperVts.h>
28 
29 namespace android {
30 namespace hardware {
31 namespace graphics {
32 namespace mapper {
33 namespace V2_0 {
34 namespace vts {
35 namespace {
36 
37 using android::hardware::graphics::common::V1_0::BufferUsage;
38 using android::hardware::graphics::common::V1_0::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     ASSERT_NO_FATAL_FAILURE(
286         data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage, region, fence)));
287 
288     // RGBA_8888
289     size_t strideInBytes = stride * 4;
290     size_t writeInBytes = info.width * 4;
291 
292     for (uint32_t y = 0; y < info.height; y++) {
293         memset(data, y, writeInBytes);
294         data += strideInBytes;
295     }
296 
297     ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
298 
299     // lock again for reading
300     ASSERT_NO_FATAL_FAILURE(
301         data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage, region, fence)));
302     for (uint32_t y = 0; y < info.height; y++) {
303         for (size_t i = 0; i < writeInBytes; i++) {
304             EXPECT_EQ(static_cast<uint8_t>(y), data[i]);
305         }
306         data += strideInBytes;
307     }
308 
309     ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
310     if (fence >= 0) {
311         close(fence);
312     }
313 }
314 
315 /**
316  * Test IMapper::lockYCbCr.  This locks a YV12 buffer, and makes sure we can
317  * write to and read from it.
318  */
TEST_P(GraphicsMapperHidlTest,LockYCbCrBasic)319 TEST_P(GraphicsMapperHidlTest, LockYCbCrBasic) {
320     auto info = mDummyDescriptorInfo;
321     info.format = PixelFormat::YV12;
322 
323     const native_handle_t* bufferHandle;
324     uint32_t stride;
325     ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(info, true, &stride));
326 
327     // lock buffer for writing
328     const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
329                                static_cast<int32_t>(info.height)};
330     int fence = -1;
331     YCbCrLayout layout;
332     ASSERT_NO_FATAL_FAILURE(layout = mGralloc->lockYCbCr(bufferHandle, info.usage, region, fence));
333 
334     auto yData = static_cast<uint8_t*>(layout.y);
335     auto cbData = static_cast<uint8_t*>(layout.cb);
336     auto crData = static_cast<uint8_t*>(layout.cr);
337     for (uint32_t y = 0; y < info.height; y++) {
338         for (uint32_t x = 0; x < info.width; x++) {
339             auto val = static_cast<uint8_t>(info.height * y + x);
340 
341             yData[layout.yStride * y + x] = val;
342             if (y % 2 == 0 && x % 2 == 0) {
343                 cbData[layout.cStride * y / 2 + x / 2] = val;
344                 crData[layout.cStride * y / 2 + x / 2] = val;
345             }
346         }
347     }
348 
349     ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
350 
351     // lock again for reading
352     ASSERT_NO_FATAL_FAILURE(layout = mGralloc->lockYCbCr(bufferHandle, info.usage, region, fence));
353 
354     yData = static_cast<uint8_t*>(layout.y);
355     cbData = static_cast<uint8_t*>(layout.cb);
356     crData = static_cast<uint8_t*>(layout.cr);
357     for (uint32_t y = 0; y < info.height; y++) {
358         for (uint32_t x = 0; x < info.width; x++) {
359             auto val = static_cast<uint8_t>(info.height * y + x);
360 
361             EXPECT_EQ(val, yData[layout.yStride * y + x]);
362             if (y % 2 == 0 && x % 2 == 0) {
363                 EXPECT_EQ(val, cbData[layout.cStride * y / 2 + x / 2]);
364                 EXPECT_EQ(val, crData[layout.cStride * y / 2 + x / 2]);
365             }
366         }
367     }
368 
369     ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
370     if (fence >= 0) {
371         close(fence);
372     }
373 }
374 
375 /**
376  * Test IMapper::unlock with invalid buffers.
377  */
TEST_P(GraphicsMapperHidlTest,UnlockNegative)378 TEST_P(GraphicsMapperHidlTest, UnlockNegative) {
379     native_handle_t* invalidHandle = nullptr;
380     mGralloc->getMapper()->unlock(invalidHandle, [&](const auto& tmpError, const auto&) {
381         EXPECT_EQ(Error::BAD_BUFFER, tmpError)
382             << "unlock with nullptr did not fail with BAD_BUFFER";
383     });
384 
385     invalidHandle = native_handle_create(0, 0);
386     mGralloc->getMapper()->unlock(invalidHandle, [&](const auto& tmpError, const auto&) {
387         EXPECT_EQ(Error::BAD_BUFFER, tmpError)
388             << "unlock with invalid handle did not fail with BAD_BUFFER";
389     });
390     native_handle_delete(invalidHandle);
391 
392     ASSERT_NO_FATAL_FAILURE(invalidHandle = const_cast<native_handle_t*>(
393                                 mGralloc->allocate(mDummyDescriptorInfo, false)));
394     mGralloc->getMapper()->unlock(invalidHandle, [&](const auto& tmpError, const auto&) {
395         EXPECT_EQ(Error::BAD_BUFFER, tmpError)
396             << "unlock with un-imported handle did not fail with BAD_BUFFER";
397     });
398     mGralloc->freeBuffer(invalidHandle);
399 
400 // disabled as it fails on many existing drivers
401 #if 0
402   ASSERT_NO_FATAL_FAILURE(invalidHandle = const_cast<native_handle_t*>(
403                               mGralloc->allocate(mDummyDescriptorInfo, true)));
404   mGralloc->getMapper()->unlock(
405       invalidHandle, [&](const auto& tmpError, const auto&) {
406         EXPECT_EQ(Error::BAD_BUFFER, tmpError)
407             << "unlock with unlocked handle did not fail with BAD_BUFFER";
408       });
409   mGralloc->freeBuffer(invalidHandle);
410 #endif
411 }
412 
413 INSTANTIATE_TEST_CASE_P(
414         PerInstance, GraphicsMapperHidlTest,
415         testing::Combine(
416                 testing::ValuesIn(
417                         android::hardware::getAllHalInstanceNames(IAllocator::descriptor)),
418                 testing::ValuesIn(android::hardware::getAllHalInstanceNames(IMapper::descriptor))),
419         android::hardware::PrintInstanceTupleNameToString<>);
420 
421 }  // namespace
422 }  // namespace vts
423 }  // namespace V2_0
424 }  // namespace mapper
425 }  // namespace graphics
426 }  // namespace hardware
427 }  // namespace android
428