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
9namespace android {
10namespace dvr {
11
12using pdx::LocalHandle;
13
14namespace {
15
16// Default dimensions before setDefaultBufferSize is called by the consumer.
17constexpr uint32_t kDefaultWidth = 1;
18constexpr uint32_t kDefaultHeight = 1;
19
20// Default format before setDefaultBufferFormat is called by the consumer.
21constexpr PixelFormat kDefaultFormat = HAL_PIXEL_FORMAT_RGBA_8888;
22constexpr int kDefaultConsumerUsageBits = 0;
23
24// Default transform hint before setTransformHint is called by the consumer.
25constexpr uint32_t kDefaultTransformHint = 0;
26
27constexpr int kTestApi = NATIVE_WINDOW_API_CPU;
28constexpr int kTestApiOther = NATIVE_WINDOW_API_EGL;
29constexpr int kTestApiInvalid = 0xDEADBEEF;
30constexpr int kTestProducerUsageBits = 0;
31constexpr bool kTestControlledByApp = true;
32
33// Builder pattern to slightly vary *almost* correct input
34// -- avoids copying and pasting
35struct QueueBufferInputBuilder {
36  IGraphicBufferProducer::QueueBufferInput build() {
37    return IGraphicBufferProducer::QueueBufferInput(
38        mTimestamp, mIsAutoTimestamp, mDataSpace, mCrop, mScalingMode,
39        mTransform, mFence);
40  }
41
42  QueueBufferInputBuilder& setTimestamp(int64_t timestamp) {
43    this->mTimestamp = timestamp;
44    return *this;
45  }
46
47  QueueBufferInputBuilder& setIsAutoTimestamp(bool isAutoTimestamp) {
48    this->mIsAutoTimestamp = isAutoTimestamp;
49    return *this;
50  }
51
52  QueueBufferInputBuilder& setDataSpace(android_dataspace dataSpace) {
53    this->mDataSpace = dataSpace;
54    return *this;
55  }
56
57  QueueBufferInputBuilder& setCrop(Rect crop) {
58    this->mCrop = crop;
59    return *this;
60  }
61
62  QueueBufferInputBuilder& setScalingMode(int scalingMode) {
63    this->mScalingMode = scalingMode;
64    return *this;
65  }
66
67  QueueBufferInputBuilder& setTransform(uint32_t transform) {
68    this->mTransform = transform;
69    return *this;
70  }
71
72  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.
89class BufferHubQueueProducerTest : public ::testing::Test {
90 protected:
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.
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.
117  void DequeueBuffer(int* outSlot) {
118    sp<Fence> fence;
119    ASSERT_NO_FATAL_FAILURE(DequeueBuffer(outSlot, &fence));
120  }
121
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.
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
149TEST_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
161TEST_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
170TEST_F(BufferHubQueueProducerTest, Disconnect_Succeeds) {
171  ASSERT_NO_FATAL_FAILURE(ConnectProducer());
172
173  ASSERT_EQ(NO_ERROR, mProducer->disconnect(kTestApi));
174}
175
176TEST_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
185TEST_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
212TEST_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
238TEST_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
271TEST_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)
286TEST_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
296TEST_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
309TEST_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
328TEST_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
349TEST_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
367TEST_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
378TEST_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
423TEST_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
461TEST_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
472TEST_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
485TEST_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
503TEST_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
517TEST_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
555TEST_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