blob: c303b625614559a05889892cf36177dfc42dd4cc [file] [log] [blame]
Jamie Gennis9e75ddd2012-08-31 15:32:45 -07001/*
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
Peiyong Lind8460c82020-07-28 16:04:22 -070020#include "MockConsumer.h"
Dan Stozac6f30bd2015-06-08 09:32:50 -070021
Dan Stozacf3834d2015-03-11 14:04:22 -070022#include <gui/BufferItem.h>
Dan Stozaf0eaf252014-03-21 13:05:51 -070023#include <gui/BufferQueue.h>
24#include <gui/IProducerListener.h>
Jamie Gennis9e75ddd2012-08-31 15:32:45 -070025
26#include <ui/GraphicBuffer.h>
Jamie Gennis9e75ddd2012-08-31 15:32:45 -070027
Dan Stoza1a0b8612014-03-20 15:36:31 -070028#include <binder/IPCThreadState.h>
Dan Stoza9f3053d2014-03-06 15:14:33 -080029#include <binder/IServiceManager.h>
Dan Stoza1a0b8612014-03-20 15:36:31 -070030#include <binder/ProcessState.h>
Dan Stozaf0eaf252014-03-21 13:05:51 -070031
32#include <utils/String8.h>
33#include <utils/threads.h>
34
Mathias Agopian6a3c05b2017-04-27 20:06:55 -070035#include <system/window.h>
36
Dan Stozaf0eaf252014-03-21 13:05:51 -070037#include <gtest/gtest.h>
Jamie Gennis9e75ddd2012-08-31 15:32:45 -070038
Dan Stozae77c7662016-05-13 11:37:28 -070039#include <thread>
40
41using namespace std::chrono_literals;
42
Jamie Gennis9e75ddd2012-08-31 15:32:45 -070043namespace android {
44
45class BufferQueueTest : public ::testing::Test {
Dan Stoza9f3053d2014-03-06 15:14:33 -080046
47public:
Jamie Gennis9e75ddd2012-08-31 15:32:45 -070048protected:
Igor Murashkin7ea777f2013-11-18 16:58:36 -080049 void GetMinUndequeuedBufferCount(int* bufferCount) {
Yi Konga03e0442018-07-17 11:16:57 -070050 ASSERT_TRUE(bufferCount != nullptr);
Dan Stoza9f3053d2014-03-06 15:14:33 -080051 ASSERT_EQ(OK, mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
52 bufferCount));
53 ASSERT_GE(*bufferCount, 0);
Igor Murashkin7ea777f2013-11-18 16:58:36 -080054 }
55
Dan Stoza1a0b8612014-03-20 15:36:31 -070056 void createBufferQueue() {
57 BufferQueue::createBufferQueue(&mProducer, &mConsumer);
58 }
Jamie Gennis9e75ddd2012-08-31 15:32:45 -070059
Pablo Ceballosff95aab2016-01-13 17:09:58 -080060 void testBufferItem(const IGraphicBufferProducer::QueueBufferInput& input,
61 const BufferItem& item) {
62 int64_t timestamp;
63 bool isAutoTimestamp;
64 android_dataspace dataSpace;
65 Rect crop;
66 int scalingMode;
67 uint32_t transform;
68 sp<Fence> fence;
69
70 input.deflate(&timestamp, &isAutoTimestamp, &dataSpace, &crop,
Yi Konga03e0442018-07-17 11:16:57 -070071 &scalingMode, &transform, &fence, nullptr);
Pablo Ceballosff95aab2016-01-13 17:09:58 -080072 ASSERT_EQ(timestamp, item.mTimestamp);
73 ASSERT_EQ(isAutoTimestamp, item.mIsAutoTimestamp);
74 ASSERT_EQ(dataSpace, item.mDataSpace);
75 ASSERT_EQ(crop, item.mCrop);
76 ASSERT_EQ(static_cast<uint32_t>(scalingMode), item.mScalingMode);
77 ASSERT_EQ(transform, item.mTransform);
78 ASSERT_EQ(fence, item.mFence);
79 }
80
Dan Stoza1a0b8612014-03-20 15:36:31 -070081 sp<IGraphicBufferProducer> mProducer;
82 sp<IGraphicBufferConsumer> mConsumer;
83};
Dan Stoza9f3053d2014-03-06 15:14:33 -080084
Dan Stozaf8cebe52015-04-20 12:09:38 -070085static const uint32_t TEST_DATA = 0x12345678u;
86
Dan Stoza1a0b8612014-03-20 15:36:31 -070087// XXX: Tests that fork a process to hold the BufferQueue must run before tests
88// that use a local BufferQueue, or else Binder will get unhappy
Kalle Raita88752d72017-03-27 14:11:54 -070089//
90// In one instance this was a crash in the createBufferQueue where the
91// binder call to create a buffer allocator apparently got garbage back.
92// See b/36592665.
93TEST_F(BufferQueueTest, DISABLED_BufferQueueInAnotherProcess) {
Dan Stoza1a0b8612014-03-20 15:36:31 -070094 const String16 PRODUCER_NAME = String16("BQTestProducer");
95 const String16 CONSUMER_NAME = String16("BQTestConsumer");
96
97 pid_t forkPid = fork();
98 ASSERT_NE(forkPid, -1);
99
100 if (forkPid == 0) {
101 // Child process
Dan Stozab3d0bdf2014-04-07 16:33:59 -0700102 sp<IGraphicBufferProducer> producer;
103 sp<IGraphicBufferConsumer> consumer;
Dan Stoza1a0b8612014-03-20 15:36:31 -0700104 BufferQueue::createBufferQueue(&producer, &consumer);
105 sp<IServiceManager> serviceManager = defaultServiceManager();
Marco Nelissen097ca272014-11-14 08:01:01 -0800106 serviceManager->addService(PRODUCER_NAME, IInterface::asBinder(producer));
107 serviceManager->addService(CONSUMER_NAME, IInterface::asBinder(consumer));
Dan Stoza1a0b8612014-03-20 15:36:31 -0700108 ProcessState::self()->startThreadPool();
109 IPCThreadState::self()->joinThreadPool();
110 LOG_ALWAYS_FATAL("Shouldn't be here");
111 }
112
113 sp<IServiceManager> serviceManager = defaultServiceManager();
114 sp<IBinder> binderProducer =
115 serviceManager->getService(PRODUCER_NAME);
116 mProducer = interface_cast<IGraphicBufferProducer>(binderProducer);
Yi Konga03e0442018-07-17 11:16:57 -0700117 EXPECT_TRUE(mProducer != nullptr);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700118 sp<IBinder> binderConsumer =
119 serviceManager->getService(CONSUMER_NAME);
120 mConsumer = interface_cast<IGraphicBufferConsumer>(binderConsumer);
Yi Konga03e0442018-07-17 11:16:57 -0700121 EXPECT_TRUE(mConsumer != nullptr);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700122
Peiyong Lind8460c82020-07-28 16:04:22 -0700123 sp<MockConsumer> mc(new MockConsumer);
124 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Dan Stoza1a0b8612014-03-20 15:36:31 -0700125 IGraphicBufferProducer::QueueBufferOutput output;
126 ASSERT_EQ(OK,
Yi Konga03e0442018-07-17 11:16:57 -0700127 mProducer->connect(nullptr, NATIVE_WINDOW_API_CPU, false, &output));
Dan Stoza1a0b8612014-03-20 15:36:31 -0700128
129 int slot;
130 sp<Fence> fence;
131 sp<GraphicBuffer> buffer;
132 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600133 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
134 nullptr, nullptr));
Dan Stoza1a0b8612014-03-20 15:36:31 -0700135 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
136
137 uint32_t* dataIn;
138 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
139 reinterpret_cast<void**>(&dataIn)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700140 *dataIn = TEST_DATA;
Dan Stoza1a0b8612014-03-20 15:36:31 -0700141 ASSERT_EQ(OK, buffer->unlock());
142
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800143 IGraphicBufferProducer::QueueBufferInput input(0, false,
144 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700145 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700146 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
147
Dan Stozacf3834d2015-03-11 14:04:22 -0700148 BufferItem item;
Dan Stoza1a0b8612014-03-20 15:36:31 -0700149 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
150
151 uint32_t* dataOut;
152 ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
153 reinterpret_cast<void**>(&dataOut)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700154 ASSERT_EQ(*dataOut, TEST_DATA);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700155 ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
156}
157
silence_dogoode9d092a2019-06-19 16:14:53 -0700158TEST_F(BufferQueueTest, GetMaxBufferCountInQueueBufferOutput_Succeeds) {
159 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700160 sp<MockConsumer> mc(new MockConsumer);
161 mConsumer->consumerConnect(mc, false);
silence_dogoode9d092a2019-06-19 16:14:53 -0700162 int bufferCount = 50;
163 mConsumer->setMaxBufferCount(bufferCount);
164
165 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700166 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output);
silence_dogoode9d092a2019-06-19 16:14:53 -0700167 ASSERT_EQ(output.maxBufferCount, bufferCount);
168}
169
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700170TEST_F(BufferQueueTest, AcquireBuffer_ExceedsMaxAcquireCount_Fails) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700171 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700172 sp<MockConsumer> mc(new MockConsumer);
173 mConsumer->consumerConnect(mc, false);
Andy McFadden2adaf042012-12-18 09:49:45 -0800174 IGraphicBufferProducer::QueueBufferOutput qbo;
Peiyong Lind8460c82020-07-28 16:04:22 -0700175 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &qbo);
Pablo Ceballosfa455352015-08-12 17:47:47 -0700176 mProducer->setMaxDequeuedBufferCount(3);
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700177
178 int slot;
179 sp<Fence> fence;
180 sp<GraphicBuffer> buf;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800181 IGraphicBufferProducer::QueueBufferInput qbi(0, false,
182 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700183 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Dan Stozacf3834d2015-03-11 14:04:22 -0700184 BufferItem item;
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700185
186 for (int i = 0; i < 2; i++) {
Andy McFadden2adaf042012-12-18 09:49:45 -0800187 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600188 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
189 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800190 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
191 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
192 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700193 }
194
Andy McFadden2adaf042012-12-18 09:49:45 -0800195 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600196 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
197 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800198 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
199 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700200
201 // Acquire the third buffer, which should fail.
Dan Stoza9f3053d2014-03-06 15:14:33 -0800202 ASSERT_EQ(INVALID_OPERATION, mConsumer->acquireBuffer(&item, 0));
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700203}
204
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700205TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithIllegalValues_ReturnsError) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700206 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700207 sp<MockConsumer> mc(new MockConsumer);
208 mConsumer->consumerConnect(mc, false);
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700209
Pablo Ceballos72daab62015-12-07 16:38:43 -0800210 EXPECT_EQ(OK, mConsumer->setMaxBufferCount(10));
211 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(10));
212
213 IGraphicBufferProducer::QueueBufferOutput qbo;
Peiyong Lind8460c82020-07-28 16:04:22 -0700214 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &qbo);
Pablo Ceballos72daab62015-12-07 16:38:43 -0800215 mProducer->setMaxDequeuedBufferCount(3);
216
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800217 int minBufferCount;
218 ASSERT_NO_FATAL_FAILURE(GetMinUndequeuedBufferCount(&minBufferCount));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800219 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(
220 minBufferCount - 1));
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800221
Dan Stoza9f3053d2014-03-06 15:14:33 -0800222 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(0));
223 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(-3));
224 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700225 BufferQueue::MAX_MAX_ACQUIRED_BUFFERS+1));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800226 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(100));
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700227
Pablo Ceballos72daab62015-12-07 16:38:43 -0800228 int slot;
229 sp<Fence> fence;
230 sp<GraphicBuffer> buf;
231 IGraphicBufferProducer::QueueBufferInput qbi(0, false,
232 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
233 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
234 BufferItem item;
235 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(3));
236 for (int i = 0; i < 3; i++) {
237 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600238 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
239 nullptr, nullptr));
Pablo Ceballos72daab62015-12-07 16:38:43 -0800240 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
241 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
242 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
243 }
244
245 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(2));
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700246}
247
248TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithLegalValues_Succeeds) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700249 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700250 sp<MockConsumer> mc(new MockConsumer);
251 mConsumer->consumerConnect(mc, false);
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700252
Pablo Ceballos72daab62015-12-07 16:38:43 -0800253 IGraphicBufferProducer::QueueBufferOutput qbo;
Peiyong Lind8460c82020-07-28 16:04:22 -0700254 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &qbo);
Pablo Ceballos72daab62015-12-07 16:38:43 -0800255 mProducer->setMaxDequeuedBufferCount(2);
256
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800257 int minBufferCount;
258 ASSERT_NO_FATAL_FAILURE(GetMinUndequeuedBufferCount(&minBufferCount));
259
Dan Stoza9f3053d2014-03-06 15:14:33 -0800260 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
261 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(2));
262 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(minBufferCount));
Pablo Ceballos72daab62015-12-07 16:38:43 -0800263
264 int slot;
265 sp<Fence> fence;
266 sp<GraphicBuffer> buf;
267 IGraphicBufferProducer::QueueBufferInput qbi(0, false,
268 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
269 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
270 BufferItem item;
271
272 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600273 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
274 nullptr, nullptr));
Pablo Ceballos72daab62015-12-07 16:38:43 -0800275 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
276 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
277 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
278
279 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(3));
280
281 for (int i = 0; i < 2; i++) {
282 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600283 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
284 nullptr, nullptr));
Pablo Ceballos72daab62015-12-07 16:38:43 -0800285 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
286 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
287 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
288 }
289
Dan Stoza9f3053d2014-03-06 15:14:33 -0800290 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700291 BufferQueue::MAX_MAX_ACQUIRED_BUFFERS));
292}
293
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700294TEST_F(BufferQueueTest, SetMaxBufferCountWithLegalValues_Succeeds) {
295 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700296 sp<MockConsumer> mc(new MockConsumer);
297 mConsumer->consumerConnect(mc, false);
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700298
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700299 // Test shared buffer mode
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700300 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
301}
302
303TEST_F(BufferQueueTest, SetMaxBufferCountWithIllegalValues_ReturnsError) {
304 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700305 sp<MockConsumer> mc(new MockConsumer);
306 mConsumer->consumerConnect(mc, false);
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700307
308 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(0));
309 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(
310 BufferQueue::NUM_BUFFER_SLOTS + 1));
311
312 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(5));
313 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(3));
314}
315
Dan Stoza9f3053d2014-03-06 15:14:33 -0800316TEST_F(BufferQueueTest, DetachAndReattachOnProducerSide) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700317 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700318 sp<MockConsumer> mc(new MockConsumer);
319 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800320 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700321 ASSERT_EQ(OK,
322 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800323
324 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(-1)); // Index too low
325 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(
326 BufferQueueDefs::NUM_BUFFER_SLOTS)); // Index too high
327 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(0)); // Not dequeued
328
329 int slot;
330 sp<Fence> fence;
331 sp<GraphicBuffer> buffer;
332 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600333 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
334 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800335 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(slot)); // Not requested
336 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
337 ASSERT_EQ(OK, mProducer->detachBuffer(slot));
338 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(slot)); // Not dequeued
339
340 sp<GraphicBuffer> safeToClobberBuffer;
341 // Can no longer request buffer from this slot
342 ASSERT_EQ(BAD_VALUE, mProducer->requestBuffer(slot, &safeToClobberBuffer));
343
344 uint32_t* dataIn;
345 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
346 reinterpret_cast<void**>(&dataIn)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700347 *dataIn = TEST_DATA;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800348 ASSERT_EQ(OK, buffer->unlock());
349
350 int newSlot;
Yi Konga03e0442018-07-17 11:16:57 -0700351 ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(nullptr, safeToClobberBuffer));
352 ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(&newSlot, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800353
354 ASSERT_EQ(OK, mProducer->attachBuffer(&newSlot, buffer));
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800355 IGraphicBufferProducer::QueueBufferInput input(0, false,
356 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700357 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800358 ASSERT_EQ(OK, mProducer->queueBuffer(newSlot, input, &output));
359
Dan Stozacf3834d2015-03-11 14:04:22 -0700360 BufferItem item;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800361 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
362
363 uint32_t* dataOut;
364 ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
365 reinterpret_cast<void**>(&dataOut)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700366 ASSERT_EQ(*dataOut, TEST_DATA);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700367 ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
Dan Stoza9f3053d2014-03-06 15:14:33 -0800368}
369
370TEST_F(BufferQueueTest, DetachAndReattachOnConsumerSide) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700371 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700372 sp<MockConsumer> mc(new MockConsumer);
373 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800374 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700375 ASSERT_EQ(OK,
376 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800377
378 int slot;
379 sp<Fence> fence;
380 sp<GraphicBuffer> buffer;
381 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600382 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
383 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800384 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800385 IGraphicBufferProducer::QueueBufferInput input(0, false,
386 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700387 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800388 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
389
390 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(-1)); // Index too low
391 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(
392 BufferQueueDefs::NUM_BUFFER_SLOTS)); // Index too high
393 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(0)); // Not acquired
394
Dan Stozacf3834d2015-03-11 14:04:22 -0700395 BufferItem item;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800396 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
397
Pablo Ceballos47650f42015-08-04 16:38:17 -0700398 ASSERT_EQ(OK, mConsumer->detachBuffer(item.mSlot));
399 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(item.mSlot)); // Not acquired
Dan Stoza9f3053d2014-03-06 15:14:33 -0800400
401 uint32_t* dataIn;
402 ASSERT_EQ(OK, item.mGraphicBuffer->lock(
403 GraphicBuffer::USAGE_SW_WRITE_OFTEN,
404 reinterpret_cast<void**>(&dataIn)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700405 *dataIn = TEST_DATA;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800406 ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
407
408 int newSlot;
409 sp<GraphicBuffer> safeToClobberBuffer;
Yi Konga03e0442018-07-17 11:16:57 -0700410 ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(nullptr, safeToClobberBuffer));
411 ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(&newSlot, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800412 ASSERT_EQ(OK, mConsumer->attachBuffer(&newSlot, item.mGraphicBuffer));
413
Dan Stoza99b18b42014-03-28 15:34:33 -0700414 ASSERT_EQ(OK, mConsumer->releaseBuffer(newSlot, 0, EGL_NO_DISPLAY,
Dan Stoza9f3053d2014-03-06 15:14:33 -0800415 EGL_NO_SYNC_KHR, Fence::NO_FENCE));
416
417 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600418 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
419 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800420 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
421
422 uint32_t* dataOut;
423 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
424 reinterpret_cast<void**>(&dataOut)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700425 ASSERT_EQ(*dataOut, TEST_DATA);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700426 ASSERT_EQ(OK, buffer->unlock());
Dan Stoza9f3053d2014-03-06 15:14:33 -0800427}
428
429TEST_F(BufferQueueTest, MoveFromConsumerToProducer) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700430 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700431 sp<MockConsumer> mc(new MockConsumer);
432 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800433 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700434 ASSERT_EQ(OK,
435 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800436
437 int slot;
438 sp<Fence> fence;
439 sp<GraphicBuffer> buffer;
440 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600441 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
442 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800443 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
444
445 uint32_t* dataIn;
446 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
447 reinterpret_cast<void**>(&dataIn)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700448 *dataIn = TEST_DATA;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800449 ASSERT_EQ(OK, buffer->unlock());
450
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800451 IGraphicBufferProducer::QueueBufferInput input(0, false,
452 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700453 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800454 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
455
Dan Stozacf3834d2015-03-11 14:04:22 -0700456 BufferItem item;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800457 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
Pablo Ceballos47650f42015-08-04 16:38:17 -0700458 ASSERT_EQ(OK, mConsumer->detachBuffer(item.mSlot));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800459
460 int newSlot;
461 ASSERT_EQ(OK, mProducer->attachBuffer(&newSlot, item.mGraphicBuffer));
462 ASSERT_EQ(OK, mProducer->queueBuffer(newSlot, input, &output));
463 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
464
465 uint32_t* dataOut;
466 ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
467 reinterpret_cast<void**>(&dataOut)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700468 ASSERT_EQ(*dataOut, TEST_DATA);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700469 ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
Dan Stoza9f3053d2014-03-06 15:14:33 -0800470}
471
Dan Stoza9de72932015-04-16 17:28:43 -0700472TEST_F(BufferQueueTest, TestDisallowingAllocation) {
473 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700474 sp<MockConsumer> mc(new MockConsumer);
475 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Dan Stoza9de72932015-04-16 17:28:43 -0700476 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700477 ASSERT_EQ(OK,
478 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Dan Stoza9de72932015-04-16 17:28:43 -0700479
480 static const uint32_t WIDTH = 320;
481 static const uint32_t HEIGHT = 240;
482
483 ASSERT_EQ(OK, mConsumer->setDefaultBufferSize(WIDTH, HEIGHT));
484
485 int slot;
486 sp<Fence> fence;
487 sp<GraphicBuffer> buffer;
488 // This should return an error since it would require an allocation
489 ASSERT_EQ(OK, mProducer->allowAllocation(false));
Ian Elliottd11b0442017-07-18 11:05:49 -0600490 ASSERT_EQ(WOULD_BLOCK,
491 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
492 nullptr, nullptr));
Dan Stoza9de72932015-04-16 17:28:43 -0700493
494 // This should succeed, now that we've lifted the prohibition
495 ASSERT_EQ(OK, mProducer->allowAllocation(true));
496 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600497 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
498 nullptr, nullptr));
Dan Stoza9de72932015-04-16 17:28:43 -0700499
500 // Release the previous buffer back to the BufferQueue
501 mProducer->cancelBuffer(slot, fence);
502
503 // This should fail since we're requesting a different size
504 ASSERT_EQ(OK, mProducer->allowAllocation(false));
Ian Elliottd11b0442017-07-18 11:05:49 -0600505 ASSERT_EQ(WOULD_BLOCK,
506 mProducer->dequeueBuffer(&slot, &fence, WIDTH * 2, HEIGHT * 2, 0,
507 GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr, nullptr));
Dan Stoza9de72932015-04-16 17:28:43 -0700508}
509
Dan Stoza812ed062015-06-02 15:45:22 -0700510TEST_F(BufferQueueTest, TestGenerationNumbers) {
511 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700512 sp<MockConsumer> mc(new MockConsumer);
513 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Dan Stoza812ed062015-06-02 15:45:22 -0700514 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700515 ASSERT_EQ(OK,
516 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Dan Stoza812ed062015-06-02 15:45:22 -0700517
518 ASSERT_EQ(OK, mProducer->setGenerationNumber(1));
519
520 // Get one buffer to play with
521 int slot;
522 sp<Fence> fence;
523 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600524 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stoza812ed062015-06-02 15:45:22 -0700525
526 sp<GraphicBuffer> buffer;
527 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
528
529 // Ensure that the generation number we set propagates to allocated buffers
530 ASSERT_EQ(1U, buffer->getGenerationNumber());
531
532 ASSERT_EQ(OK, mProducer->detachBuffer(slot));
533
534 ASSERT_EQ(OK, mProducer->setGenerationNumber(2));
535
536 // These should fail, since we've changed the generation number on the queue
537 int outSlot;
538 ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(&outSlot, buffer));
539 ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(&outSlot, buffer));
540
541 buffer->setGenerationNumber(2);
542
543 // This should succeed now that we've changed the buffer's generation number
544 ASSERT_EQ(OK, mProducer->attachBuffer(&outSlot, buffer));
545
546 ASSERT_EQ(OK, mProducer->detachBuffer(outSlot));
547
548 // This should also succeed with the new generation number
549 ASSERT_EQ(OK, mConsumer->attachBuffer(&outSlot, buffer));
550}
551
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700552TEST_F(BufferQueueTest, TestSharedBufferModeWithoutAutoRefresh) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700553 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700554 sp<MockConsumer> mc(new MockConsumer);
555 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700556 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700557 ASSERT_EQ(OK,
558 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700559
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700560 ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700561
562 // Get a buffer
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700563 int sharedSlot;
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700564 sp<Fence> fence;
565 sp<GraphicBuffer> buffer;
566 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600567 mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700568 ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700569
570 // Queue the buffer
571 IGraphicBufferProducer::QueueBufferInput input(0, false,
572 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
573 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700574 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700575
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800576 // Repeatedly queue and dequeue a buffer from the producer side, it should
577 // always return the same one. And we won't run out of buffers because it's
578 // always the same one and because async mode gets enabled.
579 int slot;
580 for (int i = 0; i < 5; i++) {
Ian Elliottd11b0442017-07-18 11:05:49 -0600581 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700582 ASSERT_EQ(sharedSlot, slot);
583 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800584 }
585
586 // acquire the buffer
587 BufferItem item;
588 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700589 ASSERT_EQ(sharedSlot, item.mSlot);
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800590 testBufferItem(input, item);
591 ASSERT_EQ(true, item.mQueuedBuffer);
592 ASSERT_EQ(false, item.mAutoRefresh);
593
594 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
595 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
596
597 // attempt to acquire a second time should return no buffer available
598 ASSERT_EQ(IGraphicBufferConsumer::NO_BUFFER_AVAILABLE,
599 mConsumer->acquireBuffer(&item, 0));
600}
601
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700602TEST_F(BufferQueueTest, TestSharedBufferModeWithAutoRefresh) {
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800603 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700604 sp<MockConsumer> mc(new MockConsumer);
605 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800606 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700607 ASSERT_EQ(OK,
608 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800609
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700610 ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800611 ASSERT_EQ(OK, mProducer->setAutoRefresh(true));
612
613 // Get a buffer
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700614 int sharedSlot;
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800615 sp<Fence> fence;
616 sp<GraphicBuffer> buffer;
617 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600618 mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700619 ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800620
621 // Queue the buffer
622 IGraphicBufferProducer::QueueBufferInput input(0, false,
623 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
624 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700625 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800626
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700627 // Repeatedly acquire and release a buffer from the consumer side, it should
628 // always return the same one.
629 BufferItem item;
630 for (int i = 0; i < 5; i++) {
631 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700632 ASSERT_EQ(sharedSlot, item.mSlot);
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800633 testBufferItem(input, item);
634 ASSERT_EQ(i == 0, item.mQueuedBuffer);
635 ASSERT_EQ(true, item.mAutoRefresh);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700636
637 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
638 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
639 }
640
641 // Repeatedly queue and dequeue a buffer from the producer side, it should
642 // always return the same one.
643 int slot;
644 for (int i = 0; i < 5; i++) {
Ian Elliottd11b0442017-07-18 11:05:49 -0600645 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700646 ASSERT_EQ(sharedSlot, slot);
647 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700648 }
649
650 // Repeatedly acquire and release a buffer from the consumer side, it should
651 // always return the same one. First grabbing them from the queue and then
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700652 // when the queue is empty, returning the shared buffer.
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700653 for (int i = 0; i < 10; i++) {
654 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700655 ASSERT_EQ(sharedSlot, item.mSlot);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700656 ASSERT_EQ(0, item.mTimestamp);
657 ASSERT_EQ(false, item.mIsAutoTimestamp);
658 ASSERT_EQ(HAL_DATASPACE_UNKNOWN, item.mDataSpace);
659 ASSERT_EQ(Rect(0, 0, 1, 1), item.mCrop);
660 ASSERT_EQ(NATIVE_WINDOW_SCALING_MODE_FREEZE, item.mScalingMode);
Dan Stoza5ecfb682016-01-04 17:01:02 -0800661 ASSERT_EQ(0u, item.mTransform);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700662 ASSERT_EQ(Fence::NO_FENCE, item.mFence);
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800663 ASSERT_EQ(i == 0, item.mQueuedBuffer);
664 ASSERT_EQ(true, item.mAutoRefresh);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700665
666 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
667 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
668 }
669}
670
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700671TEST_F(BufferQueueTest, TestSharedBufferModeUsingAlreadyDequeuedBuffer) {
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700672 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700673 sp<MockConsumer> mc(new MockConsumer);
674 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700675 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700676 ASSERT_EQ(OK,
677 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700678
679 // Dequeue a buffer
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700680 int sharedSlot;
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700681 sp<Fence> fence;
682 sp<GraphicBuffer> buffer;
683 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600684 mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700685 ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700686
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700687 // Enable shared buffer mode
688 ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700689
690 // Queue the buffer
691 IGraphicBufferProducer::QueueBufferInput input(0, false,
692 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
693 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700694 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700695
696 // Repeatedly queue and dequeue a buffer from the producer side, it should
697 // always return the same one. And we won't run out of buffers because it's
698 // always the same one and because async mode gets enabled.
699 int slot;
700 for (int i = 0; i < 5; i++) {
Ian Elliottd11b0442017-07-18 11:05:49 -0600701 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700702 ASSERT_EQ(sharedSlot, slot);
703 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700704 }
705
706 // acquire the buffer
707 BufferItem item;
708 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700709 ASSERT_EQ(sharedSlot, item.mSlot);
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700710 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
Dan Stoza127fc632015-06-30 13:43:32 -0700722TEST_F(BufferQueueTest, TestTimeouts) {
723 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700724 sp<MockConsumer> mc(new MockConsumer);
725 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Dan Stoza127fc632015-06-30 13:43:32 -0700726 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700727 ASSERT_EQ(OK,
728 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Dan Stoza127fc632015-06-30 13:43:32 -0700729
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;
Ian Elliottd11b0442017-07-18 11:05:49 -0600736 auto result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr);
Dan Stoza127fc632015-06-30 13:43:32 -0700737 if (i < 2) {
738 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
739 result);
740 } else {
741 ASSERT_EQ(OK, result);
742 }
743 sp<GraphicBuffer> buffer;
744 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
745 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
746 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
747 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
748 IGraphicBufferProducer::QueueBufferOutput output{};
749 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
750 }
751
752 const auto TIMEOUT = ms2ns(250);
753 mProducer->setDequeueTimeout(TIMEOUT);
754
755 // Setting a timeout will change the BufferQueue into blocking mode (with
756 // one droppable buffer in the queue and one free from the previous
757 // dequeue/queues), so dequeue and queue two more buffers: one to replace
758 // the current droppable buffer, and a second to max out the buffer count
759 sp<GraphicBuffer> buffer; // Save a buffer to attach later
760 for (int i = 0; i < 2; ++i) {
761 int slot = BufferQueue::INVALID_BUFFER_SLOT;
762 sp<Fence> fence = Fence::NO_FENCE;
Ian Elliottd11b0442017-07-18 11:05:49 -0600763 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stoza127fc632015-06-30 13:43:32 -0700764 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
765 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
766 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
767 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
768 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
769 }
770
771 int slot = BufferQueue::INVALID_BUFFER_SLOT;
772 sp<Fence> fence = Fence::NO_FENCE;
773 auto startTime = systemTime();
Ian Elliottd11b0442017-07-18 11:05:49 -0600774 ASSERT_EQ(TIMED_OUT, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stoza127fc632015-06-30 13:43:32 -0700775 ASSERT_GE(systemTime() - startTime, TIMEOUT);
776
777 // We're technically attaching the same buffer multiple times (since we
778 // queued it previously), but that doesn't matter for this test
779 startTime = systemTime();
780 ASSERT_EQ(TIMED_OUT, mProducer->attachBuffer(&slot, buffer));
781 ASSERT_GE(systemTime() - startTime, TIMEOUT);
782}
783
Dan Stoza5ecfb682016-01-04 17:01:02 -0800784TEST_F(BufferQueueTest, CanAttachWhileDisallowingAllocation) {
785 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700786 sp<MockConsumer> mc(new MockConsumer);
787 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Dan Stoza5ecfb682016-01-04 17:01:02 -0800788 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700789 ASSERT_EQ(OK,
790 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Dan Stoza5ecfb682016-01-04 17:01:02 -0800791
792 int slot = BufferQueue::INVALID_BUFFER_SLOT;
793 sp<Fence> sourceFence;
794 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600795 mProducer->dequeueBuffer(&slot, &sourceFence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stoza5ecfb682016-01-04 17:01:02 -0800796 sp<GraphicBuffer> buffer;
797 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
798 ASSERT_EQ(OK, mProducer->detachBuffer(slot));
799
800 ASSERT_EQ(OK, mProducer->allowAllocation(false));
801
802 slot = BufferQueue::INVALID_BUFFER_SLOT;
803 ASSERT_EQ(OK, mProducer->attachBuffer(&slot, buffer));
804}
805
Dan Stoza50101d02016-04-07 16:53:23 -0700806TEST_F(BufferQueueTest, CanRetrieveLastQueuedBuffer) {
807 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700808 sp<MockConsumer> mc(new MockConsumer);
809 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Dan Stoza50101d02016-04-07 16:53:23 -0700810 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700811 ASSERT_EQ(OK,
812 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
Dan Stoza50101d02016-04-07 16:53:23 -0700813
814 // Dequeue and queue the first buffer, storing the handle
815 int slot = BufferQueue::INVALID_BUFFER_SLOT;
816 sp<Fence> fence;
817 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600818 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stoza50101d02016-04-07 16:53:23 -0700819 sp<GraphicBuffer> firstBuffer;
820 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &firstBuffer));
821
822 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
823 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
824 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
825 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
826
827 // Dequeue a second buffer
828 slot = BufferQueue::INVALID_BUFFER_SLOT;
829 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600830 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stoza50101d02016-04-07 16:53:23 -0700831 sp<GraphicBuffer> secondBuffer;
832 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &secondBuffer));
833
834 // Ensure it's a new buffer
835 ASSERT_NE(firstBuffer->getNativeBuffer()->handle,
836 secondBuffer->getNativeBuffer()->handle);
837
838 // Queue the second buffer
839 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
840
841 // Acquire and release both buffers
842 for (size_t i = 0; i < 2; ++i) {
843 BufferItem item;
844 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
845 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
846 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
847 }
848
849 // Make sure we got the second buffer back
850 sp<GraphicBuffer> returnedBuffer;
851 sp<Fence> returnedFence;
John Reck1a61da52016-04-28 13:18:15 -0700852 float transform[16];
Dan Stoza50101d02016-04-07 16:53:23 -0700853 ASSERT_EQ(OK,
John Reck1a61da52016-04-28 13:18:15 -0700854 mProducer->getLastQueuedBuffer(&returnedBuffer, &returnedFence,
855 transform));
Dan Stoza50101d02016-04-07 16:53:23 -0700856 ASSERT_EQ(secondBuffer->getNativeBuffer()->handle,
857 returnedBuffer->getNativeBuffer()->handle);
858}
859
Dan Stozae77c7662016-05-13 11:37:28 -0700860TEST_F(BufferQueueTest, TestOccupancyHistory) {
861 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700862 sp<MockConsumer> mc(new MockConsumer);
863 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Dan Stozae77c7662016-05-13 11:37:28 -0700864 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700865 ASSERT_EQ(OK,
866 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
Dan Stozae77c7662016-05-13 11:37:28 -0700867
868 int slot = BufferQueue::INVALID_BUFFER_SLOT;
869 sp<Fence> fence = Fence::NO_FENCE;
870 sp<GraphicBuffer> buffer = nullptr;
871 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
872 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
873 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
874 BufferItem item{};
875
876 // Preallocate, dequeue, request, and cancel 3 buffers so we don't get
877 // BUFFER_NEEDS_REALLOCATION below
878 int slots[3] = {};
879 mProducer->setMaxDequeuedBufferCount(3);
880 for (size_t i = 0; i < 3; ++i) {
Ian Elliottd11b0442017-07-18 11:05:49 -0600881 status_t result =
882 mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0, 0, nullptr, nullptr);
Dan Stozae77c7662016-05-13 11:37:28 -0700883 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
884 ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
885 }
886 for (size_t i = 0; i < 3; ++i) {
887 ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE));
888 }
889
890 // Create 3 segments
891
892 // The first segment is a two-buffer segment, so we only put one buffer into
893 // the queue at a time
894 for (size_t i = 0; i < 5; ++i) {
Ian Elliottd11b0442017-07-18 11:05:49 -0600895 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700896 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
897 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
898 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
899 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
900 std::this_thread::sleep_for(16ms);
901 }
902
903 // Sleep between segments
904 std::this_thread::sleep_for(500ms);
905
906 // The second segment is a double-buffer segment. It starts the same as the
907 // two-buffer segment, but then at the end, we put two buffers in the queue
908 // at the same time before draining it.
909 for (size_t i = 0; i < 5; ++i) {
Ian Elliottd11b0442017-07-18 11:05:49 -0600910 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700911 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
912 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
913 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
914 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
915 std::this_thread::sleep_for(16ms);
916 }
Ian Elliottd11b0442017-07-18 11:05:49 -0600917 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700918 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
Ian Elliottd11b0442017-07-18 11:05:49 -0600919 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700920 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
921 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
922 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
923 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
924 std::this_thread::sleep_for(16ms);
925 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
926 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
927 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
928
929 // Sleep between segments
930 std::this_thread::sleep_for(500ms);
931
932 // The third segment is a triple-buffer segment, so the queue is switching
933 // between one buffer and two buffers deep.
Ian Elliottd11b0442017-07-18 11:05:49 -0600934 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700935 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
936 for (size_t i = 0; i < 5; ++i) {
Ian Elliottd11b0442017-07-18 11:05:49 -0600937 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700938 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
939 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
940 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
941 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
942 std::this_thread::sleep_for(16ms);
943 }
944 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
945 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
946 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
947
948 // Now we read the segments
949 std::vector<OccupancyTracker::Segment> history;
950 ASSERT_EQ(OK, mConsumer->getOccupancyHistory(false, &history));
951
952 // Since we didn't force a flush, we should only get the first two segments
953 // (since the third segment hasn't been closed out by the appearance of a
954 // new segment yet)
955 ASSERT_EQ(2u, history.size());
956
957 // The first segment (which will be history[1], since the newest segment
958 // should be at the front of the vector) should be a two-buffer segment,
959 // which implies that the occupancy average should be between 0 and 1, and
960 // usedThirdBuffer should be false
961 const auto& firstSegment = history[1];
962 ASSERT_EQ(5u, firstSegment.numFrames);
963 ASSERT_LT(0, firstSegment.occupancyAverage);
964 ASSERT_GT(1, firstSegment.occupancyAverage);
965 ASSERT_EQ(false, firstSegment.usedThirdBuffer);
966
967 // The second segment should be a double-buffered segment, which implies that
968 // the occupancy average should be between 0 and 1, but usedThirdBuffer
969 // should be true
970 const auto& secondSegment = history[0];
971 ASSERT_EQ(7u, secondSegment.numFrames);
972 ASSERT_LT(0, secondSegment.occupancyAverage);
973 ASSERT_GT(1, secondSegment.occupancyAverage);
974 ASSERT_EQ(true, secondSegment.usedThirdBuffer);
975
976 // If we read the segments again without flushing, we shouldn't get any new
977 // segments
978 ASSERT_EQ(OK, mConsumer->getOccupancyHistory(false, &history));
979 ASSERT_EQ(0u, history.size());
980
981 // Read the segments again, this time forcing a flush so we get the third
982 // segment
983 ASSERT_EQ(OK, mConsumer->getOccupancyHistory(true, &history));
984 ASSERT_EQ(1u, history.size());
985
986 // This segment should be a triple-buffered segment, which implies that the
987 // occupancy average should be between 1 and 2, and usedThirdBuffer should
988 // be true
989 const auto& thirdSegment = history[0];
990 ASSERT_EQ(6u, thirdSegment.numFrames);
991 ASSERT_LT(1, thirdSegment.occupancyAverage);
992 ASSERT_GT(2, thirdSegment.occupancyAverage);
993 ASSERT_EQ(true, thirdSegment.usedThirdBuffer);
994}
995
Shuzhen Wang067fcd32019-08-14 10:41:12 -0700996struct BufferDiscardedListener : public BnProducerListener {
997public:
998 BufferDiscardedListener() = default;
999 virtual ~BufferDiscardedListener() = default;
1000
1001 virtual void onBufferReleased() {}
1002 virtual bool needsReleaseNotify() { return false; }
1003 virtual void onBuffersDiscarded(const std::vector<int32_t>& slots) {
1004 mDiscardedSlots.insert(mDiscardedSlots.end(), slots.begin(), slots.end());
1005 }
1006
1007 const std::vector<int32_t>& getDiscardedSlots() const { return mDiscardedSlots; }
1008private:
1009 // No need to use lock given the test triggers the listener in the same
1010 // thread context.
1011 std::vector<int32_t> mDiscardedSlots;
1012};
1013
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001014TEST_F(BufferQueueTest, TestDiscardFreeBuffers) {
1015 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -07001016 sp<MockConsumer> mc(new MockConsumer);
1017 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001018 IGraphicBufferProducer::QueueBufferOutput output;
Shuzhen Wang067fcd32019-08-14 10:41:12 -07001019 sp<BufferDiscardedListener> pl(new BufferDiscardedListener);
1020 ASSERT_EQ(OK, mProducer->connect(pl,
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001021 NATIVE_WINDOW_API_CPU, false, &output));
1022
1023 int slot = BufferQueue::INVALID_BUFFER_SLOT;
1024 sp<Fence> fence = Fence::NO_FENCE;
1025 sp<GraphicBuffer> buffer = nullptr;
1026 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1027 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1028 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1029 BufferItem item{};
1030
1031 // Preallocate, dequeue, request, and cancel 4 buffers so we don't get
1032 // BUFFER_NEEDS_REALLOCATION below
1033 int slots[4] = {};
1034 mProducer->setMaxDequeuedBufferCount(4);
1035 for (size_t i = 0; i < 4; ++i) {
Ian Elliottd11b0442017-07-18 11:05:49 -06001036 status_t result =
1037 mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0, 0, nullptr, nullptr);
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001038 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1039 ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
1040 }
1041 for (size_t i = 0; i < 4; ++i) {
1042 ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE));
1043 }
1044
1045 // Get buffers in all states: dequeued, filled, acquired, free
1046
1047 // Fill 3 buffers
Ian Elliottd11b0442017-07-18 11:05:49 -06001048 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001049 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
Ian Elliottd11b0442017-07-18 11:05:49 -06001050 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001051 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
Ian Elliottd11b0442017-07-18 11:05:49 -06001052 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001053 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1054 // Dequeue 1 buffer
Ian Elliottd11b0442017-07-18 11:05:49 -06001055 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001056
1057 // Acquire and free 1 buffer
1058 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1059 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
1060 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
Shuzhen Wang067fcd32019-08-14 10:41:12 -07001061 int releasedSlot = item.mSlot;
1062
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001063 // Acquire 1 buffer, leaving 1 filled buffer in queue
1064 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1065
1066 // Now discard the free buffers
1067 ASSERT_EQ(OK, mConsumer->discardFreeBuffers());
1068
Shuzhen Wang067fcd32019-08-14 10:41:12 -07001069 // Check onBuffersDiscarded is called with correct slots
1070 auto buffersDiscarded = pl->getDiscardedSlots();
1071 ASSERT_EQ(buffersDiscarded.size(), 1);
1072 ASSERT_EQ(buffersDiscarded[0], releasedSlot);
1073
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001074 // Check no free buffers in dump
1075 String8 dumpString;
Dan Stoza0c9a1ed2017-04-06 15:10:21 -07001076 mConsumer->dumpState(String8{}, &dumpString);
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001077
1078 // Parse the dump to ensure that all buffer slots that are FREE also
1079 // have a null GraphicBuffer
1080 // Fragile - assumes the following format for the dump for a buffer entry:
1081 // ":%p\][^:]*state=FREE" where %p is the buffer pointer in hex.
1082 ssize_t idx = dumpString.find("state=FREE");
1083 while (idx != -1) {
1084 ssize_t bufferPtrIdx = idx - 1;
1085 while (bufferPtrIdx > 0) {
1086 if (dumpString[bufferPtrIdx] == ':') {
1087 bufferPtrIdx++;
1088 break;
1089 }
1090 bufferPtrIdx--;
1091 }
1092 ASSERT_GT(bufferPtrIdx, 0) << "Can't parse queue dump to validate";
1093 ssize_t nullPtrIdx = dumpString.find("0x0]", bufferPtrIdx);
1094 ASSERT_EQ(bufferPtrIdx, nullPtrIdx) << "Free buffer not discarded";
1095 idx = dumpString.find("FREE", idx + 1);
1096 }
1097}
1098
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001099TEST_F(BufferQueueTest, TestBufferReplacedInQueueBuffer) {
1100 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -07001101 sp<MockConsumer> mc(new MockConsumer);
1102 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001103 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -07001104 ASSERT_EQ(OK,
1105 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001106 ASSERT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
1107
1108 int slot = BufferQueue::INVALID_BUFFER_SLOT;
1109 sp<Fence> fence = Fence::NO_FENCE;
1110 sp<GraphicBuffer> buffer = nullptr;
1111 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1112 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1113 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1114 BufferItem item{};
1115
1116 // Preallocate, dequeue, request, and cancel 2 buffers so we don't get
1117 // BUFFER_NEEDS_REALLOCATION below
1118 int slots[2] = {};
1119 ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(2));
1120 for (size_t i = 0; i < 2; ++i) {
Ian Elliottd11b0442017-07-18 11:05:49 -06001121 status_t result =
1122 mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0, 0, nullptr, nullptr);
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001123 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1124 ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
1125 }
1126 for (size_t i = 0; i < 2; ++i) {
1127 ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE));
1128 }
1129
1130 // Fill 2 buffers without consumer consuming them. Verify that all
1131 // queued buffer returns proper bufferReplaced flag
Ian Elliottd11b0442017-07-18 11:05:49 -06001132 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001133 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1134 ASSERT_EQ(false, output.bufferReplaced);
Ian Elliottd11b0442017-07-18 11:05:49 -06001135 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001136 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1137 ASSERT_EQ(true, output.bufferReplaced);
1138}
1139
Dan Stozad4c6f992017-03-21 13:43:22 -07001140TEST_F(BufferQueueTest, TestStaleBufferHandleSentAfterDisconnect) {
1141 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -07001142 sp<MockConsumer> mc(new MockConsumer);
1143 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Dan Stozad4c6f992017-03-21 13:43:22 -07001144 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -07001145 sp<IProducerListener> fakeListener(new StubProducerListener);
1146 ASSERT_EQ(OK, mProducer->connect(fakeListener, NATIVE_WINDOW_API_CPU, true, &output));
Dan Stozad4c6f992017-03-21 13:43:22 -07001147
1148 int slot = BufferQueue::INVALID_BUFFER_SLOT;
1149 sp<Fence> fence = Fence::NO_FENCE;
1150 sp<GraphicBuffer> buffer = nullptr;
1151 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1152 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1153 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1154
1155 // Dequeue, request, and queue one buffer
Ian Elliottd11b0442017-07-18 11:05:49 -06001156 status_t result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr);
Dan Stozad4c6f992017-03-21 13:43:22 -07001157 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1158 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
1159 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1160
1161 // Acquire and release the buffer. Upon acquiring, the buffer handle should
1162 // be non-null since this is the first time we've acquired this slot.
1163 BufferItem item;
1164 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1165 ASSERT_EQ(slot, item.mSlot);
1166 ASSERT_NE(nullptr, item.mGraphicBuffer.get());
1167 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
1168 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
1169
1170 // Dequeue and queue the buffer again
Ian Elliottd11b0442017-07-18 11:05:49 -06001171 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stozad4c6f992017-03-21 13:43:22 -07001172 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1173
1174 // Acquire and release the buffer again. Upon acquiring, the buffer handle
1175 // should be null since this is not the first time we've acquired this slot.
1176 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1177 ASSERT_EQ(slot, item.mSlot);
1178 ASSERT_EQ(nullptr, item.mGraphicBuffer.get());
1179 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
1180 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
1181
1182 // Dequeue and queue the buffer again
Ian Elliottd11b0442017-07-18 11:05:49 -06001183 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stozad4c6f992017-03-21 13:43:22 -07001184 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1185
1186 // Disconnect the producer end. This should clear all of the slots and mark
1187 // the buffer in the queue as stale.
1188 ASSERT_EQ(OK, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
1189
1190 // Acquire the buffer again. Upon acquiring, the buffer handle should not be
1191 // null since the queued buffer should have been marked as stale, which
1192 // should trigger the BufferQueue to resend the buffer handle.
1193 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1194 ASSERT_EQ(slot, item.mSlot);
1195 ASSERT_NE(nullptr, item.mGraphicBuffer.get());
1196}
1197
Wonsik Kim3e198b22017-04-07 15:43:16 -07001198TEST_F(BufferQueueTest, TestProducerConnectDisconnect) {
1199 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -07001200 sp<MockConsumer> mc(new MockConsumer);
1201 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Wonsik Kim3e198b22017-04-07 15:43:16 -07001202 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -07001203 sp<IProducerListener> fakeListener(new StubProducerListener);
Wonsik Kim3e198b22017-04-07 15:43:16 -07001204 ASSERT_EQ(NO_INIT, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
Peiyong Lind8460c82020-07-28 16:04:22 -07001205 ASSERT_EQ(OK, mProducer->connect(fakeListener, NATIVE_WINDOW_API_CPU, true, &output));
1206 ASSERT_EQ(BAD_VALUE, mProducer->connect(fakeListener, NATIVE_WINDOW_API_MEDIA, true, &output));
Wonsik Kim3e198b22017-04-07 15:43:16 -07001207
1208 ASSERT_EQ(BAD_VALUE, mProducer->disconnect(NATIVE_WINDOW_API_MEDIA));
1209 ASSERT_EQ(OK, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
1210 ASSERT_EQ(NO_INIT, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
1211}
1212
Jamie Gennis9e75ddd2012-08-31 15:32:45 -07001213} // namespace android