blob: d168d55c54204a978bd0439125f592deb2cb0706 [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 Mouric059dcf2022-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 Mouric059dcf2022-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 Mouric059dcf2022-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 Mouric059dcf2022-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 Mouric059dcf2022-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 Mouric059dcf2022-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 Mouric059dcf2022-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 Mouric059dcf2022-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();
Shao-Chuan Lee65a2c192022-07-27 09:53:41 +0900190 mSupportsPowerHint = halWrapper && halWrapper->supportsPowerHintSession();
Matt Buckley06f299a2021-09-24 19:43:51 +0000191 }
192 return *mSupportsPowerHint;
193}
194
195bool PowerAdvisor::isPowerHintSessionRunning() {
196 return mPowerHintSessionRunning;
197}
198
Matt Buckley50c44062022-01-17 20:48:10 +0000199void PowerAdvisor::setTargetWorkDuration(int64_t targetDuration) {
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 Buckley50c44062022-01-17 20:48:10 +0000208 halWrapper->setTargetWorkDuration(targetDuration);
Matt Buckley06f299a2021-09-24 19:43:51 +0000209 }
210 }
211}
212
Matt Buckley50c44062022-01-17 20:48:10 +0000213void PowerAdvisor::sendActualWorkDuration() {
Matt Buckley06f299a2021-09-24 19:43:51 +0000214 if (!mBootFinished || !usePowerHintSession()) {
215 ALOGV("Actual work duration power hint cannot be sent, skipping");
216 return;
217 }
Matt Buckley50c44062022-01-17 20:48:10 +0000218 const std::optional<nsecs_t> actualDuration = estimateWorkDuration(false);
219 if (actualDuration.has_value()) {
Matt Buckley06f299a2021-09-24 19:43:51 +0000220 std::lock_guard lock(mPowerHalMutex);
221 HalWrapper* const halWrapper = getPowerHal();
222 if (halWrapper != nullptr) {
Matt Buckley50c44062022-01-17 20:48:10 +0000223 halWrapper->sendActualWorkDuration(*actualDuration + kTargetSafetyMargin.count(),
224 systemTime());
Matt Buckley06f299a2021-09-24 19:43:51 +0000225 }
226 }
227}
228
Matt Buckley50c44062022-01-17 20:48:10 +0000229void PowerAdvisor::sendPredictedWorkDuration() {
230 if (!mBootFinished || !usePowerHintSession()) {
231 ALOGV("Actual work duration power hint cannot be sent, skipping");
232 return;
233 }
234
235 const std::optional<nsecs_t> predictedDuration = estimateWorkDuration(true);
236
237 if (predictedDuration.has_value()) {
238 std::lock_guard lock(mPowerHalMutex);
239 HalWrapper* const halWrapper = getPowerHal();
240 if (halWrapper != nullptr) {
Matt Buckleyffabce92022-06-17 13:52:46 -0700241 halWrapper->sendActualWorkDuration(*predictedDuration + kTargetSafetyMargin.count(),
242 systemTime());
Matt Buckley50c44062022-01-17 20:48:10 +0000243 }
244 }
245}
246
Matt Buckley06f299a2021-09-24 19:43:51 +0000247void PowerAdvisor::enablePowerHint(bool enabled) {
248 mPowerHintEnabled = enabled;
249}
250
Matt Buckleyef51fba2021-10-12 19:30:12 +0000251bool PowerAdvisor::startPowerHintSession(const std::vector<int32_t>& threadIds) {
252 if (!usePowerHintSession()) {
253 ALOGI("Power hint session cannot be started, skipping");
254 }
255 {
256 std::lock_guard lock(mPowerHalMutex);
257 HalWrapper* halWrapper = getPowerHal();
258 if (halWrapper != nullptr && usePowerHintSession()) {
259 halWrapper->setPowerHintSessionThreadIds(threadIds);
260 mPowerHintSessionRunning = halWrapper->startPowerHintSession();
261 }
262 }
263 return mPowerHintSessionRunning;
264}
265
Matt Buckley50c44062022-01-17 20:48:10 +0000266void PowerAdvisor::setGpuFenceTime(DisplayId displayId, std::unique_ptr<FenceTime>&& fenceTime) {
267 DisplayTimingData& displayData = mDisplayTimingData[displayId];
268 if (displayData.gpuEndFenceTime) {
269 nsecs_t signalTime = displayData.gpuEndFenceTime->getSignalTime();
270 if (signalTime != Fence::SIGNAL_TIME_INVALID && signalTime != Fence::SIGNAL_TIME_PENDING) {
271 for (auto&& [_, otherDisplayData] : mDisplayTimingData) {
272 // If the previous display started before us but ended after we should have
273 // started, then it likely delayed our start time and we must compensate for that.
274 // Displays finishing earlier should have already made their way through this call
275 // and swapped their timing into "lastValid" from "latest", so we check that here.
276 if (!otherDisplayData.lastValidGpuStartTime.has_value()) continue;
277 if ((*otherDisplayData.lastValidGpuStartTime < *displayData.gpuStartTime) &&
278 (*otherDisplayData.lastValidGpuEndTime > *displayData.gpuStartTime)) {
279 displayData.lastValidGpuStartTime = *otherDisplayData.lastValidGpuEndTime;
280 break;
281 }
282 }
283 displayData.lastValidGpuStartTime = displayData.gpuStartTime;
284 displayData.lastValidGpuEndTime = signalTime;
285 }
286 }
287 displayData.gpuEndFenceTime = std::move(fenceTime);
288 displayData.gpuStartTime = systemTime();
289}
290
Matt Buckley16dec1f2022-06-07 21:46:20 +0000291void PowerAdvisor::setHwcValidateTiming(DisplayId displayId, nsecs_t validateStartTime,
292 nsecs_t validateEndTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000293 DisplayTimingData& displayData = mDisplayTimingData[displayId];
Matt Buckley16dec1f2022-06-07 21:46:20 +0000294 displayData.hwcValidateStartTime = validateStartTime;
295 displayData.hwcValidateEndTime = validateEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000296}
297
Matt Buckley16dec1f2022-06-07 21:46:20 +0000298void PowerAdvisor::setHwcPresentTiming(DisplayId displayId, nsecs_t presentStartTime,
299 nsecs_t presentEndTime) {
Matt Buckley50c44062022-01-17 20:48:10 +0000300 DisplayTimingData& displayData = mDisplayTimingData[displayId];
Matt Buckley16dec1f2022-06-07 21:46:20 +0000301 displayData.hwcPresentStartTime = presentStartTime;
302 displayData.hwcPresentEndTime = presentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000303}
304
305void PowerAdvisor::setSkippedValidate(DisplayId displayId, bool skipped) {
306 mDisplayTimingData[displayId].skippedValidate = skipped;
307}
308
309void PowerAdvisor::setRequiresClientComposition(DisplayId displayId,
310 bool requiresClientComposition) {
311 mDisplayTimingData[displayId].usedClientComposition = requiresClientComposition;
312}
313
314void PowerAdvisor::setExpectedPresentTime(nsecs_t expectedPresentTime) {
315 mExpectedPresentTimes.append(expectedPresentTime);
316}
317
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700318void PowerAdvisor::setPresentFenceTime(nsecs_t presentFenceTime) {
319 mLastPresentFenceTime = presentFenceTime;
320}
321
Matt Buckley50c44062022-01-17 20:48:10 +0000322void PowerAdvisor::setFrameDelay(nsecs_t frameDelayDuration) {
323 mFrameDelayDuration = frameDelayDuration;
324}
325
Matt Buckley16dec1f2022-06-07 21:46:20 +0000326void PowerAdvisor::setHwcPresentDelayedTime(
Matt Buckley50c44062022-01-17 20:48:10 +0000327 DisplayId displayId, std::chrono::steady_clock::time_point earliestFrameStartTime) {
Matt Buckley16dec1f2022-06-07 21:46:20 +0000328 mDisplayTimingData[displayId].hwcPresentDelayedTime =
Matt Buckley50c44062022-01-17 20:48:10 +0000329 (earliestFrameStartTime - std::chrono::steady_clock::now()).count() + systemTime();
330}
331
332void PowerAdvisor::setCommitStart(nsecs_t commitStartTime) {
333 mCommitStartTimes.append(commitStartTime);
334}
335
336void PowerAdvisor::setCompositeEnd(nsecs_t compositeEnd) {
337 mLastCompositeEndTime = compositeEnd;
338 // calculate the postcomp time here as well
Matt Buckley16dec1f2022-06-07 21:46:20 +0000339 std::vector<DisplayId>&& displays = getOrderedDisplayIds(&DisplayTimingData::hwcPresentEndTime);
Matt Buckley50c44062022-01-17 20:48:10 +0000340 DisplayTimingData& timingData = mDisplayTimingData[displays.back()];
341 mLastPostcompDuration = compositeEnd -
Matt Buckley16dec1f2022-06-07 21:46:20 +0000342 (timingData.skippedValidate ? *timingData.hwcValidateEndTime
343 : *timingData.hwcPresentEndTime);
Matt Buckley50c44062022-01-17 20:48:10 +0000344}
345
346void PowerAdvisor::setDisplays(std::vector<DisplayId>& displayIds) {
347 mDisplayIds = displayIds;
348}
349
350void PowerAdvisor::setTotalFrameTargetWorkDuration(nsecs_t targetDuration) {
351 mTotalFrameTargetDuration = targetDuration;
352}
353
354std::vector<DisplayId> PowerAdvisor::getOrderedDisplayIds(
355 std::optional<nsecs_t> DisplayTimingData::*sortBy) {
356 std::vector<DisplayId> sortedDisplays;
357 std::copy_if(mDisplayIds.begin(), mDisplayIds.end(), std::back_inserter(sortedDisplays),
358 [&](DisplayId id) {
359 return mDisplayTimingData.count(id) &&
360 (mDisplayTimingData[id].*sortBy).has_value();
361 });
362 std::sort(sortedDisplays.begin(), sortedDisplays.end(), [&](DisplayId idA, DisplayId idB) {
363 return *(mDisplayTimingData[idA].*sortBy) < *(mDisplayTimingData[idB].*sortBy);
364 });
365 return sortedDisplays;
366}
367
368std::optional<nsecs_t> PowerAdvisor::estimateWorkDuration(bool earlyHint) {
369 if (earlyHint && (!mExpectedPresentTimes.isFull() || !mCommitStartTimes.isFull())) {
370 return std::nullopt;
371 }
372
373 // Tracks when we finish presenting to hwc
374 nsecs_t estimatedEndTime = mCommitStartTimes[0];
375
376 // How long we spent this frame not doing anything, waiting for fences or vsync
377 nsecs_t idleDuration = 0;
378
379 // Most recent previous gpu end time in the current frame, probably from a prior display, used
380 // as the start time for the next gpu operation if it ran over time since it probably blocked
381 std::optional<nsecs_t> previousValidGpuEndTime;
382
383 // The currently estimated gpu end time for the frame,
384 // used to accumulate gpu time as we iterate over the active displays
385 std::optional<nsecs_t> estimatedGpuEndTime;
386
387 // If we're predicting at the start of the frame, we use last frame as our reference point
388 // If we're predicting at the end of the frame, we use the current frame as a reference point
389 nsecs_t referenceFrameStartTime = (earlyHint ? mCommitStartTimes[-1] : mCommitStartTimes[0]);
390
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700391 // When the prior frame should be presenting to the display
392 // If we're predicting at the start of the frame, we use last frame's expected present time
393 // If we're predicting at the end of the frame, the present fence time is already known
394 nsecs_t lastFramePresentTime = (earlyHint ? mExpectedPresentTimes[-1] : mLastPresentFenceTime);
395
Matt Buckley50c44062022-01-17 20:48:10 +0000396 // The timing info for the previously calculated display, if there was one
397 std::optional<DisplayTimeline> previousDisplayReferenceTiming;
398 std::vector<DisplayId>&& displayIds =
Matt Buckley16dec1f2022-06-07 21:46:20 +0000399 getOrderedDisplayIds(&DisplayTimingData::hwcPresentStartTime);
Matt Buckley50c44062022-01-17 20:48:10 +0000400 DisplayTimeline referenceTiming, estimatedTiming;
401
402 // Iterate over the displays in the same order they are presented
403 for (DisplayId displayId : displayIds) {
404 if (mDisplayTimingData.count(displayId) == 0) {
405 continue;
406 }
407
408 auto& displayData = mDisplayTimingData.at(displayId);
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700409
410 // mLastPresentFenceTime should always be the time of the reference frame, since it will be
411 // the previous frame's present fence if called at the start, and current frame's if called
412 // at the end
413 referenceTiming = displayData.calculateDisplayTimeline(mLastPresentFenceTime);
Matt Buckley50c44062022-01-17 20:48:10 +0000414
Matt Buckley16dec1f2022-06-07 21:46:20 +0000415 // If this is the first display, include the duration before hwc present starts
Matt Buckley50c44062022-01-17 20:48:10 +0000416 if (!previousDisplayReferenceTiming.has_value()) {
Matt Buckley16dec1f2022-06-07 21:46:20 +0000417 estimatedEndTime += referenceTiming.hwcPresentStartTime - referenceFrameStartTime;
418 } else { // Otherwise add the time since last display's hwc present finished
419 estimatedEndTime += referenceTiming.hwcPresentStartTime -
420 previousDisplayReferenceTiming->hwcPresentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000421 }
422
Matt Buckley50689e82022-06-21 13:23:27 -0700423 // Late hint can re-use reference timing here since it's estimating its own reference frame
424 estimatedTiming = earlyHint
425 ? referenceTiming.estimateTimelineFromReference(lastFramePresentTime,
426 estimatedEndTime)
427 : referenceTiming;
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700428
Matt Buckley50c44062022-01-17 20:48:10 +0000429 // Update predicted present finish time with this display's present time
Matt Buckley16dec1f2022-06-07 21:46:20 +0000430 estimatedEndTime = estimatedTiming.hwcPresentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000431
432 // Track how long we spent waiting for the fence, can be excluded from the timing estimate
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700433 idleDuration += estimatedTiming.probablyWaitsForPresentFence
434 ? lastFramePresentTime - estimatedTiming.presentFenceWaitStartTime
Matt Buckley50c44062022-01-17 20:48:10 +0000435 : 0;
436
437 // Track how long we spent waiting to present, can be excluded from the timing estimate
Matt Buckley16dec1f2022-06-07 21:46:20 +0000438 idleDuration += earlyHint ? 0 : referenceTiming.hwcPresentDelayDuration;
Matt Buckley50c44062022-01-17 20:48:10 +0000439
440 // Estimate the reference frame's gpu timing
441 auto gpuTiming = displayData.estimateGpuTiming(previousValidGpuEndTime);
442 if (gpuTiming.has_value()) {
443 previousValidGpuEndTime = gpuTiming->startTime + gpuTiming->duration;
444
445 // Estimate the prediction frame's gpu end time from the reference frame
446 estimatedGpuEndTime =
Matt Buckley16dec1f2022-06-07 21:46:20 +0000447 std::max(estimatedTiming.hwcPresentStartTime, estimatedGpuEndTime.value_or(0)) +
Matt Buckley50c44062022-01-17 20:48:10 +0000448 gpuTiming->duration;
449 }
450 previousDisplayReferenceTiming = referenceTiming;
451 }
452 ATRACE_INT64("Idle duration", idleDuration);
453
454 // Don't count time spent idly waiting in the estimate as we could do more work in that time
455 estimatedEndTime -= idleDuration;
456
457 // We finish the frame when both present and the gpu are done, so wait for the later of the two
458 // Also add the frame delay duration since the target did not move while we were delayed
459 nsecs_t totalDuration = mFrameDelayDuration +
460 std::max(estimatedEndTime, estimatedGpuEndTime.value_or(0)) - mCommitStartTimes[0];
461
462 // We finish SurfaceFlinger when post-composition finishes, so add that in here
463 nsecs_t flingerDuration = estimatedEndTime + mLastPostcompDuration - mCommitStartTimes[0];
464 nsecs_t combinedDuration = combineTimingEstimates(totalDuration, flingerDuration);
465
466 return std::make_optional(combinedDuration);
467}
468
469nsecs_t PowerAdvisor::combineTimingEstimates(nsecs_t totalDuration, nsecs_t flingerDuration) {
470 nsecs_t targetDuration;
471 {
472 std::lock_guard lock(mPowerHalMutex);
473 targetDuration = *getPowerHal()->getTargetWorkDuration();
474 }
475 if (!mTotalFrameTargetDuration.has_value()) return flingerDuration;
476
477 // Normalize total to the flinger target (vsync period) since that's how often we actually send
478 // hints
479 nsecs_t normalizedTotalDuration = (targetDuration * totalDuration) / *mTotalFrameTargetDuration;
480 return std::max(flingerDuration, normalizedTotalDuration);
481}
482
483PowerAdvisor::DisplayTimeline PowerAdvisor::DisplayTimeline::estimateTimelineFromReference(
484 nsecs_t fenceTime, nsecs_t displayStartTime) {
485 DisplayTimeline estimated;
Matt Buckley16dec1f2022-06-07 21:46:20 +0000486 estimated.hwcPresentStartTime = displayStartTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000487
488 // We don't predict waiting for vsync alignment yet
Matt Buckley16dec1f2022-06-07 21:46:20 +0000489 estimated.hwcPresentDelayDuration = 0;
Matt Buckley50c44062022-01-17 20:48:10 +0000490
Matt Buckley50c44062022-01-17 20:48:10 +0000491 // How long we expect to run before we start waiting for the fence
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700492 // For now just re-use last frame's post-present duration and assume it will not change much
493 // Excludes time spent waiting for vsync since that's not going to be consistent
494 estimated.presentFenceWaitStartTime = estimated.hwcPresentStartTime +
495 (presentFenceWaitStartTime - (hwcPresentStartTime + hwcPresentDelayDuration));
496 estimated.probablyWaitsForPresentFence = fenceTime > estimated.presentFenceWaitStartTime;
497 estimated.hwcPresentEndTime = postPresentFenceHwcPresentDuration +
498 (estimated.probablyWaitsForPresentFence ? fenceTime
499 : estimated.presentFenceWaitStartTime);
Matt Buckley50c44062022-01-17 20:48:10 +0000500 return estimated;
501}
502
503PowerAdvisor::DisplayTimeline PowerAdvisor::DisplayTimingData::calculateDisplayTimeline(
504 nsecs_t fenceTime) {
505 DisplayTimeline timeline;
Matt Buckley16dec1f2022-06-07 21:46:20 +0000506 // How long between calling hwc present and trying to wait on the fence
507 const nsecs_t fenceWaitStartDelay =
508 (skippedValidate ? kFenceWaitStartDelaySkippedValidate : kFenceWaitStartDelayValidated)
509 .count();
Matt Buckley50c44062022-01-17 20:48:10 +0000510
Matt Buckley16dec1f2022-06-07 21:46:20 +0000511 // Did our reference frame wait for an appropriate vsync before calling into hwc
512 const bool waitedOnHwcPresentTime = hwcPresentDelayedTime.has_value() &&
513 *hwcPresentDelayedTime > *hwcPresentStartTime &&
514 *hwcPresentDelayedTime < *hwcPresentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000515
516 // Use validate start here if we skipped it because we did validate + present together
Matt Buckley16dec1f2022-06-07 21:46:20 +0000517 timeline.hwcPresentStartTime = skippedValidate ? *hwcValidateStartTime : *hwcPresentStartTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000518
519 // Use validate end here if we skipped it because we did validate + present together
Matt Buckley16dec1f2022-06-07 21:46:20 +0000520 timeline.hwcPresentEndTime = skippedValidate ? *hwcValidateEndTime : *hwcPresentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000521
Matt Buckley16dec1f2022-06-07 21:46:20 +0000522 // How long hwc present was delayed waiting for the next appropriate vsync
523 timeline.hwcPresentDelayDuration =
524 (waitedOnHwcPresentTime ? *hwcPresentDelayedTime - *hwcPresentStartTime : 0);
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700525 // When we started waiting for the present fence after calling into hwc present
526 timeline.presentFenceWaitStartTime =
Matt Buckley16dec1f2022-06-07 21:46:20 +0000527 timeline.hwcPresentStartTime + timeline.hwcPresentDelayDuration + fenceWaitStartDelay;
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700528 timeline.probablyWaitsForPresentFence = fenceTime > timeline.presentFenceWaitStartTime &&
Matt Buckley16dec1f2022-06-07 21:46:20 +0000529 fenceTime < timeline.hwcPresentEndTime;
Matt Buckley50c44062022-01-17 20:48:10 +0000530
Matt Buckley16dec1f2022-06-07 21:46:20 +0000531 // How long we ran after we finished waiting for the fence but before hwc present finished
Matt Buckleyc6b9d382022-06-17 15:28:07 -0700532 timeline.postPresentFenceHwcPresentDuration = timeline.hwcPresentEndTime -
533 (timeline.probablyWaitsForPresentFence ? fenceTime
534 : timeline.presentFenceWaitStartTime);
Matt Buckley50c44062022-01-17 20:48:10 +0000535 return timeline;
536}
537
538std::optional<PowerAdvisor::GpuTimeline> PowerAdvisor::DisplayTimingData::estimateGpuTiming(
539 std::optional<nsecs_t> previousEnd) {
540 if (!(usedClientComposition && lastValidGpuStartTime.has_value() && gpuEndFenceTime)) {
541 return std::nullopt;
542 }
543 const nsecs_t latestGpuStartTime = std::max(previousEnd.value_or(0), *gpuStartTime);
544 const nsecs_t latestGpuEndTime = gpuEndFenceTime->getSignalTime();
545 nsecs_t gpuDuration = 0;
546 if (latestGpuEndTime != Fence::SIGNAL_TIME_INVALID &&
547 latestGpuEndTime != Fence::SIGNAL_TIME_PENDING) {
548 // If we know how long the most recent gpu duration was, use that
549 gpuDuration = latestGpuEndTime - latestGpuStartTime;
550 } else if (lastValidGpuEndTime.has_value()) {
551 // If we don't have the fence data, use the most recent information we do have
552 gpuDuration = *lastValidGpuEndTime - *lastValidGpuStartTime;
553 if (latestGpuEndTime == Fence::SIGNAL_TIME_PENDING) {
554 // If pending but went over the previous duration, use current time as the end
555 gpuDuration = std::max(gpuDuration, systemTime() - latestGpuStartTime);
556 }
557 }
558 return GpuTimeline{.duration = gpuDuration, .startTime = latestGpuStartTime};
559}
560
Dan Stoza030fbc12020-02-19 15:32:01 -0800561class HidlPowerHalWrapper : public PowerAdvisor::HalWrapper {
562public:
563 HidlPowerHalWrapper(sp<V1_3::IPower> powerHal) : mPowerHal(std::move(powerHal)) {}
564
565 ~HidlPowerHalWrapper() override = default;
566
567 static std::unique_ptr<HalWrapper> connect() {
568 // Power HAL 1.3 is not guaranteed to be available, thus we need to query
569 // Power HAL 1.0 first and try to cast it to Power HAL 1.3.
Dan Stoza030fbc12020-02-19 15:32:01 -0800570 sp<V1_3::IPower> powerHal = nullptr;
Dan Stoza9c051c02020-02-28 10:19:07 -0800571 sp<V1_0::IPower> powerHal_1_0 = V1_0::IPower::getService();
572 if (powerHal_1_0 != nullptr) {
573 // Try to cast to Power HAL 1.3
574 powerHal = V1_3::IPower::castFrom(powerHal_1_0);
575 if (powerHal == nullptr) {
576 ALOGW("No Power HAL 1.3 service in system, disabling PowerAdvisor");
577 } else {
578 ALOGI("Loaded Power HAL 1.3 service");
Dan Stoza030fbc12020-02-19 15:32:01 -0800579 }
Dan Stoza9c051c02020-02-28 10:19:07 -0800580 } else {
581 ALOGW("No Power HAL found, disabling PowerAdvisor");
Dan Stoza030fbc12020-02-19 15:32:01 -0800582 }
Dan Stoza9c051c02020-02-28 10:19:07 -0800583
Dan Stoza030fbc12020-02-19 15:32:01 -0800584 if (powerHal == nullptr) {
585 return nullptr;
586 }
587
588 return std::make_unique<HidlPowerHalWrapper>(std::move(powerHal));
589 }
590
591 bool setExpensiveRendering(bool enabled) override {
592 ALOGV("HIDL setExpensiveRendering %s", enabled ? "T" : "F");
593 auto ret = mPowerHal->powerHintAsync_1_3(PowerHint::EXPENSIVE_RENDERING, enabled);
Ady Abrahamabce1652022-02-24 10:51:19 -0800594 if (ret.isOk()) {
595 traceExpensiveRendering(enabled);
596 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800597 return ret.isOk();
598 }
599
600 bool notifyDisplayUpdateImminent() override {
601 // Power HAL 1.x doesn't have a notification for this
602 ALOGV("HIDL notifyUpdateImminent received but can't send");
603 return true;
604 }
605
Matt Buckley06f299a2021-09-24 19:43:51 +0000606 bool supportsPowerHintSession() override { return false; }
607
608 bool isPowerHintSessionRunning() override { return false; }
609
610 void restartPowerHintSession() override {}
611
612 void setPowerHintSessionThreadIds(const std::vector<int32_t>&) override {}
613
614 bool startPowerHintSession() override { return false; }
615
616 void setTargetWorkDuration(int64_t) override {}
617
618 void sendActualWorkDuration(int64_t, nsecs_t) override {}
619
620 bool shouldReconnectHAL() override { return false; }
621
622 std::vector<int32_t> getPowerHintSessionThreadIds() override { return std::vector<int32_t>{}; }
623
624 std::optional<int64_t> getTargetWorkDuration() override { return std::nullopt; }
625
Dan Stoza030fbc12020-02-19 15:32:01 -0800626private:
Dan Stoza030fbc12020-02-19 15:32:01 -0800627 const sp<V1_3::IPower> mPowerHal = nullptr;
628};
629
Xiang Wange12b4fa2022-03-25 23:48:40 +0000630AidlPowerHalWrapper::AidlPowerHalWrapper(sp<IPower> powerHal) : mPowerHal(std::move(powerHal)) {
631 auto ret = mPowerHal->isModeSupported(Mode::EXPENSIVE_RENDERING, &mHasExpensiveRendering);
632 if (!ret.isOk()) {
633 mHasExpensiveRendering = false;
Dan Stoza030fbc12020-02-19 15:32:01 -0800634 }
635
Xiang Wange12b4fa2022-03-25 23:48:40 +0000636 ret = mPowerHal->isBoostSupported(Boost::DISPLAY_UPDATE_IMMINENT, &mHasDisplayUpdateImminent);
637 if (!ret.isOk()) {
638 mHasDisplayUpdateImminent = false;
Dan Stoza030fbc12020-02-19 15:32:01 -0800639 }
640
Xiang Wange12b4fa2022-03-25 23:48:40 +0000641 mSupportsPowerHint = checkPowerHintSessionSupported();
Matt Buckley50c44062022-01-17 20:48:10 +0000642
Matt Buckley111de032022-08-09 22:19:51 +0000643 mAllowedActualDeviation = base::GetIntProperty<nsecs_t>("debug.sf.allowed_actual_deviation", 0);
Xiang Wange12b4fa2022-03-25 23:48:40 +0000644}
Dan Stoza030fbc12020-02-19 15:32:01 -0800645
Xiang Wange12b4fa2022-03-25 23:48:40 +0000646AidlPowerHalWrapper::~AidlPowerHalWrapper() {
647 if (mPowerHintSession != nullptr) {
648 mPowerHintSession->close();
649 mPowerHintSession = nullptr;
Dan Stoza030fbc12020-02-19 15:32:01 -0800650 }
Matt Buckley50c44062022-01-17 20:48:10 +0000651}
Dan Stoza030fbc12020-02-19 15:32:01 -0800652
Xiang Wange12b4fa2022-03-25 23:48:40 +0000653std::unique_ptr<PowerAdvisor::HalWrapper> AidlPowerHalWrapper::connect() {
654 // This only waits if the service is actually declared
655 sp<IPower> powerHal = waitForVintfService<IPower>();
656 if (powerHal == nullptr) {
657 return nullptr;
658 }
659 ALOGI("Loaded AIDL Power HAL service");
660
661 return std::make_unique<AidlPowerHalWrapper>(std::move(powerHal));
662}
663
664bool AidlPowerHalWrapper::setExpensiveRendering(bool enabled) {
665 ALOGV("AIDL setExpensiveRendering %s", enabled ? "T" : "F");
666 if (!mHasExpensiveRendering) {
667 ALOGV("Skipped sending EXPENSIVE_RENDERING because HAL doesn't support it");
668 return true;
669 }
670
671 auto ret = mPowerHal->setMode(Mode::EXPENSIVE_RENDERING, enabled);
672 if (ret.isOk()) {
673 traceExpensiveRendering(enabled);
674 }
675 return ret.isOk();
676}
677
678bool AidlPowerHalWrapper::notifyDisplayUpdateImminent() {
679 ALOGV("AIDL notifyDisplayUpdateImminent");
680 if (!mHasDisplayUpdateImminent) {
681 ALOGV("Skipped sending DISPLAY_UPDATE_IMMINENT because HAL doesn't support it");
682 return true;
683 }
684
685 auto ret = mPowerHal->setBoost(Boost::DISPLAY_UPDATE_IMMINENT, 0);
686 return ret.isOk();
687}
688
Matt Buckley50c44062022-01-17 20:48:10 +0000689// Only version 2+ of the aidl supports power hint sessions, hidl has no support
Xiang Wange12b4fa2022-03-25 23:48:40 +0000690bool AidlPowerHalWrapper::supportsPowerHintSession() {
691 return mSupportsPowerHint;
692}
693
694bool AidlPowerHalWrapper::checkPowerHintSessionSupported() {
695 int64_t unused;
696 // Try to get preferred rate to determine if hint sessions are supported
697 // We check for isOk not EX_UNSUPPORTED_OPERATION to lump together errors
698 return mPowerHal->getHintSessionPreferredRate(&unused).isOk();
699}
700
701bool AidlPowerHalWrapper::isPowerHintSessionRunning() {
702 return mPowerHintSession != nullptr;
703}
704
705void AidlPowerHalWrapper::closePowerHintSession() {
706 if (mPowerHintSession != nullptr) {
707 mPowerHintSession->close();
708 mPowerHintSession = nullptr;
709 }
710}
711
712void AidlPowerHalWrapper::restartPowerHintSession() {
713 closePowerHintSession();
714 startPowerHintSession();
715}
716
717void AidlPowerHalWrapper::setPowerHintSessionThreadIds(const std::vector<int32_t>& threadIds) {
718 if (threadIds != mPowerHintThreadIds) {
719 mPowerHintThreadIds = threadIds;
720 if (isPowerHintSessionRunning()) {
721 restartPowerHintSession();
722 }
723 }
724}
725
726bool AidlPowerHalWrapper::startPowerHintSession() {
727 if (mPowerHintSession != nullptr || mPowerHintThreadIds.empty()) {
728 ALOGV("Cannot start power hint session, skipping");
729 return false;
730 }
731 auto ret =
732 mPowerHal->createHintSession(getpid(), static_cast<int32_t>(getuid()),
733 mPowerHintThreadIds, mTargetDuration, &mPowerHintSession);
734 if (!ret.isOk()) {
735 ALOGW("Failed to start power hint session with error: %s",
736 ret.exceptionToString(ret.exceptionCode()).c_str());
737 } else {
738 mLastTargetDurationSent = mTargetDuration;
739 }
740 return isPowerHintSessionRunning();
741}
742
Matt Buckley50c44062022-01-17 20:48:10 +0000743void AidlPowerHalWrapper::setTargetWorkDuration(int64_t targetDuration) {
Xiang Wange12b4fa2022-03-25 23:48:40 +0000744 ATRACE_CALL();
Matt Buckley50c44062022-01-17 20:48:10 +0000745 mTargetDuration = targetDuration;
746 if (sTraceHintSessionData) ATRACE_INT64("Time target", targetDuration);
747 if (isPowerHintSessionRunning() && (targetDuration != mLastTargetDurationSent)) {
748 ALOGV("Sending target time: %" PRId64 "ns", targetDuration);
749 mLastTargetDurationSent = targetDuration;
750 auto ret = mPowerHintSession->updateTargetWorkDuration(targetDuration);
Xiang Wange12b4fa2022-03-25 23:48:40 +0000751 if (!ret.isOk()) {
752 ALOGW("Failed to set power hint target work duration with error: %s",
753 ret.exceptionMessage().c_str());
754 mShouldReconnectHal = true;
755 }
756 }
757}
758
Matt Buckley50c44062022-01-17 20:48:10 +0000759bool AidlPowerHalWrapper::shouldReportActualDurations() {
Matt Buckleya8a45972022-07-27 22:01:27 +0000760 // Report if we have never reported before or will go stale next frame
Xiang Wange12b4fa2022-03-25 23:48:40 +0000761 if (!mLastActualDurationSent.has_value() ||
Matt Buckleya8a45972022-07-27 22:01:27 +0000762 (mLastTargetDurationSent + systemTime() - mLastActualReportTimestamp) >
763 kStaleTimeout.count()) {
Xiang Wange12b4fa2022-03-25 23:48:40 +0000764 return true;
765 }
766
767 if (!mActualDuration.has_value()) {
768 return false;
769 }
Matt Buckley50c44062022-01-17 20:48:10 +0000770 // Report if the change in actual duration exceeds the threshold
771 return abs(*mActualDuration - *mLastActualDurationSent) > mAllowedActualDeviation;
Xiang Wange12b4fa2022-03-25 23:48:40 +0000772}
773
Matt Buckley50c44062022-01-17 20:48:10 +0000774void AidlPowerHalWrapper::sendActualWorkDuration(int64_t actualDuration, nsecs_t timestamp) {
Xiang Wange12b4fa2022-03-25 23:48:40 +0000775 ATRACE_CALL();
776
Matt Buckley50c44062022-01-17 20:48:10 +0000777 if (actualDuration < 0 || !isPowerHintSessionRunning()) {
Xiang Wange12b4fa2022-03-25 23:48:40 +0000778 ALOGV("Failed to send actual work duration, skipping");
779 return;
780 }
Matt Buckley50c44062022-01-17 20:48:10 +0000781 const nsecs_t reportedDuration = actualDuration;
Xiang Wange12b4fa2022-03-25 23:48:40 +0000782
Xiang Wang0aba49e2022-04-06 16:13:59 +0000783 mActualDuration = reportedDuration;
784 WorkDuration duration;
785 duration.durationNanos = reportedDuration;
Matt Buckley50c44062022-01-17 20:48:10 +0000786 duration.timeStampNanos = timestamp;
Xiang Wange12b4fa2022-03-25 23:48:40 +0000787 mPowerHintQueue.push_back(duration);
788
Xiang Wange12b4fa2022-03-25 23:48:40 +0000789 if (sTraceHintSessionData) {
Matt Buckley50c44062022-01-17 20:48:10 +0000790 ATRACE_INT64("Measured duration", actualDuration);
791 ATRACE_INT64("Target error term", actualDuration - mTargetDuration);
Xiang Wang0aba49e2022-04-06 16:13:59 +0000792
793 ATRACE_INT64("Reported duration", reportedDuration);
794 ATRACE_INT64("Reported target", mLastTargetDurationSent);
Matt Buckley50c44062022-01-17 20:48:10 +0000795 ATRACE_INT64("Reported target error term", reportedDuration - mLastTargetDurationSent);
Xiang Wange12b4fa2022-03-25 23:48:40 +0000796 }
797
Xiang Wang0aba49e2022-04-06 16:13:59 +0000798 ALOGV("Sending actual work duration of: %" PRId64 " on reported target: %" PRId64
Xiang Wange12b4fa2022-03-25 23:48:40 +0000799 " with error: %" PRId64,
Matt Buckley50c44062022-01-17 20:48:10 +0000800 reportedDuration, mLastTargetDurationSent, reportedDuration - mLastTargetDurationSent);
Xiang Wange12b4fa2022-03-25 23:48:40 +0000801
802 // This rate limiter queues similar duration reports to the powerhal into
803 // batches to avoid excessive binder calls. The criteria to send a given batch
804 // are outlined in shouldReportActualDurationsNow()
Matt Buckley50c44062022-01-17 20:48:10 +0000805 if (shouldReportActualDurations()) {
Xiang Wange12b4fa2022-03-25 23:48:40 +0000806 ALOGV("Sending hint update batch");
807 mLastActualReportTimestamp = systemTime();
808 auto ret = mPowerHintSession->reportActualWorkDuration(mPowerHintQueue);
809 if (!ret.isOk()) {
810 ALOGW("Failed to report actual work durations with error: %s",
811 ret.exceptionMessage().c_str());
812 mShouldReconnectHal = true;
813 }
814 mPowerHintQueue.clear();
Matt Buckley50c44062022-01-17 20:48:10 +0000815 // We save the actual duration here for rate limiting
816 mLastActualDurationSent = actualDuration;
Xiang Wange12b4fa2022-03-25 23:48:40 +0000817 }
818}
819
820bool AidlPowerHalWrapper::shouldReconnectHAL() {
821 return mShouldReconnectHal;
822}
823
824std::vector<int32_t> AidlPowerHalWrapper::getPowerHintSessionThreadIds() {
825 return mPowerHintThreadIds;
826}
827
828std::optional<int64_t> AidlPowerHalWrapper::getTargetWorkDuration() {
829 return mTargetDuration;
830}
831
Matt Buckley50c44062022-01-17 20:48:10 +0000832void AidlPowerHalWrapper::setAllowedActualDeviation(nsecs_t allowedDeviation) {
833 mAllowedActualDeviation = allowedDeviation;
834}
835
Matt Buckleyef51fba2021-10-12 19:30:12 +0000836const bool AidlPowerHalWrapper::sTraceHintSessionData =
837 base::GetBoolProperty(std::string("debug.sf.trace_hint_sessions"), false);
838
Dan Stoza030fbc12020-02-19 15:32:01 -0800839PowerAdvisor::HalWrapper* PowerAdvisor::getPowerHal() {
840 static std::unique_ptr<HalWrapper> sHalWrapper = nullptr;
Dan Stoza9c051c02020-02-28 10:19:07 -0800841 static bool sHasHal = true;
Michael Wright1509a232018-06-21 02:50:34 +0100842
Dan Stoza9c051c02020-02-28 10:19:07 -0800843 if (!sHasHal) {
844 return nullptr;
845 }
846
Matt Buckley50c44062022-01-17 20:48:10 +0000847 // Grab old hint session values before we destroy any existing wrapper
Matt Buckley06f299a2021-09-24 19:43:51 +0000848 std::vector<int32_t> oldPowerHintSessionThreadIds;
849 std::optional<int64_t> oldTargetWorkDuration;
850
851 if (sHalWrapper != nullptr) {
852 oldPowerHintSessionThreadIds = sHalWrapper->getPowerHintSessionThreadIds();
853 oldTargetWorkDuration = sHalWrapper->getTargetWorkDuration();
854 }
855
Dan Stoza9c051c02020-02-28 10:19:07 -0800856 // If we used to have a HAL, but it stopped responding, attempt to reconnect
Michael Wright1509a232018-06-21 02:50:34 +0100857 if (mReconnectPowerHal) {
Dan Stoza030fbc12020-02-19 15:32:01 -0800858 sHalWrapper = nullptr;
Michael Wright1509a232018-06-21 02:50:34 +0100859 mReconnectPowerHal = false;
860 }
861
Dan Stoza030fbc12020-02-19 15:32:01 -0800862 if (sHalWrapper != nullptr) {
Matt Buckley06f299a2021-09-24 19:43:51 +0000863 auto wrapper = sHalWrapper.get();
Matt Buckley50c44062022-01-17 20:48:10 +0000864 // If the wrapper is fine, return it, but if it indicates a reconnect, remake it
Matt Buckley06f299a2021-09-24 19:43:51 +0000865 if (!wrapper->shouldReconnectHAL()) {
866 return wrapper;
867 }
Xiang Wang65a2e6f2022-04-18 21:19:17 +0000868 ALOGD("Reconnecting Power HAL");
Matt Buckley06f299a2021-09-24 19:43:51 +0000869 sHalWrapper = nullptr;
Michael Wright1509a232018-06-21 02:50:34 +0100870 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800871
Matt Buckley50c44062022-01-17 20:48:10 +0000872 // At this point, we know for sure there is no running session
Matt Buckley06f299a2021-09-24 19:43:51 +0000873 mPowerHintSessionRunning = false;
874
Dan Stoza030fbc12020-02-19 15:32:01 -0800875 // First attempt to connect to the AIDL Power HAL
876 sHalWrapper = AidlPowerHalWrapper::connect();
877
878 // If that didn't succeed, attempt to connect to the HIDL Power HAL
879 if (sHalWrapper == nullptr) {
880 sHalWrapper = HidlPowerHalWrapper::connect();
Xiang Wang65a2e6f2022-04-18 21:19:17 +0000881 } else {
882 ALOGD("Successfully connecting AIDL Power HAL");
Matt Buckley50c44062022-01-17 20:48:10 +0000883 // If AIDL, pass on any existing hint session values
Matt Buckley06f299a2021-09-24 19:43:51 +0000884 sHalWrapper->setPowerHintSessionThreadIds(oldPowerHintSessionThreadIds);
Matt Buckley50c44062022-01-17 20:48:10 +0000885 // Only set duration and start if duration is defined
Matt Buckley06f299a2021-09-24 19:43:51 +0000886 if (oldTargetWorkDuration.has_value()) {
887 sHalWrapper->setTargetWorkDuration(*oldTargetWorkDuration);
Matt Buckley50c44062022-01-17 20:48:10 +0000888 // Only start if possible to run and both threadids and duration are defined
Matt Buckley06f299a2021-09-24 19:43:51 +0000889 if (usePowerHintSession() && !oldPowerHintSessionThreadIds.empty()) {
890 mPowerHintSessionRunning = sHalWrapper->startPowerHintSession();
891 }
892 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800893 }
894
Dan Stoza9c051c02020-02-28 10:19:07 -0800895 // If we make it to this point and still don't have a HAL, it's unlikely we
896 // will, so stop trying
897 if (sHalWrapper == nullptr) {
898 sHasHal = false;
899 }
900
Dan Stoza030fbc12020-02-19 15:32:01 -0800901 return sHalWrapper.get();
Michael Wright1509a232018-06-21 02:50:34 +0100902}
903
904} // namespace impl
905} // namespace Hwc2
906} // namespace android