SurfaceFlinger: use margin when comparing fps in PhaseOffsets

To avoid any incorrect float equality due to precision errors
use 0.01Hz margin.

Test: adb shell /data/nativetest64/libsurfaceflinger_unittest/libsurfaceflinger_unittest
Bug: 147358911
Change-Id: Ief43eb7b5064b250a6255fd41542640d9c77529d
diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
index 4330742..13014c7 100644
--- a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
+++ b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
@@ -31,6 +31,11 @@
     return std::nullopt;
 }
 
+bool fpsEqualsWithMargin(float fpsA, float fpsB) {
+    static constexpr float MARGIN = 0.01f;
+    return std::abs(fpsA - fpsB) <= MARGIN;
+}
+
 } // namespace
 
 namespace android::scheduler {
@@ -61,16 +66,15 @@
                   mThresholdForNextVsync);
 }
 
-std::unordered_map<float, PhaseDurations::Offsets> PhaseOffsets::initializeOffsets(
+std::unordered_map<float, PhaseOffsets::Offsets> PhaseOffsets::initializeOffsets(
         const scheduler::RefreshRateConfigs& refreshRateConfigs) const {
-    std::unordered_map<float, PhaseDurations::Offsets> offsets;
+    std::unordered_map<float, Offsets> offsets;
 
     for (const auto& [ignored, refreshRate] : refreshRateConfigs.getAllRefreshRates()) {
-        const nsecs_t vsyncDuration = static_cast<nsecs_t>(1e9f / refreshRate.fps);
         if (refreshRate.fps > 65.0f) {
-            offsets.emplace(refreshRate.fps, getHighFpsOffsets(vsyncDuration));
+            offsets.emplace(refreshRate.fps, getHighFpsOffsets(refreshRate.vsyncPeriod));
         } else {
-            offsets.emplace(refreshRate.fps, getDefaultOffsets(vsyncDuration));
+            offsets.emplace(refreshRate.fps, getDefaultOffsets(refreshRate.vsyncPeriod));
         }
     }
     return offsets;
@@ -150,6 +154,15 @@
     };
 }
 
+PhaseOffsets::Offsets PhaseOffsets::getOffsetsForRefreshRate(float fps) const {
+    const auto iter = std::find_if(mOffsets.begin(), mOffsets.end(),
+                                   [&fps](const std::pair<float, Offsets>& candidateFps) {
+                                       return fpsEqualsWithMargin(fps, candidateFps.first);
+                                   });
+    LOG_ALWAYS_FATAL_IF(iter == mOffsets.end());
+    return iter->second;
+}
+
 static void validateSysprops() {
     const auto validatePropertyBool = [](const char* prop) {
         LOG_ALWAYS_FATAL_IF(!property_get_bool(prop, false), "%s is false", prop);
@@ -207,7 +220,7 @@
 
 std::unordered_map<float, PhaseDurations::Offsets> PhaseDurations::initializeOffsets(
         const std::vector<float>& refreshRates) const {
-    std::unordered_map<float, PhaseDurations::Offsets> offsets;
+    std::unordered_map<float, Offsets> offsets;
 
     for (const auto fps : refreshRates) {
         const nsecs_t vsyncDuration = static_cast<nsecs_t>(1e9f / fps);
@@ -275,7 +288,9 @@
         mRefreshRateFps(currentFps) {}
 
 PhaseOffsets::Offsets PhaseDurations::getOffsetsForRefreshRate(float fps) const {
-    const auto iter = mOffsets.find(fps);
+    const auto iter = std::find_if(mOffsets.begin(), mOffsets.end(), [=](const auto& candidateFps) {
+        return fpsEqualsWithMargin(fps, candidateFps.first);
+    });
     LOG_ALWAYS_FATAL_IF(iter == mOffsets.end());
     return iter->second;
 }