1e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <base/logging.h>
2e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <private/dvr/buffer_hub_client.h>
3e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <private/dvr/buffer_hub_queue_client.h>
4e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
5e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <gtest/gtest.h>
652ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka#include <poll.h>
752ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka#include <sys/eventfd.h>
8e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
9e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <vector>
10e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
11b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka// Enable/disable debug logging.
12b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka#define TRACE 0
13b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka
14e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace android {
15e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace dvr {
16e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
17e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing pdx::LocalHandle;
18e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
19e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace {
20e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
216bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Caiconstexpr uint32_t kBufferWidth = 100;
226bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Caiconstexpr uint32_t kBufferHeight = 1;
236bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Caiconstexpr uint32_t kBufferLayerCount = 1;
246bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Caiconstexpr uint32_t kBufferFormat = HAL_PIXEL_FORMAT_BLOB;
256bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Caiconstexpr uint64_t kBufferUsage = GRALLOC_USAGE_SW_READ_RARELY;
26e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
27e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoclass BufferHubQueueTest : public ::testing::Test {
28e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko public:
296bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  bool CreateProducerQueue(const ProducerQueueConfig& config,
306bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai                           const UsagePolicy& usage) {
316bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai    producer_queue_ = ProducerQueue::Create(config, usage);
322b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka    return producer_queue_ != nullptr;
332b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  }
34e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
352b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  bool CreateConsumerQueue() {
362b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka    if (producer_queue_) {
372b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka      consumer_queue_ = producer_queue_->CreateConsumerQueue();
382b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka      return consumer_queue_ != nullptr;
392b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka    } else {
401db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka      return false;
412b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka    }
422b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  }
431db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka
446bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  bool CreateQueues(const ProducerQueueConfig& config,
456bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai                    const UsagePolicy& usage) {
466bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai    return CreateProducerQueue(config, usage) && CreateConsumerQueue();
47e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
48e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
49b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  void AllocateBuffer(size_t* slot_out = nullptr) {
50e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    // Create producer buffer.
5152ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    auto status = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
5252ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka                                                  kBufferLayerCount,
5352ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka                                                  kBufferFormat, kBufferUsage);
54b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka
558fa4e107ab6cbc24c0e54d44db3341f006fe939aJiwen 'Steve' Cai    ASSERT_TRUE(status.ok());
568fa4e107ab6cbc24c0e54d44db3341f006fe939aJiwen 'Steve' Cai    size_t slot = status.take();
57b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka    if (slot_out)
58b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka      *slot_out = slot;
59e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
60e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
6152ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  bool WaitAndHandleOnce(BufferHubQueue* queue, int timeout_ms) {
6252ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    pollfd pfd{queue->queue_fd(), POLLIN, 0};
6352ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    int ret;
6452ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    do {
6552ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka      ret = poll(&pfd, 1, timeout_ms);
6652ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    } while (ret == -1 && errno == EINTR);
6752ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka
6852ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    if (ret < 0) {
6952ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka      ALOGW("Failed to poll queue %d's event fd, error: %s.", queue->id(),
7052ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka            strerror(errno));
7152ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka      return false;
7252ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    } else if (ret == 0) {
7352ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka      return false;
7452ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    }
7552ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    return queue->HandleQueueEvents();
7652ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  }
7752ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka
78e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko protected:
796bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  ProducerQueueConfigBuilder config_builder_;
80e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::unique_ptr<ProducerQueue> producer_queue_;
81e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::unique_ptr<ConsumerQueue> consumer_queue_;
82e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko};
83e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
84e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoTEST_F(BufferHubQueueTest, TestDequeue) {
85e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  const size_t nb_dequeue_times = 16;
86e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
876bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<size_t>().Build(),
886bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai                           UsagePolicy{}));
89e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
90e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Allocate only one buffer.
91e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  AllocateBuffer();
92e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
93e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // But dequeue multiple times.
94e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  for (size_t i = 0; i < nb_dequeue_times; i++) {
95e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    size_t slot;
96ed6543224138fd753eeea909918bb8d1d2efb1e6Jiwen 'Steve' Cai    LocalHandle fence;
9752ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    auto p1_status = producer_queue_->Dequeue(100, &slot, &fence);
989d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka    ASSERT_TRUE(p1_status.ok());
999d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka    auto p1 = p1_status.take();
100e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ASSERT_NE(nullptr, p1);
101e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    size_t mi = i;
102e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ASSERT_EQ(p1->Post(LocalHandle(), &mi, sizeof(mi)), 0);
103e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    size_t mo;
1049d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka    auto c1_status = consumer_queue_->Dequeue(100, &slot, &mo, &fence);
1059d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka    ASSERT_TRUE(c1_status.ok());
1069d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka    auto c1 = c1_status.take();
107e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ASSERT_NE(nullptr, c1);
108e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ASSERT_EQ(mi, mo);
109e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    c1->Release(LocalHandle());
110e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
111e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
112e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
113e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoTEST_F(BufferHubQueueTest, TestProducerConsumer) {
114b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  const size_t kBufferCount = 16;
115e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  size_t slot;
116e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  uint64_t seq;
117e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
1186bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<uint64_t>().Build(),
1196bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai                           UsagePolicy{}));
120e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
121b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  for (size_t i = 0; i < kBufferCount; i++) {
122e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    AllocateBuffer();
123e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
124e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    // Producer queue has all the available buffers on initialize.
125e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ASSERT_EQ(producer_queue_->count(), i + 1);
126e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ASSERT_EQ(producer_queue_->capacity(), i + 1);
127e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
128e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    // Consumer queue has no avaiable buffer on initialize.
129e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ASSERT_EQ(consumer_queue_->count(), 0U);
130e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    // Consumer queue does not import buffers until a dequeue is issued.
131e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ASSERT_EQ(consumer_queue_->capacity(), i);
1329d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka    // Dequeue returns timeout since no buffer is ready to consumer, but
133e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    // this implicitly triggers buffer import and bump up |capacity|.
134ed6543224138fd753eeea909918bb8d1d2efb1e6Jiwen 'Steve' Cai    LocalHandle fence;
13552ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    auto status = consumer_queue_->Dequeue(100, &slot, &seq, &fence);
1369d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka    ASSERT_FALSE(status.ok());
1379d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka    ASSERT_EQ(ETIMEDOUT, status.error());
138e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ASSERT_EQ(consumer_queue_->capacity(), i + 1);
139e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
140e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
14152ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  // Use eventfd as a stand-in for a fence.
14252ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  LocalHandle post_fence(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
143b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka
144b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  for (size_t i = 0; i < kBufferCount; i++) {
145ed6543224138fd753eeea909918bb8d1d2efb1e6Jiwen 'Steve' Cai    LocalHandle fence;
146b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka
147b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka    // First time there is no buffer available to dequeue.
14852ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    auto consumer_status = consumer_queue_->Dequeue(100, &slot, &seq, &fence);
1499d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka    ASSERT_FALSE(consumer_status.ok());
1509d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka    ASSERT_EQ(ETIMEDOUT, consumer_status.error());
151e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
152b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka    // Make sure Producer buffer is POSTED so that it's ready to Accquire
153e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    // in the consumer's Dequeue() function.
15452ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    auto producer_status = producer_queue_->Dequeue(100, &slot, &fence);
1559d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka    ASSERT_TRUE(producer_status.ok());
1569d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka    auto producer = producer_status.take();
157e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ASSERT_NE(nullptr, producer);
158e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
159e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    uint64_t seq_in = static_cast<uint64_t>(i);
160b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka    ASSERT_EQ(producer->Post(post_fence, &seq_in, sizeof(seq_in)), 0);
161e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
162b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka    // Second time the just the POSTED buffer should be dequeued.
163e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    uint64_t seq_out = 0;
16452ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    consumer_status = consumer_queue_->Dequeue(100, &slot, &seq_out, &fence);
1659d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka    ASSERT_TRUE(consumer_status.ok());
166b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka    EXPECT_TRUE(fence.IsValid());
167b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka
1689d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka    auto consumer = consumer_status.take();
169e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ASSERT_NE(nullptr, consumer);
170e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ASSERT_EQ(seq_in, seq_out);
171e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
172e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
173e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
174bb701dbac7c9c9eb2a7d0ec48c5e020f1272de13Jiwen 'Steve' CaiTEST_F(BufferHubQueueTest, TestRemoveBuffer) {
1756bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  ASSERT_TRUE(CreateProducerQueue(config_builder_.Build(), UsagePolicy{}));
176b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka
177b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // Allocate buffers.
178b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  const size_t kBufferCount = 4u;
179b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  for (size_t i = 0; i < kBufferCount; i++) {
180b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka    AllocateBuffer();
181b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  }
182b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  ASSERT_EQ(kBufferCount, producer_queue_->count());
183b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  ASSERT_EQ(kBufferCount, producer_queue_->capacity());
184b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka
185b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  consumer_queue_ = producer_queue_->CreateConsumerQueue();
186b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  ASSERT_NE(nullptr, consumer_queue_);
187b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka
188b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // Check that buffers are correctly imported on construction.
189b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
190b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  EXPECT_EQ(0u, consumer_queue_->count());
191b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka
192b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // Dequeue all the buffers and keep track of them in an array. This prevents
193b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // the producer queue ring buffer ref counts from interfering with the tests.
194b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  struct Entry {
195b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka    std::shared_ptr<BufferProducer> buffer;
196b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka    LocalHandle fence;
197b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka    size_t slot;
198b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  };
199b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  std::array<Entry, kBufferCount> buffers;
200b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka
201b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  for (size_t i = 0; i < kBufferCount; i++) {
202b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka    Entry* entry = &buffers[i];
20352ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    auto producer_status = producer_queue_->Dequeue(
20452ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka        /*timeout_ms=*/100, &entry->slot, &entry->fence);
205b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka    ASSERT_TRUE(producer_status.ok());
206b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka    entry->buffer = producer_status.take();
207b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka    ASSERT_NE(nullptr, entry->buffer);
208b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  }
209b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka
210bb701dbac7c9c9eb2a7d0ec48c5e020f1272de13Jiwen 'Steve' Cai  // Remove a buffer and make sure both queues reflect the change.
211bb701dbac7c9c9eb2a7d0ec48c5e020f1272de13Jiwen 'Steve' Cai  ASSERT_TRUE(producer_queue_->RemoveBuffer(buffers[0].slot));
212b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  EXPECT_EQ(kBufferCount - 1, producer_queue_->capacity());
213b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka
214bb701dbac7c9c9eb2a7d0ec48c5e020f1272de13Jiwen 'Steve' Cai  // As long as the removed buffer is still alive the consumer queue won't know
215b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // its gone.
216b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
217b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  EXPECT_FALSE(consumer_queue_->HandleQueueEvents());
218b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
219b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka
220bb701dbac7c9c9eb2a7d0ec48c5e020f1272de13Jiwen 'Steve' Cai  // Release the removed buffer.
221b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  buffers[0].buffer = nullptr;
222b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka
223b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // Now the consumer queue should know it's gone.
22452ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  EXPECT_FALSE(WaitAndHandleOnce(consumer_queue_.get(), /*timeout_ms=*/100));
22552ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  ASSERT_EQ(kBufferCount - 1, consumer_queue_->capacity());
226b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka
227b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // Allocate a new buffer. This should take the first empty slot.
228b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  size_t slot;
229b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  AllocateBuffer(&slot);
230b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  ALOGE_IF(TRACE, "ALLOCATE %zu", slot);
231b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  EXPECT_EQ(buffers[0].slot, slot);
232b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  EXPECT_EQ(kBufferCount, producer_queue_->capacity());
233b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka
234b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // The consumer queue should pick up the new buffer.
235b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  EXPECT_EQ(kBufferCount - 1, consumer_queue_->capacity());
236b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  EXPECT_FALSE(consumer_queue_->HandleQueueEvents());
237b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
238b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka
239bb701dbac7c9c9eb2a7d0ec48c5e020f1272de13Jiwen 'Steve' Cai  // Remove and allocate a buffer.
240bb701dbac7c9c9eb2a7d0ec48c5e020f1272de13Jiwen 'Steve' Cai  ASSERT_TRUE(producer_queue_->RemoveBuffer(buffers[1].slot));
241b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  EXPECT_EQ(kBufferCount - 1, producer_queue_->capacity());
242b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  buffers[1].buffer = nullptr;
243b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka
244b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  AllocateBuffer(&slot);
245b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  ALOGE_IF(TRACE, "ALLOCATE %zu", slot);
246b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  EXPECT_EQ(buffers[1].slot, slot);
247b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  EXPECT_EQ(kBufferCount, producer_queue_->capacity());
248b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka
249b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // The consumer queue should pick up the new buffer but the count shouldn't
250b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // change.
251b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
252b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  EXPECT_FALSE(consumer_queue_->HandleQueueEvents());
253b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
254b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka
255bb701dbac7c9c9eb2a7d0ec48c5e020f1272de13Jiwen 'Steve' Cai  // Remove and allocate a buffer, but don't free the buffer right away.
256bb701dbac7c9c9eb2a7d0ec48c5e020f1272de13Jiwen 'Steve' Cai  ASSERT_TRUE(producer_queue_->RemoveBuffer(buffers[2].slot));
257b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  EXPECT_EQ(kBufferCount - 1, producer_queue_->capacity());
258b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka
259b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  AllocateBuffer(&slot);
260b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  ALOGE_IF(TRACE, "ALLOCATE %zu", slot);
261b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  EXPECT_EQ(buffers[2].slot, slot);
262b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  EXPECT_EQ(kBufferCount, producer_queue_->capacity());
263b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka
264b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
265b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  EXPECT_FALSE(consumer_queue_->HandleQueueEvents());
266b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
267b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka
268b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // Release the producer buffer to trigger a POLLHUP event for an already
269bb701dbac7c9c9eb2a7d0ec48c5e020f1272de13Jiwen 'Steve' Cai  // removed buffer.
270b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  buffers[2].buffer = nullptr;
271b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
272b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  EXPECT_FALSE(consumer_queue_->HandleQueueEvents());
273b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
274b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka}
275b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka
2762b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey TabakaTEST_F(BufferHubQueueTest, TestMultipleConsumers) {
2776bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  // ProducerConfigureBuilder doesn't set Metadata{size}, which means there
2786bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  // is no metadata associated with this BufferQueue's buffer.
2796bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  ASSERT_TRUE(CreateProducerQueue(config_builder_.Build(), UsagePolicy{}));
2802b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka
2812b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  // Allocate buffers.
2822b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  const size_t kBufferCount = 4u;
2832b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  for (size_t i = 0; i < kBufferCount; i++) {
2842b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka    AllocateBuffer();
2852b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  }
2862b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  ASSERT_EQ(kBufferCount, producer_queue_->count());
2872b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka
2882b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  // Build a silent consumer queue to test multi-consumer queue features.
2892b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  auto silent_queue = producer_queue_->CreateSilentConsumerQueue();
2902b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  ASSERT_NE(nullptr, silent_queue);
2912b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka
29252ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  // Check that silent queue doesn't import buffers on creation.
29352ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  EXPECT_EQ(0, silent_queue->capacity());
2942b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka
2952b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  // Dequeue and post a buffer.
2962b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  size_t slot;
2972b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  LocalHandle fence;
29852ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  auto producer_status =
29952ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka      producer_queue_->Dequeue(/*timeout_ms=*/100, &slot, &fence);
3002b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  ASSERT_TRUE(producer_status.ok());
3012b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  auto producer_buffer = producer_status.take();
3022b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  ASSERT_NE(nullptr, producer_buffer);
3032b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  ASSERT_EQ(0, producer_buffer->Post<void>({}));
30452ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  // After post, check the number of remaining available buffers.
30552ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  EXPECT_EQ(kBufferCount - 1, producer_queue_->count());
3062b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka
3072b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  // Currently we expect no buffer to be available prior to calling
3082b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  // WaitForBuffers/HandleQueueEvents.
3092b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  // TODO(eieio): Note this behavior may change in the future.
3102b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  EXPECT_EQ(0u, silent_queue->count());
3112b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  EXPECT_FALSE(silent_queue->HandleQueueEvents());
3122b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  EXPECT_EQ(0u, silent_queue->count());
3132b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka
3142b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  // Build a new consumer queue to test multi-consumer queue features.
3152b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  consumer_queue_ = silent_queue->CreateConsumerQueue();
3162b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  ASSERT_NE(nullptr, consumer_queue_);
3172b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka
3182b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  // Check that buffers are correctly imported on construction.
3192b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
3202b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  EXPECT_EQ(1u, consumer_queue_->count());
3212b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka
3222b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  // Reclaim released/ignored buffers.
32352ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  ASSERT_EQ(kBufferCount - 1, producer_queue_->count());
32452ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka
32552ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  usleep(10000);
32652ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  WaitAndHandleOnce(producer_queue_.get(), /*timeout_ms=*/100);
3272b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  ASSERT_EQ(kBufferCount - 1, producer_queue_->count());
3282b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka
3292b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  // Post another buffer.
33052ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  producer_status = producer_queue_->Dequeue(/*timeout_ms=*/100, &slot, &fence);
3312b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  ASSERT_TRUE(producer_status.ok());
3322b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  producer_buffer = producer_status.take();
3332b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  ASSERT_NE(nullptr, producer_buffer);
3342b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  ASSERT_EQ(0, producer_buffer->Post<void>({}));
3352b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka
3362b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  // Verify that the consumer queue receives it.
33752ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  size_t consumer_queue_count = consumer_queue_->count();
33852ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  WaitAndHandleOnce(consumer_queue_.get(), /*timeout_ms=*/100);
33952ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  EXPECT_LT(consumer_queue_count, consumer_queue_->count());
34052ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka
34152ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  // Save the current consumer queue buffer count to compare after the dequeue.
34252ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  consumer_queue_count = consumer_queue_->count();
3432b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka
3442b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  // Dequeue and acquire/release (discard) buffers on the consumer end.
34552ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  auto consumer_status =
34652ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka      consumer_queue_->Dequeue(/*timeout_ms=*/100, &slot, &fence);
3472b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  ASSERT_TRUE(consumer_status.ok());
3482b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  auto consumer_buffer = consumer_status.take();
3492b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  ASSERT_NE(nullptr, consumer_buffer);
3502b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  consumer_buffer->Discard();
3512b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka
3522b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  // Buffer should be returned to the producer queue without being handled by
3532b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  // the silent consumer queue.
35452ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  EXPECT_GT(consumer_queue_count, consumer_queue_->count());
3552b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  EXPECT_EQ(kBufferCount - 2, producer_queue_->count());
3562b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  EXPECT_TRUE(producer_queue_->HandleQueueEvents());
3572b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  EXPECT_EQ(kBufferCount - 1, producer_queue_->count());
3582b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka}
3592b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka
360e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostruct TestMetadata {
361e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  char a;
362e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int32_t b;
363e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int64_t c;
364e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko};
365e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
366e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoTEST_F(BufferHubQueueTest, TestMetadata) {
3676bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<TestMetadata>().Build(),
3686bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai                           UsagePolicy{}));
3696bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai
370e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  AllocateBuffer();
371e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
372e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::vector<TestMetadata> ms = {
373e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      {'0', 0, 0}, {'1', 10, 3333}, {'@', 123, 1000000000}};
374e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
375e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  for (auto mi : ms) {
376e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    size_t slot;
377ed6543224138fd753eeea909918bb8d1d2efb1e6Jiwen 'Steve' Cai    LocalHandle fence;
37852ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    auto p1_status = producer_queue_->Dequeue(100, &slot, &fence);
3799d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka    ASSERT_TRUE(p1_status.ok());
3809d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka    auto p1 = p1_status.take();
381e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ASSERT_NE(nullptr, p1);
382e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ASSERT_EQ(p1->Post(LocalHandle(-1), &mi, sizeof(mi)), 0);
383e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    TestMetadata mo;
38452ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    auto c1_status = consumer_queue_->Dequeue(100, &slot, &mo, &fence);
3859d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka    ASSERT_TRUE(c1_status.ok());
3869d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka    auto c1 = c1_status.take();
387e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ASSERT_EQ(mi.a, mo.a);
388e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ASSERT_EQ(mi.b, mo.b);
389e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ASSERT_EQ(mi.c, mo.c);
390e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    c1->Release(LocalHandle(-1));
391e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
392e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
393e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
394e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoTEST_F(BufferHubQueueTest, TestMetadataMismatch) {
3956bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
3966bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai                           UsagePolicy{}));
3976bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai
398e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  AllocateBuffer();
399e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
400e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int64_t mi = 3;
401e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  size_t slot;
402ed6543224138fd753eeea909918bb8d1d2efb1e6Jiwen 'Steve' Cai  LocalHandle fence;
40352ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  auto p1_status = producer_queue_->Dequeue(100, &slot, &fence);
4049d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka  ASSERT_TRUE(p1_status.ok());
4059d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka  auto p1 = p1_status.take();
406e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_NE(nullptr, p1);
407e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_EQ(p1->Post(LocalHandle(-1), &mi, sizeof(mi)), 0);
408e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
409e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int32_t mo;
410e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Acquire a buffer with mismatched metadata is not OK.
41152ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  auto c1_status = consumer_queue_->Dequeue(100, &slot, &mo, &fence);
4129d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka  ASSERT_FALSE(c1_status.ok());
413e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
414e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
415e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoTEST_F(BufferHubQueueTest, TestEnqueue) {
4166bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
4176bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai                           UsagePolicy{}));
418e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  AllocateBuffer();
419e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
420e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  size_t slot;
421ed6543224138fd753eeea909918bb8d1d2efb1e6Jiwen 'Steve' Cai  LocalHandle fence;
42252ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  auto p1_status = producer_queue_->Dequeue(100, &slot, &fence);
4239d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka  ASSERT_TRUE(p1_status.ok());
4249d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka  auto p1 = p1_status.take();
425e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_NE(nullptr, p1);
426e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
427e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int64_t mo;
42852ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  producer_queue_->Enqueue(p1, slot, 0ULL);
42952ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  auto c1_status = consumer_queue_->Dequeue(100, &slot, &mo, &fence);
4309d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka  ASSERT_FALSE(c1_status.ok());
431e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
432e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
433e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoTEST_F(BufferHubQueueTest, TestAllocateBuffer) {
4346bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
4356bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai                           UsagePolicy{}));
436e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
437e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  size_t s1;
438e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  AllocateBuffer();
439ed6543224138fd753eeea909918bb8d1d2efb1e6Jiwen 'Steve' Cai  LocalHandle fence;
44052ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  auto p1_status = producer_queue_->Dequeue(100, &s1, &fence);
4419d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka  ASSERT_TRUE(p1_status.ok());
4429d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka  auto p1 = p1_status.take();
443e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_NE(nullptr, p1);
444e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
445e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // producer queue is exhausted
446e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  size_t s2;
44752ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  auto p2_status = producer_queue_->Dequeue(100, &s2, &fence);
4489d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka  ASSERT_FALSE(p2_status.ok());
4499d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka  ASSERT_EQ(ETIMEDOUT, p2_status.error());
450e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
451e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // dynamically add buffer.
452e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  AllocateBuffer();
453e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_EQ(producer_queue_->count(), 1U);
454e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_EQ(producer_queue_->capacity(), 2U);
455e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
456e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // now we can dequeue again
45752ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  p2_status = producer_queue_->Dequeue(100, &s2, &fence);
4589d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka  ASSERT_TRUE(p2_status.ok());
4599d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka  auto p2 = p2_status.take();
460e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_NE(nullptr, p2);
461e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_EQ(producer_queue_->count(), 0U);
462e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // p1 and p2 should have different slot number
463e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_NE(s1, s2);
464e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
465e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Consumer queue does not import buffers until |Dequeue| or |ImportBuffers|
466e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // are called. So far consumer_queue_ should be empty.
467e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_EQ(consumer_queue_->count(), 0U);
468e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
469e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int64_t seq = 1;
470e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_EQ(p1->Post(LocalHandle(), seq), 0);
471e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  size_t cs1, cs2;
47252ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  auto c1_status = consumer_queue_->Dequeue(100, &cs1, &seq, &fence);
4739d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka  ASSERT_TRUE(c1_status.ok());
4749d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka  auto c1 = c1_status.take();
475e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_NE(nullptr, c1);
476e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_EQ(consumer_queue_->count(), 0U);
477e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_EQ(consumer_queue_->capacity(), 2U);
478e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_EQ(cs1, s1);
479e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
480e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_EQ(p2->Post(LocalHandle(), seq), 0);
48152ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  auto c2_status = consumer_queue_->Dequeue(100, &cs2, &seq, &fence);
4829d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka  ASSERT_TRUE(c2_status.ok());
4839d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka  auto c2 = c2_status.take();
484e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_NE(nullptr, c2);
485e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_EQ(cs2, s2);
486e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
487e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
488e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoTEST_F(BufferHubQueueTest, TestUsageSetMask) {
4899d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka  const uint32_t set_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
4906bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
4916bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai                           UsagePolicy{set_mask, 0, 0, 0}));
492e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
493e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // When allocation, leave out |set_mask| from usage bits on purpose.
494b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  auto status = producer_queue_->AllocateBuffer(
495b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka      kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
4968fa4e107ab6cbc24c0e54d44db3341f006fe939aJiwen 'Steve' Cai      kBufferUsage & ~set_mask);
497b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  ASSERT_TRUE(status.ok());
498e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
499ed6543224138fd753eeea909918bb8d1d2efb1e6Jiwen 'Steve' Cai  LocalHandle fence;
5008fa4e107ab6cbc24c0e54d44db3341f006fe939aJiwen 'Steve' Cai  size_t slot;
50152ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  auto p1_status = producer_queue_->Dequeue(100, &slot, &fence);
5029d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka  ASSERT_TRUE(p1_status.ok());
5039d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka  auto p1 = p1_status.take();
504e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_EQ(p1->usage() & set_mask, set_mask);
505e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
506e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
507e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoTEST_F(BufferHubQueueTest, TestUsageClearMask) {
5089d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka  const uint32_t clear_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
5096bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
5106bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai                           UsagePolicy{0, clear_mask, 0, 0}));
511e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
512e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // When allocation, add |clear_mask| into usage bits on purpose.
513b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  auto status = producer_queue_->AllocateBuffer(
514b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka      kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
5158fa4e107ab6cbc24c0e54d44db3341f006fe939aJiwen 'Steve' Cai      kBufferUsage | clear_mask);
516b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  ASSERT_TRUE(status.ok());
517e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
518ed6543224138fd753eeea909918bb8d1d2efb1e6Jiwen 'Steve' Cai  LocalHandle fence;
5198fa4e107ab6cbc24c0e54d44db3341f006fe939aJiwen 'Steve' Cai  size_t slot;
52052ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  auto p1_status = producer_queue_->Dequeue(100, &slot, &fence);
5219d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka  ASSERT_TRUE(p1_status.ok());
5229d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka  auto p1 = p1_status.take();
5239d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka  ASSERT_EQ(0u, p1->usage() & clear_mask);
524e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
525e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
526e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoTEST_F(BufferHubQueueTest, TestUsageDenySetMask) {
5279d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka  const uint32_t deny_set_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
5286bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
5296bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai                           UsagePolicy{0, 0, deny_set_mask, 0}));
530e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
531e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Now that |deny_set_mask| is illegal, allocation without those bits should
532e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // be able to succeed.
533b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  auto status = producer_queue_->AllocateBuffer(
534108e84f7e6a9117b66dba000dcf16c6d8c862e16Hendrik Wagenaar      kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
5358fa4e107ab6cbc24c0e54d44db3341f006fe939aJiwen 'Steve' Cai      kBufferUsage & ~deny_set_mask);
536b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  ASSERT_TRUE(status.ok());
537e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
538e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // While allocation with those bits should fail.
539b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  status = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
540b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka                                           kBufferLayerCount, kBufferFormat,
5418fa4e107ab6cbc24c0e54d44db3341f006fe939aJiwen 'Steve' Cai                                           kBufferUsage | deny_set_mask);
542b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  ASSERT_FALSE(status.ok());
543b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  ASSERT_EQ(EINVAL, status.error());
544e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
545e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
546e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoTEST_F(BufferHubQueueTest, TestUsageDenyClearMask) {
5479d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka  const uint32_t deny_clear_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
5486bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
5496bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai                           UsagePolicy{0, 0, 0, deny_clear_mask}));
550e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
551e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Now that clearing |deny_clear_mask| is illegal (i.e. setting these bits are
552e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // mandatory), allocation with those bits should be able to succeed.
553b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  auto status = producer_queue_->AllocateBuffer(
554108e84f7e6a9117b66dba000dcf16c6d8c862e16Hendrik Wagenaar      kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
5558fa4e107ab6cbc24c0e54d44db3341f006fe939aJiwen 'Steve' Cai      kBufferUsage | deny_clear_mask);
556b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  ASSERT_TRUE(status.ok());
557e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
558e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // While allocation without those bits should fail.
55952ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  status = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
56052ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka                                           kBufferLayerCount, kBufferFormat,
56152ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka                                           kBufferUsage & ~deny_clear_mask);
562b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  ASSERT_FALSE(status.ok());
563b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  ASSERT_EQ(EINVAL, status.error());
564e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
565e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
5666bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' CaiTEST_F(BufferHubQueueTest, TestQueueInfo) {
5676bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  static const bool kIsAsync = true;
5686bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  ASSERT_TRUE(CreateQueues(config_builder_.SetIsAsync(kIsAsync)
5696bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai                               .SetDefaultWidth(kBufferWidth)
5706bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai                               .SetDefaultHeight(kBufferHeight)
5716bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai                               .SetDefaultFormat(kBufferFormat)
5726bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai                               .Build(),
5736bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai                           UsagePolicy{}));
5746bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai
5756bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  EXPECT_EQ(producer_queue_->default_width(), kBufferWidth);
5766bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  EXPECT_EQ(producer_queue_->default_height(), kBufferHeight);
5776bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  EXPECT_EQ(producer_queue_->default_format(), kBufferFormat);
5786bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  EXPECT_EQ(producer_queue_->is_async(), kIsAsync);
5796bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai
5806bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  EXPECT_EQ(consumer_queue_->default_width(), kBufferWidth);
5816bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  EXPECT_EQ(consumer_queue_->default_height(), kBufferHeight);
5826bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  EXPECT_EQ(consumer_queue_->default_format(), kBufferFormat);
5836bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  EXPECT_EQ(consumer_queue_->is_async(), kIsAsync);
5846bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai}
5856bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai
586005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' CaiTEST_F(BufferHubQueueTest, TestFreeAllBuffers) {
587005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  constexpr size_t kBufferCount = 2;
588005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai
589005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai#define CHECK_NO_BUFFER_THEN_ALLOCATE(num_buffers)  \
590005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  EXPECT_EQ(consumer_queue_->count(), 0U);          \
591005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  EXPECT_EQ(consumer_queue_->capacity(), 0U);       \
592005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  EXPECT_EQ(producer_queue_->count(), 0U);          \
593005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  EXPECT_EQ(producer_queue_->capacity(), 0U);       \
594005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  for (size_t i = 0; i < num_buffers; i++) {        \
595005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai    AllocateBuffer();                               \
596005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  }                                                 \
597005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  EXPECT_EQ(producer_queue_->count(), num_buffers); \
598005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  EXPECT_EQ(producer_queue_->capacity(), num_buffers);
599005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai
600005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  size_t slot;
601005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  uint64_t seq;
602005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  LocalHandle fence;
603005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  pdx::Status<void> status;
604005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  pdx::Status<std::shared_ptr<BufferConsumer>> consumer_status;
605005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  pdx::Status<std::shared_ptr<BufferProducer>> producer_status;
606005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  std::shared_ptr<BufferConsumer> consumer_buffer;
607005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  std::shared_ptr<BufferProducer> producer_buffer;
608005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai
609005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<uint64_t>().Build(),
610005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai                           UsagePolicy{}));
611005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai
612005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  // Free all buffers when buffers are avaible for dequeue.
613005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount);
614005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  status = producer_queue_->FreeAllBuffers();
615005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  EXPECT_TRUE(status.ok());
616005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai
617005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  // Free all buffers when one buffer is dequeued.
618005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount);
61952ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  producer_status = producer_queue_->Dequeue(100, &slot, &fence);
620005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  ASSERT_TRUE(producer_status.ok());
621005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  status = producer_queue_->FreeAllBuffers();
622005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  EXPECT_TRUE(status.ok());
623005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai
624005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  // Free all buffers when all buffers are dequeued.
625005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount);
626005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  for (size_t i = 0; i < kBufferCount; i++) {
62752ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    producer_status = producer_queue_->Dequeue(100, &slot, &fence);
628005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai    ASSERT_TRUE(producer_status.ok());
629005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  }
630005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  status = producer_queue_->FreeAllBuffers();
631005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  EXPECT_TRUE(status.ok());
632005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai
633005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  // Free all buffers when one buffer is posted.
634005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount);
63552ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  producer_status = producer_queue_->Dequeue(100, &slot, &fence);
636005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  ASSERT_TRUE(producer_status.ok());
637005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  producer_buffer = producer_status.take();
638005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  ASSERT_NE(nullptr, producer_buffer);
639005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  ASSERT_EQ(0, producer_buffer->Post(fence, &seq, sizeof(seq)));
640005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  status = producer_queue_->FreeAllBuffers();
641005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  EXPECT_TRUE(status.ok());
642005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai
643005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  // Free all buffers when all buffers are posted.
644005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount);
645005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  for (size_t i = 0; i < kBufferCount; i++) {
64652ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    producer_status = producer_queue_->Dequeue(100, &slot, &fence);
647005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai    ASSERT_TRUE(producer_status.ok());
648005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai    producer_buffer = producer_status.take();
649005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai    ASSERT_NE(nullptr, producer_buffer);
650005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai    ASSERT_EQ(0, producer_buffer->Post(fence, &seq, sizeof(seq)));
651005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  }
652005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  status = producer_queue_->FreeAllBuffers();
653005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  EXPECT_TRUE(status.ok());
654005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai
655005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  // Free all buffers when all buffers are acquired.
656005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount);
657005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  for (size_t i = 0; i < kBufferCount; i++) {
65852ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    producer_status = producer_queue_->Dequeue(100, &slot, &fence);
659005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai    ASSERT_TRUE(producer_status.ok());
660005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai    producer_buffer = producer_status.take();
661005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai    ASSERT_NE(nullptr, producer_buffer);
662005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai    ASSERT_EQ(0, producer_buffer->Post(fence, &seq, sizeof(seq)));
66352ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    consumer_status = consumer_queue_->Dequeue(100, &slot, &seq, &fence);
664005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai    ASSERT_TRUE(consumer_status.ok());
665005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  }
666005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai
667005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  status = producer_queue_->FreeAllBuffers();
668005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  EXPECT_TRUE(status.ok());
669005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai
670005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  // In addition to FreeAllBuffers() from the queue, it is also required to
671005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  // delete all references to the ProducerBuffer (i.e. the PDX client).
672005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  producer_buffer = nullptr;
673005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai
674005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  // Crank consumer queue events to pickup EPOLLHUP events on the queue.
675005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  consumer_queue_->HandleQueueEvents();
676005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai
677005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  // One last check.
678005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount);
679005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai
680005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai#undef CHECK_NO_BUFFER_THEN_ALLOCATE
681005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai}
682005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai
683e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace
684e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
685e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace dvr
686e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace android
687