BufferQueue_test.cpp revision 9de7293b0a1b01ebe6fb1ab4a498f144adc8029f
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 <gui/BufferItem.h>
21#include <gui/BufferQueue.h>
22#include <gui/IProducerListener.h>
23
24#include <ui/GraphicBuffer.h>
25
26#include <binder/IPCThreadState.h>
27#include <binder/IServiceManager.h>
28#include <binder/ProcessState.h>
29
30#include <utils/String8.h>
31#include <utils/threads.h>
32
33#include <gtest/gtest.h>
34
35namespace android {
36
37class BufferQueueTest : public ::testing::Test {
38
39public:
40protected:
41    BufferQueueTest() {
42        const ::testing::TestInfo* const testInfo =
43            ::testing::UnitTest::GetInstance()->current_test_info();
44        ALOGV("Begin test: %s.%s", testInfo->test_case_name(),
45                testInfo->name());
46    }
47
48    ~BufferQueueTest() {
49        const ::testing::TestInfo* const testInfo =
50            ::testing::UnitTest::GetInstance()->current_test_info();
51        ALOGV("End test:   %s.%s", testInfo->test_case_name(),
52                testInfo->name());
53    }
54
55    void GetMinUndequeuedBufferCount(int* bufferCount) {
56        ASSERT_TRUE(bufferCount != NULL);
57        ASSERT_EQ(OK, mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
58                    bufferCount));
59        ASSERT_GE(*bufferCount, 0);
60    }
61
62    void createBufferQueue() {
63        BufferQueue::createBufferQueue(&mProducer, &mConsumer);
64    }
65
66    sp<IGraphicBufferProducer> mProducer;
67    sp<IGraphicBufferConsumer> mConsumer;
68};
69
70struct DummyConsumer : public BnConsumerListener {
71    virtual void onFrameAvailable(const BufferItem& /* item */) {}
72    virtual void onBuffersReleased() {}
73    virtual void onSidebandStreamChanged() {}
74};
75
76// XXX: Tests that fork a process to hold the BufferQueue must run before tests
77// that use a local BufferQueue, or else Binder will get unhappy
78TEST_F(BufferQueueTest, BufferQueueInAnotherProcess) {
79    const String16 PRODUCER_NAME = String16("BQTestProducer");
80    const String16 CONSUMER_NAME = String16("BQTestConsumer");
81
82    pid_t forkPid = fork();
83    ASSERT_NE(forkPid, -1);
84
85    if (forkPid == 0) {
86        // Child process
87        sp<IGraphicBufferProducer> producer;
88        sp<IGraphicBufferConsumer> consumer;
89        BufferQueue::createBufferQueue(&producer, &consumer);
90        sp<IServiceManager> serviceManager = defaultServiceManager();
91        serviceManager->addService(PRODUCER_NAME, IInterface::asBinder(producer));
92        serviceManager->addService(CONSUMER_NAME, IInterface::asBinder(consumer));
93        ProcessState::self()->startThreadPool();
94        IPCThreadState::self()->joinThreadPool();
95        LOG_ALWAYS_FATAL("Shouldn't be here");
96    }
97
98    sp<IServiceManager> serviceManager = defaultServiceManager();
99    sp<IBinder> binderProducer =
100        serviceManager->getService(PRODUCER_NAME);
101    mProducer = interface_cast<IGraphicBufferProducer>(binderProducer);
102    EXPECT_TRUE(mProducer != NULL);
103    sp<IBinder> binderConsumer =
104        serviceManager->getService(CONSUMER_NAME);
105    mConsumer = interface_cast<IGraphicBufferConsumer>(binderConsumer);
106    EXPECT_TRUE(mConsumer != NULL);
107
108    sp<DummyConsumer> dc(new DummyConsumer);
109    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
110    IGraphicBufferProducer::QueueBufferOutput output;
111    ASSERT_EQ(OK,
112            mProducer->connect(NULL, NATIVE_WINDOW_API_CPU, false, &output));
113
114    int slot;
115    sp<Fence> fence;
116    sp<GraphicBuffer> buffer;
117    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
118            mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0,
119                    GRALLOC_USAGE_SW_WRITE_OFTEN));
120    ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
121
122    uint32_t* dataIn;
123    ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
124            reinterpret_cast<void**>(&dataIn)));
125    *dataIn = 0x12345678;
126    ASSERT_EQ(OK, buffer->unlock());
127
128    IGraphicBufferProducer::QueueBufferInput input(0, false,
129            HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
130            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE);
131    ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
132
133    BufferItem item;
134    ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
135
136    uint32_t* dataOut;
137    ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
138            reinterpret_cast<void**>(&dataOut)));
139    ASSERT_EQ(*dataOut, 0x12345678);
140    ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
141}
142
143TEST_F(BufferQueueTest, AcquireBuffer_ExceedsMaxAcquireCount_Fails) {
144    createBufferQueue();
145    sp<DummyConsumer> dc(new DummyConsumer);
146    mConsumer->consumerConnect(dc, false);
147    IGraphicBufferProducer::QueueBufferOutput qbo;
148    mProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, false,
149            &qbo);
150    mProducer->setBufferCount(4);
151
152    int slot;
153    sp<Fence> fence;
154    sp<GraphicBuffer> buf;
155    IGraphicBufferProducer::QueueBufferInput qbi(0, false,
156            HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
157            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE);
158    BufferItem item;
159
160    for (int i = 0; i < 2; i++) {
161        ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
162                mProducer->dequeueBuffer(&slot, &fence, false, 1, 1, 0,
163                    GRALLOC_USAGE_SW_READ_OFTEN));
164        ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
165        ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
166        ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
167    }
168
169    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
170            mProducer->dequeueBuffer(&slot, &fence, false, 1, 1, 0,
171                GRALLOC_USAGE_SW_READ_OFTEN));
172    ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
173    ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
174
175    // Acquire the third buffer, which should fail.
176    ASSERT_EQ(INVALID_OPERATION, mConsumer->acquireBuffer(&item, 0));
177}
178
179TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithIllegalValues_ReturnsError) {
180    createBufferQueue();
181    sp<DummyConsumer> dc(new DummyConsumer);
182    mConsumer->consumerConnect(dc, false);
183
184    int minBufferCount;
185    ASSERT_NO_FATAL_FAILURE(GetMinUndequeuedBufferCount(&minBufferCount));
186    EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(
187                minBufferCount - 1));
188
189    EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(0));
190    EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(-3));
191    EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(
192            BufferQueue::MAX_MAX_ACQUIRED_BUFFERS+1));
193    EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(100));
194}
195
196TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithLegalValues_Succeeds) {
197    createBufferQueue();
198    sp<DummyConsumer> dc(new DummyConsumer);
199    mConsumer->consumerConnect(dc, false);
200
201    int minBufferCount;
202    ASSERT_NO_FATAL_FAILURE(GetMinUndequeuedBufferCount(&minBufferCount));
203
204    EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
205    EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(2));
206    EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(minBufferCount));
207    EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(
208            BufferQueue::MAX_MAX_ACQUIRED_BUFFERS));
209}
210
211TEST_F(BufferQueueTest, DetachAndReattachOnProducerSide) {
212    createBufferQueue();
213    sp<DummyConsumer> dc(new DummyConsumer);
214    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
215    IGraphicBufferProducer::QueueBufferOutput output;
216    ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
217            NATIVE_WINDOW_API_CPU, false, &output));
218
219    ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(-1)); // Index too low
220    ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(
221                BufferQueueDefs::NUM_BUFFER_SLOTS)); // Index too high
222    ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(0)); // Not dequeued
223
224    int slot;
225    sp<Fence> fence;
226    sp<GraphicBuffer> buffer;
227    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
228            mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0,
229                    GRALLOC_USAGE_SW_WRITE_OFTEN));
230    ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(slot)); // Not requested
231    ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
232    ASSERT_EQ(OK, mProducer->detachBuffer(slot));
233    ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(slot)); // Not dequeued
234
235    sp<GraphicBuffer> safeToClobberBuffer;
236    // Can no longer request buffer from this slot
237    ASSERT_EQ(BAD_VALUE, mProducer->requestBuffer(slot, &safeToClobberBuffer));
238
239    uint32_t* dataIn;
240    ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
241            reinterpret_cast<void**>(&dataIn)));
242    *dataIn = 0x12345678;
243    ASSERT_EQ(OK, buffer->unlock());
244
245    int newSlot;
246    ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(NULL, safeToClobberBuffer));
247    ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(&newSlot, NULL));
248
249    ASSERT_EQ(OK, mProducer->attachBuffer(&newSlot, buffer));
250    IGraphicBufferProducer::QueueBufferInput input(0, false,
251            HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
252            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE);
253    ASSERT_EQ(OK, mProducer->queueBuffer(newSlot, input, &output));
254
255    BufferItem item;
256    ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
257
258    uint32_t* dataOut;
259    ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
260            reinterpret_cast<void**>(&dataOut)));
261    ASSERT_EQ(*dataOut, 0x12345678);
262    ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
263}
264
265TEST_F(BufferQueueTest, DetachAndReattachOnConsumerSide) {
266    createBufferQueue();
267    sp<DummyConsumer> dc(new DummyConsumer);
268    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
269    IGraphicBufferProducer::QueueBufferOutput output;
270    ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
271            NATIVE_WINDOW_API_CPU, false, &output));
272
273    int slot;
274    sp<Fence> fence;
275    sp<GraphicBuffer> buffer;
276    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
277            mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0,
278                    GRALLOC_USAGE_SW_WRITE_OFTEN));
279    ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
280    IGraphicBufferProducer::QueueBufferInput input(0, false,
281            HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
282            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE);
283    ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
284
285    ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(-1)); // Index too low
286    ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(
287            BufferQueueDefs::NUM_BUFFER_SLOTS)); // Index too high
288    ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(0)); // Not acquired
289
290    BufferItem item;
291    ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
292
293    ASSERT_EQ(OK, mConsumer->detachBuffer(item.mBuf));
294    ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(item.mBuf)); // Not acquired
295
296    uint32_t* dataIn;
297    ASSERT_EQ(OK, item.mGraphicBuffer->lock(
298            GraphicBuffer::USAGE_SW_WRITE_OFTEN,
299            reinterpret_cast<void**>(&dataIn)));
300    *dataIn = 0x12345678;
301    ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
302
303    int newSlot;
304    sp<GraphicBuffer> safeToClobberBuffer;
305    ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(NULL, safeToClobberBuffer));
306    ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(&newSlot, NULL));
307    ASSERT_EQ(OK, mConsumer->attachBuffer(&newSlot, item.mGraphicBuffer));
308
309    ASSERT_EQ(OK, mConsumer->releaseBuffer(newSlot, 0, EGL_NO_DISPLAY,
310            EGL_NO_SYNC_KHR, Fence::NO_FENCE));
311
312    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
313            mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0,
314                    GRALLOC_USAGE_SW_WRITE_OFTEN));
315    ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
316
317    uint32_t* dataOut;
318    ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
319            reinterpret_cast<void**>(&dataOut)));
320    ASSERT_EQ(*dataOut, 0x12345678);
321    ASSERT_EQ(OK, buffer->unlock());
322}
323
324TEST_F(BufferQueueTest, MoveFromConsumerToProducer) {
325    createBufferQueue();
326    sp<DummyConsumer> dc(new DummyConsumer);
327    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
328    IGraphicBufferProducer::QueueBufferOutput output;
329    ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
330            NATIVE_WINDOW_API_CPU, false, &output));
331
332    int slot;
333    sp<Fence> fence;
334    sp<GraphicBuffer> buffer;
335    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
336            mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0,
337                    GRALLOC_USAGE_SW_WRITE_OFTEN));
338    ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
339
340    uint32_t* dataIn;
341    ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
342            reinterpret_cast<void**>(&dataIn)));
343    *dataIn = 0x12345678;
344    ASSERT_EQ(OK, buffer->unlock());
345
346    IGraphicBufferProducer::QueueBufferInput input(0, false,
347            HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
348            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE);
349    ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
350
351    BufferItem item;
352    ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
353    ASSERT_EQ(OK, mConsumer->detachBuffer(item.mBuf));
354
355    int newSlot;
356    ASSERT_EQ(OK, mProducer->attachBuffer(&newSlot, item.mGraphicBuffer));
357    ASSERT_EQ(OK, mProducer->queueBuffer(newSlot, input, &output));
358    ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
359
360    uint32_t* dataOut;
361    ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
362            reinterpret_cast<void**>(&dataOut)));
363    ASSERT_EQ(*dataOut, 0x12345678);
364    ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
365}
366
367TEST_F(BufferQueueTest, TestDisallowingAllocation) {
368    createBufferQueue();
369    sp<DummyConsumer> dc(new DummyConsumer);
370    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
371    IGraphicBufferProducer::QueueBufferOutput output;
372    ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
373            NATIVE_WINDOW_API_CPU, true, &output));
374
375    static const uint32_t WIDTH = 320;
376    static const uint32_t HEIGHT = 240;
377
378    ASSERT_EQ(OK, mConsumer->setDefaultBufferSize(WIDTH, HEIGHT));
379
380    int slot;
381    sp<Fence> fence;
382    sp<GraphicBuffer> buffer;
383    // This should return an error since it would require an allocation
384    ASSERT_EQ(OK, mProducer->allowAllocation(false));
385    ASSERT_EQ(WOULD_BLOCK, mProducer->dequeueBuffer(&slot, &fence, false, 0, 0,
386            0, GRALLOC_USAGE_SW_WRITE_OFTEN));
387
388    // This should succeed, now that we've lifted the prohibition
389    ASSERT_EQ(OK, mProducer->allowAllocation(true));
390    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
391            mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0,
392            GRALLOC_USAGE_SW_WRITE_OFTEN));
393
394    // Release the previous buffer back to the BufferQueue
395    mProducer->cancelBuffer(slot, fence);
396
397    // This should fail since we're requesting a different size
398    ASSERT_EQ(OK, mProducer->allowAllocation(false));
399    ASSERT_EQ(WOULD_BLOCK, mProducer->dequeueBuffer(&slot, &fence, false,
400            WIDTH * 2, HEIGHT * 2, 0, GRALLOC_USAGE_SW_WRITE_OFTEN));
401}
402
403} // namespace android
404