Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d14688f8 authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 8698879 from d70fd7a2 to tm-release

Change-Id: Ia87735ee3f3cc1e50d8f14b1b2ff5aa27a74560c
parents 9c4f4b6a d70fd7a2
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -96,6 +96,12 @@ package android.accessibilityservice {

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);
  }

  public class ValueAnimator extends android.animation.Animator {
    method @MainThread public static void setDurationScale(@FloatRange(from=0) float);
  }
+162 −1
Original line number Diff line number Diff line
@@ -17,7 +17,10 @@
package android.animation;

import android.os.SystemClock;
import android.os.SystemProperties;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
import android.view.Choreographer;

import java.util.ArrayList;
@@ -35,10 +38,13 @@ import java.util.ArrayList;
 * @hide
 */
public class AnimationHandler {

    private static final String TAG = "AnimationHandler";
    private static final boolean LOCAL_LOGV = false;

    /**
     * Internal per-thread collections used to avoid set collisions as animations start and end
     * while being processed.
     * @hide
     */
    private final ArrayMap<AnimationFrameCallback, Long> mDelayedCallbackStartTime =
            new ArrayMap<>();
@@ -48,6 +54,32 @@ public class AnimationHandler {
            new ArrayList<>();
    private AnimationFrameCallbackProvider mProvider;

    // Static flag which allows the pausing behavior to be globally disabled/enabled.
    private static boolean sAnimatorPausingEnabled = isPauseBgAnimationsEnabledInSystemProperties();

    // Static flag which prevents the system property from overriding sAnimatorPausingEnabled field.
    private static boolean sOverrideAnimatorPausingSystemProperty = false;

    /**
     * This paused list is used to store animators forcibly paused when the activity
     * went into the background (to avoid unnecessary background processing work).
     * These animators should be resume()'d when the activity returns to the foreground.
     */
    private final ArrayList<Animator> mPausedAnimators = new ArrayList<>();

    /**
     * This structure is used to store the currently active objects (ViewRootImpls or
     * WallpaperService.Engines) in the process. Each of these objects sends a request to
     * AnimationHandler when it goes into the background (request to pause) or foreground
     * (request to resume). Because all animators are managed by AnimationHandler on the same
     * thread, it should only ever pause animators when *all* requestors are in the background.
     * This list tracks the background/foreground state of all requestors and only ever
     * pauses animators when all items are in the background (false). To simplify, we only ever
     * store visible (foreground) requestors; if the set size reaches zero, there are no
     * objects in the foreground and it is time to pause animators.
     */
    private final ArraySet<Object> mAnimatorRequestors = new ArraySet<>();

    private final Choreographer.FrameCallback mFrameCallback = new Choreographer.FrameCallback() {
        @Override
        public void doFrame(long frameTimeNanos) {
@@ -68,6 +100,135 @@ public class AnimationHandler {
        return sAnimatorHandler.get();
    }

    /**
     * System property that controls the behavior of pausing infinite animators when an app
     * is moved to the background.
     *
     * @return the value of 'framework.pause_bg_animations.enabled' system property
     */
    private static boolean isPauseBgAnimationsEnabledInSystemProperties() {
        if (sOverrideAnimatorPausingSystemProperty) return sAnimatorPausingEnabled;
        return SystemProperties
                .getBoolean("framework.pause_bg_animations.enabled", true);
    }

    /**
     * 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;
    }

    /**
     * Prevents the setAnimatorPausingEnabled behavior from being overridden
     * by the 'framework.pause_bg_animations.enabled' system property value.
     *
     * This is for testing purposes only.
     *
     * @param enable Enable or disable (default behavior) overriding the system
     *               property.
     */
    public static void setOverrideAnimatorPausingSystemProperty(boolean enable) {
        sOverrideAnimatorPausingSystemProperty = enable;
    }

    /**
     * This is called when a window goes away. We should remove
     * it from the requestors list to ensure that we are counting requests correctly and not
     * tracking obsolete+enabled requestors.
     */
    public static void removeRequestor(Object requestor) {
        getInstance().removeRequestorImpl(requestor);
    }

    private void removeRequestorImpl(Object requestor) {
        // Also request disablement, in case that requestor was the sole object keeping
        // animators un-paused
        requestAnimatorsEnabled(false, requestor);
        mAnimatorRequestors.remove(requestor);
        if (LOCAL_LOGV) {
            Log.v(TAG, "removeRequestorImpl for " + requestor);
            for (int i = 0; i < mAnimatorRequestors.size(); ++i) {
                Log.v(TAG, "animatorRequesters " + i + " = " + mAnimatorRequestors.valueAt(i));
            }
        }
    }

    /**
     * This method is called from ViewRootImpl or WallpaperService when either a window is no
     * longer visible (enable == false) or when a window becomes visible (enable == true).
     * If animators are not properly disabled when activities are backgrounded, it can lead to
     * unnecessary processing, particularly for infinite animators, as the system will continue
     * to pulse timing events even though the results are not visible. As a workaround, we
     * pause all un-paused infinite animators, and resume them when any window in the process
     * becomes visible.
     */
    public static void requestAnimatorsEnabled(boolean enable, Object requestor) {
        getInstance().requestAnimatorsEnabledImpl(enable, requestor);
    }

    private void requestAnimatorsEnabledImpl(boolean enable, Object requestor) {
        boolean wasEmpty = mAnimatorRequestors.isEmpty();
        setAnimatorPausingEnabled(isPauseBgAnimationsEnabledInSystemProperties());
        if (enable) {
            mAnimatorRequestors.add(requestor);
        } 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
                resumeAnimators();
            } else {
                // Wait before pausing to avoid thrashing animator state for temporary backgrounding
                Choreographer.getInstance().postFrameCallbackDelayed(mPauser,
                        Animator.getBackgroundPauseDelay());
            }
        }
        if (LOCAL_LOGV) {
            Log.v(TAG, enable ? "enable" : "disable" + " animators for " + requestor);
            for (int i = 0; i < mAnimatorRequestors.size(); ++i) {
                Log.v(TAG, "animatorRequesters " + i + " = " + mAnimatorRequestors.valueAt(i));
            }
        }
    }

    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
            return;
        }
        for (int i = 0; i < mAnimationCallbacks.size(); ++i) {
            Animator animator = ((Animator) mAnimationCallbacks.get(i));
            if (animator != null
                    && animator.getTotalDuration() == Animator.DURATION_INFINITE
                    && !animator.isPaused()) {
                mPausedAnimators.add(animator);
                animator.pause();
            }
        }
    };

    /**
     * By default, the Choreographer is used to provide timing for frame callbacks. A custom
     * provider can be used here to provide different timing pulse.
+44 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package android.animation;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo.Config;
import android.content.res.ConstantState;
@@ -63,6 +64,49 @@ public abstract class Animator implements Cloneable {
     */
    private AnimatorConstantState mConstantState;

    /**
     * backing field for backgroundPauseDelay property. This could be simply a hardcoded
     * value in AnimationHandler, but it is useful to be able to change the value in tests.
     */
    private static long sBackgroundPauseDelay = 10000;

    /**
     * Sets the duration for delaying pausing animators when apps go into the background.
     * Used by AnimationHandler when requested to pause animators.
     *
     * @hide
     */
    @TestApi
    public static void setBackgroundPauseDelay(long value) {
        sBackgroundPauseDelay = value;
    }

    /**
     * Gets the duration for delaying pausing animators when apps go into the background.
     * Used by AnimationHandler when requested to pause animators.
     *
     * @hide
     */
    @TestApi
    public static long getBackgroundPauseDelay() {
        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);
        AnimationHandler.setOverrideAnimatorPausingSystemProperty(!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
+27 −0
Original line number Diff line number Diff line
@@ -524,6 +524,13 @@ public final class ApplicationExitInfo implements Parcelable {
     */
    private boolean mLoggedInStatsd;

    /**
     * Whether or not this process hosts one or more foreground services.
     *
     * for system internal use only, will not retain across processes.
     */
    private boolean mHasForegroundServices;

    /** @hide */
    @IntDef(prefix = { "REASON_" }, value = {
        REASON_UNKNOWN,
@@ -996,6 +1003,24 @@ public final class ApplicationExitInfo implements Parcelable {
        mLoggedInStatsd = loggedInStatsd;
    }

    /**
     * @see #mHasForegroundServices
     *
     * @hide
     */
    public boolean hasForegroundServices() {
        return mHasForegroundServices;
    }

    /**
     * @see #mHasForegroundServices
     *
     * @hide
     */
    public void setHasForegroundServices(boolean hasForegroundServices) {
        mHasForegroundServices = hasForegroundServices;
    }

    @Override
    public int describeContents() {
        return 0;
@@ -1060,6 +1085,8 @@ public final class ApplicationExitInfo implements Parcelable {
        mTraceFile = other.mTraceFile;
        mAppTraceRetriever = other.mAppTraceRetriever;
        mNativeTombstoneRetriever = other.mNativeTombstoneRetriever;
        mLoggedInStatsd = other.mLoggedInStatsd;
        mHasForegroundServices = other.mHasForegroundServices;
    }

    private ApplicationExitInfo(@NonNull Parcel in) {
+6 −1
Original line number Diff line number Diff line
@@ -28,12 +28,15 @@ public final class ProcessMemoryState implements Parcelable {
    public final int pid;
    public final String processName;
    public final int oomScore;
    public final boolean hasForegroundServices;

    public ProcessMemoryState(int uid, int pid, String processName, int oomScore) {
    public ProcessMemoryState(int uid, int pid, String processName, int oomScore,
            boolean hasForegroundServices) {
        this.uid = uid;
        this.pid = pid;
        this.processName = processName;
        this.oomScore = oomScore;
        this.hasForegroundServices = hasForegroundServices;
    }

    private ProcessMemoryState(Parcel in) {
@@ -41,6 +44,7 @@ public final class ProcessMemoryState implements Parcelable {
        pid = in.readInt();
        processName = in.readString();
        oomScore = in.readInt();
        hasForegroundServices = in.readInt() == 1;
    }

    public static final @android.annotation.NonNull Creator<ProcessMemoryState> CREATOR = new Creator<ProcessMemoryState>() {
@@ -66,5 +70,6 @@ public final class ProcessMemoryState implements Parcelable {
        parcel.writeInt(pid);
        parcel.writeString(processName);
        parcel.writeInt(oomScore);
        parcel.writeInt(hasForegroundServices ? 1 : 0);
    }
}
Loading