SF: Isolate modesetting in DisplayModeController

Move the per-display state machine for modesetting from DisplayDevice to
DMC. In lieu of mStateLock, protect display lookup from multiple threads
using a mutex internal to DMC, which fixes the following deadlock:

OneShotTimer::loop
    SF::requestDisplayModes
    mStateLock

SF::commit
    mStateLock
    SF::processDisplayChangesLocked (hotplug or resolution change)
    Scheduler::demotePacesetterDisplay
    OneShotTimer::stop

A notable change is that {initiate,finalize}DisplayModeChange(s) are no
longer called under mStateLock, thanks to DMC's granular, internal lock.
finalizeDisplayModeChange still locks mStateLock for resolution changes.

Add an ActiveModeListener to DMC and register a callback in SF to update
the refresh rate overlay, which still lives in DisplayDevice for now.

Fixes: 329450361
Bug: 241285876
Test: DisplayModeControllerTest
Test: libsurfaceflinger_unittest
Change-Id: I30ec756f134d2d67a70ac8797008dc792eac035e
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 8c72a7d..007383b 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -191,6 +191,8 @@
     void setupComposer(std::unique_ptr<Hwc2::Composer> composer) {
         mFlinger->mCompositionEngine->setHwComposer(
                 std::make_unique<impl::HWComposer>(std::move(composer)));
+        mFlinger->mDisplayModeController.setHwComposer(
+                &mFlinger->mCompositionEngine->getHwComposer());
     }
 
     void setupPowerAdvisor(std::unique_ptr<Hwc2::PowerAdvisor> powerAdvisor) {
@@ -1055,7 +1057,6 @@
 
             auto& modes = mDisplayModes;
             auto& activeModeId = mActiveModeId;
-            std::optional<Fps> refreshRateOpt;
 
             DisplayDeviceState state;
             state.isSecure = mCreationArgs.isSecure;
@@ -1093,7 +1094,9 @@
 
                 const auto activeModeOpt = modes.get(activeModeId);
                 LOG_ALWAYS_FATAL_IF(!activeModeOpt);
-                refreshRateOpt = activeModeOpt->get()->getPeakFps();
+
+                // Save a copy for use after `modes` is consumed.
+                const Fps refreshRate = activeModeOpt->get()->getPeakFps();
 
                 state.physical = {.id = *physicalId,
                                   .hwcDisplayId = *mHwcDisplayId,
@@ -1109,6 +1112,9 @@
                         .registerDisplay(*physicalId, it->second.snapshot(),
                                          mCreationArgs.refreshRateSelector);
 
+                mFlinger.mutableDisplayModeController().setActiveMode(*physicalId, activeModeId,
+                                                                      refreshRate, refreshRate);
+
                 if (mFlinger.scheduler() && mSchedulerRegistration) {
                     mFlinger.scheduler()->registerDisplay(*physicalId,
                                                           mCreationArgs.refreshRateSelector,
@@ -1120,10 +1126,6 @@
             sp<DisplayDevice> display = sp<DisplayDevice>::make(mCreationArgs);
             mFlinger.mutableDisplays().emplace_or_replace(mDisplayToken, display);
 
-            if (refreshRateOpt) {
-                display->setActiveMode(activeModeId, *refreshRateOpt, *refreshRateOpt);
-            }
-
             mFlinger.mutableCurrentState().displays.add(mDisplayToken, state);
             mFlinger.mutableDrawingState().displays.add(mDisplayToken, state);