• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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::__anonf596ea950111::QueueBufferInputBuilder36   IGraphicBufferProducer::QueueBufferInput build() {
37     return IGraphicBufferProducer::QueueBufferInput(
38         mTimestamp, mIsAutoTimestamp, mDataSpace, mCrop, mScalingMode,
39         mTransform, mFence);
40   }
41 
setTimestampandroid::dvr::__anonf596ea950111::QueueBufferInputBuilder42   QueueBufferInputBuilder& setTimestamp(int64_t timestamp) {
43     this->mTimestamp = timestamp;
44     return *this;
45   }
46 
setIsAutoTimestampandroid::dvr::__anonf596ea950111::QueueBufferInputBuilder47   QueueBufferInputBuilder& setIsAutoTimestamp(bool isAutoTimestamp) {
48     this->mIsAutoTimestamp = isAutoTimestamp;
49     return *this;
50   }
51 
setDataSpaceandroid::dvr::__anonf596ea950111::QueueBufferInputBuilder52   QueueBufferInputBuilder& setDataSpace(android_dataspace dataSpace) {
53     this->mDataSpace = dataSpace;
54     return *this;
55   }
56 
setCropandroid::dvr::__anonf596ea950111::QueueBufferInputBuilder57   QueueBufferInputBuilder& setCrop(Rect crop) {
58     this->mCrop = crop;
59     return *this;
60   }
61 
setScalingModeandroid::dvr::__anonf596ea950111::QueueBufferInputBuilder62   QueueBufferInputBuilder& setScalingMode(int scalingMode) {
63     this->mScalingMode = scalingMode;
64     return *this;
65   }
66 
setTransformandroid::dvr::__anonf596ea950111::QueueBufferInputBuilder67   QueueBufferInputBuilder& setTransform(uint32_t transform) {
68     this->mTransform = transform;
69     return *this;
70   }
71 
setFenceandroid::dvr::__anonf596ea950111::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(NO_ERROR, 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(NO_ERROR, 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(NO_ERROR, mProducer->query(NATIVE_WINDOW_WIDTH, &value));
190   EXPECT_EQ(kDefaultWidth, static_cast<uint32_t>(value));
191 
192   EXPECT_EQ(NO_ERROR, mProducer->query(NATIVE_WINDOW_HEIGHT, &value));
193   EXPECT_EQ(kDefaultHeight, static_cast<uint32_t>(value));
194 
195   EXPECT_EQ(NO_ERROR, mProducer->query(NATIVE_WINDOW_FORMAT, &value));
196   EXPECT_EQ(kDefaultFormat, value);
197 
198   EXPECT_EQ(NO_ERROR,
199             mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &value));
200   EXPECT_LE(0, value);
201   EXPECT_GE(BufferQueueDefs::NUM_BUFFER_SLOTS, value);
202 
203   EXPECT_EQ(NO_ERROR,
204             mProducer->query(NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &value));
205   EXPECT_FALSE(value);  // Can't run behind when we haven't touched the queue
206 
207   EXPECT_EQ(NO_ERROR,
208             mProducer->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &value));
209   EXPECT_EQ(kDefaultConsumerUsageBits, value);
210 }
211 
TEST_F(BufferHubQueueProducerTest,Query_ReturnsError)212 TEST_F(BufferHubQueueProducerTest, Query_ReturnsError) {
213   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
214 
215   // One past the end of the last 'query' enum value. Update this if we add more
216   // enums.
217   const int NATIVE_WINDOW_QUERY_LAST_OFF_BY_ONE = NATIVE_WINDOW_BUFFER_AGE + 1;
218 
219   int value;
220   // What was out of range
221   EXPECT_EQ(BAD_VALUE, mProducer->query(/*what*/ -1, &value));
222   EXPECT_EQ(BAD_VALUE, mProducer->query(/*what*/ 0xDEADBEEF, &value));
223   EXPECT_EQ(BAD_VALUE,
224             mProducer->query(NATIVE_WINDOW_QUERY_LAST_OFF_BY_ONE, &value));
225 
226   // Some enums from window.h are 'invalid'
227   EXPECT_EQ(BAD_VALUE,
228             mProducer->query(NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER, &value));
229   EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_CONCRETE_TYPE, &value));
230   EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_DEFAULT_WIDTH, &value));
231   EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_DEFAULT_HEIGHT, &value));
232   EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_TRANSFORM_HINT, &value));
233 
234   // Value was NULL
235   EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_FORMAT, /*value*/ NULL));
236 }
237 
TEST_F(BufferHubQueueProducerTest,Queue_Succeeds)238 TEST_F(BufferHubQueueProducerTest, Queue_Succeeds) {
239   int slot = -1;
240 
241   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
242   ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
243 
244   // Request the buffer (pre-requisite for queueing)
245   sp<GraphicBuffer> buffer;
246   ASSERT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer));
247 
248   // A generic "valid" input
249   IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
250   IGraphicBufferProducer::QueueBufferOutput output;
251 
252   // Queue the buffer back into the BQ
253   ASSERT_EQ(NO_ERROR, mProducer->queueBuffer(slot, input, &output));
254 
255   EXPECT_EQ(kDefaultWidth, output.width);
256   EXPECT_EQ(kDefaultHeight, output.height);
257   EXPECT_EQ(kDefaultTransformHint, output.transformHint);
258 
259   // BufferHubQueue delivers buffers to consumer immediately.
260   EXPECT_EQ(0u, output.numPendingBuffers);
261 
262   // Note that BufferHubQueue doesn't support nextFrameNumber as it seems to
263   // be a SurfaceFlinger specific optimization.
264   EXPECT_EQ(0u, output.nextFrameNumber);
265 
266   // Buffer was not in the dequeued state
267   EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output));
268 }
269 
270 // Test invalid slot number
TEST_F(BufferHubQueueProducerTest,QueueInvalidSlot_ReturnsError)271 TEST_F(BufferHubQueueProducerTest, QueueInvalidSlot_ReturnsError) {
272   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
273 
274   // A generic "valid" input
275   IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
276   IGraphicBufferProducer::QueueBufferOutput output;
277 
278   EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(/*slot*/ -1, input, &output));
279   EXPECT_EQ(BAD_VALUE,
280             mProducer->queueBuffer(/*slot*/ 0xDEADBEEF, input, &output));
281   EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(BufferQueueDefs::NUM_BUFFER_SLOTS,
282                                               input, &output));
283 }
284 
285 // Slot was not in the dequeued state (all slots start out in Free state)
TEST_F(BufferHubQueueProducerTest,QueueNotDequeued_ReturnsError)286 TEST_F(BufferHubQueueProducerTest, QueueNotDequeued_ReturnsError) {
287   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
288 
289   IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
290   IGraphicBufferProducer::QueueBufferOutput output;
291 
292   EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(/*slot*/ 0, input, &output));
293 }
294 
295 // Slot was enqueued without requesting a buffer
TEST_F(BufferHubQueueProducerTest,QueueNotRequested_ReturnsError)296 TEST_F(BufferHubQueueProducerTest, QueueNotRequested_ReturnsError) {
297   int slot = -1;
298 
299   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
300   ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
301 
302   IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
303   IGraphicBufferProducer::QueueBufferOutput output;
304 
305   EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output));
306 }
307 
308 // Test when fence was NULL
TEST_F(BufferHubQueueProducerTest,QueueNoFence_ReturnsError)309 TEST_F(BufferHubQueueProducerTest, QueueNoFence_ReturnsError) {
310   int slot = -1;
311 
312   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
313   ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
314 
315   sp<GraphicBuffer> buffer;
316   ASSERT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer));
317 
318   sp<Fence> nullFence = NULL;
319 
320   IGraphicBufferProducer::QueueBufferInput input =
321       QueueBufferInputBuilder().setFence(nullFence).build();
322   IGraphicBufferProducer::QueueBufferOutput output;
323 
324   EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output));
325 }
326 
327 // Test scaling mode was invalid
TEST_F(BufferHubQueueProducerTest,QueueTestInvalidScalingMode_ReturnsError)328 TEST_F(BufferHubQueueProducerTest, QueueTestInvalidScalingMode_ReturnsError) {
329   int slot = -1;
330 
331   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
332   ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
333 
334   sp<GraphicBuffer> buffer;
335   ASSERT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer));
336 
337   IGraphicBufferProducer::QueueBufferInput input =
338       QueueBufferInputBuilder().setScalingMode(-1).build();
339   IGraphicBufferProducer::QueueBufferOutput output;
340 
341   EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output));
342 
343   input = QueueBufferInputBuilder().setScalingMode(0xDEADBEEF).build();
344 
345   EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output));
346 }
347 
348 // Test crop rect is out of bounds of the buffer dimensions
TEST_F(BufferHubQueueProducerTest,QueueCropOutOfBounds_ReturnsError)349 TEST_F(BufferHubQueueProducerTest, QueueCropOutOfBounds_ReturnsError) {
350   int slot = -1;
351 
352   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
353   ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
354 
355   sp<GraphicBuffer> buffer;
356   ASSERT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer));
357 
358   IGraphicBufferProducer::QueueBufferInput input =
359       QueueBufferInputBuilder()
360           .setCrop(Rect(kDefaultWidth + 1, kDefaultHeight + 1))
361           .build();
362   IGraphicBufferProducer::QueueBufferOutput output;
363 
364   EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output));
365 }
366 
TEST_F(BufferHubQueueProducerTest,CancelBuffer_Succeeds)367 TEST_F(BufferHubQueueProducerTest, CancelBuffer_Succeeds) {
368   int slot = -1;
369   sp<Fence> fence;
370 
371   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
372   ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot, &fence));
373 
374   // Should be able to cancel buffer after a dequeue.
375   EXPECT_EQ(NO_ERROR, mProducer->cancelBuffer(slot, fence));
376 }
377 
TEST_F(BufferHubQueueProducerTest,SetMaxDequeuedBufferCount_Succeeds)378 TEST_F(BufferHubQueueProducerTest, SetMaxDequeuedBufferCount_Succeeds) {
379   return;
380   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
381 
382   int minUndequeuedBuffers;
383   ASSERT_EQ(NO_ERROR, mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
384                                        &minUndequeuedBuffers));
385 
386   const int minBuffers = 1;
387   const int maxBuffers =
388       BufferQueueDefs::NUM_BUFFER_SLOTS - minUndequeuedBuffers;
389 
390   ASSERT_EQ(NO_ERROR, mProducer->setAsyncMode(false))
391       << "async mode: " << false;
392   ASSERT_EQ(NO_ERROR, mProducer->setMaxDequeuedBufferCount(minBuffers))
393       << "bufferCount: " << minBuffers;
394 
395   // Should now be able to dequeue up to minBuffers times
396   // Should now be able to dequeue up to maxBuffers times
397   int slot = -1;
398   for (int i = 0; i < minBuffers; ++i) {
399     ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
400   }
401 
402   ASSERT_EQ(NO_ERROR, mProducer->setMaxDequeuedBufferCount(maxBuffers));
403 
404   // queue the first buffer to enable max dequeued buffer count checking
405   IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
406   IGraphicBufferProducer::QueueBufferOutput output;
407   sp<GraphicBuffer> buffer;
408   ASSERT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer));
409   ASSERT_EQ(NO_ERROR, mProducer->queueBuffer(slot, input, &output));
410 
411   sp<Fence> fence;
412   for (int i = 0; i < maxBuffers; ++i) {
413     ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot, &fence));
414   }
415 
416   // Cancel a buffer, so we can decrease the buffer count
417   ASSERT_EQ(NO_ERROR, mProducer->cancelBuffer(slot, fence));
418 
419   // Should now be able to decrease the max dequeued count by 1
420   ASSERT_EQ(NO_ERROR, mProducer->setMaxDequeuedBufferCount(maxBuffers - 1));
421 }
422 
TEST_F(BufferHubQueueProducerTest,SetMaxDequeuedBufferCount_Fails)423 TEST_F(BufferHubQueueProducerTest, SetMaxDequeuedBufferCount_Fails) {
424   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
425 
426   int minUndequeuedBuffers;
427   ASSERT_EQ(NO_ERROR, mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
428                                        &minUndequeuedBuffers));
429 
430   const int minBuffers = 1;
431   const int maxBuffers =
432       BufferQueueDefs::NUM_BUFFER_SLOTS - minUndequeuedBuffers;
433 
434   ASSERT_EQ(NO_ERROR, mProducer->setAsyncMode(false))
435       << "async mode: " << false;
436   // Buffer count was out of range
437   EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(0))
438       << "bufferCount: " << 0;
439   EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(maxBuffers + 1))
440       << "bufferCount: " << maxBuffers + 1;
441 
442   // Set max dequeue count to 2
443   ASSERT_EQ(NO_ERROR, mProducer->setMaxDequeuedBufferCount(2));
444   // Dequeue 2 buffers
445   int slot = -1;
446   sp<Fence> fence;
447   for (int i = 0; i < 2; i++) {
448     ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
449                       (mProducer->dequeueBuffer(&slot, &fence, kDefaultWidth,
450                                                 kDefaultHeight, kDefaultFormat,
451                                                 kTestProducerUsageBits,
452                                                 nullptr, nullptr)))
453         << "slot: " << slot;
454   }
455 
456   // Client has too many buffers dequeued
457   EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(1))
458       << "bufferCount: " << minBuffers;
459 }
460 
TEST_F(BufferHubQueueProducerTest,DisconnectedProducerReturnsError_dequeueBuffer)461 TEST_F(BufferHubQueueProducerTest,
462        DisconnectedProducerReturnsError_dequeueBuffer) {
463   int slot = -1;
464   sp<Fence> fence;
465 
466   ASSERT_EQ(NO_INIT, mProducer->dequeueBuffer(&slot, &fence, kDefaultWidth,
467                                               kDefaultHeight, kDefaultFormat,
468                                               kTestProducerUsageBits,
469                                               nullptr, nullptr));
470 }
471 
TEST_F(BufferHubQueueProducerTest,DisconnectedProducerReturnsError_requestBuffer)472 TEST_F(BufferHubQueueProducerTest,
473        DisconnectedProducerReturnsError_requestBuffer) {
474   int slot = -1;
475   sp<GraphicBuffer> buffer;
476 
477   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
478   ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
479 
480   // Shouldn't be able to request buffer after disconnect.
481   ASSERT_EQ(NO_ERROR, mProducer->disconnect(kTestApi));
482   ASSERT_EQ(NO_INIT, mProducer->requestBuffer(slot, &buffer));
483 }
484 
TEST_F(BufferHubQueueProducerTest,DisconnectedProducerReturnsError_queueBuffer)485 TEST_F(BufferHubQueueProducerTest,
486        DisconnectedProducerReturnsError_queueBuffer) {
487   int slot = -1;
488   sp<GraphicBuffer> buffer;
489 
490   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
491   ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
492   ASSERT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer));
493 
494   // A generic "valid" input
495   IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
496   IGraphicBufferProducer::QueueBufferOutput output;
497 
498   // Shouldn't be able to queue buffer after disconnect.
499   ASSERT_EQ(NO_ERROR, mProducer->disconnect(kTestApi));
500   ASSERT_EQ(NO_INIT, mProducer->queueBuffer(slot, input, &output));
501 }
502 
TEST_F(BufferHubQueueProducerTest,DisconnectedProducerReturnsError_cancelBuffer)503 TEST_F(BufferHubQueueProducerTest,
504        DisconnectedProducerReturnsError_cancelBuffer) {
505   int slot = -1;
506   sp<GraphicBuffer> buffer;
507 
508   ASSERT_NO_FATAL_FAILURE(ConnectProducer());
509   ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
510   ASSERT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer));
511 
512   // Shouldn't be able to cancel buffer after disconnect.
513   ASSERT_EQ(NO_ERROR, mProducer->disconnect(kTestApi));
514   ASSERT_EQ(NO_INIT, mProducer->cancelBuffer(slot, Fence::NO_FENCE));
515 }
516 
TEST_F(BufferHubQueueProducerTest,ConnectDisconnectReconnect)517 TEST_F(BufferHubQueueProducerTest, ConnectDisconnectReconnect) {
518   int slot = -1;
519   sp<GraphicBuffer> buffer;
520   IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
521   IGraphicBufferProducer::QueueBufferOutput output;
522 
523   EXPECT_NO_FATAL_FAILURE(ConnectProducer());
524 
525   constexpr int maxDequeuedBuffers = 1;
526   int minUndequeuedBuffers;
527   EXPECT_EQ(NO_ERROR, mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
528                                        &minUndequeuedBuffers));
529   EXPECT_EQ(NO_ERROR, mProducer->setAsyncMode(false));
530   EXPECT_EQ(NO_ERROR, mProducer->setMaxDequeuedBufferCount(maxDequeuedBuffers));
531 
532   int maxCapacity = maxDequeuedBuffers + minUndequeuedBuffers;
533 
534   // Dequeue, request, and queue all buffers.
535   for (int i = 0; i < maxCapacity; i++) {
536     EXPECT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
537     EXPECT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer));
538     EXPECT_EQ(NO_ERROR, mProducer->queueBuffer(slot, input, &output));
539   }
540 
541   // Disconnect then reconnect.
542   EXPECT_EQ(NO_ERROR, mProducer->disconnect(kTestApi));
543   EXPECT_NO_FATAL_FAILURE(ConnectProducer());
544 
545   // Dequeue, request, and queue all buffers.
546   for (int i = 0; i < maxCapacity; i++) {
547     EXPECT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
548     EXPECT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer));
549     EXPECT_EQ(NO_ERROR, mProducer->queueBuffer(slot, input, &output));
550   }
551 
552   EXPECT_EQ(NO_ERROR, mProducer->disconnect(kTestApi));
553 }
554 
TEST_F(BufferHubQueueProducerTest,TakeAsParcelable)555 TEST_F(BufferHubQueueProducerTest, TakeAsParcelable) {
556   // Connected producer cannot be taken out as a parcelable.
557   EXPECT_NO_FATAL_FAILURE(ConnectProducer());
558   ProducerQueueParcelable producer_parcelable;
559   EXPECT_EQ(mProducer->TakeAsParcelable(&producer_parcelable), BAD_VALUE);
560 
561   // Create a valid dummy producer parcelable.
562   auto dummy_channel_parcelable =
563       std::make_unique<pdx::default_transport::ChannelParcelable>(
564           LocalHandle(0), LocalHandle(0), LocalHandle(0));
565   EXPECT_TRUE(dummy_channel_parcelable->IsValid());
566   ProducerQueueParcelable dummy_producer_parcelable(
567       std::move(dummy_channel_parcelable));
568   EXPECT_TRUE(dummy_producer_parcelable.IsValid());
569 
570   // Disconnect producer can be taken out, but only to an invalid parcelable.
571   ASSERT_EQ(mProducer->disconnect(kTestApi), NO_ERROR);
572   EXPECT_EQ(mProducer->TakeAsParcelable(&dummy_producer_parcelable), BAD_VALUE);
573   EXPECT_FALSE(producer_parcelable.IsValid());
574   EXPECT_EQ(mProducer->TakeAsParcelable(&producer_parcelable), NO_ERROR);
575   EXPECT_TRUE(producer_parcelable.IsValid());
576 
577   // Should still be able to query buffer dimension after disconnect.
578   int32_t value = -1;
579   EXPECT_EQ(NO_ERROR, mProducer->query(NATIVE_WINDOW_WIDTH, &value));
580   EXPECT_EQ(static_cast<uint32_t>(value), kDefaultWidth);
581 
582   EXPECT_EQ(mProducer->query(NATIVE_WINDOW_HEIGHT, &value), NO_ERROR);
583   EXPECT_EQ(static_cast<uint32_t>(value), kDefaultHeight);
584 
585   EXPECT_EQ(mProducer->query(NATIVE_WINDOW_FORMAT, &value), NO_ERROR);
586   EXPECT_EQ(value, kDefaultFormat);
587 
588   // But connect to API will fail.
589   IGraphicBufferProducer::QueueBufferOutput output;
590   EXPECT_EQ(mProducer->connect(kDummyListener, kTestApi, kTestControlledByApp,
591                                &output),
592             BAD_VALUE);
593 
594   // Create a new producer from the parcelable and connect to kTestApi should
595   // succeed.
596   sp<BufferHubProducer> new_producer =
597       BufferHubProducer::Create(std::move(producer_parcelable));
598   ASSERT_TRUE(new_producer != nullptr);
599   EXPECT_EQ(new_producer->connect(kDummyListener, kTestApi,
600                                   kTestControlledByApp, &output),
601             NO_ERROR);
602 }
603 
604 }  // namespace
605 
606 }  // namespace dvr
607 }  // namespace android
608