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