SurfaceFlinger: clear LayerHistory on first touch
- Restructure the code in RefreshRateConfigs to be able to clear
LayerHistory frames on the first touch event. Without this change we
clear the history on every frame as long as the touch timer hasn't
expired.
- Add log prints for debugging
Test: Play 24fps video in YouTube PIP mode and rotate the device - no jank
Test: Chrome playing video - no refresh rate switching
Test: Hide/Show keyboard when inputting text
Test: Running Hay Day and observing refresh rate
Bug: 157096772
Change-Id: I7cabecd6ea27ec335e773aa22bb111fa8ec89195
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index dcce08d..7c2af23 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -527,7 +527,9 @@
void Scheduler::touchTimerCallback(TimerState state) {
const TouchState touch = state == TimerState::Reset ? TouchState::Active : TouchState::Inactive;
- handleTimerStateChanged(&mFeatures.touch, touch, true /* eventOnContentDetection */);
+ if (handleTimerStateChanged(&mFeatures.touch, touch, true /* eventOnContentDetection */)) {
+ mLayerHistory->clear();
+ }
ATRACE_INT("TouchState", static_cast<int>(touch));
}
@@ -550,18 +552,19 @@
}
template <class T>
-void Scheduler::handleTimerStateChanged(T* currentState, T newState, bool eventOnContentDetection) {
+bool Scheduler::handleTimerStateChanged(T* currentState, T newState, bool eventOnContentDetection) {
ConfigEvent event = ConfigEvent::None;
HwcConfigIndexType newConfigId;
+ bool touchConsidered = false;
{
std::lock_guard<std::mutex> lock(mFeatureStateLock);
if (*currentState == newState) {
- return;
+ return touchConsidered;
}
*currentState = newState;
- newConfigId = calculateRefreshRateConfigIndexType();
+ newConfigId = calculateRefreshRateConfigIndexType(&touchConsidered);
if (mFeatures.configId == newConfigId) {
- return;
+ return touchConsidered;
}
mFeatures.configId = newConfigId;
if (eventOnContentDetection && !mFeatures.contentRequirements.empty()) {
@@ -570,10 +573,12 @@
}
const RefreshRate& newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId);
mSchedulerCallback.changeRefreshRate(newRefreshRate, event);
+ return touchConsidered;
}
-HwcConfigIndexType Scheduler::calculateRefreshRateConfigIndexType() {
+HwcConfigIndexType Scheduler::calculateRefreshRateConfigIndexType(bool* touchConsidered) {
ATRACE_CALL();
+ if (touchConsidered) *touchConsidered = false;
// If Display Power is not in normal operation we want to be in performance mode. When coming
// back to normal mode, a grace period is given with DisplayPowerTimer.
@@ -608,18 +613,9 @@
.getConfigId();
}
- bool touchConsidered;
- const auto& ret = mRefreshRateConfigs
- .getBestRefreshRate(mFeatures.contentRequirements, touchActive, idle,
- &touchConsidered)
- .getConfigId();
- if (touchConsidered) {
- // Clear layer history if refresh rate was selected based on touch to allow
- // the hueristic to pick up with the new rate.
- mLayerHistory->clear();
- }
-
- return ret;
+ return mRefreshRateConfigs
+ .getBestRefreshRate(mFeatures.contentRequirements, touchActive, idle, touchConsidered)
+ .getConfigId();
}
std::optional<HwcConfigIndexType> Scheduler::getPreferredConfigId() {