SF: Complete mode change immediately if refresh is not required
Bug: 190982486
Test: atest libsurfaceflinger_unittest
Change-Id: I4be91274c6570c5e9304098d5d6c3d30c41c4e6e
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 095d5a8..9f0ab02 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1201,6 +1201,8 @@
void SurfaceFlinger::setActiveModeInHwcIfNeeded() {
ATRACE_CALL();
+ std::optional<PhysicalDisplayId> displayToUpdateImmediately;
+
for (const auto& iter : mDisplays) {
const auto& display = iter.second;
if (!display || !display->isInternal()) {
@@ -1265,8 +1267,26 @@
}
mScheduler->onNewVsyncPeriodChangeTimeline(outTimeline);
- // Scheduler will submit an empty frame to HWC if needed.
- mSetActiveModePending = true;
+ if (outTimeline.refreshRequired) {
+ // Scheduler will submit an empty frame to HWC.
+ mSetActiveModePending = true;
+ } else {
+ // Updating the internal state should be done outside the loop,
+ // because it can recreate a DisplayDevice and modify mDisplays
+ // which will invalidate the iterator.
+ displayToUpdateImmediately = display->getPhysicalId();
+ }
+ }
+
+ if (displayToUpdateImmediately) {
+ updateInternalStateWithChangedMode();
+
+ const auto display = getDisplayDeviceLocked(*displayToUpdateImmediately);
+ const auto desiredActiveMode = display->getDesiredActiveMode();
+ if (desiredActiveMode &&
+ display->getActiveMode()->getId() == desiredActiveMode->mode->getId()) {
+ desiredActiveModeChangeDone(display);
+ }
}
}