1#include <base/logging.h> 2#include <gui/BufferHubProducer.h> 3#include <gui/IProducerListener.h> 4#include <gui/Surface.h> 5#include <pdx/default_transport/channel_parcelable.h> 6 7#include <gtest/gtest.h> 8 9namespace android { 10namespace dvr { 11 12using pdx::LocalHandle; 13 14namespace { 15 16// Default dimensions before setDefaultBufferSize is called by the consumer. 17constexpr uint32_t kDefaultWidth = 1; 18constexpr uint32_t kDefaultHeight = 1; 19 20// Default format before setDefaultBufferFormat is called by the consumer. 21constexpr PixelFormat kDefaultFormat = HAL_PIXEL_FORMAT_RGBA_8888; 22constexpr int kDefaultConsumerUsageBits = 0; 23 24// Default transform hint before setTransformHint is called by the consumer. 25constexpr uint32_t kDefaultTransformHint = 0; 26 27constexpr int kTestApi = NATIVE_WINDOW_API_CPU; 28constexpr int kTestApiOther = NATIVE_WINDOW_API_EGL; 29constexpr int kTestApiInvalid = 0xDEADBEEF; 30constexpr int kTestProducerUsageBits = 0; 31constexpr bool kTestControlledByApp = true; 32 33// Builder pattern to slightly vary *almost* correct input 34// -- avoids copying and pasting 35struct QueueBufferInputBuilder { 36 IGraphicBufferProducer::QueueBufferInput build() { 37 return IGraphicBufferProducer::QueueBufferInput( 38 mTimestamp, mIsAutoTimestamp, mDataSpace, mCrop, mScalingMode, 39 mTransform, mFence); 40 } 41 42 QueueBufferInputBuilder& setTimestamp(int64_t timestamp) { 43 this->mTimestamp = timestamp; 44 return *this; 45 } 46 47 QueueBufferInputBuilder& setIsAutoTimestamp(bool isAutoTimestamp) { 48 this->mIsAutoTimestamp = isAutoTimestamp; 49 return *this; 50 } 51 52 QueueBufferInputBuilder& setDataSpace(android_dataspace dataSpace) { 53 this->mDataSpace = dataSpace; 54 return *this; 55 } 56 57 QueueBufferInputBuilder& setCrop(Rect crop) { 58 this->mCrop = crop; 59 return *this; 60 } 61 62 QueueBufferInputBuilder& setScalingMode(int scalingMode) { 63 this->mScalingMode = scalingMode; 64 return *this; 65 } 66 67 QueueBufferInputBuilder& setTransform(uint32_t transform) { 68 this->mTransform = transform; 69 return *this; 70 } 71 72 QueueBufferInputBuilder& setFence(sp<Fence> fence) { 73 this->mFence = fence; 74 return *this; 75 } 76 77 private: 78 int64_t mTimestamp{1384888611}; 79 bool mIsAutoTimestamp{false}; 80 android_dataspace mDataSpace{HAL_DATASPACE_UNKNOWN}; 81 Rect mCrop{Rect(kDefaultWidth, kDefaultHeight)}; 82 int mScalingMode{0}; 83 uint32_t mTransform{0}; 84 sp<Fence> mFence{Fence::NO_FENCE}; 85}; 86 87// This is a test that covers our implementation of bufferhubqueue-based 88// IGraphicBufferProducer. 89class BufferHubQueueProducerTest : public ::testing::Test { 90 protected: 91 virtual void SetUp() { 92 const ::testing::TestInfo* const testInfo = 93 ::testing::UnitTest::GetInstance()->current_test_info(); 94 ALOGD_IF(TRACE, "Begin test: %s.%s", testInfo->test_case_name(), 95 testInfo->name()); 96 97 auto config = ProducerQueueConfigBuilder().Build(); 98 auto queue = ProducerQueue::Create(config, UsagePolicy{}); 99 ASSERT_TRUE(queue != nullptr); 100 101 mProducer = BufferHubProducer::Create(std::move(queue)); 102 ASSERT_TRUE(mProducer != nullptr); 103 mSurface = new Surface(mProducer, true); 104 ASSERT_TRUE(mSurface != nullptr); 105 } 106 107 // Connect to a producer in a 'correct' fashion. 108 void ConnectProducer() { 109 IGraphicBufferProducer::QueueBufferOutput output; 110 // Can connect the first time. 111 ASSERT_EQ(NO_ERROR, mProducer->connect(kDummyListener, kTestApi, 112 kTestControlledByApp, &output)); 113 } 114 115 // Dequeue a buffer in a 'correct' fashion. 116 // Precondition: Producer is connected. 117 void DequeueBuffer(int* outSlot) { 118 sp<Fence> fence; 119 ASSERT_NO_FATAL_FAILURE(DequeueBuffer(outSlot, &fence)); 120 } 121 122 void DequeueBuffer(int* outSlot, sp<Fence>* outFence) { 123 ASSERT_NE(nullptr, outSlot); 124 ASSERT_NE(nullptr, outFence); 125 126 int ret = mProducer->dequeueBuffer( 127 outSlot, outFence, kDefaultWidth, kDefaultHeight, kDefaultFormat, 128 kTestProducerUsageBits, nullptr, nullptr); 129 // BUFFER_NEEDS_REALLOCATION can be either on or off. 130 ASSERT_EQ(0, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION & ret); 131 132 // Slot number should be in boundary. 133 ASSERT_LE(0, *outSlot); 134 ASSERT_GT(BufferQueueDefs::NUM_BUFFER_SLOTS, *outSlot); 135 } 136 137 // Create a generic "valid" input for queueBuffer 138 // -- uses the default buffer format, width, etc. 139 static IGraphicBufferProducer::QueueBufferInput CreateBufferInput() { 140 return QueueBufferInputBuilder().build(); 141 } 142 143 const sp<IProducerListener> kDummyListener{new DummyProducerListener}; 144 145 sp<BufferHubProducer> mProducer; 146 sp<Surface> mSurface; 147}; 148 149TEST_F(BufferHubQueueProducerTest, ConnectFirst_ReturnsError) { 150 IGraphicBufferProducer::QueueBufferOutput output; 151 152 // NULL output returns BAD_VALUE 153 EXPECT_EQ(BAD_VALUE, mProducer->connect(kDummyListener, kTestApi, 154 kTestControlledByApp, nullptr)); 155 156 // Invalid API returns bad value 157 EXPECT_EQ(BAD_VALUE, mProducer->connect(kDummyListener, kTestApiInvalid, 158 kTestControlledByApp, &output)); 159} 160 161TEST_F(BufferHubQueueProducerTest, ConnectAgain_ReturnsError) { 162 ASSERT_NO_FATAL_FAILURE(ConnectProducer()); 163 164 // Can't connect when there is already a producer connected. 165 IGraphicBufferProducer::QueueBufferOutput output; 166 EXPECT_EQ(BAD_VALUE, mProducer->connect(kDummyListener, kTestApi, 167 kTestControlledByApp, &output)); 168} 169 170TEST_F(BufferHubQueueProducerTest, Disconnect_Succeeds) { 171 ASSERT_NO_FATAL_FAILURE(ConnectProducer()); 172 173 ASSERT_EQ(NO_ERROR, mProducer->disconnect(kTestApi)); 174} 175 176TEST_F(BufferHubQueueProducerTest, Disconnect_ReturnsError) { 177 ASSERT_NO_FATAL_FAILURE(ConnectProducer()); 178 179 // Must disconnect with same API number 180 EXPECT_EQ(BAD_VALUE, mProducer->disconnect(kTestApiOther)); 181 // API must not be out of range 182 EXPECT_EQ(BAD_VALUE, mProducer->disconnect(kTestApiInvalid)); 183} 184 185TEST_F(BufferHubQueueProducerTest, Query_Succeeds) { 186 ASSERT_NO_FATAL_FAILURE(ConnectProducer()); 187 188 int32_t value = -1; 189 EXPECT_EQ(NO_ERROR, mProducer->query(NATIVE_WINDOW_WIDTH, &value)); 190 EXPECT_EQ(kDefaultWidth, static_cast<uint32_t>(value)); 191 192 EXPECT_EQ(NO_ERROR, mProducer->query(NATIVE_WINDOW_HEIGHT, &value)); 193 EXPECT_EQ(kDefaultHeight, static_cast<uint32_t>(value)); 194 195 EXPECT_EQ(NO_ERROR, mProducer->query(NATIVE_WINDOW_FORMAT, &value)); 196 EXPECT_EQ(kDefaultFormat, value); 197 198 EXPECT_EQ(NO_ERROR, 199 mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &value)); 200 EXPECT_LE(0, value); 201 EXPECT_GE(BufferQueueDefs::NUM_BUFFER_SLOTS, value); 202 203 EXPECT_EQ(NO_ERROR, 204 mProducer->query(NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &value)); 205 EXPECT_FALSE(value); // Can't run behind when we haven't touched the queue 206 207 EXPECT_EQ(NO_ERROR, 208 mProducer->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &value)); 209 EXPECT_EQ(kDefaultConsumerUsageBits, value); 210} 211 212TEST_F(BufferHubQueueProducerTest, Query_ReturnsError) { 213 ASSERT_NO_FATAL_FAILURE(ConnectProducer()); 214 215 // One past the end of the last 'query' enum value. Update this if we add more 216 // enums. 217 const int NATIVE_WINDOW_QUERY_LAST_OFF_BY_ONE = NATIVE_WINDOW_BUFFER_AGE + 1; 218 219 int value; 220 // What was out of range 221 EXPECT_EQ(BAD_VALUE, mProducer->query(/*what*/ -1, &value)); 222 EXPECT_EQ(BAD_VALUE, mProducer->query(/*what*/ 0xDEADBEEF, &value)); 223 EXPECT_EQ(BAD_VALUE, 224 mProducer->query(NATIVE_WINDOW_QUERY_LAST_OFF_BY_ONE, &value)); 225 226 // Some enums from window.h are 'invalid' 227 EXPECT_EQ(BAD_VALUE, 228 mProducer->query(NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER, &value)); 229 EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_CONCRETE_TYPE, &value)); 230 EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_DEFAULT_WIDTH, &value)); 231 EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_DEFAULT_HEIGHT, &value)); 232 EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_TRANSFORM_HINT, &value)); 233 234 // Value was NULL 235 EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_FORMAT, /*value*/ NULL)); 236} 237 238TEST_F(BufferHubQueueProducerTest, Queue_Succeeds) { 239 int slot = -1; 240 241 ASSERT_NO_FATAL_FAILURE(ConnectProducer()); 242 ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot)); 243 244 // Request the buffer (pre-requisite for queueing) 245 sp<GraphicBuffer> buffer; 246 ASSERT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer)); 247 248 // A generic "valid" input 249 IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput(); 250 IGraphicBufferProducer::QueueBufferOutput output; 251 252 // Queue the buffer back into the BQ 253 ASSERT_EQ(NO_ERROR, mProducer->queueBuffer(slot, input, &output)); 254 255 EXPECT_EQ(kDefaultWidth, output.width); 256 EXPECT_EQ(kDefaultHeight, output.height); 257 EXPECT_EQ(kDefaultTransformHint, output.transformHint); 258 259 // BufferHubQueue delivers buffers to consumer immediately. 260 EXPECT_EQ(0u, output.numPendingBuffers); 261 262 // Note that BufferHubQueue doesn't support nextFrameNumber as it seems to 263 // be a SurfaceFlinger specific optimization. 264 EXPECT_EQ(0u, output.nextFrameNumber); 265 266 // Buffer was not in the dequeued state 267 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output)); 268} 269 270// Test invalid slot number 271TEST_F(BufferHubQueueProducerTest, QueueInvalidSlot_ReturnsError) { 272 ASSERT_NO_FATAL_FAILURE(ConnectProducer()); 273 274 // A generic "valid" input 275 IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput(); 276 IGraphicBufferProducer::QueueBufferOutput output; 277 278 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(/*slot*/ -1, input, &output)); 279 EXPECT_EQ(BAD_VALUE, 280 mProducer->queueBuffer(/*slot*/ 0xDEADBEEF, input, &output)); 281 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(BufferQueueDefs::NUM_BUFFER_SLOTS, 282 input, &output)); 283} 284 285// Slot was not in the dequeued state (all slots start out in Free state) 286TEST_F(BufferHubQueueProducerTest, QueueNotDequeued_ReturnsError) { 287 ASSERT_NO_FATAL_FAILURE(ConnectProducer()); 288 289 IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput(); 290 IGraphicBufferProducer::QueueBufferOutput output; 291 292 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(/*slot*/ 0, input, &output)); 293} 294 295// Slot was enqueued without requesting a buffer 296TEST_F(BufferHubQueueProducerTest, QueueNotRequested_ReturnsError) { 297 int slot = -1; 298 299 ASSERT_NO_FATAL_FAILURE(ConnectProducer()); 300 ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot)); 301 302 IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput(); 303 IGraphicBufferProducer::QueueBufferOutput output; 304 305 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output)); 306} 307 308// Test when fence was NULL 309TEST_F(BufferHubQueueProducerTest, QueueNoFence_ReturnsError) { 310 int slot = -1; 311 312 ASSERT_NO_FATAL_FAILURE(ConnectProducer()); 313 ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot)); 314 315 sp<GraphicBuffer> buffer; 316 ASSERT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer)); 317 318 sp<Fence> nullFence = NULL; 319 320 IGraphicBufferProducer::QueueBufferInput input = 321 QueueBufferInputBuilder().setFence(nullFence).build(); 322 IGraphicBufferProducer::QueueBufferOutput output; 323 324 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output)); 325} 326 327// Test scaling mode was invalid 328TEST_F(BufferHubQueueProducerTest, QueueTestInvalidScalingMode_ReturnsError) { 329 int slot = -1; 330 331 ASSERT_NO_FATAL_FAILURE(ConnectProducer()); 332 ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot)); 333 334 sp<GraphicBuffer> buffer; 335 ASSERT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer)); 336 337 IGraphicBufferProducer::QueueBufferInput input = 338 QueueBufferInputBuilder().setScalingMode(-1).build(); 339 IGraphicBufferProducer::QueueBufferOutput output; 340 341 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output)); 342 343 input = QueueBufferInputBuilder().setScalingMode(0xDEADBEEF).build(); 344 345 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output)); 346} 347 348// Test crop rect is out of bounds of the buffer dimensions 349TEST_F(BufferHubQueueProducerTest, QueueCropOutOfBounds_ReturnsError) { 350 int slot = -1; 351 352 ASSERT_NO_FATAL_FAILURE(ConnectProducer()); 353 ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot)); 354 355 sp<GraphicBuffer> buffer; 356 ASSERT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer)); 357 358 IGraphicBufferProducer::QueueBufferInput input = 359 QueueBufferInputBuilder() 360 .setCrop(Rect(kDefaultWidth + 1, kDefaultHeight + 1)) 361 .build(); 362 IGraphicBufferProducer::QueueBufferOutput output; 363 364 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output)); 365} 366 367TEST_F(BufferHubQueueProducerTest, CancelBuffer_Succeeds) { 368 int slot = -1; 369 sp<Fence> fence; 370 371 ASSERT_NO_FATAL_FAILURE(ConnectProducer()); 372 ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot, &fence)); 373 374 // Should be able to cancel buffer after a dequeue. 375 EXPECT_EQ(NO_ERROR, mProducer->cancelBuffer(slot, fence)); 376} 377 378TEST_F(BufferHubQueueProducerTest, SetMaxDequeuedBufferCount_Succeeds) { 379 return; 380 ASSERT_NO_FATAL_FAILURE(ConnectProducer()); 381 382 int minUndequeuedBuffers; 383 ASSERT_EQ(NO_ERROR, mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, 384 &minUndequeuedBuffers)); 385 386 const int minBuffers = 1; 387 const int maxBuffers = 388 BufferQueueDefs::NUM_BUFFER_SLOTS - minUndequeuedBuffers; 389 390 ASSERT_EQ(NO_ERROR, mProducer->setAsyncMode(false)) 391 << "async mode: " << false; 392 ASSERT_EQ(NO_ERROR, mProducer->setMaxDequeuedBufferCount(minBuffers)) 393 << "bufferCount: " << minBuffers; 394 395 // Should now be able to dequeue up to minBuffers times 396 // Should now be able to dequeue up to maxBuffers times 397 int slot = -1; 398 for (int i = 0; i < minBuffers; ++i) { 399 ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot)); 400 } 401 402 ASSERT_EQ(NO_ERROR, mProducer->setMaxDequeuedBufferCount(maxBuffers)); 403 404 // queue the first buffer to enable max dequeued buffer count checking 405 IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput(); 406 IGraphicBufferProducer::QueueBufferOutput output; 407 sp<GraphicBuffer> buffer; 408 ASSERT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer)); 409 ASSERT_EQ(NO_ERROR, mProducer->queueBuffer(slot, input, &output)); 410 411 sp<Fence> fence; 412 for (int i = 0; i < maxBuffers; ++i) { 413 ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot, &fence)); 414 } 415 416 // Cancel a buffer, so we can decrease the buffer count 417 ASSERT_EQ(NO_ERROR, mProducer->cancelBuffer(slot, fence)); 418 419 // Should now be able to decrease the max dequeued count by 1 420 ASSERT_EQ(NO_ERROR, mProducer->setMaxDequeuedBufferCount(maxBuffers - 1)); 421} 422 423TEST_F(BufferHubQueueProducerTest, SetMaxDequeuedBufferCount_Fails) { 424 ASSERT_NO_FATAL_FAILURE(ConnectProducer()); 425 426 int minUndequeuedBuffers; 427 ASSERT_EQ(NO_ERROR, mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, 428 &minUndequeuedBuffers)); 429 430 const int minBuffers = 1; 431 const int maxBuffers = 432 BufferQueueDefs::NUM_BUFFER_SLOTS - minUndequeuedBuffers; 433 434 ASSERT_EQ(NO_ERROR, mProducer->setAsyncMode(false)) 435 << "async mode: " << false; 436 // Buffer count was out of range 437 EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(0)) 438 << "bufferCount: " << 0; 439 EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(maxBuffers + 1)) 440 << "bufferCount: " << maxBuffers + 1; 441 442 // Set max dequeue count to 2 443 ASSERT_EQ(NO_ERROR, mProducer->setMaxDequeuedBufferCount(2)); 444 // Dequeue 2 buffers 445 int slot = -1; 446 sp<Fence> fence; 447 for (int i = 0; i < 2; i++) { 448 ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION & 449 (mProducer->dequeueBuffer(&slot, &fence, kDefaultWidth, 450 kDefaultHeight, kDefaultFormat, 451 kTestProducerUsageBits, 452 nullptr, nullptr))) 453 << "slot: " << slot; 454 } 455 456 // Client has too many buffers dequeued 457 EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(1)) 458 << "bufferCount: " << minBuffers; 459} 460 461TEST_F(BufferHubQueueProducerTest, 462 DisconnectedProducerReturnsError_dequeueBuffer) { 463 int slot = -1; 464 sp<Fence> fence; 465 466 ASSERT_EQ(NO_INIT, mProducer->dequeueBuffer(&slot, &fence, kDefaultWidth, 467 kDefaultHeight, kDefaultFormat, 468 kTestProducerUsageBits, 469 nullptr, nullptr)); 470} 471 472TEST_F(BufferHubQueueProducerTest, 473 DisconnectedProducerReturnsError_requestBuffer) { 474 int slot = -1; 475 sp<GraphicBuffer> buffer; 476 477 ASSERT_NO_FATAL_FAILURE(ConnectProducer()); 478 ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot)); 479 480 // Shouldn't be able to request buffer after disconnect. 481 ASSERT_EQ(NO_ERROR, mProducer->disconnect(kTestApi)); 482 ASSERT_EQ(NO_INIT, mProducer->requestBuffer(slot, &buffer)); 483} 484 485TEST_F(BufferHubQueueProducerTest, 486 DisconnectedProducerReturnsError_queueBuffer) { 487 int slot = -1; 488 sp<GraphicBuffer> buffer; 489 490 ASSERT_NO_FATAL_FAILURE(ConnectProducer()); 491 ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot)); 492 ASSERT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer)); 493 494 // A generic "valid" input 495 IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput(); 496 IGraphicBufferProducer::QueueBufferOutput output; 497 498 // Shouldn't be able to queue buffer after disconnect. 499 ASSERT_EQ(NO_ERROR, mProducer->disconnect(kTestApi)); 500 ASSERT_EQ(NO_INIT, mProducer->queueBuffer(slot, input, &output)); 501} 502 503TEST_F(BufferHubQueueProducerTest, 504 DisconnectedProducerReturnsError_cancelBuffer) { 505 int slot = -1; 506 sp<GraphicBuffer> buffer; 507 508 ASSERT_NO_FATAL_FAILURE(ConnectProducer()); 509 ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot)); 510 ASSERT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer)); 511 512 // Shouldn't be able to cancel buffer after disconnect. 513 ASSERT_EQ(NO_ERROR, mProducer->disconnect(kTestApi)); 514 ASSERT_EQ(NO_INIT, mProducer->cancelBuffer(slot, Fence::NO_FENCE)); 515} 516 517TEST_F(BufferHubQueueProducerTest, ConnectDisconnectReconnect) { 518 int slot = -1; 519 sp<GraphicBuffer> buffer; 520 IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput(); 521 IGraphicBufferProducer::QueueBufferOutput output; 522 523 EXPECT_NO_FATAL_FAILURE(ConnectProducer()); 524 525 constexpr int maxDequeuedBuffers = 1; 526 int minUndequeuedBuffers; 527 EXPECT_EQ(NO_ERROR, mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, 528 &minUndequeuedBuffers)); 529 EXPECT_EQ(NO_ERROR, mProducer->setAsyncMode(false)); 530 EXPECT_EQ(NO_ERROR, mProducer->setMaxDequeuedBufferCount(maxDequeuedBuffers)); 531 532 int maxCapacity = maxDequeuedBuffers + minUndequeuedBuffers; 533 534 // Dequeue, request, and queue all buffers. 535 for (int i = 0; i < maxCapacity; i++) { 536 EXPECT_NO_FATAL_FAILURE(DequeueBuffer(&slot)); 537 EXPECT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer)); 538 EXPECT_EQ(NO_ERROR, mProducer->queueBuffer(slot, input, &output)); 539 } 540 541 // Disconnect then reconnect. 542 EXPECT_EQ(NO_ERROR, mProducer->disconnect(kTestApi)); 543 EXPECT_NO_FATAL_FAILURE(ConnectProducer()); 544 545 // Dequeue, request, and queue all buffers. 546 for (int i = 0; i < maxCapacity; i++) { 547 EXPECT_NO_FATAL_FAILURE(DequeueBuffer(&slot)); 548 EXPECT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer)); 549 EXPECT_EQ(NO_ERROR, mProducer->queueBuffer(slot, input, &output)); 550 } 551 552 EXPECT_EQ(NO_ERROR, mProducer->disconnect(kTestApi)); 553} 554 555TEST_F(BufferHubQueueProducerTest, TakeAsParcelable) { 556 // Connected producer cannot be taken out as a parcelable. 557 EXPECT_NO_FATAL_FAILURE(ConnectProducer()); 558 ProducerQueueParcelable producer_parcelable; 559 EXPECT_EQ(mProducer->TakeAsParcelable(&producer_parcelable), BAD_VALUE); 560 561 // Create a valid dummy producer parcelable. 562 auto dummy_channel_parcelable = 563 std::make_unique<pdx::default_transport::ChannelParcelable>( 564 LocalHandle(0), LocalHandle(0), LocalHandle(0)); 565 EXPECT_TRUE(dummy_channel_parcelable->IsValid()); 566 ProducerQueueParcelable dummy_producer_parcelable( 567 std::move(dummy_channel_parcelable)); 568 EXPECT_TRUE(dummy_producer_parcelable.IsValid()); 569 570 // Disconnect producer can be taken out, but only to an invalid parcelable. 571 ASSERT_EQ(mProducer->disconnect(kTestApi), NO_ERROR); 572 EXPECT_EQ(mProducer->TakeAsParcelable(&dummy_producer_parcelable), BAD_VALUE); 573 EXPECT_FALSE(producer_parcelable.IsValid()); 574 EXPECT_EQ(mProducer->TakeAsParcelable(&producer_parcelable), NO_ERROR); 575 EXPECT_TRUE(producer_parcelable.IsValid()); 576 577 // Should still be able to query buffer dimension after disconnect. 578 int32_t value = -1; 579 EXPECT_EQ(NO_ERROR, mProducer->query(NATIVE_WINDOW_WIDTH, &value)); 580 EXPECT_EQ(static_cast<uint32_t>(value), kDefaultWidth); 581 582 EXPECT_EQ(mProducer->query(NATIVE_WINDOW_HEIGHT, &value), NO_ERROR); 583 EXPECT_EQ(static_cast<uint32_t>(value), kDefaultHeight); 584 585 EXPECT_EQ(mProducer->query(NATIVE_WINDOW_FORMAT, &value), NO_ERROR); 586 EXPECT_EQ(value, kDefaultFormat); 587 588 // But connect to API will fail. 589 IGraphicBufferProducer::QueueBufferOutput output; 590 EXPECT_EQ(mProducer->connect(kDummyListener, kTestApi, kTestControlledByApp, 591 &output), 592 BAD_VALUE); 593 594 // Create a new producer from the parcelable and connect to kTestApi should 595 // succeed. 596 sp<BufferHubProducer> new_producer = 597 BufferHubProducer::Create(std::move(producer_parcelable)); 598 ASSERT_TRUE(new_producer != nullptr); 599 EXPECT_EQ(new_producer->connect(kDummyListener, kTestApi, 600 kTestControlledByApp, &output), 601 NO_ERROR); 602} 603 604} // namespace 605 606} // namespace dvr 607} // namespace android 608