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