blob: 1ec6f915f72b77f85ff9db8b6ed9ddfab16202a7 [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();
Siarhei Vishniakoubf98a572024-03-29 13:34:42 -0700122 sp<IBinder> binderProducer = serviceManager->waitForService(PRODUCER_NAME);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700123 mProducer = interface_cast<IGraphicBufferProducer>(binderProducer);
Yi Konga03e0442018-07-17 11:16:57 -0700124 EXPECT_TRUE(mProducer != nullptr);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700125 sp<IBinder> binderConsumer =
126 serviceManager->getService(CONSUMER_NAME);
127 mConsumer = interface_cast<IGraphicBufferConsumer>(binderConsumer);
Yi Konga03e0442018-07-17 11:16:57 -0700128 EXPECT_TRUE(mConsumer != nullptr);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700129
Peiyong Lind8460c82020-07-28 16:04:22 -0700130 sp<MockConsumer> mc(new MockConsumer);
131 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Dan Stoza1a0b8612014-03-20 15:36:31 -0700132 IGraphicBufferProducer::QueueBufferOutput output;
133 ASSERT_EQ(OK,
Yi Konga03e0442018-07-17 11:16:57 -0700134 mProducer->connect(nullptr, NATIVE_WINDOW_API_CPU, false, &output));
Dan Stoza1a0b8612014-03-20 15:36:31 -0700135
136 int slot;
137 sp<Fence> fence;
138 sp<GraphicBuffer> buffer;
139 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600140 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
141 nullptr, nullptr));
Dan Stoza1a0b8612014-03-20 15:36:31 -0700142 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
143
144 uint32_t* dataIn;
145 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
146 reinterpret_cast<void**>(&dataIn)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700147 *dataIn = TEST_DATA;
Dan Stoza1a0b8612014-03-20 15:36:31 -0700148 ASSERT_EQ(OK, buffer->unlock());
149
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800150 IGraphicBufferProducer::QueueBufferInput input(0, false,
151 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700152 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700153 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
154
Dan Stozacf3834d2015-03-11 14:04:22 -0700155 BufferItem item;
Dan Stoza1a0b8612014-03-20 15:36:31 -0700156 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
157
158 uint32_t* dataOut;
159 ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
160 reinterpret_cast<void**>(&dataOut)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700161 ASSERT_EQ(*dataOut, TEST_DATA);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700162 ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
163}
164
silence_dogoode9d092a2019-06-19 16:14:53 -0700165TEST_F(BufferQueueTest, GetMaxBufferCountInQueueBufferOutput_Succeeds) {
166 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700167 sp<MockConsumer> mc(new MockConsumer);
168 mConsumer->consumerConnect(mc, false);
silence_dogoode9d092a2019-06-19 16:14:53 -0700169 int bufferCount = 50;
170 mConsumer->setMaxBufferCount(bufferCount);
171
172 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700173 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output);
silence_dogoode9d092a2019-06-19 16:14:53 -0700174 ASSERT_EQ(output.maxBufferCount, bufferCount);
175}
176
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700177TEST_F(BufferQueueTest, AcquireBuffer_ExceedsMaxAcquireCount_Fails) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700178 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700179 sp<MockConsumer> mc(new MockConsumer);
180 mConsumer->consumerConnect(mc, false);
Andy McFadden2adaf042012-12-18 09:49:45 -0800181 IGraphicBufferProducer::QueueBufferOutput qbo;
Peiyong Lind8460c82020-07-28 16:04:22 -0700182 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &qbo);
Pablo Ceballosfa455352015-08-12 17:47:47 -0700183 mProducer->setMaxDequeuedBufferCount(3);
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700184
185 int slot;
186 sp<Fence> fence;
187 sp<GraphicBuffer> buf;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800188 IGraphicBufferProducer::QueueBufferInput qbi(0, false,
189 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700190 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Dan Stozacf3834d2015-03-11 14:04:22 -0700191 BufferItem item;
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700192
193 for (int i = 0; i < 2; i++) {
Andy McFadden2adaf042012-12-18 09:49:45 -0800194 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600195 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
196 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800197 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
198 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
199 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700200 }
201
Andy McFadden2adaf042012-12-18 09:49:45 -0800202 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600203 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
204 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800205 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
206 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700207
208 // Acquire the third buffer, which should fail.
Dan Stoza9f3053d2014-03-06 15:14:33 -0800209 ASSERT_EQ(INVALID_OPERATION, mConsumer->acquireBuffer(&item, 0));
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700210}
211
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700212TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithIllegalValues_ReturnsError) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700213 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700214 sp<MockConsumer> mc(new MockConsumer);
215 mConsumer->consumerConnect(mc, false);
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700216
Pablo Ceballos72daab62015-12-07 16:38:43 -0800217 EXPECT_EQ(OK, mConsumer->setMaxBufferCount(10));
218 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(10));
219
220 IGraphicBufferProducer::QueueBufferOutput qbo;
Peiyong Lind8460c82020-07-28 16:04:22 -0700221 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &qbo);
Pablo Ceballos72daab62015-12-07 16:38:43 -0800222 mProducer->setMaxDequeuedBufferCount(3);
223
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800224 int minBufferCount;
225 ASSERT_NO_FATAL_FAILURE(GetMinUndequeuedBufferCount(&minBufferCount));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800226 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(
227 minBufferCount - 1));
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800228
Dan Stoza9f3053d2014-03-06 15:14:33 -0800229 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(0));
230 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(-3));
231 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700232 BufferQueue::MAX_MAX_ACQUIRED_BUFFERS+1));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800233 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(100));
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700234
Pablo Ceballos72daab62015-12-07 16:38:43 -0800235 int slot;
236 sp<Fence> fence;
237 sp<GraphicBuffer> buf;
238 IGraphicBufferProducer::QueueBufferInput qbi(0, false,
239 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
240 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
241 BufferItem item;
242 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(3));
243 for (int i = 0; i < 3; i++) {
244 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600245 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
246 nullptr, nullptr));
Pablo Ceballos72daab62015-12-07 16:38:43 -0800247 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
248 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
249 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
250 }
251
252 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(2));
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700253}
254
255TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithLegalValues_Succeeds) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700256 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700257 sp<MockConsumer> mc(new MockConsumer);
258 mConsumer->consumerConnect(mc, false);
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700259
Pablo Ceballos72daab62015-12-07 16:38:43 -0800260 IGraphicBufferProducer::QueueBufferOutput qbo;
Peiyong Lind8460c82020-07-28 16:04:22 -0700261 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &qbo);
Pablo Ceballos72daab62015-12-07 16:38:43 -0800262 mProducer->setMaxDequeuedBufferCount(2);
263
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800264 int minBufferCount;
265 ASSERT_NO_FATAL_FAILURE(GetMinUndequeuedBufferCount(&minBufferCount));
266
Dan Stoza9f3053d2014-03-06 15:14:33 -0800267 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
268 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(2));
269 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(minBufferCount));
Pablo Ceballos72daab62015-12-07 16:38:43 -0800270
271 int slot;
272 sp<Fence> fence;
273 sp<GraphicBuffer> buf;
274 IGraphicBufferProducer::QueueBufferInput qbi(0, false,
275 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
276 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
277 BufferItem item;
278
279 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600280 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
281 nullptr, nullptr));
Pablo Ceballos72daab62015-12-07 16:38:43 -0800282 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
283 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
284 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
285
286 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(3));
287
288 for (int i = 0; i < 2; i++) {
289 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600290 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
291 nullptr, nullptr));
Pablo Ceballos72daab62015-12-07 16:38:43 -0800292 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
293 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
294 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
295 }
296
Dan Stoza9f3053d2014-03-06 15:14:33 -0800297 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700298 BufferQueue::MAX_MAX_ACQUIRED_BUFFERS));
299}
300
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700301TEST_F(BufferQueueTest, SetMaxBufferCountWithLegalValues_Succeeds) {
302 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700303 sp<MockConsumer> mc(new MockConsumer);
304 mConsumer->consumerConnect(mc, false);
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700305
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700306 // Test shared buffer mode
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700307 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
308}
309
310TEST_F(BufferQueueTest, SetMaxBufferCountWithIllegalValues_ReturnsError) {
311 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700312 sp<MockConsumer> mc(new MockConsumer);
313 mConsumer->consumerConnect(mc, false);
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700314
315 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(0));
316 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(
317 BufferQueue::NUM_BUFFER_SLOTS + 1));
318
319 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(5));
320 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(3));
321}
322
Dan Stoza9f3053d2014-03-06 15:14:33 -0800323TEST_F(BufferQueueTest, DetachAndReattachOnProducerSide) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700324 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700325 sp<MockConsumer> mc(new MockConsumer);
326 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800327 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700328 ASSERT_EQ(OK,
329 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800330
331 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(-1)); // Index too low
332 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(
333 BufferQueueDefs::NUM_BUFFER_SLOTS)); // Index too high
334 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(0)); // Not dequeued
335
336 int slot;
337 sp<Fence> fence;
338 sp<GraphicBuffer> buffer;
339 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600340 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
341 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800342 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(slot)); // Not requested
343 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
344 ASSERT_EQ(OK, mProducer->detachBuffer(slot));
345 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(slot)); // Not dequeued
346
347 sp<GraphicBuffer> safeToClobberBuffer;
348 // Can no longer request buffer from this slot
349 ASSERT_EQ(BAD_VALUE, mProducer->requestBuffer(slot, &safeToClobberBuffer));
350
351 uint32_t* dataIn;
352 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
353 reinterpret_cast<void**>(&dataIn)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700354 *dataIn = TEST_DATA;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800355 ASSERT_EQ(OK, buffer->unlock());
356
357 int newSlot;
Yi Konga03e0442018-07-17 11:16:57 -0700358 ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(nullptr, safeToClobberBuffer));
359 ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(&newSlot, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800360
361 ASSERT_EQ(OK, mProducer->attachBuffer(&newSlot, buffer));
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800362 IGraphicBufferProducer::QueueBufferInput input(0, false,
363 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700364 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800365 ASSERT_EQ(OK, mProducer->queueBuffer(newSlot, input, &output));
366
Dan Stozacf3834d2015-03-11 14:04:22 -0700367 BufferItem item;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800368 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
369
370 uint32_t* dataOut;
371 ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
372 reinterpret_cast<void**>(&dataOut)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700373 ASSERT_EQ(*dataOut, TEST_DATA);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700374 ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
Dan Stoza9f3053d2014-03-06 15:14:33 -0800375}
376
377TEST_F(BufferQueueTest, DetachAndReattachOnConsumerSide) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700378 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700379 sp<MockConsumer> mc(new MockConsumer);
380 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800381 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700382 ASSERT_EQ(OK,
383 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800384
385 int slot;
386 sp<Fence> fence;
387 sp<GraphicBuffer> buffer;
388 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600389 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
390 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800391 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800392 IGraphicBufferProducer::QueueBufferInput input(0, false,
393 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700394 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800395 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
396
397 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(-1)); // Index too low
398 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(
399 BufferQueueDefs::NUM_BUFFER_SLOTS)); // Index too high
400 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(0)); // Not acquired
401
Dan Stozacf3834d2015-03-11 14:04:22 -0700402 BufferItem item;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800403 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
404
Pablo Ceballos47650f42015-08-04 16:38:17 -0700405 ASSERT_EQ(OK, mConsumer->detachBuffer(item.mSlot));
406 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(item.mSlot)); // Not acquired
Dan Stoza9f3053d2014-03-06 15:14:33 -0800407
408 uint32_t* dataIn;
409 ASSERT_EQ(OK, item.mGraphicBuffer->lock(
410 GraphicBuffer::USAGE_SW_WRITE_OFTEN,
411 reinterpret_cast<void**>(&dataIn)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700412 *dataIn = TEST_DATA;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800413 ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
414
415 int newSlot;
416 sp<GraphicBuffer> safeToClobberBuffer;
Yi Konga03e0442018-07-17 11:16:57 -0700417 ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(nullptr, safeToClobberBuffer));
418 ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(&newSlot, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800419 ASSERT_EQ(OK, mConsumer->attachBuffer(&newSlot, item.mGraphicBuffer));
420
Dan Stoza99b18b42014-03-28 15:34:33 -0700421 ASSERT_EQ(OK, mConsumer->releaseBuffer(newSlot, 0, EGL_NO_DISPLAY,
Dan Stoza9f3053d2014-03-06 15:14:33 -0800422 EGL_NO_SYNC_KHR, Fence::NO_FENCE));
423
424 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600425 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
426 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800427 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
428
429 uint32_t* dataOut;
430 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
431 reinterpret_cast<void**>(&dataOut)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700432 ASSERT_EQ(*dataOut, TEST_DATA);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700433 ASSERT_EQ(OK, buffer->unlock());
Dan Stoza9f3053d2014-03-06 15:14:33 -0800434}
435
436TEST_F(BufferQueueTest, MoveFromConsumerToProducer) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700437 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700438 sp<MockConsumer> mc(new MockConsumer);
439 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800440 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700441 ASSERT_EQ(OK,
442 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800443
444 int slot;
445 sp<Fence> fence;
446 sp<GraphicBuffer> buffer;
447 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600448 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
449 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800450 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
451
452 uint32_t* dataIn;
453 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
454 reinterpret_cast<void**>(&dataIn)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700455 *dataIn = TEST_DATA;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800456 ASSERT_EQ(OK, buffer->unlock());
457
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800458 IGraphicBufferProducer::QueueBufferInput input(0, false,
459 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700460 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800461 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
462
Dan Stozacf3834d2015-03-11 14:04:22 -0700463 BufferItem item;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800464 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
Pablo Ceballos47650f42015-08-04 16:38:17 -0700465 ASSERT_EQ(OK, mConsumer->detachBuffer(item.mSlot));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800466
467 int newSlot;
468 ASSERT_EQ(OK, mProducer->attachBuffer(&newSlot, item.mGraphicBuffer));
469 ASSERT_EQ(OK, mProducer->queueBuffer(newSlot, input, &output));
470 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
471
472 uint32_t* dataOut;
473 ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
474 reinterpret_cast<void**>(&dataOut)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700475 ASSERT_EQ(*dataOut, TEST_DATA);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700476 ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
Dan Stoza9f3053d2014-03-06 15:14:33 -0800477}
478
Dan Stoza9de72932015-04-16 17:28:43 -0700479TEST_F(BufferQueueTest, TestDisallowingAllocation) {
480 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700481 sp<MockConsumer> mc(new MockConsumer);
482 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Dan Stoza9de72932015-04-16 17:28:43 -0700483 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700484 ASSERT_EQ(OK,
485 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Dan Stoza9de72932015-04-16 17:28:43 -0700486
487 static const uint32_t WIDTH = 320;
488 static const uint32_t HEIGHT = 240;
489
490 ASSERT_EQ(OK, mConsumer->setDefaultBufferSize(WIDTH, HEIGHT));
491
492 int slot;
493 sp<Fence> fence;
494 sp<GraphicBuffer> buffer;
495 // This should return an error since it would require an allocation
496 ASSERT_EQ(OK, mProducer->allowAllocation(false));
Ian Elliottd11b0442017-07-18 11:05:49 -0600497 ASSERT_EQ(WOULD_BLOCK,
498 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
499 nullptr, nullptr));
Dan Stoza9de72932015-04-16 17:28:43 -0700500
501 // This should succeed, now that we've lifted the prohibition
502 ASSERT_EQ(OK, mProducer->allowAllocation(true));
503 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600504 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
505 nullptr, nullptr));
Dan Stoza9de72932015-04-16 17:28:43 -0700506
507 // Release the previous buffer back to the BufferQueue
508 mProducer->cancelBuffer(slot, fence);
509
510 // This should fail since we're requesting a different size
511 ASSERT_EQ(OK, mProducer->allowAllocation(false));
Ian Elliottd11b0442017-07-18 11:05:49 -0600512 ASSERT_EQ(WOULD_BLOCK,
513 mProducer->dequeueBuffer(&slot, &fence, WIDTH * 2, HEIGHT * 2, 0,
514 GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr, nullptr));
Dan Stoza9de72932015-04-16 17:28:43 -0700515}
516
Dan Stoza812ed062015-06-02 15:45:22 -0700517TEST_F(BufferQueueTest, TestGenerationNumbers) {
518 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700519 sp<MockConsumer> mc(new MockConsumer);
520 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Dan Stoza812ed062015-06-02 15:45:22 -0700521 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700522 ASSERT_EQ(OK,
523 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Dan Stoza812ed062015-06-02 15:45:22 -0700524
525 ASSERT_EQ(OK, mProducer->setGenerationNumber(1));
526
527 // Get one buffer to play with
528 int slot;
529 sp<Fence> fence;
530 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Nolan Scobie9c427942023-05-01 16:41:28 -0400531 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
532 nullptr));
Dan Stoza812ed062015-06-02 15:45:22 -0700533
534 sp<GraphicBuffer> buffer;
535 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
536
537 // Ensure that the generation number we set propagates to allocated buffers
538 ASSERT_EQ(1U, buffer->getGenerationNumber());
539
540 ASSERT_EQ(OK, mProducer->detachBuffer(slot));
541
542 ASSERT_EQ(OK, mProducer->setGenerationNumber(2));
543
544 // These should fail, since we've changed the generation number on the queue
545 int outSlot;
546 ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(&outSlot, buffer));
547 ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(&outSlot, buffer));
548
549 buffer->setGenerationNumber(2);
550
551 // This should succeed now that we've changed the buffer's generation number
552 ASSERT_EQ(OK, mProducer->attachBuffer(&outSlot, buffer));
553
554 ASSERT_EQ(OK, mProducer->detachBuffer(outSlot));
555
556 // This should also succeed with the new generation number
557 ASSERT_EQ(OK, mConsumer->attachBuffer(&outSlot, buffer));
558}
559
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700560TEST_F(BufferQueueTest, TestSharedBufferModeWithoutAutoRefresh) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700561 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700562 sp<MockConsumer> mc(new MockConsumer);
563 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700564 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700565 ASSERT_EQ(OK,
566 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700567
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700568 ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700569
570 // Get a buffer
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700571 int sharedSlot;
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700572 sp<Fence> fence;
573 sp<GraphicBuffer> buffer;
574 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Nolan Scobie9c427942023-05-01 16:41:28 -0400575 mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
576 nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700577 ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700578
579 // Queue the buffer
580 IGraphicBufferProducer::QueueBufferInput input(0, false,
581 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
582 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700583 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700584
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800585 // Repeatedly queue and dequeue a buffer from the producer side, it should
586 // always return the same one. And we won't run out of buffers because it's
587 // always the same one and because async mode gets enabled.
588 int slot;
589 for (int i = 0; i < 5; i++) {
Nolan Scobie9c427942023-05-01 16:41:28 -0400590 ASSERT_EQ(OK,
591 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
592 nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700593 ASSERT_EQ(sharedSlot, slot);
594 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800595 }
596
597 // acquire the buffer
598 BufferItem item;
599 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700600 ASSERT_EQ(sharedSlot, item.mSlot);
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800601 testBufferItem(input, item);
602 ASSERT_EQ(true, item.mQueuedBuffer);
603 ASSERT_EQ(false, item.mAutoRefresh);
604
605 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
606 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
607
608 // attempt to acquire a second time should return no buffer available
609 ASSERT_EQ(IGraphicBufferConsumer::NO_BUFFER_AVAILABLE,
610 mConsumer->acquireBuffer(&item, 0));
611}
612
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700613TEST_F(BufferQueueTest, TestSharedBufferModeWithAutoRefresh) {
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800614 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700615 sp<MockConsumer> mc(new MockConsumer);
616 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800617 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700618 ASSERT_EQ(OK,
619 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800620
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700621 ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800622 ASSERT_EQ(OK, mProducer->setAutoRefresh(true));
623
624 // Get a buffer
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700625 int sharedSlot;
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800626 sp<Fence> fence;
627 sp<GraphicBuffer> buffer;
628 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Nolan Scobie9c427942023-05-01 16:41:28 -0400629 mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
630 nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700631 ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800632
633 // Queue the buffer
634 IGraphicBufferProducer::QueueBufferInput input(0, false,
635 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
636 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700637 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800638
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700639 // Repeatedly acquire and release a buffer from the consumer side, it should
640 // always return the same one.
641 BufferItem item;
642 for (int i = 0; i < 5; i++) {
643 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700644 ASSERT_EQ(sharedSlot, item.mSlot);
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800645 testBufferItem(input, item);
646 ASSERT_EQ(i == 0, item.mQueuedBuffer);
647 ASSERT_EQ(true, item.mAutoRefresh);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700648
649 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
650 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
651 }
652
653 // Repeatedly queue and dequeue a buffer from the producer side, it should
654 // always return the same one.
655 int slot;
656 for (int i = 0; i < 5; i++) {
Nolan Scobie9c427942023-05-01 16:41:28 -0400657 ASSERT_EQ(OK,
658 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
659 nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700660 ASSERT_EQ(sharedSlot, slot);
661 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700662 }
663
664 // Repeatedly acquire and release a buffer from the consumer side, it should
665 // always return the same one. First grabbing them from the queue and then
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700666 // when the queue is empty, returning the shared buffer.
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700667 for (int i = 0; i < 10; i++) {
668 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700669 ASSERT_EQ(sharedSlot, item.mSlot);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700670 ASSERT_EQ(0, item.mTimestamp);
671 ASSERT_EQ(false, item.mIsAutoTimestamp);
672 ASSERT_EQ(HAL_DATASPACE_UNKNOWN, item.mDataSpace);
673 ASSERT_EQ(Rect(0, 0, 1, 1), item.mCrop);
674 ASSERT_EQ(NATIVE_WINDOW_SCALING_MODE_FREEZE, item.mScalingMode);
Dan Stoza5ecfb682016-01-04 17:01:02 -0800675 ASSERT_EQ(0u, item.mTransform);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700676 ASSERT_EQ(Fence::NO_FENCE, item.mFence);
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800677 ASSERT_EQ(i == 0, item.mQueuedBuffer);
678 ASSERT_EQ(true, item.mAutoRefresh);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700679
680 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
681 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
682 }
683}
684
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700685TEST_F(BufferQueueTest, TestSharedBufferModeUsingAlreadyDequeuedBuffer) {
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700686 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700687 sp<MockConsumer> mc(new MockConsumer);
688 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700689 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700690 ASSERT_EQ(OK,
691 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700692
693 // Dequeue a buffer
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700694 int sharedSlot;
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700695 sp<Fence> fence;
696 sp<GraphicBuffer> buffer;
697 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Nolan Scobie9c427942023-05-01 16:41:28 -0400698 mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
699 nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700700 ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700701
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700702 // Enable shared buffer mode
703 ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700704
705 // Queue the buffer
706 IGraphicBufferProducer::QueueBufferInput input(0, false,
707 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
708 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700709 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700710
711 // Repeatedly queue and dequeue a buffer from the producer side, it should
712 // always return the same one. And we won't run out of buffers because it's
713 // always the same one and because async mode gets enabled.
714 int slot;
715 for (int i = 0; i < 5; i++) {
Nolan Scobie9c427942023-05-01 16:41:28 -0400716 ASSERT_EQ(OK,
717 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
718 nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700719 ASSERT_EQ(sharedSlot, slot);
720 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700721 }
722
723 // acquire the buffer
724 BufferItem item;
725 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700726 ASSERT_EQ(sharedSlot, item.mSlot);
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700727 testBufferItem(input, item);
728 ASSERT_EQ(true, item.mQueuedBuffer);
729 ASSERT_EQ(false, item.mAutoRefresh);
730
731 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
732 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
733
734 // attempt to acquire a second time should return no buffer available
735 ASSERT_EQ(IGraphicBufferConsumer::NO_BUFFER_AVAILABLE,
736 mConsumer->acquireBuffer(&item, 0));
737}
738
Dan Stoza127fc632015-06-30 13:43:32 -0700739TEST_F(BufferQueueTest, TestTimeouts) {
740 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700741 sp<MockConsumer> mc(new MockConsumer);
742 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Dan Stoza127fc632015-06-30 13:43:32 -0700743 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700744 ASSERT_EQ(OK,
745 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Dan Stoza127fc632015-06-30 13:43:32 -0700746
747 // Fill up the queue. Since the controlledByApp flags are set to true, this
748 // queue should be in non-blocking mode, and we should be recycling the same
749 // two buffers
750 for (int i = 0; i < 5; ++i) {
751 int slot = BufferQueue::INVALID_BUFFER_SLOT;
752 sp<Fence> fence = Fence::NO_FENCE;
Nolan Scobie9c427942023-05-01 16:41:28 -0400753 auto result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
754 nullptr, nullptr);
Dan Stoza127fc632015-06-30 13:43:32 -0700755 if (i < 2) {
756 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
757 result);
758 } else {
759 ASSERT_EQ(OK, result);
760 }
761 sp<GraphicBuffer> buffer;
762 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
763 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
764 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
765 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
766 IGraphicBufferProducer::QueueBufferOutput output{};
767 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
768 }
769
770 const auto TIMEOUT = ms2ns(250);
771 mProducer->setDequeueTimeout(TIMEOUT);
772
773 // Setting a timeout will change the BufferQueue into blocking mode (with
774 // one droppable buffer in the queue and one free from the previous
775 // dequeue/queues), so dequeue and queue two more buffers: one to replace
776 // the current droppable buffer, and a second to max out the buffer count
777 sp<GraphicBuffer> buffer; // Save a buffer to attach later
778 for (int i = 0; i < 2; ++i) {
779 int slot = BufferQueue::INVALID_BUFFER_SLOT;
780 sp<Fence> fence = Fence::NO_FENCE;
Nolan Scobie9c427942023-05-01 16:41:28 -0400781 ASSERT_EQ(OK,
782 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
783 nullptr, nullptr));
Dan Stoza127fc632015-06-30 13:43:32 -0700784 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
785 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
786 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
787 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
788 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
789 }
790
791 int slot = BufferQueue::INVALID_BUFFER_SLOT;
792 sp<Fence> fence = Fence::NO_FENCE;
793 auto startTime = systemTime();
Nolan Scobie9c427942023-05-01 16:41:28 -0400794 ASSERT_EQ(TIMED_OUT,
795 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
796 nullptr));
Dan Stoza127fc632015-06-30 13:43:32 -0700797 ASSERT_GE(systemTime() - startTime, TIMEOUT);
798
799 // We're technically attaching the same buffer multiple times (since we
800 // queued it previously), but that doesn't matter for this test
801 startTime = systemTime();
802 ASSERT_EQ(TIMED_OUT, mProducer->attachBuffer(&slot, buffer));
803 ASSERT_GE(systemTime() - startTime, TIMEOUT);
804}
805
Dan Stoza5ecfb682016-01-04 17:01:02 -0800806TEST_F(BufferQueueTest, CanAttachWhileDisallowingAllocation) {
807 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700808 sp<MockConsumer> mc(new MockConsumer);
809 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Dan Stoza5ecfb682016-01-04 17:01:02 -0800810 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700811 ASSERT_EQ(OK,
812 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Dan Stoza5ecfb682016-01-04 17:01:02 -0800813
814 int slot = BufferQueue::INVALID_BUFFER_SLOT;
815 sp<Fence> sourceFence;
816 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Nolan Scobie9c427942023-05-01 16:41:28 -0400817 mProducer->dequeueBuffer(&slot, &sourceFence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
818 nullptr, nullptr));
Dan Stoza5ecfb682016-01-04 17:01:02 -0800819 sp<GraphicBuffer> buffer;
820 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
821 ASSERT_EQ(OK, mProducer->detachBuffer(slot));
822
823 ASSERT_EQ(OK, mProducer->allowAllocation(false));
824
825 slot = BufferQueue::INVALID_BUFFER_SLOT;
826 ASSERT_EQ(OK, mProducer->attachBuffer(&slot, buffer));
827}
828
Dan Stoza50101d02016-04-07 16:53:23 -0700829TEST_F(BufferQueueTest, CanRetrieveLastQueuedBuffer) {
830 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700831 sp<MockConsumer> mc(new MockConsumer);
832 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Dan Stoza50101d02016-04-07 16:53:23 -0700833 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700834 ASSERT_EQ(OK,
835 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
Dan Stoza50101d02016-04-07 16:53:23 -0700836
837 // Dequeue and queue the first buffer, storing the handle
838 int slot = BufferQueue::INVALID_BUFFER_SLOT;
839 sp<Fence> fence;
840 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Nolan Scobie9c427942023-05-01 16:41:28 -0400841 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
842 nullptr));
Dan Stoza50101d02016-04-07 16:53:23 -0700843 sp<GraphicBuffer> firstBuffer;
844 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &firstBuffer));
845
846 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
847 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
848 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
849 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
850
851 // Dequeue a second buffer
852 slot = BufferQueue::INVALID_BUFFER_SLOT;
853 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Nolan Scobie9c427942023-05-01 16:41:28 -0400854 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
855 nullptr));
Dan Stoza50101d02016-04-07 16:53:23 -0700856 sp<GraphicBuffer> secondBuffer;
857 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &secondBuffer));
858
859 // Ensure it's a new buffer
860 ASSERT_NE(firstBuffer->getNativeBuffer()->handle,
861 secondBuffer->getNativeBuffer()->handle);
862
863 // Queue the second buffer
864 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
865
866 // Acquire and release both buffers
867 for (size_t i = 0; i < 2; ++i) {
868 BufferItem item;
869 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
870 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
871 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
872 }
873
874 // Make sure we got the second buffer back
875 sp<GraphicBuffer> returnedBuffer;
876 sp<Fence> returnedFence;
John Reck1a61da52016-04-28 13:18:15 -0700877 float transform[16];
Dan Stoza50101d02016-04-07 16:53:23 -0700878 ASSERT_EQ(OK,
John Reck1a61da52016-04-28 13:18:15 -0700879 mProducer->getLastQueuedBuffer(&returnedBuffer, &returnedFence,
880 transform));
Dan Stoza50101d02016-04-07 16:53:23 -0700881 ASSERT_EQ(secondBuffer->getNativeBuffer()->handle,
882 returnedBuffer->getNativeBuffer()->handle);
883}
884
Dan Stozae77c7662016-05-13 11:37:28 -0700885TEST_F(BufferQueueTest, TestOccupancyHistory) {
886 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700887 sp<MockConsumer> mc(new MockConsumer);
888 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Dan Stozae77c7662016-05-13 11:37:28 -0700889 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700890 ASSERT_EQ(OK,
891 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
Dan Stozae77c7662016-05-13 11:37:28 -0700892
893 int slot = BufferQueue::INVALID_BUFFER_SLOT;
894 sp<Fence> fence = Fence::NO_FENCE;
895 sp<GraphicBuffer> buffer = nullptr;
896 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
897 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
898 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
899 BufferItem item{};
900
901 // Preallocate, dequeue, request, and cancel 3 buffers so we don't get
902 // BUFFER_NEEDS_REALLOCATION below
903 int slots[3] = {};
904 mProducer->setMaxDequeuedBufferCount(3);
905 for (size_t i = 0; i < 3; ++i) {
Nolan Scobie9c427942023-05-01 16:41:28 -0400906 status_t result = mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0,
907 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr);
Dan Stozae77c7662016-05-13 11:37:28 -0700908 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
909 ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
910 }
911 for (size_t i = 0; i < 3; ++i) {
912 ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE));
913 }
914
915 // Create 3 segments
916
917 // The first segment is a two-buffer segment, so we only put one buffer into
918 // the queue at a time
919 for (size_t i = 0; i < 5; ++i) {
Nolan Scobie9c427942023-05-01 16:41:28 -0400920 ASSERT_EQ(OK,
921 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
922 nullptr, nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700923 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
924 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
925 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
926 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
927 std::this_thread::sleep_for(16ms);
928 }
929
930 // Sleep between segments
931 std::this_thread::sleep_for(500ms);
932
933 // The second segment is a double-buffer segment. It starts the same as the
934 // two-buffer segment, but then at the end, we put two buffers in the queue
935 // at the same time before draining it.
936 for (size_t i = 0; i < 5; ++i) {
Nolan Scobie9c427942023-05-01 16:41:28 -0400937 ASSERT_EQ(OK,
938 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
939 nullptr, nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700940 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
941 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
942 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
943 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
944 std::this_thread::sleep_for(16ms);
945 }
Nolan Scobie9c427942023-05-01 16:41:28 -0400946 ASSERT_EQ(OK,
947 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
948 nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700949 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
Nolan Scobie9c427942023-05-01 16:41:28 -0400950 ASSERT_EQ(OK,
951 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
952 nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700953 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
954 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
955 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
956 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
957 std::this_thread::sleep_for(16ms);
958 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
959 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
960 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
961
962 // Sleep between segments
963 std::this_thread::sleep_for(500ms);
964
965 // The third segment is a triple-buffer segment, so the queue is switching
966 // between one buffer and two buffers deep.
Nolan Scobie9c427942023-05-01 16:41:28 -0400967 ASSERT_EQ(OK,
968 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
969 nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700970 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
971 for (size_t i = 0; i < 5; ++i) {
Nolan Scobie9c427942023-05-01 16:41:28 -0400972 ASSERT_EQ(OK,
973 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
974 nullptr, nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700975 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
976 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
977 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
978 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
979 std::this_thread::sleep_for(16ms);
980 }
981 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
982 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
983 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
984
985 // Now we read the segments
986 std::vector<OccupancyTracker::Segment> history;
987 ASSERT_EQ(OK, mConsumer->getOccupancyHistory(false, &history));
988
989 // Since we didn't force a flush, we should only get the first two segments
990 // (since the third segment hasn't been closed out by the appearance of a
991 // new segment yet)
992 ASSERT_EQ(2u, history.size());
993
994 // The first segment (which will be history[1], since the newest segment
995 // should be at the front of the vector) should be a two-buffer segment,
996 // which implies that the occupancy average should be between 0 and 1, and
997 // usedThirdBuffer should be false
998 const auto& firstSegment = history[1];
999 ASSERT_EQ(5u, firstSegment.numFrames);
1000 ASSERT_LT(0, firstSegment.occupancyAverage);
1001 ASSERT_GT(1, firstSegment.occupancyAverage);
1002 ASSERT_EQ(false, firstSegment.usedThirdBuffer);
1003
1004 // The second segment should be a double-buffered segment, which implies that
1005 // the occupancy average should be between 0 and 1, but usedThirdBuffer
1006 // should be true
1007 const auto& secondSegment = history[0];
1008 ASSERT_EQ(7u, secondSegment.numFrames);
1009 ASSERT_LT(0, secondSegment.occupancyAverage);
1010 ASSERT_GT(1, secondSegment.occupancyAverage);
1011 ASSERT_EQ(true, secondSegment.usedThirdBuffer);
1012
1013 // If we read the segments again without flushing, we shouldn't get any new
1014 // segments
1015 ASSERT_EQ(OK, mConsumer->getOccupancyHistory(false, &history));
1016 ASSERT_EQ(0u, history.size());
1017
1018 // Read the segments again, this time forcing a flush so we get the third
1019 // segment
1020 ASSERT_EQ(OK, mConsumer->getOccupancyHistory(true, &history));
1021 ASSERT_EQ(1u, history.size());
1022
1023 // This segment should be a triple-buffered segment, which implies that the
1024 // occupancy average should be between 1 and 2, and usedThirdBuffer should
1025 // be true
1026 const auto& thirdSegment = history[0];
1027 ASSERT_EQ(6u, thirdSegment.numFrames);
1028 ASSERT_LT(1, thirdSegment.occupancyAverage);
1029 ASSERT_GT(2, thirdSegment.occupancyAverage);
1030 ASSERT_EQ(true, thirdSegment.usedThirdBuffer);
1031}
1032
Shuzhen Wang067fcd32019-08-14 10:41:12 -07001033struct BufferDiscardedListener : public BnProducerListener {
1034public:
1035 BufferDiscardedListener() = default;
1036 virtual ~BufferDiscardedListener() = default;
1037
1038 virtual void onBufferReleased() {}
1039 virtual bool needsReleaseNotify() { return false; }
1040 virtual void onBuffersDiscarded(const std::vector<int32_t>& slots) {
1041 mDiscardedSlots.insert(mDiscardedSlots.end(), slots.begin(), slots.end());
1042 }
1043
1044 const std::vector<int32_t>& getDiscardedSlots() const { return mDiscardedSlots; }
1045private:
1046 // No need to use lock given the test triggers the listener in the same
1047 // thread context.
1048 std::vector<int32_t> mDiscardedSlots;
1049};
1050
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001051TEST_F(BufferQueueTest, TestDiscardFreeBuffers) {
1052 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -07001053 sp<MockConsumer> mc(new MockConsumer);
1054 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001055 IGraphicBufferProducer::QueueBufferOutput output;
Shuzhen Wang067fcd32019-08-14 10:41:12 -07001056 sp<BufferDiscardedListener> pl(new BufferDiscardedListener);
1057 ASSERT_EQ(OK, mProducer->connect(pl,
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001058 NATIVE_WINDOW_API_CPU, false, &output));
1059
1060 int slot = BufferQueue::INVALID_BUFFER_SLOT;
1061 sp<Fence> fence = Fence::NO_FENCE;
1062 sp<GraphicBuffer> buffer = nullptr;
1063 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1064 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1065 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1066 BufferItem item{};
1067
1068 // Preallocate, dequeue, request, and cancel 4 buffers so we don't get
1069 // BUFFER_NEEDS_REALLOCATION below
1070 int slots[4] = {};
1071 mProducer->setMaxDequeuedBufferCount(4);
1072 for (size_t i = 0; i < 4; ++i) {
Nolan Scobie9c427942023-05-01 16:41:28 -04001073 status_t result = mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0,
1074 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr);
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001075 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1076 ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
1077 }
1078 for (size_t i = 0; i < 4; ++i) {
1079 ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE));
1080 }
1081
1082 // Get buffers in all states: dequeued, filled, acquired, free
1083
1084 // Fill 3 buffers
Nolan Scobie9c427942023-05-01 16:41:28 -04001085 ASSERT_EQ(OK,
1086 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1087 nullptr));
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001088 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
Nolan Scobie9c427942023-05-01 16:41:28 -04001089 ASSERT_EQ(OK,
1090 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1091 nullptr));
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001092 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
Nolan Scobie9c427942023-05-01 16:41:28 -04001093 ASSERT_EQ(OK,
1094 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1095 nullptr));
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001096 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1097 // Dequeue 1 buffer
Nolan Scobie9c427942023-05-01 16:41:28 -04001098 ASSERT_EQ(OK,
1099 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1100 nullptr));
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001101
1102 // Acquire and free 1 buffer
1103 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1104 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
1105 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
Shuzhen Wang067fcd32019-08-14 10:41:12 -07001106 int releasedSlot = item.mSlot;
1107
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001108 // Acquire 1 buffer, leaving 1 filled buffer in queue
1109 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1110
1111 // Now discard the free buffers
1112 ASSERT_EQ(OK, mConsumer->discardFreeBuffers());
1113
Shuzhen Wang067fcd32019-08-14 10:41:12 -07001114 // Check onBuffersDiscarded is called with correct slots
1115 auto buffersDiscarded = pl->getDiscardedSlots();
Siarhei Vishniakoubf98a572024-03-29 13:34:42 -07001116 ASSERT_EQ(buffersDiscarded.size(), 1u);
Shuzhen Wang067fcd32019-08-14 10:41:12 -07001117 ASSERT_EQ(buffersDiscarded[0], releasedSlot);
1118
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001119 // Check no free buffers in dump
1120 String8 dumpString;
Dan Stoza0c9a1ed2017-04-06 15:10:21 -07001121 mConsumer->dumpState(String8{}, &dumpString);
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001122
1123 // Parse the dump to ensure that all buffer slots that are FREE also
1124 // have a null GraphicBuffer
1125 // Fragile - assumes the following format for the dump for a buffer entry:
1126 // ":%p\][^:]*state=FREE" where %p is the buffer pointer in hex.
1127 ssize_t idx = dumpString.find("state=FREE");
1128 while (idx != -1) {
1129 ssize_t bufferPtrIdx = idx - 1;
1130 while (bufferPtrIdx > 0) {
1131 if (dumpString[bufferPtrIdx] == ':') {
1132 bufferPtrIdx++;
1133 break;
1134 }
1135 bufferPtrIdx--;
1136 }
1137 ASSERT_GT(bufferPtrIdx, 0) << "Can't parse queue dump to validate";
1138 ssize_t nullPtrIdx = dumpString.find("0x0]", bufferPtrIdx);
1139 ASSERT_EQ(bufferPtrIdx, nullPtrIdx) << "Free buffer not discarded";
1140 idx = dumpString.find("FREE", idx + 1);
1141 }
1142}
1143
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001144TEST_F(BufferQueueTest, TestBufferReplacedInQueueBuffer) {
1145 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -07001146 sp<MockConsumer> mc(new MockConsumer);
1147 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001148 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -07001149 ASSERT_EQ(OK,
1150 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001151 ASSERT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
1152
1153 int slot = BufferQueue::INVALID_BUFFER_SLOT;
1154 sp<Fence> fence = Fence::NO_FENCE;
1155 sp<GraphicBuffer> buffer = nullptr;
1156 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1157 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1158 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1159 BufferItem item{};
1160
1161 // Preallocate, dequeue, request, and cancel 2 buffers so we don't get
1162 // BUFFER_NEEDS_REALLOCATION below
1163 int slots[2] = {};
1164 ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(2));
1165 for (size_t i = 0; i < 2; ++i) {
Nolan Scobie9c427942023-05-01 16:41:28 -04001166 status_t result = mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0,
1167 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr);
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001168 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1169 ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
1170 }
1171 for (size_t i = 0; i < 2; ++i) {
1172 ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE));
1173 }
1174
1175 // Fill 2 buffers without consumer consuming them. Verify that all
1176 // queued buffer returns proper bufferReplaced flag
Nolan Scobie9c427942023-05-01 16:41:28 -04001177 ASSERT_EQ(OK,
1178 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1179 nullptr));
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001180 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1181 ASSERT_EQ(false, output.bufferReplaced);
Nolan Scobie9c427942023-05-01 16:41:28 -04001182 ASSERT_EQ(OK,
1183 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1184 nullptr));
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001185 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1186 ASSERT_EQ(true, output.bufferReplaced);
1187}
1188
Sungtak Lee1e7c09b2023-10-26 08:44:21 +00001189struct BufferDetachedListener : public BnProducerListener {
1190public:
1191 BufferDetachedListener() = default;
1192 virtual ~BufferDetachedListener() = default;
1193
1194 virtual void onBufferReleased() {}
1195 virtual bool needsReleaseNotify() { return true; }
1196 virtual void onBufferDetached(int slot) {
1197 mDetachedSlots.push_back(slot);
1198 }
1199 const std::vector<int>& getDetachedSlots() const { return mDetachedSlots; }
1200private:
1201 std::vector<int> mDetachedSlots;
1202};
1203
1204TEST_F(BufferQueueTest, TestConsumerDetachProducerListener) {
1205 createBufferQueue();
1206 sp<MockConsumer> mc(new MockConsumer);
1207 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
1208 IGraphicBufferProducer::QueueBufferOutput output;
1209 sp<BufferDetachedListener> pl(new BufferDetachedListener);
1210 ASSERT_EQ(OK, mProducer->connect(pl, NATIVE_WINDOW_API_CPU, true, &output));
1211 ASSERT_EQ(OK, mProducer->setDequeueTimeout(0));
1212 ASSERT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
1213
1214 sp<Fence> fence = Fence::NO_FENCE;
1215 sp<GraphicBuffer> buffer = nullptr;
1216 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1217 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1218 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1219
1220 int slots[2] = {};
1221 status_t result = OK;
1222 ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(2));
1223
1224 result = mProducer->dequeueBuffer(&slots[0], &fence, 0, 0, 0,
1225 GRALLOC_USAGE_SW_READ_RARELY, nullptr, nullptr);
1226 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1227 ASSERT_EQ(OK, mProducer->requestBuffer(slots[0], &buffer));
1228
1229 result = mProducer->dequeueBuffer(&slots[1], &fence, 0, 0, 0,
1230 GRALLOC_USAGE_SW_READ_RARELY, nullptr, nullptr);
1231 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1232 ASSERT_EQ(OK, mProducer->requestBuffer(slots[1], &buffer));
1233
1234 // Queue & detach one from two dequeued buffes.
1235 ASSERT_EQ(OK, mProducer->queueBuffer(slots[1], input, &output));
1236 BufferItem item{};
1237 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1238 ASSERT_EQ(OK, mConsumer->detachBuffer(item.mSlot));
1239
1240 // Check whether the slot from IProducerListener is same to the detached slot.
Siarhei Vishniakoubf98a572024-03-29 13:34:42 -07001241 ASSERT_EQ(pl->getDetachedSlots().size(), 1u);
Sungtak Lee1e7c09b2023-10-26 08:44:21 +00001242 ASSERT_EQ(pl->getDetachedSlots()[0], slots[1]);
1243
1244 // Dequeue another buffer.
1245 int slot;
1246 result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
1247 GRALLOC_USAGE_SW_READ_RARELY, nullptr, nullptr);
1248 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1249 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
1250
1251 // Dequeue should fail here, since we dequeued 3 buffers and one buffer was
1252 // detached from consumer(Two buffers are dequeued, and the current max
1253 // dequeued buffer count is two).
1254 result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
1255 GRALLOC_USAGE_SW_READ_RARELY, nullptr, nullptr);
1256 ASSERT_TRUE(result == WOULD_BLOCK || result == TIMED_OUT || result == INVALID_OPERATION);
1257}
1258
Dan Stozad4c6f992017-03-21 13:43:22 -07001259TEST_F(BufferQueueTest, TestStaleBufferHandleSentAfterDisconnect) {
1260 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -07001261 sp<MockConsumer> mc(new MockConsumer);
1262 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Dan Stozad4c6f992017-03-21 13:43:22 -07001263 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -07001264 sp<IProducerListener> fakeListener(new StubProducerListener);
1265 ASSERT_EQ(OK, mProducer->connect(fakeListener, NATIVE_WINDOW_API_CPU, true, &output));
Dan Stozad4c6f992017-03-21 13:43:22 -07001266
1267 int slot = BufferQueue::INVALID_BUFFER_SLOT;
1268 sp<Fence> fence = Fence::NO_FENCE;
1269 sp<GraphicBuffer> buffer = nullptr;
1270 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1271 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1272 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1273
1274 // Dequeue, request, and queue one buffer
Nolan Scobie9c427942023-05-01 16:41:28 -04001275 status_t result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
1276 nullptr, nullptr);
Dan Stozad4c6f992017-03-21 13:43:22 -07001277 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1278 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
1279 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1280
1281 // Acquire and release the buffer. Upon acquiring, the buffer handle should
1282 // be non-null since this is the first time we've acquired this slot.
1283 BufferItem item;
1284 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1285 ASSERT_EQ(slot, item.mSlot);
1286 ASSERT_NE(nullptr, item.mGraphicBuffer.get());
1287 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
1288 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
1289
1290 // Dequeue and queue the buffer again
Nolan Scobie9c427942023-05-01 16:41:28 -04001291 ASSERT_EQ(OK,
1292 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1293 nullptr));
Dan Stozad4c6f992017-03-21 13:43:22 -07001294 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1295
1296 // Acquire and release the buffer again. Upon acquiring, the buffer handle
1297 // should be null since this is not the first time we've acquired this slot.
1298 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1299 ASSERT_EQ(slot, item.mSlot);
1300 ASSERT_EQ(nullptr, item.mGraphicBuffer.get());
1301 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
1302 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
1303
1304 // Dequeue and queue the buffer again
Nolan Scobie9c427942023-05-01 16:41:28 -04001305 ASSERT_EQ(OK,
1306 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1307 nullptr));
Dan Stozad4c6f992017-03-21 13:43:22 -07001308 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1309
1310 // Disconnect the producer end. This should clear all of the slots and mark
1311 // the buffer in the queue as stale.
1312 ASSERT_EQ(OK, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
1313
1314 // Acquire the buffer again. Upon acquiring, the buffer handle should not be
1315 // null since the queued buffer should have been marked as stale, which
1316 // should trigger the BufferQueue to resend the buffer handle.
1317 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1318 ASSERT_EQ(slot, item.mSlot);
1319 ASSERT_NE(nullptr, item.mGraphicBuffer.get());
1320}
1321
Wonsik Kim3e198b22017-04-07 15:43:16 -07001322TEST_F(BufferQueueTest, TestProducerConnectDisconnect) {
1323 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -07001324 sp<MockConsumer> mc(new MockConsumer);
1325 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Wonsik Kim3e198b22017-04-07 15:43:16 -07001326 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -07001327 sp<IProducerListener> fakeListener(new StubProducerListener);
Wonsik Kim3e198b22017-04-07 15:43:16 -07001328 ASSERT_EQ(NO_INIT, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
Peiyong Lind8460c82020-07-28 16:04:22 -07001329 ASSERT_EQ(OK, mProducer->connect(fakeListener, NATIVE_WINDOW_API_CPU, true, &output));
1330 ASSERT_EQ(BAD_VALUE, mProducer->connect(fakeListener, NATIVE_WINDOW_API_MEDIA, true, &output));
Wonsik Kim3e198b22017-04-07 15:43:16 -07001331
1332 ASSERT_EQ(BAD_VALUE, mProducer->disconnect(NATIVE_WINDOW_API_MEDIA));
1333 ASSERT_EQ(OK, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
1334 ASSERT_EQ(NO_INIT, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
1335}
1336
Ady Abraham6cdd3fd2023-09-07 18:45:58 -07001337TEST_F(BufferQueueTest, TestBqSetFrameRateFlagBuildTimeIsSet) {
Ady Abraham107788e2023-10-17 12:31:08 -07001338 ASSERT_EQ(flags::bq_setframerate(), COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_SETFRAMERATE));
Ady Abraham6cdd3fd2023-09-07 18:45:58 -07001339}
1340
1341struct BufferItemConsumerSetFrameRateListener : public BufferItemConsumer {
1342 BufferItemConsumerSetFrameRateListener(const sp<IGraphicBufferConsumer>& consumer)
1343 : BufferItemConsumer(consumer, GRALLOC_USAGE_SW_READ_OFTEN, 1) {}
1344
1345 MOCK_METHOD(void, onSetFrameRate, (float, int8_t, int8_t), (override));
1346};
1347
1348TEST_F(BufferQueueTest, TestSetFrameRate) {
1349 sp<IGraphicBufferProducer> producer;
1350 sp<IGraphicBufferConsumer> consumer;
1351 BufferQueue::createBufferQueue(&producer, &consumer);
1352
1353 sp<BufferItemConsumerSetFrameRateListener> bufferConsumer =
1354 sp<BufferItemConsumerSetFrameRateListener>::make(consumer);
1355
1356 EXPECT_CALL(*bufferConsumer, onSetFrameRate(12.34f, 1, 0)).Times(1);
1357 producer->setFrameRate(12.34f, 1, 0);
1358}
1359
John Reck12daff92023-07-28 16:36:27 -04001360class Latch {
1361public:
1362 explicit Latch(int expected) : mExpected(expected) {}
1363 Latch(const Latch&) = delete;
1364 Latch& operator=(const Latch&) = delete;
1365
1366 void CountDown() {
1367 std::unique_lock<std::mutex> lock(mLock);
1368 mExpected--;
1369 if (mExpected <= 0) {
1370 mCV.notify_all();
1371 }
1372 }
1373
1374 void Wait() {
1375 std::unique_lock<std::mutex> lock(mLock);
1376 mCV.wait(lock, [&] { return mExpected == 0; });
1377 }
1378
1379private:
1380 int mExpected;
1381 std::mutex mLock;
1382 std::condition_variable mCV;
1383};
1384
1385struct OneshotOnDequeuedListener final : public BufferItemConsumer::FrameAvailableListener {
1386 OneshotOnDequeuedListener(std::function<void()>&& oneshot)
1387 : mOneshotRunnable(std::move(oneshot)) {}
1388
1389 std::function<void()> mOneshotRunnable;
1390
1391 void run() {
1392 if (mOneshotRunnable) {
1393 mOneshotRunnable();
1394 mOneshotRunnable = nullptr;
1395 }
1396 }
1397
1398 void onFrameDequeued(const uint64_t) override { run(); }
1399
1400 void onFrameAvailable(const BufferItem&) override {}
1401};
1402
1403// See b/270004534
1404TEST(BufferQueueThreading, TestProducerDequeueConsumerDestroy) {
1405 sp<IGraphicBufferProducer> producer;
1406 sp<IGraphicBufferConsumer> consumer;
1407 BufferQueue::createBufferQueue(&producer, &consumer);
1408
1409 sp<BufferItemConsumer> bufferConsumer =
1410 sp<BufferItemConsumer>::make(consumer, GRALLOC_USAGE_SW_READ_OFTEN, 2);
1411 ASSERT_NE(nullptr, bufferConsumer.get());
1412 sp<Surface> surface = sp<Surface>::make(producer);
1413 native_window_set_buffers_format(surface.get(), PIXEL_FORMAT_RGBA_8888);
1414 native_window_set_buffers_dimensions(surface.get(), 100, 100);
1415
1416 Latch triggerDisconnect(1);
1417 Latch resumeCallback(1);
1418 auto luckyListener = sp<OneshotOnDequeuedListener>::make([&]() {
1419 triggerDisconnect.CountDown();
1420 resumeCallback.Wait();
1421 });
1422 bufferConsumer->setFrameAvailableListener(luckyListener);
1423
1424 std::future<void> disconnecter = std::async(std::launch::async, [&]() {
1425 triggerDisconnect.Wait();
1426 luckyListener = nullptr;
1427 bufferConsumer = nullptr;
1428 resumeCallback.CountDown();
1429 });
1430
1431 std::future<void> render = std::async(std::launch::async, [=]() {
1432 ANativeWindow_Buffer buffer;
1433 surface->lock(&buffer, nullptr);
1434 surface->unlockAndPost();
1435 });
1436
1437 ASSERT_EQ(std::future_status::ready, render.wait_for(1s));
1438 EXPECT_EQ(nullptr, luckyListener.get());
1439 EXPECT_EQ(nullptr, bufferConsumer.get());
1440}
1441
Jamie Gennis9e75ddd2012-08-31 15:32:45 -07001442} // namespace android