• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 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            dataSpace = QUEUE_BUFFER_INPUT_DATASPACE;
130            crop = QUEUE_BUFFER_INPUT_RECT;
131            scalingMode = QUEUE_BUFFER_INPUT_SCALING_MODE;
132            transform = QUEUE_BUFFER_INPUT_TRANSFORM;
133            fence = QUEUE_BUFFER_INPUT_FENCE;
134         }
135 
buildandroid::IGraphicBufferProducerTest::QueueBufferInputBuilder136         IGraphicBufferProducer::QueueBufferInput build() {
137             return IGraphicBufferProducer::QueueBufferInput(
138                     timestamp,
139                     isAutoTimestamp,
140                     dataSpace,
141                     crop,
142                     scalingMode,
143                     transform,
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 
setDataSpaceandroid::IGraphicBufferProducerTest::QueueBufferInputBuilder157         QueueBufferInputBuilder& setDataSpace(android_dataspace dataSpace) {
158             this->dataSpace = dataSpace;
159             return *this;
160         }
161 
setCropandroid::IGraphicBufferProducerTest::QueueBufferInputBuilder162         QueueBufferInputBuilder& setCrop(Rect crop) {
163             this->crop = crop;
164             return *this;
165         }
166 
setScalingModeandroid::IGraphicBufferProducerTest::QueueBufferInputBuilder167         QueueBufferInputBuilder& setScalingMode(int scalingMode) {
168             this->scalingMode = scalingMode;
169             return *this;
170         }
171 
setTransformandroid::IGraphicBufferProducerTest::QueueBufferInputBuilder172         QueueBufferInputBuilder& setTransform(uint32_t transform) {
173             this->transform = transform;
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         android_dataspace dataSpace;
186         Rect crop;
187         int scalingMode;
188         uint32_t transform;
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(uint32_t w,uint32_t h,uint32_t format,uint32_t usage,DequeueBufferResult * result)198     status_t dequeueBuffer(uint32_t w, uint32_t h, uint32_t format, uint32_t usage, DequeueBufferResult* result) {
199         return mProducer->dequeueBuffer(&result->slot, &result->fence, w, h, format, usage);
200     }
201 
setupDequeueRequestBuffer(int * slot,sp<Fence> * fence,sp<GraphicBuffer> * buffer)202     void setupDequeueRequestBuffer(int *slot, sp<Fence> *fence,
203             sp<GraphicBuffer> *buffer)
204     {
205         ASSERT_TRUE(slot != NULL);
206         ASSERT_TRUE(fence != NULL);
207         ASSERT_TRUE(buffer != NULL);
208 
209         ASSERT_NO_FATAL_FAILURE(ConnectProducer());
210 
211         ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
212                 (mProducer->dequeueBuffer(slot, fence, DEFAULT_WIDTH,
213                 DEFAULT_HEIGHT, DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS)));
214 
215         EXPECT_LE(0, *slot);
216         EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, *slot);
217 
218         // Request the buffer (pre-requisite for queueing)
219         ASSERT_OK(mProducer->requestBuffer(*slot, buffer));
220     }
221 
222 private: // hide from test body
223     sp<DummyConsumer> mDC;
224 
225 protected: // accessible from test body
226     sp<IGraphicBufferProducer> mProducer;
227     sp<IGraphicBufferConsumer> mConsumer;
228 };
229 
TEST_F(IGraphicBufferProducerTest,ConnectFirst_ReturnsError)230 TEST_F(IGraphicBufferProducerTest, ConnectFirst_ReturnsError) {
231     IGraphicBufferProducer::QueueBufferOutput output;
232 
233     // NULL output returns BAD_VALUE
234     EXPECT_EQ(BAD_VALUE, mProducer->connect(TEST_TOKEN,
235                                             TEST_API,
236                                             TEST_CONTROLLED_BY_APP,
237                                             /*output*/NULL));
238 
239     // Invalid API returns bad value
240     EXPECT_EQ(BAD_VALUE, mProducer->connect(TEST_TOKEN,
241                                             /*api*/0xDEADBEEF,
242                                             TEST_CONTROLLED_BY_APP,
243                                             &output));
244 
245     // TODO: get a token from a dead process somehow
246 }
247 
TEST_F(IGraphicBufferProducerTest,ConnectAgain_ReturnsError)248 TEST_F(IGraphicBufferProducerTest, ConnectAgain_ReturnsError) {
249     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
250 
251     // Can't connect when there is already a producer connected
252     IGraphicBufferProducer::QueueBufferOutput output;
253     EXPECT_EQ(BAD_VALUE, mProducer->connect(TEST_TOKEN,
254                                             TEST_API,
255                                             TEST_CONTROLLED_BY_APP,
256                                             &output));
257 
258     ASSERT_OK(mConsumer->consumerDisconnect());
259     // Can't connect when IGBP is abandoned
260     EXPECT_EQ(NO_INIT, mProducer->connect(TEST_TOKEN,
261                                           TEST_API,
262                                           TEST_CONTROLLED_BY_APP,
263                                           &output));
264 }
265 
TEST_F(IGraphicBufferProducerTest,Disconnect_Succeeds)266 TEST_F(IGraphicBufferProducerTest, Disconnect_Succeeds) {
267     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
268 
269     ASSERT_OK(mProducer->disconnect(TEST_API));
270 }
271 
272 
TEST_F(IGraphicBufferProducerTest,Disconnect_ReturnsError)273 TEST_F(IGraphicBufferProducerTest, Disconnect_ReturnsError) {
274     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
275 
276     // Must disconnect with same API number
277     ASSERT_EQ(BAD_VALUE, mProducer->disconnect(TEST_API_OTHER));
278     // API must not be out of range
279     ASSERT_EQ(BAD_VALUE, mProducer->disconnect(/*api*/0xDEADBEEF));
280 
281     // TODO: somehow kill mProducer so that this returns DEAD_OBJECT
282 }
283 
TEST_F(IGraphicBufferProducerTest,Query_Succeeds)284 TEST_F(IGraphicBufferProducerTest, Query_Succeeds) {
285     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
286 
287     int32_t value = -1;
288     EXPECT_OK(mProducer->query(NATIVE_WINDOW_WIDTH, &value));
289     EXPECT_EQ(DEFAULT_WIDTH, static_cast<uint32_t>(value));
290 
291     EXPECT_OK(mProducer->query(NATIVE_WINDOW_HEIGHT, &value));
292     EXPECT_EQ(DEFAULT_HEIGHT, static_cast<uint32_t>(value));
293 
294     EXPECT_OK(mProducer->query(NATIVE_WINDOW_FORMAT, &value));
295     EXPECT_EQ(DEFAULT_FORMAT, value);
296 
297     EXPECT_OK(mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &value));
298     EXPECT_LE(0, value);
299     EXPECT_GE(BufferQueue::NUM_BUFFER_SLOTS, value);
300 
301     EXPECT_OK(mProducer->query(NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &value));
302     EXPECT_FALSE(value); // Can't run behind when we haven't touched the queue
303 
304     EXPECT_OK(mProducer->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &value));
305     EXPECT_EQ(DEFAULT_CONSUMER_USAGE_BITS, value);
306 
307 }
308 
TEST_F(IGraphicBufferProducerTest,Query_ReturnsError)309 TEST_F(IGraphicBufferProducerTest, Query_ReturnsError) {
310     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
311 
312     // One past the end of the last 'query' enum value. Update this if we add more enums.
313     const int NATIVE_WINDOW_QUERY_LAST_OFF_BY_ONE = NATIVE_WINDOW_BUFFER_AGE + 1;
314 
315     int value;
316     // What was out of range
317     EXPECT_EQ(BAD_VALUE, mProducer->query(/*what*/-1, &value));
318     EXPECT_EQ(BAD_VALUE, mProducer->query(/*what*/0xDEADBEEF, &value));
319     EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_QUERY_LAST_OFF_BY_ONE, &value));
320 
321     // Some enums from window.h are 'invalid'
322     EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER, &value));
323     EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_CONCRETE_TYPE, &value));
324     EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_DEFAULT_WIDTH, &value));
325     EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_DEFAULT_HEIGHT, &value));
326     EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_TRANSFORM_HINT, &value));
327     // TODO: Consider documented the above enums as unsupported or make a new enum for IGBP
328 
329     // Value was NULL
330     EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_FORMAT, /*value*/NULL));
331 
332     ASSERT_OK(mConsumer->consumerDisconnect());
333 
334     // BQ was abandoned
335     EXPECT_EQ(NO_INIT, mProducer->query(NATIVE_WINDOW_FORMAT, &value));
336 
337     // TODO: other things in window.h that are supported by Surface::query
338     // but not by BufferQueue::query
339 }
340 
341 // TODO: queue under more complicated situations not involving just a single buffer
TEST_F(IGraphicBufferProducerTest,Queue_Succeeds)342 TEST_F(IGraphicBufferProducerTest, Queue_Succeeds) {
343     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
344 
345     int dequeuedSlot = -1;
346     sp<Fence> dequeuedFence;
347 
348 
349     ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
350             (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
351                                      DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
352                                      TEST_PRODUCER_USAGE_BITS)));
353 
354     EXPECT_LE(0, dequeuedSlot);
355     EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, dequeuedSlot);
356 
357     // Request the buffer (pre-requisite for queueing)
358     sp<GraphicBuffer> dequeuedBuffer;
359     ASSERT_OK(mProducer->requestBuffer(dequeuedSlot, &dequeuedBuffer));
360 
361     // A generic "valid" input
362     IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
363     IGraphicBufferProducer::QueueBufferOutput output;
364 
365     // Queue the buffer back into the BQ
366     ASSERT_OK(mProducer->queueBuffer(dequeuedSlot, input, &output));
367 
368     {
369         uint32_t width;
370         uint32_t height;
371         uint32_t transformHint;
372         uint32_t numPendingBuffers;
373 
374         output.deflate(&width, &height, &transformHint, &numPendingBuffers);
375 
376         EXPECT_EQ(DEFAULT_WIDTH, width);
377         EXPECT_EQ(DEFAULT_HEIGHT, height);
378         EXPECT_EQ(DEFAULT_TRANSFORM_HINT, transformHint);
379         EXPECT_EQ(1u, numPendingBuffers); // since queueBuffer was called exactly once
380     }
381 
382     // Buffer was not in the dequeued state
383     EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output));
384 }
385 
TEST_F(IGraphicBufferProducerTest,Queue_ReturnsError)386 TEST_F(IGraphicBufferProducerTest, Queue_ReturnsError) {
387     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
388 
389     // Invalid slot number
390     {
391         // A generic "valid" input
392         IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
393         IGraphicBufferProducer::QueueBufferOutput output;
394 
395         EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(/*slot*/-1, input, &output));
396         EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(/*slot*/0xDEADBEEF, input, &output));
397         EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(BufferQueue::NUM_BUFFER_SLOTS,
398                                                     input, &output));
399     }
400 
401     // Slot was not in the dequeued state (all slots start out in Free state)
402     {
403         IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
404         IGraphicBufferProducer::QueueBufferOutput output;
405 
406         EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(/*slot*/0, input, &output));
407     }
408 
409     // Put the slot into the "dequeued" state for the rest of the test
410     int dequeuedSlot = -1;
411     sp<Fence> dequeuedFence;
412 
413     ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
414             (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
415                                      DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
416                                      TEST_PRODUCER_USAGE_BITS)));
417 
418     // Slot was enqueued without requesting a buffer
419     {
420         IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
421         IGraphicBufferProducer::QueueBufferOutput output;
422 
423         EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output));
424     }
425 
426     // Request the buffer so that the rest of the tests don't fail on earlier checks.
427     sp<GraphicBuffer> dequeuedBuffer;
428     ASSERT_OK(mProducer->requestBuffer(dequeuedSlot, &dequeuedBuffer));
429 
430     // Fence was NULL
431     {
432         sp<Fence> nullFence = NULL;
433 
434         IGraphicBufferProducer::QueueBufferInput input =
435                 QueueBufferInputBuilder().setFence(nullFence).build();
436         IGraphicBufferProducer::QueueBufferOutput output;
437 
438         EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output));
439     }
440 
441     // Scaling mode was unknown
442     {
443         IGraphicBufferProducer::QueueBufferInput input =
444                 QueueBufferInputBuilder().setScalingMode(-1).build();
445         IGraphicBufferProducer::QueueBufferOutput output;
446 
447         EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output));
448 
449         input = QueueBufferInputBuilder().setScalingMode(0xDEADBEEF).build();
450 
451         EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output));
452     }
453 
454     // Crop rect is out of bounds of the buffer dimensions
455     {
456         IGraphicBufferProducer::QueueBufferInput input =
457                 QueueBufferInputBuilder().setCrop(Rect(DEFAULT_WIDTH + 1, DEFAULT_HEIGHT + 1))
458                 .build();
459         IGraphicBufferProducer::QueueBufferOutput output;
460 
461         EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output));
462     }
463 
464     // Abandon the buffer queue so that the last test fails
465     ASSERT_OK(mConsumer->consumerDisconnect());
466 
467     // The buffer queue has been abandoned.
468     {
469         IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
470         IGraphicBufferProducer::QueueBufferOutput output;
471 
472         EXPECT_EQ(NO_INIT, mProducer->queueBuffer(dequeuedSlot, input, &output));
473     }
474 }
475 
TEST_F(IGraphicBufferProducerTest,CancelBuffer_DoesntCrash)476 TEST_F(IGraphicBufferProducerTest, CancelBuffer_DoesntCrash) {
477     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
478 
479     int dequeuedSlot = -1;
480     sp<Fence> dequeuedFence;
481 
482     ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
483             (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
484                                      DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
485                                      TEST_PRODUCER_USAGE_BITS)));
486 
487     // No return code, but at least test that it doesn't blow up...
488     // TODO: add a return code
489     mProducer->cancelBuffer(dequeuedSlot, dequeuedFence);
490 }
491 
TEST_F(IGraphicBufferProducerTest,SetMaxDequeuedBufferCount_Succeeds)492 TEST_F(IGraphicBufferProducerTest, SetMaxDequeuedBufferCount_Succeeds) {
493     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
494     int minUndequeuedBuffers;
495     ASSERT_OK(mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
496             &minUndequeuedBuffers));
497 
498     const int minBuffers = 1;
499     const int maxBuffers = BufferQueue::NUM_BUFFER_SLOTS - minUndequeuedBuffers;
500 
501     ASSERT_OK(mProducer->setAsyncMode(false)) << "async mode: " << false;
502     ASSERT_OK(mProducer->setMaxDequeuedBufferCount(minBuffers))
503             << "bufferCount: " << minBuffers;
504 
505     // Should now be able to dequeue up to minBuffers times
506     DequeueBufferResult result;
507     for (int i = 0; i < minBuffers; ++i) {
508 
509         EXPECT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
510                 (dequeueBuffer(DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
511                               TEST_PRODUCER_USAGE_BITS, &result)))
512                 << "iteration: " << i << ", slot: " << result.slot;
513     }
514 
515     ASSERT_OK(mProducer->setMaxDequeuedBufferCount(maxBuffers));
516 
517     // queue the first buffer to enable max dequeued buffer count checking
518     IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
519     IGraphicBufferProducer::QueueBufferOutput output;
520     sp<GraphicBuffer> buffer;
521     ASSERT_OK(mProducer->requestBuffer(result.slot, &buffer));
522     ASSERT_OK(mProducer->queueBuffer(result.slot, input, &output));
523 
524 
525     // Should now be able to dequeue up to maxBuffers times
526     int dequeuedSlot = -1;
527     sp<Fence> dequeuedFence;
528     for (int i = 0; i < maxBuffers; ++i) {
529 
530         EXPECT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
531                 (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
532                                          DEFAULT_WIDTH, DEFAULT_HEIGHT,
533                                          DEFAULT_FORMAT,
534                                          TEST_PRODUCER_USAGE_BITS)))
535                 << "iteration: " << i << ", slot: " << dequeuedSlot;
536     }
537 
538     // Cancel a buffer, so we can decrease the buffer count
539     ASSERT_OK(mProducer->cancelBuffer(dequeuedSlot, dequeuedFence));
540 
541     // Should now be able to decrease the max dequeued count by 1
542     ASSERT_OK(mProducer->setMaxDequeuedBufferCount(maxBuffers-1));
543 }
544 
TEST_F(IGraphicBufferProducerTest,SetMaxDequeuedBufferCount_Fails)545 TEST_F(IGraphicBufferProducerTest, SetMaxDequeuedBufferCount_Fails) {
546     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
547     int minUndequeuedBuffers;
548     ASSERT_OK(mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
549                                &minUndequeuedBuffers));
550 
551     const int minBuffers = 1;
552     const int maxBuffers = BufferQueue::NUM_BUFFER_SLOTS - minUndequeuedBuffers;
553 
554     ASSERT_OK(mProducer->setAsyncMode(false)) << "async mode: " << false;
555     // Buffer count was out of range
556     EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(0))
557             << "bufferCount: " << 0;
558     EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(maxBuffers + 1))
559             << "bufferCount: " << maxBuffers + 1;
560 
561     // Set max dequeue count to 2
562     ASSERT_OK(mProducer->setMaxDequeuedBufferCount(2));
563     // Dequeue 2 buffers
564     int dequeuedSlot = -1;
565     sp<Fence> dequeuedFence;
566     for (int i = 0; i < 2; i++) {
567         ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
568                 (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
569                                          DEFAULT_WIDTH, DEFAULT_HEIGHT,
570                                          DEFAULT_FORMAT,
571                                          TEST_PRODUCER_USAGE_BITS)))
572                 << "slot: " << dequeuedSlot;
573     }
574 
575     // Client has too many buffers dequeued
576     EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(1))
577             << "bufferCount: " << minBuffers;
578 
579     // Abandon buffer queue
580     ASSERT_OK(mConsumer->consumerDisconnect());
581 
582     // Fail because the buffer queue was abandoned
583     EXPECT_EQ(NO_INIT, mProducer->setMaxDequeuedBufferCount(minBuffers))
584             << "bufferCount: " << minBuffers;
585 
586 }
587 
TEST_F(IGraphicBufferProducerTest,SetAsyncMode_Succeeds)588 TEST_F(IGraphicBufferProducerTest, SetAsyncMode_Succeeds) {
589     ASSERT_OK(mConsumer->setMaxAcquiredBufferCount(1)) << "maxAcquire: " << 1;
590     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
591     ASSERT_OK(mProducer->setAsyncMode(true)) << "async mode: " << true;
592     ASSERT_OK(mProducer->setMaxDequeuedBufferCount(1)) << "maxDequeue: " << 1;
593 
594     int dequeuedSlot = -1;
595     sp<Fence> dequeuedFence;
596     IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
597     IGraphicBufferProducer::QueueBufferOutput output;
598     sp<GraphicBuffer> dequeuedBuffer;
599 
600     // Should now be able to queue/dequeue as many buffers as we want without
601     // blocking
602     for (int i = 0; i < 5; ++i) {
603         ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
604                 (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
605                 DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
606                 TEST_PRODUCER_USAGE_BITS))) << "slot : " << dequeuedSlot;
607         ASSERT_OK(mProducer->requestBuffer(dequeuedSlot, &dequeuedBuffer));
608         ASSERT_OK(mProducer->queueBuffer(dequeuedSlot, input, &output));
609     }
610 }
611 
TEST_F(IGraphicBufferProducerTest,SetAsyncMode_Fails)612 TEST_F(IGraphicBufferProducerTest, SetAsyncMode_Fails) {
613     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
614     // Prerequisite to fail out a valid setBufferCount call
615     {
616         int dequeuedSlot = -1;
617         sp<Fence> dequeuedFence;
618 
619         ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
620                 (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
621                 DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
622                 TEST_PRODUCER_USAGE_BITS))) << "slot: " << dequeuedSlot;
623     }
624 
625     // Abandon buffer queue
626     ASSERT_OK(mConsumer->consumerDisconnect());
627 
628     // Fail because the buffer queue was abandoned
629     EXPECT_EQ(NO_INIT, mProducer->setAsyncMode(false)) << "asyncMode: "
630             << false;
631 }
632 
TEST_F(IGraphicBufferProducerTest,DisconnectedProducerReturnsError_dequeueBuffer)633 TEST_F(IGraphicBufferProducerTest,
634         DisconnectedProducerReturnsError_dequeueBuffer) {
635     int slot = -1;
636     sp<Fence> fence;
637 
638     ASSERT_EQ(NO_INIT, mProducer->dequeueBuffer(&slot, &fence, DEFAULT_WIDTH,
639             DEFAULT_HEIGHT, DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS));
640 }
641 
TEST_F(IGraphicBufferProducerTest,DisconnectedProducerReturnsError_detachNextBuffer)642 TEST_F(IGraphicBufferProducerTest,
643         DisconnectedProducerReturnsError_detachNextBuffer) {
644     sp<Fence> fence;
645     sp<GraphicBuffer> buffer;
646 
647     ASSERT_EQ(NO_INIT, mProducer->detachNextBuffer(&buffer, &fence));
648 }
649 
TEST_F(IGraphicBufferProducerTest,DisconnectedProducerReturnsError_requestBuffer)650 TEST_F(IGraphicBufferProducerTest,
651         DisconnectedProducerReturnsError_requestBuffer) {
652     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
653 
654     int slot = -1;
655     sp<Fence> fence;
656 
657     ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
658             (mProducer->dequeueBuffer(&slot, &fence, DEFAULT_WIDTH,
659             DEFAULT_HEIGHT, DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS)));
660 
661     EXPECT_LE(0, slot);
662     EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, slot);
663 
664     ASSERT_OK(mProducer->disconnect(TEST_API));
665 
666     sp<GraphicBuffer> buffer;
667 
668     ASSERT_EQ(NO_INIT, mProducer->requestBuffer(slot, &buffer));
669 }
670 
671 
TEST_F(IGraphicBufferProducerTest,DisconnectedProducerReturnsError_detachBuffer)672 TEST_F(IGraphicBufferProducerTest,
673         DisconnectedProducerReturnsError_detachBuffer) {
674     int slot = -1;
675     sp<Fence> fence;
676     sp<GraphicBuffer> buffer;
677 
678     setupDequeueRequestBuffer(&slot, &fence, &buffer);
679 
680     ASSERT_OK(mProducer->disconnect(TEST_API));
681 
682     ASSERT_EQ(NO_INIT, mProducer->detachBuffer(slot));
683 }
684 
TEST_F(IGraphicBufferProducerTest,DisconnectedProducerReturnsError_queueBuffer)685 TEST_F(IGraphicBufferProducerTest,
686         DisconnectedProducerReturnsError_queueBuffer) {
687     int slot = -1;
688     sp<Fence> fence;
689     sp<GraphicBuffer> buffer;
690 
691     setupDequeueRequestBuffer(&slot, &fence, &buffer);
692 
693     ASSERT_OK(mProducer->disconnect(TEST_API));
694 
695     // A generic "valid" input
696     IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
697     IGraphicBufferProducer::QueueBufferOutput output;
698 
699     ASSERT_EQ(NO_INIT, mProducer->queueBuffer(slot, input, &output));
700 }
701 
TEST_F(IGraphicBufferProducerTest,DisconnectedProducerReturnsError_cancelBuffer)702 TEST_F(IGraphicBufferProducerTest,
703         DisconnectedProducerReturnsError_cancelBuffer) {
704     int slot = -1;
705     sp<Fence> fence;
706     sp<GraphicBuffer> buffer;
707 
708     setupDequeueRequestBuffer(&slot, &fence, &buffer);
709 
710     ASSERT_OK(mProducer->disconnect(TEST_API));
711 
712     ASSERT_EQ(NO_INIT, mProducer->cancelBuffer(slot, fence));
713 }
714 
TEST_F(IGraphicBufferProducerTest,DisconnectedProducerReturnsError_attachBuffer)715 TEST_F(IGraphicBufferProducerTest,
716         DisconnectedProducerReturnsError_attachBuffer) {
717     int slot = -1;
718     sp<Fence> fence;
719     sp<GraphicBuffer> buffer;
720 
721     setupDequeueRequestBuffer(&slot, &fence, &buffer);
722 
723     ASSERT_OK(mProducer->detachBuffer(slot));
724 
725     ASSERT_OK(mProducer->disconnect(TEST_API));
726 
727     ASSERT_EQ(NO_INIT, mProducer->attachBuffer(&slot, buffer));
728 }
729 
730 } // namespace android
731