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