Merge "Fix early firing when adding event listeners" into qt-dev
diff --git a/libs/gui/include/gui/SurfaceControl.h b/libs/gui/include/gui/SurfaceControl.h
index 23bfc02..55efcbf 100644
--- a/libs/gui/include/gui/SurfaceControl.h
+++ b/libs/gui/include/gui/SurfaceControl.h
@@ -84,9 +84,6 @@
     
     explicit SurfaceControl(const sp<SurfaceControl>& other);
 
-    SurfaceControl(const sp<SurfaceComposerClient>& client, const sp<IBinder>& handle,
-                   const sp<IGraphicBufferProducer>& gbp, bool owned);
-
 private:
     // can't be copied
     SurfaceControl& operator = (SurfaceControl& rhs);
@@ -95,6 +92,12 @@
     friend class SurfaceComposerClient;
     friend class Surface;
 
+    SurfaceControl(
+            const sp<SurfaceComposerClient>& client,
+            const sp<IBinder>& handle,
+            const sp<IGraphicBufferProducer>& gbp,
+            bool owned);
+
     ~SurfaceControl();
 
     sp<Surface> generateSurfaceLocked() const;
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index 12947b2..226d58f 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -339,53 +339,6 @@
         if ((cnx->major == 1) && (cnx->minor == 5)) {
             mVersionString = sVersionString15;
             cnx->driverVersion = EGL_MAKE_VERSION(1, 5, 0);
-        } else if ((cnx->major == 1) && (cnx->minor == 4)) {
-            /* Querying extension strings for type Client */
-            std::string typesExtString;
-            static const char* clientExtensions =
-                    cnx->egl.eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
-            if (clientExtensions != nullptr && strlen(clientExtensions) > 0) {
-                typesExtString.append(clientExtensions);
-                typesExtString.append(" ");
-            }
-
-            /* Adding extension strings for type Display */
-            typesExtString.append(disp.queryString.extensions);
-            mVersionString = sVersionString14;
-            // Extensions needed for an EGL 1.4 implementation to be
-            // able to support EGL 1.5 functionality
-            std::vector<const char*> egl15extensions = {
-                    "EGL_EXT_client_extensions",
-                    // "EGL_EXT_platform_base",  // implemented by EGL runtime
-                    "EGL_KHR_image_base",
-                    "EGL_KHR_fence_sync",
-                    "EGL_KHR_wait_sync",
-                    "EGL_KHR_create_context",
-                    "EGL_EXT_create_context_robustness",
-                    "EGL_KHR_gl_colorspace",
-                    "EGL_ANDROID_native_fence_sync",
-            };
-            bool extensionsFound = true;
-            for (const auto& name : egl15extensions) {
-                extensionsFound &= findExtension(typesExtString.c_str(), name);
-                ALOGV("Extension %s: %s", name,
-                      findExtension(typesExtString.c_str(), name) ? "Found" : "Missing");
-            }
-            // NOTE: From the spec:
-            // Creation of fence sync objects requires support from the bound
-            // client API, and will not succeed unless the client API satisfies:
-            // client API is OpenGL ES, and either the OpenGL ES version is 3.0
-            // or greater, or the GL_OES_EGL_sync extension is supported.
-            // We don't have a way to check the GL_EXTENSIONS string at this
-            // point in the code, assume that GL_OES_EGL_sync is supported
-            // because EGL_KHR_fence_sync is supported (as verified above).
-            if (extensionsFound) {
-                // Have everything needed to emulate EGL 1.5 so report EGL 1.5
-                // to the application.
-                mVersionString = sVersionString15;
-                cnx->major = 1;
-                cnx->minor = 5;
-            }
         }
         if (mVersionString.empty()) {
             ALOGW("Unexpected driver version: %d.%d, want 1.4 or 1.5", cnx->major, cnx->minor);
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index a6ed75f..6570704 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -579,10 +579,9 @@
         }
 
         if (info.batchParams.indexOfKey(ident) >= 0) {
-          if (info.numActiveClients() == 1) {
-              // This is the first connection, we need to activate the underlying h/w sensor.
-              actuateHardware = true;
-          }
+            if (info.numActiveClients() > 0 && !info.isActive) {
+                actuateHardware = true;
+            }
         } else {
             // Log error. Every activate call should be preceded by a batch() call.
             ALOGE("\t >>>ERROR: activate called without batch");
@@ -631,6 +630,11 @@
         if (err != NO_ERROR && enabled) {
             // Failure when enabling the sensor. Clean up on failure.
             info.removeBatchParamsForIdent(ident);
+        } else {
+            // Update the isActive flag if there is no error. If there is an error when disabling a
+            // sensor, still set the flag to false since the batch parameters have already been
+            // removed. This ensures that everything remains in-sync.
+            info.isActive = enabled;
         }
     }
 
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
index 71b918f..e8685c2 100644
--- a/services/sensorservice/SensorDevice.h
+++ b/services/sensorservice/SensorDevice.h
@@ -165,6 +165,9 @@
         // requested by the client.
         KeyedVector<void*, BatchParams> batchParams;
 
+        // Flag to track if the sensor is active
+        bool isActive = false;
+
         // Sets batch parameters for this ident. Returns error if this ident is not already present
         // in the KeyedVector above.
         status_t setBatchParamsForIdent(void* ident, int flags, int64_t samplingPeriodNs,
diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp
index 508be13..e54b460 100644
--- a/services/surfaceflinger/Client.cpp
+++ b/services/surfaceflinger/Client.cpp
@@ -76,9 +76,18 @@
                                uint32_t flags, const sp<IBinder>& parentHandle,
                                LayerMetadata metadata, sp<IBinder>* handle,
                                sp<IGraphicBufferProducer>* gbp) {
+    sp<Layer> parent = nullptr;
+    if (parentHandle != nullptr) {
+        auto layerHandle = reinterpret_cast<Layer::Handle*>(parentHandle.get());
+        parent = layerHandle->owner.promote();
+        if (parent == nullptr) {
+            return NAME_NOT_FOUND;
+        }
+    }
+
     // We rely on createLayer to check permissions.
     return mFlinger->createLayer(name, this, w, h, format, flags, std::move(metadata), handle, gbp,
-                                 parentHandle);
+                                 &parent);
 }
 
 status_t Client::createWithSurfaceParent(const String8& name, uint32_t w, uint32_t h,
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 0211df9..2bbac72 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -130,6 +130,7 @@
     }
 
     mFrameTracker.logAndResetStats(mName);
+
     mFlinger->onLayerDestroyed();
 }
 
diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp
index 240c84e..e70bfe4 100644
--- a/services/surfaceflinger/RefreshRateOverlay.cpp
+++ b/services/surfaceflinger/RefreshRateOverlay.cpp
@@ -31,9 +31,9 @@
     const status_t ret =
             mFlinger.createLayer(String8("RefreshRateOverlay"), mClient, 0, 0,
                                  PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eFXSurfaceColor,
-                                 LayerMetadata(), &mIBinder, &mGbp, nullptr);
+                                 LayerMetadata(), &mIBinder, &mGbp, &mLayer);
     if (ret) {
-        ALOGE("failed to create color layer");
+        ALOGE("failed to color layer");
         return false;
     }
 
diff --git a/services/surfaceflinger/Scheduler/DispSync.cpp b/services/surfaceflinger/Scheduler/DispSync.cpp
index 5aab616..871f556 100644
--- a/services/surfaceflinger/Scheduler/DispSync.cpp
+++ b/services/surfaceflinger/Scheduler/DispSync.cpp
@@ -210,8 +210,7 @@
             const nsecs_t baseTime = now - mReferenceTime;
             const nsecs_t numPeriodsSinceReference = baseTime / mPeriod;
             const nsecs_t predictedReference = mReferenceTime + numPeriodsSinceReference * mPeriod;
-            const nsecs_t phaseCorrection = mPhase + listener.mPhase;
-            listener.mLastEventTime = predictedReference + phaseCorrection;
+            listener.mLastEventTime = predictedReference + mPhase + listener.mPhase;
             // If we're very close in time to the predicted last event time,
             // and we're not very close to the next predicted last event time
             // then we need to back up the last event time so that we can
@@ -282,7 +281,6 @@
                 return NO_ERROR;
             }
         }
-
         return BAD_VALUE;
     }
 
@@ -528,21 +526,40 @@
     mNumResyncSamples = 0;
 }
 
-bool DispSync::addResyncSample(nsecs_t timestamp) {
+bool DispSync::addResyncSample(nsecs_t timestamp, bool* periodChanged) {
     Mutex::Autolock lock(mMutex);
 
     ALOGV("[%s] addResyncSample(%" PRId64 ")", mName, ns2us(timestamp));
 
-    size_t idx = (mFirstResyncSample + mNumResyncSamples) % MAX_RESYNC_SAMPLES;
+    *periodChanged = false;
+    const size_t idx = (mFirstResyncSample + mNumResyncSamples) % MAX_RESYNC_SAMPLES;
     mResyncSamples[idx] = timestamp;
     if (mNumResyncSamples == 0) {
         mPhase = 0;
-        mReferenceTime = timestamp;
         ALOGV("[%s] First resync sample: mPeriod = %" PRId64 ", mPhase = 0, "
               "mReferenceTime = %" PRId64,
-              mName, ns2us(mPeriod), ns2us(mReferenceTime));
-        mThread->updateModel(mPeriod, mPhase, mReferenceTime);
+              mName, ns2us(mPeriod), ns2us(timestamp));
+    } else if (mPendingPeriod > 0) {
+        // mNumResyncSamples > 0, so priorIdx won't overflow
+        const size_t priorIdx = (mFirstResyncSample + mNumResyncSamples - 1) % MAX_RESYNC_SAMPLES;
+        const nsecs_t lastTimestamp = mResyncSamples[priorIdx];
+
+        const nsecs_t observedVsync = std::abs(timestamp - lastTimestamp);
+        if (std::abs(observedVsync - mPendingPeriod) < std::abs(observedVsync - mPeriod)) {
+            // Observed vsync is closer to the pending period, so reset the
+            // model and flush the pending period.
+            resetLocked();
+            mPeriod = mPendingPeriod;
+            mPendingPeriod = 0;
+            if (mTraceDetailedInfo) {
+                ATRACE_INT("DispSync:PendingPeriod", mPendingPeriod);
+            }
+            *periodChanged = true;
+        }
     }
+    // Always update the reference time with the most recent timestamp.
+    mReferenceTime = timestamp;
+    mThread->updateModel(mPeriod, mPhase, mReferenceTime);
 
     if (mNumResyncSamples < MAX_RESYNC_SAMPLES) {
         mNumResyncSamples++;
@@ -565,7 +582,7 @@
 
     // Check against kErrorThreshold / 2 to add some hysteresis before having to
     // resync again
-    bool modelLocked = mModelUpdated && mError < (kErrorThreshold / 2);
+    bool modelLocked = mModelUpdated && mError < (kErrorThreshold / 2) && mPendingPeriod == 0;
     ALOGV("[%s] addResyncSample returning %s", mName, modelLocked ? "locked" : "unlocked");
     return !modelLocked;
 }
@@ -597,9 +614,10 @@
 
 void DispSync::setPeriod(nsecs_t period) {
     Mutex::Autolock lock(mMutex);
-    mPeriod = period;
-    mPhase = 0;
-    mThread->updateModel(mPeriod, mPhase, mReferenceTime);
+    if (mTraceDetailedInfo) {
+        ATRACE_INT("DispSync:PendingPeriod", period);
+    }
+    mPendingPeriod = period;
 }
 
 nsecs_t DispSync::getPeriod() {
diff --git a/services/surfaceflinger/Scheduler/DispSync.h b/services/surfaceflinger/Scheduler/DispSync.h
index de2b874..8f8b8e7 100644
--- a/services/surfaceflinger/Scheduler/DispSync.h
+++ b/services/surfaceflinger/Scheduler/DispSync.h
@@ -49,7 +49,7 @@
     virtual void reset() = 0;
     virtual bool addPresentFence(const std::shared_ptr<FenceTime>&) = 0;
     virtual void beginResync() = 0;
-    virtual bool addResyncSample(nsecs_t timestamp) = 0;
+    virtual bool addResyncSample(nsecs_t timestamp, bool* periodChanged) = 0;
     virtual void endResync() = 0;
     virtual void setPeriod(nsecs_t period) = 0;
     virtual nsecs_t getPeriod() = 0;
@@ -119,7 +119,13 @@
     // addPresentFence returns true indicating that the model has drifted away
     // from the hardware vsync events.
     void beginResync() override;
-    bool addResyncSample(nsecs_t timestamp) override;
+    // Adds a vsync sample to the dispsync model. The timestamp is the time
+    // of the vsync event that fired. periodChanged will return true if the
+    // vsync period was detected to have changed to mPendingPeriod.
+    //
+    // This method will return true if more vsync samples are needed to lock
+    // down the DispSync model, and false otherwise.
+    bool addResyncSample(nsecs_t timestamp, bool* periodChanged) override;
     void endResync() override;
 
     // The setPeriod method sets the vsync event model's period to a specific
@@ -199,6 +205,12 @@
     // nanoseconds.
     nsecs_t mPeriod;
 
+    // mPendingPeriod is the proposed period change in nanoseconds.
+    // If mPendingPeriod differs from mPeriod and is nonzero, it will
+    // be flushed to mPeriod when we detect that the hardware switched
+    // vsync frequency.
+    nsecs_t mPendingPeriod = 0;
+
     // mPhase is the phase offset of the modeled vsync events.  It is the
     // number of nanoseconds from time 0 to the first vsync event.
     nsecs_t mPhase;
diff --git a/services/surfaceflinger/Scheduler/DispSyncSource.cpp b/services/surfaceflinger/Scheduler/DispSyncSource.cpp
index 6e89648..00948ae 100644
--- a/services/surfaceflinger/Scheduler/DispSyncSource.cpp
+++ b/services/surfaceflinger/Scheduler/DispSyncSource.cpp
@@ -87,19 +87,7 @@
     }
 }
 
-void DispSyncSource::pauseVsyncCallback(bool pause) {
-    std::lock_guard lock(mVsyncMutex);
-    mCallbackPaused = pause;
-}
-
 void DispSyncSource::onDispSyncEvent(nsecs_t when) {
-    {
-        std::lock_guard lock(mVsyncMutex);
-        if (mCallbackPaused) {
-            return;
-        }
-    }
-
     VSyncSource::Callback* callback;
     {
         std::lock_guard lock(mCallbackMutex);
diff --git a/services/surfaceflinger/Scheduler/DispSyncSource.h b/services/surfaceflinger/Scheduler/DispSyncSource.h
index 2858678..4759699 100644
--- a/services/surfaceflinger/Scheduler/DispSyncSource.h
+++ b/services/surfaceflinger/Scheduler/DispSyncSource.h
@@ -33,7 +33,6 @@
     void setVSyncEnabled(bool enable) override;
     void setCallback(VSyncSource::Callback* callback) override;
     void setPhaseOffset(nsecs_t phaseOffset) override;
-    void pauseVsyncCallback(bool pause) override;
 
 private:
     // The following method is the implementation of the DispSync::Callback.
@@ -55,7 +54,6 @@
     std::mutex mVsyncMutex;
     nsecs_t mPhaseOffset GUARDED_BY(mVsyncMutex);
     bool mEnabled GUARDED_BY(mVsyncMutex) = false;
-    bool mCallbackPaused GUARDED_BY(mVsyncMutex) = false;
 };
 
 } // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index a760079..a6c7e6c 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -210,12 +210,6 @@
     mVSyncSource->setPhaseOffset(phaseOffset);
 }
 
-void EventThread::pauseVsyncCallback(bool pause) {
-    std::lock_guard<std::mutex> lock(mMutex);
-    ATRACE_INT("vsyncPaused", pause);
-    mVSyncSource->pauseVsyncCallback(pause);
-}
-
 sp<EventThreadConnection> EventThread::createEventConnection(
         ResyncCallback resyncCallback, ResetIdleTimerCallback resetIdleTimerCallback) const {
     return new EventThreadConnection(const_cast<EventThread*>(this), std::move(resyncCallback),
diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h
index 67e6de9..7107d63 100644
--- a/services/surfaceflinger/Scheduler/EventThread.h
+++ b/services/surfaceflinger/Scheduler/EventThread.h
@@ -66,9 +66,6 @@
     virtual void setVSyncEnabled(bool enable) = 0;
     virtual void setCallback(Callback* callback) = 0;
     virtual void setPhaseOffset(nsecs_t phaseOffset) = 0;
-
-    // pause/resume vsync callback generation
-    virtual void pauseVsyncCallback(bool pause) = 0;
 };
 
 class EventThreadConnection : public BnDisplayEventConnection {
@@ -125,8 +122,6 @@
     // Requests the next vsync. If resetIdleTimer is set to true, it resets the idle timer.
     virtual void requestNextVsync(const sp<EventThreadConnection>& connection,
                                   bool resetIdleTimer) = 0;
-
-    virtual void pauseVsyncCallback(bool pause) = 0;
 };
 
 namespace impl {
@@ -162,8 +157,6 @@
 
     void setPhaseOffset(nsecs_t phaseOffset) override;
 
-    void pauseVsyncCallback(bool pause) override;
-
 private:
     friend EventThreadTest;
 
diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.h b/services/surfaceflinger/Scheduler/PhaseOffsets.h
index cbcaade..a85660a 100644
--- a/services/surfaceflinger/Scheduler/PhaseOffsets.h
+++ b/services/surfaceflinger/Scheduler/PhaseOffsets.h
@@ -68,8 +68,8 @@
     void dump(std::string& result) const override;
 
 private:
-    Offsets getmDefaultRefreshRateOffsets() { return mDefaultRefreshRateOffsets; }
-    Offsets getmHighRefreshRateOffsets() { return mHighRefreshRateOffsets; }
+    Offsets getDefaultRefreshRateOffsets() { return mDefaultRefreshRateOffsets; }
+    Offsets getHighRefreshRateOffsets() { return mHighRefreshRateOffsets; }
 
     std::atomic<RefreshRateConfigs::RefreshRateType> mRefreshRateType =
             RefreshRateConfigs::RefreshRateType::DEFAULT;
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index b1c39ef..1b154a4 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -178,12 +178,6 @@
     mConnections[handle->id]->thread->setPhaseOffset(phaseOffset);
 }
 
-void Scheduler::pauseVsyncCallback(const android::sp<android::Scheduler::ConnectionHandle>& handle,
-                                   bool pause) {
-    RETURN_IF_INVALID();
-    mConnections[handle->id]->thread->pauseVsyncCallback(pause);
-}
-
 void Scheduler::getDisplayStatInfo(DisplayStatInfo* stats) {
     stats->vsyncTime = mPrimaryDispSync->computeNextRefresh(0);
     stats->vsyncPeriod = mPrimaryDispSync->getPeriod();
@@ -255,7 +249,6 @@
 
 void Scheduler::setVsyncPeriod(const nsecs_t period) {
     std::lock_guard<std::mutex> lock(mHWVsyncLock);
-    mPrimaryDispSync->reset();
     mPrimaryDispSync->setPeriod(period);
 
     if (!mPrimaryHWVsyncEnabled) {
@@ -265,12 +258,13 @@
     }
 }
 
-void Scheduler::addResyncSample(const nsecs_t timestamp) {
+void Scheduler::addResyncSample(const nsecs_t timestamp, bool* periodChanged) {
     bool needsHwVsync = false;
+    *periodChanged = false;
     { // Scope for the lock
         std::lock_guard<std::mutex> lock(mHWVsyncLock);
         if (mPrimaryHWVsyncEnabled) {
-            needsHwVsync = mPrimaryDispSync->addResyncSample(timestamp);
+            needsHwVsync = mPrimaryDispSync->addResyncSample(timestamp, periodChanged);
         }
     }
 
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 1318fbb..134dc0b 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -131,9 +131,6 @@
     // Offers ability to modify phase offset in the event thread.
     void setPhaseOffset(const sp<ConnectionHandle>& handle, nsecs_t phaseOffset);
 
-    // pause/resume vsync callback generation to avoid sending vsync callbacks during config switch
-    void pauseVsyncCallback(const sp<ConnectionHandle>& handle, bool pause);
-
     void getDisplayStatInfo(DisplayStatInfo* stats);
 
     void enableHardwareVsync();
@@ -142,7 +139,9 @@
     // Creates a callback for resyncing.
     ResyncCallback makeResyncCallback(GetVsyncPeriod&& getVsyncPeriod);
     void setRefreshSkipCount(int count);
-    void addResyncSample(const nsecs_t timestamp);
+    // Passes a vsync sample to DispSync. periodChange will be true if DipSync
+    // detected that the vsync period changed, and false otherwise.
+    void addResyncSample(const nsecs_t timestamp, bool* periodChanged);
     void addPresentFence(const std::shared_ptr<FenceTime>& fenceTime);
     void setIgnorePresentFences(bool ignore);
     nsecs_t expectedPresentTime();
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;
 };
 
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index bd3f156..3c25564 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -922,11 +922,15 @@
     mDesiredActiveConfig.event = mDesiredActiveConfig.event | prevConfig;
 
     if (!mDesiredActiveConfigChanged) {
-        // This is the first time we set the desired
-        mScheduler->pauseVsyncCallback(mAppConnectionHandle, true);
-
         // This will trigger HWC refresh without resetting the idle timer.
         repaintEverythingForHWC();
+        // Start receiving vsync samples now, so that we can detect a period
+        // switch.
+        mScheduler->resyncToHardwareVsync(true, getVsyncPeriod());
+        mPhaseOffsets->setRefreshRateType(info.type);
+        const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
+        mVsyncModulator.onRefreshRateChangeInitiated();
+        mVsyncModulator.setPhaseOffsets(early, gl, late);
     }
     mDesiredActiveConfigChanged = true;
     ATRACE_INT("DesiredActiveConfigChanged", mDesiredActiveConfigChanged);
@@ -959,6 +963,7 @@
     display->setActiveConfig(mUpcomingActiveConfig.configId);
 
     mScheduler->resyncToHardwareVsync(true, getVsyncPeriod());
+    mPhaseOffsets->setRefreshRateType(mUpcomingActiveConfig.type);
     const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
     mVsyncModulator.setPhaseOffsets(early, gl, late);
     ATRACE_INT("ActiveConfigMode", mUpcomingActiveConfig.configId);
@@ -1000,8 +1005,6 @@
         // display is not valid or we are already in the requested mode
         // on both cases there is nothing left to do
         std::lock_guard<std::mutex> lock(mActiveConfigLock);
-        mScheduler->pauseVsyncCallback(mAppConnectionHandle, false);
-        mDesiredActiveConfig.event = Scheduler::ConfigEvent::None;
         mDesiredActiveConfigChanged = false;
         ATRACE_INT("DesiredActiveConfigChanged", mDesiredActiveConfigChanged);
         return false;
@@ -1012,6 +1015,7 @@
     // Make sure the desired config is still allowed
     if (!isDisplayConfigAllowed(desiredActiveConfig.configId)) {
         std::lock_guard<std::mutex> lock(mActiveConfigLock);
+        mDesiredActiveConfig.event = Scheduler::ConfigEvent::None;
         mDesiredActiveConfig.configId = display->getActiveConfig();
         return false;
     }
@@ -1403,7 +1407,11 @@
         return;
     }
 
-    mScheduler->addResyncSample(timestamp);
+    bool periodChanged = false;
+    mScheduler->addResyncSample(timestamp, &periodChanged);
+    if (periodChanged) {
+        mVsyncModulator.onRefreshRateChangeDetected();
+    }
 }
 
 void SurfaceFlinger::getCompositorTiming(CompositorTiming* compositorTiming) {
@@ -1436,8 +1444,6 @@
         return;
     }
 
-    mPhaseOffsets->setRefreshRateType(refreshRate);
-
     if (desiredConfigId == display->getActiveConfig()) {
         return;
     }
@@ -3393,20 +3399,12 @@
         const sp<IBinder>& handle,
         const sp<IGraphicBufferProducer>& gbc,
         const sp<Layer>& lbc,
-        const sp<IBinder>& parentHandle,
+        const sp<Layer>& parent,
         bool addToCurrentState)
 {
     // add this layer to the current state list
     {
         Mutex::Autolock _l(mStateLock);
-        sp<Layer> parent;
-        if (parentHandle != nullptr) {
-            parent = fromHandle(parentHandle);
-            if (parent == nullptr) {
-                return NAME_NOT_FOUND;
-            }
-        }
-
         if (mNumLayers >= MAX_LAYERS) {
             ALOGE("AddClientLayer failed, mNumLayers (%zu) >= MAX_LAYERS (%zu)", mNumLayers,
                   MAX_LAYERS);
@@ -4015,10 +4013,10 @@
     return flags;
 }
 
-status_t SurfaceFlinger::createLayer(
-        const String8& name, const sp<Client>& client, uint32_t w, uint32_t h, PixelFormat format,
-        uint32_t flags, LayerMetadata metadata, sp<IBinder>* handle,
-        sp<IGraphicBufferProducer>* gbp, const sp<IBinder>& parentHandle) {
+status_t SurfaceFlinger::createLayer(const String8& name, const sp<Client>& client, uint32_t w,
+                                     uint32_t h, PixelFormat format, uint32_t flags,
+                                     LayerMetadata metadata, sp<IBinder>* handle,
+                                     sp<IGraphicBufferProducer>* gbp, sp<Layer>* parent) {
     if (int32_t(w|h) < 0) {
         ALOGE("createLayer() failed, w or h is negative (w=%d, h=%d)",
                 int(w), int(h));
@@ -4083,14 +4081,12 @@
         return result;
     }
 
-    mLayersByLocalBinderToken.emplace((*handle)->localBinder(), layer);
-
     if (primaryDisplayOnly) {
         layer->setPrimaryDisplayOnly();
     }
 
     bool addToCurrentState = callingThreadHasUnscopedSurfaceFlingerAccess();
-    result = addClientLayer(client, *handle, *gbp, layer, parentHandle,
+    result = addClientLayer(client, *handle, *gbp, layer, *parent,
             addToCurrentState);
     if (result != NO_ERROR) {
         return result;
@@ -4208,16 +4204,6 @@
         mCurrentState.layersSortedByZ.remove(layer);
     }
     markLayerPendingRemovalLocked(layer);
-
-    auto it = mLayersByLocalBinderToken.begin();
-    while (it != mLayersByLocalBinderToken.end()) {
-        if (it->second == layer) {
-            it = mLayersByLocalBinderToken.erase(it);
-        } else {
-            it++;
-        }
-    }
-
     layer.clear();
 }
 
@@ -5485,50 +5471,34 @@
         const bool mChildrenOnly;
     };
 
-    int reqWidth = 0;
-    int reqHeight = 0;
-    sp<Layer> parent;
+    auto layerHandle = reinterpret_cast<Layer::Handle*>(layerHandleBinder.get());
+    auto parent = layerHandle->owner.promote();
+
+    if (parent == nullptr || parent->isRemovedFromCurrentState()) {
+        ALOGE("captureLayers called with a removed parent");
+        return NAME_NOT_FOUND;
+    }
+
+    const int uid = IPCThreadState::self()->getCallingUid();
+    const bool forSystem = uid == AID_GRAPHICS || uid == AID_SYSTEM;
+    if (!forSystem && parent->getCurrentState().flags & layer_state_t::eLayerSecure) {
+        ALOGW("Attempting to capture secure layer: PERMISSION_DENIED");
+        return PERMISSION_DENIED;
+    }
+
     Rect crop(sourceCrop);
-    std::unordered_set<sp<Layer>, ISurfaceComposer::SpHash<Layer>> excludeLayers;
+    if (sourceCrop.width() <= 0) {
+        crop.left = 0;
+        crop.right = parent->getBufferSize(parent->getCurrentState()).getWidth();
+    }
 
-    {
-        Mutex::Autolock _l(mStateLock);
+    if (sourceCrop.height() <= 0) {
+        crop.top = 0;
+        crop.bottom = parent->getBufferSize(parent->getCurrentState()).getHeight();
+    }
 
-        parent = fromHandle(layerHandleBinder);
-        if (parent == nullptr || parent->isRemovedFromCurrentState()) {
-            ALOGE("captureLayers called with an invalid or removed parent");
-            return NAME_NOT_FOUND;
-        }
-
-        const int uid = IPCThreadState::self()->getCallingUid();
-        const bool forSystem = uid == AID_GRAPHICS || uid == AID_SYSTEM;
-        if (!forSystem && parent->getCurrentState().flags & layer_state_t::eLayerSecure) {
-            ALOGW("Attempting to capture secure layer: PERMISSION_DENIED");
-            return PERMISSION_DENIED;
-        }
-
-        if (sourceCrop.width() <= 0) {
-            crop.left = 0;
-            crop.right = parent->getBufferSize(parent->getCurrentState()).getWidth();
-        }
-
-        if (sourceCrop.height() <= 0) {
-            crop.top = 0;
-            crop.bottom = parent->getBufferSize(parent->getCurrentState()).getHeight();
-        }
-        reqWidth = crop.width() * frameScale;
-        reqHeight = crop.height() * frameScale;
-
-        for (const auto& handle : excludeHandles) {
-            sp<Layer> excludeLayer = fromHandle(handle);
-            if (excludeLayer != nullptr) {
-                excludeLayers.emplace(excludeLayer);
-            } else {
-                ALOGW("Invalid layer handle passed as excludeLayer to captureLayers");
-                return NAME_NOT_FOUND;
-            }
-        }
-    } // mStateLock
+    int32_t reqWidth = crop.width() * frameScale;
+    int32_t reqHeight = crop.height() * frameScale;
 
     // really small crop or frameScale
     if (reqWidth <= 0) {
@@ -5538,6 +5508,18 @@
         reqHeight = 1;
     }
 
+    std::unordered_set<sp<Layer>, ISurfaceComposer::SpHash<Layer>> excludeLayers;
+    for (const auto& handle : excludeHandles) {
+        BBinder* local = handle->localBinder();
+        if (local != nullptr) {
+            auto layerHandle = reinterpret_cast<Layer::Handle*>(local);
+            excludeLayers.emplace(layerHandle->owner.promote());
+        } else {
+            ALOGW("Invalid layer handle passed as excludeLayer to captureLayers");
+            return NAME_NOT_FOUND;
+        }
+    }
+
     LayerRenderArea renderArea(this, parent, crop, reqWidth, reqHeight, reqDataspace, childrenOnly);
     auto traverseLayers = [parent, childrenOnly,
                            &excludeLayers](const LayerVector::Visitor& visitor) {
@@ -5884,18 +5866,6 @@
     mFlinger->setInputWindowsFinished();
 }
 
-sp<Layer> SurfaceFlinger::fromHandle(const sp<IBinder>& handle) {
-    BBinder *b = handle->localBinder();
-    if (b == nullptr) {
-        return nullptr;
-    }
-    auto it = mLayersByLocalBinderToken.find(b);
-    if (it != mLayersByLocalBinderToken.end()) {
-        return it->second.promote();
-    }
-    return nullptr;
-}
-
 } // namespace android
 
 #if defined(__gl_h_)
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index d8108c5..4c482a1 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -313,8 +313,6 @@
         return mTransactionCompletedThread;
     }
 
-    sp<Layer> fromHandle(const sp<IBinder>& handle) REQUIRES(mStateLock);
-
 private:
     friend class BufferLayer;
     friend class BufferQueueLayer;
@@ -575,10 +573,9 @@
     /* ------------------------------------------------------------------------
      * Layer management
      */
-    status_t createLayer(
-            const String8& name, const sp<Client>& client, uint32_t w, uint32_t h,
-            PixelFormat format, uint32_t flags, LayerMetadata metadata,
-            sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, const sp<IBinder>& parentHandle);
+    status_t createLayer(const String8& name, const sp<Client>& client, uint32_t w, uint32_t h,
+                         PixelFormat format, uint32_t flags, LayerMetadata metadata,
+                         sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* parent);
 
     status_t createBufferQueueLayer(const sp<Client>& client, const String8& name, uint32_t w,
                                     uint32_t h, uint32_t flags, LayerMetadata metadata,
@@ -610,7 +607,7 @@
             const sp<IBinder>& handle,
             const sp<IGraphicBufferProducer>& gbc,
             const sp<Layer>& lbc,
-            const sp<IBinder>& parentHandle,
+            const sp<Layer>& parent,
             bool addToCurrentState);
 
     // Traverse through all the layers and compute and cache its bounds.
@@ -984,9 +981,6 @@
     std::map<wp<IBinder>, sp<DisplayDevice>> mDisplays;
     std::unordered_map<DisplayId, sp<IBinder>> mPhysicalDisplayTokens;
 
-    // protected by mStateLock
-    std::unordered_map<BBinder*, wp<Layer>> mLayersByLocalBinderToken;
-
     // don't use a lock for these, we don't care
     int mDebugRegion = 0;
     bool mDebugDisableHWC = false;
diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp
index d3c87bf..f121a95 100644
--- a/services/surfaceflinger/tests/Android.bp
+++ b/services/surfaceflinger/tests/Android.bp
@@ -19,7 +19,6 @@
     srcs: [
         "BufferGenerator.cpp",
         "Credentials_test.cpp",
-        "InvalidHandles_test.cpp",
         "Stress_test.cpp",
         "SurfaceInterceptor_test.cpp",
         "Transaction_test.cpp",
diff --git a/services/surfaceflinger/tests/InvalidHandles_test.cpp b/services/surfaceflinger/tests/InvalidHandles_test.cpp
deleted file mode 100644
index 42d1f5a..0000000
--- a/services/surfaceflinger/tests/InvalidHandles_test.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <binder/Binder.h>
-
-#include <gtest/gtest.h>
-
-#include <gui/ISurfaceComposer.h>
-#include <gui/SurfaceComposerClient.h>
-#include <private/gui/ComposerService.h>
-#include <ui/Rect.h>
-
-namespace android {
-namespace {
-
-class NotALayer : public BBinder {};
-
-/**
- * For all of these tests we make a SurfaceControl with an invalid layer handle
- * and verify we aren't able to trick SurfaceFlinger.
- */
-class InvalidHandleTest : public ::testing::Test {
-protected:
-    sp<SurfaceComposerClient> mScc;
-    sp<SurfaceControl> mNotSc;
-    void SetUp() override {
-        mScc = new SurfaceComposerClient;
-        ASSERT_EQ(NO_ERROR, mScc->initCheck());
-        mNotSc = makeNotSurfaceControl();
-    }
-
-    sp<SurfaceControl> makeNotSurfaceControl() {
-        return new SurfaceControl(mScc, new NotALayer(), nullptr, true);
-    }
-};
-
-TEST_F(InvalidHandleTest, createSurfaceInvalidHandle) {
-    auto notSc = makeNotSurfaceControl();
-    ASSERT_EQ(nullptr,
-              mScc->createSurface(String8("lolcats"), 19, 47, PIXEL_FORMAT_RGBA_8888, 0,
-                                  notSc.get())
-                      .get());
-}
-
-TEST_F(InvalidHandleTest, captureLayersInvalidHandle) {
-    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
-    sp<GraphicBuffer> outBuffer;
-
-    ASSERT_EQ(NAME_NOT_FOUND,
-              sf->captureLayers(mNotSc->getHandle(), &outBuffer, Rect::EMPTY_RECT, 1.0f));
-}
-
-} // namespace
-} // namespace android
diff --git a/services/surfaceflinger/tests/SurfaceFlinger_test.filter b/services/surfaceflinger/tests/SurfaceFlinger_test.filter
index a8d09ea..be862c9 100644
--- a/services/surfaceflinger/tests/SurfaceFlinger_test.filter
+++ b/services/surfaceflinger/tests/SurfaceFlinger_test.filter
@@ -1,5 +1,5 @@
 {
         "presubmit": {
-            "filter": "CredentialsTest.*:SurfaceFlingerStress.*:SurfaceInterceptorTest.*:LayerTransactionTest.*:LayerTypeTransactionTest.*:LayerUpdateTest.*:GeometryLatchingTest.*:CropLatchingTest.*:ChildLayerTest.*:ScreenCaptureTest.*:ScreenCaptureChildOnlyTest.*:DereferenceSurfaceControlTest.*:BoundlessLayerTest.*:MultiDisplayLayerBoundsTest.*:InvalidHandleTest.*"
+            "filter": "CredentialsTest.*:SurfaceFlingerStress.*:SurfaceInterceptorTest.*:LayerTransactionTest.*:LayerTypeTransactionTest.*:LayerUpdateTest.*:GeometryLatchingTest.*:CropLatchingTest.*:ChildLayerTest.*:ScreenCaptureTest.*:ScreenCaptureChildOnlyTest.*:DereferenceSurfaceControlTest.*:BoundlessLayerTest.*:MultiDisplayLayerBoundsTest.*"
         }
 }
diff --git a/services/surfaceflinger/tests/unittests/DispSyncSourceTest.cpp b/services/surfaceflinger/tests/unittests/DispSyncSourceTest.cpp
index 92bdebd..2e705da 100644
--- a/services/surfaceflinger/tests/unittests/DispSyncSourceTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DispSyncSourceTest.cpp
@@ -142,23 +142,5 @@
     }
 }
 
-TEST_F(DispSyncSourceTest, pauseCallbacks) {
-    createDispSyncSource();
-    EXPECT_TRUE(mDispSyncSource);
-
-    mDispSyncSource->setVSyncEnabled(true);
-    EXPECT_EQ(mDispSync->getCallbackPhase(), mPhaseOffset.count());
-    mDispSync->triggerCallback();
-    EXPECT_TRUE(mVSyncEventCallRecorder.waitForCall().has_value());
-
-    mDispSyncSource->pauseVsyncCallback(true);
-    mDispSync->triggerCallback();
-    EXPECT_FALSE(mVSyncEventCallRecorder.waitForUnexpectedCall().has_value());
-
-    mDispSyncSource->pauseVsyncCallback(false);
-    mDispSync->triggerCallback();
-    EXPECT_TRUE(mVSyncEventCallRecorder.waitForUnexpectedCall().has_value());
-}
-
 } // namespace
 } // namespace android
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index d83f1bd..a13b888 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -2830,7 +2830,6 @@
 
 struct DispSyncIsSupportedVariant {
     static void setupBeginResyncCallExpectations(DisplayTransactionTest* test) {
-        EXPECT_CALL(*test->mPrimaryDispSync, reset()).Times(1);
         EXPECT_CALL(*test->mPrimaryDispSync, setPeriod(DEFAULT_REFRESH_RATE)).Times(1);
         EXPECT_CALL(*test->mPrimaryDispSync, beginResync()).Times(1);
     }
diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
index 249c78f..83a92c8 100644
--- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
+++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
@@ -73,7 +73,6 @@
 
     void expectVSyncSetEnabledCallReceived(bool expectedState);
     void expectVSyncSetPhaseOffsetCallReceived(nsecs_t expectedPhaseOffset);
-    void expectVSyncPauseVsyncCallbackCallReceived(bool expectedPause);
     VSyncSource::Callback* expectVSyncSetCallbackCallReceived();
     void expectInterceptCallReceived(nsecs_t expectedTimestamp);
     void expectVsyncEventReceivedByConnection(const char* name,
@@ -88,7 +87,6 @@
     AsyncCallRecorder<void (*)(bool)> mVSyncSetEnabledCallRecorder;
     AsyncCallRecorder<void (*)(VSyncSource::Callback*)> mVSyncSetCallbackCallRecorder;
     AsyncCallRecorder<void (*)(nsecs_t)> mVSyncSetPhaseOffsetCallRecorder;
-    AsyncCallRecorder<void (*)(bool)> mVSyncPauseVsyncCallbackCallRecorder;
     AsyncCallRecorder<void (*)()> mResyncCallRecorder;
     AsyncCallRecorder<void (*)()> mResetIdleTimerCallRecorder;
     AsyncCallRecorder<void (*)(nsecs_t)> mInterceptVSyncCallRecorder;
@@ -114,9 +112,6 @@
     EXPECT_CALL(mVSyncSource, setPhaseOffset(_))
             .WillRepeatedly(Invoke(mVSyncSetPhaseOffsetCallRecorder.getInvocable()));
 
-    EXPECT_CALL(mVSyncSource, pauseVsyncCallback(_))
-            .WillRepeatedly(Invoke(mVSyncPauseVsyncCallbackCallRecorder.getInvocable()));
-
     createThread();
     mConnection = createConnection(mConnectionEventCallRecorder);
 
@@ -166,12 +161,6 @@
     EXPECT_EQ(expectedPhaseOffset, std::get<0>(args.value()));
 }
 
-void EventThreadTest::expectVSyncPauseVsyncCallbackCallReceived(bool expectedPause) {
-    auto args = mVSyncPauseVsyncCallbackCallRecorder.waitForCall();
-    ASSERT_TRUE(args.has_value());
-    EXPECT_EQ(expectedPause, std::get<0>(args.value()));
-}
-
 VSyncSource::Callback* EventThreadTest::expectVSyncSetCallbackCallReceived() {
     auto callbackSet = mVSyncSetCallbackCallRecorder.waitForCall();
     return callbackSet.has_value() ? std::get<0>(callbackSet.value()) : nullptr;
@@ -431,16 +420,6 @@
     expectVSyncSetPhaseOffsetCallReceived(321);
 }
 
-TEST_F(EventThreadTest, pauseVsyncCallbackForwardsToVSyncSource) {
-    mThread->pauseVsyncCallback(true);
-    expectVSyncPauseVsyncCallbackCallReceived(true);
-}
-
-TEST_F(EventThreadTest, resumeVsyncCallbackForwardsToVSyncSource) {
-    mThread->pauseVsyncCallback(false);
-    expectVSyncPauseVsyncCallbackCallReceived(false);
-}
-
 TEST_F(EventThreadTest, postHotplugInternalDisconnect) {
     mThread->onHotplugReceived(INTERNAL_DISPLAY_ID, false);
     expectHotplugEventReceivedByConnection(INTERNAL_DISPLAY_ID, false);
diff --git a/services/surfaceflinger/tests/unittests/mock/MockDispSync.h b/services/surfaceflinger/tests/unittests/mock/MockDispSync.h
index afcda5b..12a349d 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockDispSync.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockDispSync.h
@@ -31,7 +31,7 @@
     MOCK_METHOD0(reset, void());
     MOCK_METHOD1(addPresentFence, bool(const std::shared_ptr<FenceTime>&));
     MOCK_METHOD0(beginResync, void());
-    MOCK_METHOD1(addResyncSample, bool(nsecs_t));
+    MOCK_METHOD2(addResyncSample, bool(nsecs_t, bool*));
     MOCK_METHOD0(endResync, void());
     MOCK_METHOD1(setPeriod, void(nsecs_t));
     MOCK_METHOD0(getPeriod, nsecs_t());