The main problem is the timer thread could be woken after the session was destroyed. We did have a closed flag which was set in destructor and the flag would be checked before handleMessage accessing the session instance. To fix the problem, the operations of flag checking and session instance accessing should be guarded by the lock. Bug: 236674672 Test: manual test Change-Id: I49a18efbc135b1bc070b101038a8a0bcc6e19fec (cherry picked from commit 5c75978f530b27bd976d8695ed79acd336c24776) Merged-In: I49a18efbc135b1bc070b101038a8a0bcc6e19fec
594 lines
23 KiB
C++
594 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);
|
|
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
|