blob: b5678b49b8dc22713c06dcfcc2db01220a287195 [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 {
Alec Mouri29382ad2022-05-11 18:38:38 +000067std::chrono::milliseconds getUpdateTimeout() {
Dan Stoza030fbc12020-02-19 15:32:01 -080068 // Default to a timeout of 80ms if nothing else is specified
Alec Mouri29382ad2022-05-11 18:38:38 +000069 static std::chrono::milliseconds timeout =
70 std::chrono::milliseconds(sysprop::display_update_imminent_timeout_ms(80));
Dan Stoza030fbc12020-02-19 15:32:01 -080071 return timeout;
72}
73
Ady Abrahamabce1652022-02-24 10:51:19 -080074void traceExpensiveRendering(bool enabled) {
75 if (enabled) {
76 ATRACE_ASYNC_BEGIN("ExpensiveRendering", 0);
77 } else {
78 ATRACE_ASYNC_END("ExpensiveRendering", 0);
79 }
80}
81
Dan Stoza030fbc12020-02-19 15:32:01 -080082} // namespace
83
Alec Mouri19609692022-05-05 23:40:07 +000084PowerAdvisor::PowerAdvisor(SurfaceFlinger& flinger) : mFlinger(flinger) {
Alec Mouri29382ad2022-05-11 18:38:38 +000085 if (getUpdateTimeout() > 0ms) {
86 mScreenUpdateTimer.emplace("UpdateImminentTimer", getUpdateTimeout(),
Alec Mouri19609692022-05-05 23:40:07 +000087 /* resetCallback */ nullptr,
88 /* timeoutCallback */
89 [this] {
Alec Mouri29382ad2022-05-11 18:38:38 +000090 while (true) {
91 auto timeSinceLastUpdate = std::chrono::nanoseconds(
92 systemTime() - mLastScreenUpdatedTime.load());
93 if (timeSinceLastUpdate >= getUpdateTimeout()) {
94 break;
95 }
Alec Mouri19609692022-05-05 23:40:07 +000096 // We may try to disable expensive rendering and allow
97 // for sending DISPLAY_UPDATE_IMMINENT hints too early if
98 // we idled very shortly after updating the screen, so
99 // make sure we wait enough time.
Alec Mouri29382ad2022-05-11 18:38:38 +0000100 std::this_thread::sleep_for(getUpdateTimeout() -
101 timeSinceLastUpdate);
Alec Mouri19609692022-05-05 23:40:07 +0000102 }
103 mSendUpdateImminent.store(true);
104 mFlinger.disableExpensiveRendering();
105 });
106 }
107}
Alec Mouridea1ac52021-06-23 18:12:18 -0700108
109void PowerAdvisor::init() {
110 // Defer starting the screen update timer until SurfaceFlinger finishes construction.
Alec Mouri19609692022-05-05 23:40:07 +0000111 if (mScreenUpdateTimer) {
112 mScreenUpdateTimer->start();
Dan Stoza030fbc12020-02-19 15:32:01 -0800113 }
114}
Michael Wright1509a232018-06-21 02:50:34 +0100115
Dan Stoza29e7bdf2020-03-23 14:43:09 -0700116void PowerAdvisor::onBootFinished() {
117 mBootFinished.store(true);
118}
119
Peiyong Lin74ca2f42019-01-14 19:36:57 -0800120void PowerAdvisor::setExpensiveRenderingExpected(DisplayId displayId, bool expected) {
Michael Wright1509a232018-06-21 02:50:34 +0100121 if (expected) {
122 mExpensiveDisplays.insert(displayId);
123 } else {
124 mExpensiveDisplays.erase(displayId);
125 }
126
Michael Wright1509a232018-06-21 02:50:34 +0100127 const bool expectsExpensiveRendering = !mExpensiveDisplays.empty();
128 if (mNotifiedExpensiveRendering != expectsExpensiveRendering) {
Dan Stoza20950002020-06-18 14:56:58 -0700129 std::lock_guard lock(mPowerHalMutex);
Dan Stoza030fbc12020-02-19 15:32:01 -0800130 HalWrapper* const halWrapper = getPowerHal();
131 if (halWrapper == nullptr) {
Peiyong Lin81934972018-07-02 11:00:54 -0700132 return;
133 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800134
135 if (!halWrapper->setExpensiveRendering(expectsExpensiveRendering)) {
136 // The HAL has become unavailable; attempt to reconnect later
Michael Wright1509a232018-06-21 02:50:34 +0100137 mReconnectPowerHal = true;
138 return;
139 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800140
Michael Wright1509a232018-06-21 02:50:34 +0100141 mNotifiedExpensiveRendering = expectsExpensiveRendering;
142 }
143}
144
Dan Stoza030fbc12020-02-19 15:32:01 -0800145void PowerAdvisor::notifyDisplayUpdateImminent() {
Dan Stoza29e7bdf2020-03-23 14:43:09 -0700146 // Only start sending this notification once the system has booted so we don't introduce an
147 // early-boot dependency on Power HAL
148 if (!mBootFinished.load()) {
149 return;
150 }
151
Alec Mouri19609692022-05-05 23:40:07 +0000152 if (mSendUpdateImminent.exchange(false)) {
Dan Stoza20950002020-06-18 14:56:58 -0700153 std::lock_guard lock(mPowerHalMutex);
Dan Stoza030fbc12020-02-19 15:32:01 -0800154 HalWrapper* const halWrapper = getPowerHal();
155 if (halWrapper == nullptr) {
156 return;
157 }
158
159 if (!halWrapper->notifyDisplayUpdateImminent()) {
160 // The HAL has become unavailable; attempt to reconnect later
161 mReconnectPowerHal = true;
162 return;
163 }
Alec Mouri19609692022-05-05 23:40:07 +0000164
165 if (mScreenUpdateTimer) {
166 mScreenUpdateTimer->reset();
167 } else {
168 // If we don't have a screen update timer, then we don't throttle power hal calls so
169 // flip this bit back to allow for calling into power hal again.
170 mSendUpdateImminent.store(true);
171 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800172 }
173
Alec Mouri19609692022-05-05 23:40:07 +0000174 if (mScreenUpdateTimer) {
175 mLastScreenUpdatedTime.store(systemTime());
Dan Stoza030fbc12020-02-19 15:32:01 -0800176 }
177}
178
Matt Buckley06f299a2021-09-24 19:43:51 +0000179// checks both if it supports and if it's enabled
180bool PowerAdvisor::usePowerHintSession() {
181 // uses cached value since the underlying support and flag are unlikely to change at runtime
Matt Buckley06f299a2021-09-24 19:43:51 +0000182 return mPowerHintEnabled.value_or(false) && supportsPowerHintSession();
183}
184
185bool PowerAdvisor::supportsPowerHintSession() {
186 // cache to avoid needing lock every time
187 if (!mSupportsPowerHint.has_value()) {
188 std::lock_guard lock(mPowerHalMutex);
189 HalWrapper* const halWrapper = getPowerHal();
190 mSupportsPowerHint = halWrapper->supportsPowerHintSession();
191 }
192 return *mSupportsPowerHint;
193}
194
195bool PowerAdvisor::isPowerHintSessionRunning() {
196 return mPowerHintSessionRunning;
197}
198
199void PowerAdvisor::setTargetWorkDuration(int64_t targetDurationNanos) {
Matt Buckleyef51fba2021-10-12 19:30:12 +0000200 if (!usePowerHintSession()) {
Matt Buckley06f299a2021-09-24 19:43:51 +0000201 ALOGV("Power hint session target duration cannot be set, skipping");
202 return;
203 }
204 {
205 std::lock_guard lock(mPowerHalMutex);
206 HalWrapper* const halWrapper = getPowerHal();
207 if (halWrapper != nullptr) {
Matt Buckleyef51fba2021-10-12 19:30:12 +0000208 halWrapper->setTargetWorkDuration(targetDurationNanos - kTargetSafetyMargin.count());
Matt Buckley06f299a2021-09-24 19:43:51 +0000209 }
210 }
211}
212
213void PowerAdvisor::sendActualWorkDuration(int64_t actualDurationNanos, nsecs_t timeStampNanos) {
214 if (!mBootFinished || !usePowerHintSession()) {
215 ALOGV("Actual work duration power hint cannot be sent, skipping");
216 return;
217 }
218 {
219 std::lock_guard lock(mPowerHalMutex);
220 HalWrapper* const halWrapper = getPowerHal();
221 if (halWrapper != nullptr) {
222 halWrapper->sendActualWorkDuration(actualDurationNanos, timeStampNanos);
223 }
224 }
225}
226
227// needs to be set after the flag is known but before PowerAdvisor enters onBootFinished
228void PowerAdvisor::enablePowerHint(bool enabled) {
229 mPowerHintEnabled = enabled;
230}
231
Matt Buckleyef51fba2021-10-12 19:30:12 +0000232bool PowerAdvisor::startPowerHintSession(const std::vector<int32_t>& threadIds) {
233 if (!usePowerHintSession()) {
234 ALOGI("Power hint session cannot be started, skipping");
235 }
236 {
237 std::lock_guard lock(mPowerHalMutex);
238 HalWrapper* halWrapper = getPowerHal();
239 if (halWrapper != nullptr && usePowerHintSession()) {
240 halWrapper->setPowerHintSessionThreadIds(threadIds);
241 mPowerHintSessionRunning = halWrapper->startPowerHintSession();
242 }
243 }
244 return mPowerHintSessionRunning;
245}
246
Dan Stoza030fbc12020-02-19 15:32:01 -0800247class HidlPowerHalWrapper : public PowerAdvisor::HalWrapper {
248public:
249 HidlPowerHalWrapper(sp<V1_3::IPower> powerHal) : mPowerHal(std::move(powerHal)) {}
250
251 ~HidlPowerHalWrapper() override = default;
252
253 static std::unique_ptr<HalWrapper> connect() {
254 // Power HAL 1.3 is not guaranteed to be available, thus we need to query
255 // Power HAL 1.0 first and try to cast it to Power HAL 1.3.
Dan Stoza030fbc12020-02-19 15:32:01 -0800256 sp<V1_3::IPower> powerHal = nullptr;
Dan Stoza9c051c02020-02-28 10:19:07 -0800257 sp<V1_0::IPower> powerHal_1_0 = V1_0::IPower::getService();
258 if (powerHal_1_0 != nullptr) {
259 // Try to cast to Power HAL 1.3
260 powerHal = V1_3::IPower::castFrom(powerHal_1_0);
261 if (powerHal == nullptr) {
262 ALOGW("No Power HAL 1.3 service in system, disabling PowerAdvisor");
263 } else {
264 ALOGI("Loaded Power HAL 1.3 service");
Dan Stoza030fbc12020-02-19 15:32:01 -0800265 }
Dan Stoza9c051c02020-02-28 10:19:07 -0800266 } else {
267 ALOGW("No Power HAL found, disabling PowerAdvisor");
Dan Stoza030fbc12020-02-19 15:32:01 -0800268 }
Dan Stoza9c051c02020-02-28 10:19:07 -0800269
Dan Stoza030fbc12020-02-19 15:32:01 -0800270 if (powerHal == nullptr) {
271 return nullptr;
272 }
273
274 return std::make_unique<HidlPowerHalWrapper>(std::move(powerHal));
275 }
276
277 bool setExpensiveRendering(bool enabled) override {
278 ALOGV("HIDL setExpensiveRendering %s", enabled ? "T" : "F");
279 auto ret = mPowerHal->powerHintAsync_1_3(PowerHint::EXPENSIVE_RENDERING, enabled);
Ady Abrahamabce1652022-02-24 10:51:19 -0800280 if (ret.isOk()) {
281 traceExpensiveRendering(enabled);
282 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800283 return ret.isOk();
284 }
285
286 bool notifyDisplayUpdateImminent() override {
287 // Power HAL 1.x doesn't have a notification for this
288 ALOGV("HIDL notifyUpdateImminent received but can't send");
289 return true;
290 }
291
Matt Buckley06f299a2021-09-24 19:43:51 +0000292 bool supportsPowerHintSession() override { return false; }
293
294 bool isPowerHintSessionRunning() override { return false; }
295
296 void restartPowerHintSession() override {}
297
298 void setPowerHintSessionThreadIds(const std::vector<int32_t>&) override {}
299
300 bool startPowerHintSession() override { return false; }
301
302 void setTargetWorkDuration(int64_t) override {}
303
304 void sendActualWorkDuration(int64_t, nsecs_t) override {}
305
306 bool shouldReconnectHAL() override { return false; }
307
308 std::vector<int32_t> getPowerHintSessionThreadIds() override { return std::vector<int32_t>{}; }
309
310 std::optional<int64_t> getTargetWorkDuration() override { return std::nullopt; }
311
Dan Stoza030fbc12020-02-19 15:32:01 -0800312private:
Dan Stoza030fbc12020-02-19 15:32:01 -0800313 const sp<V1_3::IPower> mPowerHal = nullptr;
314};
315
Xiang Wange12b4fa2022-03-25 23:48:40 +0000316AidlPowerHalWrapper::AidlPowerHalWrapper(sp<IPower> powerHal) : mPowerHal(std::move(powerHal)) {
317 auto ret = mPowerHal->isModeSupported(Mode::EXPENSIVE_RENDERING, &mHasExpensiveRendering);
318 if (!ret.isOk()) {
319 mHasExpensiveRendering = false;
Dan Stoza030fbc12020-02-19 15:32:01 -0800320 }
321
Xiang Wange12b4fa2022-03-25 23:48:40 +0000322 ret = mPowerHal->isBoostSupported(Boost::DISPLAY_UPDATE_IMMINENT, &mHasDisplayUpdateImminent);
323 if (!ret.isOk()) {
324 mHasDisplayUpdateImminent = false;
Dan Stoza030fbc12020-02-19 15:32:01 -0800325 }
326
Xiang Wange12b4fa2022-03-25 23:48:40 +0000327 mSupportsPowerHint = checkPowerHintSessionSupported();
328}
Dan Stoza030fbc12020-02-19 15:32:01 -0800329
Xiang Wange12b4fa2022-03-25 23:48:40 +0000330AidlPowerHalWrapper::~AidlPowerHalWrapper() {
331 if (mPowerHintSession != nullptr) {
332 mPowerHintSession->close();
333 mPowerHintSession = nullptr;
Dan Stoza030fbc12020-02-19 15:32:01 -0800334 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800335};
336
Xiang Wange12b4fa2022-03-25 23:48:40 +0000337std::unique_ptr<PowerAdvisor::HalWrapper> AidlPowerHalWrapper::connect() {
338 // This only waits if the service is actually declared
339 sp<IPower> powerHal = waitForVintfService<IPower>();
340 if (powerHal == nullptr) {
341 return nullptr;
342 }
343 ALOGI("Loaded AIDL Power HAL service");
344
345 return std::make_unique<AidlPowerHalWrapper>(std::move(powerHal));
346}
347
348bool AidlPowerHalWrapper::setExpensiveRendering(bool enabled) {
349 ALOGV("AIDL setExpensiveRendering %s", enabled ? "T" : "F");
350 if (!mHasExpensiveRendering) {
351 ALOGV("Skipped sending EXPENSIVE_RENDERING because HAL doesn't support it");
352 return true;
353 }
354
355 auto ret = mPowerHal->setMode(Mode::EXPENSIVE_RENDERING, enabled);
356 if (ret.isOk()) {
357 traceExpensiveRendering(enabled);
358 }
359 return ret.isOk();
360}
361
362bool AidlPowerHalWrapper::notifyDisplayUpdateImminent() {
363 ALOGV("AIDL notifyDisplayUpdateImminent");
364 if (!mHasDisplayUpdateImminent) {
365 ALOGV("Skipped sending DISPLAY_UPDATE_IMMINENT because HAL doesn't support it");
366 return true;
367 }
368
369 auto ret = mPowerHal->setBoost(Boost::DISPLAY_UPDATE_IMMINENT, 0);
370 return ret.isOk();
371}
372
373// only version 2+ of the aidl supports power hint sessions, hidl has no support
374bool AidlPowerHalWrapper::supportsPowerHintSession() {
375 return mSupportsPowerHint;
376}
377
378bool AidlPowerHalWrapper::checkPowerHintSessionSupported() {
379 int64_t unused;
380 // Try to get preferred rate to determine if hint sessions are supported
381 // We check for isOk not EX_UNSUPPORTED_OPERATION to lump together errors
382 return mPowerHal->getHintSessionPreferredRate(&unused).isOk();
383}
384
385bool AidlPowerHalWrapper::isPowerHintSessionRunning() {
386 return mPowerHintSession != nullptr;
387}
388
389void AidlPowerHalWrapper::closePowerHintSession() {
390 if (mPowerHintSession != nullptr) {
391 mPowerHintSession->close();
392 mPowerHintSession = nullptr;
393 }
394}
395
396void AidlPowerHalWrapper::restartPowerHintSession() {
397 closePowerHintSession();
398 startPowerHintSession();
399}
400
401void AidlPowerHalWrapper::setPowerHintSessionThreadIds(const std::vector<int32_t>& threadIds) {
402 if (threadIds != mPowerHintThreadIds) {
403 mPowerHintThreadIds = threadIds;
404 if (isPowerHintSessionRunning()) {
405 restartPowerHintSession();
406 }
407 }
408}
409
410bool AidlPowerHalWrapper::startPowerHintSession() {
411 if (mPowerHintSession != nullptr || mPowerHintThreadIds.empty()) {
412 ALOGV("Cannot start power hint session, skipping");
413 return false;
414 }
415 auto ret =
416 mPowerHal->createHintSession(getpid(), static_cast<int32_t>(getuid()),
417 mPowerHintThreadIds, mTargetDuration, &mPowerHintSession);
418 if (!ret.isOk()) {
419 ALOGW("Failed to start power hint session with error: %s",
420 ret.exceptionToString(ret.exceptionCode()).c_str());
421 } else {
422 mLastTargetDurationSent = mTargetDuration;
423 }
424 return isPowerHintSessionRunning();
425}
426
427bool AidlPowerHalWrapper::shouldSetTargetDuration(int64_t targetDurationNanos) {
428 if (targetDurationNanos <= 0) {
429 return false;
430 }
431 // report if the change in target from our last submission to now exceeds the threshold
432 return abs(1.0 -
433 static_cast<double>(mLastTargetDurationSent) /
434 static_cast<double>(targetDurationNanos)) >= kAllowedTargetDeviationPercent;
435}
436
437void AidlPowerHalWrapper::setTargetWorkDuration(int64_t targetDurationNanos) {
438 ATRACE_CALL();
439 mTargetDuration = targetDurationNanos;
440 if (sTraceHintSessionData) ATRACE_INT64("Time target", targetDurationNanos);
441 if (!sNormalizeTarget && isPowerHintSessionRunning() &&
442 shouldSetTargetDuration(targetDurationNanos)) {
443 if (mLastActualDurationSent.has_value()) {
444 // update the error term here since we are actually sending an update to powerhal
445 if (sTraceHintSessionData)
446 ATRACE_INT64("Target error term", targetDurationNanos - *mLastActualDurationSent);
447 }
448 ALOGV("Sending target time: %" PRId64 "ns", targetDurationNanos);
449 mLastTargetDurationSent = targetDurationNanos;
450 auto ret = mPowerHintSession->updateTargetWorkDuration(targetDurationNanos);
451 if (!ret.isOk()) {
452 ALOGW("Failed to set power hint target work duration with error: %s",
453 ret.exceptionMessage().c_str());
454 mShouldReconnectHal = true;
455 }
456 }
457}
458
459bool AidlPowerHalWrapper::shouldReportActualDurationsNow() {
460 // report if we have never reported before or are approaching a stale session
461 if (!mLastActualDurationSent.has_value() ||
462 (systemTime() - mLastActualReportTimestamp) > kStaleTimeout.count()) {
463 return true;
464 }
465
466 if (!mActualDuration.has_value()) {
467 return false;
468 }
469
470 // duration of most recent timing
471 const double mostRecentActualDuration = static_cast<double>(*mActualDuration);
472 // duration of the last timing actually reported to the powerhal
473 const double lastReportedActualDuration = static_cast<double>(*mLastActualDurationSent);
474
475 // report if the change in duration from then to now exceeds the threshold
476 return abs(1.0 - mostRecentActualDuration / lastReportedActualDuration) >=
477 kAllowedActualDeviationPercent;
478}
479
480void AidlPowerHalWrapper::sendActualWorkDuration(int64_t actualDurationNanos,
481 nsecs_t timeStampNanos) {
482 ATRACE_CALL();
483
484 if (actualDurationNanos < 0 || !isPowerHintSessionRunning()) {
485 ALOGV("Failed to send actual work duration, skipping");
486 return;
487 }
Xiang Wang0aba49e2022-04-06 16:13:59 +0000488 nsecs_t reportedDuration = actualDurationNanos;
Xiang Wange12b4fa2022-03-25 23:48:40 +0000489
490 // normalize the sent values to a pre-set target
491 if (sNormalizeTarget) {
Xiang Wang0aba49e2022-04-06 16:13:59 +0000492 reportedDuration += mLastTargetDurationSent - mTargetDuration;
493 } else {
494 // when target duration change is within deviation and not updated, adjust the actual
495 // duration proportionally based on the difference, e.g. if new target is 5ms longer than
496 // last reported but actual duration is the same as last target, we want to report a smaller
497 // actual work duration now to indicate that we are overshooting
498 if (mLastTargetDurationSent != kDefaultTarget.count() && mTargetDuration != 0) {
499 reportedDuration =
500 static_cast<int64_t>(static_cast<long double>(mLastTargetDurationSent) /
501 mTargetDuration * actualDurationNanos);
502 mActualDuration = reportedDuration;
503 }
Xiang Wange12b4fa2022-03-25 23:48:40 +0000504 }
Xiang Wang0aba49e2022-04-06 16:13:59 +0000505 mActualDuration = reportedDuration;
506 WorkDuration duration;
507 duration.durationNanos = reportedDuration;
Xiang Wange12b4fa2022-03-25 23:48:40 +0000508 duration.timeStampNanos = timeStampNanos;
509 mPowerHintQueue.push_back(duration);
510
Xiang Wange12b4fa2022-03-25 23:48:40 +0000511 if (sTraceHintSessionData) {
Xiang Wang0aba49e2022-04-06 16:13:59 +0000512 ATRACE_INT64("Measured duration", actualDurationNanos);
513 ATRACE_INT64("Target error term", mTargetDuration - actualDurationNanos);
514
515 ATRACE_INT64("Reported duration", reportedDuration);
516 ATRACE_INT64("Reported target", mLastTargetDurationSent);
517 ATRACE_INT64("Reported target error term", mLastTargetDurationSent - reportedDuration);
Xiang Wange12b4fa2022-03-25 23:48:40 +0000518 }
519
Xiang Wang0aba49e2022-04-06 16:13:59 +0000520 ALOGV("Sending actual work duration of: %" PRId64 " on reported target: %" PRId64
Xiang Wange12b4fa2022-03-25 23:48:40 +0000521 " with error: %" PRId64,
Xiang Wang0aba49e2022-04-06 16:13:59 +0000522 reportedDuration, mLastTargetDurationSent, mLastTargetDurationSent - reportedDuration);
Xiang Wange12b4fa2022-03-25 23:48:40 +0000523
524 // This rate limiter queues similar duration reports to the powerhal into
525 // batches to avoid excessive binder calls. The criteria to send a given batch
526 // are outlined in shouldReportActualDurationsNow()
527 if (shouldReportActualDurationsNow()) {
528 ALOGV("Sending hint update batch");
529 mLastActualReportTimestamp = systemTime();
530 auto ret = mPowerHintSession->reportActualWorkDuration(mPowerHintQueue);
531 if (!ret.isOk()) {
532 ALOGW("Failed to report actual work durations with error: %s",
533 ret.exceptionMessage().c_str());
534 mShouldReconnectHal = true;
535 }
536 mPowerHintQueue.clear();
537 // we save the non-normalized value here to detect % changes
Xiang Wang0aba49e2022-04-06 16:13:59 +0000538 mLastActualDurationSent = reportedDuration;
Xiang Wange12b4fa2022-03-25 23:48:40 +0000539 }
540}
541
542bool AidlPowerHalWrapper::shouldReconnectHAL() {
543 return mShouldReconnectHal;
544}
545
546std::vector<int32_t> AidlPowerHalWrapper::getPowerHintSessionThreadIds() {
547 return mPowerHintThreadIds;
548}
549
550std::optional<int64_t> AidlPowerHalWrapper::getTargetWorkDuration() {
551 return mTargetDuration;
552}
553
Matt Buckleyef51fba2021-10-12 19:30:12 +0000554const bool AidlPowerHalWrapper::sTraceHintSessionData =
555 base::GetBoolProperty(std::string("debug.sf.trace_hint_sessions"), false);
556
557const bool AidlPowerHalWrapper::sNormalizeTarget =
Xiang Wang76236e12022-03-22 17:25:30 +0000558 base::GetBoolProperty(std::string("debug.sf.normalize_hint_session_durations"), false);
Matt Buckleyef51fba2021-10-12 19:30:12 +0000559
Dan Stoza030fbc12020-02-19 15:32:01 -0800560PowerAdvisor::HalWrapper* PowerAdvisor::getPowerHal() {
561 static std::unique_ptr<HalWrapper> sHalWrapper = nullptr;
Dan Stoza9c051c02020-02-28 10:19:07 -0800562 static bool sHasHal = true;
Michael Wright1509a232018-06-21 02:50:34 +0100563
Dan Stoza9c051c02020-02-28 10:19:07 -0800564 if (!sHasHal) {
565 return nullptr;
566 }
567
Matt Buckley06f299a2021-09-24 19:43:51 +0000568 // grab old hint session values before we destroy any existing wrapper
569 std::vector<int32_t> oldPowerHintSessionThreadIds;
570 std::optional<int64_t> oldTargetWorkDuration;
571
572 if (sHalWrapper != nullptr) {
573 oldPowerHintSessionThreadIds = sHalWrapper->getPowerHintSessionThreadIds();
574 oldTargetWorkDuration = sHalWrapper->getTargetWorkDuration();
575 }
576
Dan Stoza9c051c02020-02-28 10:19:07 -0800577 // If we used to have a HAL, but it stopped responding, attempt to reconnect
Michael Wright1509a232018-06-21 02:50:34 +0100578 if (mReconnectPowerHal) {
Dan Stoza030fbc12020-02-19 15:32:01 -0800579 sHalWrapper = nullptr;
Michael Wright1509a232018-06-21 02:50:34 +0100580 mReconnectPowerHal = false;
581 }
582
Dan Stoza030fbc12020-02-19 15:32:01 -0800583 if (sHalWrapper != nullptr) {
Matt Buckley06f299a2021-09-24 19:43:51 +0000584 auto wrapper = sHalWrapper.get();
585 // if the wrapper is fine, return it, but if it indicates a reconnect, remake it
586 if (!wrapper->shouldReconnectHAL()) {
587 return wrapper;
588 }
Xiang Wang65a2e6f2022-04-18 21:19:17 +0000589 ALOGD("Reconnecting Power HAL");
Matt Buckley06f299a2021-09-24 19:43:51 +0000590 sHalWrapper = nullptr;
Michael Wright1509a232018-06-21 02:50:34 +0100591 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800592
Matt Buckley06f299a2021-09-24 19:43:51 +0000593 // at this point, we know for sure there is no running session
594 mPowerHintSessionRunning = false;
595
Dan Stoza030fbc12020-02-19 15:32:01 -0800596 // First attempt to connect to the AIDL Power HAL
597 sHalWrapper = AidlPowerHalWrapper::connect();
598
599 // If that didn't succeed, attempt to connect to the HIDL Power HAL
600 if (sHalWrapper == nullptr) {
601 sHalWrapper = HidlPowerHalWrapper::connect();
Xiang Wang65a2e6f2022-04-18 21:19:17 +0000602 } else {
603 ALOGD("Successfully connecting AIDL Power HAL");
604 // if AIDL, pass on any existing hint session values
Matt Buckley06f299a2021-09-24 19:43:51 +0000605 // thread ids always safe to set
606 sHalWrapper->setPowerHintSessionThreadIds(oldPowerHintSessionThreadIds);
607 // only set duration and start if duration is defined
608 if (oldTargetWorkDuration.has_value()) {
609 sHalWrapper->setTargetWorkDuration(*oldTargetWorkDuration);
610 // only start if possible to run and both threadids and duration are defined
611 if (usePowerHintSession() && !oldPowerHintSessionThreadIds.empty()) {
612 mPowerHintSessionRunning = sHalWrapper->startPowerHintSession();
613 }
614 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800615 }
616
Dan Stoza9c051c02020-02-28 10:19:07 -0800617 // If we make it to this point and still don't have a HAL, it's unlikely we
618 // will, so stop trying
619 if (sHalWrapper == nullptr) {
620 sHasHal = false;
621 }
622
Dan Stoza030fbc12020-02-19 15:32:01 -0800623 return sHalWrapper.get();
Michael Wright1509a232018-06-21 02:50:34 +0100624}
625
626} // namespace impl
627} // namespace Hwc2
628} // namespace android