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 
19 namespace android::scheduler {
20 using FrameRateOverride = DisplayEventReceiver::Event::FrameRateOverride;
21 
getFrameRateOverrideForUid(uid_t uid,bool supportsFrameRateOverrideByContent) const22 std::optional<Fps> FrameRateOverrideMappings::getFrameRateOverrideForUid(
23         uid_t uid, bool supportsFrameRateOverrideByContent) const {
24     std::lock_guard lock(mFrameRateOverridesLock);
25 
26     {
27         const auto iter = mFrameRateOverridesFromBackdoor.find(uid);
28         if (iter != mFrameRateOverridesFromBackdoor.end()) {
29             return iter->second;
30         }
31     }
32 
33     {
34         const auto iter = mFrameRateOverridesFromGameManager.find(uid);
35         if (iter != mFrameRateOverridesFromGameManager.end()) {
36             return iter->second;
37         }
38     }
39 
40     if (!supportsFrameRateOverrideByContent) {
41         return std::nullopt;
42     }
43 
44     {
45         const auto iter = mFrameRateOverridesByContent.find(uid);
46         if (iter != mFrameRateOverridesByContent.end()) {
47             return iter->second;
48         }
49     }
50 
51     return std::nullopt;
52 }
53 
getAllFrameRateOverrides(bool supportsFrameRateOverrideByContent)54 std::vector<FrameRateOverride> FrameRateOverrideMappings::getAllFrameRateOverrides(
55         bool supportsFrameRateOverrideByContent) {
56     std::lock_guard lock(mFrameRateOverridesLock);
57 
58     std::vector<FrameRateOverride> overrides;
59     overrides.reserve(maxOverridesCount());
60 
61     for (const auto& [uid, frameRate] : mFrameRateOverridesFromBackdoor) {
62         overrides.emplace_back(FrameRateOverride{uid, frameRate.getValue()});
63     }
64     for (const auto& [uid, frameRate] : mFrameRateOverridesFromGameManager) {
65         if (std::find_if(overrides.begin(), overrides.end(),
66                          [uid = uid](auto i) { return i.uid == uid; }) == overrides.end()) {
67             overrides.emplace_back(FrameRateOverride{uid, frameRate.getValue()});
68         }
69     }
70 
71     if (!supportsFrameRateOverrideByContent) {
72         return overrides;
73     }
74 
75     for (const auto& [uid, frameRate] : mFrameRateOverridesByContent) {
76         if (std::find_if(overrides.begin(), overrides.end(),
77                          [uid = uid](auto i) { return i.uid == uid; }) == overrides.end()) {
78             overrides.emplace_back(FrameRateOverride{uid, frameRate.getValue()});
79         }
80     }
81 
82     return overrides;
83 }
84 
dump(utils::Dumper & dumper) const85 void FrameRateOverrideMappings::dump(utils::Dumper& dumper) const {
86     using namespace std::string_view_literals;
87 
88     std::lock_guard lock(mFrameRateOverridesLock);
89 
90     const bool hasOverrides = maxOverridesCount() > 0;
91     dumper.dump("FrameRateOverrides"sv, hasOverrides ? ""sv : "none"sv);
92 
93     if (!hasOverrides) return;
94 
95     dump(dumper, "setFrameRate"sv, mFrameRateOverridesByContent);
96     dump(dumper, "GameManager"sv, mFrameRateOverridesFromGameManager);
97     dump(dumper, "Backdoor"sv, mFrameRateOverridesFromBackdoor);
98 }
99 
dump(utils::Dumper & dumper,std::string_view name,const UidToFrameRateOverride & overrides) const100 void FrameRateOverrideMappings::dump(utils::Dumper& dumper, std::string_view name,
101                                      const UidToFrameRateOverride& overrides) const {
102     if (overrides.empty()) return;
103 
104     utils::Dumper::Indent indent(dumper);
105     dumper.dump(name);
106     {
107         utils::Dumper::Indent indent(dumper);
108         for (const auto& [uid, frameRate] : overrides) {
109             using namespace std::string_view_literals;
110             dumper.dump("(uid, frameRate)"sv, uid, frameRate);
111         }
112     }
113 }
114 
updateFrameRateOverridesByContent(const UidToFrameRateOverride & frameRateOverrides)115 bool FrameRateOverrideMappings::updateFrameRateOverridesByContent(
116         const UidToFrameRateOverride& frameRateOverrides) {
117     std::lock_guard lock(mFrameRateOverridesLock);
118     if (!std::equal(mFrameRateOverridesByContent.begin(), mFrameRateOverridesByContent.end(),
119                     frameRateOverrides.begin(), frameRateOverrides.end(),
120                     [](const auto& lhs, const auto& rhs) {
121                         return lhs.first == rhs.first && isApproxEqual(lhs.second, rhs.second);
122                     })) {
123         mFrameRateOverridesByContent = frameRateOverrides;
124         return true;
125     }
126     return false;
127 }
128 
setGameModeRefreshRateForUid(FrameRateOverride frameRateOverride)129 void FrameRateOverrideMappings::setGameModeRefreshRateForUid(FrameRateOverride frameRateOverride) {
130     std::lock_guard lock(mFrameRateOverridesLock);
131     if (frameRateOverride.frameRateHz != 0.f) {
132         mFrameRateOverridesFromGameManager[frameRateOverride.uid] =
133                 Fps::fromValue(frameRateOverride.frameRateHz);
134     } else {
135         mFrameRateOverridesFromGameManager.erase(frameRateOverride.uid);
136     }
137 }
138 
setPreferredRefreshRateForUid(FrameRateOverride frameRateOverride)139 void FrameRateOverrideMappings::setPreferredRefreshRateForUid(FrameRateOverride frameRateOverride) {
140     std::lock_guard lock(mFrameRateOverridesLock);
141     if (frameRateOverride.frameRateHz != 0.f) {
142         mFrameRateOverridesFromBackdoor[frameRateOverride.uid] =
143                 Fps::fromValue(frameRateOverride.frameRateHz);
144     } else {
145         mFrameRateOverridesFromBackdoor.erase(frameRateOverride.uid);
146     }
147 }
148 } // namespace android::scheduler
149