Home | History | Annotate | Download | only in tests
      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 
      9 namespace android {
     10 namespace dvr {
     11 
     12 using pdx::LocalHandle;
     13 
     14 namespace {
     15 
     16 // Default dimensions before setDefaultBufferSize is called by the consumer.
     17 constexpr uint32_t kDefaultWidth = 1;
     18 constexpr uint32_t kDefaultHeight = 1;
     19 
     20 // Default format before setDefaultBufferFormat is called by the consumer.
     21 constexpr PixelFormat kDefaultFormat = HAL_PIXEL_FORMAT_RGBA_8888;
     22 constexpr int kDefaultConsumerUsageBits = 0;
     23 
     24 // Default transform hint before setTransformHint is called by the consumer.
     25 constexpr uint32_t kDefaultTransformHint = 0;
     26 
     27 constexpr int kTestApi = NATIVE_WINDOW_API_CPU;
     28 constexpr int kTestApiOther = NATIVE_WINDOW_API_EGL;
     29 constexpr int kTestApiInvalid = 0xDEADBEEF;
     30 constexpr int kTestProducerUsageBits = 0;
     31 constexpr bool kTestControlledByApp = true;
     32 
     33 // Builder pattern to slightly vary *almost* correct input
     34 // -- avoids copying and pasting
     35 struct 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.
     89 class 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(OK, 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 
    149 TEST_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 
    161 TEST_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 
    170 TEST_F(BufferHubQueueProducerTest, Disconnect_Succeeds) {
    171   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
    172 
    173   ASSERT_EQ(OK, mProducer->disconnect(kTestApi));
    174 }
    175 
    176 TEST_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 
    185 TEST_F(BufferHubQueueProducerTest, Query_Succeeds) {
    186   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
    187 
    188   int32_t value = -1;
    189   EXPECT_EQ(OK, mProducer->query(NATIVE_WINDOW_WIDTH, &value));
    190   EXPECT_EQ(kDefaultWidth, static_cast<uint32_t>(value));
    191 
    192   EXPECT_EQ(OK, mProducer->query(NATIVE_WINDOW_HEIGHT, &value));
    193   EXPECT_EQ(kDefaultHeight, static_cast<uint32_t>(value));
    194 
    195   EXPECT_EQ(OK, mProducer->query(NATIVE_WINDOW_FORMAT, &value));
    196   EXPECT_EQ(kDefaultFormat, value);
    197 
    198   EXPECT_EQ(OK, mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &value));
    199   EXPECT_LE(0, value);
    200   EXPECT_GE(BufferQueueDefs::NUM_BUFFER_SLOTS, value);
    201 
    202   EXPECT_EQ(OK,
    203             mProducer->query(NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &value));
    204   EXPECT_FALSE(value);  // Can't run behind when we haven't touched the queue
    205 
    206   EXPECT_EQ(OK, mProducer->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &value));
    207   EXPECT_EQ(kDefaultConsumerUsageBits, value);
    208 }
    209 
    210 TEST_F(BufferHubQueueProducerTest, Query_ReturnsError) {
    211   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
    212 
    213   // One past the end of the last 'query' enum value. Update this if we add more
    214   // enums.
    215   const int NATIVE_WINDOW_QUERY_LAST_OFF_BY_ONE = NATIVE_WINDOW_BUFFER_AGE + 1;
    216 
    217   int value;
    218   // What was out of range
    219   EXPECT_EQ(BAD_VALUE, mProducer->query(/*what*/ -1, &value));
    220   EXPECT_EQ(BAD_VALUE, mProducer->query(/*what*/ 0xDEADBEEF, &value));
    221   EXPECT_EQ(BAD_VALUE,
    222             mProducer->query(NATIVE_WINDOW_QUERY_LAST_OFF_BY_ONE, &value));
    223 
    224   // Some enums from window.h are 'invalid'
    225   EXPECT_EQ(BAD_VALUE,
    226             mProducer->query(NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER, &value));
    227   EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_CONCRETE_TYPE, &value));
    228   EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_DEFAULT_WIDTH, &value));
    229   EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_DEFAULT_HEIGHT, &value));
    230   EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_TRANSFORM_HINT, &value));
    231 
    232   // Value was NULL
    233   EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_FORMAT, /*value*/ NULL));
    234 }
    235 
    236 TEST_F(BufferHubQueueProducerTest, Queue_Succeeds) {
    237   int slot = -1;
    238 
    239   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
    240   ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
    241 
    242   // Request the buffer (pre-requisite for queueing)
    243   sp<GraphicBuffer> buffer;
    244   ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
    245 
    246   // A generic "valid" input
    247   IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
    248   IGraphicBufferProducer::QueueBufferOutput output;
    249 
    250   // Queue the buffer back into the BQ
    251   ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
    252 
    253   EXPECT_EQ(kDefaultWidth, output.width);
    254   EXPECT_EQ(kDefaultHeight, output.height);
    255   EXPECT_EQ(kDefaultTransformHint, output.transformHint);
    256 
    257   // BufferHubQueue delivers buffers to consumer immediately.
    258   EXPECT_EQ(0u, output.numPendingBuffers);
    259 
    260   // Note that BufferHubQueue doesn't support nextFrameNumber as it seems to
    261   // be a SurfaceFlinger specific optimization.
    262   EXPECT_EQ(0u, output.nextFrameNumber);
    263 
    264   // Buffer was not in the dequeued state
    265   EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output));
    266 }
    267 
    268 // Test invalid slot number
    269 TEST_F(BufferHubQueueProducerTest, QueueInvalidSlot_ReturnsError) {
    270   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
    271 
    272   // A generic "valid" input
    273   IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
    274   IGraphicBufferProducer::QueueBufferOutput output;
    275 
    276   EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(/*slot*/ -1, input, &output));
    277   EXPECT_EQ(BAD_VALUE,
    278             mProducer->queueBuffer(/*slot*/ 0xDEADBEEF, input, &output));
    279   EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(BufferQueueDefs::NUM_BUFFER_SLOTS,
    280                                               input, &output));
    281 }
    282 
    283 // Slot was not in the dequeued state (all slots start out in Free state)
    284 TEST_F(BufferHubQueueProducerTest, QueueNotDequeued_ReturnsError) {
    285   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
    286 
    287   IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
    288   IGraphicBufferProducer::QueueBufferOutput output;
    289 
    290   EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(/*slot*/ 0, input, &output));
    291 }
    292 
    293 // Slot was enqueued without requesting a buffer
    294 TEST_F(BufferHubQueueProducerTest, QueueNotRequested_ReturnsError) {
    295   int slot = -1;
    296 
    297   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
    298   ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
    299 
    300   IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
    301   IGraphicBufferProducer::QueueBufferOutput output;
    302 
    303   EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output));
    304 }
    305 
    306 // Test when fence was NULL
    307 TEST_F(BufferHubQueueProducerTest, QueueNoFence_ReturnsError) {
    308   int slot = -1;
    309 
    310   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
    311   ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
    312 
    313   sp<GraphicBuffer> buffer;
    314   ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
    315 
    316   sp<Fence> nullFence = NULL;
    317 
    318   IGraphicBufferProducer::QueueBufferInput input =
    319       QueueBufferInputBuilder().setFence(nullFence).build();
    320   IGraphicBufferProducer::QueueBufferOutput output;
    321 
    322   EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output));
    323 }
    324 
    325 // Test scaling mode was invalid
    326 TEST_F(BufferHubQueueProducerTest, QueueTestInvalidScalingMode_ReturnsError) {
    327   int slot = -1;
    328 
    329   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
    330   ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
    331 
    332   sp<GraphicBuffer> buffer;
    333   ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
    334 
    335   IGraphicBufferProducer::QueueBufferInput input =
    336       QueueBufferInputBuilder().setScalingMode(-1).build();
    337   IGraphicBufferProducer::QueueBufferOutput output;
    338 
    339   EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output));
    340 
    341   input = QueueBufferInputBuilder().setScalingMode(0xDEADBEEF).build();
    342 
    343   EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output));
    344 }
    345 
    346 // Test crop rect is out of bounds of the buffer dimensions
    347 TEST_F(BufferHubQueueProducerTest, QueueCropOutOfBounds_ReturnsError) {
    348   int slot = -1;
    349 
    350   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
    351   ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
    352 
    353   sp<GraphicBuffer> buffer;
    354   ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
    355 
    356   IGraphicBufferProducer::QueueBufferInput input =
    357       QueueBufferInputBuilder()
    358           .setCrop(Rect(kDefaultWidth + 1, kDefaultHeight + 1))
    359           .build();
    360   IGraphicBufferProducer::QueueBufferOutput output;
    361 
    362   EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output));
    363 }
    364 
    365 TEST_F(BufferHubQueueProducerTest, CancelBuffer_Succeeds) {
    366   int slot = -1;
    367   sp<Fence> fence;
    368 
    369   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
    370   ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot, &fence));
    371 
    372   // Should be able to cancel buffer after a dequeue.
    373   EXPECT_EQ(OK, mProducer->cancelBuffer(slot, fence));
    374 }
    375 
    376 TEST_F(BufferHubQueueProducerTest, SetMaxDequeuedBufferCount_Succeeds) {
    377   return;
    378   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
    379 
    380   int minUndequeuedBuffers;
    381   ASSERT_EQ(OK, mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
    382                                  &minUndequeuedBuffers));
    383 
    384   const int minBuffers = 1;
    385   const int maxBuffers =
    386       BufferQueueDefs::NUM_BUFFER_SLOTS - minUndequeuedBuffers;
    387 
    388   ASSERT_EQ(OK, mProducer->setAsyncMode(false)) << "async mode: " << false;
    389   ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(minBuffers))
    390       << "bufferCount: " << minBuffers;
    391 
    392   // Should now be able to dequeue up to minBuffers times
    393   // Should now be able to dequeue up to maxBuffers times
    394   int slot = -1;
    395   for (int i = 0; i < minBuffers; ++i) {
    396     ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
    397   }
    398 
    399   ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(maxBuffers));
    400 
    401   // queue the first buffer to enable max dequeued buffer count checking
    402   IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
    403   IGraphicBufferProducer::QueueBufferOutput output;
    404   sp<GraphicBuffer> buffer;
    405   ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
    406   ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
    407 
    408   sp<Fence> fence;
    409   for (int i = 0; i < maxBuffers; ++i) {
    410     ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot, &fence));
    411   }
    412 
    413   // Cancel a buffer, so we can decrease the buffer count
    414   ASSERT_EQ(OK, mProducer->cancelBuffer(slot, fence));
    415 
    416   // Should now be able to decrease the max dequeued count by 1
    417   ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(maxBuffers - 1));
    418 }
    419 
    420 TEST_F(BufferHubQueueProducerTest, SetMaxDequeuedBufferCount_Fails) {
    421   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
    422 
    423   int minUndequeuedBuffers;
    424   ASSERT_EQ(OK, mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
    425                                  &minUndequeuedBuffers));
    426 
    427   const int minBuffers = 1;
    428   const int maxBuffers =
    429       BufferQueueDefs::NUM_BUFFER_SLOTS - minUndequeuedBuffers;
    430 
    431   ASSERT_EQ(OK, mProducer->setAsyncMode(false)) << "async mode: " << false;
    432   // Buffer count was out of range
    433   EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(0))
    434       << "bufferCount: " << 0;
    435   EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(maxBuffers + 1))
    436       << "bufferCount: " << maxBuffers + 1;
    437 
    438   // Set max dequeue count to 2
    439   ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(2));
    440   // Dequeue 2 buffers
    441   int slot = -1;
    442   sp<Fence> fence;
    443   for (int i = 0; i < 2; i++) {
    444     ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
    445                       (mProducer->dequeueBuffer(&slot, &fence, kDefaultWidth,
    446                                                 kDefaultHeight, kDefaultFormat,
    447                                                 kTestProducerUsageBits,
    448                                                 nullptr, nullptr)))
    449         << "slot: " << slot;
    450   }
    451 
    452   // Client has too many buffers dequeued
    453   EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(1))
    454       << "bufferCount: " << minBuffers;
    455 }
    456 
    457 TEST_F(BufferHubQueueProducerTest,
    458        DisconnectedProducerReturnsError_dequeueBuffer) {
    459   int slot = -1;
    460   sp<Fence> fence;
    461 
    462   ASSERT_EQ(NO_INIT, mProducer->dequeueBuffer(&slot, &fence, kDefaultWidth,
    463                                               kDefaultHeight, kDefaultFormat,
    464                                               kTestProducerUsageBits,
    465                                               nullptr, nullptr));
    466 }
    467 
    468 TEST_F(BufferHubQueueProducerTest,
    469        DisconnectedProducerReturnsError_requestBuffer) {
    470   int slot = -1;
    471   sp<GraphicBuffer> buffer;
    472 
    473   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
    474   ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
    475 
    476   // Shouldn't be able to request buffer after disconnect.
    477   ASSERT_EQ(OK, mProducer->disconnect(kTestApi));
    478   ASSERT_EQ(NO_INIT, mProducer->requestBuffer(slot, &buffer));
    479 }
    480 
    481 TEST_F(BufferHubQueueProducerTest,
    482        DisconnectedProducerReturnsError_queueBuffer) {
    483   int slot = -1;
    484   sp<GraphicBuffer> buffer;
    485 
    486   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
    487   ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
    488   ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
    489 
    490   // A generic "valid" input
    491   IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
    492   IGraphicBufferProducer::QueueBufferOutput output;
    493 
    494   // Shouldn't be able to queue buffer after disconnect.
    495   ASSERT_EQ(OK, mProducer->disconnect(kTestApi));
    496   ASSERT_EQ(NO_INIT, mProducer->queueBuffer(slot, input, &output));
    497 }
    498 
    499 TEST_F(BufferHubQueueProducerTest,
    500        DisconnectedProducerReturnsError_cancelBuffer) {
    501   int slot = -1;
    502   sp<GraphicBuffer> buffer;
    503 
    504   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
    505   ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
    506   ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
    507 
    508   // Shouldn't be able to cancel buffer after disconnect.
    509   ASSERT_EQ(OK, mProducer->disconnect(kTestApi));
    510   ASSERT_EQ(NO_INIT, mProducer->cancelBuffer(slot, Fence::NO_FENCE));
    511 }
    512 
    513 TEST_F(BufferHubQueueProducerTest, ConnectDisconnectReconnect) {
    514   int slot = -1;
    515   sp<GraphicBuffer> buffer;
    516   IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
    517   IGraphicBufferProducer::QueueBufferOutput output;
    518 
    519   EXPECT_NO_FATAL_FAILURE(ConnectProducer());
    520 
    521   constexpr int maxDequeuedBuffers = 1;
    522   int minUndequeuedBuffers;
    523   EXPECT_EQ(OK, mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
    524                                  &minUndequeuedBuffers));
    525   EXPECT_EQ(OK, mProducer->setAsyncMode(false));
    526   EXPECT_EQ(OK, mProducer->setMaxDequeuedBufferCount(maxDequeuedBuffers));
    527 
    528   int maxCapacity = maxDequeuedBuffers + minUndequeuedBuffers;
    529 
    530   // Dequeue, request, and queue all buffers.
    531   for (int i = 0; i < maxCapacity; i++) {
    532     EXPECT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
    533     EXPECT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
    534     EXPECT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
    535   }
    536 
    537   // Disconnect then reconnect.
    538   EXPECT_EQ(OK, mProducer->disconnect(kTestApi));
    539   EXPECT_NO_FATAL_FAILURE(ConnectProducer());
    540 
    541   // Dequeue, request, and queue all buffers.
    542   for (int i = 0; i < maxCapacity; i++) {
    543     EXPECT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
    544     EXPECT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
    545     EXPECT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
    546   }
    547 
    548   EXPECT_EQ(OK, mProducer->disconnect(kTestApi));
    549 }
    550 
    551 TEST_F(BufferHubQueueProducerTest, TakeAsParcelable) {
    552   // Connected producer cannot be taken out as a parcelable.
    553   EXPECT_NO_FATAL_FAILURE(ConnectProducer());
    554   ProducerQueueParcelable producer_parcelable;
    555   EXPECT_EQ(mProducer->TakeAsParcelable(&producer_parcelable), BAD_VALUE);
    556 
    557   // Create a valid dummy producer parcelable.
    558   auto dummy_channel_parcelable =
    559       std::make_unique<pdx::default_transport::ChannelParcelable>(
    560           LocalHandle(0), LocalHandle(0), LocalHandle(0));
    561   EXPECT_TRUE(dummy_channel_parcelable->IsValid());
    562   ProducerQueueParcelable dummy_producer_parcelable(
    563       std::move(dummy_channel_parcelable));
    564   EXPECT_TRUE(dummy_producer_parcelable.IsValid());
    565 
    566   // Disconnect producer can be taken out, but only to an invalid parcelable.
    567   ASSERT_EQ(mProducer->disconnect(kTestApi), OK);
    568   EXPECT_EQ(mProducer->TakeAsParcelable(&dummy_producer_parcelable), BAD_VALUE);
    569   EXPECT_FALSE(producer_parcelable.IsValid());
    570   EXPECT_EQ(mProducer->TakeAsParcelable(&producer_parcelable), OK);
    571   EXPECT_TRUE(producer_parcelable.IsValid());
    572 
    573   // Should still be able to query buffer dimension after disconnect.
    574   int32_t value = -1;
    575   EXPECT_EQ(OK, mProducer->query(NATIVE_WINDOW_WIDTH, &value));
    576   EXPECT_EQ(static_cast<uint32_t>(value), kDefaultWidth);
    577 
    578   EXPECT_EQ(mProducer->query(NATIVE_WINDOW_HEIGHT, &value), OK);
    579   EXPECT_EQ(static_cast<uint32_t>(value), kDefaultHeight);
    580 
    581   EXPECT_EQ(mProducer->query(NATIVE_WINDOW_FORMAT, &value), OK);
    582   EXPECT_EQ(value, kDefaultFormat);
    583 
    584   // But connect to API will fail.
    585   IGraphicBufferProducer::QueueBufferOutput output;
    586   EXPECT_EQ(mProducer->connect(kDummyListener, kTestApi, kTestControlledByApp,
    587                                &output),
    588             BAD_VALUE);
    589 
    590   // Create a new producer from the parcelable and connect to kTestApi should
    591   // succeed.
    592   sp<BufferHubProducer> new_producer =
    593       BufferHubProducer::Create(std::move(producer_parcelable));
    594   ASSERT_TRUE(new_producer != nullptr);
    595   EXPECT_EQ(new_producer->connect(kDummyListener, kTestApi,
    596                                   kTestControlledByApp, &output),
    597             OK);
    598 }
    599 
    600 }  // namespace
    601 
    602 }  // namespace dvr
    603 }  // namespace android
    604