/*
 * 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 "VsyncModulator"

#include "VsyncModulator.h"

#include <android-base/properties.h>
#include <log/log.h>
#include <utils/Trace.h>

#include <chrono>
#include <cinttypes>
#include <mutex>

using namespace std::chrono_literals;

namespace android::scheduler {

const std::chrono::nanoseconds VsyncModulator::MIN_EARLY_TRANSACTION_TIME = 1ms;

VsyncModulator::VsyncModulator(const VsyncConfigSet& config, Now now)
      : mVsyncConfigSet(config),
        mNow(now),
        mTraceDetailedInfo(base::GetBoolProperty("debug.sf.vsync_trace_detailed_info", false)) {}

VsyncModulator::VsyncConfig VsyncModulator::setVsyncConfigSet(const VsyncConfigSet& config) {
    std::lock_guard<std::mutex> lock(mMutex);
    mVsyncConfigSet = config;
    return updateVsyncConfigLocked();
}

VsyncModulator::VsyncConfigOpt VsyncModulator::setTransactionSchedule(TransactionSchedule schedule,
                                                                      const sp<IBinder>& token) {
    std::lock_guard<std::mutex> lock(mMutex);
    switch (schedule) {
        case Schedule::EarlyStart:
            if (token) {
                mEarlyWakeupRequests.emplace(token);
                token->linkToDeath(this);
            } else {
                ALOGW("%s: EarlyStart requested without a valid token", __func__);
            }
            break;
        case Schedule::EarlyEnd: {
            if (token && mEarlyWakeupRequests.erase(token) > 0) {
                token->unlinkToDeath(this);
            } else {
                ALOGW("%s: Unexpected EarlyEnd", __func__);
            }
            break;
        }
        case Schedule::Late:
            // No change to mEarlyWakeup for non-explicit states.
            break;
    }

    if (mTraceDetailedInfo) {
        ATRACE_INT("mEarlyWakeup", static_cast<int>(mEarlyWakeupRequests.size()));
    }

    if (mEarlyWakeupRequests.empty() && schedule == Schedule::EarlyEnd) {
        mEarlyTransactionFrames = MIN_EARLY_TRANSACTION_FRAMES;
        mEarlyTransactionStartTime = mNow();
    }

    // An early transaction stays an early transaction.
    if (schedule == mTransactionSchedule || mTransactionSchedule == Schedule::EarlyEnd) {
        return std::nullopt;
    }
    mTransactionSchedule = schedule;
    return updateVsyncConfigLocked();
}

VsyncModulator::VsyncConfigOpt VsyncModulator::onTransactionCommit() {
    mLastTransactionCommitTime = mNow();
    if (mTransactionSchedule == Schedule::Late) return std::nullopt;
    mTransactionSchedule = Schedule::Late;
    return updateVsyncConfig();
}

VsyncModulator::VsyncConfigOpt VsyncModulator::onRefreshRateChangeInitiated() {
    if (mRefreshRateChangePending) return std::nullopt;
    mRefreshRateChangePending = true;
    return updateVsyncConfig();
}

VsyncModulator::VsyncConfigOpt VsyncModulator::onRefreshRateChangeCompleted() {
    if (!mRefreshRateChangePending) return std::nullopt;
    mRefreshRateChangePending = false;
    return updateVsyncConfig();
}

VsyncModulator::VsyncConfigOpt VsyncModulator::onDisplayRefresh(bool usedGpuComposition) {
    bool updateOffsetsNeeded = false;

    if (mEarlyTransactionStartTime.load() + MIN_EARLY_TRANSACTION_TIME <=
        mLastTransactionCommitTime.load()) {
        if (mEarlyTransactionFrames > 0) {
            mEarlyTransactionFrames--;
            updateOffsetsNeeded = true;
        }
    }
    if (usedGpuComposition) {
        mEarlyGpuFrames = MIN_EARLY_GPU_FRAMES;
        updateOffsetsNeeded = true;
    } else if (mEarlyGpuFrames > 0) {
        mEarlyGpuFrames--;
        updateOffsetsNeeded = true;
    }

    if (!updateOffsetsNeeded) return std::nullopt;
    return updateVsyncConfig();
}

VsyncModulator::VsyncConfig VsyncModulator::getVsyncConfig() const {
    std::lock_guard<std::mutex> lock(mMutex);
    return mVsyncConfig;
}

const VsyncModulator::VsyncConfig& VsyncModulator::getNextVsyncConfig() const {
    // Early offsets are used if we're in the middle of a refresh rate
    // change, or if we recently begin a transaction.
    if (!mEarlyWakeupRequests.empty() || mTransactionSchedule == Schedule::EarlyEnd ||
        mEarlyTransactionFrames > 0 || mRefreshRateChangePending) {
        return mVsyncConfigSet.early;
    } else if (mEarlyGpuFrames > 0) {
        return mVsyncConfigSet.earlyGpu;
    } else {
        return mVsyncConfigSet.late;
    }
}

VsyncModulator::VsyncConfig VsyncModulator::updateVsyncConfig() {
    std::lock_guard<std::mutex> lock(mMutex);
    return updateVsyncConfigLocked();
}

VsyncModulator::VsyncConfig VsyncModulator::updateVsyncConfigLocked() {
    const VsyncConfig& offsets = getNextVsyncConfig();
    mVsyncConfig = offsets;

    if (mTraceDetailedInfo) {
        const bool isEarly = &offsets == &mVsyncConfigSet.early;
        const bool isEarlyGpu = &offsets == &mVsyncConfigSet.earlyGpu;
        const bool isLate = &offsets == &mVsyncConfigSet.late;

        ATRACE_INT("Vsync-EarlyOffsetsOn", isEarly);
        ATRACE_INT("Vsync-EarlyGpuOffsetsOn", isEarlyGpu);
        ATRACE_INT("Vsync-LateOffsetsOn", isLate);
    }

    return offsets;
}

void VsyncModulator::binderDied(const wp<IBinder>& who) {
    std::lock_guard<std::mutex> lock(mMutex);
    mEarlyWakeupRequests.erase(who);

    static_cast<void>(updateVsyncConfigLocked());
}

} // namespace android::scheduler
