blob: 3e9698940ce9cd6c70d68b630ba12711fda88ea2 [file] [log] [blame]
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08001#include <base/logging.h>
Jiwen 'Steve' Cai0f950842018-01-16 17:05:54 -08002#include <gui/BufferHubProducer.h>
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -07003#include <gui/IProducerListener.h>
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08004#include <gui/Surface.h>
Jiwen 'Steve' Cai5afb7402017-11-09 18:50:32 -08005#include <pdx/default_transport/channel_parcelable.h>
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -07006
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08007#include <gtest/gtest.h>
8
9namespace android {
10namespace dvr {
11
Jiwen 'Steve' Cai5afb7402017-11-09 18:50:32 -080012using pdx::LocalHandle;
13
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080014namespace {
15
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -070016// Default dimensions before setDefaultBufferSize is called by the consumer.
17constexpr uint32_t kDefaultWidth = 1;
18constexpr uint32_t kDefaultHeight = 1;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080019
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -070020// 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
Jiwen 'Steve' Cai5afb7402017-11-09 18:50:32 -080097 auto config = ProducerQueueConfigBuilder()
98 .SetMetadata<DvrNativeBufferMetadata>()
99 .Build();
100 auto queue = ProducerQueue::Create(config, UsagePolicy{});
101 ASSERT_TRUE(queue != nullptr);
102
Jiwen 'Steve' Cai0f950842018-01-16 17:05:54 -0800103 mProducer = BufferHubProducer::Create(std::move(queue));
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700104 ASSERT_TRUE(mProducer != nullptr);
105 mSurface = new Surface(mProducer, true);
106 ASSERT_TRUE(mSurface != nullptr);
107 }
108
109 // Connect to a producer in a 'correct' fashion.
110 void ConnectProducer() {
111 IGraphicBufferProducer::QueueBufferOutput output;
112 // Can connect the first time.
113 ASSERT_EQ(NO_ERROR, mProducer->connect(kDummyListener, kTestApi,
114 kTestControlledByApp, &output));
115 }
116
117 // Dequeue a buffer in a 'correct' fashion.
118 // Precondition: Producer is connected.
119 void DequeueBuffer(int* outSlot) {
120 sp<Fence> fence;
121 ASSERT_NO_FATAL_FAILURE(DequeueBuffer(outSlot, &fence));
122 }
123
124 void DequeueBuffer(int* outSlot, sp<Fence>* outFence) {
125 ASSERT_NE(nullptr, outSlot);
126 ASSERT_NE(nullptr, outFence);
127
Ian Elliotta2eb34c2017-07-18 11:05:49 -0600128 int ret = mProducer->dequeueBuffer(
129 outSlot, outFence, kDefaultWidth, kDefaultHeight, kDefaultFormat,
130 kTestProducerUsageBits, nullptr, nullptr);
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700131 // BUFFER_NEEDS_REALLOCATION can be either on or off.
132 ASSERT_EQ(0, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION & ret);
133
134 // Slot number should be in boundary.
135 ASSERT_LE(0, *outSlot);
136 ASSERT_GT(BufferQueueDefs::NUM_BUFFER_SLOTS, *outSlot);
137 }
138
139 // Create a generic "valid" input for queueBuffer
140 // -- uses the default buffer format, width, etc.
141 static IGraphicBufferProducer::QueueBufferInput CreateBufferInput() {
142 return QueueBufferInputBuilder().build();
143 }
144
145 const sp<IProducerListener> kDummyListener{new DummyProducerListener};
146
Jiwen 'Steve' Cai0f950842018-01-16 17:05:54 -0800147 sp<BufferHubProducer> mProducer;
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700148 sp<Surface> mSurface;
149};
150
151TEST_F(BufferHubQueueProducerTest, ConnectFirst_ReturnsError) {
152 IGraphicBufferProducer::QueueBufferOutput output;
153
154 // NULL output returns BAD_VALUE
155 EXPECT_EQ(BAD_VALUE, mProducer->connect(kDummyListener, kTestApi,
156 kTestControlledByApp, nullptr));
157
158 // Invalid API returns bad value
159 EXPECT_EQ(BAD_VALUE, mProducer->connect(kDummyListener, kTestApiInvalid,
160 kTestControlledByApp, &output));
161}
162
163TEST_F(BufferHubQueueProducerTest, ConnectAgain_ReturnsError) {
164 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
165
166 // Can't connect when there is already a producer connected.
167 IGraphicBufferProducer::QueueBufferOutput output;
168 EXPECT_EQ(BAD_VALUE, mProducer->connect(kDummyListener, kTestApi,
169 kTestControlledByApp, &output));
170}
171
172TEST_F(BufferHubQueueProducerTest, Disconnect_Succeeds) {
173 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
174
175 ASSERT_EQ(NO_ERROR, mProducer->disconnect(kTestApi));
176}
177
178TEST_F(BufferHubQueueProducerTest, Disconnect_ReturnsError) {
179 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
180
181 // Must disconnect with same API number
182 EXPECT_EQ(BAD_VALUE, mProducer->disconnect(kTestApiOther));
183 // API must not be out of range
184 EXPECT_EQ(BAD_VALUE, mProducer->disconnect(kTestApiInvalid));
185}
186
187TEST_F(BufferHubQueueProducerTest, Query_Succeeds) {
188 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
189
190 int32_t value = -1;
191 EXPECT_EQ(NO_ERROR, mProducer->query(NATIVE_WINDOW_WIDTH, &value));
192 EXPECT_EQ(kDefaultWidth, static_cast<uint32_t>(value));
193
194 EXPECT_EQ(NO_ERROR, mProducer->query(NATIVE_WINDOW_HEIGHT, &value));
195 EXPECT_EQ(kDefaultHeight, static_cast<uint32_t>(value));
196
197 EXPECT_EQ(NO_ERROR, mProducer->query(NATIVE_WINDOW_FORMAT, &value));
198 EXPECT_EQ(kDefaultFormat, value);
199
200 EXPECT_EQ(NO_ERROR,
201 mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &value));
202 EXPECT_LE(0, value);
Corey Tabakab7ca5de2017-05-08 18:55:02 -0700203 EXPECT_GE(BufferQueueDefs::NUM_BUFFER_SLOTS, value);
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700204
205 EXPECT_EQ(NO_ERROR,
206 mProducer->query(NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &value));
207 EXPECT_FALSE(value); // Can't run behind when we haven't touched the queue
208
209 EXPECT_EQ(NO_ERROR,
210 mProducer->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &value));
211 EXPECT_EQ(kDefaultConsumerUsageBits, value);
212}
213
214TEST_F(BufferHubQueueProducerTest, Query_ReturnsError) {
215 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
216
217 // One past the end of the last 'query' enum value. Update this if we add more
218 // enums.
219 const int NATIVE_WINDOW_QUERY_LAST_OFF_BY_ONE = NATIVE_WINDOW_BUFFER_AGE + 1;
220
221 int value;
222 // What was out of range
223 EXPECT_EQ(BAD_VALUE, mProducer->query(/*what*/ -1, &value));
224 EXPECT_EQ(BAD_VALUE, mProducer->query(/*what*/ 0xDEADBEEF, &value));
225 EXPECT_EQ(BAD_VALUE,
226 mProducer->query(NATIVE_WINDOW_QUERY_LAST_OFF_BY_ONE, &value));
227
228 // Some enums from window.h are 'invalid'
229 EXPECT_EQ(BAD_VALUE,
230 mProducer->query(NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER, &value));
231 EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_CONCRETE_TYPE, &value));
232 EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_DEFAULT_WIDTH, &value));
233 EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_DEFAULT_HEIGHT, &value));
234 EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_TRANSFORM_HINT, &value));
235
236 // Value was NULL
237 EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_FORMAT, /*value*/ NULL));
238}
239
240TEST_F(BufferHubQueueProducerTest, Queue_Succeeds) {
241 int slot = -1;
242
243 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
244 ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
245
246 // Request the buffer (pre-requisite for queueing)
247 sp<GraphicBuffer> buffer;
248 ASSERT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer));
249
250 // A generic "valid" input
251 IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
252 IGraphicBufferProducer::QueueBufferOutput output;
253
254 // Queue the buffer back into the BQ
255 ASSERT_EQ(NO_ERROR, mProducer->queueBuffer(slot, input, &output));
256
257 EXPECT_EQ(kDefaultWidth, output.width);
258 EXPECT_EQ(kDefaultHeight, output.height);
259 EXPECT_EQ(kDefaultTransformHint, output.transformHint);
260
261 // BufferHubQueue delivers buffers to consumer immediately.
262 EXPECT_EQ(0u, output.numPendingBuffers);
263
264 // Note that BufferHubQueue doesn't support nextFrameNumber as it seems to
265 // be a SurfaceFlinger specific optimization.
266 EXPECT_EQ(0u, output.nextFrameNumber);
267
268 // Buffer was not in the dequeued state
269 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output));
270}
271
272// Test invalid slot number
273TEST_F(BufferHubQueueProducerTest, QueueInvalidSlot_ReturnsError) {
274 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
275
276 // A generic "valid" input
277 IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
278 IGraphicBufferProducer::QueueBufferOutput output;
279
280 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(/*slot*/ -1, input, &output));
281 EXPECT_EQ(BAD_VALUE,
282 mProducer->queueBuffer(/*slot*/ 0xDEADBEEF, input, &output));
283 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(BufferQueueDefs::NUM_BUFFER_SLOTS,
284 input, &output));
285}
286
287// Slot was not in the dequeued state (all slots start out in Free state)
288TEST_F(BufferHubQueueProducerTest, QueueNotDequeued_ReturnsError) {
289 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
290
291 IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
292 IGraphicBufferProducer::QueueBufferOutput output;
293
294 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(/*slot*/ 0, input, &output));
295}
296
297// Slot was enqueued without requesting a buffer
298TEST_F(BufferHubQueueProducerTest, QueueNotRequested_ReturnsError) {
299 int slot = -1;
300
301 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
302 ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
303
304 IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
305 IGraphicBufferProducer::QueueBufferOutput output;
306
307 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output));
308}
309
310// Test when fence was NULL
311TEST_F(BufferHubQueueProducerTest, QueueNoFence_ReturnsError) {
312 int slot = -1;
313
314 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
315 ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
316
317 sp<GraphicBuffer> buffer;
318 ASSERT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer));
319
320 sp<Fence> nullFence = NULL;
321
322 IGraphicBufferProducer::QueueBufferInput input =
323 QueueBufferInputBuilder().setFence(nullFence).build();
324 IGraphicBufferProducer::QueueBufferOutput output;
325
326 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output));
327}
328
329// Test scaling mode was invalid
330TEST_F(BufferHubQueueProducerTest, QueueTestInvalidScalingMode_ReturnsError) {
331 int slot = -1;
332
333 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
334 ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
335
336 sp<GraphicBuffer> buffer;
337 ASSERT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer));
338
339 IGraphicBufferProducer::QueueBufferInput input =
340 QueueBufferInputBuilder().setScalingMode(-1).build();
341 IGraphicBufferProducer::QueueBufferOutput output;
342
343 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output));
344
345 input = QueueBufferInputBuilder().setScalingMode(0xDEADBEEF).build();
346
347 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output));
348}
349
350// Test crop rect is out of bounds of the buffer dimensions
351TEST_F(BufferHubQueueProducerTest, QueueCropOutOfBounds_ReturnsError) {
352 int slot = -1;
353
354 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
355 ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
356
357 sp<GraphicBuffer> buffer;
358 ASSERT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer));
359
360 IGraphicBufferProducer::QueueBufferInput input =
361 QueueBufferInputBuilder()
362 .setCrop(Rect(kDefaultWidth + 1, kDefaultHeight + 1))
363 .build();
364 IGraphicBufferProducer::QueueBufferOutput output;
365
366 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output));
367}
368
369TEST_F(BufferHubQueueProducerTest, CancelBuffer_Succeeds) {
370 int slot = -1;
371 sp<Fence> fence;
372
373 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
374 ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot, &fence));
375
376 // Should be able to cancel buffer after a dequeue.
377 EXPECT_EQ(NO_ERROR, mProducer->cancelBuffer(slot, fence));
378}
379
380TEST_F(BufferHubQueueProducerTest, SetMaxDequeuedBufferCount_Succeeds) {
381 return;
382 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
383
384 int minUndequeuedBuffers;
385 ASSERT_EQ(NO_ERROR, mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
386 &minUndequeuedBuffers));
387
388 const int minBuffers = 1;
389 const int maxBuffers =
390 BufferQueueDefs::NUM_BUFFER_SLOTS - minUndequeuedBuffers;
391
392 ASSERT_EQ(NO_ERROR, mProducer->setAsyncMode(false))
393 << "async mode: " << false;
394 ASSERT_EQ(NO_ERROR, mProducer->setMaxDequeuedBufferCount(minBuffers))
395 << "bufferCount: " << minBuffers;
396
397 // Should now be able to dequeue up to minBuffers times
398 // Should now be able to dequeue up to maxBuffers times
399 int slot = -1;
400 for (int i = 0; i < minBuffers; ++i) {
401 ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
402 }
403
404 ASSERT_EQ(NO_ERROR, mProducer->setMaxDequeuedBufferCount(maxBuffers));
405
406 // queue the first buffer to enable max dequeued buffer count checking
407 IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
408 IGraphicBufferProducer::QueueBufferOutput output;
409 sp<GraphicBuffer> buffer;
410 ASSERT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer));
411 ASSERT_EQ(NO_ERROR, mProducer->queueBuffer(slot, input, &output));
412
413 sp<Fence> fence;
414 for (int i = 0; i < maxBuffers; ++i) {
415 ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot, &fence));
416 }
417
418 // Cancel a buffer, so we can decrease the buffer count
419 ASSERT_EQ(NO_ERROR, mProducer->cancelBuffer(slot, fence));
420
421 // Should now be able to decrease the max dequeued count by 1
422 ASSERT_EQ(NO_ERROR, mProducer->setMaxDequeuedBufferCount(maxBuffers - 1));
423}
424
425TEST_F(BufferHubQueueProducerTest, SetMaxDequeuedBufferCount_Fails) {
426 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
427
428 int minUndequeuedBuffers;
429 ASSERT_EQ(NO_ERROR, mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
430 &minUndequeuedBuffers));
431
432 const int minBuffers = 1;
433 const int maxBuffers =
434 BufferQueueDefs::NUM_BUFFER_SLOTS - minUndequeuedBuffers;
435
436 ASSERT_EQ(NO_ERROR, mProducer->setAsyncMode(false))
437 << "async mode: " << false;
438 // Buffer count was out of range
439 EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(0))
440 << "bufferCount: " << 0;
441 EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(maxBuffers + 1))
442 << "bufferCount: " << maxBuffers + 1;
443
444 // Set max dequeue count to 2
445 ASSERT_EQ(NO_ERROR, mProducer->setMaxDequeuedBufferCount(2));
446 // Dequeue 2 buffers
447 int slot = -1;
448 sp<Fence> fence;
449 for (int i = 0; i < 2; i++) {
450 ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
Ian Elliotta2eb34c2017-07-18 11:05:49 -0600451 (mProducer->dequeueBuffer(&slot, &fence, kDefaultWidth,
452 kDefaultHeight, kDefaultFormat,
453 kTestProducerUsageBits,
454 nullptr, nullptr)))
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700455 << "slot: " << slot;
456 }
457
458 // Client has too many buffers dequeued
459 EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(1))
460 << "bufferCount: " << minBuffers;
461}
462
463TEST_F(BufferHubQueueProducerTest,
464 DisconnectedProducerReturnsError_dequeueBuffer) {
465 int slot = -1;
466 sp<Fence> fence;
467
468 ASSERT_EQ(NO_INIT, mProducer->dequeueBuffer(&slot, &fence, kDefaultWidth,
469 kDefaultHeight, kDefaultFormat,
Ian Elliotta2eb34c2017-07-18 11:05:49 -0600470 kTestProducerUsageBits,
471 nullptr, nullptr));
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700472}
473
474TEST_F(BufferHubQueueProducerTest,
475 DisconnectedProducerReturnsError_requestBuffer) {
476 int slot = -1;
477 sp<GraphicBuffer> buffer;
478
479 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
480 ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
481
482 // Shouldn't be able to request buffer after disconnect.
483 ASSERT_EQ(NO_ERROR, mProducer->disconnect(kTestApi));
484 ASSERT_EQ(NO_INIT, mProducer->requestBuffer(slot, &buffer));
485}
486
487TEST_F(BufferHubQueueProducerTest,
488 DisconnectedProducerReturnsError_queueBuffer) {
489 int slot = -1;
490 sp<GraphicBuffer> buffer;
491
492 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
493 ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
494 ASSERT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer));
495
496 // A generic "valid" input
497 IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
498 IGraphicBufferProducer::QueueBufferOutput output;
499
500 // Shouldn't be able to queue buffer after disconnect.
501 ASSERT_EQ(NO_ERROR, mProducer->disconnect(kTestApi));
502 ASSERT_EQ(NO_INIT, mProducer->queueBuffer(slot, input, &output));
503}
504
505TEST_F(BufferHubQueueProducerTest,
506 DisconnectedProducerReturnsError_cancelBuffer) {
507 int slot = -1;
508 sp<GraphicBuffer> buffer;
509
510 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
511 ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
512 ASSERT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer));
513
514 // Shouldn't be able to cancel buffer after disconnect.
515 ASSERT_EQ(NO_ERROR, mProducer->disconnect(kTestApi));
516 ASSERT_EQ(NO_INIT, mProducer->cancelBuffer(slot, Fence::NO_FENCE));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800517}
518
Jiwen 'Steve' Cai005f45d2017-08-04 17:34:37 -0700519TEST_F(BufferHubQueueProducerTest, ConnectDisconnectReconnect) {
520 int slot = -1;
521 sp<GraphicBuffer> buffer;
522 IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
523 IGraphicBufferProducer::QueueBufferOutput output;
524
525 EXPECT_NO_FATAL_FAILURE(ConnectProducer());
526
527 constexpr int maxDequeuedBuffers = 1;
528 int minUndequeuedBuffers;
529 EXPECT_EQ(NO_ERROR, mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
530 &minUndequeuedBuffers));
531 EXPECT_EQ(NO_ERROR, mProducer->setAsyncMode(false));
532 EXPECT_EQ(NO_ERROR, mProducer->setMaxDequeuedBufferCount(maxDequeuedBuffers));
533
534 int maxCapacity = maxDequeuedBuffers + minUndequeuedBuffers;
535
536 // Dequeue, request, and queue all buffers.
537 for (int i = 0; i < maxCapacity; i++) {
538 EXPECT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
539 EXPECT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer));
540 EXPECT_EQ(NO_ERROR, mProducer->queueBuffer(slot, input, &output));
541 }
542
543 // Disconnect then reconnect.
544 EXPECT_EQ(NO_ERROR, mProducer->disconnect(kTestApi));
545 EXPECT_NO_FATAL_FAILURE(ConnectProducer());
546
547 // Dequeue, request, and queue all buffers.
548 for (int i = 0; i < maxCapacity; i++) {
549 EXPECT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
550 EXPECT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer));
551 EXPECT_EQ(NO_ERROR, mProducer->queueBuffer(slot, input, &output));
552 }
553
554 EXPECT_EQ(NO_ERROR, mProducer->disconnect(kTestApi));
555}
556
Jiwen 'Steve' Cai5afb7402017-11-09 18:50:32 -0800557TEST_F(BufferHubQueueProducerTest, TakeAsParcelable) {
558 // Connected producer cannot be taken out as a parcelable.
559 EXPECT_NO_FATAL_FAILURE(ConnectProducer());
560 ProducerQueueParcelable producer_parcelable;
561 EXPECT_EQ(mProducer->TakeAsParcelable(&producer_parcelable), BAD_VALUE);
562
563 // Create a valid dummy producer parcelable.
564 auto dummy_channel_parcelable =
565 std::make_unique<pdx::default_transport::ChannelParcelable>(
566 LocalHandle(0), LocalHandle(0), LocalHandle(0));
567 EXPECT_TRUE(dummy_channel_parcelable->IsValid());
568 ProducerQueueParcelable dummy_producer_parcelable(
569 std::move(dummy_channel_parcelable));
570 EXPECT_TRUE(dummy_producer_parcelable.IsValid());
571
572 // Disconnect producer can be taken out, but only to an invalid parcelable.
573 ASSERT_EQ(mProducer->disconnect(kTestApi), NO_ERROR);
574 EXPECT_EQ(mProducer->TakeAsParcelable(&dummy_producer_parcelable), BAD_VALUE);
575 EXPECT_FALSE(producer_parcelable.IsValid());
576 EXPECT_EQ(mProducer->TakeAsParcelable(&producer_parcelable), NO_ERROR);
577 EXPECT_TRUE(producer_parcelable.IsValid());
578
579 // Should still be able to query buffer dimension after disconnect.
580 int32_t value = -1;
581 EXPECT_EQ(NO_ERROR, mProducer->query(NATIVE_WINDOW_WIDTH, &value));
582 EXPECT_EQ(static_cast<uint32_t>(value), kDefaultWidth);
583
584 EXPECT_EQ(mProducer->query(NATIVE_WINDOW_HEIGHT, &value), NO_ERROR);
585 EXPECT_EQ(static_cast<uint32_t>(value), kDefaultHeight);
586
587 EXPECT_EQ(mProducer->query(NATIVE_WINDOW_FORMAT, &value), NO_ERROR);
588 EXPECT_EQ(value, kDefaultFormat);
589
590 // But connect to API will fail.
591 IGraphicBufferProducer::QueueBufferOutput output;
592 EXPECT_EQ(mProducer->connect(kDummyListener, kTestApi, kTestControlledByApp,
593 &output),
594 BAD_VALUE);
595
596 // Create a new producer from the parcelable and connect to kTestApi should
597 // succeed.
Jiwen 'Steve' Cai0f950842018-01-16 17:05:54 -0800598 sp<BufferHubProducer> new_producer =
599 BufferHubProducer::Create(std::move(producer_parcelable));
Jiwen 'Steve' Cai5afb7402017-11-09 18:50:32 -0800600 ASSERT_TRUE(new_producer != nullptr);
601 EXPECT_EQ(new_producer->connect(kDummyListener, kTestApi,
602 kTestControlledByApp, &output),
603 NO_ERROR);
604}
605
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800606} // namespace
607
608} // namespace dvr
609} // namespace android