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