Optimize boost: A more efficient way is to trigger the wakeup boost through mTidSessionListMap, so the time complexity reduce from O(n^3) to O(n^2). The original code path: PSM:wakeSessions() contains a loop that is O(n), inside the loop, it calls to PHS::wakeup() which call to PSM::setUclampMinLocked(), and PSM::setUclampMinLocked() contains two loops O(n^2) The new code path: PSM::wakeSessions() directly checks all the ADPF tasks O(n) and get the wakeup boost value O(n), then directly set the uclamp.min The time complexity lower to O(n^2). Fix unstable boost: The original flow is to find max boost and wake it up from stale state one by one. But the previous woken ones would not be counted when the later ones finding their max boost value. The new flow boost all the tasks first, then wake up all those sessions. Bug: 235510337 Test: Manually playing UIBench -> Transitions -> ActivityTransition Change-Id: I995673b74401e198eb72188134ba1ebc134f971c
597 lines
23 KiB
C++
597 lines
23 KiB
C++
/*
|
|
* Copyright 2021 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 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);
|
|
setSessionUclampMin(0);
|
|
{
|
|
std::lock_guard<std::mutex> guard(mSessionLock);
|
|
mSessionClosed.store(true);
|
|
}
|
|
mDescriptor->is_active.store(false);
|
|
mEarlyBoostHandler->setSessionDead();
|
|
mStaleTimerHandler->setSessionDead();
|
|
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 &) {
|
|
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(mStaleLock);
|
|
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
|