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