Merge "Only apply early offsets when transaction has been applied" into rvc-dev am: 6ac57abe60 am: e34a648ea2 am: 7d77888ead am: f8f44dafdd

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/native/+/11761255

Change-Id: I305117d055dbaafc229e891ec651052391493a8f
diff --git a/services/surfaceflinger/Scheduler/VSyncModulator.cpp b/services/surfaceflinger/Scheduler/VSyncModulator.cpp
index 40a992c..510dc2d 100644
--- a/services/surfaceflinger/Scheduler/VSyncModulator.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncModulator.cpp
@@ -25,6 +25,7 @@
 #include <cutils/properties.h>
 #include <utils/Trace.h>
 
+#include <chrono>
 #include <cinttypes>
 #include <mutex>
 
@@ -52,6 +53,7 @@
 void VSyncModulator::setTransactionStart(Scheduler::TransactionStart transactionStart) {
     if (transactionStart == Scheduler::TransactionStart::EARLY) {
         mRemainingEarlyFrameCount = MIN_EARLY_FRAME_COUNT_TRANSACTION;
+        mEarlyTxnStartTime = std::chrono::steady_clock::now();
     }
 
     // An early transaction stays an early transaction.
@@ -64,6 +66,7 @@
 }
 
 void VSyncModulator::onTransactionHandled() {
+    mTxnAppliedTime = std::chrono::steady_clock::now();
     if (mTransactionStart == Scheduler::TransactionStart::NORMAL) return;
     mTransactionStart = Scheduler::TransactionStart::NORMAL;
     updateOffsets();
@@ -87,9 +90,16 @@
 
 void VSyncModulator::onRefreshed(bool usedRenderEngine) {
     bool updateOffsetsNeeded = false;
-    if (mRemainingEarlyFrameCount > 0) {
-        mRemainingEarlyFrameCount--;
-        updateOffsetsNeeded = true;
+
+    // Apply a 1ms margin to account for potential data races
+    // This might make us stay in early offsets for one
+    // additional frame but it's better to be conservative here.
+    static const constexpr std::chrono::nanoseconds kMargin = 1ms;
+    if ((mEarlyTxnStartTime.load() + kMargin) < mTxnAppliedTime.load()) {
+        if (mRemainingEarlyFrameCount > 0) {
+            mRemainingEarlyFrameCount--;
+            updateOffsetsNeeded = true;
+        }
     }
     if (usedRenderEngine) {
         mRemainingRenderEngineUsageCount = MIN_EARLY_GL_FRAME_COUNT_TRANSACTION;
diff --git a/services/surfaceflinger/Scheduler/VSyncModulator.h b/services/surfaceflinger/Scheduler/VSyncModulator.h
index 704a5d5..d777ef9 100644
--- a/services/surfaceflinger/Scheduler/VSyncModulator.h
+++ b/services/surfaceflinger/Scheduler/VSyncModulator.h
@@ -16,6 +16,7 @@
 
 #pragma once
 
+#include <chrono>
 #include <mutex>
 
 #include "Scheduler.h"
@@ -110,6 +111,8 @@
     std::atomic<bool> mRefreshRateChangePending = false;
     std::atomic<int> mRemainingEarlyFrameCount = 0;
     std::atomic<int> mRemainingRenderEngineUsageCount = 0;
+    std::atomic<std::chrono::steady_clock::time_point> mEarlyTxnStartTime = {};
+    std::atomic<std::chrono::steady_clock::time_point> mTxnAppliedTime = {};
 
     bool mTraceDetailedInfo = false;
 };