blob: 1daa5d62d794d62893543d1b58e56b9b30eda244 [file] [log] [blame]
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08001#include <gtest/gtest.h>
2#include <private/dvr/buffer_hub_client.h>
3
4#include <mutex>
5#include <thread>
6
Alex Vakulenko4fe60582017-02-02 11:35:59 -08007#define RETRY_EINTR(fnc_call) \
8 ([&]() -> decltype(fnc_call) { \
9 decltype(fnc_call) result; \
10 do { \
11 result = (fnc_call); \
12 } while (result == -1 && errno == EINTR); \
13 return result; \
14 })()
15
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080016using android::dvr::BufferProducer;
17using android::dvr::BufferConsumer;
18using android::pdx::LocalHandle;
19
20const int kWidth = 640;
21const int kHeight = 480;
22const int kFormat = HAL_PIXEL_FORMAT_RGBA_8888;
23const int kUsage = 0;
24const uint64_t kContext = 42;
25
26using LibBufferHubTest = ::testing::Test;
27
28TEST_F(LibBufferHubTest, TestBasicUsage) {
29 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
30 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
31 ASSERT_TRUE(p.get() != nullptr);
32 std::unique_ptr<BufferConsumer> c =
33 BufferConsumer::Import(p->CreateConsumer());
34 ASSERT_TRUE(c.get() != nullptr);
35 // Check that consumers can spawn other consumers.
36 std::unique_ptr<BufferConsumer> c2 =
37 BufferConsumer::Import(c->CreateConsumer());
38 ASSERT_TRUE(c2.get() != nullptr);
39
40 EXPECT_EQ(0, p->Post(LocalHandle(), kContext));
41 // Both consumers should be triggered.
Alex Vakulenko4fe60582017-02-02 11:35:59 -080042 EXPECT_GE(0, RETRY_EINTR(p->Poll(0)));
43 EXPECT_LT(0, RETRY_EINTR(c->Poll(10)));
44 EXPECT_LT(0, RETRY_EINTR(c2->Poll(10)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080045
46 uint64_t context;
47 LocalHandle fence;
48 EXPECT_LE(0, c->Acquire(&fence, &context));
49 EXPECT_EQ(kContext, context);
Alex Vakulenko4fe60582017-02-02 11:35:59 -080050 EXPECT_GE(0, RETRY_EINTR(c->Poll(0)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080051
52 EXPECT_LE(0, c2->Acquire(&fence, &context));
53 EXPECT_EQ(kContext, context);
Alex Vakulenko4fe60582017-02-02 11:35:59 -080054 EXPECT_GE(0, RETRY_EINTR(c2->Poll(0)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080055
56 EXPECT_EQ(0, c->Release(LocalHandle()));
Alex Vakulenko4fe60582017-02-02 11:35:59 -080057 EXPECT_GE(0, RETRY_EINTR(p->Poll(0)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080058 EXPECT_EQ(0, c2->Discard());
59
Alex Vakulenko4fe60582017-02-02 11:35:59 -080060 EXPECT_LE(0, RETRY_EINTR(p->Poll(0)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080061 EXPECT_EQ(0, p->Gain(&fence));
Alex Vakulenko4fe60582017-02-02 11:35:59 -080062 EXPECT_GE(0, RETRY_EINTR(p->Poll(0)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080063}
64
Corey Tabakad53870c2017-07-06 18:04:27 -070065TEST_F(LibBufferHubTest, TestStateTransitions) {
66 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
67 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
68 ASSERT_TRUE(p.get() != nullptr);
69 std::unique_ptr<BufferConsumer> c =
70 BufferConsumer::Import(p->CreateConsumer());
71 ASSERT_TRUE(c.get() != nullptr);
72
73 uint64_t context;
74 LocalHandle fence;
75
76 // The producer buffer starts in gained state.
77
78 // Acquire, release, and gain in gained state should fail.
79 EXPECT_EQ(-EBUSY, c->Acquire(&fence, &context));
80 EXPECT_EQ(-EBUSY, c->Release(LocalHandle()));
81 EXPECT_EQ(-EALREADY, p->Gain(&fence));
82
83 // Post in gained state should succeed.
84 EXPECT_EQ(0, p->Post(LocalHandle(), kContext));
85
86 // Post, release, and gain in posted state should fail.
87 EXPECT_EQ(-EBUSY, p->Post(LocalHandle(), kContext));
88 EXPECT_EQ(-EBUSY, c->Release(LocalHandle()));
89 EXPECT_EQ(-EBUSY, p->Gain(&fence));
90
91 // Acquire in posted state should succeed.
92 EXPECT_LE(0, c->Acquire(&fence, &context));
93
94 // Acquire, post, and gain in acquired state should fail.
95 EXPECT_EQ(-EBUSY, c->Acquire(&fence, &context));
96 EXPECT_EQ(-EBUSY, p->Post(LocalHandle(), kContext));
97 EXPECT_EQ(-EBUSY, p->Gain(&fence));
98
99 // Release in acquired state should succeed.
100 EXPECT_EQ(0, c->Release(LocalHandle()));
101
102 // Release, acquire, and post in released state should fail.
103 EXPECT_EQ(-EBUSY, c->Release(LocalHandle()));
104 EXPECT_EQ(-EBUSY, c->Acquire(&fence, &context));
105 EXPECT_EQ(-EBUSY, p->Post(LocalHandle(), kContext));
106
107 // Gain in released state should succeed.
108 EXPECT_EQ(0, p->Gain(&fence));
109
110 // Acquire, release, and gain in gained state should fail.
111 EXPECT_EQ(-EBUSY, c->Acquire(&fence, &context));
112 EXPECT_EQ(-EBUSY, c->Release(LocalHandle()));
113 EXPECT_EQ(-EALREADY, p->Gain(&fence));
114}
115
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800116TEST_F(LibBufferHubTest, TestWithCustomMetadata) {
117 struct Metadata {
118 int64_t field1;
119 int64_t field2;
120 };
121 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
122 kWidth, kHeight, kFormat, kUsage, sizeof(Metadata));
123 ASSERT_TRUE(p.get() != nullptr);
124 std::unique_ptr<BufferConsumer> c =
125 BufferConsumer::Import(p->CreateConsumer());
126 ASSERT_TRUE(c.get() != nullptr);
127
128 Metadata m = {1, 3};
129 EXPECT_EQ(0, p->Post(LocalHandle(), m));
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800130 EXPECT_LE(0, RETRY_EINTR(c->Poll(10)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800131
132 LocalHandle fence;
133 Metadata m2 = {};
134 EXPECT_EQ(0, c->Acquire(&fence, &m2));
135 EXPECT_EQ(m.field1, m2.field1);
136 EXPECT_EQ(m.field2, m2.field2);
137
138 EXPECT_EQ(0, c->Release(LocalHandle()));
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800139 EXPECT_LT(0, RETRY_EINTR(p->Poll(0)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800140}
141
142TEST_F(LibBufferHubTest, TestPostWithWrongMetaSize) {
143 struct Metadata {
144 int64_t field1;
145 int64_t field2;
146 };
147 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
148 kWidth, kHeight, kFormat, kUsage, sizeof(Metadata));
149 ASSERT_TRUE(p.get() != nullptr);
150 std::unique_ptr<BufferConsumer> c =
151 BufferConsumer::Import(p->CreateConsumer());
152 ASSERT_TRUE(c.get() != nullptr);
153
154 int64_t sequence = 3;
155 EXPECT_NE(0, p->Post(LocalHandle(), sequence));
Alex Vakulenko4fe60582017-02-02 11:35:59 -0800156 EXPECT_GE(0, RETRY_EINTR(c->Poll(10)));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800157}
158
159TEST_F(LibBufferHubTest, TestAcquireWithWrongMetaSize) {
160 struct Metadata {
161 int64_t field1;
162 int64_t field2;
163 };
164 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
165 kWidth, kHeight, kFormat, kUsage, sizeof(Metadata));
166 ASSERT_TRUE(p.get() != nullptr);
167 std::unique_ptr<BufferConsumer> c =
168 BufferConsumer::Import(p->CreateConsumer());
169 ASSERT_TRUE(c.get() != nullptr);
170
171 Metadata m = {1, 3};
172 EXPECT_EQ(0, p->Post(LocalHandle(), m));
173
174 LocalHandle fence;
175 int64_t sequence;
176 EXPECT_NE(0, c->Acquire(&fence, &sequence));
177}
178
179TEST_F(LibBufferHubTest, TestAcquireWithNoMeta) {
180 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
181 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
182 ASSERT_TRUE(p.get() != nullptr);
183 std::unique_ptr<BufferConsumer> c =
184 BufferConsumer::Import(p->CreateConsumer());
185 ASSERT_TRUE(c.get() != nullptr);
186
187 int64_t sequence = 3;
188 EXPECT_EQ(0, p->Post(LocalHandle(), sequence));
189
190 LocalHandle fence;
191 EXPECT_EQ(0, c->Acquire(&fence));
192}
193
194TEST_F(LibBufferHubTest, TestWithNoMeta) {
195 std::unique_ptr<BufferProducer> p =
196 BufferProducer::Create(kWidth, kHeight, kFormat, kUsage);
197 ASSERT_TRUE(p.get() != nullptr);
198 std::unique_ptr<BufferConsumer> c =
199 BufferConsumer::Import(p->CreateConsumer());
200 ASSERT_TRUE(c.get() != nullptr);
201
202 LocalHandle fence;
203
204 EXPECT_EQ(0, p->Post<void>(LocalHandle()));
205 EXPECT_EQ(0, c->Acquire(&fence));
206}
207
208TEST_F(LibBufferHubTest, TestFailureToPostMetaFromABufferWithoutMeta) {
209 std::unique_ptr<BufferProducer> p =
210 BufferProducer::Create(kWidth, kHeight, kFormat, kUsage);
211 ASSERT_TRUE(p.get() != nullptr);
212 std::unique_ptr<BufferConsumer> c =
213 BufferConsumer::Import(p->CreateConsumer());
214 ASSERT_TRUE(c.get() != nullptr);
215
216 int64_t sequence = 3;
217 EXPECT_NE(0, p->Post(LocalHandle(), sequence));
218}
219
220TEST_F(LibBufferHubTest, TestPersistentBufferPersistence) {
221 auto p = BufferProducer::Create("TestPersistentBuffer", -1, -1, kWidth,
222 kHeight, kFormat, kUsage);
223 ASSERT_NE(nullptr, p);
224
225 // Record the original buffer id for later comparison.
226 const int buffer_id = p->id();
227
228 auto c = BufferConsumer::Import(p->CreateConsumer());
229 ASSERT_NE(nullptr, c);
230
231 EXPECT_EQ(0, p->Post<void>(LocalHandle()));
232
233 // Close the connection to the producer. This should not affect the consumer.
234 p = nullptr;
235
236 LocalHandle fence;
237 EXPECT_EQ(0, c->Acquire(&fence));
238 EXPECT_EQ(0, c->Release(LocalHandle()));
239
240 // Attempt to reconnect to the persistent buffer.
241 p = BufferProducer::Create("TestPersistentBuffer");
242 ASSERT_NE(nullptr, p);
243 EXPECT_EQ(buffer_id, p->id());
244 EXPECT_EQ(0, p->Gain(&fence));
245}
246
247TEST_F(LibBufferHubTest, TestPersistentBufferMismatchParams) {
248 auto p = BufferProducer::Create("TestPersistentBuffer", -1, -1, kWidth,
249 kHeight, kFormat, kUsage);
250 ASSERT_NE(nullptr, p);
251
252 // Close the connection to the producer.
253 p = nullptr;
254
255 // Mismatch the params.
256 p = BufferProducer::Create("TestPersistentBuffer", -1, -1, kWidth * 2,
257 kHeight, kFormat, kUsage);
258 ASSERT_EQ(nullptr, p);
259}
260
261TEST_F(LibBufferHubTest, TestRemovePersistentBuffer) {
262 auto p = BufferProducer::Create("TestPersistentBuffer", -1, -1, kWidth,
263 kHeight, kFormat, kUsage);
264 ASSERT_NE(nullptr, p);
265
266 LocalHandle fence;
267 auto c = BufferConsumer::Import(p->CreateConsumer());
268 ASSERT_NE(nullptr, c);
269 EXPECT_NE(-EPIPE, c->Acquire(&fence));
270
271 // Test that removing persistence and closing the producer orphans the
272 // consumer.
273 EXPECT_EQ(0, p->RemovePersistence());
274 p = nullptr;
275
276 EXPECT_EQ(-EPIPE, c->Release(LocalHandle()));
277}