Refactor game-related frame rate override to LayerHistory

Previously game-related frame rate overrides are maintained in Scheduler
only, which does not provide votes to the actual display refresh rate.
This causes an issue that these overrides will only be viable when they
are the divisors of the display refresh rate at the moment.

This change moves the game intervention and newly-added game default
frame rate overrides to LayerHistory, where overrides will be considered
in layer frame rate votes. Scheduler will get this information and
select the display frame rate accordingly

Bug: 286084594
Test: SurfaceFlinger unit test
      atest LayerHistoryTest
      atest FrameRateOverrideMappingsTest
      atest CtsGraphicsTestCases --test-filter "SetFrameRateTest*"
      atest CtsFrameRateOverrideTestCases
Change-Id: I9957af8e53fbdd44b8d70028572e6db8e779a1fe
diff --git a/services/surfaceflinger/Scheduler/FrameRateOverrideMappings.cpp b/services/surfaceflinger/Scheduler/FrameRateOverrideMappings.cpp
index cb9bfe9..82af61a 100644
--- a/services/surfaceflinger/Scheduler/FrameRateOverrideMappings.cpp
+++ b/services/surfaceflinger/Scheduler/FrameRateOverrideMappings.cpp
@@ -15,6 +15,7 @@
  */
 
 #include "FrameRateOverrideMappings.h"
+#include <common/FlagManager.h>
 
 namespace android::scheduler {
 using FrameRateOverride = DisplayEventReceiver::Event::FrameRateOverride;
@@ -30,7 +31,7 @@
         }
     }
 
-    {
+    if (!FlagManager::getInstance().game_default_frame_rate()) {
         const auto iter = mFrameRateOverridesFromGameManager.find(uid);
         if (iter != mFrameRateOverridesFromGameManager.end()) {
             return iter->second;
@@ -61,10 +62,13 @@
     for (const auto& [uid, frameRate] : mFrameRateOverridesFromBackdoor) {
         overrides.emplace_back(FrameRateOverride{uid, frameRate.getValue()});
     }
-    for (const auto& [uid, frameRate] : mFrameRateOverridesFromGameManager) {
-        if (std::find_if(overrides.begin(), overrides.end(),
-                         [uid = uid](auto i) { return i.uid == uid; }) == overrides.end()) {
-            overrides.emplace_back(FrameRateOverride{uid, frameRate.getValue()});
+
+    if (!FlagManager::getInstance().game_default_frame_rate()) {
+        for (const auto& [uid, frameRate] : mFrameRateOverridesFromGameManager) {
+            if (std::find_if(overrides.begin(), overrides.end(),
+                             [uid = uid](auto i) { return i.uid == uid; }) == overrides.end()) {
+                overrides.emplace_back(FrameRateOverride{uid, frameRate.getValue()});
+            }
         }
     }
 
@@ -93,7 +97,9 @@
     if (!hasOverrides) return;
 
     dump(dumper, "setFrameRate"sv, mFrameRateOverridesByContent);
-    dump(dumper, "GameManager"sv, mFrameRateOverridesFromGameManager);
+    if (!FlagManager::getInstance().game_default_frame_rate()) {
+        dump(dumper, "GameManager"sv, mFrameRateOverridesFromGameManager);
+    }
     dump(dumper, "Backdoor"sv, mFrameRateOverridesFromBackdoor);
 }
 
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp
index 9c00302..5ce883c 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp
@@ -266,6 +266,7 @@
         if (isLayerActive(*info, threshold)) {
             // Set layer vote if set
             const auto frameRate = info->getSetFrameRateVote();
+
             const auto voteType = [&]() {
                 switch (frameRate.vote.type) {
                     case Layer::FrameRateCompatibility::Default:
@@ -283,12 +284,40 @@
                 }
             }();
 
-            if (frameRate.isValid()) {
-                const auto type = info->isVisible() ? voteType : LayerVoteType::NoVote;
-                info->setLayerVote({type, frameRate.vote.rate, frameRate.vote.seamlessness,
-                                    frameRate.category});
+            if (FlagManager::getInstance().game_default_frame_rate()) {
+                // Determine the layer frame rate considering the following priorities:
+                // 1. Game mode intervention frame rate override
+                // 2. setFrameRate vote
+                // 3. Game default frame rate override
+
+                const auto& [gameModeFrameRateOverride, gameDefaultFrameRateOverride] =
+                        getGameFrameRateOverrideLocked(info->getOwnerUid());
+
+                const auto gameFrameRateOverrideVoteType =
+                        info->isVisible() ? LayerVoteType::ExplicitDefault : LayerVoteType::NoVote;
+
+                const auto setFrameRateVoteType =
+                        info->isVisible() ? voteType : LayerVoteType::NoVote;
+
+                if (gameModeFrameRateOverride.isValid()) {
+                    info->setLayerVote({gameFrameRateOverrideVoteType, gameModeFrameRateOverride});
+                } else if (frameRate.isValid()) {
+                    info->setLayerVote({setFrameRateVoteType, frameRate.vote.rate,
+                                        frameRate.vote.seamlessness, frameRate.category});
+                } else if (gameDefaultFrameRateOverride.isValid()) {
+                    info->setLayerVote(
+                            {gameFrameRateOverrideVoteType, gameDefaultFrameRateOverride});
+                } else {
+                    info->resetLayerVote();
+                }
             } else {
-                info->resetLayerVote();
+                if (frameRate.isValid()) {
+                    const auto type = info->isVisible() ? voteType : LayerVoteType::NoVote;
+                    info->setLayerVote({type, frameRate.vote.rate, frameRate.vote.seamlessness,
+                                        frameRate.category});
+                } else {
+                    info->resetLayerVote();
+                }
             }
 
             it++;
@@ -347,4 +376,56 @@
     return isSmallDirty;
 }
 
+void LayerHistory::updateGameModeFrameRateOverride(FrameRateOverride frameRateOverride) {
+    const uid_t uid = frameRateOverride.uid;
+    std::lock_guard lock(mLock);
+    if (frameRateOverride.frameRateHz != 0.f) {
+        mGameFrameRateOverride[uid].first = Fps::fromValue(frameRateOverride.frameRateHz);
+    } else {
+        if (mGameFrameRateOverride[uid].second.getValue() == 0.f) {
+            mGameFrameRateOverride.erase(uid);
+        } else {
+            mGameFrameRateOverride[uid].first = Fps();
+        }
+    }
+}
+
+void LayerHistory::updateGameDefaultFrameRateOverride(FrameRateOverride frameRateOverride) {
+    const uid_t uid = frameRateOverride.uid;
+    std::lock_guard lock(mLock);
+    if (frameRateOverride.frameRateHz != 0.f) {
+        mGameFrameRateOverride[uid].second = Fps::fromValue(frameRateOverride.frameRateHz);
+    } else {
+        if (mGameFrameRateOverride[uid].first.getValue() == 0.f) {
+            mGameFrameRateOverride.erase(uid);
+        } else {
+            mGameFrameRateOverride[uid].second = Fps();
+        }
+    }
+}
+
+std::pair<Fps, Fps> LayerHistory::getGameFrameRateOverride(uid_t uid) const {
+    if (!FlagManager::getInstance().game_default_frame_rate()) {
+        return std::pair<Fps, Fps>();
+    }
+
+    std::lock_guard lock(mLock);
+
+    return getGameFrameRateOverrideLocked(uid);
+}
+
+std::pair<Fps, Fps> LayerHistory::getGameFrameRateOverrideLocked(uid_t uid) const {
+    if (!FlagManager::getInstance().game_default_frame_rate()) {
+        return std::pair<Fps, Fps>();
+    }
+
+    const auto it = mGameFrameRateOverride.find(uid);
+
+    if (it == mGameFrameRateOverride.end()) {
+        return std::pair<Fps, Fps>(Fps(), Fps());
+    }
+
+    return it->second;
+}
+
 } // namespace android::scheduler
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h
index 5a9445b..930d06c 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.h
+++ b/services/surfaceflinger/Scheduler/LayerHistory.h
@@ -43,6 +43,7 @@
 
 class LayerHistory {
 public:
+    using FrameRateOverride = DisplayEventReceiver::Event::FrameRateOverride;
     using LayerVoteType = RefreshRateSelector::LayerVoteType;
     static constexpr std::chrono::nanoseconds kMaxPeriodForHistory = 1s;
 
@@ -89,6 +90,15 @@
 
     bool isSmallDirtyArea(uint32_t dirtyArea, float threshold) const;
 
+    // Updates the frame rate override set by game mode intervention
+    void updateGameModeFrameRateOverride(FrameRateOverride frameRateOverride) EXCLUDES(mLock);
+
+    // Updates the frame rate override set by game default frame rate
+    void updateGameDefaultFrameRateOverride(FrameRateOverride frameRateOverride) EXCLUDES(mLock);
+
+    std::pair<Fps, Fps> getGameFrameRateOverride(uid_t uid) const EXCLUDES(mLock);
+    std::pair<Fps, Fps> getGameFrameRateOverrideLocked(uid_t uid) const REQUIRES(mLock);
+
 private:
     friend class LayerHistoryTest;
     friend class LayerHistoryIntegrationTest;
@@ -137,6 +147,13 @@
 
     // Whether a mode change is in progress or not
     std::atomic<bool> mModeChangePending = false;
+
+    // A list to look up the game frame rate overrides
+    // Each entry includes:
+    // 1. the uid of the app
+    // 2. a pair of game mode intervention frame frame and game default frame rate override
+    // set to 0.0 if there is no such override
+    std::map<uid_t, std::pair<Fps, Fps>> mGameFrameRateOverride GUARDED_BY(mLock);
 };
 
 } // namespace scheduler
diff --git a/services/surfaceflinger/Scheduler/LayerInfo.h b/services/surfaceflinger/Scheduler/LayerInfo.h
index 50bb83d..326e444 100644
--- a/services/surfaceflinger/Scheduler/LayerInfo.h
+++ b/services/surfaceflinger/Scheduler/LayerInfo.h
@@ -175,7 +175,8 @@
                             bool pendingModeChange, const LayerProps& props);
 
     // Sets an explicit layer vote. This usually comes directly from the application via
-    // ANativeWindow_setFrameRate API
+    // ANativeWindow_setFrameRate API. This is also used by Game Default Frame Rate and
+    // Game Mode Intervention Frame Rate.
     void setLayerVote(LayerVote vote) { mLayerVote = vote; }
 
     // Sets the default layer vote. This will be the layer vote after calling to resetLayerVote().
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index aa8d54d..6a85788 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -1226,12 +1226,27 @@
     mLayerHistory.setDisplayArea(displayArea);
 }
 
-void Scheduler::setGameModeRefreshRateForUid(FrameRateOverride frameRateOverride) {
+void Scheduler::setGameModeFrameRateForUid(FrameRateOverride frameRateOverride) {
     if (frameRateOverride.frameRateHz > 0.f && frameRateOverride.frameRateHz < 1.f) {
         return;
     }
 
-    mFrameRateOverrideMappings.setGameModeRefreshRateForUid(frameRateOverride);
+    if (FlagManager::getInstance().game_default_frame_rate()) {
+        // update the frame rate override mapping in LayerHistory
+        mLayerHistory.updateGameModeFrameRateOverride(frameRateOverride);
+    } else {
+        mFrameRateOverrideMappings.setGameModeRefreshRateForUid(frameRateOverride);
+    }
+}
+
+void Scheduler::setGameDefaultFrameRateForUid(FrameRateOverride frameRateOverride) {
+    if (!FlagManager::getInstance().game_default_frame_rate() ||
+        (frameRateOverride.frameRateHz > 0.f && frameRateOverride.frameRateHz < 1.f)) {
+        return;
+    }
+
+    // update the frame rate override mapping in LayerHistory
+    mLayerHistory.updateGameDefaultFrameRateOverride(frameRateOverride);
 }
 
 void Scheduler::setPreferredRefreshRateForUid(FrameRateOverride frameRateOverride) {
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 454ef83..ce585c6 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -293,7 +293,17 @@
     // FrameRateOverride.refreshRateHz == 0 means no preference.
     void setPreferredRefreshRateForUid(FrameRateOverride);
 
-    void setGameModeRefreshRateForUid(FrameRateOverride);
+    // Stores the frame rate override that a game should run at set by game interventions.
+    // FrameRateOverride.refreshRateHz == 0 means no preference.
+    void setGameModeFrameRateForUid(FrameRateOverride) EXCLUDES(mDisplayLock);
+
+    // Stores the frame rate override that a game should run rat set by default game frame rate.
+    // FrameRateOverride.refreshRateHz == 0 means no preference, game default game frame rate is not
+    // enabled.
+    //
+    // "ro.surface_flinger.game_default_frame_rate_override" sets the frame rate value,
+    // "persist.graphics.game_default_frame_rate.enabled" controls whether this feature is enabled.
+    void setGameDefaultFrameRateForUid(FrameRateOverride) EXCLUDES(mDisplayLock);
 
     void updateSmallAreaDetection(std::vector<std::pair<int32_t, float>>& uidThresholdMappings);