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