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