blob: be6c7d6a5b9862a44c7899a2e866f3137902a519 [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>
John Reck12daff92023-07-28 16:36:27 -040024#include <gui/BufferItemConsumer.h>
Dan Stozaf0eaf252014-03-21 13:05:51 -070025#include <gui/BufferQueue.h>
26#include <gui/IProducerListener.h>
John Reck12daff92023-07-28 16:36:27 -040027#include <gui/Surface.h>
Jamie Gennis9e75ddd2012-08-31 15:32:45 -070028
29#include <ui/GraphicBuffer.h>
Jamie Gennis9e75ddd2012-08-31 15:32:45 -070030
Dan Stoza1a0b8612014-03-20 15:36:31 -070031#include <binder/IPCThreadState.h>
Dan Stoza9f3053d2014-03-06 15:14:33 -080032#include <binder/IServiceManager.h>
Dan Stoza1a0b8612014-03-20 15:36:31 -070033#include <binder/ProcessState.h>
Dan Stozaf0eaf252014-03-21 13:05:51 -070034
35#include <utils/String8.h>
36#include <utils/threads.h>
37
Mathias Agopian6a3c05b2017-04-27 20:06:55 -070038#include <system/window.h>
39
Ady Abraham6cdd3fd2023-09-07 18:45:58 -070040#include <gmock/gmock.h>
Dan Stozaf0eaf252014-03-21 13:05:51 -070041#include <gtest/gtest.h>
Jamie Gennis9e75ddd2012-08-31 15:32:45 -070042
John Reck12daff92023-07-28 16:36:27 -040043#include <future>
Dan Stozae77c7662016-05-13 11:37:28 -070044#include <thread>
45
Ady Abraham6cdd3fd2023-09-07 18:45:58 -070046#include <com_android_graphics_libgui_flags.h>
47
Dan Stozae77c7662016-05-13 11:37:28 -070048using namespace std::chrono_literals;
49
Jamie Gennis9e75ddd2012-08-31 15:32:45 -070050namespace android {
Ady Abraham6cdd3fd2023-09-07 18:45:58 -070051using namespace com::android::graphics::libgui;
Jamie Gennis9e75ddd2012-08-31 15:32:45 -070052
53class BufferQueueTest : public ::testing::Test {
Dan Stoza9f3053d2014-03-06 15:14:33 -080054
55public:
Jamie Gennis9e75ddd2012-08-31 15:32:45 -070056protected:
Igor Murashkin7ea777f2013-11-18 16:58:36 -080057 void GetMinUndequeuedBufferCount(int* bufferCount) {
Yi Konga03e0442018-07-17 11:16:57 -070058 ASSERT_TRUE(bufferCount != nullptr);
Dan Stoza9f3053d2014-03-06 15:14:33 -080059 ASSERT_EQ(OK, mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
60 bufferCount));
61 ASSERT_GE(*bufferCount, 0);
Igor Murashkin7ea777f2013-11-18 16:58:36 -080062 }
63
Dan Stoza1a0b8612014-03-20 15:36:31 -070064 void createBufferQueue() {
65 BufferQueue::createBufferQueue(&mProducer, &mConsumer);
66 }
Jamie Gennis9e75ddd2012-08-31 15:32:45 -070067
Pablo Ceballosff95aab2016-01-13 17:09:58 -080068 void testBufferItem(const IGraphicBufferProducer::QueueBufferInput& input,
69 const BufferItem& item) {
70 int64_t timestamp;
71 bool isAutoTimestamp;
72 android_dataspace dataSpace;
73 Rect crop;
74 int scalingMode;
75 uint32_t transform;
76 sp<Fence> fence;
77
78 input.deflate(&timestamp, &isAutoTimestamp, &dataSpace, &crop,
Yi Konga03e0442018-07-17 11:16:57 -070079 &scalingMode, &transform, &fence, nullptr);
Pablo Ceballosff95aab2016-01-13 17:09:58 -080080 ASSERT_EQ(timestamp, item.mTimestamp);
81 ASSERT_EQ(isAutoTimestamp, item.mIsAutoTimestamp);
82 ASSERT_EQ(dataSpace, item.mDataSpace);
83 ASSERT_EQ(crop, item.mCrop);
84 ASSERT_EQ(static_cast<uint32_t>(scalingMode), item.mScalingMode);
85 ASSERT_EQ(transform, item.mTransform);
86 ASSERT_EQ(fence, item.mFence);
87 }
88
Dan Stoza1a0b8612014-03-20 15:36:31 -070089 sp<IGraphicBufferProducer> mProducer;
90 sp<IGraphicBufferConsumer> mConsumer;
91};
Dan Stoza9f3053d2014-03-06 15:14:33 -080092
Dan Stozaf8cebe52015-04-20 12:09:38 -070093static const uint32_t TEST_DATA = 0x12345678u;
94
Dan Stoza1a0b8612014-03-20 15:36:31 -070095// XXX: Tests that fork a process to hold the BufferQueue must run before tests
96// that use a local BufferQueue, or else Binder will get unhappy
Kalle Raita88752d72017-03-27 14:11:54 -070097//
98// In one instance this was a crash in the createBufferQueue where the
99// binder call to create a buffer allocator apparently got garbage back.
100// See b/36592665.
101TEST_F(BufferQueueTest, DISABLED_BufferQueueInAnotherProcess) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700102 const String16 PRODUCER_NAME = String16("BQTestProducer");
103 const String16 CONSUMER_NAME = String16("BQTestConsumer");
104
105 pid_t forkPid = fork();
106 ASSERT_NE(forkPid, -1);
107
108 if (forkPid == 0) {
109 // Child process
Dan Stozab3d0bdf2014-04-07 16:33:59 -0700110 sp<IGraphicBufferProducer> producer;
111 sp<IGraphicBufferConsumer> consumer;
Dan Stoza1a0b8612014-03-20 15:36:31 -0700112 BufferQueue::createBufferQueue(&producer, &consumer);
113 sp<IServiceManager> serviceManager = defaultServiceManager();
Marco Nelissen097ca272014-11-14 08:01:01 -0800114 serviceManager->addService(PRODUCER_NAME, IInterface::asBinder(producer));
115 serviceManager->addService(CONSUMER_NAME, IInterface::asBinder(consumer));
Dan Stoza1a0b8612014-03-20 15:36:31 -0700116 ProcessState::self()->startThreadPool();
117 IPCThreadState::self()->joinThreadPool();
118 LOG_ALWAYS_FATAL("Shouldn't be here");
119 }
120
121 sp<IServiceManager> serviceManager = defaultServiceManager();
122 sp<IBinder> binderProducer =
123 serviceManager->getService(PRODUCER_NAME);
124 mProducer = interface_cast<IGraphicBufferProducer>(binderProducer);
Yi Konga03e0442018-07-17 11:16:57 -0700125 EXPECT_TRUE(mProducer != nullptr);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700126 sp<IBinder> binderConsumer =
127 serviceManager->getService(CONSUMER_NAME);
128 mConsumer = interface_cast<IGraphicBufferConsumer>(binderConsumer);
Yi Konga03e0442018-07-17 11:16:57 -0700129 EXPECT_TRUE(mConsumer != nullptr);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700130
Peiyong Lind8460c82020-07-28 16:04:22 -0700131 sp<MockConsumer> mc(new MockConsumer);
132 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Dan Stoza1a0b8612014-03-20 15:36:31 -0700133 IGraphicBufferProducer::QueueBufferOutput output;
134 ASSERT_EQ(OK,
Yi Konga03e0442018-07-17 11:16:57 -0700135 mProducer->connect(nullptr, NATIVE_WINDOW_API_CPU, false, &output));
Dan Stoza1a0b8612014-03-20 15:36:31 -0700136
137 int slot;
138 sp<Fence> fence;
139 sp<GraphicBuffer> buffer;
140 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600141 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
142 nullptr, nullptr));
Dan Stoza1a0b8612014-03-20 15:36:31 -0700143 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
144
145 uint32_t* dataIn;
146 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
147 reinterpret_cast<void**>(&dataIn)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700148 *dataIn = TEST_DATA;
Dan Stoza1a0b8612014-03-20 15:36:31 -0700149 ASSERT_EQ(OK, buffer->unlock());
150
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800151 IGraphicBufferProducer::QueueBufferInput input(0, false,
152 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700153 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700154 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
155
Dan Stozacf3834d2015-03-11 14:04:22 -0700156 BufferItem item;
Dan Stoza1a0b8612014-03-20 15:36:31 -0700157 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
158
159 uint32_t* dataOut;
160 ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
161 reinterpret_cast<void**>(&dataOut)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700162 ASSERT_EQ(*dataOut, TEST_DATA);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700163 ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
164}
165
silence_dogoode9d092a2019-06-19 16:14:53 -0700166TEST_F(BufferQueueTest, GetMaxBufferCountInQueueBufferOutput_Succeeds) {
167 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700168 sp<MockConsumer> mc(new MockConsumer);
169 mConsumer->consumerConnect(mc, false);
silence_dogoode9d092a2019-06-19 16:14:53 -0700170 int bufferCount = 50;
171 mConsumer->setMaxBufferCount(bufferCount);
172
173 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700174 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output);
silence_dogoode9d092a2019-06-19 16:14:53 -0700175 ASSERT_EQ(output.maxBufferCount, bufferCount);
176}
177
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700178TEST_F(BufferQueueTest, AcquireBuffer_ExceedsMaxAcquireCount_Fails) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700179 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700180 sp<MockConsumer> mc(new MockConsumer);
181 mConsumer->consumerConnect(mc, false);
Andy McFadden2adaf042012-12-18 09:49:45 -0800182 IGraphicBufferProducer::QueueBufferOutput qbo;
Peiyong Lind8460c82020-07-28 16:04:22 -0700183 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &qbo);
Pablo Ceballosfa455352015-08-12 17:47:47 -0700184 mProducer->setMaxDequeuedBufferCount(3);
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700185
186 int slot;
187 sp<Fence> fence;
188 sp<GraphicBuffer> buf;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800189 IGraphicBufferProducer::QueueBufferInput qbi(0, false,
190 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700191 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Dan Stozacf3834d2015-03-11 14:04:22 -0700192 BufferItem item;
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700193
194 for (int i = 0; i < 2; i++) {
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));
200 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700201 }
202
Andy McFadden2adaf042012-12-18 09:49:45 -0800203 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600204 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
205 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800206 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
207 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700208
209 // Acquire the third buffer, which should fail.
Dan Stoza9f3053d2014-03-06 15:14:33 -0800210 ASSERT_EQ(INVALID_OPERATION, mConsumer->acquireBuffer(&item, 0));
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700211}
212
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700213TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithIllegalValues_ReturnsError) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700214 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700215 sp<MockConsumer> mc(new MockConsumer);
216 mConsumer->consumerConnect(mc, false);
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700217
Pablo Ceballos72daab62015-12-07 16:38:43 -0800218 EXPECT_EQ(OK, mConsumer->setMaxBufferCount(10));
219 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(10));
220
221 IGraphicBufferProducer::QueueBufferOutput qbo;
Peiyong Lind8460c82020-07-28 16:04:22 -0700222 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &qbo);
Pablo Ceballos72daab62015-12-07 16:38:43 -0800223 mProducer->setMaxDequeuedBufferCount(3);
224
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800225 int minBufferCount;
226 ASSERT_NO_FATAL_FAILURE(GetMinUndequeuedBufferCount(&minBufferCount));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800227 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(
228 minBufferCount - 1));
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800229
Dan Stoza9f3053d2014-03-06 15:14:33 -0800230 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(0));
231 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(-3));
232 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700233 BufferQueue::MAX_MAX_ACQUIRED_BUFFERS+1));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800234 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(100));
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700235
Pablo Ceballos72daab62015-12-07 16:38:43 -0800236 int slot;
237 sp<Fence> fence;
238 sp<GraphicBuffer> buf;
239 IGraphicBufferProducer::QueueBufferInput qbi(0, false,
240 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
241 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
242 BufferItem item;
243 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(3));
244 for (int i = 0; i < 3; i++) {
245 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600246 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
247 nullptr, nullptr));
Pablo Ceballos72daab62015-12-07 16:38:43 -0800248 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
249 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
250 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
251 }
252
253 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(2));
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700254}
255
256TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithLegalValues_Succeeds) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700257 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700258 sp<MockConsumer> mc(new MockConsumer);
259 mConsumer->consumerConnect(mc, false);
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700260
Pablo Ceballos72daab62015-12-07 16:38:43 -0800261 IGraphicBufferProducer::QueueBufferOutput qbo;
Peiyong Lind8460c82020-07-28 16:04:22 -0700262 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &qbo);
Pablo Ceballos72daab62015-12-07 16:38:43 -0800263 mProducer->setMaxDequeuedBufferCount(2);
264
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800265 int minBufferCount;
266 ASSERT_NO_FATAL_FAILURE(GetMinUndequeuedBufferCount(&minBufferCount));
267
Dan Stoza9f3053d2014-03-06 15:14:33 -0800268 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
269 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(2));
270 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(minBufferCount));
Pablo Ceballos72daab62015-12-07 16:38:43 -0800271
272 int slot;
273 sp<Fence> fence;
274 sp<GraphicBuffer> buf;
275 IGraphicBufferProducer::QueueBufferInput qbi(0, false,
276 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
277 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
278 BufferItem item;
279
280 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600281 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
282 nullptr, nullptr));
Pablo Ceballos72daab62015-12-07 16:38:43 -0800283 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
284 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
285 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
286
287 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(3));
288
289 for (int i = 0; i < 2; i++) {
290 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600291 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
292 nullptr, nullptr));
Pablo Ceballos72daab62015-12-07 16:38:43 -0800293 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
294 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
295 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
296 }
297
Dan Stoza9f3053d2014-03-06 15:14:33 -0800298 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700299 BufferQueue::MAX_MAX_ACQUIRED_BUFFERS));
300}
301
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700302TEST_F(BufferQueueTest, SetMaxBufferCountWithLegalValues_Succeeds) {
303 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700304 sp<MockConsumer> mc(new MockConsumer);
305 mConsumer->consumerConnect(mc, false);
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700306
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700307 // Test shared buffer mode
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700308 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
309}
310
311TEST_F(BufferQueueTest, SetMaxBufferCountWithIllegalValues_ReturnsError) {
312 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700313 sp<MockConsumer> mc(new MockConsumer);
314 mConsumer->consumerConnect(mc, false);
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700315
316 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(0));
317 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(
318 BufferQueue::NUM_BUFFER_SLOTS + 1));
319
320 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(5));
321 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(3));
322}
323
Dan Stoza9f3053d2014-03-06 15:14:33 -0800324TEST_F(BufferQueueTest, DetachAndReattachOnProducerSide) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700325 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700326 sp<MockConsumer> mc(new MockConsumer);
327 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800328 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700329 ASSERT_EQ(OK,
330 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800331
332 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(-1)); // Index too low
333 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(
334 BufferQueueDefs::NUM_BUFFER_SLOTS)); // Index too high
335 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(0)); // Not dequeued
336
337 int slot;
338 sp<Fence> fence;
339 sp<GraphicBuffer> buffer;
340 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600341 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
342 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800343 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(slot)); // Not requested
344 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
345 ASSERT_EQ(OK, mProducer->detachBuffer(slot));
346 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(slot)); // Not dequeued
347
348 sp<GraphicBuffer> safeToClobberBuffer;
349 // Can no longer request buffer from this slot
350 ASSERT_EQ(BAD_VALUE, mProducer->requestBuffer(slot, &safeToClobberBuffer));
351
352 uint32_t* dataIn;
353 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
354 reinterpret_cast<void**>(&dataIn)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700355 *dataIn = TEST_DATA;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800356 ASSERT_EQ(OK, buffer->unlock());
357
358 int newSlot;
Yi Konga03e0442018-07-17 11:16:57 -0700359 ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(nullptr, safeToClobberBuffer));
360 ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(&newSlot, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800361
362 ASSERT_EQ(OK, mProducer->attachBuffer(&newSlot, buffer));
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800363 IGraphicBufferProducer::QueueBufferInput input(0, false,
364 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700365 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800366 ASSERT_EQ(OK, mProducer->queueBuffer(newSlot, input, &output));
367
Dan Stozacf3834d2015-03-11 14:04:22 -0700368 BufferItem item;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800369 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
370
371 uint32_t* dataOut;
372 ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
373 reinterpret_cast<void**>(&dataOut)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700374 ASSERT_EQ(*dataOut, TEST_DATA);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700375 ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
Dan Stoza9f3053d2014-03-06 15:14:33 -0800376}
377
378TEST_F(BufferQueueTest, DetachAndReattachOnConsumerSide) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700379 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700380 sp<MockConsumer> mc(new MockConsumer);
381 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800382 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700383 ASSERT_EQ(OK,
384 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800385
386 int slot;
387 sp<Fence> fence;
388 sp<GraphicBuffer> buffer;
389 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600390 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
391 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800392 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800393 IGraphicBufferProducer::QueueBufferInput input(0, false,
394 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700395 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800396 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
397
398 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(-1)); // Index too low
399 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(
400 BufferQueueDefs::NUM_BUFFER_SLOTS)); // Index too high
401 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(0)); // Not acquired
402
Dan Stozacf3834d2015-03-11 14:04:22 -0700403 BufferItem item;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800404 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
405
Pablo Ceballos47650f42015-08-04 16:38:17 -0700406 ASSERT_EQ(OK, mConsumer->detachBuffer(item.mSlot));
407 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(item.mSlot)); // Not acquired
Dan Stoza9f3053d2014-03-06 15:14:33 -0800408
409 uint32_t* dataIn;
410 ASSERT_EQ(OK, item.mGraphicBuffer->lock(
411 GraphicBuffer::USAGE_SW_WRITE_OFTEN,
412 reinterpret_cast<void**>(&dataIn)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700413 *dataIn = TEST_DATA;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800414 ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
415
416 int newSlot;
417 sp<GraphicBuffer> safeToClobberBuffer;
Yi Konga03e0442018-07-17 11:16:57 -0700418 ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(nullptr, safeToClobberBuffer));
419 ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(&newSlot, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800420 ASSERT_EQ(OK, mConsumer->attachBuffer(&newSlot, item.mGraphicBuffer));
421
Dan Stoza99b18b42014-03-28 15:34:33 -0700422 ASSERT_EQ(OK, mConsumer->releaseBuffer(newSlot, 0, EGL_NO_DISPLAY,
Dan Stoza9f3053d2014-03-06 15:14:33 -0800423 EGL_NO_SYNC_KHR, Fence::NO_FENCE));
424
425 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600426 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
427 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800428 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
429
430 uint32_t* dataOut;
431 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
432 reinterpret_cast<void**>(&dataOut)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700433 ASSERT_EQ(*dataOut, TEST_DATA);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700434 ASSERT_EQ(OK, buffer->unlock());
Dan Stoza9f3053d2014-03-06 15:14:33 -0800435}
436
437TEST_F(BufferQueueTest, MoveFromConsumerToProducer) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700438 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700439 sp<MockConsumer> mc(new MockConsumer);
440 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800441 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700442 ASSERT_EQ(OK,
443 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800444
445 int slot;
446 sp<Fence> fence;
447 sp<GraphicBuffer> buffer;
448 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600449 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
450 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800451 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
452
453 uint32_t* dataIn;
454 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
455 reinterpret_cast<void**>(&dataIn)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700456 *dataIn = TEST_DATA;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800457 ASSERT_EQ(OK, buffer->unlock());
458
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800459 IGraphicBufferProducer::QueueBufferInput input(0, false,
460 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700461 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800462 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
463
Dan Stozacf3834d2015-03-11 14:04:22 -0700464 BufferItem item;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800465 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
Pablo Ceballos47650f42015-08-04 16:38:17 -0700466 ASSERT_EQ(OK, mConsumer->detachBuffer(item.mSlot));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800467
468 int newSlot;
469 ASSERT_EQ(OK, mProducer->attachBuffer(&newSlot, item.mGraphicBuffer));
470 ASSERT_EQ(OK, mProducer->queueBuffer(newSlot, input, &output));
471 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
472
473 uint32_t* dataOut;
474 ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
475 reinterpret_cast<void**>(&dataOut)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700476 ASSERT_EQ(*dataOut, TEST_DATA);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700477 ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
Dan Stoza9f3053d2014-03-06 15:14:33 -0800478}
479
Dan Stoza9de72932015-04-16 17:28:43 -0700480TEST_F(BufferQueueTest, TestDisallowingAllocation) {
481 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700482 sp<MockConsumer> mc(new MockConsumer);
483 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Dan Stoza9de72932015-04-16 17:28:43 -0700484 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700485 ASSERT_EQ(OK,
486 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Dan Stoza9de72932015-04-16 17:28:43 -0700487
488 static const uint32_t WIDTH = 320;
489 static const uint32_t HEIGHT = 240;
490
491 ASSERT_EQ(OK, mConsumer->setDefaultBufferSize(WIDTH, HEIGHT));
492
493 int slot;
494 sp<Fence> fence;
495 sp<GraphicBuffer> buffer;
496 // This should return an error since it would require an allocation
497 ASSERT_EQ(OK, mProducer->allowAllocation(false));
Ian Elliottd11b0442017-07-18 11:05:49 -0600498 ASSERT_EQ(WOULD_BLOCK,
499 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
500 nullptr, nullptr));
Dan Stoza9de72932015-04-16 17:28:43 -0700501
502 // This should succeed, now that we've lifted the prohibition
503 ASSERT_EQ(OK, mProducer->allowAllocation(true));
504 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600505 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
506 nullptr, nullptr));
Dan Stoza9de72932015-04-16 17:28:43 -0700507
508 // Release the previous buffer back to the BufferQueue
509 mProducer->cancelBuffer(slot, fence);
510
511 // This should fail since we're requesting a different size
512 ASSERT_EQ(OK, mProducer->allowAllocation(false));
Ian Elliottd11b0442017-07-18 11:05:49 -0600513 ASSERT_EQ(WOULD_BLOCK,
514 mProducer->dequeueBuffer(&slot, &fence, WIDTH * 2, HEIGHT * 2, 0,
515 GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr, nullptr));
Dan Stoza9de72932015-04-16 17:28:43 -0700516}
517
Dan Stoza812ed062015-06-02 15:45:22 -0700518TEST_F(BufferQueueTest, TestGenerationNumbers) {
519 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700520 sp<MockConsumer> mc(new MockConsumer);
521 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Dan Stoza812ed062015-06-02 15:45:22 -0700522 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700523 ASSERT_EQ(OK,
524 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Dan Stoza812ed062015-06-02 15:45:22 -0700525
526 ASSERT_EQ(OK, mProducer->setGenerationNumber(1));
527
528 // Get one buffer to play with
529 int slot;
530 sp<Fence> fence;
531 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Nolan Scobie9c427942023-05-01 16:41:28 -0400532 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
533 nullptr));
Dan Stoza812ed062015-06-02 15:45:22 -0700534
535 sp<GraphicBuffer> buffer;
536 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
537
538 // Ensure that the generation number we set propagates to allocated buffers
539 ASSERT_EQ(1U, buffer->getGenerationNumber());
540
541 ASSERT_EQ(OK, mProducer->detachBuffer(slot));
542
543 ASSERT_EQ(OK, mProducer->setGenerationNumber(2));
544
545 // These should fail, since we've changed the generation number on the queue
546 int outSlot;
547 ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(&outSlot, buffer));
548 ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(&outSlot, buffer));
549
550 buffer->setGenerationNumber(2);
551
552 // This should succeed now that we've changed the buffer's generation number
553 ASSERT_EQ(OK, mProducer->attachBuffer(&outSlot, buffer));
554
555 ASSERT_EQ(OK, mProducer->detachBuffer(outSlot));
556
557 // This should also succeed with the new generation number
558 ASSERT_EQ(OK, mConsumer->attachBuffer(&outSlot, buffer));
559}
560
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700561TEST_F(BufferQueueTest, TestSharedBufferModeWithoutAutoRefresh) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700562 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700563 sp<MockConsumer> mc(new MockConsumer);
564 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700565 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700566 ASSERT_EQ(OK,
567 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700568
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700569 ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700570
571 // Get a buffer
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700572 int sharedSlot;
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700573 sp<Fence> fence;
574 sp<GraphicBuffer> buffer;
575 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Nolan Scobie9c427942023-05-01 16:41:28 -0400576 mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
577 nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700578 ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700579
580 // Queue the buffer
581 IGraphicBufferProducer::QueueBufferInput input(0, false,
582 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
583 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700584 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700585
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800586 // Repeatedly queue and dequeue a buffer from the producer side, it should
587 // always return the same one. And we won't run out of buffers because it's
588 // always the same one and because async mode gets enabled.
589 int slot;
590 for (int i = 0; i < 5; i++) {
Nolan Scobie9c427942023-05-01 16:41:28 -0400591 ASSERT_EQ(OK,
592 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
593 nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700594 ASSERT_EQ(sharedSlot, slot);
595 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800596 }
597
598 // acquire the buffer
599 BufferItem item;
600 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700601 ASSERT_EQ(sharedSlot, item.mSlot);
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800602 testBufferItem(input, item);
603 ASSERT_EQ(true, item.mQueuedBuffer);
604 ASSERT_EQ(false, item.mAutoRefresh);
605
606 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
607 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
608
609 // attempt to acquire a second time should return no buffer available
610 ASSERT_EQ(IGraphicBufferConsumer::NO_BUFFER_AVAILABLE,
611 mConsumer->acquireBuffer(&item, 0));
612}
613
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700614TEST_F(BufferQueueTest, TestSharedBufferModeWithAutoRefresh) {
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800615 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700616 sp<MockConsumer> mc(new MockConsumer);
617 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800618 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700619 ASSERT_EQ(OK,
620 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800621
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700622 ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800623 ASSERT_EQ(OK, mProducer->setAutoRefresh(true));
624
625 // Get a buffer
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700626 int sharedSlot;
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800627 sp<Fence> fence;
628 sp<GraphicBuffer> buffer;
629 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Nolan Scobie9c427942023-05-01 16:41:28 -0400630 mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
631 nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700632 ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800633
634 // Queue the buffer
635 IGraphicBufferProducer::QueueBufferInput input(0, false,
636 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
637 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700638 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800639
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700640 // Repeatedly acquire and release a buffer from the consumer side, it should
641 // always return the same one.
642 BufferItem item;
643 for (int i = 0; i < 5; i++) {
644 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700645 ASSERT_EQ(sharedSlot, item.mSlot);
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800646 testBufferItem(input, item);
647 ASSERT_EQ(i == 0, item.mQueuedBuffer);
648 ASSERT_EQ(true, item.mAutoRefresh);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700649
650 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
651 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
652 }
653
654 // Repeatedly queue and dequeue a buffer from the producer side, it should
655 // always return the same one.
656 int slot;
657 for (int i = 0; i < 5; i++) {
Nolan Scobie9c427942023-05-01 16:41:28 -0400658 ASSERT_EQ(OK,
659 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
660 nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700661 ASSERT_EQ(sharedSlot, slot);
662 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700663 }
664
665 // Repeatedly acquire and release a buffer from the consumer side, it should
666 // always return the same one. First grabbing them from the queue and then
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700667 // when the queue is empty, returning the shared buffer.
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700668 for (int i = 0; i < 10; i++) {
669 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700670 ASSERT_EQ(sharedSlot, item.mSlot);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700671 ASSERT_EQ(0, item.mTimestamp);
672 ASSERT_EQ(false, item.mIsAutoTimestamp);
673 ASSERT_EQ(HAL_DATASPACE_UNKNOWN, item.mDataSpace);
674 ASSERT_EQ(Rect(0, 0, 1, 1), item.mCrop);
675 ASSERT_EQ(NATIVE_WINDOW_SCALING_MODE_FREEZE, item.mScalingMode);
Dan Stoza5ecfb682016-01-04 17:01:02 -0800676 ASSERT_EQ(0u, item.mTransform);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700677 ASSERT_EQ(Fence::NO_FENCE, item.mFence);
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800678 ASSERT_EQ(i == 0, item.mQueuedBuffer);
679 ASSERT_EQ(true, item.mAutoRefresh);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700680
681 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
682 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
683 }
684}
685
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700686TEST_F(BufferQueueTest, TestSharedBufferModeUsingAlreadyDequeuedBuffer) {
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700687 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700688 sp<MockConsumer> mc(new MockConsumer);
689 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700690 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700691 ASSERT_EQ(OK,
692 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700693
694 // Dequeue a buffer
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700695 int sharedSlot;
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700696 sp<Fence> fence;
697 sp<GraphicBuffer> buffer;
698 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Nolan Scobie9c427942023-05-01 16:41:28 -0400699 mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
700 nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700701 ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700702
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700703 // Enable shared buffer mode
704 ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700705
706 // Queue the buffer
707 IGraphicBufferProducer::QueueBufferInput input(0, false,
708 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
709 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700710 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700711
712 // Repeatedly queue and dequeue a buffer from the producer side, it should
713 // always return the same one. And we won't run out of buffers because it's
714 // always the same one and because async mode gets enabled.
715 int slot;
716 for (int i = 0; i < 5; i++) {
Nolan Scobie9c427942023-05-01 16:41:28 -0400717 ASSERT_EQ(OK,
718 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
719 nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700720 ASSERT_EQ(sharedSlot, slot);
721 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700722 }
723
724 // acquire the buffer
725 BufferItem item;
726 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700727 ASSERT_EQ(sharedSlot, item.mSlot);
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700728 testBufferItem(input, item);
729 ASSERT_EQ(true, item.mQueuedBuffer);
730 ASSERT_EQ(false, item.mAutoRefresh);
731
732 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
733 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
734
735 // attempt to acquire a second time should return no buffer available
736 ASSERT_EQ(IGraphicBufferConsumer::NO_BUFFER_AVAILABLE,
737 mConsumer->acquireBuffer(&item, 0));
738}
739
Dan Stoza127fc632015-06-30 13:43:32 -0700740TEST_F(BufferQueueTest, TestTimeouts) {
741 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700742 sp<MockConsumer> mc(new MockConsumer);
743 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Dan Stoza127fc632015-06-30 13:43:32 -0700744 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700745 ASSERT_EQ(OK,
746 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Dan Stoza127fc632015-06-30 13:43:32 -0700747
748 // Fill up the queue. Since the controlledByApp flags are set to true, this
749 // queue should be in non-blocking mode, and we should be recycling the same
750 // two buffers
751 for (int i = 0; i < 5; ++i) {
752 int slot = BufferQueue::INVALID_BUFFER_SLOT;
753 sp<Fence> fence = Fence::NO_FENCE;
Nolan Scobie9c427942023-05-01 16:41:28 -0400754 auto result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
755 nullptr, nullptr);
Dan Stoza127fc632015-06-30 13:43:32 -0700756 if (i < 2) {
757 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
758 result);
759 } else {
760 ASSERT_EQ(OK, result);
761 }
762 sp<GraphicBuffer> buffer;
763 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
764 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
765 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
766 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
767 IGraphicBufferProducer::QueueBufferOutput output{};
768 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
769 }
770
771 const auto TIMEOUT = ms2ns(250);
772 mProducer->setDequeueTimeout(TIMEOUT);
773
774 // Setting a timeout will change the BufferQueue into blocking mode (with
775 // one droppable buffer in the queue and one free from the previous
776 // dequeue/queues), so dequeue and queue two more buffers: one to replace
777 // the current droppable buffer, and a second to max out the buffer count
778 sp<GraphicBuffer> buffer; // Save a buffer to attach later
779 for (int i = 0; i < 2; ++i) {
780 int slot = BufferQueue::INVALID_BUFFER_SLOT;
781 sp<Fence> fence = Fence::NO_FENCE;
Nolan Scobie9c427942023-05-01 16:41:28 -0400782 ASSERT_EQ(OK,
783 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
784 nullptr, nullptr));
Dan Stoza127fc632015-06-30 13:43:32 -0700785 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
786 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
787 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
788 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
789 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
790 }
791
792 int slot = BufferQueue::INVALID_BUFFER_SLOT;
793 sp<Fence> fence = Fence::NO_FENCE;
794 auto startTime = systemTime();
Nolan Scobie9c427942023-05-01 16:41:28 -0400795 ASSERT_EQ(TIMED_OUT,
796 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
797 nullptr));
Dan Stoza127fc632015-06-30 13:43:32 -0700798 ASSERT_GE(systemTime() - startTime, TIMEOUT);
799
800 // We're technically attaching the same buffer multiple times (since we
801 // queued it previously), but that doesn't matter for this test
802 startTime = systemTime();
803 ASSERT_EQ(TIMED_OUT, mProducer->attachBuffer(&slot, buffer));
804 ASSERT_GE(systemTime() - startTime, TIMEOUT);
805}
806
Dan Stoza5ecfb682016-01-04 17:01:02 -0800807TEST_F(BufferQueueTest, CanAttachWhileDisallowingAllocation) {
808 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700809 sp<MockConsumer> mc(new MockConsumer);
810 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Dan Stoza5ecfb682016-01-04 17:01:02 -0800811 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700812 ASSERT_EQ(OK,
813 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Dan Stoza5ecfb682016-01-04 17:01:02 -0800814
815 int slot = BufferQueue::INVALID_BUFFER_SLOT;
816 sp<Fence> sourceFence;
817 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Nolan Scobie9c427942023-05-01 16:41:28 -0400818 mProducer->dequeueBuffer(&slot, &sourceFence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
819 nullptr, nullptr));
Dan Stoza5ecfb682016-01-04 17:01:02 -0800820 sp<GraphicBuffer> buffer;
821 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
822 ASSERT_EQ(OK, mProducer->detachBuffer(slot));
823
824 ASSERT_EQ(OK, mProducer->allowAllocation(false));
825
826 slot = BufferQueue::INVALID_BUFFER_SLOT;
827 ASSERT_EQ(OK, mProducer->attachBuffer(&slot, buffer));
828}
829
Dan Stoza50101d02016-04-07 16:53:23 -0700830TEST_F(BufferQueueTest, CanRetrieveLastQueuedBuffer) {
831 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700832 sp<MockConsumer> mc(new MockConsumer);
833 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Dan Stoza50101d02016-04-07 16:53:23 -0700834 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700835 ASSERT_EQ(OK,
836 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
Dan Stoza50101d02016-04-07 16:53:23 -0700837
838 // Dequeue and queue the first buffer, storing the handle
839 int slot = BufferQueue::INVALID_BUFFER_SLOT;
840 sp<Fence> fence;
841 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Nolan Scobie9c427942023-05-01 16:41:28 -0400842 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
843 nullptr));
Dan Stoza50101d02016-04-07 16:53:23 -0700844 sp<GraphicBuffer> firstBuffer;
845 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &firstBuffer));
846
847 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
848 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
849 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
850 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
851
852 // Dequeue a second buffer
853 slot = BufferQueue::INVALID_BUFFER_SLOT;
854 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Nolan Scobie9c427942023-05-01 16:41:28 -0400855 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
856 nullptr));
Dan Stoza50101d02016-04-07 16:53:23 -0700857 sp<GraphicBuffer> secondBuffer;
858 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &secondBuffer));
859
860 // Ensure it's a new buffer
861 ASSERT_NE(firstBuffer->getNativeBuffer()->handle,
862 secondBuffer->getNativeBuffer()->handle);
863
864 // Queue the second buffer
865 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
866
867 // Acquire and release both buffers
868 for (size_t i = 0; i < 2; ++i) {
869 BufferItem item;
870 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
871 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
872 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
873 }
874
875 // Make sure we got the second buffer back
876 sp<GraphicBuffer> returnedBuffer;
877 sp<Fence> returnedFence;
John Reck1a61da52016-04-28 13:18:15 -0700878 float transform[16];
Dan Stoza50101d02016-04-07 16:53:23 -0700879 ASSERT_EQ(OK,
John Reck1a61da52016-04-28 13:18:15 -0700880 mProducer->getLastQueuedBuffer(&returnedBuffer, &returnedFence,
881 transform));
Dan Stoza50101d02016-04-07 16:53:23 -0700882 ASSERT_EQ(secondBuffer->getNativeBuffer()->handle,
883 returnedBuffer->getNativeBuffer()->handle);
884}
885
Dan Stozae77c7662016-05-13 11:37:28 -0700886TEST_F(BufferQueueTest, TestOccupancyHistory) {
887 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700888 sp<MockConsumer> mc(new MockConsumer);
889 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Dan Stozae77c7662016-05-13 11:37:28 -0700890 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700891 ASSERT_EQ(OK,
892 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
Dan Stozae77c7662016-05-13 11:37:28 -0700893
894 int slot = BufferQueue::INVALID_BUFFER_SLOT;
895 sp<Fence> fence = Fence::NO_FENCE;
896 sp<GraphicBuffer> buffer = nullptr;
897 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
898 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
899 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
900 BufferItem item{};
901
902 // Preallocate, dequeue, request, and cancel 3 buffers so we don't get
903 // BUFFER_NEEDS_REALLOCATION below
904 int slots[3] = {};
905 mProducer->setMaxDequeuedBufferCount(3);
906 for (size_t i = 0; i < 3; ++i) {
Nolan Scobie9c427942023-05-01 16:41:28 -0400907 status_t result = mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0,
908 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr);
Dan Stozae77c7662016-05-13 11:37:28 -0700909 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
910 ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
911 }
912 for (size_t i = 0; i < 3; ++i) {
913 ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE));
914 }
915
916 // Create 3 segments
917
918 // The first segment is a two-buffer segment, so we only put one buffer into
919 // the queue at a time
920 for (size_t i = 0; i < 5; ++i) {
Nolan Scobie9c427942023-05-01 16:41:28 -0400921 ASSERT_EQ(OK,
922 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
923 nullptr, nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700924 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
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 std::this_thread::sleep_for(16ms);
929 }
930
931 // Sleep between segments
932 std::this_thread::sleep_for(500ms);
933
934 // The second segment is a double-buffer segment. It starts the same as the
935 // two-buffer segment, but then at the end, we put two buffers in the queue
936 // at the same time before draining it.
937 for (size_t i = 0; i < 5; ++i) {
Nolan Scobie9c427942023-05-01 16:41:28 -0400938 ASSERT_EQ(OK,
939 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
940 nullptr, nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700941 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
942 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
943 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
944 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
945 std::this_thread::sleep_for(16ms);
946 }
Nolan Scobie9c427942023-05-01 16:41:28 -0400947 ASSERT_EQ(OK,
948 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
949 nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700950 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
Nolan Scobie9c427942023-05-01 16:41:28 -0400951 ASSERT_EQ(OK,
952 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
953 nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700954 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
955 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
956 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
957 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
958 std::this_thread::sleep_for(16ms);
959 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
960 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
961 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
962
963 // Sleep between segments
964 std::this_thread::sleep_for(500ms);
965
966 // The third segment is a triple-buffer segment, so the queue is switching
967 // between one buffer and two buffers deep.
Nolan Scobie9c427942023-05-01 16:41:28 -0400968 ASSERT_EQ(OK,
969 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
970 nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700971 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
972 for (size_t i = 0; i < 5; ++i) {
Nolan Scobie9c427942023-05-01 16:41:28 -0400973 ASSERT_EQ(OK,
974 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
975 nullptr, nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700976 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
977 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
978 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
979 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
980 std::this_thread::sleep_for(16ms);
981 }
982 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
983 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
984 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
985
986 // Now we read the segments
987 std::vector<OccupancyTracker::Segment> history;
988 ASSERT_EQ(OK, mConsumer->getOccupancyHistory(false, &history));
989
990 // Since we didn't force a flush, we should only get the first two segments
991 // (since the third segment hasn't been closed out by the appearance of a
992 // new segment yet)
993 ASSERT_EQ(2u, history.size());
994
995 // The first segment (which will be history[1], since the newest segment
996 // should be at the front of the vector) should be a two-buffer segment,
997 // which implies that the occupancy average should be between 0 and 1, and
998 // usedThirdBuffer should be false
999 const auto& firstSegment = history[1];
1000 ASSERT_EQ(5u, firstSegment.numFrames);
1001 ASSERT_LT(0, firstSegment.occupancyAverage);
1002 ASSERT_GT(1, firstSegment.occupancyAverage);
1003 ASSERT_EQ(false, firstSegment.usedThirdBuffer);
1004
1005 // The second segment should be a double-buffered segment, which implies that
1006 // the occupancy average should be between 0 and 1, but usedThirdBuffer
1007 // should be true
1008 const auto& secondSegment = history[0];
1009 ASSERT_EQ(7u, secondSegment.numFrames);
1010 ASSERT_LT(0, secondSegment.occupancyAverage);
1011 ASSERT_GT(1, secondSegment.occupancyAverage);
1012 ASSERT_EQ(true, secondSegment.usedThirdBuffer);
1013
1014 // If we read the segments again without flushing, we shouldn't get any new
1015 // segments
1016 ASSERT_EQ(OK, mConsumer->getOccupancyHistory(false, &history));
1017 ASSERT_EQ(0u, history.size());
1018
1019 // Read the segments again, this time forcing a flush so we get the third
1020 // segment
1021 ASSERT_EQ(OK, mConsumer->getOccupancyHistory(true, &history));
1022 ASSERT_EQ(1u, history.size());
1023
1024 // This segment should be a triple-buffered segment, which implies that the
1025 // occupancy average should be between 1 and 2, and usedThirdBuffer should
1026 // be true
1027 const auto& thirdSegment = history[0];
1028 ASSERT_EQ(6u, thirdSegment.numFrames);
1029 ASSERT_LT(1, thirdSegment.occupancyAverage);
1030 ASSERT_GT(2, thirdSegment.occupancyAverage);
1031 ASSERT_EQ(true, thirdSegment.usedThirdBuffer);
1032}
1033
Shuzhen Wang067fcd32019-08-14 10:41:12 -07001034struct BufferDiscardedListener : public BnProducerListener {
1035public:
1036 BufferDiscardedListener() = default;
1037 virtual ~BufferDiscardedListener() = default;
1038
1039 virtual void onBufferReleased() {}
1040 virtual bool needsReleaseNotify() { return false; }
1041 virtual void onBuffersDiscarded(const std::vector<int32_t>& slots) {
1042 mDiscardedSlots.insert(mDiscardedSlots.end(), slots.begin(), slots.end());
1043 }
1044
1045 const std::vector<int32_t>& getDiscardedSlots() const { return mDiscardedSlots; }
1046private:
1047 // No need to use lock given the test triggers the listener in the same
1048 // thread context.
1049 std::vector<int32_t> mDiscardedSlots;
1050};
1051
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001052TEST_F(BufferQueueTest, TestDiscardFreeBuffers) {
1053 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -07001054 sp<MockConsumer> mc(new MockConsumer);
1055 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001056 IGraphicBufferProducer::QueueBufferOutput output;
Shuzhen Wang067fcd32019-08-14 10:41:12 -07001057 sp<BufferDiscardedListener> pl(new BufferDiscardedListener);
1058 ASSERT_EQ(OK, mProducer->connect(pl,
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001059 NATIVE_WINDOW_API_CPU, false, &output));
1060
1061 int slot = BufferQueue::INVALID_BUFFER_SLOT;
1062 sp<Fence> fence = Fence::NO_FENCE;
1063 sp<GraphicBuffer> buffer = nullptr;
1064 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1065 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1066 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1067 BufferItem item{};
1068
1069 // Preallocate, dequeue, request, and cancel 4 buffers so we don't get
1070 // BUFFER_NEEDS_REALLOCATION below
1071 int slots[4] = {};
1072 mProducer->setMaxDequeuedBufferCount(4);
1073 for (size_t i = 0; i < 4; ++i) {
Nolan Scobie9c427942023-05-01 16:41:28 -04001074 status_t result = mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0,
1075 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr);
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001076 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1077 ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
1078 }
1079 for (size_t i = 0; i < 4; ++i) {
1080 ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE));
1081 }
1082
1083 // Get buffers in all states: dequeued, filled, acquired, free
1084
1085 // Fill 3 buffers
Nolan Scobie9c427942023-05-01 16:41:28 -04001086 ASSERT_EQ(OK,
1087 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1088 nullptr));
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001089 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
Nolan Scobie9c427942023-05-01 16:41:28 -04001090 ASSERT_EQ(OK,
1091 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1092 nullptr));
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001093 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
Nolan Scobie9c427942023-05-01 16:41:28 -04001094 ASSERT_EQ(OK,
1095 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1096 nullptr));
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001097 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1098 // Dequeue 1 buffer
Nolan Scobie9c427942023-05-01 16:41:28 -04001099 ASSERT_EQ(OK,
1100 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1101 nullptr));
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001102
1103 // Acquire and free 1 buffer
1104 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1105 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
1106 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
Shuzhen Wang067fcd32019-08-14 10:41:12 -07001107 int releasedSlot = item.mSlot;
1108
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001109 // Acquire 1 buffer, leaving 1 filled buffer in queue
1110 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1111
1112 // Now discard the free buffers
1113 ASSERT_EQ(OK, mConsumer->discardFreeBuffers());
1114
Shuzhen Wang067fcd32019-08-14 10:41:12 -07001115 // Check onBuffersDiscarded is called with correct slots
1116 auto buffersDiscarded = pl->getDiscardedSlots();
1117 ASSERT_EQ(buffersDiscarded.size(), 1);
1118 ASSERT_EQ(buffersDiscarded[0], releasedSlot);
1119
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001120 // Check no free buffers in dump
1121 String8 dumpString;
Dan Stoza0c9a1ed2017-04-06 15:10:21 -07001122 mConsumer->dumpState(String8{}, &dumpString);
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001123
1124 // Parse the dump to ensure that all buffer slots that are FREE also
1125 // have a null GraphicBuffer
1126 // Fragile - assumes the following format for the dump for a buffer entry:
1127 // ":%p\][^:]*state=FREE" where %p is the buffer pointer in hex.
1128 ssize_t idx = dumpString.find("state=FREE");
1129 while (idx != -1) {
1130 ssize_t bufferPtrIdx = idx - 1;
1131 while (bufferPtrIdx > 0) {
1132 if (dumpString[bufferPtrIdx] == ':') {
1133 bufferPtrIdx++;
1134 break;
1135 }
1136 bufferPtrIdx--;
1137 }
1138 ASSERT_GT(bufferPtrIdx, 0) << "Can't parse queue dump to validate";
1139 ssize_t nullPtrIdx = dumpString.find("0x0]", bufferPtrIdx);
1140 ASSERT_EQ(bufferPtrIdx, nullPtrIdx) << "Free buffer not discarded";
1141 idx = dumpString.find("FREE", idx + 1);
1142 }
1143}
1144
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001145TEST_F(BufferQueueTest, TestBufferReplacedInQueueBuffer) {
1146 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -07001147 sp<MockConsumer> mc(new MockConsumer);
1148 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001149 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -07001150 ASSERT_EQ(OK,
1151 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001152 ASSERT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
1153
1154 int slot = BufferQueue::INVALID_BUFFER_SLOT;
1155 sp<Fence> fence = Fence::NO_FENCE;
1156 sp<GraphicBuffer> buffer = nullptr;
1157 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1158 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1159 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1160 BufferItem item{};
1161
1162 // Preallocate, dequeue, request, and cancel 2 buffers so we don't get
1163 // BUFFER_NEEDS_REALLOCATION below
1164 int slots[2] = {};
1165 ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(2));
1166 for (size_t i = 0; i < 2; ++i) {
Nolan Scobie9c427942023-05-01 16:41:28 -04001167 status_t result = mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0,
1168 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr);
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001169 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1170 ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
1171 }
1172 for (size_t i = 0; i < 2; ++i) {
1173 ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE));
1174 }
1175
1176 // Fill 2 buffers without consumer consuming them. Verify that all
1177 // queued buffer returns proper bufferReplaced flag
Nolan Scobie9c427942023-05-01 16:41:28 -04001178 ASSERT_EQ(OK,
1179 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1180 nullptr));
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001181 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1182 ASSERT_EQ(false, output.bufferReplaced);
Nolan Scobie9c427942023-05-01 16:41:28 -04001183 ASSERT_EQ(OK,
1184 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1185 nullptr));
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001186 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1187 ASSERT_EQ(true, output.bufferReplaced);
1188}
1189
Sungtak Lee1e7c09b2023-10-26 08:44:21 +00001190struct BufferDetachedListener : public BnProducerListener {
1191public:
1192 BufferDetachedListener() = default;
1193 virtual ~BufferDetachedListener() = default;
1194
1195 virtual void onBufferReleased() {}
1196 virtual bool needsReleaseNotify() { return true; }
1197 virtual void onBufferDetached(int slot) {
1198 mDetachedSlots.push_back(slot);
1199 }
1200 const std::vector<int>& getDetachedSlots() const { return mDetachedSlots; }
1201private:
1202 std::vector<int> mDetachedSlots;
1203};
1204
1205TEST_F(BufferQueueTest, TestConsumerDetachProducerListener) {
1206 createBufferQueue();
1207 sp<MockConsumer> mc(new MockConsumer);
1208 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
1209 IGraphicBufferProducer::QueueBufferOutput output;
1210 sp<BufferDetachedListener> pl(new BufferDetachedListener);
1211 ASSERT_EQ(OK, mProducer->connect(pl, NATIVE_WINDOW_API_CPU, true, &output));
1212 ASSERT_EQ(OK, mProducer->setDequeueTimeout(0));
1213 ASSERT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
1214
1215 sp<Fence> fence = Fence::NO_FENCE;
1216 sp<GraphicBuffer> buffer = nullptr;
1217 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1218 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1219 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1220
1221 int slots[2] = {};
1222 status_t result = OK;
1223 ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(2));
1224
1225 result = mProducer->dequeueBuffer(&slots[0], &fence, 0, 0, 0,
1226 GRALLOC_USAGE_SW_READ_RARELY, nullptr, nullptr);
1227 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1228 ASSERT_EQ(OK, mProducer->requestBuffer(slots[0], &buffer));
1229
1230 result = mProducer->dequeueBuffer(&slots[1], &fence, 0, 0, 0,
1231 GRALLOC_USAGE_SW_READ_RARELY, nullptr, nullptr);
1232 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1233 ASSERT_EQ(OK, mProducer->requestBuffer(slots[1], &buffer));
1234
1235 // Queue & detach one from two dequeued buffes.
1236 ASSERT_EQ(OK, mProducer->queueBuffer(slots[1], input, &output));
1237 BufferItem item{};
1238 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1239 ASSERT_EQ(OK, mConsumer->detachBuffer(item.mSlot));
1240
1241 // Check whether the slot from IProducerListener is same to the detached slot.
1242 ASSERT_EQ(pl->getDetachedSlots().size(), 1);
1243 ASSERT_EQ(pl->getDetachedSlots()[0], slots[1]);
1244
1245 // Dequeue another buffer.
1246 int slot;
1247 result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
1248 GRALLOC_USAGE_SW_READ_RARELY, nullptr, nullptr);
1249 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1250 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
1251
1252 // Dequeue should fail here, since we dequeued 3 buffers and one buffer was
1253 // detached from consumer(Two buffers are dequeued, and the current max
1254 // dequeued buffer count is two).
1255 result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
1256 GRALLOC_USAGE_SW_READ_RARELY, nullptr, nullptr);
1257 ASSERT_TRUE(result == WOULD_BLOCK || result == TIMED_OUT || result == INVALID_OPERATION);
1258}
1259
Sungtak Lee6d223cb2024-07-31 19:35:07 +00001260#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_CONSUMER_ATTACH_CALLBACK)
1261struct BufferAttachedListener : public BnProducerListener {
1262public:
1263 BufferAttachedListener(bool enable) : mEnabled(enable), mAttached(0) {}
1264 virtual ~BufferAttachedListener() = default;
1265
1266 virtual void onBufferReleased() {}
1267 virtual bool needsReleaseNotify() { return true; }
1268 virtual void onBufferAttached() {
1269 ++mAttached;
1270 }
1271 virtual bool needsAttachNotify() { return mEnabled; }
1272
1273 int getNumAttached() const { return mAttached; }
1274private:
1275 const bool mEnabled;
1276 int mAttached;
1277};
1278
1279TEST_F(BufferQueueTest, TestConsumerAttachProducerListener) {
1280 createBufferQueue();
1281 sp<MockConsumer> mc1(new MockConsumer);
1282 ASSERT_EQ(OK, mConsumer->consumerConnect(mc1, true));
1283 IGraphicBufferProducer::QueueBufferOutput output;
1284 // Do not enable attach callback.
1285 sp<BufferAttachedListener> pl1(new BufferAttachedListener(false));
1286 ASSERT_EQ(OK, mProducer->connect(pl1, NATIVE_WINDOW_API_CPU, true, &output));
1287 ASSERT_EQ(OK, mProducer->setDequeueTimeout(0));
1288 ASSERT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
1289
1290 sp<Fence> fence = Fence::NO_FENCE;
1291 sp<GraphicBuffer> buffer = nullptr;
1292
1293 int slot;
1294 status_t result = OK;
1295
1296 ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(1));
1297
1298 result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
1299 GRALLOC_USAGE_SW_READ_RARELY, nullptr, nullptr);
1300 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1301 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
1302 ASSERT_EQ(OK, mProducer->detachBuffer(slot));
1303
1304 // Check # of attach is zero.
1305 ASSERT_EQ(0, pl1->getNumAttached());
1306
1307 // Attach a buffer and check the callback was not called.
1308 ASSERT_EQ(OK, mConsumer->attachBuffer(&slot, buffer));
1309 ASSERT_EQ(0, pl1->getNumAttached());
1310
1311 mProducer = nullptr;
1312 mConsumer = nullptr;
1313 createBufferQueue();
1314
1315 sp<MockConsumer> mc2(new MockConsumer);
1316 ASSERT_EQ(OK, mConsumer->consumerConnect(mc2, true));
1317 // Enable attach callback.
1318 sp<BufferAttachedListener> pl2(new BufferAttachedListener(true));
1319 ASSERT_EQ(OK, mProducer->connect(pl2, NATIVE_WINDOW_API_CPU, true, &output));
1320 ASSERT_EQ(OK, mProducer->setDequeueTimeout(0));
1321 ASSERT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
1322
1323 fence = Fence::NO_FENCE;
1324 buffer = nullptr;
1325
1326 result = OK;
1327
1328 ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(1));
1329
1330 result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
1331 GRALLOC_USAGE_SW_READ_RARELY, nullptr, nullptr);
1332 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1333 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
1334 ASSERT_EQ(OK, mProducer->detachBuffer(slot));
1335
1336 // Check # of attach is zero.
1337 ASSERT_EQ(0, pl2->getNumAttached());
1338
1339 // Attach a buffer and check the callback was called.
1340 ASSERT_EQ(OK, mConsumer->attachBuffer(&slot, buffer));
1341 ASSERT_EQ(1, pl2->getNumAttached());
1342}
1343#endif
1344
Dan Stozad4c6f992017-03-21 13:43:22 -07001345TEST_F(BufferQueueTest, TestStaleBufferHandleSentAfterDisconnect) {
1346 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -07001347 sp<MockConsumer> mc(new MockConsumer);
1348 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Dan Stozad4c6f992017-03-21 13:43:22 -07001349 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -07001350 sp<IProducerListener> fakeListener(new StubProducerListener);
1351 ASSERT_EQ(OK, mProducer->connect(fakeListener, NATIVE_WINDOW_API_CPU, true, &output));
Dan Stozad4c6f992017-03-21 13:43:22 -07001352
1353 int slot = BufferQueue::INVALID_BUFFER_SLOT;
1354 sp<Fence> fence = Fence::NO_FENCE;
1355 sp<GraphicBuffer> buffer = nullptr;
1356 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1357 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1358 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1359
1360 // Dequeue, request, and queue one buffer
Nolan Scobie9c427942023-05-01 16:41:28 -04001361 status_t result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
1362 nullptr, nullptr);
Dan Stozad4c6f992017-03-21 13:43:22 -07001363 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1364 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
1365 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1366
1367 // Acquire and release the buffer. Upon acquiring, the buffer handle should
1368 // be non-null since this is the first time we've acquired this slot.
1369 BufferItem item;
1370 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1371 ASSERT_EQ(slot, item.mSlot);
1372 ASSERT_NE(nullptr, item.mGraphicBuffer.get());
1373 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
1374 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
1375
1376 // Dequeue and queue the buffer again
Nolan Scobie9c427942023-05-01 16:41:28 -04001377 ASSERT_EQ(OK,
1378 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1379 nullptr));
Dan Stozad4c6f992017-03-21 13:43:22 -07001380 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1381
1382 // Acquire and release the buffer again. Upon acquiring, the buffer handle
1383 // should be null since this is not the first time we've acquired this slot.
1384 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1385 ASSERT_EQ(slot, item.mSlot);
1386 ASSERT_EQ(nullptr, item.mGraphicBuffer.get());
1387 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
1388 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
1389
1390 // Dequeue and queue the buffer again
Nolan Scobie9c427942023-05-01 16:41:28 -04001391 ASSERT_EQ(OK,
1392 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1393 nullptr));
Dan Stozad4c6f992017-03-21 13:43:22 -07001394 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1395
1396 // Disconnect the producer end. This should clear all of the slots and mark
1397 // the buffer in the queue as stale.
1398 ASSERT_EQ(OK, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
1399
1400 // Acquire the buffer again. Upon acquiring, the buffer handle should not be
1401 // null since the queued buffer should have been marked as stale, which
1402 // should trigger the BufferQueue to resend the buffer handle.
1403 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1404 ASSERT_EQ(slot, item.mSlot);
1405 ASSERT_NE(nullptr, item.mGraphicBuffer.get());
1406}
1407
Wonsik Kim3e198b22017-04-07 15:43:16 -07001408TEST_F(BufferQueueTest, TestProducerConnectDisconnect) {
1409 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -07001410 sp<MockConsumer> mc(new MockConsumer);
1411 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Wonsik Kim3e198b22017-04-07 15:43:16 -07001412 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -07001413 sp<IProducerListener> fakeListener(new StubProducerListener);
Wonsik Kim3e198b22017-04-07 15:43:16 -07001414 ASSERT_EQ(NO_INIT, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
Peiyong Lind8460c82020-07-28 16:04:22 -07001415 ASSERT_EQ(OK, mProducer->connect(fakeListener, NATIVE_WINDOW_API_CPU, true, &output));
1416 ASSERT_EQ(BAD_VALUE, mProducer->connect(fakeListener, NATIVE_WINDOW_API_MEDIA, true, &output));
Wonsik Kim3e198b22017-04-07 15:43:16 -07001417
1418 ASSERT_EQ(BAD_VALUE, mProducer->disconnect(NATIVE_WINDOW_API_MEDIA));
1419 ASSERT_EQ(OK, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
1420 ASSERT_EQ(NO_INIT, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
1421}
1422
Ady Abraham6cdd3fd2023-09-07 18:45:58 -07001423TEST_F(BufferQueueTest, TestBqSetFrameRateFlagBuildTimeIsSet) {
Ady Abraham107788e2023-10-17 12:31:08 -07001424 ASSERT_EQ(flags::bq_setframerate(), COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_SETFRAMERATE));
Ady Abraham6cdd3fd2023-09-07 18:45:58 -07001425}
1426
1427struct BufferItemConsumerSetFrameRateListener : public BufferItemConsumer {
1428 BufferItemConsumerSetFrameRateListener(const sp<IGraphicBufferConsumer>& consumer)
1429 : BufferItemConsumer(consumer, GRALLOC_USAGE_SW_READ_OFTEN, 1) {}
1430
1431 MOCK_METHOD(void, onSetFrameRate, (float, int8_t, int8_t), (override));
1432};
1433
1434TEST_F(BufferQueueTest, TestSetFrameRate) {
1435 sp<IGraphicBufferProducer> producer;
1436 sp<IGraphicBufferConsumer> consumer;
1437 BufferQueue::createBufferQueue(&producer, &consumer);
1438
1439 sp<BufferItemConsumerSetFrameRateListener> bufferConsumer =
1440 sp<BufferItemConsumerSetFrameRateListener>::make(consumer);
1441
1442 EXPECT_CALL(*bufferConsumer, onSetFrameRate(12.34f, 1, 0)).Times(1);
1443 producer->setFrameRate(12.34f, 1, 0);
1444}
1445
John Reck12daff92023-07-28 16:36:27 -04001446class Latch {
1447public:
1448 explicit Latch(int expected) : mExpected(expected) {}
1449 Latch(const Latch&) = delete;
1450 Latch& operator=(const Latch&) = delete;
1451
1452 void CountDown() {
1453 std::unique_lock<std::mutex> lock(mLock);
1454 mExpected--;
1455 if (mExpected <= 0) {
1456 mCV.notify_all();
1457 }
1458 }
1459
1460 void Wait() {
1461 std::unique_lock<std::mutex> lock(mLock);
1462 mCV.wait(lock, [&] { return mExpected == 0; });
1463 }
1464
1465private:
1466 int mExpected;
1467 std::mutex mLock;
1468 std::condition_variable mCV;
1469};
1470
1471struct OneshotOnDequeuedListener final : public BufferItemConsumer::FrameAvailableListener {
1472 OneshotOnDequeuedListener(std::function<void()>&& oneshot)
1473 : mOneshotRunnable(std::move(oneshot)) {}
1474
1475 std::function<void()> mOneshotRunnable;
1476
1477 void run() {
1478 if (mOneshotRunnable) {
1479 mOneshotRunnable();
1480 mOneshotRunnable = nullptr;
1481 }
1482 }
1483
1484 void onFrameDequeued(const uint64_t) override { run(); }
1485
1486 void onFrameAvailable(const BufferItem&) override {}
1487};
1488
1489// See b/270004534
1490TEST(BufferQueueThreading, TestProducerDequeueConsumerDestroy) {
1491 sp<IGraphicBufferProducer> producer;
1492 sp<IGraphicBufferConsumer> consumer;
1493 BufferQueue::createBufferQueue(&producer, &consumer);
1494
1495 sp<BufferItemConsumer> bufferConsumer =
1496 sp<BufferItemConsumer>::make(consumer, GRALLOC_USAGE_SW_READ_OFTEN, 2);
1497 ASSERT_NE(nullptr, bufferConsumer.get());
1498 sp<Surface> surface = sp<Surface>::make(producer);
1499 native_window_set_buffers_format(surface.get(), PIXEL_FORMAT_RGBA_8888);
1500 native_window_set_buffers_dimensions(surface.get(), 100, 100);
1501
1502 Latch triggerDisconnect(1);
1503 Latch resumeCallback(1);
1504 auto luckyListener = sp<OneshotOnDequeuedListener>::make([&]() {
1505 triggerDisconnect.CountDown();
1506 resumeCallback.Wait();
1507 });
1508 bufferConsumer->setFrameAvailableListener(luckyListener);
1509
1510 std::future<void> disconnecter = std::async(std::launch::async, [&]() {
1511 triggerDisconnect.Wait();
1512 luckyListener = nullptr;
1513 bufferConsumer = nullptr;
1514 resumeCallback.CountDown();
1515 });
1516
1517 std::future<void> render = std::async(std::launch::async, [=]() {
1518 ANativeWindow_Buffer buffer;
1519 surface->lock(&buffer, nullptr);
1520 surface->unlockAndPost();
1521 });
1522
1523 ASSERT_EQ(std::future_status::ready, render.wait_for(1s));
1524 EXPECT_EQ(nullptr, luckyListener.get());
1525 EXPECT_EQ(nullptr, bufferConsumer.get());
1526}
1527
Jamie Gennis9e75ddd2012-08-31 15:32:45 -07001528} // namespace android