blob: 20e38d01044f201e40d0d0ded05f7bad278296bc [file] [log] [blame]
Michael Wright1509a232018-06-21 02:50:34 +01001/*
2 * Copyright 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Dan Stoza030fbc12020-02-19 15:32:01 -080017//#define LOG_NDEBUG 0
18
Ady Abrahamabce1652022-02-24 10:51:19 -080019#define ATRACE_TAG ATRACE_TAG_GRAPHICS
20
Michael Wright1509a232018-06-21 02:50:34 +010021#undef LOG_TAG
22#define LOG_TAG "PowerAdvisor"
23
Matt Buckley06f299a2021-09-24 19:43:51 +000024#include <unistd.h>
Michael Wright1509a232018-06-21 02:50:34 +010025#include <cinttypes>
Matt Buckley06f299a2021-09-24 19:43:51 +000026#include <cstdint>
27#include <optional>
Michael Wright1509a232018-06-21 02:50:34 +010028
Dan Stoza030fbc12020-02-19 15:32:01 -080029#include <android-base/properties.h>
Michael Wright1509a232018-06-21 02:50:34 +010030#include <utils/Log.h>
31#include <utils/Mutex.h>
Ady Abrahamabce1652022-02-24 10:51:19 -080032#include <utils/Trace.h>
Michael Wright1509a232018-06-21 02:50:34 +010033
Dan Stoza030fbc12020-02-19 15:32:01 -080034#include <android/hardware/power/1.3/IPower.h>
Matt Buckley06f299a2021-09-24 19:43:51 +000035#include <android/hardware/power/IPowerHintSession.h>
36#include <android/hardware/power/WorkDuration.h>
37
Dan Stoza030fbc12020-02-19 15:32:01 -080038#include <binder/IServiceManager.h>
39
40#include "../SurfaceFlingerProperties.h"
41
Michael Wright1509a232018-06-21 02:50:34 +010042#include "PowerAdvisor.h"
Alec Mouridea1ac52021-06-23 18:12:18 -070043#include "SurfaceFlinger.h"
Michael Wright1509a232018-06-21 02:50:34 +010044
45namespace android {
46namespace Hwc2 {
47
48PowerAdvisor::~PowerAdvisor() = default;
49
50namespace impl {
51
52namespace V1_0 = android::hardware::power::V1_0;
Dan Stoza030fbc12020-02-19 15:32:01 -080053namespace V1_3 = android::hardware::power::V1_3;
Michael Wright1509a232018-06-21 02:50:34 +010054using V1_3::PowerHint;
55
Dan Stoza030fbc12020-02-19 15:32:01 -080056using android::hardware::power::Boost;
57using android::hardware::power::IPower;
Matt Buckley06f299a2021-09-24 19:43:51 +000058using android::hardware::power::IPowerHintSession;
Dan Stoza030fbc12020-02-19 15:32:01 -080059using android::hardware::power::Mode;
Matt Buckley06f299a2021-09-24 19:43:51 +000060using android::hardware::power::WorkDuration;
61
Dan Stoza030fbc12020-02-19 15:32:01 -080062using scheduler::OneShotTimer;
63
Michael Wright1509a232018-06-21 02:50:34 +010064PowerAdvisor::~PowerAdvisor() = default;
65
Dan Stoza030fbc12020-02-19 15:32:01 -080066namespace {
67int32_t getUpdateTimeout() {
68 // Default to a timeout of 80ms if nothing else is specified
69 static int32_t timeout = sysprop::display_update_imminent_timeout_ms(80);
70 return timeout;
71}
72
Ady Abrahamabce1652022-02-24 10:51:19 -080073void traceExpensiveRendering(bool enabled) {
74 if (enabled) {
75 ATRACE_ASYNC_BEGIN("ExpensiveRendering", 0);
76 } else {
77 ATRACE_ASYNC_END("ExpensiveRendering", 0);
78 }
79}
80
Dan Stoza030fbc12020-02-19 15:32:01 -080081} // namespace
82
Alec Mouridea1ac52021-06-23 18:12:18 -070083PowerAdvisor::PowerAdvisor(SurfaceFlinger& flinger)
84 : mFlinger(flinger),
85 mUseScreenUpdateTimer(getUpdateTimeout() > 0),
86 mScreenUpdateTimer(
Ady Abrahamdb3dfee2020-11-17 17:07:12 -080087 "UpdateImminentTimer", OneShotTimer::Interval(getUpdateTimeout()),
Dan Stoza030fbc12020-02-19 15:32:01 -080088 /* resetCallback */ [this] { mSendUpdateImminent.store(false); },
Alec Mouridea1ac52021-06-23 18:12:18 -070089 /* timeoutCallback */
90 [this] {
91 mSendUpdateImminent.store(true);
92 mFlinger.disableExpensiveRendering();
93 }) {}
94
95void PowerAdvisor::init() {
96 // Defer starting the screen update timer until SurfaceFlinger finishes construction.
97 if (mUseScreenUpdateTimer) {
98 mScreenUpdateTimer.start();
Dan Stoza030fbc12020-02-19 15:32:01 -080099 }
100}
Michael Wright1509a232018-06-21 02:50:34 +0100101
Dan Stoza29e7bdf2020-03-23 14:43:09 -0700102void PowerAdvisor::onBootFinished() {
103 mBootFinished.store(true);
104}
105
Peiyong Lin74ca2f42019-01-14 19:36:57 -0800106void PowerAdvisor::setExpensiveRenderingExpected(DisplayId displayId, bool expected) {
Michael Wright1509a232018-06-21 02:50:34 +0100107 if (expected) {
108 mExpensiveDisplays.insert(displayId);
109 } else {
110 mExpensiveDisplays.erase(displayId);
111 }
112
Michael Wright1509a232018-06-21 02:50:34 +0100113 const bool expectsExpensiveRendering = !mExpensiveDisplays.empty();
114 if (mNotifiedExpensiveRendering != expectsExpensiveRendering) {
Dan Stoza20950002020-06-18 14:56:58 -0700115 std::lock_guard lock(mPowerHalMutex);
Dan Stoza030fbc12020-02-19 15:32:01 -0800116 HalWrapper* const halWrapper = getPowerHal();
117 if (halWrapper == nullptr) {
Peiyong Lin81934972018-07-02 11:00:54 -0700118 return;
119 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800120
121 if (!halWrapper->setExpensiveRendering(expectsExpensiveRendering)) {
122 // The HAL has become unavailable; attempt to reconnect later
Michael Wright1509a232018-06-21 02:50:34 +0100123 mReconnectPowerHal = true;
124 return;
125 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800126
Michael Wright1509a232018-06-21 02:50:34 +0100127 mNotifiedExpensiveRendering = expectsExpensiveRendering;
128 }
129}
130
Dan Stoza030fbc12020-02-19 15:32:01 -0800131void PowerAdvisor::notifyDisplayUpdateImminent() {
Dan Stoza29e7bdf2020-03-23 14:43:09 -0700132 // Only start sending this notification once the system has booted so we don't introduce an
133 // early-boot dependency on Power HAL
134 if (!mBootFinished.load()) {
135 return;
136 }
137
Dan Stoza030fbc12020-02-19 15:32:01 -0800138 if (mSendUpdateImminent.load()) {
Dan Stoza20950002020-06-18 14:56:58 -0700139 std::lock_guard lock(mPowerHalMutex);
Dan Stoza030fbc12020-02-19 15:32:01 -0800140 HalWrapper* const halWrapper = getPowerHal();
141 if (halWrapper == nullptr) {
142 return;
143 }
144
145 if (!halWrapper->notifyDisplayUpdateImminent()) {
146 // The HAL has become unavailable; attempt to reconnect later
147 mReconnectPowerHal = true;
148 return;
149 }
150 }
151
Alec Mouridea1ac52021-06-23 18:12:18 -0700152 if (mUseScreenUpdateTimer) {
153 mScreenUpdateTimer.reset();
Dan Stoza030fbc12020-02-19 15:32:01 -0800154 }
155}
156
Matt Buckley06f299a2021-09-24 19:43:51 +0000157// checks both if it supports and if it's enabled
158bool PowerAdvisor::usePowerHintSession() {
159 // uses cached value since the underlying support and flag are unlikely to change at runtime
Matt Buckley06f299a2021-09-24 19:43:51 +0000160 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
Matt Buckley50c44062022-01-17 20:48:10 +0000177void PowerAdvisor::setTargetWorkDuration(int64_t targetDuration) {
Matt Buckleyef51fba2021-10-12 19:30:12 +0000178 if (!usePowerHintSession()) {
Matt Buckley06f299a2021-09-24 19:43:51 +0000179 ALOGV("Power hint session target duration cannot be set, skipping");
180 return;
181 }
182 {
183 std::lock_guard lock(mPowerHalMutex);
184 HalWrapper* const halWrapper = getPowerHal();
185 if (halWrapper != nullptr) {
Matt Buckley50c44062022-01-17 20:48:10 +0000186 halWrapper->setTargetWorkDuration(targetDuration);
Matt Buckley06f299a2021-09-24 19:43:51 +0000187 }
188 }
189}
190
Matt Buckley50c44062022-01-17 20:48:10 +0000191void PowerAdvisor::sendActualWorkDuration() {
Matt Buckley06f299a2021-09-24 19:43:51 +0000192 if (!mBootFinished || !usePowerHintSession()) {
193 ALOGV("Actual work duration power hint cannot be sent, skipping");
194 return;
195 }
Matt Buckley50c44062022-01-17 20:48:10 +0000196 const std::optional<nsecs_t> actualDuration = estimateWorkDuration(false);
197 if (actualDuration.has_value()) {
Matt Buckley06f299a2021-09-24 19:43:51 +0000198 std::lock_guard lock(mPowerHalMutex);
199 HalWrapper* const halWrapper = getPowerHal();
200 if (halWrapper != nullptr) {
Matt Buckley50c44062022-01-17 20:48:10 +0000201 halWrapper->sendActualWorkDuration(*actualDuration + kTargetSafetyMargin.count(),
202 systemTime());
Matt Buckley06f299a2021-09-24 19:43:51 +0000203 }
204 }
205}
206
Matt Buckley50c44062022-01-17 20:48:10 +0000207void PowerAdvisor::sendPredictedWorkDuration() {
208 if (!mBootFinished || !usePowerHintSession()) {
209 ALOGV("Actual work duration power hint cannot be sent, skipping");
210 return;
211 }
212
213 const std::optional<nsecs_t> predictedDuration = estimateWorkDuration(true);
214
215 if (predictedDuration.has_value()) {
216 std::lock_guard lock(mPowerHalMutex);
217 HalWrapper* const halWrapper = getPowerHal();
218 if (halWrapper != nullptr) {
219 halWrapper->sendActualWorkDuration(*predictedDuration, systemTime());
220 }
221 }
222}
223
Matt Buckley06f299a2021-09-24 19:43:51 +0000224void PowerAdvisor::enablePowerHint(bool enabled) {
225 mPowerHintEnabled = enabled;
226}
227
Matt Buckleyef51fba2021-10-12 19:30:12 +0000228bool PowerAdvisor::startPowerHintSession(const std::vector<int32_t>& threadIds) {
229 if (!usePowerHintSession()) {
230 ALOGI("Power hint session cannot be started, skipping");
231 }
232 {
233 std::lock_guard lock(mPowerHalMutex);
234 HalWrapper* halWrapper = getPowerHal();
235 if (halWrapper != nullptr && usePowerHintSession()) {
236 halWrapper->setPowerHintSessionThreadIds(threadIds);
237 mPowerHintSessionRunning = halWrapper->startPowerHintSession();
238 }
239 }
240 return mPowerHintSessionRunning;
241}
242
Matt Buckley50c44062022-01-17 20:48:10 +0000243void PowerAdvisor::setGpuFenceTime(DisplayId displayId, std::unique_ptr<FenceTime>&& fenceTime) {
244 DisplayTimingData& displayData = mDisplayTimingData[displayId];
245 if (displayData.gpuEndFenceTime) {
246 nsecs_t signalTime = displayData.gpuEndFenceTime->getSignalTime();
247 if (signalTime != Fence::SIGNAL_TIME_INVALID && signalTime != Fence::SIGNAL_TIME_PENDING) {
248 for (auto&& [_, otherDisplayData] : mDisplayTimingData) {
249 // If the previous display started before us but ended after we should have
250 // started, then it likely delayed our start time and we must compensate for that.
251 // Displays finishing earlier should have already made their way through this call
252 // and swapped their timing into "lastValid" from "latest", so we check that here.
253 if (!otherDisplayData.lastValidGpuStartTime.has_value()) continue;
254 if ((*otherDisplayData.lastValidGpuStartTime < *displayData.gpuStartTime) &&
255 (*otherDisplayData.lastValidGpuEndTime > *displayData.gpuStartTime)) {
256 displayData.lastValidGpuStartTime = *otherDisplayData.lastValidGpuEndTime;
257 break;
258 }
259 }
260 displayData.lastValidGpuStartTime = displayData.gpuStartTime;
261 displayData.lastValidGpuEndTime = signalTime;
262 }
263 }
264 displayData.gpuEndFenceTime = std::move(fenceTime);
265 displayData.gpuStartTime = systemTime();
266}
267
268void PowerAdvisor::setValidateTiming(DisplayId displayId, nsecs_t validateStartTime,
269 nsecs_t validateEndTime) {
270 DisplayTimingData& displayData = mDisplayTimingData[displayId];
271 displayData.validateStartTime = validateStartTime;
272 displayData.validateEndTime = validateEndTime;
273}
274
275void PowerAdvisor::setPresentTiming(DisplayId displayId, nsecs_t presentStartTime,
276 nsecs_t presentEndTime) {
277 DisplayTimingData& displayData = mDisplayTimingData[displayId];
278 displayData.presentStartTime = presentStartTime;
279 displayData.presentEndTime = presentEndTime;
280}
281
282void PowerAdvisor::setSkippedValidate(DisplayId displayId, bool skipped) {
283 mDisplayTimingData[displayId].skippedValidate = skipped;
284}
285
286void PowerAdvisor::setRequiresClientComposition(DisplayId displayId,
287 bool requiresClientComposition) {
288 mDisplayTimingData[displayId].usedClientComposition = requiresClientComposition;
289}
290
291void PowerAdvisor::setExpectedPresentTime(nsecs_t expectedPresentTime) {
292 mExpectedPresentTimes.append(expectedPresentTime);
293}
294
295void PowerAdvisor::setFrameDelay(nsecs_t frameDelayDuration) {
296 mFrameDelayDuration = frameDelayDuration;
297}
298
299void PowerAdvisor::setPresentDelayedTime(
300 DisplayId displayId, std::chrono::steady_clock::time_point earliestFrameStartTime) {
301 mDisplayTimingData[displayId].presentDelayedTime =
302 (earliestFrameStartTime - std::chrono::steady_clock::now()).count() + systemTime();
303}
304
305void PowerAdvisor::setCommitStart(nsecs_t commitStartTime) {
306 mCommitStartTimes.append(commitStartTime);
307}
308
309void PowerAdvisor::setCompositeEnd(nsecs_t compositeEnd) {
310 mLastCompositeEndTime = compositeEnd;
311 // calculate the postcomp time here as well
312 std::vector<DisplayId>&& displays = getOrderedDisplayIds(&DisplayTimingData::presentEndTime);
313 DisplayTimingData& timingData = mDisplayTimingData[displays.back()];
314 mLastPostcompDuration = compositeEnd -
315 (timingData.skippedValidate ? *timingData.validateEndTime : *timingData.presentEndTime);
316}
317
318void PowerAdvisor::setDisplays(std::vector<DisplayId>& displayIds) {
319 mDisplayIds = displayIds;
320}
321
322void PowerAdvisor::setTotalFrameTargetWorkDuration(nsecs_t targetDuration) {
323 mTotalFrameTargetDuration = targetDuration;
324}
325
326std::vector<DisplayId> PowerAdvisor::getOrderedDisplayIds(
327 std::optional<nsecs_t> DisplayTimingData::*sortBy) {
328 std::vector<DisplayId> sortedDisplays;
329 std::copy_if(mDisplayIds.begin(), mDisplayIds.end(), std::back_inserter(sortedDisplays),
330 [&](DisplayId id) {
331 return mDisplayTimingData.count(id) &&
332 (mDisplayTimingData[id].*sortBy).has_value();
333 });
334 std::sort(sortedDisplays.begin(), sortedDisplays.end(), [&](DisplayId idA, DisplayId idB) {
335 return *(mDisplayTimingData[idA].*sortBy) < *(mDisplayTimingData[idB].*sortBy);
336 });
337 return sortedDisplays;
338}
339
340std::optional<nsecs_t> PowerAdvisor::estimateWorkDuration(bool earlyHint) {
341 if (earlyHint && (!mExpectedPresentTimes.isFull() || !mCommitStartTimes.isFull())) {
342 return std::nullopt;
343 }
344
345 // Tracks when we finish presenting to hwc
346 nsecs_t estimatedEndTime = mCommitStartTimes[0];
347
348 // How long we spent this frame not doing anything, waiting for fences or vsync
349 nsecs_t idleDuration = 0;
350
351 // Most recent previous gpu end time in the current frame, probably from a prior display, used
352 // as the start time for the next gpu operation if it ran over time since it probably blocked
353 std::optional<nsecs_t> previousValidGpuEndTime;
354
355 // The currently estimated gpu end time for the frame,
356 // used to accumulate gpu time as we iterate over the active displays
357 std::optional<nsecs_t> estimatedGpuEndTime;
358
359 // If we're predicting at the start of the frame, we use last frame as our reference point
360 // If we're predicting at the end of the frame, we use the current frame as a reference point
361 nsecs_t referenceFrameStartTime = (earlyHint ? mCommitStartTimes[-1] : mCommitStartTimes[0]);
362
363 // We need an idea of when the last present fence fired and how long it made us wait
364 // If we're predicting at the start of the frame, we want frame n-2's present fence time
365 // If we're predicting at the end of the frame we want frame n-1's present time
366 nsecs_t referenceFenceTime =
367 (earlyHint ? mExpectedPresentTimes[-2] : mExpectedPresentTimes[-1]);
368 // The timing info for the previously calculated display, if there was one
369 std::optional<DisplayTimeline> previousDisplayReferenceTiming;
370 std::vector<DisplayId>&& displayIds =
371 getOrderedDisplayIds(&DisplayTimingData::presentStartTime);
372 DisplayTimeline referenceTiming, estimatedTiming;
373
374 // Iterate over the displays in the same order they are presented
375 for (DisplayId displayId : displayIds) {
376 if (mDisplayTimingData.count(displayId) == 0) {
377 continue;
378 }
379
380 auto& displayData = mDisplayTimingData.at(displayId);
381 referenceTiming = displayData.calculateDisplayTimeline(referenceFenceTime);
382
383 // If this is the first display, add the pre-present time to the total
384 if (!previousDisplayReferenceTiming.has_value()) {
385 estimatedEndTime += referenceTiming.prePresentTime - referenceFrameStartTime;
386 } else { // Otherwise add last display's postprocessing time to the total
387 estimatedEndTime += referenceTiming.prePresentTime -
388 previousDisplayReferenceTiming->postPresentTime;
389 }
390
391 estimatedTiming = referenceTiming.estimateTimelineFromReference(mExpectedPresentTimes[-1],
392 estimatedEndTime);
393 // Update predicted present finish time with this display's present time
394 estimatedEndTime = estimatedTiming.postPresentTime;
395
396 // Track how long we spent waiting for the fence, can be excluded from the timing estimate
397 idleDuration += estimatedTiming.probablyWaitsForFence
398 ? mExpectedPresentTimes[-1] - estimatedTiming.preFenceWaitTime
399 : 0;
400
401 // Track how long we spent waiting to present, can be excluded from the timing estimate
402 idleDuration +=
403 !earlyHint ? referenceTiming.presentStartTime - referenceTiming.prePresentTime : 0;
404
405 // Estimate the reference frame's gpu timing
406 auto gpuTiming = displayData.estimateGpuTiming(previousValidGpuEndTime);
407 if (gpuTiming.has_value()) {
408 previousValidGpuEndTime = gpuTiming->startTime + gpuTiming->duration;
409
410 // Estimate the prediction frame's gpu end time from the reference frame
411 estimatedGpuEndTime =
412 std::max(estimatedTiming.prePresentTime, estimatedGpuEndTime.value_or(0)) +
413 gpuTiming->duration;
414 }
415 previousDisplayReferenceTiming = referenceTiming;
416 }
417 ATRACE_INT64("Idle duration", idleDuration);
418
419 // Don't count time spent idly waiting in the estimate as we could do more work in that time
420 estimatedEndTime -= idleDuration;
421
422 // We finish the frame when both present and the gpu are done, so wait for the later of the two
423 // Also add the frame delay duration since the target did not move while we were delayed
424 nsecs_t totalDuration = mFrameDelayDuration +
425 std::max(estimatedEndTime, estimatedGpuEndTime.value_or(0)) - mCommitStartTimes[0];
426
427 // We finish SurfaceFlinger when post-composition finishes, so add that in here
428 nsecs_t flingerDuration = estimatedEndTime + mLastPostcompDuration - mCommitStartTimes[0];
429 nsecs_t combinedDuration = combineTimingEstimates(totalDuration, flingerDuration);
430
431 return std::make_optional(combinedDuration);
432}
433
434nsecs_t PowerAdvisor::combineTimingEstimates(nsecs_t totalDuration, nsecs_t flingerDuration) {
435 nsecs_t targetDuration;
436 {
437 std::lock_guard lock(mPowerHalMutex);
438 targetDuration = *getPowerHal()->getTargetWorkDuration();
439 }
440 if (!mTotalFrameTargetDuration.has_value()) return flingerDuration;
441
442 // Normalize total to the flinger target (vsync period) since that's how often we actually send
443 // hints
444 nsecs_t normalizedTotalDuration = (targetDuration * totalDuration) / *mTotalFrameTargetDuration;
445 return std::max(flingerDuration, normalizedTotalDuration);
446}
447
448PowerAdvisor::DisplayTimeline PowerAdvisor::DisplayTimeline::estimateTimelineFromReference(
449 nsecs_t fenceTime, nsecs_t displayStartTime) {
450 DisplayTimeline estimated;
451 estimated.prePresentTime = displayStartTime;
452
453 // We don't predict waiting for vsync alignment yet
454 estimated.presentStartTime = estimated.prePresentTime;
455
456 // For now just re-use last frame's post-present duration and assume it will not change much
457 // How long we expect to run before we start waiting for the fence
458 estimated.preFenceWaitTime = estimated.presentStartTime + (preFenceWaitTime - presentStartTime);
459 estimated.probablyWaitsForFence = fenceTime > estimated.preFenceWaitTime;
460 estimated.postPresentTime = postFenceDuration +
461 (estimated.probablyWaitsForFence ? fenceTime : estimated.preFenceWaitTime);
462 return estimated;
463}
464
465PowerAdvisor::DisplayTimeline PowerAdvisor::DisplayTimingData::calculateDisplayTimeline(
466 nsecs_t fenceTime) {
467 DisplayTimeline timeline;
468 // How long between calling present from flinger and trying to wait on the fence in HWC
469 const nsecs_t preFenceWaitDelay =
470 (skippedValidate ? kPrefenceDelaySkippedValidate : kPrefenceDelayValidated).count();
471
472 // Did our reference frame wait for an earliest present time before calling the HWC
473 const bool waitedOnPresentTime = presentDelayedTime.has_value() &&
474 *presentDelayedTime > *presentStartTime && *presentDelayedTime < *presentEndTime;
475
476 // Use validate start here if we skipped it because we did validate + present together
477 timeline.prePresentTime = skippedValidate ? *validateStartTime : *presentStartTime;
478
479 // Use validate end here if we skipped it because we did validate + present together
480 timeline.postPresentTime = skippedValidate ? *validateEndTime : *presentEndTime;
481
482 // When we think we started waiting for the fence after calling into present
483 // This is after any time spent waiting for the earliest present time
484 timeline.presentStartTime =
485 (waitedOnPresentTime ? *presentDelayedTime : timeline.prePresentTime);
486 timeline.preFenceWaitTime = timeline.presentStartTime + preFenceWaitDelay;
487 timeline.probablyWaitsForFence =
488 fenceTime > timeline.preFenceWaitTime && fenceTime < timeline.postPresentTime;
489
490 // How long we ran after we finished waiting for the fence but before present happened
491 timeline.postFenceDuration = timeline.postPresentTime -
492 (timeline.probablyWaitsForFence ? fenceTime : timeline.preFenceWaitTime);
493 return timeline;
494}
495
496std::optional<PowerAdvisor::GpuTimeline> PowerAdvisor::DisplayTimingData::estimateGpuTiming(
497 std::optional<nsecs_t> previousEnd) {
498 if (!(usedClientComposition && lastValidGpuStartTime.has_value() && gpuEndFenceTime)) {
499 return std::nullopt;
500 }
501 const nsecs_t latestGpuStartTime = std::max(previousEnd.value_or(0), *gpuStartTime);
502 const nsecs_t latestGpuEndTime = gpuEndFenceTime->getSignalTime();
503 nsecs_t gpuDuration = 0;
504 if (latestGpuEndTime != Fence::SIGNAL_TIME_INVALID &&
505 latestGpuEndTime != Fence::SIGNAL_TIME_PENDING) {
506 // If we know how long the most recent gpu duration was, use that
507 gpuDuration = latestGpuEndTime - latestGpuStartTime;
508 } else if (lastValidGpuEndTime.has_value()) {
509 // If we don't have the fence data, use the most recent information we do have
510 gpuDuration = *lastValidGpuEndTime - *lastValidGpuStartTime;
511 if (latestGpuEndTime == Fence::SIGNAL_TIME_PENDING) {
512 // If pending but went over the previous duration, use current time as the end
513 gpuDuration = std::max(gpuDuration, systemTime() - latestGpuStartTime);
514 }
515 }
516 return GpuTimeline{.duration = gpuDuration, .startTime = latestGpuStartTime};
517}
518
Dan Stoza030fbc12020-02-19 15:32:01 -0800519class HidlPowerHalWrapper : public PowerAdvisor::HalWrapper {
520public:
521 HidlPowerHalWrapper(sp<V1_3::IPower> powerHal) : mPowerHal(std::move(powerHal)) {}
522
523 ~HidlPowerHalWrapper() override = default;
524
525 static std::unique_ptr<HalWrapper> connect() {
526 // Power HAL 1.3 is not guaranteed to be available, thus we need to query
527 // Power HAL 1.0 first and try to cast it to Power HAL 1.3.
Dan Stoza030fbc12020-02-19 15:32:01 -0800528 sp<V1_3::IPower> powerHal = nullptr;
Dan Stoza9c051c02020-02-28 10:19:07 -0800529 sp<V1_0::IPower> powerHal_1_0 = V1_0::IPower::getService();
530 if (powerHal_1_0 != nullptr) {
531 // Try to cast to Power HAL 1.3
532 powerHal = V1_3::IPower::castFrom(powerHal_1_0);
533 if (powerHal == nullptr) {
534 ALOGW("No Power HAL 1.3 service in system, disabling PowerAdvisor");
535 } else {
536 ALOGI("Loaded Power HAL 1.3 service");
Dan Stoza030fbc12020-02-19 15:32:01 -0800537 }
Dan Stoza9c051c02020-02-28 10:19:07 -0800538 } else {
539 ALOGW("No Power HAL found, disabling PowerAdvisor");
Dan Stoza030fbc12020-02-19 15:32:01 -0800540 }
Dan Stoza9c051c02020-02-28 10:19:07 -0800541
Dan Stoza030fbc12020-02-19 15:32:01 -0800542 if (powerHal == nullptr) {
543 return nullptr;
544 }
545
546 return std::make_unique<HidlPowerHalWrapper>(std::move(powerHal));
547 }
548
549 bool setExpensiveRendering(bool enabled) override {
550 ALOGV("HIDL setExpensiveRendering %s", enabled ? "T" : "F");
551 auto ret = mPowerHal->powerHintAsync_1_3(PowerHint::EXPENSIVE_RENDERING, enabled);
Ady Abrahamabce1652022-02-24 10:51:19 -0800552 if (ret.isOk()) {
553 traceExpensiveRendering(enabled);
554 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800555 return ret.isOk();
556 }
557
558 bool notifyDisplayUpdateImminent() override {
559 // Power HAL 1.x doesn't have a notification for this
560 ALOGV("HIDL notifyUpdateImminent received but can't send");
561 return true;
562 }
563
Matt Buckley06f299a2021-09-24 19:43:51 +0000564 bool supportsPowerHintSession() override { return false; }
565
566 bool isPowerHintSessionRunning() override { return false; }
567
568 void restartPowerHintSession() override {}
569
570 void setPowerHintSessionThreadIds(const std::vector<int32_t>&) override {}
571
572 bool startPowerHintSession() override { return false; }
573
574 void setTargetWorkDuration(int64_t) override {}
575
576 void sendActualWorkDuration(int64_t, nsecs_t) override {}
577
578 bool shouldReconnectHAL() override { return false; }
579
580 std::vector<int32_t> getPowerHintSessionThreadIds() override { return std::vector<int32_t>{}; }
581
582 std::optional<int64_t> getTargetWorkDuration() override { return std::nullopt; }
583
Dan Stoza030fbc12020-02-19 15:32:01 -0800584private:
Dan Stoza030fbc12020-02-19 15:32:01 -0800585 const sp<V1_3::IPower> mPowerHal = nullptr;
586};
587
Xiang Wange12b4fa2022-03-25 23:48:40 +0000588AidlPowerHalWrapper::AidlPowerHalWrapper(sp<IPower> powerHal) : mPowerHal(std::move(powerHal)) {
589 auto ret = mPowerHal->isModeSupported(Mode::EXPENSIVE_RENDERING, &mHasExpensiveRendering);
590 if (!ret.isOk()) {
591 mHasExpensiveRendering = false;
Dan Stoza030fbc12020-02-19 15:32:01 -0800592 }
593
Xiang Wange12b4fa2022-03-25 23:48:40 +0000594 ret = mPowerHal->isBoostSupported(Boost::DISPLAY_UPDATE_IMMINENT, &mHasDisplayUpdateImminent);
595 if (!ret.isOk()) {
596 mHasDisplayUpdateImminent = false;
Dan Stoza030fbc12020-02-19 15:32:01 -0800597 }
598
Xiang Wange12b4fa2022-03-25 23:48:40 +0000599 mSupportsPowerHint = checkPowerHintSessionSupported();
Matt Buckley50c44062022-01-17 20:48:10 +0000600
601 mAllowedActualDeviation =
602 base::GetIntProperty<nsecs_t>("debug.sf.allowed_actual_deviation",
603 std::chrono::nanoseconds(250us).count());
Xiang Wange12b4fa2022-03-25 23:48:40 +0000604}
Dan Stoza030fbc12020-02-19 15:32:01 -0800605
Xiang Wange12b4fa2022-03-25 23:48:40 +0000606AidlPowerHalWrapper::~AidlPowerHalWrapper() {
607 if (mPowerHintSession != nullptr) {
608 mPowerHintSession->close();
609 mPowerHintSession = nullptr;
Dan Stoza030fbc12020-02-19 15:32:01 -0800610 }
Matt Buckley50c44062022-01-17 20:48:10 +0000611}
Dan Stoza030fbc12020-02-19 15:32:01 -0800612
Xiang Wange12b4fa2022-03-25 23:48:40 +0000613std::unique_ptr<PowerAdvisor::HalWrapper> AidlPowerHalWrapper::connect() {
614 // This only waits if the service is actually declared
615 sp<IPower> powerHal = waitForVintfService<IPower>();
616 if (powerHal == nullptr) {
617 return nullptr;
618 }
619 ALOGI("Loaded AIDL Power HAL service");
620
621 return std::make_unique<AidlPowerHalWrapper>(std::move(powerHal));
622}
623
624bool AidlPowerHalWrapper::setExpensiveRendering(bool enabled) {
625 ALOGV("AIDL setExpensiveRendering %s", enabled ? "T" : "F");
626 if (!mHasExpensiveRendering) {
627 ALOGV("Skipped sending EXPENSIVE_RENDERING because HAL doesn't support it");
628 return true;
629 }
630
631 auto ret = mPowerHal->setMode(Mode::EXPENSIVE_RENDERING, enabled);
632 if (ret.isOk()) {
633 traceExpensiveRendering(enabled);
634 }
635 return ret.isOk();
636}
637
638bool AidlPowerHalWrapper::notifyDisplayUpdateImminent() {
639 ALOGV("AIDL notifyDisplayUpdateImminent");
640 if (!mHasDisplayUpdateImminent) {
641 ALOGV("Skipped sending DISPLAY_UPDATE_IMMINENT because HAL doesn't support it");
642 return true;
643 }
644
645 auto ret = mPowerHal->setBoost(Boost::DISPLAY_UPDATE_IMMINENT, 0);
646 return ret.isOk();
647}
648
Matt Buckley50c44062022-01-17 20:48:10 +0000649// Only version 2+ of the aidl supports power hint sessions, hidl has no support
Xiang Wange12b4fa2022-03-25 23:48:40 +0000650bool AidlPowerHalWrapper::supportsPowerHintSession() {
651 return mSupportsPowerHint;
652}
653
654bool AidlPowerHalWrapper::checkPowerHintSessionSupported() {
655 int64_t unused;
656 // Try to get preferred rate to determine if hint sessions are supported
657 // We check for isOk not EX_UNSUPPORTED_OPERATION to lump together errors
658 return mPowerHal->getHintSessionPreferredRate(&unused).isOk();
659}
660
661bool AidlPowerHalWrapper::isPowerHintSessionRunning() {
662 return mPowerHintSession != nullptr;
663}
664
665void AidlPowerHalWrapper::closePowerHintSession() {
666 if (mPowerHintSession != nullptr) {
667 mPowerHintSession->close();
668 mPowerHintSession = nullptr;
669 }
670}
671
672void AidlPowerHalWrapper::restartPowerHintSession() {
673 closePowerHintSession();
674 startPowerHintSession();
675}
676
677void AidlPowerHalWrapper::setPowerHintSessionThreadIds(const std::vector<int32_t>& threadIds) {
678 if (threadIds != mPowerHintThreadIds) {
679 mPowerHintThreadIds = threadIds;
680 if (isPowerHintSessionRunning()) {
681 restartPowerHintSession();
682 }
683 }
684}
685
686bool AidlPowerHalWrapper::startPowerHintSession() {
687 if (mPowerHintSession != nullptr || mPowerHintThreadIds.empty()) {
688 ALOGV("Cannot start power hint session, skipping");
689 return false;
690 }
691 auto ret =
692 mPowerHal->createHintSession(getpid(), static_cast<int32_t>(getuid()),
693 mPowerHintThreadIds, mTargetDuration, &mPowerHintSession);
694 if (!ret.isOk()) {
695 ALOGW("Failed to start power hint session with error: %s",
696 ret.exceptionToString(ret.exceptionCode()).c_str());
697 } else {
698 mLastTargetDurationSent = mTargetDuration;
699 }
700 return isPowerHintSessionRunning();
701}
702
Matt Buckley50c44062022-01-17 20:48:10 +0000703void AidlPowerHalWrapper::setTargetWorkDuration(int64_t targetDuration) {
Xiang Wange12b4fa2022-03-25 23:48:40 +0000704 ATRACE_CALL();
Matt Buckley50c44062022-01-17 20:48:10 +0000705 mTargetDuration = targetDuration;
706 if (sTraceHintSessionData) ATRACE_INT64("Time target", targetDuration);
707 if (isPowerHintSessionRunning() && (targetDuration != mLastTargetDurationSent)) {
708 ALOGV("Sending target time: %" PRId64 "ns", targetDuration);
709 mLastTargetDurationSent = targetDuration;
710 auto ret = mPowerHintSession->updateTargetWorkDuration(targetDuration);
Xiang Wange12b4fa2022-03-25 23:48:40 +0000711 if (!ret.isOk()) {
712 ALOGW("Failed to set power hint target work duration with error: %s",
713 ret.exceptionMessage().c_str());
714 mShouldReconnectHal = true;
715 }
716 }
717}
718
Matt Buckley50c44062022-01-17 20:48:10 +0000719bool AidlPowerHalWrapper::shouldReportActualDurations() {
720 // Report if we have never reported before or are approaching a stale session
Xiang Wange12b4fa2022-03-25 23:48:40 +0000721 if (!mLastActualDurationSent.has_value() ||
722 (systemTime() - mLastActualReportTimestamp) > kStaleTimeout.count()) {
723 return true;
724 }
725
726 if (!mActualDuration.has_value()) {
727 return false;
728 }
Matt Buckley50c44062022-01-17 20:48:10 +0000729 // Report if the change in actual duration exceeds the threshold
730 return abs(*mActualDuration - *mLastActualDurationSent) > mAllowedActualDeviation;
Xiang Wange12b4fa2022-03-25 23:48:40 +0000731}
732
Matt Buckley50c44062022-01-17 20:48:10 +0000733void AidlPowerHalWrapper::sendActualWorkDuration(int64_t actualDuration, nsecs_t timestamp) {
Xiang Wange12b4fa2022-03-25 23:48:40 +0000734 ATRACE_CALL();
735
Matt Buckley50c44062022-01-17 20:48:10 +0000736 if (actualDuration < 0 || !isPowerHintSessionRunning()) {
Xiang Wange12b4fa2022-03-25 23:48:40 +0000737 ALOGV("Failed to send actual work duration, skipping");
738 return;
739 }
Matt Buckley50c44062022-01-17 20:48:10 +0000740 const nsecs_t reportedDuration = actualDuration;
Xiang Wange12b4fa2022-03-25 23:48:40 +0000741
Xiang Wang0aba49e2022-04-06 16:13:59 +0000742 mActualDuration = reportedDuration;
743 WorkDuration duration;
744 duration.durationNanos = reportedDuration;
Matt Buckley50c44062022-01-17 20:48:10 +0000745 duration.timeStampNanos = timestamp;
Xiang Wange12b4fa2022-03-25 23:48:40 +0000746 mPowerHintQueue.push_back(duration);
747
Xiang Wange12b4fa2022-03-25 23:48:40 +0000748 if (sTraceHintSessionData) {
Matt Buckley50c44062022-01-17 20:48:10 +0000749 ATRACE_INT64("Measured duration", actualDuration);
750 ATRACE_INT64("Target error term", actualDuration - mTargetDuration);
Xiang Wang0aba49e2022-04-06 16:13:59 +0000751
752 ATRACE_INT64("Reported duration", reportedDuration);
753 ATRACE_INT64("Reported target", mLastTargetDurationSent);
Matt Buckley50c44062022-01-17 20:48:10 +0000754 ATRACE_INT64("Reported target error term", reportedDuration - mLastTargetDurationSent);
Xiang Wange12b4fa2022-03-25 23:48:40 +0000755 }
756
Xiang Wang0aba49e2022-04-06 16:13:59 +0000757 ALOGV("Sending actual work duration of: %" PRId64 " on reported target: %" PRId64
Xiang Wange12b4fa2022-03-25 23:48:40 +0000758 " with error: %" PRId64,
Matt Buckley50c44062022-01-17 20:48:10 +0000759 reportedDuration, mLastTargetDurationSent, reportedDuration - mLastTargetDurationSent);
Xiang Wange12b4fa2022-03-25 23:48:40 +0000760
761 // This rate limiter queues similar duration reports to the powerhal into
762 // batches to avoid excessive binder calls. The criteria to send a given batch
763 // are outlined in shouldReportActualDurationsNow()
Matt Buckley50c44062022-01-17 20:48:10 +0000764 if (shouldReportActualDurations()) {
Xiang Wange12b4fa2022-03-25 23:48:40 +0000765 ALOGV("Sending hint update batch");
766 mLastActualReportTimestamp = systemTime();
767 auto ret = mPowerHintSession->reportActualWorkDuration(mPowerHintQueue);
768 if (!ret.isOk()) {
769 ALOGW("Failed to report actual work durations with error: %s",
770 ret.exceptionMessage().c_str());
771 mShouldReconnectHal = true;
772 }
773 mPowerHintQueue.clear();
Matt Buckley50c44062022-01-17 20:48:10 +0000774 // We save the actual duration here for rate limiting
775 mLastActualDurationSent = actualDuration;
Xiang Wange12b4fa2022-03-25 23:48:40 +0000776 }
777}
778
779bool AidlPowerHalWrapper::shouldReconnectHAL() {
780 return mShouldReconnectHal;
781}
782
783std::vector<int32_t> AidlPowerHalWrapper::getPowerHintSessionThreadIds() {
784 return mPowerHintThreadIds;
785}
786
787std::optional<int64_t> AidlPowerHalWrapper::getTargetWorkDuration() {
788 return mTargetDuration;
789}
790
Matt Buckley50c44062022-01-17 20:48:10 +0000791void AidlPowerHalWrapper::setAllowedActualDeviation(nsecs_t allowedDeviation) {
792 mAllowedActualDeviation = allowedDeviation;
793}
794
Matt Buckleyef51fba2021-10-12 19:30:12 +0000795const bool AidlPowerHalWrapper::sTraceHintSessionData =
796 base::GetBoolProperty(std::string("debug.sf.trace_hint_sessions"), false);
797
Dan Stoza030fbc12020-02-19 15:32:01 -0800798PowerAdvisor::HalWrapper* PowerAdvisor::getPowerHal() {
799 static std::unique_ptr<HalWrapper> sHalWrapper = nullptr;
Dan Stoza9c051c02020-02-28 10:19:07 -0800800 static bool sHasHal = true;
Michael Wright1509a232018-06-21 02:50:34 +0100801
Dan Stoza9c051c02020-02-28 10:19:07 -0800802 if (!sHasHal) {
803 return nullptr;
804 }
805
Matt Buckley50c44062022-01-17 20:48:10 +0000806 // Grab old hint session values before we destroy any existing wrapper
Matt Buckley06f299a2021-09-24 19:43:51 +0000807 std::vector<int32_t> oldPowerHintSessionThreadIds;
808 std::optional<int64_t> oldTargetWorkDuration;
809
810 if (sHalWrapper != nullptr) {
811 oldPowerHintSessionThreadIds = sHalWrapper->getPowerHintSessionThreadIds();
812 oldTargetWorkDuration = sHalWrapper->getTargetWorkDuration();
813 }
814
Dan Stoza9c051c02020-02-28 10:19:07 -0800815 // If we used to have a HAL, but it stopped responding, attempt to reconnect
Michael Wright1509a232018-06-21 02:50:34 +0100816 if (mReconnectPowerHal) {
Dan Stoza030fbc12020-02-19 15:32:01 -0800817 sHalWrapper = nullptr;
Michael Wright1509a232018-06-21 02:50:34 +0100818 mReconnectPowerHal = false;
819 }
820
Dan Stoza030fbc12020-02-19 15:32:01 -0800821 if (sHalWrapper != nullptr) {
Matt Buckley06f299a2021-09-24 19:43:51 +0000822 auto wrapper = sHalWrapper.get();
Matt Buckley50c44062022-01-17 20:48:10 +0000823 // If the wrapper is fine, return it, but if it indicates a reconnect, remake it
Matt Buckley06f299a2021-09-24 19:43:51 +0000824 if (!wrapper->shouldReconnectHAL()) {
825 return wrapper;
826 }
Xiang Wang65a2e6f2022-04-18 21:19:17 +0000827 ALOGD("Reconnecting Power HAL");
Matt Buckley06f299a2021-09-24 19:43:51 +0000828 sHalWrapper = nullptr;
Michael Wright1509a232018-06-21 02:50:34 +0100829 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800830
Matt Buckley50c44062022-01-17 20:48:10 +0000831 // At this point, we know for sure there is no running session
Matt Buckley06f299a2021-09-24 19:43:51 +0000832 mPowerHintSessionRunning = false;
833
Dan Stoza030fbc12020-02-19 15:32:01 -0800834 // First attempt to connect to the AIDL Power HAL
835 sHalWrapper = AidlPowerHalWrapper::connect();
836
837 // If that didn't succeed, attempt to connect to the HIDL Power HAL
838 if (sHalWrapper == nullptr) {
839 sHalWrapper = HidlPowerHalWrapper::connect();
Xiang Wang65a2e6f2022-04-18 21:19:17 +0000840 } else {
841 ALOGD("Successfully connecting AIDL Power HAL");
Matt Buckley50c44062022-01-17 20:48:10 +0000842 // If AIDL, pass on any existing hint session values
Matt Buckley06f299a2021-09-24 19:43:51 +0000843 sHalWrapper->setPowerHintSessionThreadIds(oldPowerHintSessionThreadIds);
Matt Buckley50c44062022-01-17 20:48:10 +0000844 // Only set duration and start if duration is defined
Matt Buckley06f299a2021-09-24 19:43:51 +0000845 if (oldTargetWorkDuration.has_value()) {
846 sHalWrapper->setTargetWorkDuration(*oldTargetWorkDuration);
Matt Buckley50c44062022-01-17 20:48:10 +0000847 // Only start if possible to run and both threadids and duration are defined
Matt Buckley06f299a2021-09-24 19:43:51 +0000848 if (usePowerHintSession() && !oldPowerHintSessionThreadIds.empty()) {
849 mPowerHintSessionRunning = sHalWrapper->startPowerHintSession();
850 }
851 }
Dan Stoza030fbc12020-02-19 15:32:01 -0800852 }
853
Dan Stoza9c051c02020-02-28 10:19:07 -0800854 // If we make it to this point and still don't have a HAL, it's unlikely we
855 // will, so stop trying
856 if (sHalWrapper == nullptr) {
857 sHasHal = false;
858 }
859
Dan Stoza030fbc12020-02-19 15:32:01 -0800860 return sHalWrapper.get();
Michael Wright1509a232018-06-21 02:50:34 +0100861}
862
863} // namespace impl
864} // namespace Hwc2
865} // namespace android