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 "Constants.h"
21 #include "MockConsumer.h"
22
23 #include <gui/BufferItem.h>
24 #include <gui/BufferItemConsumer.h>
25 #include <gui/BufferQueue.h>
26 #include <gui/IProducerListener.h>
27 #include <gui/Surface.h>
28
29 #include <ui/GraphicBuffer.h>
30 #include <ui/PictureProfileHandle.h>
31
32 #include <android-base/properties.h>
33
34 #include <binder/IPCThreadState.h>
35 #include <binder/IServiceManager.h>
36 #include <binder/ProcessState.h>
37
38 #include <utils/String8.h>
39 #include <utils/threads.h>
40
41 #include <system/window.h>
42
43 #include <gmock/gmock.h>
44 #include <gtest/gtest.h>
45
46 #include <future>
47 #include <thread>
48
49 #include <com_android_graphics_libgui_flags.h>
50
51 using namespace std::chrono_literals;
52
IsCuttlefish()53 static bool IsCuttlefish() {
54 return ::android::base::GetProperty("ro.product.board", "") == "cutf";
55 }
56
57 namespace android {
58 using namespace com::android::graphics::libgui;
59
60 class BufferQueueTest : public ::testing::Test {
61
62 public:
63 protected:
GetMinUndequeuedBufferCount(int * bufferCount)64 void GetMinUndequeuedBufferCount(int* bufferCount) {
65 ASSERT_TRUE(bufferCount != nullptr);
66 ASSERT_EQ(OK, mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
67 bufferCount));
68 ASSERT_GE(*bufferCount, 0);
69 }
70
createBufferQueue()71 void createBufferQueue() {
72 BufferQueue::createBufferQueue(&mProducer, &mConsumer);
73 }
74
testBufferItem(const IGraphicBufferProducer::QueueBufferInput & input,const BufferItem & item)75 void testBufferItem(const IGraphicBufferProducer::QueueBufferInput& input,
76 const BufferItem& item) {
77 int64_t timestamp;
78 bool isAutoTimestamp;
79 android_dataspace dataSpace;
80 Rect crop;
81 int scalingMode;
82 uint32_t transform;
83 sp<Fence> fence;
84
85 input.deflate(×tamp, &isAutoTimestamp, &dataSpace, &crop,
86 &scalingMode, &transform, &fence, nullptr);
87 ASSERT_EQ(timestamp, item.mTimestamp);
88 ASSERT_EQ(isAutoTimestamp, item.mIsAutoTimestamp);
89 ASSERT_EQ(dataSpace, item.mDataSpace);
90 ASSERT_EQ(crop, item.mCrop);
91 ASSERT_EQ(static_cast<uint32_t>(scalingMode), item.mScalingMode);
92 ASSERT_EQ(transform, item.mTransform);
93 ASSERT_EQ(fence, item.mFence);
94 }
95
96 sp<IGraphicBufferProducer> mProducer;
97 sp<IGraphicBufferConsumer> mConsumer;
98 };
99
100 static const uint32_t TEST_DATA = 0x12345678u;
101
102 // XXX: Tests that fork a process to hold the BufferQueue must run before tests
103 // that use a local BufferQueue, or else Binder will get unhappy
104 //
105 // In one instance this was a crash in the createBufferQueue where the
106 // binder call to create a buffer allocator apparently got garbage back.
107 // See b/36592665.
TEST_F(BufferQueueTest,DISABLED_BufferQueueInAnotherProcess)108 TEST_F(BufferQueueTest, DISABLED_BufferQueueInAnotherProcess) {
109 const String16 PRODUCER_NAME = String16("BQTestProducer");
110 const String16 CONSUMER_NAME = String16("BQTestConsumer");
111
112 pid_t forkPid = fork();
113 ASSERT_NE(forkPid, -1);
114
115 if (forkPid == 0) {
116 // Child process
117 sp<IGraphicBufferProducer> producer;
118 sp<IGraphicBufferConsumer> consumer;
119 BufferQueue::createBufferQueue(&producer, &consumer);
120 sp<IServiceManager> serviceManager = defaultServiceManager();
121 serviceManager->addService(PRODUCER_NAME, IInterface::asBinder(producer));
122 serviceManager->addService(CONSUMER_NAME, IInterface::asBinder(consumer));
123 ProcessState::self()->startThreadPool();
124 IPCThreadState::self()->joinThreadPool();
125 LOG_ALWAYS_FATAL("Shouldn't be here");
126 }
127
128 sp<IServiceManager> serviceManager = defaultServiceManager();
129 sp<IBinder> binderProducer = serviceManager->waitForService(PRODUCER_NAME);
130 mProducer = interface_cast<IGraphicBufferProducer>(binderProducer);
131 EXPECT_TRUE(mProducer != nullptr);
132 sp<IBinder> binderConsumer =
133 serviceManager->getService(CONSUMER_NAME);
134 mConsumer = interface_cast<IGraphicBufferConsumer>(binderConsumer);
135 EXPECT_TRUE(mConsumer != nullptr);
136
137 sp<MockConsumer> mc(new MockConsumer);
138 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
139 IGraphicBufferProducer::QueueBufferOutput output;
140 ASSERT_EQ(OK,
141 mProducer->connect(nullptr, NATIVE_WINDOW_API_CPU, false, &output));
142
143 int slot;
144 sp<Fence> fence;
145 sp<GraphicBuffer> buffer;
146 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
147 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
148 nullptr, nullptr));
149 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)));
154 *dataIn = TEST_DATA;
155 ASSERT_EQ(OK, buffer->unlock());
156
157 IGraphicBufferProducer::QueueBufferInput input(0, false,
158 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
159 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
160 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
161
162 BufferItem item;
163 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)));
168 ASSERT_EQ(*dataOut, TEST_DATA);
169 ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
170 }
171
TEST_F(BufferQueueTest,GetMaxBufferCountInQueueBufferOutput_Succeeds)172 TEST_F(BufferQueueTest, GetMaxBufferCountInQueueBufferOutput_Succeeds) {
173 createBufferQueue();
174 sp<MockConsumer> mc(new MockConsumer);
175 mConsumer->consumerConnect(mc, false);
176 int bufferCount = 50;
177 mConsumer->setMaxBufferCount(bufferCount);
178
179 IGraphicBufferProducer::QueueBufferOutput output;
180 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output);
181 ASSERT_EQ(output.maxBufferCount, bufferCount);
182 }
183
TEST_F(BufferQueueTest,AcquireBuffer_ExceedsMaxAcquireCount_Fails)184 TEST_F(BufferQueueTest, AcquireBuffer_ExceedsMaxAcquireCount_Fails) {
185 createBufferQueue();
186 sp<MockConsumer> mc(new MockConsumer);
187 mConsumer->consumerConnect(mc, false);
188 IGraphicBufferProducer::QueueBufferOutput qbo;
189 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &qbo);
190 mProducer->setMaxDequeuedBufferCount(3);
191
192 int slot;
193 sp<Fence> fence;
194 sp<GraphicBuffer> buf;
195 IGraphicBufferProducer::QueueBufferInput qbi(0, false,
196 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
197 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
198 BufferItem item;
199
200 for (int i = 0; i < 2; i++) {
201 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
202 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
203 nullptr, nullptr));
204 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
205 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
206 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
207 }
208
209 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
210 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
211 nullptr, nullptr));
212 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
213 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
214
215 // Acquire the third buffer, which should fail.
216 ASSERT_EQ(INVALID_OPERATION, mConsumer->acquireBuffer(&item, 0));
217 }
218
TEST_F(BufferQueueTest,SetMaxAcquiredBufferCountWithIllegalValues_ReturnsError)219 TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithIllegalValues_ReturnsError) {
220 createBufferQueue();
221 sp<MockConsumer> mc(new MockConsumer);
222 mConsumer->consumerConnect(mc, false);
223
224 EXPECT_EQ(OK, mConsumer->setMaxBufferCount(10));
225 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(10));
226
227 IGraphicBufferProducer::QueueBufferOutput qbo;
228 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &qbo);
229 mProducer->setMaxDequeuedBufferCount(3);
230
231 int minBufferCount;
232 ASSERT_NO_FATAL_FAILURE(GetMinUndequeuedBufferCount(&minBufferCount));
233 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(
234 minBufferCount - 1));
235
236 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(0));
237 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(-3));
238 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(
239 BufferQueue::MAX_MAX_ACQUIRED_BUFFERS+1));
240 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(100));
241
242 int slot;
243 sp<Fence> fence;
244 sp<GraphicBuffer> buf;
245 IGraphicBufferProducer::QueueBufferInput qbi(0, false,
246 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
247 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
248 BufferItem item;
249 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(3));
250 for (int i = 0; i < 3; i++) {
251 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
252 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
253 nullptr, nullptr));
254 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
255 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
256 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
257 }
258
259 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(2));
260 }
261
TEST_F(BufferQueueTest,SetMaxAcquiredBufferCountWithLegalValues_Succeeds)262 TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithLegalValues_Succeeds) {
263 createBufferQueue();
264 sp<MockConsumer> mc(new MockConsumer);
265 mConsumer->consumerConnect(mc, false);
266
267 IGraphicBufferProducer::QueueBufferOutput qbo;
268 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &qbo);
269 mProducer->setMaxDequeuedBufferCount(2);
270
271 int minBufferCount;
272 ASSERT_NO_FATAL_FAILURE(GetMinUndequeuedBufferCount(&minBufferCount));
273
274 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
275 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(2));
276 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(minBufferCount));
277
278 int slot;
279 sp<Fence> fence;
280 sp<GraphicBuffer> buf;
281 IGraphicBufferProducer::QueueBufferInput qbi(0, false,
282 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
283 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
284 BufferItem item;
285
286 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
287 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
288 nullptr, nullptr));
289 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
290 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
291 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
292
293 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(3));
294
295 for (int i = 0; i < 2; i++) {
296 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
297 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
298 nullptr, nullptr));
299 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
300 ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
301 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
302 }
303
304 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(
305 BufferQueue::MAX_MAX_ACQUIRED_BUFFERS));
306 }
307
TEST_F(BufferQueueTest,SetMaxBufferCountWithLegalValues_Succeeds)308 TEST_F(BufferQueueTest, SetMaxBufferCountWithLegalValues_Succeeds) {
309 createBufferQueue();
310 sp<MockConsumer> mc(new MockConsumer);
311 mConsumer->consumerConnect(mc, false);
312
313 // Test shared buffer mode
314 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
315 }
316
TEST_F(BufferQueueTest,SetMaxBufferCountWithIllegalValues_ReturnsError)317 TEST_F(BufferQueueTest, SetMaxBufferCountWithIllegalValues_ReturnsError) {
318 createBufferQueue();
319 sp<MockConsumer> mc(new MockConsumer);
320 mConsumer->consumerConnect(mc, false);
321
322 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(0));
323 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(
324 BufferQueue::NUM_BUFFER_SLOTS + 1));
325
326 EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(5));
327 EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(3));
328 }
329
TEST_F(BufferQueueTest,DetachAndReattachOnProducerSide)330 TEST_F(BufferQueueTest, DetachAndReattachOnProducerSide) {
331 createBufferQueue();
332 sp<MockConsumer> mc(new MockConsumer);
333 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
334 IGraphicBufferProducer::QueueBufferOutput output;
335 ASSERT_EQ(OK,
336 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
337
338 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(-1)); // Index too low
339 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(
340 BufferQueueDefs::NUM_BUFFER_SLOTS)); // Index too high
341 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(0)); // Not dequeued
342
343 int slot;
344 sp<Fence> fence;
345 sp<GraphicBuffer> buffer;
346 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
347 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
348 nullptr, nullptr));
349 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(slot)); // Not requested
350 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
351 ASSERT_EQ(OK, mProducer->detachBuffer(slot));
352 ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(slot)); // Not dequeued
353
354 sp<GraphicBuffer> safeToClobberBuffer;
355 // Can no longer request buffer from this slot
356 ASSERT_EQ(BAD_VALUE, mProducer->requestBuffer(slot, &safeToClobberBuffer));
357
358 uint32_t* dataIn;
359 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
360 reinterpret_cast<void**>(&dataIn)));
361 *dataIn = TEST_DATA;
362 ASSERT_EQ(OK, buffer->unlock());
363
364 int newSlot;
365 ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(nullptr, safeToClobberBuffer));
366 ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(&newSlot, nullptr));
367
368 ASSERT_EQ(OK, mProducer->attachBuffer(&newSlot, buffer));
369 IGraphicBufferProducer::QueueBufferInput input(0, false,
370 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
371 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
372 ASSERT_EQ(OK, mProducer->queueBuffer(newSlot, input, &output));
373
374 BufferItem item;
375 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
376
377 uint32_t* dataOut;
378 ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
379 reinterpret_cast<void**>(&dataOut)));
380 ASSERT_EQ(*dataOut, TEST_DATA);
381 ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
382 }
383
TEST_F(BufferQueueTest,DetachAndReattachOnConsumerSide)384 TEST_F(BufferQueueTest, DetachAndReattachOnConsumerSide) {
385 createBufferQueue();
386 sp<MockConsumer> mc(new MockConsumer);
387 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
388 IGraphicBufferProducer::QueueBufferOutput output;
389 ASSERT_EQ(OK,
390 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
391
392 int slot;
393 sp<Fence> fence;
394 sp<GraphicBuffer> buffer;
395 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
396 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
397 nullptr, nullptr));
398 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
399 IGraphicBufferProducer::QueueBufferInput input(0, false,
400 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
401 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
402 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
403
404 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(-1)); // Index too low
405 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(
406 BufferQueueDefs::NUM_BUFFER_SLOTS)); // Index too high
407 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(0)); // Not acquired
408
409 BufferItem item;
410 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
411
412 ASSERT_EQ(OK, mConsumer->detachBuffer(item.mSlot));
413 ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(item.mSlot)); // Not acquired
414
415 uint32_t* dataIn;
416 ASSERT_EQ(OK, item.mGraphicBuffer->lock(
417 GraphicBuffer::USAGE_SW_WRITE_OFTEN,
418 reinterpret_cast<void**>(&dataIn)));
419 *dataIn = TEST_DATA;
420 ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
421
422 int newSlot;
423 sp<GraphicBuffer> safeToClobberBuffer;
424 ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(nullptr, safeToClobberBuffer));
425 ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(&newSlot, nullptr));
426 ASSERT_EQ(OK, mConsumer->attachBuffer(&newSlot, item.mGraphicBuffer));
427
428 ASSERT_EQ(OK, mConsumer->releaseBuffer(newSlot, 0, Fence::NO_FENCE));
429
430 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
431 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
432 nullptr, nullptr));
433 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
434
435 uint32_t* dataOut;
436 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
437 reinterpret_cast<void**>(&dataOut)));
438 ASSERT_EQ(*dataOut, TEST_DATA);
439 ASSERT_EQ(OK, buffer->unlock());
440 }
441
TEST_F(BufferQueueTest,MoveFromConsumerToProducer)442 TEST_F(BufferQueueTest, MoveFromConsumerToProducer) {
443 createBufferQueue();
444 sp<MockConsumer> mc(new MockConsumer);
445 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
446 IGraphicBufferProducer::QueueBufferOutput output;
447 ASSERT_EQ(OK,
448 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
449
450 int slot;
451 sp<Fence> fence;
452 sp<GraphicBuffer> buffer;
453 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
454 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
455 nullptr, nullptr));
456 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
457
458 uint32_t* dataIn;
459 ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
460 reinterpret_cast<void**>(&dataIn)));
461 *dataIn = TEST_DATA;
462 ASSERT_EQ(OK, buffer->unlock());
463
464 IGraphicBufferProducer::QueueBufferInput input(0, false,
465 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
466 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
467 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
468
469 BufferItem item;
470 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
471 ASSERT_EQ(OK, mConsumer->detachBuffer(item.mSlot));
472
473 int newSlot;
474 ASSERT_EQ(OK, mProducer->attachBuffer(&newSlot, item.mGraphicBuffer));
475 ASSERT_EQ(OK, mProducer->queueBuffer(newSlot, input, &output));
476 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
477
478 uint32_t* dataOut;
479 ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
480 reinterpret_cast<void**>(&dataOut)));
481 ASSERT_EQ(*dataOut, TEST_DATA);
482 ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
483 }
484
TEST_F(BufferQueueTest,TestDisallowingAllocation)485 TEST_F(BufferQueueTest, TestDisallowingAllocation) {
486 createBufferQueue();
487 sp<MockConsumer> mc(new MockConsumer);
488 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
489 IGraphicBufferProducer::QueueBufferOutput output;
490 ASSERT_EQ(OK,
491 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
492
493 static const uint32_t WIDTH = 320;
494 static const uint32_t HEIGHT = 240;
495
496 ASSERT_EQ(OK, mConsumer->setDefaultBufferSize(WIDTH, HEIGHT));
497
498 int slot;
499 sp<Fence> fence;
500 sp<GraphicBuffer> buffer;
501 // This should return an error since it would require an allocation
502 ASSERT_EQ(OK, mProducer->allowAllocation(false));
503 ASSERT_EQ(WOULD_BLOCK,
504 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
505 nullptr, nullptr));
506
507 // This should succeed, now that we've lifted the prohibition
508 ASSERT_EQ(OK, mProducer->allowAllocation(true));
509 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
510 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
511 nullptr, nullptr));
512
513 // Release the previous buffer back to the BufferQueue
514 mProducer->cancelBuffer(slot, fence);
515
516 // This should fail since we're requesting a different size
517 ASSERT_EQ(OK, mProducer->allowAllocation(false));
518 ASSERT_EQ(WOULD_BLOCK,
519 mProducer->dequeueBuffer(&slot, &fence, WIDTH * 2, HEIGHT * 2, 0,
520 GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr, nullptr));
521 }
522
TEST_F(BufferQueueTest,TestGenerationNumbers)523 TEST_F(BufferQueueTest, TestGenerationNumbers) {
524 createBufferQueue();
525 sp<MockConsumer> mc(new MockConsumer);
526 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
527 IGraphicBufferProducer::QueueBufferOutput output;
528 ASSERT_EQ(OK,
529 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
530
531 ASSERT_EQ(OK, mProducer->setGenerationNumber(1));
532
533 // Get one buffer to play with
534 int slot;
535 sp<Fence> fence;
536 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
537 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
538 nullptr));
539
540 sp<GraphicBuffer> buffer;
541 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
542
543 // Ensure that the generation number we set propagates to allocated buffers
544 ASSERT_EQ(1U, buffer->getGenerationNumber());
545
546 ASSERT_EQ(OK, mProducer->detachBuffer(slot));
547
548 ASSERT_EQ(OK, mProducer->setGenerationNumber(2));
549
550 // These should fail, since we've changed the generation number on the queue
551 int outSlot;
552 ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(&outSlot, buffer));
553 ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(&outSlot, buffer));
554
555 buffer->setGenerationNumber(2);
556
557 // This should succeed now that we've changed the buffer's generation number
558 ASSERT_EQ(OK, mProducer->attachBuffer(&outSlot, buffer));
559
560 ASSERT_EQ(OK, mProducer->detachBuffer(outSlot));
561
562 // This should also succeed with the new generation number
563 ASSERT_EQ(OK, mConsumer->attachBuffer(&outSlot, buffer));
564 }
565
TEST_F(BufferQueueTest,TestSharedBufferModeWithoutAutoRefresh)566 TEST_F(BufferQueueTest, TestSharedBufferModeWithoutAutoRefresh) {
567 createBufferQueue();
568 sp<MockConsumer> mc(new MockConsumer);
569 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
570 IGraphicBufferProducer::QueueBufferOutput output;
571 ASSERT_EQ(OK,
572 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
573
574 ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
575
576 // Get a buffer
577 int sharedSlot;
578 sp<Fence> fence;
579 sp<GraphicBuffer> buffer;
580 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
581 mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
582 nullptr, nullptr));
583 ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
584
585 // Queue the buffer
586 IGraphicBufferProducer::QueueBufferInput input(0, false,
587 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
588 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
589 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
590
591 // Repeatedly queue and dequeue a buffer from the producer side, it should
592 // always return the same one. And we won't run out of buffers because it's
593 // always the same one and because async mode gets enabled.
594 int slot;
595 for (int i = 0; i < 5; i++) {
596 ASSERT_EQ(OK,
597 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
598 nullptr, nullptr));
599 ASSERT_EQ(sharedSlot, slot);
600 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
601 }
602
603 // acquire the buffer
604 BufferItem item;
605 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
606 ASSERT_EQ(sharedSlot, item.mSlot);
607 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, Fence::NO_FENCE));
612
613 // attempt to acquire a second time should return no buffer available
614 ASSERT_EQ(IGraphicBufferConsumer::NO_BUFFER_AVAILABLE,
615 mConsumer->acquireBuffer(&item, 0));
616 }
617
TEST_F(BufferQueueTest,TestSharedBufferModeWithAutoRefresh)618 TEST_F(BufferQueueTest, TestSharedBufferModeWithAutoRefresh) {
619 createBufferQueue();
620 sp<MockConsumer> mc(new MockConsumer);
621 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
622 IGraphicBufferProducer::QueueBufferOutput output;
623 ASSERT_EQ(OK,
624 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
625
626 ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
627 ASSERT_EQ(OK, mProducer->setAutoRefresh(true));
628
629 // Get a buffer
630 int sharedSlot;
631 sp<Fence> fence;
632 sp<GraphicBuffer> buffer;
633 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
634 mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
635 nullptr, nullptr));
636 ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
637
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);
642 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
643
644 // 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));
649 ASSERT_EQ(sharedSlot, item.mSlot);
650 testBufferItem(input, item);
651 ASSERT_EQ(i == 0, item.mQueuedBuffer);
652 ASSERT_EQ(true, item.mAutoRefresh);
653
654 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, Fence::NO_FENCE));
655 }
656
657 // Repeatedly queue and dequeue a buffer from the producer side, it should
658 // always return the same one.
659 int slot;
660 for (int i = 0; i < 5; i++) {
661 ASSERT_EQ(OK,
662 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
663 nullptr, nullptr));
664 ASSERT_EQ(sharedSlot, slot);
665 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
666 }
667
668 // Repeatedly acquire and release a buffer from the consumer side, it should
669 // always return the same one. First grabbing them from the queue and then
670 // when the queue is empty, returning the shared buffer.
671 for (int i = 0; i < 10; i++) {
672 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
673 ASSERT_EQ(sharedSlot, item.mSlot);
674 ASSERT_EQ(0, item.mTimestamp);
675 ASSERT_EQ(false, item.mIsAutoTimestamp);
676 ASSERT_EQ(HAL_DATASPACE_UNKNOWN, item.mDataSpace);
677 ASSERT_EQ(Rect(0, 0, 1, 1), item.mCrop);
678 ASSERT_EQ(NATIVE_WINDOW_SCALING_MODE_FREEZE, item.mScalingMode);
679 ASSERT_EQ(0u, item.mTransform);
680 ASSERT_EQ(Fence::NO_FENCE, item.mFence);
681 ASSERT_EQ(i == 0, item.mQueuedBuffer);
682 ASSERT_EQ(true, item.mAutoRefresh);
683
684 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, Fence::NO_FENCE));
685 }
686 }
687
TEST_F(BufferQueueTest,TestSharedBufferModeUsingAlreadyDequeuedBuffer)688 TEST_F(BufferQueueTest, TestSharedBufferModeUsingAlreadyDequeuedBuffer) {
689 createBufferQueue();
690 sp<MockConsumer> mc(new MockConsumer);
691 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
692 IGraphicBufferProducer::QueueBufferOutput output;
693 ASSERT_EQ(OK,
694 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
695
696 // Dequeue a buffer
697 int sharedSlot;
698 sp<Fence> fence;
699 sp<GraphicBuffer> buffer;
700 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
701 mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
702 nullptr, nullptr));
703 ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
704
705 // Enable shared buffer mode
706 ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
707
708 // Queue the buffer
709 IGraphicBufferProducer::QueueBufferInput input(0, false,
710 HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
711 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
712 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
713
714 // Repeatedly queue and dequeue a buffer from the producer side, it should
715 // always return the same one. And we won't run out of buffers because it's
716 // always the same one and because async mode gets enabled.
717 int slot;
718 for (int i = 0; i < 5; i++) {
719 ASSERT_EQ(OK,
720 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
721 nullptr, nullptr));
722 ASSERT_EQ(sharedSlot, slot);
723 ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
724 }
725
726 // acquire the buffer
727 BufferItem item;
728 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
729 ASSERT_EQ(sharedSlot, item.mSlot);
730 testBufferItem(input, item);
731 ASSERT_EQ(true, item.mQueuedBuffer);
732 ASSERT_EQ(false, item.mAutoRefresh);
733
734 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, Fence::NO_FENCE));
735
736 // attempt to acquire a second time should return no buffer available
737 ASSERT_EQ(IGraphicBufferConsumer::NO_BUFFER_AVAILABLE,
738 mConsumer->acquireBuffer(&item, 0));
739 }
740
TEST_F(BufferQueueTest,TestTimeouts)741 TEST_F(BufferQueueTest, TestTimeouts) {
742 createBufferQueue();
743 sp<MockConsumer> mc(new MockConsumer);
744 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
745 IGraphicBufferProducer::QueueBufferOutput output;
746 ASSERT_EQ(OK,
747 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
748
749 // Fill up the queue. Since the controlledByApp flags are set to true, this
750 // queue should be in non-blocking mode, and we should be recycling the same
751 // two buffers
752 for (int i = 0; i < 5; ++i) {
753 int slot = BufferQueue::INVALID_BUFFER_SLOT;
754 sp<Fence> fence = Fence::NO_FENCE;
755 auto result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
756 nullptr, nullptr);
757 if (i < 2) {
758 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
759 result);
760 } else {
761 ASSERT_EQ(OK, result);
762 }
763 sp<GraphicBuffer> buffer;
764 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
765 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
766 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
767 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
768 IGraphicBufferProducer::QueueBufferOutput output{};
769 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
770 }
771
772 const auto TIMEOUT = ms2ns(250);
773 mProducer->setDequeueTimeout(TIMEOUT);
774
775 // Setting a timeout will change the BufferQueue into blocking mode (with
776 // one droppable buffer in the queue and one free from the previous
777 // dequeue/queues), so dequeue and queue two more buffers: one to replace
778 // the current droppable buffer, and a second to max out the buffer count
779 sp<GraphicBuffer> buffer; // Save a buffer to attach later
780 for (int i = 0; i < 2; ++i) {
781 int slot = BufferQueue::INVALID_BUFFER_SLOT;
782 sp<Fence> fence = Fence::NO_FENCE;
783 ASSERT_EQ(OK,
784 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
785 nullptr, nullptr));
786 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
787 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
788 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
789 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
790 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
791 }
792
793 int slot = BufferQueue::INVALID_BUFFER_SLOT;
794 sp<Fence> fence = Fence::NO_FENCE;
795 auto startTime = systemTime();
796 ASSERT_EQ(TIMED_OUT,
797 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
798 nullptr));
799 ASSERT_GE(systemTime() - startTime, TIMEOUT);
800
801 // We're technically attaching the same buffer multiple times (since we
802 // queued it previously), but that doesn't matter for this test
803 startTime = systemTime();
804 ASSERT_EQ(TIMED_OUT, mProducer->attachBuffer(&slot, buffer));
805 ASSERT_GE(systemTime() - startTime, TIMEOUT);
806 }
807
TEST_F(BufferQueueTest,CanAttachWhileDisallowingAllocation)808 TEST_F(BufferQueueTest, CanAttachWhileDisallowingAllocation) {
809 createBufferQueue();
810 sp<MockConsumer> mc(new MockConsumer);
811 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
812 IGraphicBufferProducer::QueueBufferOutput output;
813 ASSERT_EQ(OK,
814 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
815
816 int slot = BufferQueue::INVALID_BUFFER_SLOT;
817 sp<Fence> sourceFence;
818 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
819 mProducer->dequeueBuffer(&slot, &sourceFence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
820 nullptr, nullptr));
821 sp<GraphicBuffer> buffer;
822 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
823 ASSERT_EQ(OK, mProducer->detachBuffer(slot));
824
825 ASSERT_EQ(OK, mProducer->allowAllocation(false));
826
827 slot = BufferQueue::INVALID_BUFFER_SLOT;
828 ASSERT_EQ(OK, mProducer->attachBuffer(&slot, buffer));
829 }
830
TEST_F(BufferQueueTest,CanRetrieveLastQueuedBuffer)831 TEST_F(BufferQueueTest, CanRetrieveLastQueuedBuffer) {
832 createBufferQueue();
833 sp<MockConsumer> mc(new MockConsumer);
834 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
835 IGraphicBufferProducer::QueueBufferOutput output;
836 ASSERT_EQ(OK,
837 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
838
839 // Dequeue and queue the first buffer, storing the handle
840 int slot = BufferQueue::INVALID_BUFFER_SLOT;
841 sp<Fence> fence;
842 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
843 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
844 nullptr));
845 sp<GraphicBuffer> firstBuffer;
846 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &firstBuffer));
847
848 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
849 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
850 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
851 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
852
853 // Dequeue a second buffer
854 slot = BufferQueue::INVALID_BUFFER_SLOT;
855 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
856 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
857 nullptr));
858 sp<GraphicBuffer> secondBuffer;
859 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &secondBuffer));
860
861 // Ensure it's a new buffer
862 ASSERT_NE(firstBuffer->getNativeBuffer()->handle,
863 secondBuffer->getNativeBuffer()->handle);
864
865 // Queue the second buffer
866 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
867
868 // Acquire and release both buffers
869 for (size_t i = 0; i < 2; ++i) {
870 BufferItem item;
871 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
872 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, Fence::NO_FENCE));
873 }
874
875 // Make sure we got the second buffer back
876 sp<GraphicBuffer> returnedBuffer;
877 sp<Fence> returnedFence;
878 float transform[16];
879 ASSERT_EQ(OK,
880 mProducer->getLastQueuedBuffer(&returnedBuffer, &returnedFence,
881 transform));
882 ASSERT_EQ(secondBuffer->getNativeBuffer()->handle,
883 returnedBuffer->getNativeBuffer()->handle);
884 }
885
TEST_F(BufferQueueTest,TestOccupancyHistory)886 TEST_F(BufferQueueTest, TestOccupancyHistory) {
887 createBufferQueue();
888 sp<MockConsumer> mc(new MockConsumer);
889 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
890 IGraphicBufferProducer::QueueBufferOutput output;
891 ASSERT_EQ(OK,
892 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
893
894 int slot = BufferQueue::INVALID_BUFFER_SLOT;
895 sp<Fence> fence = Fence::NO_FENCE;
896 sp<GraphicBuffer> buffer = nullptr;
897 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
898 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
899 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
900 BufferItem item{};
901
902 // Preallocate, dequeue, request, and cancel 3 buffers so we don't get
903 // BUFFER_NEEDS_REALLOCATION below
904 int slots[3] = {};
905 mProducer->setMaxDequeuedBufferCount(3);
906 for (size_t i = 0; i < 3; ++i) {
907 status_t result = mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0,
908 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr);
909 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
910 ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
911 }
912 for (size_t i = 0; i < 3; ++i) {
913 ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE));
914 }
915
916 // Create 3 segments
917
918 // The first segment is a two-buffer segment, so we only put one buffer into
919 // the queue at a time
920 for (size_t i = 0; i < 5; ++i) {
921 ASSERT_EQ(OK,
922 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
923 nullptr, nullptr));
924 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
925 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
926 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, Fence::NO_FENCE));
927 std::this_thread::sleep_for(16ms);
928 }
929
930 // Sleep between segments
931 std::this_thread::sleep_for(500ms);
932
933 // The second segment is a double-buffer segment. It starts the same as the
934 // two-buffer segment, but then at the end, we put two buffers in the queue
935 // at the same time before draining it.
936 for (size_t i = 0; i < 5; ++i) {
937 ASSERT_EQ(OK,
938 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
939 nullptr, nullptr));
940 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
941 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
942 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, Fence::NO_FENCE));
943 std::this_thread::sleep_for(16ms);
944 }
945 ASSERT_EQ(OK,
946 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
947 nullptr));
948 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
949 ASSERT_EQ(OK,
950 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
951 nullptr));
952 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
953 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
954 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, Fence::NO_FENCE));
955 std::this_thread::sleep_for(16ms);
956 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
957 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, Fence::NO_FENCE));
958
959 // Sleep between segments
960 std::this_thread::sleep_for(500ms);
961
962 // The third segment is a triple-buffer segment, so the queue is switching
963 // between one buffer and two buffers deep.
964 ASSERT_EQ(OK,
965 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
966 nullptr));
967 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
968 for (size_t i = 0; i < 5; ++i) {
969 ASSERT_EQ(OK,
970 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
971 nullptr, nullptr));
972 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
973 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
974 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, Fence::NO_FENCE));
975 std::this_thread::sleep_for(16ms);
976 }
977 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
978 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, Fence::NO_FENCE));
979
980 // Now we read the segments
981 std::vector<OccupancyTracker::Segment> history;
982 ASSERT_EQ(OK, mConsumer->getOccupancyHistory(false, &history));
983
984 // Since we didn't force a flush, we should only get the first two segments
985 // (since the third segment hasn't been closed out by the appearance of a
986 // new segment yet)
987 ASSERT_EQ(2u, history.size());
988
989 // The first segment (which will be history[1], since the newest segment
990 // should be at the front of the vector) should be a two-buffer segment,
991 // which implies that the occupancy average should be between 0 and 1, and
992 // usedThirdBuffer should be false
993 const auto& firstSegment = history[1];
994 ASSERT_EQ(5u, firstSegment.numFrames);
995 ASSERT_LT(0, firstSegment.occupancyAverage);
996 ASSERT_GT(1, firstSegment.occupancyAverage);
997 ASSERT_EQ(false, firstSegment.usedThirdBuffer);
998
999 // The second segment should be a double-buffered segment, which implies that
1000 // the occupancy average should be between 0 and 1, but usedThirdBuffer
1001 // should be true
1002 const auto& secondSegment = history[0];
1003 ASSERT_EQ(7u, secondSegment.numFrames);
1004 ASSERT_LT(0, secondSegment.occupancyAverage);
1005 ASSERT_GT(1, secondSegment.occupancyAverage);
1006 ASSERT_EQ(true, secondSegment.usedThirdBuffer);
1007
1008 // If we read the segments again without flushing, we shouldn't get any new
1009 // segments
1010 ASSERT_EQ(OK, mConsumer->getOccupancyHistory(false, &history));
1011 ASSERT_EQ(0u, history.size());
1012
1013 // Read the segments again, this time forcing a flush so we get the third
1014 // segment
1015 ASSERT_EQ(OK, mConsumer->getOccupancyHistory(true, &history));
1016 ASSERT_EQ(1u, history.size());
1017
1018 // This segment should be a triple-buffered segment, which implies that the
1019 // occupancy average should be between 1 and 2, and usedThirdBuffer should
1020 // be true
1021 const auto& thirdSegment = history[0];
1022 ASSERT_EQ(6u, thirdSegment.numFrames);
1023 ASSERT_LT(1, thirdSegment.occupancyAverage);
1024 ASSERT_GT(2, thirdSegment.occupancyAverage);
1025 ASSERT_EQ(true, thirdSegment.usedThirdBuffer);
1026 }
1027
1028 struct BufferDiscardedListener : public BnProducerListener {
1029 public:
1030 BufferDiscardedListener() = default;
1031 virtual ~BufferDiscardedListener() = default;
1032
onBufferReleasedandroid::BufferDiscardedListener1033 virtual void onBufferReleased() {}
needsReleaseNotifyandroid::BufferDiscardedListener1034 virtual bool needsReleaseNotify() { return false; }
onBuffersDiscardedandroid::BufferDiscardedListener1035 virtual void onBuffersDiscarded(const std::vector<int32_t>& slots) {
1036 mDiscardedSlots.insert(mDiscardedSlots.end(), slots.begin(), slots.end());
1037 }
1038
getDiscardedSlotsandroid::BufferDiscardedListener1039 const std::vector<int32_t>& getDiscardedSlots() const { return mDiscardedSlots; }
1040 private:
1041 // No need to use lock given the test triggers the listener in the same
1042 // thread context.
1043 std::vector<int32_t> mDiscardedSlots;
1044 };
1045
TEST_F(BufferQueueTest,TestDiscardFreeBuffers)1046 TEST_F(BufferQueueTest, TestDiscardFreeBuffers) {
1047 createBufferQueue();
1048 sp<MockConsumer> mc(new MockConsumer);
1049 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
1050 IGraphicBufferProducer::QueueBufferOutput output;
1051 sp<BufferDiscardedListener> pl(new BufferDiscardedListener);
1052 ASSERT_EQ(OK, mProducer->connect(pl,
1053 NATIVE_WINDOW_API_CPU, false, &output));
1054
1055 int slot = BufferQueue::INVALID_BUFFER_SLOT;
1056 sp<Fence> fence = Fence::NO_FENCE;
1057 sp<GraphicBuffer> buffer = nullptr;
1058 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1059 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1060 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1061 BufferItem item{};
1062
1063 // Preallocate, dequeue, request, and cancel 4 buffers so we don't get
1064 // BUFFER_NEEDS_REALLOCATION below
1065 int slots[4] = {};
1066 mProducer->setMaxDequeuedBufferCount(4);
1067 for (size_t i = 0; i < 4; ++i) {
1068 status_t result = mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0,
1069 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr);
1070 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1071 ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
1072 }
1073 for (size_t i = 0; i < 4; ++i) {
1074 ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE));
1075 }
1076
1077 // Get buffers in all states: dequeued, filled, acquired, free
1078
1079 // Fill 3 buffers
1080 ASSERT_EQ(OK,
1081 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1082 nullptr));
1083 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1084 ASSERT_EQ(OK,
1085 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1086 nullptr));
1087 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1088 ASSERT_EQ(OK,
1089 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1090 nullptr));
1091 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1092 // Dequeue 1 buffer
1093 ASSERT_EQ(OK,
1094 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1095 nullptr));
1096
1097 // Acquire and free 1 buffer
1098 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1099 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, Fence::NO_FENCE));
1100 int releasedSlot = item.mSlot;
1101
1102 // Acquire 1 buffer, leaving 1 filled buffer in queue
1103 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1104
1105 // Now discard the free buffers
1106 ASSERT_EQ(OK, mConsumer->discardFreeBuffers());
1107
1108 // Check onBuffersDiscarded is called with correct slots
1109 auto buffersDiscarded = pl->getDiscardedSlots();
1110 ASSERT_EQ(buffersDiscarded.size(), 1u);
1111 ASSERT_EQ(buffersDiscarded[0], releasedSlot);
1112
1113 // Check no free buffers in dump
1114 String8 dumpString;
1115 mConsumer->dumpState(String8{}, &dumpString);
1116
1117 // Parse the dump to ensure that all buffer slots that are FREE also
1118 // have a null GraphicBuffer
1119 // Fragile - assumes the following format for the dump for a buffer entry:
1120 // ":%p\][^:]*state=FREE" where %p is the buffer pointer in hex.
1121 ssize_t idx = dumpString.find("state=FREE");
1122 while (idx != -1) {
1123 ssize_t bufferPtrIdx = idx - 1;
1124 while (bufferPtrIdx > 0) {
1125 if (dumpString[bufferPtrIdx] == ':') {
1126 bufferPtrIdx++;
1127 break;
1128 }
1129 bufferPtrIdx--;
1130 }
1131 ASSERT_GT(bufferPtrIdx, 0) << "Can't parse queue dump to validate";
1132 ssize_t nullPtrIdx = dumpString.find("0x0]", bufferPtrIdx);
1133 ASSERT_EQ(bufferPtrIdx, nullPtrIdx) << "Free buffer not discarded";
1134 idx = dumpString.find("FREE", idx + 1);
1135 }
1136 }
1137
TEST_F(BufferQueueTest,TestBufferReplacedInQueueBuffer)1138 TEST_F(BufferQueueTest, TestBufferReplacedInQueueBuffer) {
1139 createBufferQueue();
1140 sp<MockConsumer> mc(new MockConsumer);
1141 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
1142 IGraphicBufferProducer::QueueBufferOutput output;
1143 ASSERT_EQ(OK,
1144 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
1145 ASSERT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
1146
1147 int slot = BufferQueue::INVALID_BUFFER_SLOT;
1148 sp<Fence> fence = Fence::NO_FENCE;
1149 sp<GraphicBuffer> buffer = nullptr;
1150 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1151 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1152 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1153 BufferItem item{};
1154
1155 // Preallocate, dequeue, request, and cancel 2 buffers so we don't get
1156 // BUFFER_NEEDS_REALLOCATION below
1157 int slots[2] = {};
1158 ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(2));
1159 for (size_t i = 0; i < 2; ++i) {
1160 status_t result = mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0,
1161 TEST_PRODUCER_USAGE_BITS, nullptr, nullptr);
1162 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1163 ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
1164 }
1165 for (size_t i = 0; i < 2; ++i) {
1166 ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE));
1167 }
1168
1169 // Fill 2 buffers without consumer consuming them. Verify that all
1170 // queued buffer returns proper bufferReplaced flag
1171 ASSERT_EQ(OK,
1172 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1173 nullptr));
1174 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1175 ASSERT_EQ(false, output.bufferReplaced);
1176 ASSERT_EQ(OK,
1177 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1178 nullptr));
1179 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1180 ASSERT_EQ(true, output.bufferReplaced);
1181 }
1182
1183 struct BufferDetachedListener : public BnProducerListener {
1184 public:
1185 BufferDetachedListener() = default;
1186 virtual ~BufferDetachedListener() = default;
1187
onBufferReleasedandroid::BufferDetachedListener1188 virtual void onBufferReleased() {}
needsReleaseNotifyandroid::BufferDetachedListener1189 virtual bool needsReleaseNotify() { return true; }
onBufferDetachedandroid::BufferDetachedListener1190 virtual void onBufferDetached(int slot) {
1191 mDetachedSlots.push_back(slot);
1192 }
getDetachedSlotsandroid::BufferDetachedListener1193 const std::vector<int>& getDetachedSlots() const { return mDetachedSlots; }
1194 private:
1195 std::vector<int> mDetachedSlots;
1196 };
1197
TEST_F(BufferQueueTest,TestConsumerDetachProducerListener)1198 TEST_F(BufferQueueTest, TestConsumerDetachProducerListener) {
1199 createBufferQueue();
1200 sp<MockConsumer> mc(new MockConsumer);
1201 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
1202 IGraphicBufferProducer::QueueBufferOutput output;
1203 sp<BufferDetachedListener> pl(new BufferDetachedListener);
1204 ASSERT_EQ(OK, mProducer->connect(pl, NATIVE_WINDOW_API_CPU, true, &output));
1205 ASSERT_EQ(OK, mProducer->setDequeueTimeout(0));
1206 ASSERT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
1207
1208 sp<Fence> fence = Fence::NO_FENCE;
1209 sp<GraphicBuffer> buffer = nullptr;
1210 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1211 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1212 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1213
1214 int slots[2] = {};
1215 status_t result = OK;
1216 ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(2));
1217
1218 result = mProducer->dequeueBuffer(&slots[0], &fence, 0, 0, 0,
1219 GRALLOC_USAGE_SW_READ_RARELY, nullptr, nullptr);
1220 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1221 ASSERT_EQ(OK, mProducer->requestBuffer(slots[0], &buffer));
1222
1223 result = mProducer->dequeueBuffer(&slots[1], &fence, 0, 0, 0,
1224 GRALLOC_USAGE_SW_READ_RARELY, nullptr, nullptr);
1225 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1226 ASSERT_EQ(OK, mProducer->requestBuffer(slots[1], &buffer));
1227
1228 // Queue & detach one from two dequeued buffes.
1229 ASSERT_EQ(OK, mProducer->queueBuffer(slots[1], input, &output));
1230 BufferItem item{};
1231 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1232 ASSERT_EQ(OK, mConsumer->detachBuffer(item.mSlot));
1233
1234 // Check whether the slot from IProducerListener is same to the detached slot.
1235 ASSERT_EQ(pl->getDetachedSlots().size(), 1u);
1236 ASSERT_EQ(pl->getDetachedSlots()[0], slots[1]);
1237
1238 // Dequeue another buffer.
1239 int slot;
1240 result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
1241 GRALLOC_USAGE_SW_READ_RARELY, nullptr, nullptr);
1242 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1243 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
1244
1245 // Dequeue should fail here, since we dequeued 3 buffers and one buffer was
1246 // detached from consumer(Two buffers are dequeued, and the current max
1247 // dequeued buffer count is two).
1248 result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
1249 GRALLOC_USAGE_SW_READ_RARELY, nullptr, nullptr);
1250 ASSERT_TRUE(result == WOULD_BLOCK || result == TIMED_OUT || result == INVALID_OPERATION);
1251 }
1252
1253 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_CONSUMER_ATTACH_CALLBACK)
1254 struct BufferAttachedListener : public BnProducerListener {
1255 public:
BufferAttachedListenerandroid::BufferAttachedListener1256 BufferAttachedListener(bool enable) : mEnabled(enable), mAttached(0) {}
1257 virtual ~BufferAttachedListener() = default;
1258
onBufferReleasedandroid::BufferAttachedListener1259 virtual void onBufferReleased() {}
needsReleaseNotifyandroid::BufferAttachedListener1260 virtual bool needsReleaseNotify() { return true; }
onBufferAttachedandroid::BufferAttachedListener1261 virtual void onBufferAttached() {
1262 ++mAttached;
1263 }
needsAttachNotifyandroid::BufferAttachedListener1264 virtual bool needsAttachNotify() { return mEnabled; }
1265
getNumAttachedandroid::BufferAttachedListener1266 int getNumAttached() const { return mAttached; }
1267 private:
1268 const bool mEnabled;
1269 int mAttached;
1270 };
1271
TEST_F(BufferQueueTest,TestConsumerAttachProducerListener)1272 TEST_F(BufferQueueTest, TestConsumerAttachProducerListener) {
1273 createBufferQueue();
1274 sp<MockConsumer> mc1(new MockConsumer);
1275 ASSERT_EQ(OK, mConsumer->consumerConnect(mc1, true));
1276 IGraphicBufferProducer::QueueBufferOutput output;
1277 // Do not enable attach callback.
1278 sp<BufferAttachedListener> pl1(new BufferAttachedListener(false));
1279 ASSERT_EQ(OK, mProducer->connect(pl1, NATIVE_WINDOW_API_CPU, true, &output));
1280 ASSERT_EQ(OK, mProducer->setDequeueTimeout(0));
1281 ASSERT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
1282
1283 sp<Fence> fence = Fence::NO_FENCE;
1284 sp<GraphicBuffer> buffer = nullptr;
1285
1286 int slot;
1287 status_t result = OK;
1288
1289 ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(1));
1290
1291 result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
1292 GRALLOC_USAGE_SW_READ_RARELY, nullptr, nullptr);
1293 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1294 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
1295 ASSERT_EQ(OK, mProducer->detachBuffer(slot));
1296
1297 // Check # of attach is zero.
1298 ASSERT_EQ(0, pl1->getNumAttached());
1299
1300 // Attach a buffer and check the callback was not called.
1301 ASSERT_EQ(OK, mConsumer->attachBuffer(&slot, buffer));
1302 ASSERT_EQ(0, pl1->getNumAttached());
1303
1304 mProducer = nullptr;
1305 mConsumer = nullptr;
1306 createBufferQueue();
1307
1308 sp<MockConsumer> mc2(new MockConsumer);
1309 ASSERT_EQ(OK, mConsumer->consumerConnect(mc2, true));
1310 // Enable attach callback.
1311 sp<BufferAttachedListener> pl2(new BufferAttachedListener(true));
1312 ASSERT_EQ(OK, mProducer->connect(pl2, NATIVE_WINDOW_API_CPU, true, &output));
1313 ASSERT_EQ(OK, mProducer->setDequeueTimeout(0));
1314 ASSERT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
1315
1316 fence = Fence::NO_FENCE;
1317 buffer = nullptr;
1318
1319 result = OK;
1320
1321 ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(1));
1322
1323 result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
1324 GRALLOC_USAGE_SW_READ_RARELY, nullptr, nullptr);
1325 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1326 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
1327 ASSERT_EQ(OK, mProducer->detachBuffer(slot));
1328
1329 // Check # of attach is zero.
1330 ASSERT_EQ(0, pl2->getNumAttached());
1331
1332 // Attach a buffer and check the callback was called.
1333 ASSERT_EQ(OK, mConsumer->attachBuffer(&slot, buffer));
1334 ASSERT_EQ(1, pl2->getNumAttached());
1335 }
1336 #endif
1337
TEST_F(BufferQueueTest,TestStaleBufferHandleSentAfterDisconnect)1338 TEST_F(BufferQueueTest, TestStaleBufferHandleSentAfterDisconnect) {
1339 createBufferQueue();
1340 sp<MockConsumer> mc(new MockConsumer);
1341 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
1342 IGraphicBufferProducer::QueueBufferOutput output;
1343 sp<IProducerListener> fakeListener(new StubProducerListener);
1344 ASSERT_EQ(OK, mProducer->connect(fakeListener, NATIVE_WINDOW_API_CPU, true, &output));
1345
1346 int slot = BufferQueue::INVALID_BUFFER_SLOT;
1347 sp<Fence> fence = Fence::NO_FENCE;
1348 sp<GraphicBuffer> buffer = nullptr;
1349 IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1350 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1351 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1352
1353 // Dequeue, request, and queue one buffer
1354 status_t result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS,
1355 nullptr, nullptr);
1356 ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1357 ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
1358 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1359
1360 // Acquire and release the buffer. Upon acquiring, the buffer handle should
1361 // be non-null since this is the first time we've acquired this slot.
1362 BufferItem item;
1363 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1364 ASSERT_EQ(slot, item.mSlot);
1365 ASSERT_NE(nullptr, item.mGraphicBuffer.get());
1366 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, Fence::NO_FENCE));
1367
1368 // Dequeue and queue the buffer again
1369 ASSERT_EQ(OK,
1370 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1371 nullptr));
1372 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1373
1374 // Acquire and release the buffer again. Upon acquiring, the buffer handle
1375 // should be null since this is not the first time we've acquired this slot.
1376 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1377 ASSERT_EQ(slot, item.mSlot);
1378 ASSERT_EQ(nullptr, item.mGraphicBuffer.get());
1379 ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, Fence::NO_FENCE));
1380
1381 // Dequeue and queue the buffer again
1382 ASSERT_EQ(OK,
1383 mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, TEST_PRODUCER_USAGE_BITS, nullptr,
1384 nullptr));
1385 ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1386
1387 // Disconnect the producer end. This should clear all of the slots and mark
1388 // the buffer in the queue as stale.
1389 ASSERT_EQ(OK, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
1390
1391 // Acquire the buffer again. Upon acquiring, the buffer handle should not be
1392 // null since the queued buffer should have been marked as stale, which
1393 // should trigger the BufferQueue to resend the buffer handle.
1394 ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1395 ASSERT_EQ(slot, item.mSlot);
1396 ASSERT_NE(nullptr, item.mGraphicBuffer.get());
1397 }
1398
TEST_F(BufferQueueTest,TestProducerConnectDisconnect)1399 TEST_F(BufferQueueTest, TestProducerConnectDisconnect) {
1400 createBufferQueue();
1401 sp<MockConsumer> mc(new MockConsumer);
1402 ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
1403 IGraphicBufferProducer::QueueBufferOutput output;
1404 sp<IProducerListener> fakeListener(new StubProducerListener);
1405 ASSERT_EQ(NO_INIT, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
1406 ASSERT_EQ(OK, mProducer->connect(fakeListener, NATIVE_WINDOW_API_CPU, true, &output));
1407 ASSERT_EQ(BAD_VALUE, mProducer->connect(fakeListener, NATIVE_WINDOW_API_MEDIA, true, &output));
1408
1409 ASSERT_EQ(BAD_VALUE, mProducer->disconnect(NATIVE_WINDOW_API_MEDIA));
1410 ASSERT_EQ(OK, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
1411 ASSERT_EQ(NO_INIT, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
1412 }
1413
TEST_F(BufferQueueTest,TestBqSetFrameRateFlagBuildTimeIsSet)1414 TEST_F(BufferQueueTest, TestBqSetFrameRateFlagBuildTimeIsSet) {
1415 ASSERT_EQ(flags::bq_setframerate(), COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_SETFRAMERATE));
1416 }
1417
1418 struct BufferItemConsumerSetFrameRateListener : public BufferItemConsumer {
BufferItemConsumerSetFrameRateListenerandroid::BufferItemConsumerSetFrameRateListener1419 BufferItemConsumerSetFrameRateListener() : BufferItemConsumer(GRALLOC_USAGE_SW_READ_OFTEN, 1) {}
1420
1421 MOCK_METHOD(void, onSetFrameRate, (float, int8_t, int8_t), (override));
1422 };
1423
TEST_F(BufferQueueTest,TestSetFrameRate)1424 TEST_F(BufferQueueTest, TestSetFrameRate) {
1425 sp<BufferItemConsumerSetFrameRateListener> bufferConsumer =
1426 sp<BufferItemConsumerSetFrameRateListener>::make();
1427 sp<IGraphicBufferProducer> producer = bufferConsumer->getSurface()->getIGraphicBufferProducer();
1428
1429 EXPECT_CALL(*bufferConsumer, onSetFrameRate(12.34f, 1, 0)).Times(1);
1430 producer->setFrameRate(12.34f, 1, 0);
1431 }
1432
1433 class Latch {
1434 public:
Latch(int expected)1435 explicit Latch(int expected) : mExpected(expected) {}
1436 Latch(const Latch&) = delete;
1437 Latch& operator=(const Latch&) = delete;
1438
CountDown()1439 void CountDown() {
1440 std::unique_lock<std::mutex> lock(mLock);
1441 mExpected--;
1442 if (mExpected <= 0) {
1443 mCV.notify_all();
1444 }
1445 }
1446
Wait()1447 void Wait() {
1448 std::unique_lock<std::mutex> lock(mLock);
1449 mCV.wait(lock, [&] { return mExpected == 0; });
1450 }
1451
1452 private:
1453 int mExpected;
1454 std::mutex mLock;
1455 std::condition_variable mCV;
1456 };
1457
1458 struct OneshotOnDequeuedListener final : public BufferItemConsumer::FrameAvailableListener {
OneshotOnDequeuedListenerandroid::OneshotOnDequeuedListener1459 OneshotOnDequeuedListener(std::function<void()>&& oneshot)
1460 : mOneshotRunnable(std::move(oneshot)) {}
1461
1462 std::function<void()> mOneshotRunnable;
1463
runandroid::OneshotOnDequeuedListener1464 void run() {
1465 if (mOneshotRunnable) {
1466 mOneshotRunnable();
1467 mOneshotRunnable = nullptr;
1468 }
1469 }
1470
onFrameDequeuedandroid::OneshotOnDequeuedListener1471 void onFrameDequeued(const uint64_t) override { run(); }
1472
onFrameAvailableandroid::OneshotOnDequeuedListener1473 void onFrameAvailable(const BufferItem&) override {}
1474 };
1475
1476 // See b/270004534
TEST(BufferQueueThreading,TestProducerDequeueConsumerDestroy)1477 TEST(BufferQueueThreading, TestProducerDequeueConsumerDestroy) {
1478 sp<BufferItemConsumer> bufferConsumer =
1479 sp<BufferItemConsumer>::make(GRALLOC_USAGE_SW_READ_OFTEN, 2);
1480 ASSERT_NE(nullptr, bufferConsumer.get());
1481 sp<Surface> surface = bufferConsumer->getSurface();
1482 native_window_set_buffers_format(surface.get(), PIXEL_FORMAT_RGBA_8888);
1483 native_window_set_buffers_dimensions(surface.get(), 100, 100);
1484
1485 Latch triggerDisconnect(1);
1486 Latch resumeCallback(1);
1487 auto luckyListener = sp<OneshotOnDequeuedListener>::make([&]() {
1488 triggerDisconnect.CountDown();
1489 resumeCallback.Wait();
1490 });
1491 bufferConsumer->setFrameAvailableListener(luckyListener);
1492
1493 std::future<void> disconnecter = std::async(std::launch::async, [&]() {
1494 triggerDisconnect.Wait();
1495 luckyListener = nullptr;
1496 bufferConsumer = nullptr;
1497 resumeCallback.CountDown();
1498 });
1499
1500 std::future<void> render = std::async(std::launch::async, [=]() {
1501 ANativeWindow_Buffer buffer;
1502 surface->lock(&buffer, nullptr);
1503 surface->unlockAndPost();
1504 });
1505
1506 ASSERT_EQ(std::future_status::ready, render.wait_for(1s));
1507 EXPECT_EQ(nullptr, luckyListener.get());
1508 EXPECT_EQ(nullptr, bufferConsumer.get());
1509 }
1510
TEST_F(BufferQueueTest,TestAdditionalOptions)1511 TEST_F(BufferQueueTest, TestAdditionalOptions) {
1512 sp<BufferItemConsumer> bufferConsumer =
1513 sp<BufferItemConsumer>::make(GRALLOC_USAGE_SW_READ_OFTEN, 2);
1514 ASSERT_NE(nullptr, bufferConsumer.get());
1515 sp<Surface> surface = bufferConsumer->getSurface();
1516 native_window_set_buffers_format(surface.get(), PIXEL_FORMAT_RGBA_8888);
1517 native_window_set_buffers_dimensions(surface.get(), 100, 100);
1518
1519 std::array<AHardwareBufferLongOptions, 1> extras = {{
1520 {.name = "android.hardware.graphics.common.Dataspace", ADATASPACE_DISPLAY_P3},
1521 }};
1522
1523 ASSERT_EQ(NO_INIT,
1524 native_window_set_buffers_additional_options(surface.get(), extras.data(),
1525 extras.size()));
1526
1527 if (!IsCuttlefish()) {
1528 GTEST_SKIP() << "Not cuttlefish";
1529 }
1530
1531 ASSERT_EQ(OK, native_window_api_connect(surface.get(), NATIVE_WINDOW_API_CPU));
1532 ASSERT_EQ(OK,
1533 native_window_set_buffers_additional_options(surface.get(), extras.data(),
1534 extras.size()));
1535
1536 ANativeWindowBuffer* windowBuffer = nullptr;
1537 int fence = -1;
1538 ASSERT_EQ(OK, ANativeWindow_dequeueBuffer(surface.get(), &windowBuffer, &fence));
1539
1540 AHardwareBuffer* buffer = ANativeWindowBuffer_getHardwareBuffer(windowBuffer);
1541 ASSERT_TRUE(buffer);
1542 ADataSpace dataSpace = AHardwareBuffer_getDataSpace(buffer);
1543 EXPECT_EQ(ADATASPACE_DISPLAY_P3, dataSpace);
1544
1545 ANativeWindow_cancelBuffer(surface.get(), windowBuffer, -1);
1546
1547 // Check that reconnecting properly clears the options
1548 ASSERT_EQ(OK, native_window_api_disconnect(surface.get(), NATIVE_WINDOW_API_CPU));
1549 ASSERT_EQ(OK, native_window_api_connect(surface.get(), NATIVE_WINDOW_API_CPU));
1550
1551 ASSERT_EQ(OK, ANativeWindow_dequeueBuffer(surface.get(), &windowBuffer, &fence));
1552 buffer = ANativeWindowBuffer_getHardwareBuffer(windowBuffer);
1553 ASSERT_TRUE(buffer);
1554 dataSpace = AHardwareBuffer_getDataSpace(buffer);
1555 EXPECT_EQ(ADATASPACE_UNKNOWN, dataSpace);
1556 }
1557
TEST_F(BufferQueueTest,PassesThroughPictureProfileHandle)1558 TEST_F(BufferQueueTest, PassesThroughPictureProfileHandle) {
1559 createBufferQueue();
1560 sp<MockConsumer> mc(new MockConsumer);
1561 mConsumer->consumerConnect(mc, false);
1562
1563 IGraphicBufferProducer::QueueBufferOutput qbo;
1564 mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &qbo);
1565 mProducer->setMaxDequeuedBufferCount(2);
1566 mConsumer->setMaxAcquiredBufferCount(2);
1567
1568 // First try to pass a valid picture profile handle
1569 {
1570 int slot;
1571 sp<Fence> fence;
1572 sp<GraphicBuffer> buf;
1573 IGraphicBufferProducer::QueueBufferInput qbi(0, false, HAL_DATASPACE_UNKNOWN,
1574 Rect(0, 0, 1, 1),
1575 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0,
1576 Fence::NO_FENCE);
1577 qbi.setPictureProfileHandle(PictureProfileHandle(1));
1578
1579 EXPECT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
1580 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
1581 nullptr, nullptr));
1582 EXPECT_EQ(OK, mProducer->requestBuffer(slot, &buf));
1583 EXPECT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
1584
1585 BufferItem item;
1586 EXPECT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1587
1588 ASSERT_TRUE(item.mPictureProfileHandle.has_value());
1589 ASSERT_EQ(item.mPictureProfileHandle, PictureProfileHandle(1));
1590 }
1591
1592 // Then validate that the picture profile handle isn't sticky and is reset for the next buffer
1593 {
1594 int slot;
1595 sp<Fence> fence;
1596 sp<GraphicBuffer> buf;
1597 IGraphicBufferProducer::QueueBufferInput qbi(0, false, HAL_DATASPACE_UNKNOWN,
1598 Rect(0, 0, 1, 1),
1599 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0,
1600 Fence::NO_FENCE);
1601
1602 EXPECT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
1603 mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
1604 nullptr, nullptr));
1605 EXPECT_EQ(OK, mProducer->requestBuffer(slot, &buf));
1606 EXPECT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
1607
1608 BufferItem item;
1609 EXPECT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1610
1611 ASSERT_FALSE(item.mPictureProfileHandle.has_value());
1612 }
1613 }
1614
1615 } // namespace android
1616