blob: 5c2390eb3864a915563d21dd58d7d8d55005be17 [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
Michael Wright1509a232018-06-21 02:50:34 +010019#undef LOG_TAG
20#define LOG_TAG "PowerAdvisor"
21
Matt Buckley06f299a2021-09-24 19:43:51 +000022#include <unistd.h>
Michael Wright1509a232018-06-21 02:50:34 +010023#include <cinttypes>
Matt Buckley06f299a2021-09-24 19:43:51 +000024#include <cstdint>
25#include <optional>
Michael Wright1509a232018-06-21 02:50:34 +010026
Dan Stoza030fbc12020-02-19 15:32:01 -080027#include <android-base/properties.h>
Michael Wright1509a232018-06-21 02:50:34 +010028#include <utils/Log.h>
29#include <utils/Mutex.h>
30
Dan Stoza030fbc12020-02-19 15:32:01 -080031#include <android/hardware/power/1.3/IPower.h>
32#include <android/hardware/power/IPower.h>
Matt Buckley06f299a2021-09-24 19:43:51 +000033#include <android/hardware/power/IPowerHintSession.h>
34#include <android/hardware/power/WorkDuration.h>
35
Dan Stoza030fbc12020-02-19 15:32:01 -080036#include <binder/IServiceManager.h>
37
38#include "../SurfaceFlingerProperties.h"
39
Michael Wright1509a232018-06-21 02:50:34 +010040#include "PowerAdvisor.h"
Alec Mouridea1ac52021-06-23 18:12:18 -070041#include "SurfaceFlinger.h"
Michael Wright1509a232018-06-21 02:50:34 +010042
43namespace android {
44namespace Hwc2 {
45
46PowerAdvisor::~PowerAdvisor() = default;
47
48namespace impl {
49
50namespace V1_0 = android::hardware::power::V1_0;
Dan Stoza030fbc12020-02-19 15:32:01 -080051namespace V1_3 = android::hardware::power::V1_3;
Michael Wright1509a232018-06-21 02:50:34 +010052using V1_3::PowerHint;
53
Dan Stoza030fbc12020-02-19 15:32:01 -080054using android::hardware::power::Boost;
55using android::hardware::power::IPower;
Matt Buckley06f299a2021-09-24 19:43:51 +000056using android::hardware::power::IPowerHintSession;
Dan Stoza030fbc12020-02-19 15:32:01 -080057using android::hardware::power::Mode;
Matt Buckley06f299a2021-09-24 19:43:51 +000058using android::hardware::power::WorkDuration;
59
Dan Stoza030fbc12020-02-19 15:32:01 -080060using scheduler::OneShotTimer;
61
Matt Buckley06f299a2021-09-24 19:43:51 +000062class AidlPowerHalWrapper;
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
73} // namespace
74
Alec Mouridea1ac52021-06-23 18:12:18 -070075PowerAdvisor::PowerAdvisor(SurfaceFlinger& flinger)
76 : mFlinger(flinger),
77 mUseScreenUpdateTimer(getUpdateTimeout() > 0),
78 mScreenUpdateTimer(
Ady Abrahamdb3dfee2020-11-17 17:07:12 -080079 "UpdateImminentTimer", OneShotTimer::Interval(getUpdateTimeout()),
Dan Stoza030fbc12020-02-19 15:32:01 -080080 /* resetCallback */ [this] { mSendUpdateImminent.store(false); },
Alec Mouridea1ac52021-06-23 18:12:18 -070081 /* timeoutCallback */
82 [this] {
83 mSendUpdateImminent.store(true);
84 mFlinger.disableExpensiveRendering();
85 }) {}
86
87void PowerAdvisor::init() {
88 // Defer starting the screen update timer until SurfaceFlinger finishes construction.
89 if (mUseScreenUpdateTimer) {
90 mScreenUpdateTimer.start();
Dan Stoza030fbc12020-02-19 15:32:01 -080091 }
92}
Michael Wright1509a232018-06-21 02:50:34 +010093
Dan Stoza29e7bdf2020-03-23 14:43:09 -070094void PowerAdvisor::onBootFinished() {
95 mBootFinished.store(true);
Matt Buckley06f299a2021-09-24 19:43:51 +000096 {
97 std::lock_guard lock(mPowerHalMutex);
98 HalWrapper* halWrapper = getPowerHal();
99 if (halWrapper != nullptr && usePowerHintSession()) {
100 mPowerHintSessionRunning = halWrapper->startPowerHintSession();
101 }
102 }
Dan Stoza29e7bdf2020-03-23 14:43:09 -0700103}
104
Peiyong Lin74ca2f42019-01-14 19:36:57 -0800105void PowerAdvisor::setExpensiveRenderingExpected(DisplayId displayId, bool expected) {
Michael Wright1509a232018-06-21 02:50:34 +0100106 if (expected) {
107 mExpensiveDisplays.insert(displayId);
108 } else {
109 mExpensiveDisplays.erase(displayId);
110 }
111
Michael Wright1509a232018-06-21 02:50:34 +0100112 const bool expectsExpensiveRendering = !mExpensiveDisplays.empty();
113 if (mNotifiedExpensiveRendering != expectsExpensiveRendering) {
Dan Stoza20950002020-06-18 14:56:58 -0700114 std::lock_guard lock(mPowerHalMutex);
Dan Stoza030fbc12020-02-19 15:32:01 -0800115 HalWrapper* const halWrapper = getPowerHal();
116 if (halWrapper == nullptr) {
Peiyong Lin81934972018-07-02 11:00:54 -0700117 return;
118 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800119
120 if (!halWrapper->setExpensiveRendering(expectsExpensiveRendering)) {
121 // The HAL has become unavailable; attempt to reconnect later
Michael Wright1509a232018-06-21 02:50:34 +0100122 mReconnectPowerHal = true;
123 return;
124 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800125
Michael Wright1509a232018-06-21 02:50:34 +0100126 mNotifiedExpensiveRendering = expectsExpensiveRendering;
127 }
128}
129
Dan Stoza030fbc12020-02-19 15:32:01 -0800130void PowerAdvisor::notifyDisplayUpdateImminent() {
Dan Stoza29e7bdf2020-03-23 14:43:09 -0700131 // Only start sending this notification once the system has booted so we don't introduce an
132 // early-boot dependency on Power HAL
133 if (!mBootFinished.load()) {
134 return;
135 }
136
Dan Stoza030fbc12020-02-19 15:32:01 -0800137 if (mSendUpdateImminent.load()) {
Dan Stoza20950002020-06-18 14:56:58 -0700138 std::lock_guard lock(mPowerHalMutex);
Dan Stoza030fbc12020-02-19 15:32:01 -0800139 HalWrapper* const halWrapper = getPowerHal();
140 if (halWrapper == nullptr) {
141 return;
142 }
143
144 if (!halWrapper->notifyDisplayUpdateImminent()) {
145 // The HAL has become unavailable; attempt to reconnect later
146 mReconnectPowerHal = true;
147 return;
148 }
149 }
150
Alec Mouridea1ac52021-06-23 18:12:18 -0700151 if (mUseScreenUpdateTimer) {
152 mScreenUpdateTimer.reset();
Dan Stoza030fbc12020-02-19 15:32:01 -0800153 }
154}
155
Matt Buckley06f299a2021-09-24 19:43:51 +0000156// checks both if it supports and if it's enabled
157bool PowerAdvisor::usePowerHintSession() {
158 // uses cached value since the underlying support and flag are unlikely to change at runtime
159 ALOGE_IF(!mPowerHintEnabled.has_value(), "Power hint session cannot be used before boot!");
160 return mPowerHintEnabled.value_or(false) && supportsPowerHintSession();
161}
162
163bool PowerAdvisor::supportsPowerHintSession() {
164 // cache to avoid needing lock every time
165 if (!mSupportsPowerHint.has_value()) {
166 std::lock_guard lock(mPowerHalMutex);
167 HalWrapper* const halWrapper = getPowerHal();
168 mSupportsPowerHint = halWrapper->supportsPowerHintSession();
169 }
170 return *mSupportsPowerHint;
171}
172
173bool PowerAdvisor::isPowerHintSessionRunning() {
174 return mPowerHintSessionRunning;
175}
176
177void PowerAdvisor::setTargetWorkDuration(int64_t targetDurationNanos) {
178 // we check "supports" here not "usePowerHintSession" because this needs to work
179 // before the session is actually running, and "use" will always fail before boot
180 // we store the values passed in before boot to start the session with during onBootFinished
181 if (!supportsPowerHintSession()) {
182 ALOGV("Power hint session target duration cannot be set, skipping");
183 return;
184 }
185 {
186 std::lock_guard lock(mPowerHalMutex);
187 HalWrapper* const halWrapper = getPowerHal();
188 if (halWrapper != nullptr) {
189 halWrapper->setTargetWorkDuration(targetDurationNanos);
190 }
191 }
192}
193
194void PowerAdvisor::setPowerHintSessionThreadIds(const std::vector<int32_t>& threadIds) {
195 // we check "supports" here not "usePowerHintSession" because this needs to wsork
196 // before the session is actually running, and "use" will always fail before boot.
197 // we store the values passed in before boot to start the session with during onBootFinished
198 if (!supportsPowerHintSession()) {
199 ALOGV("Power hint session thread ids cannot be set, skipping");
200 return;
201 }
202 {
203 std::lock_guard lock(mPowerHalMutex);
204 HalWrapper* const halWrapper = getPowerHal();
205 if (halWrapper != nullptr) {
206 halWrapper->setPowerHintSessionThreadIds(const_cast<std::vector<int32_t>&>(threadIds));
207 }
208 }
209}
210
211void PowerAdvisor::sendActualWorkDuration(int64_t actualDurationNanos, nsecs_t timeStampNanos) {
212 if (!mBootFinished || !usePowerHintSession()) {
213 ALOGV("Actual work duration power hint cannot be sent, skipping");
214 return;
215 }
216 {
217 std::lock_guard lock(mPowerHalMutex);
218 HalWrapper* const halWrapper = getPowerHal();
219 if (halWrapper != nullptr) {
220 halWrapper->sendActualWorkDuration(actualDurationNanos, timeStampNanos);
221 }
222 }
223}
224
225// needs to be set after the flag is known but before PowerAdvisor enters onBootFinished
226void PowerAdvisor::enablePowerHint(bool enabled) {
227 mPowerHintEnabled = enabled;
228}
229
Dan Stoza030fbc12020-02-19 15:32:01 -0800230class HidlPowerHalWrapper : public PowerAdvisor::HalWrapper {
231public:
232 HidlPowerHalWrapper(sp<V1_3::IPower> powerHal) : mPowerHal(std::move(powerHal)) {}
233
234 ~HidlPowerHalWrapper() override = default;
235
236 static std::unique_ptr<HalWrapper> connect() {
237 // Power HAL 1.3 is not guaranteed to be available, thus we need to query
238 // Power HAL 1.0 first and try to cast it to Power HAL 1.3.
Dan Stoza030fbc12020-02-19 15:32:01 -0800239 sp<V1_3::IPower> powerHal = nullptr;
Dan Stoza9c051c02020-02-28 10:19:07 -0800240 sp<V1_0::IPower> powerHal_1_0 = V1_0::IPower::getService();
241 if (powerHal_1_0 != nullptr) {
242 // Try to cast to Power HAL 1.3
243 powerHal = V1_3::IPower::castFrom(powerHal_1_0);
244 if (powerHal == nullptr) {
245 ALOGW("No Power HAL 1.3 service in system, disabling PowerAdvisor");
246 } else {
247 ALOGI("Loaded Power HAL 1.3 service");
Dan Stoza030fbc12020-02-19 15:32:01 -0800248 }
Dan Stoza9c051c02020-02-28 10:19:07 -0800249 } else {
250 ALOGW("No Power HAL found, disabling PowerAdvisor");
Dan Stoza030fbc12020-02-19 15:32:01 -0800251 }
Dan Stoza9c051c02020-02-28 10:19:07 -0800252
Dan Stoza030fbc12020-02-19 15:32:01 -0800253 if (powerHal == nullptr) {
254 return nullptr;
255 }
256
257 return std::make_unique<HidlPowerHalWrapper>(std::move(powerHal));
258 }
259
260 bool setExpensiveRendering(bool enabled) override {
261 ALOGV("HIDL setExpensiveRendering %s", enabled ? "T" : "F");
262 auto ret = mPowerHal->powerHintAsync_1_3(PowerHint::EXPENSIVE_RENDERING, enabled);
263 return ret.isOk();
264 }
265
266 bool notifyDisplayUpdateImminent() override {
267 // Power HAL 1.x doesn't have a notification for this
268 ALOGV("HIDL notifyUpdateImminent received but can't send");
269 return true;
270 }
271
Matt Buckley06f299a2021-09-24 19:43:51 +0000272 bool supportsPowerHintSession() override { return false; }
273
274 bool isPowerHintSessionRunning() override { return false; }
275
276 void restartPowerHintSession() override {}
277
278 void setPowerHintSessionThreadIds(const std::vector<int32_t>&) override {}
279
280 bool startPowerHintSession() override { return false; }
281
282 void setTargetWorkDuration(int64_t) override {}
283
284 void sendActualWorkDuration(int64_t, nsecs_t) override {}
285
286 bool shouldReconnectHAL() override { return false; }
287
288 std::vector<int32_t> getPowerHintSessionThreadIds() override { return std::vector<int32_t>{}; }
289
290 std::optional<int64_t> getTargetWorkDuration() override { return std::nullopt; }
291
Dan Stoza030fbc12020-02-19 15:32:01 -0800292private:
Dan Stoza030fbc12020-02-19 15:32:01 -0800293 const sp<V1_3::IPower> mPowerHal = nullptr;
294};
295
Dan Stoza030fbc12020-02-19 15:32:01 -0800296class AidlPowerHalWrapper : public PowerAdvisor::HalWrapper {
297public:
298 AidlPowerHalWrapper(sp<IPower> powerHal) : mPowerHal(std::move(powerHal)) {
299 auto ret = mPowerHal->isModeSupported(Mode::EXPENSIVE_RENDERING, &mHasExpensiveRendering);
300 if (!ret.isOk()) {
301 mHasExpensiveRendering = false;
302 }
303
304 ret = mPowerHal->isBoostSupported(Boost::DISPLAY_UPDATE_IMMINENT,
305 &mHasDisplayUpdateImminent);
306 if (!ret.isOk()) {
307 mHasDisplayUpdateImminent = false;
308 }
Matt Buckley06f299a2021-09-24 19:43:51 +0000309
310 // This just gives a number not a binder status, so no .isOk()
311 mSupportsPowerHints = mPowerHal->getInterfaceVersion() >= 2;
312
313 if (mSupportsPowerHints) {
314 mPowerHintQueue.reserve(MAX_QUEUE_SIZE);
315 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800316 }
317
Matt Buckley06f299a2021-09-24 19:43:51 +0000318 ~AidlPowerHalWrapper() override {
319 if (mPowerHintSession != nullptr) {
320 mPowerHintSession->close();
321 mPowerHintSession = nullptr;
322 }
323 };
Dan Stoza030fbc12020-02-19 15:32:01 -0800324
325 static std::unique_ptr<HalWrapper> connect() {
326 // This only waits if the service is actually declared
327 sp<IPower> powerHal = waitForVintfService<IPower>();
328 if (powerHal == nullptr) {
329 return nullptr;
330 }
331 ALOGI("Loaded AIDL Power HAL service");
332
333 return std::make_unique<AidlPowerHalWrapper>(std::move(powerHal));
334 }
335
336 bool setExpensiveRendering(bool enabled) override {
337 ALOGV("AIDL setExpensiveRendering %s", enabled ? "T" : "F");
338 if (!mHasExpensiveRendering) {
339 ALOGV("Skipped sending EXPENSIVE_RENDERING because HAL doesn't support it");
340 return true;
341 }
342
343 auto ret = mPowerHal->setMode(Mode::EXPENSIVE_RENDERING, enabled);
344 return ret.isOk();
345 }
346
347 bool notifyDisplayUpdateImminent() override {
348 ALOGV("AIDL notifyDisplayUpdateImminent");
349 if (!mHasDisplayUpdateImminent) {
350 ALOGV("Skipped sending DISPLAY_UPDATE_IMMINENT because HAL doesn't support it");
351 return true;
352 }
353
354 auto ret = mPowerHal->setBoost(Boost::DISPLAY_UPDATE_IMMINENT, 0);
355 return ret.isOk();
356 }
357
Matt Buckley06f299a2021-09-24 19:43:51 +0000358 // only version 2+ of the aidl supports power hint sessions, hidl has no support
359 bool supportsPowerHintSession() override { return mSupportsPowerHints; }
360
361 bool isPowerHintSessionRunning() override { return mPowerHintSession != nullptr; }
362
363 void closePowerHintSession() {
364 if (mPowerHintSession != nullptr) {
365 mPowerHintSession->close();
366 mPowerHintSession = nullptr;
367 }
368 }
369
370 void restartPowerHintSession() {
371 closePowerHintSession();
372 startPowerHintSession();
373 }
374
375 void setPowerHintSessionThreadIds(const std::vector<int32_t>& threadIds) override {
376 if (threadIds != mPowerHintThreadIds) {
377 mPowerHintThreadIds = threadIds;
378 if (isPowerHintSessionRunning()) {
379 restartPowerHintSession();
380 }
381 }
382 }
383
384 bool startPowerHintSession() override {
385 if (mPowerHintSession != nullptr || !mPowerHintTargetDuration.has_value() ||
386 mPowerHintThreadIds.empty()) {
387 ALOGV("Cannot start power hint session, skipping");
388 return false;
389 }
390 auto ret = mPowerHal->createHintSession(getpid(), static_cast<int32_t>(getuid()),
391 mPowerHintThreadIds, *mPowerHintTargetDuration,
392 &mPowerHintSession);
393 if (!ret.isOk()) {
394 ALOGW("Failed to start power hint session with error: %s",
395 ret.exceptionToString(ret.exceptionCode()).c_str());
396 // Indicate to the poweradvisor that this wrapper likely needs to be remade
397 mShouldReconnectHal = true;
398 }
399 return isPowerHintSessionRunning();
400 }
401
402 bool shouldSetTargetDuration(int64_t targetDurationNanos) {
403 if (!mLastTargetDurationSent.has_value()) {
404 return true;
405 }
406
407 // report if the change in target from our last submission to now exceeds the threshold
408 return abs(1.0 -
409 static_cast<double>(*mLastTargetDurationSent) /
410 static_cast<double>(targetDurationNanos)) >=
411 ALLOWED_TARGET_DEVIATION_PERCENT;
412 }
413
414 void setTargetWorkDuration(int64_t targetDurationNanos) override {
415 mPowerHintTargetDuration = targetDurationNanos;
416 if (shouldSetTargetDuration(targetDurationNanos) && isPowerHintSessionRunning()) {
417 mLastTargetDurationSent = targetDurationNanos;
418 auto ret = mPowerHintSession->updateTargetWorkDuration(targetDurationNanos);
419 if (!ret.isOk()) {
420 ALOGW("Failed to set power hint target work duration with error: %s",
421 ret.exceptionMessage().c_str());
422 mShouldReconnectHal = true;
423 }
424 }
425 }
426
427 bool shouldReportActualDurationsNow() {
428 // report if we have never reported before or have exceeded the max queue size
429 if (!mLastMessageReported.has_value() || mPowerHintQueue.size() >= MAX_QUEUE_SIZE) {
430 return true;
431 }
432
433 // duration of most recent timing
434 const double mostRecentActualDuration =
435 static_cast<double>(mPowerHintQueue.back().durationNanos);
436 // duration of the last timing actually reported to the powerhal
437 const double lastReportedActualDuration =
438 static_cast<double>(mLastMessageReported->durationNanos);
439
440 // report if the change in duration from then to now exceeds the threshold
441 return abs(1.0 - mostRecentActualDuration / lastReportedActualDuration) >=
442 ALLOWED_ACTUAL_DEVIATION_PERCENT;
443 }
444
445 void sendActualWorkDuration(int64_t actualDurationNanos, nsecs_t timeStampNanos) override {
446 if (actualDurationNanos < 0 || !isPowerHintSessionRunning()) {
447 ALOGV("Failed to send actual work duration, skipping");
448 return;
449 }
450
451 WorkDuration duration;
452 duration.durationNanos = actualDurationNanos;
453 duration.timeStampNanos = timeStampNanos;
454 mPowerHintQueue.push_back(duration);
455
456 // This rate limiter queues similar duration reports to the powerhal into
457 // batches to avoid excessive binder calls. The criteria to send a given batch
458 // are outlined in shouldReportActualDurationsNow()
459 if (shouldReportActualDurationsNow()) {
460 auto ret = mPowerHintSession->reportActualWorkDuration(mPowerHintQueue);
461 if (!ret.isOk()) {
462 ALOGW("Failed to report actual work durations with error: %s",
463 ret.exceptionMessage().c_str());
464 mShouldReconnectHal = true;
465 }
466 mPowerHintQueue.clear();
467 mLastMessageReported = duration;
468 }
469 }
470
471 bool shouldReconnectHAL() override { return mShouldReconnectHal; }
472
473 std::vector<int32_t> getPowerHintSessionThreadIds() override { return mPowerHintThreadIds; }
474
475 std::optional<int64_t> getTargetWorkDuration() override { return mPowerHintTargetDuration; }
476
Dan Stoza030fbc12020-02-19 15:32:01 -0800477private:
Matt Buckley06f299a2021-09-24 19:43:51 +0000478 // max number of messages allowed in mPowerHintQueue before reporting is forced
479 static constexpr int32_t MAX_QUEUE_SIZE = 15;
480 // max percent the actual duration can vary without causing a report (eg: 0.1 = 10%)
481 static constexpr double ALLOWED_ACTUAL_DEVIATION_PERCENT = 0.1;
482 // max percent the target duration can vary without causing a report (eg: 0.05 = 5%)
483 static constexpr double ALLOWED_TARGET_DEVIATION_PERCENT = 0.05;
484
Dan Stoza030fbc12020-02-19 15:32:01 -0800485 const sp<IPower> mPowerHal = nullptr;
486 bool mHasExpensiveRendering = false;
487 bool mHasDisplayUpdateImminent = false;
Matt Buckley06f299a2021-09-24 19:43:51 +0000488 bool mShouldReconnectHal = false; // used to indicate an error state and need for reconstruction
489 // This is not thread safe, but is currently protected by mPowerHalMutex so it needs no lock
490 sp<IPowerHintSession> mPowerHintSession = nullptr;
491 std::vector<WorkDuration> mPowerHintQueue;
492 // halwrapper owns these values so we can init when we want and reconnect if broken
493 std::optional<int64_t> mPowerHintTargetDuration;
494 std::vector<int32_t> mPowerHintThreadIds;
495 // keep track of the last messages sent for rate limiter change detection
496 std::optional<WorkDuration> mLastMessageReported;
497 std::optional<int64_t> mLastTargetDurationSent;
498 bool mSupportsPowerHints;
Dan Stoza030fbc12020-02-19 15:32:01 -0800499};
500
501PowerAdvisor::HalWrapper* PowerAdvisor::getPowerHal() {
502 static std::unique_ptr<HalWrapper> sHalWrapper = nullptr;
Dan Stoza9c051c02020-02-28 10:19:07 -0800503 static bool sHasHal = true;
Michael Wright1509a232018-06-21 02:50:34 +0100504
Dan Stoza9c051c02020-02-28 10:19:07 -0800505 if (!sHasHal) {
506 return nullptr;
507 }
508
Matt Buckley06f299a2021-09-24 19:43:51 +0000509 // grab old hint session values before we destroy any existing wrapper
510 std::vector<int32_t> oldPowerHintSessionThreadIds;
511 std::optional<int64_t> oldTargetWorkDuration;
512
513 if (sHalWrapper != nullptr) {
514 oldPowerHintSessionThreadIds = sHalWrapper->getPowerHintSessionThreadIds();
515 oldTargetWorkDuration = sHalWrapper->getTargetWorkDuration();
516 }
517
Dan Stoza9c051c02020-02-28 10:19:07 -0800518 // If we used to have a HAL, but it stopped responding, attempt to reconnect
Michael Wright1509a232018-06-21 02:50:34 +0100519 if (mReconnectPowerHal) {
Dan Stoza030fbc12020-02-19 15:32:01 -0800520 sHalWrapper = nullptr;
Michael Wright1509a232018-06-21 02:50:34 +0100521 mReconnectPowerHal = false;
522 }
523
Dan Stoza030fbc12020-02-19 15:32:01 -0800524 if (sHalWrapper != nullptr) {
Matt Buckley06f299a2021-09-24 19:43:51 +0000525 auto wrapper = sHalWrapper.get();
526 // if the wrapper is fine, return it, but if it indicates a reconnect, remake it
527 if (!wrapper->shouldReconnectHAL()) {
528 return wrapper;
529 }
530 sHalWrapper = nullptr;
Michael Wright1509a232018-06-21 02:50:34 +0100531 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800532
Matt Buckley06f299a2021-09-24 19:43:51 +0000533 // at this point, we know for sure there is no running session
534 mPowerHintSessionRunning = false;
535
Dan Stoza030fbc12020-02-19 15:32:01 -0800536 // First attempt to connect to the AIDL Power HAL
537 sHalWrapper = AidlPowerHalWrapper::connect();
538
539 // If that didn't succeed, attempt to connect to the HIDL Power HAL
540 if (sHalWrapper == nullptr) {
541 sHalWrapper = HidlPowerHalWrapper::connect();
Matt Buckley06f299a2021-09-24 19:43:51 +0000542 } else { // if AIDL, pass on any existing hint session values
543 // thread ids always safe to set
544 sHalWrapper->setPowerHintSessionThreadIds(oldPowerHintSessionThreadIds);
545 // only set duration and start if duration is defined
546 if (oldTargetWorkDuration.has_value()) {
547 sHalWrapper->setTargetWorkDuration(*oldTargetWorkDuration);
548 // only start if possible to run and both threadids and duration are defined
549 if (usePowerHintSession() && !oldPowerHintSessionThreadIds.empty()) {
550 mPowerHintSessionRunning = sHalWrapper->startPowerHintSession();
551 }
552 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800553 }
554
Dan Stoza9c051c02020-02-28 10:19:07 -0800555 // If we make it to this point and still don't have a HAL, it's unlikely we
556 // will, so stop trying
557 if (sHalWrapper == nullptr) {
558 sHasHal = false;
559 }
560
Dan Stoza030fbc12020-02-19 15:32:01 -0800561 return sHalWrapper.get();
Michael Wright1509a232018-06-21 02:50:34 +0100562}
563
564} // namespace impl
565} // namespace Hwc2
566} // namespace android