1#include <dvr/dvr_api.h>
2#include <dvr/dvr_buffer_queue.h>
3#include <gui/Surface.h>
4#include <private/dvr/buffer_hub_queue_client.h>
5
6#include <base/logging.h>
7#include <gtest/gtest.h>
8
9#include "../dvr_internal.h"
10
11namespace android {
12namespace dvr {
13
14namespace {
15
16static constexpr int kBufferWidth = 100;
17static constexpr int kBufferHeight = 1;
18static constexpr int kLayerCount = 1;
19static constexpr int kBufferFormat = HAL_PIXEL_FORMAT_BLOB;
20static constexpr int kBufferUsage = GRALLOC_USAGE_SW_READ_RARELY;
21static constexpr size_t kQueueCapacity = 3;
22
23typedef uint64_t TestMeta;
24
25class DvrBufferQueueTest : public ::testing::Test {
26 protected:
27  void SetUp() override {
28    write_queue_ = CreateDvrWriteBufferQueueFromProducerQueue(
29        ProducerQueue::Create<TestMeta>(0, 0, 0, 0));
30    ASSERT_NE(nullptr, write_queue_);
31  }
32
33  void TearDown() override {
34    if (write_queue_ != nullptr) {
35      dvrWriteBufferQueueDestroy(write_queue_);
36      write_queue_ = nullptr;
37    }
38  }
39
40  void AllocateBuffers(size_t buffer_count) {
41    size_t out_slot;
42    for (size_t i = 0; i < buffer_count; i++) {
43      int ret = GetProducerQueueFromDvrWriteBufferQueue(write_queue_)
44                    ->AllocateBuffer(kBufferWidth, kBufferHeight, kLayerCount,
45                                     kBufferFormat, kBufferUsage, &out_slot);
46      ASSERT_EQ(0, ret);
47    }
48  }
49
50  DvrWriteBufferQueue* write_queue_{nullptr};
51};
52
53TEST_F(DvrBufferQueueTest, TestWrite_QueueDestroy) {
54  dvrWriteBufferQueueDestroy(write_queue_);
55  write_queue_ = nullptr;
56}
57
58TEST_F(DvrBufferQueueTest, TestWrite_QueueGetCapacity) {
59  AllocateBuffers(kQueueCapacity);
60  size_t capacity = dvrWriteBufferQueueGetCapacity(write_queue_);
61
62  ALOGD_IF(TRACE, "TestWrite_QueueGetCapacity, capacity=%zu", capacity);
63  ASSERT_EQ(kQueueCapacity, capacity);
64}
65
66TEST_F(DvrBufferQueueTest, TestCreateReadQueueFromWriteQueue) {
67  DvrReadBufferQueue* read_queue = nullptr;
68  int ret = dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue);
69
70  ASSERT_EQ(0, ret);
71  ASSERT_NE(nullptr, read_queue);
72
73  dvrReadBufferQueueDestroy(read_queue);
74}
75
76TEST_F(DvrBufferQueueTest, TestCreateReadQueueFromReadQueue) {
77  DvrReadBufferQueue* read_queue1 = nullptr;
78  DvrReadBufferQueue* read_queue2 = nullptr;
79  int ret = dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue1);
80
81  ASSERT_EQ(0, ret);
82  ASSERT_NE(nullptr, read_queue1);
83
84  ret = dvrReadBufferQueueCreateReadQueue(read_queue1, &read_queue2);
85  ASSERT_EQ(0, ret);
86  ASSERT_NE(nullptr, read_queue2);
87  ASSERT_NE(read_queue1, read_queue2);
88
89  dvrReadBufferQueueDestroy(read_queue1);
90  dvrReadBufferQueueDestroy(read_queue2);
91}
92
93TEST_F(DvrBufferQueueTest, CreateEmptyBuffer) {
94  AllocateBuffers(3);
95
96  DvrReadBuffer* read_buffer = nullptr;
97  DvrWriteBuffer* write_buffer = nullptr;
98
99  EXPECT_FALSE(dvrReadBufferIsValid(read_buffer));
100  EXPECT_FALSE(dvrWriteBufferIsValid(write_buffer));
101
102  dvrReadBufferCreateEmpty(&read_buffer);
103  ASSERT_NE(nullptr, read_buffer);
104
105  dvrWriteBufferCreateEmpty(&write_buffer);
106  ASSERT_NE(nullptr, write_buffer);
107
108  EXPECT_FALSE(dvrReadBufferIsValid(read_buffer));
109  EXPECT_FALSE(dvrWriteBufferIsValid(write_buffer));
110
111  DvrReadBufferQueue* read_queue = nullptr;
112
113  ASSERT_EQ(0, dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue));
114
115  const int kTimeoutMs = 0;
116  int fence_fd = -1;
117  ASSERT_EQ(0, dvrWriteBufferQueueDequeue(write_queue_, kTimeoutMs,
118                                          write_buffer, &fence_fd));
119  EXPECT_EQ(-1, fence_fd);
120  EXPECT_TRUE(dvrWriteBufferIsValid(write_buffer));
121
122  ASSERT_EQ(0, dvrWriteBufferClear(write_buffer));
123  EXPECT_FALSE(dvrWriteBufferIsValid(write_buffer));
124}
125
126TEST_F(DvrBufferQueueTest, TestDequeuePostDequeueRelease) {
127  static constexpr int kTimeout = 0;
128  DvrReadBufferQueue* read_queue = nullptr;
129  DvrReadBuffer* rb = nullptr;
130  DvrWriteBuffer* wb = nullptr;
131  int fence_fd = -1;
132
133  int ret = dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue);
134
135  ASSERT_EQ(0, ret);
136  ASSERT_NE(nullptr, read_queue);
137
138  dvrWriteBufferCreateEmpty(&wb);
139  ASSERT_NE(nullptr, wb);
140
141  dvrReadBufferCreateEmpty(&rb);
142  ASSERT_NE(nullptr, rb);
143
144  AllocateBuffers(kQueueCapacity);
145
146  // Gain buffer for writing.
147  ret = dvrWriteBufferQueueDequeue(write_queue_, kTimeout, wb, &fence_fd);
148  ASSERT_EQ(0, ret);
149  ASSERT_TRUE(dvrWriteBufferIsValid(wb));
150  ALOGD_IF(TRACE, "TestDequeuePostDequeueRelease, gain buffer %p, fence_fd=%d",
151           wb, fence_fd);
152  pdx::LocalHandle release_fence(fence_fd);
153
154  // Post buffer to the read_queue.
155  TestMeta seq = 42U;
156  ret = dvrWriteBufferPost(wb, /* fence */ -1, &seq, sizeof(seq));
157  ASSERT_EQ(0, ret);
158  dvrWriteBufferDestroy(wb);
159  wb = nullptr;
160
161  // Acquire buffer for reading.
162  TestMeta acquired_seq = 0U;
163  ret = dvrReadBufferQueueDequeue(read_queue, kTimeout, rb, &fence_fd,
164                                  &acquired_seq, sizeof(acquired_seq));
165  ASSERT_EQ(0, ret);
166  ASSERT_TRUE(dvrReadBufferIsValid(rb));
167  ASSERT_EQ(seq, acquired_seq);
168  ALOGD_IF(TRACE,
169           "TestDequeuePostDequeueRelease, acquire buffer %p, fence_fd=%d", rb,
170           fence_fd);
171  pdx::LocalHandle acquire_fence(fence_fd);
172
173  // Release buffer to the write_queue.
174  ret = dvrReadBufferRelease(rb, -1);
175  ASSERT_EQ(0, ret);
176  dvrReadBufferDestroy(rb);
177  rb = nullptr;
178
179  // TODO(b/34387835) Currently buffer allocation has to happen after all queues
180  // are initialized.
181  size_t capacity = dvrReadBufferQueueGetCapacity(read_queue);
182
183  ALOGD_IF(TRACE, "TestDequeuePostDequeueRelease, capacity=%zu", capacity);
184  ASSERT_EQ(kQueueCapacity, capacity);
185
186  dvrReadBufferQueueDestroy(read_queue);
187}
188
189TEST_F(DvrBufferQueueTest, TestGetExternalSurface) {
190  ANativeWindow* window = nullptr;
191
192  // The |write_queue_| doesn't have proper metadata (must be
193  // DvrNativeBufferMetadata) configured during creation.
194  int ret = dvrWriteBufferQueueGetExternalSurface(write_queue_, &window);
195  ASSERT_EQ(-EINVAL, ret);
196  ASSERT_EQ(nullptr, window);
197
198  // A write queue with DvrNativeBufferMetadata should work fine.
199  std::unique_ptr<DvrWriteBufferQueue, decltype(&dvrWriteBufferQueueDestroy)>
200      write_queue(
201          CreateDvrWriteBufferQueueFromProducerQueue(
202              ProducerQueue::Create<DvrNativeBufferMetadata>(0, 0, 0, 0)),
203          dvrWriteBufferQueueDestroy);
204  ASSERT_NE(nullptr, write_queue.get());
205
206  ret = dvrWriteBufferQueueGetExternalSurface(write_queue.get(), &window);
207  ASSERT_EQ(0, ret);
208  ASSERT_NE(nullptr, window);
209
210  sp<Surface> surface = static_cast<Surface*>(window);
211  ASSERT_TRUE(Surface::isValid(surface));
212}
213
214}  // namespace
215
216}  // namespace dvr
217}  // namespace android
218