• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2014 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 "StreamSplitter_test"
18 //#define LOG_NDEBUG 0
19 
20 #include <gui/BufferItem.h>
21 #include <gui/BufferQueue.h>
22 #include <gui/IConsumerListener.h>
23 #include <gui/ISurfaceComposer.h>
24 #include <gui/StreamSplitter.h>
25 #include <private/gui/ComposerService.h>
26 
27 #include <gtest/gtest.h>
28 
29 namespace android {
30 
31 class StreamSplitterTest : public ::testing::Test {
32 
33 protected:
StreamSplitterTest()34     StreamSplitterTest() {
35         const ::testing::TestInfo* const testInfo =
36             ::testing::UnitTest::GetInstance()->current_test_info();
37         ALOGV("Begin test: %s.%s", testInfo->test_case_name(),
38                 testInfo->name());
39     }
40 
~StreamSplitterTest()41     ~StreamSplitterTest() {
42         const ::testing::TestInfo* const testInfo =
43             ::testing::UnitTest::GetInstance()->current_test_info();
44         ALOGV("End test:   %s.%s", testInfo->test_case_name(),
45                 testInfo->name());
46     }
47 };
48 
49 struct DummyListener : public BnConsumerListener {
onFrameAvailableandroid::DummyListener50     virtual void onFrameAvailable(const BufferItem& /* item */) {}
onBuffersReleasedandroid::DummyListener51     virtual void onBuffersReleased() {}
onSidebandStreamChangedandroid::DummyListener52     virtual void onSidebandStreamChanged() {}
53 };
54 
55 static const uint32_t TEST_DATA = 0x12345678u;
56 
TEST_F(StreamSplitterTest,OneInputOneOutput)57 TEST_F(StreamSplitterTest, OneInputOneOutput) {
58     sp<IGraphicBufferProducer> inputProducer;
59     sp<IGraphicBufferConsumer> inputConsumer;
60     BufferQueue::createBufferQueue(&inputProducer, &inputConsumer);
61 
62     sp<IGraphicBufferProducer> outputProducer;
63     sp<IGraphicBufferConsumer> outputConsumer;
64     BufferQueue::createBufferQueue(&outputProducer, &outputConsumer);
65     ASSERT_EQ(OK, outputConsumer->consumerConnect(new DummyListener, false));
66 
67     sp<StreamSplitter> splitter;
68     status_t status = StreamSplitter::createSplitter(inputConsumer, &splitter);
69     ASSERT_EQ(OK, status);
70     ASSERT_EQ(OK, splitter->addOutput(outputProducer));
71 
72     // Never allow the output BufferQueue to allocate a buffer
73     ASSERT_EQ(OK, outputProducer->allowAllocation(false));
74 
75     IGraphicBufferProducer::QueueBufferOutput qbOutput;
76     ASSERT_EQ(OK, inputProducer->connect(new DummyProducerListener,
77             NATIVE_WINDOW_API_CPU, false, &qbOutput));
78 
79     int slot;
80     sp<Fence> fence;
81     sp<GraphicBuffer> buffer;
82     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
83             inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
84                     GRALLOC_USAGE_SW_WRITE_OFTEN));
85     ASSERT_EQ(OK, inputProducer->requestBuffer(slot, &buffer));
86 
87     uint32_t* dataIn;
88     ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
89             reinterpret_cast<void**>(&dataIn)));
90     *dataIn = TEST_DATA;
91     ASSERT_EQ(OK, buffer->unlock());
92 
93     IGraphicBufferProducer::QueueBufferInput qbInput(0, false,
94             HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
95             NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
96     ASSERT_EQ(OK, inputProducer->queueBuffer(slot, qbInput, &qbOutput));
97 
98     // Now that we have dequeued/allocated one buffer, prevent any further
99     // allocations
100     ASSERT_EQ(OK, inputProducer->allowAllocation(false));
101 
102     BufferItem item;
103     ASSERT_EQ(OK, outputConsumer->acquireBuffer(&item, 0));
104 
105     uint32_t* dataOut;
106     ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
107             reinterpret_cast<void**>(&dataOut)));
108     ASSERT_EQ(*dataOut, TEST_DATA);
109     ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
110 
111     ASSERT_EQ(OK, outputConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
112             EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
113 
114     // This should succeed even with allocation disabled since it will have
115     // received the buffer back from the output BufferQueue
116     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
117             inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
118                     GRALLOC_USAGE_SW_WRITE_OFTEN));
119 }
120 
TEST_F(StreamSplitterTest,OneInputMultipleOutputs)121 TEST_F(StreamSplitterTest, OneInputMultipleOutputs) {
122     const int NUM_OUTPUTS = 4;
123 
124     sp<IGraphicBufferProducer> inputProducer;
125     sp<IGraphicBufferConsumer> inputConsumer;
126     BufferQueue::createBufferQueue(&inputProducer, &inputConsumer);
127 
128     sp<IGraphicBufferProducer> outputProducers[NUM_OUTPUTS] = {};
129     sp<IGraphicBufferConsumer> outputConsumers[NUM_OUTPUTS] = {};
130     for (int output = 0; output < NUM_OUTPUTS; ++output) {
131         BufferQueue::createBufferQueue(&outputProducers[output],
132                 &outputConsumers[output]);
133         ASSERT_EQ(OK, outputConsumers[output]->consumerConnect(
134                     new DummyListener, false));
135     }
136 
137     sp<StreamSplitter> splitter;
138     status_t status = StreamSplitter::createSplitter(inputConsumer, &splitter);
139     ASSERT_EQ(OK, status);
140     for (int output = 0; output < NUM_OUTPUTS; ++output) {
141         ASSERT_EQ(OK, splitter->addOutput(outputProducers[output]));
142 
143         // Never allow the output BufferQueues to allocate a buffer
144         ASSERT_EQ(OK, outputProducers[output]->allowAllocation(false));
145     }
146 
147     IGraphicBufferProducer::QueueBufferOutput qbOutput;
148     ASSERT_EQ(OK, inputProducer->connect(new DummyProducerListener,
149             NATIVE_WINDOW_API_CPU, false, &qbOutput));
150 
151     int slot;
152     sp<Fence> fence;
153     sp<GraphicBuffer> buffer;
154     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
155             inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
156                     GRALLOC_USAGE_SW_WRITE_OFTEN));
157     ASSERT_EQ(OK, inputProducer->requestBuffer(slot, &buffer));
158 
159     uint32_t* dataIn;
160     ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
161             reinterpret_cast<void**>(&dataIn)));
162     *dataIn = TEST_DATA;
163     ASSERT_EQ(OK, buffer->unlock());
164 
165     IGraphicBufferProducer::QueueBufferInput qbInput(0, false,
166             HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
167             NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
168     ASSERT_EQ(OK, inputProducer->queueBuffer(slot, qbInput, &qbOutput));
169 
170     // Now that we have dequeued/allocated one buffer, prevent any further
171     // allocations
172     ASSERT_EQ(OK, inputProducer->allowAllocation(false));
173 
174     for (int output = 0; output < NUM_OUTPUTS; ++output) {
175         BufferItem item;
176         ASSERT_EQ(OK, outputConsumers[output]->acquireBuffer(&item, 0));
177 
178         uint32_t* dataOut;
179         ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
180                     reinterpret_cast<void**>(&dataOut)));
181         ASSERT_EQ(*dataOut, TEST_DATA);
182         ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
183 
184         ASSERT_EQ(OK, outputConsumers[output]->releaseBuffer(item.mSlot,
185                     item.mFrameNumber, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR,
186                     Fence::NO_FENCE));
187     }
188 
189     // This should succeed even with allocation disabled since it will have
190     // received the buffer back from the output BufferQueues
191     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
192             inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
193                     GRALLOC_USAGE_SW_WRITE_OFTEN));
194 }
195 
TEST_F(StreamSplitterTest,OutputAbandonment)196 TEST_F(StreamSplitterTest, OutputAbandonment) {
197     sp<IGraphicBufferProducer> inputProducer;
198     sp<IGraphicBufferConsumer> inputConsumer;
199     BufferQueue::createBufferQueue(&inputProducer, &inputConsumer);
200 
201     sp<IGraphicBufferProducer> outputProducer;
202     sp<IGraphicBufferConsumer> outputConsumer;
203     BufferQueue::createBufferQueue(&outputProducer, &outputConsumer);
204     ASSERT_EQ(OK, outputConsumer->consumerConnect(new DummyListener, false));
205 
206     sp<StreamSplitter> splitter;
207     status_t status = StreamSplitter::createSplitter(inputConsumer, &splitter);
208     ASSERT_EQ(OK, status);
209     ASSERT_EQ(OK, splitter->addOutput(outputProducer));
210 
211     IGraphicBufferProducer::QueueBufferOutput qbOutput;
212     ASSERT_EQ(OK, inputProducer->connect(new DummyProducerListener,
213             NATIVE_WINDOW_API_CPU, false, &qbOutput));
214 
215     int slot;
216     sp<Fence> fence;
217     sp<GraphicBuffer> buffer;
218     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
219             inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
220                     GRALLOC_USAGE_SW_WRITE_OFTEN));
221     ASSERT_EQ(OK, inputProducer->requestBuffer(slot, &buffer));
222 
223     // Abandon the output
224     outputConsumer->consumerDisconnect();
225 
226     IGraphicBufferProducer::QueueBufferInput qbInput(0, false,
227             HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
228             NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
229     ASSERT_EQ(OK, inputProducer->queueBuffer(slot, qbInput, &qbOutput));
230 
231     // Input should be abandoned
232     ASSERT_EQ(NO_INIT, inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
233             GRALLOC_USAGE_SW_WRITE_OFTEN));
234 }
235 
236 } // namespace android
237