1 /* 2 * Copyright (C) 2012 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 "BufferQueue_test" 18 //#define LOG_NDEBUG 0 19 20 #include "DummyConsumer.h" 21 22 #include <gui/BufferItem.h> 23 #include <gui/BufferQueue.h> 24 #include <gui/IProducerListener.h> 25 26 #include <ui/GraphicBuffer.h> 27 28 #include <binder/IPCThreadState.h> 29 #include <binder/IServiceManager.h> 30 #include <binder/ProcessState.h> 31 32 #include <utils/String8.h> 33 #include <utils/threads.h> 34 35 #include <system/window.h> 36 37 #include <gtest/gtest.h> 38 39 #include <thread> 40 41 using namespace std::chrono_literals; 42 43 namespace android { 44 45 class BufferQueueTest : public ::testing::Test { 46 47 public: 48 protected: 49 BufferQueueTest() { 50 const ::testing::TestInfo* const testInfo = 51 ::testing::UnitTest::GetInstance()->current_test_info(); 52 ALOGV("Begin test: %s.%s", testInfo->test_case_name(), 53 testInfo->name()); 54 } 55 56 ~BufferQueueTest() { 57 const ::testing::TestInfo* const testInfo = 58 ::testing::UnitTest::GetInstance()->current_test_info(); 59 ALOGV("End test: %s.%s", testInfo->test_case_name(), 60 testInfo->name()); 61 } 62 63 void GetMinUndequeuedBufferCount(int* bufferCount) { 64 ASSERT_TRUE(bufferCount != NULL); 65 ASSERT_EQ(OK, mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, 66 bufferCount)); 67 ASSERT_GE(*bufferCount, 0); 68 } 69 70 void createBufferQueue() { 71 BufferQueue::createBufferQueue(&mProducer, &mConsumer); 72 } 73 74 void testBufferItem(const IGraphicBufferProducer::QueueBufferInput& input, 75 const BufferItem& item) { 76 int64_t timestamp; 77 bool isAutoTimestamp; 78 android_dataspace dataSpace; 79 Rect crop; 80 int scalingMode; 81 uint32_t transform; 82 sp<Fence> fence; 83 84 input.deflate(×tamp, &isAutoTimestamp, &dataSpace, &crop, 85 &scalingMode, &transform, &fence, NULL); 86 ASSERT_EQ(timestamp, item.mTimestamp); 87 ASSERT_EQ(isAutoTimestamp, item.mIsAutoTimestamp); 88 ASSERT_EQ(dataSpace, item.mDataSpace); 89 ASSERT_EQ(crop, item.mCrop); 90 ASSERT_EQ(static_cast<uint32_t>(scalingMode), item.mScalingMode); 91 ASSERT_EQ(transform, item.mTransform); 92 ASSERT_EQ(fence, item.mFence); 93 } 94 95 sp<IGraphicBufferProducer> mProducer; 96 sp<IGraphicBufferConsumer> mConsumer; 97 }; 98 99 static const uint32_t TEST_DATA = 0x12345678u; 100 101 // XXX: Tests that fork a process to hold the BufferQueue must run before tests 102 // that use a local BufferQueue, or else Binder will get unhappy 103 // 104 // In one instance this was a crash in the createBufferQueue where the 105 // binder call to create a buffer allocator apparently got garbage back. 106 // See b/36592665. 107 TEST_F(BufferQueueTest, DISABLED_BufferQueueInAnotherProcess) { 108 const String16 PRODUCER_NAME = String16("BQTestProducer"); 109 const String16 CONSUMER_NAME = String16("BQTestConsumer"); 110 111 pid_t forkPid = fork(); 112 ASSERT_NE(forkPid, -1); 113 114 if (forkPid == 0) { 115 // Child process 116 sp<IGraphicBufferProducer> producer; 117 sp<IGraphicBufferConsumer> consumer; 118 BufferQueue::createBufferQueue(&producer, &consumer); 119 sp<IServiceManager> serviceManager = defaultServiceManager(); 120 serviceManager->addService(PRODUCER_NAME, IInterface::asBinder(producer)); 121 serviceManager->addService(CONSUMER_NAME, IInterface::asBinder(consumer)); 122 ProcessState::self()->startThreadPool(); 123 IPCThreadState::self()->joinThreadPool(); 124 LOG_ALWAYS_FATAL("Shouldn't be here"); 125 } 126 127 sp<IServiceManager> serviceManager = defaultServiceManager(); 128 sp<IBinder> binderProducer = 129 serviceManager->getService(PRODUCER_NAME); 130 mProducer = interface_cast<IGraphicBufferProducer>(binderProducer); 131 EXPECT_TRUE(mProducer != NULL); 132 sp<IBinder> binderConsumer = 133 serviceManager->getService(CONSUMER_NAME); 134 mConsumer = interface_cast<IGraphicBufferConsumer>(binderConsumer); 135 EXPECT_TRUE(mConsumer != NULL); 136 137 sp<DummyConsumer> dc(new DummyConsumer); 138 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false)); 139 IGraphicBufferProducer::QueueBufferOutput output; 140 ASSERT_EQ(OK, 141 mProducer->connect(NULL, NATIVE_WINDOW_API_CPU, false, &output)); 142 143 int slot; 144 sp<Fence> fence; 145 sp<GraphicBuffer> buffer; 146 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, 147 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN, 148 nullptr, nullptr)); 149 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer)); 150 151 uint32_t* dataIn; 152 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN, 153 reinterpret_cast<void**>(&dataIn))); 154 *dataIn = TEST_DATA; 155 ASSERT_EQ(OK, buffer->unlock()); 156 157 IGraphicBufferProducer::QueueBufferInput input(0, false, 158 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1), 159 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE); 160 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output)); 161 162 BufferItem item; 163 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0)); 164 165 uint32_t* dataOut; 166 ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, 167 reinterpret_cast<void**>(&dataOut))); 168 ASSERT_EQ(*dataOut, TEST_DATA); 169 ASSERT_EQ(OK, item.mGraphicBuffer->unlock()); 170 } 171 172 TEST_F(BufferQueueTest, AcquireBuffer_ExceedsMaxAcquireCount_Fails) { 173 createBufferQueue(); 174 sp<DummyConsumer> dc(new DummyConsumer); 175 mConsumer->consumerConnect(dc, false); 176 IGraphicBufferProducer::QueueBufferOutput qbo; 177 mProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, false, 178 &qbo); 179 mProducer->setMaxDequeuedBufferCount(3); 180 181 int slot; 182 sp<Fence> fence; 183 sp<GraphicBuffer> buf; 184 IGraphicBufferProducer::QueueBufferInput qbi(0, false, 185 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1), 186 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE); 187 BufferItem item; 188 189 for (int i = 0; i < 2; i++) { 190 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, 191 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN, 192 nullptr, nullptr)); 193 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf)); 194 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo)); 195 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0)); 196 } 197 198 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, 199 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN, 200 nullptr, nullptr)); 201 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf)); 202 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo)); 203 204 // Acquire the third buffer, which should fail. 205 ASSERT_EQ(INVALID_OPERATION, mConsumer->acquireBuffer(&item, 0)); 206 } 207 208 TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithIllegalValues_ReturnsError) { 209 createBufferQueue(); 210 sp<DummyConsumer> dc(new DummyConsumer); 211 mConsumer->consumerConnect(dc, false); 212 213 EXPECT_EQ(OK, mConsumer->setMaxBufferCount(10)); 214 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(10)); 215 216 IGraphicBufferProducer::QueueBufferOutput qbo; 217 mProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, false, 218 &qbo); 219 mProducer->setMaxDequeuedBufferCount(3); 220 221 int minBufferCount; 222 ASSERT_NO_FATAL_FAILURE(GetMinUndequeuedBufferCount(&minBufferCount)); 223 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount( 224 minBufferCount - 1)); 225 226 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(0)); 227 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(-3)); 228 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount( 229 BufferQueue::MAX_MAX_ACQUIRED_BUFFERS+1)); 230 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(100)); 231 232 int slot; 233 sp<Fence> fence; 234 sp<GraphicBuffer> buf; 235 IGraphicBufferProducer::QueueBufferInput qbi(0, false, 236 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1), 237 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE); 238 BufferItem item; 239 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(3)); 240 for (int i = 0; i < 3; i++) { 241 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, 242 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN, 243 nullptr, nullptr)); 244 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf)); 245 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo)); 246 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0)); 247 } 248 249 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(2)); 250 } 251 252 TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithLegalValues_Succeeds) { 253 createBufferQueue(); 254 sp<DummyConsumer> dc(new DummyConsumer); 255 mConsumer->consumerConnect(dc, false); 256 257 IGraphicBufferProducer::QueueBufferOutput qbo; 258 mProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, false, 259 &qbo); 260 mProducer->setMaxDequeuedBufferCount(2); 261 262 int minBufferCount; 263 ASSERT_NO_FATAL_FAILURE(GetMinUndequeuedBufferCount(&minBufferCount)); 264 265 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1)); 266 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(2)); 267 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(minBufferCount)); 268 269 int slot; 270 sp<Fence> fence; 271 sp<GraphicBuffer> buf; 272 IGraphicBufferProducer::QueueBufferInput qbi(0, false, 273 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1), 274 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE); 275 BufferItem item; 276 277 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, 278 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN, 279 nullptr, nullptr)); 280 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf)); 281 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo)); 282 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0)); 283 284 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(3)); 285 286 for (int i = 0; i < 2; i++) { 287 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, 288 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN, 289 nullptr, nullptr)); 290 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf)); 291 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo)); 292 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0)); 293 } 294 295 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount( 296 BufferQueue::MAX_MAX_ACQUIRED_BUFFERS)); 297 } 298 299 TEST_F(BufferQueueTest, SetMaxBufferCountWithLegalValues_Succeeds) { 300 createBufferQueue(); 301 sp<DummyConsumer> dc(new DummyConsumer); 302 mConsumer->consumerConnect(dc, false); 303 304 // Test shared buffer mode 305 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1)); 306 } 307 308 TEST_F(BufferQueueTest, SetMaxBufferCountWithIllegalValues_ReturnsError) { 309 createBufferQueue(); 310 sp<DummyConsumer> dc(new DummyConsumer); 311 mConsumer->consumerConnect(dc, false); 312 313 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(0)); 314 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount( 315 BufferQueue::NUM_BUFFER_SLOTS + 1)); 316 317 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(5)); 318 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(3)); 319 } 320 321 TEST_F(BufferQueueTest, DetachAndReattachOnProducerSide) { 322 createBufferQueue(); 323 sp<DummyConsumer> dc(new DummyConsumer); 324 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false)); 325 IGraphicBufferProducer::QueueBufferOutput output; 326 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener, 327 NATIVE_WINDOW_API_CPU, false, &output)); 328 329 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(-1)); // Index too low 330 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer( 331 BufferQueueDefs::NUM_BUFFER_SLOTS)); // Index too high 332 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(0)); // Not dequeued 333 334 int slot; 335 sp<Fence> fence; 336 sp<GraphicBuffer> buffer; 337 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, 338 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN, 339 nullptr, nullptr)); 340 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(slot)); // Not requested 341 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer)); 342 ASSERT_EQ(OK, mProducer->detachBuffer(slot)); 343 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(slot)); // Not dequeued 344 345 sp<GraphicBuffer> safeToClobberBuffer; 346 // Can no longer request buffer from this slot 347 ASSERT_EQ(BAD_VALUE, mProducer->requestBuffer(slot, &safeToClobberBuffer)); 348 349 uint32_t* dataIn; 350 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN, 351 reinterpret_cast<void**>(&dataIn))); 352 *dataIn = TEST_DATA; 353 ASSERT_EQ(OK, buffer->unlock()); 354 355 int newSlot; 356 ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(NULL, safeToClobberBuffer)); 357 ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(&newSlot, NULL)); 358 359 ASSERT_EQ(OK, mProducer->attachBuffer(&newSlot, buffer)); 360 IGraphicBufferProducer::QueueBufferInput input(0, false, 361 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1), 362 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE); 363 ASSERT_EQ(OK, mProducer->queueBuffer(newSlot, input, &output)); 364 365 BufferItem item; 366 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0))); 367 368 uint32_t* dataOut; 369 ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, 370 reinterpret_cast<void**>(&dataOut))); 371 ASSERT_EQ(*dataOut, TEST_DATA); 372 ASSERT_EQ(OK, item.mGraphicBuffer->unlock()); 373 } 374 375 TEST_F(BufferQueueTest, DetachAndReattachOnConsumerSide) { 376 createBufferQueue(); 377 sp<DummyConsumer> dc(new DummyConsumer); 378 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false)); 379 IGraphicBufferProducer::QueueBufferOutput output; 380 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener, 381 NATIVE_WINDOW_API_CPU, false, &output)); 382 383 int slot; 384 sp<Fence> fence; 385 sp<GraphicBuffer> buffer; 386 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, 387 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN, 388 nullptr, nullptr)); 389 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer)); 390 IGraphicBufferProducer::QueueBufferInput input(0, false, 391 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1), 392 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE); 393 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output)); 394 395 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(-1)); // Index too low 396 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer( 397 BufferQueueDefs::NUM_BUFFER_SLOTS)); // Index too high 398 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(0)); // Not acquired 399 400 BufferItem item; 401 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0))); 402 403 ASSERT_EQ(OK, mConsumer->detachBuffer(item.mSlot)); 404 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(item.mSlot)); // Not acquired 405 406 uint32_t* dataIn; 407 ASSERT_EQ(OK, item.mGraphicBuffer->lock( 408 GraphicBuffer::USAGE_SW_WRITE_OFTEN, 409 reinterpret_cast<void**>(&dataIn))); 410 *dataIn = TEST_DATA; 411 ASSERT_EQ(OK, item.mGraphicBuffer->unlock()); 412 413 int newSlot; 414 sp<GraphicBuffer> safeToClobberBuffer; 415 ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(NULL, safeToClobberBuffer)); 416 ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(&newSlot, NULL)); 417 ASSERT_EQ(OK, mConsumer->attachBuffer(&newSlot, item.mGraphicBuffer)); 418 419 ASSERT_EQ(OK, mConsumer->releaseBuffer(newSlot, 0, EGL_NO_DISPLAY, 420 EGL_NO_SYNC_KHR, Fence::NO_FENCE)); 421 422 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, 423 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN, 424 nullptr, nullptr)); 425 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer)); 426 427 uint32_t* dataOut; 428 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, 429 reinterpret_cast<void**>(&dataOut))); 430 ASSERT_EQ(*dataOut, TEST_DATA); 431 ASSERT_EQ(OK, buffer->unlock()); 432 } 433 434 TEST_F(BufferQueueTest, MoveFromConsumerToProducer) { 435 createBufferQueue(); 436 sp<DummyConsumer> dc(new DummyConsumer); 437 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false)); 438 IGraphicBufferProducer::QueueBufferOutput output; 439 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener, 440 NATIVE_WINDOW_API_CPU, false, &output)); 441 442 int slot; 443 sp<Fence> fence; 444 sp<GraphicBuffer> buffer; 445 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, 446 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN, 447 nullptr, nullptr)); 448 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer)); 449 450 uint32_t* dataIn; 451 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN, 452 reinterpret_cast<void**>(&dataIn))); 453 *dataIn = TEST_DATA; 454 ASSERT_EQ(OK, buffer->unlock()); 455 456 IGraphicBufferProducer::QueueBufferInput input(0, false, 457 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1), 458 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE); 459 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output)); 460 461 BufferItem item; 462 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0))); 463 ASSERT_EQ(OK, mConsumer->detachBuffer(item.mSlot)); 464 465 int newSlot; 466 ASSERT_EQ(OK, mProducer->attachBuffer(&newSlot, item.mGraphicBuffer)); 467 ASSERT_EQ(OK, mProducer->queueBuffer(newSlot, input, &output)); 468 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0))); 469 470 uint32_t* dataOut; 471 ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, 472 reinterpret_cast<void**>(&dataOut))); 473 ASSERT_EQ(*dataOut, TEST_DATA); 474 ASSERT_EQ(OK, item.mGraphicBuffer->unlock()); 475 } 476 477 TEST_F(BufferQueueTest, TestDisallowingAllocation) { 478 createBufferQueue(); 479 sp<DummyConsumer> dc(new DummyConsumer); 480 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true)); 481 IGraphicBufferProducer::QueueBufferOutput output; 482 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener, 483 NATIVE_WINDOW_API_CPU, true, &output)); 484 485 static const uint32_t WIDTH = 320; 486 static const uint32_t HEIGHT = 240; 487 488 ASSERT_EQ(OK, mConsumer->setDefaultBufferSize(WIDTH, HEIGHT)); 489 490 int slot; 491 sp<Fence> fence; 492 sp<GraphicBuffer> buffer; 493 // This should return an error since it would require an allocation 494 ASSERT_EQ(OK, mProducer->allowAllocation(false)); 495 ASSERT_EQ(WOULD_BLOCK, 496 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN, 497 nullptr, nullptr)); 498 499 // This should succeed, now that we've lifted the prohibition 500 ASSERT_EQ(OK, mProducer->allowAllocation(true)); 501 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, 502 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN, 503 nullptr, nullptr)); 504 505 // Release the previous buffer back to the BufferQueue 506 mProducer->cancelBuffer(slot, fence); 507 508 // This should fail since we're requesting a different size 509 ASSERT_EQ(OK, mProducer->allowAllocation(false)); 510 ASSERT_EQ(WOULD_BLOCK, 511 mProducer->dequeueBuffer(&slot, &fence, WIDTH * 2, HEIGHT * 2, 0, 512 GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr, nullptr)); 513 } 514 515 TEST_F(BufferQueueTest, TestGenerationNumbers) { 516 createBufferQueue(); 517 sp<DummyConsumer> dc(new DummyConsumer); 518 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true)); 519 IGraphicBufferProducer::QueueBufferOutput output; 520 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener, 521 NATIVE_WINDOW_API_CPU, true, &output)); 522 523 ASSERT_EQ(OK, mProducer->setGenerationNumber(1)); 524 525 // Get one buffer to play with 526 int slot; 527 sp<Fence> fence; 528 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, 529 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr)); 530 531 sp<GraphicBuffer> buffer; 532 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer)); 533 534 // Ensure that the generation number we set propagates to allocated buffers 535 ASSERT_EQ(1U, buffer->getGenerationNumber()); 536 537 ASSERT_EQ(OK, mProducer->detachBuffer(slot)); 538 539 ASSERT_EQ(OK, mProducer->setGenerationNumber(2)); 540 541 // These should fail, since we've changed the generation number on the queue 542 int outSlot; 543 ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(&outSlot, buffer)); 544 ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(&outSlot, buffer)); 545 546 buffer->setGenerationNumber(2); 547 548 // This should succeed now that we've changed the buffer's generation number 549 ASSERT_EQ(OK, mProducer->attachBuffer(&outSlot, buffer)); 550 551 ASSERT_EQ(OK, mProducer->detachBuffer(outSlot)); 552 553 // This should also succeed with the new generation number 554 ASSERT_EQ(OK, mConsumer->attachBuffer(&outSlot, buffer)); 555 } 556 557 TEST_F(BufferQueueTest, TestSharedBufferModeWithoutAutoRefresh) { 558 createBufferQueue(); 559 sp<DummyConsumer> dc(new DummyConsumer); 560 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true)); 561 IGraphicBufferProducer::QueueBufferOutput output; 562 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener, 563 NATIVE_WINDOW_API_CPU, true, &output)); 564 565 ASSERT_EQ(OK, mProducer->setSharedBufferMode(true)); 566 567 // Get a buffer 568 int sharedSlot; 569 sp<Fence> fence; 570 sp<GraphicBuffer> buffer; 571 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, 572 mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0, nullptr, nullptr)); 573 ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer)); 574 575 // Queue the buffer 576 IGraphicBufferProducer::QueueBufferInput input(0, false, 577 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1), 578 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE); 579 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output)); 580 581 // Repeatedly queue and dequeue a buffer from the producer side, it should 582 // always return the same one. And we won't run out of buffers because it's 583 // always the same one and because async mode gets enabled. 584 int slot; 585 for (int i = 0; i < 5; i++) { 586 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr)); 587 ASSERT_EQ(sharedSlot, slot); 588 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output)); 589 } 590 591 // acquire the buffer 592 BufferItem item; 593 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0)); 594 ASSERT_EQ(sharedSlot, item.mSlot); 595 testBufferItem(input, item); 596 ASSERT_EQ(true, item.mQueuedBuffer); 597 ASSERT_EQ(false, item.mAutoRefresh); 598 599 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, 600 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE)); 601 602 // attempt to acquire a second time should return no buffer available 603 ASSERT_EQ(IGraphicBufferConsumer::NO_BUFFER_AVAILABLE, 604 mConsumer->acquireBuffer(&item, 0)); 605 } 606 607 TEST_F(BufferQueueTest, TestSharedBufferModeWithAutoRefresh) { 608 createBufferQueue(); 609 sp<DummyConsumer> dc(new DummyConsumer); 610 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true)); 611 IGraphicBufferProducer::QueueBufferOutput output; 612 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener, 613 NATIVE_WINDOW_API_CPU, true, &output)); 614 615 ASSERT_EQ(OK, mProducer->setSharedBufferMode(true)); 616 ASSERT_EQ(OK, mProducer->setAutoRefresh(true)); 617 618 // Get a buffer 619 int sharedSlot; 620 sp<Fence> fence; 621 sp<GraphicBuffer> buffer; 622 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, 623 mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0, nullptr, nullptr)); 624 ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer)); 625 626 // Queue the buffer 627 IGraphicBufferProducer::QueueBufferInput input(0, false, 628 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1), 629 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE); 630 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output)); 631 632 // Repeatedly acquire and release a buffer from the consumer side, it should 633 // always return the same one. 634 BufferItem item; 635 for (int i = 0; i < 5; i++) { 636 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0)); 637 ASSERT_EQ(sharedSlot, item.mSlot); 638 testBufferItem(input, item); 639 ASSERT_EQ(i == 0, item.mQueuedBuffer); 640 ASSERT_EQ(true, item.mAutoRefresh); 641 642 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, 643 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE)); 644 } 645 646 // Repeatedly queue and dequeue a buffer from the producer side, it should 647 // always return the same one. 648 int slot; 649 for (int i = 0; i < 5; i++) { 650 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr)); 651 ASSERT_EQ(sharedSlot, slot); 652 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output)); 653 } 654 655 // Repeatedly acquire and release a buffer from the consumer side, it should 656 // always return the same one. First grabbing them from the queue and then 657 // when the queue is empty, returning the shared buffer. 658 for (int i = 0; i < 10; i++) { 659 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0)); 660 ASSERT_EQ(sharedSlot, item.mSlot); 661 ASSERT_EQ(0, item.mTimestamp); 662 ASSERT_EQ(false, item.mIsAutoTimestamp); 663 ASSERT_EQ(HAL_DATASPACE_UNKNOWN, item.mDataSpace); 664 ASSERT_EQ(Rect(0, 0, 1, 1), item.mCrop); 665 ASSERT_EQ(NATIVE_WINDOW_SCALING_MODE_FREEZE, item.mScalingMode); 666 ASSERT_EQ(0u, item.mTransform); 667 ASSERT_EQ(Fence::NO_FENCE, item.mFence); 668 ASSERT_EQ(i == 0, item.mQueuedBuffer); 669 ASSERT_EQ(true, item.mAutoRefresh); 670 671 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, 672 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE)); 673 } 674 } 675 676 TEST_F(BufferQueueTest, TestSharedBufferModeUsingAlreadyDequeuedBuffer) { 677 createBufferQueue(); 678 sp<DummyConsumer> dc(new DummyConsumer); 679 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true)); 680 IGraphicBufferProducer::QueueBufferOutput output; 681 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener, 682 NATIVE_WINDOW_API_CPU, true, &output)); 683 684 // Dequeue a buffer 685 int sharedSlot; 686 sp<Fence> fence; 687 sp<GraphicBuffer> buffer; 688 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, 689 mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0, nullptr, nullptr)); 690 ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer)); 691 692 // Enable shared buffer mode 693 ASSERT_EQ(OK, mProducer->setSharedBufferMode(true)); 694 695 // Queue the buffer 696 IGraphicBufferProducer::QueueBufferInput input(0, false, 697 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1), 698 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE); 699 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output)); 700 701 // Repeatedly queue and dequeue a buffer from the producer side, it should 702 // always return the same one. And we won't run out of buffers because it's 703 // always the same one and because async mode gets enabled. 704 int slot; 705 for (int i = 0; i < 5; i++) { 706 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr)); 707 ASSERT_EQ(sharedSlot, slot); 708 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output)); 709 } 710 711 // acquire the buffer 712 BufferItem item; 713 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0)); 714 ASSERT_EQ(sharedSlot, item.mSlot); 715 testBufferItem(input, item); 716 ASSERT_EQ(true, item.mQueuedBuffer); 717 ASSERT_EQ(false, item.mAutoRefresh); 718 719 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, 720 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE)); 721 722 // attempt to acquire a second time should return no buffer available 723 ASSERT_EQ(IGraphicBufferConsumer::NO_BUFFER_AVAILABLE, 724 mConsumer->acquireBuffer(&item, 0)); 725 } 726 727 TEST_F(BufferQueueTest, TestTimeouts) { 728 createBufferQueue(); 729 sp<DummyConsumer> dc(new DummyConsumer); 730 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true)); 731 IGraphicBufferProducer::QueueBufferOutput output; 732 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener, 733 NATIVE_WINDOW_API_CPU, true, &output)); 734 735 // Fill up the queue. Since the controlledByApp flags are set to true, this 736 // queue should be in non-blocking mode, and we should be recycling the same 737 // two buffers 738 for (int i = 0; i < 5; ++i) { 739 int slot = BufferQueue::INVALID_BUFFER_SLOT; 740 sp<Fence> fence = Fence::NO_FENCE; 741 auto result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr); 742 if (i < 2) { 743 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, 744 result); 745 } else { 746 ASSERT_EQ(OK, result); 747 } 748 sp<GraphicBuffer> buffer; 749 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer)); 750 IGraphicBufferProducer::QueueBufferInput input(0ull, true, 751 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT, 752 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE); 753 IGraphicBufferProducer::QueueBufferOutput output{}; 754 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output)); 755 } 756 757 const auto TIMEOUT = ms2ns(250); 758 mProducer->setDequeueTimeout(TIMEOUT); 759 760 // Setting a timeout will change the BufferQueue into blocking mode (with 761 // one droppable buffer in the queue and one free from the previous 762 // dequeue/queues), so dequeue and queue two more buffers: one to replace 763 // the current droppable buffer, and a second to max out the buffer count 764 sp<GraphicBuffer> buffer; // Save a buffer to attach later 765 for (int i = 0; i < 2; ++i) { 766 int slot = BufferQueue::INVALID_BUFFER_SLOT; 767 sp<Fence> fence = Fence::NO_FENCE; 768 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr)); 769 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer)); 770 IGraphicBufferProducer::QueueBufferInput input(0ull, true, 771 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT, 772 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE); 773 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output)); 774 } 775 776 int slot = BufferQueue::INVALID_BUFFER_SLOT; 777 sp<Fence> fence = Fence::NO_FENCE; 778 auto startTime = systemTime(); 779 ASSERT_EQ(TIMED_OUT, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr)); 780 ASSERT_GE(systemTime() - startTime, TIMEOUT); 781 782 // We're technically attaching the same buffer multiple times (since we 783 // queued it previously), but that doesn't matter for this test 784 startTime = systemTime(); 785 ASSERT_EQ(TIMED_OUT, mProducer->attachBuffer(&slot, buffer)); 786 ASSERT_GE(systemTime() - startTime, TIMEOUT); 787 } 788 789 TEST_F(BufferQueueTest, CanAttachWhileDisallowingAllocation) { 790 createBufferQueue(); 791 sp<DummyConsumer> dc(new DummyConsumer); 792 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true)); 793 IGraphicBufferProducer::QueueBufferOutput output; 794 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener, 795 NATIVE_WINDOW_API_CPU, true, &output)); 796 797 int slot = BufferQueue::INVALID_BUFFER_SLOT; 798 sp<Fence> sourceFence; 799 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, 800 mProducer->dequeueBuffer(&slot, &sourceFence, 0, 0, 0, 0, nullptr, nullptr)); 801 sp<GraphicBuffer> buffer; 802 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer)); 803 ASSERT_EQ(OK, mProducer->detachBuffer(slot)); 804 805 ASSERT_EQ(OK, mProducer->allowAllocation(false)); 806 807 slot = BufferQueue::INVALID_BUFFER_SLOT; 808 ASSERT_EQ(OK, mProducer->attachBuffer(&slot, buffer)); 809 } 810 811 TEST_F(BufferQueueTest, CanRetrieveLastQueuedBuffer) { 812 createBufferQueue(); 813 sp<DummyConsumer> dc(new DummyConsumer); 814 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false)); 815 IGraphicBufferProducer::QueueBufferOutput output; 816 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener, 817 NATIVE_WINDOW_API_CPU, false, &output)); 818 819 // Dequeue and queue the first buffer, storing the handle 820 int slot = BufferQueue::INVALID_BUFFER_SLOT; 821 sp<Fence> fence; 822 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, 823 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr)); 824 sp<GraphicBuffer> firstBuffer; 825 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &firstBuffer)); 826 827 IGraphicBufferProducer::QueueBufferInput input(0ull, true, 828 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT, 829 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE); 830 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output)); 831 832 // Dequeue a second buffer 833 slot = BufferQueue::INVALID_BUFFER_SLOT; 834 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, 835 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr)); 836 sp<GraphicBuffer> secondBuffer; 837 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &secondBuffer)); 838 839 // Ensure it's a new buffer 840 ASSERT_NE(firstBuffer->getNativeBuffer()->handle, 841 secondBuffer->getNativeBuffer()->handle); 842 843 // Queue the second buffer 844 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output)); 845 846 // Acquire and release both buffers 847 for (size_t i = 0; i < 2; ++i) { 848 BufferItem item; 849 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0)); 850 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, 851 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE)); 852 } 853 854 // Make sure we got the second buffer back 855 sp<GraphicBuffer> returnedBuffer; 856 sp<Fence> returnedFence; 857 float transform[16]; 858 ASSERT_EQ(OK, 859 mProducer->getLastQueuedBuffer(&returnedBuffer, &returnedFence, 860 transform)); 861 ASSERT_EQ(secondBuffer->getNativeBuffer()->handle, 862 returnedBuffer->getNativeBuffer()->handle); 863 } 864 865 TEST_F(BufferQueueTest, TestOccupancyHistory) { 866 createBufferQueue(); 867 sp<DummyConsumer> dc(new DummyConsumer); 868 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false)); 869 IGraphicBufferProducer::QueueBufferOutput output; 870 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener, 871 NATIVE_WINDOW_API_CPU, false, &output)); 872 873 int slot = BufferQueue::INVALID_BUFFER_SLOT; 874 sp<Fence> fence = Fence::NO_FENCE; 875 sp<GraphicBuffer> buffer = nullptr; 876 IGraphicBufferProducer::QueueBufferInput input(0ull, true, 877 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT, 878 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE); 879 BufferItem item{}; 880 881 // Preallocate, dequeue, request, and cancel 3 buffers so we don't get 882 // BUFFER_NEEDS_REALLOCATION below 883 int slots[3] = {}; 884 mProducer->setMaxDequeuedBufferCount(3); 885 for (size_t i = 0; i < 3; ++i) { 886 status_t result = 887 mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0, 0, nullptr, nullptr); 888 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result); 889 ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer)); 890 } 891 for (size_t i = 0; i < 3; ++i) { 892 ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE)); 893 } 894 895 // Create 3 segments 896 897 // The first segment is a two-buffer segment, so we only put one buffer into 898 // the queue at a time 899 for (size_t i = 0; i < 5; ++i) { 900 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr)); 901 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output)); 902 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0)); 903 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, 904 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE)); 905 std::this_thread::sleep_for(16ms); 906 } 907 908 // Sleep between segments 909 std::this_thread::sleep_for(500ms); 910 911 // The second segment is a double-buffer segment. It starts the same as the 912 // two-buffer segment, but then at the end, we put two buffers in the queue 913 // at the same time before draining it. 914 for (size_t i = 0; i < 5; ++i) { 915 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr)); 916 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output)); 917 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0)); 918 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, 919 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE)); 920 std::this_thread::sleep_for(16ms); 921 } 922 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr)); 923 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output)); 924 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr)); 925 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output)); 926 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0)); 927 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, 928 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE)); 929 std::this_thread::sleep_for(16ms); 930 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0)); 931 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, 932 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE)); 933 934 // Sleep between segments 935 std::this_thread::sleep_for(500ms); 936 937 // The third segment is a triple-buffer segment, so the queue is switching 938 // between one buffer and two buffers deep. 939 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr)); 940 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output)); 941 for (size_t i = 0; i < 5; ++i) { 942 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr)); 943 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output)); 944 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0)); 945 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, 946 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE)); 947 std::this_thread::sleep_for(16ms); 948 } 949 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0)); 950 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, 951 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE)); 952 953 // Now we read the segments 954 std::vector<OccupancyTracker::Segment> history; 955 ASSERT_EQ(OK, mConsumer->getOccupancyHistory(false, &history)); 956 957 // Since we didn't force a flush, we should only get the first two segments 958 // (since the third segment hasn't been closed out by the appearance of a 959 // new segment yet) 960 ASSERT_EQ(2u, history.size()); 961 962 // The first segment (which will be history[1], since the newest segment 963 // should be at the front of the vector) should be a two-buffer segment, 964 // which implies that the occupancy average should be between 0 and 1, and 965 // usedThirdBuffer should be false 966 const auto& firstSegment = history[1]; 967 ASSERT_EQ(5u, firstSegment.numFrames); 968 ASSERT_LT(0, firstSegment.occupancyAverage); 969 ASSERT_GT(1, firstSegment.occupancyAverage); 970 ASSERT_EQ(false, firstSegment.usedThirdBuffer); 971 972 // The second segment should be a double-buffered segment, which implies that 973 // the occupancy average should be between 0 and 1, but usedThirdBuffer 974 // should be true 975 const auto& secondSegment = history[0]; 976 ASSERT_EQ(7u, secondSegment.numFrames); 977 ASSERT_LT(0, secondSegment.occupancyAverage); 978 ASSERT_GT(1, secondSegment.occupancyAverage); 979 ASSERT_EQ(true, secondSegment.usedThirdBuffer); 980 981 // If we read the segments again without flushing, we shouldn't get any new 982 // segments 983 ASSERT_EQ(OK, mConsumer->getOccupancyHistory(false, &history)); 984 ASSERT_EQ(0u, history.size()); 985 986 // Read the segments again, this time forcing a flush so we get the third 987 // segment 988 ASSERT_EQ(OK, mConsumer->getOccupancyHistory(true, &history)); 989 ASSERT_EQ(1u, history.size()); 990 991 // This segment should be a triple-buffered segment, which implies that the 992 // occupancy average should be between 1 and 2, and usedThirdBuffer should 993 // be true 994 const auto& thirdSegment = history[0]; 995 ASSERT_EQ(6u, thirdSegment.numFrames); 996 ASSERT_LT(1, thirdSegment.occupancyAverage); 997 ASSERT_GT(2, thirdSegment.occupancyAverage); 998 ASSERT_EQ(true, thirdSegment.usedThirdBuffer); 999 } 1000 1001 TEST_F(BufferQueueTest, TestDiscardFreeBuffers) { 1002 createBufferQueue(); 1003 sp<DummyConsumer> dc(new DummyConsumer); 1004 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false)); 1005 IGraphicBufferProducer::QueueBufferOutput output; 1006 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener, 1007 NATIVE_WINDOW_API_CPU, false, &output)); 1008 1009 int slot = BufferQueue::INVALID_BUFFER_SLOT; 1010 sp<Fence> fence = Fence::NO_FENCE; 1011 sp<GraphicBuffer> buffer = nullptr; 1012 IGraphicBufferProducer::QueueBufferInput input(0ull, true, 1013 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT, 1014 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE); 1015 BufferItem item{}; 1016 1017 // Preallocate, dequeue, request, and cancel 4 buffers so we don't get 1018 // BUFFER_NEEDS_REALLOCATION below 1019 int slots[4] = {}; 1020 mProducer->setMaxDequeuedBufferCount(4); 1021 for (size_t i = 0; i < 4; ++i) { 1022 status_t result = 1023 mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0, 0, nullptr, nullptr); 1024 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result); 1025 ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer)); 1026 } 1027 for (size_t i = 0; i < 4; ++i) { 1028 ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE)); 1029 } 1030 1031 // Get buffers in all states: dequeued, filled, acquired, free 1032 1033 // Fill 3 buffers 1034 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr)); 1035 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output)); 1036 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr)); 1037 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output)); 1038 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr)); 1039 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output)); 1040 // Dequeue 1 buffer 1041 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr)); 1042 1043 // Acquire and free 1 buffer 1044 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0)); 1045 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, 1046 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE)); 1047 // Acquire 1 buffer, leaving 1 filled buffer in queue 1048 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0)); 1049 1050 // Now discard the free buffers 1051 ASSERT_EQ(OK, mConsumer->discardFreeBuffers()); 1052 1053 // Check no free buffers in dump 1054 String8 dumpString; 1055 mConsumer->dumpState(String8{}, &dumpString); 1056 1057 // Parse the dump to ensure that all buffer slots that are FREE also 1058 // have a null GraphicBuffer 1059 // Fragile - assumes the following format for the dump for a buffer entry: 1060 // ":%p\][^:]*state=FREE" where %p is the buffer pointer in hex. 1061 ssize_t idx = dumpString.find("state=FREE"); 1062 while (idx != -1) { 1063 ssize_t bufferPtrIdx = idx - 1; 1064 while (bufferPtrIdx > 0) { 1065 if (dumpString[bufferPtrIdx] == ':') { 1066 bufferPtrIdx++; 1067 break; 1068 } 1069 bufferPtrIdx--; 1070 } 1071 ASSERT_GT(bufferPtrIdx, 0) << "Can't parse queue dump to validate"; 1072 ssize_t nullPtrIdx = dumpString.find("0x0]", bufferPtrIdx); 1073 ASSERT_EQ(bufferPtrIdx, nullPtrIdx) << "Free buffer not discarded"; 1074 idx = dumpString.find("FREE", idx + 1); 1075 } 1076 } 1077 1078 TEST_F(BufferQueueTest, TestBufferReplacedInQueueBuffer) { 1079 createBufferQueue(); 1080 sp<DummyConsumer> dc(new DummyConsumer); 1081 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true)); 1082 IGraphicBufferProducer::QueueBufferOutput output; 1083 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener, 1084 NATIVE_WINDOW_API_CPU, true, &output)); 1085 ASSERT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1)); 1086 1087 int slot = BufferQueue::INVALID_BUFFER_SLOT; 1088 sp<Fence> fence = Fence::NO_FENCE; 1089 sp<GraphicBuffer> buffer = nullptr; 1090 IGraphicBufferProducer::QueueBufferInput input(0ull, true, 1091 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT, 1092 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE); 1093 BufferItem item{}; 1094 1095 // Preallocate, dequeue, request, and cancel 2 buffers so we don't get 1096 // BUFFER_NEEDS_REALLOCATION below 1097 int slots[2] = {}; 1098 ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(2)); 1099 for (size_t i = 0; i < 2; ++i) { 1100 status_t result = 1101 mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0, 0, nullptr, nullptr); 1102 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result); 1103 ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer)); 1104 } 1105 for (size_t i = 0; i < 2; ++i) { 1106 ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE)); 1107 } 1108 1109 // Fill 2 buffers without consumer consuming them. Verify that all 1110 // queued buffer returns proper bufferReplaced flag 1111 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr)); 1112 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output)); 1113 ASSERT_EQ(false, output.bufferReplaced); 1114 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr)); 1115 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output)); 1116 ASSERT_EQ(true, output.bufferReplaced); 1117 } 1118 1119 TEST_F(BufferQueueTest, TestStaleBufferHandleSentAfterDisconnect) { 1120 createBufferQueue(); 1121 sp<DummyConsumer> dc(new DummyConsumer); 1122 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true)); 1123 IGraphicBufferProducer::QueueBufferOutput output; 1124 sp<IProducerListener> dummyListener(new DummyProducerListener); 1125 ASSERT_EQ(OK, mProducer->connect(dummyListener, NATIVE_WINDOW_API_CPU, 1126 true, &output)); 1127 1128 int slot = BufferQueue::INVALID_BUFFER_SLOT; 1129 sp<Fence> fence = Fence::NO_FENCE; 1130 sp<GraphicBuffer> buffer = nullptr; 1131 IGraphicBufferProducer::QueueBufferInput input(0ull, true, 1132 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT, 1133 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE); 1134 1135 // Dequeue, request, and queue one buffer 1136 status_t result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr); 1137 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result); 1138 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer)); 1139 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output)); 1140 1141 // Acquire and release the buffer. Upon acquiring, the buffer handle should 1142 // be non-null since this is the first time we've acquired this slot. 1143 BufferItem item; 1144 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0)); 1145 ASSERT_EQ(slot, item.mSlot); 1146 ASSERT_NE(nullptr, item.mGraphicBuffer.get()); 1147 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, 1148 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE)); 1149 1150 // Dequeue and queue the buffer again 1151 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr)); 1152 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output)); 1153 1154 // Acquire and release the buffer again. Upon acquiring, the buffer handle 1155 // should be null since this is not the first time we've acquired this slot. 1156 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0)); 1157 ASSERT_EQ(slot, item.mSlot); 1158 ASSERT_EQ(nullptr, item.mGraphicBuffer.get()); 1159 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, 1160 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE)); 1161 1162 // Dequeue and queue the buffer again 1163 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr)); 1164 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output)); 1165 1166 // Disconnect the producer end. This should clear all of the slots and mark 1167 // the buffer in the queue as stale. 1168 ASSERT_EQ(OK, mProducer->disconnect(NATIVE_WINDOW_API_CPU)); 1169 1170 // Acquire the buffer again. Upon acquiring, the buffer handle should not be 1171 // null since the queued buffer should have been marked as stale, which 1172 // should trigger the BufferQueue to resend the buffer handle. 1173 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0)); 1174 ASSERT_EQ(slot, item.mSlot); 1175 ASSERT_NE(nullptr, item.mGraphicBuffer.get()); 1176 } 1177 1178 TEST_F(BufferQueueTest, TestProducerConnectDisconnect) { 1179 createBufferQueue(); 1180 sp<DummyConsumer> dc(new DummyConsumer); 1181 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true)); 1182 IGraphicBufferProducer::QueueBufferOutput output; 1183 sp<IProducerListener> dummyListener(new DummyProducerListener); 1184 ASSERT_EQ(NO_INIT, mProducer->disconnect(NATIVE_WINDOW_API_CPU)); 1185 ASSERT_EQ(OK, mProducer->connect( 1186 dummyListener, NATIVE_WINDOW_API_CPU, true, &output)); 1187 ASSERT_EQ(BAD_VALUE, mProducer->connect( 1188 dummyListener, NATIVE_WINDOW_API_MEDIA, true, &output)); 1189 1190 ASSERT_EQ(BAD_VALUE, mProducer->disconnect(NATIVE_WINDOW_API_MEDIA)); 1191 ASSERT_EQ(OK, mProducer->disconnect(NATIVE_WINDOW_API_CPU)); 1192 ASSERT_EQ(NO_INIT, mProducer->disconnect(NATIVE_WINDOW_API_CPU)); 1193 } 1194 1195 } // namespace android 1196