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