• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "powerhal-libperfmgr"
18 #define ATRACE_TAG (ATRACE_TAG_POWER | ATRACE_TAG_HAL)
19 
20 #include "PowerHintSession.h"
21 
22 #include <android-base/logging.h>
23 #include <android-base/parsedouble.h>
24 #include <android-base/properties.h>
25 #include <android-base/stringprintf.h>
26 #include <perfmgr/AdpfConfig.h>
27 #include <private/android_filesystem_config.h>
28 #include <sys/syscall.h>
29 #include <time.h>
30 #include <utils/Trace.h>
31 
32 #include <atomic>
33 
34 #include "PowerSessionManager.h"
35 
36 namespace aidl {
37 namespace google {
38 namespace hardware {
39 namespace power {
40 namespace impl {
41 namespace pixel {
42 
43 using ::android::base::StringPrintf;
44 using ::android::perfmgr::AdpfConfig;
45 using ::android::perfmgr::HintManager;
46 using std::chrono::duration_cast;
47 using std::chrono::nanoseconds;
48 
49 namespace {
50 
ns_to_100us(int64_t ns)51 static inline int64_t ns_to_100us(int64_t ns) {
52     return ns / 100000;
53 }
54 
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)55 static int64_t convertWorkDurationToBoostByPid(std::shared_ptr<AdpfConfig> adpfConfig,
56                                                nanoseconds targetDuration,
57                                                const std::vector<WorkDuration> &actualDurations,
58                                                int64_t *integral_error, int64_t *previous_error,
59                                                const std::string &idstr) {
60     uint64_t samplingWindowP = adpfConfig->mSamplingWindowP;
61     uint64_t samplingWindowI = adpfConfig->mSamplingWindowI;
62     uint64_t samplingWindowD = adpfConfig->mSamplingWindowD;
63     int64_t targetDurationNanos = (int64_t)targetDuration.count();
64     int64_t length = actualDurations.size();
65     int64_t p_start =
66             samplingWindowP == 0 || samplingWindowP > length ? 0 : length - samplingWindowP;
67     int64_t i_start =
68             samplingWindowI == 0 || samplingWindowI > length ? 0 : length - samplingWindowI;
69     int64_t d_start =
70             samplingWindowD == 0 || samplingWindowD > length ? 0 : length - samplingWindowD;
71     int64_t dt = ns_to_100us(targetDurationNanos);
72     int64_t err_sum = 0;
73     int64_t derivative_sum = 0;
74     for (int64_t i = std::min({p_start, i_start, d_start}); i < length; i++) {
75         int64_t actualDurationNanos = actualDurations[i].durationNanos;
76         if (std::abs(actualDurationNanos) > targetDurationNanos * 20) {
77             ALOGW("The actual duration is way far from the target (%" PRId64 " >> %" PRId64 ")",
78                   actualDurationNanos, targetDurationNanos);
79         }
80         // PID control algorithm
81         int64_t error = ns_to_100us(actualDurationNanos - targetDurationNanos);
82         if (i >= d_start) {
83             derivative_sum += error - (*previous_error);
84         }
85         if (i >= p_start) {
86             err_sum += error;
87         }
88         if (i >= i_start) {
89             *integral_error = *integral_error + error * dt;
90             *integral_error = std::min(adpfConfig->getPidIHighDivI(), *integral_error);
91             *integral_error = std::max(adpfConfig->getPidILowDivI(), *integral_error);
92         }
93         *previous_error = error;
94     }
95     int64_t pOut = static_cast<int64_t>((err_sum > 0 ? adpfConfig->mPidPo : adpfConfig->mPidPu) *
96                                         err_sum / (length - p_start));
97     int64_t iOut = static_cast<int64_t>(adpfConfig->mPidI * (*integral_error));
98     int64_t dOut =
99             static_cast<int64_t>((derivative_sum > 0 ? adpfConfig->mPidDo : adpfConfig->mPidDu) *
100                                  derivative_sum / dt / (length - d_start));
101 
102     int64_t output = pOut + iOut + dOut;
103     if (ATRACE_ENABLED()) {
104         std::string sz = StringPrintf("adpf.%s-pid.err", idstr.c_str());
105         ATRACE_INT(sz.c_str(), err_sum / (length - p_start));
106         sz = StringPrintf("adpf.%s-pid.integral", idstr.c_str());
107         ATRACE_INT(sz.c_str(), *integral_error);
108         sz = StringPrintf("adpf.%s-pid.derivative", idstr.c_str());
109         ATRACE_INT(sz.c_str(), derivative_sum / dt / (length - d_start));
110         sz = StringPrintf("adpf.%s-pid.pOut", idstr.c_str());
111         ATRACE_INT(sz.c_str(), pOut);
112         sz = StringPrintf("adpf.%s-pid.iOut", idstr.c_str());
113         ATRACE_INT(sz.c_str(), iOut);
114         sz = StringPrintf("adpf.%s-pid.dOut", idstr.c_str());
115         ATRACE_INT(sz.c_str(), dOut);
116         sz = StringPrintf("adpf.%s-pid.output", idstr.c_str());
117         ATRACE_INT(sz.c_str(), output);
118     }
119     return output;
120 }
121 
122 }  // namespace
123 
PowerHintSession(std::shared_ptr<AdaptiveCpu> adaptiveCpu,int32_t tgid,int32_t uid,const std::vector<int32_t> & threadIds,int64_t durationNanos)124 PowerHintSession::PowerHintSession(std::shared_ptr<AdaptiveCpu> adaptiveCpu, int32_t tgid,
125                                    int32_t uid, const std::vector<int32_t> &threadIds,
126                                    int64_t durationNanos)
127     : mAdaptiveCpu(adaptiveCpu) {
128     mDescriptor = new AppHintDesc(tgid, uid, threadIds);
129     mDescriptor->duration = std::chrono::nanoseconds(durationNanos);
130     mStaleTimerHandler = sp<StaleTimerHandler>(new StaleTimerHandler(this));
131     mEarlyBoostHandler = sp<EarlyBoostHandler>(new EarlyBoostHandler(this));
132     mPowerManagerHandler = PowerSessionManager::getInstance();
133     mLastUpdatedTime.store(std::chrono::steady_clock::now());
134     mLastStartedTimeNs =
135             std::chrono::duration_cast<std::chrono::nanoseconds>(
136                     (std::chrono::steady_clock::now() - mDescriptor->duration).time_since_epoch())
137                     .count();
138     mLastDurationNs = durationNanos;
139     mWorkPeriodNs = durationNanos;
140 
141     if (ATRACE_ENABLED()) {
142         const std::string idstr = getIdString();
143         std::string sz = StringPrintf("adpf.%s-target", idstr.c_str());
144         ATRACE_INT(sz.c_str(), (int64_t)mDescriptor->duration.count());
145         sz = StringPrintf("adpf.%s-active", idstr.c_str());
146         ATRACE_INT(sz.c_str(), mDescriptor->is_active.load());
147     }
148     PowerSessionManager::getInstance()->addPowerSession(this);
149     // init boost
150     setSessionUclampMin(HintManager::GetInstance()->GetAdpfProfile()->mUclampMinInit);
151     ALOGV("PowerHintSession created: %s", mDescriptor->toString().c_str());
152 }
153 
~PowerHintSession()154 PowerHintSession::~PowerHintSession() {
155     close();
156     ALOGV("PowerHintSession deleted: %s", mDescriptor->toString().c_str());
157     if (ATRACE_ENABLED()) {
158         const std::string idstr = getIdString();
159         std::string sz = StringPrintf("adpf.%s-target", idstr.c_str());
160         ATRACE_INT(sz.c_str(), 0);
161         sz = StringPrintf("adpf.%s-actl_last", idstr.c_str());
162         ATRACE_INT(sz.c_str(), 0);
163         sz = sz = StringPrintf("adpf.%s-active", idstr.c_str());
164         ATRACE_INT(sz.c_str(), 0);
165     }
166     delete mDescriptor;
167 }
168 
getIdString() const169 std::string PowerHintSession::getIdString() const {
170     std::string idstr = StringPrintf("%" PRId32 "-%" PRId32 "-%" PRIxPTR, mDescriptor->tgid,
171                                      mDescriptor->uid, reinterpret_cast<uintptr_t>(this) & 0xffff);
172     return idstr;
173 }
174 
isAppSession()175 bool PowerHintSession::isAppSession() {
176     // Check if uid is in range reserved for applications
177     return mDescriptor->uid >= AID_APP_START;
178 }
179 
updateUniveralBoostMode()180 void PowerHintSession::updateUniveralBoostMode() {
181     if (!isAppSession()) {
182         return;
183     }
184     if (ATRACE_ENABLED()) {
185         const std::string tag = StringPrintf("%s:updateUniveralBoostMode()", getIdString().c_str());
186         ATRACE_BEGIN(tag.c_str());
187     }
188     PowerHintMonitor::getInstance()->getLooper()->sendMessage(mPowerManagerHandler, NULL);
189     if (ATRACE_ENABLED()) {
190         ATRACE_END();
191     }
192 }
193 
tryToSendPowerHint(std::string hint)194 void PowerHintSession::tryToSendPowerHint(std::string hint) {
195     if (!mSupportedHints[hint].has_value()) {
196         mSupportedHints[hint] = HintManager::GetInstance()->IsHintSupported(hint);
197     }
198     if (mSupportedHints[hint].value()) {
199         HintManager::GetInstance()->DoHint(hint);
200     }
201 }
202 
setSessionUclampMin(int32_t min)203 int PowerHintSession::setSessionUclampMin(int32_t min) {
204     {
205         std::lock_guard<std::mutex> guard(mSessionLock);
206         mDescriptor->current_min = min;
207     }
208     if (min) {
209         mStaleTimerHandler->updateTimer();
210     }
211     PowerSessionManager::getInstance()->setUclampMin(this, min);
212 
213     if (ATRACE_ENABLED()) {
214         const std::string idstr = getIdString();
215         std::string sz = StringPrintf("adpf.%s-min", idstr.c_str());
216         ATRACE_INT(sz.c_str(), min);
217     }
218     return 0;
219 }
220 
getUclampMin()221 int PowerHintSession::getUclampMin() {
222     return mDescriptor->current_min;
223 }
224 
dumpToStream(std::ostream & stream)225 void PowerHintSession::dumpToStream(std::ostream &stream) {
226     stream << "ID.Min.Act.Timeout(" << getIdString();
227     stream << ", " << mDescriptor->current_min;
228     stream << ", " << mDescriptor->is_active;
229     stream << ", " << isTimeout() << ")";
230 }
231 
pause()232 ndk::ScopedAStatus PowerHintSession::pause() {
233     if (mSessionClosed) {
234         ALOGE("Error: session is dead");
235         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
236     }
237     if (!mDescriptor->is_active.load())
238         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
239     // Reset to default uclamp value.
240     mDescriptor->is_active.store(false);
241     setStale();
242     if (ATRACE_ENABLED()) {
243         const std::string idstr = getIdString();
244         std::string sz = StringPrintf("adpf.%s-active", idstr.c_str());
245         ATRACE_INT(sz.c_str(), mDescriptor->is_active.load());
246     }
247     updateUniveralBoostMode();
248     return ndk::ScopedAStatus::ok();
249 }
250 
resume()251 ndk::ScopedAStatus PowerHintSession::resume() {
252     if (mSessionClosed) {
253         ALOGE("Error: session is dead");
254         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
255     }
256     if (mDescriptor->is_active.load())
257         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
258     mDescriptor->is_active.store(true);
259     // resume boost
260     setSessionUclampMin(mDescriptor->current_min);
261     if (ATRACE_ENABLED()) {
262         const std::string idstr = getIdString();
263         std::string sz = StringPrintf("adpf.%s-active", idstr.c_str());
264         ATRACE_INT(sz.c_str(), mDescriptor->is_active.load());
265     }
266     updateUniveralBoostMode();
267     return ndk::ScopedAStatus::ok();
268 }
269 
close()270 ndk::ScopedAStatus PowerHintSession::close() {
271     bool sessionClosedExpectedToBe = false;
272     if (!mSessionClosed.compare_exchange_strong(sessionClosedExpectedToBe, true)) {
273         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
274     }
275     // Remove the session from PowerSessionManager first to avoid racing.
276     PowerSessionManager::getInstance()->removePowerSession(this);
277     mEarlyBoostHandler->setSessionDead();
278     mStaleTimerHandler->setSessionDead();
279     setSessionUclampMin(0);
280     mDescriptor->is_active.store(false);
281     updateUniveralBoostMode();
282     return ndk::ScopedAStatus::ok();
283 }
284 
updateTargetWorkDuration(int64_t targetDurationNanos)285 ndk::ScopedAStatus PowerHintSession::updateTargetWorkDuration(int64_t targetDurationNanos) {
286     if (mSessionClosed) {
287         ALOGE("Error: session is dead");
288         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
289     }
290     if (targetDurationNanos <= 0) {
291         ALOGE("Error: targetDurationNanos(%" PRId64 ") should bigger than 0", targetDurationNanos);
292         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
293     }
294     targetDurationNanos =
295             targetDurationNanos * HintManager::GetInstance()->GetAdpfProfile()->mTargetTimeFactor;
296     ALOGV("update target duration: %" PRId64 " ns", targetDurationNanos);
297 
298     mDescriptor->duration = std::chrono::nanoseconds(targetDurationNanos);
299     if (ATRACE_ENABLED()) {
300         const std::string idstr = getIdString();
301         std::string sz = StringPrintf("adpf.%s-target", idstr.c_str());
302         ATRACE_INT(sz.c_str(), (int64_t)mDescriptor->duration.count());
303     }
304 
305     return ndk::ScopedAStatus::ok();
306 }
307 
reportActualWorkDuration(const std::vector<WorkDuration> & actualDurations)308 ndk::ScopedAStatus PowerHintSession::reportActualWorkDuration(
309         const std::vector<WorkDuration> &actualDurations) {
310     if (mSessionClosed) {
311         ALOGE("Error: session is dead");
312         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
313     }
314     if (mDescriptor->duration.count() == 0LL) {
315         ALOGE("Expect to call updateTargetWorkDuration() first.");
316         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
317     }
318     if (actualDurations.size() == 0) {
319         ALOGE("Error: duration.size() shouldn't be %zu.", actualDurations.size());
320         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
321     }
322     if (!mDescriptor->is_active.load()) {
323         ALOGE("Error: shouldn't report duration during pause state.");
324         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
325     }
326     std::shared_ptr<AdpfConfig> adpfConfig = HintManager::GetInstance()->GetAdpfProfile();
327     mDescriptor->update_count++;
328     bool isFirstFrame = isTimeout();
329     if (ATRACE_ENABLED()) {
330         const std::string idstr = getIdString();
331         std::string sz = StringPrintf("adpf.%s-batch_size", idstr.c_str());
332         ATRACE_INT(sz.c_str(), actualDurations.size());
333         sz = StringPrintf("adpf.%s-actl_last", idstr.c_str());
334         ATRACE_INT(sz.c_str(), actualDurations.back().durationNanos);
335         sz = StringPrintf("adpf.%s-target", idstr.c_str());
336         ATRACE_INT(sz.c_str(), (int64_t)mDescriptor->duration.count());
337         sz = StringPrintf("adpf.%s-hint.count", idstr.c_str());
338         ATRACE_INT(sz.c_str(), mDescriptor->update_count);
339         sz = StringPrintf("adpf.%s-hint.overtime", idstr.c_str());
340         ATRACE_INT(sz.c_str(),
341                    actualDurations.back().durationNanos - mDescriptor->duration.count() > 0);
342     }
343 
344     mLastUpdatedTime.store(std::chrono::steady_clock::now());
345     if (isFirstFrame) {
346         if (isAppSession()) {
347             tryToSendPowerHint("ADPF_FIRST_FRAME");
348         }
349         updateUniveralBoostMode();
350     }
351 
352     if (!adpfConfig->mPidOn) {
353         setSessionUclampMin(adpfConfig->mUclampMinHigh);
354         return ndk::ScopedAStatus::ok();
355     }
356     int64_t output = convertWorkDurationToBoostByPid(
357             adpfConfig, mDescriptor->duration, actualDurations, &(mDescriptor->integral_error),
358             &(mDescriptor->previous_error), getIdString());
359 
360     /* apply to all the threads in the group */
361     int next_min = std::min(static_cast<int>(adpfConfig->mUclampMinHigh),
362                             mDescriptor->current_min + static_cast<int>(output));
363     next_min = std::max(static_cast<int>(adpfConfig->mUclampMinLow), next_min);
364     setSessionUclampMin(next_min);
365     mStaleTimerHandler->updateTimer(getStaleTime());
366     if (HintManager::GetInstance()->GetAdpfProfile()->mEarlyBoostOn) {
367         updateWorkPeriod(actualDurations);
368         mEarlyBoostHandler->updateTimer(getEarlyBoostTime());
369     }
370 
371     mAdaptiveCpu->ReportWorkDurations(actualDurations, mDescriptor->duration);
372 
373     return ndk::ScopedAStatus::ok();
374 }
375 
toString() const376 std::string AppHintDesc::toString() const {
377     std::string out =
378             StringPrintf("session %" PRIxPTR "\n", reinterpret_cast<uintptr_t>(this) & 0xffff);
379     const int64_t durationNanos = duration.count();
380     out.append(StringPrintf("  duration: %" PRId64 " ns\n", durationNanos));
381     out.append(StringPrintf("  uclamp.min: %d \n", current_min));
382     out.append(StringPrintf("  uid: %d, tgid: %d\n", uid, tgid));
383 
384     out.append("  threadIds: [");
385     bool first = true;
386     for (int tid : threadIds) {
387         if (!first) {
388             out.append(", ");
389         }
390         out.append(std::to_string(tid));
391         first = false;
392     }
393     out.append("]\n");
394     return out;
395 }
396 
isActive()397 bool PowerHintSession::isActive() {
398     return mDescriptor->is_active.load();
399 }
400 
isTimeout()401 bool PowerHintSession::isTimeout() {
402     auto now = std::chrono::steady_clock::now();
403     return now >= getStaleTime();
404 }
405 
getTidList() const406 const std::vector<int> &PowerHintSession::getTidList() const {
407     return mDescriptor->threadIds;
408 }
409 
setStale()410 void PowerHintSession::setStale() {
411     // Reset to default uclamp value.
412     PowerSessionManager::getInstance()->setUclampMin(this, 0);
413     // Deliver a task to check if all sessions are inactive.
414     updateUniveralBoostMode();
415     if (ATRACE_ENABLED()) {
416         const std::string idstr = getIdString();
417         std::string sz = StringPrintf("adpf.%s-min", idstr.c_str());
418         ATRACE_INT(sz.c_str(), 0);
419     }
420 }
421 
wakeup()422 void PowerHintSession::wakeup() {
423     std::lock_guard<std::mutex> guard(mSessionLock);
424 
425     // We only wake up non-paused session
426     if (mSessionClosed || !isActive()) {
427         return;
428     }
429     // Update session's timer
430     mStaleTimerHandler->updateTimer();
431     // Skip uclamp update for stale session
432     if (!isTimeout()) {
433         return;
434     }
435     if (ATRACE_ENABLED()) {
436         std::string tag = StringPrintf("wakeup.%s(a:%d,s:%d)", getIdString().c_str(), isActive(),
437                                        isTimeout());
438         ATRACE_NAME(tag.c_str());
439     }
440     std::shared_ptr<AdpfConfig> adpfConfig = HintManager::GetInstance()->GetAdpfProfile();
441     mDescriptor->current_min =
442             std::max(mDescriptor->current_min, static_cast<int>(adpfConfig->mUclampMinInit));
443 
444     if (ATRACE_ENABLED()) {
445         const std::string idstr = getIdString();
446         std::string sz = StringPrintf("adpf.%s-min", idstr.c_str());
447         ATRACE_INT(sz.c_str(), mDescriptor->current_min);
448     }
449 }
450 
updateWorkPeriod(const std::vector<WorkDuration> & actualDurations)451 void PowerHintSession::updateWorkPeriod(const std::vector<WorkDuration> &actualDurations) {
452     if (actualDurations.size() == 0)
453         return;
454     if (actualDurations.size() >= 2) {
455         const WorkDuration &last = actualDurations[actualDurations.size() - 2];
456         mLastStartedTimeNs = last.timeStampNanos - last.durationNanos;
457     }
458     const WorkDuration &current = actualDurations.back();
459     int64_t curr_start = current.timeStampNanos - current.durationNanos;
460     int64_t period = curr_start - mLastStartedTimeNs;
461     if (period > 0 && period < mDescriptor->duration.count() * 2) {
462         // Accounting workload period with moving average for the last 10 workload.
463         mWorkPeriodNs = 0.9 * mWorkPeriodNs + 0.1 * period;
464         if (ATRACE_ENABLED()) {
465             const std::string idstr = getIdString();
466             std::string sz = StringPrintf("adpf.%s-timer.period", idstr.c_str());
467             ATRACE_INT(sz.c_str(), mWorkPeriodNs);
468         }
469     }
470     mLastStartedTimeNs = curr_start;
471     mLastDurationNs = current.durationNanos;
472 }
473 
getEarlyBoostTime()474 time_point<steady_clock> PowerHintSession::getEarlyBoostTime() {
475     std::shared_ptr<AdpfConfig> adpfConfig = HintManager::GetInstance()->GetAdpfProfile();
476     int64_t earlyBoostTimeoutNs =
477             (int64_t)mDescriptor->duration.count() * adpfConfig->mEarlyBoostTimeFactor;
478     time_point<steady_clock> nextStartTime =
479             mLastUpdatedTime.load() + nanoseconds(mWorkPeriodNs - mLastDurationNs);
480     return nextStartTime + nanoseconds(earlyBoostTimeoutNs);
481 }
482 
getStaleTime()483 time_point<steady_clock> PowerHintSession::getStaleTime() {
484     return mLastUpdatedTime.load() +
485            nanoseconds(static_cast<int64_t>(
486                    mDescriptor->duration.count() *
487                    HintManager::GetInstance()->GetAdpfProfile()->mStaleTimeFactor));
488 }
489 
updateTimer()490 void PowerHintSession::StaleTimerHandler::updateTimer() {
491     time_point<steady_clock> staleTime =
492             std::chrono::steady_clock::now() +
493             nanoseconds(static_cast<int64_t>(
494                     mSession->mDescriptor->duration.count() *
495                     HintManager::GetInstance()->GetAdpfProfile()->mStaleTimeFactor));
496     updateTimer(staleTime);
497 }
498 
updateTimer(time_point<steady_clock> staleTime)499 void PowerHintSession::StaleTimerHandler::updateTimer(time_point<steady_clock> staleTime) {
500     mStaleTime.store(staleTime);
501     {
502         std::lock_guard<std::mutex> guard(mMessageLock);
503         PowerHintMonitor::getInstance()->getLooper()->removeMessages(mSession->mStaleTimerHandler);
504         PowerHintMonitor::getInstance()->getLooper()->sendMessage(mSession->mStaleTimerHandler,
505                                                                   NULL);
506     }
507     mIsMonitoring.store(true);
508     if (ATRACE_ENABLED()) {
509         const std::string idstr = mSession->getIdString();
510         std::string sz = StringPrintf("adpf.%s-timer.stale", idstr.c_str());
511         ATRACE_INT(sz.c_str(), 0);
512     }
513 }
514 
handleMessage(const Message &)515 void PowerHintSession::StaleTimerHandler::handleMessage(const Message &) {
516     std::lock_guard<std::mutex> guard(mClosedLock);
517     if (mIsSessionDead) {
518         return;
519     }
520     auto now = std::chrono::steady_clock::now();
521     int64_t next =
522             static_cast<int64_t>(duration_cast<nanoseconds>(mStaleTime.load() - now).count());
523     if (next > 0) {
524         // Schedule for the stale timeout check.
525         std::lock_guard<std::mutex> guard(mMessageLock);
526         PowerHintMonitor::getInstance()->getLooper()->removeMessages(mSession->mStaleTimerHandler);
527         PowerHintMonitor::getInstance()->getLooper()->sendMessageDelayed(
528                 next, mSession->mStaleTimerHandler, NULL);
529     } else {
530         mSession->setStale();
531         mIsMonitoring.store(false);
532         if (ATRACE_ENABLED()) {
533             const std::string idstr = mSession->getIdString();
534             std::string sz = StringPrintf("adpf.%s-timer.earlyboost", idstr.c_str());
535             ATRACE_INT(sz.c_str(), 0);
536         }
537     }
538     if (ATRACE_ENABLED()) {
539         const std::string idstr = mSession->getIdString();
540         std::string sz = StringPrintf("adpf.%s-timer.stale", idstr.c_str());
541         ATRACE_INT(sz.c_str(), mIsMonitoring ? 0 : 1);
542     }
543 }
544 
setSessionDead()545 void PowerHintSession::StaleTimerHandler::setSessionDead() {
546     std::lock_guard<std::mutex> guard(mClosedLock);
547     mIsSessionDead = true;
548     PowerHintMonitor::getInstance()->getLooper()->removeMessages(mSession->mStaleTimerHandler);
549 }
550 
updateTimer(time_point<steady_clock> boostTime)551 void PowerHintSession::EarlyBoostHandler::updateTimer(time_point<steady_clock> boostTime) {
552     mBoostTime.store(boostTime);
553     {
554         std::lock_guard<std::mutex> guard(mMessageLock);
555         PowerHintMonitor::getInstance()->getLooper()->removeMessages(mSession->mEarlyBoostHandler);
556         PowerHintMonitor::getInstance()->getLooper()->sendMessage(mSession->mEarlyBoostHandler,
557                                                                   NULL);
558     }
559     mIsMonitoring.store(true);
560     if (ATRACE_ENABLED()) {
561         const std::string idstr = mSession->getIdString();
562         std::string sz = StringPrintf("adpf.%s-timer.earlyboost", idstr.c_str());
563         ATRACE_INT(sz.c_str(), 1);
564     }
565 }
566 
handleMessage(const Message &)567 void PowerHintSession::EarlyBoostHandler::handleMessage(const Message &) {
568     std::lock_guard<std::mutex> guard(mBoostLock);
569     if (mIsSessionDead) {
570         return;
571     }
572     auto now = std::chrono::steady_clock::now();
573     int64_t next =
574             static_cast<int64_t>(duration_cast<nanoseconds>(mBoostTime.load() - now).count());
575     if (next > 0) {
576         if (ATRACE_ENABLED()) {
577             const std::string idstr = mSession->getIdString();
578             std::string sz = StringPrintf("adpf.%s-timer.earlyboost", idstr.c_str());
579             ATRACE_INT(sz.c_str(), 1);
580         }
581         std::lock_guard<std::mutex> guard(mMessageLock);
582         PowerHintMonitor::getInstance()->getLooper()->removeMessages(mSession->mEarlyBoostHandler);
583         PowerHintMonitor::getInstance()->getLooper()->sendMessageDelayed(
584                 next, mSession->mEarlyBoostHandler, NULL);
585     } else {
586         std::shared_ptr<AdpfConfig> adpfConfig = HintManager::GetInstance()->GetAdpfProfile();
587         PowerSessionManager::getInstance()->setUclampMin(mSession, adpfConfig->mUclampMinHigh);
588         mIsMonitoring.store(false);
589         if (ATRACE_ENABLED()) {
590             const std::string idstr = mSession->getIdString();
591             std::string sz = StringPrintf("adpf.%s-min", idstr.c_str());
592             ATRACE_INT(sz.c_str(), adpfConfig->mUclampMinHigh);
593             sz = StringPrintf("adpf.%s-timer.earlyboost", idstr.c_str());
594             ATRACE_INT(sz.c_str(), 2);
595         }
596     }
597 }
598 
setSessionDead()599 void PowerHintSession::EarlyBoostHandler::setSessionDead() {
600     std::lock_guard<std::mutex> guard(mBoostLock);
601     mIsSessionDead = true;
602     PowerHintMonitor::getInstance()->getLooper()->removeMessages(mSession->mEarlyBoostHandler);
603 }
604 
605 }  // namespace pixel
606 }  // namespace impl
607 }  // namespace power
608 }  // namespace hardware
609 }  // namespace google
610 }  // namespace aidl
611