blob: 3c99f9927b8ceafc8386a9361155a88ea159cfba [file] [log] [blame]
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08001#include <gtest/gtest.h>
Corey Tabaka52ea25c2017-09-13 18:02:48 -07002#include <poll.h>
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08003#include <private/dvr/buffer_hub_client.h>
Corey Tabaka52ea25c2017-09-13 18:02:48 -07004#include <private/dvr/bufferhub_rpc.h>
5#include <sys/epoll.h>
6#include <sys/eventfd.h>
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08007
8#include <mutex>
9#include <thread>
10
Alex Vakulenko4fe60582017-02-02 11:35:59 -080011#define RETRY_EINTR(fnc_call) \
12 ([&]() -> decltype(fnc_call) { \
13 decltype(fnc_call) result; \
14 do { \
15 result = (fnc_call); \
16 } while (result == -1 && errno == EINTR); \
17 return result; \
18 })()
19
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080020using android::dvr::BufferConsumer;
Corey Tabaka52ea25c2017-09-13 18:02:48 -070021using android::dvr::BufferHubDefs::kConsumerStateMask;
22using android::dvr::BufferHubDefs::kProducerStateBit;
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -070023using android::dvr::BufferHubDefs::IsBufferGained;
24using android::dvr::BufferHubDefs::IsBufferPosted;
25using android::dvr::BufferHubDefs::IsBufferAcquired;
26using android::dvr::BufferHubDefs::IsBufferReleased;
Corey Tabaka52ea25c2017-09-13 18:02:48 -070027using android::dvr::BufferProducer;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080028using android::pdx::LocalHandle;
29
30const int kWidth = 640;
31const int kHeight = 480;
32const int kFormat = HAL_PIXEL_FORMAT_RGBA_8888;
33const int kUsage = 0;
34const uint64_t kContext = 42;
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -070035const size_t kMaxConsumerCount = 63;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080036
37using LibBufferHubTest = ::testing::Test;
38
39TEST_F(LibBufferHubTest, TestBasicUsage) {
40 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
41 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
42 ASSERT_TRUE(p.get() != nullptr);
43 std::unique_ptr<BufferConsumer> c =
44 BufferConsumer::Import(p->CreateConsumer());
45 ASSERT_TRUE(c.get() != nullptr);
46 // Check that consumers can spawn other consumers.
47 std::unique_ptr<BufferConsumer> c2 =
48 BufferConsumer::Import(c->CreateConsumer());
49 ASSERT_TRUE(c2.get() != nullptr);
50
Corey Tabaka52ea25c2017-09-13 18:02:48 -070051 // Producer state mask is unique, i.e. 1.
52 EXPECT_EQ(p->buffer_state_bit(), kProducerStateBit);
53 // Consumer state mask cannot have producer bit on.
54 EXPECT_EQ(c->buffer_state_bit() & kProducerStateBit, 0);
55 // Consumer state mask must be a single, i.e. power of 2.
56 EXPECT_NE(c->buffer_state_bit(), 0);
57 EXPECT_EQ(c->buffer_state_bit() & (c->buffer_state_bit() - 1), 0);
58 // Consumer state mask cannot have producer bit on.
59 EXPECT_EQ(c2->buffer_state_bit() & kProducerStateBit, 0);
60 // Consumer state mask must be a single, i.e. power of 2.
61 EXPECT_NE(c2->buffer_state_bit(), 0);
62 EXPECT_EQ(c2->buffer_state_bit() & (c2->buffer_state_bit() - 1), 0);
63 // Each consumer should have unique bit.
64 EXPECT_EQ(c->buffer_state_bit() & c2->buffer_state_bit(), 0);
65
66 // Initial state: producer not available, consumers not available.
67 EXPECT_EQ(0, RETRY_EINTR(p->Poll(100)));
68 EXPECT_EQ(0, RETRY_EINTR(c->Poll(100)));
69 EXPECT_EQ(0, RETRY_EINTR(c2->Poll(100)));
70
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080071 EXPECT_EQ(0, p->Post(LocalHandle(), kContext));
Corey Tabaka52ea25c2017-09-13 18:02:48 -070072
73 // New state: producer not available, consumers available.
74 EXPECT_EQ(0, RETRY_EINTR(p->Poll(100)));
75 EXPECT_EQ(1, RETRY_EINTR(c->Poll(100)));
76 EXPECT_EQ(1, RETRY_EINTR(c2->Poll(100)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080077
78 uint64_t context;
79 LocalHandle fence;
Corey Tabaka52ea25c2017-09-13 18:02:48 -070080 EXPECT_EQ(0, c->Acquire(&fence, &context));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080081 EXPECT_EQ(kContext, context);
Corey Tabaka52ea25c2017-09-13 18:02:48 -070082 EXPECT_EQ(0, RETRY_EINTR(c->Poll(100)));
83 EXPECT_EQ(1, RETRY_EINTR(c2->Poll(100)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080084
Corey Tabaka52ea25c2017-09-13 18:02:48 -070085 EXPECT_EQ(0, c2->Acquire(&fence, &context));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080086 EXPECT_EQ(kContext, context);
Corey Tabaka52ea25c2017-09-13 18:02:48 -070087 EXPECT_EQ(0, RETRY_EINTR(c2->Poll(100)));
88 EXPECT_EQ(0, RETRY_EINTR(c->Poll(100)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080089
90 EXPECT_EQ(0, c->Release(LocalHandle()));
Corey Tabaka52ea25c2017-09-13 18:02:48 -070091 EXPECT_EQ(0, RETRY_EINTR(p->Poll(100)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080092 EXPECT_EQ(0, c2->Discard());
93
Corey Tabaka52ea25c2017-09-13 18:02:48 -070094 EXPECT_EQ(1, RETRY_EINTR(p->Poll(100)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080095 EXPECT_EQ(0, p->Gain(&fence));
Corey Tabaka52ea25c2017-09-13 18:02:48 -070096 EXPECT_EQ(0, RETRY_EINTR(p->Poll(100)));
97 EXPECT_EQ(0, RETRY_EINTR(c->Poll(100)));
98 EXPECT_EQ(0, RETRY_EINTR(c2->Poll(100)));
99}
100
101TEST_F(LibBufferHubTest, TestEpoll) {
102 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
103 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
104 ASSERT_TRUE(p.get() != nullptr);
105 std::unique_ptr<BufferConsumer> c =
106 BufferConsumer::Import(p->CreateConsumer());
107 ASSERT_TRUE(c.get() != nullptr);
108
109 LocalHandle epoll_fd{epoll_create1(EPOLL_CLOEXEC)};
110 ASSERT_TRUE(epoll_fd.IsValid());
111
112 epoll_event event;
113 std::array<epoll_event, 64> events;
114
115 auto event_sources = p->GetEventSources();
116 ASSERT_LT(event_sources.size(), events.size());
117
118 for (const auto& event_source : event_sources) {
119 event = {.events = event_source.event_mask | EPOLLET,
120 .data = {.fd = p->event_fd()}};
121 ASSERT_EQ(0, epoll_ctl(epoll_fd.Get(), EPOLL_CTL_ADD, event_source.event_fd,
122 &event));
123 }
124
125 event_sources = c->GetEventSources();
126 ASSERT_LT(event_sources.size(), events.size());
127
128 for (const auto& event_source : event_sources) {
129 event = {.events = event_source.event_mask | EPOLLET,
130 .data = {.fd = c->event_fd()}};
131 ASSERT_EQ(0, epoll_ctl(epoll_fd.Get(), EPOLL_CTL_ADD, event_source.event_fd,
132 &event));
133 }
134
135 // No events should be signaled initially.
136 ASSERT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 0));
137
138 // Post the producer and check for consumer signal.
139 EXPECT_EQ(0, p->Post({}, kContext));
140 ASSERT_EQ(1, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 100));
141 ASSERT_TRUE(events[0].events & EPOLLIN);
142 ASSERT_EQ(c->event_fd(), events[0].data.fd);
143
144 // Save the event bits to translate later.
145 event = events[0];
146
147 // Check for events again. Edge-triggered mode should prevent any.
148 EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 100));
149 EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 100));
150 EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 100));
151 EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 100));
152
153 // Translate the events.
154 auto event_status = c->GetEventMask(event.events);
155 ASSERT_TRUE(event_status);
156 ASSERT_TRUE(event_status.get() & EPOLLIN);
157
158 // Check for events again. Edge-triggered mode should prevent any.
159 EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 100));
160}
161
162TEST_F(LibBufferHubTest, TestStateMask) {
163 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
164 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
165 ASSERT_TRUE(p.get() != nullptr);
166
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700167 // It's ok to create up to kMaxConsumerCount consumer buffers.
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700168 uint64_t buffer_state_bits = p->buffer_state_bit();
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700169 std::array<std::unique_ptr<BufferConsumer>, kMaxConsumerCount> cs;
170 for (size_t i = 0; i < kMaxConsumerCount; i++) {
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700171 cs[i] = BufferConsumer::Import(p->CreateConsumer());
172 ASSERT_TRUE(cs[i].get() != nullptr);
173 // Expect all buffers have unique state mask.
174 EXPECT_EQ(buffer_state_bits & cs[i]->buffer_state_bit(), 0);
175 buffer_state_bits |= cs[i]->buffer_state_bit();
176 }
177 EXPECT_EQ(buffer_state_bits, kProducerStateBit | kConsumerStateMask);
178
179 // The 64th creation will fail with out-of-memory error.
180 auto state = p->CreateConsumer();
181 EXPECT_EQ(state.error(), E2BIG);
182
183 // Release any consumer should allow us to re-create.
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700184 for (size_t i = 0; i < kMaxConsumerCount; i++) {
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700185 buffer_state_bits &= ~cs[i]->buffer_state_bit();
186 cs[i] = nullptr;
187 cs[i] = BufferConsumer::Import(p->CreateConsumer());
188 ASSERT_TRUE(cs[i].get() != nullptr);
189 // The released state mask will be reused.
190 EXPECT_EQ(buffer_state_bits & cs[i]->buffer_state_bit(), 0);
191 buffer_state_bits |= cs[i]->buffer_state_bit();
192 EXPECT_EQ(buffer_state_bits, kProducerStateBit | kConsumerStateMask);
193 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800194}
195
Corey Tabakad53870c2017-07-06 18:04:27 -0700196TEST_F(LibBufferHubTest, TestStateTransitions) {
197 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
198 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
199 ASSERT_TRUE(p.get() != nullptr);
200 std::unique_ptr<BufferConsumer> c =
201 BufferConsumer::Import(p->CreateConsumer());
202 ASSERT_TRUE(c.get() != nullptr);
203
204 uint64_t context;
205 LocalHandle fence;
206
207 // The producer buffer starts in gained state.
208
209 // Acquire, release, and gain in gained state should fail.
210 EXPECT_EQ(-EBUSY, c->Acquire(&fence, &context));
211 EXPECT_EQ(-EBUSY, c->Release(LocalHandle()));
212 EXPECT_EQ(-EALREADY, p->Gain(&fence));
213
214 // Post in gained state should succeed.
215 EXPECT_EQ(0, p->Post(LocalHandle(), kContext));
216
217 // Post, release, and gain in posted state should fail.
218 EXPECT_EQ(-EBUSY, p->Post(LocalHandle(), kContext));
219 EXPECT_EQ(-EBUSY, c->Release(LocalHandle()));
220 EXPECT_EQ(-EBUSY, p->Gain(&fence));
221
222 // Acquire in posted state should succeed.
223 EXPECT_LE(0, c->Acquire(&fence, &context));
224
225 // Acquire, post, and gain in acquired state should fail.
226 EXPECT_EQ(-EBUSY, c->Acquire(&fence, &context));
227 EXPECT_EQ(-EBUSY, p->Post(LocalHandle(), kContext));
228 EXPECT_EQ(-EBUSY, p->Gain(&fence));
229
230 // Release in acquired state should succeed.
231 EXPECT_EQ(0, c->Release(LocalHandle()));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700232 EXPECT_LT(0, RETRY_EINTR(p->Poll(10)));
Corey Tabakad53870c2017-07-06 18:04:27 -0700233
234 // Release, acquire, and post in released state should fail.
235 EXPECT_EQ(-EBUSY, c->Release(LocalHandle()));
236 EXPECT_EQ(-EBUSY, c->Acquire(&fence, &context));
237 EXPECT_EQ(-EBUSY, p->Post(LocalHandle(), kContext));
238
239 // Gain in released state should succeed.
240 EXPECT_EQ(0, p->Gain(&fence));
241
242 // Acquire, release, and gain in gained state should fail.
243 EXPECT_EQ(-EBUSY, c->Acquire(&fence, &context));
244 EXPECT_EQ(-EBUSY, c->Release(LocalHandle()));
245 EXPECT_EQ(-EALREADY, p->Gain(&fence));
246}
247
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700248TEST_F(LibBufferHubTest, TestAsyncStateTransitions) {
249 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
250 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
251 ASSERT_TRUE(p.get() != nullptr);
252 std::unique_ptr<BufferConsumer> c =
253 BufferConsumer::Import(p->CreateConsumer());
254 ASSERT_TRUE(c.get() != nullptr);
255
256 DvrNativeBufferMetadata metadata;
257 LocalHandle invalid_fence;
258
259 // The producer buffer starts in gained state.
260
261 // Acquire, release, and gain in gained state should fail.
262 EXPECT_EQ(-EBUSY, c->AcquireAsync(&metadata, &invalid_fence));
263 EXPECT_FALSE(invalid_fence.IsValid());
264 EXPECT_EQ(-EBUSY, c->ReleaseAsync(&metadata, invalid_fence));
265 EXPECT_EQ(-EALREADY, p->GainAsync(&metadata, &invalid_fence));
266 EXPECT_FALSE(invalid_fence.IsValid());
267
268 // Post in gained state should succeed.
269 EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
270 EXPECT_EQ(p->buffer_state(), c->buffer_state());
271 EXPECT_TRUE(IsBufferPosted(p->buffer_state()));
272
273 // Post, release, and gain in posted state should fail.
274 EXPECT_EQ(-EBUSY, p->PostAsync(&metadata, invalid_fence));
275 EXPECT_EQ(-EBUSY, c->ReleaseAsync(&metadata, invalid_fence));
276 EXPECT_EQ(-EBUSY, p->GainAsync(&metadata, &invalid_fence));
277 EXPECT_FALSE(invalid_fence.IsValid());
278
279 // Acquire in posted state should succeed.
280 EXPECT_LT(0, RETRY_EINTR(c->Poll(10)));
281 EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
282 EXPECT_FALSE(invalid_fence.IsValid());
283 EXPECT_EQ(p->buffer_state(), c->buffer_state());
284 EXPECT_TRUE(IsBufferAcquired(p->buffer_state()));
285
286 // Acquire, post, and gain in acquired state should fail.
287 EXPECT_EQ(-EBUSY, c->AcquireAsync(&metadata, &invalid_fence));
288 EXPECT_FALSE(invalid_fence.IsValid());
289 EXPECT_EQ(-EBUSY, p->PostAsync(&metadata, invalid_fence));
290 EXPECT_EQ(-EBUSY, p->GainAsync(&metadata, &invalid_fence));
291 EXPECT_FALSE(invalid_fence.IsValid());
292
293 // Release in acquired state should succeed.
294 EXPECT_EQ(0, c->ReleaseAsync(&metadata, invalid_fence));
295 EXPECT_LT(0, RETRY_EINTR(p->Poll(10)));
296 EXPECT_EQ(p->buffer_state(), c->buffer_state());
297 EXPECT_TRUE(IsBufferReleased(p->buffer_state()));
298
299 // Release, acquire, and post in released state should fail.
300 EXPECT_EQ(-EBUSY, c->ReleaseAsync(&metadata, invalid_fence));
301 EXPECT_EQ(-EBUSY, c->AcquireAsync(&metadata, &invalid_fence));
302 EXPECT_FALSE(invalid_fence.IsValid());
303 EXPECT_EQ(-EBUSY, p->PostAsync(&metadata, invalid_fence));
304
305 // Gain in released state should succeed.
306 EXPECT_EQ(0, p->GainAsync(&metadata, &invalid_fence));
307 EXPECT_FALSE(invalid_fence.IsValid());
308 EXPECT_EQ(p->buffer_state(), c->buffer_state());
309 EXPECT_TRUE(IsBufferGained(p->buffer_state()));
310
311 // Acquire, release, and gain in gained state should fail.
312 EXPECT_EQ(-EBUSY, c->AcquireAsync(&metadata, &invalid_fence));
313 EXPECT_FALSE(invalid_fence.IsValid());
314 EXPECT_EQ(-EBUSY, c->ReleaseAsync(&metadata, invalid_fence));
315 EXPECT_EQ(-EALREADY, p->GainAsync(&metadata, &invalid_fence));
316 EXPECT_FALSE(invalid_fence.IsValid());
317}
318
319TEST_F(LibBufferHubTest, TestZeroConsumer) {
320 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
321 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
322 ASSERT_TRUE(p.get() != nullptr);
323
324 DvrNativeBufferMetadata metadata;
325 LocalHandle invalid_fence;
326
327 // Newly created.
328 EXPECT_TRUE(IsBufferGained(p->buffer_state()));
329 EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
330 EXPECT_TRUE(IsBufferPosted(p->buffer_state()));
331
332 // The buffer should stay in posted stay until a consumer picks it up.
333 EXPECT_GE(0, RETRY_EINTR(p->Poll(100)));
334
335 // A new consumer should still be able to acquire the buffer immediately.
336 std::unique_ptr<BufferConsumer> c =
337 BufferConsumer::Import(p->CreateConsumer());
338 ASSERT_TRUE(c.get() != nullptr);
339 EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
340 EXPECT_TRUE(IsBufferAcquired(c->buffer_state()));
341}
342
343TEST_F(LibBufferHubTest, TestMaxConsumers) {
344 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
345 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
346 ASSERT_TRUE(p.get() != nullptr);
347
348 std::array<std::unique_ptr<BufferConsumer>, kMaxConsumerCount> cs;
349 for (size_t i = 0; i < kMaxConsumerCount; i++) {
350 cs[i] = BufferConsumer::Import(p->CreateConsumer());
351 ASSERT_TRUE(cs[i].get() != nullptr);
352 EXPECT_TRUE(IsBufferGained(cs[i]->buffer_state()));
353 }
354
355 DvrNativeBufferMetadata metadata;
356 LocalHandle invalid_fence;
357
358 // Post the producer should trigger all consumers to be available.
359 EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
360 EXPECT_TRUE(IsBufferPosted(p->buffer_state()));
361 for (size_t i = 0; i < kMaxConsumerCount; i++) {
362 EXPECT_TRUE(IsBufferPosted(cs[i]->buffer_state(),
363 cs[i]->buffer_state_bit()));
364 EXPECT_LT(0, RETRY_EINTR(cs[i]->Poll(10)));
365 EXPECT_EQ(0, cs[i]->AcquireAsync(&metadata, &invalid_fence));
366 EXPECT_TRUE(IsBufferAcquired(p->buffer_state()));
367 }
368
369 // All consumers have to release before the buffer is considered to be
370 // released.
371 for (size_t i = 0; i < kMaxConsumerCount; i++) {
372 EXPECT_FALSE(IsBufferReleased(p->buffer_state()));
373 EXPECT_EQ(0, cs[i]->ReleaseAsync(&metadata, invalid_fence));
374 }
375
376 EXPECT_LT(0, RETRY_EINTR(p->Poll(10)));
377 EXPECT_TRUE(IsBufferReleased(p->buffer_state()));
378
379 // Buffer state cross all clients must be consistent.
380 for (size_t i = 0; i < kMaxConsumerCount; i++) {
381 EXPECT_EQ(p->buffer_state(), cs[i]->buffer_state());
382 }
383}
384
385TEST_F(LibBufferHubTest, TestCreateConsumerWhenBufferGained) {
386 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
387 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
388 ASSERT_TRUE(p.get() != nullptr);
389 EXPECT_TRUE(IsBufferGained(p->buffer_state()));
390
391 std::unique_ptr<BufferConsumer> c =
392 BufferConsumer::Import(p->CreateConsumer());
393 ASSERT_TRUE(c.get() != nullptr);
394 EXPECT_TRUE(IsBufferGained(c->buffer_state()));
395
396 DvrNativeBufferMetadata metadata;
397 LocalHandle invalid_fence;
398
399 // Post the gained buffer should signal already created consumer.
400 EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
401 EXPECT_TRUE(IsBufferPosted(p->buffer_state()));
402 EXPECT_LT(0, RETRY_EINTR(c->Poll(10)));
403 EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
404 EXPECT_TRUE(IsBufferAcquired(c->buffer_state()));
405}
406
407TEST_F(LibBufferHubTest, TestCreateConsumerWhenBufferPosted) {
408 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
409 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
410 ASSERT_TRUE(p.get() != nullptr);
411 EXPECT_TRUE(IsBufferGained(p->buffer_state()));
412
413 DvrNativeBufferMetadata metadata;
414 LocalHandle invalid_fence;
415
416 // Post the gained buffer before any consumer gets created.
417 EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
418 EXPECT_TRUE(IsBufferPosted(p->buffer_state()));
419
420 // Newly created consumer should be automatically sigalled.
421 std::unique_ptr<BufferConsumer> c =
422 BufferConsumer::Import(p->CreateConsumer());
423 ASSERT_TRUE(c.get() != nullptr);
424 EXPECT_TRUE(IsBufferPosted(c->buffer_state()));
425 EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
426 EXPECT_TRUE(IsBufferAcquired(c->buffer_state()));
427}
428
429TEST_F(LibBufferHubTest, TestCreateConsumerWhenBufferReleased) {
430 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
431 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
432 ASSERT_TRUE(p.get() != nullptr);
433
434 std::unique_ptr<BufferConsumer> c1 =
435 BufferConsumer::Import(p->CreateConsumer());
436 ASSERT_TRUE(c1.get() != nullptr);
437
438 DvrNativeBufferMetadata metadata;
439 LocalHandle invalid_fence;
440
441 // Post, acquire, and release the buffer..
442 EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
443 EXPECT_LT(0, RETRY_EINTR(c1->Poll(10)));
444 EXPECT_EQ(0, c1->AcquireAsync(&metadata, &invalid_fence));
445 EXPECT_EQ(0, c1->ReleaseAsync(&metadata, invalid_fence));
446
447 // Create another consumer immediately after the release, should not make the
448 // buffer un-released. This is guaranteed by IPC execution order in bufferhubd.
449 std::unique_ptr<BufferConsumer> c2 =
450 BufferConsumer::Import(p->CreateConsumer());
451 ASSERT_TRUE(c2.get() != nullptr);
452
453 EXPECT_LT(0, RETRY_EINTR(p->Poll(10)));
454 EXPECT_TRUE(IsBufferReleased(p->buffer_state()));
455 EXPECT_EQ(0, p->GainAsync(&metadata, &invalid_fence));
456 EXPECT_TRUE(IsBufferGained(p->buffer_state()));
457}
458
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800459TEST_F(LibBufferHubTest, TestWithCustomMetadata) {
460 struct Metadata {
461 int64_t field1;
462 int64_t field2;
463 };
464 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
465 kWidth, kHeight, kFormat, kUsage, sizeof(Metadata));
466 ASSERT_TRUE(p.get() != nullptr);
467 std::unique_ptr<BufferConsumer> c =
468 BufferConsumer::Import(p->CreateConsumer());
469 ASSERT_TRUE(c.get() != nullptr);
470
471 Metadata m = {1, 3};
472 EXPECT_EQ(0, p->Post(LocalHandle(), m));
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800473 EXPECT_LE(0, RETRY_EINTR(c->Poll(10)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800474
475 LocalHandle fence;
476 Metadata m2 = {};
477 EXPECT_EQ(0, c->Acquire(&fence, &m2));
478 EXPECT_EQ(m.field1, m2.field1);
479 EXPECT_EQ(m.field2, m2.field2);
480
481 EXPECT_EQ(0, c->Release(LocalHandle()));
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800482 EXPECT_LT(0, RETRY_EINTR(p->Poll(0)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800483}
484
485TEST_F(LibBufferHubTest, TestPostWithWrongMetaSize) {
486 struct Metadata {
487 int64_t field1;
488 int64_t field2;
489 };
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700490 struct OverSizedMetadata {
491 int64_t field1;
492 int64_t field2;
493 int64_t field3;
494 };
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800495 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
496 kWidth, kHeight, kFormat, kUsage, sizeof(Metadata));
497 ASSERT_TRUE(p.get() != nullptr);
498 std::unique_ptr<BufferConsumer> c =
499 BufferConsumer::Import(p->CreateConsumer());
500 ASSERT_TRUE(c.get() != nullptr);
501
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700502 // It is illegal to post metadata larger than originally requested during
503 // buffer allocation.
504 OverSizedMetadata evil_meta = {};
505 EXPECT_NE(0, p->Post(LocalHandle(), evil_meta));
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800506 EXPECT_GE(0, RETRY_EINTR(c->Poll(10)));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700507
508 // It is ok to post metadata smaller than originally requested during
509 // buffer allocation.
510 int64_t sequence = 42;
511 EXPECT_EQ(0, p->Post(LocalHandle(), sequence));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800512}
513
514TEST_F(LibBufferHubTest, TestAcquireWithWrongMetaSize) {
515 struct Metadata {
516 int64_t field1;
517 int64_t field2;
518 };
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700519 struct OverSizedMetadata {
520 int64_t field1;
521 int64_t field2;
522 int64_t field3;
523 };
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800524 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
525 kWidth, kHeight, kFormat, kUsage, sizeof(Metadata));
526 ASSERT_TRUE(p.get() != nullptr);
527 std::unique_ptr<BufferConsumer> c =
528 BufferConsumer::Import(p->CreateConsumer());
529 ASSERT_TRUE(c.get() != nullptr);
530
531 Metadata m = {1, 3};
532 EXPECT_EQ(0, p->Post(LocalHandle(), m));
533
534 LocalHandle fence;
535 int64_t sequence;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700536 OverSizedMetadata e;
537
538 // It is illegal to acquire metadata larger than originally requested during
539 // buffer allocation.
540 EXPECT_NE(0, c->Acquire(&fence, &e));
541
542 // It is ok to acquire metadata smaller than originally requested during
543 // buffer allocation.
544 EXPECT_EQ(0, c->Acquire(&fence, &sequence));
545 EXPECT_EQ(m.field1, sequence);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800546}
547
548TEST_F(LibBufferHubTest, TestAcquireWithNoMeta) {
549 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
550 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
551 ASSERT_TRUE(p.get() != nullptr);
552 std::unique_ptr<BufferConsumer> c =
553 BufferConsumer::Import(p->CreateConsumer());
554 ASSERT_TRUE(c.get() != nullptr);
555
556 int64_t sequence = 3;
557 EXPECT_EQ(0, p->Post(LocalHandle(), sequence));
558
559 LocalHandle fence;
560 EXPECT_EQ(0, c->Acquire(&fence));
561}
562
563TEST_F(LibBufferHubTest, TestWithNoMeta) {
564 std::unique_ptr<BufferProducer> p =
565 BufferProducer::Create(kWidth, kHeight, kFormat, kUsage);
566 ASSERT_TRUE(p.get() != nullptr);
567 std::unique_ptr<BufferConsumer> c =
568 BufferConsumer::Import(p->CreateConsumer());
569 ASSERT_TRUE(c.get() != nullptr);
570
571 LocalHandle fence;
572
573 EXPECT_EQ(0, p->Post<void>(LocalHandle()));
574 EXPECT_EQ(0, c->Acquire(&fence));
575}
576
577TEST_F(LibBufferHubTest, TestFailureToPostMetaFromABufferWithoutMeta) {
578 std::unique_ptr<BufferProducer> p =
579 BufferProducer::Create(kWidth, kHeight, kFormat, kUsage);
580 ASSERT_TRUE(p.get() != nullptr);
581 std::unique_ptr<BufferConsumer> c =
582 BufferConsumer::Import(p->CreateConsumer());
583 ASSERT_TRUE(c.get() != nullptr);
584
585 int64_t sequence = 3;
586 EXPECT_NE(0, p->Post(LocalHandle(), sequence));
587}
588
589TEST_F(LibBufferHubTest, TestPersistentBufferPersistence) {
590 auto p = BufferProducer::Create("TestPersistentBuffer", -1, -1, kWidth,
591 kHeight, kFormat, kUsage);
592 ASSERT_NE(nullptr, p);
593
594 // Record the original buffer id for later comparison.
595 const int buffer_id = p->id();
596
597 auto c = BufferConsumer::Import(p->CreateConsumer());
598 ASSERT_NE(nullptr, c);
599
600 EXPECT_EQ(0, p->Post<void>(LocalHandle()));
601
602 // Close the connection to the producer. This should not affect the consumer.
603 p = nullptr;
604
605 LocalHandle fence;
606 EXPECT_EQ(0, c->Acquire(&fence));
607 EXPECT_EQ(0, c->Release(LocalHandle()));
608
609 // Attempt to reconnect to the persistent buffer.
610 p = BufferProducer::Create("TestPersistentBuffer");
611 ASSERT_NE(nullptr, p);
612 EXPECT_EQ(buffer_id, p->id());
613 EXPECT_EQ(0, p->Gain(&fence));
614}
615
616TEST_F(LibBufferHubTest, TestPersistentBufferMismatchParams) {
617 auto p = BufferProducer::Create("TestPersistentBuffer", -1, -1, kWidth,
618 kHeight, kFormat, kUsage);
619 ASSERT_NE(nullptr, p);
620
621 // Close the connection to the producer.
622 p = nullptr;
623
624 // Mismatch the params.
625 p = BufferProducer::Create("TestPersistentBuffer", -1, -1, kWidth * 2,
626 kHeight, kFormat, kUsage);
627 ASSERT_EQ(nullptr, p);
628}
629
630TEST_F(LibBufferHubTest, TestRemovePersistentBuffer) {
631 auto p = BufferProducer::Create("TestPersistentBuffer", -1, -1, kWidth,
632 kHeight, kFormat, kUsage);
633 ASSERT_NE(nullptr, p);
634
635 LocalHandle fence;
636 auto c = BufferConsumer::Import(p->CreateConsumer());
637 ASSERT_NE(nullptr, c);
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700638 EXPECT_EQ(0, p->Post<void>(LocalHandle()));
639 EXPECT_EQ(0, c->Acquire(&fence));
640 EXPECT_EQ(0, c->Release(LocalHandle()));
641 EXPECT_LT(0, RETRY_EINTR(p->Poll(10)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800642
643 // Test that removing persistence and closing the producer orphans the
644 // consumer.
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700645 EXPECT_EQ(0, p->Gain(&fence));
646 EXPECT_EQ(0, p->Post<void>(LocalHandle()));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800647 EXPECT_EQ(0, p->RemovePersistence());
648 p = nullptr;
649
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700650 // Orphaned consumer can acquire the posted buffer one more time in
651 // asynchronous manner. But synchronous call will fail.
652 DvrNativeBufferMetadata meta;
653 EXPECT_EQ(0, c->AcquireAsync(&meta, &fence));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800654 EXPECT_EQ(-EPIPE, c->Release(LocalHandle()));
655}
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700656
657namespace {
658
659int PollFd(int fd, int timeout_ms) {
660 pollfd p = {fd, POLLIN, 0};
661 return poll(&p, 1, timeout_ms);
662}
663
664} // namespace
665
666TEST_F(LibBufferHubTest, TestAcquireFence) {
667 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
668 kWidth, kHeight, kFormat, kUsage, /*metadata_size=*/0);
669 ASSERT_TRUE(p.get() != nullptr);
670 std::unique_ptr<BufferConsumer> c =
671 BufferConsumer::Import(p->CreateConsumer());
672 ASSERT_TRUE(c.get() != nullptr);
673
674 DvrNativeBufferMetadata meta;
675 LocalHandle f1(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
676
677 // Post with unsignaled fence.
678 EXPECT_EQ(0, p->PostAsync(&meta, f1));
679
680 // Should acquire a valid fence.
681 LocalHandle f2;
682 EXPECT_LT(0, RETRY_EINTR(c->Poll(10)));
683 EXPECT_EQ(0, c->AcquireAsync(&meta, &f2));
684 EXPECT_TRUE(f2.IsValid());
685 // The original fence and acquired fence should have different fd number.
686 EXPECT_NE(f1.Get(), f2.Get());
687 EXPECT_GE(0, PollFd(f2.Get(), 0));
688
689 // Signal the original fence will trigger the new fence.
690 eventfd_write(f1.Get(), 1);
691 // Now the original FD has been signaled.
692 EXPECT_LT(0, PollFd(f2.Get(), 10));
693
694 // Release the consumer with an invalid fence.
695 EXPECT_EQ(0, c->ReleaseAsync(&meta, LocalHandle()));
696
697 // Should gain an invalid fence.
698 LocalHandle f3;
699 EXPECT_LT(0, RETRY_EINTR(p->Poll(10)));
700 EXPECT_EQ(0, p->GainAsync(&meta, &f3));
701 EXPECT_FALSE(f3.IsValid());
702
703 // Post with a signaled fence.
704 EXPECT_EQ(0, p->PostAsync(&meta, f1));
705
706 // Should acquire a valid fence and it's already signalled.
707 LocalHandle f4;
708 EXPECT_LT(0, RETRY_EINTR(c->Poll(10)));
709 EXPECT_EQ(0, c->AcquireAsync(&meta, &f4));
710 EXPECT_TRUE(f4.IsValid());
711 EXPECT_LT(0, PollFd(f4.Get(), 10));
712
713 // Release with an unsignalled fence and signal it immediately after release
714 // without producer gainning.
715 LocalHandle f5(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
716 EXPECT_EQ(0, c->ReleaseAsync(&meta, f5));
717 eventfd_write(f5.Get(), 1);
718
719 // Should gain a valid fence, which is already signaled.
720 LocalHandle f6;
721 EXPECT_LT(0, RETRY_EINTR(p->Poll(10)));
722 EXPECT_EQ(0, p->GainAsync(&meta, &f6));
723 EXPECT_TRUE(f6.IsValid());
724 EXPECT_LT(0, PollFd(f6.Get(), 10));
725}
726
727TEST_F(LibBufferHubTest, TestOrphanedAcquire) {
728 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
729 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
730 ASSERT_TRUE(p.get() != nullptr);
731 std::unique_ptr<BufferConsumer> c1 =
732 BufferConsumer::Import(p->CreateConsumer());
733 ASSERT_TRUE(c1.get() != nullptr);
734 const uint64_t consumer_state_bit1 = c1->buffer_state_bit();
735
736 DvrNativeBufferMetadata meta;
737 EXPECT_EQ(0, p->PostAsync(&meta, LocalHandle()));
738
739 LocalHandle fence;
740 EXPECT_LT(0, RETRY_EINTR(c1->Poll(10)));
741 EXPECT_LE(0, c1->AcquireAsync(&meta, &fence));
742 // Destroy the consumer now will make it orphaned and the buffer is still
743 // acquired.
744 c1 = nullptr;
745 EXPECT_GE(0, RETRY_EINTR(p->Poll(10)));
746
747 std::unique_ptr<BufferConsumer> c2 =
748 BufferConsumer::Import(p->CreateConsumer());
749 ASSERT_TRUE(c2.get() != nullptr);
750 const uint64_t consumer_state_bit2 = c2->buffer_state_bit();
751 EXPECT_NE(consumer_state_bit1, consumer_state_bit2);
752
753 // The new consumer is available for acquire.
754 EXPECT_LT(0, RETRY_EINTR(c2->Poll(10)));
755 EXPECT_LE(0, c2->AcquireAsync(&meta, &fence));
756 // Releasing the consumer makes the buffer gainable.
757 EXPECT_EQ(0, c2->ReleaseAsync(&meta, LocalHandle()));
758
759 // The buffer is now available for the producer to gain.
760 EXPECT_LT(0, RETRY_EINTR(p->Poll(10)));
761
762 // But if another consumer is created in released state.
763 std::unique_ptr<BufferConsumer> c3 =
764 BufferConsumer::Import(p->CreateConsumer());
765 ASSERT_TRUE(c3.get() != nullptr);
766 const uint64_t consumer_state_bit3 = c3->buffer_state_bit();
767 EXPECT_NE(consumer_state_bit2, consumer_state_bit3);
768 // The consumer buffer is not acquirable.
769 EXPECT_GE(0, RETRY_EINTR(c3->Poll(10)));
770 EXPECT_EQ(-EBUSY, c3->AcquireAsync(&meta, &fence));
771
772 // Producer should be able to gain no matter what.
773 EXPECT_EQ(0, p->GainAsync(&meta, &fence));
774}