blob: d1208ee5ae8ceb0d3697e69566cb7498afc62fe7 [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
Peiyong Lind8460c82020-07-28 16:04:22 -070020#include "MockConsumer.h"
Dan Stozac6f30bd2015-06-08 09:32:50 -070021
Dan Stozacf3834d2015-03-11 14:04:22 -070022#include <gui/BufferItem.h>
Dan Stozaf0eaf252014-03-21 13:05:51 -070023#include <gui/BufferQueue.h>
24#include <gui/IProducerListener.h>
Jamie Gennis9e75ddd2012-08-31 15:32:45 -070025
26#include <ui/GraphicBuffer.h>
Jamie Gennis9e75ddd2012-08-31 15:32:45 -070027
Dan Stoza1a0b8612014-03-20 15:36:31 -070028#include <binder/IPCThreadState.h>
Dan Stoza9f3053d2014-03-06 15:14:33 -080029#include <binder/IServiceManager.h>
Dan Stoza1a0b8612014-03-20 15:36:31 -070030#include <binder/ProcessState.h>
Dan Stozaf0eaf252014-03-21 13:05:51 -070031
32#include <utils/String8.h>
33#include <utils/threads.h>
34
Mathias Agopian6a3c05b2017-04-27 20:06:55 -070035#include <system/window.h>
36
Dan Stozaf0eaf252014-03-21 13:05:51 -070037#include <gtest/gtest.h>
Jamie Gennis9e75ddd2012-08-31 15:32:45 -070038
Dan Stozae77c7662016-05-13 11:37:28 -070039#include <thread>
40
41using namespace std::chrono_literals;
42
Jamie Gennis9e75ddd2012-08-31 15:32:45 -070043namespace android {
44
45class BufferQueueTest : public ::testing::Test {
Dan Stoza9f3053d2014-03-06 15:14:33 -080046
47public:
Jamie Gennis9e75ddd2012-08-31 15:32:45 -070048protected:
Dan Stoza9f3053d2014-03-06 15:14:33 -080049 BufferQueueTest() {
Jamie Gennis9e75ddd2012-08-31 15:32:45 -070050 const ::testing::TestInfo* const testInfo =
51 ::testing::UnitTest::GetInstance()->current_test_info();
52 ALOGV("Begin test: %s.%s", testInfo->test_case_name(),
53 testInfo->name());
Jamie Gennis9e75ddd2012-08-31 15:32:45 -070054 }
55
Dan Stoza9f3053d2014-03-06 15:14:33 -080056 ~BufferQueueTest() {
Jamie Gennis9e75ddd2012-08-31 15:32:45 -070057 const ::testing::TestInfo* const testInfo =
58 ::testing::UnitTest::GetInstance()->current_test_info();
59 ALOGV("End test: %s.%s", testInfo->test_case_name(),
60 testInfo->name());
61 }
62
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();
128 sp<IBinder> binderProducer =
129 serviceManager->getService(PRODUCER_NAME);
130 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,
Ian Elliottd11b0442017-07-18 11:05:49 -0600538 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, 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,
Ian Elliottd11b0442017-07-18 11:05:49 -0600581 mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700582 ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700583
584 // Queue the buffer
585 IGraphicBufferProducer::QueueBufferInput input(0, false,
586 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
587 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700588 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700589
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800590 // Repeatedly queue and dequeue a buffer from the producer side, it should
591 // always return the same one. And we won't run out of buffers because it's
592 // always the same one and because async mode gets enabled.
593 int slot;
594 for (int i = 0; i < 5; i++) {
Ian Elliottd11b0442017-07-18 11:05:49 -0600595 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700596 ASSERT_EQ(sharedSlot, slot);
597 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800598 }
599
600 // acquire the buffer
601 BufferItem item;
602 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700603 ASSERT_EQ(sharedSlot, item.mSlot);
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800604 testBufferItem(input, item);
605 ASSERT_EQ(true, item.mQueuedBuffer);
606 ASSERT_EQ(false, item.mAutoRefresh);
607
608 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
609 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
610
611 // attempt to acquire a second time should return no buffer available
612 ASSERT_EQ(IGraphicBufferConsumer::NO_BUFFER_AVAILABLE,
613 mConsumer->acquireBuffer(&item, 0));
614}
615
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700616TEST_F(BufferQueueTest, TestSharedBufferModeWithAutoRefresh) {
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800617 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700618 sp<MockConsumer> mc(new MockConsumer);
619 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800620 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700621 ASSERT_EQ(OK,
622 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800623
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700624 ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800625 ASSERT_EQ(OK, mProducer->setAutoRefresh(true));
626
627 // Get a buffer
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700628 int sharedSlot;
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800629 sp<Fence> fence;
630 sp<GraphicBuffer> buffer;
631 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600632 mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700633 ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800634
635 // Queue the buffer
636 IGraphicBufferProducer::QueueBufferInput input(0, false,
637 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
638 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700639 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800640
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700641 // Repeatedly acquire and release a buffer from the consumer side, it should
642 // always return the same one.
643 BufferItem item;
644 for (int i = 0; i < 5; i++) {
645 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700646 ASSERT_EQ(sharedSlot, item.mSlot);
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800647 testBufferItem(input, item);
648 ASSERT_EQ(i == 0, item.mQueuedBuffer);
649 ASSERT_EQ(true, item.mAutoRefresh);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700650
651 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
652 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
653 }
654
655 // Repeatedly queue and dequeue a buffer from the producer side, it should
656 // always return the same one.
657 int slot;
658 for (int i = 0; i < 5; i++) {
Ian Elliottd11b0442017-07-18 11:05:49 -0600659 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700660 ASSERT_EQ(sharedSlot, slot);
661 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700662 }
663
664 // Repeatedly acquire and release a buffer from the consumer side, it should
665 // always return the same one. First grabbing them from the queue and then
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700666 // when the queue is empty, returning the shared buffer.
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700667 for (int i = 0; i < 10; i++) {
668 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700669 ASSERT_EQ(sharedSlot, item.mSlot);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700670 ASSERT_EQ(0, item.mTimestamp);
671 ASSERT_EQ(false, item.mIsAutoTimestamp);
672 ASSERT_EQ(HAL_DATASPACE_UNKNOWN, item.mDataSpace);
673 ASSERT_EQ(Rect(0, 0, 1, 1), item.mCrop);
674 ASSERT_EQ(NATIVE_WINDOW_SCALING_MODE_FREEZE, item.mScalingMode);
Dan Stoza5ecfb682016-01-04 17:01:02 -0800675 ASSERT_EQ(0u, item.mTransform);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700676 ASSERT_EQ(Fence::NO_FENCE, item.mFence);
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800677 ASSERT_EQ(i == 0, item.mQueuedBuffer);
678 ASSERT_EQ(true, item.mAutoRefresh);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700679
680 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
681 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
682 }
683}
684
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700685TEST_F(BufferQueueTest, TestSharedBufferModeUsingAlreadyDequeuedBuffer) {
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700686 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700687 sp<MockConsumer> mc(new MockConsumer);
688 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700689 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700690 ASSERT_EQ(OK,
691 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700692
693 // Dequeue a buffer
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700694 int sharedSlot;
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700695 sp<Fence> fence;
696 sp<GraphicBuffer> buffer;
697 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600698 mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700699 ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700700
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700701 // Enable shared buffer mode
702 ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700703
704 // Queue the buffer
705 IGraphicBufferProducer::QueueBufferInput input(0, false,
706 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
707 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700708 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700709
710 // Repeatedly queue and dequeue a buffer from the producer side, it should
711 // always return the same one. And we won't run out of buffers because it's
712 // always the same one and because async mode gets enabled.
713 int slot;
714 for (int i = 0; i < 5; i++) {
Ian Elliottd11b0442017-07-18 11:05:49 -0600715 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700716 ASSERT_EQ(sharedSlot, slot);
717 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700718 }
719
720 // acquire the buffer
721 BufferItem item;
722 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700723 ASSERT_EQ(sharedSlot, item.mSlot);
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700724 testBufferItem(input, item);
725 ASSERT_EQ(true, item.mQueuedBuffer);
726 ASSERT_EQ(false, item.mAutoRefresh);
727
728 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
729 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
730
731 // attempt to acquire a second time should return no buffer available
732 ASSERT_EQ(IGraphicBufferConsumer::NO_BUFFER_AVAILABLE,
733 mConsumer->acquireBuffer(&item, 0));
734}
735
Dan Stoza127fc632015-06-30 13:43:32 -0700736TEST_F(BufferQueueTest, TestTimeouts) {
737 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700738 sp<MockConsumer> mc(new MockConsumer);
739 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Dan Stoza127fc632015-06-30 13:43:32 -0700740 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700741 ASSERT_EQ(OK,
742 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Dan Stoza127fc632015-06-30 13:43:32 -0700743
744 // Fill up the queue. Since the controlledByApp flags are set to true, this
745 // queue should be in non-blocking mode, and we should be recycling the same
746 // two buffers
747 for (int i = 0; i < 5; ++i) {
748 int slot = BufferQueue::INVALID_BUFFER_SLOT;
749 sp<Fence> fence = Fence::NO_FENCE;
Ian Elliottd11b0442017-07-18 11:05:49 -0600750 auto result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr);
Dan Stoza127fc632015-06-30 13:43:32 -0700751 if (i < 2) {
752 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
753 result);
754 } else {
755 ASSERT_EQ(OK, result);
756 }
757 sp<GraphicBuffer> buffer;
758 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
759 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
760 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
761 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
762 IGraphicBufferProducer::QueueBufferOutput output{};
763 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
764 }
765
766 const auto TIMEOUT = ms2ns(250);
767 mProducer->setDequeueTimeout(TIMEOUT);
768
769 // Setting a timeout will change the BufferQueue into blocking mode (with
770 // one droppable buffer in the queue and one free from the previous
771 // dequeue/queues), so dequeue and queue two more buffers: one to replace
772 // the current droppable buffer, and a second to max out the buffer count
773 sp<GraphicBuffer> buffer; // Save a buffer to attach later
774 for (int i = 0; i < 2; ++i) {
775 int slot = BufferQueue::INVALID_BUFFER_SLOT;
776 sp<Fence> fence = Fence::NO_FENCE;
Ian Elliottd11b0442017-07-18 11:05:49 -0600777 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stoza127fc632015-06-30 13:43:32 -0700778 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
779 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
780 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
781 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
782 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
783 }
784
785 int slot = BufferQueue::INVALID_BUFFER_SLOT;
786 sp<Fence> fence = Fence::NO_FENCE;
787 auto startTime = systemTime();
Ian Elliottd11b0442017-07-18 11:05:49 -0600788 ASSERT_EQ(TIMED_OUT, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stoza127fc632015-06-30 13:43:32 -0700789 ASSERT_GE(systemTime() - startTime, TIMEOUT);
790
791 // We're technically attaching the same buffer multiple times (since we
792 // queued it previously), but that doesn't matter for this test
793 startTime = systemTime();
794 ASSERT_EQ(TIMED_OUT, mProducer->attachBuffer(&slot, buffer));
795 ASSERT_GE(systemTime() - startTime, TIMEOUT);
796}
797
Dan Stoza5ecfb682016-01-04 17:01:02 -0800798TEST_F(BufferQueueTest, CanAttachWhileDisallowingAllocation) {
799 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700800 sp<MockConsumer> mc(new MockConsumer);
801 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Dan Stoza5ecfb682016-01-04 17:01:02 -0800802 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700803 ASSERT_EQ(OK,
804 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Dan Stoza5ecfb682016-01-04 17:01:02 -0800805
806 int slot = BufferQueue::INVALID_BUFFER_SLOT;
807 sp<Fence> sourceFence;
808 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600809 mProducer->dequeueBuffer(&slot, &sourceFence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stoza5ecfb682016-01-04 17:01:02 -0800810 sp<GraphicBuffer> buffer;
811 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
812 ASSERT_EQ(OK, mProducer->detachBuffer(slot));
813
814 ASSERT_EQ(OK, mProducer->allowAllocation(false));
815
816 slot = BufferQueue::INVALID_BUFFER_SLOT;
817 ASSERT_EQ(OK, mProducer->attachBuffer(&slot, buffer));
818}
819
Dan Stoza50101d02016-04-07 16:53:23 -0700820TEST_F(BufferQueueTest, CanRetrieveLastQueuedBuffer) {
821 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700822 sp<MockConsumer> mc(new MockConsumer);
823 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Dan Stoza50101d02016-04-07 16:53:23 -0700824 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700825 ASSERT_EQ(OK,
826 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
Dan Stoza50101d02016-04-07 16:53:23 -0700827
828 // Dequeue and queue the first buffer, storing the handle
829 int slot = BufferQueue::INVALID_BUFFER_SLOT;
830 sp<Fence> fence;
831 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600832 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stoza50101d02016-04-07 16:53:23 -0700833 sp<GraphicBuffer> firstBuffer;
834 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &firstBuffer));
835
836 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
837 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
838 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
839 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
840
841 // Dequeue a second buffer
842 slot = BufferQueue::INVALID_BUFFER_SLOT;
843 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600844 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stoza50101d02016-04-07 16:53:23 -0700845 sp<GraphicBuffer> secondBuffer;
846 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &secondBuffer));
847
848 // Ensure it's a new buffer
849 ASSERT_NE(firstBuffer->getNativeBuffer()->handle,
850 secondBuffer->getNativeBuffer()->handle);
851
852 // Queue the second buffer
853 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
854
855 // Acquire and release both buffers
856 for (size_t i = 0; i < 2; ++i) {
857 BufferItem item;
858 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
859 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
860 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
861 }
862
863 // Make sure we got the second buffer back
864 sp<GraphicBuffer> returnedBuffer;
865 sp<Fence> returnedFence;
John Reck1a61da52016-04-28 13:18:15 -0700866 float transform[16];
Dan Stoza50101d02016-04-07 16:53:23 -0700867 ASSERT_EQ(OK,
John Reck1a61da52016-04-28 13:18:15 -0700868 mProducer->getLastQueuedBuffer(&returnedBuffer, &returnedFence,
869 transform));
Dan Stoza50101d02016-04-07 16:53:23 -0700870 ASSERT_EQ(secondBuffer->getNativeBuffer()->handle,
871 returnedBuffer->getNativeBuffer()->handle);
872}
873
Dan Stozae77c7662016-05-13 11:37:28 -0700874TEST_F(BufferQueueTest, TestOccupancyHistory) {
875 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -0700876 sp<MockConsumer> mc(new MockConsumer);
877 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Dan Stozae77c7662016-05-13 11:37:28 -0700878 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -0700879 ASSERT_EQ(OK,
880 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
Dan Stozae77c7662016-05-13 11:37:28 -0700881
882 int slot = BufferQueue::INVALID_BUFFER_SLOT;
883 sp<Fence> fence = Fence::NO_FENCE;
884 sp<GraphicBuffer> buffer = nullptr;
885 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
886 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
887 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
888 BufferItem item{};
889
890 // Preallocate, dequeue, request, and cancel 3 buffers so we don't get
891 // BUFFER_NEEDS_REALLOCATION below
892 int slots[3] = {};
893 mProducer->setMaxDequeuedBufferCount(3);
894 for (size_t i = 0; i < 3; ++i) {
Ian Elliottd11b0442017-07-18 11:05:49 -0600895 status_t result =
896 mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0, 0, nullptr, nullptr);
Dan Stozae77c7662016-05-13 11:37:28 -0700897 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
898 ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
899 }
900 for (size_t i = 0; i < 3; ++i) {
901 ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE));
902 }
903
904 // Create 3 segments
905
906 // The first segment is a two-buffer segment, so we only put one buffer into
907 // the queue at a time
908 for (size_t i = 0; i < 5; ++i) {
Ian Elliottd11b0442017-07-18 11:05:49 -0600909 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700910 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
911 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
912 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
913 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
914 std::this_thread::sleep_for(16ms);
915 }
916
917 // Sleep between segments
918 std::this_thread::sleep_for(500ms);
919
920 // The second segment is a double-buffer segment. It starts the same as the
921 // two-buffer segment, but then at the end, we put two buffers in the queue
922 // at the same time before draining it.
923 for (size_t i = 0; i < 5; ++i) {
Ian Elliottd11b0442017-07-18 11:05:49 -0600924 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700925 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
926 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
927 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
928 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
929 std::this_thread::sleep_for(16ms);
930 }
Ian Elliottd11b0442017-07-18 11:05:49 -0600931 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700932 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
Ian Elliottd11b0442017-07-18 11:05:49 -0600933 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700934 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
935 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
936 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
937 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
938 std::this_thread::sleep_for(16ms);
939 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
940 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
941 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
942
943 // Sleep between segments
944 std::this_thread::sleep_for(500ms);
945
946 // The third segment is a triple-buffer segment, so the queue is switching
947 // between one buffer and two buffers deep.
Ian Elliottd11b0442017-07-18 11:05:49 -0600948 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700949 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
950 for (size_t i = 0; i < 5; ++i) {
Ian Elliottd11b0442017-07-18 11:05:49 -0600951 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700952 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
953 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
954 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
955 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
956 std::this_thread::sleep_for(16ms);
957 }
958 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
959 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
960 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
961
962 // Now we read the segments
963 std::vector<OccupancyTracker::Segment> history;
964 ASSERT_EQ(OK, mConsumer->getOccupancyHistory(false, &history));
965
966 // Since we didn't force a flush, we should only get the first two segments
967 // (since the third segment hasn't been closed out by the appearance of a
968 // new segment yet)
969 ASSERT_EQ(2u, history.size());
970
971 // The first segment (which will be history[1], since the newest segment
972 // should be at the front of the vector) should be a two-buffer segment,
973 // which implies that the occupancy average should be between 0 and 1, and
974 // usedThirdBuffer should be false
975 const auto& firstSegment = history[1];
976 ASSERT_EQ(5u, firstSegment.numFrames);
977 ASSERT_LT(0, firstSegment.occupancyAverage);
978 ASSERT_GT(1, firstSegment.occupancyAverage);
979 ASSERT_EQ(false, firstSegment.usedThirdBuffer);
980
981 // The second segment should be a double-buffered segment, which implies that
982 // the occupancy average should be between 0 and 1, but usedThirdBuffer
983 // should be true
984 const auto& secondSegment = history[0];
985 ASSERT_EQ(7u, secondSegment.numFrames);
986 ASSERT_LT(0, secondSegment.occupancyAverage);
987 ASSERT_GT(1, secondSegment.occupancyAverage);
988 ASSERT_EQ(true, secondSegment.usedThirdBuffer);
989
990 // If we read the segments again without flushing, we shouldn't get any new
991 // segments
992 ASSERT_EQ(OK, mConsumer->getOccupancyHistory(false, &history));
993 ASSERT_EQ(0u, history.size());
994
995 // Read the segments again, this time forcing a flush so we get the third
996 // segment
997 ASSERT_EQ(OK, mConsumer->getOccupancyHistory(true, &history));
998 ASSERT_EQ(1u, history.size());
999
1000 // This segment should be a triple-buffered segment, which implies that the
1001 // occupancy average should be between 1 and 2, and usedThirdBuffer should
1002 // be true
1003 const auto& thirdSegment = history[0];
1004 ASSERT_EQ(6u, thirdSegment.numFrames);
1005 ASSERT_LT(1, thirdSegment.occupancyAverage);
1006 ASSERT_GT(2, thirdSegment.occupancyAverage);
1007 ASSERT_EQ(true, thirdSegment.usedThirdBuffer);
1008}
1009
Shuzhen Wang067fcd32019-08-14 10:41:12 -07001010struct BufferDiscardedListener : public BnProducerListener {
1011public:
1012 BufferDiscardedListener() = default;
1013 virtual ~BufferDiscardedListener() = default;
1014
1015 virtual void onBufferReleased() {}
1016 virtual bool needsReleaseNotify() { return false; }
1017 virtual void onBuffersDiscarded(const std::vector<int32_t>& slots) {
1018 mDiscardedSlots.insert(mDiscardedSlots.end(), slots.begin(), slots.end());
1019 }
1020
1021 const std::vector<int32_t>& getDiscardedSlots() const { return mDiscardedSlots; }
1022private:
1023 // No need to use lock given the test triggers the listener in the same
1024 // thread context.
1025 std::vector<int32_t> mDiscardedSlots;
1026};
1027
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001028TEST_F(BufferQueueTest, TestDiscardFreeBuffers) {
1029 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -07001030 sp<MockConsumer> mc(new MockConsumer);
1031 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001032 IGraphicBufferProducer::QueueBufferOutput output;
Shuzhen Wang067fcd32019-08-14 10:41:12 -07001033 sp<BufferDiscardedListener> pl(new BufferDiscardedListener);
1034 ASSERT_EQ(OK, mProducer->connect(pl,
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001035 NATIVE_WINDOW_API_CPU, false, &output));
1036
1037 int slot = BufferQueue::INVALID_BUFFER_SLOT;
1038 sp<Fence> fence = Fence::NO_FENCE;
1039 sp<GraphicBuffer> buffer = nullptr;
1040 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1041 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1042 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1043 BufferItem item{};
1044
1045 // Preallocate, dequeue, request, and cancel 4 buffers so we don't get
1046 // BUFFER_NEEDS_REALLOCATION below
1047 int slots[4] = {};
1048 mProducer->setMaxDequeuedBufferCount(4);
1049 for (size_t i = 0; i < 4; ++i) {
Ian Elliottd11b0442017-07-18 11:05:49 -06001050 status_t result =
1051 mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0, 0, nullptr, nullptr);
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001052 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1053 ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
1054 }
1055 for (size_t i = 0; i < 4; ++i) {
1056 ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE));
1057 }
1058
1059 // Get buffers in all states: dequeued, filled, acquired, free
1060
1061 // Fill 3 buffers
Ian Elliottd11b0442017-07-18 11:05:49 -06001062 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001063 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
Ian Elliottd11b0442017-07-18 11:05:49 -06001064 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001065 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
Ian Elliottd11b0442017-07-18 11:05:49 -06001066 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001067 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1068 // Dequeue 1 buffer
Ian Elliottd11b0442017-07-18 11:05:49 -06001069 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001070
1071 // Acquire and free 1 buffer
1072 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1073 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
1074 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
Shuzhen Wang067fcd32019-08-14 10:41:12 -07001075 int releasedSlot = item.mSlot;
1076
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001077 // Acquire 1 buffer, leaving 1 filled buffer in queue
1078 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1079
1080 // Now discard the free buffers
1081 ASSERT_EQ(OK, mConsumer->discardFreeBuffers());
1082
Shuzhen Wang067fcd32019-08-14 10:41:12 -07001083 // Check onBuffersDiscarded is called with correct slots
1084 auto buffersDiscarded = pl->getDiscardedSlots();
1085 ASSERT_EQ(buffersDiscarded.size(), 1);
1086 ASSERT_EQ(buffersDiscarded[0], releasedSlot);
1087
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001088 // Check no free buffers in dump
1089 String8 dumpString;
Dan Stoza0c9a1ed2017-04-06 15:10:21 -07001090 mConsumer->dumpState(String8{}, &dumpString);
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001091
1092 // Parse the dump to ensure that all buffer slots that are FREE also
1093 // have a null GraphicBuffer
1094 // Fragile - assumes the following format for the dump for a buffer entry:
1095 // ":%p\][^:]*state=FREE" where %p is the buffer pointer in hex.
1096 ssize_t idx = dumpString.find("state=FREE");
1097 while (idx != -1) {
1098 ssize_t bufferPtrIdx = idx - 1;
1099 while (bufferPtrIdx > 0) {
1100 if (dumpString[bufferPtrIdx] == ':') {
1101 bufferPtrIdx++;
1102 break;
1103 }
1104 bufferPtrIdx--;
1105 }
1106 ASSERT_GT(bufferPtrIdx, 0) << "Can't parse queue dump to validate";
1107 ssize_t nullPtrIdx = dumpString.find("0x0]", bufferPtrIdx);
1108 ASSERT_EQ(bufferPtrIdx, nullPtrIdx) << "Free buffer not discarded";
1109 idx = dumpString.find("FREE", idx + 1);
1110 }
1111}
1112
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001113TEST_F(BufferQueueTest, TestBufferReplacedInQueueBuffer) {
1114 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -07001115 sp<MockConsumer> mc(new MockConsumer);
1116 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001117 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -07001118 ASSERT_EQ(OK,
1119 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001120 ASSERT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
1121
1122 int slot = BufferQueue::INVALID_BUFFER_SLOT;
1123 sp<Fence> fence = Fence::NO_FENCE;
1124 sp<GraphicBuffer> buffer = nullptr;
1125 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1126 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1127 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1128 BufferItem item{};
1129
1130 // Preallocate, dequeue, request, and cancel 2 buffers so we don't get
1131 // BUFFER_NEEDS_REALLOCATION below
1132 int slots[2] = {};
1133 ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(2));
1134 for (size_t i = 0; i < 2; ++i) {
Ian Elliottd11b0442017-07-18 11:05:49 -06001135 status_t result =
1136 mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0, 0, nullptr, nullptr);
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001137 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1138 ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
1139 }
1140 for (size_t i = 0; i < 2; ++i) {
1141 ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE));
1142 }
1143
1144 // Fill 2 buffers without consumer consuming them. Verify that all
1145 // queued buffer returns proper bufferReplaced flag
Ian Elliottd11b0442017-07-18 11:05:49 -06001146 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001147 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1148 ASSERT_EQ(false, output.bufferReplaced);
Ian Elliottd11b0442017-07-18 11:05:49 -06001149 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001150 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1151 ASSERT_EQ(true, output.bufferReplaced);
1152}
1153
Dan Stozad4c6f992017-03-21 13:43:22 -07001154TEST_F(BufferQueueTest, TestStaleBufferHandleSentAfterDisconnect) {
1155 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -07001156 sp<MockConsumer> mc(new MockConsumer);
1157 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Dan Stozad4c6f992017-03-21 13:43:22 -07001158 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -07001159 sp<IProducerListener> fakeListener(new StubProducerListener);
1160 ASSERT_EQ(OK, mProducer->connect(fakeListener, NATIVE_WINDOW_API_CPU, true, &output));
Dan Stozad4c6f992017-03-21 13:43:22 -07001161
1162 int slot = BufferQueue::INVALID_BUFFER_SLOT;
1163 sp<Fence> fence = Fence::NO_FENCE;
1164 sp<GraphicBuffer> buffer = nullptr;
1165 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1166 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1167 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1168
1169 // Dequeue, request, and queue one buffer
Ian Elliottd11b0442017-07-18 11:05:49 -06001170 status_t result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr);
Dan Stozad4c6f992017-03-21 13:43:22 -07001171 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1172 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
1173 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1174
1175 // Acquire and release the buffer. Upon acquiring, the buffer handle should
1176 // be non-null since this is the first time we've acquired this slot.
1177 BufferItem item;
1178 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1179 ASSERT_EQ(slot, item.mSlot);
1180 ASSERT_NE(nullptr, item.mGraphicBuffer.get());
1181 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
1182 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
1183
1184 // Dequeue and queue the buffer again
Ian Elliottd11b0442017-07-18 11:05:49 -06001185 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stozad4c6f992017-03-21 13:43:22 -07001186 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1187
1188 // Acquire and release the buffer again. Upon acquiring, the buffer handle
1189 // should be null since this is not the first time we've acquired this slot.
1190 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1191 ASSERT_EQ(slot, item.mSlot);
1192 ASSERT_EQ(nullptr, item.mGraphicBuffer.get());
1193 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
1194 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
1195
1196 // Dequeue and queue the buffer again
Ian Elliottd11b0442017-07-18 11:05:49 -06001197 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stozad4c6f992017-03-21 13:43:22 -07001198 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1199
1200 // Disconnect the producer end. This should clear all of the slots and mark
1201 // the buffer in the queue as stale.
1202 ASSERT_EQ(OK, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
1203
1204 // Acquire the buffer again. Upon acquiring, the buffer handle should not be
1205 // null since the queued buffer should have been marked as stale, which
1206 // should trigger the BufferQueue to resend the buffer handle.
1207 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1208 ASSERT_EQ(slot, item.mSlot);
1209 ASSERT_NE(nullptr, item.mGraphicBuffer.get());
1210}
1211
Wonsik Kim3e198b22017-04-07 15:43:16 -07001212TEST_F(BufferQueueTest, TestProducerConnectDisconnect) {
1213 createBufferQueue();
Peiyong Lind8460c82020-07-28 16:04:22 -07001214 sp<MockConsumer> mc(new MockConsumer);
1215 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
Wonsik Kim3e198b22017-04-07 15:43:16 -07001216 IGraphicBufferProducer::QueueBufferOutput output;
Peiyong Lind8460c82020-07-28 16:04:22 -07001217 sp<IProducerListener> fakeListener(new StubProducerListener);
Wonsik Kim3e198b22017-04-07 15:43:16 -07001218 ASSERT_EQ(NO_INIT, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
Peiyong Lind8460c82020-07-28 16:04:22 -07001219 ASSERT_EQ(OK, mProducer->connect(fakeListener, NATIVE_WINDOW_API_CPU, true, &output));
1220 ASSERT_EQ(BAD_VALUE, mProducer->connect(fakeListener, NATIVE_WINDOW_API_MEDIA, true, &output));
Wonsik Kim3e198b22017-04-07 15:43:16 -07001221
1222 ASSERT_EQ(BAD_VALUE, mProducer->disconnect(NATIVE_WINDOW_API_MEDIA));
1223 ASSERT_EQ(OK, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
1224 ASSERT_EQ(NO_INIT, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
1225}
1226
Jamie Gennis9e75ddd2012-08-31 15:32:45 -07001227} // namespace android