Merge "SF: Fix thread safety for scheduler callbacks"
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index 91ae087..5d9cfde 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -100,8 +100,10 @@
 } // namespace
 
 EventThreadConnection::EventThreadConnection(EventThread* eventThread,
-                                             ResyncCallback resyncCallback)
+                                             ResyncCallback resyncCallback,
+                                             ResetIdleTimerCallback resetIdleTimerCallback)
       : resyncCallback(std::move(resyncCallback)),
+        resetIdleTimerCallback(std::move(resetIdleTimerCallback)),
         mEventThread(eventThread),
         mChannel(gui::BitTube::DefaultSize) {}
 
@@ -147,22 +149,18 @@
 namespace impl {
 
 EventThread::EventThread(std::unique_ptr<VSyncSource> src,
-                         const InterceptVSyncsCallback& interceptVSyncsCallback,
-                         const ResetIdleTimerCallback& resetIdleTimerCallback,
-                         const char* threadName)
-      : EventThread(nullptr, std::move(src), interceptVSyncsCallback, threadName) {
-    mResetIdleTimer = resetIdleTimerCallback;
-}
+                         InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName)
+      : EventThread(nullptr, std::move(src), std::move(interceptVSyncsCallback), threadName) {}
 
 EventThread::EventThread(VSyncSource* src, InterceptVSyncsCallback interceptVSyncsCallback,
                          const char* threadName)
-      : EventThread(src, nullptr, interceptVSyncsCallback, threadName) {}
+      : EventThread(src, nullptr, std::move(interceptVSyncsCallback), threadName) {}
 
 EventThread::EventThread(VSyncSource* src, std::unique_ptr<VSyncSource> uniqueSrc,
                          InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName)
       : mVSyncSource(src),
         mVSyncSourceUnique(std::move(uniqueSrc)),
-        mInterceptVSyncsCallback(interceptVSyncsCallback),
+        mInterceptVSyncsCallback(std::move(interceptVSyncsCallback)),
         mThreadName(threadName) {
     if (src == nullptr) {
         mVSyncSource = mVSyncSourceUnique.get();
@@ -205,8 +203,10 @@
     mVSyncSource->setPhaseOffset(phaseOffset);
 }
 
-sp<EventThreadConnection> EventThread::createEventConnection(ResyncCallback resyncCallback) const {
-    return new EventThreadConnection(const_cast<EventThread*>(this), std::move(resyncCallback));
+sp<EventThreadConnection> EventThread::createEventConnection(
+        ResyncCallback resyncCallback, ResetIdleTimerCallback resetIdleTimerCallback) const {
+    return new EventThreadConnection(const_cast<EventThread*>(this), std::move(resyncCallback),
+                                     std::move(resetIdleTimerCallback));
 }
 
 status_t EventThread::registerDisplayEventConnection(const sp<EventThreadConnection>& connection) {
@@ -249,9 +249,9 @@
 }
 
 void EventThread::requestNextVsync(const sp<EventThreadConnection>& connection, bool reset) {
-    if (mResetIdleTimer && reset) {
+    if (connection->resetIdleTimerCallback && reset) {
         ATRACE_NAME("resetIdleTimer");
-        mResetIdleTimer();
+        connection->resetIdleTimerCallback();
     }
 
     if (connection->resyncCallback) {
diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h
index 62b6a8b..b275183 100644
--- a/services/surfaceflinger/Scheduler/EventThread.h
+++ b/services/surfaceflinger/Scheduler/EventThread.h
@@ -45,6 +45,7 @@
 // ---------------------------------------------------------------------------
 
 using ResyncCallback = std::function<void()>;
+using ResetIdleTimerCallback = std::function<void()>;
 
 enum class VSyncRequest {
     None = -1,
@@ -69,7 +70,7 @@
 
 class EventThreadConnection : public BnDisplayEventConnection {
 public:
-    EventThreadConnection(EventThread* eventThread, ResyncCallback resyncCallback);
+    EventThreadConnection(EventThread*, ResyncCallback, ResetIdleTimerCallback);
     virtual ~EventThreadConnection();
 
     virtual status_t postEvent(const DisplayEventReceiver::Event& event);
@@ -83,6 +84,7 @@
 
     // Called in response to requestNextVsync.
     const ResyncCallback resyncCallback;
+    const ResetIdleTimerCallback resetIdleTimerCallback;
 
     VSyncRequest vsyncRequest = VSyncRequest::None;
 
@@ -96,8 +98,8 @@
 public:
     virtual ~EventThread();
 
-    virtual sp<EventThreadConnection> createEventConnection(
-            ResyncCallback resyncCallback) const = 0;
+    virtual sp<EventThreadConnection> createEventConnection(ResyncCallback,
+                                                            ResetIdleTimerCallback) const = 0;
 
     // called before the screen is turned off from main thread
     virtual void onScreenReleased() = 0;
@@ -124,17 +126,14 @@
 class EventThread : public android::EventThread, private VSyncSource::Callback {
 public:
     using InterceptVSyncsCallback = std::function<void(nsecs_t)>;
-    using ResetIdleTimerCallback = std::function<void()>;
 
     // TODO(b/113612090): Once the Scheduler is complete this constructor will become obsolete.
-    EventThread(VSyncSource* src, InterceptVSyncsCallback interceptVSyncsCallback,
-                const char* threadName);
-    EventThread(std::unique_ptr<VSyncSource> src,
-                const InterceptVSyncsCallback& interceptVSyncsCallback,
-                const ResetIdleTimerCallback& resetIdleTimerCallback, const char* threadName);
+    EventThread(VSyncSource*, InterceptVSyncsCallback, const char* threadName);
+    EventThread(std::unique_ptr<VSyncSource>, InterceptVSyncsCallback, const char* threadName);
     ~EventThread();
 
-    sp<EventThreadConnection> createEventConnection(ResyncCallback resyncCallback) const override;
+    sp<EventThreadConnection> createEventConnection(ResyncCallback,
+                                                    ResetIdleTimerCallback) const override;
 
     status_t registerDisplayEventConnection(const sp<EventThreadConnection>& connection) override;
     void setVsyncRate(uint32_t rate, const sp<EventThreadConnection>& connection) override;
@@ -220,9 +219,6 @@
     State mState GUARDED_BY(mMutex) = State::Idle;
 
     static const char* toCString(State);
-
-    // Callback that resets the idle timer when the next vsync is received.
-    ResetIdleTimerCallback mResetIdleTimer;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/Scheduler/MessageQueue.cpp b/services/surfaceflinger/Scheduler/MessageQueue.cpp
index 75a410b..1f18ead 100644
--- a/services/surfaceflinger/Scheduler/MessageQueue.cpp
+++ b/services/surfaceflinger/Scheduler/MessageQueue.cpp
@@ -96,7 +96,8 @@
     }
 
     mEventThread = eventThread;
-    mEvents = eventThread->createEventConnection(std::move(resyncCallback));
+    mEvents =
+            eventThread->createEventConnection(std::move(resyncCallback), ResetIdleTimerCallback());
     mEvents->stealReceiveChannel(&mEventTube);
     mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT, MessageQueue::cb_eventReceiver,
                    this);
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 3060f1d..2f581d2 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -87,6 +87,7 @@
 
 sp<Scheduler::ConnectionHandle> Scheduler::createConnection(
         const char* connectionName, int64_t phaseOffsetNs, ResyncCallback resyncCallback,
+        ResetIdleTimerCallback resetIdleTimerCallback,
         impl::EventThread::InterceptVSyncsCallback interceptCallback) {
     const int64_t id = sNextId++;
     ALOGV("Creating a connection handle with ID: %" PRId64 "\n", id);
@@ -94,12 +95,14 @@
     std::unique_ptr<EventThread> eventThread =
             makeEventThread(connectionName, mPrimaryDispSync.get(), phaseOffsetNs,
                             std::move(interceptCallback));
-    auto connection = std::make_unique<Connection>(new ConnectionHandle(id),
-                                                   eventThread->createEventConnection(
-                                                           std::move(resyncCallback)),
-                                                   std::move(eventThread));
 
-    mConnections.insert(std::make_pair(id, std::move(connection)));
+    auto eventThreadConnection =
+            createConnectionInternal(eventThread.get(), std::move(resyncCallback),
+                                     std::move(resetIdleTimerCallback));
+    mConnections.emplace(id,
+                         std::make_unique<Connection>(new ConnectionHandle(id),
+                                                      eventThreadConnection,
+                                                      std::move(eventThread)));
     return mConnections[id]->handle;
 }
 
@@ -109,14 +112,29 @@
     std::unique_ptr<VSyncSource> eventThreadSource =
             std::make_unique<DispSyncSource>(dispSync, phaseOffsetNs, true, connectionName);
     return std::make_unique<impl::EventThread>(std::move(eventThreadSource),
-                                               std::move(interceptCallback),
-                                               [this] { resetIdleTimer(); }, connectionName);
+                                               std::move(interceptCallback), connectionName);
+}
+
+sp<EventThreadConnection> Scheduler::createConnectionInternal(
+        EventThread* eventThread, ResyncCallback&& resyncCallback,
+        ResetIdleTimerCallback&& resetIdleTimerCallback) {
+    return eventThread->createEventConnection(std::move(resyncCallback),
+                                              [this,
+                                               resetIdleTimerCallback =
+                                                       std::move(resetIdleTimerCallback)] {
+                                                  resetIdleTimer();
+                                                  if (resetIdleTimerCallback) {
+                                                      resetIdleTimerCallback();
+                                                  }
+                                              });
 }
 
 sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection(
-        const sp<Scheduler::ConnectionHandle>& handle, ResyncCallback resyncCallback) {
+        const sp<Scheduler::ConnectionHandle>& handle, ResyncCallback resyncCallback,
+        ResetIdleTimerCallback resetIdleTimerCallback) {
     RETURN_VALUE_IF_INVALID(nullptr);
-    return mConnections[handle->id]->thread->createEventConnection(std::move(resyncCallback));
+    return createConnectionInternal(mConnections[handle->id]->thread.get(),
+                                    std::move(resyncCallback), std::move(resetIdleTimerCallback));
 }
 
 EventThread* Scheduler::getEventThread(const sp<Scheduler::ConnectionHandle>& handle) {
@@ -241,11 +259,6 @@
     mExpiredTimerCallback = expiredTimerCallback;
 }
 
-void Scheduler::setResetIdleTimerCallback(const ResetIdleTimerCallback& resetTimerCallback) {
-    std::lock_guard<std::mutex> lock(mCallbackLock);
-    mResetTimerCallback = resetTimerCallback;
-}
-
 void Scheduler::updateFrameSkipping(const int64_t skipCount) {
     ATRACE_INT("FrameSkipCount", skipCount);
     if (mSkipCount != skipCount) {
@@ -336,11 +349,6 @@
         mIdleTimer->reset();
         ATRACE_INT("ExpiredIdleTimer", 0);
     }
-
-    std::lock_guard<std::mutex> lock(mCallbackLock);
-    if (mResetTimerCallback) {
-        mResetTimerCallback();
-    }
 }
 
 void Scheduler::expiredTimerCallback() {
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index e77dc06..4abf027 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -37,7 +37,6 @@
 class Scheduler {
 public:
     using ExpiredIdleTimerCallback = std::function<void()>;
-    using ResetIdleTimerCallback = std::function<void()>;
 
     // Enum to indicate whether to start the transaction early, or at vsync time.
     enum class TransactionStart { EARLY, NORMAL };
@@ -72,12 +71,13 @@
     virtual ~Scheduler();
 
     /** Creates an EventThread connection. */
-    sp<ConnectionHandle> createConnection(
-            const char* connectionName, int64_t phaseOffsetNs, ResyncCallback resyncCallback,
-            impl::EventThread::InterceptVSyncsCallback interceptCallback);
+    sp<ConnectionHandle> createConnection(const char* connectionName, int64_t phaseOffsetNs,
+                                          ResyncCallback, ResetIdleTimerCallback,
+                                          impl::EventThread::InterceptVSyncsCallback);
 
     sp<IDisplayEventConnection> createDisplayEventConnection(const sp<ConnectionHandle>& handle,
-                                                             ResyncCallback resyncCallback);
+                                                             ResyncCallback,
+                                                             ResetIdleTimerCallback);
 
     // Getter methods.
     EventThread* getEventThread(const sp<ConnectionHandle>& handle);
@@ -116,8 +116,6 @@
     void incrementFrameCounter();
     // Callback that gets invoked once the idle timer expires.
     void setExpiredIdleTimerCallback(const ExpiredIdleTimerCallback& expiredTimerCallback);
-    // Callback that gets invoked once the idle timer is reset.
-    void setResetIdleTimerCallback(const ResetIdleTimerCallback& resetTimerCallback);
     // Returns relevant information about Scheduler for dumpsys purposes.
     std::string doDump();
 
@@ -127,6 +125,10 @@
             impl::EventThread::InterceptVSyncsCallback interceptCallback);
 
 private:
+    // Creates a connection on the given EventThread and forwards the given callbacks.
+    sp<EventThreadConnection> createConnectionInternal(EventThread*, ResyncCallback&&,
+                                                       ResetIdleTimerCallback&&);
+
     nsecs_t calculateAverage() const;
     void updateFrameSkipping(const int64_t skipCount);
     // Collects the statistical mean (average) and median between timestamp
@@ -184,7 +186,6 @@
 
     std::mutex mCallbackLock;
     ExpiredIdleTimerCallback mExpiredTimerCallback GUARDED_BY(mCallbackLock);
-    ResetIdleTimerCallback mResetTimerCallback GUARDED_BY(mCallbackLock);
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 51eb6ba..5f8de83 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -120,6 +120,7 @@
 using namespace android::hardware::configstore;
 using namespace android::hardware::configstore::V1_0;
 using namespace android::sysprop;
+
 using base::StringAppendF;
 using ui::ColorMode;
 using ui::Dataspace;
@@ -127,6 +128,8 @@
 using ui::Hdr;
 using ui::RenderIntent;
 
+using RefreshRateType = scheduler::RefreshRateConfigs::RefreshRateType;
+
 namespace {
 
 #pragma clang diagnostic push
@@ -211,6 +214,9 @@
 constexpr float kSrgbWhiteY = 1.0000f;
 constexpr float kSrgbWhiteZ = 1.0891f;
 
+constexpr float kDefaultRefreshRate = 60.f;
+constexpr float kPerformanceRefreshRate = 90.f;
+
 // ---------------------------------------------------------------------------
 int64_t SurfaceFlinger::dispSyncPresentTimeOffset;
 bool SurfaceFlinger::useHwcForRgbToYuv;
@@ -627,13 +633,17 @@
         mPhaseOffsets->setRefreshRateType(
                 scheduler::RefreshRateConfigs::RefreshRateType::PERFORMANCE);
 
+        auto resetIdleTimerCallback =
+                std::bind(&SurfaceFlinger::setRefreshRateTo, this, RefreshRateType::PERFORMANCE);
+
         mAppConnectionHandle =
                 mScheduler->createConnection("appConnection", mPhaseOffsets->getCurrentAppOffset(),
-                                             resyncCallback,
+                                             resyncCallback, resetIdleTimerCallback,
                                              impl::EventThread::InterceptVSyncsCallback());
         mSfConnectionHandle =
                 mScheduler->createConnection("sfConnection", mPhaseOffsets->getCurrentSfOffset(),
-                                             resyncCallback, [this](nsecs_t timestamp) {
+                                             resyncCallback, resetIdleTimerCallback,
+                                             [this](nsecs_t timestamp) {
                                                  mInterceptor->saveVSyncEvent(timestamp);
                                              });
 
@@ -731,20 +741,11 @@
     }
 
     if (mUseScheduler) {
-        mScheduler->setExpiredIdleTimerCallback([this]() {
-            mPhaseOffsets->setRefreshRateType(
-                    scheduler::RefreshRateConfigs::RefreshRateType::DEFAULT);
-            const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
-            mVsyncModulator.setPhaseOffsets(early, gl, late);
-            setRefreshRateTo(60.f /* fps */);
+        mScheduler->setExpiredIdleTimerCallback([this] {
+            Mutex::Autolock lock(mStateLock);
+            setRefreshRateTo(RefreshRateType::DEFAULT);
         });
-        mScheduler->setResetIdleTimerCallback([this]() {
-            mPhaseOffsets->setRefreshRateType(
-                    scheduler::RefreshRateConfigs::RefreshRateType::PERFORMANCE);
-            const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
-            mVsyncModulator.setPhaseOffsets(early, gl, late);
-            setRefreshRateTo(90.f /* fps */);
-        });
+
         mRefreshRateStats =
                 std::make_unique<scheduler::RefreshRateStats>(getHwComposer().getConfigs(
                                                                       *display->getId()),
@@ -956,13 +957,6 @@
     return display->getActiveConfig();
 }
 
-status_t SurfaceFlinger::setActiveConfigAsync(const sp<IBinder>& displayToken, int mode) {
-    ATRACE_NAME("setActiveConfigAsync");
-    postMessageAsync(new LambdaMessage(
-            [=]() NO_THREAD_SAFETY_ANALYSIS { setActiveConfigInternal(displayToken, mode); }));
-    return NO_ERROR;
-}
-
 status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& displayToken, int mode) {
     ATRACE_NAME("setActiveConfigSync");
     postMessageSync(new LambdaMessage(
@@ -1269,16 +1263,21 @@
     });
 
     if (mUseScheduler) {
-        if (vsyncSource == eVsyncSourceSurfaceFlinger) {
-            return mScheduler->createDisplayEventConnection(mSfConnectionHandle, resyncCallback);
-        } else {
-            return mScheduler->createDisplayEventConnection(mAppConnectionHandle, resyncCallback);
-        }
+        auto resetIdleTimerCallback = [this] {
+            Mutex::Autolock lock(mStateLock);
+            setRefreshRateTo(RefreshRateType::PERFORMANCE);
+        };
+
+        const auto& handle = vsyncSource == eVsyncSourceSurfaceFlinger ? mSfConnectionHandle
+                                                                       : mAppConnectionHandle;
+
+        return mScheduler->createDisplayEventConnection(handle, std::move(resyncCallback),
+                                                        std::move(resetIdleTimerCallback));
     } else {
         if (vsyncSource == eVsyncSourceSurfaceFlinger) {
-            return mSFEventThread->createEventConnection(resyncCallback);
+            return mSFEventThread->createEventConnection(resyncCallback, ResetIdleTimerCallback());
         } else {
-            return mEventThread->createEventConnection(resyncCallback);
+            return mEventThread->createEventConnection(resyncCallback, ResetIdleTimerCallback());
         }
     }
 }
@@ -1440,12 +1439,16 @@
     *compositorTiming = getBE().mCompositorTiming;
 }
 
-// TODO(b/123715322): Fix thread safety.
-void SurfaceFlinger::setRefreshRateTo(float newFps) NO_THREAD_SAFETY_ANALYSIS {
-    const auto display = getDefaultDisplayDeviceLocked();
-    if (!display || mBootStage != BootStage::FINISHED) {
+void SurfaceFlinger::setRefreshRateTo(RefreshRateType refreshRate) {
+    mPhaseOffsets->setRefreshRateType(refreshRate);
+
+    const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
+    mVsyncModulator.setPhaseOffsets(early, gl, late);
+
+    if (mBootStage != BootStage::FINISHED) {
         return;
     }
+
     // TODO(b/113612090): There should be a message queue flush here. Because this esentially
     // runs on a mainthread, we cannot call postMessageSync. This can be resolved in a better
     // manner, once the setActiveConfig is synchronous, and is executed at a known time in a
@@ -1456,14 +1459,20 @@
     if (currentVsyncPeriod == 0) {
         return;
     }
+
     // TODO(b/113612090): Consider having an enum value for correct refresh rates, rather than
     // floating numbers.
     const float currentFps = 1e9 / currentVsyncPeriod;
+    const float newFps = refreshRate == RefreshRateType::PERFORMANCE ? kPerformanceRefreshRate
+                                                                     : kDefaultRefreshRate;
     if (std::abs(currentFps - newFps) <= 1) {
         return;
     }
 
-    auto configs = getHwComposer().getConfigs(*display->getId());
+    const auto displayId = getInternalDisplayIdLocked();
+    LOG_ALWAYS_FATAL_IF(!displayId);
+
+    auto configs = getHwComposer().getConfigs(*displayId);
     for (int i = 0; i < configs.size(); i++) {
         const nsecs_t vsyncPeriod = configs.at(i)->getVsyncPeriod();
         if (vsyncPeriod == 0) {
@@ -1473,12 +1482,7 @@
         // TODO(b/113612090): There should be a better way at determining which config
         // has the right refresh rate.
         if (std::abs(fps - newFps) <= 1) {
-            const sp<IBinder> token = display->getDisplayToken().promote();
-            LOG_ALWAYS_FATAL_IF(token == nullptr);
-
-            // This is posted in async function to avoid deadlock when getDisplayDevice
-            // requires mStateLock.
-            setActiveConfigAsync(token, i);
+            setActiveConfigInternal(getInternalDisplayTokenLocked(), i);
             ATRACE_INT("FPS", newFps);
         }
     }
@@ -5386,8 +5390,8 @@
     DisplayRenderArea renderArea(display, sourceCrop, reqWidth, reqHeight, reqDataspace,
                                  renderAreaRotation);
 
-    auto traverseLayers = std::bind(std::mem_fn(&SurfaceFlinger::traverseLayersInDisplay), this,
-                                    display, std::placeholders::_1);
+    auto traverseLayers = std::bind(&SurfaceFlinger::traverseLayersInDisplay, this, display,
+                                    std::placeholders::_1);
     return captureScreenCommon(renderArea, traverseLayers, outBuffer, reqPixelFormat,
                                useIdentityTransform);
 }
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index c404ef2..6546973 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -60,6 +60,7 @@
 #include "Scheduler/EventThread.h"
 #include "Scheduler/MessageQueue.h"
 #include "Scheduler/PhaseOffsets.h"
+#include "Scheduler/RefreshRateConfigs.h"
 #include "Scheduler/RefreshRateStats.h"
 #include "Scheduler/Scheduler.h"
 #include "Scheduler/VSyncModulator.h"
@@ -502,8 +503,6 @@
 
     // called on the main thread in response to initializeDisplays()
     void onInitializeDisplays() REQUIRES(mStateLock);
-    // setActiveConfigInternal() posted on a main thread for async execution
-    status_t setActiveConfigAsync(const sp<IBinder>& displayToken, int mode);
     // called on the main thread in response to setActiveConfig()
     void setActiveConfigInternal(const sp<IBinder>& displayToken, int mode) REQUIRES(mStateLock);
     // called on the main thread in response to setPowerMode()
@@ -770,9 +769,9 @@
     void resyncToHardwareVsync(bool makeAvailable, nsecs_t period);
     void disableHardwareVsync(bool makeUnavailable);
 
-    // Sets the refresh rate to newFps by switching active configs, if they are available for
+    // Sets the refresh rate by switching active configs, if they are available for
     // the desired refresh rate.
-    void setRefreshRateTo(float newFps);
+    void setRefreshRateTo(scheduler::RefreshRateConfigs::RefreshRateType) REQUIRES(mStateLock);
 
     using GetVsyncPeriod = std::function<nsecs_t()>;
 
diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
index fa5bb26..3a7cfba 100644
--- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
+++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
@@ -53,8 +53,10 @@
     class MockEventThreadConnection : public EventThreadConnection {
     public:
         MockEventThreadConnection(android::impl::EventThread* eventThread,
-                                  ResyncCallback&& resyncCallback)
-              : EventThreadConnection(eventThread, std::move(resyncCallback)) {}
+                                  ResyncCallback&& resyncCallback,
+                                  ResetIdleTimerCallback&& resetIdleTimerCallback)
+              : EventThreadConnection(eventThread, std::move(resyncCallback),
+                                      std::move(resetIdleTimerCallback)) {}
         MOCK_METHOD1(postEvent, status_t(const DisplayEventReceiver::Event& event));
     };
 
@@ -82,6 +84,7 @@
     AsyncCallRecorder<void (*)(VSyncSource::Callback*)> mVSyncSetCallbackCallRecorder;
     AsyncCallRecorder<void (*)(nsecs_t)> mVSyncSetPhaseOffsetCallRecorder;
     AsyncCallRecorder<void (*)()> mResyncCallRecorder;
+    AsyncCallRecorder<void (*)()> mResetIdleTimerCallRecorder;
     AsyncCallRecorder<void (*)(nsecs_t)> mInterceptVSyncCallRecorder;
     ConnectionEventRecorder mConnectionEventCallRecorder{0};
 
@@ -136,7 +139,8 @@
 sp<EventThreadTest::MockEventThreadConnection> EventThreadTest::createConnection(
         ConnectionEventRecorder& recorder) {
     sp<MockEventThreadConnection> connection =
-            new MockEventThreadConnection(mThread.get(), mResyncCallRecorder.getInvocable());
+            new MockEventThreadConnection(mThread.get(), mResyncCallRecorder.getInvocable(),
+                                          mResetIdleTimerCallRecorder.getInvocable());
     EXPECT_CALL(*connection, postEvent(_)).WillRepeatedly(Invoke(recorder.getInvocable()));
     return connection;
 }
@@ -207,6 +211,7 @@
     EXPECT_FALSE(mVSyncSetCallbackCallRecorder.waitForCall(0us).has_value());
     EXPECT_FALSE(mVSyncSetPhaseOffsetCallRecorder.waitForCall(0us).has_value());
     EXPECT_FALSE(mResyncCallRecorder.waitForCall(0us).has_value());
+    EXPECT_FALSE(mResetIdleTimerCallRecorder.waitForCall(0us).has_value());
     EXPECT_FALSE(mInterceptVSyncCallRecorder.waitForCall(0us).has_value());
     EXPECT_FALSE(mConnectionEventCallRecorder.waitForCall(0us).has_value());
 }
@@ -224,9 +229,10 @@
 
 TEST_F(EventThreadTest, requestNextVsyncPostsASingleVSyncEventToTheConnection) {
     // Signal that we want the next vsync event to be posted to the connection
-    mThread->requestNextVsync(mConnection, false);
+    mThread->requestNextVsync(mConnection, true);
 
-    // EventThread should immediately request a resync.
+    // EventThread should immediately reset the idle timer and request a resync.
+    EXPECT_TRUE(mResetIdleTimerCallRecorder.waitForCall().has_value());
     EXPECT_TRUE(mResyncCallRecorder.waitForCall().has_value());
 
     // EventThread should enable vsync callbacks.
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index 0db96d9..26b6d0c 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -25,7 +25,7 @@
     class MockEventThreadConnection : public android::EventThreadConnection {
     public:
         explicit MockEventThreadConnection(EventThread* eventThread)
-              : EventThreadConnection(eventThread, ResyncCallback()) {}
+              : EventThreadConnection(eventThread, ResyncCallback(), ResetIdleTimerCallback()) {}
         ~MockEventThreadConnection() = default;
 
         MOCK_METHOD1(stealReceiveChannel, status_t(gui::BitTube* outChannel));
@@ -78,10 +78,11 @@
 
     // createConnection call to scheduler makes a createEventConnection call to EventThread. Make
     // sure that call gets executed and returns an EventThread::Connection object.
-    EXPECT_CALL(*mEventThread, createEventConnection(_))
+    EXPECT_CALL(*mEventThread, createEventConnection(_, _))
             .WillRepeatedly(Return(mEventThreadConnection));
 
     mConnectionHandle = mScheduler->createConnection("appConnection", 16, ResyncCallback(),
+                                                     ResetIdleTimerCallback(),
                                                      impl::EventThread::InterceptVSyncsCallback());
     EXPECT_TRUE(mConnectionHandle != nullptr);
 }
@@ -102,7 +103,8 @@
     // exceptions, just gracefully continues.
     sp<IDisplayEventConnection> returnedValue;
     ASSERT_NO_FATAL_FAILURE(
-            returnedValue = mScheduler->createDisplayEventConnection(nullptr, ResyncCallback()));
+            returnedValue = mScheduler->createDisplayEventConnection(nullptr, ResyncCallback(),
+                                                                     ResetIdleTimerCallback()));
     EXPECT_TRUE(returnedValue == nullptr);
     EXPECT_TRUE(mScheduler->getEventThread(nullptr) == nullptr);
     EXPECT_TRUE(mScheduler->getEventConnection(nullptr) == nullptr);
@@ -123,7 +125,8 @@
     sp<IDisplayEventConnection> returnedValue;
     ASSERT_NO_FATAL_FAILURE(
             returnedValue =
-                    mScheduler->createDisplayEventConnection(connectionHandle, ResyncCallback()));
+                    mScheduler->createDisplayEventConnection(connectionHandle, ResyncCallback(),
+                                                             ResetIdleTimerCallback()));
     EXPECT_TRUE(returnedValue == nullptr);
     EXPECT_TRUE(mScheduler->getEventThread(connectionHandle) == nullptr);
     EXPECT_TRUE(mScheduler->getEventConnection(connectionHandle) == nullptr);
@@ -152,7 +155,8 @@
     sp<IDisplayEventConnection> returnedValue;
     ASSERT_NO_FATAL_FAILURE(
             returnedValue =
-                    mScheduler->createDisplayEventConnection(mConnectionHandle, ResyncCallback()));
+                    mScheduler->createDisplayEventConnection(mConnectionHandle, ResyncCallback(),
+                                                             ResetIdleTimerCallback()));
     EXPECT_TRUE(returnedValue != nullptr);
     ASSERT_EQ(returnedValue, mEventThreadConnection);
 
diff --git a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
index aaf67e9..589237d 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
@@ -28,7 +28,8 @@
     EventThread();
     ~EventThread() override;
 
-    MOCK_CONST_METHOD1(createEventConnection, sp<EventThreadConnection>(ResyncCallback));
+    MOCK_CONST_METHOD2(createEventConnection,
+                       sp<EventThreadConnection>(ResyncCallback, ResetIdleTimerCallback));
     MOCK_METHOD0(onScreenReleased, void());
     MOCK_METHOD0(onScreenAcquired, void());
     MOCK_METHOD2(onHotplugReceived, void(PhysicalDisplayId, bool));