1 #include <android/log.h>
2 #include <android/native_window.h>
3 #include <android-base/unique_fd.h>
4 #include <dvr/dvr_api.h>
5 #include <dvr/dvr_buffer_queue.h>
7 #include <gtest/gtest.h>
10 #include <unordered_map>
13 #define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
17 #define ALOGD_IF(cond, ...) \
18 ((__predict_false(cond)) ? ((void)ALOGD(__VA_ARGS__)) : (void)0)
23 static constexpr uint32_t kBufferWidth = 100;
24 static constexpr uint32_t kBufferHeight = 1;
25 static constexpr uint32_t kLayerCount = 1;
26 static constexpr uint32_t kBufferFormat = AHARDWAREBUFFER_FORMAT_BLOB;
27 static constexpr uint64_t kBufferUsage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN;
28 static constexpr size_t kQueueCapacity = 3;
30 class DvrBufferQueueTest : public ::testing::Test {
32 static void BufferAvailableCallback(void* context) {
33 DvrBufferQueueTest* thiz = static_cast<DvrBufferQueueTest*>(context);
34 thiz->HandleBufferAvailable();
37 static void BufferRemovedCallback(DvrReadBuffer* buffer, void* context) {
38 DvrBufferQueueTest* thiz = static_cast<DvrBufferQueueTest*>(context);
39 thiz->HandleBufferRemoved(buffer);
43 void TearDown() override {
44 if (write_queue_ != nullptr) {
45 dvrWriteBufferQueueDestroy(write_queue_);
46 write_queue_ = nullptr;
50 void HandleBufferAvailable() {
51 buffer_available_count_ += 1;
52 ALOGD_IF(TRACE, "Buffer avaiable, count=%d", buffer_available_count_);
55 void HandleBufferRemoved(DvrReadBuffer* buffer) {
56 buffer_removed_count_ += 1;
57 ALOGD_IF(TRACE, "Buffer removed, buffer=%p, count=%d", buffer,
58 buffer_removed_count_);
61 DvrWriteBufferQueue* write_queue_{nullptr};
62 int buffer_available_count_{0};
63 int buffer_removed_count_{0};
66 TEST_F(DvrBufferQueueTest, WriteQueueCreateDestroy) {
67 int ret = dvrWriteBufferQueueCreate(
68 kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
69 /*capacity=*/0, sizeof(DvrNativeBufferMetadata), &write_queue_);
72 dvrWriteBufferQueueDestroy(write_queue_);
73 write_queue_ = nullptr;
76 TEST_F(DvrBufferQueueTest, WriteQueueGetCapacity) {
77 int ret = dvrWriteBufferQueueCreate(
78 kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
79 kQueueCapacity, sizeof(DvrNativeBufferMetadata), &write_queue_);
82 size_t capacity = dvrWriteBufferQueueGetCapacity(write_queue_);
84 ALOGD_IF(TRACE, "TestWrite_QueueGetCapacity, capacity=%zu", capacity);
85 ASSERT_EQ(kQueueCapacity, capacity);
88 TEST_F(DvrBufferQueueTest, CreateReadQueueFromWriteQueue) {
89 int ret = dvrWriteBufferQueueCreate(
90 kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
91 /*capacity=*/0, sizeof(DvrNativeBufferMetadata), &write_queue_);
94 DvrReadBufferQueue* read_queue = nullptr;
95 ret = dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue);
98 ASSERT_NE(nullptr, read_queue);
100 dvrReadBufferQueueDestroy(read_queue);
103 TEST_F(DvrBufferQueueTest, CreateReadQueueFromReadQueue) {
104 int ret = dvrWriteBufferQueueCreate(
105 kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
106 /*capacity=*/0, sizeof(DvrNativeBufferMetadata), &write_queue_);
109 DvrReadBufferQueue* read_queue1 = nullptr;
110 DvrReadBufferQueue* read_queue2 = nullptr;
111 ret = dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue1);
114 ASSERT_NE(nullptr, read_queue1);
116 ret = dvrReadBufferQueueCreateReadQueue(read_queue1, &read_queue2);
118 ASSERT_NE(nullptr, read_queue2);
119 ASSERT_NE(read_queue1, read_queue2);
121 dvrReadBufferQueueDestroy(read_queue1);
122 dvrReadBufferQueueDestroy(read_queue2);
125 TEST_F(DvrBufferQueueTest, GainBuffer) {
126 int ret = dvrWriteBufferQueueCreate(
127 kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
128 kQueueCapacity, sizeof(DvrNativeBufferMetadata), &write_queue_);
131 DvrWriteBuffer* wb = nullptr;
132 EXPECT_FALSE(dvrWriteBufferIsValid(wb));
134 DvrNativeBufferMetadata meta = {0};
136 ret = dvrWriteBufferQueueGainBuffer(write_queue_, /*timeout=*/0, &wb, &meta,
139 EXPECT_EQ(fence_fd, -1);
140 EXPECT_NE(wb, nullptr);
141 EXPECT_TRUE(dvrWriteBufferIsValid(wb));
144 TEST_F(DvrBufferQueueTest, AcquirePostGainRelease) {
145 int ret = dvrWriteBufferQueueCreate(
146 kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
147 kQueueCapacity, sizeof(DvrNativeBufferMetadata), &write_queue_);
150 DvrReadBufferQueue* read_queue = nullptr;
151 DvrReadBuffer* rb = nullptr;
152 DvrWriteBuffer* wb = nullptr;
153 DvrNativeBufferMetadata meta1 = {0};
154 DvrNativeBufferMetadata meta2 = {0};
157 ret = dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue);
160 ASSERT_NE(read_queue, nullptr);
162 dvrReadBufferQueueSetBufferAvailableCallback(read_queue,
163 &BufferAvailableCallback, this);
165 // Gain buffer for writing.
166 ret = dvrWriteBufferQueueGainBuffer(write_queue_, /*timeout=*/0, &wb, &meta1,
169 ASSERT_NE(wb, nullptr);
170 ASSERT_TRUE(dvrWriteBufferIsValid(wb));
171 ALOGD_IF(TRACE, "TestDequeuePostDequeueRelease, gain buffer %p, fence_fd=%d",
173 android::base::unique_fd release_fence(fence_fd);
175 // Post buffer to the read_queue.
176 meta1.timestamp = 42;
177 ret = dvrWriteBufferQueuePostBuffer(write_queue_, wb, &meta1, /*fence=*/-1);
179 ASSERT_FALSE(dvrWriteBufferIsValid(wb));
182 // Acquire buffer for reading.
183 ret = dvrReadBufferQueueAcquireBuffer(read_queue, /*timeout=*/0, &rb, &meta2,
186 ASSERT_NE(rb, nullptr);
188 // Dequeue is successfully, BufferAvailableCallback should be fired once.
189 ASSERT_EQ(buffer_available_count_, 1);
190 ASSERT_TRUE(dvrReadBufferIsValid(rb));
192 // Metadata should be passed along from producer to consumer properly.
193 ASSERT_EQ(meta1.timestamp, meta2.timestamp);
196 "TestDequeuePostDequeueRelease, acquire buffer %p, fence_fd=%d", rb,
198 android::base::unique_fd acquire_fence(fence_fd);
200 // Release buffer to the write_queue.
201 ret = dvrReadBufferQueueReleaseBuffer(read_queue, rb, &meta2,
202 /*release_fence_fd=*/-1);
204 ASSERT_FALSE(dvrReadBufferIsValid(rb));
207 // TODO(b/34387835) Currently buffer allocation has to happen after all queues
209 size_t capacity = dvrReadBufferQueueGetCapacity(read_queue);
211 ALOGD_IF(TRACE, "TestDequeuePostDequeueRelease, capacity=%zu", capacity);
212 ASSERT_EQ(kQueueCapacity, capacity);
214 dvrReadBufferQueueDestroy(read_queue);
217 TEST_F(DvrBufferQueueTest, GetANativeWindow) {
218 int ret = dvrWriteBufferQueueCreate(
219 kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
220 /*capacity=*/0, sizeof(DvrNativeBufferMetadata), &write_queue_);
222 ASSERT_NE(nullptr, write_queue_);
224 ANativeWindow* window = nullptr;
225 ret = dvrWriteBufferQueueGetANativeWindow(write_queue_, &window);
227 ASSERT_NE(nullptr, window);
229 uint32_t width = ANativeWindow_getWidth(window);
230 uint32_t height = ANativeWindow_getHeight(window);
231 uint32_t format = ANativeWindow_getFormat(window);
232 ASSERT_EQ(kBufferWidth, width);
233 ASSERT_EQ(kBufferHeight, height);
234 ASSERT_EQ(kBufferFormat, format);
237 // Create buffer queue of three buffers and dequeue three buffers out of it.
238 // Before each dequeue operation, we resize the buffer queue and expect the
239 // queue always return buffer with desired dimension.
240 TEST_F(DvrBufferQueueTest, ResizeBuffer) {
241 int ret = dvrWriteBufferQueueCreate(
242 kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
243 kQueueCapacity, sizeof(DvrNativeBufferMetadata), &write_queue_);
248 DvrNativeBufferMetadata meta = {0};
249 DvrReadBufferQueue* read_queue = nullptr;
250 DvrWriteBuffer* wb1 = nullptr;
251 DvrWriteBuffer* wb2 = nullptr;
252 DvrWriteBuffer* wb3 = nullptr;
253 AHardwareBuffer* ahb1 = nullptr;
254 AHardwareBuffer* ahb2 = nullptr;
255 AHardwareBuffer* ahb3 = nullptr;
256 AHardwareBuffer_Desc buffer_desc;
258 ret = dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue);
261 ASSERT_NE(nullptr, read_queue);
263 dvrReadBufferQueueSetBufferRemovedCallback(read_queue, &BufferRemovedCallback,
266 // Handle all pending events on the read queue.
267 ret = dvrReadBufferQueueHandleEvents(read_queue);
270 size_t capacity = dvrReadBufferQueueGetCapacity(read_queue);
271 ALOGD_IF(TRACE, "TestResizeBuffer, capacity=%zu", capacity);
272 ASSERT_EQ(kQueueCapacity, capacity);
274 // Resize before dequeuing.
275 constexpr uint32_t w1 = 10;
276 ret = dvrWriteBufferQueueResizeBuffer(write_queue_, w1, kBufferHeight);
279 // Gain first buffer for writing. All buffers will be resized.
280 ret = dvrWriteBufferQueueGainBuffer(write_queue_, /*timeout=*/0, &wb1, &meta,
283 ASSERT_TRUE(dvrWriteBufferIsValid(wb1));
284 ALOGD_IF(TRACE, "TestResizeBuffer, gain buffer %p", wb1);
285 android::base::unique_fd release_fence1(fence_fd);
287 // Check the buffer dimension.
288 ret = dvrWriteBufferGetAHardwareBuffer(wb1, &ahb1);
290 AHardwareBuffer_describe(ahb1, &buffer_desc);
291 ASSERT_EQ(w1, buffer_desc.width);
292 ASSERT_EQ(kBufferHeight, buffer_desc.height);
293 AHardwareBuffer_release(ahb1);
295 // For the first resize, all buffers are reallocated.
296 int expected_buffer_removed_count = kQueueCapacity;
297 ret = dvrReadBufferQueueHandleEvents(read_queue);
299 ASSERT_EQ(expected_buffer_removed_count, buffer_removed_count_);
301 // Resize the queue. We are testing with blob format, keep height to be 1.
302 constexpr uint32_t w2 = 20;
303 ret = dvrWriteBufferQueueResizeBuffer(write_queue_, w2, kBufferHeight);
306 // The next buffer we dequeued should have new width.
307 ret = dvrWriteBufferQueueGainBuffer(write_queue_, /*timeout=*/0, &wb2, &meta,
310 ASSERT_TRUE(dvrWriteBufferIsValid(wb2));
311 ALOGD_IF(TRACE, "TestResizeBuffer, gain buffer %p, fence_fd=%d", wb2,
313 android::base::unique_fd release_fence2(fence_fd);
315 // Check the buffer dimension, should be new width
316 ret = dvrWriteBufferGetAHardwareBuffer(wb2, &ahb2);
318 AHardwareBuffer_describe(ahb2, &buffer_desc);
319 ASSERT_EQ(w2, buffer_desc.width);
320 AHardwareBuffer_release(ahb2);
322 // For the second resize, all but one buffers are reallocated.
323 expected_buffer_removed_count += (kQueueCapacity - 1);
324 ret = dvrReadBufferQueueHandleEvents(read_queue);
326 ASSERT_EQ(expected_buffer_removed_count, buffer_removed_count_);
328 // Resize the queue for the third time.
329 constexpr uint32_t w3 = 30;
330 ret = dvrWriteBufferQueueResizeBuffer(write_queue_, w3, kBufferHeight);
333 // The next buffer we dequeued should have new width.
334 ret = dvrWriteBufferQueueGainBuffer(write_queue_, /*timeout=*/0, &wb3, &meta,
337 ASSERT_TRUE(dvrWriteBufferIsValid(wb3));
338 ALOGD_IF(TRACE, "TestResizeBuffer, gain buffer %p, fence_fd=%d", wb3,
340 android::base::unique_fd release_fence3(fence_fd);
342 // Check the buffer dimension, should be new width
343 ret = dvrWriteBufferGetAHardwareBuffer(wb3, &ahb3);
345 AHardwareBuffer_describe(ahb3, &buffer_desc);
346 ASSERT_EQ(w3, buffer_desc.width);
347 AHardwareBuffer_release(ahb3);
349 // For the third resize, all but two buffers are reallocated.
350 expected_buffer_removed_count += (kQueueCapacity - 2);
351 ret = dvrReadBufferQueueHandleEvents(read_queue);
353 ASSERT_EQ(expected_buffer_removed_count, buffer_removed_count_);
355 dvrReadBufferQueueDestroy(read_queue);
358 TEST_F(DvrBufferQueueTest, ReadQueueEventFd) {
359 int ret = dvrWriteBufferQueueCreate(
360 kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
361 kQueueCapacity, sizeof(DvrNativeBufferMetadata), &write_queue_);
364 DvrReadBufferQueue* read_queue = nullptr;
365 ret = dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue);
368 ASSERT_NE(nullptr, read_queue);
370 int event_fd = dvrReadBufferQueueGetEventFd(read_queue);
371 ASSERT_GT(event_fd, 0);
374 // Verifies a Dvr{Read,Write}BufferQueue contains the same set of
375 // Dvr{Read,Write}Buffer(s) during their lifecycles. And for the same buffer_id,
376 // the corresponding AHardwareBuffer handle stays the same.
377 TEST_F(DvrBufferQueueTest, StableBufferIdAndHardwareBuffer) {
378 int ret = dvrWriteBufferQueueCreate(
379 kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
380 kQueueCapacity, sizeof(DvrNativeBufferMetadata), &write_queue_);
384 DvrReadBufferQueue* read_queue = nullptr;
385 EXPECT_EQ(0, dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue));
388 std::array<DvrReadBuffer*, kQueueCapacity> rbs;
390 std::array<DvrWriteBuffer*, kQueueCapacity> wbs;
392 std::array<DvrNativeBufferMetadata, kQueueCapacity> metas;
393 // Hardware buffers for Read buffers.
394 std::unordered_map<int, AHardwareBuffer*> rhbs;
395 // Hardware buffers for Write buffers.
396 std::unordered_map<int, AHardwareBuffer*> whbs;
398 constexpr int kNumTests = 100;
400 // This test runs the following operations many many times. Thus we prefer to
401 // use ASSERT_XXX rather than EXPECT_XXX to avoid spamming the output.
402 std::function<void(size_t i)> Gain = [&](size_t i) {
403 int ret = dvrWriteBufferQueueGainBuffer(write_queue_, /*timeout=*/0,
404 &wbs[i], &metas[i], &fence_fd);
406 ASSERT_LT(fence_fd, 0); // expect invalid fence.
407 ASSERT_TRUE(dvrWriteBufferIsValid(wbs[i]));
408 int buffer_id = dvrWriteBufferGetId(wbs[i]);
409 ASSERT_GT(buffer_id, 0);
411 AHardwareBuffer* hb = nullptr;
412 ASSERT_EQ(0, dvrWriteBufferGetAHardwareBuffer(wbs[i], &hb));
414 auto whb_it = whbs.find(buffer_id);
415 if (whb_it == whbs.end()) {
416 // If this is a new buffer id, check that total number of unique
417 // hardware buffers won't exceed queue capacity.
418 ASSERT_LT(whbs.size(), kQueueCapacity);
419 whbs.emplace(buffer_id, hb);
421 // If this is a buffer id we have seen before, check that the
422 // buffer_id maps to the same AHardwareBuffer handle.
423 ASSERT_EQ(hb, whb_it->second);
427 std::function<void(size_t i)> Post = [&](size_t i) {
428 ASSERT_TRUE(dvrWriteBufferIsValid(wbs[i]));
430 metas[i].timestamp++;
431 int ret = dvrWriteBufferQueuePostBuffer(write_queue_, wbs[i], &metas[i],
436 std::function<void(size_t i)> Acquire = [&](size_t i) {
437 int ret = dvrReadBufferQueueAcquireBuffer(read_queue, /*timeout=*/0,
438 &rbs[i], &metas[i], &fence_fd);
440 ASSERT_LT(fence_fd, 0); // expect invalid fence.
441 ASSERT_TRUE(dvrReadBufferIsValid(rbs[i]));
443 int buffer_id = dvrReadBufferGetId(rbs[i]);
444 ASSERT_GT(buffer_id, 0);
446 AHardwareBuffer* hb = nullptr;
447 ASSERT_EQ(0, dvrReadBufferGetAHardwareBuffer(rbs[i], &hb));
449 auto rhb_it = rhbs.find(buffer_id);
450 if (rhb_it == rhbs.end()) {
451 // If this is a new buffer id, check that total number of unique hardware
452 // buffers won't exceed queue capacity.
453 ASSERT_LT(rhbs.size(), kQueueCapacity);
454 rhbs.emplace(buffer_id, hb);
456 // If this is a buffer id we have seen before, check that the buffer_id
457 // maps to the same AHardwareBuffer handle.
458 ASSERT_EQ(hb, rhb_it->second);
462 std::function<void(size_t i)> Release = [&](size_t i) {
463 ASSERT_TRUE(dvrReadBufferIsValid(rbs[i]));
465 int ret = dvrReadBufferQueueReleaseBuffer(read_queue, rbs[i], &metas[i],
466 /*release_fence_fd=*/-1);
471 for (int i = 0; i < kNumTests; i++) {
472 // Gain all write buffers.
473 for (size_t i = 0; i < kQueueCapacity; i++) {
474 ASSERT_NO_FATAL_FAILURE(Gain(i));
476 // Post all write buffers.
477 for (size_t i = 0; i < kQueueCapacity; i++) {
478 ASSERT_NO_FATAL_FAILURE(Post(i));
480 // Acquire all read buffers.
481 for (size_t i = 0; i < kQueueCapacity; i++) {
482 ASSERT_NO_FATAL_FAILURE(Acquire(i));
484 // Release all read buffers.
485 for (size_t i = 0; i < kQueueCapacity; i++) {
486 ASSERT_NO_FATAL_FAILURE(Release(i));
491 for (int i = 0; i < kNumTests; i++) {
492 // Gain and post all write buffers.
493 for (size_t i = 0; i < kQueueCapacity; i++) {
494 ASSERT_NO_FATAL_FAILURE(Gain(i));
495 ASSERT_NO_FATAL_FAILURE(Post(i));
497 // Acquire and release all read buffers.
498 for (size_t i = 0; i < kQueueCapacity; i++) {
499 ASSERT_NO_FATAL_FAILURE(Acquire(i));
500 ASSERT_NO_FATAL_FAILURE(Release(i));
505 for (int i = 0; i < kNumTests; i++) {
506 // Gain all write buffers then post them in reversed order.
507 for (size_t i = 0; i < kQueueCapacity; i++) {
508 ASSERT_NO_FATAL_FAILURE(Gain(i));
510 for (size_t i = 0; i < kQueueCapacity; i++) {
511 ASSERT_NO_FATAL_FAILURE(Post(kQueueCapacity - 1 - i));
514 // Acquire all write buffers then release them in reversed order.
515 for (size_t i = 0; i < kQueueCapacity; i++) {
516 ASSERT_NO_FATAL_FAILURE(Acquire(i));
518 for (size_t i = 0; i < kQueueCapacity; i++) {
519 ASSERT_NO_FATAL_FAILURE(Release(kQueueCapacity - 1 - i));