1 /*
2  * Copyright 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "FrameRateOverrideMappings.h"
18 #include <common/FlagManager.h>
19 
20 namespace android::scheduler {
21 using FrameRateOverride = DisplayEventReceiver::Event::FrameRateOverride;
22 
getFrameRateOverrideForUid(uid_t uid,bool supportsFrameRateOverrideByContent) const23 std::optional<Fps> FrameRateOverrideMappings::getFrameRateOverrideForUid(
24         uid_t uid, bool supportsFrameRateOverrideByContent) const {
25     std::lock_guard lock(mFrameRateOverridesLock);
26 
27     {
28         const auto iter = mFrameRateOverridesFromBackdoor.find(uid);
29         if (iter != mFrameRateOverridesFromBackdoor.end()) {
30             return iter->second;
31         }
32     }
33 
34     if (!FlagManager::getInstance().game_default_frame_rate()) {
35         const auto iter = mFrameRateOverridesFromGameManager.find(uid);
36         if (iter != mFrameRateOverridesFromGameManager.end()) {
37             return iter->second;
38         }
39     }
40 
41     if (!supportsFrameRateOverrideByContent) {
42         return std::nullopt;
43     }
44 
45     {
46         const auto iter = mFrameRateOverridesByContent.find(uid);
47         if (iter != mFrameRateOverridesByContent.end()) {
48             return iter->second;
49         }
50     }
51 
52     return std::nullopt;
53 }
54 
getAllFrameRateOverrides(bool supportsFrameRateOverrideByContent)55 std::vector<FrameRateOverride> FrameRateOverrideMappings::getAllFrameRateOverrides(
56         bool supportsFrameRateOverrideByContent) {
57     std::lock_guard lock(mFrameRateOverridesLock);
58 
59     std::vector<FrameRateOverride> overrides;
60     overrides.reserve(maxOverridesCount());
61 
62     for (const auto& [uid, frameRate] : mFrameRateOverridesFromBackdoor) {
63         overrides.emplace_back(FrameRateOverride{uid, frameRate.getValue()});
64     }
65 
66     if (!FlagManager::getInstance().game_default_frame_rate()) {
67         for (const auto& [uid, frameRate] : mFrameRateOverridesFromGameManager) {
68             if (std::find_if(overrides.begin(), overrides.end(),
69                              [uid = uid](auto i) { return i.uid == uid; }) == overrides.end()) {
70                 overrides.emplace_back(FrameRateOverride{uid, frameRate.getValue()});
71             }
72         }
73     }
74 
75     if (!supportsFrameRateOverrideByContent) {
76         return overrides;
77     }
78 
79     for (const auto& [uid, frameRate] : mFrameRateOverridesByContent) {
80         if (std::find_if(overrides.begin(), overrides.end(),
81                          [uid = uid](auto i) { return i.uid == uid; }) == overrides.end()) {
82             overrides.emplace_back(FrameRateOverride{uid, frameRate.getValue()});
83         }
84     }
85 
86     return overrides;
87 }
88 
dump(utils::Dumper & dumper) const89 void FrameRateOverrideMappings::dump(utils::Dumper& dumper) const {
90     using namespace std::string_view_literals;
91 
92     std::lock_guard lock(mFrameRateOverridesLock);
93 
94     const bool hasOverrides = maxOverridesCount() > 0;
95     dumper.dump("FrameRateOverrides"sv, hasOverrides ? ""sv : "none"sv);
96 
97     if (!hasOverrides) return;
98 
99     dump(dumper, "setFrameRate"sv, mFrameRateOverridesByContent);
100     if (!FlagManager::getInstance().game_default_frame_rate()) {
101         dump(dumper, "GameManager"sv, mFrameRateOverridesFromGameManager);
102     }
103     dump(dumper, "Backdoor"sv, mFrameRateOverridesFromBackdoor);
104 }
105 
dump(utils::Dumper & dumper,std::string_view name,const UidToFrameRateOverride & overrides) const106 void FrameRateOverrideMappings::dump(utils::Dumper& dumper, std::string_view name,
107                                      const UidToFrameRateOverride& overrides) const {
108     if (overrides.empty()) return;
109 
110     utils::Dumper::Indent indent(dumper);
111     dumper.dump(name);
112     {
113         utils::Dumper::Indent indent(dumper);
114         for (const auto& [uid, frameRate] : overrides) {
115             using namespace std::string_view_literals;
116             dumper.dump("(uid, frameRate)"sv, uid, frameRate);
117         }
118     }
119 }
120 
updateFrameRateOverridesByContent(const UidToFrameRateOverride & frameRateOverrides)121 bool FrameRateOverrideMappings::updateFrameRateOverridesByContent(
122         const UidToFrameRateOverride& frameRateOverrides) {
123     std::lock_guard lock(mFrameRateOverridesLock);
124     if (!std::equal(mFrameRateOverridesByContent.begin(), mFrameRateOverridesByContent.end(),
125                     frameRateOverrides.begin(), frameRateOverrides.end(),
126                     [](const auto& lhs, const auto& rhs) {
127                         return lhs.first == rhs.first && isApproxEqual(lhs.second, rhs.second);
128                     })) {
129         mFrameRateOverridesByContent = frameRateOverrides;
130         return true;
131     }
132     return false;
133 }
134 
setGameModeRefreshRateForUid(FrameRateOverride frameRateOverride)135 void FrameRateOverrideMappings::setGameModeRefreshRateForUid(FrameRateOverride frameRateOverride) {
136     std::lock_guard lock(mFrameRateOverridesLock);
137     if (frameRateOverride.frameRateHz != 0.f) {
138         mFrameRateOverridesFromGameManager[frameRateOverride.uid] =
139                 Fps::fromValue(frameRateOverride.frameRateHz);
140     } else {
141         mFrameRateOverridesFromGameManager.erase(frameRateOverride.uid);
142     }
143 }
144 
setPreferredRefreshRateForUid(FrameRateOverride frameRateOverride)145 void FrameRateOverrideMappings::setPreferredRefreshRateForUid(FrameRateOverride frameRateOverride) {
146     std::lock_guard lock(mFrameRateOverridesLock);
147     if (frameRateOverride.frameRateHz != 0.f) {
148         mFrameRateOverridesFromBackdoor[frameRateOverride.uid] =
149                 Fps::fromValue(frameRateOverride.frameRateHz);
150     } else {
151         mFrameRateOverridesFromBackdoor.erase(frameRateOverride.uid);
152     }
153 }
154 } // namespace android::scheduler
155