1 #include <base/logging.h>
2 #include <gui/BufferHubProducer.h>
3 #include <gui/IProducerListener.h>
4 #include <gui/Surface.h>
5 #include <pdx/default_transport/channel_parcelable.h>
6 
7 #include <gtest/gtest.h>
8 
9 namespace android {
10 namespace dvr {
11 
12 using pdx::LocalHandle;
13 
14 namespace {
15 
16 // Default dimensions before setDefaultBufferSize is called by the consumer.
17 constexpr uint32_t kDefaultWidth = 1;
18 constexpr uint32_t kDefaultHeight = 1;
19 
20 // Default format before setDefaultBufferFormat is called by the consumer.
21 constexpr PixelFormat kDefaultFormat = HAL_PIXEL_FORMAT_RGBA_8888;
22 constexpr int kDefaultConsumerUsageBits = 0;
23 
24 // Default transform hint before setTransformHint is called by the consumer.
25 constexpr uint32_t kDefaultTransformHint = 0;
26 
27 constexpr int kTestApi = NATIVE_WINDOW_API_CPU;
28 constexpr int kTestApiOther = NATIVE_WINDOW_API_EGL;
29 constexpr int kTestApiInvalid = 0xDEADBEEF;
30 constexpr int kTestProducerUsageBits = 0;
31 constexpr bool kTestControlledByApp = true;
32 
33 // Builder pattern to slightly vary *almost* correct input
34 // -- avoids copying and pasting
35 struct QueueBufferInputBuilder {
buildandroid::dvr::__anon3978ae580111::QueueBufferInputBuilder36   IGraphicBufferProducer::QueueBufferInput build() {
37     return IGraphicBufferProducer::QueueBufferInput(
38         mTimestamp, mIsAutoTimestamp, mDataSpace, mCrop, mScalingMode,
39         mTransform, mFence);
40   }
41 
setTimestampandroid::dvr::__anon3978ae580111::QueueBufferInputBuilder42   QueueBufferInputBuilder& setTimestamp(int64_t timestamp) {
43     this->mTimestamp = timestamp;
44     return *this;
45   }
46 
setIsAutoTimestampandroid::dvr::__anon3978ae580111::QueueBufferInputBuilder47   QueueBufferInputBuilder& setIsAutoTimestamp(bool isAutoTimestamp) {
48     this->mIsAutoTimestamp = isAutoTimestamp;
49     return *this;
50   }
51 
setDataSpaceandroid::dvr::__anon3978ae580111::QueueBufferInputBuilder52   QueueBufferInputBuilder& setDataSpace(android_dataspace dataSpace) {
53     this->mDataSpace = dataSpace;
54     return *this;
55   }
56 
setCropandroid::dvr::__anon3978ae580111::QueueBufferInputBuilder57   QueueBufferInputBuilder& setCrop(Rect crop) {
58     this->mCrop = crop;
59     return *this;
60   }
61 
setScalingModeandroid::dvr::__anon3978ae580111::QueueBufferInputBuilder62   QueueBufferInputBuilder& setScalingMode(int scalingMode) {
63     this->mScalingMode = scalingMode;
64     return *this;
65   }
66 
setTransformandroid::dvr::__anon3978ae580111::QueueBufferInputBuilder67   QueueBufferInputBuilder& setTransform(uint32_t transform) {
68     this->mTransform = transform;
69     return *this;
70   }
71 
setFenceandroid::dvr::__anon3978ae580111::QueueBufferInputBuilder72   QueueBufferInputBuilder& setFence(sp<Fence> fence) {
73     this->mFence = fence;
74     return *this;
75   }
76 
77  private:
78   int64_t mTimestamp{1384888611};
79   bool mIsAutoTimestamp{false};
80   android_dataspace mDataSpace{HAL_DATASPACE_UNKNOWN};
81   Rect mCrop{Rect(kDefaultWidth, kDefaultHeight)};
82   int mScalingMode{0};
83   uint32_t mTransform{0};
84   sp<Fence> mFence{Fence::NO_FENCE};
85 };
86 
87 // This is a test that covers our implementation of bufferhubqueue-based
88 // IGraphicBufferProducer.
89 class BufferHubQueueProducerTest : public ::testing::Test {
90  protected:
SetUp()91   virtual void SetUp() {
92     const ::testing::TestInfo* const testInfo =
93         ::testing::UnitTest::GetInstance()->current_test_info();
94     ALOGD_IF(TRACE, "Begin test: %s.%s", testInfo->test_case_name(),
95              testInfo->name());
96 
97     auto config = ProducerQueueConfigBuilder().Build();
98     auto queue = ProducerQueue::Create(config, UsagePolicy{});
99     ASSERT_TRUE(queue != nullptr);
100 
101     mProducer = BufferHubProducer::Create(std::move(queue));
102     ASSERT_TRUE(mProducer != nullptr);
103     mSurface = new Surface(mProducer, true);
104     ASSERT_TRUE(mSurface != nullptr);
105   }
106 
107   // Connect to a producer in a 'correct' fashion.
ConnectProducer()108   void ConnectProducer() {
109     IGraphicBufferProducer::QueueBufferOutput output;
110     // Can connect the first time.
111     ASSERT_EQ(OK, mProducer->connect(kDummyListener, kTestApi,
112                                      kTestControlledByApp, &output));
113   }
114 
115   // Dequeue a buffer in a 'correct' fashion.
116   //   Precondition: Producer is connected.
DequeueBuffer(int * outSlot)117   void DequeueBuffer(int* outSlot) {
118     sp<Fence> fence;
119     ASSERT_NO_FATAL_FAILURE(DequeueBuffer(outSlot, &fence));
120   }
121 
DequeueBuffer(int * outSlot,sp<Fence> * outFence)122   void DequeueBuffer(int* outSlot, sp<Fence>* outFence) {
123     ASSERT_NE(nullptr, outSlot);
124     ASSERT_NE(nullptr, outFence);
125 
126     int ret = mProducer->dequeueBuffer(
127         outSlot, outFence, kDefaultWidth, kDefaultHeight, kDefaultFormat,
128         kTestProducerUsageBits, nullptr, nullptr);
129     // BUFFER_NEEDS_REALLOCATION can be either on or off.
130     ASSERT_EQ(0, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION & ret);
131 
132     // Slot number should be in boundary.
133     ASSERT_LE(0, *outSlot);
134     ASSERT_GT(BufferQueueDefs::NUM_BUFFER_SLOTS, *outSlot);
135   }
136 
137   // Create a generic "valid" input for queueBuffer
138   // -- uses the default buffer format, width, etc.
CreateBufferInput()139   static IGraphicBufferProducer::QueueBufferInput CreateBufferInput() {
140     return QueueBufferInputBuilder().build();
141   }
142 
143   const sp<IProducerListener> kDummyListener{new DummyProducerListener};
144 
145   sp<BufferHubProducer> mProducer;
146   sp<Surface> mSurface;
147 };
148 
TEST_F(BufferHubQueueProducerTest,ConnectFirst_ReturnsError)149 TEST_F(BufferHubQueueProducerTest, ConnectFirst_ReturnsError) {
150   IGraphicBufferProducer::QueueBufferOutput output;
151 
152   // NULL output returns BAD_VALUE
153   EXPECT_EQ(BAD_VALUE, mProducer->connect(kDummyListener, kTestApi,
154                                           kTestControlledByApp, nullptr));
155 
156   // Invalid API returns bad value
157   EXPECT_EQ(BAD_VALUE, mProducer->connect(kDummyListener, kTestApiInvalid,
158                                           kTestControlledByApp, &output));
159 }
160 
TEST_F(BufferHubQueueProducerTest,ConnectAgain_ReturnsError)161 TEST_F(BufferHubQueueProducerTest, ConnectAgain_ReturnsError) {
162   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
163 
164   // Can't connect when there is already a producer connected.
165   IGraphicBufferProducer::QueueBufferOutput output;
166   EXPECT_EQ(BAD_VALUE, mProducer->connect(kDummyListener, kTestApi,
167                                           kTestControlledByApp, &output));
168 }
169 
TEST_F(BufferHubQueueProducerTest,Disconnect_Succeeds)170 TEST_F(BufferHubQueueProducerTest, Disconnect_Succeeds) {
171   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
172 
173   ASSERT_EQ(OK, mProducer->disconnect(kTestApi));
174 }
175 
TEST_F(BufferHubQueueProducerTest,Disconnect_ReturnsError)176 TEST_F(BufferHubQueueProducerTest, Disconnect_ReturnsError) {
177   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
178 
179   // Must disconnect with same API number
180   EXPECT_EQ(BAD_VALUE, mProducer->disconnect(kTestApiOther));
181   // API must not be out of range
182   EXPECT_EQ(BAD_VALUE, mProducer->disconnect(kTestApiInvalid));
183 }
184 
TEST_F(BufferHubQueueProducerTest,Query_Succeeds)185 TEST_F(BufferHubQueueProducerTest, Query_Succeeds) {
186   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
187 
188   int32_t value = -1;
189   EXPECT_EQ(OK, mProducer->query(NATIVE_WINDOW_WIDTH, &value));
190   EXPECT_EQ(kDefaultWidth, static_cast<uint32_t>(value));
191 
192   EXPECT_EQ(OK, mProducer->query(NATIVE_WINDOW_HEIGHT, &value));
193   EXPECT_EQ(kDefaultHeight, static_cast<uint32_t>(value));
194 
195   EXPECT_EQ(OK, mProducer->query(NATIVE_WINDOW_FORMAT, &value));
196   EXPECT_EQ(kDefaultFormat, value);
197 
198   EXPECT_EQ(OK, mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &value));
199   EXPECT_LE(0, value);
200   EXPECT_GE(BufferQueueDefs::NUM_BUFFER_SLOTS, value);
201 
202   EXPECT_EQ(OK,
203             mProducer->query(NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &value));
204   EXPECT_FALSE(value);  // Can't run behind when we haven't touched the queue
205 
206   EXPECT_EQ(OK, mProducer->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &value));
207   EXPECT_EQ(kDefaultConsumerUsageBits, value);
208 }
209 
TEST_F(BufferHubQueueProducerTest,Query_ReturnsError)210 TEST_F(BufferHubQueueProducerTest, Query_ReturnsError) {
211   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
212 
213   // One past the end of the last 'query' enum value. Update this if we add more
214   // enums.
215   const int NATIVE_WINDOW_QUERY_LAST_OFF_BY_ONE = NATIVE_WINDOW_BUFFER_AGE + 1;
216 
217   int value;
218   // What was out of range
219   EXPECT_EQ(BAD_VALUE, mProducer->query(/*what*/ -1, &value));
220   EXPECT_EQ(BAD_VALUE, mProducer->query(/*what*/ 0xDEADBEEF, &value));
221   EXPECT_EQ(BAD_VALUE,
222             mProducer->query(NATIVE_WINDOW_QUERY_LAST_OFF_BY_ONE, &value));
223 
224   // Some enums from window.h are 'invalid'
225   EXPECT_EQ(BAD_VALUE,
226             mProducer->query(NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER, &value));
227   EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_CONCRETE_TYPE, &value));
228   EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_DEFAULT_WIDTH, &value));
229   EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_DEFAULT_HEIGHT, &value));
230   EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_TRANSFORM_HINT, &value));
231 
232   // Value was NULL
233   EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_FORMAT, /*value*/ NULL));
234 }
235 
TEST_F(BufferHubQueueProducerTest,Queue_Succeeds)236 TEST_F(BufferHubQueueProducerTest, Queue_Succeeds) {
237   int slot = -1;
238 
239   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
240   ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
241 
242   // Request the buffer (pre-requisite for queueing)
243   sp<GraphicBuffer> buffer;
244   ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
245 
246   // A generic "valid" input
247   IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
248   IGraphicBufferProducer::QueueBufferOutput output;
249 
250   // Queue the buffer back into the BQ
251   ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
252 
253   EXPECT_EQ(kDefaultWidth, output.width);
254   EXPECT_EQ(kDefaultHeight, output.height);
255   EXPECT_EQ(kDefaultTransformHint, output.transformHint);
256 
257   // BufferHubQueue delivers buffers to consumer immediately.
258   EXPECT_EQ(0u, output.numPendingBuffers);
259 
260   // Note that BufferHubQueue doesn't support nextFrameNumber as it seems to
261   // be a SurfaceFlinger specific optimization.
262   EXPECT_EQ(0u, output.nextFrameNumber);
263 
264   // Buffer was not in the dequeued state
265   EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output));
266 }
267 
268 // Test invalid slot number
TEST_F(BufferHubQueueProducerTest,QueueInvalidSlot_ReturnsError)269 TEST_F(BufferHubQueueProducerTest, QueueInvalidSlot_ReturnsError) {
270   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
271 
272   // A generic "valid" input
273   IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
274   IGraphicBufferProducer::QueueBufferOutput output;
275 
276   EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(/*slot*/ -1, input, &output));
277   EXPECT_EQ(BAD_VALUE,
278             mProducer->queueBuffer(/*slot*/ 0xDEADBEEF, input, &output));
279   EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(BufferQueueDefs::NUM_BUFFER_SLOTS,
280                                               input, &output));
281 }
282 
283 // Slot was not in the dequeued state (all slots start out in Free state)
TEST_F(BufferHubQueueProducerTest,QueueNotDequeued_ReturnsError)284 TEST_F(BufferHubQueueProducerTest, QueueNotDequeued_ReturnsError) {
285   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
286 
287   IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
288   IGraphicBufferProducer::QueueBufferOutput output;
289 
290   EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(/*slot*/ 0, input, &output));
291 }
292 
293 // Slot was enqueued without requesting a buffer
TEST_F(BufferHubQueueProducerTest,QueueNotRequested_ReturnsError)294 TEST_F(BufferHubQueueProducerTest, QueueNotRequested_ReturnsError) {
295   int slot = -1;
296 
297   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
298   ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
299 
300   IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
301   IGraphicBufferProducer::QueueBufferOutput output;
302 
303   EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output));
304 }
305 
306 // Test when fence was NULL
TEST_F(BufferHubQueueProducerTest,QueueNoFence_ReturnsError)307 TEST_F(BufferHubQueueProducerTest, QueueNoFence_ReturnsError) {
308   int slot = -1;
309 
310   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
311   ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
312 
313   sp<GraphicBuffer> buffer;
314   ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
315 
316   sp<Fence> nullFence = NULL;
317 
318   IGraphicBufferProducer::QueueBufferInput input =
319       QueueBufferInputBuilder().setFence(nullFence).build();
320   IGraphicBufferProducer::QueueBufferOutput output;
321 
322   EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output));
323 }
324 
325 // Test scaling mode was invalid
TEST_F(BufferHubQueueProducerTest,QueueTestInvalidScalingMode_ReturnsError)326 TEST_F(BufferHubQueueProducerTest, QueueTestInvalidScalingMode_ReturnsError) {
327   int slot = -1;
328 
329   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
330   ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
331 
332   sp<GraphicBuffer> buffer;
333   ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
334 
335   IGraphicBufferProducer::QueueBufferInput input =
336       QueueBufferInputBuilder().setScalingMode(-1).build();
337   IGraphicBufferProducer::QueueBufferOutput output;
338 
339   EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output));
340 
341   input = QueueBufferInputBuilder().setScalingMode(0xDEADBEEF).build();
342 
343   EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output));
344 }
345 
346 // Test crop rect is out of bounds of the buffer dimensions
TEST_F(BufferHubQueueProducerTest,QueueCropOutOfBounds_ReturnsError)347 TEST_F(BufferHubQueueProducerTest, QueueCropOutOfBounds_ReturnsError) {
348   int slot = -1;
349 
350   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
351   ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
352 
353   sp<GraphicBuffer> buffer;
354   ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
355 
356   IGraphicBufferProducer::QueueBufferInput input =
357       QueueBufferInputBuilder()
358           .setCrop(Rect(kDefaultWidth + 1, kDefaultHeight + 1))
359           .build();
360   IGraphicBufferProducer::QueueBufferOutput output;
361 
362   EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output));
363 }
364 
TEST_F(BufferHubQueueProducerTest,CancelBuffer_Succeeds)365 TEST_F(BufferHubQueueProducerTest, CancelBuffer_Succeeds) {
366   int slot = -1;
367   sp<Fence> fence;
368 
369   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
370   ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot, &fence));
371 
372   // Should be able to cancel buffer after a dequeue.
373   EXPECT_EQ(OK, mProducer->cancelBuffer(slot, fence));
374 }
375 
TEST_F(BufferHubQueueProducerTest,SetMaxDequeuedBufferCount_Succeeds)376 TEST_F(BufferHubQueueProducerTest, SetMaxDequeuedBufferCount_Succeeds) {
377   return;
378   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
379 
380   int minUndequeuedBuffers;
381   ASSERT_EQ(OK, mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
382                                  &minUndequeuedBuffers));
383 
384   const int minBuffers = 1;
385   const int maxBuffers =
386       BufferQueueDefs::NUM_BUFFER_SLOTS - minUndequeuedBuffers;
387 
388   ASSERT_EQ(OK, mProducer->setAsyncMode(false)) << "async mode: " << false;
389   ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(minBuffers))
390       << "bufferCount: " << minBuffers;
391 
392   // Should now be able to dequeue up to minBuffers times
393   // Should now be able to dequeue up to maxBuffers times
394   int slot = -1;
395   for (int i = 0; i < minBuffers; ++i) {
396     ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
397   }
398 
399   ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(maxBuffers));
400 
401   // queue the first buffer to enable max dequeued buffer count checking
402   IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
403   IGraphicBufferProducer::QueueBufferOutput output;
404   sp<GraphicBuffer> buffer;
405   ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
406   ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
407 
408   sp<Fence> fence;
409   for (int i = 0; i < maxBuffers; ++i) {
410     ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot, &fence));
411   }
412 
413   // Cancel a buffer, so we can decrease the buffer count
414   ASSERT_EQ(OK, mProducer->cancelBuffer(slot, fence));
415 
416   // Should now be able to decrease the max dequeued count by 1
417   ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(maxBuffers - 1));
418 }
419 
TEST_F(BufferHubQueueProducerTest,SetMaxDequeuedBufferCount_Fails)420 TEST_F(BufferHubQueueProducerTest, SetMaxDequeuedBufferCount_Fails) {
421   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
422 
423   int minUndequeuedBuffers;
424   ASSERT_EQ(OK, mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
425                                  &minUndequeuedBuffers));
426 
427   const int minBuffers = 1;
428   const int maxBuffers =
429       BufferQueueDefs::NUM_BUFFER_SLOTS - minUndequeuedBuffers;
430 
431   ASSERT_EQ(OK, mProducer->setAsyncMode(false)) << "async mode: " << false;
432   // Buffer count was out of range
433   EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(0))
434       << "bufferCount: " << 0;
435   EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(maxBuffers + 1))
436       << "bufferCount: " << maxBuffers + 1;
437 
438   // Set max dequeue count to 2
439   ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(2));
440   // Dequeue 2 buffers
441   int slot = -1;
442   sp<Fence> fence;
443   for (int i = 0; i < 2; i++) {
444     ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
445                       (mProducer->dequeueBuffer(&slot, &fence, kDefaultWidth,
446                                                 kDefaultHeight, kDefaultFormat,
447                                                 kTestProducerUsageBits,
448                                                 nullptr, nullptr)))
449         << "slot: " << slot;
450   }
451 
452   // Client has too many buffers dequeued
453   EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(1))
454       << "bufferCount: " << minBuffers;
455 }
456 
TEST_F(BufferHubQueueProducerTest,DisconnectedProducerReturnsError_dequeueBuffer)457 TEST_F(BufferHubQueueProducerTest,
458        DisconnectedProducerReturnsError_dequeueBuffer) {
459   int slot = -1;
460   sp<Fence> fence;
461 
462   ASSERT_EQ(NO_INIT, mProducer->dequeueBuffer(&slot, &fence, kDefaultWidth,
463                                               kDefaultHeight, kDefaultFormat,
464                                               kTestProducerUsageBits,
465                                               nullptr, nullptr));
466 }
467 
TEST_F(BufferHubQueueProducerTest,DisconnectedProducerReturnsError_requestBuffer)468 TEST_F(BufferHubQueueProducerTest,
469        DisconnectedProducerReturnsError_requestBuffer) {
470   int slot = -1;
471   sp<GraphicBuffer> buffer;
472 
473   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
474   ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
475 
476   // Shouldn't be able to request buffer after disconnect.
477   ASSERT_EQ(OK, mProducer->disconnect(kTestApi));
478   ASSERT_EQ(NO_INIT, mProducer->requestBuffer(slot, &buffer));
479 }
480 
TEST_F(BufferHubQueueProducerTest,DisconnectedProducerReturnsError_queueBuffer)481 TEST_F(BufferHubQueueProducerTest,
482        DisconnectedProducerReturnsError_queueBuffer) {
483   int slot = -1;
484   sp<GraphicBuffer> buffer;
485 
486   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
487   ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
488   ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
489 
490   // A generic "valid" input
491   IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
492   IGraphicBufferProducer::QueueBufferOutput output;
493 
494   // Shouldn't be able to queue buffer after disconnect.
495   ASSERT_EQ(OK, mProducer->disconnect(kTestApi));
496   ASSERT_EQ(NO_INIT, mProducer->queueBuffer(slot, input, &output));
497 }
498 
TEST_F(BufferHubQueueProducerTest,DisconnectedProducerReturnsError_cancelBuffer)499 TEST_F(BufferHubQueueProducerTest,
500        DisconnectedProducerReturnsError_cancelBuffer) {
501   int slot = -1;
502   sp<GraphicBuffer> buffer;
503 
504   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
505   ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
506   ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
507 
508   // Shouldn't be able to cancel buffer after disconnect.
509   ASSERT_EQ(OK, mProducer->disconnect(kTestApi));
510   ASSERT_EQ(NO_INIT, mProducer->cancelBuffer(slot, Fence::NO_FENCE));
511 }
512 
TEST_F(BufferHubQueueProducerTest,ConnectDisconnectReconnect)513 TEST_F(BufferHubQueueProducerTest, ConnectDisconnectReconnect) {
514   int slot = -1;
515   sp<GraphicBuffer> buffer;
516   IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
517   IGraphicBufferProducer::QueueBufferOutput output;
518 
519   EXPECT_NO_FATAL_FAILURE(ConnectProducer());
520 
521   constexpr int maxDequeuedBuffers = 1;
522   int minUndequeuedBuffers;
523   EXPECT_EQ(OK, mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
524                                  &minUndequeuedBuffers));
525   EXPECT_EQ(OK, mProducer->setAsyncMode(false));
526   EXPECT_EQ(OK, mProducer->setMaxDequeuedBufferCount(maxDequeuedBuffers));
527 
528   int maxCapacity = maxDequeuedBuffers + minUndequeuedBuffers;
529 
530   // Dequeue, request, and queue all buffers.
531   for (int i = 0; i < maxCapacity; i++) {
532     EXPECT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
533     EXPECT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
534     EXPECT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
535   }
536 
537   // Disconnect then reconnect.
538   EXPECT_EQ(OK, mProducer->disconnect(kTestApi));
539   EXPECT_NO_FATAL_FAILURE(ConnectProducer());
540 
541   // Dequeue, request, and queue all buffers.
542   for (int i = 0; i < maxCapacity; i++) {
543     EXPECT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
544     EXPECT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
545     EXPECT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
546   }
547 
548   EXPECT_EQ(OK, mProducer->disconnect(kTestApi));
549 }
550 
TEST_F(BufferHubQueueProducerTest,TakeAsParcelable)551 TEST_F(BufferHubQueueProducerTest, TakeAsParcelable) {
552   // Connected producer cannot be taken out as a parcelable.
553   EXPECT_NO_FATAL_FAILURE(ConnectProducer());
554   ProducerQueueParcelable producer_parcelable;
555   EXPECT_EQ(mProducer->TakeAsParcelable(&producer_parcelable), BAD_VALUE);
556 
557   // Create a valid dummy producer parcelable.
558   auto dummy_channel_parcelable =
559       std::make_unique<pdx::default_transport::ChannelParcelable>(
560           LocalHandle(0), LocalHandle(0), LocalHandle(0));
561   EXPECT_TRUE(dummy_channel_parcelable->IsValid());
562   ProducerQueueParcelable dummy_producer_parcelable(
563       std::move(dummy_channel_parcelable));
564   EXPECT_TRUE(dummy_producer_parcelable.IsValid());
565 
566   // Disconnect producer can be taken out, but only to an invalid parcelable.
567   ASSERT_EQ(mProducer->disconnect(kTestApi), OK);
568   EXPECT_EQ(mProducer->TakeAsParcelable(&dummy_producer_parcelable), BAD_VALUE);
569   EXPECT_FALSE(producer_parcelable.IsValid());
570   EXPECT_EQ(mProducer->TakeAsParcelable(&producer_parcelable), OK);
571   EXPECT_TRUE(producer_parcelable.IsValid());
572 
573   // Should still be able to query buffer dimension after disconnect.
574   int32_t value = -1;
575   EXPECT_EQ(OK, mProducer->query(NATIVE_WINDOW_WIDTH, &value));
576   EXPECT_EQ(static_cast<uint32_t>(value), kDefaultWidth);
577 
578   EXPECT_EQ(mProducer->query(NATIVE_WINDOW_HEIGHT, &value), OK);
579   EXPECT_EQ(static_cast<uint32_t>(value), kDefaultHeight);
580 
581   EXPECT_EQ(mProducer->query(NATIVE_WINDOW_FORMAT, &value), OK);
582   EXPECT_EQ(value, kDefaultFormat);
583 
584   // But connect to API will fail.
585   IGraphicBufferProducer::QueueBufferOutput output;
586   EXPECT_EQ(mProducer->connect(kDummyListener, kTestApi, kTestControlledByApp,
587                                &output),
588             BAD_VALUE);
589 
590   // Create a new producer from the parcelable and connect to kTestApi should
591   // succeed.
592   sp<BufferHubProducer> new_producer =
593       BufferHubProducer::Create(std::move(producer_parcelable));
594   ASSERT_TRUE(new_producer != nullptr);
595   EXPECT_EQ(new_producer->connect(kDummyListener, kTestApi,
596                                   kTestControlledByApp, &output),
597             OK);
598 }
599 
600 }  // namespace
601 
602 }  // namespace dvr
603 }  // namespace android
604