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
43namespace android {
44
45namespace {
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
69class IGraphicBufferProducerTest : public ::testing::Test {
70protected:
71
72    IGraphicBufferProducerTest() {}
73
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
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
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.
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.
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 {
122        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
132        IGraphicBufferProducer::QueueBufferInput build() {
133            return IGraphicBufferProducer::QueueBufferInput(
134                    timestamp,
135                    isAutoTimestamp,
136                    dataSpace,
137                    crop,
138                    scalingMode,
139                    transform,
140                    fence);
141        }
142
143        QueueBufferInputBuilder& setTimestamp(int64_t timestamp) {
144            this->timestamp = timestamp;
145            return *this;
146        }
147
148        QueueBufferInputBuilder& setIsAutoTimestamp(bool isAutoTimestamp) {
149            this->isAutoTimestamp = isAutoTimestamp;
150            return *this;
151        }
152
153        QueueBufferInputBuilder& setDataSpace(android_dataspace dataSpace) {
154            this->dataSpace = dataSpace;
155            return *this;
156        }
157
158        QueueBufferInputBuilder& setCrop(Rect crop) {
159            this->crop = crop;
160            return *this;
161        }
162
163        QueueBufferInputBuilder& setScalingMode(int scalingMode) {
164            this->scalingMode = scalingMode;
165            return *this;
166        }
167
168        QueueBufferInputBuilder& setTransform(uint32_t transform) {
169            this->transform = transform;
170            return *this;
171        }
172
173        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
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
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
218private: // hide from test body
219    sp<DummyConsumer> mDC;
220
221protected: // accessible from test body
222    sp<IGraphicBufferProducer> mProducer;
223    sp<IGraphicBufferConsumer> mConsumer;
224};
225
226TEST_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
244TEST_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
262TEST_F(IGraphicBufferProducerTest, Disconnect_Succeeds) {
263    ASSERT_NO_FATAL_FAILURE(ConnectProducer());
264
265    ASSERT_OK(mProducer->disconnect(TEST_API));
266}
267
268
269TEST_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
280TEST_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
305TEST_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
338TEST_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
377TEST_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
467TEST_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
483TEST_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
536TEST_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
579TEST_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
604TEST_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
626TEST_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
635TEST_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
643TEST_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
666TEST_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
679TEST_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
696TEST_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
709TEST_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