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
16using 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.
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
65TEST_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
91TEST_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
108TEST_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
128TEST_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
143TEST_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
157TEST_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
169TEST_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
196TEST_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
210TEST_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