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