• 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         uint64_t nextFrameNumber;
374 
375         output.deflate(&width, &height, &transformHint, &numPendingBuffers,
376                 &nextFrameNumber);
377 
378         EXPECT_EQ(DEFAULT_WIDTH, width);
379         EXPECT_EQ(DEFAULT_HEIGHT, height);
380         EXPECT_EQ(DEFAULT_TRANSFORM_HINT, transformHint);
381         EXPECT_EQ(1u, numPendingBuffers); // since queueBuffer was called exactly once
382         EXPECT_EQ(2u, nextFrameNumber);
383     }
384 
385     // Buffer was not in the dequeued state
386     EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output));
387 }
388 
TEST_F(IGraphicBufferProducerTest,Queue_ReturnsError)389 TEST_F(IGraphicBufferProducerTest, Queue_ReturnsError) {
390     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
391 
392     // Invalid slot number
393     {
394         // A generic "valid" input
395         IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
396         IGraphicBufferProducer::QueueBufferOutput output;
397 
398         EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(/*slot*/-1, input, &output));
399         EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(/*slot*/0xDEADBEEF, input, &output));
400         EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(BufferQueue::NUM_BUFFER_SLOTS,
401                                                     input, &output));
402     }
403 
404     // Slot was not in the dequeued state (all slots start out in Free state)
405     {
406         IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
407         IGraphicBufferProducer::QueueBufferOutput output;
408 
409         EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(/*slot*/0, input, &output));
410     }
411 
412     // Put the slot into the "dequeued" state for the rest of the test
413     int dequeuedSlot = -1;
414     sp<Fence> dequeuedFence;
415 
416     ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
417             (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
418                                      DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
419                                      TEST_PRODUCER_USAGE_BITS)));
420 
421     // Slot was enqueued without requesting a buffer
422     {
423         IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
424         IGraphicBufferProducer::QueueBufferOutput output;
425 
426         EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output));
427     }
428 
429     // Request the buffer so that the rest of the tests don't fail on earlier checks.
430     sp<GraphicBuffer> dequeuedBuffer;
431     ASSERT_OK(mProducer->requestBuffer(dequeuedSlot, &dequeuedBuffer));
432 
433     // Fence was NULL
434     {
435         sp<Fence> nullFence = NULL;
436 
437         IGraphicBufferProducer::QueueBufferInput input =
438                 QueueBufferInputBuilder().setFence(nullFence).build();
439         IGraphicBufferProducer::QueueBufferOutput output;
440 
441         EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output));
442     }
443 
444     // Scaling mode was unknown
445     {
446         IGraphicBufferProducer::QueueBufferInput input =
447                 QueueBufferInputBuilder().setScalingMode(-1).build();
448         IGraphicBufferProducer::QueueBufferOutput output;
449 
450         EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output));
451 
452         input = QueueBufferInputBuilder().setScalingMode(0xDEADBEEF).build();
453 
454         EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output));
455     }
456 
457     // Crop rect is out of bounds of the buffer dimensions
458     {
459         IGraphicBufferProducer::QueueBufferInput input =
460                 QueueBufferInputBuilder().setCrop(Rect(DEFAULT_WIDTH + 1, DEFAULT_HEIGHT + 1))
461                 .build();
462         IGraphicBufferProducer::QueueBufferOutput output;
463 
464         EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output));
465     }
466 
467     // Abandon the buffer queue so that the last test fails
468     ASSERT_OK(mConsumer->consumerDisconnect());
469 
470     // The buffer queue has been abandoned.
471     {
472         IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
473         IGraphicBufferProducer::QueueBufferOutput output;
474 
475         EXPECT_EQ(NO_INIT, mProducer->queueBuffer(dequeuedSlot, input, &output));
476     }
477 }
478 
TEST_F(IGraphicBufferProducerTest,CancelBuffer_DoesntCrash)479 TEST_F(IGraphicBufferProducerTest, CancelBuffer_DoesntCrash) {
480     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
481 
482     int dequeuedSlot = -1;
483     sp<Fence> dequeuedFence;
484 
485     ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
486             (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
487                                      DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
488                                      TEST_PRODUCER_USAGE_BITS)));
489 
490     // No return code, but at least test that it doesn't blow up...
491     // TODO: add a return code
492     mProducer->cancelBuffer(dequeuedSlot, dequeuedFence);
493 }
494 
TEST_F(IGraphicBufferProducerTest,SetMaxDequeuedBufferCount_Succeeds)495 TEST_F(IGraphicBufferProducerTest, SetMaxDequeuedBufferCount_Succeeds) {
496     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
497     int minUndequeuedBuffers;
498     ASSERT_OK(mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
499             &minUndequeuedBuffers));
500 
501     const int minBuffers = 1;
502     const int maxBuffers = BufferQueue::NUM_BUFFER_SLOTS - minUndequeuedBuffers;
503 
504     ASSERT_OK(mProducer->setAsyncMode(false)) << "async mode: " << false;
505     ASSERT_OK(mProducer->setMaxDequeuedBufferCount(minBuffers))
506             << "bufferCount: " << minBuffers;
507 
508     // Should now be able to dequeue up to minBuffers times
509     DequeueBufferResult result;
510     for (int i = 0; i < minBuffers; ++i) {
511 
512         EXPECT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
513                 (dequeueBuffer(DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
514                               TEST_PRODUCER_USAGE_BITS, &result)))
515                 << "iteration: " << i << ", slot: " << result.slot;
516     }
517 
518     ASSERT_OK(mProducer->setMaxDequeuedBufferCount(maxBuffers));
519 
520     // queue the first buffer to enable max dequeued buffer count checking
521     IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
522     IGraphicBufferProducer::QueueBufferOutput output;
523     sp<GraphicBuffer> buffer;
524     ASSERT_OK(mProducer->requestBuffer(result.slot, &buffer));
525     ASSERT_OK(mProducer->queueBuffer(result.slot, input, &output));
526 
527 
528     // Should now be able to dequeue up to maxBuffers times
529     int dequeuedSlot = -1;
530     sp<Fence> dequeuedFence;
531     for (int i = 0; i < maxBuffers; ++i) {
532 
533         EXPECT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
534                 (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
535                                          DEFAULT_WIDTH, DEFAULT_HEIGHT,
536                                          DEFAULT_FORMAT,
537                                          TEST_PRODUCER_USAGE_BITS)))
538                 << "iteration: " << i << ", slot: " << dequeuedSlot;
539     }
540 
541     // Cancel a buffer, so we can decrease the buffer count
542     ASSERT_OK(mProducer->cancelBuffer(dequeuedSlot, dequeuedFence));
543 
544     // Should now be able to decrease the max dequeued count by 1
545     ASSERT_OK(mProducer->setMaxDequeuedBufferCount(maxBuffers-1));
546 }
547 
TEST_F(IGraphicBufferProducerTest,SetMaxDequeuedBufferCount_Fails)548 TEST_F(IGraphicBufferProducerTest, SetMaxDequeuedBufferCount_Fails) {
549     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
550     int minUndequeuedBuffers;
551     ASSERT_OK(mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
552                                &minUndequeuedBuffers));
553 
554     const int minBuffers = 1;
555     const int maxBuffers = BufferQueue::NUM_BUFFER_SLOTS - minUndequeuedBuffers;
556 
557     ASSERT_OK(mProducer->setAsyncMode(false)) << "async mode: " << false;
558     // Buffer count was out of range
559     EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(0))
560             << "bufferCount: " << 0;
561     EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(maxBuffers + 1))
562             << "bufferCount: " << maxBuffers + 1;
563 
564     // Set max dequeue count to 2
565     ASSERT_OK(mProducer->setMaxDequeuedBufferCount(2));
566     // Dequeue 2 buffers
567     int dequeuedSlot = -1;
568     sp<Fence> dequeuedFence;
569     for (int i = 0; i < 2; i++) {
570         ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
571                 (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
572                                          DEFAULT_WIDTH, DEFAULT_HEIGHT,
573                                          DEFAULT_FORMAT,
574                                          TEST_PRODUCER_USAGE_BITS)))
575                 << "slot: " << dequeuedSlot;
576     }
577 
578     // Client has too many buffers dequeued
579     EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(1))
580             << "bufferCount: " << minBuffers;
581 
582     // Abandon buffer queue
583     ASSERT_OK(mConsumer->consumerDisconnect());
584 
585     // Fail because the buffer queue was abandoned
586     EXPECT_EQ(NO_INIT, mProducer->setMaxDequeuedBufferCount(minBuffers))
587             << "bufferCount: " << minBuffers;
588 
589 }
590 
TEST_F(IGraphicBufferProducerTest,SetAsyncMode_Succeeds)591 TEST_F(IGraphicBufferProducerTest, SetAsyncMode_Succeeds) {
592     ASSERT_OK(mConsumer->setMaxAcquiredBufferCount(1)) << "maxAcquire: " << 1;
593     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
594     ASSERT_OK(mProducer->setAsyncMode(true)) << "async mode: " << true;
595     ASSERT_OK(mProducer->setMaxDequeuedBufferCount(1)) << "maxDequeue: " << 1;
596 
597     int dequeuedSlot = -1;
598     sp<Fence> dequeuedFence;
599     IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
600     IGraphicBufferProducer::QueueBufferOutput output;
601     sp<GraphicBuffer> dequeuedBuffer;
602 
603     // Should now be able to queue/dequeue as many buffers as we want without
604     // blocking
605     for (int i = 0; i < 5; ++i) {
606         ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
607                 (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
608                 DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
609                 TEST_PRODUCER_USAGE_BITS))) << "slot : " << dequeuedSlot;
610         ASSERT_OK(mProducer->requestBuffer(dequeuedSlot, &dequeuedBuffer));
611         ASSERT_OK(mProducer->queueBuffer(dequeuedSlot, input, &output));
612     }
613 }
614 
TEST_F(IGraphicBufferProducerTest,SetAsyncMode_Fails)615 TEST_F(IGraphicBufferProducerTest, SetAsyncMode_Fails) {
616     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
617     // Prerequisite to fail out a valid setBufferCount call
618     {
619         int dequeuedSlot = -1;
620         sp<Fence> dequeuedFence;
621 
622         ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
623                 (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
624                 DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
625                 TEST_PRODUCER_USAGE_BITS))) << "slot: " << dequeuedSlot;
626     }
627 
628     // Abandon buffer queue
629     ASSERT_OK(mConsumer->consumerDisconnect());
630 
631     // Fail because the buffer queue was abandoned
632     EXPECT_EQ(NO_INIT, mProducer->setAsyncMode(false)) << "asyncMode: "
633             << false;
634 }
635 
TEST_F(IGraphicBufferProducerTest,DisconnectedProducerReturnsError_dequeueBuffer)636 TEST_F(IGraphicBufferProducerTest,
637         DisconnectedProducerReturnsError_dequeueBuffer) {
638     int slot = -1;
639     sp<Fence> fence;
640 
641     ASSERT_EQ(NO_INIT, mProducer->dequeueBuffer(&slot, &fence, DEFAULT_WIDTH,
642             DEFAULT_HEIGHT, DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS));
643 }
644 
TEST_F(IGraphicBufferProducerTest,DisconnectedProducerReturnsError_detachNextBuffer)645 TEST_F(IGraphicBufferProducerTest,
646         DisconnectedProducerReturnsError_detachNextBuffer) {
647     sp<Fence> fence;
648     sp<GraphicBuffer> buffer;
649 
650     ASSERT_EQ(NO_INIT, mProducer->detachNextBuffer(&buffer, &fence));
651 }
652 
TEST_F(IGraphicBufferProducerTest,DisconnectedProducerReturnsError_requestBuffer)653 TEST_F(IGraphicBufferProducerTest,
654         DisconnectedProducerReturnsError_requestBuffer) {
655     ASSERT_NO_FATAL_FAILURE(ConnectProducer());
656 
657     int slot = -1;
658     sp<Fence> fence;
659 
660     ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
661             (mProducer->dequeueBuffer(&slot, &fence, DEFAULT_WIDTH,
662             DEFAULT_HEIGHT, DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS)));
663 
664     EXPECT_LE(0, slot);
665     EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, slot);
666 
667     ASSERT_OK(mProducer->disconnect(TEST_API));
668 
669     sp<GraphicBuffer> buffer;
670 
671     ASSERT_EQ(NO_INIT, mProducer->requestBuffer(slot, &buffer));
672 }
673 
674 
TEST_F(IGraphicBufferProducerTest,DisconnectedProducerReturnsError_detachBuffer)675 TEST_F(IGraphicBufferProducerTest,
676         DisconnectedProducerReturnsError_detachBuffer) {
677     int slot = -1;
678     sp<Fence> fence;
679     sp<GraphicBuffer> buffer;
680 
681     setupDequeueRequestBuffer(&slot, &fence, &buffer);
682 
683     ASSERT_OK(mProducer->disconnect(TEST_API));
684 
685     ASSERT_EQ(NO_INIT, mProducer->detachBuffer(slot));
686 }
687 
TEST_F(IGraphicBufferProducerTest,DisconnectedProducerReturnsError_queueBuffer)688 TEST_F(IGraphicBufferProducerTest,
689         DisconnectedProducerReturnsError_queueBuffer) {
690     int slot = -1;
691     sp<Fence> fence;
692     sp<GraphicBuffer> buffer;
693 
694     setupDequeueRequestBuffer(&slot, &fence, &buffer);
695 
696     ASSERT_OK(mProducer->disconnect(TEST_API));
697 
698     // A generic "valid" input
699     IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
700     IGraphicBufferProducer::QueueBufferOutput output;
701 
702     ASSERT_EQ(NO_INIT, mProducer->queueBuffer(slot, input, &output));
703 }
704 
TEST_F(IGraphicBufferProducerTest,DisconnectedProducerReturnsError_cancelBuffer)705 TEST_F(IGraphicBufferProducerTest,
706         DisconnectedProducerReturnsError_cancelBuffer) {
707     int slot = -1;
708     sp<Fence> fence;
709     sp<GraphicBuffer> buffer;
710 
711     setupDequeueRequestBuffer(&slot, &fence, &buffer);
712 
713     ASSERT_OK(mProducer->disconnect(TEST_API));
714 
715     ASSERT_EQ(NO_INIT, mProducer->cancelBuffer(slot, fence));
716 }
717 
TEST_F(IGraphicBufferProducerTest,DisconnectedProducerReturnsError_attachBuffer)718 TEST_F(IGraphicBufferProducerTest,
719         DisconnectedProducerReturnsError_attachBuffer) {
720     int slot = -1;
721     sp<Fence> fence;
722     sp<GraphicBuffer> buffer;
723 
724     setupDequeueRequestBuffer(&slot, &fence, &buffer);
725 
726     ASSERT_OK(mProducer->detachBuffer(slot));
727 
728     ASSERT_OK(mProducer->disconnect(TEST_API));
729 
730     ASSERT_EQ(NO_INIT, mProducer->attachBuffer(&slot, buffer));
731 }
732 
733 } // namespace android
734