SF: Clear layer history when inconclusive to frequent
layer transition
BUG: 265561529
Test: atest LayerHistoryTest
Benchmark shows improvement with the changes https://android-build.googleplex.com/builds/abtd/run/L82600000959656128
Change-Id: I152aa97f00592960411133de150990747ca8b31d
diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp
index 5a90d58..bae3739 100644
--- a/services/surfaceflinger/Scheduler/LayerInfo.cpp
+++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp
@@ -78,17 +78,16 @@
.count();
}
-bool LayerInfo::isFrequent(nsecs_t now) const {
- using fps_approx_ops::operator>=;
+LayerInfo::Frequent LayerInfo::isFrequent(nsecs_t now) const {
// If we know nothing about this layer (e.g. after touch event),
// we consider it as frequent as it might be the start of an animation.
if (mFrameTimes.size() < kFrequentLayerWindowSize) {
- return true;
+ return {/* isFrequent */ true, /* clearHistory */ false, /* isConclusive */ true};
}
// Non-active layers are also infrequent
if (mLastUpdatedTime < getActiveLayerThreshold(now)) {
- return false;
+ return {/* isFrequent */ false, /* clearHistory */ false, /* isConclusive */ true};
}
// We check whether we can classify this layer as frequent or infrequent:
@@ -111,12 +110,20 @@
}
if (isFrequent || isInfrequent) {
- return isFrequent;
+ // If the layer was previously inconclusive, we clear
+ // the history as indeterminate layers changed to frequent,
+ // and we should not look at the stale data.
+ return {isFrequent, isFrequent && !mIsFrequencyConclusive, /* isConclusive */ true};
}
// If we can't determine whether the layer is frequent or not, we return
- // the last known classification.
- return !mLastRefreshRate.infrequent;
+ // the last known classification and mark the layer frequency as inconclusive.
+ isFrequent = !mLastRefreshRate.infrequent;
+
+ // If the layer was previously tagged as animating, we clear
+ // the history as it is likely the layer just changed its behavior,
+ // and we should not look at stale data.
+ return {isFrequent, isFrequent && mLastRefreshRate.animating, /* isConclusive */ false};
}
Fps LayerInfo::getFps(nsecs_t now) const {
@@ -273,19 +280,18 @@
return {LayerHistory::LayerVoteType::Max, Fps()};
}
- if (!isFrequent(now)) {
+ const LayerInfo::Frequent frequent = isFrequent(now);
+ mIsFrequencyConclusive = frequent.isConclusive;
+ if (!frequent.isFrequent) {
ATRACE_FORMAT_INSTANT("infrequent");
ALOGV("%s is infrequent", mName.c_str());
mLastRefreshRate.infrequent = true;
- // Infrequent layers vote for mininal refresh rate for
+ // Infrequent layers vote for minimal refresh rate for
// battery saving purposes and also to prevent b/135718869.
return {LayerHistory::LayerVoteType::Min, Fps()};
}
- // If the layer was previously tagged as animating or infrequent, we clear
- // the history as it is likely the layer just changed its behavior
- // and we should not look at stale data
- if (mLastRefreshRate.animating || mLastRefreshRate.infrequent) {
+ if (frequent.clearHistory) {
clearHistory(now);
}
diff --git a/services/surfaceflinger/Scheduler/LayerInfo.h b/services/surfaceflinger/Scheduler/LayerInfo.h
index a3523ac..c5a6057 100644
--- a/services/surfaceflinger/Scheduler/LayerInfo.h
+++ b/services/surfaceflinger/Scheduler/LayerInfo.h
@@ -181,6 +181,7 @@
mFrameTimeValidSince = std::chrono::time_point<std::chrono::steady_clock>(timePoint);
mLastRefreshRate = {};
mRefreshRateHistory.clear();
+ mIsFrequencyConclusive = true;
}
void clearHistory(nsecs_t now) {
@@ -251,7 +252,15 @@
static constexpr float MARGIN_CONSISTENT_FPS = 1.0;
};
- bool isFrequent(nsecs_t now) const;
+ // Represents whether we were able to determine either layer is frequent or infrequent
+ bool mIsFrequencyConclusive = true;
+ struct Frequent {
+ bool isFrequent;
+ bool clearHistory;
+ // Represents whether we were able to determine isFrequent conclusively
+ bool isConclusive;
+ };
+ Frequent isFrequent(nsecs_t now) const;
bool isAnimating(nsecs_t now) const;
bool hasEnoughDataForHeuristic() const;
std::optional<Fps> calculateRefreshRateIfPossible(const RefreshRateSelector&, nsecs_t now);