BufferQueue_test.cpp revision 0c9a1ed91f8e19887ac43eff5af16e59878c8226
1/*
2 * Copyright (C) 2012 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 "BufferQueue_test"
18//#define LOG_NDEBUG 0
19
20#include "DummyConsumer.h"
21
22#include <gui/BufferItem.h>
23#include <gui/BufferQueue.h>
24#include <gui/IProducerListener.h>
25
26#include <ui/GraphicBuffer.h>
27
28#include <binder/IPCThreadState.h>
29#include <binder/IServiceManager.h>
30#include <binder/ProcessState.h>
31
32#include <utils/String8.h>
33#include <utils/threads.h>
34
35#include <gtest/gtest.h>
36
37#include <thread>
38
39using namespace std::chrono_literals;
40
41namespace android {
42
43class BufferQueueTest : public ::testing::Test {
44
45public:
46protected:
47    BufferQueueTest() {
48        const ::testing::TestInfo* const testInfo =
49            ::testing::UnitTest::GetInstance()->current_test_info();
50        ALOGV("Begin test: %s.%s", testInfo->test_case_name(),
51                testInfo->name());
52    }
53
54    ~BufferQueueTest() {
55        const ::testing::TestInfo* const testInfo =
56            ::testing::UnitTest::GetInstance()->current_test_info();
57        ALOGV("End test:   %s.%s", testInfo->test_case_name(),
58                testInfo->name());
59    }
60
61    void GetMinUndequeuedBufferCount(int* bufferCount) {
62        ASSERT_TRUE(bufferCount != NULL);
63        ASSERT_EQ(OK, mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
64                    bufferCount));
65        ASSERT_GE(*bufferCount, 0);
66    }
67
68    void createBufferQueue() {
69        BufferQueue::createBufferQueue(&mProducer, &mConsumer);
70    }
71
72    void testBufferItem(const IGraphicBufferProducer::QueueBufferInput& input,
73            const BufferItem& item) {
74        int64_t timestamp;
75        bool isAutoTimestamp;
76        android_dataspace dataSpace;
77        Rect crop;
78        int scalingMode;
79        uint32_t transform;
80        sp<Fence> fence;
81
82        input.deflate(&timestamp, &isAutoTimestamp, &dataSpace, &crop,
83                &scalingMode, &transform, &fence, NULL);
84        ASSERT_EQ(timestamp, item.mTimestamp);
85        ASSERT_EQ(isAutoTimestamp, item.mIsAutoTimestamp);
86        ASSERT_EQ(dataSpace, item.mDataSpace);
87        ASSERT_EQ(crop, item.mCrop);
88        ASSERT_EQ(static_cast<uint32_t>(scalingMode), item.mScalingMode);
89        ASSERT_EQ(transform, item.mTransform);
90        ASSERT_EQ(fence, item.mFence);
91    }
92
93    sp<IGraphicBufferProducer> mProducer;
94    sp<IGraphicBufferConsumer> mConsumer;
95};
96
97static const uint32_t TEST_DATA = 0x12345678u;
98
99// XXX: Tests that fork a process to hold the BufferQueue must run before tests
100// that use a local BufferQueue, or else Binder will get unhappy
101//
102// In one instance this was a crash in the createBufferQueue where the
103// binder call to create a buffer allocator apparently got garbage back.
104// See b/36592665.
105TEST_F(BufferQueueTest, DISABLED_BufferQueueInAnotherProcess) {
106    const String16 PRODUCER_NAME = String16("BQTestProducer");
107    const String16 CONSUMER_NAME = String16("BQTestConsumer");
108
109    pid_t forkPid = fork();
110    ASSERT_NE(forkPid, -1);
111
112    if (forkPid == 0) {
113        // Child process
114        sp<IGraphicBufferProducer> producer;
115        sp<IGraphicBufferConsumer> consumer;
116        BufferQueue::createBufferQueue(&producer, &consumer);
117        sp<IServiceManager> serviceManager = defaultServiceManager();
118        serviceManager->addService(PRODUCER_NAME, IInterface::asBinder(producer));
119        serviceManager->addService(CONSUMER_NAME, IInterface::asBinder(consumer));
120        ProcessState::self()->startThreadPool();
121        IPCThreadState::self()->joinThreadPool();
122        LOG_ALWAYS_FATAL("Shouldn't be here");
123    }
124
125    sp<IServiceManager> serviceManager = defaultServiceManager();
126    sp<IBinder> binderProducer =
127        serviceManager->getService(PRODUCER_NAME);
128    mProducer = interface_cast<IGraphicBufferProducer>(binderProducer);
129    EXPECT_TRUE(mProducer != NULL);
130    sp<IBinder> binderConsumer =
131        serviceManager->getService(CONSUMER_NAME);
132    mConsumer = interface_cast<IGraphicBufferConsumer>(binderConsumer);
133    EXPECT_TRUE(mConsumer != NULL);
134
135    sp<DummyConsumer> dc(new DummyConsumer);
136    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
137    IGraphicBufferProducer::QueueBufferOutput output;
138    ASSERT_EQ(OK,
139            mProducer->connect(NULL, NATIVE_WINDOW_API_CPU, false, &output));
140
141    int slot;
142    sp<Fence> fence;
143    sp<GraphicBuffer> buffer;
144    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
145            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
146                    GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
147    ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
148
149    uint32_t* dataIn;
150    ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
151            reinterpret_cast<void**>(&dataIn)));
152    *dataIn = TEST_DATA;
153    ASSERT_EQ(OK, buffer->unlock());
154
155    IGraphicBufferProducer::QueueBufferInput input(0, false,
156            HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
157            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
158    ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
159
160    BufferItem item;
161    ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
162
163    uint32_t* dataOut;
164    ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
165            reinterpret_cast<void**>(&dataOut)));
166    ASSERT_EQ(*dataOut, TEST_DATA);
167    ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
168}
169
170TEST_F(BufferQueueTest, AcquireBuffer_ExceedsMaxAcquireCount_Fails) {
171    createBufferQueue();
172    sp<DummyConsumer> dc(new DummyConsumer);
173    mConsumer->consumerConnect(dc, false);
174    IGraphicBufferProducer::QueueBufferOutput qbo;
175    mProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, false,
176            &qbo);
177    mProducer->setMaxDequeuedBufferCount(3);
178
179    int slot;
180    sp<Fence> fence;
181    sp<GraphicBuffer> buf;
182    IGraphicBufferProducer::QueueBufferInput qbi(0, false,
183            HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
184            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
185    BufferItem item;
186
187    for (int i = 0; i < 2; i++) {
188        ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
189                mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0,
190                    GRALLOC_USAGE_SW_READ_OFTEN, nullptr));
191        ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
192        ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
193        ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
194    }
195
196    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
197            mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0,
198                GRALLOC_USAGE_SW_READ_OFTEN, nullptr));
199    ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
200    ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
201
202    // Acquire the third buffer, which should fail.
203    ASSERT_EQ(INVALID_OPERATION, mConsumer->acquireBuffer(&item, 0));
204}
205
206TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithIllegalValues_ReturnsError) {
207    createBufferQueue();
208    sp<DummyConsumer> dc(new DummyConsumer);
209    mConsumer->consumerConnect(dc, false);
210
211    EXPECT_EQ(OK, mConsumer->setMaxBufferCount(10));
212    EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(10));
213
214    IGraphicBufferProducer::QueueBufferOutput qbo;
215    mProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, false,
216            &qbo);
217    mProducer->setMaxDequeuedBufferCount(3);
218
219    int minBufferCount;
220    ASSERT_NO_FATAL_FAILURE(GetMinUndequeuedBufferCount(&minBufferCount));
221    EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(
222                minBufferCount - 1));
223
224    EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(0));
225    EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(-3));
226    EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(
227            BufferQueue::MAX_MAX_ACQUIRED_BUFFERS+1));
228    EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(100));
229
230    int slot;
231    sp<Fence> fence;
232    sp<GraphicBuffer> buf;
233    IGraphicBufferProducer::QueueBufferInput qbi(0, false,
234            HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
235            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
236    BufferItem item;
237    EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(3));
238    for (int i = 0; i < 3; i++) {
239        ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
240                mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0,
241                    GRALLOC_USAGE_SW_READ_OFTEN, nullptr));
242        ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
243        ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
244        ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
245    }
246
247    EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(2));
248}
249
250TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithLegalValues_Succeeds) {
251    createBufferQueue();
252    sp<DummyConsumer> dc(new DummyConsumer);
253    mConsumer->consumerConnect(dc, false);
254
255    IGraphicBufferProducer::QueueBufferOutput qbo;
256    mProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, false,
257            &qbo);
258    mProducer->setMaxDequeuedBufferCount(2);
259
260    int minBufferCount;
261    ASSERT_NO_FATAL_FAILURE(GetMinUndequeuedBufferCount(&minBufferCount));
262
263    EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
264    EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(2));
265    EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(minBufferCount));
266
267    int slot;
268    sp<Fence> fence;
269    sp<GraphicBuffer> buf;
270    IGraphicBufferProducer::QueueBufferInput qbi(0, false,
271            HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
272            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
273    BufferItem item;
274
275    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
276            mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0,
277            GRALLOC_USAGE_SW_READ_OFTEN, nullptr));
278    ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
279    ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
280    ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
281
282    EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(3));
283
284    for (int i = 0; i < 2; i++) {
285        ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
286                mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0,
287                GRALLOC_USAGE_SW_READ_OFTEN, nullptr));
288        ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
289        ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
290        ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
291    }
292
293    EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(
294            BufferQueue::MAX_MAX_ACQUIRED_BUFFERS));
295}
296
297TEST_F(BufferQueueTest, SetMaxBufferCountWithLegalValues_Succeeds) {
298    createBufferQueue();
299    sp<DummyConsumer> dc(new DummyConsumer);
300    mConsumer->consumerConnect(dc, false);
301
302    // Test shared buffer mode
303    EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
304}
305
306TEST_F(BufferQueueTest, SetMaxBufferCountWithIllegalValues_ReturnsError) {
307    createBufferQueue();
308    sp<DummyConsumer> dc(new DummyConsumer);
309    mConsumer->consumerConnect(dc, false);
310
311    EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(0));
312    EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(
313            BufferQueue::NUM_BUFFER_SLOTS + 1));
314
315    EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(5));
316    EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(3));
317}
318
319TEST_F(BufferQueueTest, DetachAndReattachOnProducerSide) {
320    createBufferQueue();
321    sp<DummyConsumer> dc(new DummyConsumer);
322    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
323    IGraphicBufferProducer::QueueBufferOutput output;
324    ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
325            NATIVE_WINDOW_API_CPU, false, &output));
326
327    ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(-1)); // Index too low
328    ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(
329                BufferQueueDefs::NUM_BUFFER_SLOTS)); // Index too high
330    ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(0)); // Not dequeued
331
332    int slot;
333    sp<Fence> fence;
334    sp<GraphicBuffer> buffer;
335    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
336            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
337                    GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
338    ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(slot)); // Not requested
339    ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
340    ASSERT_EQ(OK, mProducer->detachBuffer(slot));
341    ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(slot)); // Not dequeued
342
343    sp<GraphicBuffer> safeToClobberBuffer;
344    // Can no longer request buffer from this slot
345    ASSERT_EQ(BAD_VALUE, mProducer->requestBuffer(slot, &safeToClobberBuffer));
346
347    uint32_t* dataIn;
348    ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
349            reinterpret_cast<void**>(&dataIn)));
350    *dataIn = TEST_DATA;
351    ASSERT_EQ(OK, buffer->unlock());
352
353    int newSlot;
354    ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(NULL, safeToClobberBuffer));
355    ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(&newSlot, NULL));
356
357    ASSERT_EQ(OK, mProducer->attachBuffer(&newSlot, buffer));
358    IGraphicBufferProducer::QueueBufferInput input(0, false,
359            HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
360            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
361    ASSERT_EQ(OK, mProducer->queueBuffer(newSlot, input, &output));
362
363    BufferItem item;
364    ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
365
366    uint32_t* dataOut;
367    ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
368            reinterpret_cast<void**>(&dataOut)));
369    ASSERT_EQ(*dataOut, TEST_DATA);
370    ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
371}
372
373TEST_F(BufferQueueTest, DetachAndReattachOnConsumerSide) {
374    createBufferQueue();
375    sp<DummyConsumer> dc(new DummyConsumer);
376    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
377    IGraphicBufferProducer::QueueBufferOutput output;
378    ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
379            NATIVE_WINDOW_API_CPU, false, &output));
380
381    int slot;
382    sp<Fence> fence;
383    sp<GraphicBuffer> buffer;
384    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
385            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
386                    GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
387    ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
388    IGraphicBufferProducer::QueueBufferInput input(0, false,
389            HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
390            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
391    ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
392
393    ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(-1)); // Index too low
394    ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(
395            BufferQueueDefs::NUM_BUFFER_SLOTS)); // Index too high
396    ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(0)); // Not acquired
397
398    BufferItem item;
399    ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
400
401    ASSERT_EQ(OK, mConsumer->detachBuffer(item.mSlot));
402    ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(item.mSlot)); // Not acquired
403
404    uint32_t* dataIn;
405    ASSERT_EQ(OK, item.mGraphicBuffer->lock(
406            GraphicBuffer::USAGE_SW_WRITE_OFTEN,
407            reinterpret_cast<void**>(&dataIn)));
408    *dataIn = TEST_DATA;
409    ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
410
411    int newSlot;
412    sp<GraphicBuffer> safeToClobberBuffer;
413    ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(NULL, safeToClobberBuffer));
414    ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(&newSlot, NULL));
415    ASSERT_EQ(OK, mConsumer->attachBuffer(&newSlot, item.mGraphicBuffer));
416
417    ASSERT_EQ(OK, mConsumer->releaseBuffer(newSlot, 0, EGL_NO_DISPLAY,
418            EGL_NO_SYNC_KHR, Fence::NO_FENCE));
419
420    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
421            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
422                    GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
423    ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
424
425    uint32_t* dataOut;
426    ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
427            reinterpret_cast<void**>(&dataOut)));
428    ASSERT_EQ(*dataOut, TEST_DATA);
429    ASSERT_EQ(OK, buffer->unlock());
430}
431
432TEST_F(BufferQueueTest, MoveFromConsumerToProducer) {
433    createBufferQueue();
434    sp<DummyConsumer> dc(new DummyConsumer);
435    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
436    IGraphicBufferProducer::QueueBufferOutput output;
437    ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
438            NATIVE_WINDOW_API_CPU, false, &output));
439
440    int slot;
441    sp<Fence> fence;
442    sp<GraphicBuffer> buffer;
443    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
444            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
445                    GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
446    ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
447
448    uint32_t* dataIn;
449    ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
450            reinterpret_cast<void**>(&dataIn)));
451    *dataIn = TEST_DATA;
452    ASSERT_EQ(OK, buffer->unlock());
453
454    IGraphicBufferProducer::QueueBufferInput input(0, false,
455            HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
456            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
457    ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
458
459    BufferItem item;
460    ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
461    ASSERT_EQ(OK, mConsumer->detachBuffer(item.mSlot));
462
463    int newSlot;
464    ASSERT_EQ(OK, mProducer->attachBuffer(&newSlot, item.mGraphicBuffer));
465    ASSERT_EQ(OK, mProducer->queueBuffer(newSlot, input, &output));
466    ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
467
468    uint32_t* dataOut;
469    ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
470            reinterpret_cast<void**>(&dataOut)));
471    ASSERT_EQ(*dataOut, TEST_DATA);
472    ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
473}
474
475TEST_F(BufferQueueTest, TestDisallowingAllocation) {
476    createBufferQueue();
477    sp<DummyConsumer> dc(new DummyConsumer);
478    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
479    IGraphicBufferProducer::QueueBufferOutput output;
480    ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
481            NATIVE_WINDOW_API_CPU, true, &output));
482
483    static const uint32_t WIDTH = 320;
484    static const uint32_t HEIGHT = 240;
485
486    ASSERT_EQ(OK, mConsumer->setDefaultBufferSize(WIDTH, HEIGHT));
487
488    int slot;
489    sp<Fence> fence;
490    sp<GraphicBuffer> buffer;
491    // This should return an error since it would require an allocation
492    ASSERT_EQ(OK, mProducer->allowAllocation(false));
493    ASSERT_EQ(WOULD_BLOCK, mProducer->dequeueBuffer(&slot, &fence, 0, 0,
494            0, GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
495
496    // This should succeed, now that we've lifted the prohibition
497    ASSERT_EQ(OK, mProducer->allowAllocation(true));
498    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
499            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
500            GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
501
502    // Release the previous buffer back to the BufferQueue
503    mProducer->cancelBuffer(slot, fence);
504
505    // This should fail since we're requesting a different size
506    ASSERT_EQ(OK, mProducer->allowAllocation(false));
507    ASSERT_EQ(WOULD_BLOCK, mProducer->dequeueBuffer(&slot, &fence,
508            WIDTH * 2, HEIGHT * 2, 0, GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
509}
510
511TEST_F(BufferQueueTest, TestGenerationNumbers) {
512    createBufferQueue();
513    sp<DummyConsumer> dc(new DummyConsumer);
514    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
515    IGraphicBufferProducer::QueueBufferOutput output;
516    ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
517            NATIVE_WINDOW_API_CPU, true, &output));
518
519    ASSERT_EQ(OK, mProducer->setGenerationNumber(1));
520
521    // Get one buffer to play with
522    int slot;
523    sp<Fence> fence;
524    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
525            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
526
527    sp<GraphicBuffer> buffer;
528    ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
529
530    // Ensure that the generation number we set propagates to allocated buffers
531    ASSERT_EQ(1U, buffer->getGenerationNumber());
532
533    ASSERT_EQ(OK, mProducer->detachBuffer(slot));
534
535    ASSERT_EQ(OK, mProducer->setGenerationNumber(2));
536
537    // These should fail, since we've changed the generation number on the queue
538    int outSlot;
539    ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(&outSlot, buffer));
540    ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(&outSlot, buffer));
541
542    buffer->setGenerationNumber(2);
543
544    // This should succeed now that we've changed the buffer's generation number
545    ASSERT_EQ(OK, mProducer->attachBuffer(&outSlot, buffer));
546
547    ASSERT_EQ(OK, mProducer->detachBuffer(outSlot));
548
549    // This should also succeed with the new generation number
550    ASSERT_EQ(OK, mConsumer->attachBuffer(&outSlot, buffer));
551}
552
553TEST_F(BufferQueueTest, TestSharedBufferModeWithoutAutoRefresh) {
554    createBufferQueue();
555    sp<DummyConsumer> dc(new DummyConsumer);
556    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
557    IGraphicBufferProducer::QueueBufferOutput output;
558    ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
559            NATIVE_WINDOW_API_CPU, true, &output));
560
561    ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
562
563    // Get a buffer
564    int sharedSlot;
565    sp<Fence> fence;
566    sp<GraphicBuffer> buffer;
567    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
568            mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0, nullptr));
569    ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
570
571    // Queue the buffer
572    IGraphicBufferProducer::QueueBufferInput input(0, false,
573            HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
574            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
575    ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
576
577    // Repeatedly queue and dequeue a buffer from the producer side, it should
578    // always return the same one. And we won't run out of buffers because it's
579    // always the same one and because async mode gets enabled.
580    int slot;
581    for (int i = 0; i < 5; i++) {
582        ASSERT_EQ(OK, mProducer->dequeueBuffer(
583                &slot, &fence, 0, 0, 0, 0, nullptr));
584        ASSERT_EQ(sharedSlot, slot);
585        ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
586    }
587
588    // acquire the buffer
589    BufferItem item;
590    ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
591    ASSERT_EQ(sharedSlot, item.mSlot);
592    testBufferItem(input, item);
593    ASSERT_EQ(true, item.mQueuedBuffer);
594    ASSERT_EQ(false, item.mAutoRefresh);
595
596    ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
597            EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
598
599    // attempt to acquire a second time should return no buffer available
600    ASSERT_EQ(IGraphicBufferConsumer::NO_BUFFER_AVAILABLE,
601            mConsumer->acquireBuffer(&item, 0));
602}
603
604TEST_F(BufferQueueTest, TestSharedBufferModeWithAutoRefresh) {
605    createBufferQueue();
606    sp<DummyConsumer> dc(new DummyConsumer);
607    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
608    IGraphicBufferProducer::QueueBufferOutput output;
609    ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
610            NATIVE_WINDOW_API_CPU, true, &output));
611
612    ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
613    ASSERT_EQ(OK, mProducer->setAutoRefresh(true));
614
615    // Get a buffer
616    int sharedSlot;
617    sp<Fence> fence;
618    sp<GraphicBuffer> buffer;
619    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
620            mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0, nullptr));
621    ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
622
623    // Queue the buffer
624    IGraphicBufferProducer::QueueBufferInput input(0, false,
625            HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
626            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
627    ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
628
629    // Repeatedly acquire and release a buffer from the consumer side, it should
630    // always return the same one.
631    BufferItem item;
632    for (int i = 0; i < 5; i++) {
633        ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
634        ASSERT_EQ(sharedSlot, item.mSlot);
635        testBufferItem(input, item);
636        ASSERT_EQ(i == 0, item.mQueuedBuffer);
637        ASSERT_EQ(true, item.mAutoRefresh);
638
639        ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
640                EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
641    }
642
643    // Repeatedly queue and dequeue a buffer from the producer side, it should
644    // always return the same one.
645    int slot;
646    for (int i = 0; i < 5; i++) {
647        ASSERT_EQ(OK, mProducer->dequeueBuffer(
648                &slot, &fence, 0, 0, 0, 0, nullptr));
649        ASSERT_EQ(sharedSlot, slot);
650        ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
651    }
652
653    // Repeatedly acquire and release a buffer from the consumer side, it should
654    // always return the same one. First grabbing them from the queue and then
655    // when the queue is empty, returning the shared buffer.
656    for (int i = 0; i < 10; i++) {
657        ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
658        ASSERT_EQ(sharedSlot, item.mSlot);
659        ASSERT_EQ(0, item.mTimestamp);
660        ASSERT_EQ(false, item.mIsAutoTimestamp);
661        ASSERT_EQ(HAL_DATASPACE_UNKNOWN, item.mDataSpace);
662        ASSERT_EQ(Rect(0, 0, 1, 1), item.mCrop);
663        ASSERT_EQ(NATIVE_WINDOW_SCALING_MODE_FREEZE, item.mScalingMode);
664        ASSERT_EQ(0u, item.mTransform);
665        ASSERT_EQ(Fence::NO_FENCE, item.mFence);
666        ASSERT_EQ(i == 0, item.mQueuedBuffer);
667        ASSERT_EQ(true, item.mAutoRefresh);
668
669        ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
670                EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
671    }
672}
673
674TEST_F(BufferQueueTest, TestSharedBufferModeUsingAlreadyDequeuedBuffer) {
675    createBufferQueue();
676    sp<DummyConsumer> dc(new DummyConsumer);
677    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
678    IGraphicBufferProducer::QueueBufferOutput output;
679    ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
680            NATIVE_WINDOW_API_CPU, true, &output));
681
682    // Dequeue a buffer
683    int sharedSlot;
684    sp<Fence> fence;
685    sp<GraphicBuffer> buffer;
686    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
687            mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0, nullptr));
688    ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
689
690    // Enable shared buffer mode
691    ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
692
693    // Queue the buffer
694    IGraphicBufferProducer::QueueBufferInput input(0, false,
695            HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
696            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
697    ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
698
699    // Repeatedly queue and dequeue a buffer from the producer side, it should
700    // always return the same one. And we won't run out of buffers because it's
701    // always the same one and because async mode gets enabled.
702    int slot;
703    for (int i = 0; i < 5; i++) {
704        ASSERT_EQ(OK, mProducer->dequeueBuffer(
705                &slot, &fence, 0, 0, 0, 0, nullptr));
706        ASSERT_EQ(sharedSlot, slot);
707        ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
708    }
709
710    // acquire the buffer
711    BufferItem item;
712    ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
713    ASSERT_EQ(sharedSlot, item.mSlot);
714    testBufferItem(input, item);
715    ASSERT_EQ(true, item.mQueuedBuffer);
716    ASSERT_EQ(false, item.mAutoRefresh);
717
718    ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
719            EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
720
721    // attempt to acquire a second time should return no buffer available
722    ASSERT_EQ(IGraphicBufferConsumer::NO_BUFFER_AVAILABLE,
723            mConsumer->acquireBuffer(&item, 0));
724}
725
726TEST_F(BufferQueueTest, TestTimeouts) {
727    createBufferQueue();
728    sp<DummyConsumer> dc(new DummyConsumer);
729    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
730    IGraphicBufferProducer::QueueBufferOutput output;
731    ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
732            NATIVE_WINDOW_API_CPU, true, &output));
733
734    // Fill up the queue. Since the controlledByApp flags are set to true, this
735    // queue should be in non-blocking mode, and we should be recycling the same
736    // two buffers
737    for (int i = 0; i < 5; ++i) {
738        int slot = BufferQueue::INVALID_BUFFER_SLOT;
739        sp<Fence> fence = Fence::NO_FENCE;
740        auto result = mProducer->dequeueBuffer(
741                &slot, &fence, 0, 0, 0, 0, nullptr);
742        if (i < 2) {
743            ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
744                    result);
745        } else {
746            ASSERT_EQ(OK, result);
747        }
748        sp<GraphicBuffer> buffer;
749        ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
750        IGraphicBufferProducer::QueueBufferInput input(0ull, true,
751                HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
752                NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
753        IGraphicBufferProducer::QueueBufferOutput output{};
754        ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
755    }
756
757    const auto TIMEOUT = ms2ns(250);
758    mProducer->setDequeueTimeout(TIMEOUT);
759
760    // Setting a timeout will change the BufferQueue into blocking mode (with
761    // one droppable buffer in the queue and one free from the previous
762    // dequeue/queues), so dequeue and queue two more buffers: one to replace
763    // the current droppable buffer, and a second to max out the buffer count
764    sp<GraphicBuffer> buffer; // Save a buffer to attach later
765    for (int i = 0; i < 2; ++i) {
766        int slot = BufferQueue::INVALID_BUFFER_SLOT;
767        sp<Fence> fence = Fence::NO_FENCE;
768        ASSERT_EQ(OK, mProducer->dequeueBuffer(
769                &slot, &fence, 0, 0, 0, 0, nullptr));
770        ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
771        IGraphicBufferProducer::QueueBufferInput input(0ull, true,
772                HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
773                NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
774        ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
775    }
776
777    int slot = BufferQueue::INVALID_BUFFER_SLOT;
778    sp<Fence> fence = Fence::NO_FENCE;
779    auto startTime = systemTime();
780    ASSERT_EQ(TIMED_OUT, mProducer->dequeueBuffer(
781            &slot, &fence, 0, 0, 0, 0, nullptr));
782    ASSERT_GE(systemTime() - startTime, TIMEOUT);
783
784    // We're technically attaching the same buffer multiple times (since we
785    // queued it previously), but that doesn't matter for this test
786    startTime = systemTime();
787    ASSERT_EQ(TIMED_OUT, mProducer->attachBuffer(&slot, buffer));
788    ASSERT_GE(systemTime() - startTime, TIMEOUT);
789}
790
791TEST_F(BufferQueueTest, CanAttachWhileDisallowingAllocation) {
792    createBufferQueue();
793    sp<DummyConsumer> dc(new DummyConsumer);
794    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
795    IGraphicBufferProducer::QueueBufferOutput output;
796    ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
797            NATIVE_WINDOW_API_CPU, true, &output));
798
799    int slot = BufferQueue::INVALID_BUFFER_SLOT;
800    sp<Fence> sourceFence;
801    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
802            mProducer->dequeueBuffer(&slot, &sourceFence, 0, 0, 0, 0, nullptr));
803    sp<GraphicBuffer> buffer;
804    ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
805    ASSERT_EQ(OK, mProducer->detachBuffer(slot));
806
807    ASSERT_EQ(OK, mProducer->allowAllocation(false));
808
809    slot = BufferQueue::INVALID_BUFFER_SLOT;
810    ASSERT_EQ(OK, mProducer->attachBuffer(&slot, buffer));
811}
812
813TEST_F(BufferQueueTest, CanRetrieveLastQueuedBuffer) {
814    createBufferQueue();
815    sp<DummyConsumer> dc(new DummyConsumer);
816    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
817    IGraphicBufferProducer::QueueBufferOutput output;
818    ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
819            NATIVE_WINDOW_API_CPU, false, &output));
820
821    // Dequeue and queue the first buffer, storing the handle
822    int slot = BufferQueue::INVALID_BUFFER_SLOT;
823    sp<Fence> fence;
824    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
825            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
826    sp<GraphicBuffer> firstBuffer;
827    ASSERT_EQ(OK, mProducer->requestBuffer(slot, &firstBuffer));
828
829    IGraphicBufferProducer::QueueBufferInput input(0ull, true,
830        HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
831        NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
832    ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
833
834    // Dequeue a second buffer
835    slot = BufferQueue::INVALID_BUFFER_SLOT;
836    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
837            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
838    sp<GraphicBuffer> secondBuffer;
839    ASSERT_EQ(OK, mProducer->requestBuffer(slot, &secondBuffer));
840
841    // Ensure it's a new buffer
842    ASSERT_NE(firstBuffer->getNativeBuffer()->handle,
843            secondBuffer->getNativeBuffer()->handle);
844
845    // Queue the second buffer
846    ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
847
848    // Acquire and release both buffers
849    for (size_t i = 0; i < 2; ++i) {
850        BufferItem item;
851        ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
852        ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
853                    EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
854    }
855
856    // Make sure we got the second buffer back
857    sp<GraphicBuffer> returnedBuffer;
858    sp<Fence> returnedFence;
859    float transform[16];
860    ASSERT_EQ(OK,
861            mProducer->getLastQueuedBuffer(&returnedBuffer, &returnedFence,
862            transform));
863    ASSERT_EQ(secondBuffer->getNativeBuffer()->handle,
864            returnedBuffer->getNativeBuffer()->handle);
865}
866
867TEST_F(BufferQueueTest, TestOccupancyHistory) {
868    createBufferQueue();
869    sp<DummyConsumer> dc(new DummyConsumer);
870    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
871    IGraphicBufferProducer::QueueBufferOutput output;
872    ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
873            NATIVE_WINDOW_API_CPU, false, &output));
874
875    int slot = BufferQueue::INVALID_BUFFER_SLOT;
876    sp<Fence> fence = Fence::NO_FENCE;
877    sp<GraphicBuffer> buffer = nullptr;
878    IGraphicBufferProducer::QueueBufferInput input(0ull, true,
879        HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
880        NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
881    BufferItem item{};
882
883    // Preallocate, dequeue, request, and cancel 3 buffers so we don't get
884    // BUFFER_NEEDS_REALLOCATION below
885    int slots[3] = {};
886    mProducer->setMaxDequeuedBufferCount(3);
887    for (size_t i = 0; i < 3; ++i) {
888        status_t result = mProducer->dequeueBuffer(&slots[i], &fence,
889                0, 0, 0, 0, nullptr);
890        ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
891        ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
892    }
893    for (size_t i = 0; i < 3; ++i) {
894        ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE));
895    }
896
897    // Create 3 segments
898
899    // The first segment is a two-buffer segment, so we only put one buffer into
900    // the queue at a time
901    for (size_t i = 0; i < 5; ++i) {
902        ASSERT_EQ(OK, mProducer->dequeueBuffer(
903                &slot, &fence, 0, 0, 0, 0, nullptr));
904        ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
905        ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
906        ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
907                EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
908        std::this_thread::sleep_for(16ms);
909    }
910
911    // Sleep between segments
912    std::this_thread::sleep_for(500ms);
913
914    // The second segment is a double-buffer segment. It starts the same as the
915    // two-buffer segment, but then at the end, we put two buffers in the queue
916    // at the same time before draining it.
917    for (size_t i = 0; i < 5; ++i) {
918        ASSERT_EQ(OK, mProducer->dequeueBuffer(
919                &slot, &fence, 0, 0, 0, 0, nullptr));
920        ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
921        ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
922        ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
923                EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
924        std::this_thread::sleep_for(16ms);
925    }
926    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
927    ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
928    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
929    ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
930    ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
931    ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
932            EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
933    std::this_thread::sleep_for(16ms);
934    ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
935    ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
936            EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
937
938    // Sleep between segments
939    std::this_thread::sleep_for(500ms);
940
941    // The third segment is a triple-buffer segment, so the queue is switching
942    // between one buffer and two buffers deep.
943    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
944    ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
945    for (size_t i = 0; i < 5; ++i) {
946        ASSERT_EQ(OK, mProducer->dequeueBuffer(
947                &slot, &fence, 0, 0, 0, 0, nullptr));
948        ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
949        ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
950        ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
951                    EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
952        std::this_thread::sleep_for(16ms);
953    }
954    ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
955    ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
956            EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
957
958    // Now we read the segments
959    std::vector<OccupancyTracker::Segment> history;
960    ASSERT_EQ(OK, mConsumer->getOccupancyHistory(false, &history));
961
962    // Since we didn't force a flush, we should only get the first two segments
963    // (since the third segment hasn't been closed out by the appearance of a
964    // new segment yet)
965    ASSERT_EQ(2u, history.size());
966
967    // The first segment (which will be history[1], since the newest segment
968    // should be at the front of the vector) should be a two-buffer segment,
969    // which implies that the occupancy average should be between 0 and 1, and
970    // usedThirdBuffer should be false
971    const auto& firstSegment = history[1];
972    ASSERT_EQ(5u, firstSegment.numFrames);
973    ASSERT_LT(0, firstSegment.occupancyAverage);
974    ASSERT_GT(1, firstSegment.occupancyAverage);
975    ASSERT_EQ(false, firstSegment.usedThirdBuffer);
976
977    // The second segment should be a double-buffered segment, which implies that
978    // the occupancy average should be between 0 and 1, but usedThirdBuffer
979    // should be true
980    const auto& secondSegment = history[0];
981    ASSERT_EQ(7u, secondSegment.numFrames);
982    ASSERT_LT(0, secondSegment.occupancyAverage);
983    ASSERT_GT(1, secondSegment.occupancyAverage);
984    ASSERT_EQ(true, secondSegment.usedThirdBuffer);
985
986    // If we read the segments again without flushing, we shouldn't get any new
987    // segments
988    ASSERT_EQ(OK, mConsumer->getOccupancyHistory(false, &history));
989    ASSERT_EQ(0u, history.size());
990
991    // Read the segments again, this time forcing a flush so we get the third
992    // segment
993    ASSERT_EQ(OK, mConsumer->getOccupancyHistory(true, &history));
994    ASSERT_EQ(1u, history.size());
995
996    // This segment should be a triple-buffered segment, which implies that the
997    // occupancy average should be between 1 and 2, and usedThirdBuffer should
998    // be true
999    const auto& thirdSegment = history[0];
1000    ASSERT_EQ(6u, thirdSegment.numFrames);
1001    ASSERT_LT(1, thirdSegment.occupancyAverage);
1002    ASSERT_GT(2, thirdSegment.occupancyAverage);
1003    ASSERT_EQ(true, thirdSegment.usedThirdBuffer);
1004}
1005
1006TEST_F(BufferQueueTest, TestDiscardFreeBuffers) {
1007    createBufferQueue();
1008    sp<DummyConsumer> dc(new DummyConsumer);
1009    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
1010    IGraphicBufferProducer::QueueBufferOutput output;
1011    ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
1012            NATIVE_WINDOW_API_CPU, false, &output));
1013
1014    int slot = BufferQueue::INVALID_BUFFER_SLOT;
1015    sp<Fence> fence = Fence::NO_FENCE;
1016    sp<GraphicBuffer> buffer = nullptr;
1017    IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1018        HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1019        NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1020    BufferItem item{};
1021
1022    // Preallocate, dequeue, request, and cancel 4 buffers so we don't get
1023    // BUFFER_NEEDS_REALLOCATION below
1024    int slots[4] = {};
1025    mProducer->setMaxDequeuedBufferCount(4);
1026    for (size_t i = 0; i < 4; ++i) {
1027        status_t result = mProducer->dequeueBuffer(&slots[i], &fence,
1028                0, 0, 0, 0, nullptr);
1029        ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1030        ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
1031    }
1032    for (size_t i = 0; i < 4; ++i) {
1033        ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE));
1034    }
1035
1036    // Get buffers in all states: dequeued, filled, acquired, free
1037
1038    // Fill 3 buffers
1039    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
1040    ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1041    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
1042    ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1043    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
1044    ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1045    // Dequeue 1 buffer
1046    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
1047
1048    // Acquire and free 1 buffer
1049    ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1050    ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
1051                    EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
1052    // Acquire 1 buffer, leaving 1 filled buffer in queue
1053    ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1054
1055    // Now discard the free buffers
1056    ASSERT_EQ(OK, mConsumer->discardFreeBuffers());
1057
1058    // Check no free buffers in dump
1059    String8 dumpString;
1060    mConsumer->dumpState(String8{}, &dumpString);
1061
1062    // Parse the dump to ensure that all buffer slots that are FREE also
1063    // have a null GraphicBuffer
1064    // Fragile - assumes the following format for the dump for a buffer entry:
1065    // ":%p\][^:]*state=FREE" where %p is the buffer pointer in hex.
1066    ssize_t idx = dumpString.find("state=FREE");
1067    while (idx != -1) {
1068        ssize_t bufferPtrIdx = idx - 1;
1069        while (bufferPtrIdx > 0) {
1070            if (dumpString[bufferPtrIdx] == ':') {
1071                bufferPtrIdx++;
1072                break;
1073            }
1074            bufferPtrIdx--;
1075        }
1076        ASSERT_GT(bufferPtrIdx, 0) << "Can't parse queue dump to validate";
1077        ssize_t nullPtrIdx = dumpString.find("0x0]", bufferPtrIdx);
1078        ASSERT_EQ(bufferPtrIdx, nullPtrIdx) << "Free buffer not discarded";
1079        idx = dumpString.find("FREE", idx + 1);
1080    }
1081}
1082
1083TEST_F(BufferQueueTest, TestBufferReplacedInQueueBuffer) {
1084    createBufferQueue();
1085    sp<DummyConsumer> dc(new DummyConsumer);
1086    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
1087    IGraphicBufferProducer::QueueBufferOutput output;
1088    ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
1089            NATIVE_WINDOW_API_CPU, true, &output));
1090    ASSERT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
1091
1092    int slot = BufferQueue::INVALID_BUFFER_SLOT;
1093    sp<Fence> fence = Fence::NO_FENCE;
1094    sp<GraphicBuffer> buffer = nullptr;
1095    IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1096        HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1097        NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1098    BufferItem item{};
1099
1100    // Preallocate, dequeue, request, and cancel 2 buffers so we don't get
1101    // BUFFER_NEEDS_REALLOCATION below
1102    int slots[2] = {};
1103    ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(2));
1104    for (size_t i = 0; i < 2; ++i) {
1105        status_t result = mProducer->dequeueBuffer(&slots[i], &fence,
1106                0, 0, 0, 0, nullptr);
1107        ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1108        ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
1109    }
1110    for (size_t i = 0; i < 2; ++i) {
1111        ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE));
1112    }
1113
1114    // Fill 2 buffers without consumer consuming them. Verify that all
1115    // queued buffer returns proper bufferReplaced flag
1116    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
1117    ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1118    ASSERT_EQ(false, output.bufferReplaced);
1119    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
1120    ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1121    ASSERT_EQ(true, output.bufferReplaced);
1122}
1123
1124TEST_F(BufferQueueTest, TestStaleBufferHandleSentAfterDisconnect) {
1125    createBufferQueue();
1126    sp<DummyConsumer> dc(new DummyConsumer);
1127    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
1128    IGraphicBufferProducer::QueueBufferOutput output;
1129    sp<IProducerListener> dummyListener(new DummyProducerListener);
1130    ASSERT_EQ(OK, mProducer->connect(dummyListener, NATIVE_WINDOW_API_CPU,
1131            true, &output));
1132
1133    int slot = BufferQueue::INVALID_BUFFER_SLOT;
1134    sp<Fence> fence = Fence::NO_FENCE;
1135    sp<GraphicBuffer> buffer = nullptr;
1136    IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1137            HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1138            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1139
1140    // Dequeue, request, and queue one buffer
1141    status_t result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0,
1142            nullptr);
1143    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1144    ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
1145    ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1146
1147    // Acquire and release the buffer. Upon acquiring, the buffer handle should
1148    // be non-null since this is the first time we've acquired this slot.
1149    BufferItem item;
1150    ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1151    ASSERT_EQ(slot, item.mSlot);
1152    ASSERT_NE(nullptr, item.mGraphicBuffer.get());
1153    ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
1154            EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
1155
1156    // Dequeue and queue the buffer again
1157    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
1158    ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1159
1160    // Acquire and release the buffer again. Upon acquiring, the buffer handle
1161    // should be null since this is not the first time we've acquired this slot.
1162    ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1163    ASSERT_EQ(slot, item.mSlot);
1164    ASSERT_EQ(nullptr, item.mGraphicBuffer.get());
1165    ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
1166            EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
1167
1168    // Dequeue and queue the buffer again
1169    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
1170    ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1171
1172    // Disconnect the producer end. This should clear all of the slots and mark
1173    // the buffer in the queue as stale.
1174    ASSERT_EQ(OK, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
1175
1176    // Acquire the buffer again. Upon acquiring, the buffer handle should not be
1177    // null since the queued buffer should have been marked as stale, which
1178    // should trigger the BufferQueue to resend the buffer handle.
1179    ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1180    ASSERT_EQ(slot, item.mSlot);
1181    ASSERT_NE(nullptr, item.mGraphicBuffer.get());
1182}
1183
1184} // namespace android
1185