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 <gtest/gtest.h>
21 
22 #include <utils/String8.h>
23 #include <utils/threads.h>
24 
25 #include <ui/GraphicBuffer.h>
26 
27 #include <gui/BufferQueue.h>
28 #include <gui/IProducerListener.h>
29 
30 #include <vector>
31 
32 #define ASSERT_OK(x) ASSERT_EQ(OK, (x))
33 #define EXPECT_OK(x) EXPECT_EQ(OK, (x))
34 
35 #define TEST_TOKEN ((IProducerListener*)(NULL))
36 #define TEST_API NATIVE_WINDOW_API_CPU
37 #define TEST_API_OTHER NATIVE_WINDOW_API_EGL // valid API that's not TEST_API
38 #define TEST_CONTROLLED_BY_APP false
39 #define TEST_PRODUCER_USAGE_BITS (0)
40 
41 namespace android {
42 
43 namespace {
44     // Default dimensions before setDefaultBufferSize is called
45     const uint32_t DEFAULT_WIDTH = 1;
46     const uint32_t DEFAULT_HEIGHT = 1;
47 
48     // Default format before setDefaultBufferFormat is called
49     const PixelFormat DEFAULT_FORMAT = HAL_PIXEL_FORMAT_RGBA_8888;
50 
51     // Default transform hint before setTransformHint is called
52     const uint32_t DEFAULT_TRANSFORM_HINT = 0;
53 
54     // TODO: Make these constants in header
55     const int DEFAULT_CONSUMER_USAGE_BITS = 0;
56 
57     // Parameters for a generic "valid" input for queueBuffer.
58     const int64_t QUEUE_BUFFER_INPUT_TIMESTAMP = 1384888611;
59     const bool QUEUE_BUFFER_INPUT_IS_AUTO_TIMESTAMP = false;
60     const android_dataspace QUEUE_BUFFER_INPUT_DATASPACE = HAL_DATASPACE_UNKNOWN;
61     const Rect QUEUE_BUFFER_INPUT_RECT = Rect(DEFAULT_WIDTH, DEFAULT_HEIGHT);
62     const int QUEUE_BUFFER_INPUT_SCALING_MODE = 0;
63     const int QUEUE_BUFFER_INPUT_TRANSFORM = 0;
64     const bool QUEUE_BUFFER_INPUT_ASYNC = false;
65     const sp<Fence> QUEUE_BUFFER_INPUT_FENCE = Fence::NO_FENCE;
66 }; // namespace anonymous
67 
68 struct DummyConsumer : public BnConsumerListener {
onFrameAvailableandroid::DummyConsumer69     virtual void onFrameAvailable(const BufferItem& /* item */) {}
onBuffersReleasedandroid::DummyConsumer70     virtual void onBuffersReleased() {}
onSidebandStreamChangedandroid::DummyConsumer71     virtual void onSidebandStreamChanged() {}
72 };
73 
74 class IGraphicBufferProducerTest : public ::testing::Test {
75 protected:
76 
IGraphicBufferProducerTest()77     IGraphicBufferProducerTest() {}
78 
SetUp()79     virtual void SetUp() {
80         const ::testing::TestInfo* const testInfo =
81             ::testing::UnitTest::GetInstance()->current_test_info();
82         ALOGV("Begin test: %s.%s", testInfo->test_case_name(),
83                 testInfo->name());
84 
85         mDC = new DummyConsumer;
86 
87         BufferQueue::createBufferQueue(&mProducer, &mConsumer);
88 
89         // Test check: Can't connect producer if no consumer yet
90         ASSERT_EQ(NO_INIT, TryConnectProducer());
91 
92         // Must connect consumer before producer connects will succeed.
93         ASSERT_OK(mConsumer->consumerConnect(mDC, /*controlledByApp*/false));
94     }
95 
TearDown()96     virtual void TearDown() {
97         const ::testing::TestInfo* const testInfo =
98             ::testing::UnitTest::GetInstance()->current_test_info();
99         ALOGV("End test:   %s.%s", testInfo->test_case_name(),
100                 testInfo->name());
101     }
102 
TryConnectProducer()103     status_t TryConnectProducer() {
104         IGraphicBufferProducer::QueueBufferOutput output;
105         return mProducer->connect(TEST_TOKEN,
106                                   TEST_API,
107                                   TEST_CONTROLLED_BY_APP,
108                                   &output);
109         // TODO: use params to vary token, api, producercontrolledbyapp, etc
110     }
111 
112     // Connect to a producer in a 'correct' fashion.
113     //   Precondition: Consumer is connected.
ConnectProducer()114     void ConnectProducer() {
115         ASSERT_OK(TryConnectProducer());
116     }
117 
118     // Create a generic "valid" input for queueBuffer
119     // -- uses the default buffer format, width, etc.
CreateBufferInput()120     static IGraphicBufferProducer::QueueBufferInput CreateBufferInput() {
121         return QueueBufferInputBuilder().build();
122     }
123 
124     // Builder pattern to slightly vary *almost* correct input
125     // -- avoids copying and pasting
126     struct QueueBufferInputBuilder {
QueueBufferInputBuilderandroid::IGraphicBufferProducerTest::QueueBufferInputBuilder127         QueueBufferInputBuilder() {
128            timestamp = QUEUE_BUFFER_INPUT_TIMESTAMP;
129            isAutoTimestamp = QUEUE_BUFFER_INPUT_IS_AUTO_TIMESTAMP;
130            dataSpace = QUEUE_BUFFER_INPUT_DATASPACE;
131            crop = QUEUE_BUFFER_INPUT_RECT;
132            scalingMode = QUEUE_BUFFER_INPUT_SCALING_MODE;
133            transform = QUEUE_BUFFER_INPUT_TRANSFORM;
134            async = QUEUE_BUFFER_INPUT_ASYNC;
135            fence = QUEUE_BUFFER_INPUT_FENCE;
136         }
137 
buildandroid::IGraphicBufferProducerTest::QueueBufferInputBuilder138         IGraphicBufferProducer::QueueBufferInput build() {
139             return IGraphicBufferProducer::QueueBufferInput(
140                     timestamp,
141                     isAutoTimestamp,
142                     dataSpace,
143                     crop,
144                     scalingMode,
145                     transform,
146                     async,
147                     fence);
148         }
149 
setTimestampandroid::IGraphicBufferProducerTest::QueueBufferInputBuilder150         QueueBufferInputBuilder& setTimestamp(int64_t timestamp) {
151             this->timestamp = timestamp;
152             return *this;
153         }
154 
setIsAutoTimestampandroid::IGraphicBufferProducerTest::QueueBufferInputBuilder155         QueueBufferInputBuilder& setIsAutoTimestamp(bool isAutoTimestamp) {
156             this->isAutoTimestamp = isAutoTimestamp;
157             return *this;
158         }
159 
setDataSpaceandroid::IGraphicBufferProducerTest::QueueBufferInputBuilder160         QueueBufferInputBuilder& setDataSpace(android_dataspace dataSpace) {
161             this->dataSpace = dataSpace;
162             return *this;
163         }
164 
setCropandroid::IGraphicBufferProducerTest::QueueBufferInputBuilder165         QueueBufferInputBuilder& setCrop(Rect crop) {
166             this->crop = crop;
167             return *this;
168         }
169 
setScalingModeandroid::IGraphicBufferProducerTest::QueueBufferInputBuilder170         QueueBufferInputBuilder& setScalingMode(int scalingMode) {
171             this->scalingMode = scalingMode;
172             return *this;
173         }
174 
setTransformandroid::IGraphicBufferProducerTest::QueueBufferInputBuilder175         QueueBufferInputBuilder& setTransform(uint32_t transform) {
176             this->transform = transform;
177             return *this;
178         }
179 
setAsyncandroid::IGraphicBufferProducerTest::QueueBufferInputBuilder180         QueueBufferInputBuilder& setAsync(bool async) {
181             this->async = async;
182             return *this;
183         }
184 
setFenceandroid::IGraphicBufferProducerTest::QueueBufferInputBuilder185         QueueBufferInputBuilder& setFence(sp<Fence> fence) {
186             this->fence = fence;
187             return *this;
188         }
189 
190     private:
191         int64_t timestamp;
192         bool isAutoTimestamp;
193         android_dataspace dataSpace;
194         Rect crop;
195         int scalingMode;
196         uint32_t transform;
197         int async;
198         sp<Fence> fence;
199     }; // struct QueueBufferInputBuilder
200 
201     // To easily store dequeueBuffer results into containers
202     struct DequeueBufferResult {
203         int slot;
204         sp<Fence> fence;
205     };
206 
dequeueBuffer(bool async,uint32_t w,uint32_t h,uint32_t format,uint32_t usage,DequeueBufferResult * result)207     status_t dequeueBuffer(bool async, uint32_t w, uint32_t h, uint32_t format, uint32_t usage, DequeueBufferResult* result) {
208         return mProducer->dequeueBuffer(&result->slot, &result->fence, async, w, h, format, usage);
209     }
210 
211 private: // hide from test body
212     sp<DummyConsumer> mDC;
213 
214 protected: // accessible from test body
215     sp<IGraphicBufferProducer> mProducer;
216     sp<IGraphicBufferConsumer> mConsumer;
217 };
218 
TEST_F(IGraphicBufferProducerTest,ConnectFirst_ReturnsError)219 TEST_F(IGraphicBufferProducerTest, ConnectFirst_ReturnsError) {
220     IGraphicBufferProducer::QueueBufferOutput output;
221 
222     // NULL output returns BAD_VALUE
223     EXPECT_EQ(BAD_VALUE, mProducer->connect(TEST_TOKEN,
224                                             TEST_API,
225                                             TEST_CONTROLLED_BY_APP,
226                                             /*output*/NULL));
227 
228     // Invalid API returns bad value
229     EXPECT_EQ(BAD_VALUE, mProducer->connect(TEST_TOKEN,
230                                             /*api*/0xDEADBEEF,
231                                             TEST_CONTROLLED_BY_APP,
232                                             &output));
233 
234     // TODO: get a token from a dead process somehow
235 }
236 
TEST_F(IGraphicBufferProducerTest,ConnectAgain_ReturnsError)237 TEST_F(IGraphicBufferProducerTest, ConnectAgain_ReturnsError) {
238     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
239 
240     // Can't connect when there is already a producer connected
241     IGraphicBufferProducer::QueueBufferOutput output;
242     EXPECT_EQ(BAD_VALUE, mProducer->connect(TEST_TOKEN,
243                                             TEST_API,
244                                             TEST_CONTROLLED_BY_APP,
245                                             &output));
246 
247     ASSERT_OK(mConsumer->consumerDisconnect());
248     // Can't connect when IGBP is abandoned
249     EXPECT_EQ(NO_INIT, mProducer->connect(TEST_TOKEN,
250                                           TEST_API,
251                                           TEST_CONTROLLED_BY_APP,
252                                           &output));
253 }
254 
TEST_F(IGraphicBufferProducerTest,Disconnect_Succeeds)255 TEST_F(IGraphicBufferProducerTest, Disconnect_Succeeds) {
256     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
257 
258     ASSERT_OK(mProducer->disconnect(TEST_API));
259 }
260 
261 
TEST_F(IGraphicBufferProducerTest,Disconnect_ReturnsError)262 TEST_F(IGraphicBufferProducerTest, Disconnect_ReturnsError) {
263     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
264 
265     // Must disconnect with same API number
266     ASSERT_EQ(BAD_VALUE, mProducer->disconnect(TEST_API_OTHER));
267     // API must not be out of range
268     ASSERT_EQ(BAD_VALUE, mProducer->disconnect(/*api*/0xDEADBEEF));
269 
270     // TODO: somehow kill mProducer so that this returns DEAD_OBJECT
271 }
272 
TEST_F(IGraphicBufferProducerTest,Query_Succeeds)273 TEST_F(IGraphicBufferProducerTest, Query_Succeeds) {
274     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
275 
276     int32_t value = -1;
277     EXPECT_OK(mProducer->query(NATIVE_WINDOW_WIDTH, &value));
278     EXPECT_EQ(DEFAULT_WIDTH, static_cast<uint32_t>(value));
279 
280     EXPECT_OK(mProducer->query(NATIVE_WINDOW_HEIGHT, &value));
281     EXPECT_EQ(DEFAULT_HEIGHT, static_cast<uint32_t>(value));
282 
283     EXPECT_OK(mProducer->query(NATIVE_WINDOW_FORMAT, &value));
284     EXPECT_EQ(DEFAULT_FORMAT, value);
285 
286     EXPECT_OK(mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &value));
287     EXPECT_LE(0, value);
288     EXPECT_GE(BufferQueue::NUM_BUFFER_SLOTS, value);
289 
290     EXPECT_OK(mProducer->query(NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &value));
291     EXPECT_FALSE(value); // Can't run behind when we haven't touched the queue
292 
293     EXPECT_OK(mProducer->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &value));
294     EXPECT_EQ(DEFAULT_CONSUMER_USAGE_BITS, value);
295 
296 }
297 
TEST_F(IGraphicBufferProducerTest,Query_ReturnsError)298 TEST_F(IGraphicBufferProducerTest, Query_ReturnsError) {
299     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
300 
301     // One past the end of the last 'query' enum value. Update this if we add more enums.
302     const int NATIVE_WINDOW_QUERY_LAST_OFF_BY_ONE = NATIVE_WINDOW_BUFFER_AGE + 1;
303 
304     int value;
305     // What was out of range
306     EXPECT_EQ(BAD_VALUE, mProducer->query(/*what*/-1, &value));
307     EXPECT_EQ(BAD_VALUE, mProducer->query(/*what*/0xDEADBEEF, &value));
308     EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_QUERY_LAST_OFF_BY_ONE, &value));
309 
310     // Some enums from window.h are 'invalid'
311     EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER, &value));
312     EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_CONCRETE_TYPE, &value));
313     EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_DEFAULT_WIDTH, &value));
314     EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_DEFAULT_HEIGHT, &value));
315     EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_TRANSFORM_HINT, &value));
316     // TODO: Consider documented the above enums as unsupported or make a new enum for IGBP
317 
318     // Value was NULL
319     EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_FORMAT, /*value*/NULL));
320 
321     ASSERT_OK(mConsumer->consumerDisconnect());
322 
323     // BQ was abandoned
324     EXPECT_EQ(NO_INIT, mProducer->query(NATIVE_WINDOW_FORMAT, &value));
325 
326     // TODO: other things in window.h that are supported by Surface::query
327     // but not by BufferQueue::query
328 }
329 
330 // TODO: queue under more complicated situations not involving just a single buffer
TEST_F(IGraphicBufferProducerTest,Queue_Succeeds)331 TEST_F(IGraphicBufferProducerTest, Queue_Succeeds) {
332     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
333 
334     int dequeuedSlot = -1;
335     sp<Fence> dequeuedFence;
336 
337     // XX: OK to assume first call returns this flag or not? Not really documented.
338     ASSERT_EQ(OK | IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
339             mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
340                                      QUEUE_BUFFER_INPUT_ASYNC,
341                                      DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
342                                      TEST_PRODUCER_USAGE_BITS));
343 
344     EXPECT_LE(0, dequeuedSlot);
345     EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, dequeuedSlot);
346 
347     // Request the buffer (pre-requisite for queueing)
348     sp<GraphicBuffer> dequeuedBuffer;
349     ASSERT_OK(mProducer->requestBuffer(dequeuedSlot, &dequeuedBuffer));
350 
351     // A generic "valid" input
352     IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
353     IGraphicBufferProducer::QueueBufferOutput output;
354 
355     // Queue the buffer back into the BQ
356     ASSERT_OK(mProducer->queueBuffer(dequeuedSlot, input, &output));
357 
358     {
359         uint32_t width;
360         uint32_t height;
361         uint32_t transformHint;
362         uint32_t numPendingBuffers;
363 
364         output.deflate(&width, &height, &transformHint, &numPendingBuffers);
365 
366         EXPECT_EQ(DEFAULT_WIDTH, width);
367         EXPECT_EQ(DEFAULT_HEIGHT, height);
368         EXPECT_EQ(DEFAULT_TRANSFORM_HINT, transformHint);
369         EXPECT_EQ(1u, numPendingBuffers); // since queueBuffer was called exactly once
370     }
371 
372     // Buffer was not in the dequeued state
373     EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output));
374 }
375 
TEST_F(IGraphicBufferProducerTest,Queue_ReturnsError)376 TEST_F(IGraphicBufferProducerTest, Queue_ReturnsError) {
377     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
378 
379     // Invalid slot number
380     {
381         // A generic "valid" input
382         IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
383         IGraphicBufferProducer::QueueBufferOutput output;
384 
385         EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(/*slot*/-1, input, &output));
386         EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(/*slot*/0xDEADBEEF, input, &output));
387         EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(BufferQueue::NUM_BUFFER_SLOTS,
388                                                     input, &output));
389     }
390 
391     // Slot was not in the dequeued state (all slots start out in Free state)
392     {
393         IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
394         IGraphicBufferProducer::QueueBufferOutput output;
395 
396         EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(/*slot*/0, input, &output));
397     }
398 
399     // Put the slot into the "dequeued" state for the rest of the test
400     int dequeuedSlot = -1;
401     sp<Fence> dequeuedFence;
402 
403     ASSERT_EQ(OK | IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
404             mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
405                                      QUEUE_BUFFER_INPUT_ASYNC,
406                                      DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
407                                      TEST_PRODUCER_USAGE_BITS));
408 
409     // Slot was enqueued without requesting a buffer
410     {
411         IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
412         IGraphicBufferProducer::QueueBufferOutput output;
413 
414         EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output));
415     }
416 
417     // Request the buffer so that the rest of the tests don't fail on earlier checks.
418     sp<GraphicBuffer> dequeuedBuffer;
419     ASSERT_OK(mProducer->requestBuffer(dequeuedSlot, &dequeuedBuffer));
420 
421     // Fence was NULL
422     {
423         sp<Fence> nullFence = NULL;
424 
425         IGraphicBufferProducer::QueueBufferInput input =
426                 QueueBufferInputBuilder().setFence(nullFence).build();
427         IGraphicBufferProducer::QueueBufferOutput output;
428 
429         EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output));
430     }
431 
432     // Scaling mode was unknown
433     {
434         IGraphicBufferProducer::QueueBufferInput input =
435                 QueueBufferInputBuilder().setScalingMode(-1).build();
436         IGraphicBufferProducer::QueueBufferOutput output;
437 
438         EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output));
439 
440         input = QueueBufferInputBuilder().setScalingMode(0xDEADBEEF).build();
441 
442         EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output));
443     }
444 
445     // Crop rect is out of bounds of the buffer dimensions
446     {
447         IGraphicBufferProducer::QueueBufferInput input =
448                 QueueBufferInputBuilder().setCrop(Rect(DEFAULT_WIDTH + 1, DEFAULT_HEIGHT + 1))
449                 .build();
450         IGraphicBufferProducer::QueueBufferOutput output;
451 
452         EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output));
453     }
454 
455     // Abandon the buffer queue so that the last test fails
456     ASSERT_OK(mConsumer->consumerDisconnect());
457 
458     // The buffer queue has been abandoned.
459     {
460         IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
461         IGraphicBufferProducer::QueueBufferOutput output;
462 
463         EXPECT_EQ(NO_INIT, mProducer->queueBuffer(dequeuedSlot, input, &output));
464     }
465 }
466 
TEST_F(IGraphicBufferProducerTest,CancelBuffer_DoesntCrash)467 TEST_F(IGraphicBufferProducerTest, CancelBuffer_DoesntCrash) {
468     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
469 
470     int dequeuedSlot = -1;
471     sp<Fence> dequeuedFence;
472 
473     ASSERT_EQ(OK | IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
474             mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
475                                      QUEUE_BUFFER_INPUT_ASYNC,
476                                      DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
477                                      TEST_PRODUCER_USAGE_BITS));
478 
479     // No return code, but at least test that it doesn't blow up...
480     // TODO: add a return code
481     mProducer->cancelBuffer(dequeuedSlot, dequeuedFence);
482 }
483 
TEST_F(IGraphicBufferProducerTest,SetBufferCount_Succeeds)484 TEST_F(IGraphicBufferProducerTest, SetBufferCount_Succeeds) {
485 
486     // The producer does not wish to set a buffer count
487     EXPECT_OK(mProducer->setBufferCount(0)) << "bufferCount: " << 0;
488     // TODO: how to test "0" buffer count?
489 
490     int minBuffers;
491     ASSERT_OK(mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minBuffers));
492 
493     // The MIN_UNDEQUEUED_BUFFERS limit is exclusive, so need to increment by at least 1
494     minBuffers++;
495 
496     ASSERT_OK(mProducer->setBufferCount(minBuffers)) << "bufferCount: " << minBuffers;
497 
498     std::vector<DequeueBufferResult> dequeueList;
499 
500     // Should now be able to dequeue up to minBuffers times
501     for (int i = 0; i < minBuffers; ++i) {
502         DequeueBufferResult result;
503 
504         EXPECT_LE(OK,
505                 dequeueBuffer(QUEUE_BUFFER_INPUT_ASYNC,
506                               DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
507                               TEST_PRODUCER_USAGE_BITS, &result))
508                 << "iteration: " << i << ", slot: " << result.slot;
509 
510         dequeueList.push_back(result);
511     }
512 
513     // Cancel every buffer, so we can set buffer count again
514     for (int i = 0; i < minBuffers; ++i) {
515         DequeueBufferResult& result = dequeueList[i];
516         mProducer->cancelBuffer(result.slot, result.fence);
517     }
518 
519     ASSERT_OK(mProducer->setBufferCount(BufferQueue::NUM_BUFFER_SLOTS));
520 
521     // Should now be able to dequeue up to NUM_BUFFER_SLOTS times
522     for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; ++i) {
523         int dequeuedSlot = -1;
524         sp<Fence> dequeuedFence;
525 
526         EXPECT_LE(OK,
527                 mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
528                                          QUEUE_BUFFER_INPUT_ASYNC,
529                                          DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
530                                          TEST_PRODUCER_USAGE_BITS))
531                 << "iteration: " << i << ", slot: " << dequeuedSlot;
532     }
533 }
534 
TEST_F(IGraphicBufferProducerTest,SetBufferCount_Fails)535 TEST_F(IGraphicBufferProducerTest, SetBufferCount_Fails) {
536     int minBuffers;
537     ASSERT_OK(mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minBuffers));
538 
539     // The MIN_UNDEQUEUED_BUFFERS limit is exclusive, so need to increment by at least 1
540     minBuffers++;
541 
542     // Buffer count was out of range
543     EXPECT_EQ(BAD_VALUE, mProducer->setBufferCount(-1)) << "bufferCount: " << -1;
544     EXPECT_EQ(BAD_VALUE, mProducer->setBufferCount(minBuffers - 1)) << "bufferCount: " << minBuffers - 1;
545     EXPECT_EQ(BAD_VALUE, mProducer->setBufferCount(BufferQueue::NUM_BUFFER_SLOTS + 1))
546             << "bufferCount: " << BufferQueue::NUM_BUFFER_SLOTS + 1;
547 
548     // Pre-requisite to fail out a valid setBufferCount call
549     {
550         int dequeuedSlot = -1;
551         sp<Fence> dequeuedFence;
552 
553         ASSERT_LE(OK,
554                 mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
555                                          QUEUE_BUFFER_INPUT_ASYNC,
556                                          DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
557                                          TEST_PRODUCER_USAGE_BITS))
558                 << "slot: " << dequeuedSlot;
559     }
560 
561     // Client has one or more buffers dequeued
562     EXPECT_EQ(BAD_VALUE, mProducer->setBufferCount(minBuffers)) << "bufferCount: " << minBuffers;
563 
564     // Abandon buffer queue
565     ASSERT_OK(mConsumer->consumerDisconnect());
566 
567     // Fail because the buffer queue was abandoned
568     EXPECT_EQ(NO_INIT, mProducer->setBufferCount(minBuffers)) << "bufferCount: " << minBuffers;
569 
570 }
571 
572 } // namespace android
573