1 /*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "IGraphicBufferProducer_test"
18 //#define LOG_NDEBUG 0
19
20 #include "Constants.h"
21 #include "MockConsumer.h"
22
23 #include <gtest/gtest.h>
24
25 #include <utils/String8.h>
26 #include <utils/threads.h>
27
28 #include <ui/GraphicBuffer.h>
29
30 #include <gui/BufferQueue.h>
31 #include <gui/IProducerListener.h>
32
33 #include <system/window.h>
34
35 #include <vector>
36
37 #define ASSERT_OK(x) ASSERT_EQ(OK, (x))
38 #define EXPECT_OK(x) EXPECT_EQ(OK, (x))
39
40 #define TEST_TOKEN ((IProducerListener*)(NULL))
41 #define TEST_API NATIVE_WINDOW_API_CPU
42 #define TEST_API_OTHER NATIVE_WINDOW_API_EGL // valid API that's not TEST_API
43 #define TEST_CONTROLLED_BY_APP false
44
45 namespace android {
46
47 namespace {
48 // Default dimensions before setDefaultBufferSize is called
49 const uint32_t DEFAULT_WIDTH = 1;
50 const uint32_t DEFAULT_HEIGHT = 1;
51
52 // Default format before setDefaultBufferFormat is called
53 const PixelFormat DEFAULT_FORMAT = HAL_PIXEL_FORMAT_RGBA_8888;
54
55 // Default transform hint before setTransformHint is called
56 const uint32_t DEFAULT_TRANSFORM_HINT = 0;
57
58 // TODO: Make these constants in header
59 const int DEFAULT_CONSUMER_USAGE_BITS = 0;
60
61 // Parameters for a generic "valid" input for queueBuffer.
62 const int64_t QUEUE_BUFFER_INPUT_TIMESTAMP = 1384888611;
63 const bool QUEUE_BUFFER_INPUT_IS_AUTO_TIMESTAMP = false;
64 const android_dataspace QUEUE_BUFFER_INPUT_DATASPACE = HAL_DATASPACE_UNKNOWN;
65 const Rect QUEUE_BUFFER_INPUT_RECT = Rect(DEFAULT_WIDTH, DEFAULT_HEIGHT);
66 const int QUEUE_BUFFER_INPUT_SCALING_MODE = 0;
67 const int QUEUE_BUFFER_INPUT_TRANSFORM = 0;
68 const sp<Fence> QUEUE_BUFFER_INPUT_FENCE = Fence::NO_FENCE;
69 const uint32_t QUEUE_BUFFER_INPUT_STICKY_TRANSFORM = 0;
70 const bool QUEUE_BUFFER_INPUT_GET_TIMESTAMPS = 0;
71 const int QUEUE_BUFFER_INPUT_SLOT = -1;
72
73 // Enums to control which IGraphicBufferProducer backend to test.
74 enum IGraphicBufferProducerTestCode {
75 USE_BUFFER_QUEUE_PRODUCER = 0,
76 };
77 }; // namespace anonymous
78
79 class IGraphicBufferProducerTest : public ::testing::TestWithParam<uint32_t> {
80 protected:
81
IGraphicBufferProducerTest()82 IGraphicBufferProducerTest() {}
83
SetUp()84 virtual void SetUp() {
85 mMC = new MockConsumer;
86
87 switch (GetParam()) {
88 case USE_BUFFER_QUEUE_PRODUCER: {
89 BufferQueue::createBufferQueue(&mProducer, &mConsumer);
90 break;
91 }
92 default: {
93 // Should never reach here.
94 LOG_ALWAYS_FATAL("Invalid test params: %u", GetParam());
95 break;
96 }
97 }
98
99 // Test check: Can't connect producer if no consumer yet
100 if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
101 // TODO(b/73267953): Make BufferHub honor producer and consumer connection.
102 ASSERT_EQ(NO_INIT, TryConnectProducer());
103 }
104
105 // Must connect consumer before producer connects will succeed.
106 ASSERT_OK(mConsumer->consumerConnect(mMC, /*controlledByApp*/ false));
107 }
108
TryConnectProducer()109 status_t TryConnectProducer() {
110 IGraphicBufferProducer::QueueBufferOutput output;
111 return mProducer->connect(TEST_TOKEN,
112 TEST_API,
113 TEST_CONTROLLED_BY_APP,
114 &output);
115 // TODO: use params to vary token, api, producercontrolledbyapp, etc
116 }
117
118 // Connect to a producer in a 'correct' fashion.
119 // Precondition: Consumer is connected.
ConnectProducer()120 void ConnectProducer() {
121 ASSERT_OK(TryConnectProducer());
122 }
123
124 // Create a generic "valid" input for queueBuffer
125 // -- uses the default buffer format, width, etc.
CreateBufferInput()126 static IGraphicBufferProducer::QueueBufferInput CreateBufferInput() {
127 return QueueBufferInputBuilder().build();
128 }
129
130 // Builder pattern to slightly vary *almost* correct input
131 // -- avoids copying and pasting
132 struct QueueBufferInputBuilder {
QueueBufferInputBuilderandroid::IGraphicBufferProducerTest::QueueBufferInputBuilder133 QueueBufferInputBuilder() {
134 timestamp = QUEUE_BUFFER_INPUT_TIMESTAMP;
135 isAutoTimestamp = QUEUE_BUFFER_INPUT_IS_AUTO_TIMESTAMP;
136 dataSpace = QUEUE_BUFFER_INPUT_DATASPACE;
137 crop = QUEUE_BUFFER_INPUT_RECT;
138 scalingMode = QUEUE_BUFFER_INPUT_SCALING_MODE;
139 transform = QUEUE_BUFFER_INPUT_TRANSFORM;
140 fence = QUEUE_BUFFER_INPUT_FENCE;
141 stickyTransform = QUEUE_BUFFER_INPUT_STICKY_TRANSFORM;
142 getTimestamps = QUEUE_BUFFER_INPUT_GET_TIMESTAMPS;
143 slot = QUEUE_BUFFER_INPUT_SLOT;
144 }
145
buildandroid::IGraphicBufferProducerTest::QueueBufferInputBuilder146 IGraphicBufferProducer::QueueBufferInput build() {
147 return IGraphicBufferProducer::QueueBufferInput(
148 timestamp,
149 isAutoTimestamp,
150 dataSpace,
151 crop,
152 scalingMode,
153 transform,
154 fence,
155 stickyTransform,
156 getTimestamps,
157 slot);
158 }
159
setTimestampandroid::IGraphicBufferProducerTest::QueueBufferInputBuilder160 QueueBufferInputBuilder& setTimestamp(int64_t timestamp) {
161 this->timestamp = timestamp;
162 return *this;
163 }
164
setIsAutoTimestampandroid::IGraphicBufferProducerTest::QueueBufferInputBuilder165 QueueBufferInputBuilder& setIsAutoTimestamp(bool isAutoTimestamp) {
166 this->isAutoTimestamp = isAutoTimestamp;
167 return *this;
168 }
169
setDataSpaceandroid::IGraphicBufferProducerTest::QueueBufferInputBuilder170 QueueBufferInputBuilder& setDataSpace(android_dataspace dataSpace) {
171 this->dataSpace = dataSpace;
172 return *this;
173 }
174
setCropandroid::IGraphicBufferProducerTest::QueueBufferInputBuilder175 QueueBufferInputBuilder& setCrop(Rect crop) {
176 this->crop = crop;
177 return *this;
178 }
179
setScalingModeandroid::IGraphicBufferProducerTest::QueueBufferInputBuilder180 QueueBufferInputBuilder& setScalingMode(int scalingMode) {
181 this->scalingMode = scalingMode;
182 return *this;
183 }
184
setTransformandroid::IGraphicBufferProducerTest::QueueBufferInputBuilder185 QueueBufferInputBuilder& setTransform(uint32_t transform) {
186 this->transform = transform;
187 return *this;
188 }
189
setFenceandroid::IGraphicBufferProducerTest::QueueBufferInputBuilder190 QueueBufferInputBuilder& setFence(sp<Fence> fence) {
191 this->fence = fence;
192 return *this;
193 }
194
setStickyTransformandroid::IGraphicBufferProducerTest::QueueBufferInputBuilder195 QueueBufferInputBuilder& setStickyTransform(uint32_t stickyTransform) {
196 this->stickyTransform = stickyTransform;
197 return *this;
198 }
199
setGetTimestampsandroid::IGraphicBufferProducerTest::QueueBufferInputBuilder200 QueueBufferInputBuilder& setGetTimestamps(bool getTimestamps) {
201 this->getTimestamps = getTimestamps;
202 return *this;
203 }
204
setSlotandroid::IGraphicBufferProducerTest::QueueBufferInputBuilder205 QueueBufferInputBuilder& setSlot(int slot) {
206 this->slot = slot;
207 return *this;
208 }
209
210 private:
211 int64_t timestamp;
212 bool isAutoTimestamp;
213 android_dataspace dataSpace;
214 Rect crop;
215 int scalingMode;
216 uint32_t transform;
217 sp<Fence> fence;
218 uint32_t stickyTransform;
219 bool getTimestamps;
220 int slot;
221 }; // struct QueueBufferInputBuilder
222
dequeueBuffer(uint32_t w,uint32_t h,uint32_t format,uint32_t usage,IGraphicBufferProducer::DequeueBufferOutput * result)223 status_t dequeueBuffer(uint32_t w, uint32_t h, uint32_t format, uint32_t usage,
224 IGraphicBufferProducer::DequeueBufferOutput* result) {
225 result->result =
226 mProducer->dequeueBuffer(&result->slot, &result->fence, w, h, format, usage,
227 &result->bufferAge, nullptr);
228 return result->result;
229 }
230
setupDequeueRequestBuffer(int * slot,sp<Fence> * fence,sp<GraphicBuffer> * buffer)231 void setupDequeueRequestBuffer(int *slot, sp<Fence> *fence,
232 sp<GraphicBuffer> *buffer)
233 {
234 ASSERT_TRUE(slot != nullptr);
235 ASSERT_TRUE(fence != nullptr);
236 ASSERT_TRUE(buffer != nullptr);
237
238 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
239
240
241 ASSERT_EQ(OK,
242 ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
243 (mProducer->dequeueBuffer(slot, fence, DEFAULT_WIDTH, DEFAULT_HEIGHT,
244 DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS,
245 nullptr, nullptr)));
246
247 EXPECT_LE(0, *slot);
248 EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, *slot);
249
250 // Request the buffer (pre-requisite for queueing)
251 ASSERT_OK(mProducer->requestBuffer(*slot, buffer));
252 }
253
254 private: // hide from test body
255 sp<MockConsumer> mMC;
256
257 protected: // accessible from test body
258 sp<IGraphicBufferProducer> mProducer;
259 sp<IGraphicBufferConsumer> mConsumer;
260 };
261
TEST_P(IGraphicBufferProducerTest,ConnectFirst_ReturnsError)262 TEST_P(IGraphicBufferProducerTest, ConnectFirst_ReturnsError) {
263 IGraphicBufferProducer::QueueBufferOutput output;
264
265 // NULL output returns BAD_VALUE
266 EXPECT_EQ(BAD_VALUE, mProducer->connect(TEST_TOKEN,
267 TEST_API,
268 TEST_CONTROLLED_BY_APP,
269 /*output*/nullptr));
270
271 // Invalid API returns bad value
272 EXPECT_EQ(BAD_VALUE, mProducer->connect(TEST_TOKEN,
273 /*api*/0xDEADBEEF,
274 TEST_CONTROLLED_BY_APP,
275 &output));
276
277 // TODO: get a token from a dead process somehow
278 }
279
TEST_P(IGraphicBufferProducerTest,ConnectAgain_ReturnsError)280 TEST_P(IGraphicBufferProducerTest, ConnectAgain_ReturnsError) {
281 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
282
283 // Can't connect when there is already a producer connected
284 IGraphicBufferProducer::QueueBufferOutput output;
285 EXPECT_EQ(BAD_VALUE, mProducer->connect(TEST_TOKEN,
286 TEST_API,
287 TEST_CONTROLLED_BY_APP,
288 &output));
289
290 ASSERT_OK(mConsumer->consumerDisconnect());
291 // Can't connect when IGBP is abandoned
292 if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
293 // TODO(b/73267953): Make BufferHub honor producer and consumer connection.
294 EXPECT_EQ(NO_INIT, mProducer->connect(TEST_TOKEN,
295 TEST_API,
296 TEST_CONTROLLED_BY_APP,
297 &output));
298 }
299 }
300
TEST_P(IGraphicBufferProducerTest,Disconnect_Succeeds)301 TEST_P(IGraphicBufferProducerTest, Disconnect_Succeeds) {
302 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
303
304 ASSERT_OK(mProducer->disconnect(TEST_API));
305 }
306
307
TEST_P(IGraphicBufferProducerTest,Disconnect_ReturnsError)308 TEST_P(IGraphicBufferProducerTest, Disconnect_ReturnsError) {
309 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
310
311 // Must disconnect with same API number
312 ASSERT_EQ(BAD_VALUE, mProducer->disconnect(TEST_API_OTHER));
313 // API must not be out of range
314 ASSERT_EQ(BAD_VALUE, mProducer->disconnect(/*api*/0xDEADBEEF));
315
316 // TODO: somehow kill mProducer so that this returns DEAD_OBJECT
317 }
318
TEST_P(IGraphicBufferProducerTest,Query_Succeeds)319 TEST_P(IGraphicBufferProducerTest, Query_Succeeds) {
320 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
321
322 int32_t value = -1;
323 EXPECT_OK(mProducer->query(NATIVE_WINDOW_WIDTH, &value));
324 EXPECT_EQ(DEFAULT_WIDTH, static_cast<uint32_t>(value));
325
326 EXPECT_OK(mProducer->query(NATIVE_WINDOW_HEIGHT, &value));
327 EXPECT_EQ(DEFAULT_HEIGHT, static_cast<uint32_t>(value));
328
329 EXPECT_OK(mProducer->query(NATIVE_WINDOW_FORMAT, &value));
330 EXPECT_EQ(DEFAULT_FORMAT, value);
331
332 EXPECT_OK(mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &value));
333 EXPECT_LE(0, value);
334 EXPECT_GE(BufferQueue::NUM_BUFFER_SLOTS, value);
335
336 EXPECT_OK(mProducer->query(NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &value));
337 EXPECT_FALSE(value); // Can't run behind when we haven't touched the queue
338
339 EXPECT_OK(mProducer->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &value));
340 EXPECT_EQ(DEFAULT_CONSUMER_USAGE_BITS, value);
341
342 { // Test the batched version
343 std::vector<int32_t> inputs = {
344 NATIVE_WINDOW_WIDTH,
345 NATIVE_WINDOW_HEIGHT,
346 NATIVE_WINDOW_FORMAT,
347 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
348 NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND,
349 NATIVE_WINDOW_CONSUMER_USAGE_BITS };
350 using QueryOutput = IGraphicBufferProducer::QueryOutput;
351 std::vector<QueryOutput> outputs;
352 EXPECT_OK(mProducer->query(inputs, &outputs));
353 EXPECT_EQ(DEFAULT_WIDTH, static_cast<uint32_t>(outputs[0].value));
354 EXPECT_EQ(DEFAULT_HEIGHT, static_cast<uint32_t>(outputs[1].value));
355 EXPECT_EQ(DEFAULT_FORMAT, outputs[2].value);
356 EXPECT_LE(0, outputs[3].value);
357 EXPECT_FALSE(outputs[4].value);
358 EXPECT_EQ(DEFAULT_CONSUMER_USAGE_BITS, outputs[5].value);
359 for (const QueryOutput& output : outputs) {
360 EXPECT_OK(output.result);
361 }
362 }
363 }
364
TEST_P(IGraphicBufferProducerTest,Query_ReturnsError)365 TEST_P(IGraphicBufferProducerTest, Query_ReturnsError) {
366 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
367
368 // One past the end of the last 'query' enum value. Update this if we add more enums.
369 const int NATIVE_WINDOW_QUERY_LAST_OFF_BY_ONE = NATIVE_WINDOW_BUFFER_AGE + 1;
370
371 int value;
372 // What was out of range
373 EXPECT_EQ(BAD_VALUE, mProducer->query(/*what*/-1, &value));
374 EXPECT_EQ(BAD_VALUE, mProducer->query(/*what*/0xDEADBEEF, &value));
375 EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_QUERY_LAST_OFF_BY_ONE, &value));
376
377 // Some enums from window.h are 'invalid'
378 EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER, &value));
379 EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_CONCRETE_TYPE, &value));
380 EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_DEFAULT_WIDTH, &value));
381 EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_DEFAULT_HEIGHT, &value));
382 EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_TRANSFORM_HINT, &value));
383 // TODO: Consider documented the above enums as unsupported or make a new enum for IGBP
384
385 { // Test the batched version
386 std::vector<int32_t> inputs = {
387 -1,
388 static_cast<int32_t>(0xDEADBEEF),
389 NATIVE_WINDOW_QUERY_LAST_OFF_BY_ONE,
390 NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER,
391 NATIVE_WINDOW_CONCRETE_TYPE,
392 NATIVE_WINDOW_DEFAULT_WIDTH,
393 NATIVE_WINDOW_DEFAULT_HEIGHT,
394 NATIVE_WINDOW_TRANSFORM_HINT};
395 using QueryOutput = IGraphicBufferProducer::QueryOutput;
396 std::vector<QueryOutput> outputs;
397 EXPECT_OK(mProducer->query(inputs, &outputs));
398 for (const QueryOutput& output : outputs) {
399 EXPECT_EQ(BAD_VALUE, output.result);
400 }
401 }
402
403 // Value was NULL
404 EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_FORMAT, /*value*/nullptr));
405
406 ASSERT_OK(mConsumer->consumerDisconnect());
407
408 // BQ was abandoned
409 if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
410 // TODO(b/73267953): Make BufferHub honor producer and consumer connection.
411 EXPECT_EQ(NO_INIT, mProducer->query(NATIVE_WINDOW_FORMAT, &value));
412 }
413
414 // TODO: other things in window.h that are supported by Surface::query
415 // but not by BufferQueue::query
416 }
417
418 // TODO: queue under more complicated situations not involving just a single buffer
TEST_P(IGraphicBufferProducerTest,Queue_Succeeds)419 TEST_P(IGraphicBufferProducerTest, Queue_Succeeds) {
420 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
421
422 int dequeuedSlot = -1;
423 sp<Fence> dequeuedFence;
424
425 ASSERT_EQ(OK,
426 ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
427 (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence, DEFAULT_WIDTH,
428 DEFAULT_HEIGHT, DEFAULT_FORMAT,
429 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr)));
430
431 EXPECT_LE(0, dequeuedSlot);
432 EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, dequeuedSlot);
433
434 // Request the buffer (pre-requisite for queueing)
435 sp<GraphicBuffer> dequeuedBuffer;
436 ASSERT_OK(mProducer->requestBuffer(dequeuedSlot, &dequeuedBuffer));
437
438 // A generic "valid" input
439 IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
440 IGraphicBufferProducer::QueueBufferOutput output;
441
442 // Queue the buffer back into the BQ
443 ASSERT_OK(mProducer->queueBuffer(dequeuedSlot, input, &output));
444
445 {
446 EXPECT_EQ(DEFAULT_WIDTH, output.width);
447 EXPECT_EQ(DEFAULT_HEIGHT, output.height);
448 EXPECT_EQ(DEFAULT_TRANSFORM_HINT, output.transformHint);
449
450 // Since queueBuffer was called exactly once
451 if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
452 // TODO(b/70041889): BufferHubProducer need to support metadata: numPendingBuffers
453 EXPECT_EQ(1u, output.numPendingBuffers);
454 // TODO(b/70041952): BufferHubProducer need to support metadata: nextFrameNumber
455 EXPECT_EQ(2u, output.nextFrameNumber);
456 }
457 }
458
459 // Buffer was not in the dequeued state
460 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output));
461
462 { // Test batched methods
463 constexpr size_t BATCH_SIZE = 4;
464
465 ASSERT_OK(mProducer->setMaxDequeuedBufferCount(BATCH_SIZE));
466 // Dequeue
467 using DequeueBufferInput = IGraphicBufferProducer::DequeueBufferInput;
468 using DequeueBufferOutput = IGraphicBufferProducer::DequeueBufferOutput;
469 DequeueBufferInput dequeueInput;
470 dequeueInput.width = DEFAULT_WIDTH;
471 dequeueInput.height = DEFAULT_HEIGHT;
472 dequeueInput.format = DEFAULT_FORMAT;
473 dequeueInput.usage = TEST_PRODUCER_USAGE_BITS;
474 dequeueInput.getTimestamps = false;
475 std::vector<DequeueBufferInput> dequeueInputs(BATCH_SIZE, dequeueInput);
476 std::vector<DequeueBufferOutput> dequeueOutputs;
477 EXPECT_OK(mProducer->dequeueBuffers(dequeueInputs, &dequeueOutputs));
478 ASSERT_EQ(dequeueInputs.size(), dequeueOutputs.size());
479
480 // Request
481 std::vector<int32_t> requestInputs;
482 requestInputs.reserve(BATCH_SIZE);
483 for (const DequeueBufferOutput& dequeueOutput : dequeueOutputs) {
484 ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
485 dequeueOutput.result);
486 requestInputs.emplace_back(dequeueOutput.slot);
487 }
488 using RequestBufferOutput = IGraphicBufferProducer::RequestBufferOutput;
489 std::vector<RequestBufferOutput> requestOutputs;
490 EXPECT_OK(mProducer->requestBuffers(requestInputs, &requestOutputs));
491 ASSERT_EQ(requestInputs.size(), requestOutputs.size());
492 for (const RequestBufferOutput& requestOutput : requestOutputs) {
493 EXPECT_OK(requestOutput.result);
494 }
495
496 // Queue
497 using QueueBufferInput = IGraphicBufferProducer::QueueBufferInput;
498 using QueueBufferOutput = IGraphicBufferProducer::QueueBufferOutput;
499 std::vector<QueueBufferInput> queueInputs;
500 queueInputs.reserve(BATCH_SIZE);
501 for (const DequeueBufferOutput& dequeueOutput : dequeueOutputs) {
502 queueInputs.emplace_back(CreateBufferInput()).slot =
503 dequeueOutput.slot;
504 }
505 std::vector<QueueBufferOutput> queueOutputs;
506 EXPECT_OK(mProducer->queueBuffers(queueInputs, &queueOutputs));
507 ASSERT_EQ(queueInputs.size(), queueOutputs.size());
508 for (const QueueBufferOutput& queueOutput : queueOutputs) {
509 EXPECT_OK(queueOutput.result);
510 }
511
512 // Re-queue
513 EXPECT_OK(mProducer->queueBuffers(queueInputs, &queueOutputs));
514 ASSERT_EQ(queueInputs.size(), queueOutputs.size());
515 for (const QueueBufferOutput& queueOutput : queueOutputs) {
516 EXPECT_EQ(BAD_VALUE, queueOutput.result);
517 }
518 }
519 }
520
TEST_P(IGraphicBufferProducerTest,Queue_ReturnsError)521 TEST_P(IGraphicBufferProducerTest, Queue_ReturnsError) {
522 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
523
524 using QueueBufferInput = IGraphicBufferProducer::QueueBufferInput;
525 using QueueBufferOutput = IGraphicBufferProducer::QueueBufferOutput;
526 // Invalid slot number
527 {
528 // A generic "valid" input
529 QueueBufferInput input = CreateBufferInput();
530 QueueBufferOutput output;
531
532 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(/*slot*/-1, input, &output));
533 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(/*slot*/0xDEADBEEF, input, &output));
534 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(BufferQueue::NUM_BUFFER_SLOTS,
535 input, &output));
536
537 { // Test with the batched version
538 constexpr size_t BATCH_SIZE = 16;
539 input.slot = -1;
540 std::vector<QueueBufferInput> inputs(BATCH_SIZE, input);
541 std::vector<QueueBufferOutput> outputs;
542 EXPECT_OK(mProducer->queueBuffers(inputs, &outputs));
543 ASSERT_EQ(inputs.size(), outputs.size());
544 for (const QueueBufferOutput& output : outputs) {
545 EXPECT_EQ(BAD_VALUE, output.result);
546 }
547 }
548 }
549
550 // Slot was not in the dequeued state (all slots start out in Free state)
551 {
552 QueueBufferInput input = CreateBufferInput();
553 QueueBufferOutput output;
554
555 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(/*slot*/0, input, &output));
556
557 { // Test with the batched version
558 constexpr size_t BATCH_SIZE = 16;
559 input.slot = 0;
560 std::vector<QueueBufferInput> inputs(BATCH_SIZE, input);
561 std::vector<QueueBufferOutput> outputs;
562 EXPECT_OK(mProducer->queueBuffers(inputs, &outputs));
563 ASSERT_EQ(inputs.size(), outputs.size());
564 for (const QueueBufferOutput& output : outputs) {
565 EXPECT_EQ(BAD_VALUE, output.result);
566 }
567 }
568 }
569
570 // Put the slot into the "dequeued" state for the rest of the test
571 int dequeuedSlot = -1;
572 sp<Fence> dequeuedFence;
573
574 ASSERT_EQ(OK,
575 ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
576 (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence, DEFAULT_WIDTH,
577 DEFAULT_HEIGHT, DEFAULT_FORMAT,
578 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr)));
579
580 // Slot was enqueued without requesting a buffer
581 {
582 QueueBufferInput input = CreateBufferInput();
583 QueueBufferOutput output;
584
585 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output));
586
587 { // Test with the batched version
588 constexpr size_t BATCH_SIZE = 16;
589 input.slot = dequeuedSlot;
590 std::vector<QueueBufferInput> inputs(BATCH_SIZE, input);
591 std::vector<QueueBufferOutput> outputs;
592 EXPECT_OK(mProducer->queueBuffers(inputs, &outputs));
593 ASSERT_EQ(inputs.size(), outputs.size());
594 for (const QueueBufferOutput& output : outputs) {
595 EXPECT_EQ(BAD_VALUE, output.result);
596 }
597 }
598 }
599
600 // Request the buffer so that the rest of the tests don't fail on earlier checks.
601 sp<GraphicBuffer> dequeuedBuffer;
602 ASSERT_OK(mProducer->requestBuffer(dequeuedSlot, &dequeuedBuffer));
603
604 // Fence was NULL
605 {
606 sp<Fence> nullFence = nullptr;
607
608 QueueBufferInput input =
609 QueueBufferInputBuilder().setFence(nullFence).build();
610 QueueBufferOutput output;
611
612 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output));
613
614 { // Test with the batched version
615 constexpr size_t BATCH_SIZE = 16;
616 input.slot = dequeuedSlot;
617 std::vector<QueueBufferInput> inputs(BATCH_SIZE, input);
618 std::vector<QueueBufferOutput> outputs;
619 EXPECT_OK(mProducer->queueBuffers(inputs, &outputs));
620 ASSERT_EQ(inputs.size(), outputs.size());
621 for (const QueueBufferOutput& output : outputs) {
622 EXPECT_EQ(BAD_VALUE, output.result);
623 }
624 }
625 }
626
627 // Scaling mode was unknown
628 {
629 IGraphicBufferProducer::QueueBufferInput input =
630 QueueBufferInputBuilder().setScalingMode(-1).build();
631 IGraphicBufferProducer::QueueBufferOutput output;
632
633 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output));
634
635 { // Test with the batched version
636 constexpr size_t BATCH_SIZE = 16;
637 input.slot = dequeuedSlot;
638 std::vector<QueueBufferInput> inputs(BATCH_SIZE, input);
639 std::vector<QueueBufferOutput> outputs;
640 EXPECT_OK(mProducer->queueBuffers(inputs, &outputs));
641 ASSERT_EQ(inputs.size(), outputs.size());
642 for (const QueueBufferOutput& output : outputs) {
643 EXPECT_EQ(BAD_VALUE, output.result);
644 }
645 }
646
647 input = QueueBufferInputBuilder().setScalingMode(0xDEADBEEF).build();
648
649 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output));
650
651 { // Test with the batched version
652 constexpr size_t BATCH_SIZE = 16;
653 input.slot = dequeuedSlot;
654 std::vector<QueueBufferInput> inputs(BATCH_SIZE, input);
655 std::vector<QueueBufferOutput> outputs;
656 EXPECT_OK(mProducer->queueBuffers(inputs, &outputs));
657 ASSERT_EQ(inputs.size(), outputs.size());
658 for (const QueueBufferOutput& output : outputs) {
659 EXPECT_EQ(BAD_VALUE, output.result);
660 }
661 }
662 }
663
664 // Crop rect is out of bounds of the buffer dimensions
665 {
666 IGraphicBufferProducer::QueueBufferInput input =
667 QueueBufferInputBuilder().setCrop(Rect(DEFAULT_WIDTH + 1, DEFAULT_HEIGHT + 1))
668 .build();
669 IGraphicBufferProducer::QueueBufferOutput output;
670
671 EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output));
672
673 { // Test with the batched version
674 constexpr size_t BATCH_SIZE = 16;
675 input.slot = dequeuedSlot;
676 std::vector<QueueBufferInput> inputs(BATCH_SIZE, input);
677 std::vector<QueueBufferOutput> outputs;
678 EXPECT_OK(mProducer->queueBuffers(inputs, &outputs));
679 ASSERT_EQ(inputs.size(), outputs.size());
680 for (const QueueBufferOutput& output : outputs) {
681 EXPECT_EQ(BAD_VALUE, output.result);
682 }
683 }
684 }
685
686 // Abandon the buffer queue so that the last test fails
687 ASSERT_OK(mConsumer->consumerDisconnect());
688
689 // The buffer queue has been abandoned.
690 if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
691 IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
692 IGraphicBufferProducer::QueueBufferOutput output;
693
694 // TODO(b/73267953): Make BufferHub honor producer and consumer connection.
695 EXPECT_EQ(NO_INIT, mProducer->queueBuffer(dequeuedSlot, input, &output));
696
697 { // Test with the batched version
698 constexpr size_t BATCH_SIZE = 16;
699 input.slot = dequeuedSlot;
700 std::vector<QueueBufferInput> inputs(BATCH_SIZE, input);
701 std::vector<QueueBufferOutput> outputs;
702 EXPECT_OK(mProducer->queueBuffers(inputs, &outputs));
703 ASSERT_EQ(inputs.size(), outputs.size());
704 for (const QueueBufferOutput& output : outputs) {
705 EXPECT_EQ(NO_INIT, output.result);
706 }
707 }
708 }
709 }
710
TEST_P(IGraphicBufferProducerTest,CancelBuffer_DoesntCrash)711 TEST_P(IGraphicBufferProducerTest, CancelBuffer_DoesntCrash) {
712 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
713
714 int dequeuedSlot = -1;
715 sp<Fence> dequeuedFence;
716
717 ASSERT_EQ(OK,
718 ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
719 (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence, DEFAULT_WIDTH,
720 DEFAULT_HEIGHT, DEFAULT_FORMAT,
721 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr)));
722
723 // No return code, but at least test that it doesn't blow up...
724 // TODO: add a return code
725 mProducer->cancelBuffer(dequeuedSlot, dequeuedFence);
726
727 { // Test batched methods
728 constexpr size_t BATCH_SIZE = 4;
729 ASSERT_OK(mProducer->setMaxDequeuedBufferCount(BATCH_SIZE));
730
731 // Dequeue
732 using DequeueBufferInput = IGraphicBufferProducer::DequeueBufferInput;
733 using DequeueBufferOutput = IGraphicBufferProducer::DequeueBufferOutput;
734 DequeueBufferInput dequeueInput;
735 dequeueInput.width = DEFAULT_WIDTH;
736 dequeueInput.height = DEFAULT_HEIGHT;
737 dequeueInput.format = DEFAULT_FORMAT;
738 dequeueInput.usage = TEST_PRODUCER_USAGE_BITS;
739 dequeueInput.getTimestamps = false;
740 std::vector<DequeueBufferInput> dequeueInputs(BATCH_SIZE, dequeueInput);
741 std::vector<DequeueBufferOutput> dequeueOutputs;
742 EXPECT_OK(mProducer->dequeueBuffers(dequeueInputs, &dequeueOutputs));
743 ASSERT_EQ(dequeueInputs.size(), dequeueOutputs.size());
744
745 // Cancel
746 using CancelBufferInput = IGraphicBufferProducer::CancelBufferInput;
747 std::vector<CancelBufferInput> cancelInputs;
748 cancelInputs.reserve(BATCH_SIZE);
749 for (const DequeueBufferOutput& dequeueOutput : dequeueOutputs) {
750 ASSERT_EQ(OK,
751 ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
752 dequeueOutput.result);
753 CancelBufferInput& cancelInput = cancelInputs.emplace_back();
754 cancelInput.slot = dequeueOutput.slot;
755 cancelInput.fence = dequeueOutput.fence;
756 }
757 std::vector<status_t> cancelOutputs;
758 EXPECT_OK(mProducer->cancelBuffers(cancelInputs, &cancelOutputs));
759 ASSERT_EQ(cancelInputs.size(), cancelOutputs.size());
760 for (status_t result : cancelOutputs) {
761 EXPECT_OK(result);
762 }
763 }
764 }
765
TEST_P(IGraphicBufferProducerTest,SetMaxDequeuedBufferCount_Succeeds)766 TEST_P(IGraphicBufferProducerTest, SetMaxDequeuedBufferCount_Succeeds) {
767 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
768 int minUndequeuedBuffers;
769 ASSERT_OK(mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
770 &minUndequeuedBuffers));
771
772 const int minBuffers = 1;
773 const int maxBuffers = BufferQueue::NUM_BUFFER_SLOTS - minUndequeuedBuffers;
774
775 ASSERT_OK(mProducer->setAsyncMode(false)) << "async mode: " << false;
776 ASSERT_OK(mProducer->setMaxDequeuedBufferCount(minBuffers))
777 << "bufferCount: " << minBuffers;
778
779 // Should now be able to dequeue up to minBuffers times
780 IGraphicBufferProducer::DequeueBufferOutput result;
781 for (int i = 0; i < minBuffers; ++i) {
782 EXPECT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
783 (dequeueBuffer(DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
784 TEST_PRODUCER_USAGE_BITS, &result)))
785 << "iteration: " << i << ", slot: " << result.slot;
786 }
787
788 ASSERT_OK(mProducer->setMaxDequeuedBufferCount(maxBuffers));
789
790 // queue the first buffer to enable max dequeued buffer count checking
791 IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
792 IGraphicBufferProducer::QueueBufferOutput output;
793 sp<GraphicBuffer> buffer;
794 ASSERT_OK(mProducer->requestBuffer(result.slot, &buffer));
795 ASSERT_OK(mProducer->queueBuffer(result.slot, input, &output));
796
797 // Should now be able to dequeue up to maxBuffers times
798 int dequeuedSlot = -1;
799 sp<Fence> dequeuedFence;
800 for (int i = 0; i < maxBuffers; ++i) {
801 EXPECT_EQ(OK,
802 ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
803 (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence, DEFAULT_WIDTH,
804 DEFAULT_HEIGHT, DEFAULT_FORMAT,
805 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr)))
806 << "iteration: " << i << ", slot: " << dequeuedSlot;
807 }
808
809 // Cancel a buffer, so we can decrease the buffer count
810 ASSERT_OK(mProducer->cancelBuffer(dequeuedSlot, dequeuedFence));
811
812 // Should now be able to decrease the max dequeued count by 1
813 ASSERT_OK(mProducer->setMaxDequeuedBufferCount(maxBuffers-1));
814 }
815
TEST_P(IGraphicBufferProducerTest,SetMaxDequeuedBufferCount_Fails)816 TEST_P(IGraphicBufferProducerTest, SetMaxDequeuedBufferCount_Fails) {
817 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
818 int minUndequeuedBuffers;
819 ASSERT_OK(mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
820 &minUndequeuedBuffers));
821
822 const int minBuffers = 1;
823 const int maxBuffers = BufferQueue::NUM_BUFFER_SLOTS - minUndequeuedBuffers;
824
825 ASSERT_OK(mProducer->setAsyncMode(false)) << "async mode: " << false;
826 // Buffer count was out of range
827 EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(0))
828 << "bufferCount: " << 0;
829 EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(maxBuffers + 1))
830 << "bufferCount: " << maxBuffers + 1;
831
832 // Set max dequeue count to 2
833 ASSERT_OK(mProducer->setMaxDequeuedBufferCount(2));
834 // Dequeue 2 buffers
835 int dequeuedSlot = -1;
836 sp<Fence> dequeuedFence;
837 for (int i = 0; i < 2; i++) {
838 ASSERT_EQ(OK,
839 ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
840 (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence, DEFAULT_WIDTH,
841 DEFAULT_HEIGHT, DEFAULT_FORMAT,
842 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr)))
843 << "slot: " << dequeuedSlot;
844 }
845
846 // Client has too many buffers dequeued
847 EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(1))
848 << "bufferCount: " << minBuffers;
849
850 // Abandon buffer queue
851 ASSERT_OK(mConsumer->consumerDisconnect());
852
853 // Fail because the buffer queue was abandoned
854 if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
855 // TODO(b/73267953): Make BufferHub honor producer and consumer connection.
856 EXPECT_EQ(NO_INIT, mProducer->setMaxDequeuedBufferCount(minBuffers))
857 << "bufferCount: " << minBuffers;
858 }
859 }
860
TEST_P(IGraphicBufferProducerTest,SetAsyncMode_Succeeds)861 TEST_P(IGraphicBufferProducerTest, SetAsyncMode_Succeeds) {
862 ASSERT_OK(mConsumer->setMaxAcquiredBufferCount(1)) << "maxAcquire: " << 1;
863 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
864 ASSERT_OK(mProducer->setAsyncMode(true)) << "async mode: " << true;
865 ASSERT_OK(mProducer->setMaxDequeuedBufferCount(1)) << "maxDequeue: " << 1;
866
867 int dequeuedSlot = -1;
868 sp<Fence> dequeuedFence;
869 IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
870 IGraphicBufferProducer::QueueBufferOutput output;
871 sp<GraphicBuffer> dequeuedBuffer;
872
873 // Should now be able to queue/dequeue as many buffers as we want without
874 // blocking
875 for (int i = 0; i < 5; ++i) {
876 ASSERT_EQ(OK,
877 ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
878 (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence, DEFAULT_WIDTH,
879 DEFAULT_HEIGHT, DEFAULT_FORMAT,
880 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr)))
881 << "slot : " << dequeuedSlot;
882 ASSERT_OK(mProducer->requestBuffer(dequeuedSlot, &dequeuedBuffer));
883 ASSERT_OK(mProducer->queueBuffer(dequeuedSlot, input, &output));
884 }
885 }
886
TEST_P(IGraphicBufferProducerTest,SetAsyncMode_Fails)887 TEST_P(IGraphicBufferProducerTest, SetAsyncMode_Fails) {
888 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
889 // Prerequisite to fail out a valid setBufferCount call
890 {
891 int dequeuedSlot = -1;
892 sp<Fence> dequeuedFence;
893
894 ASSERT_EQ(OK,
895 ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
896 (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence, DEFAULT_WIDTH,
897 DEFAULT_HEIGHT, DEFAULT_FORMAT,
898 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr)))
899 << "slot: " << dequeuedSlot;
900 }
901
902 // Abandon buffer queue
903 ASSERT_OK(mConsumer->consumerDisconnect());
904
905 // Fail because the buffer queue was abandoned
906 if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
907 // TODO(b/36724099): Make BufferHub honor producer and consumer connection.
908 EXPECT_EQ(NO_INIT, mProducer->setAsyncMode(false)) << "asyncMode: " << false;
909 }
910 }
911
TEST_P(IGraphicBufferProducerTest,DisconnectedProducerReturnsError_dequeueBuffer)912 TEST_P(IGraphicBufferProducerTest,
913 DisconnectedProducerReturnsError_dequeueBuffer) {
914 int slot = -1;
915 sp<Fence> fence;
916
917 ASSERT_EQ(NO_INIT,
918 mProducer->dequeueBuffer(&slot, &fence, DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
919 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr));
920 }
921
TEST_P(IGraphicBufferProducerTest,DisconnectedProducerReturnsError_detachNextBuffer)922 TEST_P(IGraphicBufferProducerTest,
923 DisconnectedProducerReturnsError_detachNextBuffer) {
924 sp<Fence> fence;
925 sp<GraphicBuffer> buffer;
926
927 ASSERT_EQ(NO_INIT, mProducer->detachNextBuffer(&buffer, &fence));
928 }
929
TEST_P(IGraphicBufferProducerTest,DisconnectedProducerReturnsError_requestBuffer)930 TEST_P(IGraphicBufferProducerTest,
931 DisconnectedProducerReturnsError_requestBuffer) {
932 ASSERT_NO_FATAL_FAILURE(ConnectProducer());
933
934 int slot = -1;
935 sp<Fence> fence;
936
937 ASSERT_EQ(OK,
938 ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
939 (mProducer->dequeueBuffer(&slot, &fence, DEFAULT_WIDTH, DEFAULT_HEIGHT,
940 DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS,
941 nullptr, nullptr)));
942
943 EXPECT_LE(0, slot);
944 EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, slot);
945
946 ASSERT_OK(mProducer->disconnect(TEST_API));
947
948 sp<GraphicBuffer> buffer;
949
950 ASSERT_EQ(NO_INIT, mProducer->requestBuffer(slot, &buffer));
951 }
952
953
TEST_P(IGraphicBufferProducerTest,DisconnectedProducerReturnsError_detachBuffer)954 TEST_P(IGraphicBufferProducerTest,
955 DisconnectedProducerReturnsError_detachBuffer) {
956 int slot = -1;
957 sp<Fence> fence;
958 sp<GraphicBuffer> buffer;
959
960 setupDequeueRequestBuffer(&slot, &fence, &buffer);
961
962 ASSERT_OK(mProducer->disconnect(TEST_API));
963
964 ASSERT_EQ(NO_INIT, mProducer->detachBuffer(slot));
965 }
966
TEST_P(IGraphicBufferProducerTest,DisconnectedProducerReturnsError_queueBuffer)967 TEST_P(IGraphicBufferProducerTest,
968 DisconnectedProducerReturnsError_queueBuffer) {
969 int slot = -1;
970 sp<Fence> fence;
971 sp<GraphicBuffer> buffer;
972
973 setupDequeueRequestBuffer(&slot, &fence, &buffer);
974
975 ASSERT_OK(mProducer->disconnect(TEST_API));
976
977 // A generic "valid" input
978 IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
979 IGraphicBufferProducer::QueueBufferOutput output;
980
981 ASSERT_EQ(NO_INIT, mProducer->queueBuffer(slot, input, &output));
982 }
983
TEST_P(IGraphicBufferProducerTest,DisconnectedProducerReturnsError_cancelBuffer)984 TEST_P(IGraphicBufferProducerTest,
985 DisconnectedProducerReturnsError_cancelBuffer) {
986 int slot = -1;
987 sp<Fence> fence;
988 sp<GraphicBuffer> buffer;
989
990 setupDequeueRequestBuffer(&slot, &fence, &buffer);
991
992 ASSERT_OK(mProducer->disconnect(TEST_API));
993
994 ASSERT_EQ(NO_INIT, mProducer->cancelBuffer(slot, fence));
995 }
996
TEST_P(IGraphicBufferProducerTest,DisconnectedProducerReturnsError_attachBuffer)997 TEST_P(IGraphicBufferProducerTest,
998 DisconnectedProducerReturnsError_attachBuffer) {
999 int slot = -1;
1000 sp<Fence> fence;
1001 sp<GraphicBuffer> buffer;
1002
1003 setupDequeueRequestBuffer(&slot, &fence, &buffer);
1004 ASSERT_TRUE(buffer != nullptr);
1005
1006 ASSERT_OK(mProducer->detachBuffer(slot));
1007 EXPECT_OK(buffer->initCheck());
1008
1009 ASSERT_OK(mProducer->disconnect(TEST_API));
1010
1011 ASSERT_EQ(NO_INIT, mProducer->attachBuffer(&slot, buffer));
1012 }
1013
TEST_P(IGraphicBufferProducerTest,DetachThenAttach_Succeeds)1014 TEST_P(IGraphicBufferProducerTest, DetachThenAttach_Succeeds) {
1015 int slot = -1;
1016 sp<Fence> fence;
1017 sp<GraphicBuffer> buffer;
1018
1019 setupDequeueRequestBuffer(&slot, &fence, &buffer);
1020 ASSERT_TRUE(buffer != nullptr);
1021
1022 ASSERT_OK(mProducer->detachBuffer(slot));
1023 EXPECT_OK(buffer->initCheck());
1024
1025 EXPECT_OK(mProducer->attachBuffer(&slot, buffer));
1026 EXPECT_OK(buffer->initCheck());
1027
1028 ASSERT_OK(mProducer->detachBuffer(slot));
1029
1030 { // Test batched methods
1031 constexpr size_t BATCH_SIZE = 4;
1032 ASSERT_OK(mProducer->setMaxDequeuedBufferCount(BATCH_SIZE));
1033
1034 // Dequeue
1035 using DequeueBufferInput = IGraphicBufferProducer::DequeueBufferInput;
1036 using DequeueBufferOutput = IGraphicBufferProducer::DequeueBufferOutput;
1037 DequeueBufferInput dequeueInput;
1038 dequeueInput.width = DEFAULT_WIDTH;
1039 dequeueInput.height = DEFAULT_HEIGHT;
1040 dequeueInput.format = DEFAULT_FORMAT;
1041 dequeueInput.usage = TEST_PRODUCER_USAGE_BITS;
1042 dequeueInput.getTimestamps = false;
1043 std::vector<DequeueBufferInput> dequeueInputs(BATCH_SIZE, dequeueInput);
1044 std::vector<DequeueBufferOutput> dequeueOutputs;
1045 EXPECT_OK(mProducer->dequeueBuffers(dequeueInputs, &dequeueOutputs));
1046 ASSERT_EQ(dequeueInputs.size(), dequeueOutputs.size());
1047
1048 // Request
1049 std::vector<int32_t> requestInputs;
1050 requestInputs.reserve(BATCH_SIZE);
1051 for (const DequeueBufferOutput& dequeueOutput : dequeueOutputs) {
1052 ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
1053 dequeueOutput.result);
1054 requestInputs.emplace_back(dequeueOutput.slot);
1055 }
1056 using RequestBufferOutput = IGraphicBufferProducer::RequestBufferOutput;
1057 std::vector<RequestBufferOutput> requestOutputs;
1058 EXPECT_OK(mProducer->requestBuffers(requestInputs, &requestOutputs));
1059 ASSERT_EQ(requestInputs.size(), requestOutputs.size());
1060 for (const RequestBufferOutput& requestOutput : requestOutputs) {
1061 EXPECT_OK(requestOutput.result);
1062 }
1063
1064 // Detach
1065 std::vector<int32_t> detachInputs;
1066 detachInputs.reserve(BATCH_SIZE);
1067 for (const DequeueBufferOutput& dequeueOutput : dequeueOutputs) {
1068 detachInputs.emplace_back(dequeueOutput.slot);
1069 }
1070 std::vector<status_t> detachOutputs;
1071 EXPECT_OK(mProducer->detachBuffers(detachInputs, &detachOutputs));
1072 ASSERT_EQ(detachInputs.size(), detachOutputs.size());
1073 for (status_t result : detachOutputs) {
1074 EXPECT_OK(result);
1075 }
1076
1077 // Attach
1078 using AttachBufferOutput = IGraphicBufferProducer::AttachBufferOutput;
1079 std::vector<sp<GraphicBuffer>> attachInputs;
1080 attachInputs.reserve(BATCH_SIZE);
1081 for (const RequestBufferOutput& requestOutput : requestOutputs) {
1082 attachInputs.emplace_back(requestOutput.buffer);
1083 }
1084 std::vector<AttachBufferOutput> attachOutputs;
1085 EXPECT_OK(mProducer->attachBuffers(attachInputs, &attachOutputs));
1086 ASSERT_EQ(attachInputs.size(), attachOutputs.size());
1087 for (const AttachBufferOutput& attachOutput : attachOutputs) {
1088 EXPECT_OK(attachOutput.result);
1089 EXPECT_NE(-1, attachOutput.slot);
1090 }
1091 }
1092 }
1093
1094 INSTANTIATE_TEST_CASE_P(IGraphicBufferProducerBackends, IGraphicBufferProducerTest,
1095 ::testing::Values(USE_BUFFER_QUEUE_PRODUCER));
1096
1097 } // namespace android
1098