| /* |
| * 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(); |
| } |
| } |
| |
| void PowerHintSession::tryToSendPowerHint(std::string hint) { |
| if (!mSupportedHints[hint].has_value()) { |
| mSupportedHints[hint] = HintManager::GetInstance()->IsHintSupported(hint); |
| } |
| if (mSupportedHints[hint].value()) { |
| HintManager::GetInstance()->DoHint(hint); |
| } |
| } |
| |
| 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 ¤t = 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 |