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 <VtsHalHidlTargetTestBase.h>
20 #include <android-base/logging.h>
21 #include <mapper-vts/2.0/MapperVts.h>
22
23 namespace android {
24 namespace hardware {
25 namespace graphics {
26 namespace mapper {
27 namespace V2_0 {
28 namespace vts {
29 namespace {
30
31 using android::hardware::graphics::common::V1_0::BufferUsage;
32 using android::hardware::graphics::common::V1_0::PixelFormat;
33
34 // Test environment for graphics.mapper.
35 class GraphicsMapperHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
36 public:
37 // get the test environment singleton
Instance()38 static GraphicsMapperHidlEnvironment* Instance() {
39 static GraphicsMapperHidlEnvironment* instance = new GraphicsMapperHidlEnvironment;
40 return instance;
41 }
42
registerTestServices()43 virtual void registerTestServices() override {
44 registerTestService<IAllocator>();
45 registerTestService<IMapper>();
46 }
47 };
48
49 class GraphicsMapperHidlTest : public ::testing::VtsHalHidlTargetTestBase {
50 protected:
SetUp()51 void SetUp() override {
52 ASSERT_NO_FATAL_FAILURE(
53 mGralloc = std::make_unique<Gralloc>(
54 GraphicsMapperHidlEnvironment::Instance()->getServiceName<IAllocator>(),
55 GraphicsMapperHidlEnvironment::Instance()->getServiceName<IMapper>()));
56
57 mDummyDescriptorInfo.width = 64;
58 mDummyDescriptorInfo.height = 64;
59 mDummyDescriptorInfo.layerCount = 1;
60 mDummyDescriptorInfo.format = PixelFormat::RGBA_8888;
61 mDummyDescriptorInfo.usage =
62 static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN);
63 }
64
TearDown()65 void TearDown() override {}
66
67 std::unique_ptr<Gralloc> mGralloc;
68 IMapper::BufferDescriptorInfo mDummyDescriptorInfo{};
69 };
70
71 /**
72 * Test IAllocator::dumpDebugInfo by calling it.
73 */
TEST_F(GraphicsMapperHidlTest,AllocatorDumpDebugInfo)74 TEST_F(GraphicsMapperHidlTest, AllocatorDumpDebugInfo) {
75 mGralloc->dumpDebugInfo();
76 }
77
78 /**
79 * Test IAllocator::allocate with valid buffer descriptors.
80 */
TEST_F(GraphicsMapperHidlTest,AllocatorAllocate)81 TEST_F(GraphicsMapperHidlTest, AllocatorAllocate) {
82 BufferDescriptor descriptor;
83 ASSERT_NO_FATAL_FAILURE(descriptor = mGralloc->createDescriptor(mDummyDescriptorInfo));
84
85 for (uint32_t count = 0; count < 5; count++) {
86 std::vector<const native_handle_t*> bufferHandles;
87 uint32_t stride;
88 ASSERT_NO_FATAL_FAILURE(bufferHandles =
89 mGralloc->allocate(descriptor, count, false, &stride));
90
91 if (count >= 1) {
92 EXPECT_LE(mDummyDescriptorInfo.width, stride) << "invalid buffer stride";
93 }
94
95 for (auto bufferHandle : bufferHandles) {
96 mGralloc->freeBuffer(bufferHandle);
97 }
98 }
99 }
100
101 /**
102 * Test IAllocator::allocate with invalid buffer descriptors.
103 */
TEST_F(GraphicsMapperHidlTest,AllocatorAllocateNegative)104 TEST_F(GraphicsMapperHidlTest, AllocatorAllocateNegative) {
105 // this assumes any valid descriptor is non-empty
106 BufferDescriptor descriptor;
107 mGralloc->getAllocator()->allocate(descriptor, 1,
108 [&](const auto& tmpError, const auto&, const auto&) {
109 EXPECT_EQ(Error::BAD_DESCRIPTOR, tmpError);
110 });
111 }
112
113 /**
114 * Test IAllocator::allocate does not leak.
115 */
TEST_F(GraphicsMapperHidlTest,AllocatorAllocateNoLeak)116 TEST_F(GraphicsMapperHidlTest, AllocatorAllocateNoLeak) {
117 auto info = mDummyDescriptorInfo;
118 info.width = 1024;
119 info.height = 1024;
120
121 for (int i = 0; i < 2048; i++) {
122 auto bufferHandle = mGralloc->allocate(info, false);
123 mGralloc->freeBuffer(bufferHandle);
124 }
125 }
126
127 /**
128 * Test IMapper::createDescriptor with valid descriptor info.
129 */
TEST_F(GraphicsMapperHidlTest,CreateDescriptorBasic)130 TEST_F(GraphicsMapperHidlTest, CreateDescriptorBasic) {
131 ASSERT_NO_FATAL_FAILURE(mGralloc->createDescriptor(mDummyDescriptorInfo));
132 }
133
134 /**
135 * Test IMapper::createDescriptor with invalid descriptor info.
136 */
TEST_F(GraphicsMapperHidlTest,CreateDescriptorNegative)137 TEST_F(GraphicsMapperHidlTest, CreateDescriptorNegative) {
138 auto info = mDummyDescriptorInfo;
139 info.width = 0;
140 mGralloc->getMapper()->createDescriptor(info, [&](const auto& tmpError, const auto&) {
141 EXPECT_EQ(Error::BAD_VALUE, tmpError) << "createDescriptor did not fail with BAD_VALUE";
142 });
143 }
144
145 /**
146 * Test IMapper::importBuffer and IMapper::freeBuffer with allocated buffers.
147 */
TEST_F(GraphicsMapperHidlTest,ImportFreeBufferBasic)148 TEST_F(GraphicsMapperHidlTest, ImportFreeBufferBasic) {
149 const native_handle_t* bufferHandle;
150 ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(mDummyDescriptorInfo, true));
151 ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(bufferHandle));
152 }
153
154 /**
155 * Test IMapper::importBuffer and IMapper::freeBuffer with cloned buffers.
156 */
TEST_F(GraphicsMapperHidlTest,ImportFreeBufferClone)157 TEST_F(GraphicsMapperHidlTest, ImportFreeBufferClone) {
158 const native_handle_t* clonedBufferHandle;
159 ASSERT_NO_FATAL_FAILURE(clonedBufferHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
160
161 // A cloned handle is a raw handle. Check that we can import it multiple
162 // times.
163 const native_handle_t* importedBufferHandles[2];
164 ASSERT_NO_FATAL_FAILURE(importedBufferHandles[0] = mGralloc->importBuffer(clonedBufferHandle));
165 ASSERT_NO_FATAL_FAILURE(importedBufferHandles[1] = mGralloc->importBuffer(clonedBufferHandle));
166 ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(importedBufferHandles[0]));
167 ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(importedBufferHandles[1]));
168
169 ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(clonedBufferHandle));
170 }
171
172 /**
173 * Test IMapper::importBuffer and IMapper::freeBuffer cross mapper instances.
174 */
TEST_F(GraphicsMapperHidlTest,ImportFreeBufferSingleton)175 TEST_F(GraphicsMapperHidlTest, ImportFreeBufferSingleton) {
176 const native_handle_t* rawHandle;
177 ASSERT_NO_FATAL_FAILURE(rawHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
178
179 native_handle_t* importedHandle = nullptr;
180 mGralloc->getMapper()->importBuffer(rawHandle, [&](const auto& tmpError, const auto& buffer) {
181 ASSERT_EQ(Error::NONE, tmpError);
182 importedHandle = static_cast<native_handle_t*>(buffer);
183 });
184
185 // free the imported handle with another mapper
186 std::unique_ptr<Gralloc> anotherGralloc;
187 ASSERT_NO_FATAL_FAILURE(
188 anotherGralloc = std::make_unique<Gralloc>(
189 GraphicsMapperHidlEnvironment::Instance()->getServiceName<IAllocator>(),
190 GraphicsMapperHidlEnvironment::Instance()->getServiceName<IMapper>()));
191 Error error = mGralloc->getMapper()->freeBuffer(importedHandle);
192 ASSERT_EQ(Error::NONE, error);
193
194 ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(rawHandle));
195 }
196
197 /**
198 * Test IMapper::importBuffer and IMapper::freeBuffer do not leak.
199 */
TEST_F(GraphicsMapperHidlTest,ImportFreeBufferNoLeak)200 TEST_F(GraphicsMapperHidlTest, ImportFreeBufferNoLeak) {
201 auto info = mDummyDescriptorInfo;
202 info.width = 1024;
203 info.height = 1024;
204
205 for (int i = 0; i < 2048; i++) {
206 auto bufferHandle = mGralloc->allocate(info, true);
207 mGralloc->freeBuffer(bufferHandle);
208 }
209 }
210
211 /**
212 * Test IMapper::importBuffer with invalid buffers.
213 */
TEST_F(GraphicsMapperHidlTest,ImportBufferNegative)214 TEST_F(GraphicsMapperHidlTest, ImportBufferNegative) {
215 native_handle_t* invalidHandle = nullptr;
216 mGralloc->getMapper()->importBuffer(invalidHandle, [&](const auto& tmpError, const auto&) {
217 EXPECT_EQ(Error::BAD_BUFFER, tmpError)
218 << "importBuffer with nullptr did not fail with BAD_BUFFER";
219 });
220
221 invalidHandle = native_handle_create(0, 0);
222 mGralloc->getMapper()->importBuffer(invalidHandle, [&](const auto& tmpError, const auto&) {
223 EXPECT_EQ(Error::BAD_BUFFER, tmpError)
224 << "importBuffer with invalid handle did not fail with BAD_BUFFER";
225 });
226 native_handle_delete(invalidHandle);
227 }
228
229 /**
230 * Test IMapper::freeBuffer with invalid buffers.
231 */
TEST_F(GraphicsMapperHidlTest,FreeBufferNegative)232 TEST_F(GraphicsMapperHidlTest, FreeBufferNegative) {
233 native_handle_t* invalidHandle = nullptr;
234 Error error = mGralloc->getMapper()->freeBuffer(invalidHandle);
235 EXPECT_EQ(Error::BAD_BUFFER, error) << "freeBuffer with nullptr did not fail with BAD_BUFFER";
236
237 invalidHandle = native_handle_create(0, 0);
238 error = mGralloc->getMapper()->freeBuffer(invalidHandle);
239 EXPECT_EQ(Error::BAD_BUFFER, error)
240 << "freeBuffer with invalid handle did not fail with BAD_BUFFER";
241 native_handle_delete(invalidHandle);
242
243 const native_handle_t* clonedBufferHandle;
244 ASSERT_NO_FATAL_FAILURE(clonedBufferHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
245 error = mGralloc->getMapper()->freeBuffer(invalidHandle);
246 EXPECT_EQ(Error::BAD_BUFFER, error)
247 << "freeBuffer with un-imported handle did not fail with BAD_BUFFER";
248
249 mGralloc->freeBuffer(clonedBufferHandle);
250 }
251
252 /**
253 * Test IMapper::lock and IMapper::unlock.
254 */
TEST_F(GraphicsMapperHidlTest,LockUnlockBasic)255 TEST_F(GraphicsMapperHidlTest, LockUnlockBasic) {
256 const auto& info = mDummyDescriptorInfo;
257
258 const native_handle_t* bufferHandle;
259 uint32_t stride;
260 ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(info, true, &stride));
261
262 // lock buffer for writing
263 const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
264 static_cast<int32_t>(info.height)};
265 int fence = -1;
266 uint8_t* data;
267 ASSERT_NO_FATAL_FAILURE(
268 data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage, region, fence)));
269
270 // RGBA_8888
271 size_t strideInBytes = stride * 4;
272 size_t writeInBytes = info.width * 4;
273
274 for (uint32_t y = 0; y < info.height; y++) {
275 memset(data, y, writeInBytes);
276 data += strideInBytes;
277 }
278
279 ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
280
281 // lock again for reading
282 ASSERT_NO_FATAL_FAILURE(
283 data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage, region, fence)));
284 for (uint32_t y = 0; y < info.height; y++) {
285 for (size_t i = 0; i < writeInBytes; i++) {
286 EXPECT_EQ(static_cast<uint8_t>(y), data[i]);
287 }
288 data += strideInBytes;
289 }
290
291 ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
292 if (fence >= 0) {
293 close(fence);
294 }
295 }
296
297 /**
298 * Test IMapper::lockYCbCr. This locks a YV12 buffer, and makes sure we can
299 * write to and read from it.
300 */
TEST_F(GraphicsMapperHidlTest,LockYCbCrBasic)301 TEST_F(GraphicsMapperHidlTest, LockYCbCrBasic) {
302 auto info = mDummyDescriptorInfo;
303 info.format = PixelFormat::YV12;
304
305 const native_handle_t* bufferHandle;
306 uint32_t stride;
307 ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(info, true, &stride));
308
309 // lock buffer for writing
310 const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
311 static_cast<int32_t>(info.height)};
312 int fence = -1;
313 YCbCrLayout layout;
314 ASSERT_NO_FATAL_FAILURE(layout = mGralloc->lockYCbCr(bufferHandle, info.usage, region, fence));
315
316 auto yData = static_cast<uint8_t*>(layout.y);
317 auto cbData = static_cast<uint8_t*>(layout.cb);
318 auto crData = static_cast<uint8_t*>(layout.cr);
319 for (uint32_t y = 0; y < info.height; y++) {
320 for (uint32_t x = 0; x < info.width; x++) {
321 auto val = static_cast<uint8_t>(info.height * y + x);
322
323 yData[layout.yStride * y + x] = val;
324 if (y % 2 == 0 && x % 2 == 0) {
325 cbData[layout.cStride * y / 2 + x / 2] = val;
326 crData[layout.cStride * y / 2 + x / 2] = val;
327 }
328 }
329 }
330
331 ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
332
333 // lock again for reading
334 ASSERT_NO_FATAL_FAILURE(layout = mGralloc->lockYCbCr(bufferHandle, info.usage, region, fence));
335
336 yData = static_cast<uint8_t*>(layout.y);
337 cbData = static_cast<uint8_t*>(layout.cb);
338 crData = static_cast<uint8_t*>(layout.cr);
339 for (uint32_t y = 0; y < info.height; y++) {
340 for (uint32_t x = 0; x < info.width; x++) {
341 auto val = static_cast<uint8_t>(info.height * y + x);
342
343 EXPECT_EQ(val, yData[layout.yStride * y + x]);
344 if (y % 2 == 0 && x % 2 == 0) {
345 EXPECT_EQ(val, cbData[layout.cStride * y / 2 + x / 2]);
346 EXPECT_EQ(val, crData[layout.cStride * y / 2 + x / 2]);
347 }
348 }
349 }
350
351 ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
352 if (fence >= 0) {
353 close(fence);
354 }
355 }
356
357 /**
358 * Test IMapper::unlock with invalid buffers.
359 */
TEST_F(GraphicsMapperHidlTest,UnlockNegative)360 TEST_F(GraphicsMapperHidlTest, UnlockNegative) {
361 native_handle_t* invalidHandle = nullptr;
362 mGralloc->getMapper()->unlock(invalidHandle, [&](const auto& tmpError, const auto&) {
363 EXPECT_EQ(Error::BAD_BUFFER, tmpError)
364 << "unlock with nullptr did not fail with BAD_BUFFER";
365 });
366
367 invalidHandle = native_handle_create(0, 0);
368 mGralloc->getMapper()->unlock(invalidHandle, [&](const auto& tmpError, const auto&) {
369 EXPECT_EQ(Error::BAD_BUFFER, tmpError)
370 << "unlock with invalid handle did not fail with BAD_BUFFER";
371 });
372 native_handle_delete(invalidHandle);
373
374 ASSERT_NO_FATAL_FAILURE(invalidHandle = const_cast<native_handle_t*>(
375 mGralloc->allocate(mDummyDescriptorInfo, false)));
376 mGralloc->getMapper()->unlock(invalidHandle, [&](const auto& tmpError, const auto&) {
377 EXPECT_EQ(Error::BAD_BUFFER, tmpError)
378 << "unlock with un-imported handle did not fail with BAD_BUFFER";
379 });
380 mGralloc->freeBuffer(invalidHandle);
381
382 // disabled as it fails on many existing drivers
383 #if 0
384 ASSERT_NO_FATAL_FAILURE(invalidHandle = const_cast<native_handle_t*>(
385 mGralloc->allocate(mDummyDescriptorInfo, true)));
386 mGralloc->getMapper()->unlock(
387 invalidHandle, [&](const auto& tmpError, const auto&) {
388 EXPECT_EQ(Error::BAD_BUFFER, tmpError)
389 << "unlock with unlocked handle did not fail with BAD_BUFFER";
390 });
391 mGralloc->freeBuffer(invalidHandle);
392 #endif
393 }
394
395 } // namespace
396 } // namespace vts
397 } // namespace V2_0
398 } // namespace mapper
399 } // namespace graphics
400 } // namespace hardware
401 } // namespace android
402
main(int argc,char ** argv)403 int main(int argc, char** argv) {
404 using android::hardware::graphics::mapper::V2_0::vts::GraphicsMapperHidlEnvironment;
405 ::testing::AddGlobalTestEnvironment(GraphicsMapperHidlEnvironment::Instance());
406 ::testing::InitGoogleTest(&argc, argv);
407 GraphicsMapperHidlEnvironment::Instance()->init(&argc, argv);
408 int status = RUN_ALL_TESTS();
409 LOG(INFO) << "Test result = " << status;
410 return status;
411 }
412