1 #include <gtest/gtest.h>
2 #include <private/dvr/buffer_hub_client.h>
3
4 #include <mutex>
5 #include <thread>
6
7 #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
16 using android::dvr::BufferProducer;
17 using android::dvr::BufferConsumer;
18 using android::pdx::LocalHandle;
19
20 const int kWidth = 640;
21 const int kHeight = 480;
22 const int kFormat = HAL_PIXEL_FORMAT_RGBA_8888;
23 const int kUsage = 0;
24 const uint64_t kContext = 42;
25
26 using LibBufferHubTest = ::testing::Test;
27
TEST_F(LibBufferHubTest,TestBasicUsage)28 TEST_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.
42 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)));
45
46 uint64_t context;
47 LocalHandle fence;
48 EXPECT_LE(0, c->Acquire(&fence, &context));
49 EXPECT_EQ(kContext, context);
50 EXPECT_GE(0, RETRY_EINTR(c->Poll(0)));
51
52 EXPECT_LE(0, c2->Acquire(&fence, &context));
53 EXPECT_EQ(kContext, context);
54 EXPECT_GE(0, RETRY_EINTR(c2->Poll(0)));
55
56 EXPECT_EQ(0, c->Release(LocalHandle()));
57 EXPECT_GE(0, RETRY_EINTR(p->Poll(0)));
58 EXPECT_EQ(0, c2->Discard());
59
60 EXPECT_LE(0, RETRY_EINTR(p->Poll(0)));
61 EXPECT_EQ(0, p->Gain(&fence));
62 EXPECT_GE(0, RETRY_EINTR(p->Poll(0)));
63 }
64
TEST_F(LibBufferHubTest,TestWithCustomMetadata)65 TEST_F(LibBufferHubTest, TestWithCustomMetadata) {
66 struct Metadata {
67 int64_t field1;
68 int64_t field2;
69 };
70 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
71 kWidth, kHeight, kFormat, kUsage, sizeof(Metadata));
72 ASSERT_TRUE(p.get() != nullptr);
73 std::unique_ptr<BufferConsumer> c =
74 BufferConsumer::Import(p->CreateConsumer());
75 ASSERT_TRUE(c.get() != nullptr);
76
77 Metadata m = {1, 3};
78 EXPECT_EQ(0, p->Post(LocalHandle(), m));
79 EXPECT_LE(0, RETRY_EINTR(c->Poll(10)));
80
81 LocalHandle fence;
82 Metadata m2 = {};
83 EXPECT_EQ(0, c->Acquire(&fence, &m2));
84 EXPECT_EQ(m.field1, m2.field1);
85 EXPECT_EQ(m.field2, m2.field2);
86
87 EXPECT_EQ(0, c->Release(LocalHandle()));
88 EXPECT_LT(0, RETRY_EINTR(p->Poll(0)));
89 }
90
TEST_F(LibBufferHubTest,TestPostWithWrongMetaSize)91 TEST_F(LibBufferHubTest, TestPostWithWrongMetaSize) {
92 struct Metadata {
93 int64_t field1;
94 int64_t field2;
95 };
96 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
97 kWidth, kHeight, kFormat, kUsage, sizeof(Metadata));
98 ASSERT_TRUE(p.get() != nullptr);
99 std::unique_ptr<BufferConsumer> c =
100 BufferConsumer::Import(p->CreateConsumer());
101 ASSERT_TRUE(c.get() != nullptr);
102
103 int64_t sequence = 3;
104 EXPECT_NE(0, p->Post(LocalHandle(), sequence));
105 EXPECT_GE(0, RETRY_EINTR(c->Poll(10)));
106 }
107
TEST_F(LibBufferHubTest,TestAcquireWithWrongMetaSize)108 TEST_F(LibBufferHubTest, TestAcquireWithWrongMetaSize) {
109 struct Metadata {
110 int64_t field1;
111 int64_t field2;
112 };
113 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
114 kWidth, kHeight, kFormat, kUsage, sizeof(Metadata));
115 ASSERT_TRUE(p.get() != nullptr);
116 std::unique_ptr<BufferConsumer> c =
117 BufferConsumer::Import(p->CreateConsumer());
118 ASSERT_TRUE(c.get() != nullptr);
119
120 Metadata m = {1, 3};
121 EXPECT_EQ(0, p->Post(LocalHandle(), m));
122
123 LocalHandle fence;
124 int64_t sequence;
125 EXPECT_NE(0, c->Acquire(&fence, &sequence));
126 }
127
TEST_F(LibBufferHubTest,TestAcquireWithNoMeta)128 TEST_F(LibBufferHubTest, TestAcquireWithNoMeta) {
129 std::unique_ptr<BufferProducer> p = BufferProducer::Create(
130 kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
131 ASSERT_TRUE(p.get() != nullptr);
132 std::unique_ptr<BufferConsumer> c =
133 BufferConsumer::Import(p->CreateConsumer());
134 ASSERT_TRUE(c.get() != nullptr);
135
136 int64_t sequence = 3;
137 EXPECT_EQ(0, p->Post(LocalHandle(), sequence));
138
139 LocalHandle fence;
140 EXPECT_EQ(0, c->Acquire(&fence));
141 }
142
TEST_F(LibBufferHubTest,TestWithNoMeta)143 TEST_F(LibBufferHubTest, TestWithNoMeta) {
144 std::unique_ptr<BufferProducer> p =
145 BufferProducer::Create(kWidth, kHeight, kFormat, kUsage);
146 ASSERT_TRUE(p.get() != nullptr);
147 std::unique_ptr<BufferConsumer> c =
148 BufferConsumer::Import(p->CreateConsumer());
149 ASSERT_TRUE(c.get() != nullptr);
150
151 LocalHandle fence;
152
153 EXPECT_EQ(0, p->Post<void>(LocalHandle()));
154 EXPECT_EQ(0, c->Acquire(&fence));
155 }
156
TEST_F(LibBufferHubTest,TestFailureToPostMetaFromABufferWithoutMeta)157 TEST_F(LibBufferHubTest, TestFailureToPostMetaFromABufferWithoutMeta) {
158 std::unique_ptr<BufferProducer> p =
159 BufferProducer::Create(kWidth, kHeight, kFormat, kUsage);
160 ASSERT_TRUE(p.get() != nullptr);
161 std::unique_ptr<BufferConsumer> c =
162 BufferConsumer::Import(p->CreateConsumer());
163 ASSERT_TRUE(c.get() != nullptr);
164
165 int64_t sequence = 3;
166 EXPECT_NE(0, p->Post(LocalHandle(), sequence));
167 }
168
TEST_F(LibBufferHubTest,TestPersistentBufferPersistence)169 TEST_F(LibBufferHubTest, TestPersistentBufferPersistence) {
170 auto p = BufferProducer::Create("TestPersistentBuffer", -1, -1, kWidth,
171 kHeight, kFormat, kUsage);
172 ASSERT_NE(nullptr, p);
173
174 // Record the original buffer id for later comparison.
175 const int buffer_id = p->id();
176
177 auto c = BufferConsumer::Import(p->CreateConsumer());
178 ASSERT_NE(nullptr, c);
179
180 EXPECT_EQ(0, p->Post<void>(LocalHandle()));
181
182 // Close the connection to the producer. This should not affect the consumer.
183 p = nullptr;
184
185 LocalHandle fence;
186 EXPECT_EQ(0, c->Acquire(&fence));
187 EXPECT_EQ(0, c->Release(LocalHandle()));
188
189 // Attempt to reconnect to the persistent buffer.
190 p = BufferProducer::Create("TestPersistentBuffer");
191 ASSERT_NE(nullptr, p);
192 EXPECT_EQ(buffer_id, p->id());
193 EXPECT_EQ(0, p->Gain(&fence));
194 }
195
TEST_F(LibBufferHubTest,TestPersistentBufferMismatchParams)196 TEST_F(LibBufferHubTest, TestPersistentBufferMismatchParams) {
197 auto p = BufferProducer::Create("TestPersistentBuffer", -1, -1, kWidth,
198 kHeight, kFormat, kUsage);
199 ASSERT_NE(nullptr, p);
200
201 // Close the connection to the producer.
202 p = nullptr;
203
204 // Mismatch the params.
205 p = BufferProducer::Create("TestPersistentBuffer", -1, -1, kWidth * 2,
206 kHeight, kFormat, kUsage);
207 ASSERT_EQ(nullptr, p);
208 }
209
TEST_F(LibBufferHubTest,TestRemovePersistentBuffer)210 TEST_F(LibBufferHubTest, TestRemovePersistentBuffer) {
211 auto p = BufferProducer::Create("TestPersistentBuffer", -1, -1, kWidth,
212 kHeight, kFormat, kUsage);
213 ASSERT_NE(nullptr, p);
214
215 LocalHandle fence;
216 auto c = BufferConsumer::Import(p->CreateConsumer());
217 ASSERT_NE(nullptr, c);
218 EXPECT_NE(-EPIPE, c->Acquire(&fence));
219
220 // Test that removing persistence and closing the producer orphans the
221 // consumer.
222 EXPECT_EQ(0, p->RemovePersistence());
223 p = nullptr;
224
225 EXPECT_EQ(-EPIPE, c->Release(LocalHandle()));
226 }
227