Non-visible layers are now "inactive"

When setting "explicit_refresh_rate_hints", we saw the perfetto trace is
very noisy in LayerHistory/RefreshRateSelector. This change fixes this
in a few ways:
- Non-visible layers should now be inactive in LayerHistory. This should
  be safe because non-visible layers were treated as NoVote,
  and does not affect the refresh rate chosen.
- LayerInfo for ExplicitCategory now considers NoVote (from non-visible
  layer).
- RefreshRateSelector::calculateLayerScoreLocked does not have any
  interesting trace calls itself, so remove its ATRACE_CALL.

Bug: 305008279
Test: atest libsurfaceflinger_unittest
Test: atest SetFrameRateTest
Test: perfetto trace not noisy
Change-Id: I40056ea48b8323b7be0936e7717706bf9a0926f9
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp
index 069d89b..ff82914 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp
@@ -21,6 +21,7 @@
 #include "LayerHistory.h"
 
 #include <android-base/stringprintf.h>
+#include <com_android_graphics_surfaceflinger_flags.h>
 #include <cutils/properties.h>
 #include <gui/TraceUtils.h>
 #include <utils/Log.h>
@@ -39,8 +40,14 @@
 
 namespace {
 
+using namespace com::android::graphics::surfaceflinger;
+
 bool isLayerActive(const LayerInfo& info, nsecs_t threshold) {
-    // Layers with an explicit frame rate or frame rate category are always kept active,
+    if (flags::misc1() && !info.isVisible()) {
+        return false;
+    }
+
+    // Layers with an explicit frame rate or frame rate category are kept active,
     // but ignore NoVote.
     if (info.getSetFrameRateVote().isValid() && !info.getSetFrameRateVote().isNoVote()) {
         return true;
diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp
index 36f2475..54e9022 100644
--- a/services/surfaceflinger/Scheduler/LayerInfo.cpp
+++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp
@@ -304,19 +304,22 @@
 
     if (mLayerVote.type != LayerHistory::LayerVoteType::Heuristic) {
         if (mLayerVote.category != FrameRateCategory::Default) {
-            ATRACE_FORMAT_INSTANT("ExplicitCategory (%s)",
+            const auto voteType = mLayerVote.type == LayerHistory::LayerVoteType::NoVote
+                    ? LayerHistory::LayerVoteType::NoVote
+                    : LayerHistory::LayerVoteType::ExplicitCategory;
+            ATRACE_FORMAT_INSTANT("Vote %s (category=%s)", ftl::enum_string(voteType).c_str(),
                                   ftl::enum_string(mLayerVote.category).c_str());
-            ALOGV("%s uses frame rate category: %d", mName.c_str(),
-                  static_cast<int>(mLayerVote.category));
-            votes.push_back({LayerHistory::LayerVoteType::ExplicitCategory, Fps(),
-                             Seamlessness::Default, mLayerVote.category,
+            ALOGV("%s voted %s with category: %s", mName.c_str(),
+                  ftl::enum_string(voteType).c_str(),
+                  ftl::enum_string(mLayerVote.category).c_str());
+            votes.push_back({voteType, Fps(), Seamlessness::Default, mLayerVote.category,
                              mLayerVote.categorySmoothSwitchOnly});
         }
 
         if (mLayerVote.fps.isValid() ||
             mLayerVote.type != LayerHistory::LayerVoteType::ExplicitDefault) {
             ATRACE_FORMAT_INSTANT("Vote %s", ftl::enum_string(mLayerVote.type).c_str());
-            ALOGV("%s voted %d ", mName.c_str(), static_cast<int>(mLayerVote.type));
+            ALOGV("%s voted %d", mName.c_str(), static_cast<int>(mLayerVote.type));
             votes.push_back(mLayerVote);
         }
 
diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
index 1d23fb5..eb69d0b 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
@@ -401,7 +401,6 @@
 
 float RefreshRateSelector::calculateLayerScoreLocked(const LayerRequirement& layer, Fps refreshRate,
                                                      bool isSeamlessSwitch) const {
-    ATRACE_CALL();
     // Slightly prefer seamless switches.
     constexpr float kSeamedSwitchPenalty = 0.95f;
     const float seamlessness = isSeamlessSwitch ? 1.0f : kSeamedSwitchPenalty;
diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryIntegrationTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryIntegrationTest.cpp
index 631adf1..2f6058f 100644
--- a/services/surfaceflinger/tests/unittests/LayerHistoryIntegrationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHistoryIntegrationTest.cpp
@@ -18,12 +18,14 @@
 #define LOG_TAG "LayerHistoryIntegrationTest"
 
 #include <Layer.h>
+#include <com_android_graphics_surfaceflinger_flags.h>
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 #include <log/log.h>
 
 #include <renderengine/mock/FakeExternalTexture.h>
 
+#include "FlagUtils.h"
 #include "FpsOps.h"
 #include "LayerHierarchyTest.h"
 #include "Scheduler/LayerHistory.h"
@@ -36,6 +38,7 @@
 namespace android::scheduler {
 
 using android::mock::createDisplayMode;
+using namespace com::android::graphics::surfaceflinger;
 
 class LayerHistoryIntegrationTest : public surfaceflinger::frontend::LayerSnapshotTestBase {
 protected:
@@ -492,7 +495,9 @@
     EXPECT_EQ(1, frequentLayerCount(time));
 }
 
-TEST_F(LayerHistoryIntegrationTest, invisibleExplicitLayer) {
+TEST_F(LayerHistoryIntegrationTest, invisibleExplicitLayerIsActive) {
+    SET_FLAG_FOR_TEST(flags::misc1, false);
+
     auto explicitVisiblelayer = createLegacyAndFrontedEndLayer(1);
     auto explicitInvisiblelayer = createLegacyAndFrontedEndLayer(2);
     hideLayer(2);
@@ -515,6 +520,31 @@
     EXPECT_EQ(2, frequentLayerCount(time));
 }
 
+TEST_F(LayerHistoryIntegrationTest, invisibleExplicitLayerIsNotActive) {
+    SET_FLAG_FOR_TEST(flags::misc1, true);
+
+    auto explicitVisiblelayer = createLegacyAndFrontedEndLayer(1);
+    auto explicitInvisiblelayer = createLegacyAndFrontedEndLayer(2);
+    hideLayer(2);
+    setFrameRate(1, 60.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE,
+                 ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
+    setFrameRate(2, 90.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE,
+                 ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
+    nsecs_t time = systemTime();
+
+    // Post a buffer to the layers to make them active
+    setBufferWithPresentTime(explicitVisiblelayer, time);
+    setBufferWithPresentTime(explicitInvisiblelayer, time);
+
+    EXPECT_EQ(2u, layerCount());
+    ASSERT_EQ(1u, summarizeLayerHistory(time).size());
+    EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple,
+              summarizeLayerHistory(time)[0].vote);
+    EXPECT_EQ(60_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate);
+    EXPECT_EQ(1u, activeLayerCount());
+    EXPECT_EQ(1, frequentLayerCount(time));
+}
+
 TEST_F(LayerHistoryIntegrationTest, infrequentAnimatingLayer) {
     auto layer = createLegacyAndFrontedEndLayer(1);
 
diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
index 33c1d86..e8831ab 100644
--- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
@@ -22,10 +22,12 @@
 #define LOG_TAG "LayerHistoryTest"
 
 #include <Layer.h>
+#include <com_android_graphics_surfaceflinger_flags.h>
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 #include <log/log.h>
 
+#include "FlagUtils.h"
 #include "FpsOps.h"
 #include "Scheduler/LayerHistory.h"
 #include "Scheduler/LayerInfo.h"
@@ -149,6 +151,8 @@
 
 namespace {
 
+using namespace com::android::graphics::surfaceflinger;
+
 TEST_F(LayerHistoryTest, singleLayerNoVoteDefaultCompatibility) {
     const auto layer = createLayer();
     EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true));
@@ -555,6 +559,33 @@
     EXPECT_EQ(FrameRateCategory::High, summarizeLayerHistory(time)[0].frameRateCategory);
 }
 
+TEST_F(LayerHistoryTest, oneLayerExplicitVoteWithCategoryNotVisibleDoesNotVote) {
+    SET_FLAG_FOR_TEST(flags::misc1, true);
+
+    auto layer = createLayer();
+    EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(false));
+    EXPECT_CALL(*layer, getFrameRateForLayerTree())
+            .WillRepeatedly(
+                    Return(Layer::FrameRate(12.34_Hz, Layer::FrameRateCompatibility::Default,
+                                            Seamlessness::OnlySeamless, FrameRateCategory::High)));
+
+    EXPECT_EQ(1, layerCount());
+    EXPECT_EQ(0, activeLayerCount());
+
+    nsecs_t time = systemTime();
+    for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) {
+        history().record(layer->getSequence(), layer->getLayerProps(), time, time,
+                         LayerHistory::LayerUpdateType::Buffer);
+        time += HI_FPS_PERIOD;
+    }
+
+    // Layer is not visible, so the layer is moved to inactive, infrequent, and it will not have
+    // votes to consider for refresh rate selection.
+    ASSERT_EQ(0, summarizeLayerHistory(time).size());
+    EXPECT_EQ(0, activeLayerCount());
+    EXPECT_EQ(0, frequentLayerCount(time));
+}
+
 TEST_F(LayerHistoryTest, multipleLayers) {
     auto layer1 = createLayer("A");
     auto layer2 = createLayer("B");
@@ -780,6 +811,8 @@
 }
 
 TEST_F(LayerHistoryTest, invisibleExplicitLayer) {
+    SET_FLAG_FOR_TEST(flags::misc1, false);
+
     auto explicitVisiblelayer = createLayer();
     auto explicitInvisiblelayer = createLayer();
 
@@ -810,6 +843,39 @@
     EXPECT_EQ(2, frequentLayerCount(time));
 }
 
+TEST_F(LayerHistoryTest, invisibleExplicitLayerDoesNotVote) {
+    SET_FLAG_FOR_TEST(flags::misc1, true);
+
+    auto explicitVisiblelayer = createLayer();
+    auto explicitInvisiblelayer = createLayer();
+
+    EXPECT_CALL(*explicitVisiblelayer, isVisible()).WillRepeatedly(Return(true));
+    EXPECT_CALL(*explicitVisiblelayer, getFrameRateForLayerTree())
+            .WillRepeatedly(Return(
+                    Layer::FrameRate(60_Hz, Layer::FrameRateCompatibility::ExactOrMultiple)));
+
+    EXPECT_CALL(*explicitInvisiblelayer, isVisible()).WillRepeatedly(Return(false));
+    EXPECT_CALL(*explicitInvisiblelayer, getFrameRateForLayerTree())
+            .WillRepeatedly(Return(
+                    Layer::FrameRate(90_Hz, Layer::FrameRateCompatibility::ExactOrMultiple)));
+
+    nsecs_t time = systemTime();
+
+    // Post a buffer to the layers to make them active
+    history().record(explicitVisiblelayer->getSequence(), explicitVisiblelayer->getLayerProps(),
+                     time, time, LayerHistory::LayerUpdateType::Buffer);
+    history().record(explicitInvisiblelayer->getSequence(), explicitInvisiblelayer->getLayerProps(),
+                     time, time, LayerHistory::LayerUpdateType::Buffer);
+
+    EXPECT_EQ(2, layerCount());
+    ASSERT_EQ(1, summarizeLayerHistory(time).size());
+    EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple,
+              summarizeLayerHistory(time)[0].vote);
+    EXPECT_EQ(60_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate);
+    EXPECT_EQ(1, activeLayerCount());
+    EXPECT_EQ(1, frequentLayerCount(time));
+}
+
 TEST_F(LayerHistoryTest, infrequentAnimatingLayer) {
     auto layer = createLayer();
 
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 8f1982d..03af56c 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -271,7 +271,7 @@
         resetScheduler(mScheduler);
     }
 
-    void setupMockScheduler(test::MockSchedulerOptions options = {}) {
+    void setupMockScheduler(surfaceflinger::test::MockSchedulerOptions options = {}) {
         using testing::_;
         using testing::Return;