/*
 * Copyright 2024 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 ATRACE_TAG ATRACE_TAG_GRAPHICS

#include "Display/DisplayModeController.h"
#include "Display/DisplaySnapshot.h"
#include "DisplayHardware/HWComposer.h"

#include <android-base/properties.h>
#include <common/FlagManager.h>
#include <common/trace.h>
#include <ftl/concat.h>
#include <ftl/expected.h>
#include <ftl/fake_guard.h>
#include <log/log.h>
#include <utils/Errors.h>
#include <utils/Timers.h>

namespace android::display {

template <size_t N>
inline std::string DisplayModeController::Display::concatId(const char (&str)[N]) const {
    return std::string(ftl::Concat(str, ' ', snapshot.get().displayId().value).str());
}

DisplayModeController::Display::Display(DisplaySnapshotRef snapshot,
                                        RefreshRateSelectorPtr selectorPtr)
      : snapshot(snapshot),
        selectorPtr(std::move(selectorPtr)),
        pendingModeFpsTrace(concatId("PendingModeFps")),
        activeModeFpsTrace(concatId("ActiveModeFps")),
        renderRateFpsTrace(concatId("RenderRateFps")),
        hasDesiredModeTrace(concatId("HasDesiredMode"), false) {}

void DisplayModeController::registerDisplay(PhysicalDisplayId displayId,
                                            DisplaySnapshotRef snapshotRef,
                                            RefreshRateSelectorPtr selectorPtr) {
    DisplayPtr displayPtr = std::make_unique<Display>(snapshotRef, selectorPtr);

    displayPtr->setSecure(snapshotRef.get().connectionType() ==
                            ui::DisplayConnectionType::Internal);
    std::lock_guard lock(mDisplayLock);
    mDisplays.emplace_or_replace(displayId, std::move(displayPtr));
}

void DisplayModeController::registerDisplay(DisplaySnapshotRef snapshotRef,
                                            DisplayModeId activeModeId,
                                            scheduler::RefreshRateSelector::Config config) {
    const auto& snapshot = snapshotRef.get();
    const auto displayId = snapshot.displayId();
    DisplayPtr displayPtr =
            std::make_unique<Display>(snapshotRef, snapshot.displayModes(), activeModeId, config);

    displayPtr->setSecure(snapshotRef.get().connectionType() ==
                            ui::DisplayConnectionType::Internal);
    std::lock_guard lock(mDisplayLock);
    mDisplays.emplace_or_replace(displayId, std::move(displayPtr));
}

void DisplayModeController::unregisterDisplay(PhysicalDisplayId displayId) {
    std::lock_guard lock(mDisplayLock);
    const bool ok = mDisplays.erase(displayId);
    ALOGE_IF(!ok, "%s: Unknown display %s", __func__, to_string(displayId).c_str());
}

auto DisplayModeController::selectorPtrFor(PhysicalDisplayId displayId) const
        -> RefreshRateSelectorPtr {
    std::lock_guard lock(mDisplayLock);
    return mDisplays.get(displayId)
            .transform([](const DisplayPtr& displayPtr) { return displayPtr->selectorPtr; })
            .value_or(nullptr);
}

auto DisplayModeController::setDesiredMode(PhysicalDisplayId displayId,
                                           DisplayModeRequest&& desiredMode) -> DesiredModeAction {
    std::lock_guard lock(mDisplayLock);
    const auto& displayPtr =
            FTL_EXPECT(mDisplays.get(displayId).ok_or(DesiredModeAction::None)).get();

    {
        SFTRACE_NAME(displayPtr->concatId(__func__).c_str());
        ALOGD("%s %s", displayPtr->concatId(__func__).c_str(), to_string(desiredMode).c_str());

        std::scoped_lock lock(displayPtr->desiredModeLock);

        if (auto& desiredModeOpt = displayPtr->desiredModeOpt) {
            if (!FlagManager::getInstance().modeset_state_machine() ||
                desiredMode.mode.matchesResolution(desiredModeOpt->mode)) {
                // A mode transition was already scheduled, so just override the desired mode.
                const bool emitEvent = desiredModeOpt->emitEvent;
                const bool force = desiredModeOpt->force;
                desiredModeOpt = std::move(desiredMode);
                desiredModeOpt->emitEvent |= emitEvent;
                desiredModeOpt->force |= force;
                return DesiredModeAction::MergeDisplayModeSwitch;
            }
        }

        // If the desired mode is already active...
        const auto activeMode = displayPtr->selectorPtr->getActiveMode();
        if (const auto& desiredModePtr = desiredMode.mode.modePtr;
            !desiredMode.force && activeMode.modePtr->getId() == desiredModePtr->getId()) {
            ftl::FakeGuard guard(kMainThreadContext);

            // ...and there is no pending resolution change...
            if (!FlagManager::getInstance().modeset_state_machine() ||
                (!displayPtr->pendingModeOpt && desiredMode.mode.matchesResolution(activeMode))) {
                if (activeMode == desiredMode.mode) {
                    return DesiredModeAction::None;
                }

                // ...but the render rate changed:
                setActiveModeLocked(displayId, desiredModePtr->getId(),
                                    desiredModePtr->getVsyncRate(), desiredMode.mode.fps);
                return DesiredModeAction::InitiateRenderRateSwitch;
            }
        }

        // Restore peak render rate to schedule the next frame as soon as possible.
        setActiveModeLocked(displayId, activeMode.modePtr->getId(),
                            activeMode.modePtr->getVsyncRate(), activeMode.modePtr->getPeakFps());

        // Initiate a mode change.
        displayPtr->desiredModeOpt = std::move(desiredMode);
        displayPtr->hasDesiredModeTrace = true;
    }

    return DesiredModeAction::InitiateDisplayModeSwitch;
}

auto DisplayModeController::getDesiredMode(PhysicalDisplayId displayId) const
        -> DisplayModeRequestOpt {
    std::lock_guard lock(mDisplayLock);
    const auto& displayPtr =
            FTL_EXPECT(mDisplays.get(displayId).ok_or(DisplayModeRequestOpt())).get();

    {
        std::scoped_lock lock(displayPtr->desiredModeLock);
        return displayPtr->desiredModeOpt;
    }
}

auto DisplayModeController::getDisplayIdForRequest(sp<IBinder> displaySynchronizationToken) const
        -> std::vector<PhysicalDisplayId> {
    std::lock_guard lock(mDisplayLock);
    std::vector<PhysicalDisplayId> result;
    for (const auto& [displayId, displayPtr] : mDisplays) {
        std::scoped_lock lock(displayPtr->desiredModeLock);
        if (displayPtr->desiredModeOpt &&
            displayPtr->desiredModeOpt->displaySynchronizationToken ==
                    displaySynchronizationToken) {
            result.push_back(displayId);
        }
    }

    return result;
}

auto DisplayModeController::getPendingMode(PhysicalDisplayId displayId) const
        -> DisplayModeRequestOpt {
    std::lock_guard lock(mDisplayLock);
    const auto& displayPtr =
            FTL_EXPECT(mDisplays.get(displayId).ok_or(DisplayModeRequestOpt())).get();

    if (FlagManager::getInstance().modeset_state_machine()) {
        return displayPtr->pendingModeOpt;
    }

    {
        std::scoped_lock lock(displayPtr->desiredModeLock);
        return displayPtr->pendingModeOpt;
    }
}

bool DisplayModeController::isModeSetPending(PhysicalDisplayId displayId) const {
    if (FlagManager::getInstance().modeset_state_machine()) {
        return getPendingMode(displayId).has_value();
    }

    std::lock_guard lock(mDisplayLock);
    const auto& displayPtr = FTL_EXPECT(mDisplays.get(displayId).ok_or(false)).get();

    {
        std::scoped_lock lock(displayPtr->desiredModeLock);
        return displayPtr->isModeSetPending;
    }
}

scheduler::FrameRateMode DisplayModeController::getActiveMode(PhysicalDisplayId displayId) const {
    return selectorPtrFor(displayId)->getActiveMode();
}

auto DisplayModeController::takeDesiredModeIfMatches(PhysicalDisplayId displayId,
                                                     ui::Size expectedResolution,
                                                     bool shouldSyncResolutionSwitch)
        -> DisplayModeRequestOpt {
    std::lock_guard lock(mDisplayLock);
    const auto& displayPtr =
            FTL_EXPECT(mDisplays.get(displayId).ok_or(DisplayModeRequestOpt())).get();

    DisplayModeRequestOpt desiredModeOpt;
    {
        std::scoped_lock lock(displayPtr->desiredModeLock);

        if (shouldSyncResolutionSwitch) {
            if (const auto modeOpt = displayPtr->desiredModeOpt.transform(
                        [](const auto& request) { return request.mode; })) {
                const bool resolutionMatch =
                        displayPtr->selectorPtr->getActiveMode().matchesResolution(*modeOpt);

                if (!resolutionMatch) {
                    if (expectedResolution == modeOpt->modePtr->getResolution()) {
                        displayPtr->desiredModeOpt->force = true;
                    } else {
                        // When initiating a resolution change, wait until the commit that resizes
                        // the display.
                        return std::nullopt;
                    }
                }
            }
        }

        std::swap(displayPtr->desiredModeOpt, desiredModeOpt);
        displayPtr->hasDesiredModeTrace = false;
    }
    return desiredModeOpt;
}

void DisplayModeController::clearDesiredMode(PhysicalDisplayId displayId) {
    std::lock_guard lock(mDisplayLock);
    const auto& displayPtr = FTL_TRY(mDisplays.get(displayId).ok_or(ftl::Unit())).get();

    {
        std::scoped_lock lock(displayPtr->desiredModeLock);
        displayPtr->desiredModeOpt.reset();
        displayPtr->hasDesiredModeTrace = false;
    }
}

void DisplayModeController::clearPendingMode(PhysicalDisplayId displayId) {
    std::lock_guard lock(mDisplayLock);
    const auto& displayPtr = FTL_TRY(mDisplays.get(displayId).ok_or(ftl::Unit())).get();
    displayPtr->pendingModeOpt.reset();
}

auto DisplayModeController::initiateModeChange(PhysicalDisplayId displayId,
                                               DisplayModeRequest&& desiredMode,
                                               const hal::VsyncPeriodChangeConstraints& constraints,
                                               hal::VsyncPeriodChangeTimeline& outTimeline)
        -> ModeChangeResult {
    std::lock_guard lock(mDisplayLock);
    const auto& displayPtr =
            FTL_EXPECT(mDisplays.get(displayId).ok_or(ModeChangeResult::Aborted)).get();

    if (!FlagManager::getInstance().modeset_state_machine()) {
        displayPtr->isModeSetPending = true;

        // For now, `desiredMode` and `desiredModeOpt` are one and the same, but the latter is not
        // cleared until the next `SF::initiateDisplayModeChanges`. However, the desired mode has
        // been consumed at this point, so clear the `force` flag to prevent an endless loop of
        // `initiateModeChange`.
        std::scoped_lock lock(displayPtr->desiredModeLock);
        if (displayPtr->desiredModeOpt) {
            displayPtr->desiredModeOpt->force = false;
        }
    }

    ALOGD("%s %s", displayPtr->concatId(__func__).c_str(), to_string(desiredMode).c_str());
    displayPtr->pendingModeOpt = std::move(desiredMode);

    const auto& mode = *displayPtr->pendingModeOpt->mode.modePtr;
    status_t error;
    if (!mComposerPtr->getComposer()->isDisplayCommandModesetSupported()) {
        error = mComposerPtr->setActiveModeWithConstraints(displayId, mode.getHwcId(), constraints,
                                                           &outTimeline);
    } else {
        error = mComposerPtr->setDisplayMode(displayId, mode.getHwcId(),
                                             constraints.seamlessRequired);
        // DisplayCommand modeset, when successful, is immediate and doesn't need a refresh.
        outTimeline.refreshRequired = false;
        outTimeline.newVsyncAppliedTimeNanos = systemTime();
    }

    if (error != OK) {
        if (FlagManager::getInstance().modeset_state_machine()) {
            displayPtr->pendingModeOpt.reset();
        } else {
            displayPtr->isModeSetPending = false;
        }
    }

    switch (error) {
        case FAILED_TRANSACTION:
            return ModeChangeResult::Rejected;
        case OK:
            SFTRACE_INT(displayPtr->pendingModeFpsTrace.c_str(), mode.getVsyncRate().getIntValue());
            return ModeChangeResult::Changed;
        default:
            return ModeChangeResult::Aborted;
    }
}

auto DisplayModeController::initiateModeChange(
        ui::PhysicalDisplayMap<PhysicalDisplayId, DisplayModeRequest>&& modeRequestMap)
        -> ModeChangeResult {
    std::lock_guard lock(mDisplayLock);
    std::vector<std::pair<PhysicalDisplayId, hal::HWConfigId>> displayModes;
    ui::PhysicalDisplayVector<Display*> displayPtrs;
    bool seamlessRequired = true;
    for (auto& [displayId, desiredMode] : modeRequestMap) {
        const auto& displayPtr =
                FTL_EXPECT(mDisplays.get(displayId).ok_or(ModeChangeResult::Aborted)).get();
        displayPtrs.push_back(displayPtr.get());

        ALOGD("%s %s", displayPtr->concatId(__func__).c_str(), to_string(desiredMode).c_str());
        displayPtr->pendingModeOpt = std::move(desiredMode);

        const auto& mode = *displayPtr->pendingModeOpt->mode.modePtr;
        // Either all display(s) are seamless or none of them are.
        seamlessRequired &= displayPtr->pendingModeOpt->seamless;
        displayModes.push_back({displayId, mode.getHwcId()});
    }

    const auto error = mComposerPtr->setDisplayModes(displayModes, seamlessRequired);

    for (auto displayPtr : displayPtrs) {
        if (error != OK) {
            displayPtr->pendingModeOpt.reset();
        } else {
            const auto& mode = *displayPtr->pendingModeOpt->mode.modePtr;
            SFTRACE_INT(displayPtr->pendingModeFpsTrace.c_str(), mode.getVsyncRate().getIntValue());
        }
    }

    switch (error) {
        case FAILED_TRANSACTION:
            return ModeChangeResult::Rejected;
        case OK:
            return ModeChangeResult::Changed;
        default:
            return ModeChangeResult::Aborted;
    }
}

void DisplayModeController::finalizeModeChange(PhysicalDisplayId displayId, DisplayModeId modeId,
                                               Fps vsyncRate, Fps renderFps) {
    std::lock_guard lock(mDisplayLock);
    setActiveModeLocked(displayId, modeId, vsyncRate, renderFps);

    const auto& displayPtr = FTL_TRY(mDisplays.get(displayId).ok_or(ftl::Unit())).get();
    displayPtr->isModeSetPending = false;
}

auto DisplayModeController::finalizeModeChange(PhysicalDisplayId displayId) -> ModeChange {
    std::lock_guard lock(mDisplayLock);

    const auto& displayPtr =
            FTL_EXPECT(mDisplays.get(displayId).ok_or(NoModeChange{"Unknown display"})).get();
    if (!displayPtr->pendingModeOpt) return NoModeChange{"No pending mode"};

    auto pendingMode = *std::exchange(displayPtr->pendingModeOpt, std::nullopt);
    auto& pendingModePtr = pendingMode.mode.modePtr;

    if (!displayPtr->selectorPtr->displayModes().contains(pendingModePtr->getId())) {
        return NoModeChange{"Unknown pending mode"};
    }

    const bool resolutionMatch =
            displayPtr->selectorPtr->getActiveMode().matchesResolution(pendingMode.mode);

    setActiveModeLocked(displayId, pendingModePtr->getId(), pendingModePtr->getVsyncRate(),
                        pendingMode.mode.fps);

    if (resolutionMatch) {
        return RefreshRateChange{std::move(pendingMode)};
    } else {
        return ResolutionChange{std::move(pendingMode)};
    }
}

void DisplayModeController::setActiveMode(PhysicalDisplayId displayId, DisplayModeId modeId,
                                          Fps vsyncRate, Fps renderFps) {
    std::lock_guard lock(mDisplayLock);
    setActiveModeLocked(displayId, modeId, vsyncRate, renderFps);
}

void DisplayModeController::setActiveModeLocked(PhysicalDisplayId displayId, DisplayModeId modeId,
                                                Fps vsyncRate, Fps renderFps) {
    const auto& displayPtr = FTL_TRY(mDisplays.get(displayId).ok_or(ftl::Unit())).get();

    SFTRACE_INT(displayPtr->activeModeFpsTrace.c_str(), vsyncRate.getIntValue());
    SFTRACE_INT(displayPtr->renderRateFpsTrace.c_str(), renderFps.getIntValue());

    displayPtr->selectorPtr->setActiveMode(modeId, renderFps);

    if (mActiveModeListener) {
        mActiveModeListener(displayId, vsyncRate, renderFps);
    }
}

void DisplayModeController::updateKernelIdleTimer(PhysicalDisplayId displayId) {
    std::lock_guard lock(mDisplayLock);
    const auto& displayPtr = FTL_TRY(mDisplays.get(displayId).ok_or(ftl::Unit())).get();

    const auto controllerOpt = displayPtr->selectorPtr->kernelIdleTimerController();
    if (!controllerOpt) return;

    using KernelIdleTimerAction = scheduler::RefreshRateSelector::KernelIdleTimerAction;

    switch (displayPtr->selectorPtr->getIdleTimerAction()) {
        case KernelIdleTimerAction::TurnOff:
            if (displayPtr->isKernelIdleTimerEnabled) {
                SFTRACE_INT("KernelIdleTimer", 0);
                updateKernelIdleTimer(displayId, std::chrono::milliseconds::zero(), *controllerOpt);
                displayPtr->isKernelIdleTimerEnabled = false;
            }
            break;
        case KernelIdleTimerAction::TurnOn:
            if (!displayPtr->isKernelIdleTimerEnabled) {
                SFTRACE_INT("KernelIdleTimer", 1);
                const auto timeout = displayPtr->selectorPtr->getIdleTimerTimeout();
                updateKernelIdleTimer(displayId, timeout, *controllerOpt);
                displayPtr->isKernelIdleTimerEnabled = true;
            }
            break;
    }
}

void DisplayModeController::updateKernelIdleTimer(PhysicalDisplayId displayId,
                                                  std::chrono::milliseconds timeout,
                                                  KernelIdleTimerController controller) {
    switch (controller) {
        case KernelIdleTimerController::HwcApi:
            mComposerPtr->setIdleTimerEnabled(displayId, timeout);
            break;

        case KernelIdleTimerController::Sysprop:
            using namespace std::string_literals;
            base::SetProperty("graphics.display.kernel_idle_timer.enabled"s,
                              timeout > std::chrono::milliseconds::zero() ? "true"s : "false"s);
            break;
    }
}

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-value" // b/369277774
auto DisplayModeController::getKernelIdleTimerState(PhysicalDisplayId displayId) const
        -> KernelIdleTimerState {
    std::lock_guard lock(mDisplayLock);
    const auto& displayPtr =
            FTL_EXPECT(mDisplays.get(displayId).ok_or(KernelIdleTimerState())).get();

    const auto desiredModeIdOpt =
            (std::scoped_lock(displayPtr->desiredModeLock), displayPtr->desiredModeOpt)
                    .transform([](const display::DisplayModeRequest& request) {
                        return request.mode.modePtr->getId();
                    });

    return {desiredModeIdOpt, displayPtr->isKernelIdleTimerEnabled};
}

void DisplayModeController::startHdcpNegotiation(PhysicalDisplayId displayId) {
    using aidl::android::hardware::drm::HdcpLevel;
    using aidl::android::hardware::drm::HdcpLevels;
    constexpr HdcpLevels kLevels = {.connectedLevel = HdcpLevel::HDCP_V2_1,
                                    .maxLevel = HdcpLevel::HDCP_V2_3};

    std::lock_guard lock(mDisplayLock);
    const auto& displayPtr = FTL_TRY(mDisplays.get(displayId).ok_or(ftl::Unit())).get();
    if (displayPtr->hdcpState == HdcpState::Desired) {
        const auto status = mComposerPtr->startHdcpNegotiation(displayId, kLevels);
        displayPtr->hdcpState = (status == NO_ERROR) ? HdcpState::Enabled : HdcpState::Undesired;
    }
}

void DisplayModeController::setSecure(PhysicalDisplayId displayId, bool secure) {
    std::lock_guard lock(mDisplayLock);
    const auto& displayPtr = FTL_TRY(mDisplays.get(displayId).ok_or(ftl::Unit())).get();
    displayPtr->setSecure(secure);
}

#pragma clang diagnostic pop
} // namespace android::display
