Add pending period to DispSync.

When the period is updated due to a config change, cache the period
and don't immediately update the model until we actually observe updated
vsyncs from the hardware.

To make this more reliable, force hardware vsync to be enabled when we
first initiate a refresh rate change.

Also, override offsets with custom offsets while the period is in flux,
so that we don't fall into bad offsets when ramping up to 90hz

Bug: 128848865
Bug: 128860504
Test: systrace
Change-Id: I6aa87ad29b3effce9067a1d54d444023c7362b22
diff --git a/services/surfaceflinger/Scheduler/VSyncModulator.h b/services/surfaceflinger/Scheduler/VSyncModulator.h
index dab2003..1a0de08 100644
--- a/services/surfaceflinger/Scheduler/VSyncModulator.h
+++ b/services/surfaceflinger/Scheduler/VSyncModulator.h
@@ -30,9 +30,10 @@
  */
 class VSyncModulator {
 private:
-    // Number of frames we'll keep the early phase offsets once they are activated. This acts as a
-    // low-pass filter in case the client isn't quick enough in sending new transactions.
-    const int MIN_EARLY_FRAME_COUNT = 2;
+    // Number of frames we'll keep the early phase offsets once they are activated for a
+    // transaction. This acts as a low-pass filter in case the client isn't quick enough in
+    // sending new transactions.
+    const int MIN_EARLY_FRAME_COUNT_TRANSACTION = 2;
 
 public:
     struct Offsets {
@@ -85,7 +86,7 @@
 
     void setTransactionStart(Scheduler::TransactionStart transactionStart) {
         if (transactionStart == Scheduler::TransactionStart::EARLY) {
-            mRemainingEarlyFrameCount = MIN_EARLY_FRAME_COUNT;
+            mRemainingEarlyFrameCount = MIN_EARLY_FRAME_COUNT_TRANSACTION;
         }
 
         // An early transaction stays an early transaction.
@@ -103,6 +104,26 @@
         updateOffsets();
     }
 
+    // Called when we send a refresh rate change to hardware composer, so that
+    // we can move into early offsets.
+    void onRefreshRateChangeInitiated() {
+        if (mRefreshRateChangePending) {
+            return;
+        }
+        mRefreshRateChangePending = true;
+        updateOffsets();
+    }
+
+    // Called when we detect from vsync signals that the refresh rate changed.
+    // This way we can move out of early offsets if no longer necessary.
+    void onRefreshRateChangeDetected() {
+        if (!mRefreshRateChangePending) {
+            return;
+        }
+        mRefreshRateChangePending = false;
+        updateOffsets();
+    }
+
     void onRefreshed(bool usedRenderEngine) {
         bool updateOffsetsNeeded = false;
         if (mRemainingEarlyFrameCount > 0) {
@@ -147,8 +168,10 @@
     }
 
     Offsets getOffsets() {
+        // Early offsets are used if we're in the middle of a refresh rate
+        // change, or if we recently begin a transaction.
         if (mTransactionStart == Scheduler::TransactionStart::EARLY ||
-            mRemainingEarlyFrameCount > 0) {
+            mRemainingEarlyFrameCount > 0 || mRefreshRateChangePending) {
             return mEarlyOffsets;
         } else if (mLastFrameUsedRenderEngine) {
             return mEarlyGlOffsets;
@@ -173,6 +196,7 @@
     std::atomic<Scheduler::TransactionStart> mTransactionStart =
             Scheduler::TransactionStart::NORMAL;
     std::atomic<bool> mLastFrameUsedRenderEngine = false;
+    std::atomic<bool> mRefreshRateChangePending = false;
     std::atomic<int> mRemainingEarlyFrameCount = 0;
 };