• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
BufferAvailableCallback(void * context)35   static void BufferAvailableCallback(void* context) {
36     DvrBufferQueueTest* thiz = static_cast<DvrBufferQueueTest*>(context);
37     thiz->HandleBufferAvailable();
38   }
39 
BufferRemovedCallback(DvrReadBuffer * buffer,void * context)40   static void BufferRemovedCallback(DvrReadBuffer* buffer, void* context) {
41     DvrBufferQueueTest* thiz = static_cast<DvrBufferQueueTest*>(context);
42     thiz->HandleBufferRemoved(buffer);
43   }
44 
45  protected:
TearDown()46   void TearDown() override {
47     if (write_queue_ != nullptr) {
48       api_.WriteBufferQueueDestroy(write_queue_);
49       write_queue_ = nullptr;
50     }
51     DvrApiTest::TearDown();
52   }
53 
HandleBufferAvailable()54   void HandleBufferAvailable() {
55     buffer_available_count_ += 1;
56     ALOGD_IF(TRACE, "Buffer avaiable, count=%d", buffer_available_count_);
57   }
58 
HandleBufferRemoved(DvrReadBuffer * buffer)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 
TEST_F(DvrBufferQueueTest,WriteQueueCreateDestroy)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 
TEST_F(DvrBufferQueueTest,WriteQueueGetCapacity)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 
TEST_F(DvrBufferQueueTest,CreateReadQueueFromWriteQueue)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 
TEST_F(DvrBufferQueueTest,CreateReadQueueFromReadQueue)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 
TEST_F(DvrBufferQueueTest,GainBuffer)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 
TEST_F(DvrBufferQueueTest,AcquirePostGainRelease)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 
TEST_F(DvrBufferQueueTest,GetANativeWindow)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.
TEST_F(DvrBufferQueueTest,ResizeBuffer)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 
TEST_F(DvrBufferQueueTest,ReadQueueEventFd)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.
TEST_F(DvrBufferQueueTest,StableBufferIdAndHardwareBuffer)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 
TEST_F(DvrBufferQueueTest,ConsumerReleaseAfterProducerDestroy)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