diff options
author | 2025-02-26 11:55:07 -0800 | |
---|---|---|
committer | 2025-02-26 11:55:07 -0800 | |
commit | 98bdc04b7658fde0a99403fc052d1d18e7d48ea6 (patch) | |
tree | eddfcd420408117ba0399a190f75c13cf2db0036 /include | |
parent | 7ba28a3a24fadce84a590a6f4a94907840fe814c (diff) | |
parent | 8c6afcf151af438342729f2399c43560ae1f353c (diff) |
Merge 25Q1 (ab/12770256) to aosp-main-future
Bug: 385190204
Merged-In: I0fb567cbcca67a2fc6c088f652c8af570b8d7e53
Change-Id: Iaae8cd491ff963cf422f4b19c54be33e1244a9a1
Diffstat (limited to 'include')
23 files changed, 1716 insertions, 72 deletions
diff --git a/include/android/display_luts.h b/include/android/display_luts.h new file mode 100644 index 0000000000..eae2bfd351 --- /dev/null +++ b/include/android/display_luts.h @@ -0,0 +1,167 @@ +/* + * 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. + */ + +/** + * @addtogroup NativeActivity Native Activity + * @{ + */ + +/** + * @file display_luts.h + */ +#pragma once + +#include <inttypes.h> + +__BEGIN_DECLS + +/** + * The dimension of the lut + */ +enum ADisplayLuts_Dimension : int32_t { + ADISPLAYLUTS_ONE_DIMENSION = 1, + ADISPLAYLUTS_THREE_DIMENSION = 3, +}; +typedef enum ADisplayLuts_Dimension ADisplayLuts_Dimension; + +/** + * The sampling key used by the lut + */ +enum ADisplayLuts_SamplingKey : int32_t { + ADISPLAYLUTS_SAMPLINGKEY_RGB = 0, + ADISPLAYLUTS_SAMPLINGKEY_MAX_RGB = 1, + ADISPLAYLUTS_SAMPLINGKEY_CIE_Y = 2, +}; +typedef enum ADisplayLuts_SamplingKey ADisplayLuts_SamplingKey; + +/** + * Used to get and set display luts entry + */ +typedef struct ADisplayLutsEntry ADisplayLutsEntry; + +/** + * Used to get and set display luts + */ +typedef struct ADisplayLuts ADisplayLuts; + +/** + * Creates a \a ADisplayLutsEntry entry. + * + * You are responsible for mamanging the memory of the returned object. + * Always call \a ADisplayLutsEntry_destroy to release it after use. + * + * Functions like \a ADisplayLuts_set create their own copies of entries, + * therefore they don't take the ownership of the instance created by + * \a ADisplayLutsEntry_create. + * + * @param buffer The lut raw buffer. The function creates a copy of it and does not need to + * outlive the life of the ADisplayLutsEntry. + * @param length The length of lut raw buffer + * @param dimension The dimension of the lut. see \a ADisplayLuts_Dimension + * @param key The sampling key used by the lut. see \a ADisplayLuts_SamplingKey + * @return a new \a ADisplayLutsEntry instance. + */ +ADisplayLutsEntry* _Nonnull ADisplayLutsEntry_createEntry(float* _Nonnull buffer, + int32_t length, ADisplayLuts_Dimension dimension, ADisplayLuts_SamplingKey key) + __INTRODUCED_IN(36); + +/** + * Destroy the \a ADisplayLutsEntry instance. + * + * @param entry The entry to be destroyed + */ +void ADisplayLutsEntry_destroy(ADisplayLutsEntry* _Nullable entry) __INTRODUCED_IN(36); + +/** + * Gets the dimension of the entry. + * + * The function is only valid for the lifetime of the `entry`. + * + * @param entry The entry to query + * @return the dimension of the lut + */ +ADisplayLuts_Dimension ADisplayLutsEntry_getDimension(const ADisplayLutsEntry* _Nonnull entry) + __INTRODUCED_IN(36); + +/** + * Gets the size for each dimension of the entry. + * + * The function is only valid for the lifetime of the `entry`. + * + * @param entry The entry to query + * @return the size of each dimension of the lut + */ +int32_t ADisplayLutsEntry_getSize(const ADisplayLutsEntry* _Nonnull entry) + __INTRODUCED_IN(36); + +/** + * Gets the sampling key used by the entry. + * + * The function is only valid for the lifetime of the `entry`. + * + * @param entry The entry to query + * @return the sampling key used by the lut + */ +ADisplayLuts_SamplingKey ADisplayLutsEntry_getSamplingKey(const ADisplayLutsEntry* _Nonnull entry) + __INTRODUCED_IN(36); + +/** + * Gets the lut buffer of the entry. + * + * The function is only valid for the lifetime of the `entry`. + * + * @param entry The entry to query + * @return a pointer to the raw lut buffer + */ +const float* _Nonnull ADisplayLutsEntry_getBuffer(const ADisplayLutsEntry* _Nonnull entry) + __INTRODUCED_IN(36); + +/** + * Creates a \a ADisplayLuts instance. + * + * You are responsible for mamanging the memory of the returned object. + * Always call \a ADisplayLuts_destroy to release it after use. E.g., after calling + * the function \a ASurfaceTransaction_setLuts. + * + * @return a new \a ADisplayLuts instance + */ +ADisplayLuts* _Nonnull ADisplayLuts_create() __INTRODUCED_IN(36); + +/** + * Sets Luts in order to be applied. + * + * The function accepts a single 1D Lut, or a single 3D Lut or both 1D and 3D Lut in order. + * And the function will replace any previously set lut(s). + * If you want to clear the previously set lut(s), set `entries` to be nullptr, + * and `numEntries` will be internally ignored. + * + * @param luts the pointer of the \a ADisplayLuts instance + * @param entries the pointer of the array of lut entries to be applied + * @param numEntries the number of lut entries. The value should be either 1 or 2. + */ +void ADisplayLuts_setEntries(ADisplayLuts* _Nonnull luts, + ADisplayLutsEntry* _Nullable *_Nullable entries, int32_t numEntries) __INTRODUCED_IN(36); + +/** + * Deletes the \a ADisplayLuts instance. + * + * @param luts The luts to be destroyed + */ +void ADisplayLuts_destroy(ADisplayLuts* _Nullable luts) __INTRODUCED_IN(36); + +__END_DECLS + +/** @} */
\ No newline at end of file diff --git a/include/android/keycodes.h b/include/android/keycodes.h index 79cdbcaf7b..495e0bdb1f 100644 --- a/include/android/keycodes.h +++ b/include/android/keycodes.h @@ -843,6 +843,44 @@ enum { AKEYCODE_EMOJI_PICKER = 317, /** Take Screenshot */ AKEYCODE_SCREENSHOT = 318, + /** To start dictate to an input field */ + AKEYCODE_DICTATE = 319, + /** AC New */ + AKEYCODE_NEW = 320, + /** AC Close */ + AKEYCODE_CLOSE = 321, + /** To toggle 'Do Not Disturb' mode */ + AKEYCODE_DO_NOT_DISTURB = 322, + /** To Print */ + AKEYCODE_PRINT = 323, + /** To Lock the screen */ + AKEYCODE_LOCK = 324, + /** To toggle fullscreen mode (on the current application) */ + AKEYCODE_FULLSCREEN = 325, + /** F13 key */ + AKEYCODE_F13 = 326, + /** F14 key */ + AKEYCODE_F14 = 327, + /** F15 key */ + AKEYCODE_F15 = 328, + /** F16 key */ + AKEYCODE_F16 = 329, + /** F17 key */ + AKEYCODE_F17 = 330, + /** F18 key */ + AKEYCODE_F18 = 331, + /** F19 key */ + AKEYCODE_F19 = 332, + /** F20 key */ + AKEYCODE_F20 = 333, + /** F21 key */ + AKEYCODE_F21 = 334, + /** F22 key */ + AKEYCODE_F22 = 335, + /** F23 key */ + AKEYCODE_F23 = 336, + /** F24 key */ + AKEYCODE_F24 = 337, // NOTE: If you add a new keycode here you must also add it to several other files. // Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list. diff --git a/include/android/performance_hint.h b/include/android/performance_hint.h index 3486e9b1d7..2b4a5f5f53 100644 --- a/include/android/performance_hint.h +++ b/include/android/performance_hint.h @@ -19,9 +19,23 @@ * * APerformanceHint allows apps to create performance hint sessions for groups * of threads, and provide hints to the system about the workload of those threads, - * to help the system more accurately allocate power for them. It is the NDK + * to help the system more accurately allocate resources for them. It is the NDK * counterpart to the Java PerformanceHintManager SDK API. * + * This API is intended for periodic workloads, such as frame production. Clients are + * expected to create an instance of APerformanceHintManager, create a session with + * that, and then set a target duration for the session. Then, they can report the actual + * work duration at the end of each cycle to inform the framework about how long those + * workloads are taking. The framework will then compare the actual durations to the target + * duration and attempt to help the client reach a steady state under the target. + * + * Unlike reportActualWorkDuration, the "notify..." hints are intended to be sent in + * advance of large changes in the workload, to prevent them from going over the target + * when there is a sudden, unforseen change. Their effects are intended to last for only + * one cycle, after which reportActualWorkDuration will have a chance to catch up. + * These hints should be used judiciously, only in cases where the workload is changing + * substantially. To enforce that, they are tracked using a per-app rate limiter to avoid + * excessive hinting and encourage clients to be mindful about when to send them. * @{ */ @@ -35,6 +49,7 @@ #define ANDROID_NATIVE_PERFORMANCE_HINT_H #include <sys/cdefs.h> +#include <jni.h> /****************************************************************** * @@ -61,6 +76,8 @@ __BEGIN_DECLS struct APerformanceHintManager; struct APerformanceHintSession; struct AWorkDuration; +struct ANativeWindow; +struct ASurfaceControl; /** * {@link AWorkDuration} is an opaque type that represents the breakdown of the @@ -96,9 +113,24 @@ typedef struct AWorkDuration AWorkDuration; typedef struct APerformanceHintManager APerformanceHintManager; /** + * An opaque type representing a handle to a performance hint session creation configuration. + * It is consumed by {@link APerformanceHint_createSessionUsingConfig}. + * + * A session creation config encapsulates the required information for a session. + * Additionally, the caller can set various settings for the session, + * to be passed during creation, streamlining the session setup process. + * + * The caller may reuse this object and modify the settings in it + * to create additional sessions. + * + */ +typedef struct ASessionCreationConfig ASessionCreationConfig; + +/** * An opaque type representing a handle to a performance hint session. * A session can only be acquired from a {@link APerformanceHintManager} - * with {@link APerformanceHint_createSession}. It must be + * with {@link APerformanceHint_createSession} + * or {@link APerformanceHint_createSessionUsingConfig}. It must be * freed with {@link APerformanceHint_closeSession} after use. * * A Session represents a group of threads with an inter-related workload such that hints for @@ -120,6 +152,9 @@ typedef struct APerformanceHintManager APerformanceHintManager; */ typedef struct APerformanceHintSession APerformanceHintSession; +typedef struct ANativeWindow ANativeWindow; +typedef struct ASurfaceControl ASurfaceControl; + /** * Acquire an instance of the performance hint manager. * @@ -138,7 +173,7 @@ APerformanceHintManager* _Nullable APerformanceHint_getManager() * @param size The size of the list of threadIds. * @param initialTargetWorkDurationNanos The target duration in nanoseconds for the new session. * This must be positive if using the work duration API, or 0 otherwise. - * @return APerformanceHintManager instance on success, nullptr on failure. + * @return APerformanceHintSession pointer on success, nullptr on failure. */ APerformanceHintSession* _Nullable APerformanceHint_createSession( APerformanceHintManager* _Nonnull manager, @@ -146,6 +181,20 @@ APerformanceHintSession* _Nullable APerformanceHint_createSession( int64_t initialTargetWorkDurationNanos) __INTRODUCED_IN(__ANDROID_API_T__); /** + * Creates a session for the given set of threads that are graphics pipeline threads + * and set their initial target work duration. + * + * @param manager The performance hint manager instance. + * @param config The configuration struct containing required information + * to create a session. + * @return APerformanceHintSession pointer on success, nullptr on failure. + */ +APerformanceHintSession* _Nullable APerformanceHint_createSessionUsingConfig( + APerformanceHintManager* _Nonnull manager, + ASessionCreationConfig* _Nonnull config) + __INTRODUCED_IN(36); + +/** * Get preferred update rate information for this device. * * @param manager The performance hint manager instance. @@ -155,6 +204,15 @@ int64_t APerformanceHint_getPreferredUpdateRateNanos( APerformanceHintManager* _Nonnull manager) __INTRODUCED_IN(__ANDROID_API_T__); /** + * Get maximum number of graphics pipieline threads per-app for this device. + * + * @param manager The performance hint manager instance. + * @return the maximum number of graphics pipeline threads supported by device. + */ + int APerformanceHint_getMaxGraphicsPipelineThreadsCount( + APerformanceHintManager* _Nonnull manager) __INTRODUCED_IN(36); + +/** * Updates this session's target duration for each cycle of work. * * @param session The performance hint session instance to update. @@ -188,6 +246,9 @@ int APerformanceHint_reportActualWorkDuration( * Release the performance hint manager pointer acquired via * {@link APerformanceHint_createSession}. * + * This cannot be used to close a Java PerformanceHintManager.Session, as its + * lifecycle is tied to the object in the SDK. + * * @param session The performance hint session instance to release. */ void APerformanceHint_closeSession( @@ -250,16 +311,122 @@ int APerformanceHint_reportActualWorkDuration2( AWorkDuration* _Nonnull workDuration) __INTRODUCED_IN(__ANDROID_API_V__); /** + * Informs the framework of an upcoming increase in the workload of a graphics pipeline + * bound to this session. The user can specify whether the increase is expected to be + * on the CPU, GPU, or both. + * + * Sending hints for both CPU and GPU counts as two separate hints for the purposes of the + * rate limiter. + * + * @param cpu Indicates if the workload increase is expected to affect the CPU. + * @param gpu Indicates if the workload increase is expected to affect the GPU. + * @param debugName A required string used to identify this specific hint during + * tracing. This debug string will only be held for the duration of the + * method, and can be safely discarded after. + * + * @return 0 on success. + * EINVAL if no hints were requested. + * EBUSY if the hint was rate limited. + * EPIPE if communication with the system service has failed. + * ENOTSUP if the hint is not supported. + */ +int APerformanceHint_notifyWorkloadIncrease( + APerformanceHintSession* _Nonnull session, + bool cpu, bool gpu, const char* _Nonnull debugName) __INTRODUCED_IN(36); + +/** + * Informs the framework of an upcoming reset in the workload of a graphics pipeline + * bound to this session, or the imminent start of a new workload. The user can specify + * whether the reset is expected to affect the CPU, GPU, or both. + * + * Sending hints for both CPU and GPU counts as two separate hints for the purposes of the + * this load tracking. + * + * @param cpu Indicates if the workload reset is expected to affect the CPU. + * @param gpu Indicates if the workload reset is expected to affect the GPU. + * @param debugName A required string used to identify this specific hint during + * tracing. This debug string will only be held for the duration of the + * method, and can be safely discarded after. + * + * @return 0 on success. + * EINVAL if no hints were requested. + * EBUSY if the hint was rate limited. + * EPIPE if communication with the system service has failed. + * ENOTSUP if the hint is not supported. + */ +int APerformanceHint_notifyWorkloadReset( + APerformanceHintSession* _Nonnull session, + bool cpu, bool gpu, const char* _Nonnull debugName) __INTRODUCED_IN(36); + +/** + * Informs the framework of an upcoming one-off expensive frame for a graphics pipeline + * bound to this session. This frame will be treated as not representative of the workload as a + * whole, and it will be discarded the purposes of load tracking. The user can specify + * whether the workload spike is expected to be on the CPU, GPU, or both. + * + * Sending hints for both CPU and GPU counts as two separate hints for the purposes of the + * rate limiter. + * + * @param cpu Indicates if the workload spike is expected to affect the CPU. + * @param gpu Indicates if the workload spike is expected to affect the GPU. + * @param debugName A required string used to identify this specific hint during + * tracing. This debug string will only be held for the duration of the + * method, and can be safely discarded after. + * + * @return 0 on success. + * EINVAL if no hints were requested. + * EBUSY if the hint was rate limited. + * EPIPE if communication with the system service has failed. + * ENOTSUP if the hint is not supported. + */ +int APerformanceHint_notifyWorkloadSpike( + APerformanceHintSession* _Nonnull session, + bool cpu, bool gpu, const char* _Nonnull debugName) __INTRODUCED_IN(36); + +/** + * Associates a session with any {@link ASurfaceControl} or {@link ANativeWindow} + * instances managed by this session. + * + * This method is primarily intended for sessions that manage the timing of an entire + * graphics pipeline end-to-end, such as those using the + * {@link ASessionCreationConfig_setGraphicsPipeline} API. However, any session directly + * or indirectly managing a graphics pipeline should still associate themselves with + * directly relevant ASurfaceControl or ANativeWindow instances for better optimization. + * + * To see any benefit from this method, the client must make sure they are updating the framerate + * of attached surfaces using methods such as {@link ANativeWindow_setFrameRate}, or by updating + * any associated ASurfaceControls with transactions that have {ASurfaceTransaction_setFrameRate}. + * + * @param session The {@link APerformanceHintSession} instance to update. + * @param nativeWindows A pointer to a list of ANativeWindows associated with this session. + * nullptr can be passed to indicate there are no associated ANativeWindows. + * @param nativeWindowsSize The number of ANativeWindows in the list. + * @param surfaceControls A pointer to a list of ASurfaceControls associated with this session. + * nullptr can be passed to indicate there are no associated ASurfaceControls. + * @param surfaceControlsSize The number of ASurfaceControls in the list. + * + * @return 0 on success. + * EPIPE if communication has failed. + * ENOTSUP if unsupported. + * EINVAL if invalid or empty arguments passed. + */ + +int APerformanceHint_setNativeSurfaces(APerformanceHintSession* _Nonnull session, + ANativeWindow* _Nonnull* _Nullable nativeWindows, int nativeWindowsSize, + ASurfaceControl* _Nonnull* _Nullable surfaceControls, int surfaceControlsSize) + __INTRODUCED_IN(36); + +/** * Creates a new AWorkDuration. When the client finishes using {@link AWorkDuration}, it should * call {@link AWorkDuration_release()} to destroy {@link AWorkDuration} and release all resources * associated with it. * - * @return AWorkDuration on success and nullptr otherwise. + * @return AWorkDuration pointer. */ AWorkDuration* _Nonnull AWorkDuration_create() __INTRODUCED_IN(__ANDROID_API_V__); /** - * Destroys {@link AWorkDuration} and free all resources associated to it. + * Destroys a {@link AWorkDuration} and frees all resources associated with it. * * @param aWorkDuration The {@link AWorkDuration} created by calling {@link AWorkDuration_create()} */ @@ -308,6 +475,171 @@ void AWorkDuration_setActualCpuDurationNanos(AWorkDuration* _Nonnull aWorkDurati void AWorkDuration_setActualGpuDurationNanos(AWorkDuration* _Nonnull aWorkDuration, int64_t actualGpuDurationNanos) __INTRODUCED_IN(__ANDROID_API_V__); +/** + * Return the APerformanceHintSession wrapped by a Java PerformanceHintManager.Session object. + * + * The Java session maintains ownership over the wrapped native session, so it cannot be + * closed using {@link APerformanceHint_closeSession}. + * + * @param env The Java environment where the PerformanceHintManager.Session lives. + * @param sessionObj The Java Session to unwrap. + * + * @return A pointer to the APerformanceHintManager that backs the Java Session. + */ +APerformanceHintSession* _Nonnull APerformanceHint_borrowSessionFromJava( + JNIEnv* _Nonnull env, jobject _Nonnull sessionObj) __INTRODUCED_IN(36); + +/* + * Creates a new ASessionCreationConfig. + * + * When the client finishes using {@link ASessionCreationConfig}, it should + * call {@link ASessionCreationConfig_release()} to destroy + * {@link ASessionCreationConfig} and release all resources + * associated with it. + * + * @return ASessionCreationConfig pointer. + */ +ASessionCreationConfig* _Nonnull ASessionCreationConfig_create() + __INTRODUCED_IN(36); + + +/** + * Destroys a {@link ASessionCreationConfig} and frees all + * resources associated with it. + * + * @param config The {@link ASessionCreationConfig} + * created by calling {@link ASessionCreationConfig_create()}. + */ +void ASessionCreationConfig_release( + ASessionCreationConfig* _Nonnull config) __INTRODUCED_IN(36); + +/** + * Sets the tids to be associated with the session to be created. + * + * @param config The {@link ASessionCreationConfig} + * created by calling {@link ASessionCreationConfig_create()} + * @param tids The list of tids to be associated with this session. They must be part of + * this process' thread group. + * @param size The size of the list of tids. + * + * @return 0 on success. + * EINVAL if invalid array pointer or the value of size + */ +int ASessionCreationConfig_setTids( + ASessionCreationConfig* _Nonnull config, + const pid_t* _Nonnull tids, size_t size) __INTRODUCED_IN(36); + +/** + * Sets the initial target work duration in nanoseconds for the session to be created. + * + * @param config The {@link ASessionCreationConfig} + * created by calling {@link ASessionCreationConfig_create()}. + * @param targetWorkDurationNanos The parameter to specify a target duration + * in nanoseconds for the new session; this value must be positive to use + * the work duration API. + * + * @return 0 on success. + * ENOTSUP if unsupported + * EINVAL if invalid value + */ +int ASessionCreationConfig_setTargetWorkDurationNanos( + ASessionCreationConfig* _Nonnull config, + int64_t targetWorkDurationNanos) __INTRODUCED_IN(36); + +/** + * Sets whether power efficiency mode will be enabled for the session. + * This tells the session that these threads can be + * safely scheduled to prefer power efficiency over performance. + * + * @param config The {@link ASessionCreationConfig} + * created by calling {@link ASessionCreationConfig_create()}. + * @param enabled Whether power efficiency mode will be enabled. + * + * @return 0 on success. + * ENOTSUP if unsupported + * EINVAL if invalid pointer to creation config + */ +int ASessionCreationConfig_setPreferPowerEfficiency( + ASessionCreationConfig* _Nonnull config, bool enabled) __INTRODUCED_IN(36); + +/** + * Sessions setting this hint are expected to time the critical path of + * graphics pipeline from end to end, with the total work duration + * representing the time from the start of frame production until the + * buffer is fully finished drawing. + * + * It should include any threads on the critical path of that pipeline, + * up to a limit accessible from {@link getMaxGraphicsPipelineThreadsCount()}. + * + * @param config The {@link ASessionCreationConfig} + * created by calling {@link ASessionCreationConfig_create()}. + * @param enabled Whether this session manages a graphics pipeline's critical path. + * + * @return 0 on success. + * ENOTSUP if unsupported + * EINVAL if invalid pointer to creation config or maximum threads for graphics + pipeline is reached. + */ +int ASessionCreationConfig_setGraphicsPipeline( + ASessionCreationConfig* _Nonnull config, bool enabled) __INTRODUCED_IN(36); + +/** + * Associates a session with any {@link ASurfaceControl} or {@link ANativeWindow} + * instances managed by this session. See {@link APerformanceHint_setNativeSurfaces} + * for more details. + * + * @param config The {@link ASessionCreationConfig} + * created by calling {@link ASessionCreationConfig_create()}. + * @param nativeWindows A pointer to a list of ANativeWindows associated with this session. + * nullptr can be passed to indicate there are no associated ANativeWindows. + * @param nativeWindowsSize The number of ANativeWindows in the list. + * @param surfaceControls A pointer to a list of ASurfaceControls associated with this session. + * nullptr can be passed to indicate there are no associated ASurfaceControls. + * @param surfaceControlsSize The number of ASurfaceControls in the list. + * + * @return 0 on success. + * ENOTSUP if unsupported. + * EINVAL if invalid or empty arguments passed. + */ +int ASessionCreationConfig_setNativeSurfaces( + ASessionCreationConfig* _Nonnull config, + ANativeWindow* _Nonnull* _Nullable nativeWindows, int nativeWindowsSize, + ASurfaceControl* _Nonnull* _Nullable surfaceControls, int surfaceControlsSize) + __INTRODUCED_IN(36); + +/** + * Enable automatic timing mode for sessions using the GRAPHICS_PIPELINE API with an attached + * surface. In this mode, sessions do not need to report actual durations and only need + * to keep their thread list up-to-date, set a native surface, call + * {@link ASessionCreationConfig_setGraphicsPipeline()} to signal that the session is in + * "graphics pipeline" mode, and then set whether automatic timing is desired for the + * CPU, GPU, or both, using this method. + * + * It is still be beneficial to set an accurate target time, as this may help determine + * timing information for some workloads where there is less information available from + * the framework, such as games. Additionally, reported CPU durations will be ignored + * while automatic CPU timing is enabled, and similarly GPU durations will be ignored + * when automatic GPU timing is enabled. When both are enabled, the entire + * reportActualWorkDuration call will be ignored, and the session will be managed + * completely automatically. + * + * This mode will not work unless the client makes sure they are updating the framerate + * of attached surfaces with methods such as {@link ANativeWindow_setFrameRate}, or updating + * any associated ASurfaceControls with transactions that have {ASurfaceTransaction_setFrameRate}. + * + * @param config The {@link ASessionCreationConfig} + * created by calling {@link ASessionCreationConfig_create()}. + * @param cpu Whether to enable automatic timing for the CPU for this session. + * @param gpu Whether to enable automatic timing for the GPU for this session. + * + * @return 0 on success. + * ENOTSUP if unsupported. + */ +int ASessionCreationConfig_setUseAutoTiming( + ASessionCreationConfig* _Nonnull config, + bool cpu, bool gpu) + __INTRODUCED_IN(36); + __END_DECLS #endif // ANDROID_NATIVE_PERFORMANCE_HINT_H diff --git a/include/android/surface_control.h b/include/android/surface_control.h index bf9acb37da..6323333429 100644 --- a/include/android/surface_control.h +++ b/include/android/surface_control.h @@ -28,6 +28,7 @@ #include <sys/cdefs.h> +#include <android/display_luts.h> #include <android/choreographer.h> #include <android/data_space.h> #include <android/hardware_buffer.h> @@ -156,8 +157,6 @@ typedef struct ASurfaceTransactionStats ASurfaceTransactionStats; * * THREADING * The transaction completed callback can be invoked on any thread. - * - * Available since API level 29. */ typedef void (*ASurfaceTransaction_OnComplete)(void* _Null_unspecified context, ASurfaceTransactionStats* _Nonnull stats); @@ -184,8 +183,6 @@ typedef void (*ASurfaceTransaction_OnComplete)(void* _Null_unspecified context, * * THREADING * The transaction committed callback can be invoked on any thread. - * - * Available since API level 31. */ typedef void (*ASurfaceTransaction_OnCommit)(void* _Null_unspecified context, ASurfaceTransactionStats* _Nonnull stats); @@ -213,8 +210,6 @@ typedef void (*ASurfaceTransaction_OnCommit)(void* _Null_unspecified context, * * THREADING * The callback can be invoked on any thread. - * - * Available since API level 36. */ typedef void (*ASurfaceTransaction_OnBufferRelease)(void* _Null_unspecified context, int release_fence_fd); @@ -719,6 +714,23 @@ void ASurfaceTransaction_setDesiredHdrHeadroom(ASurfaceTransaction* _Nonnull tra __INTRODUCED_IN(__ANDROID_API_V__); /** + * Sets the Lut(s) to be applied for the layer. + * + * The function makes a deep copy of the provided `luts`. + * Any modifications made to the `luts` object after calling this function + * will not affect the Lut(s) applied to the layer. + * + * @param surface_control The layer where Lut(s) is being applied + * @param luts The Lut(s) to be applied + * + * Available since API level 36. + */ +void ASurfaceTransaction_setLuts(ASurfaceTransaction* _Nonnull transaction, + ASurfaceControl* _Nonnull surface_control, + const struct ADisplayLuts* _Nullable luts) + __INTRODUCED_IN(36); + +/** * Same as ASurfaceTransaction_setFrameRateWithChangeStrategy(transaction, surface_control, * frameRate, compatibility, ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS). * diff --git a/include/android/system_health.h b/include/android/system_health.h new file mode 100644 index 0000000000..69620df16e --- /dev/null +++ b/include/android/system_health.h @@ -0,0 +1,351 @@ +/* + * 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 +* @{ +*/ + +/** + * @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; + +/** + * Creates a new instance of 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 ACpuHeadroomParams. + */ +ACpuHeadroomParams *_Nonnull ACpuHeadroomParams_create() +__INTRODUCED_IN(36); + +enum ACpuHeadroomCalculationType { + /** + * Use the minimum headroom value within the calculation window. + * Introduced in API level 36. + */ + ACPU_HEADROOM_CALCULATION_TYPE_MIN = 0, + /** + * Use the average headroom value within the calculation window. + * Introduced in API level 36. + */ + ACPU_HEADROOM_CALCULATION_TYPE_AVERAGE = 1, +}; +typedef enum ACpuHeadroomCalculationType ACpuHeadroomCalculationType; + +enum AGpuHeadroomCalculationType { + /** + * Use the minimum headroom value within the calculation window. + * Introduced in API level 36. + */ + AGPU_HEADROOM_CALCULATION_TYPE_MIN = 0, + /** + * Use the average headroom value within the calculation window. + * Introduced in API level 36. + */ + AGPU_HEADROOM_CALCULATION_TYPE_AVERAGE = 1, +}; +typedef enum AGpuHeadroomCalculationType AGpuHeadroomCalculationType; + +/** + * Sets the headroom calculation window size in ACpuHeadroomParams. + * + * Available since API level 36. + * + * @param params The params to be set. + * @param windowMillis The window size in milliseconds ranged from [50, 10000]. 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 headroom calculation window size in ACpuHeadroomParams. + * + * Available since API level 36. + * + * @param params The params to be set. + * @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 headroom calculation window size in AGpuHeadroomParams. + * + * Available since API level 36. + * + * @param params The params to be set. + * @param windowMillis The window size in milliseconds ranged from [50, 10000]. 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 headroom calculation window size in AGpuHeadroomParams. + * + * Available since API level 36. + * + * @param params The params to be set. + * @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 headroom calculation type in 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 headroom calculation type in ACpuHeadroomParams. + * + * Available since API level 36. + * + * @param params The params to be set. + * @return The headroom calculation type. + */ +ACpuHeadroomCalculationType +ACpuHeadroomParams_getCalculationType(ACpuHeadroomParams *_Nonnull params) +__INTRODUCED_IN(36); + +/** + * Sets the headroom calculation type in 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 headroom calculation type in AGpuHeadroomParams. + * + * Available since API level 36. + * + * @param params The params to be set. + * @return The headroom calculation type. + */ +AGpuHeadroomCalculationType +AGpuHeadroomParams_getCalculationType(AGpuHeadroomParams *_Nonnull params) +__INTRODUCED_IN(36); + +/** + * Sets the thread TIDs to track in ACpuHeadroomParams. + * + * Available since API level 36. + * + * @param params The params to be set. + * @param tids Non-null array of TIDs, maximum 5. + * @param tidsSize The size of the tids array. + */ +void ACpuHeadroomParams_setTids(ACpuHeadroomParams *_Nonnull params, const int *_Nonnull tids, + int tidsSize) +__INTRODUCED_IN(36); + +/** + * Creates a new instance of 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 AGpuHeadroomParams. + */ +AGpuHeadroomParams *_Nonnull AGpuHeadroomParams_create() +__INTRODUCED_IN(36); + +/** + * Deletes the ACpuHeadroomParams instance. + * + * Available since API level 36. + * + * @param params The params to be deleted. + */ +void ACpuHeadroomParams_destroy(ACpuHeadroomParams *_Nonnull params) +__INTRODUCED_IN(36); + +/** + * Deletes the AGpuHeadroomParams instance. + * + * Available since API level 36. + * + * @param params The params to be deleted. + */ +void AGpuHeadroomParams_destroy(AGpuHeadroomParams *_Nonnull params) +__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. + * + * Available since API level 36. + * + * @param params The params to customize the CPU headroom calculation, or nullptr to use the 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. + * 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. + * + * Available since API level 36 + * + * @param params The params to customize the GPU headroom calculation, or nullptr to use the 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 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 + * EPIPE if failed to get the minimum polling interval. + * 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 getGpuHeadroom API may return cached result if called more frequent 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 + * EPIPE if failed to get the minimum polling interval. + * ENOTSUP if API is unsupported. + */ +int ASystemHealth_getGpuHeadroomMinIntervalMillis(int64_t *_Nonnull outMinIntervalMillis) +__INTRODUCED_IN(36); + +#ifdef __cplusplus +} +#endif + +#endif // _ANDROID_SYSTEM_HEALTH_H + +/** @} */ diff --git a/include/android/thermal.h b/include/android/thermal.h index 1d7ad12294..e5d46b5b8a 100644 --- a/include/android/thermal.h +++ b/include/android/thermal.h @@ -140,45 +140,47 @@ void AThermal_releaseManager(AThermalManager* _Nonnull manager) __INTRODUCED_IN( * Available since API level 30. * * @param manager The manager instance to use to query the thermal status. - * Acquired via {@link AThermal_acquireManager}. + * Acquired via {@link AThermal_acquireManager}. * * @return current thermal status, ATHERMAL_STATUS_ERROR on failure. */ AThermalStatus -AThermal_getCurrentThermalStatus(AThermalManager* _Nonnull manager) __INTRODUCED_IN(30); +AThermal_getCurrentThermalStatus(AThermalManager *_Nonnull manager) __INTRODUCED_IN(30); /** - * Register the thermal status listener for thermal status change. + * Register a thermal status listener for thermal status change. * * Available since API level 30. * * @param manager The manager instance to use to register. - * Acquired via {@link AThermal_acquireManager}. - * @param callback The callback function to be called when thermal status updated. + * Acquired via {@link AThermal_acquireManager}. + * @param callback The callback function to be called on system binder thread pool when thermal + * status updated. * @param data The data pointer to be passed when callback is called. * * @return 0 on success * EINVAL if the listener and data pointer were previously added and not removed. - * EPERM if the required permission is not held. - * EPIPE if communication with the system service has failed. + * EPIPE if communication with the system service has failed, the listener will not get + * removed and this call should be retried */ -int AThermal_registerThermalStatusListener(AThermalManager* _Nonnull manager, +int AThermal_registerThermalStatusListener(AThermalManager *_Nonnull manager, AThermal_StatusCallback _Nullable callback, void* _Nullable data) __INTRODUCED_IN(30); /** - * Unregister the thermal status listener previously resgistered. + * Unregister a thermal status listener previously registered. + * + * No subsequent invocations of the callback will occur after this function returns successfully. * * Available since API level 30. * * @param manager The manager instance to use to unregister. - * Acquired via {@link AThermal_acquireManager}. - * @param callback The callback function to be called when thermal status updated. + * Acquired via {@link AThermal_acquireManager}. + * @param callback The callback function that was previously registered. * @param data The data pointer to be passed when callback is called. * * @return 0 on success * EINVAL if the listener and data pointer were not previously added. - * EPERM if the required permission is not held. * EPIPE if communication with the system service has failed. */ int AThermal_unregisterThermalStatusListener(AThermalManager* _Nonnull manager, @@ -254,7 +256,7 @@ typedef struct AThermalHeadroomThreshold AThermalHeadroomThreshold; * The headroom threshold is used to interpret the possible thermal throttling status based on * the headroom prediction. For example, if the headroom threshold for * {@link ATHERMAL_STATUS_LIGHT} is 0.7, and a headroom prediction in 10s returns 0.75 - * (or `AThermal_getThermalHeadroom(10)=0.75`), one can expect that in 10 seconds the system + * (or `AThermal_getThermalHeadroom(10)=0.75}`, one can expect that in 10 seconds the system * could be in lightly throttled state if the workload remains the same. The app can consider * taking actions according to the nearest throttling status the difference between the headroom and * the threshold. @@ -262,7 +264,7 @@ typedef struct AThermalHeadroomThreshold AThermalHeadroomThreshold; * For new devices it's guaranteed to have a single sensor, but for older devices with multiple * sensors reporting different threshold values, the minimum threshold is taken to be conservative * on predictions. Thus, when reading real-time headroom, it's not guaranteed that a real-time value - * of 0.75 (or `AThermal_getThermalHeadroom(0)`=0.75) exceeding the threshold of 0.7 above + * of 0.75 (or `AThermal_getThermalHeadroom(0)=0.75`) exceeding the threshold of 0.7 above * will always come with lightly throttled state * (or `AThermal_getCurrentThermalStatus()=ATHERMAL_STATUS_LIGHT`) but it can be lower * (or `AThermal_getCurrentThermalStatus()=ATHERMAL_STATUS_NONE`). @@ -271,15 +273,21 @@ typedef struct AThermalHeadroomThreshold AThermalHeadroomThreshold; * {@link #ATHERMAL_STATUS_MODERATE} but always lower, and 0.65 will never come with * {@link ATHERMAL_STATUS_LIGHT} but {@link #ATHERMAL_STATUS_NONE}. * <p> - * The returned list of thresholds is cached on first successful query and owned by the thermal - * manager, which will not change between calls to this function. The caller should only need to - * free the manager with {@link AThermal_releaseManager}. + * Starting in Android 16, this polling API may return different results when called depending on + * the device. The new headroom listener API {@link #AThermal_HeadroomCallback} can be used to + * detect headroom thresholds changes. + * <p> + * Before API level 36 the returned list of thresholds is cached on first successful query and owned + * by the thermal manager, which will not change between calls to this function. The caller should + * only need to free the manager with {@link AThermal_releaseManager}. + * <p> * * @param manager The manager instance to use. * Acquired via {@link AThermal_acquireManager}. * @param outThresholds non-null output pointer to null AThermalHeadroomThreshold pointer, which - * will be set to the cached array of thresholds if thermal thresholds are supported - * by the system or device, otherwise nullptr or unmodified. + * will be set to a new array of thresholds if thermal thresholds are supported + * by the system or device, otherwise nullptr or unmodified. The client should + * clean up the thresholds by array-deleting the threshold pointer. * @param size non-null output pointer whose value will be set to the size of the threshold array * or 0 if it's not supported. * @return 0 on success @@ -292,6 +300,71 @@ int AThermal_getThermalHeadroomThresholds(AThermalManager* _Nonnull manager, * _Nullable outThresholds, size_t* _Nonnull size) __INTRODUCED_IN(35); +/** + * Prototype of the function that is called when thermal headroom or thresholds changes. + * It's passed the updated thermal headroom and thresholds as parameters, as well as the + * pointer provided by the client that registered a callback. + * + * @param data The data pointer to be passed when callback is called. + * @param headroom The current non-negative normalized headroom value, also see + * {@link AThermal_getThermalHeadroom}. + * @param forecastHeadroom The forecasted non-negative normalized headroom value, also see + * {@link AThermal_getThermalHeadroom}. + * @param forecastSeconds The seconds used for the forecast by the system. + * @param thresholds The current headroom thresholds. The thresholds pointer will be a constant + * shared across all callbacks registered from the same process, and it will be + * destroyed after all the callbacks are finished. If the client intents to + * persist the values, it should make a copy of it during the callback. + * @param thresholdsCount The count of thresholds. + */ +typedef void (*AThermal_HeadroomCallback)(void *_Nullable data, + float headroom, + float forecastHeadroom, + int forecastSeconds, + const AThermalHeadroomThreshold* _Nullable thresholds, + size_t thresholdsCount); + +/** + * Register a thermal headroom listener for thermal headroom or thresholds change. + * + * Available since API level 36. + * + * @param manager The manager instance to use to register. + * Acquired via {@link AThermal_acquireManager}. + * @param callback The callback function to be called on system binder thread pool when thermal + * headroom or thresholds update. + * @param data The data pointer to be passed when callback is called. + * + * @return 0 on success + * EINVAL if the listener and data pointer were previously added and not removed. + * EPIPE if communication with the system service has failed. + */ +int AThermal_registerThermalHeadroomListener(AThermalManager* _Nonnull manager, + AThermal_HeadroomCallback _Nullable callback, + void* _Nullable data) __INTRODUCED_IN(36); + +/** + * Unregister a thermal headroom listener previously registered. + * + * No subsequent invocations of the callback will occur after this function returns successfully. + * + * Available since API level 36. + * + * @param manager The manager instance to use to unregister. + * Acquired via {@link AThermal_acquireManager}. + * @param callback The callback function that was previously registered. + * @param data The data pointer that was previously registered. + * + * @return 0 on success + * EINVAL if the listener and data pointer were not previously added. + * EPIPE if communication with the system service has failed, the listener will not get + * removed and this call should be retried + */ + +int AThermal_unregisterThermalHeadroomListener(AThermalManager* _Nonnull manager, + AThermal_HeadroomCallback _Nullable callback, + void* _Nullable data) __INTRODUCED_IN(36); + #ifdef __cplusplus } #endif diff --git a/include/audiomanager/AudioManager.h b/include/audiomanager/AudioManager.h index 43048dbff0..203623dea7 100644 --- a/include/audiomanager/AudioManager.h +++ b/include/audiomanager/AudioManager.h @@ -22,6 +22,7 @@ namespace android { // must be kept in sync with definitions in AudioPlaybackConfiguration.java #define PLAYER_PIID_INVALID -1 +// TODO (b/309532236) remove manual IAudioManager impl in favor of AIDL. typedef enum { PLAYER_TYPE_SLES_AUDIOPLAYER_BUFFERQUEUE = 11, PLAYER_TYPE_SLES_AUDIOPLAYER_URI_FD = 12, @@ -59,6 +60,8 @@ enum { PLAYER_MUTE_PLAYBACK_RESTRICTED = (1 << 3), PLAYER_MUTE_CLIENT_VOLUME = (1 << 4), PLAYER_MUTE_VOLUME_SHAPER = (1 << 5), + PLAYER_MUTE_PORT_VOLUME = (1 << 6), + PLAYER_MUTE_OP_AUDIO_CONTROL = (1 << 7), }; struct mute_state_t { @@ -72,8 +75,12 @@ struct mute_state_t { bool muteFromPlaybackRestricted = false; /** Flag used when audio track was muted by client volume. */ bool muteFromClientVolume = false; - /** Flag used when volume is muted by volume shaper. */ + /** Flag used when volume is muted by volume shaper. */ bool muteFromVolumeShaper = false; + /** Flag used when volume is muted by port volume. */ + bool muteFromPortVolume = false; + /** Flag used when volume is muted by audio control op. */ + bool muteFromOpAudioControl = false; explicit operator int() const { @@ -83,6 +90,8 @@ struct mute_state_t { result |= muteFromPlaybackRestricted * PLAYER_MUTE_PLAYBACK_RESTRICTED; result |= muteFromClientVolume * PLAYER_MUTE_CLIENT_VOLUME; result |= muteFromVolumeShaper * PLAYER_MUTE_VOLUME_SHAPER; + result |= muteFromPortVolume * PLAYER_MUTE_PORT_VOLUME; + result |= muteFromOpAudioControl * PLAYER_MUTE_OP_AUDIO_CONTROL; return result; } diff --git a/include/audiomanager/IAudioManager.h b/include/audiomanager/IAudioManager.h index 0b7e16bc7d..a35a145084 100644 --- a/include/audiomanager/IAudioManager.h +++ b/include/audiomanager/IAudioManager.h @@ -56,7 +56,7 @@ public: /*oneway*/ virtual status_t playerAttributes(audio_unique_id_t piid, audio_usage_t usage, audio_content_type_t content)= 0; /*oneway*/ virtual status_t playerEvent(audio_unique_id_t piid, player_state_t event, - audio_port_handle_t eventId) = 0; + const std::vector<audio_port_handle_t>& eventIds) = 0; /*oneway*/ virtual status_t releasePlayer(audio_unique_id_t piid) = 0; virtual audio_unique_id_t trackRecorder(const sp<IBinder>& recorder) = 0; /*oneway*/ virtual status_t recorderEvent(audio_unique_id_t riid, recorder_state_t event) = 0; diff --git a/include/ftl/flags.h b/include/ftl/flags.h index dbe3148fc5..a2a22ebebe 100644 --- a/include/ftl/flags.h +++ b/include/ftl/flags.h @@ -22,6 +22,7 @@ #include <bitset> #include <cstdint> #include <iterator> +#include <initializer_list> #include <string> #include <type_traits> @@ -40,6 +41,7 @@ class Flags { public: constexpr Flags(F f) : mFlags(static_cast<U>(f)) {} + constexpr Flags(std::initializer_list<F> fs) : mFlags(combine(fs)) {} constexpr Flags() : mFlags(0) {} constexpr Flags(const Flags<F>& f) : mFlags(f.mFlags) {} @@ -197,6 +199,14 @@ public: private: U mFlags; + static constexpr U combine(std::initializer_list<F> fs) { + U result = 0; + for (const F f : fs) { + result |= static_cast<U>(f); + } + return result; + } + static void appendFlag(std::string& str, const std::string_view& flag, bool& first) { if (first) { first = false; diff --git a/include/ftl/non_null.h b/include/ftl/non_null.h index 4a5d8bffd0..e68428810b 100644 --- a/include/ftl/non_null.h +++ b/include/ftl/non_null.h @@ -68,6 +68,15 @@ class NonNull final { constexpr NonNull(const NonNull&) = default; constexpr NonNull& operator=(const NonNull&) = default; + template <typename U, typename = std::enable_if_t<std::is_convertible_v<U, Pointer>>> + constexpr NonNull(const NonNull<U>& other) : pointer_(other.get()) {} + + template <typename U, typename = std::enable_if_t<std::is_convertible_v<U, Pointer>>> + constexpr NonNull& operator=(const NonNull<U>& other) { + pointer_ = other.get(); + return *this; + } + [[nodiscard]] constexpr const Pointer& get() const { return pointer_; } [[nodiscard]] constexpr explicit operator const Pointer&() const { return get(); } diff --git a/include/input/CoordinateFilter.h b/include/input/CoordinateFilter.h new file mode 100644 index 0000000000..8f2e605e85 --- /dev/null +++ b/include/input/CoordinateFilter.h @@ -0,0 +1,54 @@ +/** + * Copyright 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. + */ + +#pragma once + +#include <chrono> + +#include <input/Input.h> +#include <input/OneEuroFilter.h> + +namespace android { + +/** + * Pair of OneEuroFilters that independently filter X and Y coordinates. Both filters share the same + * constructor's parameters. The minimum cutoff frequency is the base cutoff frequency, that is, the + * resulting cutoff frequency in the absence of signal's speed. Likewise, beta is a scaling factor + * of the signal's speed that sets how much the signal's speed contributes to the resulting cutoff + * frequency. The adaptive cutoff frequency criterion is f_c = f_c_min + β|̇x_filtered| + */ +class CoordinateFilter { +public: + explicit CoordinateFilter(float minCutoffFreq, float beta); + + /** + * Filters in place only the AXIS_X and AXIS_Y fields from coords. Each call to filter must + * provide a timestamp strictly greater than the timestamp of the previous call. The first time + * this method is invoked no filtering takes place. Subsequent calls do overwrite `coords` with + * filtered data. + * + * @param timestamp The timestamps at which to filter. It must be greater than the one passed in + * the previous call. + * @param coords Coordinates to be overwritten by the corresponding filtered coordinates. + */ + void filter(std::chrono::nanoseconds timestamp, PointerCoords& coords); + +private: + OneEuroFilter mXFilter; + OneEuroFilter mYFilter; +}; + +} // namespace android
\ No newline at end of file diff --git a/include/input/DisplayTopologyGraph.h b/include/input/DisplayTopologyGraph.h new file mode 100644 index 0000000000..90427bd76d --- /dev/null +++ b/include/input/DisplayTopologyGraph.h @@ -0,0 +1,57 @@ +/* + * Copyright 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. + */ + +#pragma once + +#include <ftl/enum.h> +#include <ui/LogicalDisplayId.h> + +#include <cinttypes> +#include <unordered_map> +#include <vector> + +namespace android { + +/** + * The edge of the current display, where adjacent display is attached to. + */ +enum class DisplayTopologyPosition : int32_t { + LEFT = 0, + TOP = 1, + RIGHT = 2, + BOTTOM = 3, + + ftl_last = BOTTOM +}; + +/** + * Directed edge in the graph of adjacent displays. + */ +struct DisplayTopologyAdjacentDisplay { + ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID; + DisplayTopologyPosition position; + float offsetPx; +}; + +/** + * Directed Graph representation of Display Topology. + */ +struct DisplayTopologyGraph { + ui::LogicalDisplayId primaryDisplayId = ui::LogicalDisplayId::INVALID; + std::unordered_map<ui::LogicalDisplayId, std::vector<DisplayTopologyAdjacentDisplay>> graph; +}; + +} // namespace android diff --git a/include/input/Input.h b/include/input/Input.h index a8684bd19b..2cabd56204 100644 --- a/include/input/Input.h +++ b/include/input/Input.h @@ -294,6 +294,8 @@ enum class KeyboardType { NONE = AINPUT_KEYBOARD_TYPE_NONE, NON_ALPHABETIC = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, ALPHABETIC = AINPUT_KEYBOARD_TYPE_ALPHABETIC, + ftl_first = NONE, + ftl_last = ALPHABETIC, }; bool isStylusToolType(ToolType toolType); @@ -994,6 +996,15 @@ protected: std::vector<PointerProperties> mPointerProperties; std::vector<nsecs_t> mSampleEventTimes; std::vector<PointerCoords> mSamplePointerCoords; + +private: + /** + * Create a human-readable string representation of the event's data for debugging purposes. + * + * Unlike operator<<, this method does not assume that the event data is valid or consistent, or + * call any accessor methods that might themselves call safeDump in the case of invalid data. + */ + std::string safeDump() const; }; std::ostream& operator<<(std::ostream& out, const MotionEvent& event); diff --git a/include/input/InputConsumerNoResampling.h b/include/input/InputConsumerNoResampling.h index c98b9cf8c1..70d00d16f4 100644 --- a/include/input/InputConsumerNoResampling.h +++ b/include/input/InputConsumerNoResampling.h @@ -16,6 +16,7 @@ #pragma once +#include <functional> #include <map> #include <memory> #include <optional> @@ -75,12 +76,13 @@ public: * the event is ready to consume. * @param looper needs to be sp and not shared_ptr because it inherits from * RefBase - * @param resampler the resampling strategy to use. If null, no resampling will be - * performed. + * @param resamplerCreator callable that returns the resampling strategy to be used. If null, no + * resampling will be performed. resamplerCreator must never return nullptr. */ - explicit InputConsumerNoResampling(const std::shared_ptr<InputChannel>& channel, - sp<Looper> looper, InputConsumerCallbacks& callbacks, - std::unique_ptr<Resampler> resampler); + explicit InputConsumerNoResampling( + const std::shared_ptr<InputChannel>& channel, sp<Looper> looper, + InputConsumerCallbacks& callbacks, + std::function<std::unique_ptr<Resampler>()> resamplerCreator); ~InputConsumerNoResampling(); @@ -117,7 +119,13 @@ private: std::shared_ptr<InputChannel> mChannel; sp<Looper> mLooper; InputConsumerCallbacks& mCallbacks; - std::unique_ptr<Resampler> mResampler; + const std::function<std::unique_ptr<Resampler>()> mResamplerCreator; + + /** + * A map to manage multidevice resampling. Each contained resampler is never null. This map is + * only modified by handleMessages. + */ + std::map<DeviceId, std::unique_ptr<Resampler>> mResamplers; // Looper-related infrastructure /** @@ -133,7 +141,7 @@ private: } private: - std::function<int(int events)> mCallback; + const std::function<int(int events)> mCallback; }; sp<LooperEventCallback> mCallback; /** @@ -190,7 +198,10 @@ private: /** * Batch messages that can be batched. When an unbatchable message is encountered, send it * to the InputConsumerCallbacks immediately. If there are batches remaining, - * notify InputConsumerCallbacks. + * notify InputConsumerCallbacks. If a resampleable ACTION_DOWN message is received, then a + * resampler is inserted for that deviceId in mResamplers. If a resampleable ACTION_UP or + * ACTION_CANCEL message is received then the resampler associated to that deviceId is erased + * from mResamplers. */ void handleMessages(std::vector<InputMessage>&& messages); /** @@ -200,16 +211,17 @@ private: * `consumeBatchedInputEvents`. */ std::map<DeviceId, std::queue<InputMessage>> mBatches; + /** - * Creates a MotionEvent by consuming samples from the provided queue. If one message has - * eventTime > adjustedFrameTime, all subsequent messages in the queue will be skipped. It is - * assumed that messages are queued in chronological order. In other words, only events that - * occurred prior to the adjustedFrameTime will be consumed. - * @param requestedFrameTime the time up to which to consume events. - * @param messages the queue of messages to consume from + * Creates a MotionEvent by consuming samples from the provided queue. Consumes all messages + * with eventTime <= requestedFrameTime - resampleLatency, where `resampleLatency` is latency + * introduced by the resampler. Assumes that messages are queued in chronological order. + * @param requestedFrameTime The time up to which consume messages, as given by the inequality + * above. If std::nullopt, everything in messages will be consumed. + * @param messages the queue of messages to consume from. */ std::pair<std::unique_ptr<MotionEvent>, std::optional<uint32_t>> createBatchedMotionEvent( - const nsecs_t requestedFrameTime, std::queue<InputMessage>& messages); + const std::optional<nsecs_t> requestedFrameTime, std::queue<InputMessage>& messages); /** * Consumes the batched input events, optionally allowing the caller to specify a device id diff --git a/include/input/InputDevice.h b/include/input/InputDevice.h index 1a482396ee..ea1e4aee01 100644 --- a/include/input/InputDevice.h +++ b/include/input/InputDevice.h @@ -111,12 +111,12 @@ enum class InputDeviceSensorType : int32_t { }; enum class InputDeviceSensorAccuracy : int32_t { - ACCURACY_NONE = 0, - ACCURACY_LOW = 1, - ACCURACY_MEDIUM = 2, - ACCURACY_HIGH = 3, + NONE = 0, + LOW = 1, + MEDIUM = 2, + HIGH = 3, - ftl_last = ACCURACY_HIGH, + ftl_last = HIGH, }; enum class InputDeviceSensorReportingMode : int32_t { @@ -131,8 +131,9 @@ enum class InputDeviceLightType : int32_t { PLAYER_ID = 1, KEYBOARD_BACKLIGHT = 2, KEYBOARD_MIC_MUTE = 3, + KEYBOARD_VOLUME_MUTE = 4, - ftl_last = KEYBOARD_MIC_MUTE + ftl_last = KEYBOARD_VOLUME_MUTE }; enum class InputDeviceLightCapability : uint32_t { @@ -266,6 +267,7 @@ class InputDeviceInfo { public: InputDeviceInfo(); InputDeviceInfo(const InputDeviceInfo& other); + InputDeviceInfo& operator=(const InputDeviceInfo& other); ~InputDeviceInfo(); struct MotionRange { @@ -315,13 +317,11 @@ public: inline const InputDeviceViewBehavior& getViewBehavior() const { return mViewBehavior; } - inline void setKeyCharacterMap(const std::shared_ptr<KeyCharacterMap> value) { - mKeyCharacterMap = value; + inline void setKeyCharacterMap(std::unique_ptr<KeyCharacterMap> value) { + mKeyCharacterMap = std::move(value); } - inline const std::shared_ptr<KeyCharacterMap> getKeyCharacterMap() const { - return mKeyCharacterMap; - } + inline const KeyCharacterMap* getKeyCharacterMap() const { return mKeyCharacterMap.get(); } inline void setVibrator(bool hasVibrator) { mHasVibrator = hasVibrator; } inline bool hasVibrator() const { return mHasVibrator; } @@ -364,7 +364,7 @@ private: std::optional<KeyboardLayoutInfo> mKeyboardLayoutInfo; uint32_t mSources; int32_t mKeyboardType; - std::shared_ptr<KeyCharacterMap> mKeyCharacterMap; + std::unique_ptr<KeyCharacterMap> mKeyCharacterMap; std::optional<InputDeviceUsiVersion> mUsiVersion; ui::LogicalDisplayId mAssociatedDisplayId{ui::LogicalDisplayId::INVALID}; bool mEnabled; diff --git a/include/input/InputEventBuilders.h b/include/input/InputEventBuilders.h index 5bd5070488..1696a62693 100644 --- a/include/input/InputEventBuilders.h +++ b/include/input/InputEventBuilders.h @@ -21,6 +21,7 @@ #include <input/Input.h> #include <input/InputTransport.h> #include <ui/LogicalDisplayId.h> +#include <ui/Transform.h> #include <utils/Timers.h> // for nsecs_t, systemTime #include <vector> @@ -94,16 +95,81 @@ public: return *this; } + InputMessageBuilder& hmac(const std::array<uint8_t, 32>& hmac) { + mHmac = hmac; + return *this; + } + InputMessageBuilder& action(int32_t action) { mAction = action; return *this; } + InputMessageBuilder& actionButton(int32_t actionButton) { + mActionButton = actionButton; + return *this; + } + + InputMessageBuilder& flags(int32_t flags) { + mFlags = flags; + return *this; + } + + InputMessageBuilder& metaState(int32_t metaState) { + mMetaState = metaState; + return *this; + } + + InputMessageBuilder& buttonState(int32_t buttonState) { + mButtonState = buttonState; + return *this; + } + + InputMessageBuilder& classification(MotionClassification classification) { + mClassification = classification; + return *this; + } + + InputMessageBuilder& edgeFlags(int32_t edgeFlags) { + mEdgeFlags = edgeFlags; + return *this; + } + InputMessageBuilder& downTime(nsecs_t downTime) { mDownTime = downTime; return *this; } + InputMessageBuilder& transform(const ui::Transform& transform) { + mTransform = transform; + return *this; + } + + InputMessageBuilder& xPrecision(float xPrecision) { + mXPrecision = xPrecision; + return *this; + } + + InputMessageBuilder& yPrecision(float yPrecision) { + mYPrecision = yPrecision; + return *this; + } + + InputMessageBuilder& xCursorPosition(float xCursorPosition) { + mXCursorPosition = xCursorPosition; + return *this; + } + + InputMessageBuilder& yCursorPosition(float yCursorPosition) { + mYCursorPosition = yCursorPosition; + return *this; + } + + InputMessageBuilder& rawTransform(const ui::Transform& rawTransform) { + mRawTransform = rawTransform; + return *this; + } + InputMessageBuilder& pointer(PointerBuilder pointerBuilder) { mPointers.push_back(pointerBuilder); return *this; @@ -121,8 +187,30 @@ public: message.body.motion.deviceId = mDeviceId; message.body.motion.source = mSource; message.body.motion.displayId = mDisplayId.val(); + message.body.motion.hmac = std::move(mHmac); message.body.motion.action = mAction; + message.body.motion.actionButton = mActionButton; + message.body.motion.flags = mFlags; + message.body.motion.metaState = mMetaState; + message.body.motion.buttonState = mButtonState; + message.body.motion.edgeFlags = mEdgeFlags; message.body.motion.downTime = mDownTime; + message.body.motion.dsdx = mTransform.dsdx(); + message.body.motion.dtdx = mTransform.dtdx(); + message.body.motion.dtdy = mTransform.dtdy(); + message.body.motion.dsdy = mTransform.dsdy(); + message.body.motion.tx = mTransform.ty(); + message.body.motion.ty = mTransform.tx(); + message.body.motion.xPrecision = mXPrecision; + message.body.motion.yPrecision = mYPrecision; + message.body.motion.xCursorPosition = mXCursorPosition; + message.body.motion.yCursorPosition = mYCursorPosition; + message.body.motion.dsdxRaw = mRawTransform.dsdx(); + message.body.motion.dtdxRaw = mRawTransform.dtdx(); + message.body.motion.dtdyRaw = mRawTransform.dtdy(); + message.body.motion.dsdyRaw = mRawTransform.dsdy(); + message.body.motion.txRaw = mRawTransform.ty(); + message.body.motion.tyRaw = mRawTransform.tx(); for (size_t i = 0; i < mPointers.size(); ++i) { message.body.motion.pointers[i].properties = mPointers[i].buildProperties(); @@ -140,9 +228,21 @@ private: DeviceId mDeviceId{DEFAULT_DEVICE_ID}; int32_t mSource{AINPUT_SOURCE_TOUCHSCREEN}; ui::LogicalDisplayId mDisplayId{ui::LogicalDisplayId::DEFAULT}; + std::array<uint8_t, 32> mHmac{INVALID_HMAC}; int32_t mAction{AMOTION_EVENT_ACTION_MOVE}; + int32_t mActionButton{0}; + int32_t mFlags{0}; + int32_t mMetaState{AMETA_NONE}; + int32_t mButtonState{0}; + MotionClassification mClassification{MotionClassification::NONE}; + int32_t mEdgeFlags{0}; nsecs_t mDownTime{mEventTime}; - + ui::Transform mTransform{}; + float mXPrecision{1.0f}; + float mYPrecision{1.0f}; + float mXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION}; + float mYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION}; + ui::Transform mRawTransform{}; std::vector<PointerBuilder> mPointers; }; @@ -150,6 +250,9 @@ class MotionEventBuilder { public: MotionEventBuilder(int32_t action, int32_t source) { mAction = action; + if (mAction == AMOTION_EVENT_ACTION_CANCEL) { + mFlags |= AMOTION_EVENT_FLAG_CANCELED; + } mSource = source; mEventTime = systemTime(SYSTEM_TIME_MONOTONIC); mDownTime = mEventTime; diff --git a/include/input/KeyCharacterMap.h b/include/input/KeyCharacterMap.h index 67b37b1213..0a9e74f73b 100644 --- a/include/input/KeyCharacterMap.h +++ b/include/input/KeyCharacterMap.h @@ -72,7 +72,7 @@ public: }; /* Loads a key character map from a file. */ - static base::Result<std::shared_ptr<KeyCharacterMap>> load(const std::string& filename, + static base::Result<std::unique_ptr<KeyCharacterMap>> load(const std::string& filename, Format format); /* Loads a key character map from its string contents. */ @@ -137,6 +137,9 @@ public: /* Returns keycode after applying Android key code remapping defined in mKeyRemapping */ int32_t applyKeyRemapping(int32_t fromKeyCode) const; + /** Returns list of keycodes that remap to provided keycode (@see setKeyRemapping()) */ + std::vector<int32_t> findKeyCodesMappedToKeyCode(int32_t toKeyCode) const; + /* Returns the <keyCode, metaState> pair after applying key behavior defined in the kcm file, * that tries to find a replacement key code based on current meta state */ std::pair<int32_t /*keyCode*/, int32_t /*metaState*/> applyKeyBehavior(int32_t keyCode, diff --git a/include/input/OneEuroFilter.h b/include/input/OneEuroFilter.h new file mode 100644 index 0000000000..bdd82b2ee8 --- /dev/null +++ b/include/input/OneEuroFilter.h @@ -0,0 +1,101 @@ +/** + * Copyright 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. + */ + +#pragma once + +#include <chrono> +#include <optional> + +#include <input/Input.h> + +namespace android { + +/** + * Low pass filter with adaptive low pass frequency based on the signal's speed. The signal's cutoff + * frequency is determined by f_c = f_c_min + β|̇x_filtered|. Refer to + * https://dl.acm.org/doi/10.1145/2207676.2208639 for details on how the filter works and how to + * tune it. + */ +class OneEuroFilter { +public: + /** + * Default cutoff frequency of the filtered signal's speed. 1.0 Hz is the value in the filter's + * paper. + */ + static constexpr float kDefaultSpeedCutoffFreq = 1.0; + + OneEuroFilter() = delete; + + explicit OneEuroFilter(float minCutoffFreq, float beta, + float speedCutoffFreq = kDefaultSpeedCutoffFreq); + + OneEuroFilter(const OneEuroFilter&) = delete; + OneEuroFilter& operator=(const OneEuroFilter&) = delete; + OneEuroFilter(OneEuroFilter&&) = delete; + OneEuroFilter& operator=(OneEuroFilter&&) = delete; + + /** + * Returns the filtered value of rawPosition. Each call to filter must provide a timestamp + * strictly greater than the timestamp of the previous call. The first time the method is + * called, it returns the value of rawPosition. Any subsequent calls provide a filtered value. + * + * @param timestamp The timestamp at which to filter. It must be strictly greater than the one + * provided in the previous call. + * @param rawPosition Position to be filtered. + */ + float filter(std::chrono::nanoseconds timestamp, float rawPosition); + +private: + /** + * Minimum cutoff frequency. This is the constant term in the adaptive cutoff frequency + * criterion. Units are Hertz. + */ + const float mMinCutoffFreq; + + /** + * Slope of the cutoff frequency criterion. This is the term scaling the absolute value of the + * filtered signal's speed. Units are 1 / position. + */ + const float mBeta; + + /** + * Cutoff frequency of the signal's speed. This is the cutoff frequency applied to the filtering + * of the signal's speed. Units are Hertz. + */ + const float mSpeedCutoffFreq; + + /** + * The timestamp from the previous call. + */ + std::optional<std::chrono::nanoseconds> mPrevTimestamp; + + /** + * The raw position from the previous call. + */ + std::optional<float> mPrevRawPosition; + + /** + * The filtered velocity from the previous call. Units are position per nanosecond. + */ + std::optional<float> mPrevFilteredVelocity; + + /** + * The filtered position from the previous call. + */ + std::optional<float> mPrevFilteredPosition; +}; + +} // namespace android diff --git a/include/input/Resampler.h b/include/input/Resampler.h index dcb25b729f..155097732c 100644 --- a/include/input/Resampler.h +++ b/include/input/Resampler.h @@ -16,10 +16,16 @@ #pragma once +#include <array> #include <chrono> +#include <iterator> +#include <map> #include <optional> #include <vector> +#include <android-base/logging.h> +#include <ftl/mixins.h> +#include <input/CoordinateFilter.h> #include <input/Input.h> #include <input/InputTransport.h> #include <input/RingBuffer.h> @@ -65,7 +71,8 @@ public: * extrapolation takes place and `resampleTime` is too far in the future. If `futureSample` is * not null, interpolation will occur. If `futureSample` is null and there is enough historical * data, LegacyResampler will extrapolate. Otherwise, no resampling takes place and - * `motionEvent` is unmodified. + * `motionEvent` is unmodified. Furthermore, motionEvent is not resampled if resampleTime equals + * the last sample eventTime of motionEvent. */ void resampleMotionEvent(std::chrono::nanoseconds frameTime, MotionEvent& motionEvent, const InputMessage* futureSample) override; @@ -78,13 +85,127 @@ private: PointerCoords coords; }; + /** + * Container that stores pointers as an associative array, supporting O(1) lookup by pointer id, + * as well as forward iteration in the order in which the pointer or pointers were inserted in + * the container. PointerMap has a maximum capacity equal to MAX_POINTERS. + */ + class PointerMap { + public: + struct PointerId : ftl::DefaultConstructible<PointerId, int32_t>, + ftl::Equatable<PointerId> { + using DefaultConstructible::DefaultConstructible; + }; + + /** + * Custom iterator to enable use of range-based for loops. + */ + template <typename T> + class iterator { + public: + using iterator_category = std::forward_iterator_tag; + using value_type = T; + using difference_type = std::ptrdiff_t; + using pointer = T*; + using reference = T&; + + explicit iterator(pointer element) : mElement{element} {} + + friend bool operator==(const iterator& lhs, const iterator& rhs) { + return lhs.mElement == rhs.mElement; + } + + friend bool operator!=(const iterator& lhs, const iterator& rhs) { + return !(lhs == rhs); + } + + iterator operator++() { + ++mElement; + return *this; + } + + reference operator*() const { return *mElement; } + + private: + pointer mElement; + }; + + PointerMap() { + idToIndex.fill(std::nullopt); + for (Pointer& pointer : pointers) { + pointer.properties.clear(); + pointer.coords.clear(); + } + } + + /** + * Forward iterators to traverse the pointers in `pointers`. The order of the pointers is + * determined by the order in which they were inserted (not by id). + */ + iterator<Pointer> begin() { return iterator<Pointer>{&pointers[0]}; } + + iterator<const Pointer> begin() const { return iterator<const Pointer>{&pointers[0]}; } + + iterator<Pointer> end() { return iterator<Pointer>{&pointers[nextPointerIndex]}; } + + iterator<const Pointer> end() const { + return iterator<const Pointer>{&pointers[nextPointerIndex]}; + } + + /** + * Inserts the given pointer into the PointerMap. Precondition: The current number of + * contained pointers must be less than MAX_POINTERS when this function is called. It + * fatally logs if the user tries to insert more than MAX_POINTERS, or if pointer id is out + * of bounds. + */ + void insert(const Pointer& pointer) { + LOG_IF(FATAL, nextPointerIndex >= pointers.size()) + << "Cannot insert more than " << MAX_POINTERS << " in PointerMap."; + LOG_IF(FATAL, (pointer.properties.id < 0) || (pointer.properties.id > MAX_POINTER_ID)) + << "Invalid pointer id."; + idToIndex[pointer.properties.id] = std::optional<size_t>{nextPointerIndex}; + pointers[nextPointerIndex] = pointer; + ++nextPointerIndex; + } + + /** + * Returns the pointer associated with the provided id if it exists. + * Otherwise, std::nullopt is returned. + */ + std::optional<Pointer> find(PointerId id) const { + const int32_t idValue = ftl::to_underlying(id); + LOG_IF(FATAL, (idValue < 0) || (idValue > MAX_POINTER_ID)) << "Invalid pointer id."; + const std::optional<size_t> index = idToIndex[idValue]; + return index.has_value() ? std::optional{pointers[*index]} : std::nullopt; + } + + private: + /** + * The index at which a pointer is inserted in `pointers`. Likewise, it represents the + * number of pointers in PointerMap. + */ + size_t nextPointerIndex{0}; + + /** + * Sequentially stores pointers. Each pointer's position is determined by the value of + * nextPointerIndex at insertion time. + */ + std::array<Pointer, MAX_POINTERS + 1> pointers; + + /** + * Maps each pointer id to its associated index in pointers. If no pointer with the id + * exists in pointers, the mapped value is std::nullopt. + */ + std::array<std::optional<size_t>, MAX_POINTER_ID + 1> idToIndex; + }; + struct Sample { std::chrono::nanoseconds eventTime; - std::vector<Pointer> pointers; + PointerMap pointerMap; std::vector<PointerCoords> asPointerCoords() const { std::vector<PointerCoords> pointersCoords; - for (const Pointer& pointer : pointers) { + for (const Pointer& pointer : pointerMap) { pointersCoords.push_back(pointer.coords); } return pointersCoords; @@ -92,12 +213,6 @@ private: }; /** - * Keeps track of the previous MotionEvent deviceId to enable comparison between the previous - * and the current deviceId. - */ - std::optional<DeviceId> mPreviousDeviceId; - - /** * Up to two latest samples from MotionEvent. Updated every time resampleMotionEvent is called. * Note: We store up to two samples in order to simplify the implementation. Although, * calculations are possible with only one previous sample. @@ -105,6 +220,16 @@ private: RingBuffer<Sample> mLatestSamples{/*capacity=*/2}; /** + * Latest sample in mLatestSamples after resampling motion event. + */ + std::optional<Sample> mLastRealSample; + + /** + * Latest prediction. That is, the latest extrapolated sample. + */ + std::optional<Sample> mPreviousPrediction; + + /** * Adds up to mLatestSamples.capacity() of motionEvent's latest samples to mLatestSamples. If * motionEvent has fewer samples than mLatestSamples.capacity(), then the available samples are * added to mLatestSamples. @@ -128,12 +253,12 @@ private: bool canInterpolate(const InputMessage& futureSample) const; /** - * Returns a sample interpolated between the latest sample of mLatestSamples and futureSample, + * Returns a sample interpolated between the latest sample of mLatestSamples and futureMessage, * if the conditions from canInterpolate are satisfied. Otherwise, returns nullopt. * mLatestSamples must have at least one sample when attemptInterpolation is called. */ std::optional<Sample> attemptInterpolation(std::chrono::nanoseconds resampleTime, - const InputMessage& futureSample) const; + const InputMessage& futureMessage) const; /** * Checks if there are necessary conditions to extrapolate. That is, there are at least two @@ -149,6 +274,64 @@ private: */ std::optional<Sample> attemptExtrapolation(std::chrono::nanoseconds resampleTime) const; + /** + * Iterates through motion event samples, and replaces real coordinates with resampled + * coordinates to avoid jerkiness in certain conditions. + */ + void overwriteMotionEventSamples(MotionEvent& motionEvent) const; + + /** + * Overwrites with resampled data the pointer coordinates that did not move between motion event + * samples, that is, both x and y values are identical to mLastRealSample. + */ + void overwriteStillPointers(MotionEvent& motionEvent, size_t sampleIndex) const; + + /** + * Overwrites the pointer coordinates of a sample with event time older than + * that of mPreviousPrediction. + */ + void overwriteOldPointers(MotionEvent& motionEvent, size_t sampleIndex) const; + inline static void addSampleToMotionEvent(const Sample& sample, MotionEvent& motionEvent); }; + +/** + * Resampler that first applies the LegacyResampler resampling algorithm, then independently filters + * the X and Y coordinates with a pair of One Euro filters. + */ +class FilteredLegacyResampler final : public Resampler { +public: + /** + * Creates a resampler, using the given minCutoffFreq and beta to instantiate its One Euro + * filters. + */ + explicit FilteredLegacyResampler(float minCutoffFreq, float beta); + + void resampleMotionEvent(std::chrono::nanoseconds requestedFrameTime, MotionEvent& motionEvent, + const InputMessage* futureMessage) override; + + std::chrono::nanoseconds getResampleLatency() const override; + +private: + LegacyResampler mResampler; + + /** + * Minimum cutoff frequency of the value's low pass filter. Refer to OneEuroFilter class for a + * more detailed explanation. + */ + const float mMinCutoffFreq; + + /** + * Scaling factor of the adaptive cutoff frequency criterion. Refer to OneEuroFilter class for a + * more detailed explanation. + */ + const float mBeta; + + /* + * Note: an associative array with constant insertion and lookup times would be more efficient. + * When this was implemented, there was no container with these properties. + */ + std::map<int32_t /*pointerId*/, CoordinateFilter> mFilteredPointers; +}; + } // namespace android diff --git a/include/powermanager/PowerHalController.h b/include/powermanager/PowerHalController.h index 7e0bd5bedc..f4f4d5e05c 100644 --- a/include/powermanager/PowerHalController.h +++ b/include/powermanager/PowerHalController.h @@ -72,6 +72,7 @@ public: virtual HalResult<aidl::android::hardware::power::ChannelConfig> getSessionChannel( int tgid, int uid) override; virtual HalResult<void> closeSessionChannel(int tgid, int uid) override; + virtual HalResult<aidl::android::hardware::power::SupportInfo> getSupportInfo() override; private: std::mutex mConnectedHalMutex; diff --git a/include/powermanager/PowerHalWrapper.h b/include/powermanager/PowerHalWrapper.h index 6e347a9ce9..42901821bc 100644 --- a/include/powermanager/PowerHalWrapper.h +++ b/include/powermanager/PowerHalWrapper.h @@ -63,6 +63,7 @@ public: virtual HalResult<aidl::android::hardware::power::ChannelConfig> getSessionChannel(int tgid, int uid) = 0; virtual HalResult<void> closeSessionChannel(int tgid, int uid) = 0; + virtual HalResult<aidl::android::hardware::power::SupportInfo> getSupportInfo() = 0; }; // Empty Power HAL wrapper that ignores all api calls. @@ -85,6 +86,7 @@ public: HalResult<aidl::android::hardware::power::ChannelConfig> getSessionChannel(int tgid, int uid) override; HalResult<void> closeSessionChannel(int tgid, int uid) override; + HalResult<aidl::android::hardware::power::SupportInfo> getSupportInfo() override; protected: virtual const char* getUnsupportedMessage(); @@ -170,6 +172,7 @@ public: HalResult<aidl::android::hardware::power::ChannelConfig> getSessionChannel(int tgid, int uid) override; HalResult<void> closeSessionChannel(int tgid, int uid) override; + HalResult<aidl::android::hardware::power::SupportInfo> getSupportInfo() override; protected: const char* getUnsupportedMessage() override; diff --git a/include/private/display_luts_private.h b/include/private/display_luts_private.h new file mode 100644 index 0000000000..c347a0c85d --- /dev/null +++ b/include/private/display_luts_private.h @@ -0,0 +1,66 @@ +/* + * 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. + */ + +#pragma once + +#include <android/display_luts.h> +#include <stdint.h> +#include <vector> +#include <utils/RefBase.h> + +using namespace android; + +__BEGIN_DECLS + +struct ADisplayLutsEntry_buffer { + std::vector<float> data; +}; + +struct ADisplayLutsEntry_properties { + ADisplayLuts_Dimension dimension; + int32_t size; + ADisplayLuts_SamplingKey samplingKey; +}; + +struct ADisplayLutsEntry: public RefBase { + struct ADisplayLutsEntry_buffer buffer; + struct ADisplayLutsEntry_properties properties; + ADisplayLutsEntry() {} + + // copy constructor + ADisplayLutsEntry(const ADisplayLutsEntry& other) : + buffer(other.buffer), + properties(other.properties) {} + + // copy operator + ADisplayLutsEntry& operator=(const ADisplayLutsEntry& other) { + if (this != &other) { // Protect against self-assignment + buffer = other.buffer; + properties = other.properties; + } + return *this; + } +}; + +struct ADisplayLuts: public RefBase { + int32_t totalBufferSize; + std::vector<int32_t> offsets; + std::vector<sp<ADisplayLutsEntry>> entries; + + ADisplayLuts() : totalBufferSize(0) {} +}; + +__END_DECLS
\ No newline at end of file diff --git a/include/private/performance_hint_private.h b/include/private/performance_hint_private.h index e5eee340ca..e3f98badbe 100644 --- a/include/private/performance_hint_private.h +++ b/include/private/performance_hint_private.h @@ -74,6 +74,20 @@ enum SessionHint: int32_t { * baseline to prepare for an arbitrary load, and must wake up if inactive. */ GPU_LOAD_RESET = 7, + + /** + * This hint indicates an upcoming CPU workload that is abnormally large and + * not representative of the workload. This should be used for rare, one-time + * operations and should be ignored by any load tracking or session hysteresis. + */ + CPU_LOAD_SPIKE = 8, + + /** + * This hint indicates an upcoming GPU workload that is abnormally large and + * not representative of the workload. This should be used for rare, one-time + * operations and should be ignored by any load tracking or session hysteresis. + */ + GPU_LOAD_SPIKE = 9, }; // Allows access to PowerHAL's SessionTags without needing to import its AIDL @@ -83,6 +97,7 @@ enum class SessionTag : int32_t { HWUI = 2, GAME = 3, APP = 4, + SYSUI = 5, }; /** @@ -107,12 +122,46 @@ int APerformanceHint_getThreadIds(APerformanceHintSession* session, APerformanceHintSession* APerformanceHint_createSessionInternal(APerformanceHintManager* manager, const int32_t* threadIds, size_t size, int64_t initialTargetWorkDurationNanos, SessionTag tag); +/** + * Creates a session using ASessionCreationConfig + */ +APerformanceHintSession* APerformanceHint_createSessionUsingConfigInternal( + APerformanceHintManager* manager, ASessionCreationConfig* sessionCreationConfig, + SessionTag tag); + +/** + * Creates a session from the Java SDK implementation + */ +APerformanceHintSession* APerformanceHint_createSessionFromJava(APerformanceHintManager* manager, + const int32_t* threadIds, size_t size, + int64_t initialTargetWorkDurationNanos); + +/** + * Special method for Java SDK implementation to kill sessions + */ +void APerformanceHint_closeSessionFromJava(APerformanceHintSession* session); /** * Forces FMQ to be enabled or disabled, for testing only. */ void APerformanceHint_setUseFMQForTesting(bool enabled); +/** + * Get the rate limiter properties for testing. + */ +void APerformanceHint_getRateLimiterPropertiesForTesting( + int32_t* maxLoadHintsPerInterval, int64_t* loadHintInterval); + +/* + * Forces the "new load hint" flag to be disabled for testing. + */ +void APerformanceHint_setUseNewLoadHintBehaviorForTesting(bool newBehavior); + +/* + * Forces the graphics pipeline flag to be enabled or disabled, for testing only. + */ +void APerformanceHint_setUseGraphicsPipelineForTesting(bool enabled); + __END_DECLS #endif // ANDROID_PRIVATE_NATIVE_PERFORMANCE_HINT_PRIVATE_H |