SurfaceFlinger: previousFrameFence needs to check the current time
previousFrameFence returns the fence associated with the previous vsync.
In case that SF wake up was delayed due to a previous frame, up to the
point that the wake up occurs after the vsync, SF needs to check fence
N-1 and not N-2 since frame N-1 was targeting the vsync prior to SF
wake up.
Bug: 187886038
Test: run bouncy ball and simulate the first frame missed
Change-Id: I176c6641dd42132fcfd75a79898a5d2bd8da9c90
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index ecee977..267dd6d 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1709,11 +1709,11 @@
}
SurfaceFlinger::FenceWithFenceTime SurfaceFlinger::previousFrameFence() {
- // We are storing the last 2 present fences. If sf's phase offset is to be
- // woken up before the actual vsync but targeting the next vsync, we need to check
- // fence N-2
- return mVsyncModulator->getVsyncConfig().sfOffset > 0 ? mPreviousPresentFences[0]
- : mPreviousPresentFences[1];
+ const auto now = systemTime();
+ const auto vsyncPeriod = mScheduler->getDisplayStatInfo(now).vsyncPeriod;
+ const bool expectedPresentTimeIsTheNextVsync = mExpectedPresentTime - now <= vsyncPeriod;
+ return expectedPresentTimeIsTheNextVsync ? mPreviousPresentFences[0]
+ : mPreviousPresentFences[1];
}
bool SurfaceFlinger::previousFramePending(int graceTimeMs) {