Moving DispSync into Scheduler.

This change is part of go/surface-flinger-scheduler.

Test: SF tests pass.
Change-Id: I073a54c2111fa3146af3eb68f3294c3c5c95543c
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index ab9a2f8..06e8a98 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -230,10 +230,13 @@
     LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
                     getProducerStickyTransform() != 0, mName.string(), mOverrideScalingMode,
                     getTransformToDisplayInverse(), mFreezeGeometryUpdates);
+
+    const nsecs_t expectedPresentTime = mFlinger->mUseScheduler
+            ? mFlinger->mScheduler->mPrimaryDispSync->expectedPresentTime()
+            : mFlinger->mPrimaryDispSync->expectedPresentTime();
     status_t updateResult =
-            mConsumer->updateTexImage(&r, mFlinger->mPrimaryDispSync->expectedPresentTime(),
-                                      &mAutoRefresh, &queuedBuffer, mLastFrameNumberReceived,
-                                      releaseFence);
+            mConsumer->updateTexImage(&r, expectedPresentTime, &mAutoRefresh, &queuedBuffer,
+                                      mLastFrameNumberReceived, releaseFence);
     if (updateResult == BufferQueue::PRESENT_LATER) {
         // Producer doesn't want buffer to be displayed yet.  Signal a
         // layer update so we check again at the next opportunity.
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 54e19c7..18a8bb1 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -20,15 +20,25 @@
 #include <cstdint>
 #include <memory>
 
+#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
+#include <android/hardware/configstore/1.1/ISurfaceFlingerConfigs.h>
+#include <android/hardware/configstore/1.2/ISurfaceFlingerConfigs.h>
+#include <configstore/Utils.h>
+
 #include <gui/ISurfaceComposer.h>
+#include <ui/DisplayStatInfo.h>
 
 #include "DispSync.h"
 #include "DispSyncSource.h"
+#include "EventControlThread.h"
 #include "EventThread.h"
 #include "InjectVSyncSource.h"
 
 namespace android {
 
+using namespace android::hardware::configstore;
+using namespace android::hardware::configstore::V1_0;
+
 #define RETURN_VALUE_IF_INVALID(value) \
     if (handle == nullptr || mConnections.count(handle->id) == 0) return value
 #define RETURN_IF_INVALID() \
@@ -36,17 +46,34 @@
 
 std::atomic<int64_t> Scheduler::sNextId = 0;
 
+Scheduler::Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function)
+      : mHasSyncFramework(
+                getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasSyncFramework>(true)),
+        mDispSyncPresentTimeOffset(
+                getInt64<ISurfaceFlingerConfigs,
+                         &ISurfaceFlingerConfigs::presentTimeOffsetFromVSyncNs>(0)),
+        mPrimaryHWVsyncEnabled(false),
+        mHWVsyncAvailable(false) {
+    // Note: We create a local temporary with the real DispSync implementation
+    // type temporarily so we can initialize it with the configured values,
+    // before storing it for more generic use using the interface type.
+    auto primaryDispSync = std::make_unique<impl::DispSync>("SchedulerDispSync");
+    primaryDispSync->init(mHasSyncFramework, mDispSyncPresentTimeOffset);
+    mPrimaryDispSync = std::move(primaryDispSync);
+    mEventControlThread = std::make_unique<impl::EventControlThread>(function);
+}
+
 Scheduler::~Scheduler() = default;
 
 sp<Scheduler::ConnectionHandle> Scheduler::createConnection(
-        const std::string& connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
+        const std::string& connectionName, int64_t phaseOffsetNs,
         impl::EventThread::ResyncWithRateLimitCallback resyncCallback,
         impl::EventThread::InterceptVSyncsCallback interceptCallback) {
     const int64_t id = sNextId++;
     ALOGV("Creating a connection handle with ID: %" PRId64 "\n", id);
 
     std::unique_ptr<EventThread> eventThread =
-            makeEventThread(connectionName, dispSync, phaseOffsetNs, resyncCallback,
+            makeEventThread(connectionName, mPrimaryDispSync.get(), phaseOffsetNs, resyncCallback,
                             interceptCallback);
     auto connection = std::make_unique<Connection>(new ConnectionHandle(id),
                                                    eventThread->createEventConnection(),
@@ -108,4 +135,65 @@
     RETURN_IF_INVALID();
     mConnections[handle->id]->thread->setPhaseOffset(phaseOffset);
 }
+
+void Scheduler::getDisplayStatInfo(DisplayStatInfo* stats) {
+    stats->vsyncTime = mPrimaryDispSync->computeNextRefresh(0);
+    stats->vsyncPeriod = mPrimaryDispSync->getPeriod();
+}
+
+void Scheduler::enableHardwareVsync() {
+    std::lock_guard<std::mutex> lock(mHWVsyncLock);
+    if (!mPrimaryHWVsyncEnabled && mHWVsyncAvailable) {
+        mPrimaryDispSync->beginResync();
+        mEventControlThread->setVsyncEnabled(true);
+        mPrimaryHWVsyncEnabled = true;
+    }
+}
+
+void Scheduler::disableHardwareVsync(bool makeUnavailable) {
+    std::lock_guard<std::mutex> lock(mHWVsyncLock);
+    if (mPrimaryHWVsyncEnabled) {
+        mEventControlThread->setVsyncEnabled(false);
+        mPrimaryDispSync->endResync();
+        mPrimaryHWVsyncEnabled = false;
+    }
+    if (makeUnavailable) {
+        mHWVsyncAvailable = false;
+    }
+}
+
+void Scheduler::setVsyncPeriod(const nsecs_t period) {
+    mPrimaryDispSync->reset();
+    mPrimaryDispSync->setPeriod(period);
+    enableHardwareVsync();
+}
+
+void Scheduler::addResyncSample(const nsecs_t timestamp) {
+    bool needsHwVsync = false;
+    { // Scope for the lock
+        std::lock_guard<std::mutex> lock(mHWVsyncLock);
+        if (mPrimaryHWVsyncEnabled) {
+            needsHwVsync = mPrimaryDispSync->addResyncSample(timestamp);
+        }
+    }
+
+    if (needsHwVsync) {
+        enableHardwareVsync();
+    } else {
+        disableHardwareVsync(false);
+    }
+}
+
+void Scheduler::addPresentFence(const std::shared_ptr<FenceTime>& fenceTime) {
+    if (mPrimaryDispSync->addPresentFence(fenceTime)) {
+        enableHardwareVsync();
+    } else {
+        disableHardwareVsync(false);
+    }
+}
+
+void Scheduler::setIgnorePresentFences(bool ignore) {
+    mPrimaryDispSync->setIgnorePresentFences(ignore);
+}
+
 } // namespace android
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index d7c9651..fdafe58 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -20,13 +20,17 @@
 #include <memory>
 
 #include <gui/ISurfaceComposer.h>
+#include <ui/DisplayStatInfo.h>
 
 #include "DispSync.h"
+#include "EventControlThread.h"
 #include "EventThread.h"
 #include "InjectVSyncSource.h"
 
 namespace android {
 
+class EventControlThread;
+
 class Scheduler {
 public:
     // Enum to indicate whether to start the transaction early, or at vsync time.
@@ -38,7 +42,9 @@
     class ConnectionHandle : public BBinder {
     public:
         ConnectionHandle(int64_t id) : id(id) {}
+
         ~ConnectionHandle() = default;
+
         const int64_t id;
     };
 
@@ -47,6 +53,7 @@
         Connection(sp<ConnectionHandle> handle, sp<BnDisplayEventConnection> eventConnection,
                    std::unique_ptr<EventThread> eventThread)
               : handle(handle), eventConnection(eventConnection), thread(std::move(eventThread)) {}
+
         ~Connection() = default;
 
         sp<ConnectionHandle> handle;
@@ -54,32 +61,48 @@
         const std::unique_ptr<EventThread> thread;
     };
 
-    Scheduler() = default;
+    explicit Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function);
+
     virtual ~Scheduler();
 
     /** Creates an EventThread connection. */
     sp<ConnectionHandle> createConnection(
-            const std::string& connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
+            const std::string& connectionName, int64_t phaseOffsetNs,
             impl::EventThread::ResyncWithRateLimitCallback resyncCallback,
             impl::EventThread::InterceptVSyncsCallback interceptCallback);
+
     sp<IDisplayEventConnection> createDisplayEventConnection(const sp<ConnectionHandle>& handle);
 
     // Getter methods.
     EventThread* getEventThread(const sp<ConnectionHandle>& handle);
+
     sp<BnDisplayEventConnection> getEventConnection(const sp<ConnectionHandle>& handle);
 
     // Should be called when receiving a hotplug event.
     void hotplugReceived(const sp<ConnectionHandle>& handle, EventThread::DisplayType displayType,
                          bool connected);
+
     // Should be called after the screen is turned on.
     void onScreenAcquired(const sp<ConnectionHandle>& handle);
+
     // Should be called before the screen is turned off.
     void onScreenReleased(const sp<ConnectionHandle>& handle);
+
     // Should be called when dumpsys command is received.
     void dump(const sp<ConnectionHandle>& handle, String8& result) const;
+
     // Offers ability to modify phase offset in the event thread.
     void setPhaseOffset(const sp<ConnectionHandle>& handle, nsecs_t phaseOffset);
 
+    void getDisplayStatInfo(DisplayStatInfo* stats);
+
+    void enableHardwareVsync();
+    void disableHardwareVsync(bool makeUnavailable);
+    void setVsyncPeriod(const nsecs_t period);
+    void addResyncSample(const nsecs_t timestamp);
+    void addPresentFence(const std::shared_ptr<FenceTime>& fenceTime);
+    void setIgnorePresentFences(bool ignore);
+
 protected:
     virtual std::unique_ptr<EventThread> makeEventThread(
             const std::string& connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
@@ -87,8 +110,29 @@
             impl::EventThread::InterceptVSyncsCallback interceptCallback);
 
 private:
+    // TODO(b/113612090): Instead of letting BufferQueueLayer to access mDispSync directly, it
+    // should make request to Scheduler to compute next refresh.
+    friend class BufferQueueLayer;
+
+    // If fences from sync Framework are supported.
+    const bool mHasSyncFramework;
+
+    // The offset in nanoseconds to use, when DispSync timestamps present fence
+    // signaling time.
+    const nsecs_t mDispSyncPresentTimeOffset;
+
+    // Each connection has it's own ID. This variable keeps track of the count.
     static std::atomic<int64_t> sNextId;
+
+    // Connections are stored in a map <connection ID, connection> for easy retrieval.
     std::unordered_map<int64_t, std::unique_ptr<Connection>> mConnections;
+
+    std::mutex mHWVsyncLock;
+    bool mPrimaryHWVsyncEnabled GUARDED_BY(mHWVsyncLock);
+    bool mHWVsyncAvailable GUARDED_BY(mHWVsyncLock);
+
+    std::unique_ptr<DispSync> mPrimaryDispSync;
+    std::unique_ptr<EventControlThread> mEventControlThread;
 };
 
 } // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 23281c2..f0723e8 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -584,15 +584,14 @@
 
     // start the EventThread
     if (mUseScheduler) {
-        mScheduler = std::make_unique<Scheduler>();
+        mScheduler = std::make_unique<Scheduler>(
+                [this](bool enabled) { setVsyncEnabled(HWC_DISPLAY_PRIMARY, enabled); });
         mAppConnectionHandle =
-                mScheduler->createConnection("appConnection", mPrimaryDispSync.get(),
-                                             SurfaceFlinger::vsyncPhaseOffsetNs,
+                mScheduler->createConnection("appConnection", SurfaceFlinger::vsyncPhaseOffsetNs,
                                              [this] { resyncWithRateLimit(); },
                                              impl::EventThread::InterceptVSyncsCallback());
         mSfConnectionHandle =
-                mScheduler->createConnection("sfConnection", mPrimaryDispSync.get(),
-                                             SurfaceFlinger::sfVsyncPhaseOffsetNs,
+                mScheduler->createConnection("sfConnection", SurfaceFlinger::sfVsyncPhaseOffsetNs,
                                              [this] { resyncWithRateLimit(); },
                                              [this](nsecs_t timestamp) {
                                                  mInterceptor->saveVSyncEvent(timestamp);
@@ -912,10 +911,13 @@
         return BAD_VALUE;
     }
 
-    // FIXME for now we always return stats for the primary display
-    memset(stats, 0, sizeof(*stats));
-    stats->vsyncTime = mPrimaryDispSync->computeNextRefresh(0);
-    stats->vsyncPeriod = mPrimaryDispSync->getPeriod();
+    // FIXME for now we always return stats for the primary display.
+    if (mUseScheduler) {
+        mScheduler->getDisplayStatInfo(stats);
+    } else {
+        stats->vsyncTime = mPrimaryDispSync->computeNextRefresh(0);
+        stats->vsyncPeriod = mPrimaryDispSync->getPeriod();
+    }
     return NO_ERROR;
 }
 
@@ -1246,13 +1248,17 @@
     const auto activeConfig = getHwComposer().getActiveConfig(displayId);
     const nsecs_t period = activeConfig->getVsyncPeriod();
 
-    mPrimaryDispSync->reset();
-    mPrimaryDispSync->setPeriod(period);
+    if (mUseScheduler) {
+        mScheduler->setVsyncPeriod(period);
+    } else {
+        mPrimaryDispSync->reset();
+        mPrimaryDispSync->setPeriod(period);
 
-    if (!mPrimaryHWVsyncEnabled) {
-        mPrimaryDispSync->beginResync();
-        mEventControlThread->setVsyncEnabled(true);
-        mPrimaryHWVsyncEnabled = true;
+        if (!mPrimaryHWVsyncEnabled) {
+            mPrimaryDispSync->beginResync();
+            mEventControlThread->setVsyncEnabled(true);
+            mPrimaryHWVsyncEnabled = true;
+        }
     }
 }
 
@@ -1300,19 +1306,22 @@
         return;
     }
 
-    bool needsHwVsync = false;
-
-    { // Scope for the lock
-        Mutex::Autolock _l(mHWVsyncLock);
-        if (mPrimaryHWVsyncEnabled) {
-            needsHwVsync = mPrimaryDispSync->addResyncSample(timestamp);
-        }
-    }
-
-    if (needsHwVsync) {
-        enableHardwareVsync();
+    if (mUseScheduler) {
+        mScheduler->addResyncSample(timestamp);
     } else {
-        disableHardwareVsync(false);
+        bool needsHwVsync = false;
+        { // Scope for the lock
+            Mutex::Autolock _l(mHWVsyncLock);
+            if (mPrimaryHWVsyncEnabled) {
+                needsHwVsync = mPrimaryDispSync->addResyncSample(timestamp);
+            }
+        }
+
+        if (needsHwVsync) {
+            enableHardwareVsync();
+        } else {
+            disableHardwareVsync(false);
+        }
     }
 }
 
@@ -1364,7 +1373,11 @@
 
 // Note: it is assumed the caller holds |mStateLock| when this is called
 void SurfaceFlinger::resetDisplayState() {
-    disableHardwareVsync(true);
+    if (mUseScheduler) {
+        mScheduler->disableHardwareVsync(true);
+    } else {
+        disableHardwareVsync(true);
+    }
     // Clear the drawing state so that the logic inside of
     // handleTransactionLocked will fire. It will determine the delta between
     // mCurrentState and mDrawingState and re-apply all changes when we make the
@@ -1432,12 +1445,17 @@
 
     // The present fences returned from vr_hwc are not an accurate
     // representation of vsync times.
-    mPrimaryDispSync->setIgnorePresentFences(getBE().mHwc->isUsingVrComposer() ||
-                                             !hasSyncFramework);
+    if (mUseScheduler) {
+        mScheduler->setIgnorePresentFences(getBE().mHwc->isUsingVrComposer() || !hasSyncFramework);
+    } else {
+        mPrimaryDispSync->setIgnorePresentFences(getBE().mHwc->isUsingVrComposer() ||
+                                                 !hasSyncFramework);
+    }
 
     // Use phase of 0 since phase is not known.
     // Use latency of 0, which will snap to the ideal latency.
-    setCompositorTimingSnapped(0, period, 0);
+    DisplayStatInfo stats{0 /* vsyncTime */, period /* vsyncPeriod */};
+    setCompositorTimingSnapped(stats, 0);
 
     resyncToHardwareVsync(false);
 
@@ -1736,9 +1754,8 @@
     }
 }
 
-void SurfaceFlinger::updateCompositorTiming(
-        nsecs_t vsyncPhase, nsecs_t vsyncInterval, nsecs_t compositeTime,
-        std::shared_ptr<FenceTime>& presentFenceTime) {
+void SurfaceFlinger::updateCompositorTiming(const DisplayStatInfo& stats, nsecs_t compositeTime,
+                                            std::shared_ptr<FenceTime>& presentFenceTime) {
     // Update queue of past composite+present times and determine the
     // most recently known composite to present latency.
     getBE().mCompositePresentTimes.push({compositeTime, presentFenceTime});
@@ -1760,21 +1777,20 @@
         getBE().mCompositePresentTimes.pop();
     }
 
-    setCompositorTimingSnapped(
-            vsyncPhase, vsyncInterval, compositeToPresentLatency);
+    setCompositorTimingSnapped(stats, compositeToPresentLatency);
 }
 
-void SurfaceFlinger::setCompositorTimingSnapped(nsecs_t vsyncPhase,
-        nsecs_t vsyncInterval, nsecs_t compositeToPresentLatency) {
+void SurfaceFlinger::setCompositorTimingSnapped(const DisplayStatInfo& stats,
+                                                nsecs_t compositeToPresentLatency) {
     // Integer division and modulo round toward 0 not -inf, so we need to
     // treat negative and positive offsets differently.
-    nsecs_t idealLatency = (sfVsyncPhaseOffsetNs > 0) ?
-            (vsyncInterval - (sfVsyncPhaseOffsetNs % vsyncInterval)) :
-            ((-sfVsyncPhaseOffsetNs) % vsyncInterval);
+    nsecs_t idealLatency = (sfVsyncPhaseOffsetNs > 0)
+            ? (stats.vsyncPeriod - (sfVsyncPhaseOffsetNs % stats.vsyncPeriod))
+            : ((-sfVsyncPhaseOffsetNs) % stats.vsyncPeriod);
 
     // Just in case sfVsyncPhaseOffsetNs == -vsyncInterval.
     if (idealLatency <= 0) {
-        idealLatency = vsyncInterval;
+        idealLatency = stats.vsyncPeriod;
     }
 
     // Snap the latency to a value that removes scheduling jitter from the
@@ -1783,15 +1799,14 @@
     // something (such as user input) to an accurate diasplay time.
     // Snapping also allows an app to precisely calculate sfVsyncPhaseOffsetNs
     // with (presentLatency % interval).
-    nsecs_t bias = vsyncInterval / 2;
-    int64_t extraVsyncs =
-            (compositeToPresentLatency - idealLatency + bias) / vsyncInterval;
-    nsecs_t snappedCompositeToPresentLatency = (extraVsyncs > 0) ?
-            idealLatency + (extraVsyncs * vsyncInterval) : idealLatency;
+    nsecs_t bias = stats.vsyncPeriod / 2;
+    int64_t extraVsyncs = (compositeToPresentLatency - idealLatency + bias) / stats.vsyncPeriod;
+    nsecs_t snappedCompositeToPresentLatency =
+            (extraVsyncs > 0) ? idealLatency + (extraVsyncs * stats.vsyncPeriod) : idealLatency;
 
     std::lock_guard<std::mutex> lock(getBE().mCompositorTimingLock);
-    getBE().mCompositorTiming.deadline = vsyncPhase - idealLatency;
-    getBE().mCompositorTiming.interval = vsyncInterval;
+    getBE().mCompositorTiming.deadline = stats.vsyncTime - idealLatency;
+    getBE().mCompositorTiming.interval = stats.vsyncPeriod;
     getBE().mCompositorTiming.presentLatency = snappedCompositeToPresentLatency;
 }
 
@@ -1825,14 +1840,18 @@
     auto presentFenceTime = std::make_shared<FenceTime>(mPreviousPresentFence);
     getBE().mDisplayTimeline.push(presentFenceTime);
 
-    nsecs_t vsyncPhase = mPrimaryDispSync->computeNextRefresh(0);
-    nsecs_t vsyncInterval = mPrimaryDispSync->getPeriod();
+    DisplayStatInfo stats;
+    if (mUseScheduler) {
+        mScheduler->getDisplayStatInfo(&stats);
+    } else {
+        stats.vsyncTime = mPrimaryDispSync->computeNextRefresh(0);
+        stats.vsyncPeriod = mPrimaryDispSync->getPeriod();
+    }
 
     // We use the mRefreshStartTime which might be sampled a little later than
     // when we started doing work for this frame, but that should be okay
     // since updateCompositorTiming has snapping logic.
-    updateCompositorTiming(
-        vsyncPhase, vsyncInterval, mRefreshStartTime, presentFenceTime);
+    updateCompositorTiming(stats, mRefreshStartTime, presentFenceTime);
     CompositorTiming compositorTiming;
     {
         std::lock_guard<std::mutex> lock(getBE().mCompositorTimingLock);
@@ -1849,16 +1868,24 @@
     });
 
     if (presentFenceTime->isValid()) {
-        if (mPrimaryDispSync->addPresentFence(presentFenceTime)) {
-            enableHardwareVsync();
+        if (mUseScheduler) {
+            mScheduler->addPresentFence(presentFenceTime);
         } else {
-            disableHardwareVsync(false);
+            if (mPrimaryDispSync->addPresentFence(presentFenceTime)) {
+                enableHardwareVsync();
+            } else {
+                disableHardwareVsync(false);
+            }
         }
     }
 
     if (!hasSyncFramework) {
         if (display && getHwComposer().isConnected(display->getId()) && display->isPoweredOn()) {
-            enableHardwareVsync();
+            if (mUseScheduler) {
+                mScheduler->enableHardwareVsync();
+            } else {
+                enableHardwareVsync();
+            }
         }
     }
 
@@ -1892,7 +1919,7 @@
         mHasPoweredOff = false;
     } else {
         nsecs_t elapsedTime = currentTime - getBE().mLastSwapTime;
-        size_t numPeriods = static_cast<size_t>(elapsedTime / vsyncInterval);
+        size_t numPeriods = static_cast<size_t>(elapsedTime / stats.vsyncPeriod);
         if (numPeriods < SurfaceFlingerBE::NUM_BUCKETS - 1) {
             getBE().mFrameBuckets[numPeriods] += elapsedTime;
         } else {
@@ -3991,7 +4018,8 @@
 
     // Use phase of 0 since phase is not known.
     // Use latency of 0, which will snap to the ideal latency.
-    setCompositorTimingSnapped(0, period, 0);
+    DisplayStatInfo stats{0 /* vsyncTime */, period /* vsyncPeriod */};
+    setCompositorTimingSnapped(stats, 0);
 }
 
 void SurfaceFlinger::initializeDisplays() {
@@ -4057,8 +4085,11 @@
         }
 
         if (display->isPrimary() && currentMode != HWC_POWER_MODE_DOZE_SUSPEND) {
-            disableHardwareVsync(true); // also cancels any in-progress resync
-
+            if (mUseScheduler) {
+                mScheduler->disableHardwareVsync(true);
+            } else {
+                disableHardwareVsync(true); // also cancels any in-progress resync
+            }
             // FIXME: eventthread only knows about the main display right now
             if (mUseScheduler) {
                 mScheduler->onScreenReleased(mAppConnectionHandle);
@@ -4086,7 +4117,11 @@
     } else if (mode == HWC_POWER_MODE_DOZE_SUSPEND) {
         // Leave display going to doze
         if (display->isPrimary()) {
-            disableHardwareVsync(true); // also cancels any in-progress resync
+            if (mUseScheduler) {
+                mScheduler->disableHardwareVsync(true);
+            } else {
+                disableHardwareVsync(true); // also cancels any in-progress resync
+            }
             // FIXME: eventthread only knows about the main display right now
             if (mUseScheduler) {
                 mScheduler->onScreenReleased(mAppConnectionHandle);
@@ -5033,6 +5068,7 @@
             // Needs to be shifted to proper binder interface when we productize
             case 1016: {
                 n = data.readInt32();
+                // TODO(b/113612090): Evaluate if this can be removed.
                 mPrimaryDispSync->setRefreshSkipCount(n);
                 return NO_ERROR;
             }
@@ -5161,9 +5197,17 @@
                 }
 
                 if ((frequencyScaler.multiplier == 1) && (frequencyScaler.divisor == 1)) {
-                    enableHardwareVsync();
+                    if (mUseScheduler) {
+                        mScheduler->enableHardwareVsync();
+                    } else {
+                        enableHardwareVsync();
+                    }
                 } else {
-                    disableHardwareVsync(true);
+                    if (mUseScheduler) {
+                        mScheduler->disableHardwareVsync(true);
+                    } else {
+                        disableHardwareVsync(true);
+                    }
                 }
                 mPrimaryDispSync->scalePeriod(frequencyScaler);
                 getBE().mHwc->setDisplayFrequencyScaleParameters(frequencyScaler);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 19dcee7..f535c4e 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -662,12 +662,10 @@
 
     void preComposition();
     void postComposition();
-    void updateCompositorTiming(
-            nsecs_t vsyncPhase, nsecs_t vsyncInterval, nsecs_t compositeTime,
-            std::shared_ptr<FenceTime>& presentFenceTime);
-    void setCompositorTimingSnapped(
-            nsecs_t vsyncPhase, nsecs_t vsyncInterval,
-            nsecs_t compositeToPresentLatency);
+    void updateCompositorTiming(const DisplayStatInfo& stats, nsecs_t compositeTime,
+                                std::shared_ptr<FenceTime>& presentFenceTime);
+    void setCompositorTimingSnapped(const DisplayStatInfo& stats,
+                                    nsecs_t compositeToPresentLatency);
     void rebuildLayerStacks();
 
     ui::Dataspace getBestDataspace(const sp<const DisplayDevice>& display,
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index df0d982..be91a9c 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -6,8 +6,11 @@
 
 #include <log/log.h>
 
+#include <mutex>
+
 #include "AsyncCallRecorder.h"
 #include "Scheduler/DispSync.h"
+#include "Scheduler/EventControlThread.h"
 #include "Scheduler/EventThread.h"
 #include "Scheduler/Scheduler.h"
 #include "mock/MockDispSync.h"
@@ -37,7 +40,7 @@
     class MockScheduler : public android::Scheduler {
     public:
         MockScheduler(std::unique_ptr<EventThread> eventThread)
-              : mEventThread(std::move(eventThread)) {}
+              : Scheduler([](bool) {}), mEventThread(std::move(eventThread)) {}
 
         std::unique_ptr<EventThread> makeEventThread(
                 const std::string& /* connectionName */, DispSync* /* dispSync */,
@@ -81,9 +84,9 @@
     EXPECT_CALL(*mEventThread, createEventConnection())
             .WillRepeatedly(Return(mEventThreadConnection));
 
-    mConnectionHandle = mScheduler->createConnection("appConnection", mPrimaryDispSync, 16,
-                                                     mResyncCallRecorder.getInvocable(),
-                                                     mInterceptVSyncCallRecorder.getInvocable());
+    mConnectionHandle =
+            mScheduler->createConnection("appConnection", 16, mResyncCallRecorder.getInvocable(),
+                                         mInterceptVSyncCallRecorder.getInvocable());
 }
 
 SchedulerTest::~SchedulerTest() {