SF: move RefreshRateConfigs to DisplayDevice

Move RefreshRateConfigs to DisplayDevice to be able to maintain
a per-display refresh rate switching policy.

Test: SF unit tests
Test: refresh rate switching is working on device with
more than one display
Bug: 187539899

Change-Id: Ica6a955e8ad0e563a0740f6579b61fc592eb982c
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 18cb0c2..40e0ed6 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1073,7 +1073,13 @@
 
 void SurfaceFlinger::setDesiredActiveMode(const ActiveModeInfo& info) {
     ATRACE_CALL();
-    auto refreshRate = mRefreshRateConfigs->getRefreshRateFromModeId(info.modeId);
+    const auto display = getDefaultDisplayDeviceLocked();
+    if (!display) {
+        ALOGW("%s: default display is null", __func__);
+        return;
+    }
+
+    auto refreshRate = display->refreshRateConfigs().getRefreshRateFromModeId(info.modeId);
     ALOGV("%s(%s)", __func__, refreshRate.getName().c_str());
 
     std::lock_guard<std::mutex> lock(mActiveModeLock);
@@ -1084,8 +1090,7 @@
         mDesiredActiveMode.event = mDesiredActiveMode.event | prevConfig;
     } else {
         // Check if we are already at the desired mode
-        const auto display = getDefaultDisplayDeviceLocked();
-        if (!display || display->getActiveMode()->getId() == refreshRate.getModeId()) {
+        if (display->getActiveMode()->getId() == refreshRate.getModeId()) {
             return;
         }
 
@@ -1136,7 +1141,7 @@
         const auto fps = mode->getFps();
         // Keep the old switching type.
         const auto allowGroupSwitching =
-                mRefreshRateConfigs->getCurrentPolicy().allowGroupSwitching;
+                display->refreshRateConfigs().getCurrentPolicy().allowGroupSwitching;
         const scheduler::RefreshRateConfigs::Policy policy{mode->getId(),
                                                            allowGroupSwitching,
                                                            {fps, fps}};
@@ -1178,7 +1183,6 @@
     }
 
     std::lock_guard<std::mutex> lock(mActiveModeLock);
-    mRefreshRateConfigs->setCurrentModeId(mUpcomingActiveMode.modeId);
     display->setActiveMode(mUpcomingActiveMode.modeId);
 
     const Fps refreshRate = upcomingMode->getFps();
@@ -1744,7 +1748,12 @@
 }
 
 bool SurfaceFlinger::isDisplayModeAllowed(DisplayModeId modeId) const {
-    return mRefreshRateConfigs->isModeAllowed(modeId);
+    const auto display = getDefaultDisplayDeviceLocked();
+    if (display) {
+        return display->refreshRateConfigs().isModeAllowed(modeId);
+    }
+    ALOGW("%s: default display is null", __func__);
+    return false;
 }
 
 void SurfaceFlinger::changeRefreshRateLocked(const RefreshRate& refreshRate,
@@ -2470,7 +2479,6 @@
     // We call getTransactionFlags(), which will also clear the flags,
     // with mStateLock held to guarantee that mCurrentState won't change
     // until the transaction is committed.
-
     modulateVsync(&VsyncModulator::onTransactionCommit);
     transactionFlags = getTransactionFlags(eTransactionMask);
     handleTransactionLocked(transactionFlags);
@@ -2583,11 +2591,6 @@
                 sp<IBinder> token = new BBinder();
                 mCurrentState.displays.add(token, state);
                 mPhysicalDisplayTokens.emplace(displayId, std::move(token));
-
-                if (event.hwcDisplayId == getHwComposer().getInternalHwcDisplayId()) {
-                    initScheduler(state);
-                }
-
                 mInterceptor->saveDisplayCreation(state);
             } else {
                 ALOGV("Recreating display %s", to_string(displayId).c_str());
@@ -2642,6 +2645,14 @@
     if (const auto& physical = state.physical) {
         creationArgs.connectionType = physical->type;
         creationArgs.supportedModes = physical->supportedModes;
+        creationArgs.activeModeId = physical->activeMode->getId();
+        scheduler::RefreshRateConfigs::Config config =
+                {.enableFrameRateOverride = android::sysprop::enable_frame_rate_override(false),
+                 .frameRateMultipleThreshold =
+                         base::GetIntProperty("debug.sf.frame_rate_multiple_threshold", 0)};
+        creationArgs.refreshRateConfigs =
+                std::make_shared<scheduler::RefreshRateConfigs>(creationArgs.supportedModes,
+                                                                creationArgs.activeModeId, config);
     }
 
     if (const auto id = PhysicalDisplayId::tryCast(compositionDisplay->getId())) {
@@ -2780,6 +2791,9 @@
     const auto display = setupNewDisplayDeviceInternal(displayToken, std::move(compositionDisplay),
                                                        state, displaySurface, producer);
     mDisplays.emplace(displayToken, display);
+    if (display->isPrimary()) {
+        initScheduler(display);
+    }
     if (!state.isVirtual()) {
         dispatchDisplayHotplugEvent(display->getPhysicalId(), true);
     }
@@ -2847,8 +2861,7 @@
 
             // TODO(b/175678251) Call a listener instead.
             if (currentState.physical->hwcDisplayId == getHwComposer().getInternalHwcDisplayId()) {
-                updateInternalDisplayVsyncLocked(currentState.physical->supportedModes,
-                                                 currentState.physical->activeMode->getId());
+                updateInternalDisplayVsyncLocked(display);
             }
         }
         return;
@@ -2884,11 +2897,9 @@
         }
     }
 }
-void SurfaceFlinger::updateInternalDisplayVsyncLocked(const DisplayModes& modes,
-                                                      DisplayModeId currentModeId) {
-    mRefreshRateConfigs->updateDisplayModes(modes, currentModeId);
+void SurfaceFlinger::updateInternalDisplayVsyncLocked(const sp<DisplayDevice>& activeDisplay) {
     mVsyncConfiguration->reset();
-    const Fps refreshRate = mRefreshRateConfigs->getCurrentRefreshRate().getFps();
+    const Fps refreshRate = activeDisplay->refreshRateConfigs().getCurrentRefreshRate().getFps();
     updatePhaseConfiguration(refreshRate);
     mRefreshRateStats->setRefreshRate(refreshRate);
     if (mRefreshRateOverlay) {
@@ -3122,24 +3133,15 @@
     mScheduler->onFrameRateOverridesChanged(mAppConnectionHandle, displayId);
 }
 
-void SurfaceFlinger::initScheduler(const DisplayDeviceState& displayState) {
+void SurfaceFlinger::initScheduler(const sp<DisplayDevice>& display) {
     if (mScheduler) {
         // In practice it's not allowed to hotplug in/out the primary display once it's been
         // connected during startup, but some tests do it, so just warn and return.
         ALOGW("Can't re-init scheduler");
         return;
     }
-    const auto displayId = displayState.physical->id;
-    scheduler::RefreshRateConfigs::Config config =
-            {.enableFrameRateOverride = android::sysprop::enable_frame_rate_override(false),
-             .frameRateMultipleThreshold =
-                     base::GetIntProperty("debug.sf.frame_rate_multiple_threshold", 0)};
-    mRefreshRateConfigs =
-            std::make_unique<scheduler::RefreshRateConfigs>(displayState.physical->supportedModes,
-                                                            displayState.physical->activeMode
-                                                                    ->getId(),
-                                                            config);
-    const auto currRefreshRate = displayState.physical->activeMode->getFps();
+    const auto displayId = display->getId();
+    const auto currRefreshRate = display->getActiveMode()->getFps();
     mRefreshRateStats = std::make_unique<scheduler::RefreshRateStats>(*mTimeStats, currRefreshRate,
                                                                       hal::PowerMode::OFF);
 
@@ -3147,7 +3149,7 @@
     mVsyncModulator.emplace(mVsyncConfiguration->getCurrentConfigs());
 
     // start the EventThread
-    mScheduler = getFactory().createScheduler(*mRefreshRateConfigs, *this);
+    mScheduler = getFactory().createScheduler(display->holdRefreshRateConfigs(), *this);
     const auto configs = mVsyncConfiguration->getCurrentConfigs();
     const nsecs_t vsyncPeriod = currRefreshRate.getPeriodNsecs();
     mAppConnectionHandle =
@@ -3176,9 +3178,9 @@
     // This is a bit hacky, but this avoids a back-pointer into the main SF
     // classes from EventThread, and there should be no run-time binder cost
     // anyway since there are no connected apps at this point.
-    mScheduler->onPrimaryDisplayModeChanged(mAppConnectionHandle, displayId,
-                                            displayState.physical->activeMode->getId(),
-                                            vsyncPeriod);
+    mScheduler->onPrimaryDisplayModeChanged(mAppConnectionHandle,
+                                            *PhysicalDisplayId::tryCast(displayId),
+                                            display->getActiveMode()->getId(), vsyncPeriod);
     static auto ignorePresentFences =
             base::GetBoolProperty("debug.sf.vsync_reactor_ignore_present_fences"s, false);
     mScheduler->setIgnorePresentFences(
@@ -4496,7 +4498,8 @@
                           {}, getpid(), getuid(), 0 /* Undefined transactionId */);
 
     setPowerModeInternal(display, hal::PowerMode::ON);
-    const nsecs_t vsyncPeriod = mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod();
+    const nsecs_t vsyncPeriod =
+            display->refreshRateConfigs().getCurrentRefreshRate().getVsyncPeriod();
     mAnimFrameTracker.setDisplayRefreshPeriod(vsyncPeriod);
     mDefaultDisplayTransformHint = display->getTransformHint();
     // Use phase of 0 since phase is not known.
@@ -4549,7 +4552,7 @@
     if (mInterceptor->isEnabled()) {
         mInterceptor->savePowerModeUpdate(display->getSequenceId(), static_cast<int32_t>(mode));
     }
-    const auto vsyncPeriod = mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod();
+    const auto vsyncPeriod = display->refreshRateConfigs().getCurrentRefreshRate().getVsyncPeriod();
     if (currentMode == hal::PowerMode::OFF) {
         const auto activeDisplay = getDisplayDeviceLocked(mActiveDisplayToken);
         if (display->isInternal() && (!activeDisplay || !activeDisplay->isPoweredOn())) {
@@ -4781,8 +4784,6 @@
                   "      present offset: %9" PRId64 " ns\t     VSYNC period: %9" PRId64 " ns\n\n",
                   dispSyncPresentTimeOffset, getVsyncPeriodFromHWC());
 
-    mRefreshRateConfigs->dump(result);
-
     StringAppendF(&result, "(mode override by backdoor: %s)\n\n",
                   mDebugDisplayModeSetByBackdoor ? "yes" : "no");
 
@@ -5823,8 +5824,13 @@
                 desiredActiveMode ? std::make_optional(desiredActiveMode->modeId) : std::nullopt;
 
         const bool timerExpired = mKernelIdleTimerEnabled && expired;
+        const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked());
+        if (!display) {
+            ALOGW("%s: default display is null", __func__);
+            return;
+        }
         const auto newRefreshRate =
-                mRefreshRateConfigs->onKernelTimerChanged(desiredModeId, timerExpired);
+                display->refreshRateConfigs().onKernelTimerChanged(desiredModeId, timerExpired);
         if (newRefreshRate) {
             if (Mutex::Autolock lock(mStateLock); mRefreshRateOverlay) {
                 mRefreshRateOverlay->changeRefreshRate(*newRefreshRate);
@@ -5841,8 +5847,13 @@
     if (!mSupportKernelIdleTimer) {
         return;
     }
-    const KernelIdleTimerAction action = mRefreshRateConfigs->getIdleTimerAction();
+    const auto display = getDefaultDisplayDeviceLocked();
+    if (!display) {
+        ALOGW("%s: default display is null", __func__);
+        return;
+    }
 
+    const KernelIdleTimerAction action = display->refreshRateConfigs().getIdleTimerAction();
     switch (action) {
         case KernelIdleTimerAction::TurnOff:
             if (mKernelIdleTimerEnabled) {
@@ -6471,6 +6482,16 @@
         return NO_ERROR;
     }
 
+    status_t setPolicyResult = overridePolicy
+            ? display->refreshRateConfigs().setOverridePolicy(policy)
+            : display->refreshRateConfigs().setDisplayManagerPolicy(*policy);
+    if (setPolicyResult < 0) {
+        return BAD_VALUE;
+    }
+    if (setPolicyResult == scheduler::RefreshRateConfigs::CURRENT_POLICY_UNCHANGED) {
+        return NO_ERROR;
+    }
+
     if (!isDefaultDisplay) {
         // TODO(b/144711714): For non-default displays we should be able to set an active mode
         // as well. For now, just call directly to initiateModeChange but ideally
@@ -6497,16 +6518,8 @@
         return NO_ERROR;
     }
 
-    status_t setPolicyResult = overridePolicy
-            ? mRefreshRateConfigs->setOverridePolicy(policy)
-            : mRefreshRateConfigs->setDisplayManagerPolicy(*policy);
-    if (setPolicyResult < 0) {
-        return BAD_VALUE;
-    }
-    if (setPolicyResult == scheduler::RefreshRateConfigs::CURRENT_POLICY_UNCHANGED) {
-        return NO_ERROR;
-    }
-    scheduler::RefreshRateConfigs::Policy currentPolicy = mRefreshRateConfigs->getCurrentPolicy();
+    scheduler::RefreshRateConfigs::Policy currentPolicy =
+            display->refreshRateConfigs().getCurrentPolicy();
 
     ALOGV("Setting desired display mode specs: %s", currentPolicy.toString().c_str());
 
@@ -6519,11 +6532,9 @@
                                             vsyncPeriod);
     toggleKernelIdleTimer();
 
-    auto modeId = mScheduler->getPreferredModeId();
-    auto preferredRefreshRate = modeId
-            ? mRefreshRateConfigs->getRefreshRateFromModeId(*modeId)
-            // NOTE: Choose the default mode ID, if Scheduler doesn't have one in mind.
-            : mRefreshRateConfigs->getRefreshRateFromModeId(currentPolicy.defaultMode);
+    auto modeId = mScheduler->getPreferredModeId() ? *mScheduler->getPreferredModeId()
+                                                   : currentPolicy.defaultMode;
+    auto preferredRefreshRate = display->refreshRateConfigs().getRefreshRateFromModeId(modeId);
     ALOGV("trying to switch to Scheduler preferred mode %d (%s)",
           preferredRefreshRate.getModeId().value(), preferredRefreshRate.getName().c_str());
 
@@ -6593,29 +6604,19 @@
         return NAME_NOT_FOUND;
     }
 
-    if (display == getDefaultDisplayDeviceLocked()) {
-        scheduler::RefreshRateConfigs::Policy policy =
-                mRefreshRateConfigs->getDisplayManagerPolicy();
-        *outDefaultMode = policy.defaultMode.value();
-        *outAllowGroupSwitching = policy.allowGroupSwitching;
-        *outPrimaryRefreshRateMin = policy.primaryRange.min.getValue();
-        *outPrimaryRefreshRateMax = policy.primaryRange.max.getValue();
-        *outAppRequestRefreshRateMin = policy.appRequestRange.min.getValue();
-        *outAppRequestRefreshRateMax = policy.appRequestRange.max.getValue();
-        return NO_ERROR;
-    } else if (display->isVirtual()) {
+    if (display->isVirtual()) {
         return INVALID_OPERATION;
-    } else {
-        const auto activeMode = display->getActiveMode();
-        *outDefaultMode = activeMode->getId().value();
-        *outAllowGroupSwitching = false;
-        auto vsyncPeriod = activeMode->getVsyncPeriod();
-        *outPrimaryRefreshRateMin = Fps::fromPeriodNsecs(vsyncPeriod).getValue();
-        *outPrimaryRefreshRateMax = Fps::fromPeriodNsecs(vsyncPeriod).getValue();
-        *outAppRequestRefreshRateMin = Fps::fromPeriodNsecs(vsyncPeriod).getValue();
-        *outAppRequestRefreshRateMax = Fps::fromPeriodNsecs(vsyncPeriod).getValue();
-        return NO_ERROR;
     }
+
+    scheduler::RefreshRateConfigs::Policy policy =
+            display->refreshRateConfigs().getDisplayManagerPolicy();
+    *outDefaultMode = policy.defaultMode.value();
+    *outAllowGroupSwitching = policy.allowGroupSwitching;
+    *outPrimaryRefreshRateMin = policy.primaryRange.min.getValue();
+    *outPrimaryRefreshRateMax = policy.primaryRange.max.getValue();
+    *outAppRequestRefreshRateMin = policy.appRequestRange.min.getValue();
+    *outAppRequestRefreshRateMax = policy.appRequestRange.max.getValue();
+    return NO_ERROR;
 }
 
 wp<Layer> SurfaceFlinger::fromHandle(const sp<IBinder>& handle) {
@@ -6746,7 +6747,8 @@
             // matter for the override policy though, since we set allowGroupSwitching to
             // true, so it's not a problem.
             scheduler::RefreshRateConfigs::Policy overridePolicy;
-            overridePolicy.defaultMode = mRefreshRateConfigs->getDisplayManagerPolicy().defaultMode;
+            overridePolicy.defaultMode =
+                    display->refreshRateConfigs().getDisplayManagerPolicy().defaultMode;
             overridePolicy.allowGroupSwitching = true;
             constexpr bool kOverridePolicy = true;
             result = setDesiredDisplayModeSpecsInternal(display, overridePolicy, kOverridePolicy);
@@ -6860,7 +6862,14 @@
 }
 
 status_t SurfaceFlinger::getMaxAcquiredBufferCount(int* buffers) const {
-    const auto maxSupportedRefreshRate = mRefreshRateConfigs->getSupportedRefreshRateRange().max;
+    const auto maxSupportedRefreshRate = [&] {
+        const auto display = getDefaultDisplayDevice();
+        if (display) {
+            return display->refreshRateConfigs().getSupportedRefreshRateRange().max;
+        }
+        ALOGW("%s: default display is null", __func__);
+        return Fps(60);
+    }();
     *buffers = getMaxAcquiredBufferCountForRefreshRate(maxSupportedRefreshRate);
     return NO_ERROR;
 }
@@ -6871,7 +6880,14 @@
         if (frameRateOverride.has_value()) {
             return frameRateOverride.value();
         }
-        return mRefreshRateConfigs->getCurrentRefreshRate().getFps();
+
+        const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked());
+        if (display) {
+            return display->refreshRateConfigs().getCurrentRefreshRate().getFps();
+        }
+
+        ALOGW("%s: default display is null", __func__);
+        return Fps(60);
     }();
     return getMaxAcquiredBufferCountForRefreshRate(refreshRate);
 }
@@ -6999,8 +7015,8 @@
         ALOGE("%s: activeDisplay is null", __func__);
         return;
     }
-    updateInternalDisplayVsyncLocked(activeDisplay->getSupportedModes(),
-                                     activeDisplay->getActiveMode()->getId());
+    updateInternalDisplayVsyncLocked(activeDisplay);
+    mScheduler->setRefreshRateConfigs(activeDisplay->holdRefreshRateConfigs());
     onActiveDisplaySizeChanged(activeDisplay);
     if (mRefreshRateOverlay) {
         mRefreshRateOverlay->setViewport(activeDisplay->getSize());