xref: /aosp_15_r20/frameworks/base/native/android/system_health.cpp (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
1 /*
2  * Copyright (C) 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 <aidl/android/hardware/power/CpuHeadroomParams.h>
18 #include <aidl/android/hardware/power/GpuHeadroomParams.h>
19 #include <aidl/android/os/CpuHeadroomParamsInternal.h>
20 #include <aidl/android/os/GpuHeadroomParamsInternal.h>
21 #include <aidl/android/os/IHintManager.h>
22 #include <android/binder_manager.h>
23 #include <android/system_health.h>
24 #include <binder/IServiceManager.h>
25 #include <binder/Status.h>
26 
27 using namespace android;
28 using namespace aidl::android::os;
29 namespace hal = aidl::android::hardware::power;
30 
31 struct ACpuHeadroomParams : public CpuHeadroomParamsInternal {};
32 struct AGpuHeadroomParams : public GpuHeadroomParamsInternal {};
33 
34 const int CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN = 50;
35 const int CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX = 10000;
36 const int GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN = 50;
37 const int GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX = 10000;
38 const int CPU_HEADROOM_MAX_TID_COUNT = 5;
39 
40 struct ASystemHealthManager {
41 public:
42     static ASystemHealthManager* getInstance();
43     ASystemHealthManager(std::shared_ptr<IHintManager>& hintManager);
44     ASystemHealthManager() = delete;
45     ~ASystemHealthManager();
46     int getCpuHeadroom(const ACpuHeadroomParams* params, float* outHeadroom);
47     int getGpuHeadroom(const AGpuHeadroomParams* params, float* outHeadroom);
48     int getCpuHeadroomMinIntervalMillis(int64_t* outMinIntervalMillis);
49     int getGpuHeadroomMinIntervalMillis(int64_t* outMinIntervalMillis);
50 
51 private:
52     static ASystemHealthManager* create(std::shared_ptr<IHintManager> hintManager);
53     std::shared_ptr<IHintManager> mHintManager;
54 };
55 
getInstance()56 ASystemHealthManager* ASystemHealthManager::getInstance() {
57     static std::once_flag creationFlag;
58     static ASystemHealthManager* instance = nullptr;
59     std::call_once(creationFlag, []() { instance = create(nullptr); });
60     return instance;
61 }
62 
ASystemHealthManager(std::shared_ptr<IHintManager> & hintManager)63 ASystemHealthManager::ASystemHealthManager(std::shared_ptr<IHintManager>& hintManager)
64       : mHintManager(std::move(hintManager)) {}
65 
~ASystemHealthManager()66 ASystemHealthManager::~ASystemHealthManager() {}
67 
create(std::shared_ptr<IHintManager> hintManager)68 ASystemHealthManager* ASystemHealthManager::create(std::shared_ptr<IHintManager> hintManager) {
69     if (!hintManager) {
70         hintManager = IHintManager::fromBinder(
71                 ndk::SpAIBinder(AServiceManager_waitForService("performance_hint")));
72     }
73     if (hintManager == nullptr) {
74         ALOGE("%s: PerformanceHint service is not ready ", __FUNCTION__);
75         return nullptr;
76     }
77     return new ASystemHealthManager(hintManager);
78 }
79 
ASystemHealth_acquireManager()80 ASystemHealthManager* ASystemHealth_acquireManager() {
81     return ASystemHealthManager::getInstance();
82 }
83 
getCpuHeadroom(const ACpuHeadroomParams * params,float * outHeadroom)84 int ASystemHealthManager::getCpuHeadroom(const ACpuHeadroomParams* params, float* outHeadroom) {
85     std::optional<hal::CpuHeadroomResult> res;
86     ::ndk::ScopedAStatus ret;
87     CpuHeadroomParamsInternal internalParams;
88     if (!params) {
89         ret = mHintManager->getCpuHeadroom(internalParams, &res);
90     } else {
91         ret = mHintManager->getCpuHeadroom(*params, &res);
92     }
93     if (!ret.isOk()) {
94         LOG_ALWAYS_FATAL_IF(ret.getExceptionCode() == EX_ILLEGAL_ARGUMENT,
95                             "Invalid ACpuHeadroomParams: %s", ret.getMessage());
96         ALOGE("ASystemHealth_getCpuHeadroom fails: %s", ret.getMessage());
97         if (ret.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
98             return ENOTSUP;
99         } else if (ret.getExceptionCode() == EX_SECURITY) {
100             return EPERM;
101         }
102         return EPIPE;
103     }
104     *outHeadroom = res->get<hal::CpuHeadroomResult::Tag::globalHeadroom>();
105     return OK;
106 }
107 
getGpuHeadroom(const AGpuHeadroomParams * params,float * outHeadroom)108 int ASystemHealthManager::getGpuHeadroom(const AGpuHeadroomParams* params, float* outHeadroom) {
109     std::optional<hal::GpuHeadroomResult> res;
110     ::ndk::ScopedAStatus ret;
111     GpuHeadroomParamsInternal internalParams;
112     if (!params) {
113         ret = mHintManager->getGpuHeadroom(internalParams, &res);
114     } else {
115         ret = mHintManager->getGpuHeadroom(*params, &res);
116     }
117     if (!ret.isOk()) {
118         LOG_ALWAYS_FATAL_IF(ret.getExceptionCode() == EX_ILLEGAL_ARGUMENT,
119                             "Invalid AGpuHeadroomParams: %s", ret.getMessage());
120         ALOGE("ASystemHealth_getGpuHeadroom fails: %s", ret.getMessage());
121         if (ret.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
122             return ENOTSUP;
123         }
124         return EPIPE;
125     }
126     *outHeadroom = res->get<hal::GpuHeadroomResult::Tag::globalHeadroom>();
127     return OK;
128 }
129 
getCpuHeadroomMinIntervalMillis(int64_t * outMinIntervalMillis)130 int ASystemHealthManager::getCpuHeadroomMinIntervalMillis(int64_t* outMinIntervalMillis) {
131     int64_t minIntervalMillis = 0;
132     ::ndk::ScopedAStatus ret = mHintManager->getCpuHeadroomMinIntervalMillis(&minIntervalMillis);
133     if (!ret.isOk()) {
134         ALOGE("ASystemHealth_getCpuHeadroomMinIntervalMillis fails: %s", ret.getMessage());
135         if (ret.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
136             return ENOTSUP;
137         }
138         return EPIPE;
139     }
140     *outMinIntervalMillis = minIntervalMillis;
141     return OK;
142 }
143 
getGpuHeadroomMinIntervalMillis(int64_t * outMinIntervalMillis)144 int ASystemHealthManager::getGpuHeadroomMinIntervalMillis(int64_t* outMinIntervalMillis) {
145     int64_t minIntervalMillis = 0;
146     ::ndk::ScopedAStatus ret = mHintManager->getGpuHeadroomMinIntervalMillis(&minIntervalMillis);
147     if (!ret.isOk()) {
148         ALOGE("ASystemHealth_getGpuHeadroomMinIntervalMillis fails: %s", ret.getMessage());
149         if (ret.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
150             return ENOTSUP;
151         }
152         return EPIPE;
153     }
154     *outMinIntervalMillis = minIntervalMillis;
155     return OK;
156 }
157 
ASystemHealth_getCpuHeadroom(const ACpuHeadroomParams * _Nullable params,float * _Nonnull outHeadroom)158 int ASystemHealth_getCpuHeadroom(const ACpuHeadroomParams* _Nullable params,
159                                  float* _Nonnull outHeadroom) {
160     LOG_ALWAYS_FATAL_IF(outHeadroom == nullptr, "%s: outHeadroom should not be null", __FUNCTION__);
161     auto manager = ASystemHealthManager::getInstance();
162     if (manager == nullptr) return ENOTSUP;
163     return manager->getCpuHeadroom(params, outHeadroom);
164 }
165 
ASystemHealth_getGpuHeadroom(const AGpuHeadroomParams * _Nullable params,float * _Nonnull outHeadroom)166 int ASystemHealth_getGpuHeadroom(const AGpuHeadroomParams* _Nullable params,
167                                  float* _Nonnull outHeadroom) {
168     LOG_ALWAYS_FATAL_IF(outHeadroom == nullptr, "%s: outHeadroom should not be null", __FUNCTION__);
169     auto manager = ASystemHealthManager::getInstance();
170     if (manager == nullptr) return ENOTSUP;
171     return manager->getGpuHeadroom(params, outHeadroom);
172 }
173 
ASystemHealth_getCpuHeadroomMinIntervalMillis(int64_t * _Nonnull outMinIntervalMillis)174 int ASystemHealth_getCpuHeadroomMinIntervalMillis(int64_t* _Nonnull outMinIntervalMillis) {
175     LOG_ALWAYS_FATAL_IF(outMinIntervalMillis == nullptr,
176                         "%s: outMinIntervalMillis should not be null", __FUNCTION__);
177     auto manager = ASystemHealthManager::getInstance();
178     if (manager == nullptr) return ENOTSUP;
179     return manager->getCpuHeadroomMinIntervalMillis(outMinIntervalMillis);
180 }
181 
ASystemHealth_getGpuHeadroomMinIntervalMillis(int64_t * _Nonnull outMinIntervalMillis)182 int ASystemHealth_getGpuHeadroomMinIntervalMillis(int64_t* _Nonnull outMinIntervalMillis) {
183     LOG_ALWAYS_FATAL_IF(outMinIntervalMillis == nullptr,
184                         "%s: outMinIntervalMillis should not be null", __FUNCTION__);
185     auto manager = ASystemHealthManager::getInstance();
186     if (manager == nullptr) return ENOTSUP;
187     return manager->getGpuHeadroomMinIntervalMillis(outMinIntervalMillis);
188 }
189 
ACpuHeadroomParams_setCalculationWindowMillis(ACpuHeadroomParams * _Nonnull params,int windowMillis)190 void ACpuHeadroomParams_setCalculationWindowMillis(ACpuHeadroomParams* _Nonnull params,
191                                                    int windowMillis) {
192     LOG_ALWAYS_FATAL_IF(windowMillis < CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN ||
193                                 windowMillis > CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX,
194                         "%s: windowMillis should be in range [50, 10000] but got %d", __FUNCTION__,
195                         windowMillis);
196     params->calculationWindowMillis = windowMillis;
197 }
198 
AGpuHeadroomParams_setCalculationWindowMillis(AGpuHeadroomParams * _Nonnull params,int windowMillis)199 void AGpuHeadroomParams_setCalculationWindowMillis(AGpuHeadroomParams* _Nonnull params,
200                                                    int windowMillis) {
201     LOG_ALWAYS_FATAL_IF(windowMillis < GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN ||
202                                 windowMillis > GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX,
203                         "%s: windowMillis should be in range [50, 10000] but got %d", __FUNCTION__,
204                         windowMillis);
205     params->calculationWindowMillis = windowMillis;
206 }
207 
ACpuHeadroomParams_getCalculationWindowMillis(ACpuHeadroomParams * _Nonnull params)208 int ACpuHeadroomParams_getCalculationWindowMillis(ACpuHeadroomParams* _Nonnull params) {
209     return params->calculationWindowMillis;
210 }
211 
AGpuHeadroomParams_getCalculationWindowMillis(AGpuHeadroomParams * _Nonnull params)212 int AGpuHeadroomParams_getCalculationWindowMillis(AGpuHeadroomParams* _Nonnull params) {
213     return params->calculationWindowMillis;
214 }
215 
ACpuHeadroomParams_setTids(ACpuHeadroomParams * _Nonnull params,const int * _Nonnull tids,int tidsSize)216 void ACpuHeadroomParams_setTids(ACpuHeadroomParams* _Nonnull params, const int* _Nonnull tids,
217                                 int tidsSize) {
218     LOG_ALWAYS_FATAL_IF(tids == nullptr, "%s: tids should not be null", __FUNCTION__);
219     LOG_ALWAYS_FATAL_IF(tidsSize > CPU_HEADROOM_MAX_TID_COUNT, "%s: tids size should not exceed 5",
220                         __FUNCTION__);
221     params->tids.resize(tidsSize);
222     params->tids.clear();
223     for (int i = 0; i < tidsSize; ++i) {
224         LOG_ALWAYS_FATAL_IF(tids[i] <= 0, "ACpuHeadroomParams_setTids: Invalid non-positive tid %d",
225                             tids[i]);
226         params->tids[i] = tids[i];
227     }
228 }
229 
ACpuHeadroomParams_setCalculationType(ACpuHeadroomParams * _Nonnull params,ACpuHeadroomCalculationType calculationType)230 void ACpuHeadroomParams_setCalculationType(ACpuHeadroomParams* _Nonnull params,
231                                            ACpuHeadroomCalculationType calculationType) {
232     LOG_ALWAYS_FATAL_IF(calculationType < ACpuHeadroomCalculationType::
233                                                   ACPU_HEADROOM_CALCULATION_TYPE_MIN ||
234                                 calculationType > ACpuHeadroomCalculationType::
235                                                           ACPU_HEADROOM_CALCULATION_TYPE_AVERAGE,
236                         "%s: calculationType should be one of ACpuHeadroomCalculationType values "
237                         "but got %d",
238                         __FUNCTION__, calculationType);
239     params->calculationType = static_cast<hal::CpuHeadroomParams::CalculationType>(calculationType);
240 }
241 
ACpuHeadroomParams_getCalculationType(ACpuHeadroomParams * _Nonnull params)242 ACpuHeadroomCalculationType ACpuHeadroomParams_getCalculationType(
243         ACpuHeadroomParams* _Nonnull params) {
244     return static_cast<ACpuHeadroomCalculationType>(params->calculationType);
245 }
246 
AGpuHeadroomParams_setCalculationType(AGpuHeadroomParams * _Nonnull params,AGpuHeadroomCalculationType calculationType)247 void AGpuHeadroomParams_setCalculationType(AGpuHeadroomParams* _Nonnull params,
248                                            AGpuHeadroomCalculationType calculationType) {
249     LOG_ALWAYS_FATAL_IF(calculationType < AGpuHeadroomCalculationType::
250                                                   AGPU_HEADROOM_CALCULATION_TYPE_MIN ||
251                                 calculationType > AGpuHeadroomCalculationType::
252                                                           AGPU_HEADROOM_CALCULATION_TYPE_AVERAGE,
253                         "%s: calculationType should be one of AGpuHeadroomCalculationType values "
254                         "but got %d",
255                         __FUNCTION__, calculationType);
256     params->calculationType = static_cast<hal::GpuHeadroomParams::CalculationType>(calculationType);
257 }
258 
AGpuHeadroomParams_getCalculationType(AGpuHeadroomParams * _Nonnull params)259 AGpuHeadroomCalculationType AGpuHeadroomParams_getCalculationType(
260         AGpuHeadroomParams* _Nonnull params) {
261     return static_cast<AGpuHeadroomCalculationType>(params->calculationType);
262 }
263 
ACpuHeadroomParams_create()264 ACpuHeadroomParams* _Nonnull ACpuHeadroomParams_create() {
265     return new ACpuHeadroomParams();
266 }
267 
AGpuHeadroomParams_create()268 AGpuHeadroomParams* _Nonnull AGpuHeadroomParams_create() {
269     return new AGpuHeadroomParams();
270 }
271 
ACpuHeadroomParams_destroy(ACpuHeadroomParams * _Nonnull params)272 void ACpuHeadroomParams_destroy(ACpuHeadroomParams* _Nonnull params) {
273     delete params;
274 }
275 
AGpuHeadroomParams_destroy(AGpuHeadroomParams * _Nonnull params)276 void AGpuHeadroomParams_destroy(AGpuHeadroomParams* _Nonnull params) {
277     delete params;
278 }
279