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