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 42 static GraphicsMapperHidlEnvironment* Instance() { 43 static GraphicsMapperHidlEnvironment* instance = new GraphicsMapperHidlEnvironment; 44 return instance; 45 } 46 47 virtual void registerTestServices() override { 48 registerTestService<IAllocator>(); 49 registerTestService<IMapper>(); 50 } 51 }; 52 53 class GraphicsMapperHidlTest : public ::testing::VtsHalHidlTargetTestBase { 54 protected: 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 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 */ 78 TEST_F(GraphicsMapperHidlTest, AllocatorDumpDebugInfo) { 79 mGralloc->dumpDebugInfo(); 80 } 81 82 /** 83 * Test IAllocator::allocate with valid buffer descriptors. 84 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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