Home | History | Annotate | Download | only in tests
      1 #include <android/log.h>
      2 #include <android/native_window.h>
      3 #include <dvr/dvr_api.h>
      4 #include <dvr/dvr_buffer_queue.h>
      5 
      6 #include <gtest/gtest.h>
      7 
      8 #include <array>
      9 #include <unordered_map>
     10 
     11 #include "dvr_api_test.h"
     12 
     13 #define LOG_TAG "dvr_buffer_queue-test"
     14 
     15 #ifndef ALOGD
     16 #define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
     17 #endif
     18 
     19 #ifndef ALOGD_IF
     20 #define ALOGD_IF(cond, ...) \
     21   ((__predict_false(cond)) ? ((void)ALOGD(__VA_ARGS__)) : (void)0)
     22 #endif
     23 
     24 namespace {
     25 
     26 static constexpr uint32_t kBufferWidth = 100;
     27 static constexpr uint32_t kBufferHeight = 1;
     28 static constexpr uint32_t kLayerCount = 1;
     29 static constexpr uint32_t kBufferFormat = AHARDWAREBUFFER_FORMAT_BLOB;
     30 static constexpr uint64_t kBufferUsage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN;
     31 static constexpr size_t kQueueCapacity = 3;
     32 
     33 class DvrBufferQueueTest : public DvrApiTest {
     34  public:
     35   static void BufferAvailableCallback(void* context) {
     36     DvrBufferQueueTest* thiz = static_cast<DvrBufferQueueTest*>(context);
     37     thiz->HandleBufferAvailable();
     38   }
     39 
     40   static void BufferRemovedCallback(DvrReadBuffer* buffer, void* context) {
     41     DvrBufferQueueTest* thiz = static_cast<DvrBufferQueueTest*>(context);
     42     thiz->HandleBufferRemoved(buffer);
     43   }
     44 
     45  protected:
     46   void TearDown() override {
     47     if (write_queue_ != nullptr) {
     48       api_.WriteBufferQueueDestroy(write_queue_);
     49       write_queue_ = nullptr;
     50     }
     51     DvrApiTest::TearDown();
     52   }
     53 
     54   void HandleBufferAvailable() {
     55     buffer_available_count_ += 1;
     56     ALOGD_IF(TRACE, "Buffer avaiable, count=%d", buffer_available_count_);
     57   }
     58 
     59   void HandleBufferRemoved(DvrReadBuffer* buffer) {
     60     buffer_removed_count_ += 1;
     61     ALOGD_IF(TRACE, "Buffer removed, buffer=%p, count=%d", buffer,
     62              buffer_removed_count_);
     63   }
     64 
     65   DvrWriteBufferQueue* write_queue_{nullptr};
     66   int buffer_available_count_{0};
     67   int buffer_removed_count_{0};
     68 };
     69 
     70 TEST_F(DvrBufferQueueTest, WriteQueueCreateDestroy) {
     71   int ret = api_.WriteBufferQueueCreate(
     72       kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
     73       /*capacity=*/0, sizeof(DvrNativeBufferMetadata), &write_queue_);
     74   ASSERT_EQ(0, ret);
     75 
     76   api_.WriteBufferQueueDestroy(write_queue_);
     77   write_queue_ = nullptr;
     78 }
     79 
     80 TEST_F(DvrBufferQueueTest, WriteQueueGetCapacity) {
     81   int ret = api_.WriteBufferQueueCreate(
     82       kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
     83       kQueueCapacity, sizeof(DvrNativeBufferMetadata), &write_queue_);
     84   ASSERT_EQ(0, ret);
     85 
     86   size_t capacity = api_.WriteBufferQueueGetCapacity(write_queue_);
     87 
     88   ALOGD_IF(TRACE, "TestWrite_QueueGetCapacity, capacity=%zu", capacity);
     89   ASSERT_EQ(kQueueCapacity, capacity);
     90 }
     91 
     92 TEST_F(DvrBufferQueueTest, CreateReadQueueFromWriteQueue) {
     93   int ret = api_.WriteBufferQueueCreate(
     94       kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
     95       /*capacity=*/0, sizeof(DvrNativeBufferMetadata), &write_queue_);
     96   ASSERT_EQ(0, ret);
     97 
     98   DvrReadBufferQueue* read_queue = nullptr;
     99   ret = api_.WriteBufferQueueCreateReadQueue(write_queue_, &read_queue);
    100 
    101   ASSERT_EQ(0, ret);
    102   ASSERT_NE(nullptr, read_queue);
    103 
    104   api_.ReadBufferQueueDestroy(read_queue);
    105 }
    106 
    107 TEST_F(DvrBufferQueueTest, CreateReadQueueFromReadQueue) {
    108   int ret = api_.WriteBufferQueueCreate(
    109       kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
    110       /*capacity=*/0, sizeof(DvrNativeBufferMetadata), &write_queue_);
    111   ASSERT_EQ(0, ret);
    112 
    113   DvrReadBufferQueue* read_queue1 = nullptr;
    114   DvrReadBufferQueue* read_queue2 = nullptr;
    115   ret = api_.WriteBufferQueueCreateReadQueue(write_queue_, &read_queue1);
    116 
    117   ASSERT_EQ(0, ret);
    118   ASSERT_NE(nullptr, read_queue1);
    119 
    120   ret = api_.ReadBufferQueueCreateReadQueue(read_queue1, &read_queue2);
    121   ASSERT_EQ(0, ret);
    122   ASSERT_NE(nullptr, read_queue2);
    123   ASSERT_NE(read_queue1, read_queue2);
    124 
    125   api_.ReadBufferQueueDestroy(read_queue1);
    126   api_.ReadBufferQueueDestroy(read_queue2);
    127 }
    128 
    129 TEST_F(DvrBufferQueueTest, GainBuffer) {
    130   int ret = api_.WriteBufferQueueCreate(
    131       kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
    132       kQueueCapacity, sizeof(DvrNativeBufferMetadata), &write_queue_);
    133   ASSERT_EQ(ret, 0);
    134 
    135   DvrWriteBuffer* wb = nullptr;
    136   EXPECT_FALSE(api_.WriteBufferIsValid(wb));
    137 
    138   DvrNativeBufferMetadata meta;
    139   int fence_fd = -1;
    140   ret = api_.WriteBufferQueueGainBuffer(write_queue_, /*timeout=*/0, &wb, &meta,
    141                                         &fence_fd);
    142   ASSERT_EQ(ret, 0);
    143   EXPECT_EQ(fence_fd, -1);
    144   EXPECT_NE(wb, nullptr);
    145   EXPECT_TRUE(api_.WriteBufferIsValid(wb));
    146 }
    147 
    148 TEST_F(DvrBufferQueueTest, AcquirePostGainRelease) {
    149   int ret = api_.WriteBufferQueueCreate(
    150       kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
    151       kQueueCapacity, sizeof(DvrNativeBufferMetadata), &write_queue_);
    152   ASSERT_EQ(ret, 0);
    153 
    154   DvrReadBufferQueue* read_queue = nullptr;
    155   DvrReadBuffer* rb = nullptr;
    156   DvrWriteBuffer* wb = nullptr;
    157   DvrNativeBufferMetadata meta1;
    158   DvrNativeBufferMetadata meta2;
    159   int fence_fd = -1;
    160 
    161   ret = api_.WriteBufferQueueCreateReadQueue(write_queue_, &read_queue);
    162 
    163   ASSERT_EQ(ret, 0);
    164   ASSERT_NE(read_queue, nullptr);
    165 
    166   api_.ReadBufferQueueSetBufferAvailableCallback(
    167       read_queue, &BufferAvailableCallback, this);
    168 
    169   // Gain buffer for writing.
    170   ret = api_.WriteBufferQueueGainBuffer(write_queue_, /*timeout=*/0, &wb,
    171                                         &meta1, &fence_fd);
    172   ASSERT_EQ(ret, 0);
    173   ASSERT_NE(wb, nullptr);
    174   ASSERT_TRUE(api_.WriteBufferIsValid(wb));
    175   ALOGD_IF(TRACE, "TestDequeuePostDequeueRelease, gain buffer %p, fence_fd=%d",
    176            wb, fence_fd);
    177   close(fence_fd);
    178 
    179   // Post buffer to the read_queue.
    180   meta1.timestamp = 42;
    181   ret = api_.WriteBufferQueuePostBuffer(write_queue_, wb, &meta1, /*fence=*/-1);
    182   ASSERT_EQ(ret, 0);
    183   ASSERT_FALSE(api_.WriteBufferIsValid(wb));
    184   wb = nullptr;
    185 
    186   // Acquire buffer for reading.
    187   ret = api_.ReadBufferQueueAcquireBuffer(read_queue, /*timeout=*/10, &rb,
    188                                           &meta2, &fence_fd);
    189   ASSERT_EQ(ret, 0);
    190   ASSERT_NE(rb, nullptr);
    191 
    192   // Dequeue is successfully, BufferAvailableCallback should be fired once.
    193   ASSERT_EQ(buffer_available_count_, 1);
    194   ASSERT_TRUE(api_.ReadBufferIsValid(rb));
    195 
    196   // Metadata should be passed along from producer to consumer properly.
    197   ASSERT_EQ(meta1.timestamp, meta2.timestamp);
    198 
    199   ALOGD_IF(TRACE,
    200            "TestDequeuePostDequeueRelease, acquire buffer %p, fence_fd=%d", rb,
    201            fence_fd);
    202   close(fence_fd);
    203 
    204   // Release buffer to the write_queue.
    205   ret = api_.ReadBufferQueueReleaseBuffer(read_queue, rb, &meta2,
    206                                           /*release_fence_fd=*/-1);
    207   ASSERT_EQ(ret, 0);
    208   ASSERT_FALSE(api_.ReadBufferIsValid(rb));
    209   rb = nullptr;
    210 
    211   // TODO(b/34387835) Currently buffer allocation has to happen after all queues
    212   // are initialized.
    213   size_t capacity = api_.ReadBufferQueueGetCapacity(read_queue);
    214 
    215   ALOGD_IF(TRACE, "TestDequeuePostDequeueRelease, capacity=%zu", capacity);
    216   ASSERT_EQ(kQueueCapacity, capacity);
    217 
    218   api_.ReadBufferQueueDestroy(read_queue);
    219 }
    220 
    221 TEST_F(DvrBufferQueueTest, GetANativeWindow) {
    222   int ret = api_.WriteBufferQueueCreate(
    223       kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
    224       /*capacity=*/0, /*user_metadata_size=*/0, &write_queue_);
    225   ASSERT_EQ(0, ret);
    226   ASSERT_NE(nullptr, write_queue_);
    227 
    228   ANativeWindow* window = nullptr;
    229   ret = api_.WriteBufferQueueGetANativeWindow(write_queue_, &window);
    230   ASSERT_EQ(0, ret);
    231   ASSERT_NE(nullptr, window);
    232 
    233   uint32_t width = ANativeWindow_getWidth(window);
    234   uint32_t height = ANativeWindow_getHeight(window);
    235   uint32_t format = ANativeWindow_getFormat(window);
    236   ASSERT_EQ(kBufferWidth, width);
    237   ASSERT_EQ(kBufferHeight, height);
    238   ASSERT_EQ(kBufferFormat, format);
    239 }
    240 
    241 // Create buffer queue of three buffers and dequeue three buffers out of it.
    242 // Before each dequeue operation, we resize the buffer queue and expect the
    243 // queue always return buffer with desired dimension.
    244 TEST_F(DvrBufferQueueTest, ResizeBuffer) {
    245   int ret = api_.WriteBufferQueueCreate(
    246       kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
    247       kQueueCapacity, sizeof(DvrNativeBufferMetadata), &write_queue_);
    248   ASSERT_EQ(0, ret);
    249 
    250   int fence_fd = -1;
    251 
    252   DvrNativeBufferMetadata meta;
    253   DvrReadBufferQueue* read_queue = nullptr;
    254   DvrWriteBuffer* wb1 = nullptr;
    255   DvrWriteBuffer* wb2 = nullptr;
    256   DvrWriteBuffer* wb3 = nullptr;
    257   AHardwareBuffer* ahb1 = nullptr;
    258   AHardwareBuffer* ahb2 = nullptr;
    259   AHardwareBuffer* ahb3 = nullptr;
    260   AHardwareBuffer_Desc buffer_desc;
    261 
    262   ret = api_.WriteBufferQueueCreateReadQueue(write_queue_, &read_queue);
    263 
    264   ASSERT_EQ(0, ret);
    265   ASSERT_NE(nullptr, read_queue);
    266 
    267   api_.ReadBufferQueueSetBufferRemovedCallback(read_queue,
    268                                                &BufferRemovedCallback, this);
    269 
    270   // Handle all pending events on the read queue.
    271   ret = api_.ReadBufferQueueHandleEvents(read_queue);
    272   ASSERT_EQ(0, ret);
    273 
    274   size_t capacity = api_.ReadBufferQueueGetCapacity(read_queue);
    275   ALOGD_IF(TRACE, "TestResizeBuffer, capacity=%zu", capacity);
    276   ASSERT_EQ(kQueueCapacity, capacity);
    277 
    278   // Resize before dequeuing.
    279   constexpr uint32_t w1 = 10;
    280   ret = api_.WriteBufferQueueResizeBuffer(write_queue_, w1, kBufferHeight);
    281   ASSERT_EQ(0, ret);
    282 
    283   // Gain first buffer for writing. All buffers will be resized.
    284   ret = api_.WriteBufferQueueGainBuffer(write_queue_, /*timeout=*/0, &wb1,
    285                                         &meta, &fence_fd);
    286   ASSERT_EQ(0, ret);
    287   ASSERT_TRUE(api_.WriteBufferIsValid(wb1));
    288   ALOGD_IF(TRACE, "TestResizeBuffer, gain buffer %p", wb1);
    289   close(fence_fd);
    290 
    291   // Check the buffer dimension.
    292   ret = api_.WriteBufferGetAHardwareBuffer(wb1, &ahb1);
    293   ASSERT_EQ(0, ret);
    294   AHardwareBuffer_describe(ahb1, &buffer_desc);
    295   ASSERT_EQ(w1, buffer_desc.width);
    296   ASSERT_EQ(kBufferHeight, buffer_desc.height);
    297   AHardwareBuffer_release(ahb1);
    298 
    299   // For the first resize, all buffers are reallocated.
    300   int expected_buffer_removed_count = kQueueCapacity;
    301   ret = api_.ReadBufferQueueHandleEvents(read_queue);
    302   ASSERT_EQ(0, ret);
    303   ASSERT_EQ(expected_buffer_removed_count, buffer_removed_count_);
    304 
    305   // Resize the queue. We are testing with blob format, keep height to be 1.
    306   constexpr uint32_t w2 = 20;
    307   ret = api_.WriteBufferQueueResizeBuffer(write_queue_, w2, kBufferHeight);
    308   ASSERT_EQ(0, ret);
    309 
    310   // The next buffer we dequeued should have new width.
    311   ret = api_.WriteBufferQueueGainBuffer(write_queue_, /*timeout=*/0, &wb2,
    312                                         &meta, &fence_fd);
    313   ASSERT_EQ(0, ret);
    314   ASSERT_TRUE(api_.WriteBufferIsValid(wb2));
    315   ALOGD_IF(TRACE, "TestResizeBuffer, gain buffer %p, fence_fd=%d", wb2,
    316            fence_fd);
    317   close(fence_fd);
    318 
    319   // Check the buffer dimension, should be new width
    320   ret = api_.WriteBufferGetAHardwareBuffer(wb2, &ahb2);
    321   ASSERT_EQ(0, ret);
    322   AHardwareBuffer_describe(ahb2, &buffer_desc);
    323   ASSERT_EQ(w2, buffer_desc.width);
    324   AHardwareBuffer_release(ahb2);
    325 
    326   // For the second resize, all but one buffers are reallocated.
    327   expected_buffer_removed_count += (kQueueCapacity - 1);
    328   ret = api_.ReadBufferQueueHandleEvents(read_queue);
    329   ASSERT_EQ(0, ret);
    330   ASSERT_EQ(expected_buffer_removed_count, buffer_removed_count_);
    331 
    332   // Resize the queue for the third time.
    333   constexpr uint32_t w3 = 30;
    334   ret = api_.WriteBufferQueueResizeBuffer(write_queue_, w3, kBufferHeight);
    335   ASSERT_EQ(0, ret);
    336 
    337   // The next buffer we dequeued should have new width.
    338   ret = api_.WriteBufferQueueGainBuffer(write_queue_, /*timeout=*/0, &wb3,
    339                                         &meta, &fence_fd);
    340   ASSERT_EQ(0, ret);
    341   ASSERT_TRUE(api_.WriteBufferIsValid(wb3));
    342   ALOGD_IF(TRACE, "TestResizeBuffer, gain buffer %p, fence_fd=%d", wb3,
    343            fence_fd);
    344   close(fence_fd);
    345 
    346   // Check the buffer dimension, should be new width
    347   ret = api_.WriteBufferGetAHardwareBuffer(wb3, &ahb3);
    348   ASSERT_EQ(0, ret);
    349   AHardwareBuffer_describe(ahb3, &buffer_desc);
    350   ASSERT_EQ(w3, buffer_desc.width);
    351   AHardwareBuffer_release(ahb3);
    352 
    353   // For the third resize, all but two buffers are reallocated.
    354   expected_buffer_removed_count += (kQueueCapacity - 2);
    355   ret = api_.ReadBufferQueueHandleEvents(read_queue);
    356   ASSERT_EQ(0, ret);
    357   ASSERT_EQ(expected_buffer_removed_count, buffer_removed_count_);
    358 
    359   api_.ReadBufferQueueDestroy(read_queue);
    360 }
    361 
    362 TEST_F(DvrBufferQueueTest, ReadQueueEventFd) {
    363   int ret = api_.WriteBufferQueueCreate(
    364       kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
    365       kQueueCapacity, sizeof(DvrNativeBufferMetadata), &write_queue_);
    366   ASSERT_EQ(0, ret);
    367 
    368   DvrReadBufferQueue* read_queue = nullptr;
    369   ret = api_.WriteBufferQueueCreateReadQueue(write_queue_, &read_queue);
    370 
    371   ASSERT_EQ(0, ret);
    372   ASSERT_NE(nullptr, read_queue);
    373 
    374   int event_fd = api_.ReadBufferQueueGetEventFd(read_queue);
    375   ASSERT_GT(event_fd, 0);
    376 }
    377 
    378 // Verifies a Dvr{Read,Write}BufferQueue contains the same set of
    379 // Dvr{Read,Write}Buffer(s) during their lifecycles. And for the same buffer_id,
    380 // the corresponding AHardwareBuffer handle stays the same.
    381 TEST_F(DvrBufferQueueTest, StableBufferIdAndHardwareBuffer) {
    382   int ret = api_.WriteBufferQueueCreate(
    383       kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
    384       kQueueCapacity, sizeof(DvrNativeBufferMetadata), &write_queue_);
    385   ASSERT_EQ(0, ret);
    386 
    387   int fence_fd = -1;
    388   DvrReadBufferQueue* read_queue = nullptr;
    389   EXPECT_EQ(0, api_.WriteBufferQueueCreateReadQueue(write_queue_, &read_queue));
    390 
    391   // Read buffers.
    392   std::array<DvrReadBuffer*, kQueueCapacity> rbs;
    393   // Write buffers.
    394   std::array<DvrWriteBuffer*, kQueueCapacity> wbs;
    395   // Buffer metadata.
    396   std::array<DvrNativeBufferMetadata, kQueueCapacity> metas;
    397   // Hardware buffers for Read buffers.
    398   std::unordered_map<int, AHardwareBuffer*> rhbs;
    399   // Hardware buffers for Write buffers.
    400   std::unordered_map<int, AHardwareBuffer*> whbs;
    401 
    402   constexpr int kNumTests = 100;
    403 
    404   // This test runs the following operations many many times. Thus we prefer to
    405   // use ASSERT_XXX rather than EXPECT_XXX to avoid spamming the output.
    406   std::function<void(size_t i)> Gain = [&](size_t i) {
    407     int ret = api_.WriteBufferQueueGainBuffer(write_queue_, /*timeout=*/10,
    408                                               &wbs[i], &metas[i], &fence_fd);
    409     ASSERT_EQ(ret, 0);
    410     ASSERT_LT(fence_fd, 0);  // expect invalid fence.
    411     ASSERT_TRUE(api_.WriteBufferIsValid(wbs[i]));
    412     int buffer_id = api_.WriteBufferGetId(wbs[i]);
    413     ASSERT_GT(buffer_id, 0);
    414 
    415     AHardwareBuffer* hb = nullptr;
    416     ASSERT_EQ(0, api_.WriteBufferGetAHardwareBuffer(wbs[i], &hb));
    417 
    418     auto whb_it = whbs.find(buffer_id);
    419     if (whb_it == whbs.end()) {
    420       // If this is a new buffer id, check that total number of unique
    421       // hardware buffers won't exceed queue capacity.
    422       ASSERT_LT(whbs.size(), kQueueCapacity);
    423       whbs.emplace(buffer_id, hb);
    424     } else {
    425       // If this is a buffer id we have seen before, check that the
    426       // buffer_id maps to the same AHardwareBuffer handle.
    427       ASSERT_EQ(hb, whb_it->second);
    428     }
    429   };
    430 
    431   std::function<void(size_t i)> Post = [&](size_t i) {
    432     ASSERT_TRUE(api_.WriteBufferIsValid(wbs[i]));
    433 
    434     metas[i].timestamp++;
    435     int ret = api_.WriteBufferQueuePostBuffer(write_queue_, wbs[i], &metas[i],
    436                                               /*fence=*/-1);
    437     ASSERT_EQ(ret, 0);
    438   };
    439 
    440   std::function<void(size_t i)> Acquire = [&](size_t i) {
    441     int ret = api_.ReadBufferQueueAcquireBuffer(read_queue, /*timeout=*/10,
    442                                                 &rbs[i], &metas[i], &fence_fd);
    443     ASSERT_EQ(ret, 0);
    444     ASSERT_LT(fence_fd, 0);  // expect invalid fence.
    445     ASSERT_TRUE(api_.ReadBufferIsValid(rbs[i]));
    446 
    447     int buffer_id = api_.ReadBufferGetId(rbs[i]);
    448     ASSERT_GT(buffer_id, 0);
    449 
    450     AHardwareBuffer* hb = nullptr;
    451     ASSERT_EQ(0, api_.ReadBufferGetAHardwareBuffer(rbs[i], &hb));
    452 
    453     auto rhb_it = rhbs.find(buffer_id);
    454     if (rhb_it == rhbs.end()) {
    455       // If this is a new buffer id, check that total number of unique hardware
    456       // buffers won't exceed queue capacity.
    457       ASSERT_LT(rhbs.size(), kQueueCapacity);
    458       rhbs.emplace(buffer_id, hb);
    459     } else {
    460       // If this is a buffer id we have seen before, check that the buffer_id
    461       // maps to the same AHardwareBuffer handle.
    462       ASSERT_EQ(hb, rhb_it->second);
    463     }
    464   };
    465 
    466   std::function<void(size_t i)> Release = [&](size_t i) {
    467     ASSERT_TRUE(api_.ReadBufferIsValid(rbs[i]));
    468 
    469     int ret = api_.ReadBufferQueueReleaseBuffer(read_queue, rbs[i], &metas[i],
    470                                                 /*release_fence_fd=*/-1);
    471     ASSERT_EQ(ret, 0);
    472   };
    473 
    474   // Scenario one:
    475   for (int i = 0; i < kNumTests; i++) {
    476     // Gain all write buffers.
    477     for (size_t i = 0; i < kQueueCapacity; i++) {
    478       ASSERT_NO_FATAL_FAILURE(Gain(i));
    479     }
    480     // Post all write buffers.
    481     for (size_t i = 0; i < kQueueCapacity; i++) {
    482       ASSERT_NO_FATAL_FAILURE(Post(i));
    483     }
    484     // Acquire all read buffers.
    485     for (size_t i = 0; i < kQueueCapacity; i++) {
    486       ASSERT_NO_FATAL_FAILURE(Acquire(i));
    487     }
    488     // Release all read buffers.
    489     for (size_t i = 0; i < kQueueCapacity; i++) {
    490       ASSERT_NO_FATAL_FAILURE(Release(i));
    491     }
    492   }
    493 
    494   // Scenario two:
    495   for (int i = 0; i < kNumTests; i++) {
    496     // Gain and post all write buffers.
    497     for (size_t i = 0; i < kQueueCapacity; i++) {
    498       ASSERT_NO_FATAL_FAILURE(Gain(i));
    499       ASSERT_NO_FATAL_FAILURE(Post(i));
    500     }
    501     // Acquire and release all read buffers.
    502     for (size_t i = 0; i < kQueueCapacity; i++) {
    503       ASSERT_NO_FATAL_FAILURE(Acquire(i));
    504       ASSERT_NO_FATAL_FAILURE(Release(i));
    505     }
    506   }
    507 
    508   // Scenario three:
    509   for (int i = 0; i < kNumTests; i++) {
    510     // Gain all write buffers then post them in reversed order.
    511     for (size_t i = 0; i < kQueueCapacity; i++) {
    512       ASSERT_NO_FATAL_FAILURE(Gain(i));
    513     }
    514     for (size_t i = 0; i < kQueueCapacity; i++) {
    515       ASSERT_NO_FATAL_FAILURE(Post(kQueueCapacity - 1 - i));
    516     }
    517 
    518     // Acquire all write buffers then release them in reversed order.
    519     for (size_t i = 0; i < kQueueCapacity; i++) {
    520       ASSERT_NO_FATAL_FAILURE(Acquire(i));
    521     }
    522     for (size_t i = 0; i < kQueueCapacity; i++) {
    523       ASSERT_NO_FATAL_FAILURE(Release(kQueueCapacity - 1 - i));
    524     }
    525   }
    526 }
    527 
    528 TEST_F(DvrBufferQueueTest, ConsumerReleaseAfterProducerDestroy) {
    529   int ret = api_.WriteBufferQueueCreate(
    530       kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
    531       kQueueCapacity, sizeof(DvrNativeBufferMetadata), &write_queue_);
    532   ASSERT_EQ(ret, 0);
    533 
    534   DvrReadBufferQueue* read_queue = nullptr;
    535   DvrReadBuffer* rb = nullptr;
    536   DvrWriteBuffer* wb = nullptr;
    537   DvrNativeBufferMetadata meta1;
    538   DvrNativeBufferMetadata meta2;
    539   int fence_fd = -1;
    540 
    541   ret = api_.WriteBufferQueueCreateReadQueue(write_queue_, &read_queue);
    542   ASSERT_EQ(ret, 0);
    543 
    544   api_.ReadBufferQueueSetBufferAvailableCallback(
    545       read_queue, &BufferAvailableCallback, this);
    546 
    547   // Gain buffer for writing.
    548   ret = api_.WriteBufferQueueGainBuffer(write_queue_, /*timeout=*/0, &wb,
    549                                         &meta1, &fence_fd);
    550   ASSERT_EQ(ret, 0);
    551   close(fence_fd);
    552 
    553   // Post buffer to the read_queue.
    554   ret = api_.WriteBufferQueuePostBuffer(write_queue_, wb, &meta1, /*fence=*/-1);
    555   ASSERT_EQ(ret, 0);
    556   wb = nullptr;
    557 
    558   // Acquire buffer for reading.
    559   ret = api_.ReadBufferQueueAcquireBuffer(read_queue, /*timeout=*/10, &rb,
    560                                           &meta2, &fence_fd);
    561   ASSERT_EQ(ret, 0);
    562   close(fence_fd);
    563 
    564   // Destroy the write buffer queue and make sure the reader queue is picking
    565   // these events up.
    566   api_.WriteBufferQueueDestroy(write_queue_);
    567   ret = api_.ReadBufferQueueHandleEvents(read_queue);
    568   ASSERT_EQ(0, ret);
    569 
    570   // Release buffer to the write_queue.
    571   ret = api_.ReadBufferQueueReleaseBuffer(read_queue, rb, &meta2,
    572                                           /*release_fence_fd=*/-1);
    573   ASSERT_EQ(ret, 0);
    574   rb = nullptr;
    575 
    576   api_.ReadBufferQueueDestroy(read_queue);
    577 }
    578 
    579 }  // namespace
    580