SurfaceFlinger: allow switching when layers vote to refresh rate

This CL is a refinement of the refresh rate switching algorithm
to allow refresh rate switching even if some of the layers voted
explicitly for a refresh rate.

Test: Run ExoPlayer demo app and scroll the list while playing a video
Bug: 147516364
Change-Id: Id01ff8477804bba9e859545e20b05eeb1ec0d319
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 71ac90e..3a44332 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -439,7 +439,7 @@
             return;
         }
         mFeatures.contentRequirements = summary;
-        mFeatures.contentDetection =
+        mFeatures.contentDetectionV1 =
                 !summary.empty() ? ContentDetectionState::On : ContentDetectionState::Off;
 
         newConfigId = calculateRefreshRateConfigIndexType();
@@ -466,7 +466,7 @@
     // NOTE: Instead of checking all the layers, we should be checking the layer
     // that is currently on top. b/142507166 will give us this capability.
     std::lock_guard<std::mutex> lock(mFeatureStateLock);
-    if (mLayerHistory && !layerHistoryHasClientSpecifiedFrameRate()) {
+    if (mLayerHistory) {
         mLayerHistory->clear();
 
         mTouchTimer->reset();
@@ -556,7 +556,7 @@
             return;
         }
         mFeatures.configId = newConfigId;
-        if (eventOnContentDetection && mFeatures.contentDetection == ContentDetectionState::On) {
+        if (eventOnContentDetection && !mFeatures.contentRequirements.empty()) {
             event = ConfigEvent::Changed;
         }
     }
@@ -564,33 +564,10 @@
     mSchedulerCallback.changeRefreshRate(newRefreshRate, event);
 }
 
-bool Scheduler::layerHistoryHasClientSpecifiedFrameRate() {
-    // Traverse all the layers to see if any of them requested frame rate.
-    for (const auto& layer : mFeatures.contentRequirements) {
-        if (layer.vote == scheduler::RefreshRateConfigs::LayerVoteType::ExplicitDefault ||
-            layer.vote == scheduler::RefreshRateConfigs::LayerVoteType::ExplicitExactOrMultiple) {
-            return true;
-        }
-    }
-
-    return false;
-}
-
 HwcConfigIndexType Scheduler::calculateRefreshRateConfigIndexType() {
-    // This block of the code checks whether any layers used the SetFrameRate API. If they have,
-    // their request should be honored depending on other active layers.
-    if (layerHistoryHasClientSpecifiedFrameRate()) {
-        if (!mUseContentDetectionV2) {
-            return mRefreshRateConfigs.getRefreshRateForContent(mFeatures.contentRequirements)
-                    .configId;
-        } else {
-            return mRefreshRateConfigs.getRefreshRateForContentV2(mFeatures.contentRequirements)
-                    .configId;
-        }
-    }
+    ATRACE_CALL();
 
-    // If the layer history doesn't have the frame rate specified, check for other features and
-    // honor them. NOTE: If we remove the kernel idle timer, and use our internal idle timer, this
+    // NOTE: If we remove the kernel idle timer, and use our internal idle timer, this
     // code will have to be refactored. 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.
@@ -600,9 +577,11 @@
         return mRefreshRateConfigs.getMaxRefreshRateByPolicy().configId;
     }
 
-    // As long as touch is active we want to be in performance mode.
-    if (mTouchTimer && mFeatures.touch == TouchState::Active) {
-        return mRefreshRateConfigs.getMaxRefreshRateByPolicy().configId;
+    if (!mUseContentDetectionV2) {
+        // As long as touch is active we want to be in performance mode.
+        if (mTouchTimer && mFeatures.touch == TouchState::Active) {
+            return mRefreshRateConfigs.getMaxRefreshRateByPolicy().configId;
+        }
     }
 
     // If timer has expired as it means there is no new content on the screen.
@@ -612,7 +591,7 @@
 
     if (!mUseContentDetectionV2) {
         // If content detection is off we choose performance as we don't know the content fps.
-        if (mFeatures.contentDetection == ContentDetectionState::Off) {
+        if (mFeatures.contentDetectionV1 == ContentDetectionState::Off) {
             // NOTE: V1 always calls this, but this is not a default behavior for V2.
             return mRefreshRateConfigs.getMaxRefreshRateByPolicy().configId;
         }
@@ -621,14 +600,10 @@
         return mRefreshRateConfigs.getRefreshRateForContent(mFeatures.contentRequirements).configId;
     }
 
-    // Content detection is on, find the appropriate refresh rate with minimal error
-    if (mFeatures.contentDetection == ContentDetectionState::On) {
-        return mRefreshRateConfigs.getRefreshRateForContentV2(mFeatures.contentRequirements)
-                .configId;
-    }
-
-    // There are no signals for refresh rate, just leave it as is.
-    return mRefreshRateConfigs.getCurrentRefreshRateByPolicy().configId;
+    return mRefreshRateConfigs
+            .getRefreshRateForContentV2(mFeatures.contentRequirements,
+                                        mTouchTimer && mFeatures.touch == TouchState::Active)
+            .configId;
 }
 
 std::optional<HwcConfigIndexType> Scheduler::getPreferredConfigId() {