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