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