blob: 6d7b6bb9c6771297c9f79b93d6c03b869b6b7509 [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
Dan Stozac6f30bd2015-06-08 09:32:50 -070020#include "DummyConsumer.h"
21
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
137 sp<DummyConsumer> dc(new DummyConsumer);
138 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
139 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();
174 sp<DummyConsumer> dc(new DummyConsumer);
175 mConsumer->consumerConnect(dc, false);
176 int bufferCount = 50;
177 mConsumer->setMaxBufferCount(bufferCount);
178
179 IGraphicBufferProducer::QueueBufferOutput output;
180 mProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, false, &output);
181 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();
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700186 sp<DummyConsumer> dc(new DummyConsumer);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800187 mConsumer->consumerConnect(dc, false);
Andy McFadden2adaf042012-12-18 09:49:45 -0800188 IGraphicBufferProducer::QueueBufferOutput qbo;
Dan Stozaf0eaf252014-03-21 13:05:51 -0700189 mProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, false,
190 &qbo);
Pablo Ceballosfa455352015-08-12 17:47:47 -0700191 mProducer->setMaxDequeuedBufferCount(3);
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700192
193 int slot;
194 sp<Fence> fence;
195 sp<GraphicBuffer> buf;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800196 IGraphicBufferProducer::QueueBufferInput qbi(0, false,
197 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700198 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Dan Stozacf3834d2015-03-11 14:04:22 -0700199 BufferItem item;
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700200
201 for (int i = 0; i < 2; i++) {
Andy McFadden2adaf042012-12-18 09:49:45 -0800202 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600203 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
204 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800205 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
206 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
207 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700208 }
209
Andy McFadden2adaf042012-12-18 09:49:45 -0800210 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600211 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
212 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800213 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
214 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700215
216 // Acquire the third buffer, which should fail.
Dan Stoza9f3053d2014-03-06 15:14:33 -0800217 ASSERT_EQ(INVALID_OPERATION, mConsumer->acquireBuffer(&item, 0));
Jamie Gennis9e75ddd2012-08-31 15:32:45 -0700218}
219
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700220TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithIllegalValues_ReturnsError) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700221 createBufferQueue();
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700222 sp<DummyConsumer> dc(new DummyConsumer);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800223 mConsumer->consumerConnect(dc, false);
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700224
Pablo Ceballos72daab62015-12-07 16:38:43 -0800225 EXPECT_EQ(OK, mConsumer->setMaxBufferCount(10));
226 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(10));
227
228 IGraphicBufferProducer::QueueBufferOutput qbo;
229 mProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, false,
230 &qbo);
231 mProducer->setMaxDequeuedBufferCount(3);
232
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800233 int minBufferCount;
234 ASSERT_NO_FATAL_FAILURE(GetMinUndequeuedBufferCount(&minBufferCount));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800235 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(
236 minBufferCount - 1));
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800237
Dan Stoza9f3053d2014-03-06 15:14:33 -0800238 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(0));
239 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(-3));
240 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700241 BufferQueue::MAX_MAX_ACQUIRED_BUFFERS+1));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800242 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(100));
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700243
Pablo Ceballos72daab62015-12-07 16:38:43 -0800244 int slot;
245 sp<Fence> fence;
246 sp<GraphicBuffer> buf;
247 IGraphicBufferProducer::QueueBufferInput qbi(0, false,
248 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
249 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
250 BufferItem item;
251 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(3));
252 for (int i = 0; i < 3; i++) {
253 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600254 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
255 nullptr, nullptr));
Pablo Ceballos72daab62015-12-07 16:38:43 -0800256 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
257 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
258 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
259 }
260
261 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(2));
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700262}
263
264TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithLegalValues_Succeeds) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700265 createBufferQueue();
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700266 sp<DummyConsumer> dc(new DummyConsumer);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800267 mConsumer->consumerConnect(dc, false);
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700268
Pablo Ceballos72daab62015-12-07 16:38:43 -0800269 IGraphicBufferProducer::QueueBufferOutput qbo;
270 mProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, false,
271 &qbo);
272 mProducer->setMaxDequeuedBufferCount(2);
273
Igor Murashkin7ea777f2013-11-18 16:58:36 -0800274 int minBufferCount;
275 ASSERT_NO_FATAL_FAILURE(GetMinUndequeuedBufferCount(&minBufferCount));
276
Dan Stoza9f3053d2014-03-06 15:14:33 -0800277 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
278 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(2));
279 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(minBufferCount));
Pablo Ceballos72daab62015-12-07 16:38:43 -0800280
281 int slot;
282 sp<Fence> fence;
283 sp<GraphicBuffer> buf;
284 IGraphicBufferProducer::QueueBufferInput qbi(0, false,
285 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
286 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
287 BufferItem item;
288
289 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600290 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
291 nullptr, nullptr));
Pablo Ceballos72daab62015-12-07 16:38:43 -0800292 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
293 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
294 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
295
296 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(3));
297
298 for (int i = 0; i < 2; i++) {
299 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600300 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
301 nullptr, nullptr));
Pablo Ceballos72daab62015-12-07 16:38:43 -0800302 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
303 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
304 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
305 }
306
Dan Stoza9f3053d2014-03-06 15:14:33 -0800307 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(
Jamie Gennisc68f2ec2012-08-30 18:36:22 -0700308 BufferQueue::MAX_MAX_ACQUIRED_BUFFERS));
309}
310
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700311TEST_F(BufferQueueTest, SetMaxBufferCountWithLegalValues_Succeeds) {
312 createBufferQueue();
313 sp<DummyConsumer> dc(new DummyConsumer);
314 mConsumer->consumerConnect(dc, false);
315
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700316 // Test shared buffer mode
Pablo Ceballos19e3e062015-08-19 16:16:06 -0700317 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
318}
319
320TEST_F(BufferQueueTest, SetMaxBufferCountWithIllegalValues_ReturnsError) {
321 createBufferQueue();
322 sp<DummyConsumer> dc(new DummyConsumer);
323 mConsumer->consumerConnect(dc, false);
324
325 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(0));
326 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(
327 BufferQueue::NUM_BUFFER_SLOTS + 1));
328
329 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(5));
330 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(3));
331}
332
Dan Stoza9f3053d2014-03-06 15:14:33 -0800333TEST_F(BufferQueueTest, DetachAndReattachOnProducerSide) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700334 createBufferQueue();
Dan Stoza9f3053d2014-03-06 15:14:33 -0800335 sp<DummyConsumer> dc(new DummyConsumer);
336 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
337 IGraphicBufferProducer::QueueBufferOutput output;
Dan Stozaf0eaf252014-03-21 13:05:51 -0700338 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
339 NATIVE_WINDOW_API_CPU, false, &output));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800340
341 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(-1)); // Index too low
342 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(
343 BufferQueueDefs::NUM_BUFFER_SLOTS)); // Index too high
344 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(0)); // Not dequeued
345
346 int slot;
347 sp<Fence> fence;
348 sp<GraphicBuffer> buffer;
349 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600350 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
351 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800352 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(slot)); // Not requested
353 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
354 ASSERT_EQ(OK, mProducer->detachBuffer(slot));
355 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(slot)); // Not dequeued
356
357 sp<GraphicBuffer> safeToClobberBuffer;
358 // Can no longer request buffer from this slot
359 ASSERT_EQ(BAD_VALUE, mProducer->requestBuffer(slot, &safeToClobberBuffer));
360
361 uint32_t* dataIn;
362 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
363 reinterpret_cast<void**>(&dataIn)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700364 *dataIn = TEST_DATA;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800365 ASSERT_EQ(OK, buffer->unlock());
366
367 int newSlot;
Yi Konga03e0442018-07-17 11:16:57 -0700368 ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(nullptr, safeToClobberBuffer));
369 ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(&newSlot, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800370
371 ASSERT_EQ(OK, mProducer->attachBuffer(&newSlot, buffer));
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800372 IGraphicBufferProducer::QueueBufferInput input(0, false,
373 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700374 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800375 ASSERT_EQ(OK, mProducer->queueBuffer(newSlot, input, &output));
376
Dan Stozacf3834d2015-03-11 14:04:22 -0700377 BufferItem item;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800378 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
379
380 uint32_t* dataOut;
381 ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
382 reinterpret_cast<void**>(&dataOut)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700383 ASSERT_EQ(*dataOut, TEST_DATA);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700384 ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
Dan Stoza9f3053d2014-03-06 15:14:33 -0800385}
386
387TEST_F(BufferQueueTest, DetachAndReattachOnConsumerSide) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700388 createBufferQueue();
Dan Stoza9f3053d2014-03-06 15:14:33 -0800389 sp<DummyConsumer> dc(new DummyConsumer);
390 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
391 IGraphicBufferProducer::QueueBufferOutput output;
Dan Stozaf0eaf252014-03-21 13:05:51 -0700392 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
393 NATIVE_WINDOW_API_CPU, false, &output));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800394
395 int slot;
396 sp<Fence> fence;
397 sp<GraphicBuffer> buffer;
398 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600399 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
400 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800401 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800402 IGraphicBufferProducer::QueueBufferInput input(0, false,
403 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700404 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800405 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
406
407 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(-1)); // Index too low
408 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(
409 BufferQueueDefs::NUM_BUFFER_SLOTS)); // Index too high
410 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(0)); // Not acquired
411
Dan Stozacf3834d2015-03-11 14:04:22 -0700412 BufferItem item;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800413 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
414
Pablo Ceballos47650f42015-08-04 16:38:17 -0700415 ASSERT_EQ(OK, mConsumer->detachBuffer(item.mSlot));
416 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(item.mSlot)); // Not acquired
Dan Stoza9f3053d2014-03-06 15:14:33 -0800417
418 uint32_t* dataIn;
419 ASSERT_EQ(OK, item.mGraphicBuffer->lock(
420 GraphicBuffer::USAGE_SW_WRITE_OFTEN,
421 reinterpret_cast<void**>(&dataIn)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700422 *dataIn = TEST_DATA;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800423 ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
424
425 int newSlot;
426 sp<GraphicBuffer> safeToClobberBuffer;
Yi Konga03e0442018-07-17 11:16:57 -0700427 ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(nullptr, safeToClobberBuffer));
428 ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(&newSlot, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800429 ASSERT_EQ(OK, mConsumer->attachBuffer(&newSlot, item.mGraphicBuffer));
430
Dan Stoza99b18b42014-03-28 15:34:33 -0700431 ASSERT_EQ(OK, mConsumer->releaseBuffer(newSlot, 0, EGL_NO_DISPLAY,
Dan Stoza9f3053d2014-03-06 15:14:33 -0800432 EGL_NO_SYNC_KHR, Fence::NO_FENCE));
433
434 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600435 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
436 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800437 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
438
439 uint32_t* dataOut;
440 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
441 reinterpret_cast<void**>(&dataOut)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700442 ASSERT_EQ(*dataOut, TEST_DATA);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700443 ASSERT_EQ(OK, buffer->unlock());
Dan Stoza9f3053d2014-03-06 15:14:33 -0800444}
445
446TEST_F(BufferQueueTest, MoveFromConsumerToProducer) {
Dan Stoza1a0b8612014-03-20 15:36:31 -0700447 createBufferQueue();
Dan Stoza9f3053d2014-03-06 15:14:33 -0800448 sp<DummyConsumer> dc(new DummyConsumer);
449 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
450 IGraphicBufferProducer::QueueBufferOutput output;
Dan Stozaf0eaf252014-03-21 13:05:51 -0700451 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
452 NATIVE_WINDOW_API_CPU, false, &output));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800453
454 int slot;
455 sp<Fence> fence;
456 sp<GraphicBuffer> buffer;
457 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600458 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
459 nullptr, nullptr));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800460 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
461
462 uint32_t* dataIn;
463 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
464 reinterpret_cast<void**>(&dataIn)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700465 *dataIn = TEST_DATA;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800466 ASSERT_EQ(OK, buffer->unlock());
467
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800468 IGraphicBufferProducer::QueueBufferInput input(0, false,
469 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
Pablo Ceballos567dbbb2015-08-26 18:59:08 -0700470 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Dan Stoza9f3053d2014-03-06 15:14:33 -0800471 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
472
Dan Stozacf3834d2015-03-11 14:04:22 -0700473 BufferItem item;
Dan Stoza9f3053d2014-03-06 15:14:33 -0800474 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
Pablo Ceballos47650f42015-08-04 16:38:17 -0700475 ASSERT_EQ(OK, mConsumer->detachBuffer(item.mSlot));
Dan Stoza9f3053d2014-03-06 15:14:33 -0800476
477 int newSlot;
478 ASSERT_EQ(OK, mProducer->attachBuffer(&newSlot, item.mGraphicBuffer));
479 ASSERT_EQ(OK, mProducer->queueBuffer(newSlot, input, &output));
480 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
481
482 uint32_t* dataOut;
483 ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
484 reinterpret_cast<void**>(&dataOut)));
Dan Stozaf8cebe52015-04-20 12:09:38 -0700485 ASSERT_EQ(*dataOut, TEST_DATA);
Dan Stoza1a0b8612014-03-20 15:36:31 -0700486 ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
Dan Stoza9f3053d2014-03-06 15:14:33 -0800487}
488
Dan Stoza9de72932015-04-16 17:28:43 -0700489TEST_F(BufferQueueTest, TestDisallowingAllocation) {
490 createBufferQueue();
491 sp<DummyConsumer> dc(new DummyConsumer);
492 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
493 IGraphicBufferProducer::QueueBufferOutput output;
494 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
495 NATIVE_WINDOW_API_CPU, true, &output));
496
497 static const uint32_t WIDTH = 320;
498 static const uint32_t HEIGHT = 240;
499
500 ASSERT_EQ(OK, mConsumer->setDefaultBufferSize(WIDTH, HEIGHT));
501
502 int slot;
503 sp<Fence> fence;
504 sp<GraphicBuffer> buffer;
505 // This should return an error since it would require an allocation
506 ASSERT_EQ(OK, mProducer->allowAllocation(false));
Ian Elliottd11b0442017-07-18 11:05:49 -0600507 ASSERT_EQ(WOULD_BLOCK,
508 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
509 nullptr, nullptr));
Dan Stoza9de72932015-04-16 17:28:43 -0700510
511 // This should succeed, now that we've lifted the prohibition
512 ASSERT_EQ(OK, mProducer->allowAllocation(true));
513 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600514 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
515 nullptr, nullptr));
Dan Stoza9de72932015-04-16 17:28:43 -0700516
517 // Release the previous buffer back to the BufferQueue
518 mProducer->cancelBuffer(slot, fence);
519
520 // This should fail since we're requesting a different size
521 ASSERT_EQ(OK, mProducer->allowAllocation(false));
Ian Elliottd11b0442017-07-18 11:05:49 -0600522 ASSERT_EQ(WOULD_BLOCK,
523 mProducer->dequeueBuffer(&slot, &fence, WIDTH * 2, HEIGHT * 2, 0,
524 GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr, nullptr));
Dan Stoza9de72932015-04-16 17:28:43 -0700525}
526
Dan Stoza812ed062015-06-02 15:45:22 -0700527TEST_F(BufferQueueTest, TestGenerationNumbers) {
528 createBufferQueue();
529 sp<DummyConsumer> dc(new DummyConsumer);
530 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
531 IGraphicBufferProducer::QueueBufferOutput output;
532 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
533 NATIVE_WINDOW_API_CPU, true, &output));
534
535 ASSERT_EQ(OK, mProducer->setGenerationNumber(1));
536
537 // Get one buffer to play with
538 int slot;
539 sp<Fence> fence;
540 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600541 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stoza812ed062015-06-02 15:45:22 -0700542
543 sp<GraphicBuffer> buffer;
544 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
545
546 // Ensure that the generation number we set propagates to allocated buffers
547 ASSERT_EQ(1U, buffer->getGenerationNumber());
548
549 ASSERT_EQ(OK, mProducer->detachBuffer(slot));
550
551 ASSERT_EQ(OK, mProducer->setGenerationNumber(2));
552
553 // These should fail, since we've changed the generation number on the queue
554 int outSlot;
555 ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(&outSlot, buffer));
556 ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(&outSlot, buffer));
557
558 buffer->setGenerationNumber(2);
559
560 // This should succeed now that we've changed the buffer's generation number
561 ASSERT_EQ(OK, mProducer->attachBuffer(&outSlot, buffer));
562
563 ASSERT_EQ(OK, mProducer->detachBuffer(outSlot));
564
565 // This should also succeed with the new generation number
566 ASSERT_EQ(OK, mConsumer->attachBuffer(&outSlot, buffer));
567}
568
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700569TEST_F(BufferQueueTest, TestSharedBufferModeWithoutAutoRefresh) {
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700570 createBufferQueue();
571 sp<DummyConsumer> dc(new DummyConsumer);
572 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
573 IGraphicBufferProducer::QueueBufferOutput output;
574 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
575 NATIVE_WINDOW_API_CPU, true, &output));
576
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700577 ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700578
579 // Get a buffer
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700580 int sharedSlot;
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700581 sp<Fence> fence;
582 sp<GraphicBuffer> buffer;
583 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600584 mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700585 ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700586
587 // Queue the buffer
588 IGraphicBufferProducer::QueueBufferInput input(0, false,
589 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
590 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700591 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700592
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800593 // Repeatedly queue and dequeue a buffer from the producer side, it should
594 // always return the same one. And we won't run out of buffers because it's
595 // always the same one and because async mode gets enabled.
596 int slot;
597 for (int i = 0; i < 5; i++) {
Ian Elliottd11b0442017-07-18 11:05:49 -0600598 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, 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();
621 sp<DummyConsumer> dc(new DummyConsumer);
622 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
623 IGraphicBufferProducer::QueueBufferOutput output;
624 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
625 NATIVE_WINDOW_API_CPU, true, &output));
626
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,
Ian Elliottd11b0442017-07-18 11:05:49 -0600635 mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700636 ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800637
638 // Queue the buffer
639 IGraphicBufferProducer::QueueBufferInput input(0, false,
640 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
641 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700642 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800643
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700644 // Repeatedly acquire and release a buffer from the consumer side, it should
645 // always return the same one.
646 BufferItem item;
647 for (int i = 0; i < 5; i++) {
648 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700649 ASSERT_EQ(sharedSlot, item.mSlot);
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800650 testBufferItem(input, item);
651 ASSERT_EQ(i == 0, item.mQueuedBuffer);
652 ASSERT_EQ(true, item.mAutoRefresh);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700653
654 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
655 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
656 }
657
658 // Repeatedly queue and dequeue a buffer from the producer side, it should
659 // always return the same one.
660 int slot;
661 for (int i = 0; i < 5; i++) {
Ian Elliottd11b0442017-07-18 11:05:49 -0600662 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700663 ASSERT_EQ(sharedSlot, slot);
664 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700665 }
666
667 // Repeatedly acquire and release a buffer from the consumer side, it should
668 // always return the same one. First grabbing them from the queue and then
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700669 // when the queue is empty, returning the shared buffer.
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700670 for (int i = 0; i < 10; i++) {
671 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700672 ASSERT_EQ(sharedSlot, item.mSlot);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700673 ASSERT_EQ(0, item.mTimestamp);
674 ASSERT_EQ(false, item.mIsAutoTimestamp);
675 ASSERT_EQ(HAL_DATASPACE_UNKNOWN, item.mDataSpace);
676 ASSERT_EQ(Rect(0, 0, 1, 1), item.mCrop);
677 ASSERT_EQ(NATIVE_WINDOW_SCALING_MODE_FREEZE, item.mScalingMode);
Dan Stoza5ecfb682016-01-04 17:01:02 -0800678 ASSERT_EQ(0u, item.mTransform);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700679 ASSERT_EQ(Fence::NO_FENCE, item.mFence);
Pablo Ceballosff95aab2016-01-13 17:09:58 -0800680 ASSERT_EQ(i == 0, item.mQueuedBuffer);
681 ASSERT_EQ(true, item.mAutoRefresh);
Pablo Ceballosccdfd602015-10-07 15:05:45 -0700682
683 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
684 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
685 }
686}
687
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700688TEST_F(BufferQueueTest, TestSharedBufferModeUsingAlreadyDequeuedBuffer) {
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700689 createBufferQueue();
690 sp<DummyConsumer> dc(new DummyConsumer);
691 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
692 IGraphicBufferProducer::QueueBufferOutput output;
693 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
694 NATIVE_WINDOW_API_CPU, true, &output));
695
696 // Dequeue a buffer
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700697 int sharedSlot;
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700698 sp<Fence> fence;
699 sp<GraphicBuffer> buffer;
700 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600701 mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700702 ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700703
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700704 // Enable shared buffer mode
705 ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700706
707 // Queue the buffer
708 IGraphicBufferProducer::QueueBufferInput input(0, false,
709 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
710 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700711 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700712
713 // Repeatedly queue and dequeue a buffer from the producer side, it should
714 // always return the same one. And we won't run out of buffers because it's
715 // always the same one and because async mode gets enabled.
716 int slot;
717 for (int i = 0; i < 5; i++) {
Ian Elliottd11b0442017-07-18 11:05:49 -0600718 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700719 ASSERT_EQ(sharedSlot, slot);
720 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700721 }
722
723 // acquire the buffer
724 BufferItem item;
725 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
Pablo Ceballos3559fbf2016-03-17 15:50:23 -0700726 ASSERT_EQ(sharedSlot, item.mSlot);
Pablo Ceballos295a9fc2016-03-14 16:02:19 -0700727 testBufferItem(input, item);
728 ASSERT_EQ(true, item.mQueuedBuffer);
729 ASSERT_EQ(false, item.mAutoRefresh);
730
731 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
732 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
733
734 // attempt to acquire a second time should return no buffer available
735 ASSERT_EQ(IGraphicBufferConsumer::NO_BUFFER_AVAILABLE,
736 mConsumer->acquireBuffer(&item, 0));
737}
738
Dan Stoza127fc632015-06-30 13:43:32 -0700739TEST_F(BufferQueueTest, TestTimeouts) {
740 createBufferQueue();
741 sp<DummyConsumer> dc(new DummyConsumer);
742 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
743 IGraphicBufferProducer::QueueBufferOutput output;
744 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
745 NATIVE_WINDOW_API_CPU, true, &output));
746
747 // Fill up the queue. Since the controlledByApp flags are set to true, this
748 // queue should be in non-blocking mode, and we should be recycling the same
749 // two buffers
750 for (int i = 0; i < 5; ++i) {
751 int slot = BufferQueue::INVALID_BUFFER_SLOT;
752 sp<Fence> fence = Fence::NO_FENCE;
Ian Elliottd11b0442017-07-18 11:05:49 -0600753 auto result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr);
Dan Stoza127fc632015-06-30 13:43:32 -0700754 if (i < 2) {
755 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
756 result);
757 } else {
758 ASSERT_EQ(OK, result);
759 }
760 sp<GraphicBuffer> buffer;
761 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
762 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
763 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
764 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
765 IGraphicBufferProducer::QueueBufferOutput output{};
766 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
767 }
768
769 const auto TIMEOUT = ms2ns(250);
770 mProducer->setDequeueTimeout(TIMEOUT);
771
772 // Setting a timeout will change the BufferQueue into blocking mode (with
773 // one droppable buffer in the queue and one free from the previous
774 // dequeue/queues), so dequeue and queue two more buffers: one to replace
775 // the current droppable buffer, and a second to max out the buffer count
776 sp<GraphicBuffer> buffer; // Save a buffer to attach later
777 for (int i = 0; i < 2; ++i) {
778 int slot = BufferQueue::INVALID_BUFFER_SLOT;
779 sp<Fence> fence = Fence::NO_FENCE;
Ian Elliottd11b0442017-07-18 11:05:49 -0600780 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stoza127fc632015-06-30 13:43:32 -0700781 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
782 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
783 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
784 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
785 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
786 }
787
788 int slot = BufferQueue::INVALID_BUFFER_SLOT;
789 sp<Fence> fence = Fence::NO_FENCE;
790 auto startTime = systemTime();
Ian Elliottd11b0442017-07-18 11:05:49 -0600791 ASSERT_EQ(TIMED_OUT, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stoza127fc632015-06-30 13:43:32 -0700792 ASSERT_GE(systemTime() - startTime, TIMEOUT);
793
794 // We're technically attaching the same buffer multiple times (since we
795 // queued it previously), but that doesn't matter for this test
796 startTime = systemTime();
797 ASSERT_EQ(TIMED_OUT, mProducer->attachBuffer(&slot, buffer));
798 ASSERT_GE(systemTime() - startTime, TIMEOUT);
799}
800
Dan Stoza5ecfb682016-01-04 17:01:02 -0800801TEST_F(BufferQueueTest, CanAttachWhileDisallowingAllocation) {
802 createBufferQueue();
803 sp<DummyConsumer> dc(new DummyConsumer);
804 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
805 IGraphicBufferProducer::QueueBufferOutput output;
806 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
807 NATIVE_WINDOW_API_CPU, true, &output));
808
809 int slot = BufferQueue::INVALID_BUFFER_SLOT;
810 sp<Fence> sourceFence;
811 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600812 mProducer->dequeueBuffer(&slot, &sourceFence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stoza5ecfb682016-01-04 17:01:02 -0800813 sp<GraphicBuffer> buffer;
814 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
815 ASSERT_EQ(OK, mProducer->detachBuffer(slot));
816
817 ASSERT_EQ(OK, mProducer->allowAllocation(false));
818
819 slot = BufferQueue::INVALID_BUFFER_SLOT;
820 ASSERT_EQ(OK, mProducer->attachBuffer(&slot, buffer));
821}
822
Dan Stoza50101d02016-04-07 16:53:23 -0700823TEST_F(BufferQueueTest, CanRetrieveLastQueuedBuffer) {
824 createBufferQueue();
825 sp<DummyConsumer> dc(new DummyConsumer);
826 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
827 IGraphicBufferProducer::QueueBufferOutput output;
828 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
829 NATIVE_WINDOW_API_CPU, false, &output));
830
831 // Dequeue and queue the first buffer, storing the handle
832 int slot = BufferQueue::INVALID_BUFFER_SLOT;
833 sp<Fence> fence;
834 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600835 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stoza50101d02016-04-07 16:53:23 -0700836 sp<GraphicBuffer> firstBuffer;
837 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &firstBuffer));
838
839 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
840 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
841 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
842 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
843
844 // Dequeue a second buffer
845 slot = BufferQueue::INVALID_BUFFER_SLOT;
846 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
Ian Elliottd11b0442017-07-18 11:05:49 -0600847 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stoza50101d02016-04-07 16:53:23 -0700848 sp<GraphicBuffer> secondBuffer;
849 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &secondBuffer));
850
851 // Ensure it's a new buffer
852 ASSERT_NE(firstBuffer->getNativeBuffer()->handle,
853 secondBuffer->getNativeBuffer()->handle);
854
855 // Queue the second buffer
856 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
857
858 // Acquire and release both buffers
859 for (size_t i = 0; i < 2; ++i) {
860 BufferItem item;
861 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
862 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
863 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
864 }
865
866 // Make sure we got the second buffer back
867 sp<GraphicBuffer> returnedBuffer;
868 sp<Fence> returnedFence;
John Reck1a61da52016-04-28 13:18:15 -0700869 float transform[16];
Dan Stoza50101d02016-04-07 16:53:23 -0700870 ASSERT_EQ(OK,
John Reck1a61da52016-04-28 13:18:15 -0700871 mProducer->getLastQueuedBuffer(&returnedBuffer, &returnedFence,
872 transform));
Dan Stoza50101d02016-04-07 16:53:23 -0700873 ASSERT_EQ(secondBuffer->getNativeBuffer()->handle,
874 returnedBuffer->getNativeBuffer()->handle);
875}
876
Dan Stozae77c7662016-05-13 11:37:28 -0700877TEST_F(BufferQueueTest, TestOccupancyHistory) {
878 createBufferQueue();
879 sp<DummyConsumer> dc(new DummyConsumer);
880 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
881 IGraphicBufferProducer::QueueBufferOutput output;
882 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
883 NATIVE_WINDOW_API_CPU, false, &output));
884
885 int slot = BufferQueue::INVALID_BUFFER_SLOT;
886 sp<Fence> fence = Fence::NO_FENCE;
887 sp<GraphicBuffer> buffer = nullptr;
888 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
889 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
890 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
891 BufferItem item{};
892
893 // Preallocate, dequeue, request, and cancel 3 buffers so we don't get
894 // BUFFER_NEEDS_REALLOCATION below
895 int slots[3] = {};
896 mProducer->setMaxDequeuedBufferCount(3);
897 for (size_t i = 0; i < 3; ++i) {
Ian Elliottd11b0442017-07-18 11:05:49 -0600898 status_t result =
899 mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0, 0, nullptr, nullptr);
Dan Stozae77c7662016-05-13 11:37:28 -0700900 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
901 ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
902 }
903 for (size_t i = 0; i < 3; ++i) {
904 ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE));
905 }
906
907 // Create 3 segments
908
909 // The first segment is a two-buffer segment, so we only put one buffer into
910 // the queue at a time
911 for (size_t i = 0; i < 5; ++i) {
Ian Elliottd11b0442017-07-18 11:05:49 -0600912 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700913 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
914 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
915 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
916 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
917 std::this_thread::sleep_for(16ms);
918 }
919
920 // Sleep between segments
921 std::this_thread::sleep_for(500ms);
922
923 // The second segment is a double-buffer segment. It starts the same as the
924 // two-buffer segment, but then at the end, we put two buffers in the queue
925 // at the same time before draining it.
926 for (size_t i = 0; i < 5; ++i) {
Ian Elliottd11b0442017-07-18 11:05:49 -0600927 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700928 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
929 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
930 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
931 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
932 std::this_thread::sleep_for(16ms);
933 }
Ian Elliottd11b0442017-07-18 11:05:49 -0600934 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700935 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
Ian Elliottd11b0442017-07-18 11:05:49 -0600936 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700937 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
938 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
939 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
940 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
941 std::this_thread::sleep_for(16ms);
942 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
943 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
944 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
945
946 // Sleep between segments
947 std::this_thread::sleep_for(500ms);
948
949 // The third segment is a triple-buffer segment, so the queue is switching
950 // between one buffer and two buffers deep.
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 for (size_t i = 0; i < 5; ++i) {
Ian Elliottd11b0442017-07-18 11:05:49 -0600954 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stozae77c7662016-05-13 11:37:28 -0700955 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
956 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
957 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
958 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
959 std::this_thread::sleep_for(16ms);
960 }
961 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
962 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
963 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
964
965 // Now we read the segments
966 std::vector<OccupancyTracker::Segment> history;
967 ASSERT_EQ(OK, mConsumer->getOccupancyHistory(false, &history));
968
969 // Since we didn't force a flush, we should only get the first two segments
970 // (since the third segment hasn't been closed out by the appearance of a
971 // new segment yet)
972 ASSERT_EQ(2u, history.size());
973
974 // The first segment (which will be history[1], since the newest segment
975 // should be at the front of the vector) should be a two-buffer segment,
976 // which implies that the occupancy average should be between 0 and 1, and
977 // usedThirdBuffer should be false
978 const auto& firstSegment = history[1];
979 ASSERT_EQ(5u, firstSegment.numFrames);
980 ASSERT_LT(0, firstSegment.occupancyAverage);
981 ASSERT_GT(1, firstSegment.occupancyAverage);
982 ASSERT_EQ(false, firstSegment.usedThirdBuffer);
983
984 // The second segment should be a double-buffered segment, which implies that
985 // the occupancy average should be between 0 and 1, but usedThirdBuffer
986 // should be true
987 const auto& secondSegment = history[0];
988 ASSERT_EQ(7u, secondSegment.numFrames);
989 ASSERT_LT(0, secondSegment.occupancyAverage);
990 ASSERT_GT(1, secondSegment.occupancyAverage);
991 ASSERT_EQ(true, secondSegment.usedThirdBuffer);
992
993 // If we read the segments again without flushing, we shouldn't get any new
994 // segments
995 ASSERT_EQ(OK, mConsumer->getOccupancyHistory(false, &history));
996 ASSERT_EQ(0u, history.size());
997
998 // Read the segments again, this time forcing a flush so we get the third
999 // segment
1000 ASSERT_EQ(OK, mConsumer->getOccupancyHistory(true, &history));
1001 ASSERT_EQ(1u, history.size());
1002
1003 // This segment should be a triple-buffered segment, which implies that the
1004 // occupancy average should be between 1 and 2, and usedThirdBuffer should
1005 // be true
1006 const auto& thirdSegment = history[0];
1007 ASSERT_EQ(6u, thirdSegment.numFrames);
1008 ASSERT_LT(1, thirdSegment.occupancyAverage);
1009 ASSERT_GT(2, thirdSegment.occupancyAverage);
1010 ASSERT_EQ(true, thirdSegment.usedThirdBuffer);
1011}
1012
Shuzhen Wang067fcd32019-08-14 10:41:12 -07001013struct BufferDiscardedListener : public BnProducerListener {
1014public:
1015 BufferDiscardedListener() = default;
1016 virtual ~BufferDiscardedListener() = default;
1017
1018 virtual void onBufferReleased() {}
1019 virtual bool needsReleaseNotify() { return false; }
1020 virtual void onBuffersDiscarded(const std::vector<int32_t>& slots) {
1021 mDiscardedSlots.insert(mDiscardedSlots.end(), slots.begin(), slots.end());
1022 }
1023
1024 const std::vector<int32_t>& getDiscardedSlots() const { return mDiscardedSlots; }
1025private:
1026 // No need to use lock given the test triggers the listener in the same
1027 // thread context.
1028 std::vector<int32_t> mDiscardedSlots;
1029};
1030
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001031TEST_F(BufferQueueTest, TestDiscardFreeBuffers) {
1032 createBufferQueue();
1033 sp<DummyConsumer> dc(new DummyConsumer);
1034 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
1035 IGraphicBufferProducer::QueueBufferOutput output;
Shuzhen Wang067fcd32019-08-14 10:41:12 -07001036 sp<BufferDiscardedListener> pl(new BufferDiscardedListener);
1037 ASSERT_EQ(OK, mProducer->connect(pl,
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001038 NATIVE_WINDOW_API_CPU, false, &output));
1039
1040 int slot = BufferQueue::INVALID_BUFFER_SLOT;
1041 sp<Fence> fence = Fence::NO_FENCE;
1042 sp<GraphicBuffer> buffer = nullptr;
1043 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1044 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1045 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1046 BufferItem item{};
1047
1048 // Preallocate, dequeue, request, and cancel 4 buffers so we don't get
1049 // BUFFER_NEEDS_REALLOCATION below
1050 int slots[4] = {};
1051 mProducer->setMaxDequeuedBufferCount(4);
1052 for (size_t i = 0; i < 4; ++i) {
Ian Elliottd11b0442017-07-18 11:05:49 -06001053 status_t result =
1054 mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0, 0, nullptr, nullptr);
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001055 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1056 ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
1057 }
1058 for (size_t i = 0; i < 4; ++i) {
1059 ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE));
1060 }
1061
1062 // Get buffers in all states: dequeued, filled, acquired, free
1063
1064 // Fill 3 buffers
Ian Elliottd11b0442017-07-18 11:05:49 -06001065 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001066 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
Ian Elliottd11b0442017-07-18 11:05:49 -06001067 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001068 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
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 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1071 // Dequeue 1 buffer
Ian Elliottd11b0442017-07-18 11:05:49 -06001072 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001073
1074 // Acquire and free 1 buffer
1075 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1076 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
1077 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
Shuzhen Wang067fcd32019-08-14 10:41:12 -07001078 int releasedSlot = item.mSlot;
1079
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001080 // Acquire 1 buffer, leaving 1 filled buffer in queue
1081 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1082
1083 // Now discard the free buffers
1084 ASSERT_EQ(OK, mConsumer->discardFreeBuffers());
1085
Shuzhen Wang067fcd32019-08-14 10:41:12 -07001086 // Check onBuffersDiscarded is called with correct slots
1087 auto buffersDiscarded = pl->getDiscardedSlots();
1088 ASSERT_EQ(buffersDiscarded.size(), 1);
1089 ASSERT_EQ(buffersDiscarded[0], releasedSlot);
1090
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001091 // Check no free buffers in dump
1092 String8 dumpString;
Dan Stoza0c9a1ed2017-04-06 15:10:21 -07001093 mConsumer->dumpState(String8{}, &dumpString);
Eino-Ville Talvalabc2df652016-07-21 17:06:58 -07001094
1095 // Parse the dump to ensure that all buffer slots that are FREE also
1096 // have a null GraphicBuffer
1097 // Fragile - assumes the following format for the dump for a buffer entry:
1098 // ":%p\][^:]*state=FREE" where %p is the buffer pointer in hex.
1099 ssize_t idx = dumpString.find("state=FREE");
1100 while (idx != -1) {
1101 ssize_t bufferPtrIdx = idx - 1;
1102 while (bufferPtrIdx > 0) {
1103 if (dumpString[bufferPtrIdx] == ':') {
1104 bufferPtrIdx++;
1105 break;
1106 }
1107 bufferPtrIdx--;
1108 }
1109 ASSERT_GT(bufferPtrIdx, 0) << "Can't parse queue dump to validate";
1110 ssize_t nullPtrIdx = dumpString.find("0x0]", bufferPtrIdx);
1111 ASSERT_EQ(bufferPtrIdx, nullPtrIdx) << "Free buffer not discarded";
1112 idx = dumpString.find("FREE", idx + 1);
1113 }
1114}
1115
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001116TEST_F(BufferQueueTest, TestBufferReplacedInQueueBuffer) {
1117 createBufferQueue();
1118 sp<DummyConsumer> dc(new DummyConsumer);
1119 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
1120 IGraphicBufferProducer::QueueBufferOutput output;
1121 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
1122 NATIVE_WINDOW_API_CPU, true, &output));
1123 ASSERT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
1124
1125 int slot = BufferQueue::INVALID_BUFFER_SLOT;
1126 sp<Fence> fence = Fence::NO_FENCE;
1127 sp<GraphicBuffer> buffer = nullptr;
1128 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1129 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1130 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1131 BufferItem item{};
1132
1133 // Preallocate, dequeue, request, and cancel 2 buffers so we don't get
1134 // BUFFER_NEEDS_REALLOCATION below
1135 int slots[2] = {};
1136 ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(2));
1137 for (size_t i = 0; i < 2; ++i) {
Ian Elliottd11b0442017-07-18 11:05:49 -06001138 status_t result =
1139 mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0, 0, nullptr, nullptr);
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001140 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1141 ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
1142 }
1143 for (size_t i = 0; i < 2; ++i) {
1144 ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE));
1145 }
1146
1147 // Fill 2 buffers without consumer consuming them. Verify that all
1148 // queued buffer returns proper bufferReplaced flag
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(false, output.bufferReplaced);
Ian Elliottd11b0442017-07-18 11:05:49 -06001152 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Shuzhen Wang22f842b2017-01-18 23:02:36 -08001153 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1154 ASSERT_EQ(true, output.bufferReplaced);
1155}
1156
Dan Stozad4c6f992017-03-21 13:43:22 -07001157TEST_F(BufferQueueTest, TestStaleBufferHandleSentAfterDisconnect) {
1158 createBufferQueue();
1159 sp<DummyConsumer> dc(new DummyConsumer);
1160 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
1161 IGraphicBufferProducer::QueueBufferOutput output;
1162 sp<IProducerListener> dummyListener(new DummyProducerListener);
1163 ASSERT_EQ(OK, mProducer->connect(dummyListener, NATIVE_WINDOW_API_CPU,
1164 true, &output));
1165
1166 int slot = BufferQueue::INVALID_BUFFER_SLOT;
1167 sp<Fence> fence = Fence::NO_FENCE;
1168 sp<GraphicBuffer> buffer = nullptr;
1169 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1170 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1171 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1172
1173 // Dequeue, request, and queue one buffer
Ian Elliottd11b0442017-07-18 11:05:49 -06001174 status_t result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr);
Dan Stozad4c6f992017-03-21 13:43:22 -07001175 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1176 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
1177 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1178
1179 // Acquire and release the buffer. Upon acquiring, the buffer handle should
1180 // be non-null since this is the first time we've acquired this slot.
1181 BufferItem item;
1182 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1183 ASSERT_EQ(slot, item.mSlot);
1184 ASSERT_NE(nullptr, item.mGraphicBuffer.get());
1185 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
1186 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
1187
1188 // Dequeue and queue the buffer again
Ian Elliottd11b0442017-07-18 11:05:49 -06001189 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stozad4c6f992017-03-21 13:43:22 -07001190 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1191
1192 // Acquire and release the buffer again. Upon acquiring, the buffer handle
1193 // should be null since this is not the first time we've acquired this slot.
1194 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1195 ASSERT_EQ(slot, item.mSlot);
1196 ASSERT_EQ(nullptr, item.mGraphicBuffer.get());
1197 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
1198 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
1199
1200 // Dequeue and queue the buffer again
Ian Elliottd11b0442017-07-18 11:05:49 -06001201 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
Dan Stozad4c6f992017-03-21 13:43:22 -07001202 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1203
1204 // Disconnect the producer end. This should clear all of the slots and mark
1205 // the buffer in the queue as stale.
1206 ASSERT_EQ(OK, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
1207
1208 // Acquire the buffer again. Upon acquiring, the buffer handle should not be
1209 // null since the queued buffer should have been marked as stale, which
1210 // should trigger the BufferQueue to resend the buffer handle.
1211 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1212 ASSERT_EQ(slot, item.mSlot);
1213 ASSERT_NE(nullptr, item.mGraphicBuffer.get());
1214}
1215
Wonsik Kim3e198b22017-04-07 15:43:16 -07001216TEST_F(BufferQueueTest, TestProducerConnectDisconnect) {
1217 createBufferQueue();
1218 sp<DummyConsumer> dc(new DummyConsumer);
1219 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
1220 IGraphicBufferProducer::QueueBufferOutput output;
1221 sp<IProducerListener> dummyListener(new DummyProducerListener);
1222 ASSERT_EQ(NO_INIT, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
1223 ASSERT_EQ(OK, mProducer->connect(
1224 dummyListener, NATIVE_WINDOW_API_CPU, true, &output));
1225 ASSERT_EQ(BAD_VALUE, mProducer->connect(
1226 dummyListener, NATIVE_WINDOW_API_MEDIA, true, &output));
1227
1228 ASSERT_EQ(BAD_VALUE, mProducer->disconnect(NATIVE_WINDOW_API_MEDIA));
1229 ASSERT_EQ(OK, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
1230 ASSERT_EQ(NO_INIT, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
1231}
1232
Jamie Gennis9e75ddd2012-08-31 15:32:45 -07001233} // namespace android