1 /*
2  * Copyright (C) 2021 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 APerformanceHint Performance Hint Manager
19  *
20  * APerformanceHint allows apps to create performance hint sessions for groups
21  * of threads, and provide hints to the system about the workload of those threads,
22  * to help the system more accurately allocate power for them. It is the NDK
23  * counterpart to the Java PerformanceHintManager SDK API.
24  *
25  * @{
26  */
27 
28 /**
29  * @file performance_hint.h
30  * @brief API for creating and managing a hint session.
31  */
32 
33 
34 #ifndef ANDROID_NATIVE_PERFORMANCE_HINT_H
35 #define ANDROID_NATIVE_PERFORMANCE_HINT_H
36 
37 #include <sys/cdefs.h>
38 
39 /******************************************************************
40  *
41  * IMPORTANT NOTICE:
42  *
43  *   This file is part of Android's set of stable system headers
44  *   exposed by the Android NDK (Native Development Kit).
45  *
46  *   Third-party source AND binary code relies on the definitions
47  *   here to be FROZEN ON ALL UPCOMING PLATFORM RELEASES.
48  *
49  *   - DO NOT MODIFY ENUMS (EXCEPT IF YOU ADD NEW 32-BIT VALUES)
50  *   - DO NOT MODIFY CONSTANTS OR FUNCTIONAL MACROS
51  *   - DO NOT CHANGE THE SIGNATURE OF FUNCTIONS IN ANY WAY
52  *   - DO NOT CHANGE THE LAYOUT OR SIZE OF STRUCTURES
53  */
54 
55 #include <android/api-level.h>
56 #include <stdint.h>
57 #include <unistd.h>
58 
59 __BEGIN_DECLS
60 
61 struct APerformanceHintManager;
62 struct APerformanceHintSession;
63 struct AWorkDuration;
64 
65 /**
66  * {@link AWorkDuration} is an opaque type that represents the breakdown of the
67  * actual workload duration in each component internally.
68  *
69  * A new {@link AWorkDuration} can be obtained using
70  * {@link AWorkDuration_create()}, when the client finishes using
71  * {@link AWorkDuration}, {@link AWorkDuration_release()} must be
72  * called to destroy and free up the resources associated with
73  * {@link AWorkDuration}.
74  *
75  * This file provides a set of functions to allow clients to set the measured
76  * work duration of each component on {@link AWorkDuration}.
77  *
78  * - AWorkDuration_setWorkPeriodStartTimestampNanos()
79  * - AWorkDuration_setActualTotalDurationNanos()
80  * - AWorkDuration_setActualCpuDurationNanos()
81  * - AWorkDuration_setActualGpuDurationNanos()
82  */
83 typedef struct AWorkDuration AWorkDuration;
84 
85 /**
86  * An opaque type representing a handle to a performance hint manager.
87  * It must be released after use.
88  *
89  * To use:<ul>
90  *    <li>Obtain the performance hint manager instance by calling
91  *        {@link APerformanceHint_getManager} function.</li>
92  *    <li>Create an {@link APerformanceHintSession} with
93  *        {@link APerformanceHint_createSession}.</li>
94  *    <li>Get the preferred update rate in nanoseconds with
95  *        {@link APerformanceHint_getPreferredUpdateRateNanos}.</li>
96  */
97 typedef struct APerformanceHintManager APerformanceHintManager;
98 
99 /**
100  * An opaque type representing a handle to a performance hint session.
101  * A session can only be acquired from a {@link APerformanceHintManager}
102  * with {@link APerformanceHint_createSession}. It must be
103  * freed with {@link APerformanceHint_closeSession} after use.
104  *
105  * A Session represents a group of threads with an inter-related workload such that hints for
106  * their performance should be considered as a unit. The threads in a given session should be
107  * long-lived and not created or destroyed dynamically.
108  *
109  * The work duration API can be used with periodic workloads to dynamically adjust thread
110  * performance and keep the work on schedule while optimizing the available power budget.
111  * When using the work duration API, the starting target duration should be specified
112  * while creating the session, and can later be adjusted with
113  * {@link APerformanceHint_updateTargetWorkDuration}. While using the work duration
114  * API, the client is expected to call {@link APerformanceHint_reportActualWorkDuration} each
115  * cycle to report the actual time taken to complete to the system.
116  *
117  * Note, methods of {@link APerformanceHintSession_*} are not thread safe so callers must
118  * ensure thread safety.
119  *
120  * All timings should be from `std::chrono::steady_clock` or `clock_gettime(CLOCK_MONOTONIC, ...)`
121  */
122 typedef struct APerformanceHintSession APerformanceHintSession;
123 
124 /**
125   * Acquire an instance of the performance hint manager.
126   *
127   * @return APerformanceHintManager instance on success, nullptr on failure.
128   */
129 APerformanceHintManager* _Nullable APerformanceHint_getManager()
130                          __INTRODUCED_IN(__ANDROID_API_T__);
131 
132 /**
133  * Creates a session for the given set of threads and sets their initial target work
134  * duration.
135  *
136  * @param manager The performance hint manager instance.
137  * @param threadIds The list of threads to be associated with this session. They must be part of
138  *     this process' thread group.
139  * @param size The size of the list of threadIds.
140  * @param initialTargetWorkDurationNanos The target duration in nanoseconds for the new session.
141  *     This must be positive if using the work duration API, or 0 otherwise.
142  * @return APerformanceHintManager instance on success, nullptr on failure.
143  */
144 APerformanceHintSession* _Nullable APerformanceHint_createSession(
145         APerformanceHintManager* _Nonnull manager,
146         const int32_t* _Nonnull threadIds, size_t size,
147         int64_t initialTargetWorkDurationNanos) __INTRODUCED_IN(__ANDROID_API_T__);
148 
149 /**
150  * Get preferred update rate information for this device.
151  *
152  * @param manager The performance hint manager instance.
153  * @return the preferred update rate supported by device software.
154  */
155 int64_t APerformanceHint_getPreferredUpdateRateNanos(
156         APerformanceHintManager* _Nonnull manager) __INTRODUCED_IN(__ANDROID_API_T__);
157 
158 /**
159  * Updates this session's target duration for each cycle of work.
160  *
161  * @param session The performance hint session instance to update.
162  * @param targetDurationNanos The new desired duration in nanoseconds. This must be positive.
163  * @return 0 on success.
164  *         EINVAL if targetDurationNanos is not positive.
165  *         EPIPE if communication with the system service has failed.
166  */
167 int APerformanceHint_updateTargetWorkDuration(
168         APerformanceHintSession* _Nonnull session,
169         int64_t targetDurationNanos) __INTRODUCED_IN(__ANDROID_API_T__);
170 
171 /**
172  * Reports the actual duration for the last cycle of work.
173  *
174  * The system will attempt to adjust the scheduling and performance of the
175  * threads within the thread group to bring the actual duration close to the target duration.
176  *
177  * @param session The performance hint session instance to update.
178  * @param actualDurationNanos The duration of time the thread group took to complete its last
179  *     task in nanoseconds. This must be positive.
180  * @return 0 on success.
181  *         EINVAL if actualDurationNanos is not positive.
182  *         EPIPE if communication with the system service has failed.
183  */
184 int APerformanceHint_reportActualWorkDuration(
185         APerformanceHintSession* _Nonnull session,
186         int64_t actualDurationNanos) __INTRODUCED_IN(__ANDROID_API_T__);
187 
188 /**
189  * Release the performance hint manager pointer acquired via
190  * {@link APerformanceHint_createSession}.
191  *
192  * @param session The performance hint session instance to release.
193  */
194 void APerformanceHint_closeSession(
195         APerformanceHintSession* _Nonnull session) __INTRODUCED_IN(__ANDROID_API_T__);
196 
197 /**
198  * Set a list of threads to the performance hint session. This operation will replace
199  * the current list of threads with the given list of threads.
200  *
201  * @param session The performance hint session instance to update.
202  * @param threadIds The list of threads to be associated with this session. They must be part of
203  *     this app's thread group.
204  * @param size The size of the list of threadIds.
205  * @return 0 on success.
206  *         EINVAL if the list of thread ids is empty or if any of the thread ids are not part of
207                the thread group.
208  *         EPIPE if communication with the system service has failed.
209  *         EPERM if any thread id doesn't belong to the application.
210  */
211 int APerformanceHint_setThreads(
212         APerformanceHintSession* _Nonnull session,
213         const pid_t* _Nonnull threadIds,
214         size_t size) __INTRODUCED_IN(__ANDROID_API_U__);
215 
216 /**
217  * This tells the session that these threads can be
218  * safely scheduled to prefer power efficiency over performance.
219  *
220  * @param session The performance hint session instance to update.
221  * @param enabled The flag which sets whether this session will use power-efficient scheduling.
222  * @return 0 on success.
223  *         EPIPE if communication with the system service has failed.
224  */
225 int APerformanceHint_setPreferPowerEfficiency(
226         APerformanceHintSession* _Nonnull session,
227         bool enabled) __INTRODUCED_IN(__ANDROID_API_V__);
228 
229 /**
230  * Reports the durations for the last cycle of work.
231  *
232  * The system will attempt to adjust the scheduling and performance of the
233  * threads within the thread group to bring the actual duration close to the target duration.
234  *
235  * @param session The {@link APerformanceHintSession} instance to update.
236  * @param workDuration The {@link AWorkDuration} structure of times the thread group took to
237  *     complete its last task in nanoseconds breaking down into different components.
238  *
239  *     The work period start timestamp and actual total duration must be greater than zero.
240  *
241  *     The actual CPU and GPU durations must be greater than or equal to zero, and at least one
242  *     of them must be greater than zero. When one of them is equal to zero, it means that type
243  *     of work was not measured for this workload.
244  *
245  * @return 0 on success.
246  *         EINVAL if any duration is an invalid number.
247  *         EPIPE if communication with the system service has failed.
248  */
249 int APerformanceHint_reportActualWorkDuration2(
250         APerformanceHintSession* _Nonnull session,
251         AWorkDuration* _Nonnull workDuration) __INTRODUCED_IN(__ANDROID_API_V__);
252 
253 /**
254  * Creates a new AWorkDuration. When the client finishes using {@link AWorkDuration}, it should
255  * call {@link AWorkDuration_release()} to destroy {@link AWorkDuration} and release all resources
256  * associated with it.
257  *
258  * @return AWorkDuration on success and nullptr otherwise.
259  */
260 AWorkDuration* _Nonnull AWorkDuration_create() __INTRODUCED_IN(__ANDROID_API_V__);
261 
262 /**
263  * Destroys {@link AWorkDuration} and free all resources associated to it.
264  *
265  * @param aWorkDuration The {@link AWorkDuration} created by calling {@link AWorkDuration_create()}
266  */
267 void AWorkDuration_release(AWorkDuration* _Nonnull aWorkDuration)
268      __INTRODUCED_IN(__ANDROID_API_V__);
269 
270 /**
271  * Sets the work period start timestamp in nanoseconds.
272  *
273  * @param aWorkDuration The {@link AWorkDuration} created by calling {@link AWorkDuration_create()}
274  * @param workPeriodStartTimestampNanos The work period start timestamp in nanoseconds based on
275  *        CLOCK_MONOTONIC about when the work starts. This timestamp must be greater than zero.
276  */
277 void AWorkDuration_setWorkPeriodStartTimestampNanos(AWorkDuration* _Nonnull aWorkDuration,
278         int64_t workPeriodStartTimestampNanos) __INTRODUCED_IN(__ANDROID_API_V__);
279 
280 /**
281  * Sets the actual total work duration in nanoseconds.
282  *
283  * @param aWorkDuration The {@link AWorkDuration} created by calling {@link AWorkDuration_create()}
284  * @param actualTotalDurationNanos The actual total work duration in nanoseconds. This number must
285  *        be greater than zero.
286  */
287 void AWorkDuration_setActualTotalDurationNanos(AWorkDuration* _Nonnull aWorkDuration,
288         int64_t actualTotalDurationNanos) __INTRODUCED_IN(__ANDROID_API_V__);
289 
290 /**
291  * Sets the actual CPU work duration in nanoseconds.
292  *
293  * @param aWorkDuration The {@link AWorkDuration} created by calling {@link AWorkDuration_create()}
294  * @param actualCpuDurationNanos The actual CPU work duration in nanoseconds. This number must be
295  *        greater than or equal to zero. If it is equal to zero, that means the CPU was not
296  *        measured.
297  */
298 void AWorkDuration_setActualCpuDurationNanos(AWorkDuration* _Nonnull aWorkDuration,
299         int64_t actualCpuDurationNanos) __INTRODUCED_IN(__ANDROID_API_V__);
300 
301 /**
302  * Sets the actual GPU work duration in nanoseconds.
303  *
304  * @param aWorkDuration The {@link AWorkDuration} created by calling {@link AWorkDuration_create()}.
305  * @param actualGpuDurationNanos The actual GPU work duration in nanoseconds, the number must be
306  *        greater than or equal to zero. If it is equal to zero, that means the GPU was not
307  *        measured.
308  */
309 void AWorkDuration_setActualGpuDurationNanos(AWorkDuration* _Nonnull aWorkDuration,
310         int64_t actualGpuDurationNanos) __INTRODUCED_IN(__ANDROID_API_V__);
311 
312 __END_DECLS
313 
314 #endif // ANDROID_NATIVE_PERFORMANCE_HINT_H
315 
316 /** @} */
317