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