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
24namespace {
25
26static constexpr uint32_t kBufferWidth = 100;
27static constexpr uint32_t kBufferHeight = 1;
28static constexpr uint32_t kLayerCount = 1;
29static constexpr uint32_t kBufferFormat = AHARDWAREBUFFER_FORMAT_BLOB;
30static constexpr uint64_t kBufferUsage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN;
31static constexpr size_t kQueueCapacity = 3;
32
33class 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
70TEST_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
80TEST_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
92TEST_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
107TEST_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
129TEST_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
148TEST_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
221TEST_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.
244TEST_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
362TEST_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.
381TEST_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
528TEST_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