diff options
49 files changed, 1435 insertions, 850 deletions
diff --git a/include/android/performance_hint.h b/include/android/performance_hint.h index 9ea6549e8a..52dbb61ac5 100644 --- a/include/android/performance_hint.h +++ b/include/android/performance_hint.h @@ -29,7 +29,7 @@ * 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 + * Unlike reportActualWorkDuration, the "notifyWorkload..." 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. @@ -71,6 +71,10 @@ #include <stdint.h> #include <unistd.h> +#if !defined(__DEPRECATED_IN) +#define __DEPRECATED_IN(__api_level, ...) __attribute__((__deprecated__)) +#endif + __BEGIN_DECLS struct APerformanceHintManager; @@ -116,13 +120,13 @@ 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. + * A session creation config encapsulates the required information for creating a session. The only + * mandatory parameter is the set of TIDs, set using {@link ASessionCreationConfig_setTids}. Only + * parameters relevant to the session need to be set, and any unspecified functionality will be + * treated as unused on the session. Configurations without a valid set of TIDs, or which try to + * enable automatic timing without the graphics pipeline mode, are considered invalid. * + * The caller may reuse this object and modify the settings in it to create additional sessions. */ typedef struct ASessionCreationConfig ASessionCreationConfig; @@ -181,27 +185,43 @@ 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. + * Creates a session using arguments from a corresponding {@link ASessionCreationConfig}. + * + * Note: when using graphics pipeline mode, using too many cumulative graphics pipeline threads is + * not a failure and will still create a session, but it will cause all graphics pipeline sessions + * to have undefined behavior and the method will return EBUSY. * * @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. + * @param sessionOut A client-provided pointer, which will be set to the new APerformanceHintSession + * on success or EBUSY, and to nullptr on failure. + * + * @return 0 on success. + * EINVAL if the creation config is in an invalid state. + * EPIPE if communication failed. + * ENOTSUP if hint sessions are not supported, or if auto timing is enabled but unsupported. + * EBUSY if too many graphics pipeline threads are passed. */ -APerformanceHintSession* _Nullable APerformanceHint_createSessionUsingConfig( +int APerformanceHint_createSessionUsingConfig( APerformanceHintManager* _Nonnull manager, - ASessionCreationConfig* _Nonnull config) - __INTRODUCED_IN(36); + ASessionCreationConfig* _Nonnull config, + APerformanceHintSession * _Nullable * _Nonnull sessionOut) __INTRODUCED_IN(36); /** * Get preferred update rate information for this device. * + * @deprecated Client side rate limiting is not necessary, rate limiting is handled in the + * framework. If you were using this to check for hint session support, please use + * {@link APerformanceHint_isFeatureSupported} instead. + * * @param manager The performance hint manager instance. * @return the preferred update rate supported by device software. */ int64_t APerformanceHint_getPreferredUpdateRateNanos( - APerformanceHintManager* _Nonnull manager) __INTRODUCED_IN(__ANDROID_API_T__); + APerformanceHintManager* _Nonnull manager) + __INTRODUCED_IN(__ANDROID_API_T__) __DEPRECATED_IN(36, "Client-side rate limiting is not" + " necessary, use APerformanceHint_isFeatureSupported for support checking."); /** * Get maximum number of graphics pipieline threads per-app for this device. @@ -216,9 +236,11 @@ int64_t APerformanceHint_getPreferredUpdateRateNanos( * Updates this session's target duration for each cycle of work. * * @param session The performance hint session instance to update. - * @param targetDurationNanos The new desired duration in nanoseconds. This must be positive. + * @param targetDurationNanos The new desired duration in nanoseconds. This must be positive for the + * session to report work durations, and may be zero to disable this functionality. + * * @return 0 on success. - * EINVAL if targetDurationNanos is not positive. + * EINVAL if targetDurationNanos is less than zero. * EPIPE if communication with the system service has failed. */ int APerformanceHint_updateTargetWorkDuration( @@ -235,7 +257,7 @@ int APerformanceHint_updateTargetWorkDuration( * @param actualDurationNanos The duration of time the thread group took to complete its last * task in nanoseconds. This must be positive. * @return 0 on success. - * EINVAL if actualDurationNanos is not positive. + * EINVAL if actualDurationNanos is not positive or the target it not positive. * EPIPE if communication with the system service has failed. */ int APerformanceHint_reportActualWorkDuration( @@ -258,15 +280,20 @@ void APerformanceHint_closeSession( * Set a list of threads to the performance hint session. This operation will replace * the current list of threads with the given list of threads. * + * Note: when using a session with the graphics pipeline mode enabled, using too many cumulative + * graphics pipeline threads is not a failure, but it will cause all graphics pipeline sessions to + * have undefined behavior and the method will return EBUSY. + * * @param session The performance hint session instance to update. * @param threadIds The list of threads to be associated with this session. They must be part of * this app's thread group. * @param size The size of the list of threadIds. * @return 0 on success. * EINVAL if the list of thread ids is empty or if any of the thread ids are not part of - the thread group. + * the thread group. * EPIPE if communication with the system service has failed. * EPERM if any thread id doesn't belong to the application. + * EBUSY if too many graphics pipeline threads were passed. */ int APerformanceHint_setThreads( APerformanceHintSession* _Nonnull session, @@ -311,89 +338,102 @@ 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. + * Informs the framework of an upcoming increase in the workload of 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. + * These hints should be sent shortly before the start of the cycle where the workload is going to + * change, or as early as possible during that cycle for maximum effect. Hints sent towards the end + * of the cycle may be interpreted as applying to the next cycle. Any unsupported hints will be + * silently dropped, to avoid the need for excessive support checking each time they are sent, and + * sending a hint for both CPU and GPU will count as two separate hints for the rate limiter. These + * hints should not be sent repeatedly for an ongoing expensive workload, as workload time reporting + * is intended to handle this. * + * @param session The {@link APerformanceHintSession} instance to send a hint for. * @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. + * @param identifier A required string used to distinguish this specific hint, using utf-8 encoding. + * This string will only be held for the duration of the method, and can be 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); + bool cpu, bool gpu, const char* _Nonnull identifier) __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. + * Informs the framework that the workload associated with this session is about to start, or that + * it is about to completely change, and that the system should discard any assumptions about its + * characteristics inferred from previous activity. 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. + * These hints should be sent shortly before the start of the cycle where the workload is going to + * change, or as early as possible during that cycle for maximum effect. Hints sent towards the end + * of the cycle may be interpreted as applying to the next cycle. Any unsupported hints will be + * silently dropped, to avoid the need for excessive support checking each time they are sent, and + * sending a hint for both CPU and GPU will count as two separate hints for the rate limiter. These + * hints should not be sent repeatedly for an ongoing expensive workload, as workload time reporting + * is intended to handle this. * + * @param session The {@link APerformanceHintSession} instance to send a hint for. * @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. + * @param identifier A required string used to distinguish this specific hint, using utf-8 encoding. + * This string will only be held for the duration of the method, and can be 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); + bool cpu, bool gpu, const char* _Nonnull identifier) __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. + * Informs the framework of an upcoming one-off expensive workload cycle for a given session. + * This cycle 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. + * These hints should be sent shortly before the start of the cycle where the workload is going to + * change, or as early as possible during that cycle for maximum effect. Hints sent towards the end + * of the cycle may be interpreted as applying to the next cycle. Any unsupported hints will be + * silently dropped, to avoid the need for excessive support checking each time they are sent, and + * sending a hint for both CPU and GPU will count as two separate hints for the rate limiter. These + * hints should not be sent repeatedly for an ongoing expensive workload, as workload time reporting + * is intended to handle this. * + * @param session The {@link APerformanceHintSession} instance to send a hint for. * @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. + * @param identifier A required string used to distinguish this specific hint, using utf-8 encoding. + * This string will only be held for the duration of the method, and can be 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); + bool cpu, bool gpu, const char* _Nonnull identifier) __INTRODUCED_IN(36); /** * Associates a session with any {@link ASurfaceControl} or {@link ANativeWindow} - * instances managed by this session. + * instances managed by this session. Any previously associated objects that are not passed + * in again lose their association. Invalid or dead instances are ignored, and passing both + * lists as null drops all current associations. * * This method is primarily intended for sessions that manage the timing of an entire - * graphics pipeline end-to-end, such as those using the + * graphics pipeline end-to-end for frame pacing, 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. + * Additionally, if the surface associated with a session changes, this method should be called + * again to re-create the association. * - * To see any benefit from this method, the client must make sure they are updating the framerate + * To see any benefit from this method, the client must make sure they are updating the frame rate * of attached surfaces using methods such as {@link ANativeWindow_setFrameRate}, or by updating * any associated ASurfaceControls with transactions that have {ASurfaceTransaction_setFrameRate}. * @@ -407,16 +447,77 @@ int APerformanceHint_notifyWorkloadSpike( * * @return 0 on success. * EPIPE if communication has failed. - * ENOTSUP if unsupported. - * EINVAL if invalid or empty arguments passed. + * ENOTSUP if this is not supported on the device. */ int APerformanceHint_setNativeSurfaces(APerformanceHintSession* _Nonnull session, - ANativeWindow* _Nonnull* _Nullable nativeWindows, int nativeWindowsSize, - ASurfaceControl* _Nonnull* _Nullable surfaceControls, int surfaceControlsSize) + ANativeWindow* _Nonnull* _Nullable nativeWindows, size_t nativeWindowsSize, + ASurfaceControl* _Nonnull* _Nullable surfaceControls, size_t surfaceControlsSize) __INTRODUCED_IN(36); /** + * This enum represents different aspects of performance hint functionality. These can be passed + * to {@link APerformanceHint_isFeatureSupported} to determine whether the device exposes support + * for that feature. + * + * Some of these features will not expose failure to the client if used when unsupported, to prevent + * the client from needing to worry about handling different logic for each possible support + * configuration. The exception to this is features with important user-facing side effects, such as + * {@link APERF_HINT_AUTO_CPU} and {@link APERF_HINT_AUTO_GPU} modes which expect the client not to + * report durations while they are active. + */ +typedef enum APerformanceHintFeature : int32_t { + /** + * This value represents all APerformanceHintSession functionality. Using the Performance Hint + * API at all if this is not enabled will likely result in either + * {@link APerformanceHintManager} or {@link APerformanceHintSession} failing to create, or the + * session having little to no benefit even if creation succeeds. + */ + APERF_HINT_SESSIONS, + + /** + * This value represents the power efficiency mode, as exposed by + * {@link ASessionCreationConfig_setPreferPowerEfficiency} and + * {@link APerformanceHint_setPreferPowerEfficiency}. + */ + APERF_HINT_POWER_EFFICIENCY, + + /** + * This value the ability for sessions to bind to surfaces using + * {@link APerformanceHint_setNativeSurfaces} or + * {@link ASessionCreationConfig_setNativeSurfaces} + */ + APERF_HINT_SURFACE_BINDING, + + /** + * This value represents the "graphics pipeline" mode, as exposed by + * {@link ASessionCreationConfig_setGraphicsPipeline}. + */ + APERF_HINT_GRAPHICS_PIPELINE, + + /** + * This value represents the automatic CPU timing feature, as exposed by + * {@link ASessionCreationConfig_setUseAutoTiming}. + */ + APERF_HINT_AUTO_CPU, + + /** + * This value represents the automatic GPU timing feature, as exposed by + * {@link ASessionCreationConfig_setUseAutoTiming}. + */ + APERF_HINT_AUTO_GPU, +} APerformanceHintFeature; + +/** + * Checks whether the device exposes support for a specific feature. + * + * @param feature The specific feature enum to check. + * + * @return false if unsupported, true if supported. + */ +bool APerformanceHint_isFeatureSupported(APerformanceHintFeature feature) __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. @@ -507,7 +608,6 @@ APerformanceHintSession* _Nonnull APerformanceHint_borrowSessionFromJava( ASessionCreationConfig* _Nonnull ASessionCreationConfig_create() __INTRODUCED_IN(36); - /** * Destroys a {@link ASessionCreationConfig} and frees all * resources associated with it. @@ -526,11 +626,8 @@ void ASessionCreationConfig_release( * @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( +void ASessionCreationConfig_setTids( ASessionCreationConfig* _Nonnull config, const pid_t* _Nonnull tids, size_t size) __INTRODUCED_IN(36); @@ -539,15 +636,11 @@ int ASessionCreationConfig_setTids( * * @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 + * @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, and may be ignored + * otherwise or set to zero. Negative values are invalid. */ -int ASessionCreationConfig_setTargetWorkDurationNanos( +void ASessionCreationConfig_setTargetWorkDurationNanos( ASessionCreationConfig* _Nonnull config, int64_t targetWorkDurationNanos) __INTRODUCED_IN(36); @@ -559,12 +652,8 @@ int ASessionCreationConfig_setTargetWorkDurationNanos( * @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( +void ASessionCreationConfig_setPreferPowerEfficiency( ASessionCreationConfig* _Nonnull config, bool enabled) __INTRODUCED_IN(36); /** @@ -574,24 +663,31 @@ int ASessionCreationConfig_setPreferPowerEfficiency( * 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()}. + * up to a limit accessible from {@link APerformanceHint_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( +void 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. + * Associates the created session with any {@link ASurfaceControl} or {@link ANativeWindow} + * instances it will be managing. Invalid or dead instances are ignored. + * + * This method is primarily intended for sessions that manage the timing of an entire + * graphics pipeline end-to-end for frame pacing, 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. + * Additionally, if the surface associated with a session changes, this method should be called + * again to re-create the association. + * + * To see any benefit from this method, the client must make sure they are updating the frame rate + * of attached surfaces using methods such as {@link ANativeWindow_setFrameRate}, or by updating + * any associated ASurfaceControls with transactions that have {ASurfaceTransaction_setFrameRate}. + * * * @param config The {@link ASessionCreationConfig} * created by calling {@link ASessionCreationConfig_create()}. @@ -601,49 +697,46 @@ int ASessionCreationConfig_setGraphicsPipeline( * @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( +void ASessionCreationConfig_setNativeSurfaces( ASessionCreationConfig* _Nonnull config, - ANativeWindow* _Nonnull* _Nullable nativeWindows, int nativeWindowsSize, - ASurfaceControl* _Nonnull* _Nullable surfaceControls, int surfaceControlsSize) + ANativeWindow* _Nonnull* _Nullable nativeWindows, size_t nativeWindowsSize, + ASurfaceControl* _Nonnull* _Nullable surfaceControls, size_t 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. + * surface. In this mode, sessions do not need to report timing data for the CPU, GPU, or both + * depending on the configuration. To use this mode, sessions should set a native surface + * using {@ASessionCreationConfig_setNativeSurfaces}, enable graphics pipeline mode with + * {@link ASessionCreationConfig_setGraphicsPipeline()}, and then call this method to set whether + * automatic timing is desired for the CPU, GPU, or both. Trying to enable this without also + * enabling the graphics pipeline mode will cause session creation to fail. * * 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. + * {@link APerformanceHint_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}. + * If the client is manually controlling their frame rate for those surfaces, then they must make + * sure they are updating the frame rate with {@link ANativeWindow_setFrameRate}, or updating any + * associated ASurfaceControls with transactions that have {ASurfaceTransaction_setFrameRate} set. + * + * The user of this API should ensure this feature is supported by checking + * {@link APERF_HINT_AUTO_CPU} and {@link APERF_HINT_AUTO_GPU} with + * {@link APerformanceHint_isFeatureSupported} and falling back to manual timing if it is not. + * Trying to use automatic timing when it is unsupported will cause session creation to fail. * * @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); +void ASessionCreationConfig_setUseAutoTiming( + ASessionCreationConfig* _Nonnull config, bool cpu, bool gpu) __INTRODUCED_IN(36); __END_DECLS diff --git a/include/input/AccelerationCurve.h b/include/input/AccelerationCurve.h index 0cf648a2f7..8a4a5d429b 100644 --- a/include/input/AccelerationCurve.h +++ b/include/input/AccelerationCurve.h @@ -46,4 +46,15 @@ struct AccelerationCurveSegment { std::vector<AccelerationCurveSegment> createAccelerationCurveForPointerSensitivity( int32_t sensitivity); +/* + * Creates a flat acceleration curve for disabling pointer acceleration. + * + * This method generates a single AccelerationCurveSegment with specific values + * to effectively disable acceleration for both mice and touchpads. + * A flat acceleration curve ensures a constant gain, meaning that the output + * velocity is directly proportional to the input velocity, resulting in + * a 1:1 movement ratio between the input device and the on-screen pointer. + */ +std::vector<AccelerationCurveSegment> createFlatAccelerationCurve(int32_t sensitivity); + } // namespace android diff --git a/include/private/performance_hint_private.h b/include/private/performance_hint_private.h index e3f98badbe..a468313341 100644 --- a/include/private/performance_hint_private.h +++ b/include/private/performance_hint_private.h @@ -125,8 +125,10 @@ APerformanceHintSession* APerformanceHint_createSessionInternal(APerformanceHint /** * Creates a session using ASessionCreationConfig */ -APerformanceHintSession* APerformanceHint_createSessionUsingConfigInternal( - APerformanceHintManager* manager, ASessionCreationConfig* sessionCreationConfig, +int APerformanceHint_createSessionUsingConfigInternal( + APerformanceHintManager* manager, + ASessionCreationConfig* config, + APerformanceHintSession** sessionOut, SessionTag tag); /** diff --git a/libs/input/AccelerationCurve.cpp b/libs/input/AccelerationCurve.cpp index 0a92a71596..0b47f3e6e7 100644 --- a/libs/input/AccelerationCurve.cpp +++ b/libs/input/AccelerationCurve.cpp @@ -40,6 +40,18 @@ static_assert(kSegments.back().maxPointerSpeedMmPerS == std::numeric_limits<doub constexpr std::array<double, 15> kSensitivityFactors = {1, 2, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 18, 20}; +// Calculates the base gain for a given pointer sensitivity value. +// +// The base gain is a scaling factor that is applied to the pointer movement. +// Higher sensitivity values result in larger base gains, which in turn result +// in faster pointer movements. +// +// The base gain is calculated using a linear mapping function that maps the +// sensitivity range [-7, 7] to a base gain range [0.5, 2.0]. +double calculateBaseGain(int32_t sensitivity) { + return 0.5 + (sensitivity + 7) * (2.0 - 0.5) / (7 + 7); +} + } // namespace std::vector<AccelerationCurveSegment> createAccelerationCurveForPointerSensitivity( @@ -60,4 +72,13 @@ std::vector<AccelerationCurveSegment> createAccelerationCurveForPointerSensitivi return output; } +std::vector<AccelerationCurveSegment> createFlatAccelerationCurve(int32_t sensitivity) { + LOG_ALWAYS_FATAL_IF(sensitivity < -7 || sensitivity > 7, "Invalid pointer sensitivity value"); + std::vector<AccelerationCurveSegment> output = { + AccelerationCurveSegment{std::numeric_limits<double>::infinity(), + calculateBaseGain(sensitivity), + /* reciprocal = */ 0}}; + return output; +} + } // namespace android
\ No newline at end of file diff --git a/libs/input/android/os/IInputConstants.aidl b/libs/input/android/os/IInputConstants.aidl index 31592cd6e3..6ce3fba477 100644 --- a/libs/input/android/os/IInputConstants.aidl +++ b/libs/input/android/os/IInputConstants.aidl @@ -76,6 +76,9 @@ interface IInputConstants /* The default pointer acceleration value. */ const int DEFAULT_POINTER_ACCELERATION = 3; + /* The default mouse wheel acceleration value. */ + const int DEFAULT_MOUSE_WHEEL_ACCELERATION = 4; + /** * Use the default Velocity Tracker Strategy. Different axes may use different default * strategies. diff --git a/libs/input/input_flags.aconfig b/libs/input/input_flags.aconfig index fd7704815f..6cdd249b9e 100644 --- a/libs/input/input_flags.aconfig +++ b/libs/input/input_flags.aconfig @@ -109,13 +109,6 @@ flag { } flag { - name: "enable_touchpad_fling_stop" - namespace: "input" - description: "Enable fling scrolling to be stopped by putting a finger on the touchpad again" - bug: "281106755" -} - -flag { name: "enable_prediction_pruning_via_jerk_thresholding" namespace: "input" description: "Enable prediction pruning based on jerk thresholds." diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp index 0167c433cb..85a37fe04a 100644 --- a/libs/input/tests/Android.bp +++ b/libs/input/tests/Android.bp @@ -58,11 +58,19 @@ cc_test { "-Wno-unused-parameter", ], sanitize: { + address: true, hwaddress: true, undefined: true, all_undefined: true, diag: { + cfi: true, + integer_overflow: true, + memtag_heap: true, undefined: true, + misc_undefined: [ + "bounds", + "all", + ], }, }, shared_libs: [ @@ -92,11 +100,6 @@ cc_test { "libstatssocket_lazy", ], }, - host: { - sanitize: { - address: true, - }, - }, }, native_coverage: false, } diff --git a/libs/renderengine/skia/SkiaRenderEngine.cpp b/libs/renderengine/skia/SkiaRenderEngine.cpp index 7e8ccef18e..14d08eea74 100644 --- a/libs/renderengine/skia/SkiaRenderEngine.cpp +++ b/libs/renderengine/skia/SkiaRenderEngine.cpp @@ -544,9 +544,18 @@ sk_sp<SkShader> SkiaRenderEngine::createRuntimeEffectShader( } if (graphicBuffer && parameters.layer.luts) { + const bool dimInLinearSpace = parameters.display.dimmingStage != + aidl::android::hardware::graphics::composer3::DimmingStage::GAMMA_OETF; + const ui::Dataspace runtimeEffectDataspace = !dimInLinearSpace + ? static_cast<ui::Dataspace>( + (parameters.outputDataSpace & ui::Dataspace::STANDARD_MASK) | + ui::Dataspace::TRANSFER_GAMMA2_2 | + (parameters.outputDataSpace & ui::Dataspace::RANGE_MASK)) + : parameters.outputDataSpace; + shader = mLutShader.lutShader(shader, parameters.layer.luts, parameters.layer.sourceDataspace, - toSkColorSpace(parameters.outputDataSpace)); + toSkColorSpace(runtimeEffectDataspace)); } if (parameters.requiresLinearEffect) { diff --git a/libs/renderengine/skia/VulkanInterface.cpp b/libs/renderengine/skia/VulkanInterface.cpp index 37b69f6590..7331bbc418 100644 --- a/libs/renderengine/skia/VulkanInterface.cpp +++ b/libs/renderengine/skia/VulkanInterface.cpp @@ -204,10 +204,10 @@ static skgpu::VulkanGetProc sGetProc = [](const char* proc_name, BAIL("[%s] null", #expr); \ } -#define VK_CHECK(expr) \ - if ((expr) != VK_SUCCESS) { \ - BAIL("[%s] failed. err = %d", #expr, expr); \ - return; \ +#define VK_CHECK(expr) \ + if (VkResult result = (expr); result != VK_SUCCESS) { \ + BAIL("[%s] failed. err = %d", #expr, result); \ + return; \ } #define VK_GET_PROC(F) \ diff --git a/libs/renderengine/skia/filters/KawaseBlurDualFilter.cpp b/libs/renderengine/skia/filters/KawaseBlurDualFilter.cpp index da47aae15b..750e08fa55 100644 --- a/libs/renderengine/skia/filters/KawaseBlurDualFilter.cpp +++ b/libs/renderengine/skia/filters/KawaseBlurDualFilter.cpp @@ -74,13 +74,6 @@ KawaseBlurDualFilter::KawaseBlurDualFilter() : BlurFilter() { mBlurEffect = std::move(blurEffect); } -static sk_sp<SkSurface> makeSurface(SkiaGpuContext* context, const SkRect& origRect, int scale) { - SkImageInfo scaledInfo = - SkImageInfo::MakeN32Premul(ceil(static_cast<float>(origRect.width()) / scale), - ceil(static_cast<float>(origRect.height()) / scale)); - return context->createRenderTarget(scaledInfo); -} - void KawaseBlurDualFilter::blurInto(const sk_sp<SkSurface>& drawSurface, const sk_sp<SkImage>& readImage, const float radius, const float alpha) const { @@ -124,11 +117,17 @@ sk_sp<SkImage> KawaseBlurDualFilter::generate(SkiaGpuContext* context, const uin const float filterDepth = std::min(kMaxSurfaces - 1.0f, radius * kInputScale / 2.5f); const int filterPasses = std::min(kMaxSurfaces - 1, static_cast<int>(ceil(filterDepth))); + auto makeSurface = [&](float scale) -> sk_sp<SkSurface> { + const auto newW = static_cast<float>(blurRect.width() / scale); + const auto newH = static_cast<float>(blurRect.height() / scale); + return context->createRenderTarget(input->imageInfo().makeWH(newW, newH)); + }; + // Render into surfaces downscaled by 1x, 2x, and 4x from the initial downscale. sk_sp<SkSurface> surfaces[kMaxSurfaces] = - {filterPasses >= 0 ? makeSurface(context, blurRect, 1 * kInverseInputScale) : nullptr, - filterPasses >= 1 ? makeSurface(context, blurRect, 2 * kInverseInputScale) : nullptr, - filterPasses >= 2 ? makeSurface(context, blurRect, 4 * kInverseInputScale) : nullptr}; + {filterPasses >= 0 ? makeSurface(1 * kInverseInputScale) : nullptr, + filterPasses >= 1 ? makeSurface(2 * kInverseInputScale) : nullptr, + filterPasses >= 2 ? makeSurface(4 * kInverseInputScale) : nullptr}; // These weights for scaling offsets per-pass are handpicked to look good at 1 <= radius <= 250. static const float kWeights[5] = { diff --git a/libs/tracing_perfetto/Android.bp b/libs/tracing_perfetto/Android.bp index 8bd0d0f33d..1ef83a4706 100644 --- a/libs/tracing_perfetto/Android.bp +++ b/libs/tracing_perfetto/Android.bp @@ -21,7 +21,7 @@ package { default_applicable_licenses: ["frameworks_native_license"], } -cc_library_shared { +cc_library { name: "libtracing_perfetto", export_include_dirs: [ "include", @@ -37,6 +37,7 @@ cc_library_shared { srcs: [ "tracing_perfetto.cpp", "tracing_perfetto_internal.cpp", + "tracing_sdk.cpp", ], shared_libs: [ @@ -45,6 +46,10 @@ cc_library_shared { "libperfetto_c", ], + export_shared_lib_headers: [ + "libperfetto_c", + ], + host_supported: true, // for vndbinder vendor_available: true, diff --git a/libs/tracing_perfetto/include/tracing_sdk.h b/libs/tracing_perfetto/include/tracing_sdk.h new file mode 100644 index 0000000000..4a6e849567 --- /dev/null +++ b/libs/tracing_perfetto/include/tracing_sdk.h @@ -0,0 +1,461 @@ +/* + * 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-base/logging.h> +#include <stdint.h> + +#include <optional> +#include <vector> + +#include "perfetto/public/producer.h" +#include "perfetto/public/te_category_macros.h" +#include "perfetto/public/te_macros.h" +#include "perfetto/public/track_event.h" + +/** + * The objects declared here are intended to be managed by Java. + * This means the Java Garbage Collector is responsible for freeing the + * underlying native resources. + * + * The static methods prefixed with `delete_` are special. They are designed to be + * invoked by Java through the `NativeAllocationRegistry` when the + * corresponding Java object becomes unreachable. These methods act as + * callbacks to ensure proper deallocation of native resources. + */ +namespace tracing_perfetto { +/** + * @brief Represents extra data associated with a trace event. + * This class manages a collection of PerfettoTeHlExtra pointers. + */ +class Extra; + +/** + * @brief Emits a trace event. + * @param type The type of the event. + * @param cat The category of the event. + * @param name The name of the event. + * @param arg_ptr Pointer to Extra data. + */ +void trace_event(int type, const PerfettoTeCategory* cat, const char* name, + Extra* extra); + +/** + * @brief Gets the process track UUID. + */ +uint64_t get_process_track_uuid(); + +/** + * @brief Gets the thread track UUID for a given PID. + */ +uint64_t get_thread_track_uuid(pid_t tid); + +/** + * @brief Holder for all the other classes in the file. + */ +class Extra { + public: + Extra(); + void push_extra(PerfettoTeHlExtra* extra); + void pop_extra(); + void clear_extras(); + static void delete_extra(Extra* extra); + + PerfettoTeHlExtra* const* get() const; + + private: + DISALLOW_COPY_AND_ASSIGN(Extra); + + // These PerfettoTeHlExtra pointers are really pointers to all the other + // types of extras: Category, DebugArg, Counter etc. Those objects are + // individually managed by Java. + std::vector<PerfettoTeHlExtra*> extras_; +}; + +/** + * @brief Represents a trace event category. + */ +class Category { + public: + Category(const std::string& name, const std::string& tag, + const std::string& severity); + + ~Category(); + + void register_category(); + + void unregister_category(); + + bool is_category_enabled(); + + static void delete_category(Category* category); + + const PerfettoTeCategory* get() const; + + private: + DISALLOW_COPY_AND_ASSIGN(Category); + PerfettoTeCategory category_; + const std::string name_; + const std::string tag_; + const std::string severity_; +}; + +/** + * @brief Represents one end of a flow between two events. + */ +class Flow { + public: + Flow(); + + void set_process_flow(uint64_t id); + void set_process_terminating_flow(uint64_t id); + static void delete_flow(Flow* flow); + + const PerfettoTeHlExtraFlow* get() const; + + private: + DISALLOW_COPY_AND_ASSIGN(Flow); + PerfettoTeHlExtraFlow flow_; +}; + +/** + * @brief Represents a named track. + */ +class NamedTrack { + public: + NamedTrack(uint64_t id, uint64_t parent_uuid, const std::string& name); + + static void delete_track(NamedTrack* track); + + const PerfettoTeHlExtraNamedTrack* get() const; + + private: + DISALLOW_COPY_AND_ASSIGN(NamedTrack); + const std::string name_; + PerfettoTeHlExtraNamedTrack track_; +}; + +/** + * @brief Represents a registered track. + */ +class RegisteredTrack { + public: + RegisteredTrack(uint64_t id, uint64_t parent_uuid, const std::string& name, + bool is_counter); + ~RegisteredTrack(); + + void register_track(); + void unregister_track(); + static void delete_track(RegisteredTrack* track); + + const PerfettoTeHlExtraRegisteredTrack* get() const; + + private: + DISALLOW_COPY_AND_ASSIGN(RegisteredTrack); + PerfettoTeRegisteredTrack registered_track_; + PerfettoTeHlExtraRegisteredTrack track_; + const std::string name_; + const uint64_t id_; + const uint64_t parent_uuid_; + const bool is_counter_; +}; + +/** + * @brief Represents a counter track event. + * @tparam T The data type of the counter (int64_t or double). + */ +template <typename T> +class Counter { + public: + template <typename> + struct always_false : std::false_type {}; + + struct TypeMap { + using type = std::invoke_result_t<decltype([]() { + if constexpr (std::is_same_v<T, int64_t>) { + return std::type_identity<PerfettoTeHlExtraCounterInt64>{}; + } else if constexpr (std::is_same_v<T, double>) { + return std::type_identity<PerfettoTeHlExtraCounterDouble>{}; + } else { + return std::type_identity<void>{}; + } + })>::type; + + static constexpr int enum_value = []() { + if constexpr (std::is_same_v<T, int64_t>) { + return PERFETTO_TE_HL_EXTRA_TYPE_COUNTER_INT64; + } else if constexpr (std::is_same_v<T, double>) { + return PERFETTO_TE_HL_EXTRA_TYPE_COUNTER_DOUBLE; + } else { + static_assert(always_false<T>::value, "Unsupported type"); + return 0; // Never reached, just to satisfy return type + } + }(); + }; + + Counter() { + static_assert(!std::is_same_v<typename TypeMap::type, void>, + "Unsupported type for Counter"); + + typename TypeMap::type counter; + counter.header = {TypeMap::enum_value}; + counter_ = std::move(counter); + } + + void set_value(T value) { + if constexpr (std::is_same_v<T, int64_t>) { + counter_.value = value; + } else if constexpr (std::is_same_v<T, double>) { + counter_.value = value; + } + } + + static void delete_counter(Counter* counter) { + delete counter; + } + + const TypeMap::type* get() const { + return &counter_; + } + + private: + DISALLOW_COPY_AND_ASSIGN(Counter); + TypeMap::type counter_; +}; + +/** + * @brief Represents a debug argument for a trace event. + * @tparam T The data type of the argument (bool, int64_t, double, const char*). + */ +template <typename T> +class DebugArg { + public: + template <typename> + struct always_false : std::false_type {}; + + struct TypeMap { + using type = std::invoke_result_t<decltype([]() { + if constexpr (std::is_same_v<T, bool>) { + return std::type_identity<PerfettoTeHlExtraDebugArgBool>{}; + } else if constexpr (std::is_same_v<T, int64_t>) { + return std::type_identity<PerfettoTeHlExtraDebugArgInt64>{}; + } else if constexpr (std::is_same_v<T, double>) { + return std::type_identity<PerfettoTeHlExtraDebugArgDouble>{}; + } else if constexpr (std::is_same_v<T, const char*>) { + return std::type_identity<PerfettoTeHlExtraDebugArgString>{}; + } else { + return std::type_identity<void>{}; + } + })>::type; + + static constexpr int enum_value = []() { + if constexpr (std::is_same_v<T, bool>) { + return PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_BOOL; + } else if constexpr (std::is_same_v<T, int64_t>) { + return PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_INT64; + } else if constexpr (std::is_same_v<T, double>) { + return PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_DOUBLE; + } else if constexpr (std::is_same_v<T, const char*>) { + return PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_STRING; + } else { + static_assert(always_false<T>::value, "Unsupported type"); + return 0; // Never reached, just to satisfy return type + } + }(); + }; + + DebugArg(const std::string& name) : name_(name) { + static_assert(!std::is_same_v<typename TypeMap::type, void>, + "Unsupported type for DebugArg"); + + typename TypeMap::type arg; + arg.header = {TypeMap::enum_value}; + arg.name = name_.c_str(); + arg_ = std::move(arg); + } + + ~DebugArg() { + free_string_value(); + } + + void set_value(T value) { + if constexpr (std::is_same_v<T, const char*>) { + free_string_value(); + arg_.value = value; + } else if constexpr (std::is_same_v<T, int64_t>) { + arg_.value = value; + } else if constexpr (std::is_same_v<T, bool>) { + arg_.value = value; + } else if constexpr (std::is_same_v<T, double>) { + arg_.value = value; + } + } + + static void delete_arg(DebugArg* arg) { + delete arg; + } + + const TypeMap::type* get() const { + return &arg_; + } + + private: + DISALLOW_COPY_AND_ASSIGN(DebugArg); + TypeMap::type arg_; + const std::string name_; + + constexpr void free_string_value() { + if constexpr (std::is_same_v<typename TypeMap::type, + PerfettoTeHlExtraDebugArgString>) { + if (arg_.value) { + free((void*)arg_.value); + arg_.value = nullptr; + } + } + } +}; + +template <typename T> +class ProtoField { + public: + template <typename> + struct always_false : std::false_type {}; + + struct TypeMap { + using type = std::invoke_result_t<decltype([]() { + if constexpr (std::is_same_v<T, int64_t>) { + return std::type_identity<PerfettoTeHlProtoFieldVarInt>{}; + } else if constexpr (std::is_same_v<T, double>) { + return std::type_identity<PerfettoTeHlProtoFieldDouble>{}; + } else if constexpr (std::is_same_v<T, const char*>) { + return std::type_identity<PerfettoTeHlProtoFieldCstr>{}; + } else { + return std::type_identity<void>{}; + } + })>::type; + + static constexpr PerfettoTeHlProtoFieldType enum_value = []() { + if constexpr (std::is_same_v<T, int64_t>) { + return PERFETTO_TE_HL_PROTO_TYPE_VARINT; + } else if constexpr (std::is_same_v<T, double>) { + return PERFETTO_TE_HL_PROTO_TYPE_DOUBLE; + } else if constexpr (std::is_same_v<T, const char*>) { + return PERFETTO_TE_HL_PROTO_TYPE_CSTR; + } else { + static_assert(always_false<T>::value, "Unsupported type"); + return 0; // Never reached, just to satisfy return type + } + }(); + }; + + ProtoField() { + static_assert(!std::is_same_v<typename TypeMap::type, void>, + "Unsupported type for ProtoField"); + + typename TypeMap::type arg; + arg.header.type = TypeMap::enum_value; + arg_ = std::move(arg); + } + + ~ProtoField() { + free_string_value(); + } + + void set_value(uint32_t id, T value) { + if constexpr (std::is_same_v<T, int64_t>) { + arg_.header.id = id; + arg_.value = value; + } else if constexpr (std::is_same_v<T, double>) { + arg_.header.id = id; + arg_.value = value; + } else if constexpr (std::is_same_v<T, const char*>) { + free_string_value(); + arg_.header.id = id; + arg_.str = value; + } + } + + static void delete_field(ProtoField* field) { + delete field; + } + + const TypeMap::type* get() const { + return &arg_; + } + + private: + DISALLOW_COPY_AND_ASSIGN(ProtoField); + TypeMap::type arg_; + + constexpr void free_string_value() { + if constexpr (std::is_same_v<typename TypeMap::type, + PerfettoTeHlProtoFieldCstr>) { + if (arg_.str) { + free((void*)arg_.str); + arg_.str = nullptr; + } + } + } +}; + +class ProtoFieldNested { + public: + ProtoFieldNested(); + + void add_field(PerfettoTeHlProtoField* field); + void set_id(uint32_t id); + static void delete_field(ProtoFieldNested* field); + + const PerfettoTeHlProtoFieldNested* get() const; + + private: + DISALLOW_COPY_AND_ASSIGN(ProtoFieldNested); + PerfettoTeHlProtoFieldNested field_; + // These PerfettoTeHlProtoField pointers are really pointers to all the other + // types of protos: PerfettoTeHlProtoFieldVarInt, PerfettoTeHlProtoFieldVarInt, + // PerfettoTeHlProtoFieldVarInt, PerfettoTeHlProtoFieldNested. Those objects are + // individually managed by Java. + std::vector<PerfettoTeHlProtoField*> fields_; +}; + +class Proto { + public: + Proto(); + + void add_field(PerfettoTeHlProtoField* field); + void clear_fields(); + static void delete_proto(Proto* proto); + + const PerfettoTeHlExtraProtoFields* get() const; + + private: + DISALLOW_COPY_AND_ASSIGN(Proto); + PerfettoTeHlExtraProtoFields proto_; + // These PerfettoTeHlProtoField pointers are really pointers to all the other + // types of protos: PerfettoTeHlProtoFieldVarInt, PerfettoTeHlProtoFieldVarInt, + // PerfettoTeHlProtoFieldVarInt, PerfettoTeHlProtoFieldNested. Those objects are + // individually managed by Java. + std::vector<PerfettoTeHlProtoField*> fields_; +}; + +/** + * @brief Activates a trigger. + * @param name The name of the trigger. + * @param ttl_ms The time-to-live of the trigger in milliseconds. + */ +void activate_trigger(const char* name, uint32_t ttl_ms); +} // namespace tracing_perfetto diff --git a/libs/tracing_perfetto/tests/Android.bp b/libs/tracing_perfetto/tests/Android.bp index d203467783..0dab517b7f 100644 --- a/libs/tracing_perfetto/tests/Android.bp +++ b/libs/tracing_perfetto/tests/Android.bp @@ -21,12 +21,44 @@ package { default_applicable_licenses: ["frameworks_native_license"], } +cc_library_static { + name: "libtracing_perfetto_test_utils", + export_include_dirs: [ + "include", + ], + static_libs: [ + "libflagtest", + "libgmock", + "perfetto_trace_protos", + ], + cflags: [ + "-Wall", + "-Werror", + "-Wno-enum-compare", + "-Wno-unused-function", + ], + + srcs: [ + "utils.cpp", + ], + + shared_libs: [ + "libperfetto_c", + "liblog", + "libprotobuf-cpp-lite", + ], + export_shared_lib_headers: [ + "libperfetto_c", + ], +} + cc_test { name: "libtracing_perfetto_tests", static_libs: [ "libflagtest", "libgmock", "perfetto_trace_protos", + "libtracing_perfetto_test_utils", ], cflags: [ "-Wall", @@ -42,7 +74,6 @@ cc_test { ], srcs: [ "tracing_perfetto_test.cpp", - "utils.cpp", ], test_suites: ["device-tests"], } diff --git a/libs/tracing_perfetto/tests/include/utils.h b/libs/tracing_perfetto/tests/include/utils.h new file mode 100644 index 0000000000..b2630e1829 --- /dev/null +++ b/libs/tracing_perfetto/tests/include/utils.h @@ -0,0 +1,124 @@ +/* + * 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. + */ + +// Copied from //external/perfetto/src/shared_lib/test/utils.h + +#ifndef UTILS_H +#define UTILS_H + +#include <cassert> +#include <condition_variable> +#include <cstdint> +#include <functional> +#include <iterator> +#include <memory> +#include <mutex> +#include <ostream> +#include <string> +#include <vector> + +#include "perfetto/public/abi/pb_decoder_abi.h" +#include "perfetto/public/pb_utils.h" +#include "perfetto/public/tracing_session.h" + +// Pretty printer for gtest +void PrintTo(const PerfettoPbDecoderField& field, std::ostream*); + +namespace perfetto { +namespace shlib { +namespace test_utils { + +class WaitableEvent { + public: + WaitableEvent() = default; + void Notify() { + std::unique_lock<std::mutex> lock(m_); + notified_ = true; + cv_.notify_one(); + } + bool WaitForNotification() { + std::unique_lock<std::mutex> lock(m_); + cv_.wait(lock, [this] { return notified_; }); + return notified_; + } + bool IsNotified() { + std::unique_lock<std::mutex> lock(m_); + return notified_; + } + + private: + std::mutex m_; + std::condition_variable cv_; + bool notified_ = false; +}; + +class TracingSession { + public: + class Builder { + public: + Builder() = default; + Builder& add_enabled_category(std::string category) { + enabled_categories_.push_back(std::move(category)); + return *this; + } + Builder& add_disabled_category(std::string category) { + disabled_categories_.push_back(std::move(category)); + return *this; + } + Builder& add_atrace_category(std::string category) { + atrace_categories_.push_back(std::move(category)); + return *this; + } + Builder& add_atrace_category_prefer_sdk(std::string category) { + atrace_categories_prefer_sdk_.push_back(std::move(category)); + return *this; + } + TracingSession Build(); + + private: + std::vector<std::string> enabled_categories_; + std::vector<std::string> disabled_categories_; + std::vector<std::string> atrace_categories_; + std::vector<std::string> atrace_categories_prefer_sdk_; + }; + + static TracingSession Adopt(struct PerfettoTracingSessionImpl*); + static TracingSession FromBytes(void *buf, size_t len); + + TracingSession(TracingSession&&) noexcept; + + ~TracingSession(); + + struct PerfettoTracingSessionImpl* session() const { + return session_; + } + + bool FlushBlocking(uint32_t timeout_ms); + void WaitForStopped(); + void StopBlocking(); + std::vector<uint8_t> ReadBlocking(); + + private: + TracingSession() = default; + struct PerfettoTracingSessionImpl* session_; + std::unique_ptr<WaitableEvent> stopped_; +}; + +} // namespace test_utils +} // namespace shlib +} // namespace perfetto + +#endif // UTILS_H diff --git a/libs/tracing_perfetto/tests/tracing_perfetto_test.cpp b/libs/tracing_perfetto/tests/tracing_perfetto_test.cpp index e9fee2e6cf..b21a090677 100644 --- a/libs/tracing_perfetto/tests/tracing_perfetto_test.cpp +++ b/libs/tracing_perfetto/tests/tracing_perfetto_test.cpp @@ -22,6 +22,7 @@ #include <unistd.h> #include "gtest/gtest.h" + #include "perfetto/public/abi/data_source_abi.h" #include "perfetto/public/abi/heap_buffer.h" #include "perfetto/public/abi/pb_decoder_abi.h" diff --git a/libs/tracing_perfetto/tests/utils.cpp b/libs/tracing_perfetto/tests/utils.cpp index 8c4d4a8925..af61bc2192 100644 --- a/libs/tracing_perfetto/tests/utils.cpp +++ b/libs/tracing_perfetto/tests/utils.cpp @@ -34,36 +34,17 @@ namespace perfetto { namespace shlib { namespace test_utils { -namespace { - -std::string ToHexChars(uint8_t val) { - std::string ret; - uint8_t high_nibble = (val & 0xF0) >> 4; - uint8_t low_nibble = (val & 0xF); - static const char hex_chars[] = "0123456789ABCDEF"; - ret.push_back(hex_chars[high_nibble]); - ret.push_back(hex_chars[low_nibble]); - return ret; -} - -} // namespace - TracingSession TracingSession::Builder::Build() { perfetto::protos::TraceConfig trace_config; trace_config.add_buffers()->set_size_kb(1024); - auto* track_event_ds_config = trace_config.add_data_sources()->mutable_config(); - auto* ftrace_ds_config = trace_config.add_data_sources()->mutable_config(); - - track_event_ds_config->set_name("track_event"); - track_event_ds_config->set_target_buffer(0); - - ftrace_ds_config->set_name("linux.ftrace"); - ftrace_ds_config->set_target_buffer(0); - { - auto* ftrace_config = ftrace_ds_config->mutable_ftrace_config(); if (!atrace_categories_.empty()) { + auto* ftrace_ds_config = trace_config.add_data_sources()->mutable_config(); + ftrace_ds_config->set_name("linux.ftrace"); + ftrace_ds_config->set_target_buffer(0); + + auto* ftrace_config = ftrace_ds_config->mutable_ftrace_config(); ftrace_config->add_ftrace_events("ftrace/print"); for (const std::string& cat : atrace_categories_) { ftrace_config->add_atrace_categories(cat); @@ -76,8 +57,14 @@ TracingSession TracingSession::Builder::Build() { } { - auto* track_event_config = track_event_ds_config->mutable_track_event_config(); if (!enabled_categories_.empty() || !disabled_categories_.empty()) { + auto* track_event_ds_config = trace_config.add_data_sources()->mutable_config(); + + track_event_ds_config->set_name("track_event"); + track_event_ds_config->set_target_buffer(0); + + auto* track_event_config = track_event_ds_config->mutable_track_event_config(); + for (const std::string& cat : enabled_categories_) { track_event_config->add_enabled_categories(cat); } @@ -88,13 +75,17 @@ TracingSession TracingSession::Builder::Build() { } } - struct PerfettoTracingSessionImpl* ts = - PerfettoTracingSessionCreate(PERFETTO_BACKEND_SYSTEM); - std::string trace_config_string; trace_config.SerializeToString(&trace_config_string); - PerfettoTracingSessionSetup(ts, trace_config_string.data(), trace_config_string.length()); + return TracingSession::FromBytes(trace_config_string.data(), trace_config_string.length()); +} + +TracingSession TracingSession::FromBytes(void *buf, size_t len) { + struct PerfettoTracingSessionImpl* ts = + PerfettoTracingSessionCreate(PERFETTO_BACKEND_SYSTEM); + + PerfettoTracingSessionSetup(ts, buf, len); // Fails to start here PerfettoTracingSessionStartBlocking(ts); @@ -177,39 +168,3 @@ std::vector<uint8_t> TracingSession::ReadBlocking() { } // namespace test_utils } // namespace shlib } // namespace perfetto - -void PrintTo(const PerfettoPbDecoderField& field, std::ostream* pos) { - std::ostream& os = *pos; - PerfettoPbDecoderStatus status = - static_cast<PerfettoPbDecoderStatus>(field.status); - switch (status) { - case PERFETTO_PB_DECODER_ERROR: - os << "MALFORMED PROTOBUF"; - break; - case PERFETTO_PB_DECODER_DONE: - os << "DECODER DONE"; - break; - case PERFETTO_PB_DECODER_OK: - switch (field.wire_type) { - case PERFETTO_PB_WIRE_TYPE_DELIMITED: - os << "\""; - for (size_t i = 0; i < field.value.delimited.len; i++) { - os << perfetto::shlib::test_utils::ToHexChars( - field.value.delimited.start[i]) - << " "; - } - os << "\""; - break; - case PERFETTO_PB_WIRE_TYPE_VARINT: - os << "varint: " << field.value.integer64; - break; - case PERFETTO_PB_WIRE_TYPE_FIXED32: - os << "fixed32: " << field.value.integer32; - break; - case PERFETTO_PB_WIRE_TYPE_FIXED64: - os << "fixed64: " << field.value.integer64; - break; - } - break; - } -} diff --git a/libs/tracing_perfetto/tests/utils.h b/libs/tracing_perfetto/tests/utils.h deleted file mode 100644 index 8edb4143ee..0000000000 --- a/libs/tracing_perfetto/tests/utils.h +++ /dev/null @@ -1,457 +0,0 @@ -/* - * 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. - */ - -// Copied from //external/perfetto/src/shared_lib/test/utils.h - -#ifndef UTILS_H -#define UTILS_H - -#include <cassert> -#include <condition_variable> -#include <cstdint> -#include <functional> -#include <iterator> -#include <memory> -#include <mutex> -#include <ostream> -#include <string> -#include <vector> - -#include "gmock/gmock-matchers.h" -#include "gmock/gmock-more-matchers.h" -#include "gtest/gtest-matchers.h" -#include "gtest/gtest.h" -#include "perfetto/public/abi/pb_decoder_abi.h" -#include "perfetto/public/pb_utils.h" -#include "perfetto/public/tracing_session.h" - -// Pretty printer for gtest -void PrintTo(const PerfettoPbDecoderField& field, std::ostream*); - -namespace perfetto { -namespace shlib { -namespace test_utils { - -class WaitableEvent { - public: - WaitableEvent() = default; - void Notify() { - std::unique_lock<std::mutex> lock(m_); - notified_ = true; - cv_.notify_one(); - } - bool WaitForNotification() { - std::unique_lock<std::mutex> lock(m_); - cv_.wait(lock, [this] { return notified_; }); - return notified_; - } - bool IsNotified() { - std::unique_lock<std::mutex> lock(m_); - return notified_; - } - - private: - std::mutex m_; - std::condition_variable cv_; - bool notified_ = false; -}; - -class TracingSession { - public: - class Builder { - public: - Builder() = default; - Builder& add_enabled_category(std::string category) { - enabled_categories_.push_back(std::move(category)); - return *this; - } - Builder& add_disabled_category(std::string category) { - disabled_categories_.push_back(std::move(category)); - return *this; - } - Builder& add_atrace_category(std::string category) { - atrace_categories_.push_back(std::move(category)); - return *this; - } - Builder& add_atrace_category_prefer_sdk(std::string category) { - atrace_categories_prefer_sdk_.push_back(std::move(category)); - return *this; - } - TracingSession Build(); - - private: - std::vector<std::string> enabled_categories_; - std::vector<std::string> disabled_categories_; - std::vector<std::string> atrace_categories_; - std::vector<std::string> atrace_categories_prefer_sdk_; - }; - - static TracingSession Adopt(struct PerfettoTracingSessionImpl*); - - TracingSession(TracingSession&&) noexcept; - - ~TracingSession(); - - struct PerfettoTracingSessionImpl* session() const { - return session_; - } - - bool FlushBlocking(uint32_t timeout_ms); - void WaitForStopped(); - void StopBlocking(); - std::vector<uint8_t> ReadBlocking(); - - private: - TracingSession() = default; - struct PerfettoTracingSessionImpl* session_; - std::unique_ptr<WaitableEvent> stopped_; -}; - -template <typename FieldSkipper> -class FieldViewBase { - public: - class Iterator { - public: - using iterator_category = std::input_iterator_tag; - using value_type = const PerfettoPbDecoderField; - using pointer = value_type; - using reference = value_type; - reference operator*() const { - struct PerfettoPbDecoder decoder; - decoder.read_ptr = read_ptr_; - decoder.end_ptr = end_ptr_; - struct PerfettoPbDecoderField field; - do { - field = PerfettoPbDecoderParseField(&decoder); - } while (field.status == PERFETTO_PB_DECODER_OK && - skipper_.ShouldSkip(field)); - return field; - } - Iterator& operator++() { - struct PerfettoPbDecoder decoder; - decoder.read_ptr = read_ptr_; - decoder.end_ptr = end_ptr_; - PerfettoPbDecoderSkipField(&decoder); - read_ptr_ = decoder.read_ptr; - AdvanceToFirstInterestingField(); - return *this; - } - Iterator operator++(int) { - Iterator tmp = *this; - ++(*this); - return tmp; - } - - friend bool operator==(const Iterator& a, const Iterator& b) { - return a.read_ptr_ == b.read_ptr_; - } - friend bool operator!=(const Iterator& a, const Iterator& b) { - return a.read_ptr_ != b.read_ptr_; - } - - private: - Iterator(const uint8_t* read_ptr, const uint8_t* end_ptr, - const FieldSkipper& skipper) - : read_ptr_(read_ptr), end_ptr_(end_ptr), skipper_(skipper) { - AdvanceToFirstInterestingField(); - } - void AdvanceToFirstInterestingField() { - struct PerfettoPbDecoder decoder; - decoder.read_ptr = read_ptr_; - decoder.end_ptr = end_ptr_; - struct PerfettoPbDecoderField field; - const uint8_t* prev_read_ptr; - do { - prev_read_ptr = decoder.read_ptr; - field = PerfettoPbDecoderParseField(&decoder); - } while (field.status == PERFETTO_PB_DECODER_OK && - skipper_.ShouldSkip(field)); - if (field.status == PERFETTO_PB_DECODER_OK) { - read_ptr_ = prev_read_ptr; - } else { - read_ptr_ = decoder.read_ptr; - } - } - friend class FieldViewBase<FieldSkipper>; - const uint8_t* read_ptr_; - const uint8_t* end_ptr_; - const FieldSkipper& skipper_; - }; - using value_type = const PerfettoPbDecoderField; - using const_iterator = Iterator; - template <typename... Args> - explicit FieldViewBase(const uint8_t* begin, const uint8_t* end, Args... args) - : begin_(begin), end_(end), s_(args...) { - } - template <typename... Args> - explicit FieldViewBase(const std::vector<uint8_t>& data, Args... args) - : FieldViewBase(data.data(), data.data() + data.size(), args...) { - } - template <typename... Args> - explicit FieldViewBase(const struct PerfettoPbDecoderField& field, - Args... args) - : s_(args...) { - if (field.wire_type != PERFETTO_PB_WIRE_TYPE_DELIMITED) { - abort(); - } - begin_ = field.value.delimited.start; - end_ = begin_ + field.value.delimited.len; - } - Iterator begin() const { - return Iterator(begin_, end_, s_); - } - Iterator end() const { - return Iterator(end_, end_, s_); - } - PerfettoPbDecoderField front() const { - return *begin(); - } - - size_t size() const { - size_t count = 0; - for (auto field : *this) { - (void)field; - count++; - } - return count; - } - - bool ok() const { - for (auto field : *this) { - if (field.status != PERFETTO_PB_DECODER_OK) { - return false; - } - } - return true; - } - - private: - const uint8_t* begin_; - const uint8_t* end_; - FieldSkipper s_; -}; - -// Pretty printer for gtest -template <typename FieldSkipper> -void PrintTo(const FieldViewBase<FieldSkipper>& field_view, std::ostream* pos) { - std::ostream& os = *pos; - os << "{"; - for (PerfettoPbDecoderField f : field_view) { - PrintTo(f, pos); - os << ", "; - } - os << "}"; -} - -class IdFieldSkipper { - public: - explicit IdFieldSkipper(uint32_t id) : id_(id) { - } - explicit IdFieldSkipper(int32_t id) : id_(static_cast<uint32_t>(id)) { - } - bool ShouldSkip(const struct PerfettoPbDecoderField& field) const { - return field.id != id_; - } - - private: - uint32_t id_; -}; - -class NoFieldSkipper { - public: - NoFieldSkipper() = default; - bool ShouldSkip(const struct PerfettoPbDecoderField&) const { - return false; - } -}; - -// View over all the fields of a contiguous serialized protobuf message. -// -// Examples: -// -// for (struct PerfettoPbDecoderField field : FieldView(msg_begin, msg_end)) { -// //... -// } -// FieldView fields2(/*PerfettoPbDecoderField*/ nested_field); -// FieldView fields3(/*std::vector<uint8_t>*/ data); -// size_t num = fields1.size(); // The number of fields. -// bool ok = fields1.ok(); // Checks that the message is not malformed. -using FieldView = FieldViewBase<NoFieldSkipper>; - -// Like `FieldView`, but only considers fields with a specific id. -// -// Examples: -// -// IdFieldView fields(msg_begin, msg_end, id) -using IdFieldView = FieldViewBase<IdFieldSkipper>; - -// Matches a PerfettoPbDecoderField with the specified id. Accepts another -// matcher to match the contents of the field. -// -// Example: -// PerfettoPbDecoderField field = ... -// EXPECT_THAT(field, PbField(900, VarIntField(5))); -template <typename M> -auto PbField(int32_t id, M m) { - return testing::AllOf( - testing::Field(&PerfettoPbDecoderField::status, PERFETTO_PB_DECODER_OK), - testing::Field(&PerfettoPbDecoderField::id, id), m); -} - -// Matches a PerfettoPbDecoderField submessage field. Accepts a container -// matcher for the subfields. -// -// Example: -// PerfettoPbDecoderField field = ... -// EXPECT_THAT(field, MsgField(ElementsAre(...))); -template <typename M> -auto MsgField(M m) { - auto f = [](const PerfettoPbDecoderField& field) { return FieldView(field); }; - return testing::AllOf( - testing::Field(&PerfettoPbDecoderField::status, PERFETTO_PB_DECODER_OK), - testing::Field(&PerfettoPbDecoderField::wire_type, - PERFETTO_PB_WIRE_TYPE_DELIMITED), - testing::ResultOf(f, m)); -} - -// Matches a PerfettoPbDecoderField length delimited field. Accepts a string -// matcher. -// -// Example: -// PerfettoPbDecoderField field = ... -// EXPECT_THAT(field, StringField("string")); -template <typename M> -auto StringField(M m) { - auto f = [](const PerfettoPbDecoderField& field) { - return std::string( - reinterpret_cast<const char*>(field.value.delimited.start), - field.value.delimited.len); - }; - return testing::AllOf( - testing::Field(&PerfettoPbDecoderField::status, PERFETTO_PB_DECODER_OK), - testing::Field(&PerfettoPbDecoderField::wire_type, - PERFETTO_PB_WIRE_TYPE_DELIMITED), - testing::ResultOf(f, m)); -} - -// Matches a PerfettoPbDecoderField VarInt field. Accepts an integer matcher -// -// Example: -// PerfettoPbDecoderField field = ... -// EXPECT_THAT(field, VarIntField(1))); -template <typename M> -auto VarIntField(M m) { - auto f = [](const PerfettoPbDecoderField& field) { - return field.value.integer64; - }; - return testing::AllOf( - testing::Field(&PerfettoPbDecoderField::status, PERFETTO_PB_DECODER_OK), - testing::Field(&PerfettoPbDecoderField::wire_type, - PERFETTO_PB_WIRE_TYPE_VARINT), - testing::ResultOf(f, m)); -} - -// Matches a PerfettoPbDecoderField fixed64 field. Accepts an integer matcher -// -// Example: -// PerfettoPbDecoderField field = ... -// EXPECT_THAT(field, Fixed64Field(1))); -template <typename M> -auto Fixed64Field(M m) { - auto f = [](const PerfettoPbDecoderField& field) { - return field.value.integer64; - }; - return testing::AllOf( - testing::Field(&PerfettoPbDecoderField::status, PERFETTO_PB_DECODER_OK), - testing::Field(&PerfettoPbDecoderField::wire_type, - PERFETTO_PB_WIRE_TYPE_FIXED64), - testing::ResultOf(f, m)); -} - -// Matches a PerfettoPbDecoderField fixed32 field. Accepts an integer matcher -// -// Example: -// PerfettoPbDecoderField field = ... -// EXPECT_THAT(field, Fixed32Field(1))); -template <typename M> -auto Fixed32Field(M m) { - auto f = [](const PerfettoPbDecoderField& field) { - return field.value.integer32; - }; - return testing::AllOf( - testing::Field(&PerfettoPbDecoderField::status, PERFETTO_PB_DECODER_OK), - testing::Field(&PerfettoPbDecoderField::wire_type, - PERFETTO_PB_WIRE_TYPE_FIXED32), - testing::ResultOf(f, m)); -} - -// Matches a PerfettoPbDecoderField double field. Accepts a double matcher -// -// Example: -// PerfettoPbDecoderField field = ... -// EXPECT_THAT(field, DoubleField(1.0))); -template <typename M> -auto DoubleField(M m) { - auto f = [](const PerfettoPbDecoderField& field) { - return field.value.double_val; - }; - return testing::AllOf( - testing::Field(&PerfettoPbDecoderField::status, PERFETTO_PB_DECODER_OK), - testing::Field(&PerfettoPbDecoderField::wire_type, - PERFETTO_PB_WIRE_TYPE_FIXED64), - testing::ResultOf(f, m)); -} - -// Matches a PerfettoPbDecoderField float field. Accepts a float matcher -// -// Example: -// PerfettoPbDecoderField field = ... -// EXPECT_THAT(field, FloatField(1.0))); -template <typename M> -auto FloatField(M m) { - auto f = [](const PerfettoPbDecoderField& field) { - return field.value.float_val; - }; - return testing::AllOf( - testing::Field(&PerfettoPbDecoderField::status, PERFETTO_PB_DECODER_OK), - testing::Field(&PerfettoPbDecoderField::wire_type, - PERFETTO_PB_WIRE_TYPE_FIXED32), - testing::ResultOf(f, m)); -} - -// Matches a PerfettoPbDecoderField submessage field. Accepts a container -// matcher for the subfields. -// -// Example: -// PerfettoPbDecoderField field = ... -// EXPECT_THAT(field, AllFieldsWithId(900, ElementsAre(...))); -template <typename M> -auto AllFieldsWithId(int32_t id, M m) { - auto f = [id](const PerfettoPbDecoderField& field) { - return IdFieldView(field, id); - }; - return testing::AllOf( - testing::Field(&PerfettoPbDecoderField::status, PERFETTO_PB_DECODER_OK), - testing::Field(&PerfettoPbDecoderField::wire_type, - PERFETTO_PB_WIRE_TYPE_DELIMITED), - testing::ResultOf(f, m)); -} - -} // namespace test_utils -} // namespace shlib -} // namespace perfetto - -#endif // UTILS_H diff --git a/libs/tracing_perfetto/tracing_perfetto.cpp b/libs/tracing_perfetto/tracing_perfetto.cpp index c35e078b02..4b7021393f 100644 --- a/libs/tracing_perfetto/tracing_perfetto.cpp +++ b/libs/tracing_perfetto/tracing_perfetto.cpp @@ -17,6 +17,7 @@ #include "tracing_perfetto.h" #include <cutils/trace.h> + #include <cstdarg> #include "perfetto/public/te_category_macros.h" @@ -43,8 +44,10 @@ void traceBegin(uint64_t category, const char* name) { void traceFormatBegin(uint64_t category, const char* fmt, ...) { struct PerfettoTeCategory* perfettoTeCategory = internal::toPerfettoCategory(category); - const bool preferAtrace = internal::shouldPreferAtrace(perfettoTeCategory, category); - const bool preferPerfetto = internal::isPerfettoCategoryEnabled(perfettoTeCategory); + const bool preferAtrace = + internal::shouldPreferAtrace(perfettoTeCategory, category); + const bool preferPerfetto = + internal::isPerfettoCategoryEnabled(perfettoTeCategory); if (CC_LIKELY(!(preferAtrace || preferPerfetto))) { return; } @@ -57,7 +60,6 @@ void traceFormatBegin(uint64_t category, const char* fmt, ...) { vsnprintf(buf, BUFFER_SIZE, fmt, ap); va_end(ap); - if (preferAtrace) { atrace_begin(category, buf); } else if (preferPerfetto) { @@ -99,26 +101,28 @@ void traceAsyncEnd(uint64_t category, const char* name, int32_t cookie) { } void traceAsyncBeginForTrack(uint64_t category, const char* name, - const char* trackName, int32_t cookie) { + const char* trackName, int32_t cookie) { struct PerfettoTeCategory* perfettoTeCategory = internal::toPerfettoCategory(category); if (internal::shouldPreferAtrace(perfettoTeCategory, category)) { atrace_async_for_track_begin(category, trackName, name, cookie); } else if (internal::isPerfettoCategoryEnabled(perfettoTeCategory)) { - internal::perfettoTraceAsyncBeginForTrack(*perfettoTeCategory, name, trackName, cookie); + internal::perfettoTraceAsyncBeginForTrack(*perfettoTeCategory, name, + trackName, cookie); } } void traceAsyncEndForTrack(uint64_t category, const char* trackName, - int32_t cookie) { + int32_t cookie) { struct PerfettoTeCategory* perfettoTeCategory = internal::toPerfettoCategory(category); if (internal::shouldPreferAtrace(perfettoTeCategory, category)) { atrace_async_for_track_end(category, trackName, cookie); } else if (internal::isPerfettoCategoryEnabled(perfettoTeCategory)) { - internal::perfettoTraceAsyncEndForTrack(*perfettoTeCategory, trackName, cookie); + internal::perfettoTraceAsyncEndForTrack(*perfettoTeCategory, trackName, + cookie); } } @@ -136,8 +140,10 @@ void traceInstant(uint64_t category, const char* name) { void traceFormatInstant(uint64_t category, const char* fmt, ...) { struct PerfettoTeCategory* perfettoTeCategory = internal::toPerfettoCategory(category); - const bool preferAtrace = internal::shouldPreferAtrace(perfettoTeCategory, category); - const bool preferPerfetto = internal::isPerfettoCategoryEnabled(perfettoTeCategory); + const bool preferAtrace = + internal::shouldPreferAtrace(perfettoTeCategory, category); + const bool preferPerfetto = + internal::isPerfettoCategoryEnabled(perfettoTeCategory); if (CC_LIKELY(!(preferAtrace || preferPerfetto))) { return; } @@ -158,7 +164,7 @@ void traceFormatInstant(uint64_t category, const char* fmt, ...) { } void traceInstantForTrack(uint64_t category, const char* trackName, - const char* name) { + const char* name) { struct PerfettoTeCategory* perfettoTeCategory = internal::toPerfettoCategory(category); @@ -181,20 +187,21 @@ void traceCounter(uint64_t category, const char* name, int64_t value) { } void traceCounter32(uint64_t category, const char* name, int32_t value) { - struct PerfettoTeCategory* perfettoTeCategory = internal::toPerfettoCategory(category); + struct PerfettoTeCategory* perfettoTeCategory = + internal::toPerfettoCategory(category); if (internal::shouldPreferAtrace(perfettoTeCategory, category)) { atrace_int(category, name, value); } else if (internal::isPerfettoCategoryEnabled(perfettoTeCategory)) { internal::perfettoTraceCounter(*perfettoTeCategory, name, - static_cast<int64_t>(value)); + static_cast<int64_t>(value)); } } bool isTagEnabled(uint64_t category) { struct PerfettoTeCategory* perfettoTeCategory = internal::toPerfettoCategory(category); - return internal::isPerfettoCategoryEnabled(perfettoTeCategory) - || atrace_is_tag_enabled(category); + return internal::isPerfettoCategoryEnabled(perfettoTeCategory) || + atrace_is_tag_enabled(category); } } // namespace tracing_perfetto diff --git a/libs/tracing_perfetto/tracing_sdk.cpp b/libs/tracing_perfetto/tracing_sdk.cpp new file mode 100644 index 0000000000..02e8d10aa4 --- /dev/null +++ b/libs/tracing_perfetto/tracing_sdk.cpp @@ -0,0 +1,261 @@ +/* + * 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. + */ + +#include "tracing_sdk.h" + +#include <android-base/logging.h> +#include <cutils/trace.h> + +#include <cstdarg> +#include <cstdlib> + +#include "perfetto/public/abi/producer_abi.h" +#include "perfetto/public/te_category_macros.h" +#include "perfetto/public/te_macros.h" +#include "perfetto/public/track_event.h" +#include "tracing_perfetto.h" + +namespace tracing_perfetto { +void trace_event(int type, const PerfettoTeCategory* perfettoTeCategory, + const char* name, tracing_perfetto::Extra* extra) { + bool enabled = PERFETTO_UNLIKELY(PERFETTO_ATOMIC_LOAD_EXPLICIT( + perfettoTeCategory->enabled, PERFETTO_MEMORY_ORDER_RELAXED)); + if (enabled) { + extra->push_extra(nullptr); + PerfettoTeHlEmitImpl(perfettoTeCategory->impl, type, + type == PERFETTO_TE_TYPE_COUNTER ? nullptr : name, + extra->get()); + extra->pop_extra(); + } +} + +uint64_t get_process_track_uuid() { + return PerfettoTeProcessTrackUuid(); +} + +uint64_t get_thread_track_uuid(pid_t tid) { + // Cating a signed pid_t to unsigned + return PerfettoTeProcessTrackUuid() ^ PERFETTO_STATIC_CAST(uint64_t, tid); +} + +Extra::Extra() { +} + +void Extra::push_extra(PerfettoTeHlExtra* ptr) { + extras_.push_back(ptr); +} + +void Extra::pop_extra() { + extras_.pop_back(); +} + +void Extra::clear_extras() { + extras_.clear(); +} + +void Extra::delete_extra(Extra* ptr) { + delete ptr; +} + +PerfettoTeHlExtra* const* Extra::get() const { + return extras_.data(); +} + +Category::Category(const std::string& name, const std::string& tag, + const std::string& severity) + : category_({.enabled = &perfetto_atomic_false}), + name_(name), + tag_(tag), + severity_(severity) { +} + +Category::~Category() { + unregister_category(); +} + +void Category::register_category() { + if (category_.impl) return; + + std::vector<const char*> tags; + if (!tag_.empty()) tags.push_back(tag_.data()); + if (!severity_.empty()) tags.push_back(severity_.data()); + + category_.desc = {name_.c_str(), name_.c_str(), tags.data(), tags.size()}; + + PerfettoTeCategoryRegister(&category_); + PerfettoTePublishCategories(); +} + +void Category::unregister_category() { + if (!category_.impl) return; + + PerfettoTeCategoryUnregister(&category_); + PerfettoTePublishCategories(); +} + +bool Category::is_category_enabled() { + return PERFETTO_UNLIKELY(PERFETTO_ATOMIC_LOAD_EXPLICIT( + (category_).enabled, PERFETTO_MEMORY_ORDER_RELAXED)); +} + +const PerfettoTeCategory* Category::get() const { + return &category_; +} + +void Category::delete_category(Category* ptr) { + delete ptr; +} + +Flow::Flow() : flow_{} { +} + +void Flow::set_process_flow(uint64_t id) { + flow_.header.type = PERFETTO_TE_HL_EXTRA_TYPE_FLOW; + PerfettoTeFlow ret = PerfettoTeProcessScopedFlow(id); + flow_.id = ret.id; +} + +void Flow::set_process_terminating_flow(uint64_t id) { + flow_.header.type = PERFETTO_TE_HL_EXTRA_TYPE_TERMINATING_FLOW; + PerfettoTeFlow ret = PerfettoTeProcessScopedFlow(id); + flow_.id = ret.id; +} + +const PerfettoTeHlExtraFlow* Flow::get() const { + return &flow_; +} + +void Flow::delete_flow(Flow* ptr) { + delete ptr; +} + +NamedTrack::NamedTrack(uint64_t id, uint64_t parent_uuid, + const std::string& name) + : name_(name), + track_{{PERFETTO_TE_HL_EXTRA_TYPE_NAMED_TRACK}, + name_.data(), + id, + parent_uuid} { +} + +const PerfettoTeHlExtraNamedTrack* NamedTrack::get() const { + return &track_; +} + +void NamedTrack::delete_track(NamedTrack* ptr) { + delete ptr; +} + +RegisteredTrack::RegisteredTrack(uint64_t id, uint64_t parent_uuid, + const std::string& name, bool is_counter) + : registered_track_{}, + track_{{PERFETTO_TE_HL_EXTRA_TYPE_REGISTERED_TRACK}, + &(registered_track_.impl)}, + name_(name), + id_(id), + parent_uuid_(parent_uuid), + is_counter_(is_counter) { + register_track(); +} + +RegisteredTrack::~RegisteredTrack() { + unregister_track(); +} + +void RegisteredTrack::register_track() { + if (registered_track_.impl.descriptor) return; + + if (is_counter_) { + PerfettoTeCounterTrackRegister(®istered_track_, name_.data(), + parent_uuid_); + } else { + PerfettoTeNamedTrackRegister(®istered_track_, name_.data(), id_, + parent_uuid_); + } +} + +void RegisteredTrack::unregister_track() { + if (!registered_track_.impl.descriptor) return; + PerfettoTeRegisteredTrackUnregister(®istered_track_); +} + +const PerfettoTeHlExtraRegisteredTrack* RegisteredTrack::get() const { + return &track_; +} + +void RegisteredTrack::delete_track(RegisteredTrack* ptr) { + delete ptr; +} + +Proto::Proto() : proto_({PERFETTO_TE_HL_EXTRA_TYPE_PROTO_FIELDS}, nullptr) { +} + +void Proto::add_field(PerfettoTeHlProtoField* ptr) { + if (!fields_.empty()) { + fields_.pop_back(); + } + + fields_.push_back(ptr); + fields_.push_back(nullptr); + proto_.fields = fields_.data(); +} + +void Proto::clear_fields() { + fields_.clear(); + proto_.fields = nullptr; +} + +void Proto::delete_proto(Proto* ptr) { + delete ptr; +} + +const PerfettoTeHlExtraProtoFields* Proto::get() const { + return &proto_; +} + +ProtoFieldNested::ProtoFieldNested() + : field_({PERFETTO_TE_HL_PROTO_TYPE_NESTED}, nullptr) { +} + +void ProtoFieldNested::add_field(PerfettoTeHlProtoField* ptr) { + if (!fields_.empty()) { + fields_.pop_back(); + } + + fields_.push_back(ptr); + fields_.push_back(nullptr); + field_.fields = fields_.data(); +} + +void ProtoFieldNested::set_id(uint32_t id) { + fields_.clear(); + field_.header.id = id; + field_.fields = nullptr; +} + +void ProtoFieldNested::delete_field(ProtoFieldNested* ptr) { + delete ptr; +} + +const PerfettoTeHlProtoFieldNested* ProtoFieldNested::get() const { + return &field_; +} + +void activate_trigger(const char* name, uint32_t ttl_ms) { + const char* names[] = {name, nullptr}; + PerfettoProducerActivateTriggers(names, ttl_ms); +} +} // namespace tracing_perfetto diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h index 4d6b6c7fd5..404a509247 100644 --- a/services/inputflinger/include/InputReaderBase.h +++ b/services/inputflinger/include/InputReaderBase.h @@ -139,9 +139,17 @@ struct InputReaderConfiguration { // The mouse pointer speed, as a number from -7 (slowest) to 7 (fastest). int32_t mousePointerSpeed; - // Displays on which an acceleration curve shouldn't be applied for pointer movements from mice. + // Displays on which all pointer scaling, including linear scaling based on the + // user's pointer speed setting, should be disabled for mice. This differs from + // disabling acceleration via the 'mousePointerAccelerationEnabled' setting, where + // the pointer speed setting still influences the scaling factor. std::set<ui::LogicalDisplayId> displaysWithMousePointerAccelerationDisabled; + // True if the connected mouse should exhibit pointer acceleration. If false, + // a flat acceleration curve (linear scaling) is used, but the user's pointer + // speed setting still affects the scaling factor. + bool mousePointerAccelerationEnabled; + // Velocity control parameters for touchpad pointer movements on the old touchpad stack (based // on TouchInputMapper). // @@ -275,11 +283,15 @@ struct InputReaderConfiguration { defaultPointerDisplayId(ui::LogicalDisplayId::DEFAULT), mousePointerSpeed(0), displaysWithMousePointerAccelerationDisabled(), + mousePointerAccelerationEnabled(true), pointerVelocityControlParameters(1.0f, 500.0f, 3000.0f, static_cast<float>( android::os::IInputConstants:: DEFAULT_POINTER_ACCELERATION)), - wheelVelocityControlParameters(1.0f, 15.0f, 50.0f, 4.0f), + wheelVelocityControlParameters(1.0f, 15.0f, 50.0f, + static_cast<float>( + android::os::IInputConstants:: + DEFAULT_MOUSE_WHEEL_ACCELERATION)), pointerGesturesEnabled(true), pointerGestureQuietInterval(100 * 1000000LL), // 100 ms pointerGestureDragMinSwitchSpeed(50), // 50 pixels per second diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.cpp b/services/inputflinger/reader/mapper/CursorInputMapper.cpp index b33659cae1..e9f17e796f 100644 --- a/services/inputflinger/reader/mapper/CursorInputMapper.cpp +++ b/services/inputflinger/reader/mapper/CursorInputMapper.cpp @@ -481,15 +481,21 @@ void CursorInputMapper::configureOnChangePointerSpeed(const InputReaderConfigura mPointerVelocityControl.setAccelerationEnabled(false); mWheelXVelocityControl.setParameters(FLAT_VELOCITY_CONTROL_PARAMS); mWheelYVelocityControl.setParameters(FLAT_VELOCITY_CONTROL_PARAMS); - } else { - mPointerVelocityControl.setAccelerationEnabled( - config.displaysWithMousePointerAccelerationDisabled.count( - mDisplayId.value_or(ui::LogicalDisplayId::INVALID)) == 0); - mPointerVelocityControl.setCurve( - createAccelerationCurveForPointerSensitivity(config.mousePointerSpeed)); - mWheelXVelocityControl.setParameters(config.wheelVelocityControlParameters); - mWheelYVelocityControl.setParameters(config.wheelVelocityControlParameters); + return; } + + bool disableAllScaling = config.displaysWithMousePointerAccelerationDisabled.count( + mDisplayId.value_or(ui::LogicalDisplayId::INVALID)) != 0; + + mPointerVelocityControl.setAccelerationEnabled(!disableAllScaling); + + mPointerVelocityControl.setCurve( + config.mousePointerAccelerationEnabled + ? createAccelerationCurveForPointerSensitivity(config.mousePointerSpeed) + : createFlatAccelerationCurve(config.mousePointerSpeed)); + + mWheelXVelocityControl.setParameters(config.wheelVelocityControlParameters); + mWheelYVelocityControl.setParameters(config.wheelVelocityControlParameters); } void CursorInputMapper::configureOnChangeDisplayInfo(const InputReaderConfiguration& config) { diff --git a/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp b/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp index 6bd949a09d..827076a2cf 100644 --- a/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp +++ b/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp @@ -81,7 +81,6 @@ GestureConverter::GestureConverter(InputReaderContext& readerContext, const InputDeviceContext& deviceContext, int32_t deviceId) : mDeviceId(deviceId), mReaderContext(readerContext), - mEnableFlingStop(input_flags::enable_touchpad_fling_stop()), mEnableNoFocusChange(input_flags::enable_touchpad_no_focus_change()), // We can safely assume that ABS_MT_POSITION_X and _Y axes will be available, as EventHub // won't classify a device as a touchpad if they're not present. @@ -406,7 +405,7 @@ std::list<NotifyArgs> GestureConverter::handleFling(nsecs_t when, nsecs_t readTi break; case GESTURES_FLING_TAP_DOWN: if (mCurrentClassification == MotionClassification::NONE) { - if (mEnableFlingStop && mFlingMayBeInProgress) { + if (mFlingMayBeInProgress) { // The user has just touched the pad again after ending a two-finger scroll // motion, which might have started a fling. We want to stop the fling, but // unfortunately there's currently no API for doing so. Instead, send and diff --git a/services/inputflinger/reader/mapper/gestures/GestureConverter.h b/services/inputflinger/reader/mapper/gestures/GestureConverter.h index 8d92ead80b..be76b61ce6 100644 --- a/services/inputflinger/reader/mapper/gestures/GestureConverter.h +++ b/services/inputflinger/reader/mapper/gestures/GestureConverter.h @@ -104,7 +104,6 @@ private: const int32_t mDeviceId; InputReaderContext& mReaderContext; - const bool mEnableFlingStop; const bool mEnableNoFocusChange; bool mEnableSystemGestures{true}; diff --git a/services/inputflinger/tests/CursorInputMapper_test.cpp b/services/inputflinger/tests/CursorInputMapper_test.cpp index d4e8fdfdc5..a31c4e96d7 100644 --- a/services/inputflinger/tests/CursorInputMapper_test.cpp +++ b/services/inputflinger/tests/CursorInputMapper_test.cpp @@ -27,6 +27,7 @@ #include <com_android_input_flags.h> #include <gmock/gmock.h> #include <gtest/gtest.h> +#include <input/AccelerationCurve.h> #include <input/DisplayViewport.h> #include <input/InputEventLabels.h> #include <linux/input-event-codes.h> @@ -1028,6 +1029,34 @@ TEST_F(CursorInputMapperUnitTest, ConfigureDisplayIdNoAssociatedViewport) { WithCoords(0.0f, 0.0f))))); } +TEST_F(CursorInputMapperUnitTest, PointerAccelerationDisabled) { + mReaderConfiguration.mousePointerAccelerationEnabled = false; + mReaderConfiguration.mousePointerSpeed = 3; + mPropertyMap.addProperty("cursor.mode", "pointer"); + createMapper(); + + std::list<NotifyArgs> reconfigureArgs; + + reconfigureArgs += mMapper->reconfigure(ARBITRARY_TIME, mReaderConfiguration, + InputReaderConfiguration::Change::POINTER_SPEED); + + std::vector<AccelerationCurveSegment> curve = + createFlatAccelerationCurve(mReaderConfiguration.mousePointerSpeed); + double baseGain = curve[0].baseGain; + + std::list<NotifyArgs> motionArgs; + motionArgs += process(ARBITRARY_TIME, EV_REL, REL_X, 10); + motionArgs += process(ARBITRARY_TIME, EV_REL, REL_Y, 20); + motionArgs += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + + const float expectedRelX = 10 * baseGain; + const float expectedRelY = 20 * baseGain; + ASSERT_THAT(motionArgs, + ElementsAre(VariantWith<NotifyMotionArgs>( + AllOf(WithMotionAction(HOVER_MOVE), + WithRelativeMotion(expectedRelX, expectedRelY))))); +} + TEST_F(CursorInputMapperUnitTest, ConfigureAccelerationWithAssociatedViewport) { mPropertyMap.addProperty("cursor.mode", "pointer"); DisplayViewport primaryViewport = createPrimaryViewport(ui::Rotation::Rotation0); diff --git a/services/inputflinger/tests/GestureConverter_test.cpp b/services/inputflinger/tests/GestureConverter_test.cpp index fe40a5eb4d..8fa439d633 100644 --- a/services/inputflinger/tests/GestureConverter_test.cpp +++ b/services/inputflinger/tests/GestureConverter_test.cpp @@ -1297,7 +1297,6 @@ TEST_F(GestureConverterTest, FlingTapDown) { TEST_F(GestureConverterTest, FlingTapDownAfterScrollStopsFling) { InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID); - input_flags::enable_touchpad_fling_stop(true); GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID); converter.setDisplayId(ui::LogicalDisplayId::DEFAULT); diff --git a/services/inputflinger/tests/TestEventMatchers.h b/services/inputflinger/tests/TestEventMatchers.h index 7078e49343..7fb8895719 100644 --- a/services/inputflinger/tests/TestEventMatchers.h +++ b/services/inputflinger/tests/TestEventMatchers.h @@ -32,6 +32,17 @@ namespace android { +namespace { + +template <typename T> +static bool valuesMatch(T value1, T value2) { + if constexpr (std::is_floating_point_v<T>) { + return std::abs(value1 - value2) < EPSILON; + } else { + return value1 == value2; + } +} + struct PointF { float x; float y; @@ -42,6 +53,8 @@ inline std::string pointFToString(const PointF& p) { return std::string("(") + std::to_string(p.x) + ", " + std::to_string(p.y) + ")"; } +} // namespace + /// Source class WithSourceMatcher { public: @@ -706,8 +719,8 @@ public: } const PointerCoords& coords = event.pointerCoords[mPointerIndex]; - bool matches = mRelX == coords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X) && - mRelY == coords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y); + bool matches = valuesMatch(mRelX, coords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X)) && + valuesMatch(mRelY, coords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y)); if (!matches) { *os << "expected relative motion (" << mRelX << ", " << mRelY << ") at pointer index " << mPointerIndex << ", but got (" diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp index 99a67e4b26..e63a14bb5e 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.cpp +++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp @@ -629,7 +629,7 @@ Error Display::getRequestedLuts(LayerLuts* outLuts, auto layer = getLayerById(layerIds[i]); if (layer) { auto& layerLut = tmpLuts[i]; - if (layerLut.luts.pfd.get() > 0 && layerLut.luts.offsets.has_value()) { + if (layerLut.luts.pfd.get() >= 0 && layerLut.luts.offsets.has_value()) { const auto& offsets = layerLut.luts.offsets.value(); std::vector<std::pair<int32_t, LutProperties>> lutOffsetsAndProperties; lutOffsetsAndProperties.reserve(offsets.size()); diff --git a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp index f1091a6f03..d369403737 100644 --- a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp +++ b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp @@ -182,8 +182,8 @@ void LayerLifecycleManager::onHandlesDestroyed( } } -void LayerLifecycleManager::applyTransactions(const std::vector<TransactionState>& transactions, - bool ignoreUnknownLayers) { +void LayerLifecycleManager::applyTransactions( + const std::vector<QueuedTransactionState>& transactions, bool ignoreUnknownLayers) { for (const auto& transaction : transactions) { for (const auto& resolvedComposerState : transaction.states) { const auto& clientState = resolvedComposerState.state; diff --git a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.h b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.h index 330da9a3d3..072be35b26 100644 --- a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.h +++ b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.h @@ -16,8 +16,8 @@ #pragma once +#include "QueuedTransactionState.h" #include "RequestedLayerState.h" -#include "TransactionState.h" namespace android::surfaceflinger::frontend { @@ -43,7 +43,8 @@ public: // the layers it is unreachable. When using the LayerLifecycleManager for layer trace // generation we may encounter layers which are known because we don't have an explicit // lifecycle. Ignore these errors while we have to interop with legacy. - void applyTransactions(const std::vector<TransactionState>&, bool ignoreUnknownLayers = false); + void applyTransactions(const std::vector<QueuedTransactionState>&, + bool ignoreUnknownLayers = false); // Ignore unknown handles when iteroping with legacy front end. In the old world, we // would create child layers which are not necessary with the new front end. This means // we will get notified for handle changes that don't exist in the new front end. diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.h b/services/surfaceflinger/FrontEnd/RequestedLayerState.h index 7ddd7baf1e..dd861a74f4 100644 --- a/services/surfaceflinger/FrontEnd/RequestedLayerState.h +++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.h @@ -23,7 +23,7 @@ #include "Scheduler/LayerInfo.h" #include "LayerCreationArgs.h" -#include "TransactionState.h" +#include "QueuedTransactionState.h" namespace android::surfaceflinger::frontend { using namespace ftl::flag_operators; diff --git a/services/surfaceflinger/FrontEnd/TransactionHandler.cpp b/services/surfaceflinger/FrontEnd/TransactionHandler.cpp index a1e8213132..5bf86e5705 100644 --- a/services/surfaceflinger/FrontEnd/TransactionHandler.cpp +++ b/services/surfaceflinger/FrontEnd/TransactionHandler.cpp @@ -28,7 +28,7 @@ namespace android::surfaceflinger::frontend { -void TransactionHandler::queueTransaction(TransactionState&& state) { +void TransactionHandler::queueTransaction(QueuedTransactionState&& state) { mLocklessTransactionQueue.push(std::move(state)); mPendingTransactionCount.fetch_add(1); SFTRACE_INT("TransactionQueue", static_cast<int>(mPendingTransactionCount.load())); @@ -45,9 +45,9 @@ void TransactionHandler::collectTransactions() { } } -std::vector<TransactionState> TransactionHandler::flushTransactions() { +std::vector<QueuedTransactionState> TransactionHandler::flushTransactions() { // Collect transaction that are ready to be applied. - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; TransactionFlushState flushState; flushState.queueProcessTime = systemTime(); // Transactions with a buffer pending on a barrier may be on a different applyToken @@ -76,7 +76,7 @@ std::vector<TransactionState> TransactionHandler::flushTransactions() { } void TransactionHandler::applyUnsignaledBufferTransaction( - std::vector<TransactionState>& transactions, TransactionFlushState& flushState) { + std::vector<QueuedTransactionState>& transactions, TransactionFlushState& flushState) { if (!flushState.queueWithUnsignaledBuffer) { return; } @@ -98,9 +98,9 @@ void TransactionHandler::applyUnsignaledBufferTransaction( } } -void TransactionHandler::popTransactionFromPending(std::vector<TransactionState>& transactions, - TransactionFlushState& flushState, - std::queue<TransactionState>& queue) { +void TransactionHandler::popTransactionFromPending( + std::vector<QueuedTransactionState>& transactions, TransactionFlushState& flushState, + std::queue<QueuedTransactionState>& queue) { auto& transaction = queue.front(); // Transaction is ready move it from the pending queue. flushState.firstTransaction = false; @@ -146,8 +146,8 @@ TransactionHandler::TransactionReadiness TransactionHandler::applyFilters( return ready; } -int TransactionHandler::flushPendingTransactionQueues(std::vector<TransactionState>& transactions, - TransactionFlushState& flushState) { +int TransactionHandler::flushPendingTransactionQueues( + std::vector<QueuedTransactionState>& transactions, TransactionFlushState& flushState) { int transactionsPendingBarrier = 0; auto it = mPendingTransactionQueues.begin(); while (it != mPendingTransactionQueues.end()) { diff --git a/services/surfaceflinger/FrontEnd/TransactionHandler.h b/services/surfaceflinger/FrontEnd/TransactionHandler.h index 00f6bcebe6..e78dd88be2 100644 --- a/services/surfaceflinger/FrontEnd/TransactionHandler.h +++ b/services/surfaceflinger/FrontEnd/TransactionHandler.h @@ -22,7 +22,7 @@ #include <vector> #include <LocklessQueue.h> -#include <TransactionState.h> +#include <QueuedTransactionState.h> #include <android-base/thread_annotations.h> #include <ftl/small_map.h> #include <ftl/small_vector.h> @@ -35,7 +35,7 @@ namespace surfaceflinger::frontend { class TransactionHandler { public: struct TransactionFlushState { - TransactionState* transaction; + QueuedTransactionState* transaction; bool firstTransaction = true; nsecs_t queueProcessTime = 0; // Layer handles that have transactions with buffers that are ready to be applied. @@ -61,9 +61,9 @@ public: bool hasPendingTransactions(); // Moves transactions from the lockless queue. void collectTransactions(); - std::vector<TransactionState> flushTransactions(); + std::vector<QueuedTransactionState> flushTransactions(); void addTransactionReadyFilter(TransactionFilter&&); - void queueTransaction(TransactionState&&); + void queueTransaction(QueuedTransactionState&&); struct StalledTransactionInfo { pid_t pid; @@ -81,14 +81,15 @@ private: // For unit tests friend class ::android::TestableSurfaceFlinger; - int flushPendingTransactionQueues(std::vector<TransactionState>&, TransactionFlushState&); - void applyUnsignaledBufferTransaction(std::vector<TransactionState>&, TransactionFlushState&); - void popTransactionFromPending(std::vector<TransactionState>&, TransactionFlushState&, - std::queue<TransactionState>&); + int flushPendingTransactionQueues(std::vector<QueuedTransactionState>&, TransactionFlushState&); + void applyUnsignaledBufferTransaction(std::vector<QueuedTransactionState>&, + TransactionFlushState&); + void popTransactionFromPending(std::vector<QueuedTransactionState>&, TransactionFlushState&, + std::queue<QueuedTransactionState>&); TransactionReadiness applyFilters(TransactionFlushState&); - std::unordered_map<sp<IBinder>, std::queue<TransactionState>, IListenerHash> + std::unordered_map<sp<IBinder>, std::queue<QueuedTransactionState>, IListenerHash> mPendingTransactionQueues; - LocklessQueue<TransactionState> mLocklessTransactionQueue; + LocklessQueue<QueuedTransactionState> mLocklessTransactionQueue; std::atomic<size_t> mPendingTransactionCount = 0; ftl::SmallVector<TransactionFilter, 2> mTransactionReadyFilters; diff --git a/services/surfaceflinger/FrontEnd/Update.h b/services/surfaceflinger/FrontEnd/Update.h index 4af27ab84d..f7dfeb84bc 100644 --- a/services/surfaceflinger/FrontEnd/Update.h +++ b/services/surfaceflinger/FrontEnd/Update.h @@ -19,15 +19,15 @@ #include <gui/DisplayInfo.h> #include "FrontEnd/LayerCreationArgs.h" +#include "QueuedTransactionState.h" #include "RequestedLayerState.h" -#include "TransactionState.h" namespace android::surfaceflinger::frontend { // Atomic set of changes affecting layer state. These changes are queued in binder threads and // applied every vsync. struct Update { - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; std::vector<sp<Layer>> legacyLayers; std::vector<std::unique_ptr<frontend::RequestedLayerState>> newLayers; std::vector<LayerCreationArgs> layerCreationArgs; diff --git a/services/surfaceflinger/TransactionState.h b/services/surfaceflinger/QueuedTransactionState.h index e5d648194f..af40c026a0 100644 --- a/services/surfaceflinger/TransactionState.h +++ b/services/surfaceflinger/QueuedTransactionState.h @@ -16,9 +16,7 @@ #pragma once -#include <condition_variable> #include <memory> -#include <mutex> #include <vector> #include "FrontEnd/LayerCreationArgs.h" #include "renderengine/ExternalTexture.h" @@ -47,18 +45,20 @@ public: uint32_t touchCropId = UNASSIGNED_LAYER_ID; }; -struct TransactionState { - TransactionState() = default; +struct QueuedTransactionState { + QueuedTransactionState() = default; - TransactionState(const FrameTimelineInfo& frameTimelineInfo, - std::vector<ResolvedComposerState>& composerStates, - const Vector<DisplayState>& displayStates, uint32_t transactionFlags, - const sp<IBinder>& applyToken, const InputWindowCommands& inputWindowCommands, - int64_t desiredPresentTime, bool isAutoTimestamp, - std::vector<uint64_t> uncacheBufferIds, int64_t postTime, - bool hasListenerCallbacks, std::vector<ListenerCallbacks> listenerCallbacks, - int originPid, int originUid, uint64_t transactionId, - std::vector<uint64_t> mergedTransactionIds) + QueuedTransactionState(const FrameTimelineInfo& frameTimelineInfo, + std::vector<ResolvedComposerState>& composerStates, + const Vector<DisplayState>& displayStates, uint32_t transactionFlags, + const sp<IBinder>& applyToken, + const InputWindowCommands& inputWindowCommands, + int64_t desiredPresentTime, bool isAutoTimestamp, + std::vector<uint64_t> uncacheBufferIds, int64_t postTime, + bool hasListenerCallbacks, + std::vector<ListenerCallbacks> listenerCallbacks, int originPid, + int originUid, uint64_t transactionId, + std::vector<uint64_t> mergedTransactionIds) : frameTimelineInfo(frameTimelineInfo), states(std::move(composerStates)), displays(displayStates), diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e05c5bd97c..dd1119a5d1 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4774,16 +4774,16 @@ void SurfaceFlinger::addTransactionReadyFilters() { // For tests only bool SurfaceFlinger::flushTransactionQueues() { mTransactionHandler.collectTransactions(); - std::vector<TransactionState> transactions = mTransactionHandler.flushTransactions(); + std::vector<QueuedTransactionState> transactions = mTransactionHandler.flushTransactions(); return applyTransactions(transactions); } -bool SurfaceFlinger::applyTransactions(std::vector<TransactionState>& transactions) { +bool SurfaceFlinger::applyTransactions(std::vector<QueuedTransactionState>& transactions) { Mutex::Autolock lock(mStateLock); return applyTransactionsLocked(transactions); } -bool SurfaceFlinger::applyTransactionsLocked(std::vector<TransactionState>& transactions) { +bool SurfaceFlinger::applyTransactionsLocked(std::vector<QueuedTransactionState>& transactions) { bool needsTraversal = false; // Now apply all transactions. for (auto& transaction : transactions) { @@ -4944,22 +4944,22 @@ status_t SurfaceFlinger::setTransactionState( } } - TransactionState state{frameTimelineInfo, - resolvedStates, - displays, - flags, - applyToken, - std::move(inputWindowCommands), - desiredPresentTime, - isAutoTimestamp, - std::move(uncacheBufferIds), - postTime, - hasListenerCallbacks, - listenerCallbacks, - originPid, - originUid, - transactionId, - mergedTransactionIds}; + QueuedTransactionState state{frameTimelineInfo, + resolvedStates, + displays, + flags, + applyToken, + std::move(inputWindowCommands), + desiredPresentTime, + isAutoTimestamp, + std::move(uncacheBufferIds), + postTime, + hasListenerCallbacks, + listenerCallbacks, + originPid, + originUid, + transactionId, + mergedTransactionIds}; if (mTransactionTracing) { mTransactionTracing->addQueuedTransaction(state); @@ -5044,7 +5044,7 @@ bool SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelin } bool SurfaceFlinger::applyAndCommitDisplayTransactionStatesLocked( - std::vector<TransactionState>& transactions) { + std::vector<QueuedTransactionState>& transactions) { bool needsTraversal = false; uint32_t transactionFlags = 0; for (auto& transaction : transactions) { @@ -5438,7 +5438,7 @@ void SurfaceFlinger::onHandleDestroyed(sp<Layer>& layer, uint32_t layerId) { } void SurfaceFlinger::initializeDisplays() { - TransactionState state; + QueuedTransactionState state; state.inputWindowCommands = mInputWindowCommands; const nsecs_t now = systemTime(); state.desiredPresentTime = now; @@ -5453,7 +5453,7 @@ void SurfaceFlinger::initializeDisplays() { state.displays.push(DisplayState(display.token(), ui::LayerStack::fromValue(layerStack++))); } - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(state); { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index c85c0846c5..c2e687f385 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -87,6 +87,7 @@ #include "LayerVector.h" #include "MutexUtils.h" #include "PowerAdvisor/PowerAdvisor.h" +#include "QueuedTransactionState.h" #include "Scheduler/ISchedulerCallback.h" #include "Scheduler/RefreshRateSelector.h" #include "Scheduler/Scheduler.h" @@ -95,7 +96,6 @@ #include "Tracing/LayerTracing.h" #include "Tracing/TransactionTracing.h" #include "TransactionCallbackInvoker.h" -#include "TransactionState.h" #include "Utils/OnceFuture.h" #include <algorithm> @@ -803,8 +803,9 @@ private: // For test only bool flushTransactionQueues() REQUIRES(kMainThreadContext); - bool applyTransactions(std::vector<TransactionState>&) REQUIRES(kMainThreadContext); - bool applyAndCommitDisplayTransactionStatesLocked(std::vector<TransactionState>& transactions) + bool applyTransactions(std::vector<QueuedTransactionState>&) REQUIRES(kMainThreadContext); + bool applyAndCommitDisplayTransactionStatesLocked( + std::vector<QueuedTransactionState>& transactions) REQUIRES(kMainThreadContext, mStateLock); // Returns true if there is at least one transaction that needs to be flushed @@ -833,7 +834,7 @@ private: static LatchUnsignaledConfig getLatchUnsignaledConfig(); bool shouldLatchUnsignaled(const layer_state_t&, size_t numStates, bool firstTransaction) const; - bool applyTransactionsLocked(std::vector<TransactionState>& transactions) + bool applyTransactionsLocked(std::vector<QueuedTransactionState>& transactions) REQUIRES(mStateLock, kMainThreadContext); uint32_t setDisplayStateLocked(const DisplayState& s) REQUIRES(mStateLock); uint32_t addInputWindowCommands(const InputWindowCommands& inputWindowCommands) diff --git a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp index f39a4d2af4..2676ca6777 100644 --- a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp +++ b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp @@ -20,8 +20,8 @@ #include "FrontEnd/LayerCreationArgs.h" #include "LayerProtoHelper.h" +#include "QueuedTransactionState.h" #include "TransactionProtoParser.h" -#include "TransactionState.h" #include "gui/LayerState.h" namespace android::surfaceflinger { @@ -51,7 +51,8 @@ public: ~FakeExternalTexture() = default; }; -perfetto::protos::TransactionState TransactionProtoParser::toProto(const TransactionState& t) { +perfetto::protos::TransactionState TransactionProtoParser::toProto( + const QueuedTransactionState& t) { perfetto::protos::TransactionState proto; proto.set_pid(t.originPid); proto.set_uid(t.originUid); @@ -300,9 +301,9 @@ perfetto::protos::LayerCreationArgs TransactionProtoParser::toProto(const LayerC return proto; } -TransactionState TransactionProtoParser::fromProto( +QueuedTransactionState TransactionProtoParser::fromProto( const perfetto::protos::TransactionState& proto) { - TransactionState t; + QueuedTransactionState t; t.originPid = proto.pid(); t.originUid = proto.uid(); t.frameTimelineInfo.vsyncId = proto.vsync_id(); diff --git a/services/surfaceflinger/Tracing/TransactionProtoParser.h b/services/surfaceflinger/Tracing/TransactionProtoParser.h index b3ab71cfb5..a02e2318ef 100644 --- a/services/surfaceflinger/Tracing/TransactionProtoParser.h +++ b/services/surfaceflinger/Tracing/TransactionProtoParser.h @@ -21,7 +21,7 @@ #include "FrontEnd/DisplayInfo.h" #include "FrontEnd/LayerCreationArgs.h" -#include "TransactionState.h" +#include "QueuedTransactionState.h" namespace android::surfaceflinger { @@ -44,14 +44,14 @@ public: TransactionProtoParser(std::unique_ptr<FlingerDataMapper> provider) : mMapper(std::move(provider)) {} - perfetto::protos::TransactionState toProto(const TransactionState&); + perfetto::protos::TransactionState toProto(const QueuedTransactionState&); perfetto::protos::TransactionState toProto( const std::map<uint32_t /* layerId */, TracingLayerState>&); perfetto::protos::LayerCreationArgs toProto(const LayerCreationArgs& args); perfetto::protos::LayerState toProto(const ResolvedComposerState&); static perfetto::protos::DisplayInfo toProto(const frontend::DisplayInfo&, uint32_t layerStack); - TransactionState fromProto(const perfetto::protos::TransactionState&); + QueuedTransactionState fromProto(const perfetto::protos::TransactionState&); void mergeFromProto(const perfetto::protos::LayerState&, TracingLayerState& outState); void fromProto(const perfetto::protos::LayerCreationArgs&, LayerCreationArgs& outArgs); std::unique_ptr<FlingerDataMapper> mMapper; diff --git a/services/surfaceflinger/Tracing/TransactionTracing.cpp b/services/surfaceflinger/Tracing/TransactionTracing.cpp index bc9f8094f2..1cd75170bf 100644 --- a/services/surfaceflinger/Tracing/TransactionTracing.cpp +++ b/services/surfaceflinger/Tracing/TransactionTracing.cpp @@ -166,7 +166,7 @@ void TransactionTracing::dump(std::string& result) const { mBuffer.dump(result); } -void TransactionTracing::addQueuedTransaction(const TransactionState& transaction) { +void TransactionTracing::addQueuedTransaction(const QueuedTransactionState& transaction) { perfetto::protos::TransactionState* state = new perfetto::protos::TransactionState(mProtoParser.toProto(transaction)); mTransactionQueue.push(state); diff --git a/services/surfaceflinger/Tracing/TransactionTracing.h b/services/surfaceflinger/Tracing/TransactionTracing.h index 7a0fb5ef6e..d784168553 100644 --- a/services/surfaceflinger/Tracing/TransactionTracing.h +++ b/services/surfaceflinger/Tracing/TransactionTracing.h @@ -134,7 +134,7 @@ public: // Flush event from perfetto data source void onFlush(Mode mode); - void addQueuedTransaction(const TransactionState&); + void addQueuedTransaction(const QueuedTransactionState&); void addCommittedTransactions(int64_t vsyncId, nsecs_t commitTime, frontend::Update& update, const frontend::DisplayInfos&, bool displayInfoChanged); status_t writeToFile(const std::string& filename = FILE_PATH); diff --git a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp index 1dba17585c..5cf42449c0 100644 --- a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp +++ b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp @@ -31,8 +31,8 @@ #include "FrontEnd/LayerCreationArgs.h" #include "FrontEnd/RequestedLayerState.h" #include "LayerProtoHelper.h" +#include "QueuedTransactionState.h" #include "Tracing/LayerTracing.h" -#include "TransactionState.h" #include "cutils/properties.h" #include "LayerTraceGenerator.h" @@ -95,11 +95,11 @@ bool LayerTraceGenerator::generate(const perfetto::protos::TransactionTraceFile& addedLayers.emplace_back(std::make_unique<frontend::RequestedLayerState>(args)); } - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.reserve((size_t)entry.transactions_size()); for (int j = 0; j < entry.transactions_size(); j++) { // apply transactions - TransactionState transaction = parser.fromProto(entry.transactions(j)); + QueuedTransactionState transaction = parser.fromProto(entry.transactions(j)); for (auto& resolvedComposerState : transaction.states) { if (resolvedComposerState.state.what & layer_state_t::eInputInfoChanged) { if (!resolvedComposerState.state.windowInfoHandle->getInfo()->inputConfig.test( diff --git a/services/surfaceflinger/tests/benchmarks/LayerLifecycleManager_benchmarks.cpp b/services/surfaceflinger/tests/benchmarks/LayerLifecycleManager_benchmarks.cpp index 7641a45ba4..0925118f87 100644 --- a/services/surfaceflinger/tests/benchmarks/LayerLifecycleManager_benchmarks.cpp +++ b/services/surfaceflinger/tests/benchmarks/LayerLifecycleManager_benchmarks.cpp @@ -50,7 +50,7 @@ static void updateClientStates(benchmark::State& state) { layers.emplace_back(LayerLifecycleManagerHelper::rootLayer(1)); lifecycleManager.addLayers(std::move(layers)); lifecycleManager.commitChanges(); - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); auto& transactionState = transactions.back().states.front(); @@ -74,7 +74,7 @@ static void updateClientStatesNoChanges(benchmark::State& state) { std::vector<std::unique_ptr<RequestedLayerState>> layers; layers.emplace_back(LayerLifecycleManagerHelper::rootLayer(1)); lifecycleManager.addLayers(std::move(layers)); - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); auto& transactionState = transactions.back().states.front(); diff --git a/services/surfaceflinger/tests/common/LayerLifecycleManagerHelper.h b/services/surfaceflinger/tests/common/LayerLifecycleManagerHelper.h index 97946205ba..a894c418f6 100644 --- a/services/surfaceflinger/tests/common/LayerLifecycleManagerHelper.h +++ b/services/surfaceflinger/tests/common/LayerLifecycleManagerHelper.h @@ -66,8 +66,8 @@ public: /*mirror=*/UNASSIGNED_LAYER_ID)); } - static std::vector<TransactionState> setZTransaction(uint32_t id, int32_t z) { - std::vector<TransactionState> transactions; + static std::vector<QueuedTransactionState> setZTransaction(uint32_t id, int32_t z) { + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); @@ -109,8 +109,9 @@ public: mLifecycleManager.addLayers(std::move(layers)); } - std::vector<TransactionState> reparentLayerTransaction(uint32_t id, uint32_t newParentId) { - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> reparentLayerTransaction(uint32_t id, + uint32_t newParentId) { + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().parentId = newParentId; @@ -124,8 +125,9 @@ public: mLifecycleManager.applyTransactions(reparentLayerTransaction(id, newParentId)); } - std::vector<TransactionState> relativeLayerTransaction(uint32_t id, uint32_t relativeParentId) { - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> relativeLayerTransaction(uint32_t id, + uint32_t relativeParentId) { + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().relativeParentId = relativeParentId; @@ -139,7 +141,7 @@ public: } void removeRelativeZ(uint32_t id) { - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.what = layer_state_t::eLayerChanged; @@ -148,7 +150,7 @@ public: } void setPosition(uint32_t id, float x, float y) { - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.what = layer_state_t::ePositionChanged; @@ -167,7 +169,7 @@ public: } void updateBackgroundColor(uint32_t id, half alpha) { - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.what = layer_state_t::eBackgroundColorChanged; @@ -183,7 +185,7 @@ public: } void setCrop(uint32_t id, const FloatRect& crop) { - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); @@ -196,7 +198,7 @@ public: void setCrop(uint32_t id, const Rect& crop) { setCrop(id, crop.toFloatRect()); } void setFlags(uint32_t id, uint32_t mask, uint32_t flags) { - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); @@ -208,7 +210,7 @@ public: } void setAlpha(uint32_t id, float alpha) { - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); @@ -219,7 +221,7 @@ public: } void setAutoRefresh(uint32_t id, bool autoRefresh) { - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); @@ -236,7 +238,7 @@ public: void showLayer(uint32_t id) { setFlags(id, layer_state_t::eLayerHidden, 0); } void setColor(uint32_t id, half3 rgb = half3(1._hf, 1._hf, 1._hf)) { - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.what = layer_state_t::eColorChanged; @@ -246,7 +248,7 @@ public: } void setLayerStack(uint32_t id, int32_t layerStack) { - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); @@ -257,7 +259,7 @@ public: } void setTouchableRegion(uint32_t id, Region region) { - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); @@ -272,7 +274,7 @@ public: } void setInputInfo(uint32_t id, std::function<void(gui::WindowInfo&)> configureInput) { - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); @@ -291,7 +293,7 @@ public: void setTouchableRegionCrop(uint32_t id, Region region, uint32_t touchCropId, bool replaceTouchableRegionWithCrop) { - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); @@ -309,7 +311,7 @@ public: } void setBackgroundBlurRadius(uint32_t id, uint32_t backgroundBlurRadius) { - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); @@ -320,7 +322,7 @@ public: } void setFrameRateSelectionPriority(uint32_t id, int32_t priority) { - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); @@ -332,7 +334,7 @@ public: void setFrameRate(uint32_t id, float frameRate, int8_t compatibility, int8_t changeFrameRateStrategy) { - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); @@ -345,7 +347,7 @@ public: } void setFrameRate(uint32_t id, Layer::FrameRate framerate) { - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); @@ -358,7 +360,7 @@ public: } void setFrameRateCategory(uint32_t id, int8_t frameRateCategory) { - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); @@ -369,7 +371,7 @@ public: } void setFrameRateSelectionStrategy(uint32_t id, int8_t strategy) { - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); @@ -381,7 +383,7 @@ public: } void setDefaultFrameRateCompatibility(uint32_t id, int8_t defaultFrameRateCompatibility) { - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); @@ -394,7 +396,7 @@ public: } void setRoundedCorners(uint32_t id, float radius) { - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); @@ -405,7 +407,7 @@ public: } void setBuffer(uint32_t id, std::shared_ptr<renderengine::ExternalTexture> texture) { - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); @@ -438,7 +440,7 @@ public: } void setBufferCrop(uint32_t id, const Rect& bufferCrop) { - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); @@ -449,7 +451,7 @@ public: } void setDamageRegion(uint32_t id, const Region& damageRegion) { - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); @@ -460,7 +462,7 @@ public: } void setDataspace(uint32_t id, ui::Dataspace dataspace) { - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); @@ -473,7 +475,7 @@ public: void setMatrix(uint32_t id, float dsdx, float dtdx, float dtdy, float dsdy) { layer_state_t::matrix22_t matrix{dsdx, dtdx, dtdy, dsdy}; - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); @@ -484,7 +486,7 @@ public: } void setShadowRadius(uint32_t id, float shadowRadius) { - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); @@ -495,7 +497,7 @@ public: } void setTrustedOverlay(uint32_t id, gui::TrustedOverlay trustedOverlay) { - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); @@ -506,7 +508,7 @@ public: } void setDropInputMode(uint32_t id, gui::DropInputMode dropInputMode) { - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); @@ -517,7 +519,7 @@ public: } void setGameMode(uint32_t id, gui::GameMode gameMode) { - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.what = layer_state_t::eMetadataChanged; @@ -529,7 +531,7 @@ public: } void setEdgeExtensionEffect(uint32_t id, int edge) { - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); diff --git a/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp b/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp index c7cc21ce07..976cecbe40 100644 --- a/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp @@ -21,7 +21,7 @@ #include "FrontEnd/LayerLifecycleManager.h" #include "LayerHierarchyTest.h" -#include "TransactionState.h" +#include "QueuedTransactionState.h" using namespace android::surfaceflinger; @@ -104,7 +104,7 @@ TEST_F(LayerLifecycleManagerTest, updateLayerStates) { EXPECT_FALSE(managedLayers.front()->changes.test(RequestedLayerState::Changes::Z)); // apply transactions that do not affect the hierarchy - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.backgroundBlurRadius = 22; @@ -297,7 +297,7 @@ TEST_F(LayerLifecycleManagerTest, canAddBackgroundLayer) { layers.emplace_back(rootLayer(1)); lifecycleManager.addLayers(std::move(layers)); - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.bgColor.a = 0.5; @@ -326,7 +326,7 @@ TEST_F(LayerLifecycleManagerTest, canDestroyBackgroundLayer) { layers.emplace_back(rootLayer(1)); lifecycleManager.addLayers(std::move(layers)); - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.bgColor.a = 0.5; @@ -360,7 +360,7 @@ TEST_F(LayerLifecycleManagerTest, onParentDestroyDestroysBackgroundLayer) { layers.emplace_back(rootLayer(1)); lifecycleManager.addLayers(std::move(layers)); - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.bgColor.a = 0.5; diff --git a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp index 4d322efe86..1177d1601e 100644 --- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp @@ -329,7 +329,7 @@ TEST_F(LayerSnapshotTest, ReparentingUpdatesGameMode) { } TEST_F(LayerSnapshotTest, UpdateMetadata) { - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.what = layer_state_t::eMetadataChanged; @@ -374,7 +374,7 @@ TEST_F(LayerSnapshotTest, UpdateMetadata) { TEST_F(LayerSnapshotTest, UpdateMetadataOfHiddenLayers) { hideLayer(1); - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.what = layer_state_t::eMetadataChanged; @@ -1557,7 +1557,7 @@ TEST_F(LayerSnapshotTest, NonVisibleLayerWithInput) { setColor(3, {-1._hf, -1._hf, -1._hf}); UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER); - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.what = layer_state_t::eInputInfoChanged; @@ -1586,7 +1586,7 @@ TEST_F(LayerSnapshotTest, NonVisibleLayerWithInputShouldNotBeIncluded) { setColor(3, {-1._hf, -1._hf, -1._hf}); UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER); - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.what = layer_state_t::eInputInfoChanged; @@ -2021,7 +2021,7 @@ TEST_F(LayerSnapshotTest, contentDirtyWhenParentGeometryChanges) { EXPECT_FALSE(getSnapshot(1)->contentDirty); } TEST_F(LayerSnapshotTest, shouldUpdatePictureProfileHandle) { - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.back().layerId = 1; @@ -2040,7 +2040,7 @@ TEST_F(LayerSnapshotTest, shouldUpdatePictureProfileHandle) { TEST_F(LayerSnapshotTest, shouldUpdatePictureProfilePriorityFromAppContentPriority) { { - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.back().layerId = 1; @@ -2063,7 +2063,7 @@ TEST_F(LayerSnapshotTest, shouldUpdatePictureProfilePriorityFromAppContentPriori 2); } { - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.back().layerId = 1; diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index bd1382e851..3455c13bb7 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -514,7 +514,7 @@ public: mergedTransactionIds); } - auto setTransactionStateInternal(TransactionState& transaction) { + auto setTransactionStateInternal(QueuedTransactionState& transaction) { return FTL_FAKE_GUARD(kMainThreadContext, mFlinger->mTransactionHandler.queueTransaction( std::move(transaction))); diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp index 1e8cd0a0ca..69dfcc4a8f 100644 --- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp @@ -33,8 +33,8 @@ #include <vector> #include "FrontEnd/TransactionHandler.h" +#include "QueuedTransactionState.h" #include "TestableSurfaceFlinger.h" -#include "TransactionState.h" #include <com_android_graphics_surfaceflinger_flags.h> @@ -84,7 +84,7 @@ public: static_assert(0xffffffffffffffff == static_cast<uint64_t>(-1)); }; - void checkEqual(TransactionInfo info, TransactionState state) { + void checkEqual(TransactionInfo info, QueuedTransactionState state) { EXPECT_EQ(0u, info.states.size()); EXPECT_EQ(0u, state.states.size()); @@ -318,7 +318,7 @@ TEST_F(TransactionApplicationTest, ApplyTokensUseDifferentQueues) { auto applyToken2 = sp<BBinder>::make(); // Transaction 1 has a buffer with an unfired fence. It should not be ready to be applied. - TransactionState transaction1; + QueuedTransactionState transaction1; transaction1.applyToken = applyToken1; transaction1.id = 42069; transaction1.states.emplace_back(); @@ -340,7 +340,7 @@ TEST_F(TransactionApplicationTest, ApplyTokensUseDifferentQueues) { transaction1.isAutoTimestamp = true; // Transaction 2 should be ready to be applied. - TransactionState transaction2; + QueuedTransactionState transaction2; transaction2.applyToken = applyToken2; transaction2.id = 2; transaction2.isAutoTimestamp = true; @@ -446,15 +446,15 @@ public: resolvedStates.emplace_back(resolvedState); } - TransactionState transactionState(transaction.frameTimelineInfo, resolvedStates, - transaction.displays, transaction.flags, - transaction.applyToken, - transaction.inputWindowCommands, - transaction.desiredPresentTime, - transaction.isAutoTimestamp, {}, systemTime(), - mHasListenerCallbacks, mCallbacks, getpid(), - static_cast<int>(getuid()), transaction.id, - transaction.mergedTransactionIds); + QueuedTransactionState transactionState(transaction.frameTimelineInfo, resolvedStates, + transaction.displays, transaction.flags, + transaction.applyToken, + transaction.inputWindowCommands, + transaction.desiredPresentTime, + transaction.isAutoTimestamp, {}, systemTime(), + mHasListenerCallbacks, mCallbacks, getpid(), + static_cast<int>(getuid()), transaction.id, + transaction.mergedTransactionIds); mFlinger.setTransactionStateInternal(transactionState); } mFlinger.flushTransactionQueues(); @@ -955,12 +955,12 @@ TEST_F(LatchUnsignaledDisabledTest, Flush_KeepInTheUnsignaledTheQueue) { TEST(TransactionHandlerTest, QueueTransaction) { TransactionHandler handler; - TransactionState transaction; + QueuedTransactionState transaction; transaction.applyToken = sp<BBinder>::make(); transaction.id = 42; handler.queueTransaction(std::move(transaction)); handler.collectTransactions(); - std::vector<TransactionState> transactionsReadyToBeApplied = handler.flushTransactions(); + std::vector<QueuedTransactionState> transactionsReadyToBeApplied = handler.flushTransactions(); EXPECT_EQ(transactionsReadyToBeApplied.size(), 1u); EXPECT_EQ(transactionsReadyToBeApplied.front().id, 42u); diff --git a/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp b/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp index af0233063e..d3eec5c6f3 100644 --- a/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp @@ -30,7 +30,7 @@ namespace android { TEST(TransactionProtoParserTest, parse) { const sp<IBinder> displayHandle = sp<BBinder>::make(); - TransactionState t1; + QueuedTransactionState t1; t1.originPid = 1; t1.originUid = 2; t1.frameTimelineInfo.vsyncId = 3; @@ -86,7 +86,7 @@ TEST(TransactionProtoParserTest, parse) { TransactionProtoParser parser(std::make_unique<TestMapper>(displayHandle)); perfetto::protos::TransactionState proto = parser.toProto(t1); - TransactionState t2 = parser.fromProto(proto); + QueuedTransactionState t2 = parser.fromProto(proto); ASSERT_EQ(t1.originPid, t2.originPid); ASSERT_EQ(t1.originUid, t2.originUid); diff --git a/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp b/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp index f8f08c78fd..036d8c414d 100644 --- a/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp @@ -49,19 +49,19 @@ protected: void queueAndCommitTransaction(int64_t vsyncId) { frontend::Update update; - TransactionState transaction; + QueuedTransactionState transaction; transaction.id = static_cast<uint64_t>(vsyncId * 3); transaction.originUid = 1; transaction.originPid = 2; mTracing.addQueuedTransaction(transaction); - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; update.transactions.emplace_back(transaction); mTracing.addCommittedTransactions(vsyncId, 0, update, {}, false); flush(); } void verifyEntry(const perfetto::protos::TransactionTraceEntry& actualProto, - const std::vector<TransactionState>& expectedTransactions, + const std::vector<QueuedTransactionState>& expectedTransactions, int64_t expectedVsyncId) { EXPECT_EQ(actualProto.vsync_id(), expectedVsyncId); ASSERT_EQ(actualProto.transactions().size(), @@ -92,10 +92,10 @@ protected: }; TEST_F(TransactionTracingTest, addTransactions) { - std::vector<TransactionState> transactions; + std::vector<QueuedTransactionState> transactions; transactions.reserve(100); for (uint64_t i = 0; i < 100; i++) { - TransactionState transaction; + QueuedTransactionState transaction; transaction.id = i; transaction.originPid = static_cast<int32_t>(i); transaction.mergedTransactionIds = std::vector<uint64_t>{i + 100, i + 102}; @@ -108,13 +108,13 @@ TEST_F(TransactionTracingTest, addTransactions) { int64_t firstTransactionSetVsyncId = 42; frontend::Update firstUpdate; firstUpdate.transactions = - std::vector<TransactionState>(transactions.begin() + 50, transactions.end()); + std::vector<QueuedTransactionState>(transactions.begin() + 50, transactions.end()); mTracing.addCommittedTransactions(firstTransactionSetVsyncId, 0, firstUpdate, {}, false); int64_t secondTransactionSetVsyncId = 43; frontend::Update secondUpdate; secondUpdate.transactions = - std::vector<TransactionState>(transactions.begin(), transactions.begin() + 50); + std::vector<QueuedTransactionState>(transactions.begin(), transactions.begin() + 50); mTracing.addCommittedTransactions(secondTransactionSetVsyncId, 0, secondUpdate, {}, false); flush(); @@ -140,7 +140,7 @@ protected: getLayerCreationArgs(mChildLayerId, mParentLayerId, /*layerIdToMirror=*/UNASSIGNED_LAYER_ID, /*flags=*/456, /*addToRoot=*/true)); - TransactionState transaction; + QueuedTransactionState transaction; transaction.id = 50; ResolvedComposerState layerState; layerState.layerId = mParentLayerId; @@ -164,7 +164,7 @@ protected: // add transactions that modify the layer state further so we can test that layer state // gets merged { - TransactionState transaction; + QueuedTransactionState transaction; transaction.id = 51; ResolvedComposerState layerState; layerState.layerId = mParentLayerId; @@ -278,7 +278,7 @@ protected: /*layerIdToMirror=*/mLayerId, /*flags=*/0, /*addToRoot=*/false)); - TransactionState transaction; + QueuedTransactionState transaction; transaction.id = 50; ResolvedComposerState layerState; layerState.layerId = mLayerId; |