• 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 "DummyConsumer.h"
21 
22 #include <gtest/gtest.h>
23 
24 #include <utils/String8.h>
25 #include <utils/threads.h>
26 
27 #include <ui/GraphicBuffer.h>
28 
29 #include <gui/BufferQueue.h>
30 #include <gui/IProducerListener.h>
31 
32 #include <vector>
33 
34 #define ASSERT_OK(x) ASSERT_EQ(OK, (x))
35 #define EXPECT_OK(x) EXPECT_EQ(OK, (x))
36 
37 #define TEST_TOKEN ((IProducerListener*)(NULL))
38 #define TEST_API NATIVE_WINDOW_API_CPU
39 #define TEST_API_OTHER NATIVE_WINDOW_API_EGL // valid API that's not TEST_API
40 #define TEST_CONTROLLED_BY_APP false
41 #define TEST_PRODUCER_USAGE_BITS (0)
42 
43 namespace android {
44 
45 namespace {
46     // Default dimensions before setDefaultBufferSize is called
47     const uint32_t DEFAULT_WIDTH = 1;
48     const uint32_t DEFAULT_HEIGHT = 1;
49 
50     // Default format before setDefaultBufferFormat is called
51     const PixelFormat DEFAULT_FORMAT = HAL_PIXEL_FORMAT_RGBA_8888;
52 
53     // Default transform hint before setTransformHint is called
54     const uint32_t DEFAULT_TRANSFORM_HINT = 0;
55 
56     // TODO: Make these constants in header
57     const int DEFAULT_CONSUMER_USAGE_BITS = 0;
58 
59     // Parameters for a generic "valid" input for queueBuffer.
60     const int64_t QUEUE_BUFFER_INPUT_TIMESTAMP = 1384888611;
61     const bool QUEUE_BUFFER_INPUT_IS_AUTO_TIMESTAMP = false;
62     const android_dataspace QUEUE_BUFFER_INPUT_DATASPACE = HAL_DATASPACE_UNKNOWN;
63     const Rect QUEUE_BUFFER_INPUT_RECT = Rect(DEFAULT_WIDTH, DEFAULT_HEIGHT);
64     const int QUEUE_BUFFER_INPUT_SCALING_MODE = 0;
65     const int QUEUE_BUFFER_INPUT_TRANSFORM = 0;
66     const sp<Fence> QUEUE_BUFFER_INPUT_FENCE = Fence::NO_FENCE;
67 }; // namespace anonymous
68 
69 class IGraphicBufferProducerTest : public ::testing::Test {
70 protected:
71 
IGraphicBufferProducerTest()72     IGraphicBufferProducerTest() {}
73 
SetUp()74     virtual void SetUp() {
75         const ::testing::TestInfo* const testInfo =
76             ::testing::UnitTest::GetInstance()->current_test_info();
77         ALOGV("Begin test: %s.%s", testInfo->test_case_name(),
78                 testInfo->name());
79 
80         mDC = new DummyConsumer;
81 
82         BufferQueue::createBufferQueue(&mProducer, &mConsumer);
83 
84         // Test check: Can't connect producer if no consumer yet
85         ASSERT_EQ(NO_INIT, TryConnectProducer());
86 
87         // Must connect consumer before producer connects will succeed.
88         ASSERT_OK(mConsumer->consumerConnect(mDC, /*controlledByApp*/false));
89     }
90 
TearDown()91     virtual void TearDown() {
92         const ::testing::TestInfo* const testInfo =
93             ::testing::UnitTest::GetInstance()->current_test_info();
94         ALOGV("End test:   %s.%s", testInfo->test_case_name(),
95                 testInfo->name());
96     }
97 
TryConnectProducer()98     status_t TryConnectProducer() {
99         IGraphicBufferProducer::QueueBufferOutput output;
100         return mProducer->connect(TEST_TOKEN,
101                                   TEST_API,
102                                   TEST_CONTROLLED_BY_APP,
103                                   &output);
104         // TODO: use params to vary token, api, producercontrolledbyapp, etc
105     }
106 
107     // Connect to a producer in a 'correct' fashion.
108     //   Precondition: Consumer is connected.
ConnectProducer()109     void ConnectProducer() {
110         ASSERT_OK(TryConnectProducer());
111     }
112 
113     // Create a generic "valid" input for queueBuffer
114     // -- uses the default buffer format, width, etc.
CreateBufferInput()115     static IGraphicBufferProducer::QueueBufferInput CreateBufferInput() {
116         return QueueBufferInputBuilder().build();
117     }
118 
119     // Builder pattern to slightly vary *almost* correct input
120     // -- avoids copying and pasting
121     struct QueueBufferInputBuilder {
QueueBufferInputBuilderandroid::IGraphicBufferProducerTest::QueueBufferInputBuilder122         QueueBufferInputBuilder() {
123            timestamp = QUEUE_BUFFER_INPUT_TIMESTAMP;
124            isAutoTimestamp = QUEUE_BUFFER_INPUT_IS_AUTO_TIMESTAMP;
125            dataSpace = QUEUE_BUFFER_INPUT_DATASPACE;
126            crop = QUEUE_BUFFER_INPUT_RECT;
127            scalingMode = QUEUE_BUFFER_INPUT_SCALING_MODE;
128            transform = QUEUE_BUFFER_INPUT_TRANSFORM;
129            fence = QUEUE_BUFFER_INPUT_FENCE;
130         }
131 
buildandroid::IGraphicBufferProducerTest::QueueBufferInputBuilder132         IGraphicBufferProducer::QueueBufferInput build() {
133             return IGraphicBufferProducer::QueueBufferInput(
134                     timestamp,
135                     isAutoTimestamp,
136                     dataSpace,
137                     crop,
138                     scalingMode,
139                     transform,
140                     fence);
141         }
142 
setTimestampandroid::IGraphicBufferProducerTest::QueueBufferInputBuilder143         QueueBufferInputBuilder& setTimestamp(int64_t timestamp) {
144             this->timestamp = timestamp;
145             return *this;
146         }
147 
setIsAutoTimestampandroid::IGraphicBufferProducerTest::QueueBufferInputBuilder148         QueueBufferInputBuilder& setIsAutoTimestamp(bool isAutoTimestamp) {
149             this->isAutoTimestamp = isAutoTimestamp;
150             return *this;
151         }
152 
setDataSpaceandroid::IGraphicBufferProducerTest::QueueBufferInputBuilder153         QueueBufferInputBuilder& setDataSpace(android_dataspace dataSpace) {
154             this->dataSpace = dataSpace;
155             return *this;
156         }
157 
setCropandroid::IGraphicBufferProducerTest::QueueBufferInputBuilder158         QueueBufferInputBuilder& setCrop(Rect crop) {
159             this->crop = crop;
160             return *this;
161         }
162 
setScalingModeandroid::IGraphicBufferProducerTest::QueueBufferInputBuilder163         QueueBufferInputBuilder& setScalingMode(int scalingMode) {
164             this->scalingMode = scalingMode;
165             return *this;
166         }
167 
setTransformandroid::IGraphicBufferProducerTest::QueueBufferInputBuilder168         QueueBufferInputBuilder& setTransform(uint32_t transform) {
169             this->transform = transform;
170             return *this;
171         }
172 
setFenceandroid::IGraphicBufferProducerTest::QueueBufferInputBuilder173         QueueBufferInputBuilder& setFence(sp<Fence> fence) {
174             this->fence = fence;
175             return *this;
176         }
177 
178     private:
179         int64_t timestamp;
180         bool isAutoTimestamp;
181         android_dataspace dataSpace;
182         Rect crop;
183         int scalingMode;
184         uint32_t transform;
185         sp<Fence> fence;
186     }; // struct QueueBufferInputBuilder
187 
188     // To easily store dequeueBuffer results into containers
189     struct DequeueBufferResult {
190         int slot;
191         sp<Fence> fence;
192     };
193 
dequeueBuffer(uint32_t w,uint32_t h,uint32_t format,uint32_t usage,DequeueBufferResult * result)194     status_t dequeueBuffer(uint32_t w, uint32_t h, uint32_t format, uint32_t usage, DequeueBufferResult* result) {
195         return mProducer->dequeueBuffer(&result->slot, &result->fence, w, h, format, usage, nullptr);
196     }
197 
setupDequeueRequestBuffer(int * slot,sp<Fence> * fence,sp<GraphicBuffer> * buffer)198     void setupDequeueRequestBuffer(int *slot, sp<Fence> *fence,
199             sp<GraphicBuffer> *buffer)
200     {
201         ASSERT_TRUE(slot != NULL);
202         ASSERT_TRUE(fence != NULL);
203         ASSERT_TRUE(buffer != NULL);
204 
205         ASSERT_NO_FATAL_FAILURE(ConnectProducer());
206 
207         ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
208                 (mProducer->dequeueBuffer(slot, fence, DEFAULT_WIDTH,
209                 DEFAULT_HEIGHT, DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS, nullptr)));
210 
211         EXPECT_LE(0, *slot);
212         EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, *slot);
213 
214         // Request the buffer (pre-requisite for queueing)
215         ASSERT_OK(mProducer->requestBuffer(*slot, buffer));
216     }
217 
218 private: // hide from test body
219     sp<DummyConsumer> mDC;
220 
221 protected: // accessible from test body
222     sp<IGraphicBufferProducer> mProducer;
223     sp<IGraphicBufferConsumer> mConsumer;
224 };
225 
TEST_F(IGraphicBufferProducerTest,ConnectFirst_ReturnsError)226 TEST_F(IGraphicBufferProducerTest, ConnectFirst_ReturnsError) {
227     IGraphicBufferProducer::QueueBufferOutput output;
228 
229     // NULL output returns BAD_VALUE
230     EXPECT_EQ(BAD_VALUE, mProducer->connect(TEST_TOKEN,
231                                             TEST_API,
232                                             TEST_CONTROLLED_BY_APP,
233                                             /*output*/NULL));
234 
235     // Invalid API returns bad value
236     EXPECT_EQ(BAD_VALUE, mProducer->connect(TEST_TOKEN,
237                                             /*api*/0xDEADBEEF,
238                                             TEST_CONTROLLED_BY_APP,
239                                             &output));
240 
241     // TODO: get a token from a dead process somehow
242 }
243 
TEST_F(IGraphicBufferProducerTest,ConnectAgain_ReturnsError)244 TEST_F(IGraphicBufferProducerTest, ConnectAgain_ReturnsError) {
245     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
246 
247     // Can't connect when there is already a producer connected
248     IGraphicBufferProducer::QueueBufferOutput output;
249     EXPECT_EQ(BAD_VALUE, mProducer->connect(TEST_TOKEN,
250                                             TEST_API,
251                                             TEST_CONTROLLED_BY_APP,
252                                             &output));
253 
254     ASSERT_OK(mConsumer->consumerDisconnect());
255     // Can't connect when IGBP is abandoned
256     EXPECT_EQ(NO_INIT, mProducer->connect(TEST_TOKEN,
257                                           TEST_API,
258                                           TEST_CONTROLLED_BY_APP,
259                                           &output));
260 }
261 
TEST_F(IGraphicBufferProducerTest,Disconnect_Succeeds)262 TEST_F(IGraphicBufferProducerTest, Disconnect_Succeeds) {
263     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
264 
265     ASSERT_OK(mProducer->disconnect(TEST_API));
266 }
267 
268 
TEST_F(IGraphicBufferProducerTest,Disconnect_ReturnsError)269 TEST_F(IGraphicBufferProducerTest, Disconnect_ReturnsError) {
270     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
271 
272     // Must disconnect with same API number
273     ASSERT_EQ(BAD_VALUE, mProducer->disconnect(TEST_API_OTHER));
274     // API must not be out of range
275     ASSERT_EQ(BAD_VALUE, mProducer->disconnect(/*api*/0xDEADBEEF));
276 
277     // TODO: somehow kill mProducer so that this returns DEAD_OBJECT
278 }
279 
TEST_F(IGraphicBufferProducerTest,Query_Succeeds)280 TEST_F(IGraphicBufferProducerTest, Query_Succeeds) {
281     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
282 
283     int32_t value = -1;
284     EXPECT_OK(mProducer->query(NATIVE_WINDOW_WIDTH, &value));
285     EXPECT_EQ(DEFAULT_WIDTH, static_cast<uint32_t>(value));
286 
287     EXPECT_OK(mProducer->query(NATIVE_WINDOW_HEIGHT, &value));
288     EXPECT_EQ(DEFAULT_HEIGHT, static_cast<uint32_t>(value));
289 
290     EXPECT_OK(mProducer->query(NATIVE_WINDOW_FORMAT, &value));
291     EXPECT_EQ(DEFAULT_FORMAT, value);
292 
293     EXPECT_OK(mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &value));
294     EXPECT_LE(0, value);
295     EXPECT_GE(BufferQueue::NUM_BUFFER_SLOTS, value);
296 
297     EXPECT_OK(mProducer->query(NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &value));
298     EXPECT_FALSE(value); // Can't run behind when we haven't touched the queue
299 
300     EXPECT_OK(mProducer->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &value));
301     EXPECT_EQ(DEFAULT_CONSUMER_USAGE_BITS, value);
302 
303 }
304 
TEST_F(IGraphicBufferProducerTest,Query_ReturnsError)305 TEST_F(IGraphicBufferProducerTest, Query_ReturnsError) {
306     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
307 
308     // One past the end of the last 'query' enum value. Update this if we add more enums.
309     const int NATIVE_WINDOW_QUERY_LAST_OFF_BY_ONE = NATIVE_WINDOW_BUFFER_AGE + 1;
310 
311     int value;
312     // What was out of range
313     EXPECT_EQ(BAD_VALUE, mProducer->query(/*what*/-1, &value));
314     EXPECT_EQ(BAD_VALUE, mProducer->query(/*what*/0xDEADBEEF, &value));
315     EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_QUERY_LAST_OFF_BY_ONE, &value));
316 
317     // Some enums from window.h are 'invalid'
318     EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER, &value));
319     EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_CONCRETE_TYPE, &value));
320     EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_DEFAULT_WIDTH, &value));
321     EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_DEFAULT_HEIGHT, &value));
322     EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_TRANSFORM_HINT, &value));
323     // TODO: Consider documented the above enums as unsupported or make a new enum for IGBP
324 
325     // Value was NULL
326     EXPECT_EQ(BAD_VALUE, mProducer->query(NATIVE_WINDOW_FORMAT, /*value*/NULL));
327 
328     ASSERT_OK(mConsumer->consumerDisconnect());
329 
330     // BQ was abandoned
331     EXPECT_EQ(NO_INIT, mProducer->query(NATIVE_WINDOW_FORMAT, &value));
332 
333     // TODO: other things in window.h that are supported by Surface::query
334     // but not by BufferQueue::query
335 }
336 
337 // TODO: queue under more complicated situations not involving just a single buffer
TEST_F(IGraphicBufferProducerTest,Queue_Succeeds)338 TEST_F(IGraphicBufferProducerTest, Queue_Succeeds) {
339     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
340 
341     int dequeuedSlot = -1;
342     sp<Fence> dequeuedFence;
343 
344 
345     ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
346             (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
347                                      DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
348                                      TEST_PRODUCER_USAGE_BITS, nullptr)));
349 
350     EXPECT_LE(0, dequeuedSlot);
351     EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, dequeuedSlot);
352 
353     // Request the buffer (pre-requisite for queueing)
354     sp<GraphicBuffer> dequeuedBuffer;
355     ASSERT_OK(mProducer->requestBuffer(dequeuedSlot, &dequeuedBuffer));
356 
357     // A generic "valid" input
358     IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
359     IGraphicBufferProducer::QueueBufferOutput output;
360 
361     // Queue the buffer back into the BQ
362     ASSERT_OK(mProducer->queueBuffer(dequeuedSlot, input, &output));
363 
364     {
365         EXPECT_EQ(DEFAULT_WIDTH, output.width);
366         EXPECT_EQ(DEFAULT_HEIGHT, output.height);
367         EXPECT_EQ(DEFAULT_TRANSFORM_HINT, output.transformHint);
368         // Since queueBuffer was called exactly once
369         EXPECT_EQ(1u, output.numPendingBuffers);
370         EXPECT_EQ(2u, output.nextFrameNumber);
371     }
372 
373     // Buffer was not in the dequeued state
374     EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output));
375 }
376 
TEST_F(IGraphicBufferProducerTest,Queue_ReturnsError)377 TEST_F(IGraphicBufferProducerTest, Queue_ReturnsError) {
378     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
379 
380     // Invalid slot number
381     {
382         // A generic "valid" input
383         IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
384         IGraphicBufferProducer::QueueBufferOutput output;
385 
386         EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(/*slot*/-1, input, &output));
387         EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(/*slot*/0xDEADBEEF, input, &output));
388         EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(BufferQueue::NUM_BUFFER_SLOTS,
389                                                     input, &output));
390     }
391 
392     // Slot was not in the dequeued state (all slots start out in Free state)
393     {
394         IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
395         IGraphicBufferProducer::QueueBufferOutput output;
396 
397         EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(/*slot*/0, input, &output));
398     }
399 
400     // Put the slot into the "dequeued" state for the rest of the test
401     int dequeuedSlot = -1;
402     sp<Fence> dequeuedFence;
403 
404     ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
405             (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
406                                      DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
407                                      TEST_PRODUCER_USAGE_BITS, nullptr)));
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                                      DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
476                                      TEST_PRODUCER_USAGE_BITS, nullptr)));
477 
478     // No return code, but at least test that it doesn't blow up...
479     // TODO: add a return code
480     mProducer->cancelBuffer(dequeuedSlot, dequeuedFence);
481 }
482 
TEST_F(IGraphicBufferProducerTest,SetMaxDequeuedBufferCount_Succeeds)483 TEST_F(IGraphicBufferProducerTest, SetMaxDequeuedBufferCount_Succeeds) {
484     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
485     int minUndequeuedBuffers;
486     ASSERT_OK(mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
487             &minUndequeuedBuffers));
488 
489     const int minBuffers = 1;
490     const int maxBuffers = BufferQueue::NUM_BUFFER_SLOTS - minUndequeuedBuffers;
491 
492     ASSERT_OK(mProducer->setAsyncMode(false)) << "async mode: " << false;
493     ASSERT_OK(mProducer->setMaxDequeuedBufferCount(minBuffers))
494             << "bufferCount: " << minBuffers;
495 
496     // Should now be able to dequeue up to minBuffers times
497     DequeueBufferResult result;
498     for (int i = 0; i < minBuffers; ++i) {
499 
500         EXPECT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
501                 (dequeueBuffer(DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
502                               TEST_PRODUCER_USAGE_BITS, &result)))
503                 << "iteration: " << i << ", slot: " << result.slot;
504     }
505 
506     ASSERT_OK(mProducer->setMaxDequeuedBufferCount(maxBuffers));
507 
508     // queue the first buffer to enable max dequeued buffer count checking
509     IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
510     IGraphicBufferProducer::QueueBufferOutput output;
511     sp<GraphicBuffer> buffer;
512     ASSERT_OK(mProducer->requestBuffer(result.slot, &buffer));
513     ASSERT_OK(mProducer->queueBuffer(result.slot, input, &output));
514 
515 
516     // Should now be able to dequeue up to maxBuffers times
517     int dequeuedSlot = -1;
518     sp<Fence> dequeuedFence;
519     for (int i = 0; i < maxBuffers; ++i) {
520 
521         EXPECT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
522                 (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
523                                          DEFAULT_WIDTH, DEFAULT_HEIGHT,
524                                          DEFAULT_FORMAT,
525                                          TEST_PRODUCER_USAGE_BITS, nullptr)))
526                 << "iteration: " << i << ", slot: " << dequeuedSlot;
527     }
528 
529     // Cancel a buffer, so we can decrease the buffer count
530     ASSERT_OK(mProducer->cancelBuffer(dequeuedSlot, dequeuedFence));
531 
532     // Should now be able to decrease the max dequeued count by 1
533     ASSERT_OK(mProducer->setMaxDequeuedBufferCount(maxBuffers-1));
534 }
535 
TEST_F(IGraphicBufferProducerTest,SetMaxDequeuedBufferCount_Fails)536 TEST_F(IGraphicBufferProducerTest, SetMaxDequeuedBufferCount_Fails) {
537     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
538     int minUndequeuedBuffers;
539     ASSERT_OK(mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
540                                &minUndequeuedBuffers));
541 
542     const int minBuffers = 1;
543     const int maxBuffers = BufferQueue::NUM_BUFFER_SLOTS - minUndequeuedBuffers;
544 
545     ASSERT_OK(mProducer->setAsyncMode(false)) << "async mode: " << false;
546     // Buffer count was out of range
547     EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(0))
548             << "bufferCount: " << 0;
549     EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(maxBuffers + 1))
550             << "bufferCount: " << maxBuffers + 1;
551 
552     // Set max dequeue count to 2
553     ASSERT_OK(mProducer->setMaxDequeuedBufferCount(2));
554     // Dequeue 2 buffers
555     int dequeuedSlot = -1;
556     sp<Fence> dequeuedFence;
557     for (int i = 0; i < 2; i++) {
558         ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
559                 (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
560                                          DEFAULT_WIDTH, DEFAULT_HEIGHT,
561                                          DEFAULT_FORMAT,
562                                          TEST_PRODUCER_USAGE_BITS, nullptr)))
563                 << "slot: " << dequeuedSlot;
564     }
565 
566     // Client has too many buffers dequeued
567     EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(1))
568             << "bufferCount: " << minBuffers;
569 
570     // Abandon buffer queue
571     ASSERT_OK(mConsumer->consumerDisconnect());
572 
573     // Fail because the buffer queue was abandoned
574     EXPECT_EQ(NO_INIT, mProducer->setMaxDequeuedBufferCount(minBuffers))
575             << "bufferCount: " << minBuffers;
576 
577 }
578 
TEST_F(IGraphicBufferProducerTest,SetAsyncMode_Succeeds)579 TEST_F(IGraphicBufferProducerTest, SetAsyncMode_Succeeds) {
580     ASSERT_OK(mConsumer->setMaxAcquiredBufferCount(1)) << "maxAcquire: " << 1;
581     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
582     ASSERT_OK(mProducer->setAsyncMode(true)) << "async mode: " << true;
583     ASSERT_OK(mProducer->setMaxDequeuedBufferCount(1)) << "maxDequeue: " << 1;
584 
585     int dequeuedSlot = -1;
586     sp<Fence> dequeuedFence;
587     IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
588     IGraphicBufferProducer::QueueBufferOutput output;
589     sp<GraphicBuffer> dequeuedBuffer;
590 
591     // Should now be able to queue/dequeue as many buffers as we want without
592     // blocking
593     for (int i = 0; i < 5; ++i) {
594         ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
595                 (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
596                 DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
597                 TEST_PRODUCER_USAGE_BITS, nullptr)))
598                 << "slot : " << dequeuedSlot;
599         ASSERT_OK(mProducer->requestBuffer(dequeuedSlot, &dequeuedBuffer));
600         ASSERT_OK(mProducer->queueBuffer(dequeuedSlot, input, &output));
601     }
602 }
603 
TEST_F(IGraphicBufferProducerTest,SetAsyncMode_Fails)604 TEST_F(IGraphicBufferProducerTest, SetAsyncMode_Fails) {
605     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
606     // Prerequisite to fail out a valid setBufferCount call
607     {
608         int dequeuedSlot = -1;
609         sp<Fence> dequeuedFence;
610 
611         ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
612                 (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
613                 DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
614                 TEST_PRODUCER_USAGE_BITS, nullptr)))
615                 << "slot: " << dequeuedSlot;
616     }
617 
618     // Abandon buffer queue
619     ASSERT_OK(mConsumer->consumerDisconnect());
620 
621     // Fail because the buffer queue was abandoned
622     EXPECT_EQ(NO_INIT, mProducer->setAsyncMode(false)) << "asyncMode: "
623             << false;
624 }
625 
TEST_F(IGraphicBufferProducerTest,DisconnectedProducerReturnsError_dequeueBuffer)626 TEST_F(IGraphicBufferProducerTest,
627         DisconnectedProducerReturnsError_dequeueBuffer) {
628     int slot = -1;
629     sp<Fence> fence;
630 
631     ASSERT_EQ(NO_INIT, mProducer->dequeueBuffer(&slot, &fence, DEFAULT_WIDTH,
632             DEFAULT_HEIGHT, DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS, nullptr));
633 }
634 
TEST_F(IGraphicBufferProducerTest,DisconnectedProducerReturnsError_detachNextBuffer)635 TEST_F(IGraphicBufferProducerTest,
636         DisconnectedProducerReturnsError_detachNextBuffer) {
637     sp<Fence> fence;
638     sp<GraphicBuffer> buffer;
639 
640     ASSERT_EQ(NO_INIT, mProducer->detachNextBuffer(&buffer, &fence));
641 }
642 
TEST_F(IGraphicBufferProducerTest,DisconnectedProducerReturnsError_requestBuffer)643 TEST_F(IGraphicBufferProducerTest,
644         DisconnectedProducerReturnsError_requestBuffer) {
645     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
646 
647     int slot = -1;
648     sp<Fence> fence;
649 
650     ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
651             (mProducer->dequeueBuffer(&slot, &fence, DEFAULT_WIDTH,
652             DEFAULT_HEIGHT, DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS,
653             nullptr)));
654 
655     EXPECT_LE(0, slot);
656     EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, slot);
657 
658     ASSERT_OK(mProducer->disconnect(TEST_API));
659 
660     sp<GraphicBuffer> buffer;
661 
662     ASSERT_EQ(NO_INIT, mProducer->requestBuffer(slot, &buffer));
663 }
664 
665 
TEST_F(IGraphicBufferProducerTest,DisconnectedProducerReturnsError_detachBuffer)666 TEST_F(IGraphicBufferProducerTest,
667         DisconnectedProducerReturnsError_detachBuffer) {
668     int slot = -1;
669     sp<Fence> fence;
670     sp<GraphicBuffer> buffer;
671 
672     setupDequeueRequestBuffer(&slot, &fence, &buffer);
673 
674     ASSERT_OK(mProducer->disconnect(TEST_API));
675 
676     ASSERT_EQ(NO_INIT, mProducer->detachBuffer(slot));
677 }
678 
TEST_F(IGraphicBufferProducerTest,DisconnectedProducerReturnsError_queueBuffer)679 TEST_F(IGraphicBufferProducerTest,
680         DisconnectedProducerReturnsError_queueBuffer) {
681     int slot = -1;
682     sp<Fence> fence;
683     sp<GraphicBuffer> buffer;
684 
685     setupDequeueRequestBuffer(&slot, &fence, &buffer);
686 
687     ASSERT_OK(mProducer->disconnect(TEST_API));
688 
689     // A generic "valid" input
690     IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
691     IGraphicBufferProducer::QueueBufferOutput output;
692 
693     ASSERT_EQ(NO_INIT, mProducer->queueBuffer(slot, input, &output));
694 }
695 
TEST_F(IGraphicBufferProducerTest,DisconnectedProducerReturnsError_cancelBuffer)696 TEST_F(IGraphicBufferProducerTest,
697         DisconnectedProducerReturnsError_cancelBuffer) {
698     int slot = -1;
699     sp<Fence> fence;
700     sp<GraphicBuffer> buffer;
701 
702     setupDequeueRequestBuffer(&slot, &fence, &buffer);
703 
704     ASSERT_OK(mProducer->disconnect(TEST_API));
705 
706     ASSERT_EQ(NO_INIT, mProducer->cancelBuffer(slot, fence));
707 }
708 
TEST_F(IGraphicBufferProducerTest,DisconnectedProducerReturnsError_attachBuffer)709 TEST_F(IGraphicBufferProducerTest,
710         DisconnectedProducerReturnsError_attachBuffer) {
711     int slot = -1;
712     sp<Fence> fence;
713     sp<GraphicBuffer> buffer;
714 
715     setupDequeueRequestBuffer(&slot, &fence, &buffer);
716 
717     ASSERT_OK(mProducer->detachBuffer(slot));
718 
719     ASSERT_OK(mProducer->disconnect(TEST_API));
720 
721     ASSERT_EQ(NO_INIT, mProducer->attachBuffer(&slot, buffer));
722 }
723 
724 } // namespace android
725