• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "MockConsumer.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 <system/window.h>
36 
37 #include <gtest/gtest.h>
38 
39 #include <thread>
40 
41 using namespace std::chrono_literals;
42 
43 namespace android {
44 
45 class BufferQueueTest : public ::testing::Test {
46 
47 public:
48 protected:
BufferQueueTest()49     BufferQueueTest() {
50         const ::testing::TestInfo* const testInfo =
51             ::testing::UnitTest::GetInstance()->current_test_info();
52         ALOGV("Begin test: %s.%s", testInfo->test_case_name(),
53                 testInfo->name());
54     }
55 
~BufferQueueTest()56     ~BufferQueueTest() {
57         const ::testing::TestInfo* const testInfo =
58             ::testing::UnitTest::GetInstance()->current_test_info();
59         ALOGV("End test:   %s.%s", testInfo->test_case_name(),
60                 testInfo->name());
61     }
62 
GetMinUndequeuedBufferCount(int * bufferCount)63     void GetMinUndequeuedBufferCount(int* bufferCount) {
64         ASSERT_TRUE(bufferCount != nullptr);
65         ASSERT_EQ(OK, mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
66                     bufferCount));
67         ASSERT_GE(*bufferCount, 0);
68     }
69 
createBufferQueue()70     void createBufferQueue() {
71         BufferQueue::createBufferQueue(&mProducer, &mConsumer);
72     }
73 
testBufferItem(const IGraphicBufferProducer::QueueBufferInput & input,const BufferItem & item)74     void testBufferItem(const IGraphicBufferProducer::QueueBufferInput& input,
75             const BufferItem& item) {
76         int64_t timestamp;
77         bool isAutoTimestamp;
78         android_dataspace dataSpace;
79         Rect crop;
80         int scalingMode;
81         uint32_t transform;
82         sp<Fence> fence;
83 
84         input.deflate(&timestamp, &isAutoTimestamp, &dataSpace, &crop,
85                 &scalingMode, &transform, &fence, nullptr);
86         ASSERT_EQ(timestamp, item.mTimestamp);
87         ASSERT_EQ(isAutoTimestamp, item.mIsAutoTimestamp);
88         ASSERT_EQ(dataSpace, item.mDataSpace);
89         ASSERT_EQ(crop, item.mCrop);
90         ASSERT_EQ(static_cast<uint32_t>(scalingMode), item.mScalingMode);
91         ASSERT_EQ(transform, item.mTransform);
92         ASSERT_EQ(fence, item.mFence);
93     }
94 
95     sp<IGraphicBufferProducer> mProducer;
96     sp<IGraphicBufferConsumer> mConsumer;
97 };
98 
99 static const uint32_t TEST_DATA = 0x12345678u;
100 
101 // XXX: Tests that fork a process to hold the BufferQueue must run before tests
102 // that use a local BufferQueue, or else Binder will get unhappy
103 //
104 // In one instance this was a crash in the createBufferQueue where the
105 // binder call to create a buffer allocator apparently got garbage back.
106 // See b/36592665.
TEST_F(BufferQueueTest,DISABLED_BufferQueueInAnotherProcess)107 TEST_F(BufferQueueTest, DISABLED_BufferQueueInAnotherProcess) {
108     const String16 PRODUCER_NAME = String16("BQTestProducer");
109     const String16 CONSUMER_NAME = String16("BQTestConsumer");
110 
111     pid_t forkPid = fork();
112     ASSERT_NE(forkPid, -1);
113 
114     if (forkPid == 0) {
115         // Child process
116         sp<IGraphicBufferProducer> producer;
117         sp<IGraphicBufferConsumer> consumer;
118         BufferQueue::createBufferQueue(&producer, &consumer);
119         sp<IServiceManager> serviceManager = defaultServiceManager();
120         serviceManager->addService(PRODUCER_NAME, IInterface::asBinder(producer));
121         serviceManager->addService(CONSUMER_NAME, IInterface::asBinder(consumer));
122         ProcessState::self()->startThreadPool();
123         IPCThreadState::self()->joinThreadPool();
124         LOG_ALWAYS_FATAL("Shouldn't be here");
125     }
126 
127     sp<IServiceManager> serviceManager = defaultServiceManager();
128     sp<IBinder> binderProducer =
129         serviceManager->getService(PRODUCER_NAME);
130     mProducer = interface_cast<IGraphicBufferProducer>(binderProducer);
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, EGL_NO_DISPLAY,
429             EGL_NO_SYNC_KHR, Fence::NO_FENCE));
430 
431     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
432               mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
433                                        nullptr, nullptr));
434     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
435 
436     uint32_t* dataOut;
437     ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
438             reinterpret_cast<void**>(&dataOut)));
439     ASSERT_EQ(*dataOut, TEST_DATA);
440     ASSERT_EQ(OK, buffer->unlock());
441 }
442 
TEST_F(BufferQueueTest,MoveFromConsumerToProducer)443 TEST_F(BufferQueueTest, MoveFromConsumerToProducer) {
444     createBufferQueue();
445     sp<MockConsumer> mc(new MockConsumer);
446     ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
447     IGraphicBufferProducer::QueueBufferOutput output;
448     ASSERT_EQ(OK,
449               mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
450 
451     int slot;
452     sp<Fence> fence;
453     sp<GraphicBuffer> buffer;
454     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
455               mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
456                                        nullptr, nullptr));
457     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
458 
459     uint32_t* dataIn;
460     ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
461             reinterpret_cast<void**>(&dataIn)));
462     *dataIn = TEST_DATA;
463     ASSERT_EQ(OK, buffer->unlock());
464 
465     IGraphicBufferProducer::QueueBufferInput input(0, false,
466             HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
467             NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
468     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
469 
470     BufferItem item;
471     ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
472     ASSERT_EQ(OK, mConsumer->detachBuffer(item.mSlot));
473 
474     int newSlot;
475     ASSERT_EQ(OK, mProducer->attachBuffer(&newSlot, item.mGraphicBuffer));
476     ASSERT_EQ(OK, mProducer->queueBuffer(newSlot, input, &output));
477     ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
478 
479     uint32_t* dataOut;
480     ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
481             reinterpret_cast<void**>(&dataOut)));
482     ASSERT_EQ(*dataOut, TEST_DATA);
483     ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
484 }
485 
TEST_F(BufferQueueTest,TestDisallowingAllocation)486 TEST_F(BufferQueueTest, TestDisallowingAllocation) {
487     createBufferQueue();
488     sp<MockConsumer> mc(new MockConsumer);
489     ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
490     IGraphicBufferProducer::QueueBufferOutput output;
491     ASSERT_EQ(OK,
492               mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
493 
494     static const uint32_t WIDTH = 320;
495     static const uint32_t HEIGHT = 240;
496 
497     ASSERT_EQ(OK, mConsumer->setDefaultBufferSize(WIDTH, HEIGHT));
498 
499     int slot;
500     sp<Fence> fence;
501     sp<GraphicBuffer> buffer;
502     // This should return an error since it would require an allocation
503     ASSERT_EQ(OK, mProducer->allowAllocation(false));
504     ASSERT_EQ(WOULD_BLOCK,
505               mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
506                                        nullptr, nullptr));
507 
508     // This should succeed, now that we've lifted the prohibition
509     ASSERT_EQ(OK, mProducer->allowAllocation(true));
510     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
511               mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
512                                        nullptr, nullptr));
513 
514     // Release the previous buffer back to the BufferQueue
515     mProducer->cancelBuffer(slot, fence);
516 
517     // This should fail since we're requesting a different size
518     ASSERT_EQ(OK, mProducer->allowAllocation(false));
519     ASSERT_EQ(WOULD_BLOCK,
520               mProducer->dequeueBuffer(&slot, &fence, WIDTH * 2, HEIGHT * 2, 0,
521                                        GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr, nullptr));
522 }
523 
TEST_F(BufferQueueTest,TestGenerationNumbers)524 TEST_F(BufferQueueTest, TestGenerationNumbers) {
525     createBufferQueue();
526     sp<MockConsumer> mc(new MockConsumer);
527     ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
528     IGraphicBufferProducer::QueueBufferOutput output;
529     ASSERT_EQ(OK,
530               mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
531 
532     ASSERT_EQ(OK, mProducer->setGenerationNumber(1));
533 
534     // Get one buffer to play with
535     int slot;
536     sp<Fence> fence;
537     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
538               mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, 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, 0, nullptr, nullptr));
582     ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
583 
584     // Queue the buffer
585     IGraphicBufferProducer::QueueBufferInput input(0, false,
586             HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
587             NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
588     ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
589 
590     // Repeatedly queue and dequeue a buffer from the producer side, it should
591     // always return the same one. And we won't run out of buffers because it's
592     // always the same one and because async mode gets enabled.
593     int slot;
594     for (int i = 0; i < 5; i++) {
595         ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
596         ASSERT_EQ(sharedSlot, slot);
597         ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
598     }
599 
600     // acquire the buffer
601     BufferItem item;
602     ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
603     ASSERT_EQ(sharedSlot, item.mSlot);
604     testBufferItem(input, item);
605     ASSERT_EQ(true, item.mQueuedBuffer);
606     ASSERT_EQ(false, item.mAutoRefresh);
607 
608     ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
609             EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
610 
611     // attempt to acquire a second time should return no buffer available
612     ASSERT_EQ(IGraphicBufferConsumer::NO_BUFFER_AVAILABLE,
613             mConsumer->acquireBuffer(&item, 0));
614 }
615 
TEST_F(BufferQueueTest,TestSharedBufferModeWithAutoRefresh)616 TEST_F(BufferQueueTest, TestSharedBufferModeWithAutoRefresh) {
617     createBufferQueue();
618     sp<MockConsumer> mc(new MockConsumer);
619     ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
620     IGraphicBufferProducer::QueueBufferOutput output;
621     ASSERT_EQ(OK,
622               mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
623 
624     ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
625     ASSERT_EQ(OK, mProducer->setAutoRefresh(true));
626 
627     // Get a buffer
628     int sharedSlot;
629     sp<Fence> fence;
630     sp<GraphicBuffer> buffer;
631     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
632               mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0, nullptr, nullptr));
633     ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
634 
635     // Queue the buffer
636     IGraphicBufferProducer::QueueBufferInput input(0, false,
637             HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
638             NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
639     ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
640 
641     // Repeatedly acquire and release a buffer from the consumer side, it should
642     // always return the same one.
643     BufferItem item;
644     for (int i = 0; i < 5; i++) {
645         ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
646         ASSERT_EQ(sharedSlot, item.mSlot);
647         testBufferItem(input, item);
648         ASSERT_EQ(i == 0, item.mQueuedBuffer);
649         ASSERT_EQ(true, item.mAutoRefresh);
650 
651         ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
652                 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
653     }
654 
655     // Repeatedly queue and dequeue a buffer from the producer side, it should
656     // always return the same one.
657     int slot;
658     for (int i = 0; i < 5; i++) {
659         ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
660         ASSERT_EQ(sharedSlot, slot);
661         ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
662     }
663 
664     // Repeatedly acquire and release a buffer from the consumer side, it should
665     // always return the same one. First grabbing them from the queue and then
666     // when the queue is empty, returning the shared buffer.
667     for (int i = 0; i < 10; i++) {
668         ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
669         ASSERT_EQ(sharedSlot, item.mSlot);
670         ASSERT_EQ(0, item.mTimestamp);
671         ASSERT_EQ(false, item.mIsAutoTimestamp);
672         ASSERT_EQ(HAL_DATASPACE_UNKNOWN, item.mDataSpace);
673         ASSERT_EQ(Rect(0, 0, 1, 1), item.mCrop);
674         ASSERT_EQ(NATIVE_WINDOW_SCALING_MODE_FREEZE, item.mScalingMode);
675         ASSERT_EQ(0u, item.mTransform);
676         ASSERT_EQ(Fence::NO_FENCE, item.mFence);
677         ASSERT_EQ(i == 0, item.mQueuedBuffer);
678         ASSERT_EQ(true, item.mAutoRefresh);
679 
680         ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
681                 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
682     }
683 }
684 
TEST_F(BufferQueueTest,TestSharedBufferModeUsingAlreadyDequeuedBuffer)685 TEST_F(BufferQueueTest, TestSharedBufferModeUsingAlreadyDequeuedBuffer) {
686     createBufferQueue();
687     sp<MockConsumer> mc(new MockConsumer);
688     ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
689     IGraphicBufferProducer::QueueBufferOutput output;
690     ASSERT_EQ(OK,
691               mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
692 
693     // Dequeue a buffer
694     int sharedSlot;
695     sp<Fence> fence;
696     sp<GraphicBuffer> buffer;
697     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
698               mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0, nullptr, nullptr));
699     ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
700 
701     // Enable shared buffer mode
702     ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
703 
704     // Queue the buffer
705     IGraphicBufferProducer::QueueBufferInput input(0, false,
706             HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
707             NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
708     ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
709 
710     // Repeatedly queue and dequeue a buffer from the producer side, it should
711     // always return the same one. And we won't run out of buffers because it's
712     // always the same one and because async mode gets enabled.
713     int slot;
714     for (int i = 0; i < 5; i++) {
715         ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
716         ASSERT_EQ(sharedSlot, slot);
717         ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
718     }
719 
720     // acquire the buffer
721     BufferItem item;
722     ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
723     ASSERT_EQ(sharedSlot, item.mSlot);
724     testBufferItem(input, item);
725     ASSERT_EQ(true, item.mQueuedBuffer);
726     ASSERT_EQ(false, item.mAutoRefresh);
727 
728     ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
729             EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
730 
731     // attempt to acquire a second time should return no buffer available
732     ASSERT_EQ(IGraphicBufferConsumer::NO_BUFFER_AVAILABLE,
733             mConsumer->acquireBuffer(&item, 0));
734 }
735 
TEST_F(BufferQueueTest,TestTimeouts)736 TEST_F(BufferQueueTest, TestTimeouts) {
737     createBufferQueue();
738     sp<MockConsumer> mc(new MockConsumer);
739     ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
740     IGraphicBufferProducer::QueueBufferOutput output;
741     ASSERT_EQ(OK,
742               mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
743 
744     // Fill up the queue. Since the controlledByApp flags are set to true, this
745     // queue should be in non-blocking mode, and we should be recycling the same
746     // two buffers
747     for (int i = 0; i < 5; ++i) {
748         int slot = BufferQueue::INVALID_BUFFER_SLOT;
749         sp<Fence> fence = Fence::NO_FENCE;
750         auto result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr);
751         if (i < 2) {
752             ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
753                     result);
754         } else {
755             ASSERT_EQ(OK, result);
756         }
757         sp<GraphicBuffer> buffer;
758         ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
759         IGraphicBufferProducer::QueueBufferInput input(0ull, true,
760                 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
761                 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
762         IGraphicBufferProducer::QueueBufferOutput output{};
763         ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
764     }
765 
766     const auto TIMEOUT = ms2ns(250);
767     mProducer->setDequeueTimeout(TIMEOUT);
768 
769     // Setting a timeout will change the BufferQueue into blocking mode (with
770     // one droppable buffer in the queue and one free from the previous
771     // dequeue/queues), so dequeue and queue two more buffers: one to replace
772     // the current droppable buffer, and a second to max out the buffer count
773     sp<GraphicBuffer> buffer; // Save a buffer to attach later
774     for (int i = 0; i < 2; ++i) {
775         int slot = BufferQueue::INVALID_BUFFER_SLOT;
776         sp<Fence> fence = Fence::NO_FENCE;
777         ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
778         ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
779         IGraphicBufferProducer::QueueBufferInput input(0ull, true,
780                 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
781                 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
782         ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
783     }
784 
785     int slot = BufferQueue::INVALID_BUFFER_SLOT;
786     sp<Fence> fence = Fence::NO_FENCE;
787     auto startTime = systemTime();
788     ASSERT_EQ(TIMED_OUT, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
789     ASSERT_GE(systemTime() - startTime, TIMEOUT);
790 
791     // We're technically attaching the same buffer multiple times (since we
792     // queued it previously), but that doesn't matter for this test
793     startTime = systemTime();
794     ASSERT_EQ(TIMED_OUT, mProducer->attachBuffer(&slot, buffer));
795     ASSERT_GE(systemTime() - startTime, TIMEOUT);
796 }
797 
TEST_F(BufferQueueTest,CanAttachWhileDisallowingAllocation)798 TEST_F(BufferQueueTest, CanAttachWhileDisallowingAllocation) {
799     createBufferQueue();
800     sp<MockConsumer> mc(new MockConsumer);
801     ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
802     IGraphicBufferProducer::QueueBufferOutput output;
803     ASSERT_EQ(OK,
804               mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
805 
806     int slot = BufferQueue::INVALID_BUFFER_SLOT;
807     sp<Fence> sourceFence;
808     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
809               mProducer->dequeueBuffer(&slot, &sourceFence, 0, 0, 0, 0, nullptr, nullptr));
810     sp<GraphicBuffer> buffer;
811     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
812     ASSERT_EQ(OK, mProducer->detachBuffer(slot));
813 
814     ASSERT_EQ(OK, mProducer->allowAllocation(false));
815 
816     slot = BufferQueue::INVALID_BUFFER_SLOT;
817     ASSERT_EQ(OK, mProducer->attachBuffer(&slot, buffer));
818 }
819 
TEST_F(BufferQueueTest,CanRetrieveLastQueuedBuffer)820 TEST_F(BufferQueueTest, CanRetrieveLastQueuedBuffer) {
821     createBufferQueue();
822     sp<MockConsumer> mc(new MockConsumer);
823     ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
824     IGraphicBufferProducer::QueueBufferOutput output;
825     ASSERT_EQ(OK,
826               mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
827 
828     // Dequeue and queue the first buffer, storing the handle
829     int slot = BufferQueue::INVALID_BUFFER_SLOT;
830     sp<Fence> fence;
831     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
832               mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
833     sp<GraphicBuffer> firstBuffer;
834     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &firstBuffer));
835 
836     IGraphicBufferProducer::QueueBufferInput input(0ull, true,
837         HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
838         NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
839     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
840 
841     // Dequeue a second buffer
842     slot = BufferQueue::INVALID_BUFFER_SLOT;
843     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
844               mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
845     sp<GraphicBuffer> secondBuffer;
846     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &secondBuffer));
847 
848     // Ensure it's a new buffer
849     ASSERT_NE(firstBuffer->getNativeBuffer()->handle,
850             secondBuffer->getNativeBuffer()->handle);
851 
852     // Queue the second buffer
853     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
854 
855     // Acquire and release both buffers
856     for (size_t i = 0; i < 2; ++i) {
857         BufferItem item;
858         ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
859         ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
860                     EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
861     }
862 
863     // Make sure we got the second buffer back
864     sp<GraphicBuffer> returnedBuffer;
865     sp<Fence> returnedFence;
866     float transform[16];
867     ASSERT_EQ(OK,
868             mProducer->getLastQueuedBuffer(&returnedBuffer, &returnedFence,
869             transform));
870     ASSERT_EQ(secondBuffer->getNativeBuffer()->handle,
871             returnedBuffer->getNativeBuffer()->handle);
872 }
873 
TEST_F(BufferQueueTest,TestOccupancyHistory)874 TEST_F(BufferQueueTest, TestOccupancyHistory) {
875     createBufferQueue();
876     sp<MockConsumer> mc(new MockConsumer);
877     ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
878     IGraphicBufferProducer::QueueBufferOutput output;
879     ASSERT_EQ(OK,
880               mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &output));
881 
882     int slot = BufferQueue::INVALID_BUFFER_SLOT;
883     sp<Fence> fence = Fence::NO_FENCE;
884     sp<GraphicBuffer> buffer = nullptr;
885     IGraphicBufferProducer::QueueBufferInput input(0ull, true,
886         HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
887         NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
888     BufferItem item{};
889 
890     // Preallocate, dequeue, request, and cancel 3 buffers so we don't get
891     // BUFFER_NEEDS_REALLOCATION below
892     int slots[3] = {};
893     mProducer->setMaxDequeuedBufferCount(3);
894     for (size_t i = 0; i < 3; ++i) {
895         status_t result =
896                 mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0, 0, nullptr, nullptr);
897         ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
898         ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
899     }
900     for (size_t i = 0; i < 3; ++i) {
901         ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE));
902     }
903 
904     // Create 3 segments
905 
906     // The first segment is a two-buffer segment, so we only put one buffer into
907     // the queue at a time
908     for (size_t i = 0; i < 5; ++i) {
909         ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
910         ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
911         ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
912         ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
913                 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
914         std::this_thread::sleep_for(16ms);
915     }
916 
917     // Sleep between segments
918     std::this_thread::sleep_for(500ms);
919 
920     // The second segment is a double-buffer segment. It starts the same as the
921     // two-buffer segment, but then at the end, we put two buffers in the queue
922     // at the same time before draining it.
923     for (size_t i = 0; i < 5; ++i) {
924         ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
925         ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
926         ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
927         ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
928                 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
929         std::this_thread::sleep_for(16ms);
930     }
931     ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
932     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
933     ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
934     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
935     ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
936     ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
937             EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
938     std::this_thread::sleep_for(16ms);
939     ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
940     ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
941             EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
942 
943     // Sleep between segments
944     std::this_thread::sleep_for(500ms);
945 
946     // The third segment is a triple-buffer segment, so the queue is switching
947     // between one buffer and two buffers deep.
948     ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
949     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
950     for (size_t i = 0; i < 5; ++i) {
951         ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, 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,
955                     EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
956         std::this_thread::sleep_for(16ms);
957     }
958     ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
959     ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
960             EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
961 
962     // Now we read the segments
963     std::vector<OccupancyTracker::Segment> history;
964     ASSERT_EQ(OK, mConsumer->getOccupancyHistory(false, &history));
965 
966     // Since we didn't force a flush, we should only get the first two segments
967     // (since the third segment hasn't been closed out by the appearance of a
968     // new segment yet)
969     ASSERT_EQ(2u, history.size());
970 
971     // The first segment (which will be history[1], since the newest segment
972     // should be at the front of the vector) should be a two-buffer segment,
973     // which implies that the occupancy average should be between 0 and 1, and
974     // usedThirdBuffer should be false
975     const auto& firstSegment = history[1];
976     ASSERT_EQ(5u, firstSegment.numFrames);
977     ASSERT_LT(0, firstSegment.occupancyAverage);
978     ASSERT_GT(1, firstSegment.occupancyAverage);
979     ASSERT_EQ(false, firstSegment.usedThirdBuffer);
980 
981     // The second segment should be a double-buffered segment, which implies that
982     // the occupancy average should be between 0 and 1, but usedThirdBuffer
983     // should be true
984     const auto& secondSegment = history[0];
985     ASSERT_EQ(7u, secondSegment.numFrames);
986     ASSERT_LT(0, secondSegment.occupancyAverage);
987     ASSERT_GT(1, secondSegment.occupancyAverage);
988     ASSERT_EQ(true, secondSegment.usedThirdBuffer);
989 
990     // If we read the segments again without flushing, we shouldn't get any new
991     // segments
992     ASSERT_EQ(OK, mConsumer->getOccupancyHistory(false, &history));
993     ASSERT_EQ(0u, history.size());
994 
995     // Read the segments again, this time forcing a flush so we get the third
996     // segment
997     ASSERT_EQ(OK, mConsumer->getOccupancyHistory(true, &history));
998     ASSERT_EQ(1u, history.size());
999 
1000     // This segment should be a triple-buffered segment, which implies that the
1001     // occupancy average should be between 1 and 2, and usedThirdBuffer should
1002     // be true
1003     const auto& thirdSegment = history[0];
1004     ASSERT_EQ(6u, thirdSegment.numFrames);
1005     ASSERT_LT(1, thirdSegment.occupancyAverage);
1006     ASSERT_GT(2, thirdSegment.occupancyAverage);
1007     ASSERT_EQ(true, thirdSegment.usedThirdBuffer);
1008 }
1009 
1010 struct BufferDiscardedListener : public BnProducerListener {
1011 public:
1012     BufferDiscardedListener() = default;
1013     virtual ~BufferDiscardedListener() = default;
1014 
onBufferReleasedandroid::BufferDiscardedListener1015     virtual void onBufferReleased() {}
needsReleaseNotifyandroid::BufferDiscardedListener1016     virtual bool needsReleaseNotify() { return false; }
onBuffersDiscardedandroid::BufferDiscardedListener1017     virtual void onBuffersDiscarded(const std::vector<int32_t>& slots) {
1018         mDiscardedSlots.insert(mDiscardedSlots.end(), slots.begin(), slots.end());
1019     }
1020 
getDiscardedSlotsandroid::BufferDiscardedListener1021     const std::vector<int32_t>& getDiscardedSlots() const { return mDiscardedSlots; }
1022 private:
1023     // No need to use lock given the test triggers the listener in the same
1024     // thread context.
1025     std::vector<int32_t> mDiscardedSlots;
1026 };
1027 
TEST_F(BufferQueueTest,TestDiscardFreeBuffers)1028 TEST_F(BufferQueueTest, TestDiscardFreeBuffers) {
1029     createBufferQueue();
1030     sp<MockConsumer> mc(new MockConsumer);
1031     ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
1032     IGraphicBufferProducer::QueueBufferOutput output;
1033     sp<BufferDiscardedListener> pl(new BufferDiscardedListener);
1034     ASSERT_EQ(OK, mProducer->connect(pl,
1035             NATIVE_WINDOW_API_CPU, false, &output));
1036 
1037     int slot = BufferQueue::INVALID_BUFFER_SLOT;
1038     sp<Fence> fence = Fence::NO_FENCE;
1039     sp<GraphicBuffer> buffer = nullptr;
1040     IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1041         HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1042         NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1043     BufferItem item{};
1044 
1045     // Preallocate, dequeue, request, and cancel 4 buffers so we don't get
1046     // BUFFER_NEEDS_REALLOCATION below
1047     int slots[4] = {};
1048     mProducer->setMaxDequeuedBufferCount(4);
1049     for (size_t i = 0; i < 4; ++i) {
1050         status_t result =
1051                 mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0, 0, nullptr, nullptr);
1052         ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1053         ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
1054     }
1055     for (size_t i = 0; i < 4; ++i) {
1056         ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE));
1057     }
1058 
1059     // Get buffers in all states: dequeued, filled, acquired, free
1060 
1061     // Fill 3 buffers
1062     ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
1063     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1064     ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
1065     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1066     ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
1067     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1068     // Dequeue 1 buffer
1069     ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
1070 
1071     // Acquire and free 1 buffer
1072     ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1073     ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
1074                     EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
1075     int releasedSlot = item.mSlot;
1076 
1077     // Acquire 1 buffer, leaving 1 filled buffer in queue
1078     ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1079 
1080     // Now discard the free buffers
1081     ASSERT_EQ(OK, mConsumer->discardFreeBuffers());
1082 
1083     // Check onBuffersDiscarded is called with correct slots
1084     auto buffersDiscarded = pl->getDiscardedSlots();
1085     ASSERT_EQ(buffersDiscarded.size(), 1);
1086     ASSERT_EQ(buffersDiscarded[0], releasedSlot);
1087 
1088     // Check no free buffers in dump
1089     String8 dumpString;
1090     mConsumer->dumpState(String8{}, &dumpString);
1091 
1092     // Parse the dump to ensure that all buffer slots that are FREE also
1093     // have a null GraphicBuffer
1094     // Fragile - assumes the following format for the dump for a buffer entry:
1095     // ":%p\][^:]*state=FREE" where %p is the buffer pointer in hex.
1096     ssize_t idx = dumpString.find("state=FREE");
1097     while (idx != -1) {
1098         ssize_t bufferPtrIdx = idx - 1;
1099         while (bufferPtrIdx > 0) {
1100             if (dumpString[bufferPtrIdx] == ':') {
1101                 bufferPtrIdx++;
1102                 break;
1103             }
1104             bufferPtrIdx--;
1105         }
1106         ASSERT_GT(bufferPtrIdx, 0) << "Can't parse queue dump to validate";
1107         ssize_t nullPtrIdx = dumpString.find("0x0]", bufferPtrIdx);
1108         ASSERT_EQ(bufferPtrIdx, nullPtrIdx) << "Free buffer not discarded";
1109         idx = dumpString.find("FREE", idx + 1);
1110     }
1111 }
1112 
TEST_F(BufferQueueTest,TestBufferReplacedInQueueBuffer)1113 TEST_F(BufferQueueTest, TestBufferReplacedInQueueBuffer) {
1114     createBufferQueue();
1115     sp<MockConsumer> mc(new MockConsumer);
1116     ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
1117     IGraphicBufferProducer::QueueBufferOutput output;
1118     ASSERT_EQ(OK,
1119               mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, true, &output));
1120     ASSERT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
1121 
1122     int slot = BufferQueue::INVALID_BUFFER_SLOT;
1123     sp<Fence> fence = Fence::NO_FENCE;
1124     sp<GraphicBuffer> buffer = nullptr;
1125     IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1126         HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1127         NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1128     BufferItem item{};
1129 
1130     // Preallocate, dequeue, request, and cancel 2 buffers so we don't get
1131     // BUFFER_NEEDS_REALLOCATION below
1132     int slots[2] = {};
1133     ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(2));
1134     for (size_t i = 0; i < 2; ++i) {
1135         status_t result =
1136                 mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0, 0, nullptr, nullptr);
1137         ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1138         ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
1139     }
1140     for (size_t i = 0; i < 2; ++i) {
1141         ASSERT_EQ(OK, mProducer->cancelBuffer(slots[i], Fence::NO_FENCE));
1142     }
1143 
1144     // Fill 2 buffers without consumer consuming them. Verify that all
1145     // queued buffer returns proper bufferReplaced flag
1146     ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
1147     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1148     ASSERT_EQ(false, output.bufferReplaced);
1149     ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
1150     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1151     ASSERT_EQ(true, output.bufferReplaced);
1152 }
1153 
TEST_F(BufferQueueTest,TestStaleBufferHandleSentAfterDisconnect)1154 TEST_F(BufferQueueTest, TestStaleBufferHandleSentAfterDisconnect) {
1155     createBufferQueue();
1156     sp<MockConsumer> mc(new MockConsumer);
1157     ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
1158     IGraphicBufferProducer::QueueBufferOutput output;
1159     sp<IProducerListener> fakeListener(new StubProducerListener);
1160     ASSERT_EQ(OK, mProducer->connect(fakeListener, NATIVE_WINDOW_API_CPU, true, &output));
1161 
1162     int slot = BufferQueue::INVALID_BUFFER_SLOT;
1163     sp<Fence> fence = Fence::NO_FENCE;
1164     sp<GraphicBuffer> buffer = nullptr;
1165     IGraphicBufferProducer::QueueBufferInput input(0ull, true,
1166             HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
1167             NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
1168 
1169     // Dequeue, request, and queue one buffer
1170     status_t result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr);
1171     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
1172     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
1173     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1174 
1175     // Acquire and release the buffer. Upon acquiring, the buffer handle should
1176     // be non-null since this is the first time we've acquired this slot.
1177     BufferItem item;
1178     ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1179     ASSERT_EQ(slot, item.mSlot);
1180     ASSERT_NE(nullptr, item.mGraphicBuffer.get());
1181     ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
1182             EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
1183 
1184     // Dequeue and queue the buffer again
1185     ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
1186     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1187 
1188     // Acquire and release the buffer again. Upon acquiring, the buffer handle
1189     // should be null since this is not the first time we've acquired this slot.
1190     ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1191     ASSERT_EQ(slot, item.mSlot);
1192     ASSERT_EQ(nullptr, item.mGraphicBuffer.get());
1193     ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
1194             EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
1195 
1196     // Dequeue and queue the buffer again
1197     ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
1198     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
1199 
1200     // Disconnect the producer end. This should clear all of the slots and mark
1201     // the buffer in the queue as stale.
1202     ASSERT_EQ(OK, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
1203 
1204     // Acquire the buffer again. Upon acquiring, the buffer handle should not be
1205     // null since the queued buffer should have been marked as stale, which
1206     // should trigger the BufferQueue to resend the buffer handle.
1207     ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
1208     ASSERT_EQ(slot, item.mSlot);
1209     ASSERT_NE(nullptr, item.mGraphicBuffer.get());
1210 }
1211 
TEST_F(BufferQueueTest,TestProducerConnectDisconnect)1212 TEST_F(BufferQueueTest, TestProducerConnectDisconnect) {
1213     createBufferQueue();
1214     sp<MockConsumer> mc(new MockConsumer);
1215     ASSERT_EQ(OK, mConsumer->consumerConnect(mc, true));
1216     IGraphicBufferProducer::QueueBufferOutput output;
1217     sp<IProducerListener> fakeListener(new StubProducerListener);
1218     ASSERT_EQ(NO_INIT, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
1219     ASSERT_EQ(OK, mProducer->connect(fakeListener, NATIVE_WINDOW_API_CPU, true, &output));
1220     ASSERT_EQ(BAD_VALUE, mProducer->connect(fakeListener, NATIVE_WINDOW_API_MEDIA, true, &output));
1221 
1222     ASSERT_EQ(BAD_VALUE, mProducer->disconnect(NATIVE_WINDOW_API_MEDIA));
1223     ASSERT_EQ(OK, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
1224     ASSERT_EQ(NO_INIT, mProducer->disconnect(NATIVE_WINDOW_API_CPU));
1225 }
1226 
1227 } // namespace android
1228