Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 97f5cf43 authored by Jiwen 'Steve' Cai's avatar Jiwen 'Steve' Cai
Browse files

Update buffer_hub_queue-test

Use new shared memory based bufferhub operations and clean up minor
code/test style issues (e.g. fixes unmatched types for comparing, and
avoids Yoda-style comparison).

Bug: 68732938
Test: buffer_hub_queue-test
Change-Id: I0b2e47850822d05356813dbd6627011b4149ce3b
parent a5bafdc5
Loading
Loading
Loading
Loading
+177 −137
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@ constexpr uint32_t kBufferHeight = 1;
constexpr uint32_t kBufferLayerCount = 1;
constexpr uint32_t kBufferFormat = HAL_PIXEL_FORMAT_BLOB;
constexpr uint64_t kBufferUsage = GRALLOC_USAGE_SW_READ_RARELY;
constexpr int kTimeoutMs = 100;
constexpr int kNoTimeout = 0;

class BufferHubQueueTest : public ::testing::Test {
 public:
@@ -84,41 +86,49 @@ class BufferHubQueueTest : public ::testing::Test {
};

TEST_F(BufferHubQueueTest, TestDequeue) {
  const size_t nb_dequeue_times = 16;
  const int64_t nb_dequeue_times = 16;

  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<size_t>().Build(),
                           UsagePolicy{}));
  ASSERT_TRUE(CreateQueues(config_builder_.Build(), UsagePolicy{}));

  // Allocate only one buffer.
  AllocateBuffer();

  // But dequeue multiple times.
  for (size_t i = 0; i < nb_dequeue_times; i++) {
  for (int64_t i = 0; i < nb_dequeue_times; i++) {
    size_t slot;
    LocalHandle fence;
    auto p1_status = producer_queue_->Dequeue(100, &slot, &fence);
    ASSERT_TRUE(p1_status.ok());
    DvrNativeBufferMetadata mi, mo;

    // Producer gains a buffer.
    auto p1_status = producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
    EXPECT_TRUE(p1_status.ok());
    auto p1 = p1_status.take();
    ASSERT_NE(nullptr, p1);
    size_t mi = i;
    ASSERT_EQ(p1->Post(LocalHandle(), &mi, sizeof(mi)), 0);
    size_t mo;
    auto c1_status = consumer_queue_->Dequeue(100, &slot, &mo, &fence);
    ASSERT_TRUE(c1_status.ok());
    ASSERT_NE(p1, nullptr);

    // Producer posts the buffer.
    mi.index = i;
    EXPECT_EQ(p1->PostAsync(&mi, LocalHandle()), 0);

    // Consumer acquires a buffer.
    auto c1_status = consumer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
    EXPECT_TRUE(c1_status.ok());
    auto c1 = c1_status.take();
    ASSERT_NE(nullptr, c1);
    ASSERT_EQ(mi, mo);
    c1->Release(LocalHandle());
    ASSERT_NE(c1, nullptr);
    EXPECT_EQ(mi.index, i);
    EXPECT_EQ(mo.index, i);

    // Consumer releases the buffer.
    EXPECT_EQ(c1->ReleaseAsync(&mi, LocalHandle()), 0);
  }
}

TEST_F(BufferHubQueueTest, TestProducerConsumer) {
  const size_t kBufferCount = 16;
  size_t slot;
  uint64_t seq;
  DvrNativeBufferMetadata mi, mo;
  LocalHandle fence;

  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<uint64_t>().Build(),
                           UsagePolicy{}));
  ASSERT_TRUE(CreateQueues(config_builder_.Build(), UsagePolicy{}));

  for (size_t i = 0; i < kBufferCount; i++) {
    AllocateBuffer();
@@ -133,8 +143,7 @@ TEST_F(BufferHubQueueTest, TestProducerConsumer) {
    ASSERT_EQ(consumer_queue_->capacity(), i);
    // Dequeue returns timeout since no buffer is ready to consumer, but
    // this implicitly triggers buffer import and bump up |capacity|.
    LocalHandle fence;
    auto status = consumer_queue_->Dequeue(100, &slot, &seq, &fence);
    auto status = consumer_queue_->Dequeue(kNoTimeout, &slot, &mo, &fence);
    ASSERT_FALSE(status.ok());
    ASSERT_EQ(ETIMEDOUT, status.error());
    ASSERT_EQ(consumer_queue_->capacity(), i + 1);
@@ -144,37 +153,37 @@ TEST_F(BufferHubQueueTest, TestProducerConsumer) {
  LocalHandle post_fence(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));

  for (size_t i = 0; i < kBufferCount; i++) {
    LocalHandle fence;

    // First time there is no buffer available to dequeue.
    auto consumer_status = consumer_queue_->Dequeue(100, &slot, &seq, &fence);
    auto consumer_status =
        consumer_queue_->Dequeue(kNoTimeout, &slot, &mo, &fence);
    ASSERT_FALSE(consumer_status.ok());
    ASSERT_EQ(ETIMEDOUT, consumer_status.error());
    ASSERT_EQ(consumer_status.error(), ETIMEDOUT);

    // Make sure Producer buffer is POSTED so that it's ready to Accquire
    // in the consumer's Dequeue() function.
    auto producer_status = producer_queue_->Dequeue(100, &slot, &fence);
    auto producer_status =
        producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
    ASSERT_TRUE(producer_status.ok());
    auto producer = producer_status.take();
    ASSERT_NE(nullptr, producer);

    uint64_t seq_in = static_cast<uint64_t>(i);
    ASSERT_EQ(producer->Post(post_fence, &seq_in, sizeof(seq_in)), 0);
    mi.index = static_cast<int64_t>(i);
    ASSERT_EQ(producer->PostAsync(&mi, post_fence), 0);

    // Second time the just the POSTED buffer should be dequeued.
    uint64_t seq_out = 0;
    consumer_status = consumer_queue_->Dequeue(100, &slot, &seq_out, &fence);
    consumer_status = consumer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
    ASSERT_TRUE(consumer_status.ok());
    EXPECT_TRUE(fence.IsValid());

    auto consumer = consumer_status.take();
    ASSERT_NE(nullptr, consumer);
    ASSERT_EQ(seq_in, seq_out);
    ASSERT_EQ(mi.index, mo.index);
  }
}

TEST_F(BufferHubQueueTest, TestRemoveBuffer) {
  ASSERT_TRUE(CreateProducerQueue(config_builder_.Build(), UsagePolicy{}));
  DvrNativeBufferMetadata mo;

  // Allocate buffers.
  const size_t kBufferCount = 4u;
@@ -203,7 +212,7 @@ TEST_F(BufferHubQueueTest, TestRemoveBuffer) {
  for (size_t i = 0; i < kBufferCount; i++) {
    Entry* entry = &buffers[i];
    auto producer_status = producer_queue_->Dequeue(
        /*timeout_ms=*/100, &entry->slot, &entry->fence);
        kTimeoutMs, &entry->slot, &mo, &entry->fence);
    ASSERT_TRUE(producer_status.ok());
    entry->buffer = producer_status.take();
    ASSERT_NE(nullptr, entry->buffer);
@@ -223,7 +232,7 @@ TEST_F(BufferHubQueueTest, TestRemoveBuffer) {
  buffers[0].buffer = nullptr;

  // Now the consumer queue should know it's gone.
  EXPECT_FALSE(WaitAndHandleOnce(consumer_queue_.get(), /*timeout_ms=*/100));
  EXPECT_FALSE(WaitAndHandleOnce(consumer_queue_.get(), kTimeoutMs));
  ASSERT_EQ(kBufferCount - 1, consumer_queue_->capacity());

  // Allocate a new buffer. This should take the first empty slot.
@@ -292,126 +301,154 @@ TEST_F(BufferHubQueueTest, TestMultipleConsumers) {
  ASSERT_NE(nullptr, silent_queue);

  // Check that silent queue doesn't import buffers on creation.
  EXPECT_EQ(0, silent_queue->capacity());
  EXPECT_EQ(silent_queue->capacity(), 0U);

  // Dequeue and post a buffer.
  size_t slot;
  LocalHandle fence;
  DvrNativeBufferMetadata mi, mo;
  auto producer_status =
      producer_queue_->Dequeue(/*timeout_ms=*/100, &slot, &fence);
  ASSERT_TRUE(producer_status.ok());
      producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
  EXPECT_TRUE(producer_status.ok());
  auto producer_buffer = producer_status.take();
  ASSERT_NE(nullptr, producer_buffer);
  ASSERT_EQ(0, producer_buffer->Post<void>({}));
  ASSERT_NE(producer_buffer, nullptr);
  EXPECT_EQ(producer_buffer->PostAsync(&mi, {}), 0);
  // After post, check the number of remaining available buffers.
  EXPECT_EQ(kBufferCount - 1, producer_queue_->count());
  EXPECT_EQ(producer_queue_->count(), kBufferCount - 1);

  // Currently we expect no buffer to be available prior to calling
  // WaitForBuffers/HandleQueueEvents.
  // TODO(eieio): Note this behavior may change in the future.
  EXPECT_EQ(0u, silent_queue->count());
  EXPECT_EQ(silent_queue->count(), 0U);
  EXPECT_FALSE(silent_queue->HandleQueueEvents());
  EXPECT_EQ(0u, silent_queue->count());
  EXPECT_EQ(silent_queue->count(), 0U);

  // Build a new consumer queue to test multi-consumer queue features.
  consumer_queue_ = silent_queue->CreateConsumerQueue();
  ASSERT_NE(nullptr, consumer_queue_);
  ASSERT_NE(consumer_queue_, nullptr);

  // Check that buffers are correctly imported on construction.
  EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
  EXPECT_EQ(1u, consumer_queue_->count());
  EXPECT_EQ(consumer_queue_->capacity(), kBufferCount);
  EXPECT_EQ(consumer_queue_->count(), 1U);

  // Reclaim released/ignored buffers.
  ASSERT_EQ(kBufferCount - 1, producer_queue_->count());
  EXPECT_EQ(producer_queue_->count(), kBufferCount - 1);

  usleep(10000);
  WaitAndHandleOnce(producer_queue_.get(), /*timeout_ms=*/100);
  ASSERT_EQ(kBufferCount - 1, producer_queue_->count());
  WaitAndHandleOnce(producer_queue_.get(), kTimeoutMs);
  EXPECT_EQ(producer_queue_->count(), kBufferCount - 1);

  // Post another buffer.
  producer_status = producer_queue_->Dequeue(/*timeout_ms=*/100, &slot, &fence);
  ASSERT_TRUE(producer_status.ok());
  producer_status = producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
  EXPECT_TRUE(producer_status.ok());
  producer_buffer = producer_status.take();
  ASSERT_NE(nullptr, producer_buffer);
  ASSERT_EQ(0, producer_buffer->Post<void>({}));
  ASSERT_NE(producer_buffer, nullptr);
  EXPECT_EQ(producer_buffer->PostAsync(&mi, {}), 0);

  // Verify that the consumer queue receives it.
  size_t consumer_queue_count = consumer_queue_->count();
  WaitAndHandleOnce(consumer_queue_.get(), /*timeout_ms=*/100);
  EXPECT_LT(consumer_queue_count, consumer_queue_->count());
  WaitAndHandleOnce(consumer_queue_.get(), kTimeoutMs);
  EXPECT_GT(consumer_queue_->count(), consumer_queue_count);

  // Save the current consumer queue buffer count to compare after the dequeue.
  consumer_queue_count = consumer_queue_->count();

  // Dequeue and acquire/release (discard) buffers on the consumer end.
  auto consumer_status =
      consumer_queue_->Dequeue(/*timeout_ms=*/100, &slot, &fence);
  ASSERT_TRUE(consumer_status.ok());
      consumer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
  EXPECT_TRUE(consumer_status.ok());
  auto consumer_buffer = consumer_status.take();
  ASSERT_NE(nullptr, consumer_buffer);
  ASSERT_NE(consumer_buffer, nullptr);
  consumer_buffer->Discard();

  // Buffer should be returned to the producer queue without being handled by
  // the silent consumer queue.
  EXPECT_GT(consumer_queue_count, consumer_queue_->count());
  EXPECT_EQ(kBufferCount - 2, producer_queue_->count());
  EXPECT_TRUE(producer_queue_->HandleQueueEvents());
  EXPECT_EQ(kBufferCount - 1, producer_queue_->count());
  EXPECT_LT(consumer_queue_->count(), consumer_queue_count);
  EXPECT_EQ(producer_queue_->count(), kBufferCount - 2);

  WaitAndHandleOnce(producer_queue_.get(), kTimeoutMs);
  EXPECT_EQ(producer_queue_->count(), kBufferCount - 1);
}

struct TestMetadata {
struct TestUserMetadata {
  char a;
  int32_t b;
  int64_t c;
};

TEST_F(BufferHubQueueTest, TestMetadata) {
  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<TestMetadata>().Build(),
                           UsagePolicy{}));
constexpr uint64_t kUserMetadataSize =
    static_cast<uint64_t>(sizeof(TestUserMetadata));

TEST_F(BufferHubQueueTest, TestUserMetadata) {
  ASSERT_TRUE(CreateQueues(
      config_builder_.SetMetadata<TestUserMetadata>().Build(), UsagePolicy{}));

  AllocateBuffer();

  std::vector<TestMetadata> ms = {
  std::vector<TestUserMetadata> user_metadata_list = {
      {'0', 0, 0}, {'1', 10, 3333}, {'@', 123, 1000000000}};

  for (auto mi : ms) {
  for (auto user_metadata : user_metadata_list) {
    size_t slot;
    LocalHandle fence;
    auto p1_status = producer_queue_->Dequeue(100, &slot, &fence);
    ASSERT_TRUE(p1_status.ok());
    DvrNativeBufferMetadata mi, mo;

    auto p1_status = producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
    EXPECT_TRUE(p1_status.ok());
    auto p1 = p1_status.take();
    ASSERT_NE(nullptr, p1);
    ASSERT_EQ(p1->Post(LocalHandle(-1), &mi, sizeof(mi)), 0);
    TestMetadata mo;
    auto c1_status = consumer_queue_->Dequeue(100, &slot, &mo, &fence);
    ASSERT_TRUE(c1_status.ok());
    ASSERT_NE(p1, nullptr);

    // TODO(b/69469185): Test against metadata from consumer once we implement
    // release metadata properly.
    // EXPECT_EQ(mo.user_metadata_ptr, 0U);
    // EXPECT_EQ(mo.user_metadata_size, 0U);

    mi.user_metadata_size = kUserMetadataSize;
    mi.user_metadata_ptr = reinterpret_cast<uint64_t>(&user_metadata);
    EXPECT_EQ(p1->PostAsync(&mi, {}), 0);
    auto c1_status = consumer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
    EXPECT_TRUE(c1_status.ok());
    auto c1 = c1_status.take();
    ASSERT_EQ(mi.a, mo.a);
    ASSERT_EQ(mi.b, mo.b);
    ASSERT_EQ(mi.c, mo.c);
    c1->Release(LocalHandle(-1));
    ASSERT_NE(c1, nullptr);

    EXPECT_EQ(mo.user_metadata_size, kUserMetadataSize);
    auto out_user_metadata =
        reinterpret_cast<TestUserMetadata*>(mo.user_metadata_ptr);
    EXPECT_EQ(user_metadata.a, out_user_metadata->a);
    EXPECT_EQ(user_metadata.b, out_user_metadata->b);
    EXPECT_EQ(user_metadata.c, out_user_metadata->c);

    // When release, empty metadata is also legit.
    mi.user_metadata_size = 0U;
    mi.user_metadata_ptr = 0U;
    c1->ReleaseAsync(&mi, {});
  }
}

TEST_F(BufferHubQueueTest, TestMetadataMismatch) {
  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
                           UsagePolicy{}));
TEST_F(BufferHubQueueTest, TestUserMetadataMismatch) {
  ASSERT_TRUE(CreateQueues(
      config_builder_.SetMetadata<TestUserMetadata>().Build(), UsagePolicy{}));

  AllocateBuffer();

  int64_t mi = 3;
  TestUserMetadata user_metadata;
  size_t slot;
  LocalHandle fence;
  auto p1_status = producer_queue_->Dequeue(100, &slot, &fence);
  ASSERT_TRUE(p1_status.ok());
  DvrNativeBufferMetadata mi, mo;
  auto p1_status = producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
  EXPECT_TRUE(p1_status.ok());
  auto p1 = p1_status.take();
  ASSERT_NE(nullptr, p1);
  ASSERT_EQ(p1->Post(LocalHandle(-1), &mi, sizeof(mi)), 0);
  ASSERT_NE(p1, nullptr);

  int32_t mo;
  // Acquire a buffer with mismatched metadata is not OK.
  auto c1_status = consumer_queue_->Dequeue(100, &slot, &mo, &fence);
  ASSERT_FALSE(c1_status.ok());
  // Post with mismatched user metadata size will fail. But the producer buffer
  // itself should stay untouched.
  mi.user_metadata_ptr = reinterpret_cast<uint64_t>(&user_metadata);
  mi.user_metadata_size = kUserMetadataSize + 1;
  EXPECT_EQ(p1->PostAsync(&mi, {}), -E2BIG);
  // Post with the exact same user metdata size can success.
  mi.user_metadata_ptr = reinterpret_cast<uint64_t>(&user_metadata);
  mi.user_metadata_size = kUserMetadataSize;
  EXPECT_EQ(p1->PostAsync(&mi, {}), 0);
}

TEST_F(BufferHubQueueTest, TestEnqueue) {
@@ -421,32 +458,32 @@ TEST_F(BufferHubQueueTest, TestEnqueue) {

  size_t slot;
  LocalHandle fence;
  auto p1_status = producer_queue_->Dequeue(100, &slot, &fence);
  DvrNativeBufferMetadata mo;
  auto p1_status = producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
  ASSERT_TRUE(p1_status.ok());
  auto p1 = p1_status.take();
  ASSERT_NE(nullptr, p1);

  int64_t mo;
  producer_queue_->Enqueue(p1, slot, 0ULL);
  auto c1_status = consumer_queue_->Dequeue(100, &slot, &mo, &fence);
  auto c1_status = consumer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
  ASSERT_FALSE(c1_status.ok());
}

TEST_F(BufferHubQueueTest, TestAllocateBuffer) {
  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
                           UsagePolicy{}));
  ASSERT_TRUE(CreateQueues(config_builder_.Build(), UsagePolicy{}));

  size_t s1;
  size_t ps1;
  AllocateBuffer();
  LocalHandle fence;
  auto p1_status = producer_queue_->Dequeue(100, &s1, &fence);
  DvrNativeBufferMetadata mi, mo;
  auto p1_status = producer_queue_->Dequeue(kTimeoutMs, &ps1, &mo, &fence);
  ASSERT_TRUE(p1_status.ok());
  auto p1 = p1_status.take();
  ASSERT_NE(nullptr, p1);
  ASSERT_NE(p1, nullptr);

  // producer queue is exhausted
  size_t s2;
  auto p2_status = producer_queue_->Dequeue(100, &s2, &fence);
  size_t ps2;
  auto p2_status = producer_queue_->Dequeue(kTimeoutMs, &ps2, &mo, &fence);
  ASSERT_FALSE(p2_status.ok());
  ASSERT_EQ(ETIMEDOUT, p2_status.error());

@@ -456,41 +493,43 @@ TEST_F(BufferHubQueueTest, TestAllocateBuffer) {
  ASSERT_EQ(producer_queue_->capacity(), 2U);

  // now we can dequeue again
  p2_status = producer_queue_->Dequeue(100, &s2, &fence);
  p2_status = producer_queue_->Dequeue(kTimeoutMs, &ps2, &mo, &fence);
  ASSERT_TRUE(p2_status.ok());
  auto p2 = p2_status.take();
  ASSERT_NE(nullptr, p2);
  ASSERT_NE(p2, nullptr);
  ASSERT_EQ(producer_queue_->count(), 0U);
  // p1 and p2 should have different slot number
  ASSERT_NE(s1, s2);
  ASSERT_NE(ps1, ps2);

  // Consumer queue does not import buffers until |Dequeue| or |ImportBuffers|
  // are called. So far consumer_queue_ should be empty.
  ASSERT_EQ(consumer_queue_->count(), 0U);

  int64_t seq = 1;
  ASSERT_EQ(p1->Post(LocalHandle(), seq), 0);
  mi.index = seq;
  ASSERT_EQ(p1->PostAsync(&mi, {}), 0);

  size_t cs1, cs2;
  auto c1_status = consumer_queue_->Dequeue(100, &cs1, &seq, &fence);
  auto c1_status = consumer_queue_->Dequeue(kTimeoutMs, &cs1, &mo, &fence);
  ASSERT_TRUE(c1_status.ok());
  auto c1 = c1_status.take();
  ASSERT_NE(nullptr, c1);
  ASSERT_NE(c1, nullptr);
  ASSERT_EQ(consumer_queue_->count(), 0U);
  ASSERT_EQ(consumer_queue_->capacity(), 2U);
  ASSERT_EQ(cs1, s1);
  ASSERT_EQ(cs1, ps1);

  ASSERT_EQ(p2->Post(LocalHandle(), seq), 0);
  auto c2_status = consumer_queue_->Dequeue(100, &cs2, &seq, &fence);
  ASSERT_EQ(p2->PostAsync(&mi, {}), 0);
  auto c2_status = consumer_queue_->Dequeue(kTimeoutMs, &cs2, &mo, &fence);
  ASSERT_TRUE(c2_status.ok());
  auto c2 = c2_status.take();
  ASSERT_NE(nullptr, c2);
  ASSERT_EQ(cs2, s2);
  ASSERT_NE(c2, nullptr);
  ASSERT_EQ(cs2, ps2);
}

TEST_F(BufferHubQueueTest, TestUsageSetMask) {
  const uint32_t set_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
                           UsagePolicy{set_mask, 0, 0, 0}));
  ASSERT_TRUE(
      CreateQueues(config_builder_.Build(), UsagePolicy{set_mask, 0, 0, 0}));

  // When allocation, leave out |set_mask| from usage bits on purpose.
  auto status = producer_queue_->AllocateBuffer(
@@ -500,7 +539,8 @@ TEST_F(BufferHubQueueTest, TestUsageSetMask) {

  LocalHandle fence;
  size_t slot;
  auto p1_status = producer_queue_->Dequeue(100, &slot, &fence);
  DvrNativeBufferMetadata mo;
  auto p1_status = producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
  ASSERT_TRUE(p1_status.ok());
  auto p1 = p1_status.take();
  ASSERT_EQ(p1->usage() & set_mask, set_mask);
@@ -508,8 +548,8 @@ TEST_F(BufferHubQueueTest, TestUsageSetMask) {

TEST_F(BufferHubQueueTest, TestUsageClearMask) {
  const uint32_t clear_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
                           UsagePolicy{0, clear_mask, 0, 0}));
  ASSERT_TRUE(
      CreateQueues(config_builder_.Build(), UsagePolicy{0, clear_mask, 0, 0}));

  // When allocation, add |clear_mask| into usage bits on purpose.
  auto status = producer_queue_->AllocateBuffer(
@@ -519,10 +559,11 @@ TEST_F(BufferHubQueueTest, TestUsageClearMask) {

  LocalHandle fence;
  size_t slot;
  auto p1_status = producer_queue_->Dequeue(100, &slot, &fence);
  DvrNativeBufferMetadata mo;
  auto p1_status = producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
  ASSERT_TRUE(p1_status.ok());
  auto p1 = p1_status.take();
  ASSERT_EQ(0u, p1->usage() & clear_mask);
  ASSERT_EQ(p1->usage() & clear_mask, 0U);
}

TEST_F(BufferHubQueueTest, TestUsageDenySetMask) {
@@ -600,16 +641,15 @@ TEST_F(BufferHubQueueTest, TestFreeAllBuffers) {
  EXPECT_EQ(producer_queue_->capacity(), num_buffers);

  size_t slot;
  uint64_t seq;
  LocalHandle fence;
  pdx::Status<void> status;
  pdx::Status<std::shared_ptr<BufferConsumer>> consumer_status;
  pdx::Status<std::shared_ptr<BufferProducer>> producer_status;
  std::shared_ptr<BufferConsumer> consumer_buffer;
  std::shared_ptr<BufferProducer> producer_buffer;
  DvrNativeBufferMetadata mi, mo;

  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<uint64_t>().Build(),
                           UsagePolicy{}));
  ASSERT_TRUE(CreateQueues(config_builder_.Build(), UsagePolicy{}));

  // Free all buffers when buffers are avaible for dequeue.
  CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount);
@@ -618,7 +658,7 @@ TEST_F(BufferHubQueueTest, TestFreeAllBuffers) {

  // Free all buffers when one buffer is dequeued.
  CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount);
  producer_status = producer_queue_->Dequeue(100, &slot, &fence);
  producer_status = producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
  ASSERT_TRUE(producer_status.ok());
  status = producer_queue_->FreeAllBuffers();
  EXPECT_TRUE(status.ok());
@@ -626,7 +666,7 @@ TEST_F(BufferHubQueueTest, TestFreeAllBuffers) {
  // Free all buffers when all buffers are dequeued.
  CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount);
  for (size_t i = 0; i < kBufferCount; i++) {
    producer_status = producer_queue_->Dequeue(100, &slot, &fence);
    producer_status = producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
    ASSERT_TRUE(producer_status.ok());
  }
  status = producer_queue_->FreeAllBuffers();
@@ -634,22 +674,22 @@ TEST_F(BufferHubQueueTest, TestFreeAllBuffers) {

  // Free all buffers when one buffer is posted.
  CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount);
  producer_status = producer_queue_->Dequeue(100, &slot, &fence);
  producer_status = producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
  ASSERT_TRUE(producer_status.ok());
  producer_buffer = producer_status.take();
  ASSERT_NE(nullptr, producer_buffer);
  ASSERT_EQ(0, producer_buffer->Post(fence, &seq, sizeof(seq)));
  ASSERT_EQ(0, producer_buffer->PostAsync(&mi, fence));
  status = producer_queue_->FreeAllBuffers();
  EXPECT_TRUE(status.ok());

  // Free all buffers when all buffers are posted.
  CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount);
  for (size_t i = 0; i < kBufferCount; i++) {
    producer_status = producer_queue_->Dequeue(100, &slot, &fence);
    producer_status = producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
    ASSERT_TRUE(producer_status.ok());
    producer_buffer = producer_status.take();
    ASSERT_NE(nullptr, producer_buffer);
    ASSERT_EQ(0, producer_buffer->Post(fence, &seq, sizeof(seq)));
    ASSERT_NE(producer_buffer, nullptr);
    ASSERT_EQ(producer_buffer->PostAsync(&mi, fence), 0);
  }
  status = producer_queue_->FreeAllBuffers();
  EXPECT_TRUE(status.ok());
@@ -657,12 +697,12 @@ TEST_F(BufferHubQueueTest, TestFreeAllBuffers) {
  // Free all buffers when all buffers are acquired.
  CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount);
  for (size_t i = 0; i < kBufferCount; i++) {
    producer_status = producer_queue_->Dequeue(100, &slot, &fence);
    producer_status = producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
    ASSERT_TRUE(producer_status.ok());
    producer_buffer = producer_status.take();
    ASSERT_NE(nullptr, producer_buffer);
    ASSERT_EQ(0, producer_buffer->Post(fence, &seq, sizeof(seq)));
    consumer_status = consumer_queue_->Dequeue(100, &slot, &seq, &fence);
    ASSERT_NE(producer_buffer, nullptr);
    ASSERT_EQ(producer_buffer->PostAsync(&mi, fence), 0);
    consumer_status = consumer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
    ASSERT_TRUE(consumer_status.ok());
  }

@@ -750,18 +790,18 @@ TEST_F(BufferHubQueueTest, TestProducerExportToParcelable) {
  EXPECT_TRUE(s3.ok());

  std::shared_ptr<BufferProducer> p1 = s3.take();
  EXPECT_NE(p1, nullptr);
  ASSERT_NE(p1, nullptr);

  producer_meta.timestamp = 42;
  EXPECT_EQ(p1->PostAsync(&producer_meta, LocalHandle()), 0);

  // Make sure the buffer can be dequeued from consumer side.
  auto s4 = consumer_queue_->Dequeue(100, &slot, &consumer_meta, &fence);
  auto s4 = consumer_queue_->Dequeue(kTimeoutMs, &slot, &consumer_meta, &fence);
  EXPECT_TRUE(s4.ok());
  EXPECT_EQ(consumer_queue_->capacity(), 1U);

  auto consumer = s4.take();
  EXPECT_NE(consumer, nullptr);
  ASSERT_NE(consumer, nullptr);
  EXPECT_EQ(producer_meta.timestamp, consumer_meta.timestamp);
}

@@ -817,18 +857,18 @@ TEST_F(BufferHubQueueTest, TestCreateConsumerParcelable) {
  EXPECT_TRUE(s2.ok());

  std::shared_ptr<BufferProducer> p1 = s2.take();
  EXPECT_NE(p1, nullptr);
  ASSERT_NE(p1, nullptr);

  producer_meta.timestamp = 42;
  EXPECT_EQ(p1->PostAsync(&producer_meta, LocalHandle()), 0);

  // Make sure the buffer can be dequeued from consumer side.
  auto s3 = consumer_queue_->Dequeue(100, &slot, &consumer_meta, &fence);
  auto s3 = consumer_queue_->Dequeue(kTimeoutMs, &slot, &consumer_meta, &fence);
  EXPECT_TRUE(s3.ok());
  EXPECT_EQ(consumer_queue_->capacity(), 1U);

  auto consumer = s3.take();
  EXPECT_NE(consumer, nullptr);
  ASSERT_NE(consumer, nullptr);
  EXPECT_EQ(producer_meta.timestamp, consumer_meta.timestamp);
}