Home | History | Annotate | Download | only in tests
      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:
     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 
     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 {
     50     virtual void onFrameAvailable(const BufferItem& /* item */) {}
     51     virtual void onBuffersReleased() {}
     52     virtual void onSidebandStreamChanged() {}
     53 };
     54 
     55 static const uint32_t TEST_DATA = 0x12345678u;
     56 
     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 
    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 
    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