• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <base/logging.h>
2 #include <private/dvr/buffer_hub_client.h>
3 #include <private/dvr/buffer_hub_queue_client.h>
4 
5 #include <gtest/gtest.h>
6 
7 #include <vector>
8 
9 namespace android {
10 namespace dvr {
11 
12 using pdx::LocalHandle;
13 
14 namespace {
15 
16 constexpr int kBufferWidth = 100;
17 constexpr int kBufferHeight = 1;
18 constexpr int kBufferLayerCount = 1;
19 constexpr int kBufferFormat = HAL_PIXEL_FORMAT_BLOB;
20 constexpr int kBufferUsage = GRALLOC_USAGE_SW_READ_RARELY;
21 
22 class BufferHubQueueTest : public ::testing::Test {
23  public:
24   template <typename Meta>
CreateProducerQueue(uint64_t usage_set_mask=0,uint64_t usage_clear_mask=0,uint64_t usage_deny_set_mask=0,uint64_t usage_deny_clear_mask=0)25   bool CreateProducerQueue(uint64_t usage_set_mask = 0,
26                            uint64_t usage_clear_mask = 0,
27                            uint64_t usage_deny_set_mask = 0,
28                            uint64_t usage_deny_clear_mask = 0) {
29     producer_queue_ =
30         ProducerQueue::Create<Meta>(usage_set_mask, usage_clear_mask,
31                                     usage_deny_set_mask, usage_deny_clear_mask);
32     return producer_queue_ != nullptr;
33   }
34 
CreateConsumerQueue()35   bool CreateConsumerQueue() {
36     if (producer_queue_) {
37       consumer_queue_ = producer_queue_->CreateConsumerQueue();
38       return consumer_queue_ != nullptr;
39     } else {
40       return false;
41     }
42   }
43 
44   template <typename Meta>
CreateQueues(int usage_set_mask=0,int usage_clear_mask=0,int usage_deny_set_mask=0,int usage_deny_clear_mask=0)45   bool CreateQueues(int usage_set_mask = 0, int usage_clear_mask = 0,
46                     int usage_deny_set_mask = 0,
47                     int usage_deny_clear_mask = 0) {
48     return CreateProducerQueue<Meta>(usage_set_mask, usage_clear_mask,
49                                      usage_deny_set_mask,
50                                      usage_deny_clear_mask) &&
51            CreateConsumerQueue();
52   }
53 
AllocateBuffer()54   void AllocateBuffer() {
55     // Create producer buffer.
56     size_t slot;
57     int ret = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
58                                               kBufferLayerCount, kBufferFormat,
59                                               kBufferUsage, &slot);
60     ASSERT_EQ(ret, 0);
61   }
62 
63  protected:
64   std::unique_ptr<ProducerQueue> producer_queue_;
65   std::unique_ptr<ConsumerQueue> consumer_queue_;
66 };
67 
TEST_F(BufferHubQueueTest,TestDequeue)68 TEST_F(BufferHubQueueTest, TestDequeue) {
69   const size_t nb_dequeue_times = 16;
70 
71   ASSERT_TRUE(CreateQueues<size_t>());
72 
73   // Allocate only one buffer.
74   AllocateBuffer();
75 
76   // But dequeue multiple times.
77   for (size_t i = 0; i < nb_dequeue_times; i++) {
78     size_t slot;
79     LocalHandle fence;
80     auto p1_status = producer_queue_->Dequeue(0, &slot, &fence);
81     ASSERT_TRUE(p1_status.ok());
82     auto p1 = p1_status.take();
83     ASSERT_NE(nullptr, p1);
84     size_t mi = i;
85     ASSERT_EQ(p1->Post(LocalHandle(), &mi, sizeof(mi)), 0);
86     size_t mo;
87     auto c1_status = consumer_queue_->Dequeue(100, &slot, &mo, &fence);
88     ASSERT_TRUE(c1_status.ok());
89     auto c1 = c1_status.take();
90     ASSERT_NE(nullptr, c1);
91     ASSERT_EQ(mi, mo);
92     c1->Release(LocalHandle());
93   }
94 }
95 
TEST_F(BufferHubQueueTest,TestProducerConsumer)96 TEST_F(BufferHubQueueTest, TestProducerConsumer) {
97   const size_t nb_buffer = 16;
98   size_t slot;
99   uint64_t seq;
100 
101   ASSERT_TRUE(CreateQueues<uint64_t>());
102 
103   for (size_t i = 0; i < nb_buffer; i++) {
104     AllocateBuffer();
105 
106     // Producer queue has all the available buffers on initialize.
107     ASSERT_EQ(producer_queue_->count(), i + 1);
108     ASSERT_EQ(producer_queue_->capacity(), i + 1);
109 
110     // Consumer queue has no avaiable buffer on initialize.
111     ASSERT_EQ(consumer_queue_->count(), 0U);
112     // Consumer queue does not import buffers until a dequeue is issued.
113     ASSERT_EQ(consumer_queue_->capacity(), i);
114     // Dequeue returns timeout since no buffer is ready to consumer, but
115     // this implicitly triggers buffer import and bump up |capacity|.
116     LocalHandle fence;
117     auto status = consumer_queue_->Dequeue(0, &slot, &seq, &fence);
118     ASSERT_FALSE(status.ok());
119     ASSERT_EQ(ETIMEDOUT, status.error());
120     ASSERT_EQ(consumer_queue_->capacity(), i + 1);
121   }
122 
123   for (size_t i = 0; i < nb_buffer; i++) {
124     LocalHandle fence;
125     // First time, there is no buffer available to dequeue.
126     auto consumer_status = consumer_queue_->Dequeue(0, &slot, &seq, &fence);
127     ASSERT_FALSE(consumer_status.ok());
128     ASSERT_EQ(ETIMEDOUT, consumer_status.error());
129 
130     // Make sure Producer buffer is Post()'ed so that it's ready to Accquire
131     // in the consumer's Dequeue() function.
132     auto producer_status = producer_queue_->Dequeue(0, &slot, &fence);
133     ASSERT_TRUE(producer_status.ok());
134     auto producer = producer_status.take();
135     ASSERT_NE(nullptr, producer);
136 
137     uint64_t seq_in = static_cast<uint64_t>(i);
138     ASSERT_EQ(producer->Post({}, &seq_in, sizeof(seq_in)), 0);
139 
140     // Second time, the just |Post()|'ed buffer should be dequeued.
141     uint64_t seq_out = 0;
142     consumer_status = consumer_queue_->Dequeue(0, &slot, &seq_out, &fence);
143     ASSERT_TRUE(consumer_status.ok());
144     auto consumer = consumer_status.take();
145     ASSERT_NE(nullptr, consumer);
146     ASSERT_EQ(seq_in, seq_out);
147   }
148 }
149 
TEST_F(BufferHubQueueTest,TestMultipleConsumers)150 TEST_F(BufferHubQueueTest, TestMultipleConsumers) {
151   ASSERT_TRUE(CreateProducerQueue<void>());
152 
153   // Allocate buffers.
154   const size_t kBufferCount = 4u;
155   for (size_t i = 0; i < kBufferCount; i++) {
156     AllocateBuffer();
157   }
158   ASSERT_EQ(kBufferCount, producer_queue_->count());
159 
160   // Build a silent consumer queue to test multi-consumer queue features.
161   auto silent_queue = producer_queue_->CreateSilentConsumerQueue();
162   ASSERT_NE(nullptr, silent_queue);
163 
164   // Check that buffers are correctly imported on construction.
165   EXPECT_EQ(kBufferCount, silent_queue->capacity());
166 
167   // Dequeue and post a buffer.
168   size_t slot;
169   LocalHandle fence;
170   auto producer_status = producer_queue_->Dequeue(0, &slot, &fence);
171   ASSERT_TRUE(producer_status.ok());
172   auto producer_buffer = producer_status.take();
173   ASSERT_NE(nullptr, producer_buffer);
174   ASSERT_EQ(0, producer_buffer->Post<void>({}));
175 
176   // Currently we expect no buffer to be available prior to calling
177   // WaitForBuffers/HandleQueueEvents.
178   // TODO(eieio): Note this behavior may change in the future.
179   EXPECT_EQ(0u, silent_queue->count());
180   EXPECT_FALSE(silent_queue->HandleQueueEvents());
181   EXPECT_EQ(0u, silent_queue->count());
182 
183   // Build a new consumer queue to test multi-consumer queue features.
184   consumer_queue_ = silent_queue->CreateConsumerQueue();
185   ASSERT_NE(nullptr, consumer_queue_);
186 
187   // Check that buffers are correctly imported on construction.
188   EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
189   EXPECT_EQ(1u, consumer_queue_->count());
190 
191   // Reclaim released/ignored buffers.
192   producer_queue_->HandleQueueEvents();
193   ASSERT_EQ(kBufferCount - 1, producer_queue_->count());
194 
195   // Post another buffer.
196   producer_status = producer_queue_->Dequeue(0, &slot, &fence);
197   ASSERT_TRUE(producer_status.ok());
198   producer_buffer = producer_status.take();
199   ASSERT_NE(nullptr, producer_buffer);
200   ASSERT_EQ(0, producer_buffer->Post<void>({}));
201 
202   // Verify that the consumer queue receives it.
203   EXPECT_EQ(1u, consumer_queue_->count());
204   EXPECT_TRUE(consumer_queue_->HandleQueueEvents());
205   EXPECT_EQ(2u, consumer_queue_->count());
206 
207   // Dequeue and acquire/release (discard) buffers on the consumer end.
208   auto consumer_status = consumer_queue_->Dequeue(0, &slot, &fence);
209   ASSERT_TRUE(consumer_status.ok());
210   auto consumer_buffer = consumer_status.take();
211   ASSERT_NE(nullptr, consumer_buffer);
212   consumer_buffer->Discard();
213 
214   // Buffer should be returned to the producer queue without being handled by
215   // the silent consumer queue.
216   EXPECT_EQ(1u, consumer_queue_->count());
217   EXPECT_EQ(kBufferCount - 2, producer_queue_->count());
218   EXPECT_TRUE(producer_queue_->HandleQueueEvents());
219   EXPECT_EQ(kBufferCount - 1, producer_queue_->count());
220 }
221 
222 struct TestMetadata {
223   char a;
224   int32_t b;
225   int64_t c;
226 };
227 
TEST_F(BufferHubQueueTest,TestMetadata)228 TEST_F(BufferHubQueueTest, TestMetadata) {
229   ASSERT_TRUE(CreateQueues<TestMetadata>());
230   AllocateBuffer();
231 
232   std::vector<TestMetadata> ms = {
233       {'0', 0, 0}, {'1', 10, 3333}, {'@', 123, 1000000000}};
234 
235   for (auto mi : ms) {
236     size_t slot;
237     LocalHandle fence;
238     auto p1_status = producer_queue_->Dequeue(0, &slot, &fence);
239     ASSERT_TRUE(p1_status.ok());
240     auto p1 = p1_status.take();
241     ASSERT_NE(nullptr, p1);
242     ASSERT_EQ(p1->Post(LocalHandle(-1), &mi, sizeof(mi)), 0);
243     TestMetadata mo;
244     auto c1_status = consumer_queue_->Dequeue(0, &slot, &mo, &fence);
245     ASSERT_TRUE(c1_status.ok());
246     auto c1 = c1_status.take();
247     ASSERT_EQ(mi.a, mo.a);
248     ASSERT_EQ(mi.b, mo.b);
249     ASSERT_EQ(mi.c, mo.c);
250     c1->Release(LocalHandle(-1));
251   }
252 }
253 
TEST_F(BufferHubQueueTest,TestMetadataMismatch)254 TEST_F(BufferHubQueueTest, TestMetadataMismatch) {
255   ASSERT_TRUE(CreateQueues<int64_t>());
256   AllocateBuffer();
257 
258   int64_t mi = 3;
259   size_t slot;
260   LocalHandle fence;
261   auto p1_status = producer_queue_->Dequeue(0, &slot, &fence);
262   ASSERT_TRUE(p1_status.ok());
263   auto p1 = p1_status.take();
264   ASSERT_NE(nullptr, p1);
265   ASSERT_EQ(p1->Post(LocalHandle(-1), &mi, sizeof(mi)), 0);
266 
267   int32_t mo;
268   // Acquire a buffer with mismatched metadata is not OK.
269   auto c1_status = consumer_queue_->Dequeue(0, &slot, &mo, &fence);
270   ASSERT_FALSE(c1_status.ok());
271 }
272 
TEST_F(BufferHubQueueTest,TestEnqueue)273 TEST_F(BufferHubQueueTest, TestEnqueue) {
274   ASSERT_TRUE(CreateQueues<int64_t>());
275   AllocateBuffer();
276 
277   size_t slot;
278   LocalHandle fence;
279   auto p1_status = producer_queue_->Dequeue(0, &slot, &fence);
280   ASSERT_TRUE(p1_status.ok());
281   auto p1 = p1_status.take();
282   ASSERT_NE(nullptr, p1);
283 
284   int64_t mo;
285   producer_queue_->Enqueue(p1, slot);
286   auto c1_status = consumer_queue_->Dequeue(0, &slot, &mo, &fence);
287   ASSERT_FALSE(c1_status.ok());
288 }
289 
TEST_F(BufferHubQueueTest,TestAllocateBuffer)290 TEST_F(BufferHubQueueTest, TestAllocateBuffer) {
291   ASSERT_TRUE(CreateQueues<int64_t>());
292 
293   size_t s1;
294   AllocateBuffer();
295   LocalHandle fence;
296   auto p1_status = producer_queue_->Dequeue(0, &s1, &fence);
297   ASSERT_TRUE(p1_status.ok());
298   auto p1 = p1_status.take();
299   ASSERT_NE(nullptr, p1);
300 
301   // producer queue is exhausted
302   size_t s2;
303   auto p2_status = producer_queue_->Dequeue(0, &s2, &fence);
304   ASSERT_FALSE(p2_status.ok());
305   ASSERT_EQ(ETIMEDOUT, p2_status.error());
306 
307   // dynamically add buffer.
308   AllocateBuffer();
309   ASSERT_EQ(producer_queue_->count(), 1U);
310   ASSERT_EQ(producer_queue_->capacity(), 2U);
311 
312   // now we can dequeue again
313   p2_status = producer_queue_->Dequeue(0, &s2, &fence);
314   ASSERT_TRUE(p2_status.ok());
315   auto p2 = p2_status.take();
316   ASSERT_NE(nullptr, p2);
317   ASSERT_EQ(producer_queue_->count(), 0U);
318   // p1 and p2 should have different slot number
319   ASSERT_NE(s1, s2);
320 
321   // Consumer queue does not import buffers until |Dequeue| or |ImportBuffers|
322   // are called. So far consumer_queue_ should be empty.
323   ASSERT_EQ(consumer_queue_->count(), 0U);
324 
325   int64_t seq = 1;
326   ASSERT_EQ(p1->Post(LocalHandle(), seq), 0);
327   size_t cs1, cs2;
328   auto c1_status = consumer_queue_->Dequeue(0, &cs1, &seq, &fence);
329   ASSERT_TRUE(c1_status.ok());
330   auto c1 = c1_status.take();
331   ASSERT_NE(nullptr, c1);
332   ASSERT_EQ(consumer_queue_->count(), 0U);
333   ASSERT_EQ(consumer_queue_->capacity(), 2U);
334   ASSERT_EQ(cs1, s1);
335 
336   ASSERT_EQ(p2->Post(LocalHandle(), seq), 0);
337   auto c2_status = consumer_queue_->Dequeue(0, &cs2, &seq, &fence);
338   ASSERT_TRUE(c2_status.ok());
339   auto c2 = c2_status.take();
340   ASSERT_NE(nullptr, c2);
341   ASSERT_EQ(cs2, s2);
342 }
343 
TEST_F(BufferHubQueueTest,TestUsageSetMask)344 TEST_F(BufferHubQueueTest, TestUsageSetMask) {
345   const uint32_t set_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
346   ASSERT_TRUE(CreateQueues<int64_t>(set_mask, 0, 0, 0));
347 
348   // When allocation, leave out |set_mask| from usage bits on purpose.
349   size_t slot;
350   int ret = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
351                                             kBufferFormat, kBufferLayerCount,
352                                             kBufferUsage & ~set_mask, &slot);
353   ASSERT_EQ(0, ret);
354 
355   LocalHandle fence;
356   auto p1_status = producer_queue_->Dequeue(0, &slot, &fence);
357   ASSERT_TRUE(p1_status.ok());
358   auto p1 = p1_status.take();
359   ASSERT_EQ(p1->usage() & set_mask, set_mask);
360 }
361 
TEST_F(BufferHubQueueTest,TestUsageClearMask)362 TEST_F(BufferHubQueueTest, TestUsageClearMask) {
363   const uint32_t clear_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
364   ASSERT_TRUE(CreateQueues<int64_t>(0, clear_mask, 0, 0));
365 
366   // When allocation, add |clear_mask| into usage bits on purpose.
367   size_t slot;
368   int ret = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
369                                             kBufferLayerCount, kBufferFormat,
370                                             kBufferUsage | clear_mask, &slot);
371   ASSERT_EQ(0, ret);
372 
373   LocalHandle fence;
374   auto p1_status = producer_queue_->Dequeue(0, &slot, &fence);
375   ASSERT_TRUE(p1_status.ok());
376   auto p1 = p1_status.take();
377   ASSERT_EQ(0u, p1->usage() & clear_mask);
378 }
379 
TEST_F(BufferHubQueueTest,TestUsageDenySetMask)380 TEST_F(BufferHubQueueTest, TestUsageDenySetMask) {
381   const uint32_t deny_set_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
382   ASSERT_TRUE(CreateQueues<int64_t>(0, 0, deny_set_mask, 0));
383 
384   // Now that |deny_set_mask| is illegal, allocation without those bits should
385   // be able to succeed.
386   size_t slot;
387   int ret = producer_queue_->AllocateBuffer(
388       kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
389       kBufferUsage & ~deny_set_mask, &slot);
390   ASSERT_EQ(ret, 0);
391 
392   // While allocation with those bits should fail.
393   ret = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
394                                         kBufferLayerCount, kBufferFormat,
395                                         kBufferUsage | deny_set_mask, &slot);
396   ASSERT_EQ(ret, -EINVAL);
397 }
398 
TEST_F(BufferHubQueueTest,TestUsageDenyClearMask)399 TEST_F(BufferHubQueueTest, TestUsageDenyClearMask) {
400   const uint32_t deny_clear_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
401   ASSERT_TRUE(CreateQueues<int64_t>(0, 0, 0, deny_clear_mask));
402 
403   // Now that clearing |deny_clear_mask| is illegal (i.e. setting these bits are
404   // mandatory), allocation with those bits should be able to succeed.
405   size_t slot;
406   int ret = producer_queue_->AllocateBuffer(
407       kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
408       kBufferUsage | deny_clear_mask, &slot);
409   ASSERT_EQ(ret, 0);
410 
411   // While allocation without those bits should fail.
412   ret = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
413                                         kBufferLayerCount, kBufferFormat,
414                                         kBufferUsage & ~deny_clear_mask, &slot);
415   ASSERT_EQ(ret, -EINVAL);
416 }
417 
418 }  // namespace
419 
420 }  // namespace dvr
421 }  // namespace android
422