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 /** 18 * @defgroup SystemHealth 19 * 20 * SystemHealth provides access to data about how various system resources are used by applications. 21 * 22 * CPU/GPU headroom APIs are designed to be best used by applications with consistent and intense 23 * workload such as games to query the remaining capacity headroom over a short period and perform 24 * optimization accordingly. Due to the nature of the fast job scheduling and frequency scaling of 25 * CPU and GPU, the headroom by nature will have "TOCTOU" problem which makes it less suitable for 26 * apps with inconsistent or low workload to take any useful action but simply monitoring. And to 27 * avoid oscillation it's not recommended to adjust workload too frequent (on each polling request) 28 * or too aggressively. As the headroom calculation is more based on reflecting past history usage 29 * than predicting future capacity. Take game as an example, if the API returns CPU headroom of 0 in 30 * one scenario (especially if it's constant across multiple calls), or some value significantly 31 * smaller than other scenarios, then it can reason that the recent performance result is more CPU 32 * bottlenecked. Then reducing the CPU workload intensity can help reserve some headroom to handle 33 * the load variance better, which can result in less frame drops or smooth FPS value. On the other 34 * hand, if the API returns large CPU headroom constantly, the app can be more confident to increase 35 * the workload and expect higher possibility of device meeting its performance expectation. 36 * App can also use thermal APIs to read the current thermal status and headroom first, then poll 37 * the CPU and GPU headroom if the device is (about to) getting thermal throttled. If the CPU/GPU 38 * headrooms provide enough significance such as one valued at 0 while the other at 100, then it can 39 * be used to infer that reducing CPU workload could be more efficient to cool down the device. 40 * There is a caveat that the power controller may scale down the frequency of the CPU and GPU due 41 * to thermal and other reasons, which can result in a higher than usual percentage usage of the 42 * capacity. 43 * 44 * @{ 45 */ 46 47 /** 48 * @file system_health.h 49 */ 50 51 #ifndef _ANDROID_SYSTEM_HEALTH_H 52 #define _ANDROID_SYSTEM_HEALTH_H 53 54 #include <sys/cdefs.h> 55 56 /****************************************************************** 57 * 58 * IMPORTANT NOTICE: 59 * 60 * This file is part of Android's set of stable system headers 61 * exposed by the Android NDK (Native Development Kit). 62 * 63 * Third-party source AND binary code relies on the definitions 64 * here to be FROZEN ON ALL UPCOMING PLATFORM RELEASES. 65 * 66 * - DO NOT MODIFY ENUMS (EXCEPT IF YOU ADD NEW 32-BIT VALUES) 67 * - DO NOT MODIFY CONSTANTS OR FUNCTIONAL MACROS 68 * - DO NOT CHANGE THE SIGNATURE OF FUNCTIONS IN ANY WAY 69 * - DO NOT CHANGE THE LAYOUT OR SIZE OF STRUCTURES 70 */ 71 72 73 #include <stdint.h> 74 #include <sys/types.h> 75 76 #if !defined(__INTRODUCED_IN) 77 #define __INTRODUCED_IN(__api_level) /* nothing */ 78 #endif 79 80 #ifdef __cplusplus 81 extern "C" { 82 #endif 83 84 /** 85 * Params used to customize the calculation of CPU headroom. 86 * 87 * Also see {@link ASystemHealth_getCpuHeadroom}. 88 */ 89 typedef struct ACpuHeadroomParams ACpuHeadroomParams; 90 91 /** 92 * Params used to customize the calculation of GPU headroom. 93 * 94 * Also see {@link ASystemHealth_getGpuHeadroom}. 95 */ 96 typedef struct AGpuHeadroomParams AGpuHeadroomParams; 97 98 typedef enum ACpuHeadroomCalculationType : int32_t { 99 /** 100 * The headroom calculation type bases on minimum value over a specified window. 101 * Introduced in API level 36. 102 */ 103 ACPU_HEADROOM_CALCULATION_TYPE_MIN = 0, 104 /** 105 * The headroom calculation type bases on average value over a specified window. 106 * Introduced in API level 36. 107 */ 108 ACPU_HEADROOM_CALCULATION_TYPE_AVERAGE = 1, 109 } ACpuHeadroomCalculationType; 110 111 typedef enum AGpuHeadroomCalculationType : int32_t { 112 /** 113 * The headroom calculation type bases on minimum value over a specified window. 114 * Introduced in API level 36. 115 */ 116 AGPU_HEADROOM_CALCULATION_TYPE_MIN = 0, 117 /** 118 * The headroom calculation type bases on average value over a specified window. 119 * Introduced in API level 36. 120 */ 121 AGPU_HEADROOM_CALCULATION_TYPE_AVERAGE = 1, 122 } AGpuHeadroomCalculationType; 123 124 /** 125 * Sets the CPU headroom calculation window size in milliseconds. 126 * 127 * Available since API level 36. 128 * 129 * @param params The params to be set. 130 * @param windowMillis The window size in milliseconds ranges from 131 * {@link ASystemHealth_getCpuHeadroomCalculationWindowRange}. The smaller the 132 * window size, the larger fluctuation in the headroom value should be expected. 133 * The default value can be retrieved from the 134 * {@link #ACpuHeadroomParams_getCalculationWindowMillis} if not set. The device 135 * will try to use the closest feasible window size to this param. 136 */ 137 void ACpuHeadroomParams_setCalculationWindowMillis(ACpuHeadroomParams *_Nonnull params, 138 int windowMillis) 139 __INTRODUCED_IN(36); 140 141 /** 142 * Gets the CPU headroom calculation window size in milliseconds. 143 * 144 * This will return the default value chosen by the device if not set. 145 * 146 * Available since API level 36. 147 * 148 * @param params The params to read from. 149 * @return This will return the default value chosen by the device if the params is not set. 150 */ 151 int ACpuHeadroomParams_getCalculationWindowMillis(ACpuHeadroomParams* _Nonnull params) 152 __INTRODUCED_IN(36); 153 154 /** 155 * Sets the GPU headroom calculation window size in milliseconds. 156 * 157 * Available since API level 36. 158 * 159 * @param params The params to be set. 160 * @param windowMillis The window size in milliseconds ranges from 161 * {@link ASystemHealth_getGpuHeadroomCalculationWindowRange}. The smaller the 162 * window size, the larger fluctuation in the headroom value should be expected. 163 * The default value can be retrieved from the 164 * {@link #AGpuHeadroomParams_getCalculationWindowMillis} if not set. The device 165 * will try to use the closest feasible window size to this param. 166 */ 167 void AGpuHeadroomParams_setCalculationWindowMillis(AGpuHeadroomParams* _Nonnull params, 168 int windowMillis) 169 __INTRODUCED_IN(36); 170 171 /** 172 * Gets the GPU headroom calculation window size in milliseconds. 173 * 174 * This will return the default value chosen by the device if not set. 175 * 176 * Available since API level 36. 177 * 178 * @param params The params to read from. 179 * @return This will return the default value chosen by the device if the params is not set. 180 */ 181 int AGpuHeadroomParams_getCalculationWindowMillis(AGpuHeadroomParams* _Nonnull params) 182 __INTRODUCED_IN(36); 183 184 /** 185 * Sets the CPU headroom calculation type in {@link ACpuHeadroomParams}. 186 * 187 * Available since API level 36. 188 * 189 * @param params The params to be set. 190 * @param calculationType The headroom calculation type. 191 */ 192 void ACpuHeadroomParams_setCalculationType(ACpuHeadroomParams* _Nonnull params, 193 ACpuHeadroomCalculationType calculationType) 194 __INTRODUCED_IN(36); 195 196 /** 197 * Gets the CPU headroom calculation type in {@link ACpuHeadroomParams}. 198 * 199 * This will return the default value chosen by the device if not set. 200 * 201 * Available since API level 36. 202 * 203 * @param params The params to read from. 204 * @return The headroom calculation type. 205 */ 206 ACpuHeadroomCalculationType 207 ACpuHeadroomParams_getCalculationType(ACpuHeadroomParams* _Nonnull params) 208 __INTRODUCED_IN(36); 209 210 /** 211 * Sets the GPU headroom calculation type in {@link AGpuHeadroomParams}. 212 * 213 * Available since API level 36. 214 * 215 * @param params The params to be set. 216 * @param calculationType The headroom calculation type. 217 */ 218 void AGpuHeadroomParams_setCalculationType(AGpuHeadroomParams* _Nonnull params, 219 AGpuHeadroomCalculationType calculationType) 220 __INTRODUCED_IN(36); 221 222 /** 223 * Gets the GPU headroom calculation type in {@link AGpuHeadroomParams}. 224 * 225 * This will return the default value chosen by the device if not set. 226 * 227 * Available since API level 36. 228 * 229 * @param params The params to read from. 230 * @return The headroom calculation type. 231 */ 232 AGpuHeadroomCalculationType 233 AGpuHeadroomParams_getCalculationType(AGpuHeadroomParams* _Nonnull params) 234 __INTRODUCED_IN(36); 235 236 /** 237 * Sets the thread TIDs to track in {@link ACpuHeadroomParams}. 238 * 239 * The TIDs should belong to the same of the process that will make the headroom call. And they 240 * should not have different core affinity. 241 * 242 * If not set or set to empty, the headroom will be based on the PID of the process making the call. 243 * 244 * Available since API level 36. 245 * 246 * @param params The params to be set. 247 * @param tids Non-null array of TIDs, where maximum size can be read from 248 * {@link ASystemHealth_getMaxCpuHeadroomTidsSize}. 249 * @param tidsSize The size of the tids array. 250 */ 251 void ACpuHeadroomParams_setTids(ACpuHeadroomParams* _Nonnull params, const int* _Nonnull tids, 252 size_t tidsSize) 253 __INTRODUCED_IN(36); 254 255 /** 256 * Creates a new instance of {@link ACpuHeadroomParams}. 257 * 258 * When the client finishes using {@link ACpuHeadroomParams}, 259 * {@link ACpuHeadroomParams_destroy} must be called to destroy 260 * and free up the resources associated with {@link ACpuHeadroomParams}. 261 * 262 * Available since API level 36. 263 * 264 * @return A new instance of {@link ACpuHeadroomParams}. 265 */ 266 ACpuHeadroomParams* _Nonnull ACpuHeadroomParams_create(void) 267 __INTRODUCED_IN(36); 268 269 /** 270 * Creates a new instance of {@link AGpuHeadroomParams}. 271 * 272 * When the client finishes using {@link AGpuHeadroomParams}, 273 * {@link AGpuHeadroomParams_destroy} must be called to destroy 274 * and free up the resources associated with {@link AGpuHeadroomParams}. 275 * 276 * Available since API level 36. 277 * 278 * @return A new instance of {@link AGpuHeadroomParams}. 279 */ 280 AGpuHeadroomParams* _Nonnull AGpuHeadroomParams_create(void) 281 __INTRODUCED_IN(36); 282 283 /** 284 * Deletes the {@link ACpuHeadroomParams} instance. 285 * 286 * Available since API level 36. 287 * 288 * @param params The params to be deleted. 289 */ 290 void ACpuHeadroomParams_destroy(ACpuHeadroomParams* _Nullable params) 291 __INTRODUCED_IN(36); 292 293 /** 294 * Deletes the {@link AGpuHeadroomParams} instance. 295 * 296 * Available since API level 36. 297 * 298 * @param params The params to be deleted. 299 */ 300 void AGpuHeadroomParams_destroy(AGpuHeadroomParams* _Nullable params) 301 __INTRODUCED_IN(36); 302 303 /** 304 * Gets the maximum number of TIDs this device supports for getting CPU headroom. 305 * 306 * See {@link ACpuHeadroomParams_setTids}. 307 * 308 * Available since API level 36. 309 * 310 * @param outSize Non-null output pointer to the max size. 311 * @return 0 on success. 312 * ENOTSUP if the CPU headroom API is unsupported. 313 */ 314 int ASystemHealth_getMaxCpuHeadroomTidsSize(size_t* _Nonnull outSize); 315 316 /** 317 * Gets the range of the calculation window size for CPU headroom. 318 * 319 * Available since API level 36. 320 * 321 * @param outMinMillis Non-null output pointer to be set to the minimum window size in milliseconds. 322 * @param outMaxMillis Non-null output pointer to be set to the maximum window size in milliseconds. 323 * @return 0 on success. 324 * ENOTSUP if API is unsupported. 325 */ 326 int ASystemHealth_getCpuHeadroomCalculationWindowRange(int32_t* _Nonnull outMinMillis, 327 int32_t* _Nonnull outMaxMillis) 328 __INTRODUCED_IN(36); 329 330 /** 331 * Gets the range of the calculation window size for GPU headroom. 332 * 333 * Available since API level 36. 334 * 335 * @param outMinMillis Non-null output pointer to be set to the minimum window size in milliseconds. 336 * @param outMaxMillis Non-null output pointer to be set to the maximum window size in milliseconds. 337 * @return 0 on success. 338 * ENOTSUP if API is unsupported. 339 */ 340 int ASystemHealth_getGpuHeadroomCalculationWindowRange(int32_t* _Nonnull outMinMillis, 341 int32_t* _Nonnull outMaxMillis) 342 __INTRODUCED_IN(36); 343 344 /** 345 * Provides an estimate of available CPU capacity headroom of the device. 346 * 347 * The value can be used by the calling application to determine if the workload was CPU bound and 348 * then take action accordingly to ensure that the workload can be completed smoothly. It can also 349 * be used with the thermal status and headroom to determine if reducing the CPU bound workload can 350 * help reduce the device temperature to avoid thermal throttling. 351 * 352 * If the params are valid, each call will perform at least one synchronous binder transaction that 353 * can take more than 1ms. So it's not recommended to call or wait for this on critical threads. 354 * Some devices may implement this as an on-demand API with lazy initialization, so the caller 355 * should expect higher latency when making the first call (especially with non-default params) 356 * since app starts or after changing params, as the device may need to change its data collection. 357 * 358 * Available since API level 36. 359 * 360 * @param params The params to customize the CPU headroom calculation, or nullptr to use default. 361 * @param outHeadroom Non-null output pointer to a single float, which will be set to the CPU 362 * headroom value. The value will be a single value or `Float.NaN` if it's 363 * temporarily unavailable due to server error or not enough user CPU workload. 364 * Each valid value ranges from [0, 100], where 0 indicates no more cpu resources 365 * can be granted. 366 * @return 0 on success. 367 * EPIPE if failed to get the CPU headroom. 368 * EPERM if the TIDs do not belong to the same process. 369 * ENOTSUP if API or requested params is unsupported. 370 */ 371 int ASystemHealth_getCpuHeadroom(const ACpuHeadroomParams* _Nullable params, 372 float* _Nonnull outHeadroom) 373 __INTRODUCED_IN(36); 374 375 /** 376 * Provides an estimate of available GPU capacity headroom of the device. 377 * 378 * The value can be used by the calling application to determine if the workload was GPU bound and 379 * then take action accordingly to ensure that the workload can be completed smoothly. It can also 380 * be used with the thermal status and headroom to determine if reducing the GPU bound workload can 381 * help reduce the device temperature to avoid thermal throttling. 382 * 383 * If the params are valid, each call will perform at least one synchronous binder transaction that 384 * can take more than 1ms. So it's not recommended to call or wait for this on critical threads. 385 * Some devices may implement this as an on-demand API with lazy initialization, so the caller 386 * should expect higher latency when making the first call (especially with non-default params) 387 * since app starts or after changing params, as the device may need to change its data collection. 388 * 389 * Available since API level 36 390 * 391 * @param params The params to customize the GPU headroom calculation, or nullptr to use default 392 * @param outHeadroom Non-null output pointer to a single float, which will be set to the GPU 393 * headroom value. The value will be a single value or `Float.NaN` if it's 394 * temporarily unavailable. 395 * Each valid value ranges from [0, 100], where 0 indicates no more gpu resources 396 * can be granted. 397 * @return 0 on success. 398 * EPIPE if failed to get the GPU headroom. 399 * ENOTSUP if API or requested params is unsupported. 400 */ 401 int ASystemHealth_getGpuHeadroom(const AGpuHeadroomParams* _Nullable params, 402 float* _Nonnull outHeadroom) 403 __INTRODUCED_IN(36); 404 405 /** 406 * Gets minimum polling interval for calling {@link ASystemHealth_getCpuHeadroom} in milliseconds. 407 * 408 * The {@link ASystemHealth_getCpuHeadroom} API may return cached result if called more frequently 409 * than the interval. 410 * 411 * Available since API level 36. 412 * 413 * @param outMinIntervalMillis Non-null output pointer to a int64_t, which 414 * will be set to the minimum polling interval in milliseconds. 415 * @return 0 on success. 416 * ENOTSUP if API is unsupported. 417 */ 418 int ASystemHealth_getCpuHeadroomMinIntervalMillis(int64_t* _Nonnull outMinIntervalMillis) 419 __INTRODUCED_IN(36); 420 421 /** 422 * Gets minimum polling interval for calling {@link ASystemHealth_getGpuHeadroom} in milliseconds. 423 * 424 * The {@link ASystemHealth_getGpuHeadroom} API may return cached result if called more frequently 425 * than the interval. 426 * 427 * Available since API level 36. 428 * 429 * @param outMinIntervalMillis Non-null output pointer to a int64_t, which 430 * will be set to the minimum polling interval in milliseconds. 431 * @return 0 on success. 432 * ENOTSUP if API is unsupported. 433 */ 434 int ASystemHealth_getGpuHeadroomMinIntervalMillis(int64_t* _Nonnull outMinIntervalMillis) 435 __INTRODUCED_IN(36); 436 437 #ifdef __cplusplus 438 } 439 #endif 440 441 #endif // _ANDROID_SYSTEM_HEALTH_H 442 443 /** @} */ 444