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