Fix SF hint sessions for virtual multi-display case
Currently timing for hint sessions in SurfaceFlinger do not work for
multi-display case with virtual displays (eg: Android Auto). This
patch fixes that by tracking true sf present completion time to
supplement hwc time tracking in the sf main thread deadline case.
Bug: b/241465879
Test: manual
Change-Id: I169dd4f4afd2223ed0a648440d5f59dc19dc07f6
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
index 62078ba..25f624c 100644
--- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
+++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
@@ -315,7 +315,8 @@
mExpectedPresentTimes.append(expectedPresentTime);
}
-void PowerAdvisor::setPresentFenceTime(nsecs_t presentFenceTime) {
+void PowerAdvisor::setSfPresentTiming(nsecs_t presentFenceTime, nsecs_t presentEndTime) {
+ mLastSfPresentEndTime = presentEndTime;
mLastPresentFenceTime = presentFenceTime;
}
@@ -334,13 +335,7 @@
}
void PowerAdvisor::setCompositeEnd(nsecs_t compositeEnd) {
- mLastCompositeEndTime = compositeEnd;
- // calculate the postcomp time here as well
- std::vector<DisplayId>&& displays = getOrderedDisplayIds(&DisplayTimingData::hwcPresentEndTime);
- DisplayTimingData& timingData = mDisplayTimingData[displays.back()];
- mLastPostcompDuration = compositeEnd -
- (timingData.skippedValidate ? *timingData.hwcValidateEndTime
- : *timingData.hwcPresentEndTime);
+ mLastPostcompDuration = compositeEnd - mLastSfPresentEndTime;
}
void PowerAdvisor::setDisplays(std::vector<DisplayId>& displayIds) {
@@ -399,7 +394,7 @@
getOrderedDisplayIds(&DisplayTimingData::hwcPresentStartTime);
DisplayTimeline referenceTiming, estimatedTiming;
- // Iterate over the displays in the same order they are presented
+ // Iterate over the displays that use hwc in the same order they are presented
for (DisplayId displayId : displayIds) {
if (mDisplayTimingData.count(displayId) == 0) {
continue;
@@ -451,8 +446,11 @@
}
ATRACE_INT64("Idle duration", idleDuration);
+ nsecs_t estimatedFlingerEndTime = earlyHint ? estimatedEndTime : mLastSfPresentEndTime;
+
// Don't count time spent idly waiting in the estimate as we could do more work in that time
estimatedEndTime -= idleDuration;
+ estimatedFlingerEndTime -= idleDuration;
// We finish the frame when both present and the gpu are done, so wait for the later of the two
// Also add the frame delay duration since the target did not move while we were delayed
@@ -460,7 +458,10 @@
std::max(estimatedEndTime, estimatedGpuEndTime.value_or(0)) - mCommitStartTimes[0];
// We finish SurfaceFlinger when post-composition finishes, so add that in here
- nsecs_t flingerDuration = estimatedEndTime + mLastPostcompDuration - mCommitStartTimes[0];
+ nsecs_t flingerDuration =
+ estimatedFlingerEndTime + mLastPostcompDuration - mCommitStartTimes[0];
+
+ // Combine the two timings into a single normalized one
nsecs_t combinedDuration = combineTimingEstimates(totalDuration, flingerDuration);
return std::make_optional(combinedDuration);