Tune RefreshRateConfigs for fractional refresh rates

This CL contains several changes in order to tune
RefrshRateConfigs for fractional refresh rates

1. TV devices support fractional refresh rates which are
within 1/1001 of an integer, for example 59.94 and 60.
This change reduces the tolerance we use when
selecting the best refresh rate, so we can differtiate
between the scores which 59.94 and 60 will get
when a layer requests 60 (or 59.94).

2. Changes the threshold in getFrameRateDivider
so it can differntiate between 59.94 and 60 fps.

3. Explicitly check if we're voting for a refresh
rate in a fractional pair when calculating the
vote for ExplicitExactOrMultiple. If so, vote with
a contant score.

4. Finally the CL changes some log lines to make
debugging easier and adds more comments.

Bug: 196404992
Bug: 196191168
Test: atest libsurfaceflinger_unittest
      atest MatchContentFrameRateTest SetFrameRateTest
Change-Id: I694e2aa5b16e9b4e0f6d1e8263b1ac35099605fd
Merged-In: I694e2aa5b16e9b4e0f6d1e8263b1ac35099605fd
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index 0ee9fb3..74ffc8f 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -141,6 +141,8 @@
         return 0;
     }
 
+    constexpr float kScoreForFractionalPairs = .8f;
+
     // Slightly prefer seamless switches.
     constexpr float kSeamedSwitchPenalty = 0.95f;
     const float seamlessness = isSeamlessSwitch ? 1.0f : kSeamedSwitchPenalty;
@@ -157,19 +159,29 @@
     const auto layerPeriod = layer.desiredRefreshRate.getPeriodNsecs();
     if (layer.vote == LayerVoteType::ExplicitDefault) {
         // Find the actual rate the layer will render, assuming
-        // that layerPeriod is the minimal time to render a frame
+        // that layerPeriod is the minimal period to render a frame.
+        // For example if layerPeriod is 20ms and displayPeriod is 16ms,
+        // then the actualLayerPeriod will be 32ms, because it is the
+        // smallest multiple of the display period which is >= layerPeriod.
         auto actualLayerPeriod = displayPeriod;
         int multiplier = 1;
         while (layerPeriod > actualLayerPeriod + MARGIN_FOR_PERIOD_CALCULATION) {
             multiplier++;
             actualLayerPeriod = displayPeriod * multiplier;
         }
+
+        // Because of the threshold we used above it's possible that score is slightly
+        // above 1.
         return std::min(1.0f,
                         static_cast<float>(layerPeriod) / static_cast<float>(actualLayerPeriod));
     }
 
     if (layer.vote == LayerVoteType::ExplicitExactOrMultiple ||
         layer.vote == LayerVoteType::Heuristic) {
+        if (isFractionalPairOrMultiple(refreshRate.getFps(), layer.desiredRefreshRate)) {
+            return kScoreForFractionalPairs * seamlessness;
+        }
+
         // Calculate how many display vsyncs we need to present a single frame for this
         // layer
         const auto [displayFramesQuotient, displayFramesRemainder] =
@@ -422,7 +434,7 @@
 
             const auto layerScore =
                     calculateLayerScoreLocked(layer, *scores[i].refreshRate, isSeamlessSwitch);
-            ALOGV("%s gives %s score of %.2f", formatLayerInfo(layer, weight).c_str(),
+            ALOGV("%s gives %s score of %.4f", formatLayerInfo(layer, weight).c_str(),
                   scores[i].refreshRate->getName().c_str(), layerScore);
             scores[i].score += weight * layerScore;
         }
@@ -583,7 +595,7 @@
 
 template <typename Iter>
 const RefreshRate* RefreshRateConfigs::getBestRefreshRate(Iter begin, Iter end) const {
-    constexpr auto EPSILON = 0.001f;
+    constexpr auto kEpsilon = 0.0001f;
     const RefreshRate* bestRefreshRate = begin->refreshRate;
     float max = begin->score;
     for (auto i = begin; i != end; ++i) {
@@ -592,7 +604,7 @@
 
         ATRACE_INT(refreshRate->getName().c_str(), round<int>(score * 100));
 
-        if (score > max * (1 + EPSILON)) {
+        if (score > max * (1 + kEpsilon)) {
             max = score;
             bestRefreshRate = refreshRate;
         }
@@ -945,6 +957,17 @@
     return static_cast<int>(numPeriodsRounded);
 }
 
+bool RefreshRateConfigs::isFractionalPairOrMultiple(Fps smaller, Fps bigger) {
+    if (smaller.getValue() > bigger.getValue()) {
+        return isFractionalPairOrMultiple(bigger, smaller);
+    }
+
+    const auto multiplier = std::round(bigger.getValue() / smaller.getValue());
+    constexpr float kCoef = 1000.f / 1001.f;
+    return bigger.equalsWithMargin(Fps(smaller.getValue() * multiplier / kCoef)) ||
+            bigger.equalsWithMargin(Fps(smaller.getValue() * multiplier * kCoef));
+}
+
 void RefreshRateConfigs::dump(std::string& result) const {
     std::lock_guard lock(mLock);
     base::StringAppendF(&result, "DesiredDisplayModeSpecs (DisplayManager): %s\n\n",