SF: Fix mode setting for UDFPS with disabled AOD
When AOD is off, DM sends its policy to SF while the display is powered
off. SF defers applying the policy of powered off displays, assuming it
will be applied when the display becomes the active display upon power-
on, as a special case for foldables. However, in the case of UDFPS with
disabled AOD, there is no change in active display, so SF did not apply
the policy to switch to 120 Hz on the lockscreen.
Tighten the condition for skipping mode set to only affect foldables in
non-concurrent mode.
Fixes: 300189378
Test: 120 Hz for UDFPS when Smooth Display and AOD are disabled.
Test: 60/120 Hz still works on fold/unfold and concurrent mode.
Test: DisplayModeSwitchingTest.powerOffDuringModeSet
Change-Id: Iedd25f8caed69c1dd304ee9f6341dba6bcdc87d7
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 74d4e69..77ae03d 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1380,8 +1380,7 @@
continue;
}
- if (!display->isPoweredOn()) {
- // Display is no longer powered on, so abort the mode change.
+ if (!shouldApplyRefreshRateSelectorPolicy(*display)) {
clearDesiredActiveModeState(display);
continue;
}
@@ -3885,8 +3884,9 @@
if (!display) continue;
- if (!display->isPoweredOn()) {
- ALOGV("%s(%s): Display is powered off", __func__, to_string(displayId).c_str());
+ if (ftl::FakeGuard guard(kMainThreadContext);
+ !shouldApplyRefreshRateSelectorPolicy(*display)) {
+ ALOGV("%s(%s): Skipped applying policy", __func__, to_string(displayId).c_str());
continue;
}
@@ -7645,17 +7645,33 @@
break;
}
- // TODO(b/255635711): Apply the policy once the display is powered on, which is currently only
- // done for the internal display that becomes active on fold/unfold. For now, assume that DM
- // always powers on the secondary (internal or external) display before setting its policy.
- if (!display->isPoweredOn()) {
- ALOGV("%s(%s): Display is powered off", __func__, to_string(displayId).c_str());
+ if (!shouldApplyRefreshRateSelectorPolicy(*display)) {
+ ALOGV("%s(%s): Skipped applying policy", __func__, to_string(displayId).c_str());
return NO_ERROR;
}
return applyRefreshRateSelectorPolicy(displayId, selector);
}
+bool SurfaceFlinger::shouldApplyRefreshRateSelectorPolicy(const DisplayDevice& display) const {
+ if (display.isPoweredOn() || mPhysicalDisplays.size() == 1) return true;
+
+ LOG_ALWAYS_FATAL_IF(display.isVirtual());
+ const auto displayId = display.getPhysicalId();
+
+ // The display is powered off, and this is a multi-display device. If the display is the
+ // inactive internal display of a dual-display foldable, then the policy will be applied
+ // when it becomes active upon powering on.
+ //
+ // TODO(b/255635711): Remove this function (i.e. returning `false` as a special case) once
+ // concurrent mode setting across multiple (potentially powered off) displays is supported.
+ //
+ return displayId == mActiveDisplayId ||
+ !mPhysicalDisplays.get(displayId)
+ .transform(&PhysicalDisplay::isInternal)
+ .value_or(false);
+}
+
status_t SurfaceFlinger::applyRefreshRateSelectorPolicy(
PhysicalDisplayId displayId, const scheduler::RefreshRateSelector& selector, bool force) {
const scheduler::RefreshRateSelector::Policy currentPolicy = selector.getCurrentPolicy();