1 /*
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
20 #include "DummyConsumer.h"
21
22 #include <gui/BufferItem.h>
23 #include <gui/BufferQueue.h>
24 #include <gui/IProducerListener.h>
25
26 #include <ui/GraphicBuffer.h>
27
28 #include <binder/IPCThreadState.h>
29 #include <binder/IServiceManager.h>
30 #include <binder/ProcessState.h>
31
32 #include <utils/String8.h>
33 #include <utils/threads.h>
34
35 #include <gtest/gtest.h>
36
37 #include <thread>
38
39 using namespace std::chrono_literals;
40
41 namespace android {
42
43 class BufferQueueTest : public ::testing::Test {
44
45 public:
46 protected:
BufferQueueTest()47 BufferQueueTest() {
48 const ::testing::TestInfo* const testInfo =
49 ::testing::UnitTest::GetInstance()->current_test_info();
50 ALOGV("Begin test: %s.%s", testInfo->test_case_name(),
51 testInfo->name());
52 }
53
~BufferQueueTest()54 ~BufferQueueTest() {
55 const ::testing::TestInfo* const testInfo =
56 ::testing::UnitTest::GetInstance()->current_test_info();
57 ALOGV("End test: %s.%s", testInfo->test_case_name(),
58 testInfo->name());
59 }
60
GetMinUndequeuedBufferCount(int * bufferCount)61 void GetMinUndequeuedBufferCount(int* bufferCount) {
62 ASSERT_TRUE(bufferCount != NULL);
63 ASSERT_EQ(OK, mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
64 bufferCount));
65 ASSERT_GE(*bufferCount, 0);
66 }
67
createBufferQueue()68 void createBufferQueue() {
69 BufferQueue::createBufferQueue(&mProducer, &mConsumer);
70 }
71
testBufferItem(const IGraphicBufferProducer::QueueBufferInput & input,const BufferItem & item)72 void testBufferItem(const IGraphicBufferProducer::QueueBufferInput& input,
73 const BufferItem& item) {
74 int64_t timestamp;
75 bool isAutoTimestamp;
76 android_dataspace dataSpace;
77 Rect crop;
78 int scalingMode;
79 uint32_t transform;
80 sp<Fence> fence;
81
82 input.deflate(×tamp, &isAutoTimestamp, &dataSpace, &crop,
83 &scalingMode, &transform, &fence, NULL);
84 ASSERT_EQ(timestamp, item.mTimestamp);
85 ASSERT_EQ(isAutoTimestamp, item.mIsAutoTimestamp);
86 ASSERT_EQ(dataSpace, item.mDataSpace);
87 ASSERT_EQ(crop, item.mCrop);
88 ASSERT_EQ(static_cast<uint32_t>(scalingMode), item.mScalingMode);
89 ASSERT_EQ(transform, item.mTransform);
90 ASSERT_EQ(fence, item.mFence);
91 }
92
93 sp<IGraphicBufferProducer> mProducer;
94 sp<IGraphicBufferConsumer> mConsumer;
95 };
96
97 static const uint32_t TEST_DATA = 0x12345678u;
98
99 // XXX: Tests that fork a process to hold the BufferQueue must run before tests
100 // that use a local BufferQueue, or else Binder will get unhappy
101 //
102 // In one instance this was a crash in the createBufferQueue where the
103 // binder call to create a buffer allocator apparently got garbage back.
104 // See b/36592665.
TEST_F(BufferQueueTest,DISABLED_BufferQueueInAnotherProcess)105 TEST_F(BufferQueueTest, DISABLED_BufferQueueInAnotherProcess) {
106 const String16 PRODUCER_NAME = String16("BQTestProducer");
107 const String16 CONSUMER_NAME = String16("BQTestConsumer");
108
109 pid_t forkPid = fork();
110 ASSERT_NE(forkPid, -1);
111
112 if (forkPid == 0) {
113 // Child process
114 sp<IGraphicBufferProducer> producer;
115 sp<IGraphicBufferConsumer> consumer;
116 BufferQueue::createBufferQueue(&producer, &consumer);
117 sp<IServiceManager> serviceManager = defaultServiceManager();
118 serviceManager->addService(PRODUCER_NAME, IInterface::asBinder(producer));
119 serviceManager->addService(CONSUMER_NAME, IInterface::asBinder(consumer));
120 ProcessState::self()->startThreadPool();
121 IPCThreadState::self()->joinThreadPool();
122 LOG_ALWAYS_FATAL("Shouldn't be here");
123 }
124
125 sp<IServiceManager> serviceManager = defaultServiceManager();
126 sp<IBinder> binderProducer =
127 serviceManager->getService(PRODUCER_NAME);
128 mProducer = interface_cast<IGraphicBufferProducer>(binderProducer);
129 EXPECT_TRUE(mProducer != NULL);
130 sp<IBinder> binderConsumer =
131 serviceManager->getService(CONSUMER_NAME);
132 mConsumer = interface_cast<IGraphicBufferConsumer>(binderConsumer);
133 EXPECT_TRUE(mConsumer != NULL);
134
135 sp<DummyConsumer> dc(new DummyConsumer);
136 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
137 IGraphicBufferProducer::QueueBufferOutput output;
138 ASSERT_EQ(OK,
139 mProducer->connect(NULL, NATIVE_WINDOW_API_CPU, false, &output));
140
141 int slot;
142 sp<Fence> fence;
143 sp<GraphicBuffer> buffer;
144 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
145 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
146 GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
147 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
148
149 uint32_t* dataIn;
150 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
151 reinterpret_cast<void**>(&dataIn)));
152 *dataIn = TEST_DATA;
153 ASSERT_EQ(OK, buffer->unlock());
154
155 IGraphicBufferProducer::QueueBufferInput input(0, false,
156 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
157 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
158 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
159
160 BufferItem item;
161 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
162
163 uint32_t* dataOut;
164 ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
165 reinterpret_cast<void**>(&dataOut)));
166 ASSERT_EQ(*dataOut, TEST_DATA);
167 ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
168 }
169
TEST_F(BufferQueueTest,AcquireBuffer_ExceedsMaxAcquireCount_Fails)170 TEST_F(BufferQueueTest, AcquireBuffer_ExceedsMaxAcquireCount_Fails) {
171 createBufferQueue();
172 sp<DummyConsumer> dc(new DummyConsumer);
173 mConsumer->consumerConnect(dc, false);
174 IGraphicBufferProducer::QueueBufferOutput qbo;
175 mProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, false,
176 &qbo);
177 mProducer->setMaxDequeuedBufferCount(3);
178
179 int slot;
180 sp<Fence> fence;
181 sp<GraphicBuffer> buf;
182 IGraphicBufferProducer::QueueBufferInput qbi(0, false,
183 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
184 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
185 BufferItem item;
186
187 for (int i = 0; i < 2; i++) {
188 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
189 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0,
190 GRALLOC_USAGE_SW_READ_OFTEN, nullptr));
191 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
192 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
193 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
194 }
195
196 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
197 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0,
198 GRALLOC_USAGE_SW_READ_OFTEN, nullptr));
199 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
200 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
201
202 // Acquire the third buffer, which should fail.
203 ASSERT_EQ(INVALID_OPERATION, mConsumer->acquireBuffer(&item, 0));
204 }
205
TEST_F(BufferQueueTest,SetMaxAcquiredBufferCountWithIllegalValues_ReturnsError)206 TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithIllegalValues_ReturnsError) {
207 createBufferQueue();
208 sp<DummyConsumer> dc(new DummyConsumer);
209 mConsumer->consumerConnect(dc, false);
210
211 EXPECT_EQ(OK, mConsumer->setMaxBufferCount(10));
212 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(10));
213
214 IGraphicBufferProducer::QueueBufferOutput qbo;
215 mProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, false,
216 &qbo);
217 mProducer->setMaxDequeuedBufferCount(3);
218
219 int minBufferCount;
220 ASSERT_NO_FATAL_FAILURE(GetMinUndequeuedBufferCount(&minBufferCount));
221 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(
222 minBufferCount - 1));
223
224 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(0));
225 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(-3));
226 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(
227 BufferQueue::MAX_MAX_ACQUIRED_BUFFERS+1));
228 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(100));
229
230 int slot;
231 sp<Fence> fence;
232 sp<GraphicBuffer> buf;
233 IGraphicBufferProducer::QueueBufferInput qbi(0, false,
234 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
235 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
236 BufferItem item;
237 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(3));
238 for (int i = 0; i < 3; i++) {
239 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
240 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0,
241 GRALLOC_USAGE_SW_READ_OFTEN, nullptr));
242 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
243 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
244 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
245 }
246
247 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(2));
248 }
249
TEST_F(BufferQueueTest,SetMaxAcquiredBufferCountWithLegalValues_Succeeds)250 TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithLegalValues_Succeeds) {
251 createBufferQueue();
252 sp<DummyConsumer> dc(new DummyConsumer);
253 mConsumer->consumerConnect(dc, false);
254
255 IGraphicBufferProducer::QueueBufferOutput qbo;
256 mProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, false,
257 &qbo);
258 mProducer->setMaxDequeuedBufferCount(2);
259
260 int minBufferCount;
261 ASSERT_NO_FATAL_FAILURE(GetMinUndequeuedBufferCount(&minBufferCount));
262
263 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
264 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(2));
265 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(minBufferCount));
266
267 int slot;
268 sp<Fence> fence;
269 sp<GraphicBuffer> buf;
270 IGraphicBufferProducer::QueueBufferInput qbi(0, false,
271 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
272 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
273 BufferItem item;
274
275 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
276 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0,
277 GRALLOC_USAGE_SW_READ_OFTEN, nullptr));
278 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
279 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
280 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
281
282 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(3));
283
284 for (int i = 0; i < 2; i++) {
285 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
286 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0,
287 GRALLOC_USAGE_SW_READ_OFTEN, nullptr));
288 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
289 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
290 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
291 }
292
293 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(
294 BufferQueue::MAX_MAX_ACQUIRED_BUFFERS));
295 }
296
TEST_F(BufferQueueTest,SetMaxBufferCountWithLegalValues_Succeeds)297 TEST_F(BufferQueueTest, SetMaxBufferCountWithLegalValues_Succeeds) {
298 createBufferQueue();
299 sp<DummyConsumer> dc(new DummyConsumer);
300 mConsumer->consumerConnect(dc, false);
301
302 // Test shared buffer mode
303 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
304 }
305
TEST_F(BufferQueueTest,SetMaxBufferCountWithIllegalValues_ReturnsError)306 TEST_F(BufferQueueTest, SetMaxBufferCountWithIllegalValues_ReturnsError) {
307 createBufferQueue();
308 sp<DummyConsumer> dc(new DummyConsumer);
309 mConsumer->consumerConnect(dc, false);
310
311 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(0));
312 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(
313 BufferQueue::NUM_BUFFER_SLOTS + 1));
314
315 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(5));
316 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(3));
317 }
318
TEST_F(BufferQueueTest,DetachAndReattachOnProducerSide)319 TEST_F(BufferQueueTest, DetachAndReattachOnProducerSide) {
320 createBufferQueue();
321 sp<DummyConsumer> dc(new DummyConsumer);
322 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
323 IGraphicBufferProducer::QueueBufferOutput output;
324 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
325 NATIVE_WINDOW_API_CPU, false, &output));
326
327 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(-1)); // Index too low
328 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(
329 BufferQueueDefs::NUM_BUFFER_SLOTS)); // Index too high
330 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(0)); // Not dequeued
331
332 int slot;
333 sp<Fence> fence;
334 sp<GraphicBuffer> buffer;
335 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
336 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
337 GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
338 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(slot)); // Not requested
339 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
340 ASSERT_EQ(OK, mProducer->detachBuffer(slot));
341 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(slot)); // Not dequeued
342
343 sp<GraphicBuffer> safeToClobberBuffer;
344 // Can no longer request buffer from this slot
345 ASSERT_EQ(BAD_VALUE, mProducer->requestBuffer(slot, &safeToClobberBuffer));
346
347 uint32_t* dataIn;
348 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
349 reinterpret_cast<void**>(&dataIn)));
350 *dataIn = TEST_DATA;
351 ASSERT_EQ(OK, buffer->unlock());
352
353 int newSlot;
354 ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(NULL, safeToClobberBuffer));
355 ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(&newSlot, NULL));
356
357 ASSERT_EQ(OK, mProducer->attachBuffer(&newSlot, buffer));
358 IGraphicBufferProducer::QueueBufferInput input(0, false,
359 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
360 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
361 ASSERT_EQ(OK, mProducer->queueBuffer(newSlot, input, &output));
362
363 BufferItem item;
364 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
365
366 uint32_t* dataOut;
367 ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
368 reinterpret_cast<void**>(&dataOut)));
369 ASSERT_EQ(*dataOut, TEST_DATA);
370 ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
371 }
372
TEST_F(BufferQueueTest,DetachAndReattachOnConsumerSide)373 TEST_F(BufferQueueTest, DetachAndReattachOnConsumerSide) {
374 createBufferQueue();
375 sp<DummyConsumer> dc(new DummyConsumer);
376 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
377 IGraphicBufferProducer::QueueBufferOutput output;
378 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
379 NATIVE_WINDOW_API_CPU, false, &output));
380
381 int slot;
382 sp<Fence> fence;
383 sp<GraphicBuffer> buffer;
384 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
385 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
386 GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
387 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
388 IGraphicBufferProducer::QueueBufferInput input(0, false,
389 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
390 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
391 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
392
393 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(-1)); // Index too low
394 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(
395 BufferQueueDefs::NUM_BUFFER_SLOTS)); // Index too high
396 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(0)); // Not acquired
397
398 BufferItem item;
399 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
400
401 ASSERT_EQ(OK, mConsumer->detachBuffer(item.mSlot));
402 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(item.mSlot)); // Not acquired
403
404 uint32_t* dataIn;
405 ASSERT_EQ(OK, item.mGraphicBuffer->lock(
406 GraphicBuffer::USAGE_SW_WRITE_OFTEN,
407 reinterpret_cast<void**>(&dataIn)));
408 *dataIn = TEST_DATA;
409 ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
410
411 int newSlot;
412 sp<GraphicBuffer> safeToClobberBuffer;
413 ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(NULL, safeToClobberBuffer));
414 ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(&newSlot, NULL));
415 ASSERT_EQ(OK, mConsumer->attachBuffer(&newSlot, item.mGraphicBuffer));
416
417 ASSERT_EQ(OK, mConsumer->releaseBuffer(newSlot, 0, EGL_NO_DISPLAY,
418 EGL_NO_SYNC_KHR, Fence::NO_FENCE));
419
420 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
421 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
422 GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
423 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
424
425 uint32_t* dataOut;
426 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
427 reinterpret_cast<void**>(&dataOut)));
428 ASSERT_EQ(*dataOut, TEST_DATA);
429 ASSERT_EQ(OK, buffer->unlock());
430 }
431
TEST_F(BufferQueueTest,MoveFromConsumerToProducer)432 TEST_F(BufferQueueTest, MoveFromConsumerToProducer) {
433 createBufferQueue();
434 sp<DummyConsumer> dc(new DummyConsumer);
435 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
436 IGraphicBufferProducer::QueueBufferOutput output;
437 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
438 NATIVE_WINDOW_API_CPU, false, &output));
439
440 int slot;
441 sp<Fence> fence;
442 sp<GraphicBuffer> buffer;
443 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
444 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
445 GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
446 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
447
448 uint32_t* dataIn;
449 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
450 reinterpret_cast<void**>(&dataIn)));
451 *dataIn = TEST_DATA;
452 ASSERT_EQ(OK, buffer->unlock());
453
454 IGraphicBufferProducer::QueueBufferInput input(0, false,
455 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
456 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
457 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
458
459 BufferItem item;
460 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
461 ASSERT_EQ(OK, mConsumer->detachBuffer(item.mSlot));
462
463 int newSlot;
464 ASSERT_EQ(OK, mProducer->attachBuffer(&newSlot, item.mGraphicBuffer));
465 ASSERT_EQ(OK, mProducer->queueBuffer(newSlot, input, &output));
466 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
467
468 uint32_t* dataOut;
469 ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
470 reinterpret_cast<void**>(&dataOut)));
471 ASSERT_EQ(*dataOut, TEST_DATA);
472 ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
473 }
474
TEST_F(BufferQueueTest,TestDisallowingAllocation)475 TEST_F(BufferQueueTest, TestDisallowingAllocation) {
476 createBufferQueue();
477 sp<DummyConsumer> dc(new DummyConsumer);
478 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
479 IGraphicBufferProducer::QueueBufferOutput output;
480 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
481 NATIVE_WINDOW_API_CPU, true, &output));
482
483 static const uint32_t WIDTH = 320;
484 static const uint32_t HEIGHT = 240;
485
486 ASSERT_EQ(OK, mConsumer->setDefaultBufferSize(WIDTH, HEIGHT));
487
488 int slot;
489 sp<Fence> fence;
490 sp<GraphicBuffer> buffer;
491 // This should return an error since it would require an allocation
492 ASSERT_EQ(OK, mProducer->allowAllocation(false));
493 ASSERT_EQ(WOULD_BLOCK, mProducer->dequeueBuffer(&slot, &fence, 0, 0,
494 0, GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
495
496 // This should succeed, now that we've lifted the prohibition
497 ASSERT_EQ(OK, mProducer->allowAllocation(true));
498 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
499 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
500 GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
501
502 // Release the previous buffer back to the BufferQueue
503 mProducer->cancelBuffer(slot, fence);
504
505 // This should fail since we're requesting a different size
506 ASSERT_EQ(OK, mProducer->allowAllocation(false));
507 ASSERT_EQ(WOULD_BLOCK, mProducer->dequeueBuffer(&slot, &fence,
508 WIDTH * 2, HEIGHT * 2, 0, GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
509 }
510
TEST_F(BufferQueueTest,TestGenerationNumbers)511 TEST_F(BufferQueueTest, TestGenerationNumbers) {
512 createBufferQueue();
513 sp<DummyConsumer> dc(new DummyConsumer);
514 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
515 IGraphicBufferProducer::QueueBufferOutput output;
516 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
517 NATIVE_WINDOW_API_CPU, true, &output));
518
519 ASSERT_EQ(OK, mProducer->setGenerationNumber(1));
520
521 // Get one buffer to play with
522 int slot;
523 sp<Fence> fence;
524 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
525 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
526
527 sp<GraphicBuffer> buffer;
528 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
529
530 // Ensure that the generation number we set propagates to allocated buffers
531 ASSERT_EQ(1U, buffer->getGenerationNumber());
532
533 ASSERT_EQ(OK, mProducer->detachBuffer(slot));
534
535 ASSERT_EQ(OK, mProducer->setGenerationNumber(2));
536
537 // These should fail, since we've changed the generation number on the queue
538 int outSlot;
539 ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(&outSlot, buffer));
540 ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(&outSlot, buffer));
541
542 buffer->setGenerationNumber(2);
543
544 // This should succeed now that we've changed the buffer's generation number
545 ASSERT_EQ(OK, mProducer->attachBuffer(&outSlot, buffer));
546
547 ASSERT_EQ(OK, mProducer->detachBuffer(outSlot));
548
549 // This should also succeed with the new generation number
550 ASSERT_EQ(OK, mConsumer->attachBuffer(&outSlot, buffer));
551 }
552
TEST_F(BufferQueueTest,TestSharedBufferModeWithoutAutoRefresh)553 TEST_F(BufferQueueTest, TestSharedBufferModeWithoutAutoRefresh) {
554 createBufferQueue();
555 sp<DummyConsumer> dc(new DummyConsumer);
556 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
557 IGraphicBufferProducer::QueueBufferOutput output;
558 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
559 NATIVE_WINDOW_API_CPU, true, &output));
560
561 ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
562
563 // Get a buffer
564 int sharedSlot;
565 sp<Fence> fence;
566 sp<GraphicBuffer> buffer;
567 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
568 mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0, nullptr));
569 ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
570
571 // Queue the buffer
572 IGraphicBufferProducer::QueueBufferInput input(0, false,
573 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
574 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
575 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
576
577 // Repeatedly queue and dequeue a buffer from the producer side, it should
578 // always return the same one. And we won't run out of buffers because it's
579 // always the same one and because async mode gets enabled.
580 int slot;
581 for (int i = 0; i < 5; i++) {
582 ASSERT_EQ(OK, mProducer->dequeueBuffer(
583 &slot, &fence, 0, 0, 0, 0, nullptr));
584 ASSERT_EQ(sharedSlot, slot);
585 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
586 }
587
588 // acquire the buffer
589 BufferItem item;
590 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
591 ASSERT_EQ(sharedSlot, item.mSlot);
592 testBufferItem(input, item);
593 ASSERT_EQ(true, item.mQueuedBuffer);
594 ASSERT_EQ(false, item.mAutoRefresh);
595
596 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
597 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
598
599 // attempt to acquire a second time should return no buffer available
600 ASSERT_EQ(IGraphicBufferConsumer::NO_BUFFER_AVAILABLE,
601 mConsumer->acquireBuffer(&item, 0));
602 }
603
TEST_F(BufferQueueTest,TestSharedBufferModeWithAutoRefresh)604 TEST_F(BufferQueueTest, TestSharedBufferModeWithAutoRefresh) {
605 createBufferQueue();
606 sp<DummyConsumer> dc(new DummyConsumer);
607 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
608 IGraphicBufferProducer::QueueBufferOutput output;
609 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
610 NATIVE_WINDOW_API_CPU, true, &output));
611
612 ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
613 ASSERT_EQ(OK, mProducer->setAutoRefresh(true));
614
615 // Get a buffer
616 int sharedSlot;
617 sp<Fence> fence;
618 sp<GraphicBuffer> buffer;
619 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
620 mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0, nullptr));
621 ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
622
623 // Queue the buffer
624 IGraphicBufferProducer::QueueBufferInput input(0, false,
625 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
626 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
627 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
628
629 // Repeatedly acquire and release a buffer from the consumer side, it should
630 // always return the same one.
631 BufferItem item;
632 for (int i = 0; i < 5; i++) {
633 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
634 ASSERT_EQ(sharedSlot, item.mSlot);
635 testBufferItem(input, item);
636 ASSERT_EQ(i == 0, item.mQueuedBuffer);
637 ASSERT_EQ(true, item.mAutoRefresh);
638
639 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
640 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
641 }
642
643 // Repeatedly queue and dequeue a buffer from the producer side, it should
644 // always return the same one.
645 int slot;
646 for (int i = 0; i < 5; i++) {
647 ASSERT_EQ(OK, mProducer->dequeueBuffer(
648 &slot, &fence, 0, 0, 0, 0, nullptr));
649 ASSERT_EQ(sharedSlot, slot);
650 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
651 }
652
653 // Repeatedly acquire and release a buffer from the consumer side, it should
654 // always return the same one. First grabbing them from the queue and then
655 // when the queue is empty, returning the shared buffer.
656 for (int i = 0; i < 10; i++) {
657 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
658 ASSERT_EQ(sharedSlot, item.mSlot);
659 ASSERT_EQ(0, item.mTimestamp);
660 ASSERT_EQ(false, item.mIsAutoTimestamp);
661 ASSERT_EQ(HAL_DATASPACE_UNKNOWN, item.mDataSpace);
662 ASSERT_EQ(Rect(0, 0, 1, 1), item.mCrop);
663 ASSERT_EQ(NATIVE_WINDOW_SCALING_MODE_FREEZE, item.mScalingMode);
664 ASSERT_EQ(0u, item.mTransform);
665 ASSERT_EQ(Fence::NO_FENCE, item.mFence);
666 ASSERT_EQ(i == 0, item.mQueuedBuffer);
667 ASSERT_EQ(true, item.mAutoRefresh);
668
669 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
670 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
671 }
672 }
673
TEST_F(BufferQueueTest,TestSharedBufferModeUsingAlreadyDequeuedBuffer)674 TEST_F(BufferQueueTest, TestSharedBufferModeUsingAlreadyDequeuedBuffer) {
675 createBufferQueue();
676 sp<DummyConsumer> dc(new DummyConsumer);
677 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
678 IGraphicBufferProducer::QueueBufferOutput output;
679 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
680 NATIVE_WINDOW_API_CPU, true, &output));
681
682 // Dequeue a buffer
683 int sharedSlot;
684 sp<Fence> fence;
685 sp<GraphicBuffer> buffer;
686 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
687 mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0, nullptr));
688 ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
689
690 // Enable shared buffer mode
691 ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
692
693 // Queue the buffer
694 IGraphicBufferProducer::QueueBufferInput input(0, false,
695 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
696 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
697 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
698
699 // Repeatedly queue and dequeue a buffer from the producer side, it should
700 // always return the same one. And we won't run out of buffers because it's
701 // always the same one and because async mode gets enabled.
702 int slot;
703 for (int i = 0; i < 5; i++) {
704 ASSERT_EQ(OK, mProducer->dequeueBuffer(
705 &slot, &fence, 0, 0, 0, 0, nullptr));
706 ASSERT_EQ(sharedSlot, slot);
707 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
708 }
709
710 // acquire the buffer
711 BufferItem item;
712 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
713 ASSERT_EQ(sharedSlot, item.mSlot);
714 testBufferItem(input, item);
715 ASSERT_EQ(true, item.mQueuedBuffer);
716 ASSERT_EQ(false, item.mAutoRefresh);
717
718 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
719 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
720
721 // attempt to acquire a second time should return no buffer available
722 ASSERT_EQ(IGraphicBufferConsumer::NO_BUFFER_AVAILABLE,
723 mConsumer->acquireBuffer(&item, 0));
724 }
725
TEST_F(BufferQueueTest,TestTimeouts)726 TEST_F(BufferQueueTest, TestTimeouts) {
727 createBufferQueue();
728 sp<DummyConsumer> dc(new DummyConsumer);
729 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
730 IGraphicBufferProducer::QueueBufferOutput output;
731 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
732 NATIVE_WINDOW_API_CPU, true, &output));
733
734 // Fill up the queue. Since the controlledByApp flags are set to true, this
735 // queue should be in non-blocking mode, and we should be recycling the same
736 // two buffers
737 for (int i = 0; i < 5; ++i) {
738 int slot = BufferQueue::INVALID_BUFFER_SLOT;
739 sp<Fence> fence = Fence::NO_FENCE;
740 auto result = mProducer->dequeueBuffer(
741 &slot, &fence, 0, 0, 0, 0, nullptr);
742 if (i < 2) {
743 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
744 result);
745 } else {
746 ASSERT_EQ(OK, result);
747 }
748 sp<GraphicBuffer> buffer;
749 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
750 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
751 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
752 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
753 IGraphicBufferProducer::QueueBufferOutput output{};
754 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
755 }
756
757 const auto TIMEOUT = ms2ns(250);
758 mProducer->setDequeueTimeout(TIMEOUT);
759
760 // Setting a timeout will change the BufferQueue into blocking mode (with
761 // one droppable buffer in the queue and one free from the previous
762 // dequeue/queues), so dequeue and queue two more buffers: one to replace
763 // the current droppable buffer, and a second to max out the buffer count
764 sp<GraphicBuffer> buffer; // Save a buffer to attach later
765 for (int i = 0; i < 2; ++i) {
766 int slot = BufferQueue::INVALID_BUFFER_SLOT;
767 sp<Fence> fence = Fence::NO_FENCE;
768 ASSERT_EQ(OK, mProducer->dequeueBuffer(
769 &slot, &fence, 0, 0, 0, 0, nullptr));
770 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
771 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
772 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
773 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
774 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
775 }
776
777 int slot = BufferQueue::INVALID_BUFFER_SLOT;
778 sp<Fence> fence = Fence::NO_FENCE;
779 auto startTime = systemTime();
780 ASSERT_EQ(TIMED_OUT, mProducer->dequeueBuffer(
781 &slot, &fence, 0, 0, 0, 0, nullptr));
782 ASSERT_GE(systemTime() - startTime, TIMEOUT);
783
784 // We're technically attaching the same buffer multiple times (since we
785 // queued it previously), but that doesn't matter for this test
786 startTime = systemTime();
787 ASSERT_EQ(TIMED_OUT, mProducer->attachBuffer(&slot, buffer));
788 ASSERT_GE(systemTime() - startTime, TIMEOUT);
789 }
790
TEST_F(BufferQueueTest,CanAttachWhileDisallowingAllocation)791 TEST_F(BufferQueueTest, CanAttachWhileDisallowingAllocation) {
792 createBufferQueue();
793 sp<DummyConsumer> dc(new DummyConsumer);
794 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
795 IGraphicBufferProducer::QueueBufferOutput output;
796 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
797 NATIVE_WINDOW_API_CPU, true, &output));
798
799 int slot = BufferQueue::INVALID_BUFFER_SLOT;
800 sp<Fence> sourceFence;
801 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
802 mProducer->dequeueBuffer(&slot, &sourceFence, 0, 0, 0, 0, nullptr));
803 sp<GraphicBuffer> buffer;
804 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
805 ASSERT_EQ(OK, mProducer->detachBuffer(slot));
806
807 ASSERT_EQ(OK, mProducer->allowAllocation(false));
808
809 slot = BufferQueue::INVALID_BUFFER_SLOT;
810 ASSERT_EQ(OK, mProducer->attachBuffer(&slot, buffer));
811 }
812
TEST_F(BufferQueueTest,CanRetrieveLastQueuedBuffer)813 TEST_F(BufferQueueTest, CanRetrieveLastQueuedBuffer) {
814 createBufferQueue();
815 sp<DummyConsumer> dc(new DummyConsumer);
816 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
817 IGraphicBufferProducer::QueueBufferOutput output;
818 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
819 NATIVE_WINDOW_API_CPU, false, &output));
820
821 // Dequeue and queue the first buffer, storing the handle
822 int slot = BufferQueue::INVALID_BUFFER_SLOT;
823 sp<Fence> fence;
824 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
825 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
826 sp<GraphicBuffer> firstBuffer;
827 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &firstBuffer));
828
829 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
830 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
831 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
832 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
833
834 // Dequeue a second buffer
835 slot = BufferQueue::INVALID_BUFFER_SLOT;
836 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
837 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
838 sp<GraphicBuffer> secondBuffer;
839 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &secondBuffer));
840
841 // Ensure it's a new buffer
842 ASSERT_NE(firstBuffer->getNativeBuffer()->handle,
843 secondBuffer->getNativeBuffer()->handle);
844
845 // Queue the second buffer
846 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
847
848 // Acquire and release both buffers
849 for (size_t i = 0; i < 2; ++i) {
850 BufferItem item;
851 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
852 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
853 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
854 }
855
856 // Make sure we got the second buffer back
857 sp<GraphicBuffer> returnedBuffer;
858 sp<Fence> returnedFence;
859 float transform[16];
860 ASSERT_EQ(OK,
861 mProducer->getLastQueuedBuffer(&returnedBuffer, &returnedFence,
862 transform));
863 ASSERT_EQ(secondBuffer->getNativeBuffer()->handle,
864 returnedBuffer->getNativeBuffer()->handle);
865 }
866
TEST_F(BufferQueueTest,TestOccupancyHistory)867 TEST_F(BufferQueueTest, TestOccupancyHistory) {
868 createBufferQueue();
869 sp<DummyConsumer> dc(new DummyConsumer);
870 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
871 IGraphicBufferProducer::QueueBufferOutput output;
872 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
873 NATIVE_WINDOW_API_CPU, false, &output));
874
875 int slot = BufferQueue::INVALID_BUFFER_SLOT;
876 sp<Fence> fence = Fence::NO_FENCE;
877 sp<GraphicBuffer> buffer = nullptr;
878 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
879 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
880 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
881 BufferItem item{};
882
883 // Preallocate, dequeue, request, and cancel 3 buffers so we don't get
884 // BUFFER_NEEDS_REALLOCATION below
885 int slots[3] = {};
886 mProducer->setMaxDequeuedBufferCount(3);
887 for (size_t i = 0; i < 3; ++i) {
888 status_t result = mProducer->dequeueBuffer(&slots[i], &fence,
889 0, 0, 0, 0, nullptr);
890 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
891 ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
892 }
893 for (size_t i = 0; i < 3; ++i) {
894 ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE));
895 }
896
897 // Create 3 segments
898
899 // The first segment is a two-buffer segment, so we only put one buffer into
900 // the queue at a time
901 for (size_t i = 0; i < 5; ++i) {
902 ASSERT_EQ(OK, mProducer->dequeueBuffer(
903 &slot, &fence, 0, 0, 0, 0, nullptr));
904 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
905 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
906 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
907 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
908 std::this_thread::sleep_for(16ms);
909 }
910
911 // Sleep between segments
912 std::this_thread::sleep_for(500ms);
913
914 // The second segment is a double-buffer segment. It starts the same as the
915 // two-buffer segment, but then at the end, we put two buffers in the queue
916 // at the same time before draining it.
917 for (size_t i = 0; i < 5; ++i) {
918 ASSERT_EQ(OK, mProducer->dequeueBuffer(
919 &slot, &fence, 0, 0, 0, 0, nullptr));
920 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
921 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
922 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
923 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
924 std::this_thread::sleep_for(16ms);
925 }
926 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
927 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
928 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
929 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
930 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
931 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
932 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
933 std::this_thread::sleep_for(16ms);
934 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
935 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
936 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
937
938 // Sleep between segments
939 std::this_thread::sleep_for(500ms);
940
941 // The third segment is a triple-buffer segment, so the queue is switching
942 // between one buffer and two buffers deep.
943 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
944 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
945 for (size_t i = 0; i < 5; ++i) {
946 ASSERT_EQ(OK, mProducer->dequeueBuffer(
947 &slot, &fence, 0, 0, 0, 0, nullptr));
948 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
949 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
950 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
951 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
952 std::this_thread::sleep_for(16ms);
953 }
954 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
955 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
956 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
957
958 // Now we read the segments
959 std::vector<OccupancyTracker::Segment> history;
960 ASSERT_EQ(OK, mConsumer->getOccupancyHistory(false, &history));
961
962 // Since we didn't force a flush, we should only get the first two segments
963 // (since the third segment hasn't been closed out by the appearance of a
964 // new segment yet)
965 ASSERT_EQ(2u, history.size());
966
967 // The first segment (which will be history[1], since the newest segment
968 // should be at the front of the vector) should be a two-buffer segment,
969 // which implies that the occupancy average should be between 0 and 1, and
970 // usedThirdBuffer should be false
971 const auto& firstSegment = history[1];
972 ASSERT_EQ(5u, firstSegment.numFrames);
973 ASSERT_LT(0, firstSegment.occupancyAverage);
974 ASSERT_GT(1, firstSegment.occupancyAverage);
975 ASSERT_EQ(false, firstSegment.usedThirdBuffer);
976
977 // The second segment should be a double-buffered segment, which implies that
978 // the occupancy average should be between 0 and 1, but usedThirdBuffer
979 // should be true
980 const auto& secondSegment = history[0];
981 ASSERT_EQ(7u, secondSegment.numFrames);
982 ASSERT_LT(0, secondSegment.occupancyAverage);
983 ASSERT_GT(1, secondSegment.occupancyAverage);
984 ASSERT_EQ(true, secondSegment.usedThirdBuffer);
985
986 // If we read the segments again without flushing, we shouldn't get any new
987 // segments
988 ASSERT_EQ(OK, mConsumer->getOccupancyHistory(false, &history));
989 ASSERT_EQ(0u, history.size());
990
991 // Read the segments again, this time forcing a flush so we get the third
992 // segment
993 ASSERT_EQ(OK, mConsumer->getOccupancyHistory(true, &history));
994 ASSERT_EQ(1u, history.size());
995
996 // This segment should be a triple-buffered segment, which implies that the
997 // occupancy average should be between 1 and 2, and usedThirdBuffer should
998 // be true
999 const auto& thirdSegment = history[0];
1000 ASSERT_EQ(6u, thirdSegment.numFrames);
1001 ASSERT_LT(1, thirdSegment.occupancyAverage);
1002 ASSERT_GT(2, thirdSegment.occupancyAverage);
1003 ASSERT_EQ(true, thirdSegment.usedThirdBuffer);
1004 }
1005
TEST_F(BufferQueueTest,TestDiscardFreeBuffers)1006 TEST_F(BufferQueueTest, TestDiscardFreeBuffers) {
1007 createBufferQueue();
1008 sp<DummyConsumer> dc(new DummyConsumer);
1009 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
1010 IGraphicBufferProducer::QueueBufferOutput output;
1011 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
1012 NATIVE_WINDOW_API_CPU, false, &output));
1013
1014 int slot = BufferQueue::INVALID_BUFFER_SLOT;
1015 sp<Fence> fence = Fence::NO_FENCE;
1016 sp<GraphicBuffer> buffer = nullptr;
1017 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1018 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1019 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1020 BufferItem item{};
1021
1022 // Preallocate, dequeue, request, and cancel 4 buffers so we don't get
1023 // BUFFER_NEEDS_REALLOCATION below
1024 int slots[4] = {};
1025 mProducer->setMaxDequeuedBufferCount(4);
1026 for (size_t i = 0; i < 4; ++i) {
1027 status_t result = mProducer->dequeueBuffer(&slots[i], &fence,
1028 0, 0, 0, 0, nullptr);
1029 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1030 ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
1031 }
1032 for (size_t i = 0; i < 4; ++i) {
1033 ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE));
1034 }
1035
1036 // Get buffers in all states: dequeued, filled, acquired, free
1037
1038 // Fill 3 buffers
1039 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
1040 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1041 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
1042 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1043 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
1044 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1045 // Dequeue 1 buffer
1046 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
1047
1048 // Acquire and free 1 buffer
1049 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1050 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
1051 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
1052 // Acquire 1 buffer, leaving 1 filled buffer in queue
1053 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1054
1055 // Now discard the free buffers
1056 ASSERT_EQ(OK, mConsumer->discardFreeBuffers());
1057
1058 // Check no free buffers in dump
1059 String8 dumpString;
1060 mConsumer->dumpState(String8{}, &dumpString);
1061
1062 // Parse the dump to ensure that all buffer slots that are FREE also
1063 // have a null GraphicBuffer
1064 // Fragile - assumes the following format for the dump for a buffer entry:
1065 // ":%p\][^:]*state=FREE" where %p is the buffer pointer in hex.
1066 ssize_t idx = dumpString.find("state=FREE");
1067 while (idx != -1) {
1068 ssize_t bufferPtrIdx = idx - 1;
1069 while (bufferPtrIdx > 0) {
1070 if (dumpString[bufferPtrIdx] == ':') {
1071 bufferPtrIdx++;
1072 break;
1073 }
1074 bufferPtrIdx--;
1075 }
1076 ASSERT_GT(bufferPtrIdx, 0) << "Can't parse queue dump to validate";
1077 ssize_t nullPtrIdx = dumpString.find("0x0]", bufferPtrIdx);
1078 ASSERT_EQ(bufferPtrIdx, nullPtrIdx) << "Free buffer not discarded";
1079 idx = dumpString.find("FREE", idx + 1);
1080 }
1081 }
1082
TEST_F(BufferQueueTest,TestBufferReplacedInQueueBuffer)1083 TEST_F(BufferQueueTest, TestBufferReplacedInQueueBuffer) {
1084 createBufferQueue();
1085 sp<DummyConsumer> dc(new DummyConsumer);
1086 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
1087 IGraphicBufferProducer::QueueBufferOutput output;
1088 ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
1089 NATIVE_WINDOW_API_CPU, true, &output));
1090 ASSERT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
1091
1092 int slot = BufferQueue::INVALID_BUFFER_SLOT;
1093 sp<Fence> fence = Fence::NO_FENCE;
1094 sp<GraphicBuffer> buffer = nullptr;
1095 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1096 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1097 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1098 BufferItem item{};
1099
1100 // Preallocate, dequeue, request, and cancel 2 buffers so we don't get
1101 // BUFFER_NEEDS_REALLOCATION below
1102 int slots[2] = {};
1103 ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(2));
1104 for (size_t i = 0; i < 2; ++i) {
1105 status_t result = mProducer->dequeueBuffer(&slots[i], &fence,
1106 0, 0, 0, 0, nullptr);
1107 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1108 ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
1109 }
1110 for (size_t i = 0; i < 2; ++i) {
1111 ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE));
1112 }
1113
1114 // Fill 2 buffers without consumer consuming them. Verify that all
1115 // queued buffer returns proper bufferReplaced flag
1116 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
1117 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1118 ASSERT_EQ(false, output.bufferReplaced);
1119 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
1120 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1121 ASSERT_EQ(true, output.bufferReplaced);
1122 }
1123
TEST_F(BufferQueueTest,TestStaleBufferHandleSentAfterDisconnect)1124 TEST_F(BufferQueueTest, TestStaleBufferHandleSentAfterDisconnect) {
1125 createBufferQueue();
1126 sp<DummyConsumer> dc(new DummyConsumer);
1127 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
1128 IGraphicBufferProducer::QueueBufferOutput output;
1129 sp<IProducerListener> dummyListener(new DummyProducerListener);
1130 ASSERT_EQ(OK, mProducer->connect(dummyListener, NATIVE_WINDOW_API_CPU,
1131 true, &output));
1132
1133 int slot = BufferQueue::INVALID_BUFFER_SLOT;
1134 sp<Fence> fence = Fence::NO_FENCE;
1135 sp<GraphicBuffer> buffer = nullptr;
1136 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1137 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1138 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1139
1140 // Dequeue, request, and queue one buffer
1141 status_t result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0,
1142 nullptr);
1143 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1144 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
1145 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1146
1147 // Acquire and release the buffer. Upon acquiring, the buffer handle should
1148 // be non-null since this is the first time we've acquired this slot.
1149 BufferItem item;
1150 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1151 ASSERT_EQ(slot, item.mSlot);
1152 ASSERT_NE(nullptr, item.mGraphicBuffer.get());
1153 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
1154 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
1155
1156 // Dequeue and queue the buffer again
1157 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
1158 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1159
1160 // Acquire and release the buffer again. Upon acquiring, the buffer handle
1161 // should be null since this is not the first time we've acquired this slot.
1162 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1163 ASSERT_EQ(slot, item.mSlot);
1164 ASSERT_EQ(nullptr, item.mGraphicBuffer.get());
1165 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
1166 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
1167
1168 // Dequeue and queue the buffer again
1169 ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
1170 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1171
1172 // Disconnect the producer end. This should clear all of the slots and mark
1173 // the buffer in the queue as stale.
1174 ASSERT_EQ(OK, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
1175
1176 // Acquire the buffer again. Upon acquiring, the buffer handle should not be
1177 // null since the queued buffer should have been marked as stale, which
1178 // should trigger the BufferQueue to resend the buffer handle.
1179 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1180 ASSERT_EQ(slot, item.mSlot);
1181 ASSERT_NE(nullptr, item.mGraphicBuffer.get());
1182 }
1183
TEST_F(BufferQueueTest,TestProducerConnectDisconnect)1184 TEST_F(BufferQueueTest, TestProducerConnectDisconnect) {
1185 createBufferQueue();
1186 sp<DummyConsumer> dc(new DummyConsumer);
1187 ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
1188 IGraphicBufferProducer::QueueBufferOutput output;
1189 sp<IProducerListener> dummyListener(new DummyProducerListener);
1190 ASSERT_EQ(NO_INIT, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
1191 ASSERT_EQ(OK, mProducer->connect(
1192 dummyListener, NATIVE_WINDOW_API_CPU, true, &output));
1193 ASSERT_EQ(BAD_VALUE, mProducer->connect(
1194 dummyListener, NATIVE_WINDOW_API_MEDIA, true, &output));
1195
1196 ASSERT_EQ(BAD_VALUE, mProducer->disconnect(NATIVE_WINDOW_API_MEDIA));
1197 ASSERT_EQ(OK, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
1198 ASSERT_EQ(NO_INIT, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
1199 }
1200
1201 } // namespace android
1202