blob: a5cf9ae3cb52dc0261a7e2246d828152c020b885 [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;
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -080036const int kPollTimeoutMs = 100;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080037
38using LibBufferHubTest = ::testing::Test;
39
40TEST_F(LibBufferHubTest, TestBasicUsage) {
41 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
42 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
43 ASSERT_TRUE(p.get() != nullptr);
44 std::unique_ptr<BufferConsumer> c =
45 BufferConsumer::Import(p->CreateConsumer());
46 ASSERT_TRUE(c.get() != nullptr);
47 // Check that consumers can spawn other consumers.
48 std::unique_ptr<BufferConsumer> c2 =
49 BufferConsumer::Import(c->CreateConsumer());
50 ASSERT_TRUE(c2.get() != nullptr);
51
Corey Tabaka52ea25c2017-09-13 18:02:48 -070052 // Producer state mask is unique, i.e. 1.
53 EXPECT_EQ(p->buffer_state_bit(), kProducerStateBit);
54 // Consumer state mask cannot have producer bit on.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -080055 EXPECT_EQ(c->buffer_state_bit() & kProducerStateBit, 0U);
Corey Tabaka52ea25c2017-09-13 18:02:48 -070056 // Consumer state mask must be a single, i.e. power of 2.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -080057 EXPECT_NE(c->buffer_state_bit(), 0U);
58 EXPECT_EQ(c->buffer_state_bit() & (c->buffer_state_bit() - 1), 0U);
Corey Tabaka52ea25c2017-09-13 18:02:48 -070059 // Consumer state mask cannot have producer bit on.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -080060 EXPECT_EQ(c2->buffer_state_bit() & kProducerStateBit, 0U);
Corey Tabaka52ea25c2017-09-13 18:02:48 -070061 // Consumer state mask must be a single, i.e. power of 2.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -080062 EXPECT_NE(c2->buffer_state_bit(), 0U);
63 EXPECT_EQ(c2->buffer_state_bit() & (c2->buffer_state_bit() - 1), 0U);
Corey Tabaka52ea25c2017-09-13 18:02:48 -070064 // Each consumer should have unique bit.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -080065 EXPECT_EQ(c->buffer_state_bit() & c2->buffer_state_bit(), 0U);
Corey Tabaka52ea25c2017-09-13 18:02:48 -070066
67 // Initial state: producer not available, consumers not available.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -080068 EXPECT_EQ(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
69 EXPECT_EQ(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
70 EXPECT_EQ(0, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
Corey Tabaka52ea25c2017-09-13 18:02:48 -070071
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080072 EXPECT_EQ(0, p->Post(LocalHandle(), kContext));
Corey Tabaka52ea25c2017-09-13 18:02:48 -070073
74 // New state: producer not available, consumers available.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -080075 EXPECT_EQ(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
76 EXPECT_EQ(1, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
77 EXPECT_EQ(1, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080078
79 uint64_t context;
80 LocalHandle fence;
Corey Tabaka52ea25c2017-09-13 18:02:48 -070081 EXPECT_EQ(0, c->Acquire(&fence, &context));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080082 EXPECT_EQ(kContext, context);
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -080083 EXPECT_EQ(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
84 EXPECT_EQ(1, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080085
Corey Tabaka52ea25c2017-09-13 18:02:48 -070086 EXPECT_EQ(0, c2->Acquire(&fence, &context));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080087 EXPECT_EQ(kContext, context);
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -080088 EXPECT_EQ(0, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
89 EXPECT_EQ(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080090
91 EXPECT_EQ(0, c->Release(LocalHandle()));
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -080092 EXPECT_EQ(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080093 EXPECT_EQ(0, c2->Discard());
94
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -080095 EXPECT_EQ(1, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080096 EXPECT_EQ(0, p->Gain(&fence));
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -080097 EXPECT_EQ(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
98 EXPECT_EQ(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
99 EXPECT_EQ(0, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700100}
101
102TEST_F(LibBufferHubTest, TestEpoll) {
103 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
104 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
105 ASSERT_TRUE(p.get() != nullptr);
106 std::unique_ptr<BufferConsumer> c =
107 BufferConsumer::Import(p->CreateConsumer());
108 ASSERT_TRUE(c.get() != nullptr);
109
110 LocalHandle epoll_fd{epoll_create1(EPOLL_CLOEXEC)};
111 ASSERT_TRUE(epoll_fd.IsValid());
112
113 epoll_event event;
114 std::array<epoll_event, 64> events;
115
116 auto event_sources = p->GetEventSources();
117 ASSERT_LT(event_sources.size(), events.size());
118
119 for (const auto& event_source : event_sources) {
120 event = {.events = event_source.event_mask | EPOLLET,
121 .data = {.fd = p->event_fd()}};
122 ASSERT_EQ(0, epoll_ctl(epoll_fd.Get(), EPOLL_CTL_ADD, event_source.event_fd,
123 &event));
124 }
125
126 event_sources = c->GetEventSources();
127 ASSERT_LT(event_sources.size(), events.size());
128
129 for (const auto& event_source : event_sources) {
130 event = {.events = event_source.event_mask | EPOLLET,
131 .data = {.fd = c->event_fd()}};
132 ASSERT_EQ(0, epoll_ctl(epoll_fd.Get(), EPOLL_CTL_ADD, event_source.event_fd,
133 &event));
134 }
135
136 // No events should be signaled initially.
137 ASSERT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 0));
138
139 // Post the producer and check for consumer signal.
140 EXPECT_EQ(0, p->Post({}, kContext));
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800141 ASSERT_EQ(1, epoll_wait(epoll_fd.Get(), events.data(), events.size(),
142 kPollTimeoutMs));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700143 ASSERT_TRUE(events[0].events & EPOLLIN);
144 ASSERT_EQ(c->event_fd(), events[0].data.fd);
145
146 // Save the event bits to translate later.
147 event = events[0];
148
149 // Check for events again. Edge-triggered mode should prevent any.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800150 EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(),
151 kPollTimeoutMs));
152 EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(),
153 kPollTimeoutMs));
154 EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(),
155 kPollTimeoutMs));
156 EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(),
157 kPollTimeoutMs));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700158
159 // Translate the events.
160 auto event_status = c->GetEventMask(event.events);
161 ASSERT_TRUE(event_status);
162 ASSERT_TRUE(event_status.get() & EPOLLIN);
163
164 // Check for events again. Edge-triggered mode should prevent any.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800165 EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(),
166 kPollTimeoutMs));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700167}
168
169TEST_F(LibBufferHubTest, TestStateMask) {
170 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
171 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
172 ASSERT_TRUE(p.get() != nullptr);
173
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700174 // It's ok to create up to kMaxConsumerCount consumer buffers.
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700175 uint64_t buffer_state_bits = p->buffer_state_bit();
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700176 std::array<std::unique_ptr<BufferConsumer>, kMaxConsumerCount> cs;
177 for (size_t i = 0; i < kMaxConsumerCount; i++) {
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700178 cs[i] = BufferConsumer::Import(p->CreateConsumer());
179 ASSERT_TRUE(cs[i].get() != nullptr);
180 // Expect all buffers have unique state mask.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800181 EXPECT_EQ(buffer_state_bits & cs[i]->buffer_state_bit(), 0U);
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700182 buffer_state_bits |= cs[i]->buffer_state_bit();
183 }
184 EXPECT_EQ(buffer_state_bits, kProducerStateBit | kConsumerStateMask);
185
186 // The 64th creation will fail with out-of-memory error.
187 auto state = p->CreateConsumer();
188 EXPECT_EQ(state.error(), E2BIG);
189
190 // Release any consumer should allow us to re-create.
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700191 for (size_t i = 0; i < kMaxConsumerCount; i++) {
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700192 buffer_state_bits &= ~cs[i]->buffer_state_bit();
193 cs[i] = nullptr;
194 cs[i] = BufferConsumer::Import(p->CreateConsumer());
195 ASSERT_TRUE(cs[i].get() != nullptr);
196 // The released state mask will be reused.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800197 EXPECT_EQ(buffer_state_bits & cs[i]->buffer_state_bit(), 0U);
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700198 buffer_state_bits |= cs[i]->buffer_state_bit();
199 EXPECT_EQ(buffer_state_bits, kProducerStateBit | kConsumerStateMask);
200 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800201}
202
Corey Tabakad53870c2017-07-06 18:04:27 -0700203TEST_F(LibBufferHubTest, TestStateTransitions) {
204 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
205 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
206 ASSERT_TRUE(p.get() != nullptr);
207 std::unique_ptr<BufferConsumer> c =
208 BufferConsumer::Import(p->CreateConsumer());
209 ASSERT_TRUE(c.get() != nullptr);
210
211 uint64_t context;
212 LocalHandle fence;
213
214 // The producer buffer starts in gained state.
215
216 // Acquire, release, and gain in gained state should fail.
217 EXPECT_EQ(-EBUSY, c->Acquire(&fence, &context));
218 EXPECT_EQ(-EBUSY, c->Release(LocalHandle()));
219 EXPECT_EQ(-EALREADY, p->Gain(&fence));
220
221 // Post in gained state should succeed.
222 EXPECT_EQ(0, p->Post(LocalHandle(), kContext));
223
224 // Post, release, and gain in posted state should fail.
225 EXPECT_EQ(-EBUSY, p->Post(LocalHandle(), kContext));
226 EXPECT_EQ(-EBUSY, c->Release(LocalHandle()));
227 EXPECT_EQ(-EBUSY, p->Gain(&fence));
228
229 // Acquire in posted state should succeed.
230 EXPECT_LE(0, c->Acquire(&fence, &context));
231
232 // Acquire, post, and gain in acquired state should fail.
233 EXPECT_EQ(-EBUSY, c->Acquire(&fence, &context));
234 EXPECT_EQ(-EBUSY, p->Post(LocalHandle(), kContext));
235 EXPECT_EQ(-EBUSY, p->Gain(&fence));
236
237 // Release in acquired state should succeed.
238 EXPECT_EQ(0, c->Release(LocalHandle()));
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800239 EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
Corey Tabakad53870c2017-07-06 18:04:27 -0700240
241 // Release, acquire, and post in released state should fail.
242 EXPECT_EQ(-EBUSY, c->Release(LocalHandle()));
243 EXPECT_EQ(-EBUSY, c->Acquire(&fence, &context));
244 EXPECT_EQ(-EBUSY, p->Post(LocalHandle(), kContext));
245
246 // Gain in released state should succeed.
247 EXPECT_EQ(0, p->Gain(&fence));
248
249 // Acquire, release, and gain in gained state should fail.
250 EXPECT_EQ(-EBUSY, c->Acquire(&fence, &context));
251 EXPECT_EQ(-EBUSY, c->Release(LocalHandle()));
252 EXPECT_EQ(-EALREADY, p->Gain(&fence));
253}
254
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700255TEST_F(LibBufferHubTest, TestAsyncStateTransitions) {
256 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
257 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
258 ASSERT_TRUE(p.get() != nullptr);
259 std::unique_ptr<BufferConsumer> c =
260 BufferConsumer::Import(p->CreateConsumer());
261 ASSERT_TRUE(c.get() != nullptr);
262
263 DvrNativeBufferMetadata metadata;
264 LocalHandle invalid_fence;
265
266 // The producer buffer starts in gained state.
267
268 // Acquire, release, and gain in gained state should fail.
269 EXPECT_EQ(-EBUSY, c->AcquireAsync(&metadata, &invalid_fence));
270 EXPECT_FALSE(invalid_fence.IsValid());
271 EXPECT_EQ(-EBUSY, c->ReleaseAsync(&metadata, invalid_fence));
272 EXPECT_EQ(-EALREADY, p->GainAsync(&metadata, &invalid_fence));
273 EXPECT_FALSE(invalid_fence.IsValid());
274
275 // Post in gained state should succeed.
276 EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
277 EXPECT_EQ(p->buffer_state(), c->buffer_state());
278 EXPECT_TRUE(IsBufferPosted(p->buffer_state()));
279
280 // Post, release, and gain in posted state should fail.
281 EXPECT_EQ(-EBUSY, p->PostAsync(&metadata, invalid_fence));
282 EXPECT_EQ(-EBUSY, c->ReleaseAsync(&metadata, invalid_fence));
283 EXPECT_EQ(-EBUSY, p->GainAsync(&metadata, &invalid_fence));
284 EXPECT_FALSE(invalid_fence.IsValid());
285
286 // Acquire in posted state should succeed.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800287 EXPECT_LT(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700288 EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
289 EXPECT_FALSE(invalid_fence.IsValid());
290 EXPECT_EQ(p->buffer_state(), c->buffer_state());
291 EXPECT_TRUE(IsBufferAcquired(p->buffer_state()));
292
293 // Acquire, post, and gain in acquired state should fail.
294 EXPECT_EQ(-EBUSY, c->AcquireAsync(&metadata, &invalid_fence));
295 EXPECT_FALSE(invalid_fence.IsValid());
296 EXPECT_EQ(-EBUSY, p->PostAsync(&metadata, invalid_fence));
297 EXPECT_EQ(-EBUSY, p->GainAsync(&metadata, &invalid_fence));
298 EXPECT_FALSE(invalid_fence.IsValid());
299
300 // Release in acquired state should succeed.
301 EXPECT_EQ(0, c->ReleaseAsync(&metadata, invalid_fence));
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800302 EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700303 EXPECT_EQ(p->buffer_state(), c->buffer_state());
304 EXPECT_TRUE(IsBufferReleased(p->buffer_state()));
305
306 // Release, acquire, and post in released state should fail.
307 EXPECT_EQ(-EBUSY, c->ReleaseAsync(&metadata, invalid_fence));
308 EXPECT_EQ(-EBUSY, c->AcquireAsync(&metadata, &invalid_fence));
309 EXPECT_FALSE(invalid_fence.IsValid());
310 EXPECT_EQ(-EBUSY, p->PostAsync(&metadata, invalid_fence));
311
312 // Gain in released state should succeed.
313 EXPECT_EQ(0, p->GainAsync(&metadata, &invalid_fence));
314 EXPECT_FALSE(invalid_fence.IsValid());
315 EXPECT_EQ(p->buffer_state(), c->buffer_state());
316 EXPECT_TRUE(IsBufferGained(p->buffer_state()));
317
318 // Acquire, release, and gain in gained state should fail.
319 EXPECT_EQ(-EBUSY, c->AcquireAsync(&metadata, &invalid_fence));
320 EXPECT_FALSE(invalid_fence.IsValid());
321 EXPECT_EQ(-EBUSY, c->ReleaseAsync(&metadata, invalid_fence));
322 EXPECT_EQ(-EALREADY, p->GainAsync(&metadata, &invalid_fence));
323 EXPECT_FALSE(invalid_fence.IsValid());
324}
325
326TEST_F(LibBufferHubTest, TestZeroConsumer) {
327 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
328 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
329 ASSERT_TRUE(p.get() != nullptr);
330
331 DvrNativeBufferMetadata metadata;
332 LocalHandle invalid_fence;
333
334 // Newly created.
335 EXPECT_TRUE(IsBufferGained(p->buffer_state()));
336 EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
337 EXPECT_TRUE(IsBufferPosted(p->buffer_state()));
338
339 // The buffer should stay in posted stay until a consumer picks it up.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800340 EXPECT_GE(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700341
342 // A new consumer should still be able to acquire the buffer immediately.
343 std::unique_ptr<BufferConsumer> c =
344 BufferConsumer::Import(p->CreateConsumer());
345 ASSERT_TRUE(c.get() != nullptr);
346 EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
347 EXPECT_TRUE(IsBufferAcquired(c->buffer_state()));
348}
349
350TEST_F(LibBufferHubTest, TestMaxConsumers) {
351 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
352 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
353 ASSERT_TRUE(p.get() != nullptr);
354
355 std::array<std::unique_ptr<BufferConsumer>, kMaxConsumerCount> cs;
356 for (size_t i = 0; i < kMaxConsumerCount; i++) {
357 cs[i] = BufferConsumer::Import(p->CreateConsumer());
358 ASSERT_TRUE(cs[i].get() != nullptr);
359 EXPECT_TRUE(IsBufferGained(cs[i]->buffer_state()));
360 }
361
362 DvrNativeBufferMetadata metadata;
363 LocalHandle invalid_fence;
364
365 // Post the producer should trigger all consumers to be available.
366 EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
367 EXPECT_TRUE(IsBufferPosted(p->buffer_state()));
368 for (size_t i = 0; i < kMaxConsumerCount; i++) {
369 EXPECT_TRUE(IsBufferPosted(cs[i]->buffer_state(),
370 cs[i]->buffer_state_bit()));
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800371 EXPECT_LT(0, RETRY_EINTR(cs[i]->Poll(kPollTimeoutMs)));
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700372 EXPECT_EQ(0, cs[i]->AcquireAsync(&metadata, &invalid_fence));
373 EXPECT_TRUE(IsBufferAcquired(p->buffer_state()));
374 }
375
376 // All consumers have to release before the buffer is considered to be
377 // released.
378 for (size_t i = 0; i < kMaxConsumerCount; i++) {
379 EXPECT_FALSE(IsBufferReleased(p->buffer_state()));
380 EXPECT_EQ(0, cs[i]->ReleaseAsync(&metadata, invalid_fence));
381 }
382
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800383 EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700384 EXPECT_TRUE(IsBufferReleased(p->buffer_state()));
385
386 // Buffer state cross all clients must be consistent.
387 for (size_t i = 0; i < kMaxConsumerCount; i++) {
388 EXPECT_EQ(p->buffer_state(), cs[i]->buffer_state());
389 }
390}
391
392TEST_F(LibBufferHubTest, TestCreateConsumerWhenBufferGained) {
393 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
394 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
395 ASSERT_TRUE(p.get() != nullptr);
396 EXPECT_TRUE(IsBufferGained(p->buffer_state()));
397
398 std::unique_ptr<BufferConsumer> c =
399 BufferConsumer::Import(p->CreateConsumer());
400 ASSERT_TRUE(c.get() != nullptr);
401 EXPECT_TRUE(IsBufferGained(c->buffer_state()));
402
403 DvrNativeBufferMetadata metadata;
404 LocalHandle invalid_fence;
405
406 // Post the gained buffer should signal already created consumer.
407 EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
408 EXPECT_TRUE(IsBufferPosted(p->buffer_state()));
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800409 EXPECT_LT(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700410 EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
411 EXPECT_TRUE(IsBufferAcquired(c->buffer_state()));
412}
413
414TEST_F(LibBufferHubTest, TestCreateConsumerWhenBufferPosted) {
415 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
416 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
417 ASSERT_TRUE(p.get() != nullptr);
418 EXPECT_TRUE(IsBufferGained(p->buffer_state()));
419
420 DvrNativeBufferMetadata metadata;
421 LocalHandle invalid_fence;
422
423 // Post the gained buffer before any consumer gets created.
424 EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
425 EXPECT_TRUE(IsBufferPosted(p->buffer_state()));
426
427 // Newly created consumer should be automatically sigalled.
428 std::unique_ptr<BufferConsumer> c =
429 BufferConsumer::Import(p->CreateConsumer());
430 ASSERT_TRUE(c.get() != nullptr);
431 EXPECT_TRUE(IsBufferPosted(c->buffer_state()));
432 EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
433 EXPECT_TRUE(IsBufferAcquired(c->buffer_state()));
434}
435
436TEST_F(LibBufferHubTest, TestCreateConsumerWhenBufferReleased) {
437 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
438 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
439 ASSERT_TRUE(p.get() != nullptr);
440
441 std::unique_ptr<BufferConsumer> c1 =
442 BufferConsumer::Import(p->CreateConsumer());
443 ASSERT_TRUE(c1.get() != nullptr);
444
445 DvrNativeBufferMetadata metadata;
446 LocalHandle invalid_fence;
447
448 // Post, acquire, and release the buffer..
449 EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800450 EXPECT_LT(0, RETRY_EINTR(c1->Poll(kPollTimeoutMs)));
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700451 EXPECT_EQ(0, c1->AcquireAsync(&metadata, &invalid_fence));
452 EXPECT_EQ(0, c1->ReleaseAsync(&metadata, invalid_fence));
453
454 // Create another consumer immediately after the release, should not make the
455 // buffer un-released. This is guaranteed by IPC execution order in bufferhubd.
456 std::unique_ptr<BufferConsumer> c2 =
457 BufferConsumer::Import(p->CreateConsumer());
458 ASSERT_TRUE(c2.get() != nullptr);
459
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800460 EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
Jiwen 'Steve' Cai9e7f3032017-10-20 18:39:47 -0700461 EXPECT_TRUE(IsBufferReleased(p->buffer_state()));
462 EXPECT_EQ(0, p->GainAsync(&metadata, &invalid_fence));
463 EXPECT_TRUE(IsBufferGained(p->buffer_state()));
464}
465
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800466TEST_F(LibBufferHubTest, TestWithCustomMetadata) {
467 struct Metadata {
468 int64_t field1;
469 int64_t field2;
470 };
471 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
472 kWidth, kHeight, kFormat, kUsage, sizeof(Metadata));
473 ASSERT_TRUE(p.get() != nullptr);
474 std::unique_ptr<BufferConsumer> c =
475 BufferConsumer::Import(p->CreateConsumer());
476 ASSERT_TRUE(c.get() != nullptr);
477
478 Metadata m = {1, 3};
479 EXPECT_EQ(0, p->Post(LocalHandle(), m));
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800480 EXPECT_LE(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800481
482 LocalHandle fence;
483 Metadata m2 = {};
484 EXPECT_EQ(0, c->Acquire(&fence, &m2));
485 EXPECT_EQ(m.field1, m2.field1);
486 EXPECT_EQ(m.field2, m2.field2);
487
488 EXPECT_EQ(0, c->Release(LocalHandle()));
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800489 EXPECT_LT(0, RETRY_EINTR(p->Poll(0)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800490}
491
492TEST_F(LibBufferHubTest, TestPostWithWrongMetaSize) {
493 struct Metadata {
494 int64_t field1;
495 int64_t field2;
496 };
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700497 struct OverSizedMetadata {
498 int64_t field1;
499 int64_t field2;
500 int64_t field3;
501 };
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800502 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
503 kWidth, kHeight, kFormat, kUsage, sizeof(Metadata));
504 ASSERT_TRUE(p.get() != nullptr);
505 std::unique_ptr<BufferConsumer> c =
506 BufferConsumer::Import(p->CreateConsumer());
507 ASSERT_TRUE(c.get() != nullptr);
508
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700509 // It is illegal to post metadata larger than originally requested during
510 // buffer allocation.
511 OverSizedMetadata evil_meta = {};
512 EXPECT_NE(0, p->Post(LocalHandle(), evil_meta));
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800513 EXPECT_GE(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700514
515 // It is ok to post metadata smaller than originally requested during
516 // buffer allocation.
517 int64_t sequence = 42;
518 EXPECT_EQ(0, p->Post(LocalHandle(), sequence));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800519}
520
521TEST_F(LibBufferHubTest, TestAcquireWithWrongMetaSize) {
522 struct Metadata {
523 int64_t field1;
524 int64_t field2;
525 };
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700526 struct OverSizedMetadata {
527 int64_t field1;
528 int64_t field2;
529 int64_t field3;
530 };
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800531 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
532 kWidth, kHeight, kFormat, kUsage, sizeof(Metadata));
533 ASSERT_TRUE(p.get() != nullptr);
534 std::unique_ptr<BufferConsumer> c =
535 BufferConsumer::Import(p->CreateConsumer());
536 ASSERT_TRUE(c.get() != nullptr);
537
538 Metadata m = {1, 3};
539 EXPECT_EQ(0, p->Post(LocalHandle(), m));
540
541 LocalHandle fence;
542 int64_t sequence;
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700543 OverSizedMetadata e;
544
545 // It is illegal to acquire metadata larger than originally requested during
546 // buffer allocation.
547 EXPECT_NE(0, c->Acquire(&fence, &e));
548
549 // It is ok to acquire metadata smaller than originally requested during
550 // buffer allocation.
551 EXPECT_EQ(0, c->Acquire(&fence, &sequence));
552 EXPECT_EQ(m.field1, sequence);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800553}
554
555TEST_F(LibBufferHubTest, TestAcquireWithNoMeta) {
556 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
557 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
558 ASSERT_TRUE(p.get() != nullptr);
559 std::unique_ptr<BufferConsumer> c =
560 BufferConsumer::Import(p->CreateConsumer());
561 ASSERT_TRUE(c.get() != nullptr);
562
563 int64_t sequence = 3;
564 EXPECT_EQ(0, p->Post(LocalHandle(), sequence));
565
566 LocalHandle fence;
567 EXPECT_EQ(0, c->Acquire(&fence));
568}
569
570TEST_F(LibBufferHubTest, TestWithNoMeta) {
571 std::unique_ptr<BufferProducer> p =
572 BufferProducer::Create(kWidth, kHeight, kFormat, kUsage);
573 ASSERT_TRUE(p.get() != nullptr);
574 std::unique_ptr<BufferConsumer> c =
575 BufferConsumer::Import(p->CreateConsumer());
576 ASSERT_TRUE(c.get() != nullptr);
577
578 LocalHandle fence;
579
580 EXPECT_EQ(0, p->Post<void>(LocalHandle()));
581 EXPECT_EQ(0, c->Acquire(&fence));
582}
583
584TEST_F(LibBufferHubTest, TestFailureToPostMetaFromABufferWithoutMeta) {
585 std::unique_ptr<BufferProducer> p =
586 BufferProducer::Create(kWidth, kHeight, kFormat, kUsage);
587 ASSERT_TRUE(p.get() != nullptr);
588 std::unique_ptr<BufferConsumer> c =
589 BufferConsumer::Import(p->CreateConsumer());
590 ASSERT_TRUE(c.get() != nullptr);
591
592 int64_t sequence = 3;
593 EXPECT_NE(0, p->Post(LocalHandle(), sequence));
594}
595
596TEST_F(LibBufferHubTest, TestPersistentBufferPersistence) {
597 auto p = BufferProducer::Create("TestPersistentBuffer", -1, -1, kWidth,
598 kHeight, kFormat, kUsage);
599 ASSERT_NE(nullptr, p);
600
601 // Record the original buffer id for later comparison.
602 const int buffer_id = p->id();
603
604 auto c = BufferConsumer::Import(p->CreateConsumer());
605 ASSERT_NE(nullptr, c);
606
607 EXPECT_EQ(0, p->Post<void>(LocalHandle()));
608
609 // Close the connection to the producer. This should not affect the consumer.
610 p = nullptr;
611
612 LocalHandle fence;
613 EXPECT_EQ(0, c->Acquire(&fence));
614 EXPECT_EQ(0, c->Release(LocalHandle()));
615
616 // Attempt to reconnect to the persistent buffer.
617 p = BufferProducer::Create("TestPersistentBuffer");
618 ASSERT_NE(nullptr, p);
619 EXPECT_EQ(buffer_id, p->id());
620 EXPECT_EQ(0, p->Gain(&fence));
621}
622
623TEST_F(LibBufferHubTest, TestPersistentBufferMismatchParams) {
624 auto p = BufferProducer::Create("TestPersistentBuffer", -1, -1, kWidth,
625 kHeight, kFormat, kUsage);
626 ASSERT_NE(nullptr, p);
627
628 // Close the connection to the producer.
629 p = nullptr;
630
631 // Mismatch the params.
632 p = BufferProducer::Create("TestPersistentBuffer", -1, -1, kWidth * 2,
633 kHeight, kFormat, kUsage);
634 ASSERT_EQ(nullptr, p);
635}
636
637TEST_F(LibBufferHubTest, TestRemovePersistentBuffer) {
638 auto p = BufferProducer::Create("TestPersistentBuffer", -1, -1, kWidth,
639 kHeight, kFormat, kUsage);
640 ASSERT_NE(nullptr, p);
641
642 LocalHandle fence;
643 auto c = BufferConsumer::Import(p->CreateConsumer());
644 ASSERT_NE(nullptr, c);
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700645 EXPECT_EQ(0, p->Post<void>(LocalHandle()));
646 EXPECT_EQ(0, c->Acquire(&fence));
647 EXPECT_EQ(0, c->Release(LocalHandle()));
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800648 EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800649
650 // Test that removing persistence and closing the producer orphans the
651 // consumer.
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700652 EXPECT_EQ(0, p->Gain(&fence));
653 EXPECT_EQ(0, p->Post<void>(LocalHandle()));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800654 EXPECT_EQ(0, p->RemovePersistence());
655 p = nullptr;
656
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700657 // Orphaned consumer can acquire the posted buffer one more time in
658 // asynchronous manner. But synchronous call will fail.
659 DvrNativeBufferMetadata meta;
660 EXPECT_EQ(0, c->AcquireAsync(&meta, &fence));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800661 EXPECT_EQ(-EPIPE, c->Release(LocalHandle()));
662}
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700663
664namespace {
665
666int PollFd(int fd, int timeout_ms) {
667 pollfd p = {fd, POLLIN, 0};
668 return poll(&p, 1, timeout_ms);
669}
670
671} // namespace
672
673TEST_F(LibBufferHubTest, TestAcquireFence) {
674 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
675 kWidth, kHeight, kFormat, kUsage, /*metadata_size=*/0);
676 ASSERT_TRUE(p.get() != nullptr);
677 std::unique_ptr<BufferConsumer> c =
678 BufferConsumer::Import(p->CreateConsumer());
679 ASSERT_TRUE(c.get() != nullptr);
680
681 DvrNativeBufferMetadata meta;
682 LocalHandle f1(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
683
684 // Post with unsignaled fence.
685 EXPECT_EQ(0, p->PostAsync(&meta, f1));
686
687 // Should acquire a valid fence.
688 LocalHandle f2;
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800689 EXPECT_LT(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700690 EXPECT_EQ(0, c->AcquireAsync(&meta, &f2));
691 EXPECT_TRUE(f2.IsValid());
692 // The original fence and acquired fence should have different fd number.
693 EXPECT_NE(f1.Get(), f2.Get());
694 EXPECT_GE(0, PollFd(f2.Get(), 0));
695
696 // Signal the original fence will trigger the new fence.
697 eventfd_write(f1.Get(), 1);
698 // Now the original FD has been signaled.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800699 EXPECT_LT(0, PollFd(f2.Get(), kPollTimeoutMs));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700700
701 // Release the consumer with an invalid fence.
702 EXPECT_EQ(0, c->ReleaseAsync(&meta, LocalHandle()));
703
704 // Should gain an invalid fence.
705 LocalHandle f3;
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800706 EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700707 EXPECT_EQ(0, p->GainAsync(&meta, &f3));
708 EXPECT_FALSE(f3.IsValid());
709
710 // Post with a signaled fence.
711 EXPECT_EQ(0, p->PostAsync(&meta, f1));
712
713 // Should acquire a valid fence and it's already signalled.
714 LocalHandle f4;
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800715 EXPECT_LT(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700716 EXPECT_EQ(0, c->AcquireAsync(&meta, &f4));
717 EXPECT_TRUE(f4.IsValid());
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800718 EXPECT_LT(0, PollFd(f4.Get(), kPollTimeoutMs));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700719
720 // Release with an unsignalled fence and signal it immediately after release
721 // without producer gainning.
722 LocalHandle f5(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
723 EXPECT_EQ(0, c->ReleaseAsync(&meta, f5));
724 eventfd_write(f5.Get(), 1);
725
726 // Should gain a valid fence, which is already signaled.
727 LocalHandle f6;
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800728 EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700729 EXPECT_EQ(0, p->GainAsync(&meta, &f6));
730 EXPECT_TRUE(f6.IsValid());
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800731 EXPECT_LT(0, PollFd(f6.Get(), kPollTimeoutMs));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700732}
733
734TEST_F(LibBufferHubTest, TestOrphanedAcquire) {
735 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
736 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
737 ASSERT_TRUE(p.get() != nullptr);
738 std::unique_ptr<BufferConsumer> c1 =
739 BufferConsumer::Import(p->CreateConsumer());
740 ASSERT_TRUE(c1.get() != nullptr);
741 const uint64_t consumer_state_bit1 = c1->buffer_state_bit();
742
743 DvrNativeBufferMetadata meta;
744 EXPECT_EQ(0, p->PostAsync(&meta, LocalHandle()));
745
746 LocalHandle fence;
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800747 EXPECT_LT(0, RETRY_EINTR(c1->Poll(kPollTimeoutMs)));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700748 EXPECT_LE(0, c1->AcquireAsync(&meta, &fence));
749 // Destroy the consumer now will make it orphaned and the buffer is still
750 // acquired.
751 c1 = nullptr;
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800752 EXPECT_GE(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700753
754 std::unique_ptr<BufferConsumer> c2 =
755 BufferConsumer::Import(p->CreateConsumer());
756 ASSERT_TRUE(c2.get() != nullptr);
757 const uint64_t consumer_state_bit2 = c2->buffer_state_bit();
758 EXPECT_NE(consumer_state_bit1, consumer_state_bit2);
759
760 // The new consumer is available for acquire.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800761 EXPECT_LT(0, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700762 EXPECT_LE(0, c2->AcquireAsync(&meta, &fence));
763 // Releasing the consumer makes the buffer gainable.
764 EXPECT_EQ(0, c2->ReleaseAsync(&meta, LocalHandle()));
765
766 // The buffer is now available for the producer to gain.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800767 EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700768
769 // But if another consumer is created in released state.
770 std::unique_ptr<BufferConsumer> c3 =
771 BufferConsumer::Import(p->CreateConsumer());
772 ASSERT_TRUE(c3.get() != nullptr);
773 const uint64_t consumer_state_bit3 = c3->buffer_state_bit();
774 EXPECT_NE(consumer_state_bit2, consumer_state_bit3);
775 // The consumer buffer is not acquirable.
Jiwen 'Steve' Cai30be1112017-11-08 17:12:20 -0800776 EXPECT_GE(0, RETRY_EINTR(c3->Poll(kPollTimeoutMs)));
Corey Tabaka52ea25c2017-09-13 18:02:48 -0700777 EXPECT_EQ(-EBUSY, c3->AcquireAsync(&meta, &fence));
778
779 // Producer should be able to gain no matter what.
780 EXPECT_EQ(0, p->GainAsync(&meta, &fence));
781}