blob: b026e640aa7b8c8798fad17c20abe576c8ded79d [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>
Brian Lindahl628cff42024-10-30 11:50:28 -060030#include <ui/PictureProfileHandle.h>
Jamie Gennis9e75ddd2012-08-31 15:32:45 -070031
John Reckdb164ff2024-04-03 16:59:28 -040032#include <android-base/properties.h>
33
Dan Stoza1a0b8612014-03-20 15:36:31 -070034#include <binder/IPCThreadState.h>
Dan Stoza9f3053d2014-03-06 15:14:33 -080035#include <binder/IServiceManager.h>
Dan Stoza1a0b8612014-03-20 15:36:31 -070036#include <binder/ProcessState.h>
Dan Stozaf0eaf252014-03-21 13:05:51 -070037
38#include <utils/String8.h>
39#include <utils/threads.h>
40
Mathias Agopian6a3c05b2017-04-27 20:06:55 -070041#include <system/window.h>
42
Ady Abraham6cdd3fd2023-09-07 18:45:58 -070043#include <gmock/gmock.h>
Dan Stozaf0eaf252014-03-21 13:05:51 -070044#include <gtest/gtest.h>
Jamie Gennis9e75ddd2012-08-31 15:32:45 -070045
John Reck12daff92023-07-28 16:36:27 -040046#include <future>
Dan Stozae77c7662016-05-13 11:37:28 -070047#include <thread>
48
Ady Abraham6cdd3fd2023-09-07 18:45:58 -070049#include <com_android_graphics_libgui_flags.h>
50
Dan Stozae77c7662016-05-13 11:37:28 -070051using namespace std::chrono_literals;
52
John Reckdb164ff2024-04-03 16:59:28 -040053static bool IsCuttlefish() {
54 return ::android::base::GetProperty("ro.product.board", "") == "cutf";
55}
56
Jamie Gennis9e75ddd2012-08-31 15:32:45 -070057namespace android {
Ady Abraham6cdd3fd2023-09-07 18:45:58 -070058using namespace com::android::graphics::libgui;
Jamie Gennis9e75ddd2012-08-31 15:32:45 -070059
60class BufferQueueTest : public ::testing::Test {
Dan Stoza9f3053d2014-03-06 15:14:33 -080061
62public:
Jamie Gennis9e75ddd2012-08-31 15:32:45 -070063protected:
Igor Murashkin7ea777f2013-11-18 16:58:36 -080064 void GetMinUndequeuedBufferCount(int* bufferCount) {
Yi Konga03e0442018-07-17 11:16:57 -070065 ASSERT_TRUE(bufferCount != nullptr);
Dan Stoza9f3053d2014-03-06 15:14:33 -080066 ASSERT_EQ(OK, mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
67 bufferCount));
68 ASSERT_GE(*bufferCount, 0);
Igor Murashkin7ea777f2013-11-18 16:58:36 -080069 }
70
Dan Stoza1a0b8612014-03-20 15:36:31 -070071 void createBufferQueue() {
72 BufferQueue::createBufferQueue(&mProducer, &mConsumer);
73 }
Jamie Gennis9e75ddd2012-08-31 15:32:45 -070074
Pablo Ceballosff95aab2016-01-13 17:09:58 -080075 void testBufferItem(const IGraphicBufferProducer::QueueBufferInput& input,
76 const BufferItem& item) {
77 int64_t timestamp;
78 bool isAutoTimestamp;
79 android_dataspace dataSpace;
80 Rect crop;
81 int scalingMode;
82 uint32_t transform;
83 sp<Fence> fence;
84
85 input.deflate(&timestamp, &isAutoTimestamp, &dataSpace, &crop,
Yi Konga03e0442018-07-17 11:16:57 -070086 &scalingMode, &transform, &fence, nullptr);
Pablo Ceballosff95aab2016-01-13 17:09:58 -080087 ASSERT_EQ(timestamp, item.mTimestamp);
88 ASSERT_EQ(isAutoTimestamp, item.mIsAutoTimestamp);
89 ASSERT_EQ(dataSpace, item.mDataSpace);
90 ASSERT_EQ(crop, item.mCrop);
91 ASSERT_EQ(static_cast<uint32_t>(scalingMode), item.mScalingMode);
92 ASSERT_EQ(transform, item.mTransform);
93 ASSERT_EQ(fence, item.mFence);
94 }
95
Dan Stoza1a0b8612014-03-20 15:36:31 -070096 sp<IGraphicBufferProducer> mProducer;
97 sp<IGraphicBufferConsumer> mConsumer;
98};
Dan Stoza9f3053d2014-03-06 15:14:33 -080099
Dan Stozaf8cebe52015-04-20 12:09:38 -0700100static const uint32_t TEST_DATA = 0x12345678u;
101
Dan Stoza1a0b8612014-03-20 15:36:31 -0700102// XXX: Tests that fork a process to hold the BufferQueue must run before tests
103// that use a local BufferQueue, or else Binder will get unhappy
Kalle Raita88752d72017-03-27 14:11:54 -0700104//
105// In one instance this was a crash in the createBufferQueue where the
106// binder call to create a buffer allocator apparently got garbage back.
107// See b/36592665.
108TEST_F(BufferQueueTest, DISABLED_BufferQueueInAnotherProcess) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700109 const String16 PRODUCER_NAME = String16("BQTestProducer");
110 const String16 CONSUMER_NAME = String16("BQTestConsumer");
111
112 pid_t forkPid = fork();
113 ASSERT_NE(forkPid, -1);
114
115 if (forkPid == 0) {
116 // Child process
Dan Stozab3d0bdf2014-04-07 16:33:59 -0700117 sp<IGraphicBufferProducer> producer;
118 sp<IGraphicBufferConsumer> consumer;
Dan Stoza1a0b8612014-03-20 15:36:31 -0700119 BufferQueue::createBufferQueue(&producer, &consumer);
120 sp<IServiceManager> serviceManager = defaultServiceManager();
Marco Nelissen097ca272014-11-14 08:01:01 -0800121 serviceManager->addService(PRODUCER_NAME, IInterface::asBinder(producer));
122 serviceManager->addService(CONSUMER_NAME, IInterface::asBinder(consumer));
Dan Stoza1a0b8612014-03-20 15:36:31 -0700123 ProcessState::self()->startThreadPool();
124 IPCThreadState::self()->joinThreadPool();
125 LOG_ALWAYS_FATAL("Shouldn't be here");
126 }
127
128 sp<IServiceManager> serviceManager = defaultServiceManager();
Siarhei Vishniakoubf98a572024-03-29 13:34:42 -0700129 sp<IBinder> binderProducer = serviceManager->waitForService(PRODUCER_NAME);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700130 mProducer = interface_cast<IGraphicBufferProducer>(binderProducer);
Yi Konga03e0442018-07-17 11:16:57 -0700131 EXPECT_TRUE(mProducer != nullptr);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700132 sp<IBinder> binderConsumer =
133 serviceManager->getService(CONSUMER_NAME);
134 mConsumer = interface_cast<IGraphicBufferConsumer>(binderConsumer);
Yi Konga03e0442018-07-17 11:16:57 -0700135 EXPECT_TRUE(mConsumer != nullptr);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700136
Peiyong Lind8460c82020-07-28 16:04:22 -0700137 sp<MockConsumer> mc(new MockConsumer);
138 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Dan Stoza1a0b8612014-03-20 15:36:31 -0700139 IGraphicBufferProducer::QueueBufferOutput output;
140 ASSERT_EQ(OK,
Yi Konga03e0442018-07-17 11:16:57 -0700141 mProducer->connect(nullptr, NATIVE_WINDOW_API_CPU, false, &output));
Dan Stoza1a0b8612014-03-20 15:36:31 -0700142
143 int slot;
144 sp<Fence> fence;
145 sp<GraphicBuffer> buffer;
146 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600147 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
148 nullptr, nullptr));
Dan Stoza1a0b8612014-03-20 15:36:31 -0700149 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
150
151 uint32_t* dataIn;
152 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
153 reinterpret_cast<void**>(&dataIn)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700154 *dataIn = TEST_DATA;
Dan Stoza1a0b8612014-03-20 15:36:31 -0700155 ASSERT_EQ(OK, buffer->unlock());
156
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800157 IGraphicBufferProducer::QueueBufferInput input(0, false,
158 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700159 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700160 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
161
Dan Stozacf3834d2015-03-11 14:04:22 -0700162 BufferItem item;
Dan Stoza1a0b8612014-03-20 15:36:31 -0700163 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
164
165 uint32_t* dataOut;
166 ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
167 reinterpret_cast<void**>(&dataOut)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700168 ASSERT_EQ(*dataOut, TEST_DATA);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700169 ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
170}
171
silence_dogoode9d092a2019-06-19 16:14:53 -0700172TEST_F(BufferQueueTest, GetMaxBufferCountInQueueBufferOutput_Succeeds) {
173 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700174 sp<MockConsumer> mc(new MockConsumer);
175 mConsumer->consumerConnect(mc, false);
silence_dogoode9d092a2019-06-19 16:14:53 -0700176 int bufferCount = 50;
177 mConsumer->setMaxBufferCount(bufferCount);
178
179 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700180 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output);
silence_dogoode9d092a2019-06-19 16:14:53 -0700181 ASSERT_EQ(output.maxBufferCount, bufferCount);
182}
183
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700184TEST_F(BufferQueueTest, AcquireBuffer_ExceedsMaxAcquireCount_Fails) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700185 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700186 sp<MockConsumer> mc(new MockConsumer);
187 mConsumer->consumerConnect(mc, false);
Andy McFadden2adaf042012-12-18 09:49:45 -0800188 IGraphicBufferProducer::QueueBufferOutput qbo;
Peiyong Lind8460c82020-07-28 16:04:22 -0700189 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &qbo);
Pablo Ceballosfa455352015-08-12 17:47:47 -0700190 mProducer->setMaxDequeuedBufferCount(3);
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700191
192 int slot;
193 sp<Fence> fence;
194 sp<GraphicBuffer> buf;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800195 IGraphicBufferProducer::QueueBufferInput qbi(0, false,
196 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700197 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Dan Stozacf3834d2015-03-11 14:04:22 -0700198 BufferItem item;
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700199
200 for (int i = 0; i < 2; i++) {
Andy McFadden2adaf042012-12-18 09:49:45 -0800201 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600202 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
203 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800204 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
205 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
206 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700207 }
208
Andy McFadden2adaf042012-12-18 09:49:45 -0800209 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600210 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
211 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800212 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
213 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700214
215 // Acquire the third buffer, which should fail.
Dan Stoza9f3053d2014-03-06 15:14:33 -0800216 ASSERT_EQ(INVALID_OPERATION, mConsumer->acquireBuffer(&item, 0));
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700217}
218
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700219TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithIllegalValues_ReturnsError) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700220 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700221 sp<MockConsumer> mc(new MockConsumer);
222 mConsumer->consumerConnect(mc, false);
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700223
Pablo Ceballos72daab62015-12-07 16:38:43 -0800224 EXPECT_EQ(OK, mConsumer->setMaxBufferCount(10));
225 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(10));
226
227 IGraphicBufferProducer::QueueBufferOutput qbo;
Peiyong Lind8460c82020-07-28 16:04:22 -0700228 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &qbo);
Pablo Ceballos72daab62015-12-07 16:38:43 -0800229 mProducer->setMaxDequeuedBufferCount(3);
230
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800231 int minBufferCount;
232 ASSERT_NO_FATAL_FAILURE(GetMinUndequeuedBufferCount(&minBufferCount));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800233 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(
234 minBufferCount - 1));
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800235
Dan Stoza9f3053d2014-03-06 15:14:33 -0800236 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(0));
237 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(-3));
238 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700239 BufferQueue::MAX_MAX_ACQUIRED_BUFFERS+1));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800240 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(100));
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700241
Pablo Ceballos72daab62015-12-07 16:38:43 -0800242 int slot;
243 sp<Fence> fence;
244 sp<GraphicBuffer> buf;
245 IGraphicBufferProducer::QueueBufferInput qbi(0, false,
246 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
247 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
248 BufferItem item;
249 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(3));
250 for (int i = 0; i < 3; i++) {
251 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600252 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
253 nullptr, nullptr));
Pablo Ceballos72daab62015-12-07 16:38:43 -0800254 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
255 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
256 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
257 }
258
259 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(2));
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700260}
261
262TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithLegalValues_Succeeds) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700263 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700264 sp<MockConsumer> mc(new MockConsumer);
265 mConsumer->consumerConnect(mc, false);
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700266
Pablo Ceballos72daab62015-12-07 16:38:43 -0800267 IGraphicBufferProducer::QueueBufferOutput qbo;
Peiyong Lind8460c82020-07-28 16:04:22 -0700268 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &qbo);
Pablo Ceballos72daab62015-12-07 16:38:43 -0800269 mProducer->setMaxDequeuedBufferCount(2);
270
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800271 int minBufferCount;
272 ASSERT_NO_FATAL_FAILURE(GetMinUndequeuedBufferCount(&minBufferCount));
273
Dan Stoza9f3053d2014-03-06 15:14:33 -0800274 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
275 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(2));
276 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(minBufferCount));
Pablo Ceballos72daab62015-12-07 16:38:43 -0800277
278 int slot;
279 sp<Fence> fence;
280 sp<GraphicBuffer> buf;
281 IGraphicBufferProducer::QueueBufferInput qbi(0, false,
282 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
283 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
284 BufferItem item;
285
286 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600287 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
288 nullptr, nullptr));
Pablo Ceballos72daab62015-12-07 16:38:43 -0800289 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
290 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
291 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
292
293 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(3));
294
295 for (int i = 0; i < 2; i++) {
296 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600297 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
298 nullptr, nullptr));
Pablo Ceballos72daab62015-12-07 16:38:43 -0800299 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
300 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
301 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
302 }
303
Dan Stoza9f3053d2014-03-06 15:14:33 -0800304 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700305 BufferQueue::MAX_MAX_ACQUIRED_BUFFERS));
306}
307
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700308TEST_F(BufferQueueTest, SetMaxBufferCountWithLegalValues_Succeeds) {
309 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700310 sp<MockConsumer> mc(new MockConsumer);
311 mConsumer->consumerConnect(mc, false);
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700312
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700313 // Test shared buffer mode
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700314 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
315}
316
317TEST_F(BufferQueueTest, SetMaxBufferCountWithIllegalValues_ReturnsError) {
318 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700319 sp<MockConsumer> mc(new MockConsumer);
320 mConsumer->consumerConnect(mc, false);
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700321
322 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(0));
323 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(
324 BufferQueue::NUM_BUFFER_SLOTS + 1));
325
326 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(5));
327 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(3));
328}
329
Dan Stoza9f3053d2014-03-06 15:14:33 -0800330TEST_F(BufferQueueTest, DetachAndReattachOnProducerSide) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700331 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700332 sp<MockConsumer> mc(new MockConsumer);
333 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800334 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700335 ASSERT_EQ(OK,
336 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800337
338 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(-1)); // Index too low
339 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(
340 BufferQueueDefs::NUM_BUFFER_SLOTS)); // Index too high
341 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(0)); // Not dequeued
342
343 int slot;
344 sp<Fence> fence;
345 sp<GraphicBuffer> buffer;
346 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600347 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
348 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800349 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(slot)); // Not requested
350 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
351 ASSERT_EQ(OK, mProducer->detachBuffer(slot));
352 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(slot)); // Not dequeued
353
354 sp<GraphicBuffer> safeToClobberBuffer;
355 // Can no longer request buffer from this slot
356 ASSERT_EQ(BAD_VALUE, mProducer->requestBuffer(slot, &safeToClobberBuffer));
357
358 uint32_t* dataIn;
359 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
360 reinterpret_cast<void**>(&dataIn)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700361 *dataIn = TEST_DATA;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800362 ASSERT_EQ(OK, buffer->unlock());
363
364 int newSlot;
Yi Konga03e0442018-07-17 11:16:57 -0700365 ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(nullptr, safeToClobberBuffer));
366 ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(&newSlot, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800367
368 ASSERT_EQ(OK, mProducer->attachBuffer(&newSlot, buffer));
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800369 IGraphicBufferProducer::QueueBufferInput input(0, false,
370 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700371 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800372 ASSERT_EQ(OK, mProducer->queueBuffer(newSlot, input, &output));
373
Dan Stozacf3834d2015-03-11 14:04:22 -0700374 BufferItem item;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800375 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
376
377 uint32_t* dataOut;
378 ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
379 reinterpret_cast<void**>(&dataOut)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700380 ASSERT_EQ(*dataOut, TEST_DATA);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700381 ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
Dan Stoza9f3053d2014-03-06 15:14:33 -0800382}
383
384TEST_F(BufferQueueTest, DetachAndReattachOnConsumerSide) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700385 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700386 sp<MockConsumer> mc(new MockConsumer);
387 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800388 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700389 ASSERT_EQ(OK,
390 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800391
392 int slot;
393 sp<Fence> fence;
394 sp<GraphicBuffer> buffer;
395 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600396 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
397 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800398 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800399 IGraphicBufferProducer::QueueBufferInput input(0, false,
400 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700401 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800402 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
403
404 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(-1)); // Index too low
405 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(
406 BufferQueueDefs::NUM_BUFFER_SLOTS)); // Index too high
407 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(0)); // Not acquired
408
Dan Stozacf3834d2015-03-11 14:04:22 -0700409 BufferItem item;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800410 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
411
Pablo Ceballos47650f42015-08-04 16:38:17 -0700412 ASSERT_EQ(OK, mConsumer->detachBuffer(item.mSlot));
413 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(item.mSlot)); // Not acquired
Dan Stoza9f3053d2014-03-06 15:14:33 -0800414
415 uint32_t* dataIn;
416 ASSERT_EQ(OK, item.mGraphicBuffer->lock(
417 GraphicBuffer::USAGE_SW_WRITE_OFTEN,
418 reinterpret_cast<void**>(&dataIn)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700419 *dataIn = TEST_DATA;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800420 ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
421
422 int newSlot;
423 sp<GraphicBuffer> safeToClobberBuffer;
Yi Konga03e0442018-07-17 11:16:57 -0700424 ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(nullptr, safeToClobberBuffer));
425 ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(&newSlot, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800426 ASSERT_EQ(OK, mConsumer->attachBuffer(&newSlot, item.mGraphicBuffer));
427
Dan Stoza99b18b42014-03-28 15:34:33 -0700428 ASSERT_EQ(OK, mConsumer->releaseBuffer(newSlot, 0, EGL_NO_DISPLAY,
Dan Stoza9f3053d2014-03-06 15:14:33 -0800429 EGL_NO_SYNC_KHR, Fence::NO_FENCE));
430
431 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600432 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
433 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800434 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
435
436 uint32_t* dataOut;
437 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
438 reinterpret_cast<void**>(&dataOut)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700439 ASSERT_EQ(*dataOut, TEST_DATA);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700440 ASSERT_EQ(OK, buffer->unlock());
Dan Stoza9f3053d2014-03-06 15:14:33 -0800441}
442
443TEST_F(BufferQueueTest, MoveFromConsumerToProducer) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700444 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700445 sp<MockConsumer> mc(new MockConsumer);
446 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800447 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700448 ASSERT_EQ(OK,
449 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800450
451 int slot;
452 sp<Fence> fence;
453 sp<GraphicBuffer> buffer;
454 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600455 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
456 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800457 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
458
459 uint32_t* dataIn;
460 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
461 reinterpret_cast<void**>(&dataIn)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700462 *dataIn = TEST_DATA;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800463 ASSERT_EQ(OK, buffer->unlock());
464
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800465 IGraphicBufferProducer::QueueBufferInput input(0, false,
466 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700467 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800468 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
469
Dan Stozacf3834d2015-03-11 14:04:22 -0700470 BufferItem item;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800471 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
Pablo Ceballos47650f42015-08-04 16:38:17 -0700472 ASSERT_EQ(OK, mConsumer->detachBuffer(item.mSlot));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800473
474 int newSlot;
475 ASSERT_EQ(OK, mProducer->attachBuffer(&newSlot, item.mGraphicBuffer));
476 ASSERT_EQ(OK, mProducer->queueBuffer(newSlot, input, &output));
477 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
478
479 uint32_t* dataOut;
480 ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
481 reinterpret_cast<void**>(&dataOut)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700482 ASSERT_EQ(*dataOut, TEST_DATA);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700483 ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
Dan Stoza9f3053d2014-03-06 15:14:33 -0800484}
485
Dan Stoza9de72932015-04-16 17:28:43 -0700486TEST_F(BufferQueueTest, TestDisallowingAllocation) {
487 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700488 sp<MockConsumer> mc(new MockConsumer);
489 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Dan Stoza9de72932015-04-16 17:28:43 -0700490 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700491 ASSERT_EQ(OK,
492 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Dan Stoza9de72932015-04-16 17:28:43 -0700493
494 static const uint32_t WIDTH = 320;
495 static const uint32_t HEIGHT = 240;
496
497 ASSERT_EQ(OK, mConsumer->setDefaultBufferSize(WIDTH, HEIGHT));
498
499 int slot;
500 sp<Fence> fence;
501 sp<GraphicBuffer> buffer;
502 // This should return an error since it would require an allocation
503 ASSERT_EQ(OK, mProducer->allowAllocation(false));
Ian Elliottd11b0442017-07-18 11:05:49 -0600504 ASSERT_EQ(WOULD_BLOCK,
505 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
506 nullptr, nullptr));
Dan Stoza9de72932015-04-16 17:28:43 -0700507
508 // This should succeed, now that we've lifted the prohibition
509 ASSERT_EQ(OK, mProducer->allowAllocation(true));
510 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600511 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
512 nullptr, nullptr));
Dan Stoza9de72932015-04-16 17:28:43 -0700513
514 // Release the previous buffer back to the BufferQueue
515 mProducer->cancelBuffer(slot, fence);
516
517 // This should fail since we're requesting a different size
518 ASSERT_EQ(OK, mProducer->allowAllocation(false));
Ian Elliottd11b0442017-07-18 11:05:49 -0600519 ASSERT_EQ(WOULD_BLOCK,
520 mProducer->dequeueBuffer(&slot, &fence, WIDTH * 2, HEIGHT * 2, 0,
521 GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr, nullptr));
Dan Stoza9de72932015-04-16 17:28:43 -0700522}
523
Dan Stoza812ed062015-06-02 15:45:22 -0700524TEST_F(BufferQueueTest, TestGenerationNumbers) {
525 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700526 sp<MockConsumer> mc(new MockConsumer);
527 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Dan Stoza812ed062015-06-02 15:45:22 -0700528 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700529 ASSERT_EQ(OK,
530 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Dan Stoza812ed062015-06-02 15:45:22 -0700531
532 ASSERT_EQ(OK, mProducer->setGenerationNumber(1));
533
534 // Get one buffer to play with
535 int slot;
536 sp<Fence> fence;
537 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Nolan Scobie9c427942023-05-01 16:41:28 -0400538 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
539 nullptr));
Dan Stoza812ed062015-06-02 15:45:22 -0700540
541 sp<GraphicBuffer> buffer;
542 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
543
544 // Ensure that the generation number we set propagates to allocated buffers
545 ASSERT_EQ(1U, buffer->getGenerationNumber());
546
547 ASSERT_EQ(OK, mProducer->detachBuffer(slot));
548
549 ASSERT_EQ(OK, mProducer->setGenerationNumber(2));
550
551 // These should fail, since we've changed the generation number on the queue
552 int outSlot;
553 ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(&outSlot, buffer));
554 ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(&outSlot, buffer));
555
556 buffer->setGenerationNumber(2);
557
558 // This should succeed now that we've changed the buffer's generation number
559 ASSERT_EQ(OK, mProducer->attachBuffer(&outSlot, buffer));
560
561 ASSERT_EQ(OK, mProducer->detachBuffer(outSlot));
562
563 // This should also succeed with the new generation number
564 ASSERT_EQ(OK, mConsumer->attachBuffer(&outSlot, buffer));
565}
566
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700567TEST_F(BufferQueueTest, TestSharedBufferModeWithoutAutoRefresh) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700568 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700569 sp<MockConsumer> mc(new MockConsumer);
570 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700571 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700572 ASSERT_EQ(OK,
573 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700574
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700575 ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700576
577 // Get a buffer
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700578 int sharedSlot;
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700579 sp<Fence> fence;
580 sp<GraphicBuffer> buffer;
581 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Nolan Scobie9c427942023-05-01 16:41:28 -0400582 mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
583 nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700584 ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700585
586 // Queue the buffer
587 IGraphicBufferProducer::QueueBufferInput input(0, false,
588 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
589 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700590 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700591
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800592 // Repeatedly queue and dequeue a buffer from the producer side, it should
593 // always return the same one. And we won't run out of buffers because it's
594 // always the same one and because async mode gets enabled.
595 int slot;
596 for (int i = 0; i < 5; i++) {
Nolan Scobie9c427942023-05-01 16:41:28 -0400597 ASSERT_EQ(OK,
598 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
599 nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700600 ASSERT_EQ(sharedSlot, slot);
601 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800602 }
603
604 // acquire the buffer
605 BufferItem item;
606 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700607 ASSERT_EQ(sharedSlot, item.mSlot);
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800608 testBufferItem(input, item);
609 ASSERT_EQ(true, item.mQueuedBuffer);
610 ASSERT_EQ(false, item.mAutoRefresh);
611
612 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
613 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
614
615 // attempt to acquire a second time should return no buffer available
616 ASSERT_EQ(IGraphicBufferConsumer::NO_BUFFER_AVAILABLE,
617 mConsumer->acquireBuffer(&item, 0));
618}
619
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700620TEST_F(BufferQueueTest, TestSharedBufferModeWithAutoRefresh) {
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800621 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700622 sp<MockConsumer> mc(new MockConsumer);
623 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800624 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700625 ASSERT_EQ(OK,
626 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800627
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700628 ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800629 ASSERT_EQ(OK, mProducer->setAutoRefresh(true));
630
631 // Get a buffer
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700632 int sharedSlot;
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800633 sp<Fence> fence;
634 sp<GraphicBuffer> buffer;
635 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Nolan Scobie9c427942023-05-01 16:41:28 -0400636 mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
637 nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700638 ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800639
640 // Queue the buffer
641 IGraphicBufferProducer::QueueBufferInput input(0, false,
642 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
643 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700644 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800645
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700646 // Repeatedly acquire and release a buffer from the consumer side, it should
647 // always return the same one.
648 BufferItem item;
649 for (int i = 0; i < 5; i++) {
650 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700651 ASSERT_EQ(sharedSlot, item.mSlot);
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800652 testBufferItem(input, item);
653 ASSERT_EQ(i == 0, item.mQueuedBuffer);
654 ASSERT_EQ(true, item.mAutoRefresh);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700655
656 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
657 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
658 }
659
660 // Repeatedly queue and dequeue a buffer from the producer side, it should
661 // always return the same one.
662 int slot;
663 for (int i = 0; i < 5; i++) {
Nolan Scobie9c427942023-05-01 16:41:28 -0400664 ASSERT_EQ(OK,
665 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
666 nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700667 ASSERT_EQ(sharedSlot, slot);
668 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700669 }
670
671 // Repeatedly acquire and release a buffer from the consumer side, it should
672 // always return the same one. First grabbing them from the queue and then
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700673 // when the queue is empty, returning the shared buffer.
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700674 for (int i = 0; i < 10; i++) {
675 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700676 ASSERT_EQ(sharedSlot, item.mSlot);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700677 ASSERT_EQ(0, item.mTimestamp);
678 ASSERT_EQ(false, item.mIsAutoTimestamp);
679 ASSERT_EQ(HAL_DATASPACE_UNKNOWN, item.mDataSpace);
680 ASSERT_EQ(Rect(0, 0, 1, 1), item.mCrop);
681 ASSERT_EQ(NATIVE_WINDOW_SCALING_MODE_FREEZE, item.mScalingMode);
Dan Stoza5ecfb682016-01-04 17:01:02 -0800682 ASSERT_EQ(0u, item.mTransform);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700683 ASSERT_EQ(Fence::NO_FENCE, item.mFence);
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800684 ASSERT_EQ(i == 0, item.mQueuedBuffer);
685 ASSERT_EQ(true, item.mAutoRefresh);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700686
687 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
688 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
689 }
690}
691
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700692TEST_F(BufferQueueTest, TestSharedBufferModeUsingAlreadyDequeuedBuffer) {
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700693 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700694 sp<MockConsumer> mc(new MockConsumer);
695 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700696 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700697 ASSERT_EQ(OK,
698 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700699
700 // Dequeue a buffer
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700701 int sharedSlot;
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700702 sp<Fence> fence;
703 sp<GraphicBuffer> buffer;
704 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Nolan Scobie9c427942023-05-01 16:41:28 -0400705 mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
706 nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700707 ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700708
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700709 // Enable shared buffer mode
710 ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700711
712 // Queue the buffer
713 IGraphicBufferProducer::QueueBufferInput input(0, false,
714 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
715 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700716 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700717
718 // Repeatedly queue and dequeue a buffer from the producer side, it should
719 // always return the same one. And we won't run out of buffers because it's
720 // always the same one and because async mode gets enabled.
721 int slot;
722 for (int i = 0; i < 5; i++) {
Nolan Scobie9c427942023-05-01 16:41:28 -0400723 ASSERT_EQ(OK,
724 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
725 nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700726 ASSERT_EQ(sharedSlot, slot);
727 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700728 }
729
730 // acquire the buffer
731 BufferItem item;
732 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700733 ASSERT_EQ(sharedSlot, item.mSlot);
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700734 testBufferItem(input, item);
735 ASSERT_EQ(true, item.mQueuedBuffer);
736 ASSERT_EQ(false, item.mAutoRefresh);
737
738 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
739 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
740
741 // attempt to acquire a second time should return no buffer available
742 ASSERT_EQ(IGraphicBufferConsumer::NO_BUFFER_AVAILABLE,
743 mConsumer->acquireBuffer(&item, 0));
744}
745
Dan Stoza127fc632015-06-30 13:43:32 -0700746TEST_F(BufferQueueTest, TestTimeouts) {
747 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700748 sp<MockConsumer> mc(new MockConsumer);
749 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Dan Stoza127fc632015-06-30 13:43:32 -0700750 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700751 ASSERT_EQ(OK,
752 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Dan Stoza127fc632015-06-30 13:43:32 -0700753
754 // Fill up the queue. Since the controlledByApp flags are set to true, this
755 // queue should be in non-blocking mode, and we should be recycling the same
756 // two buffers
757 for (int i = 0; i < 5; ++i) {
758 int slot = BufferQueue::INVALID_BUFFER_SLOT;
759 sp<Fence> fence = Fence::NO_FENCE;
Nolan Scobie9c427942023-05-01 16:41:28 -0400760 auto result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
761 nullptr, nullptr);
Dan Stoza127fc632015-06-30 13:43:32 -0700762 if (i < 2) {
763 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
764 result);
765 } else {
766 ASSERT_EQ(OK, result);
767 }
768 sp<GraphicBuffer> buffer;
769 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
770 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
771 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
772 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
773 IGraphicBufferProducer::QueueBufferOutput output{};
774 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
775 }
776
777 const auto TIMEOUT = ms2ns(250);
778 mProducer->setDequeueTimeout(TIMEOUT);
779
780 // Setting a timeout will change the BufferQueue into blocking mode (with
781 // one droppable buffer in the queue and one free from the previous
782 // dequeue/queues), so dequeue and queue two more buffers: one to replace
783 // the current droppable buffer, and a second to max out the buffer count
784 sp<GraphicBuffer> buffer; // Save a buffer to attach later
785 for (int i = 0; i < 2; ++i) {
786 int slot = BufferQueue::INVALID_BUFFER_SLOT;
787 sp<Fence> fence = Fence::NO_FENCE;
Nolan Scobie9c427942023-05-01 16:41:28 -0400788 ASSERT_EQ(OK,
789 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
790 nullptr, nullptr));
Dan Stoza127fc632015-06-30 13:43:32 -0700791 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
792 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
793 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
794 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
795 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
796 }
797
798 int slot = BufferQueue::INVALID_BUFFER_SLOT;
799 sp<Fence> fence = Fence::NO_FENCE;
800 auto startTime = systemTime();
Nolan Scobie9c427942023-05-01 16:41:28 -0400801 ASSERT_EQ(TIMED_OUT,
802 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
803 nullptr));
Dan Stoza127fc632015-06-30 13:43:32 -0700804 ASSERT_GE(systemTime() - startTime, TIMEOUT);
805
806 // We're technically attaching the same buffer multiple times (since we
807 // queued it previously), but that doesn't matter for this test
808 startTime = systemTime();
809 ASSERT_EQ(TIMED_OUT, mProducer->attachBuffer(&slot, buffer));
810 ASSERT_GE(systemTime() - startTime, TIMEOUT);
811}
812
Dan Stoza5ecfb682016-01-04 17:01:02 -0800813TEST_F(BufferQueueTest, CanAttachWhileDisallowingAllocation) {
814 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700815 sp<MockConsumer> mc(new MockConsumer);
816 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Dan Stoza5ecfb682016-01-04 17:01:02 -0800817 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700818 ASSERT_EQ(OK,
819 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Dan Stoza5ecfb682016-01-04 17:01:02 -0800820
821 int slot = BufferQueue::INVALID_BUFFER_SLOT;
822 sp<Fence> sourceFence;
823 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Nolan Scobie9c427942023-05-01 16:41:28 -0400824 mProducer->dequeueBuffer(&slot, &sourceFence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
825 nullptr, nullptr));
Dan Stoza5ecfb682016-01-04 17:01:02 -0800826 sp<GraphicBuffer> buffer;
827 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
828 ASSERT_EQ(OK, mProducer->detachBuffer(slot));
829
830 ASSERT_EQ(OK, mProducer->allowAllocation(false));
831
832 slot = BufferQueue::INVALID_BUFFER_SLOT;
833 ASSERT_EQ(OK, mProducer->attachBuffer(&slot, buffer));
834}
835
Dan Stoza50101d02016-04-07 16:53:23 -0700836TEST_F(BufferQueueTest, CanRetrieveLastQueuedBuffer) {
837 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700838 sp<MockConsumer> mc(new MockConsumer);
839 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Dan Stoza50101d02016-04-07 16:53:23 -0700840 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700841 ASSERT_EQ(OK,
842 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
Dan Stoza50101d02016-04-07 16:53:23 -0700843
844 // Dequeue and queue the first buffer, storing the handle
845 int slot = BufferQueue::INVALID_BUFFER_SLOT;
846 sp<Fence> fence;
847 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Nolan Scobie9c427942023-05-01 16:41:28 -0400848 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
849 nullptr));
Dan Stoza50101d02016-04-07 16:53:23 -0700850 sp<GraphicBuffer> firstBuffer;
851 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &firstBuffer));
852
853 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
854 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
855 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
856 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
857
858 // Dequeue a second buffer
859 slot = BufferQueue::INVALID_BUFFER_SLOT;
860 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Nolan Scobie9c427942023-05-01 16:41:28 -0400861 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
862 nullptr));
Dan Stoza50101d02016-04-07 16:53:23 -0700863 sp<GraphicBuffer> secondBuffer;
864 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &secondBuffer));
865
866 // Ensure it's a new buffer
867 ASSERT_NE(firstBuffer->getNativeBuffer()->handle,
868 secondBuffer->getNativeBuffer()->handle);
869
870 // Queue the second buffer
871 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
872
873 // Acquire and release both buffers
874 for (size_t i = 0; i < 2; ++i) {
875 BufferItem item;
876 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
877 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
878 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
879 }
880
881 // Make sure we got the second buffer back
882 sp<GraphicBuffer> returnedBuffer;
883 sp<Fence> returnedFence;
John Reck1a61da52016-04-28 13:18:15 -0700884 float transform[16];
Dan Stoza50101d02016-04-07 16:53:23 -0700885 ASSERT_EQ(OK,
John Reck1a61da52016-04-28 13:18:15 -0700886 mProducer->getLastQueuedBuffer(&returnedBuffer, &returnedFence,
887 transform));
Dan Stoza50101d02016-04-07 16:53:23 -0700888 ASSERT_EQ(secondBuffer->getNativeBuffer()->handle,
889 returnedBuffer->getNativeBuffer()->handle);
890}
891
Dan Stozae77c7662016-05-13 11:37:28 -0700892TEST_F(BufferQueueTest, TestOccupancyHistory) {
893 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700894 sp<MockConsumer> mc(new MockConsumer);
895 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Dan Stozae77c7662016-05-13 11:37:28 -0700896 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700897 ASSERT_EQ(OK,
898 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
Dan Stozae77c7662016-05-13 11:37:28 -0700899
900 int slot = BufferQueue::INVALID_BUFFER_SLOT;
901 sp<Fence> fence = Fence::NO_FENCE;
902 sp<GraphicBuffer> buffer = nullptr;
903 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
904 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
905 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
906 BufferItem item{};
907
908 // Preallocate, dequeue, request, and cancel 3 buffers so we don't get
909 // BUFFER_NEEDS_REALLOCATION below
910 int slots[3] = {};
911 mProducer->setMaxDequeuedBufferCount(3);
912 for (size_t i = 0; i < 3; ++i) {
Nolan Scobie9c427942023-05-01 16:41:28 -0400913 status_t result = mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0,
914 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr);
Dan Stozae77c7662016-05-13 11:37:28 -0700915 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
916 ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
917 }
918 for (size_t i = 0; i < 3; ++i) {
919 ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE));
920 }
921
922 // Create 3 segments
923
924 // The first segment is a two-buffer segment, so we only put one buffer into
925 // the queue at a time
926 for (size_t i = 0; i < 5; ++i) {
Nolan Scobie9c427942023-05-01 16:41:28 -0400927 ASSERT_EQ(OK,
928 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
929 nullptr, nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700930 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
931 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
932 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
933 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
934 std::this_thread::sleep_for(16ms);
935 }
936
937 // Sleep between segments
938 std::this_thread::sleep_for(500ms);
939
940 // The second segment is a double-buffer segment. It starts the same as the
941 // two-buffer segment, but then at the end, we put two buffers in the queue
942 // at the same time before draining it.
943 for (size_t i = 0; i < 5; ++i) {
Nolan Scobie9c427942023-05-01 16:41:28 -0400944 ASSERT_EQ(OK,
945 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
946 nullptr, nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700947 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
948 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
949 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
950 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
951 std::this_thread::sleep_for(16ms);
952 }
Nolan Scobie9c427942023-05-01 16:41:28 -0400953 ASSERT_EQ(OK,
954 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
955 nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700956 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
Nolan Scobie9c427942023-05-01 16:41:28 -0400957 ASSERT_EQ(OK,
958 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
959 nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700960 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
961 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
962 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
963 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
964 std::this_thread::sleep_for(16ms);
965 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
966 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
967 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
968
969 // Sleep between segments
970 std::this_thread::sleep_for(500ms);
971
972 // The third segment is a triple-buffer segment, so the queue is switching
973 // between one buffer and two buffers deep.
Nolan Scobie9c427942023-05-01 16:41:28 -0400974 ASSERT_EQ(OK,
975 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
976 nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700977 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
978 for (size_t i = 0; i < 5; ++i) {
Nolan Scobie9c427942023-05-01 16:41:28 -0400979 ASSERT_EQ(OK,
980 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
981 nullptr, nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700982 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
983 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
984 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
985 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
986 std::this_thread::sleep_for(16ms);
987 }
988 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
989 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
990 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
991
992 // Now we read the segments
993 std::vector<OccupancyTracker::Segment> history;
994 ASSERT_EQ(OK, mConsumer->getOccupancyHistory(false, &history));
995
996 // Since we didn't force a flush, we should only get the first two segments
997 // (since the third segment hasn't been closed out by the appearance of a
998 // new segment yet)
999 ASSERT_EQ(2u, history.size());
1000
1001 // The first segment (which will be history[1], since the newest segment
1002 // should be at the front of the vector) should be a two-buffer segment,
1003 // which implies that the occupancy average should be between 0 and 1, and
1004 // usedThirdBuffer should be false
1005 const auto& firstSegment = history[1];
1006 ASSERT_EQ(5u, firstSegment.numFrames);
1007 ASSERT_LT(0, firstSegment.occupancyAverage);
1008 ASSERT_GT(1, firstSegment.occupancyAverage);
1009 ASSERT_EQ(false, firstSegment.usedThirdBuffer);
1010
1011 // The second segment should be a double-buffered segment, which implies that
1012 // the occupancy average should be between 0 and 1, but usedThirdBuffer
1013 // should be true
1014 const auto& secondSegment = history[0];
1015 ASSERT_EQ(7u, secondSegment.numFrames);
1016 ASSERT_LT(0, secondSegment.occupancyAverage);
1017 ASSERT_GT(1, secondSegment.occupancyAverage);
1018 ASSERT_EQ(true, secondSegment.usedThirdBuffer);
1019
1020 // If we read the segments again without flushing, we shouldn't get any new
1021 // segments
1022 ASSERT_EQ(OK, mConsumer->getOccupancyHistory(false, &history));
1023 ASSERT_EQ(0u, history.size());
1024
1025 // Read the segments again, this time forcing a flush so we get the third
1026 // segment
1027 ASSERT_EQ(OK, mConsumer->getOccupancyHistory(true, &history));
1028 ASSERT_EQ(1u, history.size());
1029
1030 // This segment should be a triple-buffered segment, which implies that the
1031 // occupancy average should be between 1 and 2, and usedThirdBuffer should
1032 // be true
1033 const auto& thirdSegment = history[0];
1034 ASSERT_EQ(6u, thirdSegment.numFrames);
1035 ASSERT_LT(1, thirdSegment.occupancyAverage);
1036 ASSERT_GT(2, thirdSegment.occupancyAverage);
1037 ASSERT_EQ(true, thirdSegment.usedThirdBuffer);
1038}
1039
Shuzhen Wang067fcd32019-08-14 10:41:12 -07001040struct BufferDiscardedListener : public BnProducerListener {
1041public:
1042 BufferDiscardedListener() = default;
1043 virtual ~BufferDiscardedListener() = default;
1044
1045 virtual void onBufferReleased() {}
1046 virtual bool needsReleaseNotify() { return false; }
1047 virtual void onBuffersDiscarded(const std::vector<int32_t>& slots) {
1048 mDiscardedSlots.insert(mDiscardedSlots.end(), slots.begin(), slots.end());
1049 }
1050
1051 const std::vector<int32_t>& getDiscardedSlots() const { return mDiscardedSlots; }
1052private:
1053 // No need to use lock given the test triggers the listener in the same
1054 // thread context.
1055 std::vector<int32_t> mDiscardedSlots;
1056};
1057
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001058TEST_F(BufferQueueTest, TestDiscardFreeBuffers) {
1059 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -07001060 sp<MockConsumer> mc(new MockConsumer);
1061 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001062 IGraphicBufferProducer::QueueBufferOutput output;
Shuzhen Wang067fcd32019-08-14 10:41:12 -07001063 sp<BufferDiscardedListener> pl(new BufferDiscardedListener);
1064 ASSERT_EQ(OK, mProducer->connect(pl,
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001065 NATIVE_WINDOW_API_CPU, false, &output));
1066
1067 int slot = BufferQueue::INVALID_BUFFER_SLOT;
1068 sp<Fence> fence = Fence::NO_FENCE;
1069 sp<GraphicBuffer> buffer = nullptr;
1070 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1071 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1072 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1073 BufferItem item{};
1074
1075 // Preallocate, dequeue, request, and cancel 4 buffers so we don't get
1076 // BUFFER_NEEDS_REALLOCATION below
1077 int slots[4] = {};
1078 mProducer->setMaxDequeuedBufferCount(4);
1079 for (size_t i = 0; i < 4; ++i) {
Nolan Scobie9c427942023-05-01 16:41:28 -04001080 status_t result = mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0,
1081 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr);
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001082 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1083 ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
1084 }
1085 for (size_t i = 0; i < 4; ++i) {
1086 ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE));
1087 }
1088
1089 // Get buffers in all states: dequeued, filled, acquired, free
1090
1091 // Fill 3 buffers
Nolan Scobie9c427942023-05-01 16:41:28 -04001092 ASSERT_EQ(OK,
1093 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1094 nullptr));
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001095 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
Nolan Scobie9c427942023-05-01 16:41:28 -04001096 ASSERT_EQ(OK,
1097 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1098 nullptr));
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001099 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
Nolan Scobie9c427942023-05-01 16:41:28 -04001100 ASSERT_EQ(OK,
1101 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1102 nullptr));
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001103 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1104 // Dequeue 1 buffer
Nolan Scobie9c427942023-05-01 16:41:28 -04001105 ASSERT_EQ(OK,
1106 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1107 nullptr));
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001108
1109 // Acquire and free 1 buffer
1110 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1111 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
1112 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
Shuzhen Wang067fcd32019-08-14 10:41:12 -07001113 int releasedSlot = item.mSlot;
1114
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001115 // Acquire 1 buffer, leaving 1 filled buffer in queue
1116 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1117
1118 // Now discard the free buffers
1119 ASSERT_EQ(OK, mConsumer->discardFreeBuffers());
1120
Shuzhen Wang067fcd32019-08-14 10:41:12 -07001121 // Check onBuffersDiscarded is called with correct slots
1122 auto buffersDiscarded = pl->getDiscardedSlots();
Siarhei Vishniakoubf98a572024-03-29 13:34:42 -07001123 ASSERT_EQ(buffersDiscarded.size(), 1u);
Shuzhen Wang067fcd32019-08-14 10:41:12 -07001124 ASSERT_EQ(buffersDiscarded[0], releasedSlot);
1125
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001126 // Check no free buffers in dump
1127 String8 dumpString;
Dan Stoza0c9a1ed2017-04-06 15:10:21 -07001128 mConsumer->dumpState(String8{}, &dumpString);
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001129
1130 // Parse the dump to ensure that all buffer slots that are FREE also
1131 // have a null GraphicBuffer
1132 // Fragile - assumes the following format for the dump for a buffer entry:
1133 // ":%p\][^:]*state=FREE" where %p is the buffer pointer in hex.
1134 ssize_t idx = dumpString.find("state=FREE");
1135 while (idx != -1) {
1136 ssize_t bufferPtrIdx = idx - 1;
1137 while (bufferPtrIdx > 0) {
1138 if (dumpString[bufferPtrIdx] == ':') {
1139 bufferPtrIdx++;
1140 break;
1141 }
1142 bufferPtrIdx--;
1143 }
1144 ASSERT_GT(bufferPtrIdx, 0) << "Can't parse queue dump to validate";
1145 ssize_t nullPtrIdx = dumpString.find("0x0]", bufferPtrIdx);
1146 ASSERT_EQ(bufferPtrIdx, nullPtrIdx) << "Free buffer not discarded";
1147 idx = dumpString.find("FREE", idx + 1);
1148 }
1149}
1150
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001151TEST_F(BufferQueueTest, TestBufferReplacedInQueueBuffer) {
1152 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -07001153 sp<MockConsumer> mc(new MockConsumer);
1154 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001155 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -07001156 ASSERT_EQ(OK,
1157 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001158 ASSERT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
1159
1160 int slot = BufferQueue::INVALID_BUFFER_SLOT;
1161 sp<Fence> fence = Fence::NO_FENCE;
1162 sp<GraphicBuffer> buffer = nullptr;
1163 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1164 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1165 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1166 BufferItem item{};
1167
1168 // Preallocate, dequeue, request, and cancel 2 buffers so we don't get
1169 // BUFFER_NEEDS_REALLOCATION below
1170 int slots[2] = {};
1171 ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(2));
1172 for (size_t i = 0; i < 2; ++i) {
Nolan Scobie9c427942023-05-01 16:41:28 -04001173 status_t result = mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0,
1174 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr);
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001175 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1176 ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
1177 }
1178 for (size_t i = 0; i < 2; ++i) {
1179 ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE));
1180 }
1181
1182 // Fill 2 buffers without consumer consuming them. Verify that all
1183 // queued buffer returns proper bufferReplaced flag
Nolan Scobie9c427942023-05-01 16:41:28 -04001184 ASSERT_EQ(OK,
1185 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1186 nullptr));
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001187 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1188 ASSERT_EQ(false, output.bufferReplaced);
Nolan Scobie9c427942023-05-01 16:41:28 -04001189 ASSERT_EQ(OK,
1190 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1191 nullptr));
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001192 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1193 ASSERT_EQ(true, output.bufferReplaced);
1194}
1195
Sungtak Lee1e7c09b2023-10-26 08:44:21 +00001196struct BufferDetachedListener : public BnProducerListener {
1197public:
1198 BufferDetachedListener() = default;
1199 virtual ~BufferDetachedListener() = default;
1200
1201 virtual void onBufferReleased() {}
1202 virtual bool needsReleaseNotify() { return true; }
1203 virtual void onBufferDetached(int slot) {
1204 mDetachedSlots.push_back(slot);
1205 }
1206 const std::vector<int>& getDetachedSlots() const { return mDetachedSlots; }
1207private:
1208 std::vector<int> mDetachedSlots;
1209};
1210
1211TEST_F(BufferQueueTest, TestConsumerDetachProducerListener) {
1212 createBufferQueue();
1213 sp<MockConsumer> mc(new MockConsumer);
1214 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
1215 IGraphicBufferProducer::QueueBufferOutput output;
1216 sp<BufferDetachedListener> pl(new BufferDetachedListener);
1217 ASSERT_EQ(OK, mProducer->connect(pl, NATIVE_WINDOW_API_CPU, true, &output));
1218 ASSERT_EQ(OK, mProducer->setDequeueTimeout(0));
1219 ASSERT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
1220
1221 sp<Fence> fence = Fence::NO_FENCE;
1222 sp<GraphicBuffer> buffer = nullptr;
1223 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1224 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1225 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1226
1227 int slots[2] = {};
1228 status_t result = OK;
1229 ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(2));
1230
1231 result = mProducer->dequeueBuffer(&slots[0], &fence, 0, 0, 0,
1232 GRALLOC_USAGE_SW_READ_RARELY, nullptr, nullptr);
1233 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1234 ASSERT_EQ(OK, mProducer->requestBuffer(slots[0], &buffer));
1235
1236 result = mProducer->dequeueBuffer(&slots[1], &fence, 0, 0, 0,
1237 GRALLOC_USAGE_SW_READ_RARELY, nullptr, nullptr);
1238 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1239 ASSERT_EQ(OK, mProducer->requestBuffer(slots[1], &buffer));
1240
1241 // Queue & detach one from two dequeued buffes.
1242 ASSERT_EQ(OK, mProducer->queueBuffer(slots[1], input, &output));
1243 BufferItem item{};
1244 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1245 ASSERT_EQ(OK, mConsumer->detachBuffer(item.mSlot));
1246
1247 // Check whether the slot from IProducerListener is same to the detached slot.
Siarhei Vishniakoubf98a572024-03-29 13:34:42 -07001248 ASSERT_EQ(pl->getDetachedSlots().size(), 1u);
Sungtak Lee1e7c09b2023-10-26 08:44:21 +00001249 ASSERT_EQ(pl->getDetachedSlots()[0], slots[1]);
1250
1251 // Dequeue another buffer.
1252 int slot;
1253 result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
1254 GRALLOC_USAGE_SW_READ_RARELY, nullptr, nullptr);
1255 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1256 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
1257
1258 // Dequeue should fail here, since we dequeued 3 buffers and one buffer was
1259 // detached from consumer(Two buffers are dequeued, and the current max
1260 // dequeued buffer count is two).
1261 result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
1262 GRALLOC_USAGE_SW_READ_RARELY, nullptr, nullptr);
1263 ASSERT_TRUE(result == WOULD_BLOCK || result == TIMED_OUT || result == INVALID_OPERATION);
1264}
1265
Sungtak Leecd217472024-07-19 17:17:40 +00001266#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_CONSUMER_ATTACH_CALLBACK)
1267struct BufferAttachedListener : public BnProducerListener {
1268public:
1269 BufferAttachedListener(bool enable) : mEnabled(enable), mAttached(0) {}
1270 virtual ~BufferAttachedListener() = default;
1271
1272 virtual void onBufferReleased() {}
1273 virtual bool needsReleaseNotify() { return true; }
1274 virtual void onBufferAttached() {
1275 ++mAttached;
1276 }
1277 virtual bool needsAttachNotify() { return mEnabled; }
1278
1279 int getNumAttached() const { return mAttached; }
1280private:
1281 const bool mEnabled;
1282 int mAttached;
1283};
1284
1285TEST_F(BufferQueueTest, TestConsumerAttachProducerListener) {
1286 createBufferQueue();
1287 sp<MockConsumer> mc1(new MockConsumer);
1288 ASSERT_EQ(OK, mConsumer->consumerConnect(mc1, true));
1289 IGraphicBufferProducer::QueueBufferOutput output;
1290 // Do not enable attach callback.
1291 sp<BufferAttachedListener> pl1(new BufferAttachedListener(false));
1292 ASSERT_EQ(OK, mProducer->connect(pl1, NATIVE_WINDOW_API_CPU, true, &output));
1293 ASSERT_EQ(OK, mProducer->setDequeueTimeout(0));
1294 ASSERT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
1295
1296 sp<Fence> fence = Fence::NO_FENCE;
1297 sp<GraphicBuffer> buffer = nullptr;
1298
1299 int slot;
1300 status_t result = OK;
1301
1302 ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(1));
1303
1304 result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
1305 GRALLOC_USAGE_SW_READ_RARELY, nullptr, nullptr);
1306 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1307 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
1308 ASSERT_EQ(OK, mProducer->detachBuffer(slot));
1309
1310 // Check # of attach is zero.
1311 ASSERT_EQ(0, pl1->getNumAttached());
1312
1313 // Attach a buffer and check the callback was not called.
1314 ASSERT_EQ(OK, mConsumer->attachBuffer(&slot, buffer));
1315 ASSERT_EQ(0, pl1->getNumAttached());
1316
1317 mProducer = nullptr;
1318 mConsumer = nullptr;
1319 createBufferQueue();
1320
1321 sp<MockConsumer> mc2(new MockConsumer);
1322 ASSERT_EQ(OK, mConsumer->consumerConnect(mc2, true));
1323 // Enable attach callback.
1324 sp<BufferAttachedListener> pl2(new BufferAttachedListener(true));
1325 ASSERT_EQ(OK, mProducer->connect(pl2, NATIVE_WINDOW_API_CPU, true, &output));
1326 ASSERT_EQ(OK, mProducer->setDequeueTimeout(0));
1327 ASSERT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
1328
1329 fence = Fence::NO_FENCE;
1330 buffer = nullptr;
1331
1332 result = OK;
1333
1334 ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(1));
1335
1336 result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
1337 GRALLOC_USAGE_SW_READ_RARELY, nullptr, nullptr);
1338 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1339 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
1340 ASSERT_EQ(OK, mProducer->detachBuffer(slot));
1341
1342 // Check # of attach is zero.
1343 ASSERT_EQ(0, pl2->getNumAttached());
1344
1345 // Attach a buffer and check the callback was called.
1346 ASSERT_EQ(OK, mConsumer->attachBuffer(&slot, buffer));
1347 ASSERT_EQ(1, pl2->getNumAttached());
1348}
1349#endif
1350
Dan Stozad4c6f992017-03-21 13:43:22 -07001351TEST_F(BufferQueueTest, TestStaleBufferHandleSentAfterDisconnect) {
1352 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -07001353 sp<MockConsumer> mc(new MockConsumer);
1354 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Dan Stozad4c6f992017-03-21 13:43:22 -07001355 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -07001356 sp<IProducerListener> fakeListener(new StubProducerListener);
1357 ASSERT_EQ(OK, mProducer->connect(fakeListener, NATIVE_WINDOW_API_CPU, true, &output));
Dan Stozad4c6f992017-03-21 13:43:22 -07001358
1359 int slot = BufferQueue::INVALID_BUFFER_SLOT;
1360 sp<Fence> fence = Fence::NO_FENCE;
1361 sp<GraphicBuffer> buffer = nullptr;
1362 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1363 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1364 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1365
1366 // Dequeue, request, and queue one buffer
Nolan Scobie9c427942023-05-01 16:41:28 -04001367 status_t result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
1368 nullptr, nullptr);
Dan Stozad4c6f992017-03-21 13:43:22 -07001369 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1370 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
1371 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1372
1373 // Acquire and release the buffer. Upon acquiring, the buffer handle should
1374 // be non-null since this is the first time we've acquired this slot.
1375 BufferItem item;
1376 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1377 ASSERT_EQ(slot, item.mSlot);
1378 ASSERT_NE(nullptr, item.mGraphicBuffer.get());
1379 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
1380 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
1381
1382 // Dequeue and queue the buffer again
Nolan Scobie9c427942023-05-01 16:41:28 -04001383 ASSERT_EQ(OK,
1384 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1385 nullptr));
Dan Stozad4c6f992017-03-21 13:43:22 -07001386 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1387
1388 // Acquire and release the buffer again. Upon acquiring, the buffer handle
1389 // should be null since this is not the first time we've acquired this slot.
1390 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1391 ASSERT_EQ(slot, item.mSlot);
1392 ASSERT_EQ(nullptr, item.mGraphicBuffer.get());
1393 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
1394 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
1395
1396 // Dequeue and queue the buffer again
Nolan Scobie9c427942023-05-01 16:41:28 -04001397 ASSERT_EQ(OK,
1398 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1399 nullptr));
Dan Stozad4c6f992017-03-21 13:43:22 -07001400 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1401
1402 // Disconnect the producer end. This should clear all of the slots and mark
1403 // the buffer in the queue as stale.
1404 ASSERT_EQ(OK, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
1405
1406 // Acquire the buffer again. Upon acquiring, the buffer handle should not be
1407 // null since the queued buffer should have been marked as stale, which
1408 // should trigger the BufferQueue to resend the buffer handle.
1409 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1410 ASSERT_EQ(slot, item.mSlot);
1411 ASSERT_NE(nullptr, item.mGraphicBuffer.get());
1412}
1413
Wonsik Kim3e198b22017-04-07 15:43:16 -07001414TEST_F(BufferQueueTest, TestProducerConnectDisconnect) {
1415 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -07001416 sp<MockConsumer> mc(new MockConsumer);
1417 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Wonsik Kim3e198b22017-04-07 15:43:16 -07001418 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -07001419 sp<IProducerListener> fakeListener(new StubProducerListener);
Wonsik Kim3e198b22017-04-07 15:43:16 -07001420 ASSERT_EQ(NO_INIT, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
Peiyong Lind8460c82020-07-28 16:04:22 -07001421 ASSERT_EQ(OK, mProducer->connect(fakeListener, NATIVE_WINDOW_API_CPU, true, &output));
1422 ASSERT_EQ(BAD_VALUE, mProducer->connect(fakeListener, NATIVE_WINDOW_API_MEDIA, true, &output));
Wonsik Kim3e198b22017-04-07 15:43:16 -07001423
1424 ASSERT_EQ(BAD_VALUE, mProducer->disconnect(NATIVE_WINDOW_API_MEDIA));
1425 ASSERT_EQ(OK, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
1426 ASSERT_EQ(NO_INIT, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
1427}
1428
Ady Abraham6cdd3fd2023-09-07 18:45:58 -07001429TEST_F(BufferQueueTest, TestBqSetFrameRateFlagBuildTimeIsSet) {
Ady Abraham107788e2023-10-17 12:31:08 -07001430 ASSERT_EQ(flags::bq_setframerate(), COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_SETFRAMERATE));
Ady Abraham6cdd3fd2023-09-07 18:45:58 -07001431}
1432
1433struct BufferItemConsumerSetFrameRateListener : public BufferItemConsumer {
Jim Shargod30823a2024-07-27 02:49:39 +00001434 BufferItemConsumerSetFrameRateListener() : BufferItemConsumer(GRALLOC_USAGE_SW_READ_OFTEN, 1) {}
Ady Abraham6cdd3fd2023-09-07 18:45:58 -07001435
1436 MOCK_METHOD(void, onSetFrameRate, (float, int8_t, int8_t), (override));
1437};
1438
1439TEST_F(BufferQueueTest, TestSetFrameRate) {
Ady Abraham6cdd3fd2023-09-07 18:45:58 -07001440 sp<BufferItemConsumerSetFrameRateListener> bufferConsumer =
Jim Shargod30823a2024-07-27 02:49:39 +00001441 sp<BufferItemConsumerSetFrameRateListener>::make();
1442 sp<IGraphicBufferProducer> producer = bufferConsumer->getSurface()->getIGraphicBufferProducer();
Ady Abraham6cdd3fd2023-09-07 18:45:58 -07001443
1444 EXPECT_CALL(*bufferConsumer, onSetFrameRate(12.34f, 1, 0)).Times(1);
1445 producer->setFrameRate(12.34f, 1, 0);
1446}
1447
John Reck12daff92023-07-28 16:36:27 -04001448class Latch {
1449public:
1450 explicit Latch(int expected) : mExpected(expected) {}
1451 Latch(const Latch&) = delete;
1452 Latch& operator=(const Latch&) = delete;
1453
1454 void CountDown() {
1455 std::unique_lock<std::mutex> lock(mLock);
1456 mExpected--;
1457 if (mExpected <= 0) {
1458 mCV.notify_all();
1459 }
1460 }
1461
1462 void Wait() {
1463 std::unique_lock<std::mutex> lock(mLock);
1464 mCV.wait(lock, [&] { return mExpected == 0; });
1465 }
1466
1467private:
1468 int mExpected;
1469 std::mutex mLock;
1470 std::condition_variable mCV;
1471};
1472
1473struct OneshotOnDequeuedListener final : public BufferItemConsumer::FrameAvailableListener {
1474 OneshotOnDequeuedListener(std::function<void()>&& oneshot)
1475 : mOneshotRunnable(std::move(oneshot)) {}
1476
1477 std::function<void()> mOneshotRunnable;
1478
1479 void run() {
1480 if (mOneshotRunnable) {
1481 mOneshotRunnable();
1482 mOneshotRunnable = nullptr;
1483 }
1484 }
1485
1486 void onFrameDequeued(const uint64_t) override { run(); }
1487
1488 void onFrameAvailable(const BufferItem&) override {}
1489};
1490
1491// See b/270004534
1492TEST(BufferQueueThreading, TestProducerDequeueConsumerDestroy) {
John Reck12daff92023-07-28 16:36:27 -04001493 sp<BufferItemConsumer> bufferConsumer =
Jim Shargod30823a2024-07-27 02:49:39 +00001494 sp<BufferItemConsumer>::make(GRALLOC_USAGE_SW_READ_OFTEN, 2);
John Reck12daff92023-07-28 16:36:27 -04001495 ASSERT_NE(nullptr, bufferConsumer.get());
Jim Shargod30823a2024-07-27 02:49:39 +00001496 sp<Surface> surface = bufferConsumer->getSurface();
John Reck12daff92023-07-28 16:36:27 -04001497 native_window_set_buffers_format(surface.get(), PIXEL_FORMAT_RGBA_8888);
1498 native_window_set_buffers_dimensions(surface.get(), 100, 100);
1499
1500 Latch triggerDisconnect(1);
1501 Latch resumeCallback(1);
1502 auto luckyListener = sp<OneshotOnDequeuedListener>::make([&]() {
1503 triggerDisconnect.CountDown();
1504 resumeCallback.Wait();
1505 });
1506 bufferConsumer->setFrameAvailableListener(luckyListener);
1507
1508 std::future<void> disconnecter = std::async(std::launch::async, [&]() {
1509 triggerDisconnect.Wait();
1510 luckyListener = nullptr;
1511 bufferConsumer = nullptr;
1512 resumeCallback.CountDown();
1513 });
1514
1515 std::future<void> render = std::async(std::launch::async, [=]() {
1516 ANativeWindow_Buffer buffer;
1517 surface->lock(&buffer, nullptr);
1518 surface->unlockAndPost();
1519 });
1520
1521 ASSERT_EQ(std::future_status::ready, render.wait_for(1s));
1522 EXPECT_EQ(nullptr, luckyListener.get());
1523 EXPECT_EQ(nullptr, bufferConsumer.get());
1524}
1525
John Reckdb164ff2024-04-03 16:59:28 -04001526TEST_F(BufferQueueTest, TestAdditionalOptions) {
John Reckdb164ff2024-04-03 16:59:28 -04001527 sp<BufferItemConsumer> bufferConsumer =
Jim Shargod30823a2024-07-27 02:49:39 +00001528 sp<BufferItemConsumer>::make(GRALLOC_USAGE_SW_READ_OFTEN, 2);
John Reckdb164ff2024-04-03 16:59:28 -04001529 ASSERT_NE(nullptr, bufferConsumer.get());
Jim Shargod30823a2024-07-27 02:49:39 +00001530 sp<Surface> surface = bufferConsumer->getSurface();
John Reckdb164ff2024-04-03 16:59:28 -04001531 native_window_set_buffers_format(surface.get(), PIXEL_FORMAT_RGBA_8888);
1532 native_window_set_buffers_dimensions(surface.get(), 100, 100);
1533
1534 std::array<AHardwareBufferLongOptions, 1> extras = {{
1535 {.name = "android.hardware.graphics.common.Dataspace", ADATASPACE_DISPLAY_P3},
1536 }};
1537
1538 ASSERT_EQ(NO_INIT,
1539 native_window_set_buffers_additional_options(surface.get(), extras.data(),
1540 extras.size()));
1541
1542 if (!IsCuttlefish()) {
1543 GTEST_SKIP() << "Not cuttlefish";
1544 }
1545
1546 ASSERT_EQ(OK, native_window_api_connect(surface.get(), NATIVE_WINDOW_API_CPU));
1547 ASSERT_EQ(OK,
1548 native_window_set_buffers_additional_options(surface.get(), extras.data(),
1549 extras.size()));
1550
1551 ANativeWindowBuffer* windowBuffer = nullptr;
1552 int fence = -1;
1553 ASSERT_EQ(OK, ANativeWindow_dequeueBuffer(surface.get(), &windowBuffer, &fence));
1554
1555 AHardwareBuffer* buffer = ANativeWindowBuffer_getHardwareBuffer(windowBuffer);
1556 ASSERT_TRUE(buffer);
1557 ADataSpace dataSpace = AHardwareBuffer_getDataSpace(buffer);
1558 EXPECT_EQ(ADATASPACE_DISPLAY_P3, dataSpace);
1559
1560 ANativeWindow_cancelBuffer(surface.get(), windowBuffer, -1);
1561
1562 // Check that reconnecting properly clears the options
1563 ASSERT_EQ(OK, native_window_api_disconnect(surface.get(), NATIVE_WINDOW_API_CPU));
1564 ASSERT_EQ(OK, native_window_api_connect(surface.get(), NATIVE_WINDOW_API_CPU));
1565
1566 ASSERT_EQ(OK, ANativeWindow_dequeueBuffer(surface.get(), &windowBuffer, &fence));
1567 buffer = ANativeWindowBuffer_getHardwareBuffer(windowBuffer);
1568 ASSERT_TRUE(buffer);
1569 dataSpace = AHardwareBuffer_getDataSpace(buffer);
1570 EXPECT_EQ(ADATASPACE_UNKNOWN, dataSpace);
1571}
1572
Brian Lindahl628cff42024-10-30 11:50:28 -06001573TEST_F(BufferQueueTest, PassesThroughPictureProfileHandle) {
1574 createBufferQueue();
1575 sp<MockConsumer> mc(new MockConsumer);
1576 mConsumer->consumerConnect(mc, false);
1577
1578 IGraphicBufferProducer::QueueBufferOutput qbo;
1579 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &qbo);
1580 mProducer->setMaxDequeuedBufferCount(2);
1581 mConsumer->setMaxAcquiredBufferCount(2);
1582
1583 // First try to pass a valid picture profile handle
1584 {
1585 int slot;
1586 sp<Fence> fence;
1587 sp<GraphicBuffer> buf;
1588 IGraphicBufferProducer::QueueBufferInput qbi(0, false, HAL_DATASPACE_UNKNOWN,
1589 Rect(0, 0, 1, 1),
1590 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0,
1591 Fence::NO_FENCE);
1592 qbi.setPictureProfileHandle(PictureProfileHandle(1));
1593
1594 EXPECT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
1595 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
1596 nullptr, nullptr));
1597 EXPECT_EQ(OK, mProducer->requestBuffer(slot, &buf));
1598 EXPECT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
1599
1600 BufferItem item;
1601 EXPECT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1602
1603 ASSERT_TRUE(item.mPictureProfileHandle.has_value());
1604 ASSERT_EQ(item.mPictureProfileHandle, PictureProfileHandle(1));
1605 }
1606
1607 // Then validate that the picture profile handle isn't sticky and is reset for the next buffer
1608 {
1609 int slot;
1610 sp<Fence> fence;
1611 sp<GraphicBuffer> buf;
1612 IGraphicBufferProducer::QueueBufferInput qbi(0, false, HAL_DATASPACE_UNKNOWN,
1613 Rect(0, 0, 1, 1),
1614 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0,
1615 Fence::NO_FENCE);
1616
1617 EXPECT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
1618 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
1619 nullptr, nullptr));
1620 EXPECT_EQ(OK, mProducer->requestBuffer(slot, &buf));
1621 EXPECT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
1622
1623 BufferItem item;
1624 EXPECT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1625
1626 ASSERT_FALSE(item.mPictureProfileHandle.has_value());
1627 }
1628}
1629
Jamie Gennis9e75ddd2012-08-31 15:32:45 -07001630} // namespace android