blob: 2e6ffcb57fd186cff4fbd29e45fb0e80a977bde2 [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
John Reckdb164ff2024-04-03 16:59:28 -040031#include <android-base/properties.h>
32
Dan Stoza1a0b8612014-03-20 15:36:31 -070033#include <binder/IPCThreadState.h>
Dan Stoza9f3053d2014-03-06 15:14:33 -080034#include <binder/IServiceManager.h>
Dan Stoza1a0b8612014-03-20 15:36:31 -070035#include <binder/ProcessState.h>
Dan Stozaf0eaf252014-03-21 13:05:51 -070036
37#include <utils/String8.h>
38#include <utils/threads.h>
39
Mathias Agopian6a3c05b2017-04-27 20:06:55 -070040#include <system/window.h>
41
Ady Abraham6cdd3fd2023-09-07 18:45:58 -070042#include <gmock/gmock.h>
Dan Stozaf0eaf252014-03-21 13:05:51 -070043#include <gtest/gtest.h>
Jamie Gennis9e75ddd2012-08-31 15:32:45 -070044
John Reck12daff92023-07-28 16:36:27 -040045#include <future>
Dan Stozae77c7662016-05-13 11:37:28 -070046#include <thread>
47
Ady Abraham6cdd3fd2023-09-07 18:45:58 -070048#include <com_android_graphics_libgui_flags.h>
49
Dan Stozae77c7662016-05-13 11:37:28 -070050using namespace std::chrono_literals;
51
John Reckdb164ff2024-04-03 16:59:28 -040052static bool IsCuttlefish() {
53 return ::android::base::GetProperty("ro.product.board", "") == "cutf";
54}
55
Jamie Gennis9e75ddd2012-08-31 15:32:45 -070056namespace android {
Ady Abraham6cdd3fd2023-09-07 18:45:58 -070057using namespace com::android::graphics::libgui;
Jamie Gennis9e75ddd2012-08-31 15:32:45 -070058
59class BufferQueueTest : public ::testing::Test {
Dan Stoza9f3053d2014-03-06 15:14:33 -080060
61public:
Jamie Gennis9e75ddd2012-08-31 15:32:45 -070062protected:
Igor Murashkin7ea777f2013-11-18 16:58:36 -080063 void GetMinUndequeuedBufferCount(int* bufferCount) {
Yi Konga03e0442018-07-17 11:16:57 -070064 ASSERT_TRUE(bufferCount != nullptr);
Dan Stoza9f3053d2014-03-06 15:14:33 -080065 ASSERT_EQ(OK, mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
66 bufferCount));
67 ASSERT_GE(*bufferCount, 0);
Igor Murashkin7ea777f2013-11-18 16:58:36 -080068 }
69
Dan Stoza1a0b8612014-03-20 15:36:31 -070070 void createBufferQueue() {
71 BufferQueue::createBufferQueue(&mProducer, &mConsumer);
72 }
Jamie Gennis9e75ddd2012-08-31 15:32:45 -070073
Pablo Ceballosff95aab2016-01-13 17:09:58 -080074 void testBufferItem(const IGraphicBufferProducer::QueueBufferInput& input,
75 const BufferItem& item) {
76 int64_t timestamp;
77 bool isAutoTimestamp;
78 android_dataspace dataSpace;
79 Rect crop;
80 int scalingMode;
81 uint32_t transform;
82 sp<Fence> fence;
83
84 input.deflate(&timestamp, &isAutoTimestamp, &dataSpace, &crop,
Yi Konga03e0442018-07-17 11:16:57 -070085 &scalingMode, &transform, &fence, nullptr);
Pablo Ceballosff95aab2016-01-13 17:09:58 -080086 ASSERT_EQ(timestamp, item.mTimestamp);
87 ASSERT_EQ(isAutoTimestamp, item.mIsAutoTimestamp);
88 ASSERT_EQ(dataSpace, item.mDataSpace);
89 ASSERT_EQ(crop, item.mCrop);
90 ASSERT_EQ(static_cast<uint32_t>(scalingMode), item.mScalingMode);
91 ASSERT_EQ(transform, item.mTransform);
92 ASSERT_EQ(fence, item.mFence);
93 }
94
Dan Stoza1a0b8612014-03-20 15:36:31 -070095 sp<IGraphicBufferProducer> mProducer;
96 sp<IGraphicBufferConsumer> mConsumer;
97};
Dan Stoza9f3053d2014-03-06 15:14:33 -080098
Dan Stozaf8cebe52015-04-20 12:09:38 -070099static const uint32_t TEST_DATA = 0x12345678u;
100
Dan Stoza1a0b8612014-03-20 15:36:31 -0700101// XXX: Tests that fork a process to hold the BufferQueue must run before tests
102// that use a local BufferQueue, or else Binder will get unhappy
Kalle Raita88752d72017-03-27 14:11:54 -0700103//
104// In one instance this was a crash in the createBufferQueue where the
105// binder call to create a buffer allocator apparently got garbage back.
106// See b/36592665.
107TEST_F(BufferQueueTest, DISABLED_BufferQueueInAnotherProcess) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700108 const String16 PRODUCER_NAME = String16("BQTestProducer");
109 const String16 CONSUMER_NAME = String16("BQTestConsumer");
110
111 pid_t forkPid = fork();
112 ASSERT_NE(forkPid, -1);
113
114 if (forkPid == 0) {
115 // Child process
Dan Stozab3d0bdf2014-04-07 16:33:59 -0700116 sp<IGraphicBufferProducer> producer;
117 sp<IGraphicBufferConsumer> consumer;
Dan Stoza1a0b8612014-03-20 15:36:31 -0700118 BufferQueue::createBufferQueue(&producer, &consumer);
119 sp<IServiceManager> serviceManager = defaultServiceManager();
Marco Nelissen097ca272014-11-14 08:01:01 -0800120 serviceManager->addService(PRODUCER_NAME, IInterface::asBinder(producer));
121 serviceManager->addService(CONSUMER_NAME, IInterface::asBinder(consumer));
Dan Stoza1a0b8612014-03-20 15:36:31 -0700122 ProcessState::self()->startThreadPool();
123 IPCThreadState::self()->joinThreadPool();
124 LOG_ALWAYS_FATAL("Shouldn't be here");
125 }
126
127 sp<IServiceManager> serviceManager = defaultServiceManager();
Siarhei Vishniakoubf98a572024-03-29 13:34:42 -0700128 sp<IBinder> binderProducer = serviceManager->waitForService(PRODUCER_NAME);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700129 mProducer = interface_cast<IGraphicBufferProducer>(binderProducer);
Yi Konga03e0442018-07-17 11:16:57 -0700130 EXPECT_TRUE(mProducer != nullptr);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700131 sp<IBinder> binderConsumer =
132 serviceManager->getService(CONSUMER_NAME);
133 mConsumer = interface_cast<IGraphicBufferConsumer>(binderConsumer);
Yi Konga03e0442018-07-17 11:16:57 -0700134 EXPECT_TRUE(mConsumer != nullptr);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700135
Peiyong Lind8460c82020-07-28 16:04:22 -0700136 sp<MockConsumer> mc(new MockConsumer);
137 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Dan Stoza1a0b8612014-03-20 15:36:31 -0700138 IGraphicBufferProducer::QueueBufferOutput output;
139 ASSERT_EQ(OK,
Yi Konga03e0442018-07-17 11:16:57 -0700140 mProducer->connect(nullptr, NATIVE_WINDOW_API_CPU, false, &output));
Dan Stoza1a0b8612014-03-20 15:36:31 -0700141
142 int slot;
143 sp<Fence> fence;
144 sp<GraphicBuffer> buffer;
145 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600146 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
147 nullptr, nullptr));
Dan Stoza1a0b8612014-03-20 15:36:31 -0700148 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
149
150 uint32_t* dataIn;
151 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
152 reinterpret_cast<void**>(&dataIn)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700153 *dataIn = TEST_DATA;
Dan Stoza1a0b8612014-03-20 15:36:31 -0700154 ASSERT_EQ(OK, buffer->unlock());
155
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800156 IGraphicBufferProducer::QueueBufferInput input(0, false,
157 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700158 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700159 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
160
Dan Stozacf3834d2015-03-11 14:04:22 -0700161 BufferItem item;
Dan Stoza1a0b8612014-03-20 15:36:31 -0700162 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
163
164 uint32_t* dataOut;
165 ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
166 reinterpret_cast<void**>(&dataOut)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700167 ASSERT_EQ(*dataOut, TEST_DATA);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700168 ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
169}
170
silence_dogoode9d092a2019-06-19 16:14:53 -0700171TEST_F(BufferQueueTest, GetMaxBufferCountInQueueBufferOutput_Succeeds) {
172 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700173 sp<MockConsumer> mc(new MockConsumer);
174 mConsumer->consumerConnect(mc, false);
silence_dogoode9d092a2019-06-19 16:14:53 -0700175 int bufferCount = 50;
176 mConsumer->setMaxBufferCount(bufferCount);
177
178 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700179 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output);
silence_dogoode9d092a2019-06-19 16:14:53 -0700180 ASSERT_EQ(output.maxBufferCount, bufferCount);
181}
182
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700183TEST_F(BufferQueueTest, AcquireBuffer_ExceedsMaxAcquireCount_Fails) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700184 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700185 sp<MockConsumer> mc(new MockConsumer);
186 mConsumer->consumerConnect(mc, false);
Andy McFadden2adaf042012-12-18 09:49:45 -0800187 IGraphicBufferProducer::QueueBufferOutput qbo;
Peiyong Lind8460c82020-07-28 16:04:22 -0700188 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &qbo);
Pablo Ceballosfa455352015-08-12 17:47:47 -0700189 mProducer->setMaxDequeuedBufferCount(3);
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700190
191 int slot;
192 sp<Fence> fence;
193 sp<GraphicBuffer> buf;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800194 IGraphicBufferProducer::QueueBufferInput qbi(0, false,
195 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700196 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Dan Stozacf3834d2015-03-11 14:04:22 -0700197 BufferItem item;
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700198
199 for (int i = 0; i < 2; i++) {
Andy McFadden2adaf042012-12-18 09:49:45 -0800200 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600201 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
202 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800203 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
204 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
205 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700206 }
207
Andy McFadden2adaf042012-12-18 09:49:45 -0800208 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600209 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
210 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800211 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
212 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700213
214 // Acquire the third buffer, which should fail.
Dan Stoza9f3053d2014-03-06 15:14:33 -0800215 ASSERT_EQ(INVALID_OPERATION, mConsumer->acquireBuffer(&item, 0));
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700216}
217
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700218TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithIllegalValues_ReturnsError) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700219 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700220 sp<MockConsumer> mc(new MockConsumer);
221 mConsumer->consumerConnect(mc, false);
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700222
Pablo Ceballos72daab62015-12-07 16:38:43 -0800223 EXPECT_EQ(OK, mConsumer->setMaxBufferCount(10));
224 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(10));
225
226 IGraphicBufferProducer::QueueBufferOutput qbo;
Peiyong Lind8460c82020-07-28 16:04:22 -0700227 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &qbo);
Pablo Ceballos72daab62015-12-07 16:38:43 -0800228 mProducer->setMaxDequeuedBufferCount(3);
229
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800230 int minBufferCount;
231 ASSERT_NO_FATAL_FAILURE(GetMinUndequeuedBufferCount(&minBufferCount));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800232 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(
233 minBufferCount - 1));
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800234
Dan Stoza9f3053d2014-03-06 15:14:33 -0800235 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(0));
236 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(-3));
237 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700238 BufferQueue::MAX_MAX_ACQUIRED_BUFFERS+1));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800239 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(100));
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700240
Pablo Ceballos72daab62015-12-07 16:38:43 -0800241 int slot;
242 sp<Fence> fence;
243 sp<GraphicBuffer> buf;
244 IGraphicBufferProducer::QueueBufferInput qbi(0, false,
245 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
246 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
247 BufferItem item;
248 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(3));
249 for (int i = 0; i < 3; i++) {
250 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600251 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
252 nullptr, nullptr));
Pablo Ceballos72daab62015-12-07 16:38:43 -0800253 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
254 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
255 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
256 }
257
258 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(2));
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700259}
260
261TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithLegalValues_Succeeds) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700262 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700263 sp<MockConsumer> mc(new MockConsumer);
264 mConsumer->consumerConnect(mc, false);
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700265
Pablo Ceballos72daab62015-12-07 16:38:43 -0800266 IGraphicBufferProducer::QueueBufferOutput qbo;
Peiyong Lind8460c82020-07-28 16:04:22 -0700267 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &qbo);
Pablo Ceballos72daab62015-12-07 16:38:43 -0800268 mProducer->setMaxDequeuedBufferCount(2);
269
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800270 int minBufferCount;
271 ASSERT_NO_FATAL_FAILURE(GetMinUndequeuedBufferCount(&minBufferCount));
272
Dan Stoza9f3053d2014-03-06 15:14:33 -0800273 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
274 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(2));
275 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(minBufferCount));
Pablo Ceballos72daab62015-12-07 16:38:43 -0800276
277 int slot;
278 sp<Fence> fence;
279 sp<GraphicBuffer> buf;
280 IGraphicBufferProducer::QueueBufferInput qbi(0, false,
281 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
282 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
283 BufferItem item;
284
285 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600286 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
287 nullptr, nullptr));
Pablo Ceballos72daab62015-12-07 16:38:43 -0800288 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
289 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
290 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
291
292 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(3));
293
294 for (int i = 0; i < 2; i++) {
295 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600296 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
297 nullptr, nullptr));
Pablo Ceballos72daab62015-12-07 16:38:43 -0800298 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
299 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
300 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
301 }
302
Dan Stoza9f3053d2014-03-06 15:14:33 -0800303 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700304 BufferQueue::MAX_MAX_ACQUIRED_BUFFERS));
305}
306
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700307TEST_F(BufferQueueTest, SetMaxBufferCountWithLegalValues_Succeeds) {
308 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700309 sp<MockConsumer> mc(new MockConsumer);
310 mConsumer->consumerConnect(mc, false);
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700311
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700312 // Test shared buffer mode
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700313 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
314}
315
316TEST_F(BufferQueueTest, SetMaxBufferCountWithIllegalValues_ReturnsError) {
317 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700318 sp<MockConsumer> mc(new MockConsumer);
319 mConsumer->consumerConnect(mc, false);
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700320
321 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(0));
322 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(
323 BufferQueue::NUM_BUFFER_SLOTS + 1));
324
325 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(5));
326 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(3));
327}
328
Dan Stoza9f3053d2014-03-06 15:14:33 -0800329TEST_F(BufferQueueTest, DetachAndReattachOnProducerSide) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700330 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700331 sp<MockConsumer> mc(new MockConsumer);
332 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800333 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700334 ASSERT_EQ(OK,
335 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800336
337 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(-1)); // Index too low
338 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(
339 BufferQueueDefs::NUM_BUFFER_SLOTS)); // Index too high
340 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(0)); // Not dequeued
341
342 int slot;
343 sp<Fence> fence;
344 sp<GraphicBuffer> buffer;
345 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600346 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
347 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800348 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(slot)); // Not requested
349 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
350 ASSERT_EQ(OK, mProducer->detachBuffer(slot));
351 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(slot)); // Not dequeued
352
353 sp<GraphicBuffer> safeToClobberBuffer;
354 // Can no longer request buffer from this slot
355 ASSERT_EQ(BAD_VALUE, mProducer->requestBuffer(slot, &safeToClobberBuffer));
356
357 uint32_t* dataIn;
358 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
359 reinterpret_cast<void**>(&dataIn)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700360 *dataIn = TEST_DATA;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800361 ASSERT_EQ(OK, buffer->unlock());
362
363 int newSlot;
Yi Konga03e0442018-07-17 11:16:57 -0700364 ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(nullptr, safeToClobberBuffer));
365 ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(&newSlot, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800366
367 ASSERT_EQ(OK, mProducer->attachBuffer(&newSlot, buffer));
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800368 IGraphicBufferProducer::QueueBufferInput input(0, false,
369 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700370 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800371 ASSERT_EQ(OK, mProducer->queueBuffer(newSlot, input, &output));
372
Dan Stozacf3834d2015-03-11 14:04:22 -0700373 BufferItem item;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800374 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
375
376 uint32_t* dataOut;
377 ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
378 reinterpret_cast<void**>(&dataOut)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700379 ASSERT_EQ(*dataOut, TEST_DATA);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700380 ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
Dan Stoza9f3053d2014-03-06 15:14:33 -0800381}
382
383TEST_F(BufferQueueTest, DetachAndReattachOnConsumerSide) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700384 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700385 sp<MockConsumer> mc(new MockConsumer);
386 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800387 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700388 ASSERT_EQ(OK,
389 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800390
391 int slot;
392 sp<Fence> fence;
393 sp<GraphicBuffer> buffer;
394 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600395 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
396 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800397 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800398 IGraphicBufferProducer::QueueBufferInput input(0, false,
399 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700400 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800401 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
402
403 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(-1)); // Index too low
404 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(
405 BufferQueueDefs::NUM_BUFFER_SLOTS)); // Index too high
406 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(0)); // Not acquired
407
Dan Stozacf3834d2015-03-11 14:04:22 -0700408 BufferItem item;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800409 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
410
Pablo Ceballos47650f42015-08-04 16:38:17 -0700411 ASSERT_EQ(OK, mConsumer->detachBuffer(item.mSlot));
412 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(item.mSlot)); // Not acquired
Dan Stoza9f3053d2014-03-06 15:14:33 -0800413
414 uint32_t* dataIn;
415 ASSERT_EQ(OK, item.mGraphicBuffer->lock(
416 GraphicBuffer::USAGE_SW_WRITE_OFTEN,
417 reinterpret_cast<void**>(&dataIn)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700418 *dataIn = TEST_DATA;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800419 ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
420
421 int newSlot;
422 sp<GraphicBuffer> safeToClobberBuffer;
Yi Konga03e0442018-07-17 11:16:57 -0700423 ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(nullptr, safeToClobberBuffer));
424 ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(&newSlot, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800425 ASSERT_EQ(OK, mConsumer->attachBuffer(&newSlot, item.mGraphicBuffer));
426
Dan Stoza99b18b42014-03-28 15:34:33 -0700427 ASSERT_EQ(OK, mConsumer->releaseBuffer(newSlot, 0, EGL_NO_DISPLAY,
Dan Stoza9f3053d2014-03-06 15:14:33 -0800428 EGL_NO_SYNC_KHR, Fence::NO_FENCE));
429
430 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600431 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
432 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800433 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
434
435 uint32_t* dataOut;
436 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
437 reinterpret_cast<void**>(&dataOut)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700438 ASSERT_EQ(*dataOut, TEST_DATA);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700439 ASSERT_EQ(OK, buffer->unlock());
Dan Stoza9f3053d2014-03-06 15:14:33 -0800440}
441
442TEST_F(BufferQueueTest, MoveFromConsumerToProducer) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700443 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700444 sp<MockConsumer> mc(new MockConsumer);
445 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800446 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700447 ASSERT_EQ(OK,
448 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800449
450 int slot;
451 sp<Fence> fence;
452 sp<GraphicBuffer> buffer;
453 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600454 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
455 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800456 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
457
458 uint32_t* dataIn;
459 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
460 reinterpret_cast<void**>(&dataIn)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700461 *dataIn = TEST_DATA;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800462 ASSERT_EQ(OK, buffer->unlock());
463
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800464 IGraphicBufferProducer::QueueBufferInput input(0, false,
465 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700466 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800467 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
468
Dan Stozacf3834d2015-03-11 14:04:22 -0700469 BufferItem item;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800470 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
Pablo Ceballos47650f42015-08-04 16:38:17 -0700471 ASSERT_EQ(OK, mConsumer->detachBuffer(item.mSlot));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800472
473 int newSlot;
474 ASSERT_EQ(OK, mProducer->attachBuffer(&newSlot, item.mGraphicBuffer));
475 ASSERT_EQ(OK, mProducer->queueBuffer(newSlot, input, &output));
476 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
477
478 uint32_t* dataOut;
479 ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
480 reinterpret_cast<void**>(&dataOut)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700481 ASSERT_EQ(*dataOut, TEST_DATA);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700482 ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
Dan Stoza9f3053d2014-03-06 15:14:33 -0800483}
484
Dan Stoza9de72932015-04-16 17:28:43 -0700485TEST_F(BufferQueueTest, TestDisallowingAllocation) {
486 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700487 sp<MockConsumer> mc(new MockConsumer);
488 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Dan Stoza9de72932015-04-16 17:28:43 -0700489 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700490 ASSERT_EQ(OK,
491 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Dan Stoza9de72932015-04-16 17:28:43 -0700492
493 static const uint32_t WIDTH = 320;
494 static const uint32_t HEIGHT = 240;
495
496 ASSERT_EQ(OK, mConsumer->setDefaultBufferSize(WIDTH, HEIGHT));
497
498 int slot;
499 sp<Fence> fence;
500 sp<GraphicBuffer> buffer;
501 // This should return an error since it would require an allocation
502 ASSERT_EQ(OK, mProducer->allowAllocation(false));
Ian Elliottd11b0442017-07-18 11:05:49 -0600503 ASSERT_EQ(WOULD_BLOCK,
504 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
505 nullptr, nullptr));
Dan Stoza9de72932015-04-16 17:28:43 -0700506
507 // This should succeed, now that we've lifted the prohibition
508 ASSERT_EQ(OK, mProducer->allowAllocation(true));
509 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600510 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
511 nullptr, nullptr));
Dan Stoza9de72932015-04-16 17:28:43 -0700512
513 // Release the previous buffer back to the BufferQueue
514 mProducer->cancelBuffer(slot, fence);
515
516 // This should fail since we're requesting a different size
517 ASSERT_EQ(OK, mProducer->allowAllocation(false));
Ian Elliottd11b0442017-07-18 11:05:49 -0600518 ASSERT_EQ(WOULD_BLOCK,
519 mProducer->dequeueBuffer(&slot, &fence, WIDTH * 2, HEIGHT * 2, 0,
520 GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr, nullptr));
Dan Stoza9de72932015-04-16 17:28:43 -0700521}
522
Dan Stoza812ed062015-06-02 15:45:22 -0700523TEST_F(BufferQueueTest, TestGenerationNumbers) {
524 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700525 sp<MockConsumer> mc(new MockConsumer);
526 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Dan Stoza812ed062015-06-02 15:45:22 -0700527 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700528 ASSERT_EQ(OK,
529 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Dan Stoza812ed062015-06-02 15:45:22 -0700530
531 ASSERT_EQ(OK, mProducer->setGenerationNumber(1));
532
533 // Get one buffer to play with
534 int slot;
535 sp<Fence> fence;
536 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Nolan Scobie9c427942023-05-01 16:41:28 -0400537 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
538 nullptr));
Dan Stoza812ed062015-06-02 15:45:22 -0700539
540 sp<GraphicBuffer> buffer;
541 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
542
543 // Ensure that the generation number we set propagates to allocated buffers
544 ASSERT_EQ(1U, buffer->getGenerationNumber());
545
546 ASSERT_EQ(OK, mProducer->detachBuffer(slot));
547
548 ASSERT_EQ(OK, mProducer->setGenerationNumber(2));
549
550 // These should fail, since we've changed the generation number on the queue
551 int outSlot;
552 ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(&outSlot, buffer));
553 ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(&outSlot, buffer));
554
555 buffer->setGenerationNumber(2);
556
557 // This should succeed now that we've changed the buffer's generation number
558 ASSERT_EQ(OK, mProducer->attachBuffer(&outSlot, buffer));
559
560 ASSERT_EQ(OK, mProducer->detachBuffer(outSlot));
561
562 // This should also succeed with the new generation number
563 ASSERT_EQ(OK, mConsumer->attachBuffer(&outSlot, buffer));
564}
565
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700566TEST_F(BufferQueueTest, TestSharedBufferModeWithoutAutoRefresh) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700567 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700568 sp<MockConsumer> mc(new MockConsumer);
569 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700570 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700571 ASSERT_EQ(OK,
572 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700573
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700574 ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700575
576 // Get a buffer
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700577 int sharedSlot;
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700578 sp<Fence> fence;
579 sp<GraphicBuffer> buffer;
580 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Nolan Scobie9c427942023-05-01 16:41:28 -0400581 mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
582 nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700583 ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700584
585 // Queue the buffer
586 IGraphicBufferProducer::QueueBufferInput input(0, false,
587 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
588 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700589 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700590
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800591 // Repeatedly queue and dequeue a buffer from the producer side, it should
592 // always return the same one. And we won't run out of buffers because it's
593 // always the same one and because async mode gets enabled.
594 int slot;
595 for (int i = 0; i < 5; i++) {
Nolan Scobie9c427942023-05-01 16:41:28 -0400596 ASSERT_EQ(OK,
597 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
598 nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700599 ASSERT_EQ(sharedSlot, slot);
600 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800601 }
602
603 // acquire the buffer
604 BufferItem item;
605 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700606 ASSERT_EQ(sharedSlot, item.mSlot);
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800607 testBufferItem(input, item);
608 ASSERT_EQ(true, item.mQueuedBuffer);
609 ASSERT_EQ(false, item.mAutoRefresh);
610
611 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
612 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
613
614 // attempt to acquire a second time should return no buffer available
615 ASSERT_EQ(IGraphicBufferConsumer::NO_BUFFER_AVAILABLE,
616 mConsumer->acquireBuffer(&item, 0));
617}
618
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700619TEST_F(BufferQueueTest, TestSharedBufferModeWithAutoRefresh) {
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800620 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700621 sp<MockConsumer> mc(new MockConsumer);
622 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800623 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700624 ASSERT_EQ(OK,
625 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800626
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700627 ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800628 ASSERT_EQ(OK, mProducer->setAutoRefresh(true));
629
630 // Get a buffer
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700631 int sharedSlot;
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800632 sp<Fence> fence;
633 sp<GraphicBuffer> buffer;
634 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Nolan Scobie9c427942023-05-01 16:41:28 -0400635 mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
636 nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700637 ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800638
639 // Queue the buffer
640 IGraphicBufferProducer::QueueBufferInput input(0, false,
641 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
642 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700643 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800644
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700645 // Repeatedly acquire and release a buffer from the consumer side, it should
646 // always return the same one.
647 BufferItem item;
648 for (int i = 0; i < 5; i++) {
649 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700650 ASSERT_EQ(sharedSlot, item.mSlot);
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800651 testBufferItem(input, item);
652 ASSERT_EQ(i == 0, item.mQueuedBuffer);
653 ASSERT_EQ(true, item.mAutoRefresh);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700654
655 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
656 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
657 }
658
659 // Repeatedly queue and dequeue a buffer from the producer side, it should
660 // always return the same one.
661 int slot;
662 for (int i = 0; i < 5; i++) {
Nolan Scobie9c427942023-05-01 16:41:28 -0400663 ASSERT_EQ(OK,
664 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
665 nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700666 ASSERT_EQ(sharedSlot, slot);
667 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700668 }
669
670 // Repeatedly acquire and release a buffer from the consumer side, it should
671 // always return the same one. First grabbing them from the queue and then
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700672 // when the queue is empty, returning the shared buffer.
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700673 for (int i = 0; i < 10; i++) {
674 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700675 ASSERT_EQ(sharedSlot, item.mSlot);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700676 ASSERT_EQ(0, item.mTimestamp);
677 ASSERT_EQ(false, item.mIsAutoTimestamp);
678 ASSERT_EQ(HAL_DATASPACE_UNKNOWN, item.mDataSpace);
679 ASSERT_EQ(Rect(0, 0, 1, 1), item.mCrop);
680 ASSERT_EQ(NATIVE_WINDOW_SCALING_MODE_FREEZE, item.mScalingMode);
Dan Stoza5ecfb682016-01-04 17:01:02 -0800681 ASSERT_EQ(0u, item.mTransform);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700682 ASSERT_EQ(Fence::NO_FENCE, item.mFence);
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800683 ASSERT_EQ(i == 0, item.mQueuedBuffer);
684 ASSERT_EQ(true, item.mAutoRefresh);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700685
686 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
687 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
688 }
689}
690
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700691TEST_F(BufferQueueTest, TestSharedBufferModeUsingAlreadyDequeuedBuffer) {
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700692 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700693 sp<MockConsumer> mc(new MockConsumer);
694 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700695 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700696 ASSERT_EQ(OK,
697 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700698
699 // Dequeue a buffer
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700700 int sharedSlot;
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700701 sp<Fence> fence;
702 sp<GraphicBuffer> buffer;
703 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Nolan Scobie9c427942023-05-01 16:41:28 -0400704 mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
705 nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700706 ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700707
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700708 // Enable shared buffer mode
709 ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700710
711 // Queue the buffer
712 IGraphicBufferProducer::QueueBufferInput input(0, false,
713 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
714 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700715 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700716
717 // Repeatedly queue and dequeue a buffer from the producer side, it should
718 // always return the same one. And we won't run out of buffers because it's
719 // always the same one and because async mode gets enabled.
720 int slot;
721 for (int i = 0; i < 5; i++) {
Nolan Scobie9c427942023-05-01 16:41:28 -0400722 ASSERT_EQ(OK,
723 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
724 nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700725 ASSERT_EQ(sharedSlot, slot);
726 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700727 }
728
729 // acquire the buffer
730 BufferItem item;
731 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700732 ASSERT_EQ(sharedSlot, item.mSlot);
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700733 testBufferItem(input, item);
734 ASSERT_EQ(true, item.mQueuedBuffer);
735 ASSERT_EQ(false, item.mAutoRefresh);
736
737 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
738 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
739
740 // attempt to acquire a second time should return no buffer available
741 ASSERT_EQ(IGraphicBufferConsumer::NO_BUFFER_AVAILABLE,
742 mConsumer->acquireBuffer(&item, 0));
743}
744
Dan Stoza127fc632015-06-30 13:43:32 -0700745TEST_F(BufferQueueTest, TestTimeouts) {
746 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700747 sp<MockConsumer> mc(new MockConsumer);
748 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Dan Stoza127fc632015-06-30 13:43:32 -0700749 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700750 ASSERT_EQ(OK,
751 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Dan Stoza127fc632015-06-30 13:43:32 -0700752
753 // Fill up the queue. Since the controlledByApp flags are set to true, this
754 // queue should be in non-blocking mode, and we should be recycling the same
755 // two buffers
756 for (int i = 0; i < 5; ++i) {
757 int slot = BufferQueue::INVALID_BUFFER_SLOT;
758 sp<Fence> fence = Fence::NO_FENCE;
Nolan Scobie9c427942023-05-01 16:41:28 -0400759 auto result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
760 nullptr, nullptr);
Dan Stoza127fc632015-06-30 13:43:32 -0700761 if (i < 2) {
762 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
763 result);
764 } else {
765 ASSERT_EQ(OK, result);
766 }
767 sp<GraphicBuffer> buffer;
768 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
769 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
770 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
771 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
772 IGraphicBufferProducer::QueueBufferOutput output{};
773 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
774 }
775
776 const auto TIMEOUT = ms2ns(250);
777 mProducer->setDequeueTimeout(TIMEOUT);
778
779 // Setting a timeout will change the BufferQueue into blocking mode (with
780 // one droppable buffer in the queue and one free from the previous
781 // dequeue/queues), so dequeue and queue two more buffers: one to replace
782 // the current droppable buffer, and a second to max out the buffer count
783 sp<GraphicBuffer> buffer; // Save a buffer to attach later
784 for (int i = 0; i < 2; ++i) {
785 int slot = BufferQueue::INVALID_BUFFER_SLOT;
786 sp<Fence> fence = Fence::NO_FENCE;
Nolan Scobie9c427942023-05-01 16:41:28 -0400787 ASSERT_EQ(OK,
788 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
789 nullptr, nullptr));
Dan Stoza127fc632015-06-30 13:43:32 -0700790 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
791 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
792 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
793 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
794 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
795 }
796
797 int slot = BufferQueue::INVALID_BUFFER_SLOT;
798 sp<Fence> fence = Fence::NO_FENCE;
799 auto startTime = systemTime();
Nolan Scobie9c427942023-05-01 16:41:28 -0400800 ASSERT_EQ(TIMED_OUT,
801 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
802 nullptr));
Dan Stoza127fc632015-06-30 13:43:32 -0700803 ASSERT_GE(systemTime() - startTime, TIMEOUT);
804
805 // We're technically attaching the same buffer multiple times (since we
806 // queued it previously), but that doesn't matter for this test
807 startTime = systemTime();
808 ASSERT_EQ(TIMED_OUT, mProducer->attachBuffer(&slot, buffer));
809 ASSERT_GE(systemTime() - startTime, TIMEOUT);
810}
811
Dan Stoza5ecfb682016-01-04 17:01:02 -0800812TEST_F(BufferQueueTest, CanAttachWhileDisallowingAllocation) {
813 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700814 sp<MockConsumer> mc(new MockConsumer);
815 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Dan Stoza5ecfb682016-01-04 17:01:02 -0800816 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700817 ASSERT_EQ(OK,
818 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Dan Stoza5ecfb682016-01-04 17:01:02 -0800819
820 int slot = BufferQueue::INVALID_BUFFER_SLOT;
821 sp<Fence> sourceFence;
822 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Nolan Scobie9c427942023-05-01 16:41:28 -0400823 mProducer->dequeueBuffer(&slot, &sourceFence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
824 nullptr, nullptr));
Dan Stoza5ecfb682016-01-04 17:01:02 -0800825 sp<GraphicBuffer> buffer;
826 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
827 ASSERT_EQ(OK, mProducer->detachBuffer(slot));
828
829 ASSERT_EQ(OK, mProducer->allowAllocation(false));
830
831 slot = BufferQueue::INVALID_BUFFER_SLOT;
832 ASSERT_EQ(OK, mProducer->attachBuffer(&slot, buffer));
833}
834
Dan Stoza50101d02016-04-07 16:53:23 -0700835TEST_F(BufferQueueTest, CanRetrieveLastQueuedBuffer) {
836 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700837 sp<MockConsumer> mc(new MockConsumer);
838 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Dan Stoza50101d02016-04-07 16:53:23 -0700839 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700840 ASSERT_EQ(OK,
841 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
Dan Stoza50101d02016-04-07 16:53:23 -0700842
843 // Dequeue and queue the first buffer, storing the handle
844 int slot = BufferQueue::INVALID_BUFFER_SLOT;
845 sp<Fence> fence;
846 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Nolan Scobie9c427942023-05-01 16:41:28 -0400847 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
848 nullptr));
Dan Stoza50101d02016-04-07 16:53:23 -0700849 sp<GraphicBuffer> firstBuffer;
850 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &firstBuffer));
851
852 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
853 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
854 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
855 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
856
857 // Dequeue a second buffer
858 slot = BufferQueue::INVALID_BUFFER_SLOT;
859 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Nolan Scobie9c427942023-05-01 16:41:28 -0400860 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
861 nullptr));
Dan Stoza50101d02016-04-07 16:53:23 -0700862 sp<GraphicBuffer> secondBuffer;
863 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &secondBuffer));
864
865 // Ensure it's a new buffer
866 ASSERT_NE(firstBuffer->getNativeBuffer()->handle,
867 secondBuffer->getNativeBuffer()->handle);
868
869 // Queue the second buffer
870 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
871
872 // Acquire and release both buffers
873 for (size_t i = 0; i < 2; ++i) {
874 BufferItem item;
875 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
876 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
877 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
878 }
879
880 // Make sure we got the second buffer back
881 sp<GraphicBuffer> returnedBuffer;
882 sp<Fence> returnedFence;
John Reck1a61da52016-04-28 13:18:15 -0700883 float transform[16];
Dan Stoza50101d02016-04-07 16:53:23 -0700884 ASSERT_EQ(OK,
John Reck1a61da52016-04-28 13:18:15 -0700885 mProducer->getLastQueuedBuffer(&returnedBuffer, &returnedFence,
886 transform));
Dan Stoza50101d02016-04-07 16:53:23 -0700887 ASSERT_EQ(secondBuffer->getNativeBuffer()->handle,
888 returnedBuffer->getNativeBuffer()->handle);
889}
890
Dan Stozae77c7662016-05-13 11:37:28 -0700891TEST_F(BufferQueueTest, TestOccupancyHistory) {
892 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700893 sp<MockConsumer> mc(new MockConsumer);
894 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Dan Stozae77c7662016-05-13 11:37:28 -0700895 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700896 ASSERT_EQ(OK,
897 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
Dan Stozae77c7662016-05-13 11:37:28 -0700898
899 int slot = BufferQueue::INVALID_BUFFER_SLOT;
900 sp<Fence> fence = Fence::NO_FENCE;
901 sp<GraphicBuffer> buffer = nullptr;
902 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
903 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
904 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
905 BufferItem item{};
906
907 // Preallocate, dequeue, request, and cancel 3 buffers so we don't get
908 // BUFFER_NEEDS_REALLOCATION below
909 int slots[3] = {};
910 mProducer->setMaxDequeuedBufferCount(3);
911 for (size_t i = 0; i < 3; ++i) {
Nolan Scobie9c427942023-05-01 16:41:28 -0400912 status_t result = mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0,
913 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr);
Dan Stozae77c7662016-05-13 11:37:28 -0700914 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
915 ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
916 }
917 for (size_t i = 0; i < 3; ++i) {
918 ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE));
919 }
920
921 // Create 3 segments
922
923 // The first segment is a two-buffer segment, so we only put one buffer into
924 // the queue at a time
925 for (size_t i = 0; i < 5; ++i) {
Nolan Scobie9c427942023-05-01 16:41:28 -0400926 ASSERT_EQ(OK,
927 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
928 nullptr, nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700929 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
930 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
931 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
932 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
933 std::this_thread::sleep_for(16ms);
934 }
935
936 // Sleep between segments
937 std::this_thread::sleep_for(500ms);
938
939 // The second segment is a double-buffer segment. It starts the same as the
940 // two-buffer segment, but then at the end, we put two buffers in the queue
941 // at the same time before draining it.
942 for (size_t i = 0; i < 5; ++i) {
Nolan Scobie9c427942023-05-01 16:41:28 -0400943 ASSERT_EQ(OK,
944 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
945 nullptr, nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700946 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
947 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
948 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
949 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
950 std::this_thread::sleep_for(16ms);
951 }
Nolan Scobie9c427942023-05-01 16:41:28 -0400952 ASSERT_EQ(OK,
953 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
954 nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700955 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
Nolan Scobie9c427942023-05-01 16:41:28 -0400956 ASSERT_EQ(OK,
957 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
958 nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700959 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
960 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
961 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
962 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
963 std::this_thread::sleep_for(16ms);
964 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
965 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
966 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
967
968 // Sleep between segments
969 std::this_thread::sleep_for(500ms);
970
971 // The third segment is a triple-buffer segment, so the queue is switching
972 // between one buffer and two buffers deep.
Nolan Scobie9c427942023-05-01 16:41:28 -0400973 ASSERT_EQ(OK,
974 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
975 nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700976 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
977 for (size_t i = 0; i < 5; ++i) {
Nolan Scobie9c427942023-05-01 16:41:28 -0400978 ASSERT_EQ(OK,
979 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
980 nullptr, nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700981 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
982 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
983 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
984 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
985 std::this_thread::sleep_for(16ms);
986 }
987 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
988 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
989 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
990
991 // Now we read the segments
992 std::vector<OccupancyTracker::Segment> history;
993 ASSERT_EQ(OK, mConsumer->getOccupancyHistory(false, &history));
994
995 // Since we didn't force a flush, we should only get the first two segments
996 // (since the third segment hasn't been closed out by the appearance of a
997 // new segment yet)
998 ASSERT_EQ(2u, history.size());
999
1000 // The first segment (which will be history[1], since the newest segment
1001 // should be at the front of the vector) should be a two-buffer segment,
1002 // which implies that the occupancy average should be between 0 and 1, and
1003 // usedThirdBuffer should be false
1004 const auto& firstSegment = history[1];
1005 ASSERT_EQ(5u, firstSegment.numFrames);
1006 ASSERT_LT(0, firstSegment.occupancyAverage);
1007 ASSERT_GT(1, firstSegment.occupancyAverage);
1008 ASSERT_EQ(false, firstSegment.usedThirdBuffer);
1009
1010 // The second segment should be a double-buffered segment, which implies that
1011 // the occupancy average should be between 0 and 1, but usedThirdBuffer
1012 // should be true
1013 const auto& secondSegment = history[0];
1014 ASSERT_EQ(7u, secondSegment.numFrames);
1015 ASSERT_LT(0, secondSegment.occupancyAverage);
1016 ASSERT_GT(1, secondSegment.occupancyAverage);
1017 ASSERT_EQ(true, secondSegment.usedThirdBuffer);
1018
1019 // If we read the segments again without flushing, we shouldn't get any new
1020 // segments
1021 ASSERT_EQ(OK, mConsumer->getOccupancyHistory(false, &history));
1022 ASSERT_EQ(0u, history.size());
1023
1024 // Read the segments again, this time forcing a flush so we get the third
1025 // segment
1026 ASSERT_EQ(OK, mConsumer->getOccupancyHistory(true, &history));
1027 ASSERT_EQ(1u, history.size());
1028
1029 // This segment should be a triple-buffered segment, which implies that the
1030 // occupancy average should be between 1 and 2, and usedThirdBuffer should
1031 // be true
1032 const auto& thirdSegment = history[0];
1033 ASSERT_EQ(6u, thirdSegment.numFrames);
1034 ASSERT_LT(1, thirdSegment.occupancyAverage);
1035 ASSERT_GT(2, thirdSegment.occupancyAverage);
1036 ASSERT_EQ(true, thirdSegment.usedThirdBuffer);
1037}
1038
Shuzhen Wang067fcd32019-08-14 10:41:12 -07001039struct BufferDiscardedListener : public BnProducerListener {
1040public:
1041 BufferDiscardedListener() = default;
1042 virtual ~BufferDiscardedListener() = default;
1043
1044 virtual void onBufferReleased() {}
1045 virtual bool needsReleaseNotify() { return false; }
1046 virtual void onBuffersDiscarded(const std::vector<int32_t>& slots) {
1047 mDiscardedSlots.insert(mDiscardedSlots.end(), slots.begin(), slots.end());
1048 }
1049
1050 const std::vector<int32_t>& getDiscardedSlots() const { return mDiscardedSlots; }
1051private:
1052 // No need to use lock given the test triggers the listener in the same
1053 // thread context.
1054 std::vector<int32_t> mDiscardedSlots;
1055};
1056
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001057TEST_F(BufferQueueTest, TestDiscardFreeBuffers) {
1058 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -07001059 sp<MockConsumer> mc(new MockConsumer);
1060 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001061 IGraphicBufferProducer::QueueBufferOutput output;
Shuzhen Wang067fcd32019-08-14 10:41:12 -07001062 sp<BufferDiscardedListener> pl(new BufferDiscardedListener);
1063 ASSERT_EQ(OK, mProducer->connect(pl,
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001064 NATIVE_WINDOW_API_CPU, false, &output));
1065
1066 int slot = BufferQueue::INVALID_BUFFER_SLOT;
1067 sp<Fence> fence = Fence::NO_FENCE;
1068 sp<GraphicBuffer> buffer = nullptr;
1069 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1070 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1071 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1072 BufferItem item{};
1073
1074 // Preallocate, dequeue, request, and cancel 4 buffers so we don't get
1075 // BUFFER_NEEDS_REALLOCATION below
1076 int slots[4] = {};
1077 mProducer->setMaxDequeuedBufferCount(4);
1078 for (size_t i = 0; i < 4; ++i) {
Nolan Scobie9c427942023-05-01 16:41:28 -04001079 status_t result = mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0,
1080 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr);
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001081 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1082 ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
1083 }
1084 for (size_t i = 0; i < 4; ++i) {
1085 ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE));
1086 }
1087
1088 // Get buffers in all states: dequeued, filled, acquired, free
1089
1090 // Fill 3 buffers
Nolan Scobie9c427942023-05-01 16:41:28 -04001091 ASSERT_EQ(OK,
1092 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1093 nullptr));
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001094 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
Nolan Scobie9c427942023-05-01 16:41:28 -04001095 ASSERT_EQ(OK,
1096 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1097 nullptr));
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001098 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
Nolan Scobie9c427942023-05-01 16:41:28 -04001099 ASSERT_EQ(OK,
1100 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1101 nullptr));
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001102 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1103 // Dequeue 1 buffer
Nolan Scobie9c427942023-05-01 16:41:28 -04001104 ASSERT_EQ(OK,
1105 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1106 nullptr));
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001107
1108 // Acquire and free 1 buffer
1109 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1110 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
1111 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
Shuzhen Wang067fcd32019-08-14 10:41:12 -07001112 int releasedSlot = item.mSlot;
1113
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001114 // Acquire 1 buffer, leaving 1 filled buffer in queue
1115 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1116
1117 // Now discard the free buffers
1118 ASSERT_EQ(OK, mConsumer->discardFreeBuffers());
1119
Shuzhen Wang067fcd32019-08-14 10:41:12 -07001120 // Check onBuffersDiscarded is called with correct slots
1121 auto buffersDiscarded = pl->getDiscardedSlots();
Siarhei Vishniakoubf98a572024-03-29 13:34:42 -07001122 ASSERT_EQ(buffersDiscarded.size(), 1u);
Shuzhen Wang067fcd32019-08-14 10:41:12 -07001123 ASSERT_EQ(buffersDiscarded[0], releasedSlot);
1124
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001125 // Check no free buffers in dump
1126 String8 dumpString;
Dan Stoza0c9a1ed2017-04-06 15:10:21 -07001127 mConsumer->dumpState(String8{}, &dumpString);
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001128
1129 // Parse the dump to ensure that all buffer slots that are FREE also
1130 // have a null GraphicBuffer
1131 // Fragile - assumes the following format for the dump for a buffer entry:
1132 // ":%p\][^:]*state=FREE" where %p is the buffer pointer in hex.
1133 ssize_t idx = dumpString.find("state=FREE");
1134 while (idx != -1) {
1135 ssize_t bufferPtrIdx = idx - 1;
1136 while (bufferPtrIdx > 0) {
1137 if (dumpString[bufferPtrIdx] == ':') {
1138 bufferPtrIdx++;
1139 break;
1140 }
1141 bufferPtrIdx--;
1142 }
1143 ASSERT_GT(bufferPtrIdx, 0) << "Can't parse queue dump to validate";
1144 ssize_t nullPtrIdx = dumpString.find("0x0]", bufferPtrIdx);
1145 ASSERT_EQ(bufferPtrIdx, nullPtrIdx) << "Free buffer not discarded";
1146 idx = dumpString.find("FREE", idx + 1);
1147 }
1148}
1149
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001150TEST_F(BufferQueueTest, TestBufferReplacedInQueueBuffer) {
1151 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -07001152 sp<MockConsumer> mc(new MockConsumer);
1153 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001154 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -07001155 ASSERT_EQ(OK,
1156 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001157 ASSERT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
1158
1159 int slot = BufferQueue::INVALID_BUFFER_SLOT;
1160 sp<Fence> fence = Fence::NO_FENCE;
1161 sp<GraphicBuffer> buffer = nullptr;
1162 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1163 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1164 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1165 BufferItem item{};
1166
1167 // Preallocate, dequeue, request, and cancel 2 buffers so we don't get
1168 // BUFFER_NEEDS_REALLOCATION below
1169 int slots[2] = {};
1170 ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(2));
1171 for (size_t i = 0; i < 2; ++i) {
Nolan Scobie9c427942023-05-01 16:41:28 -04001172 status_t result = mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0,
1173 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr);
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001174 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1175 ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
1176 }
1177 for (size_t i = 0; i < 2; ++i) {
1178 ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE));
1179 }
1180
1181 // Fill 2 buffers without consumer consuming them. Verify that all
1182 // queued buffer returns proper bufferReplaced flag
Nolan Scobie9c427942023-05-01 16:41:28 -04001183 ASSERT_EQ(OK,
1184 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1185 nullptr));
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001186 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1187 ASSERT_EQ(false, output.bufferReplaced);
Nolan Scobie9c427942023-05-01 16:41:28 -04001188 ASSERT_EQ(OK,
1189 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1190 nullptr));
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001191 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1192 ASSERT_EQ(true, output.bufferReplaced);
1193}
1194
Sungtak Lee1e7c09b2023-10-26 08:44:21 +00001195struct BufferDetachedListener : public BnProducerListener {
1196public:
1197 BufferDetachedListener() = default;
1198 virtual ~BufferDetachedListener() = default;
1199
1200 virtual void onBufferReleased() {}
1201 virtual bool needsReleaseNotify() { return true; }
1202 virtual void onBufferDetached(int slot) {
1203 mDetachedSlots.push_back(slot);
1204 }
1205 const std::vector<int>& getDetachedSlots() const { return mDetachedSlots; }
1206private:
1207 std::vector<int> mDetachedSlots;
1208};
1209
1210TEST_F(BufferQueueTest, TestConsumerDetachProducerListener) {
1211 createBufferQueue();
1212 sp<MockConsumer> mc(new MockConsumer);
1213 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
1214 IGraphicBufferProducer::QueueBufferOutput output;
1215 sp<BufferDetachedListener> pl(new BufferDetachedListener);
1216 ASSERT_EQ(OK, mProducer->connect(pl, NATIVE_WINDOW_API_CPU, true, &output));
1217 ASSERT_EQ(OK, mProducer->setDequeueTimeout(0));
1218 ASSERT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
1219
1220 sp<Fence> fence = Fence::NO_FENCE;
1221 sp<GraphicBuffer> buffer = nullptr;
1222 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1223 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1224 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1225
1226 int slots[2] = {};
1227 status_t result = OK;
1228 ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(2));
1229
1230 result = mProducer->dequeueBuffer(&slots[0], &fence, 0, 0, 0,
1231 GRALLOC_USAGE_SW_READ_RARELY, nullptr, nullptr);
1232 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1233 ASSERT_EQ(OK, mProducer->requestBuffer(slots[0], &buffer));
1234
1235 result = mProducer->dequeueBuffer(&slots[1], &fence, 0, 0, 0,
1236 GRALLOC_USAGE_SW_READ_RARELY, nullptr, nullptr);
1237 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1238 ASSERT_EQ(OK, mProducer->requestBuffer(slots[1], &buffer));
1239
1240 // Queue & detach one from two dequeued buffes.
1241 ASSERT_EQ(OK, mProducer->queueBuffer(slots[1], input, &output));
1242 BufferItem item{};
1243 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1244 ASSERT_EQ(OK, mConsumer->detachBuffer(item.mSlot));
1245
1246 // Check whether the slot from IProducerListener is same to the detached slot.
Siarhei Vishniakoubf98a572024-03-29 13:34:42 -07001247 ASSERT_EQ(pl->getDetachedSlots().size(), 1u);
Sungtak Lee1e7c09b2023-10-26 08:44:21 +00001248 ASSERT_EQ(pl->getDetachedSlots()[0], slots[1]);
1249
1250 // Dequeue another buffer.
1251 int slot;
1252 result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
1253 GRALLOC_USAGE_SW_READ_RARELY, nullptr, nullptr);
1254 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1255 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
1256
1257 // Dequeue should fail here, since we dequeued 3 buffers and one buffer was
1258 // detached from consumer(Two buffers are dequeued, and the current max
1259 // dequeued buffer count is two).
1260 result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
1261 GRALLOC_USAGE_SW_READ_RARELY, nullptr, nullptr);
1262 ASSERT_TRUE(result == WOULD_BLOCK || result == TIMED_OUT || result == INVALID_OPERATION);
1263}
1264
Sungtak Leecd217472024-07-19 17:17:40 +00001265#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_CONSUMER_ATTACH_CALLBACK)
1266struct BufferAttachedListener : public BnProducerListener {
1267public:
1268 BufferAttachedListener(bool enable) : mEnabled(enable), mAttached(0) {}
1269 virtual ~BufferAttachedListener() = default;
1270
1271 virtual void onBufferReleased() {}
1272 virtual bool needsReleaseNotify() { return true; }
1273 virtual void onBufferAttached() {
1274 ++mAttached;
1275 }
1276 virtual bool needsAttachNotify() { return mEnabled; }
1277
1278 int getNumAttached() const { return mAttached; }
1279private:
1280 const bool mEnabled;
1281 int mAttached;
1282};
1283
1284TEST_F(BufferQueueTest, TestConsumerAttachProducerListener) {
1285 createBufferQueue();
1286 sp<MockConsumer> mc1(new MockConsumer);
1287 ASSERT_EQ(OK, mConsumer->consumerConnect(mc1, true));
1288 IGraphicBufferProducer::QueueBufferOutput output;
1289 // Do not enable attach callback.
1290 sp<BufferAttachedListener> pl1(new BufferAttachedListener(false));
1291 ASSERT_EQ(OK, mProducer->connect(pl1, NATIVE_WINDOW_API_CPU, true, &output));
1292 ASSERT_EQ(OK, mProducer->setDequeueTimeout(0));
1293 ASSERT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
1294
1295 sp<Fence> fence = Fence::NO_FENCE;
1296 sp<GraphicBuffer> buffer = nullptr;
1297
1298 int slot;
1299 status_t result = OK;
1300
1301 ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(1));
1302
1303 result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
1304 GRALLOC_USAGE_SW_READ_RARELY, nullptr, nullptr);
1305 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1306 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
1307 ASSERT_EQ(OK, mProducer->detachBuffer(slot));
1308
1309 // Check # of attach is zero.
1310 ASSERT_EQ(0, pl1->getNumAttached());
1311
1312 // Attach a buffer and check the callback was not called.
1313 ASSERT_EQ(OK, mConsumer->attachBuffer(&slot, buffer));
1314 ASSERT_EQ(0, pl1->getNumAttached());
1315
1316 mProducer = nullptr;
1317 mConsumer = nullptr;
1318 createBufferQueue();
1319
1320 sp<MockConsumer> mc2(new MockConsumer);
1321 ASSERT_EQ(OK, mConsumer->consumerConnect(mc2, true));
1322 // Enable attach callback.
1323 sp<BufferAttachedListener> pl2(new BufferAttachedListener(true));
1324 ASSERT_EQ(OK, mProducer->connect(pl2, NATIVE_WINDOW_API_CPU, true, &output));
1325 ASSERT_EQ(OK, mProducer->setDequeueTimeout(0));
1326 ASSERT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
1327
1328 fence = Fence::NO_FENCE;
1329 buffer = nullptr;
1330
1331 result = OK;
1332
1333 ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(1));
1334
1335 result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
1336 GRALLOC_USAGE_SW_READ_RARELY, nullptr, nullptr);
1337 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1338 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
1339 ASSERT_EQ(OK, mProducer->detachBuffer(slot));
1340
1341 // Check # of attach is zero.
1342 ASSERT_EQ(0, pl2->getNumAttached());
1343
1344 // Attach a buffer and check the callback was called.
1345 ASSERT_EQ(OK, mConsumer->attachBuffer(&slot, buffer));
1346 ASSERT_EQ(1, pl2->getNumAttached());
1347}
1348#endif
1349
Dan Stozad4c6f992017-03-21 13:43:22 -07001350TEST_F(BufferQueueTest, TestStaleBufferHandleSentAfterDisconnect) {
1351 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -07001352 sp<MockConsumer> mc(new MockConsumer);
1353 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Dan Stozad4c6f992017-03-21 13:43:22 -07001354 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -07001355 sp<IProducerListener> fakeListener(new StubProducerListener);
1356 ASSERT_EQ(OK, mProducer->connect(fakeListener, NATIVE_WINDOW_API_CPU, true, &output));
Dan Stozad4c6f992017-03-21 13:43:22 -07001357
1358 int slot = BufferQueue::INVALID_BUFFER_SLOT;
1359 sp<Fence> fence = Fence::NO_FENCE;
1360 sp<GraphicBuffer> buffer = nullptr;
1361 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1362 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1363 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1364
1365 // Dequeue, request, and queue one buffer
Nolan Scobie9c427942023-05-01 16:41:28 -04001366 status_t result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
1367 nullptr, nullptr);
Dan Stozad4c6f992017-03-21 13:43:22 -07001368 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1369 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
1370 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1371
1372 // Acquire and release the buffer. Upon acquiring, the buffer handle should
1373 // be non-null since this is the first time we've acquired this slot.
1374 BufferItem item;
1375 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1376 ASSERT_EQ(slot, item.mSlot);
1377 ASSERT_NE(nullptr, item.mGraphicBuffer.get());
1378 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
1379 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
1380
1381 // Dequeue and queue the buffer again
Nolan Scobie9c427942023-05-01 16:41:28 -04001382 ASSERT_EQ(OK,
1383 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1384 nullptr));
Dan Stozad4c6f992017-03-21 13:43:22 -07001385 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1386
1387 // Acquire and release the buffer again. Upon acquiring, the buffer handle
1388 // should be null since this is not the first time we've acquired this slot.
1389 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1390 ASSERT_EQ(slot, item.mSlot);
1391 ASSERT_EQ(nullptr, item.mGraphicBuffer.get());
1392 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
1393 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
1394
1395 // Dequeue and queue the buffer again
Nolan Scobie9c427942023-05-01 16:41:28 -04001396 ASSERT_EQ(OK,
1397 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1398 nullptr));
Dan Stozad4c6f992017-03-21 13:43:22 -07001399 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1400
1401 // Disconnect the producer end. This should clear all of the slots and mark
1402 // the buffer in the queue as stale.
1403 ASSERT_EQ(OK, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
1404
1405 // Acquire the buffer again. Upon acquiring, the buffer handle should not be
1406 // null since the queued buffer should have been marked as stale, which
1407 // should trigger the BufferQueue to resend the buffer handle.
1408 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1409 ASSERT_EQ(slot, item.mSlot);
1410 ASSERT_NE(nullptr, item.mGraphicBuffer.get());
1411}
1412
Wonsik Kim3e198b22017-04-07 15:43:16 -07001413TEST_F(BufferQueueTest, TestProducerConnectDisconnect) {
1414 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -07001415 sp<MockConsumer> mc(new MockConsumer);
1416 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Wonsik Kim3e198b22017-04-07 15:43:16 -07001417 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -07001418 sp<IProducerListener> fakeListener(new StubProducerListener);
Wonsik Kim3e198b22017-04-07 15:43:16 -07001419 ASSERT_EQ(NO_INIT, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
Peiyong Lind8460c82020-07-28 16:04:22 -07001420 ASSERT_EQ(OK, mProducer->connect(fakeListener, NATIVE_WINDOW_API_CPU, true, &output));
1421 ASSERT_EQ(BAD_VALUE, mProducer->connect(fakeListener, NATIVE_WINDOW_API_MEDIA, true, &output));
Wonsik Kim3e198b22017-04-07 15:43:16 -07001422
1423 ASSERT_EQ(BAD_VALUE, mProducer->disconnect(NATIVE_WINDOW_API_MEDIA));
1424 ASSERT_EQ(OK, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
1425 ASSERT_EQ(NO_INIT, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
1426}
1427
Ady Abraham6cdd3fd2023-09-07 18:45:58 -07001428TEST_F(BufferQueueTest, TestBqSetFrameRateFlagBuildTimeIsSet) {
Ady Abraham107788e2023-10-17 12:31:08 -07001429 ASSERT_EQ(flags::bq_setframerate(), COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_SETFRAMERATE));
Ady Abraham6cdd3fd2023-09-07 18:45:58 -07001430}
1431
1432struct BufferItemConsumerSetFrameRateListener : public BufferItemConsumer {
Jim Shargod30823a2024-07-27 02:49:39 +00001433 BufferItemConsumerSetFrameRateListener() : BufferItemConsumer(GRALLOC_USAGE_SW_READ_OFTEN, 1) {}
Ady Abraham6cdd3fd2023-09-07 18:45:58 -07001434
1435 MOCK_METHOD(void, onSetFrameRate, (float, int8_t, int8_t), (override));
1436};
1437
1438TEST_F(BufferQueueTest, TestSetFrameRate) {
Ady Abraham6cdd3fd2023-09-07 18:45:58 -07001439 sp<BufferItemConsumerSetFrameRateListener> bufferConsumer =
Jim Shargod30823a2024-07-27 02:49:39 +00001440 sp<BufferItemConsumerSetFrameRateListener>::make();
1441 sp<IGraphicBufferProducer> producer = bufferConsumer->getSurface()->getIGraphicBufferProducer();
Ady Abraham6cdd3fd2023-09-07 18:45:58 -07001442
1443 EXPECT_CALL(*bufferConsumer, onSetFrameRate(12.34f, 1, 0)).Times(1);
1444 producer->setFrameRate(12.34f, 1, 0);
1445}
1446
John Reck12daff92023-07-28 16:36:27 -04001447class Latch {
1448public:
1449 explicit Latch(int expected) : mExpected(expected) {}
1450 Latch(const Latch&) = delete;
1451 Latch& operator=(const Latch&) = delete;
1452
1453 void CountDown() {
1454 std::unique_lock<std::mutex> lock(mLock);
1455 mExpected--;
1456 if (mExpected <= 0) {
1457 mCV.notify_all();
1458 }
1459 }
1460
1461 void Wait() {
1462 std::unique_lock<std::mutex> lock(mLock);
1463 mCV.wait(lock, [&] { return mExpected == 0; });
1464 }
1465
1466private:
1467 int mExpected;
1468 std::mutex mLock;
1469 std::condition_variable mCV;
1470};
1471
1472struct OneshotOnDequeuedListener final : public BufferItemConsumer::FrameAvailableListener {
1473 OneshotOnDequeuedListener(std::function<void()>&& oneshot)
1474 : mOneshotRunnable(std::move(oneshot)) {}
1475
1476 std::function<void()> mOneshotRunnable;
1477
1478 void run() {
1479 if (mOneshotRunnable) {
1480 mOneshotRunnable();
1481 mOneshotRunnable = nullptr;
1482 }
1483 }
1484
1485 void onFrameDequeued(const uint64_t) override { run(); }
1486
1487 void onFrameAvailable(const BufferItem&) override {}
1488};
1489
1490// See b/270004534
1491TEST(BufferQueueThreading, TestProducerDequeueConsumerDestroy) {
John Reck12daff92023-07-28 16:36:27 -04001492 sp<BufferItemConsumer> bufferConsumer =
Jim Shargod30823a2024-07-27 02:49:39 +00001493 sp<BufferItemConsumer>::make(GRALLOC_USAGE_SW_READ_OFTEN, 2);
John Reck12daff92023-07-28 16:36:27 -04001494 ASSERT_NE(nullptr, bufferConsumer.get());
Jim Shargod30823a2024-07-27 02:49:39 +00001495 sp<Surface> surface = bufferConsumer->getSurface();
John Reck12daff92023-07-28 16:36:27 -04001496 native_window_set_buffers_format(surface.get(), PIXEL_FORMAT_RGBA_8888);
1497 native_window_set_buffers_dimensions(surface.get(), 100, 100);
1498
1499 Latch triggerDisconnect(1);
1500 Latch resumeCallback(1);
1501 auto luckyListener = sp<OneshotOnDequeuedListener>::make([&]() {
1502 triggerDisconnect.CountDown();
1503 resumeCallback.Wait();
1504 });
1505 bufferConsumer->setFrameAvailableListener(luckyListener);
1506
1507 std::future<void> disconnecter = std::async(std::launch::async, [&]() {
1508 triggerDisconnect.Wait();
1509 luckyListener = nullptr;
1510 bufferConsumer = nullptr;
1511 resumeCallback.CountDown();
1512 });
1513
1514 std::future<void> render = std::async(std::launch::async, [=]() {
1515 ANativeWindow_Buffer buffer;
1516 surface->lock(&buffer, nullptr);
1517 surface->unlockAndPost();
1518 });
1519
1520 ASSERT_EQ(std::future_status::ready, render.wait_for(1s));
1521 EXPECT_EQ(nullptr, luckyListener.get());
1522 EXPECT_EQ(nullptr, bufferConsumer.get());
1523}
1524
John Reckdb164ff2024-04-03 16:59:28 -04001525TEST_F(BufferQueueTest, TestAdditionalOptions) {
John Reckdb164ff2024-04-03 16:59:28 -04001526 sp<BufferItemConsumer> bufferConsumer =
Jim Shargod30823a2024-07-27 02:49:39 +00001527 sp<BufferItemConsumer>::make(GRALLOC_USAGE_SW_READ_OFTEN, 2);
John Reckdb164ff2024-04-03 16:59:28 -04001528 ASSERT_NE(nullptr, bufferConsumer.get());
Jim Shargod30823a2024-07-27 02:49:39 +00001529 sp<Surface> surface = bufferConsumer->getSurface();
John Reckdb164ff2024-04-03 16:59:28 -04001530 native_window_set_buffers_format(surface.get(), PIXEL_FORMAT_RGBA_8888);
1531 native_window_set_buffers_dimensions(surface.get(), 100, 100);
1532
1533 std::array<AHardwareBufferLongOptions, 1> extras = {{
1534 {.name = "android.hardware.graphics.common.Dataspace", ADATASPACE_DISPLAY_P3},
1535 }};
1536
1537 ASSERT_EQ(NO_INIT,
1538 native_window_set_buffers_additional_options(surface.get(), extras.data(),
1539 extras.size()));
1540
1541 if (!IsCuttlefish()) {
1542 GTEST_SKIP() << "Not cuttlefish";
1543 }
1544
1545 ASSERT_EQ(OK, native_window_api_connect(surface.get(), NATIVE_WINDOW_API_CPU));
1546 ASSERT_EQ(OK,
1547 native_window_set_buffers_additional_options(surface.get(), extras.data(),
1548 extras.size()));
1549
1550 ANativeWindowBuffer* windowBuffer = nullptr;
1551 int fence = -1;
1552 ASSERT_EQ(OK, ANativeWindow_dequeueBuffer(surface.get(), &windowBuffer, &fence));
1553
1554 AHardwareBuffer* buffer = ANativeWindowBuffer_getHardwareBuffer(windowBuffer);
1555 ASSERT_TRUE(buffer);
1556 ADataSpace dataSpace = AHardwareBuffer_getDataSpace(buffer);
1557 EXPECT_EQ(ADATASPACE_DISPLAY_P3, dataSpace);
1558
1559 ANativeWindow_cancelBuffer(surface.get(), windowBuffer, -1);
1560
1561 // Check that reconnecting properly clears the options
1562 ASSERT_EQ(OK, native_window_api_disconnect(surface.get(), NATIVE_WINDOW_API_CPU));
1563 ASSERT_EQ(OK, native_window_api_connect(surface.get(), NATIVE_WINDOW_API_CPU));
1564
1565 ASSERT_EQ(OK, ANativeWindow_dequeueBuffer(surface.get(), &windowBuffer, &fence));
1566 buffer = ANativeWindowBuffer_getHardwareBuffer(windowBuffer);
1567 ASSERT_TRUE(buffer);
1568 dataSpace = AHardwareBuffer_getDataSpace(buffer);
1569 EXPECT_EQ(ADATASPACE_UNKNOWN, dataSpace);
1570}
1571
Jamie Gennis9e75ddd2012-08-31 15:32:45 -07001572} // namespace android