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