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