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);
     }