/*
 * Copyright 2019 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
#undef LOG_TAG
#define LOG_TAG "VSyncReactor"
//#define LOG_NDEBUG 0
#include "VSyncReactor.h"
#include <cutils/properties.h>
#include <log/log.h>
#include <utils/Trace.h>
#include "../TracedOrdinal.h"
#include "TimeKeeper.h"
#include "VSyncDispatch.h"
#include "VSyncTracker.h"

namespace android::scheduler {
using base::StringAppendF;

Clock::~Clock() = default;
nsecs_t SystemClock::now() const {
    return systemTime(SYSTEM_TIME_MONOTONIC);
}

class PredictedVsyncTracer {
public:
    PredictedVsyncTracer(VSyncDispatch& dispatch)
          : mRegistration(dispatch,
                          std::bind(&PredictedVsyncTracer::callback, this, std::placeholders::_1,
                                    std::placeholders::_2),
                          "PredictedVsyncTracer") {
        mRegistration.schedule(0, 0);
    }

private:
    TracedOrdinal<bool> mParity = {"VSYNC-predicted", 0};
    VSyncCallbackRegistration mRegistration;

    void callback(nsecs_t /*vsyncTime*/, nsecs_t /*targetWakeupTim*/) {
        mParity = !mParity;
        mRegistration.schedule(0, 0);
    }
};

VSyncReactor::VSyncReactor(std::unique_ptr<Clock> clock, std::unique_ptr<VSyncDispatch> dispatch,
                           std::unique_ptr<VSyncTracker> tracker, size_t pendingFenceLimit)
      : mClock(std::move(clock)),
        mTracker(std::move(tracker)),
        mDispatch(std::move(dispatch)),
        mPendingLimit(pendingFenceLimit),
        mPredictedVsyncTracer(property_get_bool("debug.sf.show_predicted_vsync", false)
                                      ? std::make_unique<PredictedVsyncTracer>(*mDispatch)
                                      : nullptr) {}

VSyncReactor::~VSyncReactor() = default;

// The DispSync interface has a 'repeat this callback at rate' semantic. This object adapts
// VSyncDispatch's individually-scheduled callbacks so as to meet DispSync's existing semantic
// for now.
class CallbackRepeater {
public:
    CallbackRepeater(VSyncDispatch& dispatch, DispSync::Callback* cb, const char* name,
                     nsecs_t period, nsecs_t offset, nsecs_t notBefore)
          : mName(name),
            mCallback(cb),
            mRegistration(dispatch,
                          std::bind(&CallbackRepeater::callback, this, std::placeholders::_1,
                                    std::placeholders::_2),
                          mName),
            mPeriod(period),
            mOffset(offset),
            mLastCallTime(notBefore) {}

    ~CallbackRepeater() {
        std::lock_guard<std::mutex> lk(mMutex);
        mRegistration.cancel();
    }

    void start(nsecs_t offset) {
        std::lock_guard<std::mutex> lk(mMutex);
        mStopped = false;
        mOffset = offset;

        auto const schedule_result = mRegistration.schedule(calculateWorkload(), mLastCallTime);
        LOG_ALWAYS_FATAL_IF((schedule_result != ScheduleResult::Scheduled),
                            "Error scheduling callback: rc %X", schedule_result);
    }

    void setPeriod(nsecs_t period) {
        std::lock_guard<std::mutex> lk(mMutex);
        if (period == mPeriod) {
            return;
        }
        mPeriod = period;
    }

    void stop() {
        std::lock_guard<std::mutex> lk(mMutex);
        LOG_ALWAYS_FATAL_IF(mStopped, "DispSyncInterface misuse: callback already stopped");
        mStopped = true;
        mRegistration.cancel();
    }

    void dump(std::string& result) const {
        std::lock_guard<std::mutex> lk(mMutex);
        StringAppendF(&result, "\t%s: mPeriod=%.2f last vsync time %.2fms relative to now (%s)\n",
                      mName.c_str(), mPeriod / 1e6f, (mLastCallTime - systemTime()) / 1e6f,
                      mStopped ? "stopped" : "running");
    }

private:
    void callback(nsecs_t vsynctime, nsecs_t wakeupTime) {
        {
            std::lock_guard<std::mutex> lk(mMutex);
            mLastCallTime = vsynctime;
        }

        mCallback->onDispSyncEvent(wakeupTime, vsynctime);

        {
            std::lock_guard<std::mutex> lk(mMutex);
            if (mStopped) {
                return;
            }
            auto const schedule_result = mRegistration.schedule(calculateWorkload(), vsynctime);
            LOG_ALWAYS_FATAL_IF((schedule_result != ScheduleResult::Scheduled),
                                "Error rescheduling callback: rc %X", schedule_result);
        }
    }

    // DispSync offsets are defined as time after the vsync before presentation.
    // VSyncReactor workloads are defined as time before the intended presentation vsync.
    // Note change in sign between the two defnitions.
    nsecs_t calculateWorkload() REQUIRES(mMutex) { return mPeriod - mOffset; }

    const std::string mName;
    DispSync::Callback* const mCallback;

    std::mutex mutable mMutex;
    VSyncCallbackRegistration mRegistration GUARDED_BY(mMutex);
    bool mStopped GUARDED_BY(mMutex) = false;
    nsecs_t mPeriod GUARDED_BY(mMutex);
    nsecs_t mOffset GUARDED_BY(mMutex);
    nsecs_t mLastCallTime GUARDED_BY(mMutex);
};

bool VSyncReactor::addPresentFence(const std::shared_ptr<FenceTime>& fence) {
    if (!fence) {
        return false;
    }

    nsecs_t const signalTime = fence->getCachedSignalTime();
    if (signalTime == Fence::SIGNAL_TIME_INVALID) {
        return true;
    }

    std::lock_guard<std::mutex> lk(mMutex);
    if (mExternalIgnoreFences || mInternalIgnoreFences) {
        return true;
    }

    bool timestampAccepted = true;
    for (auto it = mUnfiredFences.begin(); it != mUnfiredFences.end();) {
        auto const time = (*it)->getCachedSignalTime();
        if (time == Fence::SIGNAL_TIME_PENDING) {
            it++;
        } else if (time == Fence::SIGNAL_TIME_INVALID) {
            it = mUnfiredFences.erase(it);
        } else {
            timestampAccepted &= mTracker->addVsyncTimestamp(time);

            it = mUnfiredFences.erase(it);
        }
    }

    if (signalTime == Fence::SIGNAL_TIME_PENDING) {
        if (mPendingLimit == mUnfiredFences.size()) {
            mUnfiredFences.erase(mUnfiredFences.begin());
        }
        mUnfiredFences.push_back(fence);
    } else {
        timestampAccepted &= mTracker->addVsyncTimestamp(signalTime);
    }

    if (!timestampAccepted) {
        mMoreSamplesNeeded = true;
        setIgnorePresentFencesInternal(true);
        mPeriodConfirmationInProgress = true;
    }

    return mMoreSamplesNeeded;
}

void VSyncReactor::setIgnorePresentFences(bool ignoration) {
    std::lock_guard<std::mutex> lk(mMutex);
    mExternalIgnoreFences = ignoration;
    updateIgnorePresentFencesInternal();
}

void VSyncReactor::setIgnorePresentFencesInternal(bool ignoration) {
    mInternalIgnoreFences = ignoration;
    updateIgnorePresentFencesInternal();
}

void VSyncReactor::updateIgnorePresentFencesInternal() {
    if (mExternalIgnoreFences || mInternalIgnoreFences) {
        mUnfiredFences.clear();
    }
}

nsecs_t VSyncReactor::computeNextRefresh(int periodOffset, nsecs_t now) const {
    auto const currentPeriod = periodOffset ? mTracker->currentPeriod() : 0;
    return mTracker->nextAnticipatedVSyncTimeFrom(now + periodOffset * currentPeriod);
}

nsecs_t VSyncReactor::expectedPresentTime(nsecs_t now) {
    return mTracker->nextAnticipatedVSyncTimeFrom(now);
}

void VSyncReactor::startPeriodTransition(nsecs_t newPeriod) {
    mPeriodConfirmationInProgress = true;
    mPeriodTransitioningTo = newPeriod;
    mMoreSamplesNeeded = true;
    setIgnorePresentFencesInternal(true);
}

void VSyncReactor::endPeriodTransition() {
    setIgnorePresentFencesInternal(false);
    mMoreSamplesNeeded = false;
    mPeriodTransitioningTo.reset();
    mPeriodConfirmationInProgress = false;
    mLastHwVsync.reset();
}

void VSyncReactor::setPeriod(nsecs_t period) {
    ATRACE_INT64("VSR-setPeriod", period);
    std::lock_guard lk(mMutex);
    mLastHwVsync.reset();
    if (period == getPeriod()) {
        endPeriodTransition();
    } else {
        startPeriodTransition(period);
    }
}

nsecs_t VSyncReactor::getPeriod() {
    return mTracker->currentPeriod();
}

void VSyncReactor::beginResync() {
    mTracker->resetModel();
}

void VSyncReactor::endResync() {}

bool VSyncReactor::periodConfirmed(nsecs_t vsync_timestamp, std::optional<nsecs_t> HwcVsyncPeriod) {
    if (!mPeriodConfirmationInProgress) {
        return false;
    }

    if (!mLastHwVsync && !HwcVsyncPeriod) {
        return false;
    }

    auto const period = mPeriodTransitioningTo ? *mPeriodTransitioningTo : getPeriod();
    static constexpr int allowancePercent = 10;
    static constexpr std::ratio<allowancePercent, 100> allowancePercentRatio;
    auto const allowance = period * allowancePercentRatio.num / allowancePercentRatio.den;
    if (HwcVsyncPeriod) {
        return std::abs(*HwcVsyncPeriod - period) < allowance;
    }

    auto const distance = vsync_timestamp - *mLastHwVsync;
    return std::abs(distance - period) < allowance;
}

bool VSyncReactor::addResyncSample(nsecs_t timestamp, std::optional<nsecs_t> hwcVsyncPeriod,
                                   bool* periodFlushed) {
    assert(periodFlushed);

    std::lock_guard<std::mutex> lk(mMutex);
    if (periodConfirmed(timestamp, hwcVsyncPeriod)) {
        if (mPeriodTransitioningTo) {
            mTracker->setPeriod(*mPeriodTransitioningTo);
            for (auto& entry : mCallbacks) {
                entry.second->setPeriod(*mPeriodTransitioningTo);
            }
            *periodFlushed = true;
        }
        endPeriodTransition();
    } else if (mPeriodConfirmationInProgress) {
        mLastHwVsync = timestamp;
        mMoreSamplesNeeded = true;
        *periodFlushed = false;
    } else {
        mMoreSamplesNeeded = false;
        *periodFlushed = false;
    }

    mTracker->addVsyncTimestamp(timestamp);
    return mMoreSamplesNeeded;
}

status_t VSyncReactor::addEventListener(const char* name, nsecs_t phase,
                                        DispSync::Callback* callback,
                                        nsecs_t /* lastCallbackTime */) {
    std::lock_guard<std::mutex> lk(mMutex);
    auto it = mCallbacks.find(callback);
    if (it == mCallbacks.end()) {
        // TODO (b/146557561): resolve lastCallbackTime semantics in DispSync i/f.
        static auto constexpr maxListeners = 4;
        if (mCallbacks.size() >= maxListeners) {
            ALOGE("callback %s not added, exceeded callback limit of %i (currently %zu)", name,
                  maxListeners, mCallbacks.size());
            return NO_MEMORY;
        }

        auto const period = mTracker->currentPeriod();
        auto repeater = std::make_unique<CallbackRepeater>(*mDispatch, callback, name, period,
                                                           phase, mClock->now());
        it = mCallbacks.emplace(std::pair(callback, std::move(repeater))).first;
    }

    it->second->start(phase);
    return NO_ERROR;
}

status_t VSyncReactor::removeEventListener(DispSync::Callback* callback,
                                           nsecs_t* /* outLastCallback */) {
    std::lock_guard<std::mutex> lk(mMutex);
    auto const it = mCallbacks.find(callback);
    LOG_ALWAYS_FATAL_IF(it == mCallbacks.end(), "callback %p not registered", callback);

    it->second->stop();
    return NO_ERROR;
}

status_t VSyncReactor::changePhaseOffset(DispSync::Callback* callback, nsecs_t phase) {
    std::lock_guard<std::mutex> lk(mMutex);
    auto const it = mCallbacks.find(callback);
    LOG_ALWAYS_FATAL_IF(it == mCallbacks.end(), "callback was %p not registered", callback);

    it->second->start(phase);
    return NO_ERROR;
}

void VSyncReactor::dump(std::string& result) const {
    std::lock_guard<std::mutex> lk(mMutex);
    StringAppendF(&result, "VsyncReactor in use\n");
    StringAppendF(&result, "Has %zu unfired fences\n", mUnfiredFences.size());
    StringAppendF(&result, "mInternalIgnoreFences=%d mExternalIgnoreFences=%d\n",
                  mInternalIgnoreFences, mExternalIgnoreFences);
    StringAppendF(&result, "mMoreSamplesNeeded=%d mPeriodConfirmationInProgress=%d\n",
                  mMoreSamplesNeeded, mPeriodConfirmationInProgress);
    if (mPeriodTransitioningTo) {
        StringAppendF(&result, "mPeriodTransitioningTo=%" PRId64 "\n", *mPeriodTransitioningTo);
    } else {
        StringAppendF(&result, "mPeriodTransitioningTo=nullptr\n");
    }

    if (mLastHwVsync) {
        StringAppendF(&result, "Last HW vsync was %.2fms ago\n",
                      (mClock->now() - *mLastHwVsync) / 1e6f);
    } else {
        StringAppendF(&result, "No Last HW vsync\n");
    }

    StringAppendF(&result, "CallbackRepeaters:\n");
    for (const auto& [callback, repeater] : mCallbacks) {
        repeater->dump(result);
    }

    StringAppendF(&result, "VSyncTracker:\n");
    mTracker->dump(result);
    StringAppendF(&result, "VSyncDispatch:\n");
    mDispatch->dump(result);
}

void VSyncReactor::reset() {}

} // namespace android::scheduler
