diff --git a/aidl/power-libperfmgr/Power.cpp b/aidl/power-libperfmgr/Power.cpp index 175cc47..eed933d 100644 --- a/aidl/power-libperfmgr/Power.cpp +++ b/aidl/power-libperfmgr/Power.cpp @@ -151,6 +151,7 @@ ndk::ScopedAStatus Power::isModeSupported(Mode type, bool *_aidl_return) { ndk::ScopedAStatus Power::setBoost(Boost type, int32_t durationMs) { LOG(DEBUG) << "Power setBoost: " << toString(type) << " duration: " << durationMs; + PowerSessionManager::getInstance()->updateHintBoost(toString(type), durationMs); switch (type) { case Boost::INTERACTION: if (mSustainedPerfModeOn) { diff --git a/aidl/power-libperfmgr/PowerExt.cpp b/aidl/power-libperfmgr/PowerExt.cpp index 6590cd5..e1a467e 100644 --- a/aidl/power-libperfmgr/PowerExt.cpp +++ b/aidl/power-libperfmgr/PowerExt.cpp @@ -61,6 +61,7 @@ ndk::ScopedAStatus PowerExt::isModeSupported(const std::string &mode, bool *_aid ndk::ScopedAStatus PowerExt::setBoost(const std::string &boost, int32_t durationMs) { LOG(DEBUG) << "PowerExt setBoost: " << boost << " duration: " << durationMs; + PowerSessionManager::getInstance()->updateHintBoost(boost, durationMs); if (durationMs > 0) { HintManager::GetInstance()->DoHint(boost, std::chrono::milliseconds(durationMs)); diff --git a/aidl/power-libperfmgr/PowerHintSession.cpp b/aidl/power-libperfmgr/PowerHintSession.cpp index 18a37a8..32de767 100644 --- a/aidl/power-libperfmgr/PowerHintSession.cpp +++ b/aidl/power-libperfmgr/PowerHintSession.cpp @@ -47,27 +47,6 @@ using std::chrono::duration_cast; using std::chrono::nanoseconds; namespace { -/* there is no glibc or bionic wrapper */ -struct sched_attr { - __u32 size; - __u32 sched_policy; - __u64 sched_flags; - __s32 sched_nice; - __u32 sched_priority; - __u64 sched_runtime; - __u64 sched_deadline; - __u64 sched_period; - __u32 sched_util_min; - __u32 sched_util_max; -}; - -static int sched_setattr(int pid, struct sched_attr *attr, unsigned int flags) { - if (!HintManager::GetInstance()->GetAdpfProfile()->mUclampMinOn) { - ALOGV("PowerHintSession:%s: skip", __func__); - return 0; - } - return syscall(__NR_sched_setattr, pid, attr, flags); -} static inline int64_t ns_to_100us(int64_t ns) { return ns / 100000; @@ -158,7 +137,7 @@ PowerHintSession::PowerHintSession(int32_t tgid, int32_t uid, const std::vector< } PowerSessionManager::getInstance()->addPowerSession(this); // init boost - setUclamp(HintManager::GetInstance()->GetAdpfProfile()->mUclampMinHigh); + setSessionUclampMin(HintManager::GetInstance()->GetAdpfProfile()->mUclampMinInit); ALOGV("PowerHintSession created: %s", mDescriptor->toString().c_str()); } @@ -203,35 +182,24 @@ void PowerHintSession::updateUniveralBoostMode() { } } -int PowerHintSession::setUclamp(int32_t min, bool update) { - std::lock_guard guard(mLock); - min = std::max(0, min); - min = std::min(min, kMaxUclampValue); +int PowerHintSession::setSessionUclampMin(int32_t min) { + { + std::lock_guard guard(mSessionLock); + mDescriptor->current_min = min; + } + 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); } - for (const auto tid : mDescriptor->threadIds) { - sched_attr attr = {}; - attr.size = sizeof(attr); - - attr.sched_flags = (SCHED_FLAG_KEEP_ALL | SCHED_FLAG_UTIL_CLAMP); - attr.sched_util_min = min; - attr.sched_util_max = kMaxUclampValue; - - int ret = sched_setattr(tid, &attr, 0); - if (ret) { - ALOGW("sched_setattr failed for thread %d, err=%d", tid, errno); - } - ALOGV("PowerHintSession tid: %d, uclamp(%d, %d)", tid, min, kMaxUclampValue); - } - if (update) { - mDescriptor->current_min = min; - } return 0; } +int PowerHintSession::getUclampMin() { + return mDescriptor->current_min; +} + ndk::ScopedAStatus PowerHintSession::pause() { if (mSessionClosed) { ALOGE("Error: session is dead"); @@ -240,8 +208,8 @@ ndk::ScopedAStatus PowerHintSession::pause() { if (!mDescriptor->is_active.load()) return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); // Reset to default uclamp value. - setUclamp(0, false); mDescriptor->is_active.store(false); + setStale(); if (ATRACE_ENABLED()) { const std::string idstr = getIdString(); std::string sz = StringPrintf("adpf.%s-active", idstr.c_str()); @@ -261,7 +229,7 @@ ndk::ScopedAStatus PowerHintSession::resume() { mDescriptor->is_active.store(true); mHintTimerHandler->updateHintTimer(0); // resume boost - setUclamp(mDescriptor->current_min, false); + setSessionUclampMin(mDescriptor->current_min); if (ATRACE_ENABLED()) { const std::string idstr = getIdString(); std::string sz = StringPrintf("adpf.%s-active", idstr.c_str()); @@ -276,7 +244,7 @@ ndk::ScopedAStatus PowerHintSession::close() { if (!mSessionClosed.compare_exchange_strong(sessionClosedExpectedToBe, true)) { return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); } - setUclamp(0); + setSessionUclampMin(0); PowerSessionManager::getInstance()->removePowerSession(this); updateUniveralBoostMode(); return ndk::ScopedAStatus::ok(); @@ -340,21 +308,10 @@ ndk::ScopedAStatus PowerHintSession::reportActualWorkDuration( actualDurations.back().durationNanos - mDescriptor->duration.count() > 0); } - if (PowerHintMonitor::getInstance()->isRunning() && isStale()) { - mDescriptor->integral_error = - std::max(adpfConfig->getPidIInitDivI(), mDescriptor->integral_error); - if (ATRACE_ENABLED()) { - const std::string idstr = getIdString(); - std::string sz = StringPrintf("adpf.%s-wakeup", idstr.c_str()); - ATRACE_INT(sz.c_str(), mDescriptor->integral_error); - ATRACE_INT(sz.c_str(), 0); - } - } - mHintTimerHandler->updateHintTimer(actualDurations); if (!adpfConfig->mPidOn) { - setUclamp(adpfConfig->mUclampMinHigh); + setSessionUclampMin(adpfConfig->mUclampMinHigh); return ndk::ScopedAStatus::ok(); } int64_t output = convertWorkDurationToBoostByPid( @@ -365,7 +322,7 @@ ndk::ScopedAStatus PowerHintSession::reportActualWorkDuration( int next_min = std::min(static_cast(adpfConfig->mUclampMinHigh), mDescriptor->current_min + static_cast(output)); next_min = std::max(static_cast(adpfConfig->mUclampMinLow), next_min); - setUclamp(next_min); + setSessionUclampMin(next_min); return ndk::ScopedAStatus::ok(); } @@ -406,13 +363,44 @@ const std::vector &PowerHintSession::getTidList() const { void PowerHintSession::setStale() { // Reset to default uclamp value. - setUclamp(0, false); + PowerSessionManager::getInstance()->setUclampMin(this, 0); // Deliver a task to check if all sessions are inactive. updateUniveralBoostMode(); } +void PowerHintSession::wakeup() { + if (ATRACE_ENABLED()) { + std::string tag = + StringPrintf("wakeup.%s(a:%d,s:%d)", getIdString().c_str(), isActive(), isStale()); + ATRACE_NAME(tag.c_str()); + } + // We only wake up non-paused and stale sessions + if (!isActive() || !isStale()) + return; + std::shared_ptr adpfConfig = HintManager::GetInstance()->GetAdpfProfile(); + int min = std::max(mDescriptor->current_min, static_cast(adpfConfig->mUclampMinInit)); + { + std::lock_guard guard(mSessionLock); + mDescriptor->current_min = min; + } + PowerSessionManager::getInstance()->setUclampMinLocked(this, min); + PowerHintMonitor::getInstance()->getLooper()->removeMessages(mHintTimerHandler); + PowerHintMonitor::getInstance()->getLooper()->sendMessage( + mHintTimerHandler, Message(static_cast(HintTimerHandler::POKE))); + + if (ATRACE_ENABLED()) { + const std::string idstr = getIdString(); + std::string sz = StringPrintf("adpf.%s-min", idstr.c_str()); + ATRACE_INT(sz.c_str(), min); + } +} + void PowerHintSession::HintTimerHandler::updateHintTimer(int64_t actualDurationNs) { std::lock_guard guard(mStaleLock); + PowerHintSession::HintTimerHandler::updateHintTimerLocked(actualDurationNs); +} + +void PowerHintSession::HintTimerHandler::updateHintTimerLocked(int64_t actualDurationNs) { std::shared_ptr adpfConfig = HintManager::GetInstance()->GetAdpfProfile(); HintTimerState prevState = mState; mState = MONITORING; @@ -422,7 +410,7 @@ void PowerHintSession::HintTimerHandler::updateHintTimer(int64_t actualDurationN ? mSession->mDescriptor->work_period : mSession->mDescriptor->duration.count()) - actualDurationNs); - mNextStartTime.store(now + nextStartDur); + mNextStartTime.store(actualDurationNs <= 0 ? now : now + nextStartDur); if (prevState != MONITORING) { int64_t next = static_cast(duration_cast(getEarlyBoostTime() - now).count()); @@ -497,11 +485,15 @@ PowerHintSession::HintTimerHandler::~HintTimerHandler() { ATRACE_CALL(); } -void PowerHintSession::HintTimerHandler::handleMessage(const Message &) { +void PowerHintSession::HintTimerHandler::handleMessage(const Message &msg) { std::lock_guard guard(mStaleLock); if (mIsSessionDead) { return; } + if (msg.what == POKE) { + updateHintTimerLocked(0); + return; + } std::shared_ptr adpfConfig = HintManager::GetInstance()->GetAdpfProfile(); auto now = std::chrono::steady_clock::now(); auto staleTime = getStaleTime(); @@ -513,7 +505,7 @@ void PowerHintSession::HintTimerHandler::handleMessage(const Message &) { // Schedule for the early hint check. PowerHintMonitor::getInstance()->getLooper()->removeMessages(mSession->mHintTimerHandler); PowerHintMonitor::getInstance()->getLooper()->sendMessageDelayed( - next, mSession->mHintTimerHandler, NULL); + next, mSession->mHintTimerHandler, static_cast(HintTimerHandler::TIMER)); if (ATRACE_ENABLED()) { const std::string idstr = mSession->getIdString(); std::string sz = StringPrintf("adpf.%s-timer.nexthint", idstr.c_str()); @@ -525,13 +517,13 @@ void PowerHintSession::HintTimerHandler::handleMessage(const Message &) { } else { // Check if it's time to do early boost. if (adpfConfig->mEarlyBoostOn) { mState = EARLY_BOOST; - mSession->setUclamp(adpfConfig->mUclampMinHigh); + mSession->setSessionUclampMin(adpfConfig->mUclampMinHigh); } int64_t next = static_cast(duration_cast(staleTime - now).count()); // Schedule for the stale timeout check. PowerHintMonitor::getInstance()->getLooper()->removeMessages(mSession->mHintTimerHandler); PowerHintMonitor::getInstance()->getLooper()->sendMessageDelayed( - next, mSession->mHintTimerHandler, NULL); + next, mSession->mHintTimerHandler, static_cast(HintTimerHandler::TIMER)); } if (ATRACE_ENABLED()) { const std::string idstr = mSession->getIdString(); diff --git a/aidl/power-libperfmgr/PowerHintSession.h b/aidl/power-libperfmgr/PowerHintSession.h index 4b28457..bf4280f 100644 --- a/aidl/power-libperfmgr/PowerHintSession.h +++ b/aidl/power-libperfmgr/PowerHintSession.h @@ -41,7 +41,6 @@ using std::chrono::nanoseconds; using std::chrono::steady_clock; using std::chrono::time_point; -static const int32_t kMaxUclampValue = 1024; struct AppHintDesc { AppHintDesc(int32_t tgid, int32_t uid, std::vector threadIds) : tgid(tgid), @@ -49,7 +48,6 @@ struct AppHintDesc { threadIds(std::move(threadIds)), duration(0LL), current_min(0), - transitioanl_min(0), is_active(true), update_count(0), integral_error(0), @@ -62,7 +60,6 @@ struct AppHintDesc { const std::vector threadIds; nanoseconds duration; int current_min; - int transitioanl_min; // status std::atomic is_active; // pid @@ -87,14 +84,20 @@ class PowerHintSession : public BnPowerHintSession { const std::vector &actualDurations) override; bool isActive(); bool isStale(); + void wakeup(); + void setStale(); // Is this hint session for a user application bool isAppSession(); const std::vector &getTidList() const; - int restoreUclamp(); + int getUclampMin(); private: class HintTimerHandler : public MessageHandler { public: + enum MsgType { + TIMER = 0, + POKE, + }; enum HintTimerState { STALE, MONITORING, @@ -109,6 +112,7 @@ class PowerHintSession : public BnPowerHintSession { void handleMessage(const Message &message) override; // Update HintTimer by actual work duration. void updateHintTimer(int64_t actualDurationNs); + void updateHintTimerLocked(int64_t actualDurationNs); // Update HintTimer by a list of work durations which could be used for // calculating the work period. void updateHintTimer(const std::vector &actualDurations); @@ -126,14 +130,13 @@ class PowerHintSession : public BnPowerHintSession { }; private: - void setStale(); void updateUniveralBoostMode(); - int setUclamp(int32_t min, bool update = true); + int setSessionUclampMin(int32_t min); std::string getIdString() const; AppHintDesc *mDescriptor = nullptr; sp mHintTimerHandler; sp mPowerManagerHandler; - std::mutex mLock; + std::mutex mSessionLock; std::atomic mSessionClosed = false; }; diff --git a/aidl/power-libperfmgr/PowerSessionManager.cpp b/aidl/power-libperfmgr/PowerSessionManager.cpp index be03e44..284bd7a 100644 --- a/aidl/power-libperfmgr/PowerSessionManager.cpp +++ b/aidl/power-libperfmgr/PowerSessionManager.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include namespace aidl { @@ -33,6 +34,47 @@ namespace pixel { using ::android::perfmgr::HintManager; +namespace { +/* there is no glibc or bionic wrapper */ +struct sched_attr { + __u32 size; + __u32 sched_policy; + __u64 sched_flags; + __s32 sched_nice; + __u32 sched_priority; + __u64 sched_runtime; + __u64 sched_deadline; + __u64 sched_period; + __u32 sched_util_min; + __u32 sched_util_max; +}; + +static int sched_setattr(int pid, struct sched_attr *attr, unsigned int flags) { + if (!HintManager::GetInstance()->GetAdpfProfile()->mUclampMinOn) { + ALOGV("PowerSessionManager:%s: skip", __func__); + return 0; + } + return syscall(__NR_sched_setattr, pid, attr, flags); +} + +static void set_uclamp_min(int tid, int min) { + static constexpr int32_t kMaxUclampValue = 1024; + min = std::max(0, min); + min = std::min(min, kMaxUclampValue); + + sched_attr attr = {}; + attr.size = sizeof(attr); + + attr.sched_flags = (SCHED_FLAG_KEEP_ALL | SCHED_FLAG_UTIL_CLAMP_MIN); + attr.sched_util_min = min; + + int ret = sched_setattr(tid, &attr, 0); + if (ret) { + ALOGW("sched_setattr failed for thread %d, err=%d", tid, errno); + } +} +} // namespace + void PowerSessionManager::updateHintMode(const std::string &mode, bool enabled) { ALOGV("PowerSessionManager::updateHintMode: mode: %s, enabled: %d", mode.c_str(), enabled); if (enabled && mode.compare(0, 8, "REFRESH_") == 0) { @@ -49,6 +91,22 @@ void PowerSessionManager::updateHintMode(const std::string &mode, bool enabled) } } +void PowerSessionManager::updateHintBoost(const std::string &boost, int32_t durationMs) { + ATRACE_CALL(); + ALOGV("PowerSessionManager::updateHintBoost: boost: %s, durationMs: %d", boost.c_str(), + durationMs); + if (boost.compare("DISPLAY_UPDATE_IMMINENT") == 0) { + wakeSessions(); + } +} + +void PowerSessionManager::wakeSessions() { + std::lock_guard guard(mLock); + for (PowerHintSession *s : mSessions) { + s->wakeup(); + } +} + int PowerSessionManager::getDisplayRefreshRate() { return mDisplayRefreshRate; } @@ -56,6 +114,7 @@ int PowerSessionManager::getDisplayRefreshRate() { void PowerSessionManager::addPowerSession(PowerHintSession *session) { std::lock_guard guard(mLock); for (auto t : session->getTidList()) { + mTidSessionListMap[t].insert(session); if (mTidRefCountMap.find(t) == mTidRefCountMap.end()) { if (!SetTaskProfiles(t, {"ResetUclampGrp"})) { ALOGW("Failed to set ResetUclampGrp task profile for tid:%d", t); @@ -80,6 +139,7 @@ void PowerSessionManager::removePowerSession(PowerHintSession *session) { ALOGE("Unexpected Error! Failed to look up tid:%d in TidRefCountMap", t); continue; } + mTidSessionListMap[t].erase(session); mTidRefCountMap[t]--; if (mTidRefCountMap[t] <= 0) { if (!SetTaskProfiles(t, {"NoResetUclampGrp"})) { @@ -91,6 +151,25 @@ void PowerSessionManager::removePowerSession(PowerHintSession *session) { mSessions.erase(session); } +void PowerSessionManager::setUclampMin(PowerHintSession *session, int val) { + std::lock_guard guard(mLock); + setUclampMinLocked(session, val); +} + +void PowerSessionManager::setUclampMinLocked(PowerHintSession *session, int val) { + for (auto t : session->getTidList()) { + // Get thex max uclamp.min across sessions which include the tid. + int tidMax = 0; + for (PowerHintSession *s : mTidSessionListMap[t]) { + if (!s->isActive() || s->isStale()) + continue; + tidMax = std::max(tidMax, s->getUclampMin()); + } + val = std::max(val, tidMax); + set_uclamp_min(t, val); + } +} + std::optional PowerSessionManager::isAnyAppSessionActive() { std::lock_guard guard(mLock); bool active = false; diff --git a/aidl/power-libperfmgr/PowerSessionManager.h b/aidl/power-libperfmgr/PowerSessionManager.h index 9d3a7de..a244b83 100644 --- a/aidl/power-libperfmgr/PowerSessionManager.h +++ b/aidl/power-libperfmgr/PowerSessionManager.h @@ -45,10 +45,13 @@ class PowerSessionManager : public MessageHandler { public: // current hint info void updateHintMode(const std::string &mode, bool enabled); + void updateHintBoost(const std::string &boost, int32_t durationMs); int getDisplayRefreshRate(); // monitoring session status void addPowerSession(PowerHintSession *session); void removePowerSession(PowerHintSession *session); + void setUclampMin(PowerHintSession *session, int min); + void setUclampMinLocked(PowerHintSession *session, int min); void handleMessage(const Message &message) override; @@ -59,21 +62,27 @@ class PowerSessionManager : public MessageHandler { } private: + void wakeSessions(); std::optional isAnyAppSessionActive(); void disableSystemTopAppBoost(); void enableSystemTopAppBoost(); const std::string kDisableBoostHintName; + std::unordered_set mSessions; // protected by mLock std::unordered_map mTidRefCountMap; // protected by mLock + std::unordered_map> mTidSessionListMap; + bool mActive; // protected by mLock + /** + * mLock to pretect the above data objects opertions. + **/ std::mutex mLock; int mDisplayRefreshRate; - bool mActive; // protected by mLock // Singleton PowerSessionManager() : kDisableBoostHintName(::android::base::GetProperty(kPowerHalAdpfDisableTopAppBoost, "ADPF_DISABLE_TA_BOOST")), - mDisplayRefreshRate(60), - mActive(false) {} + mActive(false), + mDisplayRefreshRate(60) {} PowerSessionManager(PowerSessionManager const &) = delete; void operator=(PowerSessionManager const &) = delete; };