SurfaceFlinger: fix early latching of buffers

Use the FrameTimeline::SurfaceFrame predicted present time
to avoid latching a buffer too early (i.e. before the time
SurfaceFlinger planned to latch this buffer when the app requested
a vsync callback).

Bug: 169901895
Test: expand notification shade and observe systrace
Change-Id: I823546992c89f88c0c29b839ce21c79ff1ffcfbd
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index fa75ffa..6561707 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -389,6 +389,20 @@
     mBufferInfo.mFrameLatencyNeeded = true;
 }
 
+bool BufferLayer::frameIsEarly(nsecs_t expectedPresentTime) const {
+    // TODO(b/169901895): kEarlyLatchVsyncThreshold should be based on the
+    // vsync period. We can do this change as soon as ag/13100772 is merged.
+    constexpr static std::chrono::nanoseconds kEarlyLatchVsyncThreshold = 5ms;
+
+    const auto presentTime = nextPredictedPresentTime();
+    if (std::abs(presentTime - expectedPresentTime) >= kEarlyLatchMaxThreshold.count()) {
+        return false;
+    }
+
+    return presentTime >= expectedPresentTime &&
+            presentTime - expectedPresentTime >= kEarlyLatchVsyncThreshold.count();
+}
+
 bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime,
                               nsecs_t expectedPresentTime) {
     ATRACE_CALL();
@@ -421,6 +435,12 @@
         return false;
     }
 
+    if (frameIsEarly(expectedPresentTime)) {
+        ATRACE_NAME("frameIsEarly()");
+        mFlinger->signalLayerUpdate();
+        return false;
+    }
+
     // If the head buffer's acquire fence hasn't signaled yet, return and
     // try again later
     if (!fenceHasSignaled()) {