SF: Don't store config ids in RefreshRateStats

Configs IDs can change during runtime, so we shouldn't store
them to calculate the refresh rate stats. Instead we store
only the current refresh rate. Additionally this CL removes
the dependency on RefreshRateConfigs.

Bug: 159590486
Test: atest RefreshRateStatsTest
Change-Id: Id0af0598fb1c72ea4c1328bdb372506f0436b8da
diff --git a/services/surfaceflinger/Scheduler/RefreshRateStats.h b/services/surfaceflinger/Scheduler/RefreshRateStats.h
index ce91a76..80f4665 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateStats.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateStats.h
@@ -18,7 +18,7 @@
 
 #include <numeric>
 
-#include "Scheduler/RefreshRateConfigs.h"
+#include "Fps.h"
 #include "Scheduler/SchedulerUtils.h"
 #include "TimeStats/TimeStats.h"
 
@@ -40,12 +40,10 @@
     static constexpr int64_t MS_PER_DAY = 24 * MS_PER_HOUR;
 
 public:
-    RefreshRateStats(const RefreshRateConfigs& refreshRateConfigs, TimeStats& timeStats,
-                     HwcConfigIndexType currentConfigId,
+    RefreshRateStats(TimeStats& timeStats, Fps currentRefreshRate,
                      android::hardware::graphics::composer::hal::PowerMode currentPowerMode)
-          : mRefreshRateConfigs(refreshRateConfigs),
-            mTimeStats(timeStats),
-            mCurrentConfigMode(currentConfigId),
+          : mTimeStats(timeStats),
+            mCurrentRefreshRate(currentRefreshRate),
             mCurrentPowerMode(currentPowerMode) {}
 
     // Sets power mode.
@@ -59,12 +57,12 @@
 
     // Sets config mode. If the mode has changed, it records how much time was spent in the previous
     // mode.
-    void setConfigMode(HwcConfigIndexType configId) {
-        if (mCurrentConfigMode == configId) {
+    void setRefreshRate(Fps currRefreshRate) {
+        if (mCurrentRefreshRate.equalsWithMargin(currRefreshRate)) {
             return;
         }
         flushTime();
-        mCurrentConfigMode = configId;
+        mCurrentRefreshRate = currRefreshRate;
     }
 
     // Returns a map between human readable refresh rate and number of seconds the device spent in
@@ -79,10 +77,10 @@
         // Multiple configs may map to the same name, e.g. "60fps". Add the
         // times for such configs together.
         for (const auto& [configId, time] : mConfigModesTotalTime) {
-            totalTime[mRefreshRateConfigs.getRefreshRateFromConfigId(configId).getName()] = 0;
+            totalTime[to_string(configId)] = 0;
         }
         for (const auto& [configId, time] : mConfigModesTotalTime) {
-            totalTime[mRefreshRateConfigs.getRefreshRateFromConfigId(configId).getName()] += time;
+            totalTime[to_string(configId)] += time;
         }
         totalTime["ScreenOff"] = mScreenOffTime;
         return totalTime;
@@ -111,14 +109,11 @@
         uint32_t fps = 0;
         if (mCurrentPowerMode == android::hardware::graphics::composer::hal::PowerMode::ON) {
             // Normal power mode is counted under different config modes.
-            if (mConfigModesTotalTime.find(mCurrentConfigMode) == mConfigModesTotalTime.end()) {
-                mConfigModesTotalTime[mCurrentConfigMode] = 0;
+            if (mConfigModesTotalTime.find(mCurrentRefreshRate) == mConfigModesTotalTime.end()) {
+                mConfigModesTotalTime[mCurrentRefreshRate] = 0;
             }
-            mConfigModesTotalTime[mCurrentConfigMode] += timeElapsedMs;
-            fps = static_cast<uint32_t>(
-                    std::round(mRefreshRateConfigs.getRefreshRateFromConfigId(mCurrentConfigMode)
-                                       .getFps()
-                                       .getValue()));
+            mConfigModesTotalTime[mCurrentRefreshRate] += timeElapsedMs;
+            fps = static_cast<uint32_t>(mCurrentRefreshRate.getIntValue());
         } else {
             mScreenOffTime += timeElapsedMs;
         }
@@ -136,16 +131,13 @@
                                   days, hours, mins, sec, secRemainderMs);
     }
 
-    // Keeps information about refresh rate configs that device has.
-    const RefreshRateConfigs& mRefreshRateConfigs;
-
     // Aggregate refresh rate statistics for telemetry.
     TimeStats& mTimeStats;
 
-    HwcConfigIndexType mCurrentConfigMode;
+    Fps mCurrentRefreshRate;
     android::hardware::graphics::composer::hal::PowerMode mCurrentPowerMode;
 
-    std::unordered_map<HwcConfigIndexType /* configId */, int64_t /* duration in ms */>
+    std::unordered_map<Fps, int64_t /* duration in ms */, std::hash<Fps>, Fps::EqualsInBuckets>
             mConfigModesTotalTime;
     int64_t mScreenOffTime = 0;
 
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 39f7391..fe80f96 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1071,11 +1071,12 @@
 
     std::lock_guard<std::mutex> lock(mActiveConfigLock);
     mRefreshRateConfigs->setCurrentConfigId(mUpcomingActiveConfig.configId);
-    mRefreshRateStats->setConfigMode(mUpcomingActiveConfig.configId);
     display->setActiveConfig(mUpcomingActiveConfig.configId);
 
     auto& refreshRate =
             mRefreshRateConfigs->getRefreshRateFromConfigId(mUpcomingActiveConfig.configId);
+    mRefreshRateStats->setRefreshRate(refreshRate.getFps());
+
     if (refreshRate.getVsyncPeriod() != oldRefreshRate.getVsyncPeriod()) {
         mTimeStats->incrementRefreshRateSwitches();
     }
@@ -2868,10 +2869,10 @@
             std::make_unique<scheduler::RefreshRateConfigs>(getHwComposer().getConfigs(
                                                                     primaryDisplayId),
                                                             currentConfig);
+    const auto& currRefreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(currentConfig);
     mRefreshRateStats =
-            std::make_unique<scheduler::RefreshRateStats>(*mRefreshRateConfigs, *mTimeStats,
-                                                          currentConfig, hal::PowerMode::OFF);
-    mRefreshRateStats->setConfigMode(currentConfig);
+            std::make_unique<scheduler::RefreshRateStats>(*mTimeStats, currRefreshRate.getFps(),
+                                                          hal::PowerMode::OFF);
 
     mVsyncConfiguration = getFactory().createVsyncConfiguration(*mRefreshRateConfigs);
     mVsyncModulator.emplace(mVsyncConfiguration->getCurrentConfigs());
@@ -2879,8 +2880,7 @@
     // start the EventThread
     mScheduler = getFactory().createScheduler(*mRefreshRateConfigs, *this);
     const auto configs = mVsyncConfiguration->getCurrentConfigs();
-    const nsecs_t vsyncPeriod =
-            mRefreshRateConfigs->getRefreshRateFromConfigId(currentConfig).getVsyncPeriod();
+    const nsecs_t vsyncPeriod = currRefreshRate.getVsyncPeriod();
     mAppConnectionHandle =
             mScheduler->createConnection("app", mFrameTimeline->getTokenManager(),
                                          /*workDuration=*/configs.late.appWorkDuration,
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp
index d0bb9e2..f938ba1 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp
@@ -25,6 +25,8 @@
 #include <log/log.h>
 #include <thread>
 
+#include "Scheduler/HwcStrongTypes.h"
+#include "Scheduler/RefreshRateConfigs.h"
 #include "Scheduler/RefreshRateStats.h"
 #include "mock/DisplayHardware/MockDisplay.h"
 #include "mock/MockTimeStats.h"
@@ -51,8 +53,9 @@
     void init(const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs) {
         mRefreshRateConfigs =
                 std::make_unique<RefreshRateConfigs>(configs, /*currentConfig=*/CONFIG_ID_0);
-        mRefreshRateStats = std::make_unique<RefreshRateStats>(*mRefreshRateConfigs, mTimeStats,
-                                                               /*currentConfigId=*/CONFIG_ID_0,
+
+        const auto currFps = mRefreshRateConfigs->getRefreshRateFromConfigId(CONFIG_ID_0).getFps();
+        mRefreshRateStats = std::make_unique<RefreshRateStats>(mTimeStats, currFps,
                                                                /*currentPowerMode=*/PowerMode::OFF);
     }
 
@@ -81,7 +84,7 @@
 std::shared_ptr<const HWC2::Display::Config> RefreshRateStatsTest::createConfig(
         HwcConfigIndexType configId, int32_t configGroup, int64_t vsyncPeriod) {
     return HWC2::Display::Config::Builder(mDisplay, configId.value())
-            .setVsyncPeriod(int32_t(vsyncPeriod))
+            .setVsyncPeriod(static_cast<int32_t>(vsyncPeriod))
             .setConfigGroup(configGroup)
             .build();
 }
@@ -110,7 +113,8 @@
     EXPECT_LT(screenOff, times["ScreenOff"]);
     EXPECT_EQ(0u, times.count("90.00fps"));
 
-    mRefreshRateStats->setConfigMode(CONFIG_ID_0);
+    const auto config0Fps = mRefreshRateConfigs->getRefreshRateFromConfigId(CONFIG_ID_0).getFps();
+    mRefreshRateStats->setRefreshRate(config0Fps);
     mRefreshRateStats->setPowerMode(PowerMode::ON);
     screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"];
     std::this_thread::sleep_for(std::chrono::milliseconds(2));
@@ -126,7 +130,7 @@
     EXPECT_LT(screenOff, times["ScreenOff"]);
     EXPECT_EQ(ninety, times["90.00fps"]);
 
-    mRefreshRateStats->setConfigMode(CONFIG_ID_0);
+    mRefreshRateStats->setRefreshRate(config0Fps);
     screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"];
     std::this_thread::sleep_for(std::chrono::milliseconds(2));
     times = mRefreshRateStats->getTotalTimes();
@@ -157,7 +161,9 @@
     times = mRefreshRateStats->getTotalTimes();
     EXPECT_LT(screenOff, times["ScreenOff"]);
 
-    mRefreshRateStats->setConfigMode(CONFIG_ID_0);
+    const auto config0Fps = mRefreshRateConfigs->getRefreshRateFromConfigId(CONFIG_ID_0).getFps();
+    const auto config1Fps = mRefreshRateConfigs->getRefreshRateFromConfigId(CONFIG_ID_1).getFps();
+    mRefreshRateStats->setRefreshRate(config0Fps);
     mRefreshRateStats->setPowerMode(PowerMode::ON);
     screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"];
     std::this_thread::sleep_for(std::chrono::milliseconds(2));
@@ -167,7 +173,7 @@
     EXPECT_LT(0, times["90.00fps"]);
 
     // When power mode is normal, time for configs updates.
-    mRefreshRateStats->setConfigMode(CONFIG_ID_1);
+    mRefreshRateStats->setRefreshRate(config1Fps);
     int ninety = mRefreshRateStats->getTotalTimes()["90.00fps"];
     std::this_thread::sleep_for(std::chrono::milliseconds(2));
     times = mRefreshRateStats->getTotalTimes();
@@ -176,7 +182,7 @@
     ASSERT_EQ(1u, times.count("60.00fps"));
     EXPECT_LT(0, times["60.00fps"]);
 
-    mRefreshRateStats->setConfigMode(CONFIG_ID_0);
+    mRefreshRateStats->setRefreshRate(config0Fps);
     int sixty = mRefreshRateStats->getTotalTimes()["60.00fps"];
     std::this_thread::sleep_for(std::chrono::milliseconds(2));
     times = mRefreshRateStats->getTotalTimes();
@@ -184,7 +190,7 @@
     EXPECT_LT(ninety, times["90.00fps"]);
     EXPECT_EQ(sixty, times["60.00fps"]);
 
-    mRefreshRateStats->setConfigMode(CONFIG_ID_1);
+    mRefreshRateStats->setRefreshRate(config1Fps);
     ninety = mRefreshRateStats->getTotalTimes()["90.00fps"];
     std::this_thread::sleep_for(std::chrono::milliseconds(2));
     times = mRefreshRateStats->getTotalTimes();
@@ -195,7 +201,7 @@
     // Because the power mode is not PowerMode::ON, switching the config
     // does not update refresh rates that come from the config.
     mRefreshRateStats->setPowerMode(PowerMode::DOZE);
-    mRefreshRateStats->setConfigMode(CONFIG_ID_0);
+    mRefreshRateStats->setRefreshRate(config0Fps);
     sixty = mRefreshRateStats->getTotalTimes()["60.00fps"];
     std::this_thread::sleep_for(std::chrono::milliseconds(2));
     times = mRefreshRateStats->getTotalTimes();
@@ -203,7 +209,7 @@
     EXPECT_EQ(ninety, times["90.00fps"]);
     EXPECT_EQ(sixty, times["60.00fps"]);
 
-    mRefreshRateStats->setConfigMode(CONFIG_ID_1);
+    mRefreshRateStats->setRefreshRate(config1Fps);
     screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"];
     std::this_thread::sleep_for(std::chrono::milliseconds(2));
     times = mRefreshRateStats->getTotalTimes();
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index c0de465..030073c 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -223,12 +223,14 @@
                                          .build());
         }
 
-        mFlinger->mRefreshRateConfigs = std::make_unique<
-                scheduler::RefreshRateConfigs>(configs, /*currentConfig=*/HwcConfigIndexType(0));
-        mFlinger->mRefreshRateStats = std::make_unique<
-                scheduler::RefreshRateStats>(*mFlinger->mRefreshRateConfigs, *mFlinger->mTimeStats,
-                                             /*currentConfig=*/HwcConfigIndexType(0),
-                                             /*powerMode=*/hal::PowerMode::OFF);
+        const auto currConfig = HwcConfigIndexType(0);
+        mFlinger->mRefreshRateConfigs =
+                std::make_unique<scheduler::RefreshRateConfigs>(configs, currConfig);
+        const auto currFps =
+                mFlinger->mRefreshRateConfigs->getRefreshRateFromConfigId(currConfig).getFps();
+        mFlinger->mRefreshRateStats =
+                std::make_unique<scheduler::RefreshRateStats>(*mFlinger->mTimeStats, currFps,
+                                                              /*powerMode=*/hal::PowerMode::OFF);
         mFlinger->mVsyncConfiguration =
                 mFactory.createVsyncConfiguration(*mFlinger->mRefreshRateConfigs);
         mFlinger->mVsyncModulator.emplace(mFlinger->mVsyncConfiguration->getCurrentConfigs());