Home | History | Annotate | Download | only in tests
      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>
     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 
     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>
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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