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());