SurfaceFlinger: always consider layers with setFrameRate

If an app called to setFrameRate on a layer, consider it when choosing
the refresh rate, even if the layer has posted buffers.

Bug: 152411921
Test: adb shell /data/nativetest64/libsurfaceflinger_unittest/libsurfaceflinger_unittest
Change-Id: I01f139b34cee01255693ed274225e79d83b0f894
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 5039761..f9dff12 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1384,6 +1384,9 @@
         return false;
     }
 
+    // Activate the layer in Scheduler's LayerHistory
+    mFlinger->mScheduler->recordLayerHistory(this, systemTime());
+
     mCurrentState.sequence++;
     mCurrentState.frameRate = frameRate;
     mCurrentState.modified = true;
diff --git a/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp b/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp
index 8b08592..b067466 100644
--- a/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp
@@ -40,9 +40,11 @@
 namespace {
 
 bool isLayerActive(const Layer& layer, const LayerInfoV2& info, nsecs_t threshold) {
+    // Layers with an explicit vote are always kept active
     if (layer.getFrameRateForLayerTree().rate > 0) {
-        return layer.isVisible();
+        return true;
     }
+
     return layer.isVisible() && info.getLastUpdatedTime() >= threshold;
 }
 
@@ -127,29 +129,24 @@
         //  an additional parameter.
         ALOGV("Layer has priority: %d", strong->getFrameRateSelectionPriority());
 
-        const bool recent = info->isRecentlyActive(now);
-        if (recent) {
-            const auto [type, refreshRate] = info->getRefreshRate(now);
-            // Skip NoVote layer as those don't have any requirements
-            if (type == LayerHistory::LayerVoteType::NoVote) {
-                continue;
-            }
+        const auto [type, refreshRate] = info->getRefreshRate(now);
+        // Skip NoVote layer as those don't have any requirements
+        if (type == LayerHistory::LayerVoteType::NoVote) {
+            continue;
+        }
 
-            // Compute the layer's position on the screen
-            const Rect bounds = Rect(strong->getBounds());
-            const ui::Transform transform = strong->getTransform();
-            constexpr bool roundOutwards = true;
-            Rect transformed = transform.transform(bounds, roundOutwards);
+        // Compute the layer's position on the screen
+        const Rect bounds = Rect(strong->getBounds());
+        const ui::Transform transform = strong->getTransform();
+        constexpr bool roundOutwards = true;
+        Rect transformed = transform.transform(bounds, roundOutwards);
 
-            const float layerArea = transformed.getWidth() * transformed.getHeight();
-            float weight = mDisplayArea ? layerArea / mDisplayArea : 0.0f;
-            summary.push_back({strong->getName(), type, refreshRate, weight});
+        const float layerArea = transformed.getWidth() * transformed.getHeight();
+        float weight = mDisplayArea ? layerArea / mDisplayArea : 0.0f;
+        summary.push_back({strong->getName(), type, refreshRate, weight});
 
-            if (CC_UNLIKELY(mTraceEnabled)) {
-                trace(layer, type, static_cast<int>(std::round(refreshRate)));
-            }
-        } else if (CC_UNLIKELY(mTraceEnabled)) {
-            trace(layer, LayerHistory::LayerVoteType::NoVote, 0);
+        if (CC_UNLIKELY(mTraceEnabled)) {
+            trace(layer, type, static_cast<int>(std::round(refreshRate)));
         }
     }
 
@@ -177,7 +174,7 @@
                         return LayerVoteType::NoVote;
                 }
             }();
-            if (frameRate.rate > 0 || voteType == LayerVoteType::NoVote) {
+            if (layer->isVisible() && (frameRate.rate > 0 || voteType == LayerVoteType::NoVote)) {
                 info->setLayerVote(voteType, frameRate.rate);
             } else {
                 info->resetLayerVote();
diff --git a/services/surfaceflinger/Scheduler/LayerInfoV2.cpp b/services/surfaceflinger/Scheduler/LayerInfoV2.cpp
index b4365bf..bf1fb88 100644
--- a/services/surfaceflinger/Scheduler/LayerInfoV2.cpp
+++ b/services/surfaceflinger/Scheduler/LayerInfoV2.cpp
@@ -45,15 +45,6 @@
     }
 }
 
-// Returns whether the earliest present time is within the active threshold.
-bool LayerInfoV2::isRecentlyActive(nsecs_t now) const {
-    if (mFrameTimes.empty()) {
-        return false;
-    }
-
-    return mFrameTimes.back().queueTime >= getActiveLayerThreshold(now);
-}
-
 bool LayerInfoV2::isFrameTimeValid(const FrameTimeData& frameTime) const {
     return frameTime.queueTime >= std::chrono::duration_cast<std::chrono::nanoseconds>(
                                           mFrameTimeValidSince.time_since_epoch())
diff --git a/services/surfaceflinger/Scheduler/LayerInfoV2.h b/services/surfaceflinger/Scheduler/LayerInfoV2.h
index 25fb95a..ad91f18 100644
--- a/services/surfaceflinger/Scheduler/LayerInfoV2.h
+++ b/services/surfaceflinger/Scheduler/LayerInfoV2.h
@@ -64,8 +64,6 @@
     // updated time, the updated time is the present time.
     void setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now);
 
-    bool isRecentlyActive(nsecs_t now) const;
-
     // Sets an explicit layer vote. This usually comes directly from the application via
     // ANativeWindow_setFrameRate API
     void setLayerVote(LayerHistory::LayerVoteType type, float fps) { mLayerVote = {type, fps}; }
diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp
index 71e37a8..6fca673 100644
--- a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp
@@ -270,12 +270,12 @@
     EXPECT_EQ(1, activeLayerCount());
     EXPECT_EQ(1, frequentLayerCount(time));
 
-    // layer became inactive
+    // layer became inactive, but the vote stays
     setLayerInfoVote(layer.get(), LayerHistory::LayerVoteType::Heuristic);
     time += MAX_ACTIVE_LAYER_PERIOD_NS.count();
-    ASSERT_TRUE(history().summarize(time).empty());
-    // TODO: activeLayerCount() should be 0 but it is 1 since getFrameRateForLayerTree() returns a
-    // value > 0
+    ASSERT_EQ(1, history().summarize(time).size());
+    EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitDefault, history().summarize(time)[0].vote);
+    EXPECT_FLOAT_EQ(73.4f, history().summarize(time)[0].desiredRefreshRate);
     EXPECT_EQ(1, activeLayerCount());
     EXPECT_EQ(0, frequentLayerCount(time));
 }
@@ -303,12 +303,13 @@
     EXPECT_EQ(1, activeLayerCount());
     EXPECT_EQ(1, frequentLayerCount(time));
 
-    // layer became inactive
+    // layer became inactive, but the vote stays
     setLayerInfoVote(layer.get(), LayerHistory::LayerVoteType::Heuristic);
     time += MAX_ACTIVE_LAYER_PERIOD_NS.count();
-    ASSERT_TRUE(history().summarize(time).empty());
-    // TODO: activeLayerCount() should be 0 but it is 1 since getFrameRateForLayerTree() returns a
-    // value > 0
+    ASSERT_EQ(1, history().summarize(time).size());
+    EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple,
+              history().summarize(time)[0].vote);
+    EXPECT_FLOAT_EQ(73.4f, history().summarize(time)[0].desiredRefreshRate);
     EXPECT_EQ(1, activeLayerCount());
     EXPECT_EQ(0, frequentLayerCount(time));
 }