• 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/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 using android::hardware::power::Boost;
53 using android::hardware::power::IPowerHintSession;
54 using android::hardware::power::Mode;
55 using android::hardware::power::SessionHint;
56 using android::hardware::power::WorkDuration;
57 
58 PowerAdvisor::~PowerAdvisor() = default;
59 
60 namespace {
getUpdateTimeout()61 std::chrono::milliseconds getUpdateTimeout() {
62     // Default to a timeout of 80ms if nothing else is specified
63     static std::chrono::milliseconds timeout =
64             std::chrono::milliseconds(sysprop::display_update_imminent_timeout_ms(80));
65     return timeout;
66 }
67 
traceExpensiveRendering(bool enabled)68 void traceExpensiveRendering(bool enabled) {
69     if (enabled) {
70         ATRACE_ASYNC_BEGIN("ExpensiveRendering", 0);
71     } else {
72         ATRACE_ASYNC_END("ExpensiveRendering", 0);
73     }
74 }
75 
76 } // namespace
77 
PowerAdvisor(SurfaceFlinger & flinger)78 PowerAdvisor::PowerAdvisor(SurfaceFlinger& flinger)
79       : mPowerHal(std::make_unique<power::PowerHalController>()), mFlinger(flinger) {
80     if (getUpdateTimeout() > 0ms) {
81         mScreenUpdateTimer.emplace("UpdateImminentTimer", getUpdateTimeout(),
82                                    /* resetCallback */ nullptr,
83                                    /* timeoutCallback */
84                                    [this] {
85                                        while (true) {
86                                            auto timeSinceLastUpdate = std::chrono::nanoseconds(
87                                                    systemTime() - mLastScreenUpdatedTime.load());
88                                            if (timeSinceLastUpdate >= getUpdateTimeout()) {
89                                                break;
90                                            }
91                                            // We may try to disable expensive rendering and allow
92                                            // for sending DISPLAY_UPDATE_IMMINENT hints too early if
93                                            // we idled very shortly after updating the screen, so
94                                            // make sure we wait enough time.
95                                            std::this_thread::sleep_for(getUpdateTimeout() -
96                                                                        timeSinceLastUpdate);
97                                        }
98                                        mSendUpdateImminent.store(true);
99                                        mFlinger.disableExpensiveRendering();
100                                    });
101     }
102 }
103 
init()104 void PowerAdvisor::init() {
105     // Defer starting the screen update timer until SurfaceFlinger finishes construction.
106     if (mScreenUpdateTimer) {
107         mScreenUpdateTimer->start();
108     }
109 }
110 
onBootFinished()111 void PowerAdvisor::onBootFinished() {
112     mBootFinished.store(true);
113 }
114 
setExpensiveRenderingExpected(DisplayId displayId,bool expected)115 void PowerAdvisor::setExpensiveRenderingExpected(DisplayId displayId, bool expected) {
116     if (!mHasExpensiveRendering) {
117         ALOGV("Skipped sending EXPENSIVE_RENDERING because HAL doesn't support it");
118         return;
119     }
120     if (expected) {
121         mExpensiveDisplays.insert(displayId);
122     } else {
123         mExpensiveDisplays.erase(displayId);
124     }
125 
126     const bool expectsExpensiveRendering = !mExpensiveDisplays.empty();
127     if (mNotifiedExpensiveRendering != expectsExpensiveRendering) {
128         auto ret = getPowerHal().setMode(Mode::EXPENSIVE_RENDERING, expectsExpensiveRendering);
129         if (!ret.isOk()) {
130             if (ret.isUnsupported()) {
131                 mHasExpensiveRendering = false;
132             }
133             return;
134         }
135 
136         mNotifiedExpensiveRendering = expectsExpensiveRendering;
137         traceExpensiveRendering(mNotifiedExpensiveRendering);
138     }
139 }
140 
notifyCpuLoadUp()141 void PowerAdvisor::notifyCpuLoadUp() {
142     // Only start sending this notification once the system has booted so we don't introduce an
143     // early-boot dependency on Power HAL
144     if (!mBootFinished.load()) {
145         return;
146     }
147     if (usePowerHintSession() && ensurePowerHintSessionRunning()) {
148         std::lock_guard lock(mHintSessionMutex);
149         auto ret = mHintSession->sendHint(SessionHint::CPU_LOAD_UP);
150         if (!ret.isOk()) {
151             mHintSessionRunning = false;
152         }
153     }
154 }
155 
notifyDisplayUpdateImminentAndCpuReset()156 void PowerAdvisor::notifyDisplayUpdateImminentAndCpuReset() {
157     // Only start sending this notification once the system has booted so we don't introduce an
158     // early-boot dependency on Power HAL
159     if (!mBootFinished.load()) {
160         return;
161     }
162 
163     if (mSendUpdateImminent.exchange(false)) {
164         ALOGV("AIDL notifyDisplayUpdateImminentAndCpuReset");
165         if (usePowerHintSession() && ensurePowerHintSessionRunning()) {
166             std::lock_guard lock(mHintSessionMutex);
167             auto ret = mHintSession->sendHint(SessionHint::CPU_LOAD_RESET);
168             if (!ret.isOk()) {
169                 mHintSessionRunning = false;
170             }
171         }
172 
173         if (!mHasDisplayUpdateImminent) {
174             ALOGV("Skipped sending DISPLAY_UPDATE_IMMINENT because HAL doesn't support it");
175         } else {
176             auto ret = getPowerHal().setBoost(Boost::DISPLAY_UPDATE_IMMINENT, 0);
177             if (ret.isUnsupported()) {
178                 mHasDisplayUpdateImminent = false;
179             }
180         }
181 
182         if (mScreenUpdateTimer) {
183             mScreenUpdateTimer->reset();
184         } else {
185             // If we don't have a screen update timer, then we don't throttle power hal calls so
186             // flip this bit back to allow for calling into power hal again.
187             mSendUpdateImminent.store(true);
188         }
189     }
190 
191     if (mScreenUpdateTimer) {
192         mLastScreenUpdatedTime.store(systemTime());
193     }
194 }
195 
196 // checks both if it supports and if it's enabled
usePowerHintSession()197 bool PowerAdvisor::usePowerHintSession() {
198     // uses cached value since the underlying support and flag are unlikely to change at runtime
199     return mHintSessionEnabled.value_or(false) && supportsPowerHintSession();
200 }
201 
supportsPowerHintSession()202 bool PowerAdvisor::supportsPowerHintSession() {
203     // cache to avoid needing lock every time
204     if (!mSupportsHintSession.has_value()) {
205         mSupportsHintSession = getPowerHal().getHintSessionPreferredRate().isOk();
206     }
207     return *mSupportsHintSession;
208 }
209 
ensurePowerHintSessionRunning()210 bool PowerAdvisor::ensurePowerHintSessionRunning() {
211     if (!mHintSessionRunning && !mHintSessionThreadIds.empty() && usePowerHintSession()) {
212         startPowerHintSession(mHintSessionThreadIds);
213     }
214     return mHintSessionRunning;
215 }
216 
updateTargetWorkDuration(Duration targetDuration)217 void PowerAdvisor::updateTargetWorkDuration(Duration targetDuration) {
218     if (!usePowerHintSession()) {
219         ALOGV("Power hint session target duration cannot be set, skipping");
220         return;
221     }
222     ATRACE_CALL();
223     {
224         mTargetDuration = targetDuration;
225         if (sTraceHintSessionData) ATRACE_INT64("Time target", targetDuration.ns());
226         if (ensurePowerHintSessionRunning() && (targetDuration != mLastTargetDurationSent)) {
227             ALOGV("Sending target time: %" PRId64 "ns", targetDuration.ns());
228             mLastTargetDurationSent = targetDuration;
229             std::lock_guard lock(mHintSessionMutex);
230             auto ret = mHintSession->updateTargetWorkDuration(targetDuration.ns());
231             if (!ret.isOk()) {
232                 ALOGW("Failed to set power hint target work duration with error: %s",
233                       ret.exceptionMessage().c_str());
234                 mHintSessionRunning = false;
235             }
236         }
237     }
238 }
239 
reportActualWorkDuration()240 void PowerAdvisor::reportActualWorkDuration() {
241     if (!mBootFinished || !sUseReportActualDuration || !usePowerHintSession()) {
242         ALOGV("Actual work duration power hint cannot be sent, skipping");
243         return;
244     }
245     ATRACE_CALL();
246     std::optional<Duration> actualDuration = estimateWorkDuration();
247     if (!actualDuration.has_value() || actualDuration < 0ns || !ensurePowerHintSessionRunning()) {
248         ALOGV("Failed to send actual work duration, skipping");
249         return;
250     }
251     actualDuration = std::make_optional(*actualDuration + sTargetSafetyMargin);
252     mActualDuration = actualDuration;
253     WorkDuration duration;
254     duration.durationNanos = actualDuration->ns();
255     duration.timeStampNanos = TimePoint::now().ns();
256     mHintSessionQueue.push_back(duration);
257 
258     if (sTraceHintSessionData) {
259         ATRACE_INT64("Measured duration", actualDuration->ns());
260         ATRACE_INT64("Target error term", Duration{*actualDuration - mTargetDuration}.ns());
261         ATRACE_INT64("Reported duration", actualDuration->ns());
262         ATRACE_INT64("Reported target", mLastTargetDurationSent.ns());
263         ATRACE_INT64("Reported target error term",
264                      Duration{*actualDuration - mLastTargetDurationSent}.ns());
265     }
266 
267     ALOGV("Sending actual work duration of: %" PRId64 " on reported target: %" PRId64
268           " with error: %" PRId64,
269           actualDuration->ns(), mLastTargetDurationSent.ns(),
270           Duration{*actualDuration - mLastTargetDurationSent}.ns());
271 
272     {
273         std::lock_guard lock(mHintSessionMutex);
274         auto ret = mHintSession->reportActualWorkDuration(mHintSessionQueue);
275         if (!ret.isOk()) {
276             ALOGW("Failed to report actual work durations with error: %s",
277                   ret.exceptionMessage().c_str());
278             mHintSessionRunning = false;
279             return;
280         }
281     }
282     mHintSessionQueue.clear();
283 }
284 
enablePowerHintSession(bool enabled)285 void PowerAdvisor::enablePowerHintSession(bool enabled) {
286     mHintSessionEnabled = enabled;
287 }
288 
startPowerHintSession(const std::vector<int32_t> & threadIds)289 bool PowerAdvisor::startPowerHintSession(const std::vector<int32_t>& threadIds) {
290     if (!mBootFinished.load()) {
291         return false;
292     }
293     if (!usePowerHintSession()) {
294         ALOGI("Cannot start power hint session: disabled or unsupported");
295         return false;
296     }
297     if (mHintSessionRunning) {
298         ALOGE("Cannot start power hint session: already running");
299         return false;
300     }
301     LOG_ALWAYS_FATAL_IF(threadIds.empty(), "No thread IDs provided to power hint session!");
302     {
303         std::lock_guard lock(mHintSessionMutex);
304         mHintSession = nullptr;
305         mHintSessionThreadIds = threadIds;
306 
307         auto ret = getPowerHal().createHintSession(getpid(), static_cast<int32_t>(getuid()),
308                                                    threadIds, mTargetDuration.ns());
309 
310         if (ret.isOk()) {
311             mHintSessionRunning = true;
312             mHintSession = ret.value();
313         }
314     }
315     return mHintSessionRunning;
316 }
317 
setGpuFenceTime(DisplayId displayId,std::unique_ptr<FenceTime> && fenceTime)318 void PowerAdvisor::setGpuFenceTime(DisplayId displayId, std::unique_ptr<FenceTime>&& fenceTime) {
319     DisplayTimingData& displayData = mDisplayTimingData[displayId];
320     if (displayData.gpuEndFenceTime) {
321         nsecs_t signalTime = displayData.gpuEndFenceTime->getSignalTime();
322         if (signalTime != Fence::SIGNAL_TIME_INVALID && signalTime != Fence::SIGNAL_TIME_PENDING) {
323             for (auto&& [_, otherDisplayData] : mDisplayTimingData) {
324                 // If the previous display started before us but ended after we should have
325                 // started, then it likely delayed our start time and we must compensate for that.
326                 // Displays finishing earlier should have already made their way through this call
327                 // and swapped their timing into "lastValid" from "latest", so we check that here.
328                 if (!otherDisplayData.lastValidGpuStartTime.has_value()) continue;
329                 if ((*otherDisplayData.lastValidGpuStartTime < *displayData.gpuStartTime) &&
330                     (*otherDisplayData.lastValidGpuEndTime > *displayData.gpuStartTime)) {
331                     displayData.lastValidGpuStartTime = *otherDisplayData.lastValidGpuEndTime;
332                     break;
333                 }
334             }
335             displayData.lastValidGpuStartTime = displayData.gpuStartTime;
336             displayData.lastValidGpuEndTime = TimePoint::fromNs(signalTime);
337         }
338     }
339     displayData.gpuEndFenceTime = std::move(fenceTime);
340     displayData.gpuStartTime = TimePoint::now();
341 }
342 
setHwcValidateTiming(DisplayId displayId,TimePoint validateStartTime,TimePoint validateEndTime)343 void PowerAdvisor::setHwcValidateTiming(DisplayId displayId, TimePoint validateStartTime,
344                                         TimePoint validateEndTime) {
345     DisplayTimingData& displayData = mDisplayTimingData[displayId];
346     displayData.hwcValidateStartTime = validateStartTime;
347     displayData.hwcValidateEndTime = validateEndTime;
348 }
349 
setHwcPresentTiming(DisplayId displayId,TimePoint presentStartTime,TimePoint presentEndTime)350 void PowerAdvisor::setHwcPresentTiming(DisplayId displayId, TimePoint presentStartTime,
351                                        TimePoint presentEndTime) {
352     DisplayTimingData& displayData = mDisplayTimingData[displayId];
353     displayData.hwcPresentStartTime = presentStartTime;
354     displayData.hwcPresentEndTime = presentEndTime;
355 }
356 
setSkippedValidate(DisplayId displayId,bool skipped)357 void PowerAdvisor::setSkippedValidate(DisplayId displayId, bool skipped) {
358     mDisplayTimingData[displayId].skippedValidate = skipped;
359 }
360 
setRequiresClientComposition(DisplayId displayId,bool requiresClientComposition)361 void PowerAdvisor::setRequiresClientComposition(DisplayId displayId,
362                                                 bool requiresClientComposition) {
363     mDisplayTimingData[displayId].usedClientComposition = requiresClientComposition;
364 }
365 
setExpectedPresentTime(TimePoint expectedPresentTime)366 void PowerAdvisor::setExpectedPresentTime(TimePoint expectedPresentTime) {
367     mExpectedPresentTimes.append(expectedPresentTime);
368 }
369 
setSfPresentTiming(TimePoint presentFenceTime,TimePoint presentEndTime)370 void PowerAdvisor::setSfPresentTiming(TimePoint presentFenceTime, TimePoint presentEndTime) {
371     mLastSfPresentEndTime = presentEndTime;
372     mLastPresentFenceTime = presentFenceTime;
373 }
374 
setFrameDelay(Duration frameDelayDuration)375 void PowerAdvisor::setFrameDelay(Duration frameDelayDuration) {
376     mFrameDelayDuration = frameDelayDuration;
377 }
378 
setHwcPresentDelayedTime(DisplayId displayId,TimePoint earliestFrameStartTime)379 void PowerAdvisor::setHwcPresentDelayedTime(DisplayId displayId, TimePoint earliestFrameStartTime) {
380     mDisplayTimingData[displayId].hwcPresentDelayedTime = earliestFrameStartTime;
381 }
382 
setCommitStart(TimePoint commitStartTime)383 void PowerAdvisor::setCommitStart(TimePoint commitStartTime) {
384     mCommitStartTimes.append(commitStartTime);
385 }
386 
setCompositeEnd(TimePoint compositeEndTime)387 void PowerAdvisor::setCompositeEnd(TimePoint compositeEndTime) {
388     mLastPostcompDuration = compositeEndTime - mLastSfPresentEndTime;
389 }
390 
setDisplays(std::vector<DisplayId> & displayIds)391 void PowerAdvisor::setDisplays(std::vector<DisplayId>& displayIds) {
392     mDisplayIds = displayIds;
393 }
394 
setTotalFrameTargetWorkDuration(Duration targetDuration)395 void PowerAdvisor::setTotalFrameTargetWorkDuration(Duration targetDuration) {
396     mTotalFrameTargetDuration = targetDuration;
397 }
398 
getOrderedDisplayIds(std::optional<TimePoint> DisplayTimingData::* sortBy)399 std::vector<DisplayId> PowerAdvisor::getOrderedDisplayIds(
400         std::optional<TimePoint> DisplayTimingData::*sortBy) {
401     std::vector<DisplayId> sortedDisplays;
402     std::copy_if(mDisplayIds.begin(), mDisplayIds.end(), std::back_inserter(sortedDisplays),
403                  [&](DisplayId id) {
404                      return mDisplayTimingData.count(id) &&
405                              (mDisplayTimingData[id].*sortBy).has_value();
406                  });
407     std::sort(sortedDisplays.begin(), sortedDisplays.end(), [&](DisplayId idA, DisplayId idB) {
408         return *(mDisplayTimingData[idA].*sortBy) < *(mDisplayTimingData[idB].*sortBy);
409     });
410     return sortedDisplays;
411 }
412 
estimateWorkDuration()413 std::optional<Duration> PowerAdvisor::estimateWorkDuration() {
414     if (!mExpectedPresentTimes.isFull() || !mCommitStartTimes.isFull()) {
415         return std::nullopt;
416     }
417 
418     // Tracks when we finish presenting to hwc
419     TimePoint estimatedHwcEndTime = mCommitStartTimes[0];
420 
421     // How long we spent this frame not doing anything, waiting for fences or vsync
422     Duration idleDuration = 0ns;
423 
424     // Most recent previous gpu end time in the current frame, probably from a prior display, used
425     // as the start time for the next gpu operation if it ran over time since it probably blocked
426     std::optional<TimePoint> previousValidGpuEndTime;
427 
428     // The currently estimated gpu end time for the frame,
429     // used to accumulate gpu time as we iterate over the active displays
430     std::optional<TimePoint> estimatedGpuEndTime;
431 
432     // The timing info for the previously calculated display, if there was one
433     std::optional<DisplayTimeline> previousDisplayTiming;
434     std::vector<DisplayId>&& displayIds =
435             getOrderedDisplayIds(&DisplayTimingData::hwcPresentStartTime);
436     DisplayTimeline displayTiming;
437 
438     // Iterate over the displays that use hwc in the same order they are presented
439     for (DisplayId displayId : displayIds) {
440         if (mDisplayTimingData.count(displayId) == 0) {
441             continue;
442         }
443 
444         auto& displayData = mDisplayTimingData.at(displayId);
445 
446         displayTiming = displayData.calculateDisplayTimeline(mLastPresentFenceTime);
447 
448         // If this is the first display, include the duration before hwc present starts
449         if (!previousDisplayTiming.has_value()) {
450             estimatedHwcEndTime += displayTiming.hwcPresentStartTime - mCommitStartTimes[0];
451         } else { // Otherwise add the time since last display's hwc present finished
452             estimatedHwcEndTime +=
453                     displayTiming.hwcPresentStartTime - previousDisplayTiming->hwcPresentEndTime;
454         }
455 
456         // Update predicted present finish time with this display's present time
457         estimatedHwcEndTime = displayTiming.hwcPresentEndTime;
458 
459         // Track how long we spent waiting for the fence, can be excluded from the timing estimate
460         idleDuration += displayTiming.probablyWaitsForPresentFence
461                 ? mLastPresentFenceTime - displayTiming.presentFenceWaitStartTime
462                 : 0ns;
463 
464         // Track how long we spent waiting to present, can be excluded from the timing estimate
465         idleDuration += displayTiming.hwcPresentDelayDuration;
466 
467         // Estimate the reference frame's gpu timing
468         auto gpuTiming = displayData.estimateGpuTiming(previousValidGpuEndTime);
469         if (gpuTiming.has_value()) {
470             previousValidGpuEndTime = gpuTiming->startTime + gpuTiming->duration;
471 
472             // Estimate the prediction frame's gpu end time from the reference frame
473             estimatedGpuEndTime = std::max(displayTiming.hwcPresentStartTime,
474                                            estimatedGpuEndTime.value_or(TimePoint{0ns})) +
475                     gpuTiming->duration;
476         }
477         previousDisplayTiming = displayTiming;
478     }
479     ATRACE_INT64("Idle duration", idleDuration.ns());
480 
481     TimePoint estimatedFlingerEndTime = mLastSfPresentEndTime;
482 
483     // Don't count time spent idly waiting in the estimate as we could do more work in that time
484     estimatedHwcEndTime -= idleDuration;
485     estimatedFlingerEndTime -= idleDuration;
486 
487     // We finish the frame when both present and the gpu are done, so wait for the later of the two
488     // Also add the frame delay duration since the target did not move while we were delayed
489     Duration totalDuration = mFrameDelayDuration +
490             std::max(estimatedHwcEndTime, estimatedGpuEndTime.value_or(TimePoint{0ns})) -
491             mCommitStartTimes[0];
492 
493     // We finish SurfaceFlinger when post-composition finishes, so add that in here
494     Duration flingerDuration =
495             estimatedFlingerEndTime + mLastPostcompDuration - mCommitStartTimes[0];
496 
497     // Combine the two timings into a single normalized one
498     Duration combinedDuration = combineTimingEstimates(totalDuration, flingerDuration);
499 
500     return std::make_optional(combinedDuration);
501 }
502 
combineTimingEstimates(Duration totalDuration,Duration flingerDuration)503 Duration PowerAdvisor::combineTimingEstimates(Duration totalDuration, Duration flingerDuration) {
504     Duration targetDuration{0ns};
505     targetDuration = mTargetDuration;
506     if (!mTotalFrameTargetDuration.has_value()) return flingerDuration;
507 
508     // Normalize total to the flinger target (vsync period) since that's how often we actually send
509     // hints
510     Duration normalizedTotalDuration = Duration::fromNs((targetDuration.ns() * totalDuration.ns()) /
511                                                         mTotalFrameTargetDuration->ns());
512     return std::max(flingerDuration, normalizedTotalDuration);
513 }
514 
calculateDisplayTimeline(TimePoint fenceTime)515 PowerAdvisor::DisplayTimeline PowerAdvisor::DisplayTimingData::calculateDisplayTimeline(
516         TimePoint fenceTime) {
517     DisplayTimeline timeline;
518     // How long between calling hwc present and trying to wait on the fence
519     const Duration fenceWaitStartDelay =
520             (skippedValidate ? kFenceWaitStartDelaySkippedValidate : kFenceWaitStartDelayValidated);
521 
522     // Did our reference frame wait for an appropriate vsync before calling into hwc
523     const bool waitedOnHwcPresentTime = hwcPresentDelayedTime.has_value() &&
524             *hwcPresentDelayedTime > *hwcPresentStartTime &&
525             *hwcPresentDelayedTime < *hwcPresentEndTime;
526 
527     // Use validate start here if we skipped it because we did validate + present together
528     timeline.hwcPresentStartTime = skippedValidate ? *hwcValidateStartTime : *hwcPresentStartTime;
529 
530     // Use validate end here if we skipped it because we did validate + present together
531     timeline.hwcPresentEndTime = skippedValidate ? *hwcValidateEndTime : *hwcPresentEndTime;
532 
533     // How long hwc present was delayed waiting for the next appropriate vsync
534     timeline.hwcPresentDelayDuration =
535             (waitedOnHwcPresentTime ? *hwcPresentDelayedTime - *hwcPresentStartTime : 0ns);
536     // When we started waiting for the present fence after calling into hwc present
537     timeline.presentFenceWaitStartTime =
538             timeline.hwcPresentStartTime + timeline.hwcPresentDelayDuration + fenceWaitStartDelay;
539     timeline.probablyWaitsForPresentFence = fenceTime > timeline.presentFenceWaitStartTime &&
540             fenceTime < timeline.hwcPresentEndTime;
541 
542     // How long we ran after we finished waiting for the fence but before hwc present finished
543     timeline.postPresentFenceHwcPresentDuration = timeline.hwcPresentEndTime -
544             (timeline.probablyWaitsForPresentFence ? fenceTime
545                                                    : timeline.presentFenceWaitStartTime);
546     return timeline;
547 }
548 
estimateGpuTiming(std::optional<TimePoint> previousEndTime)549 std::optional<PowerAdvisor::GpuTimeline> PowerAdvisor::DisplayTimingData::estimateGpuTiming(
550         std::optional<TimePoint> previousEndTime) {
551     if (!(usedClientComposition && lastValidGpuStartTime.has_value() && gpuEndFenceTime)) {
552         return std::nullopt;
553     }
554     const TimePoint latestGpuStartTime =
555             std::max(previousEndTime.value_or(TimePoint{0ns}), *gpuStartTime);
556     const nsecs_t gpuEndFenceSignal = gpuEndFenceTime->getSignalTime();
557     Duration gpuDuration{0ns};
558     if (gpuEndFenceSignal != Fence::SIGNAL_TIME_INVALID &&
559         gpuEndFenceSignal != Fence::SIGNAL_TIME_PENDING) {
560         const TimePoint latestGpuEndTime = TimePoint::fromNs(gpuEndFenceSignal);
561 
562         // If we know how long the most recent gpu duration was, use that
563         gpuDuration = latestGpuEndTime - latestGpuStartTime;
564     } else if (lastValidGpuEndTime.has_value()) {
565         // If we don't have the fence data, use the most recent information we do have
566         gpuDuration = *lastValidGpuEndTime - *lastValidGpuStartTime;
567         if (gpuEndFenceSignal == Fence::SIGNAL_TIME_PENDING) {
568             // If pending but went over the previous duration, use current time as the end
569             gpuDuration = std::max(gpuDuration, Duration{TimePoint::now() - latestGpuStartTime});
570         }
571     }
572     return GpuTimeline{.duration = gpuDuration, .startTime = latestGpuStartTime};
573 }
574 
575 const bool PowerAdvisor::sTraceHintSessionData =
576         base::GetBoolProperty(std::string("debug.sf.trace_hint_sessions"), false);
577 
578 const Duration PowerAdvisor::sTargetSafetyMargin = std::chrono::microseconds(
579         base::GetIntProperty<int64_t>("debug.sf.hint_margin_us",
580                                       ticks<std::micro>(PowerAdvisor::kDefaultTargetSafetyMargin)));
581 
582 const bool PowerAdvisor::sUseReportActualDuration =
583         base::GetBoolProperty(std::string("debug.adpf.use_report_actual_duration"), true);
584 
getPowerHal()585 power::PowerHalController& PowerAdvisor::getPowerHal() {
586     static std::once_flag halFlag;
587     std::call_once(halFlag, [this] { mPowerHal->init(); });
588     return *mPowerHal;
589 }
590 
591 } // namespace impl
592 } // namespace Hwc2
593 } // namespace android
594