From 161732cf18d560b87de3b017df49b1fb995fc8d1 Mon Sep 17 00:00:00 2001 From: Chet Haase Date: Tue, 17 May 2022 22:13:24 +0000 Subject: [PATCH] Allow system to disable behavior of pausing animators for bg apps This change adds a static method which can be called to disable the default behavior of pausing infinite animators when an app's windows are all in the background. This could potentially be used for global behavior of a system property to disable this behavior system wide. Bug: 232937493 Bug: 233391022 Test: Added new cts test to AnimatorLeakTest to verify behavior Change-Id: Idf4957e3968253228096671fde89f820311883e3 Merged-In: Idf4957e3968253228096671fde89f820311883e3 --- core/api/test-current.txt | 1 + .../android/animation/AnimationHandler.java | 33 ++++++++++++++++--- core/java/android/animation/Animator.java | 14 ++++++++ 3 files changed, 43 insertions(+), 5 deletions(-) diff --git a/core/api/test-current.txt b/core/api/test-current.txt index e5a7bc288560e..1796c7b971a9a 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -98,6 +98,7 @@ package android.animation { public abstract class Animator implements java.lang.Cloneable { method public static long getBackgroundPauseDelay(); + method public static void setAnimatorPausingEnabled(boolean); method public static void setBackgroundPauseDelay(long); } diff --git a/core/java/android/animation/AnimationHandler.java b/core/java/android/animation/AnimationHandler.java index 7f6df2261fcc8..57ab55a53e468 100644 --- a/core/java/android/animation/AnimationHandler.java +++ b/core/java/android/animation/AnimationHandler.java @@ -53,6 +53,9 @@ public class AnimationHandler { new ArrayList<>(); private AnimationFrameCallbackProvider mProvider; + // Static flag which allows the pausing behavior to be globally disabled/enabled. + private static boolean sAnimatorPausingEnabled = true; + /** * This paused list is used to store animators forcibly paused when the activity * went into the background (to avoid unnecessary background processing work). @@ -93,6 +96,15 @@ public class AnimationHandler { return sAnimatorHandler.get(); } + /** + * Disable the default behavior of pausing infinite animators when + * apps go into the background. + * + * @param enable Enable (default behavior) or disable background pausing behavior. + */ + public static void setAnimatorPausingEnabled(boolean enable) { + sAnimatorPausingEnabled = enable; + } /** * This is called when a window goes away. We should remove @@ -136,16 +148,19 @@ public class AnimationHandler { } else { mAnimatorRequestors.remove(requestor); } + if (!sAnimatorPausingEnabled) { + // Resume any animators that have been paused in the meantime, otherwise noop + // Leave logic above so that if pausing gets re-enabled, the state of the requestors + // list is valid + resumeAnimators(); + return; + } boolean isEmpty = mAnimatorRequestors.isEmpty(); if (wasEmpty != isEmpty) { // only paused/resume animators if there was a visibility change if (!isEmpty) { // If any requestors are enabled, resume currently paused animators - Choreographer.getInstance().removeFrameCallback(mPauser); - for (int i = mPausedAnimators.size() - 1; i >= 0; --i) { - mPausedAnimators.get(i).resume(); - } - mPausedAnimators.clear(); + resumeAnimators(); } else { // Wait before pausing to avoid thrashing animator state for temporary backgrounding Choreographer.getInstance().postFrameCallbackDelayed(mPauser, @@ -160,6 +175,14 @@ public class AnimationHandler { } } + private void resumeAnimators() { + Choreographer.getInstance().removeFrameCallback(mPauser); + for (int i = mPausedAnimators.size() - 1; i >= 0; --i) { + mPausedAnimators.get(i).resume(); + } + mPausedAnimators.clear(); + } + private Choreographer.FrameCallback mPauser = frameTimeNanos -> { if (mAnimatorRequestors.size() > 0) { // something enabled animators since this callback was scheduled - bail diff --git a/core/java/android/animation/Animator.java b/core/java/android/animation/Animator.java index 9e55d359b416f..f69decb087f31 100644 --- a/core/java/android/animation/Animator.java +++ b/core/java/android/animation/Animator.java @@ -92,6 +92,20 @@ public abstract class Animator implements Cloneable { return sBackgroundPauseDelay; } + /** + * Sets the behavior of animator pausing when apps go into the background. + * This is exposed as a test API for verification, but is intended for use by internal/ + * platform code, potentially for use by a system property that could disable it + * system wide. + * + * @param enable Enable (default behavior) or disable background pausing behavior. + * @hide + */ + @TestApi + public static void setAnimatorPausingEnabled(boolean enable) { + AnimationHandler.setAnimatorPausingEnabled(enable); + } + /** * Starts this animation. If the animation has a nonzero startDelay, the animation will start * running after that delay elapses. A non-delayed animation will have its initial