1/* 2 * Copyright (C) 2013 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 "IGraphicBufferProducer_test" 18//#define LOG_NDEBUG 0 19 20#include "DummyConsumer.h" 21 22#include <gtest/gtest.h> 23 24#include <utils/String8.h> 25#include <utils/threads.h> 26 27#include <ui/GraphicBuffer.h> 28 29#include <gui/BufferQueue.h> 30#include <gui/IProducerListener.h> 31 32#include <system/window.h> 33 34#include <vector> 35 36#define ASSERT_OK(x) ASSERT_EQ(OK, (x)) 37#define EXPECT_OK(x) EXPECT_EQ(OK, (x)) 38 39#define TEST_TOKEN ((IProducerListener*)(NULL)) 40#define TEST_API NATIVE_WINDOW_API_CPU 41#define TEST_API_OTHER NATIVE_WINDOW_API_EGL // valid API that's not TEST_API 42#define TEST_CONTROLLED_BY_APP false 43#define TEST_PRODUCER_USAGE_BITS (0) 44 45#ifndef USE_BUFFER_HUB_AS_BUFFER_QUEUE 46#define USE_BUFFER_HUB_AS_BUFFER_QUEUE 0 47#endif 48 49namespace android { 50 51namespace { 52 // Default dimensions before setDefaultBufferSize is called 53 const uint32_t DEFAULT_WIDTH = 1; 54 const uint32_t DEFAULT_HEIGHT = 1; 55 56 // Default format before setDefaultBufferFormat is called 57 const PixelFormat DEFAULT_FORMAT = HAL_PIXEL_FORMAT_RGBA_8888; 58 59 // Default transform hint before setTransformHint is called 60 const uint32_t DEFAULT_TRANSFORM_HINT = 0; 61 62 // TODO: Make these constants in header 63 const int DEFAULT_CONSUMER_USAGE_BITS = 0; 64 65 // Parameters for a generic "valid" input for queueBuffer. 66 const int64_t QUEUE_BUFFER_INPUT_TIMESTAMP = 1384888611; 67 const bool QUEUE_BUFFER_INPUT_IS_AUTO_TIMESTAMP = false; 68 const android_dataspace QUEUE_BUFFER_INPUT_DATASPACE = HAL_DATASPACE_UNKNOWN; 69 const Rect QUEUE_BUFFER_INPUT_RECT = Rect(DEFAULT_WIDTH, DEFAULT_HEIGHT); 70 const int QUEUE_BUFFER_INPUT_SCALING_MODE = 0; 71 const int QUEUE_BUFFER_INPUT_TRANSFORM = 0; 72 const sp<Fence> QUEUE_BUFFER_INPUT_FENCE = Fence::NO_FENCE; 73 74 // Enums to control which IGraphicBufferProducer backend to test. 75 enum IGraphicBufferProducerTestCode { 76 USE_BUFFER_QUEUE_PRODUCER = 0, 77 USE_BUFFER_HUB_PRODUCER, 78 }; 79}; // namespace anonymous 80 81class IGraphicBufferProducerTest : public ::testing::TestWithParam<uint32_t> { 82protected: 83 84 IGraphicBufferProducerTest() {} 85 86 virtual void SetUp() { 87 const ::testing::TestInfo* const testInfo = 88 ::testing::UnitTest::GetInstance()->current_test_info(); 89 ALOGV("Begin test: %s.%s", testInfo->test_case_name(), 90 testInfo->name()); 91 92 mDC = new DummyConsumer; 93 94 switch (GetParam()) { 95 case USE_BUFFER_QUEUE_PRODUCER: { 96 BufferQueue::createBufferQueue(&mProducer, &mConsumer); 97 break; 98 } 99 case USE_BUFFER_HUB_PRODUCER: { 100 BufferQueue::createBufferHubQueue(&mProducer, &mConsumer); 101 break; 102 } 103 default: { 104 // Should never reach here. 105 LOG_ALWAYS_FATAL("Invalid test params: %u", GetParam()); 106 break; 107 } 108 } 109 110 // Test check: Can't connect producer if no consumer yet 111 if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) { 112 // TODO(b/73267953): Make BufferHub honor producer and consumer connection. 113 ASSERT_EQ(NO_INIT, TryConnectProducer()); 114 } 115 116 // Must connect consumer before producer connects will succeed. 117 ASSERT_OK(mConsumer->consumerConnect(mDC, /*controlledByApp*/false)); 118 } 119 120 virtual void TearDown() { 121 const ::testing::TestInfo* const testInfo = 122 ::testing::UnitTest::GetInstance()->current_test_info(); 123 ALOGV("End test: %s.%s", testInfo->test_case_name(), 124 testInfo->name()); 125 } 126 127 status_t TryConnectProducer() { 128 IGraphicBufferProducer::QueueBufferOutput output; 129 return mProducer->connect(TEST_TOKEN, 130 TEST_API, 131 TEST_CONTROLLED_BY_APP, 132 &output); 133 // TODO: use params to vary token, api, producercontrolledbyapp, etc 134 } 135 136 // Connect to a producer in a 'correct' fashion. 137 // Precondition: Consumer is connected. 138 void ConnectProducer() { 139 ASSERT_OK(TryConnectProducer()); 140 } 141 142 // Create a generic "valid" input for queueBuffer 143 // -- uses the default buffer format, width, etc. 144 static IGraphicBufferProducer::QueueBufferInput CreateBufferInput() { 145 return QueueBufferInputBuilder().build(); 146 } 147 148 // Builder pattern to slightly vary *almost* correct input 149 // -- avoids copying and pasting 150 struct QueueBufferInputBuilder { 151 QueueBufferInputBuilder() { 152 timestamp = QUEUE_BUFFER_INPUT_TIMESTAMP; 153 isAutoTimestamp = QUEUE_BUFFER_INPUT_IS_AUTO_TIMESTAMP; 154 dataSpace = QUEUE_BUFFER_INPUT_DATASPACE; 155 crop = QUEUE_BUFFER_INPUT_RECT; 156 scalingMode = QUEUE_BUFFER_INPUT_SCALING_MODE; 157 transform = QUEUE_BUFFER_INPUT_TRANSFORM; 158 fence = QUEUE_BUFFER_INPUT_FENCE; 159 } 160 161 IGraphicBufferProducer::QueueBufferInput build() { 162 return IGraphicBufferProducer::QueueBufferInput( 163 timestamp, 164 isAutoTimestamp, 165 dataSpace, 166 crop, 167 scalingMode, 168 transform, 169 fence); 170 } 171 172 QueueBufferInputBuilder& setTimestamp(int64_t timestamp) { 173 this->timestamp = timestamp; 174 return *this; 175 } 176 177 QueueBufferInputBuilder& setIsAutoTimestamp(bool isAutoTimestamp) { 178 this->isAutoTimestamp = isAutoTimestamp; 179 return *this; 180 } 181 182 QueueBufferInputBuilder& setDataSpace(android_dataspace dataSpace) { 183 this->dataSpace = dataSpace; 184 return *this; 185 } 186 187 QueueBufferInputBuilder& setCrop(Rect crop) { 188 this->crop = crop; 189 return *this; 190 } 191 192 QueueBufferInputBuilder& setScalingMode(int scalingMode) { 193 this->scalingMode = scalingMode; 194 return *this; 195 } 196 197 QueueBufferInputBuilder& setTransform(uint32_t transform) { 198 this->transform = transform; 199 return *this; 200 } 201 202 QueueBufferInputBuilder& setFence(sp<Fence> fence) { 203 this->fence = fence; 204 return *this; 205 } 206 207 private: 208 int64_t timestamp; 209 bool isAutoTimestamp; 210 android_dataspace dataSpace; 211 Rect crop; 212 int scalingMode; 213 uint32_t transform; 214 sp<Fence> fence; 215 }; // struct QueueBufferInputBuilder 216 217 // To easily store dequeueBuffer results into containers 218 struct DequeueBufferResult { 219 int slot; 220 sp<Fence> fence; 221 }; 222 223 status_t dequeueBuffer(uint32_t w, uint32_t h, uint32_t format, uint32_t usage, DequeueBufferResult* result) { 224 return mProducer->dequeueBuffer(&result->slot, &result->fence, w, h, format, usage, 225 nullptr, nullptr); 226 } 227 228 void setupDequeueRequestBuffer(int *slot, sp<Fence> *fence, 229 sp<GraphicBuffer> *buffer) 230 { 231 ASSERT_TRUE(slot != NULL); 232 ASSERT_TRUE(fence != NULL); 233 ASSERT_TRUE(buffer != NULL); 234 235 ASSERT_NO_FATAL_FAILURE(ConnectProducer()); 236 237 238 ASSERT_EQ(OK, 239 ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION & 240 (mProducer->dequeueBuffer(slot, fence, DEFAULT_WIDTH, DEFAULT_HEIGHT, 241 DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS, 242 nullptr, nullptr))); 243 244 EXPECT_LE(0, *slot); 245 EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, *slot); 246 247 // Request the buffer (pre-requisite for queueing) 248 ASSERT_OK(mProducer->requestBuffer(*slot, buffer)); 249 } 250 251private: // hide from test body 252 sp<DummyConsumer> mDC; 253 254protected: // accessible from test body 255 sp<IGraphicBufferProducer> mProducer; 256 sp<IGraphicBufferConsumer> mConsumer; 257}; 258 259TEST_P(IGraphicBufferProducerTest, ConnectFirst_ReturnsError) { 260 IGraphicBufferProducer::QueueBufferOutput output; 261 262 // NULL output returns BAD_VALUE 263 EXPECT_EQ(BAD_VALUE, mProducer->connect(TEST_TOKEN, 264 TEST_API, 265 TEST_CONTROLLED_BY_APP, 266 /*output*/NULL)); 267 268 // Invalid API returns bad value 269 EXPECT_EQ(BAD_VALUE, mProducer->connect(TEST_TOKEN, 270 /*api*/0xDEADBEEF, 271 TEST_CONTROLLED_BY_APP, 272 &output)); 273 274 // TODO: get a token from a dead process somehow 275} 276 277TEST_P(IGraphicBufferProducerTest, ConnectAgain_ReturnsError) { 278 ASSERT_NO_FATAL_FAILURE(ConnectProducer()); 279 280 // Can't connect when there is already a producer connected 281 IGraphicBufferProducer::QueueBufferOutput output; 282 EXPECT_EQ(BAD_VALUE, mProducer->connect(TEST_TOKEN, 283 TEST_API, 284 TEST_CONTROLLED_BY_APP, 285 &output)); 286 287 ASSERT_OK(mConsumer->consumerDisconnect()); 288 // Can't connect when IGBP is abandoned 289 if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) { 290 // TODO(b/73267953): Make BufferHub honor producer and consumer connection. 291 EXPECT_EQ(NO_INIT, mProducer->connect(TEST_TOKEN, 292 TEST_API, 293 TEST_CONTROLLED_BY_APP, 294 &output)); 295 } 296} 297 298TEST_P(IGraphicBufferProducerTest, Disconnect_Succeeds) { 299 ASSERT_NO_FATAL_FAILURE(ConnectProducer()); 300 301 ASSERT_OK(mProducer->disconnect(TEST_API)); 302} 303 304 305TEST_P(IGraphicBufferProducerTest, Disconnect_ReturnsError) { 306 ASSERT_NO_FATAL_FAILURE(ConnectProducer()); 307 308 // Must disconnect with same API number 309 ASSERT_EQ(BAD_VALUE, mProducer->disconnect(TEST_API_OTHER)); 310 // API must not be out of range 311 ASSERT_EQ(BAD_VALUE, mProducer->disconnect(/*api*/0xDEADBEEF)); 312 313 // TODO: somehow kill mProducer so that this returns DEAD_OBJECT 314} 315 316TEST_P(IGraphicBufferProducerTest, Query_Succeeds) { 317 ASSERT_NO_FATAL_FAILURE(ConnectProducer()); 318 319 int32_t value = -1; 320 EXPECT_OK(mProducer->query(NATIVE_WINDOW_WIDTH, &value)); 321 EXPECT_EQ(DEFAULT_WIDTH, static_cast<uint32_t>(value)); 322 323 EXPECT_OK(mProducer->query(NATIVE_WINDOW_HEIGHT, &value)); 324 EXPECT_EQ(DEFAULT_HEIGHT, static_cast<uint32_t>(value)); 325 326 EXPECT_OK(mProducer->query(NATIVE_WINDOW_FORMAT, &value)); 327 EXPECT_EQ(DEFAULT_FORMAT, value); 328 329 EXPECT_OK(mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &value)); 330 EXPECT_LE(0, value); 331 EXPECT_GE(BufferQueue::NUM_BUFFER_SLOTS, value); 332 333 EXPECT_OK(mProducer->query(NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &value)); 334 EXPECT_FALSE(value); // Can't run behind when we haven't touched the queue 335 336 EXPECT_OK(mProducer->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &value)); 337 EXPECT_EQ(DEFAULT_CONSUMER_USAGE_BITS, value); 338 339} 340 341TEST_P(IGraphicBufferProducerTest, Query_ReturnsError) { 342 ASSERT_NO_FATAL_FAILURE(ConnectProducer()); 343 344 // One past the end of the last 'query' enum value. Update this if we add more enums. 345 const int NATIVE_WINDOW_QUERY_LAST_OFF_BY_ONE = NATIVE_WINDOW_BUFFER_AGE + 1; 346 347 int value; 348 // What was out of range 349 EXPECT_EQ(BAD_VALUE, mProducer->query(/*what*/-1, &value)); 350 EXPECT_EQ(BAD_VALUE, mProducer->query(/*what*/0xDEADBEEF, &value)); 351 EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_QUERY_LAST_OFF_BY_ONE, &value)); 352 353 // Some enums from window.h are 'invalid' 354 EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER, &value)); 355 EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_CONCRETE_TYPE, &value)); 356 EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_DEFAULT_WIDTH, &value)); 357 EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_DEFAULT_HEIGHT, &value)); 358 EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_TRANSFORM_HINT, &value)); 359 // TODO: Consider documented the above enums as unsupported or make a new enum for IGBP 360 361 // Value was NULL 362 EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_FORMAT, /*value*/NULL)); 363 364 ASSERT_OK(mConsumer->consumerDisconnect()); 365 366 // BQ was abandoned 367 if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) { 368 // TODO(b/73267953): Make BufferHub honor producer and consumer connection. 369 EXPECT_EQ(NO_INIT, mProducer->query(NATIVE_WINDOW_FORMAT, &value)); 370 } 371 372 // TODO: other things in window.h that are supported by Surface::query 373 // but not by BufferQueue::query 374} 375 376// TODO: queue under more complicated situations not involving just a single buffer 377TEST_P(IGraphicBufferProducerTest, Queue_Succeeds) { 378 ASSERT_NO_FATAL_FAILURE(ConnectProducer()); 379 380 int dequeuedSlot = -1; 381 sp<Fence> dequeuedFence; 382 383 ASSERT_EQ(OK, 384 ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION & 385 (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence, DEFAULT_WIDTH, 386 DEFAULT_HEIGHT, DEFAULT_FORMAT, 387 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr))); 388 389 EXPECT_LE(0, dequeuedSlot); 390 EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, dequeuedSlot); 391 392 // Request the buffer (pre-requisite for queueing) 393 sp<GraphicBuffer> dequeuedBuffer; 394 ASSERT_OK(mProducer->requestBuffer(dequeuedSlot, &dequeuedBuffer)); 395 396 // A generic "valid" input 397 IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput(); 398 IGraphicBufferProducer::QueueBufferOutput output; 399 400 // Queue the buffer back into the BQ 401 ASSERT_OK(mProducer->queueBuffer(dequeuedSlot, input, &output)); 402 403 { 404 EXPECT_EQ(DEFAULT_WIDTH, output.width); 405 EXPECT_EQ(DEFAULT_HEIGHT, output.height); 406 EXPECT_EQ(DEFAULT_TRANSFORM_HINT, output.transformHint); 407 408 // Since queueBuffer was called exactly once 409 if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) { 410 // TODO(b/70041889): BufferHubProducer need to support metadata: numPendingBuffers 411 EXPECT_EQ(1u, output.numPendingBuffers); 412 // TODO(b/70041952): BufferHubProducer need to support metadata: nextFrameNumber 413 EXPECT_EQ(2u, output.nextFrameNumber); 414 } 415 } 416 417 // Buffer was not in the dequeued state 418 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output)); 419} 420 421TEST_P(IGraphicBufferProducerTest, Queue_ReturnsError) { 422 ASSERT_NO_FATAL_FAILURE(ConnectProducer()); 423 424 // Invalid slot number 425 { 426 // A generic "valid" input 427 IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput(); 428 IGraphicBufferProducer::QueueBufferOutput output; 429 430 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(/*slot*/-1, input, &output)); 431 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(/*slot*/0xDEADBEEF, input, &output)); 432 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(BufferQueue::NUM_BUFFER_SLOTS, 433 input, &output)); 434 } 435 436 // Slot was not in the dequeued state (all slots start out in Free state) 437 { 438 IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput(); 439 IGraphicBufferProducer::QueueBufferOutput output; 440 441 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(/*slot*/0, input, &output)); 442 } 443 444 // Put the slot into the "dequeued" state for the rest of the test 445 int dequeuedSlot = -1; 446 sp<Fence> dequeuedFence; 447 448 ASSERT_EQ(OK, 449 ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION & 450 (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence, DEFAULT_WIDTH, 451 DEFAULT_HEIGHT, DEFAULT_FORMAT, 452 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr))); 453 454 // Slot was enqueued without requesting a buffer 455 { 456 IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput(); 457 IGraphicBufferProducer::QueueBufferOutput output; 458 459 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output)); 460 } 461 462 // Request the buffer so that the rest of the tests don't fail on earlier checks. 463 sp<GraphicBuffer> dequeuedBuffer; 464 ASSERT_OK(mProducer->requestBuffer(dequeuedSlot, &dequeuedBuffer)); 465 466 // Fence was NULL 467 { 468 sp<Fence> nullFence = NULL; 469 470 IGraphicBufferProducer::QueueBufferInput input = 471 QueueBufferInputBuilder().setFence(nullFence).build(); 472 IGraphicBufferProducer::QueueBufferOutput output; 473 474 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output)); 475 } 476 477 // Scaling mode was unknown 478 { 479 IGraphicBufferProducer::QueueBufferInput input = 480 QueueBufferInputBuilder().setScalingMode(-1).build(); 481 IGraphicBufferProducer::QueueBufferOutput output; 482 483 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output)); 484 485 input = QueueBufferInputBuilder().setScalingMode(0xDEADBEEF).build(); 486 487 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output)); 488 } 489 490 // Crop rect is out of bounds of the buffer dimensions 491 { 492 IGraphicBufferProducer::QueueBufferInput input = 493 QueueBufferInputBuilder().setCrop(Rect(DEFAULT_WIDTH + 1, DEFAULT_HEIGHT + 1)) 494 .build(); 495 IGraphicBufferProducer::QueueBufferOutput output; 496 497 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output)); 498 } 499 500 // Abandon the buffer queue so that the last test fails 501 ASSERT_OK(mConsumer->consumerDisconnect()); 502 503 // The buffer queue has been abandoned. 504 if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) { 505 IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput(); 506 IGraphicBufferProducer::QueueBufferOutput output; 507 508 // TODO(b/73267953): Make BufferHub honor producer and consumer connection. 509 EXPECT_EQ(NO_INIT, mProducer->queueBuffer(dequeuedSlot, input, &output)); 510 } 511} 512 513TEST_P(IGraphicBufferProducerTest, CancelBuffer_DoesntCrash) { 514 ASSERT_NO_FATAL_FAILURE(ConnectProducer()); 515 516 int dequeuedSlot = -1; 517 sp<Fence> dequeuedFence; 518 519 ASSERT_EQ(OK, 520 ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION & 521 (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence, DEFAULT_WIDTH, 522 DEFAULT_HEIGHT, DEFAULT_FORMAT, 523 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr))); 524 525 // No return code, but at least test that it doesn't blow up... 526 // TODO: add a return code 527 mProducer->cancelBuffer(dequeuedSlot, dequeuedFence); 528} 529 530TEST_P(IGraphicBufferProducerTest, SetMaxDequeuedBufferCount_Succeeds) { 531 ASSERT_NO_FATAL_FAILURE(ConnectProducer()); 532 int minUndequeuedBuffers; 533 ASSERT_OK(mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, 534 &minUndequeuedBuffers)); 535 536 const int minBuffers = 1; 537 const int maxBuffers = BufferQueue::NUM_BUFFER_SLOTS - minUndequeuedBuffers; 538 539 ASSERT_OK(mProducer->setAsyncMode(false)) << "async mode: " << false; 540 ASSERT_OK(mProducer->setMaxDequeuedBufferCount(minBuffers)) 541 << "bufferCount: " << minBuffers; 542 543 // Should now be able to dequeue up to minBuffers times 544 DequeueBufferResult result; 545 for (int i = 0; i < minBuffers; ++i) { 546 547 EXPECT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION & 548 (dequeueBuffer(DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT, 549 TEST_PRODUCER_USAGE_BITS, &result))) 550 << "iteration: " << i << ", slot: " << result.slot; 551 } 552 553 ASSERT_OK(mProducer->setMaxDequeuedBufferCount(maxBuffers)); 554 555 // queue the first buffer to enable max dequeued buffer count checking 556 IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput(); 557 IGraphicBufferProducer::QueueBufferOutput output; 558 sp<GraphicBuffer> buffer; 559 ASSERT_OK(mProducer->requestBuffer(result.slot, &buffer)); 560 ASSERT_OK(mProducer->queueBuffer(result.slot, input, &output)); 561 562 563 // Should now be able to dequeue up to maxBuffers times 564 int dequeuedSlot = -1; 565 sp<Fence> dequeuedFence; 566 for (int i = 0; i < maxBuffers; ++i) { 567 EXPECT_EQ(OK, 568 ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION & 569 (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence, DEFAULT_WIDTH, 570 DEFAULT_HEIGHT, DEFAULT_FORMAT, 571 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr))) 572 << "iteration: " << i << ", slot: " << dequeuedSlot; 573 } 574 575 // Cancel a buffer, so we can decrease the buffer count 576 ASSERT_OK(mProducer->cancelBuffer(dequeuedSlot, dequeuedFence)); 577 578 // Should now be able to decrease the max dequeued count by 1 579 ASSERT_OK(mProducer->setMaxDequeuedBufferCount(maxBuffers-1)); 580} 581 582TEST_P(IGraphicBufferProducerTest, SetMaxDequeuedBufferCount_Fails) { 583 ASSERT_NO_FATAL_FAILURE(ConnectProducer()); 584 int minUndequeuedBuffers; 585 ASSERT_OK(mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, 586 &minUndequeuedBuffers)); 587 588 const int minBuffers = 1; 589 const int maxBuffers = BufferQueue::NUM_BUFFER_SLOTS - minUndequeuedBuffers; 590 591 ASSERT_OK(mProducer->setAsyncMode(false)) << "async mode: " << false; 592 // Buffer count was out of range 593 EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(0)) 594 << "bufferCount: " << 0; 595 EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(maxBuffers + 1)) 596 << "bufferCount: " << maxBuffers + 1; 597 598 // Set max dequeue count to 2 599 ASSERT_OK(mProducer->setMaxDequeuedBufferCount(2)); 600 // Dequeue 2 buffers 601 int dequeuedSlot = -1; 602 sp<Fence> dequeuedFence; 603 for (int i = 0; i < 2; i++) { 604 ASSERT_EQ(OK, 605 ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION & 606 (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence, DEFAULT_WIDTH, 607 DEFAULT_HEIGHT, DEFAULT_FORMAT, 608 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr))) 609 << "slot: " << dequeuedSlot; 610 } 611 612 // Client has too many buffers dequeued 613 EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(1)) 614 << "bufferCount: " << minBuffers; 615 616 // Abandon buffer queue 617 ASSERT_OK(mConsumer->consumerDisconnect()); 618 619 // Fail because the buffer queue was abandoned 620 if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) { 621 // TODO(b/73267953): Make BufferHub honor producer and consumer connection. 622 EXPECT_EQ(NO_INIT, mProducer->setMaxDequeuedBufferCount(minBuffers)) 623 << "bufferCount: " << minBuffers; 624 } 625} 626 627TEST_P(IGraphicBufferProducerTest, SetAsyncMode_Succeeds) { 628 if (GetParam() == USE_BUFFER_HUB_PRODUCER) { 629 // TODO(b/36724099): Add support for BufferHubProducer::setAsyncMode(true) 630 return; 631 } 632 633 ASSERT_OK(mConsumer->setMaxAcquiredBufferCount(1)) << "maxAcquire: " << 1; 634 ASSERT_NO_FATAL_FAILURE(ConnectProducer()); 635 ASSERT_OK(mProducer->setAsyncMode(true)) << "async mode: " << true; 636 ASSERT_OK(mProducer->setMaxDequeuedBufferCount(1)) << "maxDequeue: " << 1; 637 638 int dequeuedSlot = -1; 639 sp<Fence> dequeuedFence; 640 IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput(); 641 IGraphicBufferProducer::QueueBufferOutput output; 642 sp<GraphicBuffer> dequeuedBuffer; 643 644 // Should now be able to queue/dequeue as many buffers as we want without 645 // blocking 646 for (int i = 0; i < 5; ++i) { 647 ASSERT_EQ(OK, 648 ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION & 649 (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence, DEFAULT_WIDTH, 650 DEFAULT_HEIGHT, DEFAULT_FORMAT, 651 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr))) 652 << "slot : " << dequeuedSlot; 653 ASSERT_OK(mProducer->requestBuffer(dequeuedSlot, &dequeuedBuffer)); 654 ASSERT_OK(mProducer->queueBuffer(dequeuedSlot, input, &output)); 655 } 656} 657 658TEST_P(IGraphicBufferProducerTest, SetAsyncMode_Fails) { 659 ASSERT_NO_FATAL_FAILURE(ConnectProducer()); 660 // Prerequisite to fail out a valid setBufferCount call 661 { 662 int dequeuedSlot = -1; 663 sp<Fence> dequeuedFence; 664 665 ASSERT_EQ(OK, 666 ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION & 667 (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence, DEFAULT_WIDTH, 668 DEFAULT_HEIGHT, DEFAULT_FORMAT, 669 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr))) 670 << "slot: " << dequeuedSlot; 671 } 672 673 // Abandon buffer queue 674 ASSERT_OK(mConsumer->consumerDisconnect()); 675 676 // Fail because the buffer queue was abandoned 677 if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) { 678 // TODO(b/36724099): Make BufferHub honor producer and consumer connection. 679 EXPECT_EQ(NO_INIT, mProducer->setAsyncMode(false)) << "asyncMode: " << false; 680 } 681} 682 683TEST_P(IGraphicBufferProducerTest, 684 DisconnectedProducerReturnsError_dequeueBuffer) { 685 int slot = -1; 686 sp<Fence> fence; 687 688 ASSERT_EQ(NO_INIT, 689 mProducer->dequeueBuffer(&slot, &fence, DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT, 690 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr)); 691} 692 693TEST_P(IGraphicBufferProducerTest, 694 DisconnectedProducerReturnsError_detachNextBuffer) { 695 sp<Fence> fence; 696 sp<GraphicBuffer> buffer; 697 698 if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) { 699 // TODO(b/38137191): Implement BufferHubProducer::detachBuffer 700 ASSERT_EQ(NO_INIT, mProducer->detachNextBuffer(&buffer, &fence)); 701 } 702} 703 704TEST_P(IGraphicBufferProducerTest, 705 DisconnectedProducerReturnsError_requestBuffer) { 706 ASSERT_NO_FATAL_FAILURE(ConnectProducer()); 707 708 int slot = -1; 709 sp<Fence> fence; 710 711 ASSERT_EQ(OK, 712 ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION & 713 (mProducer->dequeueBuffer(&slot, &fence, DEFAULT_WIDTH, DEFAULT_HEIGHT, 714 DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS, 715 nullptr, nullptr))); 716 717 EXPECT_LE(0, slot); 718 EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, slot); 719 720 ASSERT_OK(mProducer->disconnect(TEST_API)); 721 722 sp<GraphicBuffer> buffer; 723 724 ASSERT_EQ(NO_INIT, mProducer->requestBuffer(slot, &buffer)); 725} 726 727 728TEST_P(IGraphicBufferProducerTest, 729 DisconnectedProducerReturnsError_detachBuffer) { 730 int slot = -1; 731 sp<Fence> fence; 732 sp<GraphicBuffer> buffer; 733 734 setupDequeueRequestBuffer(&slot, &fence, &buffer); 735 736 ASSERT_OK(mProducer->disconnect(TEST_API)); 737 738 if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) { 739 // TODO(b/38137191): Implement BufferHubProducer::detachBuffer 740 ASSERT_EQ(NO_INIT, mProducer->detachBuffer(slot)); 741 } 742} 743 744TEST_P(IGraphicBufferProducerTest, 745 DisconnectedProducerReturnsError_queueBuffer) { 746 int slot = -1; 747 sp<Fence> fence; 748 sp<GraphicBuffer> buffer; 749 750 setupDequeueRequestBuffer(&slot, &fence, &buffer); 751 752 ASSERT_OK(mProducer->disconnect(TEST_API)); 753 754 // A generic "valid" input 755 IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput(); 756 IGraphicBufferProducer::QueueBufferOutput output; 757 758 ASSERT_EQ(NO_INIT, mProducer->queueBuffer(slot, input, &output)); 759} 760 761TEST_P(IGraphicBufferProducerTest, 762 DisconnectedProducerReturnsError_cancelBuffer) { 763 int slot = -1; 764 sp<Fence> fence; 765 sp<GraphicBuffer> buffer; 766 767 setupDequeueRequestBuffer(&slot, &fence, &buffer); 768 769 ASSERT_OK(mProducer->disconnect(TEST_API)); 770 771 ASSERT_EQ(NO_INIT, mProducer->cancelBuffer(slot, fence)); 772} 773 774TEST_P(IGraphicBufferProducerTest, 775 DisconnectedProducerReturnsError_attachBuffer) { 776 int slot = -1; 777 sp<Fence> fence; 778 sp<GraphicBuffer> buffer; 779 780 setupDequeueRequestBuffer(&slot, &fence, &buffer); 781 782 if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) { 783 // TODO(b/38137191): Implement BufferHubProducer::detachBuffer 784 ASSERT_OK(mProducer->detachBuffer(slot)); 785 } 786 787 ASSERT_OK(mProducer->disconnect(TEST_API)); 788 789 if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) { 790 // TODO(b/69981968): Implement BufferHubProducer::attachBuffer 791 ASSERT_EQ(NO_INIT, mProducer->attachBuffer(&slot, buffer)); 792 } 793} 794 795#if USE_BUFFER_HUB_AS_BUFFER_QUEUE 796INSTANTIATE_TEST_CASE_P(IGraphicBufferProducerBackends, IGraphicBufferProducerTest, 797 ::testing::Values(USE_BUFFER_QUEUE_PRODUCER, USE_BUFFER_HUB_PRODUCER)); 798#else 799// TODO(b/70046255): Remove the #ifdef here and always tests both backends once BufferHubQueue can 800// pass all existing libgui tests. 801INSTANTIATE_TEST_CASE_P(IGraphicBufferProducerBackends, IGraphicBufferProducerTest, 802 ::testing::Values(USE_BUFFER_QUEUE_PRODUCER)); 803#endif 804 805} // namespace android 806