BufferQueue_test.cpp revision 7c3ba8aa288755fad78ddbabcee0ad5a0610ac1c
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, nullptr));
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, nullptr));
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, nullptr));
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, nullptr));
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, nullptr));
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, nullptr));
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, nullptr));
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, nullptr));
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, nullptr));
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, nullptr));
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, nullptr));
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, nullptr));
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, nullptr));
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, nullptr));
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, nullptr));
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(
579                &slot, &fence, 0, 0, 0, 0, nullptr));
580        ASSERT_EQ(sharedSlot, slot);
581        ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
582    }
583
584    // acquire the buffer
585    BufferItem item;
586    ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
587    ASSERT_EQ(sharedSlot, item.mSlot);
588    testBufferItem(input, item);
589    ASSERT_EQ(true, item.mQueuedBuffer);
590    ASSERT_EQ(false, item.mAutoRefresh);
591
592    ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
593            EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
594
595    // attempt to acquire a second time should return no buffer available
596    ASSERT_EQ(IGraphicBufferConsumer::NO_BUFFER_AVAILABLE,
597            mConsumer->acquireBuffer(&item, 0));
598}
599
600TEST_F(BufferQueueTest, TestSharedBufferModeWithAutoRefresh) {
601    createBufferQueue();
602    sp<DummyConsumer> dc(new DummyConsumer);
603    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
604    IGraphicBufferProducer::QueueBufferOutput output;
605    ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
606            NATIVE_WINDOW_API_CPU, true, &output));
607
608    ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
609    ASSERT_EQ(OK, mProducer->setAutoRefresh(true));
610
611    // Get a buffer
612    int sharedSlot;
613    sp<Fence> fence;
614    sp<GraphicBuffer> buffer;
615    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
616            mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0, nullptr));
617    ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
618
619    // Queue the buffer
620    IGraphicBufferProducer::QueueBufferInput input(0, false,
621            HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
622            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
623    ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
624
625    // Repeatedly acquire and release a buffer from the consumer side, it should
626    // always return the same one.
627    BufferItem item;
628    for (int i = 0; i < 5; i++) {
629        ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
630        ASSERT_EQ(sharedSlot, item.mSlot);
631        testBufferItem(input, item);
632        ASSERT_EQ(i == 0, item.mQueuedBuffer);
633        ASSERT_EQ(true, item.mAutoRefresh);
634
635        ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
636                EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
637    }
638
639    // Repeatedly queue and dequeue a buffer from the producer side, it should
640    // always return the same one.
641    int slot;
642    for (int i = 0; i < 5; i++) {
643        ASSERT_EQ(OK, mProducer->dequeueBuffer(
644                &slot, &fence, 0, 0, 0, 0, nullptr));
645        ASSERT_EQ(sharedSlot, slot);
646        ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
647    }
648
649    // Repeatedly acquire and release a buffer from the consumer side, it should
650    // always return the same one. First grabbing them from the queue and then
651    // when the queue is empty, returning the shared buffer.
652    for (int i = 0; i < 10; i++) {
653        ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
654        ASSERT_EQ(sharedSlot, item.mSlot);
655        ASSERT_EQ(0, item.mTimestamp);
656        ASSERT_EQ(false, item.mIsAutoTimestamp);
657        ASSERT_EQ(HAL_DATASPACE_UNKNOWN, item.mDataSpace);
658        ASSERT_EQ(Rect(0, 0, 1, 1), item.mCrop);
659        ASSERT_EQ(NATIVE_WINDOW_SCALING_MODE_FREEZE, item.mScalingMode);
660        ASSERT_EQ(0u, item.mTransform);
661        ASSERT_EQ(Fence::NO_FENCE, item.mFence);
662        ASSERT_EQ(i == 0, item.mQueuedBuffer);
663        ASSERT_EQ(true, item.mAutoRefresh);
664
665        ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
666                EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
667    }
668}
669
670TEST_F(BufferQueueTest, TestSharedBufferModeUsingAlreadyDequeuedBuffer) {
671    createBufferQueue();
672    sp<DummyConsumer> dc(new DummyConsumer);
673    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
674    IGraphicBufferProducer::QueueBufferOutput output;
675    ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
676            NATIVE_WINDOW_API_CPU, true, &output));
677
678    // Dequeue a buffer
679    int sharedSlot;
680    sp<Fence> fence;
681    sp<GraphicBuffer> buffer;
682    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
683            mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0, nullptr));
684    ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
685
686    // Enable shared buffer mode
687    ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
688
689    // Queue the buffer
690    IGraphicBufferProducer::QueueBufferInput input(0, false,
691            HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
692            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
693    ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
694
695    // Repeatedly queue and dequeue a buffer from the producer side, it should
696    // always return the same one. And we won't run out of buffers because it's
697    // always the same one and because async mode gets enabled.
698    int slot;
699    for (int i = 0; i < 5; i++) {
700        ASSERT_EQ(OK, mProducer->dequeueBuffer(
701                &slot, &fence, 0, 0, 0, 0, nullptr));
702        ASSERT_EQ(sharedSlot, slot);
703        ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
704    }
705
706    // acquire the buffer
707    BufferItem item;
708    ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
709    ASSERT_EQ(sharedSlot, item.mSlot);
710    testBufferItem(input, item);
711    ASSERT_EQ(true, item.mQueuedBuffer);
712    ASSERT_EQ(false, item.mAutoRefresh);
713
714    ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
715            EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
716
717    // attempt to acquire a second time should return no buffer available
718    ASSERT_EQ(IGraphicBufferConsumer::NO_BUFFER_AVAILABLE,
719            mConsumer->acquireBuffer(&item, 0));
720}
721
722TEST_F(BufferQueueTest, TestTimeouts) {
723    createBufferQueue();
724    sp<DummyConsumer> dc(new DummyConsumer);
725    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
726    IGraphicBufferProducer::QueueBufferOutput output;
727    ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
728            NATIVE_WINDOW_API_CPU, true, &output));
729
730    // Fill up the queue. Since the controlledByApp flags are set to true, this
731    // queue should be in non-blocking mode, and we should be recycling the same
732    // two buffers
733    for (int i = 0; i < 5; ++i) {
734        int slot = BufferQueue::INVALID_BUFFER_SLOT;
735        sp<Fence> fence = Fence::NO_FENCE;
736        auto result = mProducer->dequeueBuffer(
737                &slot, &fence, 0, 0, 0, 0, nullptr);
738        if (i < 2) {
739            ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
740                    result);
741        } else {
742            ASSERT_EQ(OK, result);
743        }
744        sp<GraphicBuffer> buffer;
745        ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
746        IGraphicBufferProducer::QueueBufferInput input(0ull, true,
747                HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
748                NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
749        IGraphicBufferProducer::QueueBufferOutput output{};
750        ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
751    }
752
753    const auto TIMEOUT = ms2ns(250);
754    mProducer->setDequeueTimeout(TIMEOUT);
755
756    // Setting a timeout will change the BufferQueue into blocking mode (with
757    // one droppable buffer in the queue and one free from the previous
758    // dequeue/queues), so dequeue and queue two more buffers: one to replace
759    // the current droppable buffer, and a second to max out the buffer count
760    sp<GraphicBuffer> buffer; // Save a buffer to attach later
761    for (int i = 0; i < 2; ++i) {
762        int slot = BufferQueue::INVALID_BUFFER_SLOT;
763        sp<Fence> fence = Fence::NO_FENCE;
764        ASSERT_EQ(OK, mProducer->dequeueBuffer(
765                &slot, &fence, 0, 0, 0, 0, nullptr));
766        ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
767        IGraphicBufferProducer::QueueBufferInput input(0ull, true,
768                HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
769                NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
770        ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
771    }
772
773    int slot = BufferQueue::INVALID_BUFFER_SLOT;
774    sp<Fence> fence = Fence::NO_FENCE;
775    auto startTime = systemTime();
776    ASSERT_EQ(TIMED_OUT, mProducer->dequeueBuffer(
777            &slot, &fence, 0, 0, 0, 0, nullptr));
778    ASSERT_GE(systemTime() - startTime, TIMEOUT);
779
780    // We're technically attaching the same buffer multiple times (since we
781    // queued it previously), but that doesn't matter for this test
782    startTime = systemTime();
783    ASSERT_EQ(TIMED_OUT, mProducer->attachBuffer(&slot, buffer));
784    ASSERT_GE(systemTime() - startTime, TIMEOUT);
785}
786
787TEST_F(BufferQueueTest, CanAttachWhileDisallowingAllocation) {
788    createBufferQueue();
789    sp<DummyConsumer> dc(new DummyConsumer);
790    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
791    IGraphicBufferProducer::QueueBufferOutput output;
792    ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
793            NATIVE_WINDOW_API_CPU, true, &output));
794
795    int slot = BufferQueue::INVALID_BUFFER_SLOT;
796    sp<Fence> sourceFence;
797    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
798            mProducer->dequeueBuffer(&slot, &sourceFence, 0, 0, 0, 0, nullptr));
799    sp<GraphicBuffer> buffer;
800    ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
801    ASSERT_EQ(OK, mProducer->detachBuffer(slot));
802
803    ASSERT_EQ(OK, mProducer->allowAllocation(false));
804
805    slot = BufferQueue::INVALID_BUFFER_SLOT;
806    ASSERT_EQ(OK, mProducer->attachBuffer(&slot, buffer));
807}
808
809TEST_F(BufferQueueTest, CanRetrieveLastQueuedBuffer) {
810    createBufferQueue();
811    sp<DummyConsumer> dc(new DummyConsumer);
812    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
813    IGraphicBufferProducer::QueueBufferOutput output;
814    ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
815            NATIVE_WINDOW_API_CPU, false, &output));
816
817    // Dequeue and queue the first buffer, storing the handle
818    int slot = BufferQueue::INVALID_BUFFER_SLOT;
819    sp<Fence> fence;
820    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
821            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
822    sp<GraphicBuffer> firstBuffer;
823    ASSERT_EQ(OK, mProducer->requestBuffer(slot, &firstBuffer));
824
825    IGraphicBufferProducer::QueueBufferInput input(0ull, true,
826        HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
827        NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
828    ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
829
830    // Dequeue a second buffer
831    slot = BufferQueue::INVALID_BUFFER_SLOT;
832    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
833            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
834    sp<GraphicBuffer> secondBuffer;
835    ASSERT_EQ(OK, mProducer->requestBuffer(slot, &secondBuffer));
836
837    // Ensure it's a new buffer
838    ASSERT_NE(firstBuffer->getNativeBuffer()->handle,
839            secondBuffer->getNativeBuffer()->handle);
840
841    // Queue the second buffer
842    ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
843
844    // Acquire and release both buffers
845    for (size_t i = 0; i < 2; ++i) {
846        BufferItem item;
847        ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
848        ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
849                    EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
850    }
851
852    // Make sure we got the second buffer back
853    sp<GraphicBuffer> returnedBuffer;
854    sp<Fence> returnedFence;
855    float transform[16];
856    ASSERT_EQ(OK,
857            mProducer->getLastQueuedBuffer(&returnedBuffer, &returnedFence,
858            transform));
859    ASSERT_EQ(secondBuffer->getNativeBuffer()->handle,
860            returnedBuffer->getNativeBuffer()->handle);
861}
862
863TEST_F(BufferQueueTest, TestOccupancyHistory) {
864    createBufferQueue();
865    sp<DummyConsumer> dc(new DummyConsumer);
866    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
867    IGraphicBufferProducer::QueueBufferOutput output;
868    ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
869            NATIVE_WINDOW_API_CPU, false, &output));
870
871    int slot = BufferQueue::INVALID_BUFFER_SLOT;
872    sp<Fence> fence = Fence::NO_FENCE;
873    sp<GraphicBuffer> buffer = nullptr;
874    IGraphicBufferProducer::QueueBufferInput input(0ull, true,
875        HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
876        NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
877    BufferItem item{};
878
879    // Preallocate, dequeue, request, and cancel 3 buffers so we don't get
880    // BUFFER_NEEDS_REALLOCATION below
881    int slots[3] = {};
882    mProducer->setMaxDequeuedBufferCount(3);
883    for (size_t i = 0; i < 3; ++i) {
884        status_t result = mProducer->dequeueBuffer(&slots[i], &fence,
885                0, 0, 0, 0, nullptr);
886        ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
887        ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
888    }
889    for (size_t i = 0; i < 3; ++i) {
890        ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE));
891    }
892
893    // Create 3 segments
894
895    // The first segment is a two-buffer segment, so we only put one buffer into
896    // the queue at a time
897    for (size_t i = 0; i < 5; ++i) {
898        ASSERT_EQ(OK, mProducer->dequeueBuffer(
899                &slot, &fence, 0, 0, 0, 0, nullptr));
900        ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
901        ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
902        ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
903                EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
904        std::this_thread::sleep_for(16ms);
905    }
906
907    // Sleep between segments
908    std::this_thread::sleep_for(500ms);
909
910    // The second segment is a double-buffer segment. It starts the same as the
911    // two-buffer segment, but then at the end, we put two buffers in the queue
912    // at the same time before draining it.
913    for (size_t i = 0; i < 5; ++i) {
914        ASSERT_EQ(OK, mProducer->dequeueBuffer(
915                &slot, &fence, 0, 0, 0, 0, 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));
923    ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
924    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, 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));
940    ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
941    for (size_t i = 0; i < 5; ++i) {
942        ASSERT_EQ(OK, mProducer->dequeueBuffer(
943                &slot, &fence, 0, 0, 0, 0, nullptr));
944        ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
945        ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
946        ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
947                    EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
948        std::this_thread::sleep_for(16ms);
949    }
950    ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
951    ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
952            EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
953
954    // Now we read the segments
955    std::vector<OccupancyTracker::Segment> history;
956    ASSERT_EQ(OK, mConsumer->getOccupancyHistory(false, &history));
957
958    // Since we didn't force a flush, we should only get the first two segments
959    // (since the third segment hasn't been closed out by the appearance of a
960    // new segment yet)
961    ASSERT_EQ(2u, history.size());
962
963    // The first segment (which will be history[1], since the newest segment
964    // should be at the front of the vector) should be a two-buffer segment,
965    // which implies that the occupancy average should be between 0 and 1, and
966    // usedThirdBuffer should be false
967    const auto& firstSegment = history[1];
968    ASSERT_EQ(5u, firstSegment.numFrames);
969    ASSERT_LT(0, firstSegment.occupancyAverage);
970    ASSERT_GT(1, firstSegment.occupancyAverage);
971    ASSERT_EQ(false, firstSegment.usedThirdBuffer);
972
973    // The second segment should be a double-buffered segment, which implies that
974    // the occupancy average should be between 0 and 1, but usedThirdBuffer
975    // should be true
976    const auto& secondSegment = history[0];
977    ASSERT_EQ(7u, secondSegment.numFrames);
978    ASSERT_LT(0, secondSegment.occupancyAverage);
979    ASSERT_GT(1, secondSegment.occupancyAverage);
980    ASSERT_EQ(true, secondSegment.usedThirdBuffer);
981
982    // If we read the segments again without flushing, we shouldn't get any new
983    // segments
984    ASSERT_EQ(OK, mConsumer->getOccupancyHistory(false, &history));
985    ASSERT_EQ(0u, history.size());
986
987    // Read the segments again, this time forcing a flush so we get the third
988    // segment
989    ASSERT_EQ(OK, mConsumer->getOccupancyHistory(true, &history));
990    ASSERT_EQ(1u, history.size());
991
992    // This segment should be a triple-buffered segment, which implies that the
993    // occupancy average should be between 1 and 2, and usedThirdBuffer should
994    // be true
995    const auto& thirdSegment = history[0];
996    ASSERT_EQ(6u, thirdSegment.numFrames);
997    ASSERT_LT(1, thirdSegment.occupancyAverage);
998    ASSERT_GT(2, thirdSegment.occupancyAverage);
999    ASSERT_EQ(true, thirdSegment.usedThirdBuffer);
1000}
1001
1002TEST_F(BufferQueueTest, TestDiscardFreeBuffers) {
1003    createBufferQueue();
1004    sp<DummyConsumer> dc(new DummyConsumer);
1005    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
1006    IGraphicBufferProducer::QueueBufferOutput output;
1007    ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
1008            NATIVE_WINDOW_API_CPU, false, &output));
1009
1010    int slot = BufferQueue::INVALID_BUFFER_SLOT;
1011    sp<Fence> fence = Fence::NO_FENCE;
1012    sp<GraphicBuffer> buffer = nullptr;
1013    IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1014        HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1015        NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1016    BufferItem item{};
1017
1018    // Preallocate, dequeue, request, and cancel 4 buffers so we don't get
1019    // BUFFER_NEEDS_REALLOCATION below
1020    int slots[4] = {};
1021    mProducer->setMaxDequeuedBufferCount(4);
1022    for (size_t i = 0; i < 4; ++i) {
1023        status_t result = mProducer->dequeueBuffer(&slots[i], &fence,
1024                0, 0, 0, 0, nullptr);
1025        ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1026        ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
1027    }
1028    for (size_t i = 0; i < 4; ++i) {
1029        ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE));
1030    }
1031
1032    // Get buffers in all states: dequeued, filled, acquired, free
1033
1034    // Fill 3 buffers
1035    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
1036    ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1037    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
1038    ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1039    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
1040    ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1041    // Dequeue 1 buffer
1042    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
1043
1044    // Acquire and free 1 buffer
1045    ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1046    ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
1047                    EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
1048    // Acquire 1 buffer, leaving 1 filled buffer in queue
1049    ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1050
1051    // Now discard the free buffers
1052    ASSERT_EQ(OK, mConsumer->discardFreeBuffers());
1053
1054    // Check no free buffers in dump
1055    String8 dumpString;
1056    mConsumer->dumpState(dumpString, nullptr);
1057
1058    // Parse the dump to ensure that all buffer slots that are FREE also
1059    // have a null GraphicBuffer
1060    // Fragile - assumes the following format for the dump for a buffer entry:
1061    // ":%p\][^:]*state=FREE" where %p is the buffer pointer in hex.
1062    ssize_t idx = dumpString.find("state=FREE");
1063    while (idx != -1) {
1064        ssize_t bufferPtrIdx = idx - 1;
1065        while (bufferPtrIdx > 0) {
1066            if (dumpString[bufferPtrIdx] == ':') {
1067                bufferPtrIdx++;
1068                break;
1069            }
1070            bufferPtrIdx--;
1071        }
1072        ASSERT_GT(bufferPtrIdx, 0) << "Can't parse queue dump to validate";
1073        ssize_t nullPtrIdx = dumpString.find("0x0]", bufferPtrIdx);
1074        ASSERT_EQ(bufferPtrIdx, nullPtrIdx) << "Free buffer not discarded";
1075        idx = dumpString.find("FREE", idx + 1);
1076    }
1077}
1078
1079} // namespace android
1080