/*
 * 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 "PowerHintSession.h"

#include <android-base/logging.h>
#include <android-base/parsedouble.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <perfmgr/AdpfConfig.h>
#include <private/android_filesystem_config.h>
#include <sys/syscall.h>
#include <time.h>
#include <utils/Trace.h>

#include <atomic>

#include "PowerSessionManager.h"

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

using ::android::base::StringPrintf;
using ::android::perfmgr::AdpfConfig;
using ::android::perfmgr::HintManager;
using std::chrono::duration_cast;
using std::chrono::nanoseconds;

namespace {

static inline int64_t ns_to_100us(int64_t ns) {
    return ns / 100000;
}

static int64_t convertWorkDurationToBoostByPid(std::shared_ptr<AdpfConfig> adpfConfig,
                                               nanoseconds targetDuration,
                                               const std::vector<WorkDuration> &actualDurations,
                                               int64_t *integral_error, int64_t *previous_error,
                                               const std::string &idstr) {
    uint64_t samplingWindowP = adpfConfig->mSamplingWindowP;
    uint64_t samplingWindowI = adpfConfig->mSamplingWindowI;
    uint64_t samplingWindowD = adpfConfig->mSamplingWindowD;
    int64_t targetDurationNanos = (int64_t)targetDuration.count();
    int64_t length = actualDurations.size();
    int64_t p_start =
            samplingWindowP == 0 || samplingWindowP > length ? 0 : length - samplingWindowP;
    int64_t i_start =
            samplingWindowI == 0 || samplingWindowI > length ? 0 : length - samplingWindowI;
    int64_t d_start =
            samplingWindowD == 0 || samplingWindowD > length ? 0 : length - samplingWindowD;
    int64_t dt = ns_to_100us(targetDurationNanos);
    int64_t err_sum = 0;
    int64_t derivative_sum = 0;
    for (int64_t i = std::min({p_start, i_start, d_start}); i < length; i++) {
        int64_t actualDurationNanos = actualDurations[i].durationNanos;
        if (std::abs(actualDurationNanos) > targetDurationNanos * 20) {
            ALOGW("The actual duration is way far from the target (%" PRId64 " >> %" PRId64 ")",
                  actualDurationNanos, targetDurationNanos);
        }
        // PID control algorithm
        int64_t error = ns_to_100us(actualDurationNanos - targetDurationNanos);
        if (i >= d_start) {
            derivative_sum += error - (*previous_error);
        }
        if (i >= p_start) {
            err_sum += error;
        }
        if (i >= i_start) {
            *integral_error = *integral_error + error * dt;
            *integral_error = std::min(adpfConfig->getPidIHighDivI(), *integral_error);
            *integral_error = std::max(adpfConfig->getPidILowDivI(), *integral_error);
        }
        *previous_error = error;
    }
    int64_t pOut = static_cast<int64_t>((err_sum > 0 ? adpfConfig->mPidPo : adpfConfig->mPidPu) *
                                        err_sum / (length - p_start));
    int64_t iOut = static_cast<int64_t>(adpfConfig->mPidI * (*integral_error));
    int64_t dOut =
            static_cast<int64_t>((derivative_sum > 0 ? adpfConfig->mPidDo : adpfConfig->mPidDu) *
                                 derivative_sum / dt / (length - d_start));

    int64_t output = pOut + iOut + dOut;
    if (ATRACE_ENABLED()) {
        std::string sz = StringPrintf("adpf.%s-pid.err", idstr.c_str());
        ATRACE_INT(sz.c_str(), err_sum / (length - p_start));
        sz = StringPrintf("adpf.%s-pid.integral", idstr.c_str());
        ATRACE_INT(sz.c_str(), *integral_error);
        sz = StringPrintf("adpf.%s-pid.derivative", idstr.c_str());
        ATRACE_INT(sz.c_str(), derivative_sum / dt / (length - d_start));
        sz = StringPrintf("adpf.%s-pid.pOut", idstr.c_str());
        ATRACE_INT(sz.c_str(), pOut);
        sz = StringPrintf("adpf.%s-pid.iOut", idstr.c_str());
        ATRACE_INT(sz.c_str(), iOut);
        sz = StringPrintf("adpf.%s-pid.dOut", idstr.c_str());
        ATRACE_INT(sz.c_str(), dOut);
        sz = StringPrintf("adpf.%s-pid.output", idstr.c_str());
        ATRACE_INT(sz.c_str(), output);
    }
    return output;
}

}  // namespace

PowerHintSession::PowerHintSession(int32_t tgid, int32_t uid, const std::vector<int32_t> &threadIds,
                                   int64_t durationNanos) {
    mDescriptor = new AppHintDesc(tgid, uid, threadIds);
    mDescriptor->duration = std::chrono::nanoseconds(durationNanos);
    mStaleTimerHandler = sp<StaleTimerHandler>(new StaleTimerHandler(this));
    mEarlyBoostHandler = sp<EarlyBoostHandler>(new EarlyBoostHandler(this));
    mPowerManagerHandler = PowerSessionManager::getInstance();
    mLastUpdatedTime.store(std::chrono::steady_clock::now());
    mLastStartedTimeNs =
            std::chrono::duration_cast<std::chrono::nanoseconds>(
                    (std::chrono::steady_clock::now() - mDescriptor->duration).time_since_epoch())
                    .count();
    mLastDurationNs = durationNanos;
    mWorkPeriodNs = durationNanos;

    if (ATRACE_ENABLED()) {
        const std::string idstr = getIdString();
        std::string sz = StringPrintf("adpf.%s-target", idstr.c_str());
        ATRACE_INT(sz.c_str(), (int64_t)mDescriptor->duration.count());
        sz = StringPrintf("adpf.%s-active", idstr.c_str());
        ATRACE_INT(sz.c_str(), mDescriptor->is_active.load());
    }
    PowerSessionManager::getInstance()->addPowerSession(this);
    // init boost
    setSessionUclampMin(HintManager::GetInstance()->GetAdpfProfile()->mUclampMinInit);
    ALOGV("PowerHintSession created: %s", mDescriptor->toString().c_str());
}

PowerHintSession::~PowerHintSession() {
    close();
    ALOGV("PowerHintSession deleted: %s", mDescriptor->toString().c_str());
    if (ATRACE_ENABLED()) {
        const std::string idstr = getIdString();
        std::string sz = StringPrintf("adpf.%s-target", idstr.c_str());
        ATRACE_INT(sz.c_str(), 0);
        sz = StringPrintf("adpf.%s-actl_last", idstr.c_str());
        ATRACE_INT(sz.c_str(), 0);
        sz = sz = StringPrintf("adpf.%s-active", idstr.c_str());
        ATRACE_INT(sz.c_str(), 0);
    }
    delete mDescriptor;
}

std::string PowerHintSession::getIdString() const {
    std::string idstr = StringPrintf("%" PRId32 "-%" PRId32 "-%" PRIxPTR, mDescriptor->tgid,
                                     mDescriptor->uid, reinterpret_cast<uintptr_t>(this) & 0xffff);
    return idstr;
}

bool PowerHintSession::isAppSession() {
    // Check if uid is in range reserved for applications
    return mDescriptor->uid >= AID_APP_START;
}

void PowerHintSession::updateUniveralBoostMode() {
    if (!isAppSession()) {
        return;
    }
    if (ATRACE_ENABLED()) {
        const std::string tag = StringPrintf("%s:updateUniveralBoostMode()", getIdString().c_str());
        ATRACE_BEGIN(tag.c_str());
    }
    PowerHintMonitor::getInstance()->getLooper()->sendMessage(mPowerManagerHandler, NULL);
    if (ATRACE_ENABLED()) {
        ATRACE_END();
    }
}

int PowerHintSession::setSessionUclampMin(int32_t min) {
    {
        std::lock_guard<std::mutex> guard(mSessionLock);
        mDescriptor->current_min = min;
    }
    if (min) {
        mStaleTimerHandler->updateTimer();
    }
    PowerSessionManager::getInstance()->setUclampMin(this, min);

    if (ATRACE_ENABLED()) {
        const std::string idstr = getIdString();
        std::string sz = StringPrintf("adpf.%s-min", idstr.c_str());
        ATRACE_INT(sz.c_str(), min);
    }
    return 0;
}

int PowerHintSession::getUclampMin() {
    return mDescriptor->current_min;
}

void PowerHintSession::dumpToStream(std::ostream &stream) {
    stream << "ID.Min.Act.Timeout(" << getIdString();
    stream << ", " << mDescriptor->current_min;
    stream << ", " << mDescriptor->is_active;
    stream << ", " << isTimeout() << ")";
}

ndk::ScopedAStatus PowerHintSession::pause() {
    if (mSessionClosed) {
        ALOGE("Error: session is dead");
        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
    }
    if (!mDescriptor->is_active.load())
        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
    // Reset to default uclamp value.
    mDescriptor->is_active.store(false);
    setStale();
    if (ATRACE_ENABLED()) {
        const std::string idstr = getIdString();
        std::string sz = StringPrintf("adpf.%s-active", idstr.c_str());
        ATRACE_INT(sz.c_str(), mDescriptor->is_active.load());
    }
    updateUniveralBoostMode();
    return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus PowerHintSession::resume() {
    if (mSessionClosed) {
        ALOGE("Error: session is dead");
        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
    }
    if (mDescriptor->is_active.load())
        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
    mDescriptor->is_active.store(true);
    // resume boost
    setSessionUclampMin(mDescriptor->current_min);
    if (ATRACE_ENABLED()) {
        const std::string idstr = getIdString();
        std::string sz = StringPrintf("adpf.%s-active", idstr.c_str());
        ATRACE_INT(sz.c_str(), mDescriptor->is_active.load());
    }
    updateUniveralBoostMode();
    return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus PowerHintSession::close() {
    bool sessionClosedExpectedToBe = false;
    if (!mSessionClosed.compare_exchange_strong(sessionClosedExpectedToBe, true)) {
        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
    }
    // Remove the session from PowerSessionManager first to avoid racing.
    PowerSessionManager::getInstance()->removePowerSession(this);
    mEarlyBoostHandler->setSessionDead();
    mStaleTimerHandler->setSessionDead();
    setSessionUclampMin(0);
    mDescriptor->is_active.store(false);
    updateUniveralBoostMode();
    return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus PowerHintSession::updateTargetWorkDuration(int64_t targetDurationNanos) {
    if (mSessionClosed) {
        ALOGE("Error: session is dead");
        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
    }
    if (targetDurationNanos <= 0) {
        ALOGE("Error: targetDurationNanos(%" PRId64 ") should bigger than 0", targetDurationNanos);
        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
    }
    targetDurationNanos =
            targetDurationNanos * HintManager::GetInstance()->GetAdpfProfile()->mTargetTimeFactor;
    ALOGV("update target duration: %" PRId64 " ns", targetDurationNanos);

    mDescriptor->duration = std::chrono::nanoseconds(targetDurationNanos);
    if (ATRACE_ENABLED()) {
        const std::string idstr = getIdString();
        std::string sz = StringPrintf("adpf.%s-target", idstr.c_str());
        ATRACE_INT(sz.c_str(), (int64_t)mDescriptor->duration.count());
    }

    return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus PowerHintSession::reportActualWorkDuration(
        const std::vector<WorkDuration> &actualDurations) {
    if (mSessionClosed) {
        ALOGE("Error: session is dead");
        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
    }
    if (mDescriptor->duration.count() == 0LL) {
        ALOGE("Expect to call updateTargetWorkDuration() first.");
        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
    }
    if (actualDurations.size() == 0) {
        ALOGE("Error: duration.size() shouldn't be %zu.", actualDurations.size());
        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
    }
    if (!mDescriptor->is_active.load()) {
        ALOGE("Error: shouldn't report duration during pause state.");
        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
    }
    std::shared_ptr<AdpfConfig> adpfConfig = HintManager::GetInstance()->GetAdpfProfile();
    mDescriptor->update_count++;
    bool isFirstFrame = isTimeout();
    if (ATRACE_ENABLED()) {
        const std::string idstr = getIdString();
        std::string sz = StringPrintf("adpf.%s-batch_size", idstr.c_str());
        ATRACE_INT(sz.c_str(), actualDurations.size());
        sz = StringPrintf("adpf.%s-actl_last", idstr.c_str());
        ATRACE_INT(sz.c_str(), actualDurations.back().durationNanos);
        sz = StringPrintf("adpf.%s-target", idstr.c_str());
        ATRACE_INT(sz.c_str(), (int64_t)mDescriptor->duration.count());
        sz = StringPrintf("adpf.%s-hint.count", idstr.c_str());
        ATRACE_INT(sz.c_str(), mDescriptor->update_count);
        sz = StringPrintf("adpf.%s-hint.overtime", idstr.c_str());
        ATRACE_INT(sz.c_str(),
                   actualDurations.back().durationNanos - mDescriptor->duration.count() > 0);
    }

    mLastUpdatedTime.store(std::chrono::steady_clock::now());
    if (isFirstFrame) {
        updateUniveralBoostMode();
    }

    if (!adpfConfig->mPidOn) {
        setSessionUclampMin(adpfConfig->mUclampMinHigh);
        return ndk::ScopedAStatus::ok();
    }
    int64_t output = convertWorkDurationToBoostByPid(
            adpfConfig, mDescriptor->duration, actualDurations, &(mDescriptor->integral_error),
            &(mDescriptor->previous_error), getIdString());

    /* apply to all the threads in the group */
    int next_min = std::min(static_cast<int>(adpfConfig->mUclampMinHigh),
                            mDescriptor->current_min + static_cast<int>(output));
    next_min = std::max(static_cast<int>(adpfConfig->mUclampMinLow), next_min);
    setSessionUclampMin(next_min);
    mStaleTimerHandler->updateTimer(getStaleTime());
    if (HintManager::GetInstance()->GetAdpfProfile()->mEarlyBoostOn) {
        updateWorkPeriod(actualDurations);
        mEarlyBoostHandler->updateTimer(getEarlyBoostTime());
    }

    return ndk::ScopedAStatus::ok();
}

std::string AppHintDesc::toString() const {
    std::string out =
            StringPrintf("session %" PRIxPTR "\n", reinterpret_cast<uintptr_t>(this) & 0xffff);
    const int64_t durationNanos = duration.count();
    out.append(StringPrintf("  duration: %" PRId64 " ns\n", durationNanos));
    out.append(StringPrintf("  uclamp.min: %d \n", current_min));
    out.append(StringPrintf("  uid: %d, tgid: %d\n", uid, tgid));

    out.append("  threadIds: [");
    bool first = true;
    for (int tid : threadIds) {
        if (!first) {
            out.append(", ");
        }
        out.append(std::to_string(tid));
        first = false;
    }
    out.append("]\n");
    return out;
}

bool PowerHintSession::isActive() {
    return mDescriptor->is_active.load();
}

bool PowerHintSession::isTimeout() {
    auto now = std::chrono::steady_clock::now();
    return now >= getStaleTime();
}

const std::vector<int> &PowerHintSession::getTidList() const {
    return mDescriptor->threadIds;
}

void PowerHintSession::setStale() {
    // Reset to default uclamp value.
    PowerSessionManager::getInstance()->setUclampMin(this, 0);
    // Deliver a task to check if all sessions are inactive.
    updateUniveralBoostMode();
    if (ATRACE_ENABLED()) {
        const std::string idstr = getIdString();
        std::string sz = StringPrintf("adpf.%s-min", idstr.c_str());
        ATRACE_INT(sz.c_str(), 0);
    }
}

void PowerHintSession::wakeup() {
    std::lock_guard<std::mutex> guard(mSessionLock);

    // We only wake up non-paused session
    if (mSessionClosed || !isActive()) {
        return;
    }
    // Update session's timer
    mStaleTimerHandler->updateTimer();
    // Skip uclamp update for stale session
    if (!isTimeout()) {
        return;
    }
    if (ATRACE_ENABLED()) {
        std::string tag = StringPrintf("wakeup.%s(a:%d,s:%d)", getIdString().c_str(), isActive(),
                                       isTimeout());
        ATRACE_NAME(tag.c_str());
    }
    std::shared_ptr<AdpfConfig> adpfConfig = HintManager::GetInstance()->GetAdpfProfile();
    mDescriptor->current_min =
            std::max(mDescriptor->current_min, static_cast<int>(adpfConfig->mUclampMinInit));

    if (ATRACE_ENABLED()) {
        const std::string idstr = getIdString();
        std::string sz = StringPrintf("adpf.%s-min", idstr.c_str());
        ATRACE_INT(sz.c_str(), mDescriptor->current_min);
    }
}

void PowerHintSession::updateWorkPeriod(const std::vector<WorkDuration> &actualDurations) {
    if (actualDurations.size() == 0)
        return;
    if (actualDurations.size() >= 2) {
        const WorkDuration &last = actualDurations[actualDurations.size() - 2];
        mLastStartedTimeNs = last.timeStampNanos - last.durationNanos;
    }
    const WorkDuration &current = actualDurations.back();
    int64_t curr_start = current.timeStampNanos - current.durationNanos;
    int64_t period = curr_start - mLastStartedTimeNs;
    if (period > 0 && period < mDescriptor->duration.count() * 2) {
        // Accounting workload period with moving average for the last 10 workload.
        mWorkPeriodNs = 0.9 * mWorkPeriodNs + 0.1 * period;
        if (ATRACE_ENABLED()) {
            const std::string idstr = getIdString();
            std::string sz = StringPrintf("adpf.%s-timer.period", idstr.c_str());
            ATRACE_INT(sz.c_str(), mWorkPeriodNs);
        }
    }
    mLastStartedTimeNs = curr_start;
    mLastDurationNs = current.durationNanos;
}

time_point<steady_clock> PowerHintSession::getEarlyBoostTime() {
    std::shared_ptr<AdpfConfig> adpfConfig = HintManager::GetInstance()->GetAdpfProfile();
    int64_t earlyBoostTimeoutNs =
            (int64_t)mDescriptor->duration.count() * adpfConfig->mEarlyBoostTimeFactor;
    time_point<steady_clock> nextStartTime =
            mLastUpdatedTime.load() + nanoseconds(mWorkPeriodNs - mLastDurationNs);
    return nextStartTime + nanoseconds(earlyBoostTimeoutNs);
}

time_point<steady_clock> PowerHintSession::getStaleTime() {
    return mLastUpdatedTime.load() +
           nanoseconds(static_cast<int64_t>(
                   mDescriptor->duration.count() *
                   HintManager::GetInstance()->GetAdpfProfile()->mStaleTimeFactor));
}

void PowerHintSession::StaleTimerHandler::updateTimer() {
    time_point<steady_clock> staleTime =
            std::chrono::steady_clock::now() +
            nanoseconds(static_cast<int64_t>(
                    mSession->mDescriptor->duration.count() *
                    HintManager::GetInstance()->GetAdpfProfile()->mStaleTimeFactor));
    updateTimer(staleTime);
}

void PowerHintSession::StaleTimerHandler::updateTimer(time_point<steady_clock> staleTime) {
    mStaleTime.store(staleTime);
    {
        std::lock_guard<std::mutex> guard(mMessageLock);
        PowerHintMonitor::getInstance()->getLooper()->removeMessages(mSession->mStaleTimerHandler);
        PowerHintMonitor::getInstance()->getLooper()->sendMessage(mSession->mStaleTimerHandler,
                                                                  NULL);
    }
    mIsMonitoring.store(true);
    if (ATRACE_ENABLED()) {
        const std::string idstr = mSession->getIdString();
        std::string sz = StringPrintf("adpf.%s-timer.stale", idstr.c_str());
        ATRACE_INT(sz.c_str(), 0);
    }
}

void PowerHintSession::StaleTimerHandler::handleMessage(const Message &) {
    std::lock_guard<std::mutex> guard(mClosedLock);
    if (mIsSessionDead) {
        return;
    }
    auto now = std::chrono::steady_clock::now();
    int64_t next =
            static_cast<int64_t>(duration_cast<nanoseconds>(mStaleTime.load() - now).count());
    if (next > 0) {
        // Schedule for the stale timeout check.
        std::lock_guard<std::mutex> guard(mMessageLock);
        PowerHintMonitor::getInstance()->getLooper()->removeMessages(mSession->mStaleTimerHandler);
        PowerHintMonitor::getInstance()->getLooper()->sendMessageDelayed(
                next, mSession->mStaleTimerHandler, NULL);
    } else {
        mSession->setStale();
        mIsMonitoring.store(false);
        if (ATRACE_ENABLED()) {
            const std::string idstr = mSession->getIdString();
            std::string sz = StringPrintf("adpf.%s-timer.earlyboost", idstr.c_str());
            ATRACE_INT(sz.c_str(), 0);
        }
    }
    if (ATRACE_ENABLED()) {
        const std::string idstr = mSession->getIdString();
        std::string sz = StringPrintf("adpf.%s-timer.stale", idstr.c_str());
        ATRACE_INT(sz.c_str(), mIsMonitoring ? 0 : 1);
    }
}

void PowerHintSession::StaleTimerHandler::setSessionDead() {
    std::lock_guard<std::mutex> guard(mClosedLock);
    mIsSessionDead = true;
    PowerHintMonitor::getInstance()->getLooper()->removeMessages(mSession->mStaleTimerHandler);
}

void PowerHintSession::EarlyBoostHandler::updateTimer(time_point<steady_clock> boostTime) {
    mBoostTime.store(boostTime);
    {
        std::lock_guard<std::mutex> guard(mMessageLock);
        PowerHintMonitor::getInstance()->getLooper()->removeMessages(mSession->mEarlyBoostHandler);
        PowerHintMonitor::getInstance()->getLooper()->sendMessage(mSession->mEarlyBoostHandler,
                                                                  NULL);
    }
    mIsMonitoring.store(true);
    if (ATRACE_ENABLED()) {
        const std::string idstr = mSession->getIdString();
        std::string sz = StringPrintf("adpf.%s-timer.earlyboost", idstr.c_str());
        ATRACE_INT(sz.c_str(), 1);
    }
}

void PowerHintSession::EarlyBoostHandler::handleMessage(const Message &) {
    std::lock_guard<std::mutex> guard(mBoostLock);
    if (mIsSessionDead) {
        return;
    }
    auto now = std::chrono::steady_clock::now();
    int64_t next =
            static_cast<int64_t>(duration_cast<nanoseconds>(mBoostTime.load() - now).count());
    if (next > 0) {
        if (ATRACE_ENABLED()) {
            const std::string idstr = mSession->getIdString();
            std::string sz = StringPrintf("adpf.%s-timer.earlyboost", idstr.c_str());
            ATRACE_INT(sz.c_str(), 1);
        }
        std::lock_guard<std::mutex> guard(mMessageLock);
        PowerHintMonitor::getInstance()->getLooper()->removeMessages(mSession->mEarlyBoostHandler);
        PowerHintMonitor::getInstance()->getLooper()->sendMessageDelayed(
                next, mSession->mEarlyBoostHandler, NULL);
    } else {
        std::shared_ptr<AdpfConfig> adpfConfig = HintManager::GetInstance()->GetAdpfProfile();
        PowerSessionManager::getInstance()->setUclampMin(mSession, adpfConfig->mUclampMinHigh);
        mIsMonitoring.store(false);
        if (ATRACE_ENABLED()) {
            const std::string idstr = mSession->getIdString();
            std::string sz = StringPrintf("adpf.%s-min", idstr.c_str());
            ATRACE_INT(sz.c_str(), adpfConfig->mUclampMinHigh);
            sz = StringPrintf("adpf.%s-timer.earlyboost", idstr.c_str());
            ATRACE_INT(sz.c_str(), 2);
        }
    }
}

void PowerHintSession::EarlyBoostHandler::setSessionDead() {
    std::lock_guard<std::mutex> guard(mBoostLock);
    mIsSessionDead = true;
    PowerHintMonitor::getInstance()->getLooper()->removeMessages(mSession->mEarlyBoostHandler);
}

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