blob: d5858815824121c20b6aacc27fb52b76cef433f2 [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
Nolan Scobie9c427942023-05-01 16:41:28 -040020#include "Constants.h"
Peiyong Lind8460c82020-07-28 16:04:22 -070021#include "MockConsumer.h"
Dan Stozac6f30bd2015-06-08 09:32:50 -070022
Dan Stozacf3834d2015-03-11 14:04:22 -070023#include <gui/BufferItem.h>
Dan Stozaf0eaf252014-03-21 13:05:51 -070024#include <gui/BufferQueue.h>
25#include <gui/IProducerListener.h>
Jamie Gennis9e75ddd2012-08-31 15:32:45 -070026
27#include <ui/GraphicBuffer.h>
Jamie Gennis9e75ddd2012-08-31 15:32:45 -070028
Dan Stoza1a0b8612014-03-20 15:36:31 -070029#include <binder/IPCThreadState.h>
Dan Stoza9f3053d2014-03-06 15:14:33 -080030#include <binder/IServiceManager.h>
Dan Stoza1a0b8612014-03-20 15:36:31 -070031#include <binder/ProcessState.h>
Dan Stozaf0eaf252014-03-21 13:05:51 -070032
33#include <utils/String8.h>
34#include <utils/threads.h>
35
Mathias Agopian6a3c05b2017-04-27 20:06:55 -070036#include <system/window.h>
37
Dan Stozaf0eaf252014-03-21 13:05:51 -070038#include <gtest/gtest.h>
Jamie Gennis9e75ddd2012-08-31 15:32:45 -070039
Dan Stozae77c7662016-05-13 11:37:28 -070040#include <thread>
41
42using namespace std::chrono_literals;
43
Jamie Gennis9e75ddd2012-08-31 15:32:45 -070044namespace android {
45
46class BufferQueueTest : public ::testing::Test {
Dan Stoza9f3053d2014-03-06 15:14:33 -080047
48public:
Jamie Gennis9e75ddd2012-08-31 15:32:45 -070049protected:
Igor Murashkin7ea777f2013-11-18 16:58:36 -080050 void GetMinUndequeuedBufferCount(int* bufferCount) {
Yi Konga03e0442018-07-17 11:16:57 -070051 ASSERT_TRUE(bufferCount != nullptr);
Dan Stoza9f3053d2014-03-06 15:14:33 -080052 ASSERT_EQ(OK, mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
53 bufferCount));
54 ASSERT_GE(*bufferCount, 0);
Igor Murashkin7ea777f2013-11-18 16:58:36 -080055 }
56
Dan Stoza1a0b8612014-03-20 15:36:31 -070057 void createBufferQueue() {
58 BufferQueue::createBufferQueue(&mProducer, &mConsumer);
59 }
Jamie Gennis9e75ddd2012-08-31 15:32:45 -070060
Pablo Ceballosff95aab2016-01-13 17:09:58 -080061 void testBufferItem(const IGraphicBufferProducer::QueueBufferInput& input,
62 const BufferItem& item) {
63 int64_t timestamp;
64 bool isAutoTimestamp;
65 android_dataspace dataSpace;
66 Rect crop;
67 int scalingMode;
68 uint32_t transform;
69 sp<Fence> fence;
70
71 input.deflate(&timestamp, &isAutoTimestamp, &dataSpace, &crop,
Yi Konga03e0442018-07-17 11:16:57 -070072 &scalingMode, &transform, &fence, nullptr);
Pablo Ceballosff95aab2016-01-13 17:09:58 -080073 ASSERT_EQ(timestamp, item.mTimestamp);
74 ASSERT_EQ(isAutoTimestamp, item.mIsAutoTimestamp);
75 ASSERT_EQ(dataSpace, item.mDataSpace);
76 ASSERT_EQ(crop, item.mCrop);
77 ASSERT_EQ(static_cast<uint32_t>(scalingMode), item.mScalingMode);
78 ASSERT_EQ(transform, item.mTransform);
79 ASSERT_EQ(fence, item.mFence);
80 }
81
Dan Stoza1a0b8612014-03-20 15:36:31 -070082 sp<IGraphicBufferProducer> mProducer;
83 sp<IGraphicBufferConsumer> mConsumer;
84};
Dan Stoza9f3053d2014-03-06 15:14:33 -080085
Dan Stozaf8cebe52015-04-20 12:09:38 -070086static const uint32_t TEST_DATA = 0x12345678u;
87
Dan Stoza1a0b8612014-03-20 15:36:31 -070088// XXX: Tests that fork a process to hold the BufferQueue must run before tests
89// that use a local BufferQueue, or else Binder will get unhappy
Kalle Raita88752d72017-03-27 14:11:54 -070090//
91// In one instance this was a crash in the createBufferQueue where the
92// binder call to create a buffer allocator apparently got garbage back.
93// See b/36592665.
94TEST_F(BufferQueueTest, DISABLED_BufferQueueInAnotherProcess) {
Dan Stoza1a0b8612014-03-20 15:36:31 -070095 const String16 PRODUCER_NAME = String16("BQTestProducer");
96 const String16 CONSUMER_NAME = String16("BQTestConsumer");
97
98 pid_t forkPid = fork();
99 ASSERT_NE(forkPid, -1);
100
101 if (forkPid == 0) {
102 // Child process
Dan Stozab3d0bdf2014-04-07 16:33:59 -0700103 sp<IGraphicBufferProducer> producer;
104 sp<IGraphicBufferConsumer> consumer;
Dan Stoza1a0b8612014-03-20 15:36:31 -0700105 BufferQueue::createBufferQueue(&producer, &consumer);
106 sp<IServiceManager> serviceManager = defaultServiceManager();
Marco Nelissen097ca272014-11-14 08:01:01 -0800107 serviceManager->addService(PRODUCER_NAME, IInterface::asBinder(producer));
108 serviceManager->addService(CONSUMER_NAME, IInterface::asBinder(consumer));
Dan Stoza1a0b8612014-03-20 15:36:31 -0700109 ProcessState::self()->startThreadPool();
110 IPCThreadState::self()->joinThreadPool();
111 LOG_ALWAYS_FATAL("Shouldn't be here");
112 }
113
114 sp<IServiceManager> serviceManager = defaultServiceManager();
115 sp<IBinder> binderProducer =
116 serviceManager->getService(PRODUCER_NAME);
117 mProducer = interface_cast<IGraphicBufferProducer>(binderProducer);
Yi Konga03e0442018-07-17 11:16:57 -0700118 EXPECT_TRUE(mProducer != nullptr);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700119 sp<IBinder> binderConsumer =
120 serviceManager->getService(CONSUMER_NAME);
121 mConsumer = interface_cast<IGraphicBufferConsumer>(binderConsumer);
Yi Konga03e0442018-07-17 11:16:57 -0700122 EXPECT_TRUE(mConsumer != nullptr);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700123
Peiyong Lind8460c82020-07-28 16:04:22 -0700124 sp<MockConsumer> mc(new MockConsumer);
125 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Dan Stoza1a0b8612014-03-20 15:36:31 -0700126 IGraphicBufferProducer::QueueBufferOutput output;
127 ASSERT_EQ(OK,
Yi Konga03e0442018-07-17 11:16:57 -0700128 mProducer->connect(nullptr, NATIVE_WINDOW_API_CPU, false, &output));
Dan Stoza1a0b8612014-03-20 15:36:31 -0700129
130 int slot;
131 sp<Fence> fence;
132 sp<GraphicBuffer> buffer;
133 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600134 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
135 nullptr, nullptr));
Dan Stoza1a0b8612014-03-20 15:36:31 -0700136 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
137
138 uint32_t* dataIn;
139 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
140 reinterpret_cast<void**>(&dataIn)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700141 *dataIn = TEST_DATA;
Dan Stoza1a0b8612014-03-20 15:36:31 -0700142 ASSERT_EQ(OK, buffer->unlock());
143
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800144 IGraphicBufferProducer::QueueBufferInput input(0, false,
145 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700146 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700147 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
148
Dan Stozacf3834d2015-03-11 14:04:22 -0700149 BufferItem item;
Dan Stoza1a0b8612014-03-20 15:36:31 -0700150 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
151
152 uint32_t* dataOut;
153 ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
154 reinterpret_cast<void**>(&dataOut)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700155 ASSERT_EQ(*dataOut, TEST_DATA);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700156 ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
157}
158
silence_dogoode9d092a2019-06-19 16:14:53 -0700159TEST_F(BufferQueueTest, GetMaxBufferCountInQueueBufferOutput_Succeeds) {
160 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700161 sp<MockConsumer> mc(new MockConsumer);
162 mConsumer->consumerConnect(mc, false);
silence_dogoode9d092a2019-06-19 16:14:53 -0700163 int bufferCount = 50;
164 mConsumer->setMaxBufferCount(bufferCount);
165
166 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700167 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output);
silence_dogoode9d092a2019-06-19 16:14:53 -0700168 ASSERT_EQ(output.maxBufferCount, bufferCount);
169}
170
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700171TEST_F(BufferQueueTest, AcquireBuffer_ExceedsMaxAcquireCount_Fails) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700172 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700173 sp<MockConsumer> mc(new MockConsumer);
174 mConsumer->consumerConnect(mc, false);
Andy McFadden2adaf042012-12-18 09:49:45 -0800175 IGraphicBufferProducer::QueueBufferOutput qbo;
Peiyong Lind8460c82020-07-28 16:04:22 -0700176 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &qbo);
Pablo Ceballosfa455352015-08-12 17:47:47 -0700177 mProducer->setMaxDequeuedBufferCount(3);
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700178
179 int slot;
180 sp<Fence> fence;
181 sp<GraphicBuffer> buf;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800182 IGraphicBufferProducer::QueueBufferInput qbi(0, false,
183 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700184 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Dan Stozacf3834d2015-03-11 14:04:22 -0700185 BufferItem item;
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700186
187 for (int i = 0; i < 2; i++) {
Andy McFadden2adaf042012-12-18 09:49:45 -0800188 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600189 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
190 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800191 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
192 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
193 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700194 }
195
Andy McFadden2adaf042012-12-18 09:49:45 -0800196 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600197 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
198 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800199 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
200 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700201
202 // Acquire the third buffer, which should fail.
Dan Stoza9f3053d2014-03-06 15:14:33 -0800203 ASSERT_EQ(INVALID_OPERATION, mConsumer->acquireBuffer(&item, 0));
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700204}
205
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700206TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithIllegalValues_ReturnsError) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700207 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700208 sp<MockConsumer> mc(new MockConsumer);
209 mConsumer->consumerConnect(mc, false);
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700210
Pablo Ceballos72daab62015-12-07 16:38:43 -0800211 EXPECT_EQ(OK, mConsumer->setMaxBufferCount(10));
212 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(10));
213
214 IGraphicBufferProducer::QueueBufferOutput qbo;
Peiyong Lind8460c82020-07-28 16:04:22 -0700215 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &qbo);
Pablo Ceballos72daab62015-12-07 16:38:43 -0800216 mProducer->setMaxDequeuedBufferCount(3);
217
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800218 int minBufferCount;
219 ASSERT_NO_FATAL_FAILURE(GetMinUndequeuedBufferCount(&minBufferCount));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800220 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(
221 minBufferCount - 1));
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800222
Dan Stoza9f3053d2014-03-06 15:14:33 -0800223 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(0));
224 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(-3));
225 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700226 BufferQueue::MAX_MAX_ACQUIRED_BUFFERS+1));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800227 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(100));
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700228
Pablo Ceballos72daab62015-12-07 16:38:43 -0800229 int slot;
230 sp<Fence> fence;
231 sp<GraphicBuffer> buf;
232 IGraphicBufferProducer::QueueBufferInput qbi(0, false,
233 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
234 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
235 BufferItem item;
236 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(3));
237 for (int i = 0; i < 3; i++) {
238 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600239 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
240 nullptr, nullptr));
Pablo Ceballos72daab62015-12-07 16:38:43 -0800241 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
242 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
243 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
244 }
245
246 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(2));
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700247}
248
249TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithLegalValues_Succeeds) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700250 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700251 sp<MockConsumer> mc(new MockConsumer);
252 mConsumer->consumerConnect(mc, false);
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700253
Pablo Ceballos72daab62015-12-07 16:38:43 -0800254 IGraphicBufferProducer::QueueBufferOutput qbo;
Peiyong Lind8460c82020-07-28 16:04:22 -0700255 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &qbo);
Pablo Ceballos72daab62015-12-07 16:38:43 -0800256 mProducer->setMaxDequeuedBufferCount(2);
257
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800258 int minBufferCount;
259 ASSERT_NO_FATAL_FAILURE(GetMinUndequeuedBufferCount(&minBufferCount));
260
Dan Stoza9f3053d2014-03-06 15:14:33 -0800261 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
262 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(2));
263 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(minBufferCount));
Pablo Ceballos72daab62015-12-07 16:38:43 -0800264
265 int slot;
266 sp<Fence> fence;
267 sp<GraphicBuffer> buf;
268 IGraphicBufferProducer::QueueBufferInput qbi(0, false,
269 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
270 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
271 BufferItem item;
272
273 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600274 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
275 nullptr, nullptr));
Pablo Ceballos72daab62015-12-07 16:38:43 -0800276 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
277 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
278 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
279
280 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(3));
281
282 for (int i = 0; i < 2; i++) {
283 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600284 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
285 nullptr, nullptr));
Pablo Ceballos72daab62015-12-07 16:38:43 -0800286 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
287 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
288 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
289 }
290
Dan Stoza9f3053d2014-03-06 15:14:33 -0800291 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700292 BufferQueue::MAX_MAX_ACQUIRED_BUFFERS));
293}
294
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700295TEST_F(BufferQueueTest, SetMaxBufferCountWithLegalValues_Succeeds) {
296 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700297 sp<MockConsumer> mc(new MockConsumer);
298 mConsumer->consumerConnect(mc, false);
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700299
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700300 // Test shared buffer mode
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700301 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
302}
303
304TEST_F(BufferQueueTest, SetMaxBufferCountWithIllegalValues_ReturnsError) {
305 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700306 sp<MockConsumer> mc(new MockConsumer);
307 mConsumer->consumerConnect(mc, false);
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700308
309 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(0));
310 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(
311 BufferQueue::NUM_BUFFER_SLOTS + 1));
312
313 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(5));
314 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(3));
315}
316
Dan Stoza9f3053d2014-03-06 15:14:33 -0800317TEST_F(BufferQueueTest, DetachAndReattachOnProducerSide) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700318 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700319 sp<MockConsumer> mc(new MockConsumer);
320 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800321 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700322 ASSERT_EQ(OK,
323 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800324
325 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(-1)); // Index too low
326 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(
327 BufferQueueDefs::NUM_BUFFER_SLOTS)); // Index too high
328 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(0)); // Not dequeued
329
330 int slot;
331 sp<Fence> fence;
332 sp<GraphicBuffer> buffer;
333 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600334 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
335 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800336 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(slot)); // Not requested
337 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
338 ASSERT_EQ(OK, mProducer->detachBuffer(slot));
339 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(slot)); // Not dequeued
340
341 sp<GraphicBuffer> safeToClobberBuffer;
342 // Can no longer request buffer from this slot
343 ASSERT_EQ(BAD_VALUE, mProducer->requestBuffer(slot, &safeToClobberBuffer));
344
345 uint32_t* dataIn;
346 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
347 reinterpret_cast<void**>(&dataIn)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700348 *dataIn = TEST_DATA;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800349 ASSERT_EQ(OK, buffer->unlock());
350
351 int newSlot;
Yi Konga03e0442018-07-17 11:16:57 -0700352 ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(nullptr, safeToClobberBuffer));
353 ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(&newSlot, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800354
355 ASSERT_EQ(OK, mProducer->attachBuffer(&newSlot, buffer));
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800356 IGraphicBufferProducer::QueueBufferInput input(0, false,
357 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700358 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800359 ASSERT_EQ(OK, mProducer->queueBuffer(newSlot, input, &output));
360
Dan Stozacf3834d2015-03-11 14:04:22 -0700361 BufferItem item;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800362 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
363
364 uint32_t* dataOut;
365 ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
366 reinterpret_cast<void**>(&dataOut)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700367 ASSERT_EQ(*dataOut, TEST_DATA);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700368 ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
Dan Stoza9f3053d2014-03-06 15:14:33 -0800369}
370
371TEST_F(BufferQueueTest, DetachAndReattachOnConsumerSide) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700372 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700373 sp<MockConsumer> mc(new MockConsumer);
374 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800375 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700376 ASSERT_EQ(OK,
377 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800378
379 int slot;
380 sp<Fence> fence;
381 sp<GraphicBuffer> buffer;
382 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600383 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
384 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800385 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800386 IGraphicBufferProducer::QueueBufferInput input(0, false,
387 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700388 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800389 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
390
391 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(-1)); // Index too low
392 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(
393 BufferQueueDefs::NUM_BUFFER_SLOTS)); // Index too high
394 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(0)); // Not acquired
395
Dan Stozacf3834d2015-03-11 14:04:22 -0700396 BufferItem item;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800397 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
398
Pablo Ceballos47650f42015-08-04 16:38:17 -0700399 ASSERT_EQ(OK, mConsumer->detachBuffer(item.mSlot));
400 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(item.mSlot)); // Not acquired
Dan Stoza9f3053d2014-03-06 15:14:33 -0800401
402 uint32_t* dataIn;
403 ASSERT_EQ(OK, item.mGraphicBuffer->lock(
404 GraphicBuffer::USAGE_SW_WRITE_OFTEN,
405 reinterpret_cast<void**>(&dataIn)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700406 *dataIn = TEST_DATA;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800407 ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
408
409 int newSlot;
410 sp<GraphicBuffer> safeToClobberBuffer;
Yi Konga03e0442018-07-17 11:16:57 -0700411 ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(nullptr, safeToClobberBuffer));
412 ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(&newSlot, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800413 ASSERT_EQ(OK, mConsumer->attachBuffer(&newSlot, item.mGraphicBuffer));
414
Dan Stoza99b18b42014-03-28 15:34:33 -0700415 ASSERT_EQ(OK, mConsumer->releaseBuffer(newSlot, 0, EGL_NO_DISPLAY,
Dan Stoza9f3053d2014-03-06 15:14:33 -0800416 EGL_NO_SYNC_KHR, Fence::NO_FENCE));
417
418 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600419 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
420 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800421 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
422
423 uint32_t* dataOut;
424 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
425 reinterpret_cast<void**>(&dataOut)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700426 ASSERT_EQ(*dataOut, TEST_DATA);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700427 ASSERT_EQ(OK, buffer->unlock());
Dan Stoza9f3053d2014-03-06 15:14:33 -0800428}
429
430TEST_F(BufferQueueTest, MoveFromConsumerToProducer) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700431 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700432 sp<MockConsumer> mc(new MockConsumer);
433 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800434 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700435 ASSERT_EQ(OK,
436 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800437
438 int slot;
439 sp<Fence> fence;
440 sp<GraphicBuffer> buffer;
441 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600442 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
443 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800444 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
445
446 uint32_t* dataIn;
447 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
448 reinterpret_cast<void**>(&dataIn)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700449 *dataIn = TEST_DATA;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800450 ASSERT_EQ(OK, buffer->unlock());
451
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800452 IGraphicBufferProducer::QueueBufferInput input(0, false,
453 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700454 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800455 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
456
Dan Stozacf3834d2015-03-11 14:04:22 -0700457 BufferItem item;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800458 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
Pablo Ceballos47650f42015-08-04 16:38:17 -0700459 ASSERT_EQ(OK, mConsumer->detachBuffer(item.mSlot));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800460
461 int newSlot;
462 ASSERT_EQ(OK, mProducer->attachBuffer(&newSlot, item.mGraphicBuffer));
463 ASSERT_EQ(OK, mProducer->queueBuffer(newSlot, input, &output));
464 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
465
466 uint32_t* dataOut;
467 ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
468 reinterpret_cast<void**>(&dataOut)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700469 ASSERT_EQ(*dataOut, TEST_DATA);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700470 ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
Dan Stoza9f3053d2014-03-06 15:14:33 -0800471}
472
Dan Stoza9de72932015-04-16 17:28:43 -0700473TEST_F(BufferQueueTest, TestDisallowingAllocation) {
474 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700475 sp<MockConsumer> mc(new MockConsumer);
476 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Dan Stoza9de72932015-04-16 17:28:43 -0700477 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700478 ASSERT_EQ(OK,
479 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Dan Stoza9de72932015-04-16 17:28:43 -0700480
481 static const uint32_t WIDTH = 320;
482 static const uint32_t HEIGHT = 240;
483
484 ASSERT_EQ(OK, mConsumer->setDefaultBufferSize(WIDTH, HEIGHT));
485
486 int slot;
487 sp<Fence> fence;
488 sp<GraphicBuffer> buffer;
489 // This should return an error since it would require an allocation
490 ASSERT_EQ(OK, mProducer->allowAllocation(false));
Ian Elliottd11b0442017-07-18 11:05:49 -0600491 ASSERT_EQ(WOULD_BLOCK,
492 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
493 nullptr, nullptr));
Dan Stoza9de72932015-04-16 17:28:43 -0700494
495 // This should succeed, now that we've lifted the prohibition
496 ASSERT_EQ(OK, mProducer->allowAllocation(true));
497 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600498 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
499 nullptr, nullptr));
Dan Stoza9de72932015-04-16 17:28:43 -0700500
501 // Release the previous buffer back to the BufferQueue
502 mProducer->cancelBuffer(slot, fence);
503
504 // This should fail since we're requesting a different size
505 ASSERT_EQ(OK, mProducer->allowAllocation(false));
Ian Elliottd11b0442017-07-18 11:05:49 -0600506 ASSERT_EQ(WOULD_BLOCK,
507 mProducer->dequeueBuffer(&slot, &fence, WIDTH * 2, HEIGHT * 2, 0,
508 GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr, nullptr));
Dan Stoza9de72932015-04-16 17:28:43 -0700509}
510
Dan Stoza812ed062015-06-02 15:45:22 -0700511TEST_F(BufferQueueTest, TestGenerationNumbers) {
512 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700513 sp<MockConsumer> mc(new MockConsumer);
514 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Dan Stoza812ed062015-06-02 15:45:22 -0700515 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700516 ASSERT_EQ(OK,
517 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Dan Stoza812ed062015-06-02 15:45:22 -0700518
519 ASSERT_EQ(OK, mProducer->setGenerationNumber(1));
520
521 // Get one buffer to play with
522 int slot;
523 sp<Fence> fence;
524 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Nolan Scobie9c427942023-05-01 16:41:28 -0400525 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
526 nullptr));
Dan Stoza812ed062015-06-02 15:45:22 -0700527
528 sp<GraphicBuffer> buffer;
529 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
530
531 // Ensure that the generation number we set propagates to allocated buffers
532 ASSERT_EQ(1U, buffer->getGenerationNumber());
533
534 ASSERT_EQ(OK, mProducer->detachBuffer(slot));
535
536 ASSERT_EQ(OK, mProducer->setGenerationNumber(2));
537
538 // These should fail, since we've changed the generation number on the queue
539 int outSlot;
540 ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(&outSlot, buffer));
541 ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(&outSlot, buffer));
542
543 buffer->setGenerationNumber(2);
544
545 // This should succeed now that we've changed the buffer's generation number
546 ASSERT_EQ(OK, mProducer->attachBuffer(&outSlot, buffer));
547
548 ASSERT_EQ(OK, mProducer->detachBuffer(outSlot));
549
550 // This should also succeed with the new generation number
551 ASSERT_EQ(OK, mConsumer->attachBuffer(&outSlot, buffer));
552}
553
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700554TEST_F(BufferQueueTest, TestSharedBufferModeWithoutAutoRefresh) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700555 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700556 sp<MockConsumer> mc(new MockConsumer);
557 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700558 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700559 ASSERT_EQ(OK,
560 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700561
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700562 ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700563
564 // Get a buffer
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700565 int sharedSlot;
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700566 sp<Fence> fence;
567 sp<GraphicBuffer> buffer;
568 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Nolan Scobie9c427942023-05-01 16:41:28 -0400569 mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
570 nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700571 ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700572
573 // Queue the buffer
574 IGraphicBufferProducer::QueueBufferInput input(0, false,
575 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
576 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700577 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700578
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800579 // Repeatedly queue and dequeue a buffer from the producer side, it should
580 // always return the same one. And we won't run out of buffers because it's
581 // always the same one and because async mode gets enabled.
582 int slot;
583 for (int i = 0; i < 5; i++) {
Nolan Scobie9c427942023-05-01 16:41:28 -0400584 ASSERT_EQ(OK,
585 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
586 nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700587 ASSERT_EQ(sharedSlot, slot);
588 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800589 }
590
591 // acquire the buffer
592 BufferItem item;
593 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700594 ASSERT_EQ(sharedSlot, item.mSlot);
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800595 testBufferItem(input, item);
596 ASSERT_EQ(true, item.mQueuedBuffer);
597 ASSERT_EQ(false, item.mAutoRefresh);
598
599 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
600 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
601
602 // attempt to acquire a second time should return no buffer available
603 ASSERT_EQ(IGraphicBufferConsumer::NO_BUFFER_AVAILABLE,
604 mConsumer->acquireBuffer(&item, 0));
605}
606
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700607TEST_F(BufferQueueTest, TestSharedBufferModeWithAutoRefresh) {
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800608 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700609 sp<MockConsumer> mc(new MockConsumer);
610 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800611 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700612 ASSERT_EQ(OK,
613 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800614
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700615 ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800616 ASSERT_EQ(OK, mProducer->setAutoRefresh(true));
617
618 // Get a buffer
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700619 int sharedSlot;
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800620 sp<Fence> fence;
621 sp<GraphicBuffer> buffer;
622 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Nolan Scobie9c427942023-05-01 16:41:28 -0400623 mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
624 nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700625 ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800626
627 // Queue the buffer
628 IGraphicBufferProducer::QueueBufferInput input(0, false,
629 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
630 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700631 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800632
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700633 // Repeatedly acquire and release a buffer from the consumer side, it should
634 // always return the same one.
635 BufferItem item;
636 for (int i = 0; i < 5; i++) {
637 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700638 ASSERT_EQ(sharedSlot, item.mSlot);
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800639 testBufferItem(input, item);
640 ASSERT_EQ(i == 0, item.mQueuedBuffer);
641 ASSERT_EQ(true, item.mAutoRefresh);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700642
643 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
644 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
645 }
646
647 // Repeatedly queue and dequeue a buffer from the producer side, it should
648 // always return the same one.
649 int slot;
650 for (int i = 0; i < 5; i++) {
Nolan Scobie9c427942023-05-01 16:41:28 -0400651 ASSERT_EQ(OK,
652 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
653 nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700654 ASSERT_EQ(sharedSlot, slot);
655 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700656 }
657
658 // Repeatedly acquire and release a buffer from the consumer side, it should
659 // always return the same one. First grabbing them from the queue and then
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700660 // when the queue is empty, returning the shared buffer.
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700661 for (int i = 0; i < 10; i++) {
662 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700663 ASSERT_EQ(sharedSlot, item.mSlot);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700664 ASSERT_EQ(0, item.mTimestamp);
665 ASSERT_EQ(false, item.mIsAutoTimestamp);
666 ASSERT_EQ(HAL_DATASPACE_UNKNOWN, item.mDataSpace);
667 ASSERT_EQ(Rect(0, 0, 1, 1), item.mCrop);
668 ASSERT_EQ(NATIVE_WINDOW_SCALING_MODE_FREEZE, item.mScalingMode);
Dan Stoza5ecfb682016-01-04 17:01:02 -0800669 ASSERT_EQ(0u, item.mTransform);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700670 ASSERT_EQ(Fence::NO_FENCE, item.mFence);
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800671 ASSERT_EQ(i == 0, item.mQueuedBuffer);
672 ASSERT_EQ(true, item.mAutoRefresh);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700673
674 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
675 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
676 }
677}
678
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700679TEST_F(BufferQueueTest, TestSharedBufferModeUsingAlreadyDequeuedBuffer) {
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700680 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700681 sp<MockConsumer> mc(new MockConsumer);
682 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700683 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700684 ASSERT_EQ(OK,
685 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700686
687 // Dequeue a buffer
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700688 int sharedSlot;
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700689 sp<Fence> fence;
690 sp<GraphicBuffer> buffer;
691 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Nolan Scobie9c427942023-05-01 16:41:28 -0400692 mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
693 nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700694 ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700695
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700696 // Enable shared buffer mode
697 ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700698
699 // Queue the buffer
700 IGraphicBufferProducer::QueueBufferInput input(0, false,
701 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
702 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700703 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700704
705 // Repeatedly queue and dequeue a buffer from the producer side, it should
706 // always return the same one. And we won't run out of buffers because it's
707 // always the same one and because async mode gets enabled.
708 int slot;
709 for (int i = 0; i < 5; i++) {
Nolan Scobie9c427942023-05-01 16:41:28 -0400710 ASSERT_EQ(OK,
711 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
712 nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700713 ASSERT_EQ(sharedSlot, slot);
714 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700715 }
716
717 // acquire the buffer
718 BufferItem item;
719 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700720 ASSERT_EQ(sharedSlot, item.mSlot);
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700721 testBufferItem(input, item);
722 ASSERT_EQ(true, item.mQueuedBuffer);
723 ASSERT_EQ(false, item.mAutoRefresh);
724
725 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
726 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
727
728 // attempt to acquire a second time should return no buffer available
729 ASSERT_EQ(IGraphicBufferConsumer::NO_BUFFER_AVAILABLE,
730 mConsumer->acquireBuffer(&item, 0));
731}
732
Dan Stoza127fc632015-06-30 13:43:32 -0700733TEST_F(BufferQueueTest, TestTimeouts) {
734 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700735 sp<MockConsumer> mc(new MockConsumer);
736 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Dan Stoza127fc632015-06-30 13:43:32 -0700737 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700738 ASSERT_EQ(OK,
739 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Dan Stoza127fc632015-06-30 13:43:32 -0700740
741 // Fill up the queue. Since the controlledByApp flags are set to true, this
742 // queue should be in non-blocking mode, and we should be recycling the same
743 // two buffers
744 for (int i = 0; i < 5; ++i) {
745 int slot = BufferQueue::INVALID_BUFFER_SLOT;
746 sp<Fence> fence = Fence::NO_FENCE;
Nolan Scobie9c427942023-05-01 16:41:28 -0400747 auto result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
748 nullptr, nullptr);
Dan Stoza127fc632015-06-30 13:43:32 -0700749 if (i < 2) {
750 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
751 result);
752 } else {
753 ASSERT_EQ(OK, result);
754 }
755 sp<GraphicBuffer> buffer;
756 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
757 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
758 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
759 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
760 IGraphicBufferProducer::QueueBufferOutput output{};
761 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
762 }
763
764 const auto TIMEOUT = ms2ns(250);
765 mProducer->setDequeueTimeout(TIMEOUT);
766
767 // Setting a timeout will change the BufferQueue into blocking mode (with
768 // one droppable buffer in the queue and one free from the previous
769 // dequeue/queues), so dequeue and queue two more buffers: one to replace
770 // the current droppable buffer, and a second to max out the buffer count
771 sp<GraphicBuffer> buffer; // Save a buffer to attach later
772 for (int i = 0; i < 2; ++i) {
773 int slot = BufferQueue::INVALID_BUFFER_SLOT;
774 sp<Fence> fence = Fence::NO_FENCE;
Nolan Scobie9c427942023-05-01 16:41:28 -0400775 ASSERT_EQ(OK,
776 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
777 nullptr, nullptr));
Dan Stoza127fc632015-06-30 13:43:32 -0700778 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
779 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
780 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
781 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
782 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
783 }
784
785 int slot = BufferQueue::INVALID_BUFFER_SLOT;
786 sp<Fence> fence = Fence::NO_FENCE;
787 auto startTime = systemTime();
Nolan Scobie9c427942023-05-01 16:41:28 -0400788 ASSERT_EQ(TIMED_OUT,
789 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
790 nullptr));
Dan Stoza127fc632015-06-30 13:43:32 -0700791 ASSERT_GE(systemTime() - startTime, TIMEOUT);
792
793 // We're technically attaching the same buffer multiple times (since we
794 // queued it previously), but that doesn't matter for this test
795 startTime = systemTime();
796 ASSERT_EQ(TIMED_OUT, mProducer->attachBuffer(&slot, buffer));
797 ASSERT_GE(systemTime() - startTime, TIMEOUT);
798}
799
Dan Stoza5ecfb682016-01-04 17:01:02 -0800800TEST_F(BufferQueueTest, CanAttachWhileDisallowingAllocation) {
801 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700802 sp<MockConsumer> mc(new MockConsumer);
803 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Dan Stoza5ecfb682016-01-04 17:01:02 -0800804 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700805 ASSERT_EQ(OK,
806 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Dan Stoza5ecfb682016-01-04 17:01:02 -0800807
808 int slot = BufferQueue::INVALID_BUFFER_SLOT;
809 sp<Fence> sourceFence;
810 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Nolan Scobie9c427942023-05-01 16:41:28 -0400811 mProducer->dequeueBuffer(&slot, &sourceFence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
812 nullptr, nullptr));
Dan Stoza5ecfb682016-01-04 17:01:02 -0800813 sp<GraphicBuffer> buffer;
814 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
815 ASSERT_EQ(OK, mProducer->detachBuffer(slot));
816
817 ASSERT_EQ(OK, mProducer->allowAllocation(false));
818
819 slot = BufferQueue::INVALID_BUFFER_SLOT;
820 ASSERT_EQ(OK, mProducer->attachBuffer(&slot, buffer));
821}
822
Dan Stoza50101d02016-04-07 16:53:23 -0700823TEST_F(BufferQueueTest, CanRetrieveLastQueuedBuffer) {
824 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700825 sp<MockConsumer> mc(new MockConsumer);
826 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Dan Stoza50101d02016-04-07 16:53:23 -0700827 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700828 ASSERT_EQ(OK,
829 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
Dan Stoza50101d02016-04-07 16:53:23 -0700830
831 // Dequeue and queue the first buffer, storing the handle
832 int slot = BufferQueue::INVALID_BUFFER_SLOT;
833 sp<Fence> fence;
834 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Nolan Scobie9c427942023-05-01 16:41:28 -0400835 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
836 nullptr));
Dan Stoza50101d02016-04-07 16:53:23 -0700837 sp<GraphicBuffer> firstBuffer;
838 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &firstBuffer));
839
840 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
841 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
842 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
843 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
844
845 // Dequeue a second buffer
846 slot = BufferQueue::INVALID_BUFFER_SLOT;
847 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Nolan Scobie9c427942023-05-01 16:41:28 -0400848 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
849 nullptr));
Dan Stoza50101d02016-04-07 16:53:23 -0700850 sp<GraphicBuffer> secondBuffer;
851 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &secondBuffer));
852
853 // Ensure it's a new buffer
854 ASSERT_NE(firstBuffer->getNativeBuffer()->handle,
855 secondBuffer->getNativeBuffer()->handle);
856
857 // Queue the second buffer
858 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
859
860 // Acquire and release both buffers
861 for (size_t i = 0; i < 2; ++i) {
862 BufferItem item;
863 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
864 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
865 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
866 }
867
868 // Make sure we got the second buffer back
869 sp<GraphicBuffer> returnedBuffer;
870 sp<Fence> returnedFence;
John Reck1a61da52016-04-28 13:18:15 -0700871 float transform[16];
Dan Stoza50101d02016-04-07 16:53:23 -0700872 ASSERT_EQ(OK,
John Reck1a61da52016-04-28 13:18:15 -0700873 mProducer->getLastQueuedBuffer(&returnedBuffer, &returnedFence,
874 transform));
Dan Stoza50101d02016-04-07 16:53:23 -0700875 ASSERT_EQ(secondBuffer->getNativeBuffer()->handle,
876 returnedBuffer->getNativeBuffer()->handle);
877}
878
Dan Stozae77c7662016-05-13 11:37:28 -0700879TEST_F(BufferQueueTest, TestOccupancyHistory) {
880 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700881 sp<MockConsumer> mc(new MockConsumer);
882 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Dan Stozae77c7662016-05-13 11:37:28 -0700883 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700884 ASSERT_EQ(OK,
885 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
Dan Stozae77c7662016-05-13 11:37:28 -0700886
887 int slot = BufferQueue::INVALID_BUFFER_SLOT;
888 sp<Fence> fence = Fence::NO_FENCE;
889 sp<GraphicBuffer> buffer = nullptr;
890 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
891 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
892 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
893 BufferItem item{};
894
895 // Preallocate, dequeue, request, and cancel 3 buffers so we don't get
896 // BUFFER_NEEDS_REALLOCATION below
897 int slots[3] = {};
898 mProducer->setMaxDequeuedBufferCount(3);
899 for (size_t i = 0; i < 3; ++i) {
Nolan Scobie9c427942023-05-01 16:41:28 -0400900 status_t result = mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0,
901 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr);
Dan Stozae77c7662016-05-13 11:37:28 -0700902 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
903 ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
904 }
905 for (size_t i = 0; i < 3; ++i) {
906 ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE));
907 }
908
909 // Create 3 segments
910
911 // The first segment is a two-buffer segment, so we only put one buffer into
912 // the queue at a time
913 for (size_t i = 0; i < 5; ++i) {
Nolan Scobie9c427942023-05-01 16:41:28 -0400914 ASSERT_EQ(OK,
915 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
916 nullptr, nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700917 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
918 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
919 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
920 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
921 std::this_thread::sleep_for(16ms);
922 }
923
924 // Sleep between segments
925 std::this_thread::sleep_for(500ms);
926
927 // The second segment is a double-buffer segment. It starts the same as the
928 // two-buffer segment, but then at the end, we put two buffers in the queue
929 // at the same time before draining it.
930 for (size_t i = 0; i < 5; ++i) {
Nolan Scobie9c427942023-05-01 16:41:28 -0400931 ASSERT_EQ(OK,
932 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
933 nullptr, nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700934 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
935 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
936 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
937 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
938 std::this_thread::sleep_for(16ms);
939 }
Nolan Scobie9c427942023-05-01 16:41:28 -0400940 ASSERT_EQ(OK,
941 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
942 nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700943 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
Nolan Scobie9c427942023-05-01 16:41:28 -0400944 ASSERT_EQ(OK,
945 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
946 nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700947 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
948 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
949 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
950 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
951 std::this_thread::sleep_for(16ms);
952 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
953 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
954 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
955
956 // Sleep between segments
957 std::this_thread::sleep_for(500ms);
958
959 // The third segment is a triple-buffer segment, so the queue is switching
960 // between one buffer and two buffers deep.
Nolan Scobie9c427942023-05-01 16:41:28 -0400961 ASSERT_EQ(OK,
962 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
963 nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700964 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
965 for (size_t i = 0; i < 5; ++i) {
Nolan Scobie9c427942023-05-01 16:41:28 -0400966 ASSERT_EQ(OK,
967 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
968 nullptr, nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700969 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
970 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
971 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
972 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
973 std::this_thread::sleep_for(16ms);
974 }
975 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
976 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
977 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
978
979 // Now we read the segments
980 std::vector<OccupancyTracker::Segment> history;
981 ASSERT_EQ(OK, mConsumer->getOccupancyHistory(false, &history));
982
983 // Since we didn't force a flush, we should only get the first two segments
984 // (since the third segment hasn't been closed out by the appearance of a
985 // new segment yet)
986 ASSERT_EQ(2u, history.size());
987
988 // The first segment (which will be history[1], since the newest segment
989 // should be at the front of the vector) should be a two-buffer segment,
990 // which implies that the occupancy average should be between 0 and 1, and
991 // usedThirdBuffer should be false
992 const auto& firstSegment = history[1];
993 ASSERT_EQ(5u, firstSegment.numFrames);
994 ASSERT_LT(0, firstSegment.occupancyAverage);
995 ASSERT_GT(1, firstSegment.occupancyAverage);
996 ASSERT_EQ(false, firstSegment.usedThirdBuffer);
997
998 // The second segment should be a double-buffered segment, which implies that
999 // the occupancy average should be between 0 and 1, but usedThirdBuffer
1000 // should be true
1001 const auto& secondSegment = history[0];
1002 ASSERT_EQ(7u, secondSegment.numFrames);
1003 ASSERT_LT(0, secondSegment.occupancyAverage);
1004 ASSERT_GT(1, secondSegment.occupancyAverage);
1005 ASSERT_EQ(true, secondSegment.usedThirdBuffer);
1006
1007 // If we read the segments again without flushing, we shouldn't get any new
1008 // segments
1009 ASSERT_EQ(OK, mConsumer->getOccupancyHistory(false, &history));
1010 ASSERT_EQ(0u, history.size());
1011
1012 // Read the segments again, this time forcing a flush so we get the third
1013 // segment
1014 ASSERT_EQ(OK, mConsumer->getOccupancyHistory(true, &history));
1015 ASSERT_EQ(1u, history.size());
1016
1017 // This segment should be a triple-buffered segment, which implies that the
1018 // occupancy average should be between 1 and 2, and usedThirdBuffer should
1019 // be true
1020 const auto& thirdSegment = history[0];
1021 ASSERT_EQ(6u, thirdSegment.numFrames);
1022 ASSERT_LT(1, thirdSegment.occupancyAverage);
1023 ASSERT_GT(2, thirdSegment.occupancyAverage);
1024 ASSERT_EQ(true, thirdSegment.usedThirdBuffer);
1025}
1026
Shuzhen Wang067fcd32019-08-14 10:41:12 -07001027struct BufferDiscardedListener : public BnProducerListener {
1028public:
1029 BufferDiscardedListener() = default;
1030 virtual ~BufferDiscardedListener() = default;
1031
1032 virtual void onBufferReleased() {}
1033 virtual bool needsReleaseNotify() { return false; }
1034 virtual void onBuffersDiscarded(const std::vector<int32_t>& slots) {
1035 mDiscardedSlots.insert(mDiscardedSlots.end(), slots.begin(), slots.end());
1036 }
1037
1038 const std::vector<int32_t>& getDiscardedSlots() const { return mDiscardedSlots; }
1039private:
1040 // No need to use lock given the test triggers the listener in the same
1041 // thread context.
1042 std::vector<int32_t> mDiscardedSlots;
1043};
1044
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001045TEST_F(BufferQueueTest, TestDiscardFreeBuffers) {
1046 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -07001047 sp<MockConsumer> mc(new MockConsumer);
1048 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001049 IGraphicBufferProducer::QueueBufferOutput output;
Shuzhen Wang067fcd32019-08-14 10:41:12 -07001050 sp<BufferDiscardedListener> pl(new BufferDiscardedListener);
1051 ASSERT_EQ(OK, mProducer->connect(pl,
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001052 NATIVE_WINDOW_API_CPU, false, &output));
1053
1054 int slot = BufferQueue::INVALID_BUFFER_SLOT;
1055 sp<Fence> fence = Fence::NO_FENCE;
1056 sp<GraphicBuffer> buffer = nullptr;
1057 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1058 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1059 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1060 BufferItem item{};
1061
1062 // Preallocate, dequeue, request, and cancel 4 buffers so we don't get
1063 // BUFFER_NEEDS_REALLOCATION below
1064 int slots[4] = {};
1065 mProducer->setMaxDequeuedBufferCount(4);
1066 for (size_t i = 0; i < 4; ++i) {
Nolan Scobie9c427942023-05-01 16:41:28 -04001067 status_t result = mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0,
1068 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr);
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001069 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1070 ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
1071 }
1072 for (size_t i = 0; i < 4; ++i) {
1073 ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE));
1074 }
1075
1076 // Get buffers in all states: dequeued, filled, acquired, free
1077
1078 // Fill 3 buffers
Nolan Scobie9c427942023-05-01 16:41:28 -04001079 ASSERT_EQ(OK,
1080 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1081 nullptr));
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001082 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
Nolan Scobie9c427942023-05-01 16:41:28 -04001083 ASSERT_EQ(OK,
1084 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1085 nullptr));
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001086 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
Nolan Scobie9c427942023-05-01 16:41:28 -04001087 ASSERT_EQ(OK,
1088 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1089 nullptr));
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001090 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1091 // Dequeue 1 buffer
Nolan Scobie9c427942023-05-01 16:41:28 -04001092 ASSERT_EQ(OK,
1093 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1094 nullptr));
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001095
1096 // Acquire and free 1 buffer
1097 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1098 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
1099 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
Shuzhen Wang067fcd32019-08-14 10:41:12 -07001100 int releasedSlot = item.mSlot;
1101
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001102 // Acquire 1 buffer, leaving 1 filled buffer in queue
1103 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1104
1105 // Now discard the free buffers
1106 ASSERT_EQ(OK, mConsumer->discardFreeBuffers());
1107
Shuzhen Wang067fcd32019-08-14 10:41:12 -07001108 // Check onBuffersDiscarded is called with correct slots
1109 auto buffersDiscarded = pl->getDiscardedSlots();
1110 ASSERT_EQ(buffersDiscarded.size(), 1);
1111 ASSERT_EQ(buffersDiscarded[0], releasedSlot);
1112
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001113 // Check no free buffers in dump
1114 String8 dumpString;
Dan Stoza0c9a1ed2017-04-06 15:10:21 -07001115 mConsumer->dumpState(String8{}, &dumpString);
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001116
1117 // Parse the dump to ensure that all buffer slots that are FREE also
1118 // have a null GraphicBuffer
1119 // Fragile - assumes the following format for the dump for a buffer entry:
1120 // ":%p\][^:]*state=FREE" where %p is the buffer pointer in hex.
1121 ssize_t idx = dumpString.find("state=FREE");
1122 while (idx != -1) {
1123 ssize_t bufferPtrIdx = idx - 1;
1124 while (bufferPtrIdx > 0) {
1125 if (dumpString[bufferPtrIdx] == ':') {
1126 bufferPtrIdx++;
1127 break;
1128 }
1129 bufferPtrIdx--;
1130 }
1131 ASSERT_GT(bufferPtrIdx, 0) << "Can't parse queue dump to validate";
1132 ssize_t nullPtrIdx = dumpString.find("0x0]", bufferPtrIdx);
1133 ASSERT_EQ(bufferPtrIdx, nullPtrIdx) << "Free buffer not discarded";
1134 idx = dumpString.find("FREE", idx + 1);
1135 }
1136}
1137
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001138TEST_F(BufferQueueTest, TestBufferReplacedInQueueBuffer) {
1139 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -07001140 sp<MockConsumer> mc(new MockConsumer);
1141 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001142 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -07001143 ASSERT_EQ(OK,
1144 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001145 ASSERT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
1146
1147 int slot = BufferQueue::INVALID_BUFFER_SLOT;
1148 sp<Fence> fence = Fence::NO_FENCE;
1149 sp<GraphicBuffer> buffer = nullptr;
1150 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1151 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1152 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1153 BufferItem item{};
1154
1155 // Preallocate, dequeue, request, and cancel 2 buffers so we don't get
1156 // BUFFER_NEEDS_REALLOCATION below
1157 int slots[2] = {};
1158 ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(2));
1159 for (size_t i = 0; i < 2; ++i) {
Nolan Scobie9c427942023-05-01 16:41:28 -04001160 status_t result = mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0,
1161 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr);
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001162 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1163 ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
1164 }
1165 for (size_t i = 0; i < 2; ++i) {
1166 ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE));
1167 }
1168
1169 // Fill 2 buffers without consumer consuming them. Verify that all
1170 // queued buffer returns proper bufferReplaced flag
Nolan Scobie9c427942023-05-01 16:41:28 -04001171 ASSERT_EQ(OK,
1172 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1173 nullptr));
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001174 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1175 ASSERT_EQ(false, output.bufferReplaced);
Nolan Scobie9c427942023-05-01 16:41:28 -04001176 ASSERT_EQ(OK,
1177 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1178 nullptr));
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001179 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1180 ASSERT_EQ(true, output.bufferReplaced);
1181}
1182
Dan Stozad4c6f992017-03-21 13:43:22 -07001183TEST_F(BufferQueueTest, TestStaleBufferHandleSentAfterDisconnect) {
1184 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -07001185 sp<MockConsumer> mc(new MockConsumer);
1186 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Dan Stozad4c6f992017-03-21 13:43:22 -07001187 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -07001188 sp<IProducerListener> fakeListener(new StubProducerListener);
1189 ASSERT_EQ(OK, mProducer->connect(fakeListener, NATIVE_WINDOW_API_CPU, true, &output));
Dan Stozad4c6f992017-03-21 13:43:22 -07001190
1191 int slot = BufferQueue::INVALID_BUFFER_SLOT;
1192 sp<Fence> fence = Fence::NO_FENCE;
1193 sp<GraphicBuffer> buffer = nullptr;
1194 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1195 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1196 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1197
1198 // Dequeue, request, and queue one buffer
Nolan Scobie9c427942023-05-01 16:41:28 -04001199 status_t result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
1200 nullptr, nullptr);
Dan Stozad4c6f992017-03-21 13:43:22 -07001201 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1202 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
1203 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1204
1205 // Acquire and release the buffer. Upon acquiring, the buffer handle should
1206 // be non-null since this is the first time we've acquired this slot.
1207 BufferItem item;
1208 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1209 ASSERT_EQ(slot, item.mSlot);
1210 ASSERT_NE(nullptr, item.mGraphicBuffer.get());
1211 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
1212 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
1213
1214 // Dequeue and queue the buffer again
Nolan Scobie9c427942023-05-01 16:41:28 -04001215 ASSERT_EQ(OK,
1216 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1217 nullptr));
Dan Stozad4c6f992017-03-21 13:43:22 -07001218 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1219
1220 // Acquire and release the buffer again. Upon acquiring, the buffer handle
1221 // should be null since this is not the first time we've acquired this slot.
1222 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1223 ASSERT_EQ(slot, item.mSlot);
1224 ASSERT_EQ(nullptr, item.mGraphicBuffer.get());
1225 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
1226 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
1227
1228 // Dequeue and queue the buffer again
Nolan Scobie9c427942023-05-01 16:41:28 -04001229 ASSERT_EQ(OK,
1230 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1231 nullptr));
Dan Stozad4c6f992017-03-21 13:43:22 -07001232 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1233
1234 // Disconnect the producer end. This should clear all of the slots and mark
1235 // the buffer in the queue as stale.
1236 ASSERT_EQ(OK, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
1237
1238 // Acquire the buffer again. Upon acquiring, the buffer handle should not be
1239 // null since the queued buffer should have been marked as stale, which
1240 // should trigger the BufferQueue to resend the buffer handle.
1241 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1242 ASSERT_EQ(slot, item.mSlot);
1243 ASSERT_NE(nullptr, item.mGraphicBuffer.get());
1244}
1245
Wonsik Kim3e198b22017-04-07 15:43:16 -07001246TEST_F(BufferQueueTest, TestProducerConnectDisconnect) {
1247 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -07001248 sp<MockConsumer> mc(new MockConsumer);
1249 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Wonsik Kim3e198b22017-04-07 15:43:16 -07001250 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -07001251 sp<IProducerListener> fakeListener(new StubProducerListener);
Wonsik Kim3e198b22017-04-07 15:43:16 -07001252 ASSERT_EQ(NO_INIT, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
Peiyong Lind8460c82020-07-28 16:04:22 -07001253 ASSERT_EQ(OK, mProducer->connect(fakeListener, NATIVE_WINDOW_API_CPU, true, &output));
1254 ASSERT_EQ(BAD_VALUE, mProducer->connect(fakeListener, NATIVE_WINDOW_API_MEDIA, true, &output));
Wonsik Kim3e198b22017-04-07 15:43:16 -07001255
1256 ASSERT_EQ(BAD_VALUE, mProducer->disconnect(NATIVE_WINDOW_API_MEDIA));
1257 ASSERT_EQ(OK, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
1258 ASSERT_EQ(NO_INIT, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
1259}
1260
Jamie Gennis9e75ddd2012-08-31 15:32:45 -07001261} // namespace android