Don't clear timestamps when enabling HW vsync.

It should clear after the first HW Vsync timestamp comes in,
and when VSyncReactor period confirmed. Therefore, a prediction
when HW vsync is enabled but not yet confirmed is consistent with a
prediction when coming out of idle.

Bug: 272802278
Test: Flash, perfetto trace
Test: atest libsurfaceflinger_unittest
Change-Id: I619162d5583f33087de04c0e3b073a589ec4c2f7
diff --git a/services/surfaceflinger/Scheduler/VsyncSchedule.cpp b/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
index ff3f29d..5691792 100644
--- a/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
+++ b/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
@@ -17,6 +17,7 @@
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
 #include <ftl/fake_guard.h>
+#include <gui/TraceUtils.h>
 #include <scheduler/Fps.h>
 #include <scheduler/Timer.h>
 
@@ -144,6 +145,14 @@
 }
 
 bool VsyncSchedule::addResyncSample(TimePoint timestamp, ftl::Optional<Period> hwcVsyncPeriod) {
+    ATRACE_CALL();
+
+    if (mClearTimestampsOnNextSample) {
+        ATRACE_FORMAT("clearing sample after HW vsync enabled", __func__);
+        getTracker().resetModel();
+        mClearTimestampsOnNextSample = false;
+    }
+
     bool needsHwVsync = false;
     bool periodFlushed = false;
     {
@@ -170,7 +179,7 @@
 
 void VsyncSchedule::enableHardwareVsyncLocked() {
     if (mHwVsyncState == HwVsyncState::Disabled) {
-        getTracker().resetModel();
+        mClearTimestampsOnNextSample = true;
         mRequestHardwareVsync(mId, true);
         mHwVsyncState = HwVsyncState::Enabled;
     }
diff --git a/services/surfaceflinger/Scheduler/VsyncSchedule.h b/services/surfaceflinger/Scheduler/VsyncSchedule.h
index 5eca29a..556ef80 100644
--- a/services/surfaceflinger/Scheduler/VsyncSchedule.h
+++ b/services/surfaceflinger/Scheduler/VsyncSchedule.h
@@ -146,6 +146,11 @@
     // device is off.
     HwVsyncState mPendingHwVsyncState GUARDED_BY(kMainThreadContext) = HwVsyncState::Disabled;
 
+    // Whether to reset the timestamps stored in the vsync model on the next hw vsync sample. This
+    // is to avoid clearing the model when hw vsync is enabled, in order to be consistent with the
+    // stale timestamps. Instead, clear the model on the first hw vsync callback.
+    bool mClearTimestampsOnNextSample = false;
+
     class PredictedVsyncTracer;
     using TracerPtr = std::unique_ptr<PredictedVsyncTracer>;
 
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp
index cf3fab3..4780e49 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp
@@ -91,18 +91,16 @@
 };
 
 struct DispSyncIsSupportedVariant {
-    static void setupResetModelCallExpectations(DisplayTransactionTest* test) {
+    static void setupStartPeriodTransitionCallExpectations(DisplayTransactionTest* test) {
         auto vsyncSchedule = test->mFlinger.scheduler()->getVsyncSchedule();
         EXPECT_CALL(static_cast<mock::VsyncController&>(vsyncSchedule->getController()),
                     startPeriodTransition(DEFAULT_VSYNC_PERIOD, false))
                 .Times(1);
-        EXPECT_CALL(static_cast<mock::VSyncTracker&>(vsyncSchedule->getTracker()), resetModel())
-                .Times(1);
     }
 };
 
 struct DispSyncNotSupportedVariant {
-    static void setupResetModelCallExpectations(DisplayTransactionTest* /* test */) {}
+    static void setupStartPeriodTransitionCallExpectations(DisplayTransactionTest* /* test */) {}
 };
 
 // --------------------------------------------------------------------
@@ -125,7 +123,7 @@
     static void setupCallExpectations(DisplayTransactionTest* test) {
         Case::setupComposerCallExpectations(test, IComposerClient::PowerMode::ON);
         Case::EventThread::setupEnableVsyncCallExpectations(test);
-        Case::DispSync::setupResetModelCallExpectations(test);
+        Case::DispSync::setupStartPeriodTransitionCallExpectations(test);
         Case::setupRepaintEverythingCallExpectations(test);
     }
 
@@ -186,7 +184,7 @@
     template <typename Case>
     static void setupCallExpectations(DisplayTransactionTest* test) {
         Case::EventThread::setupEnableVsyncCallExpectations(test);
-        Case::DispSync::setupResetModelCallExpectations(test);
+        Case::DispSync::setupStartPeriodTransitionCallExpectations(test);
         Case::setupComposerCallExpectations(test, Case::Doze::ACTUAL_POWER_MODE_FOR_DOZE);
     }
 };
@@ -204,7 +202,7 @@
     template <typename Case>
     static void setupCallExpectations(DisplayTransactionTest* test) {
         Case::EventThread::setupEnableVsyncCallExpectations(test);
-        Case::DispSync::setupResetModelCallExpectations(test);
+        Case::DispSync::setupStartPeriodTransitionCallExpectations(test);
         Case::setupComposerCallExpectations(test, IComposerClient::PowerMode::ON);
     }
 };