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