SF: Enforce thread safety of active mode access

Provide two RefreshRateConfigs APIs for retrieving the active mode:
getActiveMode for access from the main thread (which does not need
to lock nor copy), and getActiveModePtr for other threads.

Bug: 241285191
Test: Build (-Wthread-safety)
Change-Id: If156d85861ec2d82a394ba181314a6ba3048974f
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 47bd91e..701071b 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -3947,7 +3947,7 @@
     }
 
     if (display) {
-        const Fps refreshRate = display->refreshRateConfigs().getActiveMode()->getFps();
+        const Fps refreshRate = display->refreshRateConfigs().getActiveModePtr()->getFps();
         const std::optional<Fps> renderRate =
                 mFlinger->mScheduler->getFrameRateOverride(getOwnerUid());
 
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index a48c921..d270655 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -27,6 +27,7 @@
 #include <android-base/properties.h>
 #include <android-base/stringprintf.h>
 #include <ftl/enum.h>
+#include <ftl/fake_guard.h>
 #include <utils/Trace.h>
 
 #include "../SurfaceFlingerProperties.h"
@@ -325,6 +326,8 @@
 
     const Policy* policy = getCurrentPolicyLocked();
     const auto& defaultMode = mDisplayModes.get(policy->defaultMode)->get();
+    const auto& activeMode = *getActiveModeItLocked()->second;
+
     // If the default mode group is different from the group of current mode,
     // this means a layer requesting a seamed mode switch just disappeared and
     // we should switch back to the default group.
@@ -332,7 +335,7 @@
     // of the current mode, in order to prevent unnecessary seamed mode switches
     // (e.g. when pausing a video playback).
     const auto anchorGroup =
-            seamedFocusedLayers > 0 ? mActiveModeIt->second->getGroup() : defaultMode->getGroup();
+            seamedFocusedLayers > 0 ? activeMode.getGroup() : defaultMode->getGroup();
 
     // Consider the touch event if there are no Explicit* layers. Otherwise wait until after we've
     // selected a refresh rate to see if we should apply touch boost.
@@ -387,12 +390,12 @@
 
         for (auto& [modeIt, overallScore, fixedRateBelowThresholdLayersScore] : scores) {
             const auto& [id, mode] = *modeIt;
-            const bool isSeamlessSwitch = mode->getGroup() == mActiveModeIt->second->getGroup();
+            const bool isSeamlessSwitch = mode->getGroup() == activeMode.getGroup();
 
             if (layer.seamlessness == Seamlessness::OnlySeamless && !isSeamlessSwitch) {
                 ALOGV("%s ignores %s to avoid non-seamless switch. Current mode = %s",
                       formatLayerInfo(layer, weight).c_str(), to_string(*mode).c_str(),
-                      to_string(*mActiveModeIt->second).c_str());
+                      to_string(activeMode).c_str());
                 continue;
             }
 
@@ -401,7 +404,7 @@
                 ALOGV("%s ignores %s because it's not focused and the switch is going to be seamed."
                       " Current mode = %s",
                       formatLayerInfo(layer, weight).c_str(), to_string(*mode).c_str(),
-                      to_string(*mActiveModeIt->second).c_str());
+                      to_string(activeMode).c_str());
                 continue;
             }
 
@@ -413,7 +416,7 @@
             const bool isInPolicyForDefault = mode->getGroup() == anchorGroup;
             if (layer.seamlessness == Seamlessness::Default && !isInPolicyForDefault) {
                 ALOGV("%s ignores %s. Current mode = %s", formatLayerInfo(layer, weight).c_str(),
-                      to_string(*mode).c_str(), to_string(*mActiveModeIt->second).c_str());
+                      to_string(*mode).c_str(), to_string(activeMode).c_str());
                 continue;
             }
 
@@ -676,7 +679,7 @@
 
     const DisplayModePtr& current = desiredActiveModeId
             ? mDisplayModes.get(*desiredActiveModeId)->get()
-            : mActiveModeIt->second;
+            : getActiveModeItLocked()->second;
 
     const DisplayModePtr& min = mMinRefreshRateModeIt->second;
     if (current == min) {
@@ -688,16 +691,17 @@
 }
 
 const DisplayModePtr& RefreshRateConfigs::getMinRefreshRateByPolicyLocked() const {
+    const auto& activeMode = *getActiveModeItLocked()->second;
+
     for (const DisplayModeIterator modeIt : mPrimaryRefreshRates) {
         const auto& mode = modeIt->second;
-        if (mActiveModeIt->second->getGroup() == mode->getGroup()) {
+        if (activeMode.getGroup() == mode->getGroup()) {
             return mode;
         }
     }
 
-    ALOGE("Can't find min refresh rate by policy with the same mode group"
-          " as the current mode %s",
-          to_string(*mActiveModeIt->second).c_str());
+    ALOGE("Can't find min refresh rate by policy with the same mode group as the current mode %s",
+          to_string(activeMode).c_str());
 
     // Default to the lowest refresh rate.
     return mPrimaryRefreshRates.front()->second;
@@ -708,6 +712,11 @@
     return getMaxRefreshRateByPolicyLocked();
 }
 
+const DisplayModePtr& RefreshRateConfigs::getMaxRefreshRateByPolicyLocked() const {
+    const int anchorGroup = getActiveModeItLocked()->second->getGroup();
+    return getMaxRefreshRateByPolicyLocked(anchorGroup);
+}
+
 const DisplayModePtr& RefreshRateConfigs::getMaxRefreshRateByPolicyLocked(int anchorGroup) const {
     for (auto it = mPrimaryRefreshRates.rbegin(); it != mPrimaryRefreshRates.rend(); ++it) {
         const auto& mode = (*it)->second;
@@ -716,17 +725,28 @@
         }
     }
 
-    ALOGE("Can't find max refresh rate by policy with the same mode group"
-          " as the current mode %s",
-          to_string(*mActiveModeIt->second).c_str());
+    const auto& activeMode = *getActiveModeItLocked()->second;
+    ALOGE("Can't find max refresh rate by policy with the same mode group as the current mode %s",
+          to_string(activeMode).c_str());
 
     // Default to the highest refresh rate.
     return mPrimaryRefreshRates.back()->second;
 }
 
-DisplayModePtr RefreshRateConfigs::getActiveMode() const {
+DisplayModePtr RefreshRateConfigs::getActiveModePtr() const {
     std::lock_guard lock(mLock);
-    return mActiveModeIt->second;
+    return getActiveModeItLocked()->second;
+}
+
+const DisplayMode& RefreshRateConfigs::getActiveMode() const {
+    // Reads from kMainThreadContext do not require mLock.
+    ftl::FakeGuard guard(mLock);
+    return *mActiveModeIt->second;
+}
+
+DisplayModeIterator RefreshRateConfigs::getActiveModeItLocked() const {
+    // Reads under mLock do not require kMainThreadContext.
+    return FTL_FAKE_GUARD(kMainThreadContext, mActiveModeIt);
 }
 
 void RefreshRateConfigs::setActiveModeId(DisplayModeId modeId) {
@@ -744,7 +764,7 @@
                                        Config config)
       : mKnownFrameRates(constructKnownFrameRates(modes)), mConfig(config) {
     initializeIdleTimer();
-    updateDisplayModes(std::move(modes), activeModeId);
+    FTL_FAKE_GUARD(kMainThreadContext, updateDisplayModes(std::move(modes), activeModeId));
 }
 
 void RefreshRateConfigs::initializeIdleTimer() {
@@ -976,7 +996,7 @@
 
     std::lock_guard lock(mLock);
 
-    const auto activeModeId = mActiveModeIt->first;
+    const auto activeModeId = getActiveModeItLocked()->first;
     result += "   activeModeId="s;
     result += std::to_string(activeModeId.value());
 
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index a79002e..b2cfb03 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -31,6 +31,7 @@
 #include "DisplayHardware/HWComposer.h"
 #include "Scheduler/OneShotTimer.h"
 #include "Scheduler/StrongTyping.h"
+#include "ThreadContext.h"
 
 namespace android::scheduler {
 
@@ -207,8 +208,11 @@
     // uses the primary range, not the app request range.
     DisplayModePtr getMaxRefreshRateByPolicy() const EXCLUDES(mLock);
 
-    void setActiveModeId(DisplayModeId) EXCLUDES(mLock);
-    DisplayModePtr getActiveMode() const EXCLUDES(mLock);
+    void setActiveModeId(DisplayModeId) EXCLUDES(mLock) REQUIRES(kMainThreadContext);
+
+    // See mActiveModeIt for thread safety.
+    DisplayModePtr getActiveModePtr() const EXCLUDES(mLock);
+    const DisplayMode& getActiveMode() const REQUIRES(kMainThreadContext);
 
     // Returns a known frame rate that is the closest to frameRate
     Fps findClosestKnownFrameRate(Fps frameRate) const;
@@ -332,6 +336,9 @@
 
     void constructAvailableRefreshRates() REQUIRES(mLock);
 
+    // See mActiveModeIt for thread safety.
+    DisplayModeIterator getActiveModeItLocked() const REQUIRES(mLock);
+
     std::pair<DisplayModePtr, GlobalSignals> getBestRefreshRateLocked(
             const std::vector<LayerRequirement>&, GlobalSignals) const REQUIRES(mLock);
 
@@ -345,10 +352,8 @@
 
     // Returns the highest refresh rate according to the current policy. May change at runtime. Only
     // uses the primary range, not the app request range.
+    const DisplayModePtr& getMaxRefreshRateByPolicyLocked() const REQUIRES(mLock);
     const DisplayModePtr& getMaxRefreshRateByPolicyLocked(int anchorGroup) const REQUIRES(mLock);
-    const DisplayModePtr& getMaxRefreshRateByPolicyLocked() const REQUIRES(mLock) {
-        return getMaxRefreshRateByPolicyLocked(mActiveModeIt->second->getGroup());
-    }
 
     const Policy* getCurrentPolicyLocked() const REQUIRES(mLock);
     bool isPolicyValidLocked(const Policy& policy) const REQUIRES(mLock);
@@ -361,7 +366,8 @@
     float calculateNonExactMatchingLayerScoreLocked(const LayerRequirement&, Fps refreshRate) const
             REQUIRES(mLock);
 
-    void updateDisplayModes(DisplayModes, DisplayModeId activeModeId) EXCLUDES(mLock);
+    void updateDisplayModes(DisplayModes, DisplayModeId activeModeId) EXCLUDES(mLock)
+            REQUIRES(kMainThreadContext);
 
     void initializeIdleTimer();
 
@@ -377,7 +383,10 @@
     // is also dependent, so must be reset as well.
     DisplayModes mDisplayModes GUARDED_BY(mLock);
 
-    DisplayModeIterator mActiveModeIt GUARDED_BY(mLock);
+    // Written under mLock exclusively from kMainThreadContext, so reads from kMainThreadContext
+    // need not be under mLock.
+    DisplayModeIterator mActiveModeIt GUARDED_BY(mLock) GUARDED_BY(kMainThreadContext);
+
     DisplayModeIterator mMinRefreshRateModeIt GUARDED_BY(mLock);
     DisplayModeIterator mMaxRefreshRateModeIt GUARDED_BY(mLock);
 
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 55ae013..bec39a7 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -182,7 +182,7 @@
 
 impl::EventThread::GetVsyncPeriodFunction Scheduler::makeGetVsyncPeriodFunction() const {
     return [this](uid_t uid) {
-        const Fps refreshRate = holdRefreshRateConfigs()->getActiveMode()->getFps();
+        const Fps refreshRate = holdRefreshRateConfigs()->getActiveModePtr()->getFps();
         const nsecs_t currentPeriod = mVsyncSchedule->period().ns() ?: refreshRate.getPeriodNsecs();
 
         const auto frameRate = getFrameRateOverride(uid);
@@ -320,7 +320,7 @@
     // mode change is in progress. In that case we shouldn't dispatch an event
     // as it will be dispatched when the current mode changes.
     if (std::scoped_lock lock(mRefreshRateConfigsLock);
-        mRefreshRateConfigs->getActiveMode() != mPolicy.mode) {
+        mRefreshRateConfigs->getActiveModePtr() != mPolicy.mode) {
         return;
     }
 
@@ -453,7 +453,7 @@
     if (now - last > kIgnoreDelay) {
         const auto refreshRate = [&] {
             std::scoped_lock lock(mRefreshRateConfigsLock);
-            return mRefreshRateConfigs->getActiveMode()->getFps();
+            return mRefreshRateConfigs->getActiveModePtr()->getFps();
         }();
         resyncToHardwareVsync(false, refreshRate);
     }
@@ -577,7 +577,7 @@
     // magic number
     const Fps refreshRate = [&] {
         std::scoped_lock lock(mRefreshRateConfigsLock);
-        return mRefreshRateConfigs->getActiveMode()->getFps();
+        return mRefreshRateConfigs->getActiveModePtr()->getFps();
     }();
 
     constexpr Fps FPS_THRESHOLD_FOR_KERNEL_TIMER = 65_Hz;
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index eb3856d..afb3459 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -229,7 +229,7 @@
 
     nsecs_t getVsyncPeriodFromRefreshRateConfigs() const EXCLUDES(mRefreshRateConfigsLock) {
         std::scoped_lock lock(mRefreshRateConfigsLock);
-        return mRefreshRateConfigs->getActiveMode()->getFps().getPeriodNsecs();
+        return mRefreshRateConfigs->getActiveModePtr()->getFps().getPeriodNsecs();
     }
 
     // Returns the framerate of the layer with the given sequence ID
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index ca578e1..78eaa14 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1157,9 +1157,7 @@
         return;
     }
 
-    const auto upcomingModeInfo =
-            FTL_FAKE_GUARD(kMainThreadContext, display->getUpcomingActiveMode());
-
+    const auto upcomingModeInfo = display->getUpcomingActiveMode();
     if (!upcomingModeInfo.mode) {
         // There is no pending mode change. This can happen if the active
         // display changed and the mode change happened on a different display.
@@ -1273,9 +1271,8 @@
         constraints.seamlessRequired = false;
         hal::VsyncPeriodChangeTimeline outTimeline;
 
-        const auto status = FTL_FAKE_GUARD(kMainThreadContext,
-                                           display->initiateModeChange(*desiredActiveMode,
-                                                                       constraints, &outTimeline));
+        const auto status =
+                display->initiateModeChange(*desiredActiveMode, constraints, &outTimeline);
 
         if (status != NO_ERROR) {
             // initiateModeChange may fail if a hotplug event is just about
@@ -2161,7 +2158,7 @@
     // Hold mStateLock as chooseRefreshRateForContent promotes wp<Layer> to sp<Layer>
     // and may eventually call to ~Layer() if it holds the last reference
     {
-        Mutex::Autolock _l(mStateLock);
+        Mutex::Autolock lock(mStateLock);
         mScheduler->chooseRefreshRateForContent();
         setActiveModeInHwcIfNeeded();
     }
@@ -3060,9 +3057,10 @@
         }
     }
 }
+
 void SurfaceFlinger::updateInternalDisplayVsyncLocked(const sp<DisplayDevice>& activeDisplay) {
     mVsyncConfiguration->reset();
-    const Fps refreshRate = activeDisplay->refreshRateConfigs().getActiveMode()->getFps();
+    const Fps refreshRate = activeDisplay->refreshRateConfigs().getActiveMode().getFps();
     updatePhaseConfiguration(refreshRate);
     mRefreshRateStats->setRefreshRate(refreshRate);
 }
@@ -4724,8 +4722,6 @@
     }
 }
 
-// ---------------------------------------------------------------------------
-
 void SurfaceFlinger::onInitializeDisplays() {
     const auto display = getDefaultDisplayDeviceLocked();
     if (!display) return;
@@ -4763,8 +4759,9 @@
 
 void SurfaceFlinger::initializeDisplays() {
     // Async since we may be called from the main thread.
-    static_cast<void>(
-            mScheduler->schedule([this]() FTL_FAKE_GUARD(mStateLock) { onInitializeDisplays(); }));
+    static_cast<void>(mScheduler->schedule(
+            [this]() FTL_FAKE_GUARD(mStateLock)
+                    FTL_FAKE_GUARD(kMainThreadContext) { onInitializeDisplays(); }));
 }
 
 void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal::PowerMode mode) {
@@ -4796,7 +4793,7 @@
     if (mInterceptor->isEnabled()) {
         mInterceptor->savePowerModeUpdate(display->getSequenceId(), static_cast<int32_t>(mode));
     }
-    const auto refreshRate = display->refreshRateConfigs().getActiveMode()->getFps();
+    const auto refreshRate = display->refreshRateConfigs().getActiveMode().getFps();
     if (*currentMode == hal::PowerMode::OFF) {
         // Turn on the display
         if (isInternalDisplay && (!activeDisplay || !activeDisplay->isPoweredOn())) {
@@ -4870,7 +4867,8 @@
 }
 
 void SurfaceFlinger::setPowerMode(const sp<IBinder>& displayToken, int mode) {
-    auto future = mScheduler->schedule([=]() FTL_FAKE_GUARD(mStateLock) {
+    auto future = mScheduler->schedule([=]() FTL_FAKE_GUARD(mStateLock) FTL_FAKE_GUARD(
+                                               kMainThreadContext) {
         const auto display = getDisplayDeviceLocked(displayToken);
         if (!display) {
             ALOGE("Attempt to set power mode %d for invalid display token %p", mode,
@@ -7021,7 +7019,7 @@
         refreshRate = *frameRateOverride;
     } else if (!getHwComposer().isHeadless()) {
         if (const auto display = FTL_FAKE_GUARD(mStateLock, getDefaultDisplayDeviceLocked())) {
-            refreshRate = display->refreshRateConfigs().getActiveMode()->getFps();
+            refreshRate = display->refreshRateConfigs().getActiveModePtr()->getFps();
         }
     }
 
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 2af17e7..f7684a0 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -648,22 +648,20 @@
     // Show spinner with refresh rate overlay
     bool mRefreshRateOverlaySpinner = false;
 
-    // Called on the main thread in response to initializeDisplays()
-    void onInitializeDisplays() REQUIRES(mStateLock);
     // Sets the desired active mode bit. It obtains the lock, and sets mDesiredActiveMode.
     void setDesiredActiveMode(const ActiveModeInfo& info) REQUIRES(mStateLock);
     status_t setActiveModeFromBackdoor(const sp<display::DisplayToken>&, DisplayModeId);
     // Sets the active mode and a new refresh rate in SF.
-    void updateInternalStateWithChangedMode() REQUIRES(mStateLock);
+    void updateInternalStateWithChangedMode() REQUIRES(mStateLock, kMainThreadContext);
     // Calls to setActiveMode on the main thread if there is a pending mode change
     // that needs to be applied.
-    void setActiveModeInHwcIfNeeded() REQUIRES(mStateLock);
+    void setActiveModeInHwcIfNeeded() REQUIRES(mStateLock, kMainThreadContext);
     void clearDesiredActiveModeState(const sp<DisplayDevice>&) REQUIRES(mStateLock);
     // Called when active mode is no longer is progress
     void desiredActiveModeChangeDone(const sp<DisplayDevice>&) REQUIRES(mStateLock);
     // Called on the main thread in response to setPowerMode()
     void setPowerModeInternal(const sp<DisplayDevice>& display, hal::PowerMode mode)
-            REQUIRES(mStateLock);
+            REQUIRES(mStateLock, kMainThreadContext);
 
     // Returns true if the display has a visible HDR layer in its layer stack.
     bool hasVisibleHdrLayer(const sp<DisplayDevice>& display) REQUIRES(mStateLock);
@@ -680,8 +678,9 @@
             const std::optional<scheduler::RefreshRateConfigs::Policy>& policy, bool overridePolicy)
             EXCLUDES(mStateLock);
 
-    void commitTransactions() EXCLUDES(mStateLock);
-    void commitTransactionsLocked(uint32_t transactionFlags) REQUIRES(mStateLock);
+    void commitTransactions() EXCLUDES(mStateLock) REQUIRES(kMainThreadContext);
+    void commitTransactionsLocked(uint32_t transactionFlags)
+            REQUIRES(mStateLock, kMainThreadContext);
     void doCommitTransactions() REQUIRES(mStateLock);
 
     // Returns whether a new buffer has been latched.
@@ -824,8 +823,10 @@
     /*
      * Display and layer stack management
      */
-    // called when starting, or restarting after system_server death
+
+    // Called during boot, and restart after system_server death.
     void initializeDisplays();
+    void onInitializeDisplays() REQUIRES(mStateLock, kMainThreadContext);
 
     bool isDisplayActiveLocked(const sp<const DisplayDevice>& display) const REQUIRES(mStateLock) {
         return display->getDisplayToken() == mActiveDisplayToken;
@@ -957,11 +958,12 @@
             const DisplayDeviceState& state,
             const sp<compositionengine::DisplaySurface>& displaySurface,
             const sp<IGraphicBufferProducer>& producer) REQUIRES(mStateLock);
-    void processDisplayChangesLocked() REQUIRES(mStateLock);
+    void processDisplayChangesLocked() REQUIRES(mStateLock, kMainThreadContext);
     void processDisplayRemoved(const wp<IBinder>& displayToken) REQUIRES(mStateLock);
     void processDisplayChanged(const wp<IBinder>& displayToken,
                                const DisplayDeviceState& currentState,
-                               const DisplayDeviceState& drawingState) REQUIRES(mStateLock);
+                               const DisplayDeviceState& drawingState)
+            REQUIRES(mStateLock, kMainThreadContext);
 
     void dispatchDisplayHotplugEvent(PhysicalDisplayId displayId, bool connected);
 
@@ -1022,7 +1024,8 @@
     VirtualDisplayId acquireVirtualDisplay(ui::Size, ui::PixelFormat) REQUIRES(mStateLock);
     void releaseVirtualDisplay(VirtualDisplayId);
 
-    void onActiveDisplayChangedLocked(const sp<DisplayDevice>& activeDisplay) REQUIRES(mStateLock);
+    void onActiveDisplayChangedLocked(const sp<DisplayDevice>& activeDisplay)
+            REQUIRES(mStateLock, kMainThreadContext);
 
     void onActiveDisplaySizeChanged(const sp<DisplayDevice>& activeDisplay);
 
@@ -1096,7 +1099,7 @@
     int getMaxAcquiredBufferCountForRefreshRate(Fps refreshRate) const;
 
     void updateInternalDisplayVsyncLocked(const sp<DisplayDevice>& activeDisplay)
-            REQUIRES(mStateLock);
+            REQUIRES(mStateLock, kMainThreadContext);
 
     bool isHdrLayer(Layer* layer) const;
 
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp
index 28b875a..79112bd 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp
@@ -237,7 +237,8 @@
 
     mTestableFlinger.enableHalVirtualDisplays(mFdp.ConsumeBool());
 
-    mTestableFlinger.commitTransactionsLocked(mFdp.ConsumeIntegral<uint32_t>());
+    FTL_FAKE_GUARD(kMainThreadContext,
+                   mTestableFlinger.commitTransactionsLocked(mFdp.ConsumeIntegral<uint32_t>()));
 
     mTestableFlinger.notifyPowerBoost(mFdp.ConsumeIntegral<int32_t>());
 
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
index 3aa3633..a861263 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
@@ -600,14 +600,18 @@
         mFlinger->binderDied(display);
         mFlinger->onFirstRef();
 
-        mFlinger->commitTransactions();
         mFlinger->updateInputFlinger();
         mFlinger->updateCursorAsync();
 
         setVsyncConfig(&mFdp);
 
-        FTL_FAKE_GUARD(kMainThreadContext,
-                       mFlinger->flushTransactionQueues(getFuzzedVsyncId(mFdp)));
+        {
+            ftl::FakeGuard guard(kMainThreadContext);
+
+            mFlinger->commitTransactions();
+            mFlinger->flushTransactionQueues(getFuzzedVsyncId(mFdp));
+            mFlinger->postComposition();
+        }
 
         mFlinger->setTransactionFlags(mFdp.ConsumeIntegral<uint32_t>());
         mFlinger->clearTransactionFlags(mFdp.ConsumeIntegral<uint32_t>());
@@ -624,8 +628,6 @@
 
         mFlinger->getMaxAcquiredBufferCountForCurrentRefreshRate(mFdp.ConsumeIntegral<uid_t>());
 
-        FTL_FAKE_GUARD(kMainThreadContext, mFlinger->postComposition());
-
         mFlinger->calculateExpectedPresentTime({});
 
         mFlinger->enableHalVirtualDisplays(mFdp.ConsumeBool());
@@ -664,7 +666,8 @@
         }
 
         mRefreshRateConfigs = std::make_shared<scheduler::RefreshRateConfigs>(modes, kModeId60);
-        const auto fps = mRefreshRateConfigs->getActiveMode()->getFps();
+        const auto fps =
+                FTL_FAKE_GUARD(kMainThreadContext, mRefreshRateConfigs->getActiveMode().getFps());
         mFlinger->mVsyncConfiguration = mFactory.createVsyncConfiguration(fps);
         mFlinger->mVsyncModulator = sp<scheduler::VsyncModulator>::make(
                 mFlinger->mVsyncConfiguration->getCurrentConfigs());
@@ -715,9 +718,9 @@
 
     void enableHalVirtualDisplays(bool enable) { mFlinger->enableHalVirtualDisplays(enable); }
 
-    auto commitTransactionsLocked(uint32_t transactionFlags) {
+    void commitTransactionsLocked(uint32_t transactionFlags) FTL_FAKE_GUARD(kMainThreadContext) {
         Mutex::Autolock lock(mFlinger->mStateLock);
-        return mFlinger->commitTransactionsLocked(transactionFlags);
+        mFlinger->commitTransactionsLocked(transactionFlags);
     }
 
     auto setDisplayStateLocked(const DisplayState &s) {
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
index 9584492..3fc2b7e 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
@@ -366,7 +366,7 @@
             {modeId,
              {Fps::fromValue(mFdp.ConsumeFloatingPoint<float>()),
               Fps::fromValue(mFdp.ConsumeFloatingPoint<float>())}});
-    refreshRateConfigs.setActiveModeId(modeId);
+    FTL_FAKE_GUARD(kMainThreadContext, refreshRateConfigs.setActiveModeId(modeId));
 
     RefreshRateConfigs::isFractionalPairOrMultiple(Fps::fromValue(
                                                            mFdp.ConsumeFloatingPoint<float>()),
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
index 188fd58..4f20932 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
@@ -18,6 +18,7 @@
 #define LOG_TAG "SchedulerUnittests"
 
 #include <ftl/enum.h>
+#include <ftl/fake_guard.h>
 #include <gmock/gmock.h>
 #include <log/log.h>
 #include <ui/Size.h>
@@ -41,6 +42,16 @@
 struct TestableRefreshRateConfigs : RefreshRateConfigs {
     using RefreshRateConfigs::RefreshRateConfigs;
 
+    void setActiveModeId(DisplayModeId modeId) {
+        ftl::FakeGuard guard(kMainThreadContext);
+        return RefreshRateConfigs::setActiveModeId(modeId);
+    }
+
+    const DisplayMode& getActiveMode() const {
+        ftl::FakeGuard guard(kMainThreadContext);
+        return RefreshRateConfigs::getActiveMode();
+    }
+
     DisplayModePtr getMinSupportedRefreshRate() const {
         std::lock_guard lock(mLock);
         return mMinRefreshRateModeIt->second;
@@ -243,20 +254,20 @@
 TEST_F(RefreshRateConfigsTest, twoModes_getActiveMode) {
     TestableRefreshRateConfigs configs(kModes_60_90, kModeId60);
     {
-        const auto mode = configs.getActiveMode();
-        EXPECT_EQ(mode->getId(), kModeId60);
+        const auto& mode = configs.getActiveMode();
+        EXPECT_EQ(mode.getId(), kModeId60);
     }
 
     configs.setActiveModeId(kModeId90);
     {
-        const auto mode = configs.getActiveMode();
-        EXPECT_EQ(mode->getId(), kModeId90);
+        const auto& mode = configs.getActiveMode();
+        EXPECT_EQ(mode.getId(), kModeId90);
     }
 
     EXPECT_GE(configs.setDisplayManagerPolicy({kModeId90, {90_Hz, 90_Hz}}), 0);
     {
-        const auto mode = configs.getActiveMode();
-        EXPECT_EQ(mode->getId(), kModeId90);
+        const auto& mode = configs.getActiveMode();
+        EXPECT_EQ(mode.getId(), kModeId90);
     }
 }
 
@@ -1898,30 +1909,30 @@
 }
 
 TEST_F(RefreshRateConfigsTest, getFrameRateDivisor) {
-    RefreshRateConfigs configs(kModes_30_60_72_90_120, kModeId30);
+    TestableRefreshRateConfigs configs(kModes_30_60_72_90_120, kModeId30);
 
     const auto frameRate = 30_Hz;
-    Fps displayRefreshRate = configs.getActiveMode()->getFps();
+    Fps displayRefreshRate = configs.getActiveMode().getFps();
     EXPECT_EQ(1, RefreshRateConfigs::getFrameRateDivisor(displayRefreshRate, frameRate));
 
     configs.setActiveModeId(kModeId60);
-    displayRefreshRate = configs.getActiveMode()->getFps();
+    displayRefreshRate = configs.getActiveMode().getFps();
     EXPECT_EQ(2, RefreshRateConfigs::getFrameRateDivisor(displayRefreshRate, frameRate));
 
     configs.setActiveModeId(kModeId72);
-    displayRefreshRate = configs.getActiveMode()->getFps();
+    displayRefreshRate = configs.getActiveMode().getFps();
     EXPECT_EQ(0, RefreshRateConfigs::getFrameRateDivisor(displayRefreshRate, frameRate));
 
     configs.setActiveModeId(kModeId90);
-    displayRefreshRate = configs.getActiveMode()->getFps();
+    displayRefreshRate = configs.getActiveMode().getFps();
     EXPECT_EQ(3, RefreshRateConfigs::getFrameRateDivisor(displayRefreshRate, frameRate));
 
     configs.setActiveModeId(kModeId120);
-    displayRefreshRate = configs.getActiveMode()->getFps();
+    displayRefreshRate = configs.getActiveMode().getFps();
     EXPECT_EQ(4, RefreshRateConfigs::getFrameRateDivisor(displayRefreshRate, frameRate));
 
     configs.setActiveModeId(kModeId90);
-    displayRefreshRate = configs.getActiveMode()->getFps();
+    displayRefreshRate = configs.getActiveMode().getFps();
     EXPECT_EQ(4, RefreshRateConfigs::getFrameRateDivisor(displayRefreshRate, 22.5_Hz));
 
     EXPECT_EQ(0, RefreshRateConfigs::getFrameRateDivisor(24_Hz, 25_Hz));
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index a6b3f7c..f8fdb65 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -223,7 +223,7 @@
             configs = std::make_shared<scheduler::RefreshRateConfigs>(modes, kModeId60);
         }
 
-        const auto fps = configs->getActiveMode()->getFps();
+        const auto fps = FTL_FAKE_GUARD(kMainThreadContext, configs->getActiveMode().getFps());
         mFlinger->mVsyncConfiguration = mFactory.createVsyncConfiguration(fps);
         mFlinger->mVsyncModulator = sp<scheduler::VsyncModulator>::make(
                 mFlinger->mVsyncConfiguration->getCurrentConfigs());
@@ -371,6 +371,7 @@
 
     void commitTransactionsLocked(uint32_t transactionFlags) {
         Mutex::Autolock lock(mFlinger->mStateLock);
+        ftl::FakeGuard guard(kMainThreadContext);
         mFlinger->commitTransactionsLocked(transactionFlags);
     }
 
@@ -464,6 +465,7 @@
 
     void onActiveDisplayChanged(const sp<DisplayDevice>& activeDisplay) {
         Mutex::Autolock lock(mFlinger->mStateLock);
+        ftl::FakeGuard guard(kMainThreadContext);
         mFlinger->onActiveDisplayChangedLocked(activeDisplay);
     }