Early wake-up for transitions (1/2)

On some devices it's very likely that we fall into GL comp during
app transitions. However, SF offsets are chosen in a way such that
the time to finish a frame is just too tight to be completely jank
free when hitting GL composition in SurfaceFlinger. Thus, we
introduce the concept of a separate early offset, and wakeup
SurfaceFlinger at that time if we think that hitting GL comp is
likely, or we already hit GL comp in the last frame.

Test: Open app, check vsync offsets in systrace
Test: Open many dialogs/apps to fall into GPU comp.
Bug: 75985430
Change-Id: Ie17e30c4575359fa11bb8912f68dcafe3e569ddb
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 18b2f68..50495ec 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -296,6 +296,12 @@
     auto listSize = property_get_int32("debug.sf.max_igbp_list_size", int32_t(defaultListSize));
     mMaxGraphicBufferProducerListSize = (listSize > 0) ? size_t(listSize) : defaultListSize;
 
+    property_get("debug.sf.early_phase_offset_ns", value, "0");
+    const int earlyWakeupOffsetOffsetNs = atoi(value);
+    ALOGI_IF(earlyWakeupOffsetOffsetNs != 0, "Enabling separate early offset");
+    mVsyncModulator.setPhaseOffsets(sfVsyncPhaseOffsetNs - earlyWakeupOffsetOffsetNs,
+            sfVsyncPhaseOffsetNs);
+
     // We should be reading 'persist.sys.sf.color_saturation' here
     // but since /data may be encrypted, we need to wait until after vold
     // comes online to attempt to read the property. The property is
@@ -522,19 +528,10 @@
             return;
         }
 
-        // Remove the listener with the old offset
-        status_t err = mDispSync->removeEventListener(
-                static_cast<DispSync::Callback*>(this));
+        status_t err = mDispSync->changePhaseOffset(static_cast<DispSync::Callback*>(this),
+                mPhaseOffset);
         if (err != NO_ERROR) {
-            ALOGE("error unregistering vsync callback: %s (%d)",
-                    strerror(-err), err);
-        }
-
-        // Add a listener with the new offset
-        err = mDispSync->addEventListener(mName, mPhaseOffset,
-                static_cast<DispSync::Callback*>(this));
-        if (err != NO_ERROR) {
-            ALOGE("error registering vsync callback: %s (%d)",
+            ALOGE("error changing vsync offset: %s (%d)",
                     strerror(-err), err);
         }
     }
@@ -623,6 +620,7 @@
     mSFEventThread = std::make_unique<impl::EventThread>(mSfEventThreadSource.get(), *this, true,
                                                          "sfEventThread");
     mEventQueue->setEventThread(mSFEventThread.get());
+    mVsyncModulator.setEventThread(mSFEventThread.get());
 
     // Get a RenderEngine for the given display / config (can't fail)
     getBE().mRenderEngine =
@@ -1498,6 +1496,7 @@
         mHadClientComposition = mHadClientComposition ||
                 getBE().mHwc->hasClientComposition(displayDevice->getHwcDisplayId());
     }
+    mVsyncModulator.setLastFrameUsedRenderEngine(mHadClientComposition);
 
     mLayersWithQueuedFrames.clear();
 }
@@ -2122,6 +2121,7 @@
     // with mStateLock held to guarantee that mCurrentState won't change
     // until the transaction is committed.
 
+    mVsyncModulator.setTransactionStart(VSyncModulator::TransactionStart::NORMAL);
     transactionFlags = getTransactionFlags(eTransactionMask);
     handleTransactionLocked(transactionFlags);
 
@@ -3070,7 +3070,13 @@
 }
 
 uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags) {
+    return setTransactionFlags(flags, VSyncModulator::TransactionStart::NORMAL);
+}
+
+uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags,
+        VSyncModulator::TransactionStart transactionStart) {
     uint32_t old = android_atomic_or(flags, &mTransactionFlags);
+    mVsyncModulator.setTransactionStart(transactionStart);
     if ((old & flags)==0) { // wake the server up
         signalTransaction();
     }
@@ -3159,7 +3165,10 @@
         }
 
         // this triggers the transaction
-        setTransactionFlags(transactionFlags);
+        const auto start = (flags & eEarlyWakeup)
+                ? VSyncModulator::TransactionStart::EARLY
+                : VSyncModulator::TransactionStart::NORMAL;
+        setTransactionFlags(transactionFlags, start);
 
         // if this is a synchronous transaction, wait for it to take effect
         // before returning.
@@ -4099,9 +4108,9 @@
     colorizer.bold(result);
     result.append("DispSync configuration: ");
     colorizer.reset(result);
-    result.appendFormat("app phase %" PRId64 " ns, sf phase %" PRId64 " ns, "
-            "present offset %" PRId64 " ns (refresh %" PRId64 " ns)",
-        vsyncPhaseOffsetNs, sfVsyncPhaseOffsetNs,
+    result.appendFormat("app phase %" PRId64 " ns, sf phase %" PRId64 " ns, early sf phase %" PRId64
+        " ns, present offset %" PRId64 " ns (refresh %" PRId64 " ns)",
+        vsyncPhaseOffsetNs, sfVsyncPhaseOffsetNs, mVsyncModulator.getEarlyPhaseOffset(),
         dispSyncPresentTimeOffset, activeConfig->getVsyncPeriod());
     result.append("\n");