SF: Fix UAF due to outliving idle timer

On Scheduler destruction, stop the timer and clear the callbacks, since
the RefreshRateConfigs may outlive the Scheduler.

On RefreshRateConfigs destruction, ensure the timer is destroyed before
the mutex/callbacks. Invoke the callback under lock.

Remove TestableSurfaceFlinger's subtle precondition that setupScheduler
must be called prior to FakeDisplayDeviceInjector for them to share
RefreshRateConfigs, which was not the case in DisplayModeSwitchingTest.

TestableScheduler is deleted through a Scheduler pointer, so ~Scheduler
should be virtual. Although ~TestableScheduler is trivial, this invoked
undefined behavior.

Bug: 213688734
Test: libsurfaceflinger_unittest --gtest_repeat=1000
Change-Id: Id23fafaf3d7071a5e28e275de386dd731a726006
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index f1e9b31..2fc7c59 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -143,11 +143,10 @@
                 .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD));
         EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
 
-        constexpr scheduler::ISchedulerCallback* kCallback = nullptr;
-        constexpr bool kHasMultipleConfigs = true;
         mFlinger.setupScheduler(std::move(vsyncController), std::move(vsyncTracker),
-                                std::move(eventThread), std::move(sfEventThread), kCallback,
-                                kHasMultipleConfigs);
+                                std::move(eventThread), std::move(sfEventThread),
+                                TestableSurfaceFlinger::SchedulerCallbackImpl::kNoOp,
+                                TestableSurfaceFlinger::kTwoDisplayModes);
     }
 
     void setupForceGeometryDirty() {
diff --git a/services/surfaceflinger/tests/unittests/DisplayDevice_InitiateModeChange.cpp b/services/surfaceflinger/tests/unittests/DisplayDevice_InitiateModeChange.cpp
index 5a0033e..40a9b1a 100644
--- a/services/surfaceflinger/tests/unittests/DisplayDevice_InitiateModeChange.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayDevice_InitiateModeChange.cpp
@@ -44,8 +44,8 @@
         mFlinger.onComposerHalHotplug(PrimaryDisplayVariant::HWC_DISPLAY_ID, Connection::CONNECTED);
 
         mDisplay = PrimaryDisplayVariant::makeFakeExistingDisplayInjector(this)
-                           .setSupportedModes({kDisplayMode60, kDisplayMode90, kDisplayMode120})
-                           .setActiveMode(kDisplayModeId60)
+                           .setDisplayModes({kDisplayMode60, kDisplayMode90, kDisplayMode120},
+                                            kDisplayModeId60)
                            .inject();
     }
 
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index c318e28..2425862 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -77,7 +77,8 @@
     mFlinger.setupScheduler(std::unique_ptr<scheduler::VsyncController>(mVsyncController),
                             std::unique_ptr<scheduler::VSyncTracker>(mVSyncTracker),
                             std::unique_ptr<EventThread>(mEventThread),
-                            std::unique_ptr<EventThread>(mSFEventThread), &mSchedulerCallback);
+                            std::unique_ptr<EventThread>(mSFEventThread),
+                            TestableSurfaceFlinger::SchedulerCallbackImpl::kMock);
 }
 
 void DisplayTransactionTest::injectMockComposer(int virtualDisplayCount) {
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
index 69ac26e..45eceff 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
@@ -48,7 +48,6 @@
 #include "mock/DisplayHardware/MockPowerAdvisor.h"
 #include "mock/MockEventThread.h"
 #include "mock/MockNativeWindowSurface.h"
-#include "mock/MockSchedulerCallback.h"
 #include "mock/MockSurfaceInterceptor.h"
 #include "mock/MockVsyncController.h"
 #include "mock/system/window/MockNativeWindow.h"
@@ -121,7 +120,6 @@
 
     mock::VsyncController* mVsyncController = new mock::VsyncController;
     mock::VSyncTracker* mVSyncTracker = new mock::VSyncTracker;
-    scheduler::mock::SchedulerCallback mSchedulerCallback;
     mock::EventThread* mEventThread = new mock::EventThread;
     mock::EventThread* mSFEventThread = new mock::EventThread;
 
diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
index fe5f9e0..2b69f13 100644
--- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
@@ -164,8 +164,9 @@
             .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD));
     EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
     mFlinger.setupScheduler(std::move(vsyncController), std::move(vsyncTracker),
-                            std::move(eventThread), std::move(sfEventThread), /*callback*/ nullptr,
-                            /*hasMultipleModes*/ true);
+                            std::move(eventThread), std::move(sfEventThread),
+                            TestableSurfaceFlinger::SchedulerCallbackImpl::kNoOp,
+                            TestableSurfaceFlinger::kTwoDisplayModes);
 }
 
 namespace {
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
index 56a0506..3205952 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
@@ -42,13 +42,18 @@
 
         mFlinger.onComposerHalHotplug(PrimaryDisplayVariant::HWC_DISPLAY_ID, Connection::CONNECTED);
 
-        mDisplay = PrimaryDisplayVariant::makeFakeExistingDisplayInjector(this)
-                           .setSupportedModes({kDisplayMode60, kDisplayMode90, kDisplayMode120,
-                                               kDisplayMode90DifferentResolution})
-                           .setActiveMode(kDisplayModeId60)
-                           .inject();
+        {
+            DisplayModes modes = {kDisplayMode60, kDisplayMode90, kDisplayMode120,
+                                  kDisplayMode90DifferentResolution};
+            const DisplayModeId activeModeId = kDisplayModeId60;
+            auto configs = std::make_shared<scheduler::RefreshRateConfigs>(modes, activeModeId);
 
-        setupScheduler();
+            mDisplay = PrimaryDisplayVariant::makeFakeExistingDisplayInjector(this)
+                               .setDisplayModes(modes, activeModeId, std::move(configs))
+                               .inject();
+        }
+
+        setupScheduler(mDisplay->holdRefreshRateConfigs());
 
         // isVsyncPeriodSwitchSupported should return true, otherwise the SF's HWC proxy
         // will call setActiveConfig instead of setActiveConfigWithConstraints.
@@ -57,7 +62,7 @@
     }
 
 protected:
-    void setupScheduler();
+    void setupScheduler(std::shared_ptr<scheduler::RefreshRateConfigs>);
     void testChangeRefreshRate(bool isDisplayActive, bool isRefreshRequired);
 
     sp<DisplayDevice> mDisplay;
@@ -108,7 +113,8 @@
                     .build();
 };
 
-void DisplayModeSwitchingTest::setupScheduler() {
+void DisplayModeSwitchingTest::setupScheduler(
+        std::shared_ptr<scheduler::RefreshRateConfigs> configs) {
     auto eventThread = std::make_unique<mock::EventThread>();
     mAppEventThread = eventThread.get();
     auto sfEventThread = std::make_unique<mock::EventThread>();
@@ -132,8 +138,9 @@
                     Return(TestableSurfaceFlinger::FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD));
     EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
     mFlinger.setupScheduler(std::move(vsyncController), std::move(vsyncTracker),
-                            std::move(eventThread), std::move(sfEventThread), /*callback*/ nullptr,
-                            /*hasMultipleModes*/ true);
+                            std::move(eventThread), std::move(sfEventThread),
+                            TestableSurfaceFlinger::SchedulerCallbackImpl::kNoOp,
+                            std::move(configs));
 }
 
 TEST_F(DisplayModeSwitchingTest, changeRefreshRate_OnActiveDisplay_WithRefreshRequired) {
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp
index b57feff..7948e60 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp
@@ -61,7 +61,7 @@
 struct EventThreadBaseSupportedVariant {
     static void setupVsyncAndEventThreadNoCallExpectations(DisplayTransactionTest* test) {
         // The callback should not be notified to toggle VSYNC.
-        EXPECT_CALL(test->mSchedulerCallback, setVsyncEnabled(_)).Times(0);
+        EXPECT_CALL(test->mFlinger.mockSchedulerCallback(), setVsyncEnabled(_)).Times(0);
 
         // The event thread should not be notified.
         EXPECT_CALL(*test->mEventThread, onScreenReleased()).Times(0);
@@ -88,7 +88,7 @@
 struct EventThreadIsSupportedVariant : public EventThreadBaseSupportedVariant {
     static void setupAcquireAndEnableVsyncCallExpectations(DisplayTransactionTest* test) {
         // The callback should be notified to enable VSYNC.
-        EXPECT_CALL(test->mSchedulerCallback, setVsyncEnabled(true)).Times(1);
+        EXPECT_CALL(test->mFlinger.mockSchedulerCallback(), setVsyncEnabled(true)).Times(1);
 
         // The event thread should be notified that the screen was acquired.
         EXPECT_CALL(*test->mEventThread, onScreenAcquired()).Times(1);
@@ -96,7 +96,7 @@
 
     static void setupReleaseAndDisableVsyncCallExpectations(DisplayTransactionTest* test) {
         // The callback should be notified to disable VSYNC.
-        EXPECT_CALL(test->mSchedulerCallback, setVsyncEnabled(false)).Times(1);
+        EXPECT_CALL(test->mFlinger.mockSchedulerCallback(), setVsyncEnabled(false)).Times(1);
 
         // The event thread should not be notified that the screen was released.
         EXPECT_CALL(*test->mEventThread, onScreenReleased()).Times(1);
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 361d629..d292e08 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -16,6 +16,9 @@
 
 #pragma once
 
+#include <algorithm>
+#include <variant>
+
 #include <compositionengine/Display.h>
 #include <compositionengine/LayerFECompositionState.h>
 #include <compositionengine/OutputLayer.h>
@@ -24,7 +27,6 @@
 #include <compositionengine/impl/OutputLayerCompositionState.h>
 #include <compositionengine/mock/DisplaySurface.h>
 #include <gui/ScreenCaptureResults.h>
-#include <algorithm>
 
 #include "BufferQueueLayer.h"
 #include "BufferStateLayer.h"
@@ -45,6 +47,7 @@
 #include "mock/DisplayHardware/MockComposer.h"
 #include "mock/MockFrameTimeline.h"
 #include "mock/MockFrameTracer.h"
+#include "mock/MockSchedulerCallback.h"
 
 namespace android {
 
@@ -170,7 +173,7 @@
 
 } // namespace surfaceflinger::test
 
-class TestableSurfaceFlinger final : private scheduler::ISchedulerCallback {
+class TestableSurfaceFlinger {
 public:
     using HotplugEvent = SurfaceFlinger::HotplugEvent;
 
@@ -193,42 +196,64 @@
         mFlinger->mCompositionEngine->setTimeStats(timeStats);
     }
 
-    // The ISchedulerCallback argument can be nullptr for a no-op implementation.
+    enum class SchedulerCallbackImpl { kNoOp, kMock };
+
+    static constexpr struct OneDisplayMode {
+    } kOneDisplayMode;
+
+    static constexpr struct TwoDisplayModes {
+    } kTwoDisplayModes;
+
+    using RefreshRateConfigsPtr = std::shared_ptr<scheduler::RefreshRateConfigs>;
+
+    using DisplayModesVariant =
+            std::variant<OneDisplayMode, TwoDisplayModes, RefreshRateConfigsPtr>;
+
     void setupScheduler(std::unique_ptr<scheduler::VsyncController> vsyncController,
                         std::unique_ptr<scheduler::VSyncTracker> vsyncTracker,
                         std::unique_ptr<EventThread> appEventThread,
                         std::unique_ptr<EventThread> sfEventThread,
-                        scheduler::ISchedulerCallback* callback = nullptr,
-                        bool hasMultipleModes = false) {
-        DisplayModes modes{DisplayMode::Builder(0)
-                                   .setId(DisplayModeId(0))
-                                   .setPhysicalDisplayId(PhysicalDisplayId::fromPort(0))
-                                   .setVsyncPeriod(16'666'667)
-                                   .setGroup(0)
-                                   .build()};
+                        SchedulerCallbackImpl callbackImpl = SchedulerCallbackImpl::kNoOp,
+                        DisplayModesVariant modesVariant = kOneDisplayMode) {
+        RefreshRateConfigsPtr configs;
+        if (std::holds_alternative<RefreshRateConfigsPtr>(modesVariant)) {
+            configs = std::move(std::get<RefreshRateConfigsPtr>(modesVariant));
+        } else {
+            DisplayModes modes = {DisplayMode::Builder(0)
+                                          .setId(DisplayModeId(0))
+                                          .setPhysicalDisplayId(PhysicalDisplayId::fromPort(0))
+                                          .setVsyncPeriod(16'666'667)
+                                          .setGroup(0)
+                                          .build()};
 
-        if (hasMultipleModes) {
-            modes.emplace_back(DisplayMode::Builder(1)
-                                       .setId(DisplayModeId(1))
-                                       .setPhysicalDisplayId(PhysicalDisplayId::fromPort(0))
-                                       .setVsyncPeriod(11'111'111)
-                                       .setGroup(0)
-                                       .build());
+            if (std::holds_alternative<TwoDisplayModes>(modesVariant)) {
+                modes.emplace_back(DisplayMode::Builder(1)
+                                           .setId(DisplayModeId(1))
+                                           .setPhysicalDisplayId(PhysicalDisplayId::fromPort(0))
+                                           .setVsyncPeriod(11'111'111)
+                                           .setGroup(0)
+                                           .build());
+            }
+
+            configs = std::make_shared<scheduler::RefreshRateConfigs>(modes, DisplayModeId(0));
         }
 
-        const auto currMode = DisplayModeId(0);
-        mRefreshRateConfigs = std::make_shared<scheduler::RefreshRateConfigs>(modes, currMode);
-        const auto currFps = mRefreshRateConfigs->getCurrentRefreshRate().getFps();
+        const auto currFps = configs->getCurrentRefreshRate().getFps();
         mFlinger->mVsyncConfiguration = mFactory.createVsyncConfiguration(currFps);
         mFlinger->mVsyncModulator = sp<scheduler::VsyncModulator>::make(
                 mFlinger->mVsyncConfiguration->getCurrentConfigs());
         mFlinger->mRefreshRateStats =
                 std::make_unique<scheduler::RefreshRateStats>(*mFlinger->mTimeStats, currFps,
-                                                              /*powerMode=*/hal::PowerMode::OFF);
+                                                              hal::PowerMode::OFF);
+
+        using Callback = scheduler::ISchedulerCallback;
+        Callback& callback = callbackImpl == SchedulerCallbackImpl::kNoOp
+                ? static_cast<Callback&>(mNoOpSchedulerCallback)
+                : static_cast<Callback&>(mSchedulerCallback);
 
         mScheduler = new scheduler::TestableScheduler(std::move(vsyncController),
-                                                      std::move(vsyncTracker), mRefreshRateConfigs,
-                                                      *(callback ?: this));
+                                                      std::move(vsyncTracker), std::move(configs),
+                                                      callback);
 
         mFlinger->mAppConnectionHandle = mScheduler->createConnection(std::move(appEventThread));
         mFlinger->mSfConnectionHandle = mScheduler->createConnection(std::move(sfEventThread));
@@ -237,7 +262,8 @@
 
     void resetScheduler(scheduler::Scheduler* scheduler) { mFlinger->mScheduler.reset(scheduler); }
 
-    scheduler::TestableScheduler& mutableScheduler() const { return *mScheduler; }
+    scheduler::TestableScheduler& mutableScheduler() { return *mScheduler; }
+    scheduler::mock::SchedulerCallback& mockSchedulerCallback() { return mSchedulerCallback; }
 
     using CreateBufferQueueFunction = surfaceflinger::test::Factory::CreateBufferQueueFunction;
     void setCreateBufferQueueFunction(CreateBufferQueueFunction f) {
@@ -662,23 +688,6 @@
                 mHwcDisplayId(hwcDisplayId) {
             mCreationArgs.connectionType = connectionType;
             mCreationArgs.isPrimary = isPrimary;
-
-            mCreationArgs.activeModeId = DisplayModeId(0);
-            DisplayModePtr activeMode =
-                    DisplayMode::Builder(FakeHwcDisplayInjector::DEFAULT_ACTIVE_CONFIG)
-                            .setId(mCreationArgs.activeModeId)
-                            .setPhysicalDisplayId(PhysicalDisplayId::fromPort(0))
-                            .setWidth(FakeHwcDisplayInjector::DEFAULT_WIDTH)
-                            .setHeight(FakeHwcDisplayInjector::DEFAULT_HEIGHT)
-                            .setVsyncPeriod(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD)
-                            .setDpiX(FakeHwcDisplayInjector::DEFAULT_DPI)
-                            .setDpiY(FakeHwcDisplayInjector::DEFAULT_DPI)
-                            .setGroup(0)
-                            .build();
-
-            DisplayModes modes{activeMode};
-            mCreationArgs.supportedModes = modes;
-            mCreationArgs.refreshRateConfigs = flinger.mRefreshRateConfigs;
         }
 
         sp<IBinder> token() const { return mDisplayToken; }
@@ -701,13 +710,16 @@
 
         auto& mutableDisplayDevice() { return mFlinger.mutableDisplays()[mDisplayToken]; }
 
-        auto& setActiveMode(DisplayModeId mode) {
-            mCreationArgs.activeModeId = mode;
-            return *this;
-        }
-
-        auto& setSupportedModes(DisplayModes mode) {
-            mCreationArgs.supportedModes = mode;
+        // If `configs` is nullptr, the injector creates RefreshRateConfigs from the `modes`.
+        // Otherwise, it uses `configs`, which the caller must create using the same `modes`.
+        //
+        // TODO(b/182939859): Once `modes` can be retrieved from RefreshRateConfigs, remove
+        // the `configs` parameter in favor of an alternative setRefreshRateConfigs API.
+        auto& setDisplayModes(DisplayModes modes, DisplayModeId activeModeId,
+                              std::shared_ptr<scheduler::RefreshRateConfigs> configs = nullptr) {
+            mCreationArgs.supportedModes = std::move(modes);
+            mCreationArgs.activeModeId = activeModeId;
+            mCreationArgs.refreshRateConfigs = std::move(configs);
             return *this;
         }
 
@@ -749,39 +761,58 @@
         }
 
         sp<DisplayDevice> inject() NO_THREAD_SAFETY_ANALYSIS {
-            const auto displayId = mCreationArgs.compositionDisplay->getDisplayId();
+            auto& modes = mCreationArgs.supportedModes;
+            auto& activeModeId = mCreationArgs.activeModeId;
+
+            if (!mCreationArgs.refreshRateConfigs) {
+                if (modes.empty()) {
+                    activeModeId = DisplayModeId(0);
+                    modes.emplace_back(
+                            DisplayMode::Builder(FakeHwcDisplayInjector::DEFAULT_ACTIVE_CONFIG)
+                                    .setId(activeModeId)
+                                    .setPhysicalDisplayId(PhysicalDisplayId::fromPort(0))
+                                    .setWidth(FakeHwcDisplayInjector::DEFAULT_WIDTH)
+                                    .setHeight(FakeHwcDisplayInjector::DEFAULT_HEIGHT)
+                                    .setVsyncPeriod(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD)
+                                    .setDpiX(FakeHwcDisplayInjector::DEFAULT_DPI)
+                                    .setDpiY(FakeHwcDisplayInjector::DEFAULT_DPI)
+                                    .setGroup(0)
+                                    .build());
+                }
+
+                mCreationArgs.refreshRateConfigs =
+                        std::make_shared<scheduler::RefreshRateConfigs>(modes, activeModeId);
+            }
 
             DisplayDeviceState state;
             if (const auto type = mCreationArgs.connectionType) {
+                const auto displayId = mCreationArgs.compositionDisplay->getDisplayId();
                 LOG_ALWAYS_FATAL_IF(!displayId);
                 const auto physicalId = PhysicalDisplayId::tryCast(*displayId);
                 LOG_ALWAYS_FATAL_IF(!physicalId);
                 LOG_ALWAYS_FATAL_IF(!mHwcDisplayId);
 
-                const DisplayModePtr activeModePtr =
-                        *std::find_if(mCreationArgs.supportedModes.begin(),
-                                      mCreationArgs.supportedModes.end(), [&](DisplayModePtr mode) {
-                                          return mode->getId() == mCreationArgs.activeModeId;
-                                      });
+                const auto it = std::find_if(modes.begin(), modes.end(),
+                                             [&activeModeId](const DisplayModePtr& mode) {
+                                                 return mode->getId() == activeModeId;
+                                             });
+                LOG_ALWAYS_FATAL_IF(it == modes.end());
+
                 state.physical = {.id = *physicalId,
                                   .type = *type,
                                   .hwcDisplayId = *mHwcDisplayId,
                                   .deviceProductInfo = {},
-                                  .supportedModes = mCreationArgs.supportedModes,
-                                  .activeMode = activeModePtr};
+                                  .supportedModes = modes,
+                                  .activeMode = *it};
             }
 
             state.isSecure = mCreationArgs.isSecure;
 
-            mCreationArgs.refreshRateConfigs =
-                    std::make_shared<scheduler::RefreshRateConfigs>(mCreationArgs.supportedModes,
-                                                                    mCreationArgs.activeModeId);
-
-            sp<DisplayDevice> device = new DisplayDevice(mCreationArgs);
-            if (!device->isVirtual()) {
-                device->setActiveMode(mCreationArgs.activeModeId);
+            sp<DisplayDevice> display = sp<DisplayDevice>::make(mCreationArgs);
+            if (!display->isVirtual()) {
+                display->setActiveMode(activeModeId);
             }
-            mFlinger.mutableDisplays().emplace(mDisplayToken, device);
+            mFlinger.mutableDisplays().emplace(mDisplayToken, display);
             mFlinger.mutableCurrentState().displays.add(mDisplayToken, state);
             mFlinger.mutableDrawingState().displays.add(mDisplayToken, state);
 
@@ -789,7 +820,7 @@
                 mFlinger.mutablePhysicalDisplayTokens()[physical->id] = mDisplayToken;
             }
 
-            return device;
+            return display;
         }
 
     private:
@@ -800,16 +831,12 @@
     };
 
 private:
-    void scheduleComposite(FrameHint) override {}
-    void setVsyncEnabled(bool) override {}
-    void changeRefreshRate(const RefreshRate&, DisplayModeEvent) override {}
-    void kernelTimerChanged(bool) override {}
-    void triggerOnFrameRateOverridesChanged() {}
-
     surfaceflinger::test::Factory mFactory;
     sp<SurfaceFlinger> mFlinger = new SurfaceFlinger(mFactory, SurfaceFlinger::SkipInitialization);
+
+    scheduler::mock::SchedulerCallback mSchedulerCallback;
+    scheduler::mock::NoOpSchedulerCallback mNoOpSchedulerCallback;
     scheduler::TestableScheduler* mScheduler = nullptr;
-    std::shared_ptr<scheduler::RefreshRateConfigs> mRefreshRateConfigs;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h b/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h
index 849e308..c90b8ed 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h
@@ -35,7 +35,7 @@
     void setVsyncEnabled(bool) override {}
     void changeRefreshRate(const RefreshRate&, DisplayModeEvent) override {}
     void kernelTimerChanged(bool) override {}
-    void triggerOnFrameRateOverridesChanged() {}
+    void triggerOnFrameRateOverridesChanged() override {}
 };
 
 } // namespace android::scheduler::mock