1 /*
2 * Copyright 2024 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 "SupportManager.h"
18
19 #include <perfmgr/HintManager.h>
20
21 #include <bitset>
22 #include <map>
23 #include <type_traits>
24
25 #include "AdpfTypes.h"
26
27 namespace aidl::google::hardware::power::impl::pixel {
28 using ::android::perfmgr::HintManager;
29
30 template <class E>
31 using SupportList = std::initializer_list<std::pair<const E, int32_t>>;
32
33 #define ASSERT_CAPACITY(Enum, list) \
34 static_assert(list.size() >= enum_size<Enum>(), \
35 "Enum " #Enum " is missing entries in SupportManager."); \
36 static_assert(std::is_same<const Enum, decltype(list.begin()->first)>::value, \
37 "Mismatched types on " #list);
38
39 // clang-format off
40 constexpr SupportList<Mode> kModeEarliestVersion {
41 {Mode::DOUBLE_TAP_TO_WAKE, 1},
42 {Mode::LOW_POWER, 1},
43 {Mode::SUSTAINED_PERFORMANCE, 1},
44 {Mode::FIXED_PERFORMANCE, 1},
45 {Mode::VR, 1},
46 {Mode::LAUNCH, 1},
47 {Mode::EXPENSIVE_RENDERING, 1},
48 {Mode::INTERACTIVE, 1},
49 {Mode::DEVICE_IDLE, 1},
50 {Mode::DISPLAY_INACTIVE, 1},
51 {Mode::AUDIO_STREAMING_LOW_LATENCY, 1},
52 {Mode::CAMERA_STREAMING_SECURE, 1},
53 {Mode::CAMERA_STREAMING_LOW, 1},
54 {Mode::CAMERA_STREAMING_MID, 1},
55 {Mode::CAMERA_STREAMING_HIGH, 1},
56 {Mode::GAME, 3},
57 {Mode::GAME_LOADING, 3},
58 {Mode::DISPLAY_CHANGE, 5},
59 {Mode::AUTOMOTIVE_PROJECTION, 5},
60 };
61
62 constexpr SupportList<Boost> kBoostEarliestVersion = {
63 {Boost::INTERACTION, 1},
64 {Boost::DISPLAY_UPDATE_IMMINENT, 1},
65 {Boost::ML_ACC, 1},
66 {Boost::AUDIO_LAUNCH, 1},
67 {Boost::CAMERA_LAUNCH, 1},
68 {Boost::CAMERA_SHOT, 1},
69 };
70
71 constexpr SupportList<SessionHint> kSessionHintEarliestVersion = {
72 {SessionHint::CPU_LOAD_UP, 4},
73 {SessionHint::CPU_LOAD_DOWN, 4},
74 {SessionHint::CPU_LOAD_RESET, 4},
75 {SessionHint::CPU_LOAD_RESUME, 4},
76 {SessionHint::POWER_EFFICIENCY, 4},
77 {SessionHint::GPU_LOAD_UP, 5},
78 {SessionHint::GPU_LOAD_DOWN, 5},
79 {SessionHint::GPU_LOAD_RESET, 5},
80 {SessionHint::CPU_LOAD_SPIKE, 6},
81 {SessionHint::GPU_LOAD_SPIKE, 6},
82 };
83
84 constexpr SupportList<SessionMode> kSessionModeEarliestVersion = {
85 {SessionMode::POWER_EFFICIENCY, 5},
86 {SessionMode::GRAPHICS_PIPELINE, 6},
87 {SessionMode::AUTO_CPU, 6},
88 {SessionMode::AUTO_GPU, 6},
89 };
90
91 constexpr SupportList<SessionTag> kSessionTagEarliestVersion {
92 {SessionTag::OTHER, 5},
93 {SessionTag::SURFACEFLINGER, 5},
94 {SessionTag::HWUI, 5},
95 {SessionTag::GAME, 5},
96 {SessionTag::APP, 5},
97 {SessionTag::SYSUI, 6},
98 };
99 // clang-format on
100
101 // Make it so that this refuses to build if you add enums but don't define them here
102 ASSERT_CAPACITY(Mode, kModeEarliestVersion);
103 ASSERT_CAPACITY(Boost, kBoostEarliestVersion);
104 ASSERT_CAPACITY(SessionHint, kSessionHintEarliestVersion);
105 ASSERT_CAPACITY(SessionMode, kSessionModeEarliestVersion);
106 ASSERT_CAPACITY(SessionTag, kSessionTagEarliestVersion);
107
108 std::map<Mode, int32_t> kModeEarliestVersionMap = kModeEarliestVersion;
109 std::map<Boost, int32_t> kBoostEarliestVersionMap = kBoostEarliestVersion;
110 std::map<SessionHint, int32_t> kSessionHintEarliestVersionMap = kSessionHintEarliestVersion;
111 std::map<SessionMode, int32_t> kSessionModeEarliestVersionMap = kSessionModeEarliestVersion;
112 std::map<SessionTag, int32_t> kSessionTagEarliestVersionMap = kSessionTagEarliestVersion;
113
makeSupportInfo()114 SupportInfo SupportManager::makeSupportInfo() {
115 SupportInfo out;
116 out.usesSessions = HintManager::GetInstance()->IsAdpfSupported();
117
118 // Assume all are unsupported
119 std::bitset<64> modeBits(0);
120 std::bitset<64> boostBits(0);
121 std::bitset<64> sessionHintBits(0);
122 std::bitset<64> sessionModeBits(0);
123 std::bitset<64> sessionTagBits(0);
124
125 for (auto &&mode : ndk::enum_range<Mode>()) {
126 modeBits[static_cast<int>(mode)] = modeSupported(mode);
127 }
128 for (auto &&boost : ndk::enum_range<Boost>()) {
129 boostBits[static_cast<int>(boost)] = boostSupported(boost);
130 }
131
132 out.modes = static_cast<int64_t>(modeBits.to_ullong());
133 out.boosts = static_cast<int64_t>(boostBits.to_ullong());
134
135 // Don't check session-specific items if they aren't supported
136 if (!out.usesSessions) {
137 return out;
138 }
139
140 for (auto &&sessionHint : ndk::enum_range<SessionHint>()) {
141 sessionHintBits[static_cast<int>(sessionHint)] = sessionHintSupported(sessionHint);
142 }
143 for (auto &&sessionMode : ndk::enum_range<SessionMode>()) {
144 sessionModeBits[static_cast<int>(sessionMode)] = sessionModeSupported(sessionMode);
145 }
146 for (auto &&sessionTag : ndk::enum_range<SessionTag>()) {
147 sessionTagBits[static_cast<int>(sessionTag)] = sessionTagSupported(sessionTag);
148 }
149
150 out.sessionHints = static_cast<int64_t>(sessionHintBits.to_ullong());
151 out.sessionModes = static_cast<int64_t>(sessionModeBits.to_ullong());
152 out.sessionTags = static_cast<int64_t>(sessionTagBits.to_ullong());
153
154 out.compositionData = {
155 .isSupported = false,
156 .disableGpuFences = false,
157 .maxBatchSize = 1,
158 .alwaysBatch = false,
159 };
160 out.headroom = {
161 .isCpuSupported = false,
162 .isGpuSupported = false,
163 .cpuMinIntervalMillis = 0,
164 .gpuMinIntervalMillis = 0,
165 };
166
167 return out;
168 }
169
modeSupported(Mode type)170 bool SupportManager::modeSupported(Mode type) {
171 auto it = kModeEarliestVersionMap.find(type);
172 if (it == kModeEarliestVersionMap.end() || IPower::version < it->second) {
173 return false;
174 }
175 bool supported = HintManager::GetInstance()->IsHintSupported(toString(type));
176 // LOW_POWER handled insides PowerHAL specifically
177 if (type == Mode::LOW_POWER) {
178 return true;
179 }
180 if (!supported && HintManager::GetInstance()->IsAdpfProfileSupported(toString(type))) {
181 return true;
182 }
183 return supported;
184 }
185
boostSupported(Boost type)186 bool SupportManager::boostSupported(Boost type) {
187 auto it = kBoostEarliestVersionMap.find(type);
188 if (it == kBoostEarliestVersionMap.end() || IPower::version < it->second) {
189 return false;
190 }
191 bool supported = HintManager::GetInstance()->IsHintSupported(toString(type));
192 if (!supported && HintManager::GetInstance()->IsAdpfProfileSupported(toString(type))) {
193 return true;
194 }
195 return supported;
196 }
197
sessionHintSupported(SessionHint type)198 bool SupportManager::sessionHintSupported(SessionHint type) {
199 auto it = kSessionHintEarliestVersionMap.find(type);
200 if (it == kSessionHintEarliestVersionMap.end() || IPower::version < it->second) {
201 return false;
202 }
203 switch (type) {
204 case SessionHint::POWER_EFFICIENCY:
205 return false;
206 default:
207 return true;
208 }
209 }
210
sessionModeSupported(SessionMode type)211 bool SupportManager::sessionModeSupported(SessionMode type) {
212 auto it = kSessionModeEarliestVersionMap.find(type);
213 if (it == kSessionModeEarliestVersionMap.end() || IPower::version < it->second) {
214 return false;
215 }
216 switch (type) {
217 case SessionMode::POWER_EFFICIENCY:
218 return false;
219 case SessionMode::GRAPHICS_PIPELINE:
220 return false;
221 default:
222 return true;
223 }
224 }
225
sessionTagSupported(SessionTag type)226 bool SupportManager::sessionTagSupported(SessionTag type) {
227 auto it = kSessionTagEarliestVersionMap.find(type);
228 if (it == kSessionTagEarliestVersionMap.end() || IPower::version < it->second) {
229 return false;
230 }
231 return true;
232 }
233
234 } // namespace aidl::google::hardware::power::impl::pixel
235