Merge "Push existing pending state when deferring transaction" into pi-dev
diff --git a/cmds/installd/otapreopt_chroot.cpp b/cmds/installd/otapreopt_chroot.cpp
index 3ae56db..e90cf3b 100644
--- a/cmds/installd/otapreopt_chroot.cpp
+++ b/cmds/installd/otapreopt_chroot.cpp
@@ -115,7 +115,7 @@
         exit(207);
     }
     {
-      std::string vendor_partition = StringPrintf("/dev/block/bootdevice/by-name/vendor%s",
+      std::string vendor_partition = StringPrintf("/dev/block/by-name/vendor%s",
                                                   arg[2]);
       int vendor_result = mount(vendor_partition.c_str(),
                                 "/postinstall/vendor",
@@ -128,7 +128,7 @@
     // Try to mount the product partition. update_engine doesn't do this for us, but we
     // want it for product APKs. Same notes as vendor above.
     {
-      std::string product_partition = StringPrintf("/dev/block/bootdevice/by-name/product%s",
+      std::string product_partition = StringPrintf("/dev/block/by-name/product%s",
                                                    arg[2]);
       int product_result = mount(product_partition.c_str(),
                                  "/postinstall/product",
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 730bdcd..97edd35 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1549,7 +1549,7 @@
         mHadClientComposition = mHadClientComposition ||
                 getBE().mHwc->hasClientComposition(displayDevice->getHwcDisplayId());
     }
-    mVsyncModulator.setLastFrameUsedRenderEngine(mHadClientComposition);
+    mVsyncModulator.onRefreshed(mHadClientComposition);
 
     mLayersWithQueuedFrames.clear();
 }
diff --git a/services/surfaceflinger/VSyncModulator.h b/services/surfaceflinger/VSyncModulator.h
index 3e5800e..d526313 100644
--- a/services/surfaceflinger/VSyncModulator.h
+++ b/services/surfaceflinger/VSyncModulator.h
@@ -28,6 +28,12 @@
  * Modulates the vsync-offsets depending on current SurfaceFlinger state.
  */
 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;
+
 public:
 
     enum TransactionStart {
@@ -55,6 +61,11 @@
     }
 
     void setTransactionStart(TransactionStart transactionStart) {
+
+        if (transactionStart == TransactionStart::EARLY) {
+            mRemainingEarlyFrameCount = MIN_EARLY_FRAME_COUNT;
+        }
+
         // An early transaction stays an early transaction.
         if (transactionStart == mTransactionStart || mTransactionStart == TransactionStart::EARLY) {
             return;
@@ -69,10 +80,19 @@
         updatePhaseOffsets();
     }
 
-    void setLastFrameUsedRenderEngine(bool re) {
-        if (re == mLastFrameUsedRenderEngine) return;
-        mLastFrameUsedRenderEngine = re;
-        updatePhaseOffsets();
+    void onRefreshed(bool usedRenderEngine) {
+        bool updatePhaseOffsetsNeeded = false;
+        if (mRemainingEarlyFrameCount > 0) {
+            mRemainingEarlyFrameCount--;
+            updatePhaseOffsetsNeeded = true;
+        }
+        if (usedRenderEngine != mLastFrameUsedRenderEngine) {
+            mLastFrameUsedRenderEngine = usedRenderEngine;
+            updatePhaseOffsetsNeeded = true;
+        }
+        if (updatePhaseOffsetsNeeded) {
+            updatePhaseOffsets();
+        }
     }
 
 private:
@@ -82,7 +102,7 @@
         // Do not change phase offsets if disabled.
         if (mEarlyPhaseOffset == mLatePhaseOffset) return;
 
-        if (mTransactionStart == TransactionStart::EARLY || mLastFrameUsedRenderEngine) {
+        if (shouldUseEarlyOffset()) {
             if (mPhaseOffset != mEarlyPhaseOffset) {
                 if (mEventThread) {
                     mEventThread->setPhaseOffset(mEarlyPhaseOffset);
@@ -99,12 +119,18 @@
         }
     }
 
+    bool shouldUseEarlyOffset() {
+        return mTransactionStart == TransactionStart::EARLY || mLastFrameUsedRenderEngine
+                || mRemainingEarlyFrameCount > 0;
+    }
+
     nsecs_t mLatePhaseOffset = 0;
     nsecs_t mEarlyPhaseOffset = 0;
     EventThread* mEventThread = nullptr;
     std::atomic<nsecs_t> mPhaseOffset = 0;
     std::atomic<TransactionStart> mTransactionStart = TransactionStart::NORMAL;
     std::atomic<bool> mLastFrameUsedRenderEngine = false;
+    std::atomic<int> mRemainingEarlyFrameCount = 0;
 };
 
 } // namespace android