SurfaceFlinger: fix calculation issues with refresh rate selection

 - Initialize BufferQueueCore::mFrameRate
 - Load BufferQueueLayer::mLatchedFrameRate value before using it
 - Fix a bug with LayerInfoV2 where a frequent layer needs to post at least
   FREQUENT_LAYER_WINDOW_SIZE buffers.
 - Fix casting issues in RefreshRateConfigs

Test: adb shell /data/nativetest64/libsurfaceflinger_unittest/libsurfaceflinger_unittest
Bug: 147516364
Change-Id: Ie6e93ef2f4dd3a030bfd0dbbf8018d96680d8bb3
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index e85281d..46bbbe1 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -130,8 +130,10 @@
 }
 
 std::optional<float> BufferQueueLayer::getFrameRate() const {
-    if (mLatchedFrameRate > 0.f || mLatchedFrameRate == FRAME_RATE_NO_VOTE)
-        return mLatchedFrameRate;
+    const auto frameRate = mLatchedFrameRate.load();
+    if (frameRate > 0.f || frameRate == FRAME_RATE_NO_VOTE) {
+        return frameRate;
+    }
 
     return {};
 }
diff --git a/services/surfaceflinger/Scheduler/LayerInfoV2.cpp b/services/surfaceflinger/Scheduler/LayerInfoV2.cpp
index d94d758..f309d4d 100644
--- a/services/surfaceflinger/Scheduler/LayerInfoV2.cpp
+++ b/services/surfaceflinger/Scheduler/LayerInfoV2.cpp
@@ -57,7 +57,7 @@
 bool LayerInfoV2::isFrequent(nsecs_t now) const {
     // Assume layer is infrequent if too few present times have been recorded.
     if (mFrameTimes.size() < FREQUENT_LAYER_WINDOW_SIZE) {
-        return true;
+        return false;
     }
 
     // Layer is frequent if the earliest value in the window of most recent present times is
@@ -100,8 +100,7 @@
             static_cast<float>(totalPresentTimeDeltas) / (mFrameTimes.size() - 1);
 
     // Now once we calculated the refresh rate we need to make sure that all the frames we captured
-    // are evenly distrubuted and we don't calculate the average across some burst of frames.
-
+    // are evenly distributed and we don't calculate the average across some burst of frames.
     for (auto it = mFrameTimes.begin(); it != mFrameTimes.end() - 1; ++it) {
         const nsecs_t presentTimeDeltas =
                 std::max(((it + 1)->presetTime - it->presetTime), mHighRefreshRatePeriod);
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index c187049..e4b0287 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -125,12 +125,13 @@
     }
 
     for (const auto& layer : layers) {
+        ALOGV("Calculating score for %s (type: %d)", layer.name.c_str(), layer.vote);
         if (layer.vote == LayerVoteType::NoVote || layer.vote == LayerVoteType::Min ||
             layer.vote == LayerVoteType::Max) {
             continue;
         }
 
-        // If we have Explicit layers, ignore the Huristic ones
+        // If we have Explicit layers, ignore the Hueristic ones
         if (explicitVoteLayers > 0 && layer.vote == LayerVoteType::Heuristic) {
             continue;
         }
@@ -148,24 +149,26 @@
             }
 
             float layerScore;
+            static constexpr size_t MAX_FRAMES_TO_FIT = 10; // Stop calculating when score < 0.1
             if (displayFramesRem == 0) {
                 // Layer desired refresh rate matches the display rate.
                 layerScore = layer.weight * 1.0f;
             } else if (displayFramesQuot == 0) {
                 // Layer desired refresh rate is higher the display rate.
-                layerScore = layer.weight * layerPeriod / displayPeriod;
+                layerScore = layer.weight *
+                        (static_cast<float>(layerPeriod) / static_cast<float>(displayPeriod)) *
+                        (1.0f / (MAX_FRAMES_TO_FIT + 1));
             } else {
                 // Layer desired refresh rate is lower the display rate. Check how well it fits the
                 // cadence
                 auto diff = std::abs(displayFramesRem - (displayPeriod - displayFramesRem));
                 int iter = 2;
-                static constexpr size_t MAX_ITERATOR = 10; // Stop calculating when score < 0.1
-                while (diff > MARGIN && iter < MAX_ITERATOR) {
+                while (diff > MARGIN && iter < MAX_FRAMES_TO_FIT) {
                     diff = diff - (displayPeriod - diff);
                     iter++;
                 }
 
-                layerScore = layer.weight * 1.0f / iter;
+                layerScore = layer.weight * (1.0f / iter);
             }
 
             ALOGV("%s (weight %.2f) %.2fHz gives %s score of %.2f", layer.name.c_str(),
diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp
index 11ace05..922966a 100644
--- a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp
@@ -34,6 +34,7 @@
 
 class LayerHistoryTestV2 : public testing::Test {
 protected:
+    static constexpr auto FREQUENT_LAYER_WINDOW_SIZE = LayerInfoV2::FREQUENT_LAYER_WINDOW_SIZE;
     static constexpr auto PRESENT_TIME_HISTORY_SIZE = LayerInfoV2::HISTORY_SIZE;
     static constexpr auto MAX_FREQUENT_LAYER_PERIOD_NS = LayerInfoV2::MAX_FREQUENT_LAYER_PERIOD_NS;
 
@@ -105,7 +106,10 @@
     for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE - 1; i++) {
         history().record(layer.get(), 0, mTime);
         ASSERT_EQ(1, history().summarize(mTime).size());
-        EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(mTime)[0].vote);
+        const auto expectedType = (i + 1 < FREQUENT_LAYER_WINDOW_SIZE)
+                ? LayerHistory::LayerVoteType::Min
+                : LayerHistory::LayerVoteType::Max;
+        EXPECT_EQ(expectedType, history().summarize(mTime)[0].vote);
         EXPECT_EQ(1, activeLayerCount());
     }
 
@@ -129,7 +133,8 @@
     history().record(layer.get(), 0, mTime);
     auto summary = history().summarize(mTime);
     ASSERT_EQ(1, history().summarize(mTime).size());
-    EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(mTime)[0].vote);
+    // Layer is still considered inactive so we expect to get Min
+    EXPECT_EQ(LayerHistory::LayerVoteType::Min, history().summarize(mTime)[0].vote);
     EXPECT_EQ(1, activeLayerCount());
 
     EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(false));
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
index 78009b8..19a58dc 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
@@ -495,7 +495,7 @@
     EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers));
 
     lr.desiredRefreshRate = 45.0f;
-    EXPECT_EQ(expected30Config, refreshRateConfigs->getRefreshRateForContentV2(layers));
+    EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers));
 
     lr.desiredRefreshRate = 30.0f;
     EXPECT_EQ(expected30Config, refreshRateConfigs->getRefreshRateForContentV2(layers));
@@ -702,6 +702,32 @@
     ASSERT_FALSE(expectedDefaultConfig.inPolicy(50.0f, 59.998f));
 }
 
+TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContentV2_75HzContent) {
+    std::vector<RefreshRateConfigs::InputConfig> configs{
+            {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60},
+             {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}};
+    auto refreshRateConfigs =
+            std::make_unique<RefreshRateConfigs>(/*refreshRateSwitching=*/true, configs,
+                                                 /*currentConfigId=*/HWC_CONFIG_ID_60);
+
+    ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported());
+
+    RefreshRate expected30Config = {HWC_CONFIG_ID_30, VSYNC_30, HWC_GROUP_ID_0, "30fps", 30};
+    RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60};
+    RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90};
+
+    auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}};
+    auto& lr = layers[0];
+
+    lr.vote = LayerVoteType::Explicit;
+    for (float fps = 75.0f; fps < 100.0f; fps += 0.1f) {
+        lr.desiredRefreshRate = fps;
+        const auto& refreshRate = refreshRateConfigs->getRefreshRateForContentV2(layers);
+        printf("%.2fHz chooses %s\n", fps, refreshRate.name.c_str());
+        EXPECT_EQ(expected90Config, refreshRate);
+    }
+}
+
 } // namespace
 } // namespace scheduler
 } // namespace android