/*
 * Copyright (C) 2018 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.
 */

#undef LOG_TAG
#define LOG_TAG "LibSurfaceFlingerUnittests"

#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include <log/log.h>
#include "system/window.h"

#include "MockComposer.h"
#include "MockDisplaySurface.h"
#include "MockEventControlThread.h"
#include "MockEventThread.h"
#include "MockGraphicBufferConsumer.h"
#include "MockGraphicBufferProducer.h"
#include "MockMessageQueue.h"
#include "MockNativeWindow.h"
#include "MockNativeWindowSurface.h"
#include "MockRenderEngine.h"
#include "MockSurfaceInterceptor.h"
#include "TestableSurfaceFlinger.h"

namespace android {
namespace {

using testing::_;
using testing::ByMove;
using testing::DoAll;
using testing::Mock;
using testing::Return;
using testing::SetArgPointee;

using android::hardware::graphics::common::V1_0::ColorMode;
using android::hardware::graphics::common::V1_0::Hdr;
using android::Hwc2::Error;
using android::Hwc2::IComposer;
using android::Hwc2::IComposerClient;

using HWC2Display = TestableSurfaceFlinger::HWC2Display;
using HotplugEvent = TestableSurfaceFlinger::HotplugEvent;

constexpr int32_t DEFAULT_REFRESH_RATE = 1666666666;
constexpr int32_t DEFAULT_DPI = 320;

constexpr int DEFAULT_CONFIG_ID = 0;

class DisplayTransactionTest : public testing::Test {
protected:
    DisplayTransactionTest();
    ~DisplayTransactionTest() override;

    // --------------------------------------------------------------------
    // Precondition helpers

    void setupComposer(int virtualDisplayCount);
    void setupFakeHwcDisplay(hwc2_display_t displayId, DisplayDevice::DisplayType type, int width,
                             int height);

    struct FakeDisplayDeviceFactory {
    public:
        FakeDisplayDeviceFactory(TestableSurfaceFlinger& flinger, sp<BBinder>& displayToken,
                                 DisplayDevice::DisplayType type, int hwcId)
              : mFlinger(flinger), mDisplayToken(displayToken), mType(type), mHwcId(hwcId) {}

        sp<DisplayDevice> build() {
            return new DisplayDevice(mFlinger.mFlinger.get(), mType, mHwcId, false, mDisplayToken,
                                     mNativeWindow, mDisplaySurface, std::move(mRenderSurface), 0,
                                     0, false, false, HWC_POWER_MODE_NORMAL);
        }

        FakeDisplayDeviceFactory& setNativeWindow(const sp<ANativeWindow>& nativeWindow) {
            mNativeWindow = nativeWindow;
            return *this;
        }

        FakeDisplayDeviceFactory& setDisplaySurface(const sp<DisplaySurface>& displaySurface) {
            mDisplaySurface = displaySurface;
            return *this;
        }

        FakeDisplayDeviceFactory& setRenderSurface(std::unique_ptr<RE::Surface> renderSurface) {
            mRenderSurface = std::move(renderSurface);
            return *this;
        }

        TestableSurfaceFlinger& mFlinger;
        sp<BBinder>& mDisplayToken;
        DisplayDevice::DisplayType mType;
        int mHwcId;
        sp<ANativeWindow> mNativeWindow;
        sp<DisplaySurface> mDisplaySurface;
        std::unique_ptr<RE::Surface> mRenderSurface;
    };

    sp<BBinder> setupFakeExistingPhysicalDisplay(hwc2_display_t displayId,
                                                 DisplayDevice::DisplayType type);

    void setupFakeBufferQueueFactory();
    void setupFakeNativeWindowSurfaceFactory(int displayWidth, int displayHeight, bool critical,
                                             bool async);
    void expectFramebufferUsageSet(int width, int height, int grallocUsage);
    void expectHwcHotplugCalls(hwc2_display_t displayId, int displayWidth, int displayHeight);

    // --------------------------------------------------------------------
    // Call expectation helpers

    void expectRESurfaceCreationCalls();
    void expectPhysicalDisplayDeviceCreationCalls(hwc2_display_t displayId, int displayWidth,
                                                  int displayHeight, bool critical, bool async);

    // --------------------------------------------------------------------
    // Postcondition helpers

    bool hasTransactionFlagSet(int flag);
    bool hasDisplayDevice(sp<IBinder> displayToken);
    sp<DisplayDevice> getDisplayDevice(sp<IBinder> displayToken);
    bool hasCurrentDisplayState(sp<IBinder> displayToken);
    const DisplayDeviceState& getCurrentDisplayState(sp<IBinder> displayToken);
    bool hasDrawingDisplayState(sp<IBinder> displayToken);
    const DisplayDeviceState& getDrawingDisplayState(sp<IBinder> displayToken);

    // --------------------------------------------------------------------
    // Test instances

    std::unordered_set<HWC2::Capability> mCapabilities;

    TestableSurfaceFlinger mFlinger;
    mock::EventThread* mEventThread = new mock::EventThread();
    mock::EventControlThread* mEventControlThread = new mock::EventControlThread();

    // These mocks are created by the test, but are destroyed by SurfaceFlinger
    // by virtue of being stored into a std::unique_ptr. However we still need
    // to keep a reference to them for use in setting up call expectations.
    RE::mock::RenderEngine* mRenderEngine = new RE::mock::RenderEngine();
    Hwc2::mock::Composer* mComposer = new Hwc2::mock::Composer();
    mock::MessageQueue* mMessageQueue = new mock::MessageQueue();
    mock::SurfaceInterceptor* mSurfaceInterceptor = new mock::SurfaceInterceptor();

    // These mocks are created only when expected to be created via a factory.
    sp<mock::GraphicBufferConsumer> mConsumer;
    sp<mock::GraphicBufferProducer> mProducer;
    mock::NativeWindowSurface* mNativeWindowSurface = nullptr;
    sp<mock::NativeWindow> mNativeWindow;
    RE::mock::Surface* mRenderSurface = nullptr;
    std::vector<std::unique_ptr<HWC2Display>> mFakeHwcDisplays;
};

DisplayTransactionTest::DisplayTransactionTest() {
    const ::testing::TestInfo* const test_info =
            ::testing::UnitTest::GetInstance()->current_test_info();
    ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());

    mFlinger.setCreateBufferQueueFunction([](auto, auto, auto) {
        ADD_FAILURE() << "Unexpected request to create a buffer queue.";
    });

    mFlinger.setCreateNativeWindowSurface([](auto) {
        ADD_FAILURE() << "Unexpected request to create a native window surface.";
        return nullptr;
    });

    mFlinger.mutableEventControlThread().reset(mEventControlThread);
    mFlinger.mutableEventThread().reset(mEventThread);
    mFlinger.mutableEventQueue().reset(mMessageQueue);
    mFlinger.setupRenderEngine(std::unique_ptr<RE::RenderEngine>(mRenderEngine));
    mFlinger.mutableInterceptor().reset(mSurfaceInterceptor);

    setupComposer(0);
}

DisplayTransactionTest::~DisplayTransactionTest() {
    const ::testing::TestInfo* const test_info =
            ::testing::UnitTest::GetInstance()->current_test_info();
    ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
}

void DisplayTransactionTest::setupComposer(int virtualDisplayCount) {
    EXPECT_CALL(*mComposer, getCapabilities())
            .WillOnce(Return(std::vector<IComposer::Capability>()));
    EXPECT_CALL(*mComposer, getMaxVirtualDisplayCount()).WillOnce(Return(virtualDisplayCount));
    mFlinger.setupComposer(std::unique_ptr<Hwc2::Composer>(mComposer));

    Mock::VerifyAndClear(mComposer);
}

void DisplayTransactionTest::setupFakeHwcDisplay(hwc2_display_t displayId,
                                                 DisplayDevice::DisplayType type, int width,
                                                 int height) {
    auto display = std::make_unique<HWC2Display>(*mComposer, mCapabilities, displayId,
                                                 HWC2::DisplayType::Physical);
    display->mutableIsConnected() = true;
    display->mutableConfigs().emplace(DEFAULT_CONFIG_ID,
                                      HWC2::Display::Config::Builder(*display, DEFAULT_CONFIG_ID)
                                              .setWidth(width)
                                              .setHeight(height)
                                              .setVsyncPeriod(DEFAULT_REFRESH_RATE)
                                              .setDpiX(DEFAULT_DPI)
                                              .setDpiY(DEFAULT_DPI)
                                              .build());

    mFlinger.mutableHwcDisplayData()[type].reset();
    mFlinger.mutableHwcDisplayData()[type].hwcDisplay = display.get();
    mFlinger.mutableHwcDisplaySlots().emplace(displayId, type);

    mFakeHwcDisplays.push_back(std::move(display));
}

sp<BBinder> DisplayTransactionTest::setupFakeExistingPhysicalDisplay(
        hwc2_display_t displayId, DisplayDevice::DisplayType type) {
    setupFakeHwcDisplay(displayId, type, 0, 0);

    sp<BBinder> displayToken = new BBinder();
    mFlinger.mutableBuiltinDisplays()[type] = displayToken;
    mFlinger.mutableDisplays()
            .add(displayToken,
                 FakeDisplayDeviceFactory(mFlinger, displayToken, type, type).build());

    DisplayDeviceState state(type, true);
    mFlinger.mutableCurrentState().displays.add(displayToken, state);
    mFlinger.mutableDrawingState().displays.add(displayToken, state);

    return displayToken;
}

void DisplayTransactionTest::setupFakeBufferQueueFactory() {
    // This setup is only expected once per test.
    ASSERT_TRUE(mConsumer == nullptr && mProducer == nullptr);

    mConsumer = new mock::GraphicBufferConsumer();
    mProducer = new mock::GraphicBufferProducer();

    mFlinger.setCreateBufferQueueFunction([this](auto outProducer, auto outConsumer, bool) {
        *outProducer = mProducer;
        *outConsumer = mConsumer;
    });
}

void DisplayTransactionTest::setupFakeNativeWindowSurfaceFactory(int displayWidth,
                                                                 int displayHeight, bool critical,
                                                                 bool async) {
    // This setup is only expected once per test.
    ASSERT_TRUE(mNativeWindowSurface == nullptr);

    mNativeWindowSurface = new mock::NativeWindowSurface();
    mNativeWindow = new mock::NativeWindow();

    mFlinger.setCreateNativeWindowSurface(
            [this](auto) { return std::unique_ptr<NativeWindowSurface>(mNativeWindowSurface); });

    EXPECT_CALL(*mNativeWindowSurface, getNativeWindow()).WillOnce(Return(mNativeWindow));

    EXPECT_CALL(*mNativeWindow, perform(19)).Times(1);

    EXPECT_CALL(*mRenderSurface, setAsync(async)).Times(1);
    EXPECT_CALL(*mRenderSurface, setCritical(critical)).Times(1);
    EXPECT_CALL(*mRenderSurface, setNativeWindow(mNativeWindow.get())).Times(1);
    EXPECT_CALL(*mRenderSurface, queryWidth()).WillOnce(Return(displayWidth));
    EXPECT_CALL(*mRenderSurface, queryHeight()).WillOnce(Return(displayHeight));
}

void DisplayTransactionTest::expectFramebufferUsageSet(int width, int height, int grallocUsage) {
    EXPECT_CALL(*mConsumer, consumerConnect(_, false)).WillOnce(Return(NO_ERROR));
    EXPECT_CALL(*mConsumer, setConsumerName(_)).WillRepeatedly(Return(NO_ERROR));
    EXPECT_CALL(*mConsumer, setConsumerUsageBits(grallocUsage)).WillRepeatedly(Return(NO_ERROR));
    EXPECT_CALL(*mConsumer, setDefaultBufferSize(width, height)).WillRepeatedly(Return(NO_ERROR));
    EXPECT_CALL(*mConsumer, setMaxAcquiredBufferCount(_)).WillRepeatedly(Return(NO_ERROR));

    EXPECT_CALL(*mProducer, allocateBuffers(0, 0, 0, 0)).WillRepeatedly(Return());
}

void DisplayTransactionTest::expectHwcHotplugCalls(hwc2_display_t displayId, int displayWidth,
                                                   int displayHeight) {
    EXPECT_CALL(*mComposer, getDisplayType(displayId, _))
            .WillOnce(DoAll(SetArgPointee<1>(IComposerClient::DisplayType::PHYSICAL),
                            Return(Error::NONE)));
    EXPECT_CALL(*mComposer, setClientTargetSlotCount(_)).WillOnce(Return(Error::NONE));
    EXPECT_CALL(*mComposer, getDisplayConfigs(_, _))
            .WillOnce(DoAll(SetArgPointee<1>(std::vector<unsigned>{0}), Return(Error::NONE)));
    EXPECT_CALL(*mComposer, getDisplayAttribute(displayId, 0, IComposerClient::Attribute::WIDTH, _))
            .WillOnce(DoAll(SetArgPointee<3>(displayWidth), Return(Error::NONE)));
    EXPECT_CALL(*mComposer,
                getDisplayAttribute(displayId, 0, IComposerClient::Attribute::HEIGHT, _))
            .WillOnce(DoAll(SetArgPointee<3>(displayHeight), Return(Error::NONE)));
    EXPECT_CALL(*mComposer,
                getDisplayAttribute(displayId, 0, IComposerClient::Attribute::VSYNC_PERIOD, _))
            .WillOnce(DoAll(SetArgPointee<3>(DEFAULT_REFRESH_RATE), Return(Error::NONE)));
    EXPECT_CALL(*mComposer, getDisplayAttribute(displayId, 0, IComposerClient::Attribute::DPI_X, _))
            .WillOnce(DoAll(SetArgPointee<3>(DEFAULT_DPI), Return(Error::NONE)));
    EXPECT_CALL(*mComposer, getDisplayAttribute(displayId, 0, IComposerClient::Attribute::DPI_Y, _))
            .WillOnce(DoAll(SetArgPointee<3>(DEFAULT_DPI), Return(Error::NONE)));
}

void DisplayTransactionTest::expectRESurfaceCreationCalls() {
    // This setup is only expected once per test.
    ASSERT_TRUE(mRenderSurface == nullptr);

    mRenderSurface = new RE::mock::Surface();
    EXPECT_CALL(*mRenderEngine, createSurface())
            .WillOnce(Return(ByMove(std::unique_ptr<RE::Surface>(mRenderSurface))));
}

void DisplayTransactionTest::expectPhysicalDisplayDeviceCreationCalls(hwc2_display_t displayId,
                                                                      int displayWidth,
                                                                      int displayHeight,
                                                                      bool critical, bool async) {
    EXPECT_CALL(*mComposer, getActiveConfig(displayId, _))
            .WillOnce(DoAll(SetArgPointee<1>(DEFAULT_CONFIG_ID), Return(Error::NONE)));
    EXPECT_CALL(*mComposer, getColorModes(displayId, _)).Times(0);
    EXPECT_CALL(*mComposer, getHdrCapabilities(displayId, _, _, _, _))
            .WillOnce(DoAll(SetArgPointee<1>(std::vector<Hdr>()), Return(Error::NONE)));

    setupFakeBufferQueueFactory();
    expectFramebufferUsageSet(displayWidth, displayHeight,
                              GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER |
                                      GRALLOC_USAGE_HW_FB);

    setupFakeNativeWindowSurfaceFactory(displayWidth, displayHeight, critical, async);
}

bool DisplayTransactionTest::hasTransactionFlagSet(int flag) {
    return mFlinger.mutableTransactionFlags() & flag;
}

bool DisplayTransactionTest::hasDisplayDevice(sp<IBinder> displayToken) {
    return mFlinger.mutableDisplays().indexOfKey(displayToken) >= 0;
}

sp<DisplayDevice> DisplayTransactionTest::getDisplayDevice(sp<IBinder> displayToken) {
    return mFlinger.mutableDisplays().valueFor(displayToken);
}

bool DisplayTransactionTest::hasCurrentDisplayState(sp<IBinder> displayToken) {
    return mFlinger.mutableCurrentState().displays.indexOfKey(displayToken) >= 0;
}

const DisplayDeviceState& DisplayTransactionTest::getCurrentDisplayState(sp<IBinder> displayToken) {
    return mFlinger.mutableCurrentState().displays.valueFor(displayToken);
}

bool DisplayTransactionTest::hasDrawingDisplayState(sp<IBinder> displayToken) {
    return mFlinger.mutableDrawingState().displays.indexOfKey(displayToken) >= 0;
}

const DisplayDeviceState& DisplayTransactionTest::getDrawingDisplayState(sp<IBinder> displayToken) {
    return mFlinger.mutableDrawingState().displays.valueFor(displayToken);
}

/* ------------------------------------------------------------------------
 * SurfaceFlinger::handleTransactionLocked(eDisplayTransactionNeeded)
 */

TEST_F(DisplayTransactionTest, handleTransactionLockedProcessesHotplugConnectPrimary) {
    constexpr hwc2_display_t externalDisplayId = 102;
    constexpr hwc2_display_t displayId = 123;
    constexpr int displayWidth = 1920;
    constexpr int displayHeight = 1080;

    // --------------------------------------------------------------------
    // Preconditions

    // An external display may already be set up
    setupFakeHwcDisplay(externalDisplayId, DisplayDevice::DISPLAY_EXTERNAL, 3840, 2160);

    // A hotplug connect comes in for a new display
    mFlinger.mutablePendingHotplugEvents().emplace_back(
            HotplugEvent{displayId, HWC2::Connection::Connected});

    // --------------------------------------------------------------------
    // Call Expectations

    EXPECT_CALL(*mComposer, isUsingVrComposer()).WillOnce(Return(false));
    expectHwcHotplugCalls(displayId, displayWidth, displayHeight);
    expectRESurfaceCreationCalls();
    expectPhysicalDisplayDeviceCreationCalls(displayId, displayWidth, displayHeight, true, false);

    EXPECT_CALL(*mSurfaceInterceptor, saveDisplayCreation(_)).Times(1);

    EXPECT_CALL(*mEventThread, onHotplugReceived(DisplayDevice::DISPLAY_PRIMARY, true)).Times(1);

    // --------------------------------------------------------------------
    // Invocation

    mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);

    // --------------------------------------------------------------------
    // Postconditions

    // HWComposer should have an entry for the display
    EXPECT_TRUE(mFlinger.mutableHwcDisplaySlots().count(displayId) == 1);

    // The display should have set up as a primary built-in display.
    auto displayToken = mFlinger.mutableBuiltinDisplays()[DisplayDevice::DISPLAY_PRIMARY];
    ASSERT_TRUE(displayToken != nullptr);

    // The display device should have been set up in the list of displays.
    ASSERT_TRUE(hasDisplayDevice(displayToken));
    const auto& device = getDisplayDevice(displayToken);
    EXPECT_TRUE(device->isSecure());
    EXPECT_TRUE(device->isPrimary());

    // The display should have been set up in the current display state
    ASSERT_TRUE(hasCurrentDisplayState(displayToken));
    const auto& current = getCurrentDisplayState(displayToken);
    EXPECT_EQ(DisplayDevice::DISPLAY_PRIMARY, current.type);

    // The display should have been set up in the drawing display state
    ASSERT_TRUE(hasDrawingDisplayState(displayToken));
    const auto& draw = getDrawingDisplayState(displayToken);
    EXPECT_EQ(DisplayDevice::DISPLAY_PRIMARY, draw.type);

    // --------------------------------------------------------------------
    // Cleanup conditions

    EXPECT_CALL(*mComposer, setVsyncEnabled(displayId, IComposerClient::Vsync::DISABLE))
            .WillOnce(Return(Error::NONE));
    EXPECT_CALL(*mConsumer, consumerDisconnect()).WillOnce(Return(NO_ERROR));
}

} // namespace
} // namespace android
