/*
 * Copyright 2021 The Android Open Source Project
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#define LOG_TAG "powerhal-libperfmgr"
#define ATRACE_TAG (ATRACE_TAG_POWER | ATRACE_TAG_HAL)

#include "PowerSessionManager.h"

#include <android-base/file.h>
#include <log/log.h>
#include <perfmgr/HintManager.h>
#include <processgroup/processgroup.h>
#include <sys/syscall.h>
#include <utils/Trace.h>

namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {

using ::android::perfmgr::AdpfConfig;
using ::android::perfmgr::HintManager;

namespace {
/* there is no glibc or bionic wrapper */
struct sched_attr {
    __u32 size;
    __u32 sched_policy;
    __u64 sched_flags;
    __s32 sched_nice;
    __u32 sched_priority;
    __u64 sched_runtime;
    __u64 sched_deadline;
    __u64 sched_period;
    __u32 sched_util_min;
    __u32 sched_util_max;
};

static int sched_setattr(int pid, struct sched_attr *attr, unsigned int flags) {
    if (!HintManager::GetInstance()->GetAdpfProfile()->mUclampMinOn) {
        ALOGV("PowerSessionManager:%s: skip", __func__);
        return 0;
    }
    return syscall(__NR_sched_setattr, pid, attr, flags);
}

static void set_uclamp_min(int tid, int min) {
    static constexpr int32_t kMaxUclampValue = 1024;
    min = std::max(0, min);
    min = std::min(min, kMaxUclampValue);

    sched_attr attr = {};
    attr.size = sizeof(attr);

    attr.sched_flags = (SCHED_FLAG_KEEP_ALL | SCHED_FLAG_UTIL_CLAMP_MIN);
    attr.sched_util_min = min;

    int ret = sched_setattr(tid, &attr, 0);
    if (ret) {
        ALOGW("sched_setattr failed for thread %d, err=%d", tid, errno);
    }
}
}  // namespace

void PowerSessionManager::updateHintMode(const std::string &mode, bool enabled) {
    ALOGV("PowerSessionManager::updateHintMode: mode: %s, enabled: %d", mode.c_str(), enabled);
    if (enabled && mode.compare(0, 8, "REFRESH_") == 0) {
        if (mode.compare("REFRESH_120FPS") == 0) {
            mDisplayRefreshRate = 120;
        } else if (mode.compare("REFRESH_90FPS") == 0) {
            mDisplayRefreshRate = 90;
        } else if (mode.compare("REFRESH_60FPS") == 0) {
            mDisplayRefreshRate = 60;
        }
    }
    if (HintManager::GetInstance()->GetAdpfProfile()) {
        HintManager::GetInstance()->SetAdpfProfile(mode);
    }
}

void PowerSessionManager::updateHintBoost(const std::string &boost, int32_t durationMs) {
    ATRACE_CALL();
    ALOGV("PowerSessionManager::updateHintBoost: boost: %s, durationMs: %d", boost.c_str(),
          durationMs);
}

int PowerSessionManager::getDisplayRefreshRate() {
    return mDisplayRefreshRate;
}

void PowerSessionManager::addPowerSession(PowerHintSession *session) {
    std::lock_guard<std::mutex> guard(mLock);
    for (auto t : session->getTidList()) {
        mTidSessionListMap[t].insert(session);
        if (mTidRefCountMap.find(t) == mTidRefCountMap.end()) {
            if (!SetTaskProfiles(t, {"ResetUclampGrp"})) {
                ALOGW("Failed to set ResetUclampGrp task profile for tid:%d", t);
            } else {
                mTidRefCountMap[t] = 1;
            }
            continue;
        }
        if (mTidRefCountMap[t] <= 0) {
            ALOGE("Error! Unexpected zero/negative RefCount:%d for tid:%d", mTidRefCountMap[t], t);
            continue;
        }
        mTidRefCountMap[t]++;
    }
    mSessions.insert(session);
}

void PowerSessionManager::removePowerSession(PowerHintSession *session) {
    std::lock_guard<std::mutex> guard(mLock);
    for (auto t : session->getTidList()) {
        if (mTidRefCountMap.find(t) == mTidRefCountMap.end()) {
            ALOGE("Unexpected Error! Failed to look up tid:%d in TidRefCountMap", t);
            continue;
        }
        mTidSessionListMap[t].erase(session);
        mTidRefCountMap[t]--;
        if (mTidRefCountMap[t] <= 0) {
            if (!SetTaskProfiles(t, {"NoResetUclampGrp"})) {
                ALOGW("Failed to set NoResetUclampGrp task profile for tid:%d", t);
            }
            mTidRefCountMap.erase(t);
        }
    }
    mSessions.erase(session);
}

void PowerSessionManager::setUclampMin(PowerHintSession *session, int val) {
    std::lock_guard<std::mutex> guard(mLock);
    setUclampMinLocked(session, val);
}

void PowerSessionManager::setUclampMinLocked(PowerHintSession *session, int val) {
    for (auto t : session->getTidList()) {
        // Get thex max uclamp.min across sessions which include the tid.
        int tidMax = 0;
        for (PowerHintSession *s : mTidSessionListMap[t]) {
            if (!s->isActive() || s->isTimeout())
                continue;
            tidMax = std::max(tidMax, s->getUclampMin());
        }
        set_uclamp_min(t, std::max(val, tidMax));
    }
}

std::optional<bool> PowerSessionManager::isAnyAppSessionActive() {
    std::lock_guard<std::mutex> guard(mLock);
    bool active = false;
    for (PowerHintSession *s : mSessions) {
        // session active and not stale is actually active.
        if (s->isActive() && !s->isTimeout() && s->isAppSession()) {
            active = true;
            break;
        }
    }
    if (active == mActive) {
        return std::nullopt;
    } else {
        mActive = active;
    }

    return active;
}

void PowerSessionManager::handleMessage(const Message &) {
    auto active = isAnyAppSessionActive();
    if (!active.has_value()) {
        return;
    }
    if (active.value()) {
        disableSystemTopAppBoost();
    } else {
        enableSystemTopAppBoost();
    }
}

void PowerSessionManager::dumpToFd(int fd) {
    std::ostringstream dump_buf;
    std::lock_guard<std::mutex> guard(mLock);
    dump_buf << "========== Begin PowerSessionManager ADPF list ==========\n";
    for (PowerHintSession *s : mSessions) {
        s->dumpToStream(dump_buf);
        dump_buf << " Tid:Ref[";
        for (size_t i = 0, len = s->getTidList().size(); i < len; i++) {
            int t = s->getTidList()[i];
            dump_buf << t << ":" << mTidSessionListMap[t].size();
            if (i < len - 1) {
                dump_buf << ", ";
            }
        }
        dump_buf << "]\n";
    }
    dump_buf << "========== End PowerSessionManager ADPF list ==========\n";
    if (!::android::base::WriteStringToFd(dump_buf.str(), fd)) {
        ALOGE("Failed to dump one of session list to fd:%d", fd);
    }
}

void PowerSessionManager::enableSystemTopAppBoost() {
    if (HintManager::GetInstance()->IsHintSupported(kDisableBoostHintName)) {
        ALOGV("PowerSessionManager::enableSystemTopAppBoost!!");
        HintManager::GetInstance()->EndHint(kDisableBoostHintName);
    }
}

void PowerSessionManager::disableSystemTopAppBoost() {
    if (HintManager::GetInstance()->IsHintSupported(kDisableBoostHintName)) {
        ALOGV("PowerSessionManager::disableSystemTopAppBoost!!");
        HintManager::GetInstance()->DoHint(kDisableBoostHintName);
    }
}

// =========== PowerHintMonitor implementation start from here ===========
void PowerHintMonitor::start() {
    if (!isRunning()) {
        run("PowerHintMonitor", ::android::PRIORITY_HIGHEST);
    }
}

bool PowerHintMonitor::threadLoop() {
    while (true) {
        mLooper->pollOnce(-1);
    }
    return true;
}

sp<Looper> PowerHintMonitor::getLooper() {
    return mLooper;
}

}  // namespace pixel
}  // namespace impl
}  // namespace power
}  // namespace hardware
}  // namespace google
}  // namespace aidl
