/*
 * Copyright 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "StreamSplitter_test"
//#define LOG_NDEBUG 0

#include <gui/BufferItem.h>
#include <gui/BufferQueue.h>
#include <gui/IConsumerListener.h>
#include <gui/ISurfaceComposer.h>
#include <gui/StreamSplitter.h>
#include <private/gui/ComposerService.h>

#include <system/window.h>

#include <gtest/gtest.h>

namespace android {

class StreamSplitterTest : public ::testing::Test {

protected:
    StreamSplitterTest() {
        const ::testing::TestInfo* const testInfo =
            ::testing::UnitTest::GetInstance()->current_test_info();
        ALOGV("Begin test: %s.%s", testInfo->test_case_name(),
                testInfo->name());
    }

    ~StreamSplitterTest() {
        const ::testing::TestInfo* const testInfo =
            ::testing::UnitTest::GetInstance()->current_test_info();
        ALOGV("End test:   %s.%s", testInfo->test_case_name(),
                testInfo->name());
    }
};

struct DummyListener : public BnConsumerListener {
    virtual void onFrameAvailable(const BufferItem& /* item */) {}
    virtual void onBuffersReleased() {}
    virtual void onSidebandStreamChanged() {}
};

static const uint32_t TEST_DATA = 0x12345678u;

TEST_F(StreamSplitterTest, OneInputOneOutput) {
    sp<IGraphicBufferProducer> inputProducer;
    sp<IGraphicBufferConsumer> inputConsumer;
    BufferQueue::createBufferQueue(&inputProducer, &inputConsumer);

    sp<IGraphicBufferProducer> outputProducer;
    sp<IGraphicBufferConsumer> outputConsumer;
    BufferQueue::createBufferQueue(&outputProducer, &outputConsumer);
    ASSERT_EQ(OK, outputConsumer->consumerConnect(new DummyListener, false));

    sp<StreamSplitter> splitter;
    status_t status = StreamSplitter::createSplitter(inputConsumer, &splitter);
    ASSERT_EQ(OK, status);
    ASSERT_EQ(OK, splitter->addOutput(outputProducer));

    // Never allow the output BufferQueue to allocate a buffer
    ASSERT_EQ(OK, outputProducer->allowAllocation(false));

    IGraphicBufferProducer::QueueBufferOutput qbOutput;
    ASSERT_EQ(OK, inputProducer->connect(new DummyProducerListener,
            NATIVE_WINDOW_API_CPU, false, &qbOutput));

    int slot;
    sp<Fence> fence;
    sp<GraphicBuffer> buffer;
    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
            inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
                    GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
    ASSERT_EQ(OK, inputProducer->requestBuffer(slot, &buffer));

    uint32_t* dataIn;
    ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
            reinterpret_cast<void**>(&dataIn)));
    *dataIn = TEST_DATA;
    ASSERT_EQ(OK, buffer->unlock());

    IGraphicBufferProducer::QueueBufferInput qbInput(0, false,
            HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
    ASSERT_EQ(OK, inputProducer->queueBuffer(slot, qbInput, &qbOutput));

    // Now that we have dequeued/allocated one buffer, prevent any further
    // allocations
    ASSERT_EQ(OK, inputProducer->allowAllocation(false));

    BufferItem item;
    ASSERT_EQ(OK, outputConsumer->acquireBuffer(&item, 0));

    uint32_t* dataOut;
    ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
            reinterpret_cast<void**>(&dataOut)));
    ASSERT_EQ(*dataOut, TEST_DATA);
    ASSERT_EQ(OK, item.mGraphicBuffer->unlock());

    ASSERT_EQ(OK, outputConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
            EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));

    // This should succeed even with allocation disabled since it will have
    // received the buffer back from the output BufferQueue
    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
            inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
                    GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
}

TEST_F(StreamSplitterTest, OneInputMultipleOutputs) {
    const int NUM_OUTPUTS = 4;

    sp<IGraphicBufferProducer> inputProducer;
    sp<IGraphicBufferConsumer> inputConsumer;
    BufferQueue::createBufferQueue(&inputProducer, &inputConsumer);

    sp<IGraphicBufferProducer> outputProducers[NUM_OUTPUTS] = {};
    sp<IGraphicBufferConsumer> outputConsumers[NUM_OUTPUTS] = {};
    for (int output = 0; output < NUM_OUTPUTS; ++output) {
        BufferQueue::createBufferQueue(&outputProducers[output],
                &outputConsumers[output]);
        ASSERT_EQ(OK, outputConsumers[output]->consumerConnect(
                    new DummyListener, false));
    }

    sp<StreamSplitter> splitter;
    status_t status = StreamSplitter::createSplitter(inputConsumer, &splitter);
    ASSERT_EQ(OK, status);
    for (int output = 0; output < NUM_OUTPUTS; ++output) {
        ASSERT_EQ(OK, splitter->addOutput(outputProducers[output]));

        // Never allow the output BufferQueues to allocate a buffer
        ASSERT_EQ(OK, outputProducers[output]->allowAllocation(false));
    }

    IGraphicBufferProducer::QueueBufferOutput qbOutput;
    ASSERT_EQ(OK, inputProducer->connect(new DummyProducerListener,
            NATIVE_WINDOW_API_CPU, false, &qbOutput));

    int slot;
    sp<Fence> fence;
    sp<GraphicBuffer> buffer;
    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
            inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
                    GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
    ASSERT_EQ(OK, inputProducer->requestBuffer(slot, &buffer));

    uint32_t* dataIn;
    ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
            reinterpret_cast<void**>(&dataIn)));
    *dataIn = TEST_DATA;
    ASSERT_EQ(OK, buffer->unlock());

    IGraphicBufferProducer::QueueBufferInput qbInput(0, false,
            HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
    ASSERT_EQ(OK, inputProducer->queueBuffer(slot, qbInput, &qbOutput));

    // Now that we have dequeued/allocated one buffer, prevent any further
    // allocations
    ASSERT_EQ(OK, inputProducer->allowAllocation(false));

    for (int output = 0; output < NUM_OUTPUTS; ++output) {
        BufferItem item;
        ASSERT_EQ(OK, outputConsumers[output]->acquireBuffer(&item, 0));

        uint32_t* dataOut;
        ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
                    reinterpret_cast<void**>(&dataOut)));
        ASSERT_EQ(*dataOut, TEST_DATA);
        ASSERT_EQ(OK, item.mGraphicBuffer->unlock());

        ASSERT_EQ(OK, outputConsumers[output]->releaseBuffer(item.mSlot,
                    item.mFrameNumber, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR,
                    Fence::NO_FENCE));
    }

    // This should succeed even with allocation disabled since it will have
    // received the buffer back from the output BufferQueues
    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
            inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
                    GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
}

TEST_F(StreamSplitterTest, OutputAbandonment) {
    sp<IGraphicBufferProducer> inputProducer;
    sp<IGraphicBufferConsumer> inputConsumer;
    BufferQueue::createBufferQueue(&inputProducer, &inputConsumer);

    sp<IGraphicBufferProducer> outputProducer;
    sp<IGraphicBufferConsumer> outputConsumer;
    BufferQueue::createBufferQueue(&outputProducer, &outputConsumer);
    ASSERT_EQ(OK, outputConsumer->consumerConnect(new DummyListener, false));

    sp<StreamSplitter> splitter;
    status_t status = StreamSplitter::createSplitter(inputConsumer, &splitter);
    ASSERT_EQ(OK, status);
    ASSERT_EQ(OK, splitter->addOutput(outputProducer));

    IGraphicBufferProducer::QueueBufferOutput qbOutput;
    ASSERT_EQ(OK, inputProducer->connect(new DummyProducerListener,
            NATIVE_WINDOW_API_CPU, false, &qbOutput));

    int slot;
    sp<Fence> fence;
    sp<GraphicBuffer> buffer;
    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
            inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
                    GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
    ASSERT_EQ(OK, inputProducer->requestBuffer(slot, &buffer));

    // Abandon the output
    outputConsumer->consumerDisconnect();

    IGraphicBufferProducer::QueueBufferInput qbInput(0, false,
            HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
    ASSERT_EQ(OK, inputProducer->queueBuffer(slot, qbInput, &qbOutput));

    // Input should be abandoned
    ASSERT_EQ(NO_INIT, inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
            GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
}

} // namespace android
