611 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			611 lines
		
	
	
		
			24 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(std::shared_ptr<AdaptiveCpu> adaptiveCpu, int32_t tgid,
 | |
|                                    int32_t uid, const std::vector<int32_t> &threadIds,
 | |
|                                    int64_t durationNanos)
 | |
|     : mAdaptiveCpu(adaptiveCpu) {
 | |
|     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) {
 | |
|         if (isAppSession()) {
 | |
|             tryToSendPowerHint("ADPF_FIRST_FRAME");
 | |
|         }
 | |
|         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());
 | |
|     }
 | |
| 
 | |
|     mAdaptiveCpu->ReportWorkDurations(actualDurations, mDescriptor->duration);
 | |
| 
 | |
|     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
 |