• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 //#define LOG_NDEBUG 0
18 
19 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
20 
21 #undef LOG_TAG
22 #define LOG_TAG "PowerAdvisor"
23 
24 #include <unistd.h>
25 #include <cinttypes>
26 #include <cstdint>
27 #include <optional>
28 
29 #include <android-base/properties.h>
30 #include <utils/Log.h>
31 #include <utils/Mutex.h>
32 #include <utils/Trace.h>
33 
34 #include <android/hardware/power/1.3/IPower.h>
35 #include <android/hardware/power/IPowerHintSession.h>
36 #include <android/hardware/power/WorkDuration.h>
37 
38 #include <binder/IServiceManager.h>
39 
40 #include "../SurfaceFlingerProperties.h"
41 
42 #include "PowerAdvisor.h"
43 #include "SurfaceFlinger.h"
44 
45 namespace android {
46 namespace Hwc2 {
47 
48 PowerAdvisor::~PowerAdvisor() = default;
49 
50 namespace impl {
51 
52 namespace V1_0 = android::hardware::power::V1_0;
53 namespace V1_3 = android::hardware::power::V1_3;
54 using V1_3::PowerHint;
55 
56 using android::hardware::power::Boost;
57 using android::hardware::power::IPower;
58 using android::hardware::power::IPowerHintSession;
59 using android::hardware::power::Mode;
60 using android::hardware::power::WorkDuration;
61 
62 using scheduler::OneShotTimer;
63 
64 PowerAdvisor::~PowerAdvisor() = default;
65 
66 namespace {
getUpdateTimeout()67 std::chrono::milliseconds getUpdateTimeout() {
68     // Default to a timeout of 80ms if nothing else is specified
69     static std::chrono::milliseconds timeout =
70             std::chrono::milliseconds(sysprop::display_update_imminent_timeout_ms(80));
71     return timeout;
72 }
73 
traceExpensiveRendering(bool enabled)74 void traceExpensiveRendering(bool enabled) {
75     if (enabled) {
76         ATRACE_ASYNC_BEGIN("ExpensiveRendering", 0);
77     } else {
78         ATRACE_ASYNC_END("ExpensiveRendering", 0);
79     }
80 }
81 
82 } // namespace
83 
PowerAdvisor(SurfaceFlinger & flinger)84 PowerAdvisor::PowerAdvisor(SurfaceFlinger& flinger) : mFlinger(flinger) {
85     if (getUpdateTimeout() > 0ms) {
86         mScreenUpdateTimer.emplace("UpdateImminentTimer", getUpdateTimeout(),
87                                    /* resetCallback */ nullptr,
88                                    /* timeoutCallback */
89                                    [this] {
90                                        while (true) {
91                                            auto timeSinceLastUpdate = std::chrono::nanoseconds(
92                                                    systemTime() - mLastScreenUpdatedTime.load());
93                                            if (timeSinceLastUpdate >= getUpdateTimeout()) {
94                                                break;
95                                            }
96                                            // 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.
100                                            std::this_thread::sleep_for(getUpdateTimeout() -
101                                                                        timeSinceLastUpdate);
102                                        }
103                                        mSendUpdateImminent.store(true);
104                                        mFlinger.disableExpensiveRendering();
105                                    });
106     }
107 }
108 
init()109 void PowerAdvisor::init() {
110     // Defer starting the screen update timer until SurfaceFlinger finishes construction.
111     if (mScreenUpdateTimer) {
112         mScreenUpdateTimer->start();
113     }
114 }
115 
onBootFinished()116 void PowerAdvisor::onBootFinished() {
117     mBootFinished.store(true);
118 }
119 
setExpensiveRenderingExpected(DisplayId displayId,bool expected)120 void PowerAdvisor::setExpensiveRenderingExpected(DisplayId displayId, bool expected) {
121     if (expected) {
122         mExpensiveDisplays.insert(displayId);
123     } else {
124         mExpensiveDisplays.erase(displayId);
125     }
126 
127     const bool expectsExpensiveRendering = !mExpensiveDisplays.empty();
128     if (mNotifiedExpensiveRendering != expectsExpensiveRendering) {
129         std::lock_guard lock(mPowerHalMutex);
130         HalWrapper* const halWrapper = getPowerHal();
131         if (halWrapper == nullptr) {
132             return;
133         }
134 
135         if (!halWrapper->setExpensiveRendering(expectsExpensiveRendering)) {
136             // The HAL has become unavailable; attempt to reconnect later
137             mReconnectPowerHal = true;
138             return;
139         }
140 
141         mNotifiedExpensiveRendering = expectsExpensiveRendering;
142     }
143 }
144 
notifyDisplayUpdateImminent()145 void PowerAdvisor::notifyDisplayUpdateImminent() {
146     // 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 
152     if (mSendUpdateImminent.exchange(false)) {
153         std::lock_guard lock(mPowerHalMutex);
154         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         }
164 
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         }
172     }
173 
174     if (mScreenUpdateTimer) {
175         mLastScreenUpdatedTime.store(systemTime());
176     }
177 }
178 
179 // checks both if it supports and if it's enabled
usePowerHintSession()180 bool PowerAdvisor::usePowerHintSession() {
181     // uses cached value since the underlying support and flag are unlikely to change at runtime
182     return mPowerHintEnabled.value_or(false) && supportsPowerHintSession();
183 }
184 
supportsPowerHintSession()185 bool PowerAdvisor::supportsPowerHintSession() {
186     // cache to avoid needing lock every time
187     if (!mSupportsPowerHint.has_value()) {
188         std::lock_guard lock(mPowerHalMutex);
189         HalWrapper* const halWrapper = getPowerHal();
190         mSupportsPowerHint = halWrapper && halWrapper->supportsPowerHintSession();
191     }
192     return *mSupportsPowerHint;
193 }
194 
isPowerHintSessionRunning()195 bool PowerAdvisor::isPowerHintSessionRunning() {
196     return mPowerHintSessionRunning;
197 }
198 
setTargetWorkDuration(int64_t targetDuration)199 void PowerAdvisor::setTargetWorkDuration(int64_t targetDuration) {
200     if (!usePowerHintSession()) {
201         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) {
208             halWrapper->setTargetWorkDuration(targetDuration);
209         }
210     }
211 }
212 
sendActualWorkDuration()213 void PowerAdvisor::sendActualWorkDuration() {
214     if (!mBootFinished || !usePowerHintSession()) {
215         ALOGV("Actual work duration power hint cannot be sent, skipping");
216         return;
217     }
218     const std::optional<nsecs_t> actualDuration = estimateWorkDuration(false);
219     if (actualDuration.has_value()) {
220         std::lock_guard lock(mPowerHalMutex);
221         HalWrapper* const halWrapper = getPowerHal();
222         if (halWrapper != nullptr) {
223             halWrapper->sendActualWorkDuration(*actualDuration + kTargetSafetyMargin.count(),
224                                                systemTime());
225         }
226     }
227 }
228 
sendPredictedWorkDuration()229 void 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) {
241             halWrapper->sendActualWorkDuration(*predictedDuration + kTargetSafetyMargin.count(),
242                                                systemTime());
243         }
244     }
245 }
246 
enablePowerHint(bool enabled)247 void PowerAdvisor::enablePowerHint(bool enabled) {
248     mPowerHintEnabled = enabled;
249 }
250 
startPowerHintSession(const std::vector<int32_t> & threadIds)251 bool 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 
setGpuFenceTime(DisplayId displayId,std::unique_ptr<FenceTime> && fenceTime)266 void 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 
setHwcValidateTiming(DisplayId displayId,nsecs_t validateStartTime,nsecs_t validateEndTime)291 void PowerAdvisor::setHwcValidateTiming(DisplayId displayId, nsecs_t validateStartTime,
292                                         nsecs_t validateEndTime) {
293     DisplayTimingData& displayData = mDisplayTimingData[displayId];
294     displayData.hwcValidateStartTime = validateStartTime;
295     displayData.hwcValidateEndTime = validateEndTime;
296 }
297 
setHwcPresentTiming(DisplayId displayId,nsecs_t presentStartTime,nsecs_t presentEndTime)298 void PowerAdvisor::setHwcPresentTiming(DisplayId displayId, nsecs_t presentStartTime,
299                                        nsecs_t presentEndTime) {
300     DisplayTimingData& displayData = mDisplayTimingData[displayId];
301     displayData.hwcPresentStartTime = presentStartTime;
302     displayData.hwcPresentEndTime = presentEndTime;
303 }
304 
setSkippedValidate(DisplayId displayId,bool skipped)305 void PowerAdvisor::setSkippedValidate(DisplayId displayId, bool skipped) {
306     mDisplayTimingData[displayId].skippedValidate = skipped;
307 }
308 
setRequiresClientComposition(DisplayId displayId,bool requiresClientComposition)309 void PowerAdvisor::setRequiresClientComposition(DisplayId displayId,
310                                                 bool requiresClientComposition) {
311     mDisplayTimingData[displayId].usedClientComposition = requiresClientComposition;
312 }
313 
setExpectedPresentTime(nsecs_t expectedPresentTime)314 void PowerAdvisor::setExpectedPresentTime(nsecs_t expectedPresentTime) {
315     mExpectedPresentTimes.append(expectedPresentTime);
316 }
317 
setSfPresentTiming(nsecs_t presentFenceTime,nsecs_t presentEndTime)318 void PowerAdvisor::setSfPresentTiming(nsecs_t presentFenceTime, nsecs_t presentEndTime) {
319     mLastSfPresentEndTime = presentEndTime;
320     mLastPresentFenceTime = presentFenceTime;
321 }
322 
setFrameDelay(nsecs_t frameDelayDuration)323 void PowerAdvisor::setFrameDelay(nsecs_t frameDelayDuration) {
324     mFrameDelayDuration = frameDelayDuration;
325 }
326 
setHwcPresentDelayedTime(DisplayId displayId,std::chrono::steady_clock::time_point earliestFrameStartTime)327 void PowerAdvisor::setHwcPresentDelayedTime(
328         DisplayId displayId, std::chrono::steady_clock::time_point earliestFrameStartTime) {
329     mDisplayTimingData[displayId].hwcPresentDelayedTime =
330             (earliestFrameStartTime - std::chrono::steady_clock::now()).count() + systemTime();
331 }
332 
setCommitStart(nsecs_t commitStartTime)333 void PowerAdvisor::setCommitStart(nsecs_t commitStartTime) {
334     mCommitStartTimes.append(commitStartTime);
335 }
336 
setCompositeEnd(nsecs_t compositeEnd)337 void PowerAdvisor::setCompositeEnd(nsecs_t compositeEnd) {
338     mLastPostcompDuration = compositeEnd - mLastSfPresentEndTime;
339 }
340 
setDisplays(std::vector<DisplayId> & displayIds)341 void PowerAdvisor::setDisplays(std::vector<DisplayId>& displayIds) {
342     mDisplayIds = displayIds;
343 }
344 
setTotalFrameTargetWorkDuration(nsecs_t targetDuration)345 void PowerAdvisor::setTotalFrameTargetWorkDuration(nsecs_t targetDuration) {
346     mTotalFrameTargetDuration = targetDuration;
347 }
348 
getOrderedDisplayIds(std::optional<nsecs_t> DisplayTimingData::* sortBy)349 std::vector<DisplayId> PowerAdvisor::getOrderedDisplayIds(
350         std::optional<nsecs_t> DisplayTimingData::*sortBy) {
351     std::vector<DisplayId> sortedDisplays;
352     std::copy_if(mDisplayIds.begin(), mDisplayIds.end(), std::back_inserter(sortedDisplays),
353                  [&](DisplayId id) {
354                      return mDisplayTimingData.count(id) &&
355                              (mDisplayTimingData[id].*sortBy).has_value();
356                  });
357     std::sort(sortedDisplays.begin(), sortedDisplays.end(), [&](DisplayId idA, DisplayId idB) {
358         return *(mDisplayTimingData[idA].*sortBy) < *(mDisplayTimingData[idB].*sortBy);
359     });
360     return sortedDisplays;
361 }
362 
estimateWorkDuration(bool earlyHint)363 std::optional<nsecs_t> PowerAdvisor::estimateWorkDuration(bool earlyHint) {
364     if (earlyHint && (!mExpectedPresentTimes.isFull() || !mCommitStartTimes.isFull())) {
365         return std::nullopt;
366     }
367 
368     // Tracks when we finish presenting to hwc
369     nsecs_t estimatedEndTime = mCommitStartTimes[0];
370 
371     // How long we spent this frame not doing anything, waiting for fences or vsync
372     nsecs_t idleDuration = 0;
373 
374     // Most recent previous gpu end time in the current frame, probably from a prior display, used
375     // as the start time for the next gpu operation if it ran over time since it probably blocked
376     std::optional<nsecs_t> previousValidGpuEndTime;
377 
378     // The currently estimated gpu end time for the frame,
379     // used to accumulate gpu time as we iterate over the active displays
380     std::optional<nsecs_t> estimatedGpuEndTime;
381 
382     // If we're predicting at the start of the frame, we use last frame as our reference point
383     // If we're predicting at the end of the frame, we use the current frame as a reference point
384     nsecs_t referenceFrameStartTime = (earlyHint ? mCommitStartTimes[-1] : mCommitStartTimes[0]);
385 
386     // When the prior frame should be presenting to the display
387     // If we're predicting at the start of the frame, we use last frame's expected present time
388     // If we're predicting at the end of the frame, the present fence time is already known
389     nsecs_t lastFramePresentTime = (earlyHint ? mExpectedPresentTimes[-1] : mLastPresentFenceTime);
390 
391     // The timing info for the previously calculated display, if there was one
392     std::optional<DisplayTimeline> previousDisplayReferenceTiming;
393     std::vector<DisplayId>&& displayIds =
394             getOrderedDisplayIds(&DisplayTimingData::hwcPresentStartTime);
395     DisplayTimeline referenceTiming, estimatedTiming;
396 
397     // Iterate over the displays that use hwc in the same order they are presented
398     for (DisplayId displayId : displayIds) {
399         if (mDisplayTimingData.count(displayId) == 0) {
400             continue;
401         }
402 
403         auto& displayData = mDisplayTimingData.at(displayId);
404 
405         // mLastPresentFenceTime should always be the time of the reference frame, since it will be
406         // the previous frame's present fence if called at the start, and current frame's if called
407         // at the end
408         referenceTiming = displayData.calculateDisplayTimeline(mLastPresentFenceTime);
409 
410         // If this is the first display, include the duration before hwc present starts
411         if (!previousDisplayReferenceTiming.has_value()) {
412             estimatedEndTime += referenceTiming.hwcPresentStartTime - referenceFrameStartTime;
413         } else { // Otherwise add the time since last display's hwc present finished
414             estimatedEndTime += referenceTiming.hwcPresentStartTime -
415                     previousDisplayReferenceTiming->hwcPresentEndTime;
416         }
417 
418         // Late hint can re-use reference timing here since it's estimating its own reference frame
419         estimatedTiming = earlyHint
420                 ? referenceTiming.estimateTimelineFromReference(lastFramePresentTime,
421                                                                 estimatedEndTime)
422                 : referenceTiming;
423 
424         // Update predicted present finish time with this display's present time
425         estimatedEndTime = estimatedTiming.hwcPresentEndTime;
426 
427         // Track how long we spent waiting for the fence, can be excluded from the timing estimate
428         idleDuration += estimatedTiming.probablyWaitsForPresentFence
429                 ? lastFramePresentTime - estimatedTiming.presentFenceWaitStartTime
430                 : 0;
431 
432         // Track how long we spent waiting to present, can be excluded from the timing estimate
433         idleDuration += earlyHint ? 0 : referenceTiming.hwcPresentDelayDuration;
434 
435         // Estimate the reference frame's gpu timing
436         auto gpuTiming = displayData.estimateGpuTiming(previousValidGpuEndTime);
437         if (gpuTiming.has_value()) {
438             previousValidGpuEndTime = gpuTiming->startTime + gpuTiming->duration;
439 
440             // Estimate the prediction frame's gpu end time from the reference frame
441             estimatedGpuEndTime =
442                     std::max(estimatedTiming.hwcPresentStartTime, estimatedGpuEndTime.value_or(0)) +
443                     gpuTiming->duration;
444         }
445         previousDisplayReferenceTiming = referenceTiming;
446     }
447     ATRACE_INT64("Idle duration", idleDuration);
448 
449     nsecs_t estimatedFlingerEndTime = earlyHint ? estimatedEndTime : mLastSfPresentEndTime;
450 
451     // Don't count time spent idly waiting in the estimate as we could do more work in that time
452     estimatedEndTime -= idleDuration;
453     estimatedFlingerEndTime -= idleDuration;
454 
455     // We finish the frame when both present and the gpu are done, so wait for the later of the two
456     // Also add the frame delay duration since the target did not move while we were delayed
457     nsecs_t totalDuration = mFrameDelayDuration +
458             std::max(estimatedEndTime, estimatedGpuEndTime.value_or(0)) - mCommitStartTimes[0];
459 
460     // We finish SurfaceFlinger when post-composition finishes, so add that in here
461     nsecs_t flingerDuration =
462             estimatedFlingerEndTime + mLastPostcompDuration - mCommitStartTimes[0];
463 
464     // Combine the two timings into a single normalized one
465     nsecs_t combinedDuration = combineTimingEstimates(totalDuration, flingerDuration);
466 
467     return std::make_optional(combinedDuration);
468 }
469 
combineTimingEstimates(nsecs_t totalDuration,nsecs_t flingerDuration)470 nsecs_t PowerAdvisor::combineTimingEstimates(nsecs_t totalDuration, nsecs_t flingerDuration) {
471     nsecs_t targetDuration;
472     {
473         std::lock_guard lock(mPowerHalMutex);
474         targetDuration = *getPowerHal()->getTargetWorkDuration();
475     }
476     if (!mTotalFrameTargetDuration.has_value()) return flingerDuration;
477 
478     // Normalize total to the flinger target (vsync period) since that's how often we actually send
479     // hints
480     nsecs_t normalizedTotalDuration = (targetDuration * totalDuration) / *mTotalFrameTargetDuration;
481     return std::max(flingerDuration, normalizedTotalDuration);
482 }
483 
estimateTimelineFromReference(nsecs_t fenceTime,nsecs_t displayStartTime)484 PowerAdvisor::DisplayTimeline PowerAdvisor::DisplayTimeline::estimateTimelineFromReference(
485         nsecs_t fenceTime, nsecs_t displayStartTime) {
486     DisplayTimeline estimated;
487     estimated.hwcPresentStartTime = displayStartTime;
488 
489     // We don't predict waiting for vsync alignment yet
490     estimated.hwcPresentDelayDuration = 0;
491 
492     // How long we expect to run before we start waiting for the fence
493     // For now just re-use last frame's post-present duration and assume it will not change much
494     // Excludes time spent waiting for vsync since that's not going to be consistent
495     estimated.presentFenceWaitStartTime = estimated.hwcPresentStartTime +
496             (presentFenceWaitStartTime - (hwcPresentStartTime + hwcPresentDelayDuration));
497     estimated.probablyWaitsForPresentFence = fenceTime > estimated.presentFenceWaitStartTime;
498     estimated.hwcPresentEndTime = postPresentFenceHwcPresentDuration +
499             (estimated.probablyWaitsForPresentFence ? fenceTime
500                                                     : estimated.presentFenceWaitStartTime);
501     return estimated;
502 }
503 
calculateDisplayTimeline(nsecs_t fenceTime)504 PowerAdvisor::DisplayTimeline PowerAdvisor::DisplayTimingData::calculateDisplayTimeline(
505         nsecs_t fenceTime) {
506     DisplayTimeline timeline;
507     // How long between calling hwc present and trying to wait on the fence
508     const nsecs_t fenceWaitStartDelay =
509             (skippedValidate ? kFenceWaitStartDelaySkippedValidate : kFenceWaitStartDelayValidated)
510                     .count();
511 
512     // Did our reference frame wait for an appropriate vsync before calling into hwc
513     const bool waitedOnHwcPresentTime = hwcPresentDelayedTime.has_value() &&
514             *hwcPresentDelayedTime > *hwcPresentStartTime &&
515             *hwcPresentDelayedTime < *hwcPresentEndTime;
516 
517     // Use validate start here if we skipped it because we did validate + present together
518     timeline.hwcPresentStartTime = skippedValidate ? *hwcValidateStartTime : *hwcPresentStartTime;
519 
520     // Use validate end here if we skipped it because we did validate + present together
521     timeline.hwcPresentEndTime = skippedValidate ? *hwcValidateEndTime : *hwcPresentEndTime;
522 
523     // How long hwc present was delayed waiting for the next appropriate vsync
524     timeline.hwcPresentDelayDuration =
525             (waitedOnHwcPresentTime ? *hwcPresentDelayedTime - *hwcPresentStartTime : 0);
526     // When we started waiting for the present fence after calling into hwc present
527     timeline.presentFenceWaitStartTime =
528             timeline.hwcPresentStartTime + timeline.hwcPresentDelayDuration + fenceWaitStartDelay;
529     timeline.probablyWaitsForPresentFence = fenceTime > timeline.presentFenceWaitStartTime &&
530             fenceTime < timeline.hwcPresentEndTime;
531 
532     // How long we ran after we finished waiting for the fence but before hwc present finished
533     timeline.postPresentFenceHwcPresentDuration = timeline.hwcPresentEndTime -
534             (timeline.probablyWaitsForPresentFence ? fenceTime
535                                                    : timeline.presentFenceWaitStartTime);
536     return timeline;
537 }
538 
estimateGpuTiming(std::optional<nsecs_t> previousEnd)539 std::optional<PowerAdvisor::GpuTimeline> PowerAdvisor::DisplayTimingData::estimateGpuTiming(
540         std::optional<nsecs_t> previousEnd) {
541     if (!(usedClientComposition && lastValidGpuStartTime.has_value() && gpuEndFenceTime)) {
542         return std::nullopt;
543     }
544     const nsecs_t latestGpuStartTime = std::max(previousEnd.value_or(0), *gpuStartTime);
545     const nsecs_t latestGpuEndTime = gpuEndFenceTime->getSignalTime();
546     nsecs_t gpuDuration = 0;
547     if (latestGpuEndTime != Fence::SIGNAL_TIME_INVALID &&
548         latestGpuEndTime != Fence::SIGNAL_TIME_PENDING) {
549         // If we know how long the most recent gpu duration was, use that
550         gpuDuration = latestGpuEndTime - latestGpuStartTime;
551     } else if (lastValidGpuEndTime.has_value()) {
552         // If we don't have the fence data, use the most recent information we do have
553         gpuDuration = *lastValidGpuEndTime - *lastValidGpuStartTime;
554         if (latestGpuEndTime == Fence::SIGNAL_TIME_PENDING) {
555             // If pending but went over the previous duration, use current time as the end
556             gpuDuration = std::max(gpuDuration, systemTime() - latestGpuStartTime);
557         }
558     }
559     return GpuTimeline{.duration = gpuDuration, .startTime = latestGpuStartTime};
560 }
561 
562 class HidlPowerHalWrapper : public PowerAdvisor::HalWrapper {
563 public:
HidlPowerHalWrapper(sp<V1_3::IPower> powerHal)564     HidlPowerHalWrapper(sp<V1_3::IPower> powerHal) : mPowerHal(std::move(powerHal)) {}
565 
566     ~HidlPowerHalWrapper() override = default;
567 
connect()568     static std::unique_ptr<HalWrapper> connect() {
569         // Power HAL 1.3 is not guaranteed to be available, thus we need to query
570         // Power HAL 1.0 first and try to cast it to Power HAL 1.3.
571         sp<V1_3::IPower> powerHal = nullptr;
572         sp<V1_0::IPower> powerHal_1_0 = V1_0::IPower::getService();
573         if (powerHal_1_0 != nullptr) {
574             // Try to cast to Power HAL 1.3
575             powerHal = V1_3::IPower::castFrom(powerHal_1_0);
576             if (powerHal == nullptr) {
577                 ALOGW("No Power HAL 1.3 service in system, disabling PowerAdvisor");
578             } else {
579                 ALOGI("Loaded Power HAL 1.3 service");
580             }
581         } else {
582             ALOGW("No Power HAL found, disabling PowerAdvisor");
583         }
584 
585         if (powerHal == nullptr) {
586             return nullptr;
587         }
588 
589         return std::make_unique<HidlPowerHalWrapper>(std::move(powerHal));
590     }
591 
setExpensiveRendering(bool enabled)592     bool setExpensiveRendering(bool enabled) override {
593         ALOGV("HIDL setExpensiveRendering %s", enabled ? "T" : "F");
594         auto ret = mPowerHal->powerHintAsync_1_3(PowerHint::EXPENSIVE_RENDERING, enabled);
595         if (ret.isOk()) {
596             traceExpensiveRendering(enabled);
597         }
598         return ret.isOk();
599     }
600 
notifyDisplayUpdateImminent()601     bool notifyDisplayUpdateImminent() override {
602         // Power HAL 1.x doesn't have a notification for this
603         ALOGV("HIDL notifyUpdateImminent received but can't send");
604         return true;
605     }
606 
supportsPowerHintSession()607     bool supportsPowerHintSession() override { return false; }
608 
isPowerHintSessionRunning()609     bool isPowerHintSessionRunning() override { return false; }
610 
restartPowerHintSession()611     void restartPowerHintSession() override {}
612 
setPowerHintSessionThreadIds(const std::vector<int32_t> &)613     void setPowerHintSessionThreadIds(const std::vector<int32_t>&) override {}
614 
startPowerHintSession()615     bool startPowerHintSession() override { return false; }
616 
setTargetWorkDuration(int64_t)617     void setTargetWorkDuration(int64_t) override {}
618 
sendActualWorkDuration(int64_t,nsecs_t)619     void sendActualWorkDuration(int64_t, nsecs_t) override {}
620 
shouldReconnectHAL()621     bool shouldReconnectHAL() override { return false; }
622 
getPowerHintSessionThreadIds()623     std::vector<int32_t> getPowerHintSessionThreadIds() override { return std::vector<int32_t>{}; }
624 
getTargetWorkDuration()625     std::optional<int64_t> getTargetWorkDuration() override { return std::nullopt; }
626 
627 private:
628     const sp<V1_3::IPower> mPowerHal = nullptr;
629 };
630 
AidlPowerHalWrapper(sp<IPower> powerHal)631 AidlPowerHalWrapper::AidlPowerHalWrapper(sp<IPower> powerHal) : mPowerHal(std::move(powerHal)) {
632     auto ret = mPowerHal->isModeSupported(Mode::EXPENSIVE_RENDERING, &mHasExpensiveRendering);
633     if (!ret.isOk()) {
634         mHasExpensiveRendering = false;
635     }
636 
637     ret = mPowerHal->isBoostSupported(Boost::DISPLAY_UPDATE_IMMINENT, &mHasDisplayUpdateImminent);
638     if (!ret.isOk()) {
639         mHasDisplayUpdateImminent = false;
640     }
641 
642     mSupportsPowerHint = checkPowerHintSessionSupported();
643 
644     // Currently set to 0 to disable rate limiter by default
645     mAllowedActualDeviation = base::GetIntProperty<nsecs_t>("debug.sf.allowed_actual_deviation", 0);
646 }
647 
~AidlPowerHalWrapper()648 AidlPowerHalWrapper::~AidlPowerHalWrapper() {
649     if (mPowerHintSession != nullptr) {
650         mPowerHintSession->close();
651         mPowerHintSession = nullptr;
652     }
653 }
654 
connect()655 std::unique_ptr<PowerAdvisor::HalWrapper> AidlPowerHalWrapper::connect() {
656     // This only waits if the service is actually declared
657     sp<IPower> powerHal = waitForVintfService<IPower>();
658     if (powerHal == nullptr) {
659         return nullptr;
660     }
661     ALOGI("Loaded AIDL Power HAL service");
662 
663     return std::make_unique<AidlPowerHalWrapper>(std::move(powerHal));
664 }
665 
setExpensiveRendering(bool enabled)666 bool AidlPowerHalWrapper::setExpensiveRendering(bool enabled) {
667     ALOGV("AIDL setExpensiveRendering %s", enabled ? "T" : "F");
668     if (!mHasExpensiveRendering) {
669         ALOGV("Skipped sending EXPENSIVE_RENDERING because HAL doesn't support it");
670         return true;
671     }
672 
673     auto ret = mPowerHal->setMode(Mode::EXPENSIVE_RENDERING, enabled);
674     if (ret.isOk()) {
675         traceExpensiveRendering(enabled);
676     }
677     return ret.isOk();
678 }
679 
notifyDisplayUpdateImminent()680 bool AidlPowerHalWrapper::notifyDisplayUpdateImminent() {
681     ALOGV("AIDL notifyDisplayUpdateImminent");
682     if (!mHasDisplayUpdateImminent) {
683         ALOGV("Skipped sending DISPLAY_UPDATE_IMMINENT because HAL doesn't support it");
684         return true;
685     }
686 
687     auto ret = mPowerHal->setBoost(Boost::DISPLAY_UPDATE_IMMINENT, 0);
688     return ret.isOk();
689 }
690 
691 // Only version 2+ of the aidl supports power hint sessions, hidl has no support
supportsPowerHintSession()692 bool AidlPowerHalWrapper::supportsPowerHintSession() {
693     return mSupportsPowerHint;
694 }
695 
checkPowerHintSessionSupported()696 bool AidlPowerHalWrapper::checkPowerHintSessionSupported() {
697     int64_t unused;
698     // Try to get preferred rate to determine if hint sessions are supported
699     // We check for isOk not EX_UNSUPPORTED_OPERATION to lump together errors
700     return mPowerHal->getHintSessionPreferredRate(&unused).isOk();
701 }
702 
isPowerHintSessionRunning()703 bool AidlPowerHalWrapper::isPowerHintSessionRunning() {
704     return mPowerHintSession != nullptr;
705 }
706 
closePowerHintSession()707 void AidlPowerHalWrapper::closePowerHintSession() {
708     if (mPowerHintSession != nullptr) {
709         mPowerHintSession->close();
710         mPowerHintSession = nullptr;
711     }
712 }
713 
restartPowerHintSession()714 void AidlPowerHalWrapper::restartPowerHintSession() {
715     closePowerHintSession();
716     startPowerHintSession();
717 }
718 
setPowerHintSessionThreadIds(const std::vector<int32_t> & threadIds)719 void AidlPowerHalWrapper::setPowerHintSessionThreadIds(const std::vector<int32_t>& threadIds) {
720     if (threadIds != mPowerHintThreadIds) {
721         mPowerHintThreadIds = threadIds;
722         if (isPowerHintSessionRunning()) {
723             restartPowerHintSession();
724         }
725     }
726 }
727 
startPowerHintSession()728 bool AidlPowerHalWrapper::startPowerHintSession() {
729     if (mPowerHintSession != nullptr || mPowerHintThreadIds.empty()) {
730         ALOGV("Cannot start power hint session, skipping");
731         return false;
732     }
733     auto ret =
734             mPowerHal->createHintSession(getpid(), static_cast<int32_t>(getuid()),
735                                          mPowerHintThreadIds, mTargetDuration, &mPowerHintSession);
736     if (!ret.isOk()) {
737         ALOGW("Failed to start power hint session with error: %s",
738               ret.exceptionToString(ret.exceptionCode()).c_str());
739     } else {
740         mLastTargetDurationSent = mTargetDuration;
741     }
742     return isPowerHintSessionRunning();
743 }
744 
setTargetWorkDuration(int64_t targetDuration)745 void AidlPowerHalWrapper::setTargetWorkDuration(int64_t targetDuration) {
746     ATRACE_CALL();
747     mTargetDuration = targetDuration;
748     if (sTraceHintSessionData) ATRACE_INT64("Time target", targetDuration);
749     if (isPowerHintSessionRunning() && (targetDuration != mLastTargetDurationSent)) {
750         ALOGV("Sending target time: %" PRId64 "ns", targetDuration);
751         mLastTargetDurationSent = targetDuration;
752         auto ret = mPowerHintSession->updateTargetWorkDuration(targetDuration);
753         if (!ret.isOk()) {
754             ALOGW("Failed to set power hint target work duration with error: %s",
755                   ret.exceptionMessage().c_str());
756             mShouldReconnectHal = true;
757         }
758     }
759 }
760 
shouldReportActualDurations()761 bool AidlPowerHalWrapper::shouldReportActualDurations() {
762     // Report if we have never reported before or are approaching a stale session
763     if (!mLastActualDurationSent.has_value() ||
764         (systemTime() - mLastActualReportTimestamp) > kStaleTimeout.count()) {
765         return true;
766     }
767 
768     if (!mActualDuration.has_value()) {
769         return false;
770     }
771     // Report if the change in actual duration exceeds the threshold
772     return abs(*mActualDuration - *mLastActualDurationSent) > mAllowedActualDeviation;
773 }
774 
sendActualWorkDuration(int64_t actualDuration,nsecs_t timestamp)775 void AidlPowerHalWrapper::sendActualWorkDuration(int64_t actualDuration, nsecs_t timestamp) {
776     ATRACE_CALL();
777 
778     if (actualDuration < 0 || !isPowerHintSessionRunning()) {
779         ALOGV("Failed to send actual work duration, skipping");
780         return;
781     }
782     const nsecs_t reportedDuration = actualDuration;
783 
784     mActualDuration = reportedDuration;
785     WorkDuration duration;
786     duration.durationNanos = reportedDuration;
787     duration.timeStampNanos = timestamp;
788     mPowerHintQueue.push_back(duration);
789 
790     if (sTraceHintSessionData) {
791         ATRACE_INT64("Measured duration", actualDuration);
792         ATRACE_INT64("Target error term", actualDuration - mTargetDuration);
793 
794         ATRACE_INT64("Reported duration", reportedDuration);
795         ATRACE_INT64("Reported target", mLastTargetDurationSent);
796         ATRACE_INT64("Reported target error term", reportedDuration - mLastTargetDurationSent);
797     }
798 
799     ALOGV("Sending actual work duration of: %" PRId64 " on reported target: %" PRId64
800           " with error: %" PRId64,
801           reportedDuration, mLastTargetDurationSent, reportedDuration - mLastTargetDurationSent);
802 
803     // This rate limiter queues similar duration reports to the powerhal into
804     // batches to avoid excessive binder calls. The criteria to send a given batch
805     // are outlined in shouldReportActualDurationsNow()
806     if (shouldReportActualDurations()) {
807         ALOGV("Sending hint update batch");
808         mLastActualReportTimestamp = systemTime();
809         auto ret = mPowerHintSession->reportActualWorkDuration(mPowerHintQueue);
810         if (!ret.isOk()) {
811             ALOGW("Failed to report actual work durations with error: %s",
812                   ret.exceptionMessage().c_str());
813             mShouldReconnectHal = true;
814         }
815         mPowerHintQueue.clear();
816         // We save the actual duration here for rate limiting
817         mLastActualDurationSent = actualDuration;
818     }
819 }
820 
shouldReconnectHAL()821 bool AidlPowerHalWrapper::shouldReconnectHAL() {
822     return mShouldReconnectHal;
823 }
824 
getPowerHintSessionThreadIds()825 std::vector<int32_t> AidlPowerHalWrapper::getPowerHintSessionThreadIds() {
826     return mPowerHintThreadIds;
827 }
828 
getTargetWorkDuration()829 std::optional<int64_t> AidlPowerHalWrapper::getTargetWorkDuration() {
830     return mTargetDuration;
831 }
832 
setAllowedActualDeviation(nsecs_t allowedDeviation)833 void AidlPowerHalWrapper::setAllowedActualDeviation(nsecs_t allowedDeviation) {
834     mAllowedActualDeviation = allowedDeviation;
835 }
836 
837 const bool AidlPowerHalWrapper::sTraceHintSessionData =
838         base::GetBoolProperty(std::string("debug.sf.trace_hint_sessions"), false);
839 
getPowerHal()840 PowerAdvisor::HalWrapper* PowerAdvisor::getPowerHal() {
841     if (!mHasHal) {
842         return nullptr;
843     }
844 
845     // Grab old hint session values before we destroy any existing wrapper
846     std::vector<int32_t> oldPowerHintSessionThreadIds;
847     std::optional<int64_t> oldTargetWorkDuration;
848 
849     if (mHalWrapper != nullptr) {
850         oldPowerHintSessionThreadIds = mHalWrapper->getPowerHintSessionThreadIds();
851         oldTargetWorkDuration = mHalWrapper->getTargetWorkDuration();
852     }
853 
854     // If we used to have a HAL, but it stopped responding, attempt to reconnect
855     if (mReconnectPowerHal) {
856         mHalWrapper = nullptr;
857         mReconnectPowerHal = false;
858     }
859 
860     if (mHalWrapper != nullptr) {
861         auto wrapper = mHalWrapper.get();
862         // If the wrapper is fine, return it, but if it indicates a reconnect, remake it
863         if (!wrapper->shouldReconnectHAL()) {
864             return wrapper;
865         }
866         ALOGD("Reconnecting Power HAL");
867         mHalWrapper = nullptr;
868     }
869 
870     // At this point, we know for sure there is no running session
871     mPowerHintSessionRunning = false;
872 
873     // First attempt to connect to the AIDL Power HAL
874     mHalWrapper = AidlPowerHalWrapper::connect();
875 
876     // If that didn't succeed, attempt to connect to the HIDL Power HAL
877     if (mHalWrapper == nullptr) {
878         mHalWrapper = HidlPowerHalWrapper::connect();
879     } else {
880         ALOGD("Successfully connecting AIDL Power HAL");
881         // If AIDL, pass on any existing hint session values
882         mHalWrapper->setPowerHintSessionThreadIds(oldPowerHintSessionThreadIds);
883         // Only set duration and start if duration is defined
884         if (oldTargetWorkDuration.has_value()) {
885             mHalWrapper->setTargetWorkDuration(*oldTargetWorkDuration);
886             // Only start if possible to run and both threadids and duration are defined
887             if (usePowerHintSession() && !oldPowerHintSessionThreadIds.empty()) {
888                 mPowerHintSessionRunning = mHalWrapper->startPowerHintSession();
889             }
890         }
891     }
892 
893     // If we make it to this point and still don't have a HAL, it's unlikely we
894     // will, so stop trying
895     if (mHalWrapper == nullptr) {
896         mHasHal = false;
897     }
898 
899     return mHalWrapper.get();
900 }
901 
902 } // namespace impl
903 } // namespace Hwc2
904 } // namespace android
905