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 ¤t = 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