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 "BufferHubBufferTest" 18 19 #include <errno.h> 20 #include <sys/epoll.h> 21 22 #include <android/frameworks/bufferhub/1.0/IBufferHub.h> 23 #include <android/hardware_buffer.h> 24 #include <cutils/native_handle.h> 25 #include <gmock/gmock.h> 26 #include <gtest/gtest.h> 27 #include <hidl/ServiceManagement.h> 28 #include <hwbinder/IPCThreadState.h> 29 #include <ui/BufferHubBuffer.h> 30 #include <ui/BufferHubEventFd.h> 31 32 namespace android { 33 34 namespace { 35 36 using ::android::BufferHubDefs::isAnyClientAcquired; 37 using ::android::BufferHubDefs::isAnyClientGained; 38 using ::android::BufferHubDefs::isAnyClientPosted; 39 using ::android::BufferHubDefs::isClientAcquired; 40 using ::android::BufferHubDefs::isClientGained; 41 using ::android::BufferHubDefs::isClientPosted; 42 using ::android::BufferHubDefs::isClientReleased; 43 using ::android::BufferHubDefs::kMetadataHeaderSize; 44 using ::android::frameworks::bufferhub::V1_0::IBufferHub; 45 using ::testing::IsNull; 46 using ::testing::NotNull; 47 48 const int kWidth = 640; 49 const int kHeight = 480; 50 const int kLayerCount = 1; 51 const int kFormat = HAL_PIXEL_FORMAT_RGBA_8888; 52 const int kUsage = 0; 53 const AHardwareBuffer_Desc kDesc = {kWidth, kHeight, kLayerCount, kFormat, 54 kUsage, /*stride=*/0UL, /*rfu0=*/0UL, /*rfu1=*/0ULL}; 55 const size_t kUserMetadataSize = 1; 56 57 class BufferHubBufferTest : public ::testing::Test { 58 protected: 59 void SetUp() override { 60 android::hardware::ProcessState::self()->startThreadPool(); 61 62 if (!BufferHubServiceRunning()) { 63 // TODO(b/112940221): Enforce the test cross all devices once BufferHub lands in Android 64 // R for all Android varieties. 65 GTEST_SKIP() << "Skip test as the BufferHub service is not running."; 66 } 67 } 68 69 bool BufferHubServiceRunning() { 70 sp<IBufferHub> bufferhub = IBufferHub::getService(); 71 return bufferhub.get() != nullptr; 72 } 73 }; 74 75 bool cmpAHardwareBufferDesc(const AHardwareBuffer_Desc& desc, const AHardwareBuffer_Desc& other) { 76 // Not comparing stride because it's unknown before allocation 77 return desc.format == other.format && desc.height == other.height && 78 desc.layers == other.layers && desc.usage == other.usage && desc.width == other.width; 79 } 80 81 class BufferHubBufferStateTransitionTest : public BufferHubBufferTest { 82 protected: 83 void SetUp() override { 84 BufferHubBufferTest::SetUp(); 85 86 if (IsSkipped()) { 87 // If the base class' SetUp() stated the test should be skipped, we should short 88 // circuit this sub-class' logic. 89 return; 90 } 91 92 CreateTwoClientsOfABuffer(); 93 } 94 95 std::unique_ptr<BufferHubBuffer> b1; 96 uint32_t b1ClientMask = 0U; 97 std::unique_ptr<BufferHubBuffer> b2; 98 uint32_t b2ClientMask = 0U; 99 100 private: 101 // Creates b1 and b2 as the clients of the same buffer for testing. 102 void CreateTwoClientsOfABuffer(); 103 }; 104 105 void BufferHubBufferStateTransitionTest::CreateTwoClientsOfABuffer() { 106 b1 = BufferHubBuffer::create(kWidth, kHeight, kLayerCount, kFormat, kUsage, kUserMetadataSize); 107 ASSERT_THAT(b1, NotNull()); 108 b1ClientMask = b1->clientStateMask(); 109 ASSERT_NE(b1ClientMask, 0U); 110 111 sp<NativeHandle> token = b1->duplicate(); 112 ASSERT_THAT(token, NotNull()); 113 114 b2 = BufferHubBuffer::import(token); 115 ASSERT_THAT(b2, NotNull()); 116 117 b2ClientMask = b2->clientStateMask(); 118 ASSERT_NE(b2ClientMask, 0U); 119 ASSERT_NE(b2ClientMask, b1ClientMask); 120 } 121 122 TEST_F(BufferHubBufferTest, CreateBufferFails) { 123 // Buffer Creation will fail: BLOB format requires height to be 1. 124 auto b1 = BufferHubBuffer::create(kWidth, /*height=*/2, kLayerCount, 125 /*format=*/HAL_PIXEL_FORMAT_BLOB, kUsage, kUserMetadataSize); 126 127 EXPECT_THAT(b1, IsNull()); 128 129 // Buffer Creation will fail: user metadata size too large. 130 auto b2 = BufferHubBuffer::create(kWidth, kHeight, kLayerCount, kFormat, kUsage, 131 /*userMetadataSize=*/std::numeric_limits<size_t>::max()); 132 133 EXPECT_THAT(b2, IsNull()); 134 135 // Buffer Creation will fail: user metadata size too large. 136 const size_t userMetadataSize = std::numeric_limits<size_t>::max() - kMetadataHeaderSize; 137 auto b3 = BufferHubBuffer::create(kWidth, kHeight, kLayerCount, kFormat, kUsage, 138 userMetadataSize); 139 140 EXPECT_THAT(b3, IsNull()); 141 } 142 143 TEST_F(BufferHubBufferTest, CreateBuffer) { 144 auto b1 = BufferHubBuffer::create(kWidth, kHeight, kLayerCount, kFormat, kUsage, 145 kUserMetadataSize); 146 ASSERT_THAT(b1, NotNull()); 147 EXPECT_TRUE(b1->isConnected()); 148 EXPECT_TRUE(b1->isValid()); 149 EXPECT_TRUE(cmpAHardwareBufferDesc(b1->desc(), kDesc)); 150 EXPECT_EQ(b1->userMetadataSize(), kUserMetadataSize); 151 } 152 153 TEST_F(BufferHubBufferTest, DuplicateAndImportBuffer) { 154 auto b1 = BufferHubBuffer::create(kWidth, kHeight, kLayerCount, kFormat, kUsage, 155 kUserMetadataSize); 156 ASSERT_THAT(b1, NotNull()); 157 EXPECT_TRUE(b1->isValid()); 158 159 sp<NativeHandle> token = b1->duplicate(); 160 ASSERT_THAT(token, NotNull()); 161 162 // The detached buffer should still be valid. 163 EXPECT_TRUE(b1->isConnected()); 164 EXPECT_TRUE(b1->isValid()); 165 166 std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::import(token); 167 168 ASSERT_THAT(b2, NotNull()); 169 EXPECT_TRUE(b2->isValid()); 170 171 EXPECT_TRUE(cmpAHardwareBufferDesc(b1->desc(), b2->desc())); 172 EXPECT_EQ(b1->userMetadataSize(), b2->userMetadataSize()); 173 174 // These two buffer instances are based on the same physical buffer under the 175 // hood, so they should share the same id. 176 EXPECT_EQ(b1->id(), b2->id()); 177 // We use clientStateMask() to tell those two instances apart. 178 EXPECT_NE(b1->clientStateMask(), b2->clientStateMask()); 179 180 // Both buffer instances should be in released state currently. 181 EXPECT_TRUE(b1->isReleased()); 182 EXPECT_TRUE(b2->isReleased()); 183 184 // The event fd should behave like duped event fds. 185 const BufferHubEventFd& eventFd1 = b1->eventFd(); 186 ASSERT_GE(eventFd1.get(), 0); 187 const BufferHubEventFd& eventFd2 = b2->eventFd(); 188 ASSERT_GE(eventFd2.get(), 0); 189 190 base::unique_fd epollFd(epoll_create(64)); 191 ASSERT_GE(epollFd.get(), 0); 192 193 // Add eventFd1 to epoll set, and signal eventFd2. 194 epoll_event e = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 0}}; 195 ASSERT_EQ(epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, eventFd1.get(), &e), 0) << strerror(errno); 196 197 std::array<epoll_event, 1> events; 198 EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0); 199 200 eventFd2.signal(); 201 EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 1); 202 203 // The epoll fd is edge triggered, so it only responds to the eventFd once. 204 EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0); 205 206 eventFd2.signal(); 207 eventFd2.clear(); 208 EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0); 209 } 210 211 TEST_F(BufferHubBufferTest, ImportFreedBuffer) { 212 auto b1 = BufferHubBuffer::create(kWidth, kHeight, kLayerCount, kFormat, kUsage, 213 kUserMetadataSize); 214 ASSERT_THAT(b1, NotNull()); 215 EXPECT_TRUE(b1->isValid()); 216 217 sp<NativeHandle> token = b1->duplicate(); 218 ASSERT_THAT(token, NotNull()); 219 220 // Explicitly destroy b1. Backend buffer should be freed and token becomes invalid 221 b1.reset(); 222 223 std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::import(token); 224 225 // Import should fail with INVALID_TOKEN 226 EXPECT_THAT(b2, IsNull()); 227 } 228 229 // nullptr must not crash the service 230 TEST_F(BufferHubBufferTest, ImportNullToken) { 231 auto b1 = BufferHubBuffer::import(nullptr); 232 EXPECT_THAT(b1, IsNull()); 233 } 234 235 TEST_F(BufferHubBufferTest, ImportInvalidToken) { 236 native_handle_t* token = native_handle_create(/*numFds=*/0, /*numInts=*/1); 237 token->data[0] = 0; 238 239 sp<NativeHandle> tokenHandle = NativeHandle::create(token, /*ownHandle=*/true); 240 auto b1 = BufferHubBuffer::import(tokenHandle); 241 242 EXPECT_THAT(b1, IsNull()); 243 } 244 245 TEST_F(BufferHubBufferStateTransitionTest, GainBuffer_fromReleasedState) { 246 ASSERT_TRUE(b1->isReleased()); 247 248 // Successful gaining the buffer should change the buffer state bit of b1 to 249 // gained state, other client state bits to released state. 250 EXPECT_EQ(b1->gain(), 0); 251 EXPECT_TRUE(isClientGained(b1->bufferState(), b1ClientMask)); 252 } 253 254 TEST_F(BufferHubBufferStateTransitionTest, GainBuffer_fromGainedState) { 255 ASSERT_EQ(b1->gain(), 0); 256 auto currentBufferState = b1->bufferState(); 257 ASSERT_TRUE(isClientGained(currentBufferState, b1ClientMask)); 258 259 // Gaining from gained state by the same client should not return error. 260 EXPECT_EQ(b1->gain(), 0); 261 262 // Gaining from gained state by another client should return error. 263 EXPECT_EQ(b2->gain(), -EBUSY); 264 } 265 266 TEST_F(BufferHubBufferStateTransitionTest, GainBuffer_fromAcquiredState) { 267 ASSERT_EQ(b1->gain(), 0); 268 ASSERT_EQ(b1->post(), 0); 269 ASSERT_EQ(b2->acquire(), 0); 270 ASSERT_TRUE(isAnyClientAcquired(b1->bufferState())); 271 272 // Gaining from acquired state should fail. 273 EXPECT_EQ(b1->gain(), -EBUSY); 274 EXPECT_EQ(b2->gain(), -EBUSY); 275 } 276 277 TEST_F(BufferHubBufferStateTransitionTest, GainBuffer_fromOtherClientInPostedState) { 278 ASSERT_EQ(b1->gain(), 0); 279 ASSERT_EQ(b1->post(), 0); 280 ASSERT_TRUE(isAnyClientPosted(b1->bufferState())); 281 282 // Gaining a buffer who has other posted client should succeed. 283 EXPECT_EQ(b1->gain(), 0); 284 } 285 286 TEST_F(BufferHubBufferStateTransitionTest, GainBuffer_fromSelfInPostedState) { 287 ASSERT_EQ(b1->gain(), 0); 288 ASSERT_EQ(b1->post(), 0); 289 ASSERT_TRUE(isAnyClientPosted(b1->bufferState())); 290 291 // A posted client should be able to gain the buffer when there is no other clients in 292 // acquired state. 293 EXPECT_EQ(b2->gain(), 0); 294 } 295 296 TEST_F(BufferHubBufferStateTransitionTest, PostBuffer_fromOtherInGainedState) { 297 ASSERT_EQ(b1->gain(), 0); 298 ASSERT_TRUE(isClientGained(b1->bufferState(), b1ClientMask)); 299 300 EXPECT_EQ(b2->post(), -EBUSY); 301 } 302 303 TEST_F(BufferHubBufferStateTransitionTest, PostBuffer_fromSelfInGainedState) { 304 ASSERT_EQ(b1->gain(), 0); 305 ASSERT_TRUE(isClientGained(b1->bufferState(), b1ClientMask)); 306 307 EXPECT_EQ(b1->post(), 0); 308 auto currentBufferState = b1->bufferState(); 309 EXPECT_TRUE(isClientReleased(currentBufferState, b1ClientMask)); 310 EXPECT_TRUE(isClientPosted(currentBufferState, b2ClientMask)); 311 } 312 313 TEST_F(BufferHubBufferStateTransitionTest, PostBuffer_fromPostedState) { 314 ASSERT_EQ(b1->gain(), 0); 315 ASSERT_EQ(b1->post(), 0); 316 ASSERT_TRUE(isAnyClientPosted(b1->bufferState())); 317 318 // Post from posted state should fail. 319 EXPECT_EQ(b1->post(), -EBUSY); 320 EXPECT_EQ(b2->post(), -EBUSY); 321 } 322 323 TEST_F(BufferHubBufferStateTransitionTest, PostBuffer_fromAcquiredState) { 324 ASSERT_EQ(b1->gain(), 0); 325 ASSERT_EQ(b1->post(), 0); 326 ASSERT_EQ(b2->acquire(), 0); 327 ASSERT_TRUE(isAnyClientAcquired(b1->bufferState())); 328 329 // Posting from acquired state should fail. 330 EXPECT_EQ(b1->post(), -EBUSY); 331 EXPECT_EQ(b2->post(), -EBUSY); 332 } 333 334 TEST_F(BufferHubBufferStateTransitionTest, PostBuffer_fromReleasedState) { 335 ASSERT_TRUE(b1->isReleased()); 336 337 // Posting from released state should fail. 338 EXPECT_EQ(b1->post(), -EBUSY); 339 EXPECT_EQ(b2->post(), -EBUSY); 340 } 341 342 TEST_F(BufferHubBufferStateTransitionTest, AcquireBuffer_fromSelfInPostedState) { 343 ASSERT_EQ(b1->gain(), 0); 344 ASSERT_EQ(b1->post(), 0); 345 ASSERT_TRUE(isClientPosted(b1->bufferState(), b2ClientMask)); 346 347 // Acquire from posted state should pass. 348 EXPECT_EQ(b2->acquire(), 0); 349 } 350 351 TEST_F(BufferHubBufferStateTransitionTest, AcquireBuffer_fromOtherInPostedState) { 352 ASSERT_EQ(b1->gain(), 0); 353 ASSERT_EQ(b1->post(), 0); 354 ASSERT_TRUE(isClientPosted(b1->bufferState(), b2ClientMask)); 355 356 // Acquire from released state should fail, although there are other clients 357 // in posted state. 358 EXPECT_EQ(b1->acquire(), -EBUSY); 359 } 360 361 TEST_F(BufferHubBufferStateTransitionTest, AcquireBuffer_fromSelfInAcquiredState) { 362 ASSERT_EQ(b1->gain(), 0); 363 ASSERT_EQ(b1->post(), 0); 364 ASSERT_EQ(b2->acquire(), 0); 365 auto currentBufferState = b1->bufferState(); 366 ASSERT_TRUE(isClientAcquired(currentBufferState, b2ClientMask)); 367 368 // Acquiring from acquired state by the same client should not error out. 369 EXPECT_EQ(b2->acquire(), 0); 370 } 371 372 TEST_F(BufferHubBufferStateTransitionTest, AcquireBuffer_fromReleasedState) { 373 ASSERT_TRUE(b1->isReleased()); 374 375 // Acquiring form released state should fail. 376 EXPECT_EQ(b1->acquire(), -EBUSY); 377 EXPECT_EQ(b2->acquire(), -EBUSY); 378 } 379 380 TEST_F(BufferHubBufferStateTransitionTest, AcquireBuffer_fromGainedState) { 381 ASSERT_EQ(b1->gain(), 0); 382 ASSERT_TRUE(isAnyClientGained(b1->bufferState())); 383 384 // Acquiring from gained state should fail. 385 EXPECT_EQ(b1->acquire(), -EBUSY); 386 EXPECT_EQ(b2->acquire(), -EBUSY); 387 } 388 389 TEST_F(BufferHubBufferStateTransitionTest, ReleaseBuffer_fromSelfInReleasedState) { 390 ASSERT_TRUE(b1->isReleased()); 391 392 EXPECT_EQ(b1->release(), 0); 393 } 394 395 TEST_F(BufferHubBufferStateTransitionTest, ReleaseBuffer_fromSelfInGainedState) { 396 ASSERT_TRUE(b1->isReleased()); 397 ASSERT_EQ(b1->gain(), 0); 398 ASSERT_TRUE(isAnyClientGained(b1->bufferState())); 399 400 EXPECT_EQ(b1->release(), 0); 401 } 402 403 TEST_F(BufferHubBufferStateTransitionTest, ReleaseBuffer_fromSelfInPostedState) { 404 ASSERT_EQ(b1->gain(), 0); 405 ASSERT_EQ(b1->post(), 0); 406 ASSERT_TRUE(isAnyClientPosted(b1->bufferState())); 407 408 EXPECT_EQ(b2->release(), 0); 409 } 410 411 TEST_F(BufferHubBufferStateTransitionTest, ReleaseBuffer_fromSelfInAcquiredState) { 412 ASSERT_EQ(b1->gain(), 0); 413 ASSERT_EQ(b1->post(), 0); 414 ASSERT_EQ(b2->acquire(), 0); 415 ASSERT_TRUE(isAnyClientAcquired(b1->bufferState())); 416 417 EXPECT_EQ(b2->release(), 0); 418 } 419 420 TEST_F(BufferHubBufferStateTransitionTest, BasicUsage) { 421 // 1 producer buffer and 1 consumer buffer initialised in testcase setup. 422 // Test if this set of basic operation succeed: 423 // Producer post three times to the consumer, and released by consumer. 424 for (int i = 0; i < 3; ++i) { 425 ASSERT_EQ(b1->gain(), 0); 426 ASSERT_EQ(b1->post(), 0); 427 ASSERT_EQ(b2->acquire(), 0); 428 ASSERT_EQ(b2->release(), 0); 429 } 430 } 431 432 TEST_F(BufferHubBufferTest, createNewConsumerAfterGain) { 433 // Create a poducer buffer and gain. 434 std::unique_ptr<BufferHubBuffer> b1 = 435 BufferHubBuffer::create(kWidth, kHeight, kLayerCount, kFormat, kUsage, 436 kUserMetadataSize); 437 ASSERT_THAT(b1, NotNull()); 438 ASSERT_EQ(b1->gain(), 0); 439 440 // Create a consumer of the buffer and test if the consumer can acquire the 441 // buffer if producer posts. 442 sp<NativeHandle> token = b1->duplicate(); 443 ASSERT_THAT(token, NotNull()); 444 445 std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::import(token); 446 447 ASSERT_THAT(b2, NotNull()); 448 ASSERT_NE(b1->clientStateMask(), b2->clientStateMask()); 449 450 ASSERT_EQ(b1->post(), 0); 451 EXPECT_EQ(b2->acquire(), 0); 452 } 453 454 TEST_F(BufferHubBufferTest, createNewConsumerAfterPost) { 455 // Create a poducer buffer and post. 456 std::unique_ptr<BufferHubBuffer> b1 = 457 BufferHubBuffer::create(kWidth, kHeight, kLayerCount, kFormat, kUsage, 458 kUserMetadataSize); 459 ASSERT_EQ(b1->gain(), 0); 460 ASSERT_EQ(b1->post(), 0); 461 462 // Create a consumer of the buffer and test if the consumer can acquire the 463 // buffer if producer posts. 464 sp<NativeHandle> token = b1->duplicate(); 465 ASSERT_THAT(token, NotNull()); 466 467 std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::import(token); 468 469 ASSERT_THAT(b2, NotNull()); 470 ASSERT_NE(b1->clientStateMask(), b2->clientStateMask()); 471 472 EXPECT_EQ(b2->acquire(), 0); 473 } 474 475 } // namespace 476 477 } // namespace android 478