Merge "Tune RefreshRateConfigs for fractional refresh rates"
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index c38cd68..e922d46 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -140,6 +140,8 @@
         return 0;
     }
 
+    constexpr float kScoreForFractionalPairs = .8f;
+
     // Slightly prefer seamless switches.
     constexpr float kSeamedSwitchPenalty = 0.95f;
     const float seamlessness = isSeamlessSwitch ? 1.0f : kSeamedSwitchPenalty;
@@ -156,19 +158,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] =
@@ -421,7 +433,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;
         }
@@ -582,7 +594,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) {
@@ -591,7 +603,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;
         }
@@ -910,7 +922,10 @@
 int RefreshRateConfigs::getFrameRateDivider(Fps displayFrameRate, Fps layerFrameRate) {
     // This calculation needs to be in sync with the java code
     // in DisplayManagerService.getDisplayInfoForFrameRateOverride
-    constexpr float kThreshold = 0.1f;
+
+    // The threshold must be smaller than 0.001 in order to differentiate
+    // between the fractional pairs (e.g. 59.94 and 60).
+    constexpr float kThreshold = 0.0009f;
     const auto numPeriods = displayFrameRate.getValue() / layerFrameRate.getValue();
     const auto numPeriodsRounded = std::round(numPeriods);
     if (std::abs(numPeriods - numPeriodsRounded) > kThreshold) {
@@ -920,6 +935,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",
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index 4a9a1fd..0d75689 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -335,6 +335,10 @@
     // layer refresh rate.
     static int getFrameRateDivider(Fps displayFrameRate, Fps layerFrameRate);
 
+    // Returns if the provided frame rates have a ratio t*1000/1001 or t*1001/1000
+    // for an integer t.
+    static bool isFractionalPairOrMultiple(Fps, Fps);
+
     using UidToFrameRateOverride = std::map<uid_t, Fps>;
     // Returns the frame rate override for each uid.
     //
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
index c04919f..a6bfde7 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
@@ -98,9 +98,15 @@
     static inline const DisplayModeId HWC_CONFIG_ID_30 = DisplayModeId(4);
     static inline const DisplayModeId HWC_CONFIG_ID_25 = DisplayModeId(5);
     static inline const DisplayModeId HWC_CONFIG_ID_50 = DisplayModeId(6);
+    static inline const DisplayModeId HWC_CONFIG_ID_24 = DisplayModeId(7);
+    static inline const DisplayModeId HWC_CONFIG_ID_24_FRAC = DisplayModeId(8);
+    static inline const DisplayModeId HWC_CONFIG_ID_30_FRAC = DisplayModeId(9);
+    static inline const DisplayModeId HWC_CONFIG_ID_60_FRAC = DisplayModeId(10);
 
     // Test configs
     DisplayModePtr mConfig60 = createDisplayMode(HWC_CONFIG_ID_60, 0, Fps(60.0f).getPeriodNsecs());
+    DisplayModePtr mConfig60Frac =
+            createDisplayMode(HWC_CONFIG_ID_60_FRAC, 0, Fps(59.94f).getPeriodNsecs());
     DisplayModePtr mConfig90 = createDisplayMode(HWC_CONFIG_ID_90, 0, Fps(90.0f).getPeriodNsecs());
     DisplayModePtr mConfig90DifferentGroup =
             createDisplayMode(HWC_CONFIG_ID_90, 1, Fps(90.0f).getPeriodNsecs());
@@ -116,9 +122,15 @@
     DisplayModePtr mConfig30 = createDisplayMode(HWC_CONFIG_ID_30, 0, Fps(30.0f).getPeriodNsecs());
     DisplayModePtr mConfig30DifferentGroup =
             createDisplayMode(HWC_CONFIG_ID_30, 1, Fps(30.0f).getPeriodNsecs());
+    DisplayModePtr mConfig30Frac =
+            createDisplayMode(HWC_CONFIG_ID_30_FRAC, 0, Fps(29.97f).getPeriodNsecs());
+    DisplayModePtr mConfig25 = createDisplayMode(HWC_CONFIG_ID_25, 0, Fps(25.0f).getPeriodNsecs());
     DisplayModePtr mConfig25DifferentGroup =
             createDisplayMode(HWC_CONFIG_ID_25, 1, Fps(25.0f).getPeriodNsecs());
     DisplayModePtr mConfig50 = createDisplayMode(HWC_CONFIG_ID_50, 0, Fps(50.0f).getPeriodNsecs());
+    DisplayModePtr mConfig24 = createDisplayMode(HWC_CONFIG_ID_24, 0, Fps(24.0f).getPeriodNsecs());
+    DisplayModePtr mConfig24Frac =
+            createDisplayMode(HWC_CONFIG_ID_24_FRAC, 0, Fps(23.976f).getPeriodNsecs());
 
     // Test device configurations
     // The positions of the configs in the arrays below MUST match their IDs. For example,
@@ -145,6 +157,11 @@
                                        mConfig50};
     DisplayModes m60_120Device = {mConfig60, mConfig120};
 
+    // This is a typical TV configuration.
+    DisplayModes m24_25_30_50_60WithFracDevice = {mConfig24, mConfig24Frac, mConfig25,
+                                                  mConfig30, mConfig30Frac, mConfig50,
+                                                  mConfig60, mConfig60Frac};
+
     // Expected RefreshRate objects
     RefreshRate mExpected60Config = {mConfig60, RefreshRate::ConstructorTag(0)};
     RefreshRate mExpectedAlmost60Config = {createDisplayMode(HWC_CONFIG_ID_60, 0, 16666665),
@@ -1230,7 +1247,109 @@
         const auto& refreshRate =
                 refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false});
         EXPECT_TRUE(refreshRate.getFps().equalsWithMargin(Fps(test.second)))
-                << "Expecting " << test.first << "fps => " << test.second << "Hz";
+                << "Expecting " << test.first << "fps => " << test.second << "Hz"
+                << " but it was " << refreshRate.getFps();
+    }
+}
+
+TEST_F(RefreshRateConfigsTest,
+       getBestRefreshRate_ExplicitExactOrMultiple_WithFractionalRefreshRates) {
+    auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}};
+    auto& lr = layers[0];
+
+    // Test that 23.976 will choose 24 if 23.976 is not supported
+    {
+        android::DisplayModes modes = {mConfig24,     mConfig25, mConfig30,
+                                       mConfig30Frac, mConfig60, mConfig60Frac};
+        auto refreshRateConfigs =
+                std::make_unique<RefreshRateConfigs>(modes, /*currentConfigId=*/HWC_CONFIG_ID_60);
+
+        lr.vote = LayerVoteType::ExplicitExactOrMultiple;
+        lr.desiredRefreshRate = Fps(23.976f);
+        lr.name = "ExplicitExactOrMultiple 23.976 fps";
+        EXPECT_EQ(HWC_CONFIG_ID_24,
+                  refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})
+                          .getModeId());
+    }
+
+    // Test that 24 will choose 23.976 if 24 is not supported
+    {
+        android::DisplayModes modes = {mConfig24Frac, mConfig25, mConfig30,
+                                       mConfig30Frac, mConfig60, mConfig60Frac};
+        auto refreshRateConfigs =
+                std::make_unique<RefreshRateConfigs>(modes, /*currentConfigId=*/HWC_CONFIG_ID_60);
+        lr.desiredRefreshRate = Fps(24.f);
+        lr.name = "ExplicitExactOrMultiple 24 fps";
+        EXPECT_EQ(HWC_CONFIG_ID_24_FRAC,
+                  refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})
+                          .getModeId());
+    }
+
+    // Test that 29.97 will prefer 59.94 over 60 and 30
+    {
+        android::DisplayModes modes = {mConfig24, mConfig24Frac, mConfig25,
+                                       mConfig30, mConfig60,     mConfig60Frac};
+        auto refreshRateConfigs =
+                std::make_unique<RefreshRateConfigs>(modes, /*currentConfigId=*/HWC_CONFIG_ID_60);
+        lr.desiredRefreshRate = Fps(29.97f);
+        lr.name = "ExplicitExactOrMultiple 29.97f fps";
+        EXPECT_EQ(HWC_CONFIG_ID_60_FRAC,
+                  refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})
+                          .getModeId());
+    }
+}
+
+TEST_F(RefreshRateConfigsTest, getBestRefreshRate_ExplicitExact_WithFractionalRefreshRates) {
+    auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}};
+    auto& lr = layers[0];
+
+    // Test that voting for supported refresh rate will select this refresh rate
+    {
+        auto refreshRateConfigs =
+                std::make_unique<RefreshRateConfigs>(m24_25_30_50_60WithFracDevice,
+                                                     /*currentConfigId=*/HWC_CONFIG_ID_60);
+
+        for (auto desiredRefreshRate : {23.976f, 24.f, 25.f, 29.97f, 30.f, 50.f, 59.94f, 60.f}) {
+            lr.vote = LayerVoteType::ExplicitExact;
+            lr.desiredRefreshRate = Fps(desiredRefreshRate);
+            std::stringstream ss;
+            ss << "ExplicitExact " << desiredRefreshRate << " fps";
+            lr.name = ss.str();
+
+            auto selecteRefreshRate =
+                    refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false});
+
+            EXPECT_TRUE(selecteRefreshRate.getFps().equalsWithMargin(lr.desiredRefreshRate))
+                    << "Expecting " << lr.desiredRefreshRate << " but it was "
+                    << selecteRefreshRate.getFps();
+        }
+    }
+
+    // Test that 23.976 will choose 24 if 23.976 is not supported
+    {
+        android::DisplayModes modes = {mConfig24,     mConfig25, mConfig30,
+                                       mConfig30Frac, mConfig60, mConfig60Frac};
+        auto refreshRateConfigs =
+                std::make_unique<RefreshRateConfigs>(modes, /*currentConfigId=*/HWC_CONFIG_ID_60);
+        lr.vote = LayerVoteType::ExplicitExact;
+        lr.desiredRefreshRate = Fps(23.976f);
+        lr.name = "ExplicitExact 23.976 fps";
+        EXPECT_EQ(HWC_CONFIG_ID_24,
+                  refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})
+                          .getModeId());
+    }
+
+    // Test that 24 will choose 23.976 if 24 is not supported
+    {
+        android::DisplayModes modes = {mConfig24Frac, mConfig25, mConfig30,
+                                       mConfig30Frac, mConfig60, mConfig60Frac};
+        auto refreshRateConfigs =
+                std::make_unique<RefreshRateConfigs>(modes, /*currentConfigId=*/HWC_CONFIG_ID_60);
+        lr.desiredRefreshRate = Fps(24.f);
+        lr.name = "ExplicitExact 24 fps";
+        EXPECT_EQ(HWC_CONFIG_ID_24_FRAC,
+                  refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})
+                          .getModeId());
     }
 }
 
@@ -2028,6 +2147,29 @@
               refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false}));
 }
 
+TEST_F(RefreshRateConfigsTest, getBestRefreshRate_FractionalRefreshRates_ExactAndDefault) {
+    RefreshRateConfigs::Config config = {.enableFrameRateOverride = true};
+    auto refreshRateConfigs =
+            std::make_unique<RefreshRateConfigs>(m24_25_30_50_60WithFracDevice,
+                                                 /*currentConfigId=*/HWC_CONFIG_ID_60, config);
+
+    auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 0.5f},
+                                                LayerRequirement{.weight = 0.5f}};
+    auto& explicitDefaultLayer = layers[0];
+    auto& explicitExactOrMultipleLayer = layers[1];
+
+    explicitExactOrMultipleLayer.vote = LayerVoteType::ExplicitExactOrMultiple;
+    explicitExactOrMultipleLayer.name = "ExplicitExactOrMultiple";
+    explicitExactOrMultipleLayer.desiredRefreshRate = Fps(60);
+
+    explicitDefaultLayer.vote = LayerVoteType::ExplicitDefault;
+    explicitDefaultLayer.name = "ExplicitDefault";
+    explicitDefaultLayer.desiredRefreshRate = Fps(59.94f);
+
+    EXPECT_EQ(mExpected60Config,
+              refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+}
+
 TEST_F(RefreshRateConfigsTest, testComparisonOperator) {
     EXPECT_TRUE(mExpected60Config < mExpected90Config);
     EXPECT_FALSE(mExpected60Config < mExpected60Config);
@@ -2116,7 +2258,38 @@
     refreshRateConfigs->setCurrentModeId(HWC_CONFIG_ID_90);
     displayRefreshRate = refreshRateConfigs->getCurrentRefreshRate().getFps();
     EXPECT_EQ(4, RefreshRateConfigs::getFrameRateDivider(displayRefreshRate, Fps(22.5f)));
-    EXPECT_EQ(4, RefreshRateConfigs::getFrameRateDivider(displayRefreshRate, Fps(22.6f)));
+
+    EXPECT_EQ(0, RefreshRateConfigs::getFrameRateDivider(Fps(24.f), Fps(25.f)));
+    EXPECT_EQ(0, RefreshRateConfigs::getFrameRateDivider(Fps(24.f), Fps(23.976f)));
+    EXPECT_EQ(0, RefreshRateConfigs::getFrameRateDivider(Fps(30.f), Fps(29.97f)));
+    EXPECT_EQ(0, RefreshRateConfigs::getFrameRateDivider(Fps(60.f), Fps(59.94f)));
+}
+
+TEST_F(RefreshRateConfigsTest, isFractionalPairOrMultiple) {
+    EXPECT_TRUE(RefreshRateConfigs::isFractionalPairOrMultiple(Fps(23.976f), Fps(24.f)));
+    EXPECT_TRUE(RefreshRateConfigs::isFractionalPairOrMultiple(Fps(24.f), Fps(23.976f)));
+
+    EXPECT_TRUE(RefreshRateConfigs::isFractionalPairOrMultiple(Fps(29.97f), Fps(30.f)));
+    EXPECT_TRUE(RefreshRateConfigs::isFractionalPairOrMultiple(Fps(30.f), Fps(29.97f)));
+
+    EXPECT_TRUE(RefreshRateConfigs::isFractionalPairOrMultiple(Fps(59.94f), Fps(60.f)));
+    EXPECT_TRUE(RefreshRateConfigs::isFractionalPairOrMultiple(Fps(60.f), Fps(59.94f)));
+
+    EXPECT_TRUE(RefreshRateConfigs::isFractionalPairOrMultiple(Fps(29.97f), Fps(60.f)));
+    EXPECT_TRUE(RefreshRateConfigs::isFractionalPairOrMultiple(Fps(60.f), Fps(29.97f)));
+
+    EXPECT_TRUE(RefreshRateConfigs::isFractionalPairOrMultiple(Fps(59.94f), Fps(30.f)));
+    EXPECT_TRUE(RefreshRateConfigs::isFractionalPairOrMultiple(Fps(30.f), Fps(59.94f)));
+
+    const std::vector<float> refreshRates = {23.976f, 24.f, 25.f, 29.97f, 30.f, 50.f, 59.94f, 60.f};
+    for (auto refreshRate : refreshRates) {
+        EXPECT_FALSE(
+                RefreshRateConfigs::isFractionalPairOrMultiple(Fps(refreshRate), Fps(refreshRate)));
+    }
+
+    EXPECT_FALSE(RefreshRateConfigs::isFractionalPairOrMultiple(Fps(24.f), Fps(25.f)));
+    EXPECT_FALSE(RefreshRateConfigs::isFractionalPairOrMultiple(Fps(23.978f), Fps(25.f)));
+    EXPECT_FALSE(RefreshRateConfigs::isFractionalPairOrMultiple(Fps(29.97f), Fps(59.94f)));
 }
 
 TEST_F(RefreshRateConfigsTest, getFrameRateOverrides_noLayers) {