[SurfaceFlinger] fix permanently enabling early offsets.
* Add notion of intended period in DispSync, and use that to detect
whether the simulated period will be changed.
* Propagate that signal to setDesiredActiveConfig, so that we don't fall
into early offsets unnecessarily, which can cause early offsets to
always be enabled.
Bug: 132678707
Test: systrace
Test: swappy test app
Test: scrolling through google news
Change-Id: I18df1b9d949cd534ecbf1c8891b6f88eab8be399
(cherry picked from commit f8e689cfd25f27c4af36a27e145d4cac1d0bb9cb)
Merged-In: I18df1b9d949cd534ecbf1c8891b6f88eab8be399
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 0cf84a9..6d73104 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -940,9 +940,14 @@
// Start receiving vsync samples now, so that we can detect a period
// switch.
mScheduler->resyncToHardwareVsync(true, getVsyncPeriod());
+ // We should only move to early offsets when we know that the refresh
+ // rate will change. Otherwise, we may be stuck in early offsets
+ // forever, as onRefreshRateChangeDetected will not be called.
+ if (mDesiredActiveConfig.event == Scheduler::ConfigEvent::Changed) {
+ mVsyncModulator.onRefreshRateChangeInitiated();
+ }
mPhaseOffsets->setRefreshRateType(info.type);
const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
- mVsyncModulator.onRefreshRateChangeInitiated();
mVsyncModulator.setPhaseOffsets(early, gl, late);
}
mDesiredActiveConfigChanged = true;
@@ -1019,6 +1024,10 @@
std::lock_guard<std::mutex> lock(mActiveConfigLock);
mDesiredActiveConfig.event = Scheduler::ConfigEvent::None;
mDesiredActiveConfigChanged = false;
+ // Update scheduler with the correct vsync period as a no-op.
+ // Otherwise, there exists a race condition where we get stuck in the
+ // incorrect vsync period.
+ mScheduler->resyncToHardwareVsync(false, getVsyncPeriod());
ATRACE_INT("DesiredActiveConfigChanged", mDesiredActiveConfigChanged);
return false;
}
@@ -1031,6 +1040,10 @@
mDesiredActiveConfig.event = Scheduler::ConfigEvent::None;
mDesiredActiveConfig.configId = display->getActiveConfig();
mDesiredActiveConfigChanged = false;
+ // Update scheduler with the current vsync period as a no-op.
+ // Otherwise, there exists a race condition where we get stuck in the
+ // incorrect vsync period.
+ mScheduler->resyncToHardwareVsync(false, getVsyncPeriod());
ATRACE_INT("DesiredActiveConfigChanged", mDesiredActiveConfigChanged);
return false;
}
@@ -1454,10 +1467,10 @@
return;
}
- bool periodChanged = false;
- mScheduler->addResyncSample(timestamp, &periodChanged);
- if (periodChanged) {
- mVsyncModulator.onRefreshRateChangeDetected();
+ bool periodFlushed = false;
+ mScheduler->addResyncSample(timestamp, &periodFlushed);
+ if (periodFlushed) {
+ mVsyncModulator.onRefreshRateChangeCompleted();
}
}