blob: 96f540421e05d0368b7f80a98f9ae7dd7d2595a0 [file] [log] [blame]
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08001#include <private/dvr/buffer_hub_queue_producer.h>
2
3#include <base/logging.h>
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -07004#include <gui/IProducerListener.h>
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08005#include <gui/Surface.h>
Jiwen 'Steve' Cai5afb7402017-11-09 18:50:32 -08006#include <pdx/default_transport/channel_parcelable.h>
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -07007
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08008#include <gtest/gtest.h>
9
10namespace android {
11namespace dvr {
12
Jiwen 'Steve' Cai5afb7402017-11-09 18:50:32 -080013using pdx::LocalHandle;
14
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080015namespace {
16
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -070017// Default dimensions before setDefaultBufferSize is called by the consumer.
18constexpr uint32_t kDefaultWidth = 1;
19constexpr uint32_t kDefaultHeight = 1;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080020
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -070021// Default format before setDefaultBufferFormat is called by the consumer.
22constexpr PixelFormat kDefaultFormat = HAL_PIXEL_FORMAT_RGBA_8888;
23constexpr int kDefaultConsumerUsageBits = 0;
24
25// Default transform hint before setTransformHint is called by the consumer.
26constexpr uint32_t kDefaultTransformHint = 0;
27
28constexpr int kTestApi = NATIVE_WINDOW_API_CPU;
29constexpr int kTestApiOther = NATIVE_WINDOW_API_EGL;
30constexpr int kTestApiInvalid = 0xDEADBEEF;
31constexpr int kTestProducerUsageBits = 0;
32constexpr bool kTestControlledByApp = true;
33
34// Builder pattern to slightly vary *almost* correct input
35// -- avoids copying and pasting
36struct QueueBufferInputBuilder {
37 IGraphicBufferProducer::QueueBufferInput build() {
38 return IGraphicBufferProducer::QueueBufferInput(
39 mTimestamp, mIsAutoTimestamp, mDataSpace, mCrop, mScalingMode,
40 mTransform, mFence);
41 }
42
43 QueueBufferInputBuilder& setTimestamp(int64_t timestamp) {
44 this->mTimestamp = timestamp;
45 return *this;
46 }
47
48 QueueBufferInputBuilder& setIsAutoTimestamp(bool isAutoTimestamp) {
49 this->mIsAutoTimestamp = isAutoTimestamp;
50 return *this;
51 }
52
53 QueueBufferInputBuilder& setDataSpace(android_dataspace dataSpace) {
54 this->mDataSpace = dataSpace;
55 return *this;
56 }
57
58 QueueBufferInputBuilder& setCrop(Rect crop) {
59 this->mCrop = crop;
60 return *this;
61 }
62
63 QueueBufferInputBuilder& setScalingMode(int scalingMode) {
64 this->mScalingMode = scalingMode;
65 return *this;
66 }
67
68 QueueBufferInputBuilder& setTransform(uint32_t transform) {
69 this->mTransform = transform;
70 return *this;
71 }
72
73 QueueBufferInputBuilder& setFence(sp<Fence> fence) {
74 this->mFence = fence;
75 return *this;
76 }
77
78 private:
79 int64_t mTimestamp{1384888611};
80 bool mIsAutoTimestamp{false};
81 android_dataspace mDataSpace{HAL_DATASPACE_UNKNOWN};
82 Rect mCrop{Rect(kDefaultWidth, kDefaultHeight)};
83 int mScalingMode{0};
84 uint32_t mTransform{0};
85 sp<Fence> mFence{Fence::NO_FENCE};
86};
87
88// This is a test that covers our implementation of bufferhubqueue-based
89// IGraphicBufferProducer.
90class BufferHubQueueProducerTest : public ::testing::Test {
91 protected:
92 virtual void SetUp() {
93 const ::testing::TestInfo* const testInfo =
94 ::testing::UnitTest::GetInstance()->current_test_info();
95 ALOGD_IF(TRACE, "Begin test: %s.%s", testInfo->test_case_name(),
96 testInfo->name());
97
Jiwen 'Steve' Cai5afb7402017-11-09 18:50:32 -080098 auto config = ProducerQueueConfigBuilder()
99 .SetMetadata<DvrNativeBufferMetadata>()
100 .Build();
101 auto queue = ProducerQueue::Create(config, UsagePolicy{});
102 ASSERT_TRUE(queue != nullptr);
103
104 mProducer = BufferHubQueueProducer::Create(std::move(queue));
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700105 ASSERT_TRUE(mProducer != nullptr);
106 mSurface = new Surface(mProducer, true);
107 ASSERT_TRUE(mSurface != nullptr);
108 }
109
110 // Connect to a producer in a 'correct' fashion.
111 void ConnectProducer() {
112 IGraphicBufferProducer::QueueBufferOutput output;
113 // Can connect the first time.
114 ASSERT_EQ(NO_ERROR, mProducer->connect(kDummyListener, kTestApi,
115 kTestControlledByApp, &output));
116 }
117
118 // Dequeue a buffer in a 'correct' fashion.
119 // Precondition: Producer is connected.
120 void DequeueBuffer(int* outSlot) {
121 sp<Fence> fence;
122 ASSERT_NO_FATAL_FAILURE(DequeueBuffer(outSlot, &fence));
123 }
124
125 void DequeueBuffer(int* outSlot, sp<Fence>* outFence) {
126 ASSERT_NE(nullptr, outSlot);
127 ASSERT_NE(nullptr, outFence);
128
Ian Elliotta2eb34c2017-07-18 11:05:49 -0600129 int ret = mProducer->dequeueBuffer(
130 outSlot, outFence, kDefaultWidth, kDefaultHeight, kDefaultFormat,
131 kTestProducerUsageBits, nullptr, nullptr);
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700132 // BUFFER_NEEDS_REALLOCATION can be either on or off.
133 ASSERT_EQ(0, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION & ret);
134
135 // Slot number should be in boundary.
136 ASSERT_LE(0, *outSlot);
137 ASSERT_GT(BufferQueueDefs::NUM_BUFFER_SLOTS, *outSlot);
138 }
139
140 // Create a generic "valid" input for queueBuffer
141 // -- uses the default buffer format, width, etc.
142 static IGraphicBufferProducer::QueueBufferInput CreateBufferInput() {
143 return QueueBufferInputBuilder().build();
144 }
145
146 const sp<IProducerListener> kDummyListener{new DummyProducerListener};
147
148 sp<BufferHubQueueProducer> mProducer;
149 sp<Surface> mSurface;
150};
151
152TEST_F(BufferHubQueueProducerTest, ConnectFirst_ReturnsError) {
153 IGraphicBufferProducer::QueueBufferOutput output;
154
155 // NULL output returns BAD_VALUE
156 EXPECT_EQ(BAD_VALUE, mProducer->connect(kDummyListener, kTestApi,
157 kTestControlledByApp, nullptr));
158
159 // Invalid API returns bad value
160 EXPECT_EQ(BAD_VALUE, mProducer->connect(kDummyListener, kTestApiInvalid,
161 kTestControlledByApp, &output));
162}
163
164TEST_F(BufferHubQueueProducerTest, ConnectAgain_ReturnsError) {
165 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
166
167 // Can't connect when there is already a producer connected.
168 IGraphicBufferProducer::QueueBufferOutput output;
169 EXPECT_EQ(BAD_VALUE, mProducer->connect(kDummyListener, kTestApi,
170 kTestControlledByApp, &output));
171}
172
173TEST_F(BufferHubQueueProducerTest, Disconnect_Succeeds) {
174 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
175
176 ASSERT_EQ(NO_ERROR, mProducer->disconnect(kTestApi));
177}
178
179TEST_F(BufferHubQueueProducerTest, Disconnect_ReturnsError) {
180 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
181
182 // Must disconnect with same API number
183 EXPECT_EQ(BAD_VALUE, mProducer->disconnect(kTestApiOther));
184 // API must not be out of range
185 EXPECT_EQ(BAD_VALUE, mProducer->disconnect(kTestApiInvalid));
186}
187
188TEST_F(BufferHubQueueProducerTest, Query_Succeeds) {
189 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
190
191 int32_t value = -1;
192 EXPECT_EQ(NO_ERROR, mProducer->query(NATIVE_WINDOW_WIDTH, &value));
193 EXPECT_EQ(kDefaultWidth, static_cast<uint32_t>(value));
194
195 EXPECT_EQ(NO_ERROR, mProducer->query(NATIVE_WINDOW_HEIGHT, &value));
196 EXPECT_EQ(kDefaultHeight, static_cast<uint32_t>(value));
197
198 EXPECT_EQ(NO_ERROR, mProducer->query(NATIVE_WINDOW_FORMAT, &value));
199 EXPECT_EQ(kDefaultFormat, value);
200
201 EXPECT_EQ(NO_ERROR,
202 mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &value));
203 EXPECT_LE(0, value);
Corey Tabakab7ca5de2017-05-08 18:55:02 -0700204 EXPECT_GE(BufferQueueDefs::NUM_BUFFER_SLOTS, value);
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700205
206 EXPECT_EQ(NO_ERROR,
207 mProducer->query(NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &value));
208 EXPECT_FALSE(value); // Can't run behind when we haven't touched the queue
209
210 EXPECT_EQ(NO_ERROR,
211 mProducer->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &value));
212 EXPECT_EQ(kDefaultConsumerUsageBits, value);
213}
214
215TEST_F(BufferHubQueueProducerTest, Query_ReturnsError) {
216 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
217
218 // One past the end of the last 'query' enum value. Update this if we add more
219 // enums.
220 const int NATIVE_WINDOW_QUERY_LAST_OFF_BY_ONE = NATIVE_WINDOW_BUFFER_AGE + 1;
221
222 int value;
223 // What was out of range
224 EXPECT_EQ(BAD_VALUE, mProducer->query(/*what*/ -1, &value));
225 EXPECT_EQ(BAD_VALUE, mProducer->query(/*what*/ 0xDEADBEEF, &value));
226 EXPECT_EQ(BAD_VALUE,
227 mProducer->query(NATIVE_WINDOW_QUERY_LAST_OFF_BY_ONE, &value));
228
229 // Some enums from window.h are 'invalid'
230 EXPECT_EQ(BAD_VALUE,
231 mProducer->query(NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER, &value));
232 EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_CONCRETE_TYPE, &value));
233 EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_DEFAULT_WIDTH, &value));
234 EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_DEFAULT_HEIGHT, &value));
235 EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_TRANSFORM_HINT, &value));
236
237 // Value was NULL
238 EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_FORMAT, /*value*/ NULL));
239}
240
241TEST_F(BufferHubQueueProducerTest, Queue_Succeeds) {
242 int slot = -1;
243
244 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
245 ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
246
247 // Request the buffer (pre-requisite for queueing)
248 sp<GraphicBuffer> buffer;
249 ASSERT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer));
250
251 // A generic "valid" input
252 IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
253 IGraphicBufferProducer::QueueBufferOutput output;
254
255 // Queue the buffer back into the BQ
256 ASSERT_EQ(NO_ERROR, mProducer->queueBuffer(slot, input, &output));
257
258 EXPECT_EQ(kDefaultWidth, output.width);
259 EXPECT_EQ(kDefaultHeight, output.height);
260 EXPECT_EQ(kDefaultTransformHint, output.transformHint);
261
262 // BufferHubQueue delivers buffers to consumer immediately.
263 EXPECT_EQ(0u, output.numPendingBuffers);
264
265 // Note that BufferHubQueue doesn't support nextFrameNumber as it seems to
266 // be a SurfaceFlinger specific optimization.
267 EXPECT_EQ(0u, output.nextFrameNumber);
268
269 // Buffer was not in the dequeued state
270 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output));
271}
272
273// Test invalid slot number
274TEST_F(BufferHubQueueProducerTest, QueueInvalidSlot_ReturnsError) {
275 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
276
277 // A generic "valid" input
278 IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
279 IGraphicBufferProducer::QueueBufferOutput output;
280
281 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(/*slot*/ -1, input, &output));
282 EXPECT_EQ(BAD_VALUE,
283 mProducer->queueBuffer(/*slot*/ 0xDEADBEEF, input, &output));
284 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(BufferQueueDefs::NUM_BUFFER_SLOTS,
285 input, &output));
286}
287
288// Slot was not in the dequeued state (all slots start out in Free state)
289TEST_F(BufferHubQueueProducerTest, QueueNotDequeued_ReturnsError) {
290 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
291
292 IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
293 IGraphicBufferProducer::QueueBufferOutput output;
294
295 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(/*slot*/ 0, input, &output));
296}
297
298// Slot was enqueued without requesting a buffer
299TEST_F(BufferHubQueueProducerTest, QueueNotRequested_ReturnsError) {
300 int slot = -1;
301
302 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
303 ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
304
305 IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
306 IGraphicBufferProducer::QueueBufferOutput output;
307
308 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output));
309}
310
311// Test when fence was NULL
312TEST_F(BufferHubQueueProducerTest, QueueNoFence_ReturnsError) {
313 int slot = -1;
314
315 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
316 ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
317
318 sp<GraphicBuffer> buffer;
319 ASSERT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer));
320
321 sp<Fence> nullFence = NULL;
322
323 IGraphicBufferProducer::QueueBufferInput input =
324 QueueBufferInputBuilder().setFence(nullFence).build();
325 IGraphicBufferProducer::QueueBufferOutput output;
326
327 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output));
328}
329
330// Test scaling mode was invalid
331TEST_F(BufferHubQueueProducerTest, QueueTestInvalidScalingMode_ReturnsError) {
332 int slot = -1;
333
334 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
335 ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
336
337 sp<GraphicBuffer> buffer;
338 ASSERT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer));
339
340 IGraphicBufferProducer::QueueBufferInput input =
341 QueueBufferInputBuilder().setScalingMode(-1).build();
342 IGraphicBufferProducer::QueueBufferOutput output;
343
344 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output));
345
346 input = QueueBufferInputBuilder().setScalingMode(0xDEADBEEF).build();
347
348 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output));
349}
350
351// Test crop rect is out of bounds of the buffer dimensions
352TEST_F(BufferHubQueueProducerTest, QueueCropOutOfBounds_ReturnsError) {
353 int slot = -1;
354
355 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
356 ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
357
358 sp<GraphicBuffer> buffer;
359 ASSERT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer));
360
361 IGraphicBufferProducer::QueueBufferInput input =
362 QueueBufferInputBuilder()
363 .setCrop(Rect(kDefaultWidth + 1, kDefaultHeight + 1))
364 .build();
365 IGraphicBufferProducer::QueueBufferOutput output;
366
367 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(slot, input, &output));
368}
369
370TEST_F(BufferHubQueueProducerTest, CancelBuffer_Succeeds) {
371 int slot = -1;
372 sp<Fence> fence;
373
374 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
375 ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot, &fence));
376
377 // Should be able to cancel buffer after a dequeue.
378 EXPECT_EQ(NO_ERROR, mProducer->cancelBuffer(slot, fence));
379}
380
381TEST_F(BufferHubQueueProducerTest, SetMaxDequeuedBufferCount_Succeeds) {
382 return;
383 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
384
385 int minUndequeuedBuffers;
386 ASSERT_EQ(NO_ERROR, mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
387 &minUndequeuedBuffers));
388
389 const int minBuffers = 1;
390 const int maxBuffers =
391 BufferQueueDefs::NUM_BUFFER_SLOTS - minUndequeuedBuffers;
392
393 ASSERT_EQ(NO_ERROR, mProducer->setAsyncMode(false))
394 << "async mode: " << false;
395 ASSERT_EQ(NO_ERROR, mProducer->setMaxDequeuedBufferCount(minBuffers))
396 << "bufferCount: " << minBuffers;
397
398 // Should now be able to dequeue up to minBuffers times
399 // Should now be able to dequeue up to maxBuffers times
400 int slot = -1;
401 for (int i = 0; i < minBuffers; ++i) {
402 ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
403 }
404
405 ASSERT_EQ(NO_ERROR, mProducer->setMaxDequeuedBufferCount(maxBuffers));
406
407 // queue the first buffer to enable max dequeued buffer count checking
408 IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
409 IGraphicBufferProducer::QueueBufferOutput output;
410 sp<GraphicBuffer> buffer;
411 ASSERT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer));
412 ASSERT_EQ(NO_ERROR, mProducer->queueBuffer(slot, input, &output));
413
414 sp<Fence> fence;
415 for (int i = 0; i < maxBuffers; ++i) {
416 ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot, &fence));
417 }
418
419 // Cancel a buffer, so we can decrease the buffer count
420 ASSERT_EQ(NO_ERROR, mProducer->cancelBuffer(slot, fence));
421
422 // Should now be able to decrease the max dequeued count by 1
423 ASSERT_EQ(NO_ERROR, mProducer->setMaxDequeuedBufferCount(maxBuffers - 1));
424}
425
426TEST_F(BufferHubQueueProducerTest, SetMaxDequeuedBufferCount_Fails) {
427 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
428
429 int minUndequeuedBuffers;
430 ASSERT_EQ(NO_ERROR, mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
431 &minUndequeuedBuffers));
432
433 const int minBuffers = 1;
434 const int maxBuffers =
435 BufferQueueDefs::NUM_BUFFER_SLOTS - minUndequeuedBuffers;
436
437 ASSERT_EQ(NO_ERROR, mProducer->setAsyncMode(false))
438 << "async mode: " << false;
439 // Buffer count was out of range
440 EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(0))
441 << "bufferCount: " << 0;
442 EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(maxBuffers + 1))
443 << "bufferCount: " << maxBuffers + 1;
444
445 // Set max dequeue count to 2
446 ASSERT_EQ(NO_ERROR, mProducer->setMaxDequeuedBufferCount(2));
447 // Dequeue 2 buffers
448 int slot = -1;
449 sp<Fence> fence;
450 for (int i = 0; i < 2; i++) {
451 ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
Ian Elliotta2eb34c2017-07-18 11:05:49 -0600452 (mProducer->dequeueBuffer(&slot, &fence, kDefaultWidth,
453 kDefaultHeight, kDefaultFormat,
454 kTestProducerUsageBits,
455 nullptr, nullptr)))
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700456 << "slot: " << slot;
457 }
458
459 // Client has too many buffers dequeued
460 EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(1))
461 << "bufferCount: " << minBuffers;
462}
463
464TEST_F(BufferHubQueueProducerTest,
465 DisconnectedProducerReturnsError_dequeueBuffer) {
466 int slot = -1;
467 sp<Fence> fence;
468
469 ASSERT_EQ(NO_INIT, mProducer->dequeueBuffer(&slot, &fence, kDefaultWidth,
470 kDefaultHeight, kDefaultFormat,
Ian Elliotta2eb34c2017-07-18 11:05:49 -0600471 kTestProducerUsageBits,
472 nullptr, nullptr));
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700473}
474
475TEST_F(BufferHubQueueProducerTest,
476 DisconnectedProducerReturnsError_requestBuffer) {
477 int slot = -1;
478 sp<GraphicBuffer> buffer;
479
480 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
481 ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
482
483 // Shouldn't be able to request buffer after disconnect.
484 ASSERT_EQ(NO_ERROR, mProducer->disconnect(kTestApi));
485 ASSERT_EQ(NO_INIT, mProducer->requestBuffer(slot, &buffer));
486}
487
488TEST_F(BufferHubQueueProducerTest,
489 DisconnectedProducerReturnsError_queueBuffer) {
490 int slot = -1;
491 sp<GraphicBuffer> buffer;
492
493 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
494 ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
495 ASSERT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer));
496
497 // A generic "valid" input
498 IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
499 IGraphicBufferProducer::QueueBufferOutput output;
500
501 // Shouldn't be able to queue buffer after disconnect.
502 ASSERT_EQ(NO_ERROR, mProducer->disconnect(kTestApi));
503 ASSERT_EQ(NO_INIT, mProducer->queueBuffer(slot, input, &output));
504}
505
506TEST_F(BufferHubQueueProducerTest,
507 DisconnectedProducerReturnsError_cancelBuffer) {
508 int slot = -1;
509 sp<GraphicBuffer> buffer;
510
511 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
512 ASSERT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
513 ASSERT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer));
514
515 // Shouldn't be able to cancel buffer after disconnect.
516 ASSERT_EQ(NO_ERROR, mProducer->disconnect(kTestApi));
517 ASSERT_EQ(NO_INIT, mProducer->cancelBuffer(slot, Fence::NO_FENCE));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800518}
519
Jiwen 'Steve' Cai005f45d2017-08-04 17:34:37 -0700520TEST_F(BufferHubQueueProducerTest, ConnectDisconnectReconnect) {
521 int slot = -1;
522 sp<GraphicBuffer> buffer;
523 IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
524 IGraphicBufferProducer::QueueBufferOutput output;
525
526 EXPECT_NO_FATAL_FAILURE(ConnectProducer());
527
528 constexpr int maxDequeuedBuffers = 1;
529 int minUndequeuedBuffers;
530 EXPECT_EQ(NO_ERROR, mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
531 &minUndequeuedBuffers));
532 EXPECT_EQ(NO_ERROR, mProducer->setAsyncMode(false));
533 EXPECT_EQ(NO_ERROR, mProducer->setMaxDequeuedBufferCount(maxDequeuedBuffers));
534
535 int maxCapacity = maxDequeuedBuffers + minUndequeuedBuffers;
536
537 // Dequeue, request, and queue all buffers.
538 for (int i = 0; i < maxCapacity; i++) {
539 EXPECT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
540 EXPECT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer));
541 EXPECT_EQ(NO_ERROR, mProducer->queueBuffer(slot, input, &output));
542 }
543
544 // Disconnect then reconnect.
545 EXPECT_EQ(NO_ERROR, mProducer->disconnect(kTestApi));
546 EXPECT_NO_FATAL_FAILURE(ConnectProducer());
547
548 // Dequeue, request, and queue all buffers.
549 for (int i = 0; i < maxCapacity; i++) {
550 EXPECT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
551 EXPECT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer));
552 EXPECT_EQ(NO_ERROR, mProducer->queueBuffer(slot, input, &output));
553 }
554
555 EXPECT_EQ(NO_ERROR, mProducer->disconnect(kTestApi));
556}
557
Jiwen 'Steve' Cai5afb7402017-11-09 18:50:32 -0800558TEST_F(BufferHubQueueProducerTest, TakeAsParcelable) {
559 // Connected producer cannot be taken out as a parcelable.
560 EXPECT_NO_FATAL_FAILURE(ConnectProducer());
561 ProducerQueueParcelable producer_parcelable;
562 EXPECT_EQ(mProducer->TakeAsParcelable(&producer_parcelable), BAD_VALUE);
563
564 // Create a valid dummy producer parcelable.
565 auto dummy_channel_parcelable =
566 std::make_unique<pdx::default_transport::ChannelParcelable>(
567 LocalHandle(0), LocalHandle(0), LocalHandle(0));
568 EXPECT_TRUE(dummy_channel_parcelable->IsValid());
569 ProducerQueueParcelable dummy_producer_parcelable(
570 std::move(dummy_channel_parcelable));
571 EXPECT_TRUE(dummy_producer_parcelable.IsValid());
572
573 // Disconnect producer can be taken out, but only to an invalid parcelable.
574 ASSERT_EQ(mProducer->disconnect(kTestApi), NO_ERROR);
575 EXPECT_EQ(mProducer->TakeAsParcelable(&dummy_producer_parcelable), BAD_VALUE);
576 EXPECT_FALSE(producer_parcelable.IsValid());
577 EXPECT_EQ(mProducer->TakeAsParcelable(&producer_parcelable), NO_ERROR);
578 EXPECT_TRUE(producer_parcelable.IsValid());
579
580 // Should still be able to query buffer dimension after disconnect.
581 int32_t value = -1;
582 EXPECT_EQ(NO_ERROR, mProducer->query(NATIVE_WINDOW_WIDTH, &value));
583 EXPECT_EQ(static_cast<uint32_t>(value), kDefaultWidth);
584
585 EXPECT_EQ(mProducer->query(NATIVE_WINDOW_HEIGHT, &value), NO_ERROR);
586 EXPECT_EQ(static_cast<uint32_t>(value), kDefaultHeight);
587
588 EXPECT_EQ(mProducer->query(NATIVE_WINDOW_FORMAT, &value), NO_ERROR);
589 EXPECT_EQ(value, kDefaultFormat);
590
591 // But connect to API will fail.
592 IGraphicBufferProducer::QueueBufferOutput output;
593 EXPECT_EQ(mProducer->connect(kDummyListener, kTestApi, kTestControlledByApp,
594 &output),
595 BAD_VALUE);
596
597 // Create a new producer from the parcelable and connect to kTestApi should
598 // succeed.
599 sp<BufferHubQueueProducer> new_producer =
600 BufferHubQueueProducer::Create(std::move(producer_parcelable));
601 ASSERT_TRUE(new_producer != nullptr);
602 EXPECT_EQ(new_producer->connect(kDummyListener, kTestApi,
603 kTestControlledByApp, &output),
604 NO_ERROR);
605}
606
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800607} // namespace
608
609} // namespace dvr
610} // namespace android