blob: bfdf6676297d04621f4054f49fdd630ef252fb93 [file] [log] [blame]
Michael Wright1509a232018-06-21 02:50:34 +01001/*
2 * Copyright 2018 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
Dan Stoza030fbc12020-02-19 15:32:01 -080017//#define LOG_NDEBUG 0
18
Ady Abrahamabce1652022-02-24 10:51:19 -080019#define ATRACE_TAG ATRACE_TAG_GRAPHICS
20
Michael Wright1509a232018-06-21 02:50:34 +010021#undef LOG_TAG
22#define LOG_TAG "PowerAdvisor"
23
Matt Buckley06f299a2021-09-24 19:43:51 +000024#include <unistd.h>
Michael Wright1509a232018-06-21 02:50:34 +010025#include <cinttypes>
Matt Buckley06f299a2021-09-24 19:43:51 +000026#include <cstdint>
27#include <optional>
Michael Wright1509a232018-06-21 02:50:34 +010028
Dan Stoza030fbc12020-02-19 15:32:01 -080029#include <android-base/properties.h>
Michael Wright1509a232018-06-21 02:50:34 +010030#include <utils/Log.h>
31#include <utils/Mutex.h>
Ady Abrahamabce1652022-02-24 10:51:19 -080032#include <utils/Trace.h>
Michael Wright1509a232018-06-21 02:50:34 +010033
Dan Stoza030fbc12020-02-19 15:32:01 -080034#include <android/hardware/power/1.3/IPower.h>
Matt Buckley06f299a2021-09-24 19:43:51 +000035#include <android/hardware/power/IPowerHintSession.h>
36#include <android/hardware/power/WorkDuration.h>
37
Dan Stoza030fbc12020-02-19 15:32:01 -080038#include <binder/IServiceManager.h>
39
40#include "../SurfaceFlingerProperties.h"
41
Michael Wright1509a232018-06-21 02:50:34 +010042#include "PowerAdvisor.h"
Alec Mouridea1ac52021-06-23 18:12:18 -070043#include "SurfaceFlinger.h"
Michael Wright1509a232018-06-21 02:50:34 +010044
45namespace android {
46namespace Hwc2 {
47
48PowerAdvisor::~PowerAdvisor() = default;
49
50namespace impl {
51
52namespace V1_0 = android::hardware::power::V1_0;
Dan Stoza030fbc12020-02-19 15:32:01 -080053namespace V1_3 = android::hardware::power::V1_3;
Michael Wright1509a232018-06-21 02:50:34 +010054using V1_3::PowerHint;
55
Dan Stoza030fbc12020-02-19 15:32:01 -080056using android::hardware::power::Boost;
57using android::hardware::power::IPower;
Matt Buckley06f299a2021-09-24 19:43:51 +000058using android::hardware::power::IPowerHintSession;
Dan Stoza030fbc12020-02-19 15:32:01 -080059using android::hardware::power::Mode;
Matt Buckley06f299a2021-09-24 19:43:51 +000060using android::hardware::power::WorkDuration;
61
Dan Stoza030fbc12020-02-19 15:32:01 -080062using scheduler::OneShotTimer;
63
Michael Wright1509a232018-06-21 02:50:34 +010064PowerAdvisor::~PowerAdvisor() = default;
65
Dan Stoza030fbc12020-02-19 15:32:01 -080066namespace {
67int32_t getUpdateTimeout() {
68 // Default to a timeout of 80ms if nothing else is specified
69 static int32_t timeout = sysprop::display_update_imminent_timeout_ms(80);
70 return timeout;
71}
72
Ady Abrahamabce1652022-02-24 10:51:19 -080073void traceExpensiveRendering(bool enabled) {
74 if (enabled) {
75 ATRACE_ASYNC_BEGIN("ExpensiveRendering", 0);
76 } else {
77 ATRACE_ASYNC_END("ExpensiveRendering", 0);
78 }
79}
80
Dan Stoza030fbc12020-02-19 15:32:01 -080081} // namespace
82
Alec Mouri19609692022-05-05 23:40:07 +000083PowerAdvisor::PowerAdvisor(SurfaceFlinger& flinger) : mFlinger(flinger) {
84 if (getUpdateTimeout()) {
85 mScreenUpdateTimer.emplace("UpdateImminentTimer",
86 OneShotTimer::Interval(getUpdateTimeout()),
87 /* resetCallback */ nullptr,
88 /* timeoutCallback */
89 [this] {
90 const nsecs_t timeSinceLastUpdate =
91 systemTime() - mLastScreenUpdatedTime.load();
92 if (timeSinceLastUpdate < getUpdateTimeout()) {
93 // We may try to disable expensive rendering and allow
94 // for sending DISPLAY_UPDATE_IMMINENT hints too early if
95 // we idled very shortly after updating the screen, so
96 // make sure we wait enough time.
97 std::this_thread::sleep_for(std::chrono::nanoseconds(
98 getUpdateTimeout() - timeSinceLastUpdate));
99 }
100 mSendUpdateImminent.store(true);
101 mFlinger.disableExpensiveRendering();
102 });
103 }
104}
Alec Mouridea1ac52021-06-23 18:12:18 -0700105
106void PowerAdvisor::init() {
107 // Defer starting the screen update timer until SurfaceFlinger finishes construction.
Alec Mouri19609692022-05-05 23:40:07 +0000108 if (mScreenUpdateTimer) {
109 mScreenUpdateTimer->start();
Dan Stoza030fbc12020-02-19 15:32:01 -0800110 }
111}
Michael Wright1509a232018-06-21 02:50:34 +0100112
Dan Stoza29e7bdf2020-03-23 14:43:09 -0700113void PowerAdvisor::onBootFinished() {
114 mBootFinished.store(true);
115}
116
Peiyong Lin74ca2f42019-01-14 19:36:57 -0800117void PowerAdvisor::setExpensiveRenderingExpected(DisplayId displayId, bool expected) {
Michael Wright1509a232018-06-21 02:50:34 +0100118 if (expected) {
119 mExpensiveDisplays.insert(displayId);
120 } else {
121 mExpensiveDisplays.erase(displayId);
122 }
123
Michael Wright1509a232018-06-21 02:50:34 +0100124 const bool expectsExpensiveRendering = !mExpensiveDisplays.empty();
125 if (mNotifiedExpensiveRendering != expectsExpensiveRendering) {
Dan Stoza20950002020-06-18 14:56:58 -0700126 std::lock_guard lock(mPowerHalMutex);
Dan Stoza030fbc12020-02-19 15:32:01 -0800127 HalWrapper* const halWrapper = getPowerHal();
128 if (halWrapper == nullptr) {
Peiyong Lin81934972018-07-02 11:00:54 -0700129 return;
130 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800131
132 if (!halWrapper->setExpensiveRendering(expectsExpensiveRendering)) {
133 // The HAL has become unavailable; attempt to reconnect later
Michael Wright1509a232018-06-21 02:50:34 +0100134 mReconnectPowerHal = true;
135 return;
136 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800137
Michael Wright1509a232018-06-21 02:50:34 +0100138 mNotifiedExpensiveRendering = expectsExpensiveRendering;
139 }
140}
141
Dan Stoza030fbc12020-02-19 15:32:01 -0800142void PowerAdvisor::notifyDisplayUpdateImminent() {
Dan Stoza29e7bdf2020-03-23 14:43:09 -0700143 // Only start sending this notification once the system has booted so we don't introduce an
144 // early-boot dependency on Power HAL
145 if (!mBootFinished.load()) {
146 return;
147 }
148
Alec Mouri19609692022-05-05 23:40:07 +0000149 if (mSendUpdateImminent.exchange(false)) {
Dan Stoza20950002020-06-18 14:56:58 -0700150 std::lock_guard lock(mPowerHalMutex);
Dan Stoza030fbc12020-02-19 15:32:01 -0800151 HalWrapper* const halWrapper = getPowerHal();
152 if (halWrapper == nullptr) {
153 return;
154 }
155
156 if (!halWrapper->notifyDisplayUpdateImminent()) {
157 // The HAL has become unavailable; attempt to reconnect later
158 mReconnectPowerHal = true;
159 return;
160 }
Alec Mouri19609692022-05-05 23:40:07 +0000161
162 if (mScreenUpdateTimer) {
163 mScreenUpdateTimer->reset();
164 } else {
165 // If we don't have a screen update timer, then we don't throttle power hal calls so
166 // flip this bit back to allow for calling into power hal again.
167 mSendUpdateImminent.store(true);
168 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800169 }
170
Alec Mouri19609692022-05-05 23:40:07 +0000171 if (mScreenUpdateTimer) {
172 mLastScreenUpdatedTime.store(systemTime());
Dan Stoza030fbc12020-02-19 15:32:01 -0800173 }
174}
175
Matt Buckley06f299a2021-09-24 19:43:51 +0000176// checks both if it supports and if it's enabled
177bool PowerAdvisor::usePowerHintSession() {
178 // uses cached value since the underlying support and flag are unlikely to change at runtime
Matt Buckley06f299a2021-09-24 19:43:51 +0000179 return mPowerHintEnabled.value_or(false) && supportsPowerHintSession();
180}
181
182bool PowerAdvisor::supportsPowerHintSession() {
183 // cache to avoid needing lock every time
184 if (!mSupportsPowerHint.has_value()) {
185 std::lock_guard lock(mPowerHalMutex);
186 HalWrapper* const halWrapper = getPowerHal();
187 mSupportsPowerHint = halWrapper->supportsPowerHintSession();
188 }
189 return *mSupportsPowerHint;
190}
191
192bool PowerAdvisor::isPowerHintSessionRunning() {
193 return mPowerHintSessionRunning;
194}
195
196void PowerAdvisor::setTargetWorkDuration(int64_t targetDurationNanos) {
Matt Buckleyef51fba2021-10-12 19:30:12 +0000197 if (!usePowerHintSession()) {
Matt Buckley06f299a2021-09-24 19:43:51 +0000198 ALOGV("Power hint session target duration cannot be set, skipping");
199 return;
200 }
201 {
202 std::lock_guard lock(mPowerHalMutex);
203 HalWrapper* const halWrapper = getPowerHal();
204 if (halWrapper != nullptr) {
Matt Buckleyef51fba2021-10-12 19:30:12 +0000205 halWrapper->setTargetWorkDuration(targetDurationNanos - kTargetSafetyMargin.count());
Matt Buckley06f299a2021-09-24 19:43:51 +0000206 }
207 }
208}
209
210void PowerAdvisor::sendActualWorkDuration(int64_t actualDurationNanos, nsecs_t timeStampNanos) {
211 if (!mBootFinished || !usePowerHintSession()) {
212 ALOGV("Actual work duration power hint cannot be sent, skipping");
213 return;
214 }
215 {
216 std::lock_guard lock(mPowerHalMutex);
217 HalWrapper* const halWrapper = getPowerHal();
218 if (halWrapper != nullptr) {
219 halWrapper->sendActualWorkDuration(actualDurationNanos, timeStampNanos);
220 }
221 }
222}
223
224// needs to be set after the flag is known but before PowerAdvisor enters onBootFinished
225void PowerAdvisor::enablePowerHint(bool enabled) {
226 mPowerHintEnabled = enabled;
227}
228
Matt Buckleyef51fba2021-10-12 19:30:12 +0000229bool PowerAdvisor::startPowerHintSession(const std::vector<int32_t>& threadIds) {
230 if (!usePowerHintSession()) {
231 ALOGI("Power hint session cannot be started, skipping");
232 }
233 {
234 std::lock_guard lock(mPowerHalMutex);
235 HalWrapper* halWrapper = getPowerHal();
236 if (halWrapper != nullptr && usePowerHintSession()) {
237 halWrapper->setPowerHintSessionThreadIds(threadIds);
238 mPowerHintSessionRunning = halWrapper->startPowerHintSession();
239 }
240 }
241 return mPowerHintSessionRunning;
242}
243
Dan Stoza030fbc12020-02-19 15:32:01 -0800244class HidlPowerHalWrapper : public PowerAdvisor::HalWrapper {
245public:
246 HidlPowerHalWrapper(sp<V1_3::IPower> powerHal) : mPowerHal(std::move(powerHal)) {}
247
248 ~HidlPowerHalWrapper() override = default;
249
250 static std::unique_ptr<HalWrapper> connect() {
251 // Power HAL 1.3 is not guaranteed to be available, thus we need to query
252 // Power HAL 1.0 first and try to cast it to Power HAL 1.3.
Dan Stoza030fbc12020-02-19 15:32:01 -0800253 sp<V1_3::IPower> powerHal = nullptr;
Dan Stoza9c051c02020-02-28 10:19:07 -0800254 sp<V1_0::IPower> powerHal_1_0 = V1_0::IPower::getService();
255 if (powerHal_1_0 != nullptr) {
256 // Try to cast to Power HAL 1.3
257 powerHal = V1_3::IPower::castFrom(powerHal_1_0);
258 if (powerHal == nullptr) {
259 ALOGW("No Power HAL 1.3 service in system, disabling PowerAdvisor");
260 } else {
261 ALOGI("Loaded Power HAL 1.3 service");
Dan Stoza030fbc12020-02-19 15:32:01 -0800262 }
Dan Stoza9c051c02020-02-28 10:19:07 -0800263 } else {
264 ALOGW("No Power HAL found, disabling PowerAdvisor");
Dan Stoza030fbc12020-02-19 15:32:01 -0800265 }
Dan Stoza9c051c02020-02-28 10:19:07 -0800266
Dan Stoza030fbc12020-02-19 15:32:01 -0800267 if (powerHal == nullptr) {
268 return nullptr;
269 }
270
271 return std::make_unique<HidlPowerHalWrapper>(std::move(powerHal));
272 }
273
274 bool setExpensiveRendering(bool enabled) override {
275 ALOGV("HIDL setExpensiveRendering %s", enabled ? "T" : "F");
276 auto ret = mPowerHal->powerHintAsync_1_3(PowerHint::EXPENSIVE_RENDERING, enabled);
Ady Abrahamabce1652022-02-24 10:51:19 -0800277 if (ret.isOk()) {
278 traceExpensiveRendering(enabled);
279 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800280 return ret.isOk();
281 }
282
283 bool notifyDisplayUpdateImminent() override {
284 // Power HAL 1.x doesn't have a notification for this
285 ALOGV("HIDL notifyUpdateImminent received but can't send");
286 return true;
287 }
288
Matt Buckley06f299a2021-09-24 19:43:51 +0000289 bool supportsPowerHintSession() override { return false; }
290
291 bool isPowerHintSessionRunning() override { return false; }
292
293 void restartPowerHintSession() override {}
294
295 void setPowerHintSessionThreadIds(const std::vector<int32_t>&) override {}
296
297 bool startPowerHintSession() override { return false; }
298
299 void setTargetWorkDuration(int64_t) override {}
300
301 void sendActualWorkDuration(int64_t, nsecs_t) override {}
302
303 bool shouldReconnectHAL() override { return false; }
304
305 std::vector<int32_t> getPowerHintSessionThreadIds() override { return std::vector<int32_t>{}; }
306
307 std::optional<int64_t> getTargetWorkDuration() override { return std::nullopt; }
308
Dan Stoza030fbc12020-02-19 15:32:01 -0800309private:
Dan Stoza030fbc12020-02-19 15:32:01 -0800310 const sp<V1_3::IPower> mPowerHal = nullptr;
311};
312
Xiang Wange12b4fa2022-03-25 23:48:40 +0000313AidlPowerHalWrapper::AidlPowerHalWrapper(sp<IPower> powerHal) : mPowerHal(std::move(powerHal)) {
314 auto ret = mPowerHal->isModeSupported(Mode::EXPENSIVE_RENDERING, &mHasExpensiveRendering);
315 if (!ret.isOk()) {
316 mHasExpensiveRendering = false;
Dan Stoza030fbc12020-02-19 15:32:01 -0800317 }
318
Xiang Wange12b4fa2022-03-25 23:48:40 +0000319 ret = mPowerHal->isBoostSupported(Boost::DISPLAY_UPDATE_IMMINENT, &mHasDisplayUpdateImminent);
320 if (!ret.isOk()) {
321 mHasDisplayUpdateImminent = false;
Dan Stoza030fbc12020-02-19 15:32:01 -0800322 }
323
Xiang Wange12b4fa2022-03-25 23:48:40 +0000324 mSupportsPowerHint = checkPowerHintSessionSupported();
325}
Dan Stoza030fbc12020-02-19 15:32:01 -0800326
Xiang Wange12b4fa2022-03-25 23:48:40 +0000327AidlPowerHalWrapper::~AidlPowerHalWrapper() {
328 if (mPowerHintSession != nullptr) {
329 mPowerHintSession->close();
330 mPowerHintSession = nullptr;
Dan Stoza030fbc12020-02-19 15:32:01 -0800331 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800332};
333
Xiang Wange12b4fa2022-03-25 23:48:40 +0000334std::unique_ptr<PowerAdvisor::HalWrapper> AidlPowerHalWrapper::connect() {
335 // This only waits if the service is actually declared
336 sp<IPower> powerHal = waitForVintfService<IPower>();
337 if (powerHal == nullptr) {
338 return nullptr;
339 }
340 ALOGI("Loaded AIDL Power HAL service");
341
342 return std::make_unique<AidlPowerHalWrapper>(std::move(powerHal));
343}
344
345bool AidlPowerHalWrapper::setExpensiveRendering(bool enabled) {
346 ALOGV("AIDL setExpensiveRendering %s", enabled ? "T" : "F");
347 if (!mHasExpensiveRendering) {
348 ALOGV("Skipped sending EXPENSIVE_RENDERING because HAL doesn't support it");
349 return true;
350 }
351
352 auto ret = mPowerHal->setMode(Mode::EXPENSIVE_RENDERING, enabled);
353 if (ret.isOk()) {
354 traceExpensiveRendering(enabled);
355 }
356 return ret.isOk();
357}
358
359bool AidlPowerHalWrapper::notifyDisplayUpdateImminent() {
360 ALOGV("AIDL notifyDisplayUpdateImminent");
361 if (!mHasDisplayUpdateImminent) {
362 ALOGV("Skipped sending DISPLAY_UPDATE_IMMINENT because HAL doesn't support it");
363 return true;
364 }
365
366 auto ret = mPowerHal->setBoost(Boost::DISPLAY_UPDATE_IMMINENT, 0);
367 return ret.isOk();
368}
369
370// only version 2+ of the aidl supports power hint sessions, hidl has no support
371bool AidlPowerHalWrapper::supportsPowerHintSession() {
372 return mSupportsPowerHint;
373}
374
375bool AidlPowerHalWrapper::checkPowerHintSessionSupported() {
376 int64_t unused;
377 // Try to get preferred rate to determine if hint sessions are supported
378 // We check for isOk not EX_UNSUPPORTED_OPERATION to lump together errors
379 return mPowerHal->getHintSessionPreferredRate(&unused).isOk();
380}
381
382bool AidlPowerHalWrapper::isPowerHintSessionRunning() {
383 return mPowerHintSession != nullptr;
384}
385
386void AidlPowerHalWrapper::closePowerHintSession() {
387 if (mPowerHintSession != nullptr) {
388 mPowerHintSession->close();
389 mPowerHintSession = nullptr;
390 }
391}
392
393void AidlPowerHalWrapper::restartPowerHintSession() {
394 closePowerHintSession();
395 startPowerHintSession();
396}
397
398void AidlPowerHalWrapper::setPowerHintSessionThreadIds(const std::vector<int32_t>& threadIds) {
399 if (threadIds != mPowerHintThreadIds) {
400 mPowerHintThreadIds = threadIds;
401 if (isPowerHintSessionRunning()) {
402 restartPowerHintSession();
403 }
404 }
405}
406
407bool AidlPowerHalWrapper::startPowerHintSession() {
408 if (mPowerHintSession != nullptr || mPowerHintThreadIds.empty()) {
409 ALOGV("Cannot start power hint session, skipping");
410 return false;
411 }
412 auto ret =
413 mPowerHal->createHintSession(getpid(), static_cast<int32_t>(getuid()),
414 mPowerHintThreadIds, mTargetDuration, &mPowerHintSession);
415 if (!ret.isOk()) {
416 ALOGW("Failed to start power hint session with error: %s",
417 ret.exceptionToString(ret.exceptionCode()).c_str());
418 } else {
419 mLastTargetDurationSent = mTargetDuration;
420 }
421 return isPowerHintSessionRunning();
422}
423
424bool AidlPowerHalWrapper::shouldSetTargetDuration(int64_t targetDurationNanos) {
425 if (targetDurationNanos <= 0) {
426 return false;
427 }
428 // report if the change in target from our last submission to now exceeds the threshold
429 return abs(1.0 -
430 static_cast<double>(mLastTargetDurationSent) /
431 static_cast<double>(targetDurationNanos)) >= kAllowedTargetDeviationPercent;
432}
433
434void AidlPowerHalWrapper::setTargetWorkDuration(int64_t targetDurationNanos) {
435 ATRACE_CALL();
436 mTargetDuration = targetDurationNanos;
437 if (sTraceHintSessionData) ATRACE_INT64("Time target", targetDurationNanos);
438 if (!sNormalizeTarget && isPowerHintSessionRunning() &&
439 shouldSetTargetDuration(targetDurationNanos)) {
440 if (mLastActualDurationSent.has_value()) {
441 // update the error term here since we are actually sending an update to powerhal
442 if (sTraceHintSessionData)
443 ATRACE_INT64("Target error term", targetDurationNanos - *mLastActualDurationSent);
444 }
445 ALOGV("Sending target time: %" PRId64 "ns", targetDurationNanos);
446 mLastTargetDurationSent = targetDurationNanos;
447 auto ret = mPowerHintSession->updateTargetWorkDuration(targetDurationNanos);
448 if (!ret.isOk()) {
449 ALOGW("Failed to set power hint target work duration with error: %s",
450 ret.exceptionMessage().c_str());
451 mShouldReconnectHal = true;
452 }
453 }
454}
455
456bool AidlPowerHalWrapper::shouldReportActualDurationsNow() {
457 // report if we have never reported before or are approaching a stale session
458 if (!mLastActualDurationSent.has_value() ||
459 (systemTime() - mLastActualReportTimestamp) > kStaleTimeout.count()) {
460 return true;
461 }
462
463 if (!mActualDuration.has_value()) {
464 return false;
465 }
466
467 // duration of most recent timing
468 const double mostRecentActualDuration = static_cast<double>(*mActualDuration);
469 // duration of the last timing actually reported to the powerhal
470 const double lastReportedActualDuration = static_cast<double>(*mLastActualDurationSent);
471
472 // report if the change in duration from then to now exceeds the threshold
473 return abs(1.0 - mostRecentActualDuration / lastReportedActualDuration) >=
474 kAllowedActualDeviationPercent;
475}
476
477void AidlPowerHalWrapper::sendActualWorkDuration(int64_t actualDurationNanos,
478 nsecs_t timeStampNanos) {
479 ATRACE_CALL();
480
481 if (actualDurationNanos < 0 || !isPowerHintSessionRunning()) {
482 ALOGV("Failed to send actual work duration, skipping");
483 return;
484 }
Xiang Wang0aba49e2022-04-06 16:13:59 +0000485 nsecs_t reportedDuration = actualDurationNanos;
Xiang Wange12b4fa2022-03-25 23:48:40 +0000486
487 // normalize the sent values to a pre-set target
488 if (sNormalizeTarget) {
Xiang Wang0aba49e2022-04-06 16:13:59 +0000489 reportedDuration += mLastTargetDurationSent - mTargetDuration;
490 } else {
491 // when target duration change is within deviation and not updated, adjust the actual
492 // duration proportionally based on the difference, e.g. if new target is 5ms longer than
493 // last reported but actual duration is the same as last target, we want to report a smaller
494 // actual work duration now to indicate that we are overshooting
495 if (mLastTargetDurationSent != kDefaultTarget.count() && mTargetDuration != 0) {
496 reportedDuration =
497 static_cast<int64_t>(static_cast<long double>(mLastTargetDurationSent) /
498 mTargetDuration * actualDurationNanos);
499 mActualDuration = reportedDuration;
500 }
Xiang Wange12b4fa2022-03-25 23:48:40 +0000501 }
Xiang Wang0aba49e2022-04-06 16:13:59 +0000502 mActualDuration = reportedDuration;
503 WorkDuration duration;
504 duration.durationNanos = reportedDuration;
Xiang Wange12b4fa2022-03-25 23:48:40 +0000505 duration.timeStampNanos = timeStampNanos;
506 mPowerHintQueue.push_back(duration);
507
Xiang Wange12b4fa2022-03-25 23:48:40 +0000508 if (sTraceHintSessionData) {
Xiang Wang0aba49e2022-04-06 16:13:59 +0000509 ATRACE_INT64("Measured duration", actualDurationNanos);
510 ATRACE_INT64("Target error term", mTargetDuration - actualDurationNanos);
511
512 ATRACE_INT64("Reported duration", reportedDuration);
513 ATRACE_INT64("Reported target", mLastTargetDurationSent);
514 ATRACE_INT64("Reported target error term", mLastTargetDurationSent - reportedDuration);
Xiang Wange12b4fa2022-03-25 23:48:40 +0000515 }
516
Xiang Wang0aba49e2022-04-06 16:13:59 +0000517 ALOGV("Sending actual work duration of: %" PRId64 " on reported target: %" PRId64
Xiang Wange12b4fa2022-03-25 23:48:40 +0000518 " with error: %" PRId64,
Xiang Wang0aba49e2022-04-06 16:13:59 +0000519 reportedDuration, mLastTargetDurationSent, mLastTargetDurationSent - reportedDuration);
Xiang Wange12b4fa2022-03-25 23:48:40 +0000520
521 // This rate limiter queues similar duration reports to the powerhal into
522 // batches to avoid excessive binder calls. The criteria to send a given batch
523 // are outlined in shouldReportActualDurationsNow()
524 if (shouldReportActualDurationsNow()) {
525 ALOGV("Sending hint update batch");
526 mLastActualReportTimestamp = systemTime();
527 auto ret = mPowerHintSession->reportActualWorkDuration(mPowerHintQueue);
528 if (!ret.isOk()) {
529 ALOGW("Failed to report actual work durations with error: %s",
530 ret.exceptionMessage().c_str());
531 mShouldReconnectHal = true;
532 }
533 mPowerHintQueue.clear();
534 // we save the non-normalized value here to detect % changes
Xiang Wang0aba49e2022-04-06 16:13:59 +0000535 mLastActualDurationSent = reportedDuration;
Xiang Wange12b4fa2022-03-25 23:48:40 +0000536 }
537}
538
539bool AidlPowerHalWrapper::shouldReconnectHAL() {
540 return mShouldReconnectHal;
541}
542
543std::vector<int32_t> AidlPowerHalWrapper::getPowerHintSessionThreadIds() {
544 return mPowerHintThreadIds;
545}
546
547std::optional<int64_t> AidlPowerHalWrapper::getTargetWorkDuration() {
548 return mTargetDuration;
549}
550
Matt Buckleyef51fba2021-10-12 19:30:12 +0000551const bool AidlPowerHalWrapper::sTraceHintSessionData =
552 base::GetBoolProperty(std::string("debug.sf.trace_hint_sessions"), false);
553
554const bool AidlPowerHalWrapper::sNormalizeTarget =
Xiang Wang76236e12022-03-22 17:25:30 +0000555 base::GetBoolProperty(std::string("debug.sf.normalize_hint_session_durations"), false);
Matt Buckleyef51fba2021-10-12 19:30:12 +0000556
Dan Stoza030fbc12020-02-19 15:32:01 -0800557PowerAdvisor::HalWrapper* PowerAdvisor::getPowerHal() {
558 static std::unique_ptr<HalWrapper> sHalWrapper = nullptr;
Dan Stoza9c051c02020-02-28 10:19:07 -0800559 static bool sHasHal = true;
Michael Wright1509a232018-06-21 02:50:34 +0100560
Dan Stoza9c051c02020-02-28 10:19:07 -0800561 if (!sHasHal) {
562 return nullptr;
563 }
564
Matt Buckley06f299a2021-09-24 19:43:51 +0000565 // grab old hint session values before we destroy any existing wrapper
566 std::vector<int32_t> oldPowerHintSessionThreadIds;
567 std::optional<int64_t> oldTargetWorkDuration;
568
569 if (sHalWrapper != nullptr) {
570 oldPowerHintSessionThreadIds = sHalWrapper->getPowerHintSessionThreadIds();
571 oldTargetWorkDuration = sHalWrapper->getTargetWorkDuration();
572 }
573
Dan Stoza9c051c02020-02-28 10:19:07 -0800574 // If we used to have a HAL, but it stopped responding, attempt to reconnect
Michael Wright1509a232018-06-21 02:50:34 +0100575 if (mReconnectPowerHal) {
Dan Stoza030fbc12020-02-19 15:32:01 -0800576 sHalWrapper = nullptr;
Michael Wright1509a232018-06-21 02:50:34 +0100577 mReconnectPowerHal = false;
578 }
579
Dan Stoza030fbc12020-02-19 15:32:01 -0800580 if (sHalWrapper != nullptr) {
Matt Buckley06f299a2021-09-24 19:43:51 +0000581 auto wrapper = sHalWrapper.get();
582 // if the wrapper is fine, return it, but if it indicates a reconnect, remake it
583 if (!wrapper->shouldReconnectHAL()) {
584 return wrapper;
585 }
Xiang Wang65a2e6f2022-04-18 21:19:17 +0000586 ALOGD("Reconnecting Power HAL");
Matt Buckley06f299a2021-09-24 19:43:51 +0000587 sHalWrapper = nullptr;
Michael Wright1509a232018-06-21 02:50:34 +0100588 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800589
Matt Buckley06f299a2021-09-24 19:43:51 +0000590 // at this point, we know for sure there is no running session
591 mPowerHintSessionRunning = false;
592
Dan Stoza030fbc12020-02-19 15:32:01 -0800593 // First attempt to connect to the AIDL Power HAL
594 sHalWrapper = AidlPowerHalWrapper::connect();
595
596 // If that didn't succeed, attempt to connect to the HIDL Power HAL
597 if (sHalWrapper == nullptr) {
598 sHalWrapper = HidlPowerHalWrapper::connect();
Xiang Wang65a2e6f2022-04-18 21:19:17 +0000599 } else {
600 ALOGD("Successfully connecting AIDL Power HAL");
601 // if AIDL, pass on any existing hint session values
Matt Buckley06f299a2021-09-24 19:43:51 +0000602 // thread ids always safe to set
603 sHalWrapper->setPowerHintSessionThreadIds(oldPowerHintSessionThreadIds);
604 // only set duration and start if duration is defined
605 if (oldTargetWorkDuration.has_value()) {
606 sHalWrapper->setTargetWorkDuration(*oldTargetWorkDuration);
607 // only start if possible to run and both threadids and duration are defined
608 if (usePowerHintSession() && !oldPowerHintSessionThreadIds.empty()) {
609 mPowerHintSessionRunning = sHalWrapper->startPowerHintSession();
610 }
611 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800612 }
613
Dan Stoza9c051c02020-02-28 10:19:07 -0800614 // If we make it to this point and still don't have a HAL, it's unlikely we
615 // will, so stop trying
616 if (sHalWrapper == nullptr) {
617 sHasHal = false;
618 }
619
Dan Stoza030fbc12020-02-19 15:32:01 -0800620 return sHalWrapper.get();
Michael Wright1509a232018-06-21 02:50:34 +0100621}
622
623} // namespace impl
624} // namespace Hwc2
625} // namespace android