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