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

Commit 3dbaae1e authored by Doris Liu's avatar Doris Liu
Browse files

Prevents recursive call into end() or cancel()

end() and cancel() in ValueAnimator will trigger onAnimationCancel
or onAnimationEnd callback on its listeners. If additional end()
or cancel() request comes from the callback, a loop will be formed.
Therefore, we need to mark when the end is reuqested so we do not
process end() or cancel() request multiple times during one animation
run, and also effectively terminate the loop.

Bug: 23596652
Change-Id: Iefb69eb8969071b43124c09d7cccbe9ff5ba5dcc
parent 2916fa11
Loading
Loading
Loading
Loading
+20 −2
Original line number Diff line number Diff line
@@ -185,6 +185,11 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio
     */
    boolean mInitialized = false;

    /**
     * Flag that tracks whether animation has been requested to end.
     */
    private boolean mAnimationEndRequested = false;

    //
    // Backing variables
    //
@@ -915,6 +920,7 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio
        mStarted = true;
        mPaused = false;
        mRunning = false;
        mAnimationEndRequested = false;
        updateScaledDuration(); // in case the scale factor has changed since creation time
        AnimationHandler animationHandler = AnimationHandler.getInstance();
        animationHandler.addAnimationFrameCallback(this, mStartDelay);
@@ -930,9 +936,15 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio
        if (Looper.myLooper() == null) {
            throw new AndroidRuntimeException("Animators may only be run on Looper threads");
        }

        // If end has already been requested, through a previous end() or cancel() call, no-op
        // until animation starts again.
        if (mAnimationEndRequested) {
            return;
        }

        // Only cancel if the animation is actually running or has been started and is about
        // to run

        // Only notify listeners if the animator has actually started
        if ((mStarted || mRunning) && mListeners != null) {
            if (!mRunning) {
@@ -1030,8 +1042,13 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio
     * called on the UI thread.
     */
    private void endAnimation() {
        if (mAnimationEndRequested) {
            return;
        }
        AnimationHandler handler = AnimationHandler.getInstance();
        handler.removeCallback(this);

        mAnimationEndRequested = true;
        mPaused = false;
        if ((mStarted || mRunning) && mListeners != null) {
            if (!mRunning) {
@@ -1256,6 +1273,7 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio
        anim.mStartListenersCalled = false;
        anim.mStartTime = 0;
        anim.mStartTimeCommitted = false;
        anim.mAnimationEndRequested = false;
        anim.mPauseTime = 0;
        anim.mLastFrameTime = 0;
        anim.mCurrentFraction = 0;