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

Commit f57bfe2f authored by Doris Liu's avatar Doris Liu
Browse files

Fix behavior change for animators without a start delay

This CL maintains the behavior that animators without any
start delay will get started right away, instead of being delayed
to the first frame as it was in the previous refactor.

Bug: 23825781
Change-Id: I7873bc6c7a761c1b4d48ee5e17af631b359fd676
parent b186388b
Loading
Loading
Loading
Loading
+56 −51
Original line number Diff line number Diff line
@@ -603,27 +603,28 @@ public final class AnimatorSet extends Animator {
        createDependencyGraph();

        // Now that all dependencies are set up, start the animations that should be started.
        boolean setIsEmpty = false;
        if (mStartDelay > 0) {
            start(mRootNode);
        if (mListeners != null) {
            ArrayList<AnimatorListener> tmpListeners =
                    (ArrayList<AnimatorListener>) mListeners.clone();
            int numListeners = tmpListeners.size();
            for (int i = 0; i < numListeners; ++i) {
                tmpListeners.get(i).onAnimationStart(this);
            }
        } else if (mNodes.size() > 1) {
            // No delay, but there are other animators in the set
            onChildAnimatorEnded(mDelayAnim);
        } else {
            // Set is empty, no delay, no other animation. Skip to end in this case
            setIsEmpty = true;
        }
        if (mNodes.size() == 0 && mStartDelay == 0) {
            // Handle unusual case where empty AnimatorSet is started - should send out
            // end event immediately since the event will not be sent out at all otherwise
            mStarted = false;

        if (mListeners != null) {
            ArrayList<AnimatorListener> tmpListeners =
                    (ArrayList<AnimatorListener>) mListeners.clone();
            int numListeners = tmpListeners.size();
            for (int i = 0; i < numListeners; ++i) {
                    tmpListeners.get(i).onAnimationEnd(this);
                tmpListeners.get(i).onAnimationStart(this);
            }
        }
        if (setIsEmpty) {
            // In the case of empty AnimatorSet, we will trigger the onAnimationEnd() right away.
            onChildAnimatorEnded(mDelayAnim);
        }
    }

@@ -751,25 +752,39 @@ public final class AnimatorSet extends Animator {
        public void onAnimationEnd(Animator animation) {
            animation.removeListener(this);
            mAnimatorSet.mPlayingSet.remove(animation);
            Node animNode = mAnimatorSet.mNodeMap.get(animation);
            mAnimatorSet.onChildAnimatorEnded(animation);
        }

        // Nothing to do
        public void onAnimationRepeat(Animator animation) {
        }

        // Nothing to do
        public void onAnimationStart(Animator animation) {
        }

    }

    private void onChildAnimatorEnded(Animator animation) {
        Node animNode = mNodeMap.get(animation);
        animNode.mEnded = true;

            if (!mAnimatorSet.mTerminated) {
        if (!mTerminated) {
            List<Node> children = animNode.mChildNodes;
            // Start children animations, if any.
            int childrenSize = children == null ? 0 : children.size();
            for (int i = 0; i < childrenSize; i++) {
                if (children.get(i).mLatestParent == animNode) {
                        mAnimatorSet.start(children.get(i));
                    start(children.get(i));
                }
            }
            // Listeners are already notified of the AnimatorSet ending in cancel() or
            // end(); the logic below only kicks in when animations end normally
            boolean allDone = true;
            // Traverse the tree and find if there's any unfinished node
                int size = mAnimatorSet.mNodes.size();
            int size = mNodes.size();
            for (int i = 0; i < size; i++) {
                    if (!mAnimatorSet.mNodes.get(i).mEnded) {
                if (!mNodes.get(i).mEnded) {
                    allDone = false;
                    break;
                }
@@ -777,28 +792,18 @@ public final class AnimatorSet extends Animator {
            if (allDone) {
                // If this was the last child animation to end, then notify listeners that this
                // AnimatorSet has ended
                    if (mAnimatorSet.mListeners != null) {
                if (mListeners != null) {
                    ArrayList<AnimatorListener> tmpListeners =
                                (ArrayList<AnimatorListener>) mAnimatorSet.mListeners.clone();
                            (ArrayList<AnimatorListener>) mListeners.clone();
                    int numListeners = tmpListeners.size();
                    for (int i = 0; i < numListeners; ++i) {
                            tmpListeners.get(i).onAnimationEnd(mAnimatorSet);
                        }
                    }
                    mAnimatorSet.mStarted = false;
                    mAnimatorSet.mPaused = false;
                }
                        tmpListeners.get(i).onAnimationEnd(this);
                    }
                }

        // Nothing to do
        public void onAnimationRepeat(Animator animation) {
                mStarted = false;
                mPaused = false;
            }

        // Nothing to do
        public void onAnimationStart(Animator animation) {
        }

    }

    /**
+13 −3
Original line number Diff line number Diff line
@@ -924,6 +924,13 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio
        updateScaledDuration(); // in case the scale factor has changed since creation time
        AnimationHandler animationHandler = AnimationHandler.getInstance();
        animationHandler.addAnimationFrameCallback(this, mStartDelay);

        if (mStartDelay == 0) {
            // If there's no start delay, init the animation and notify start listeners right away
            // Otherwise, postpone this until the first frame after the start delay.
            startAnimation();
            setCurrentFraction(mSeekFraction == -1 ? 0 : mSeekFraction);
        }
    }

    @Override
@@ -1067,6 +1074,7 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio
        mStartListenersCalled = false;
        mPlayingBackwards = false;
        mReversing = false;
        mLastFrameTime = 0;
        mCurrentIteration = 0;
        if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
            Trace.asyncTraceEnd(Trace.TRACE_TAG_VIEW, getNameForTrace(),
@@ -1176,12 +1184,13 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio
     * @hide
     */
    public final void doAnimationFrame(long frameTime) {
        mLastFrameTime = frameTime;
        AnimationHandler handler = AnimationHandler.getInstance();
        if (!mRunning) {
        if (mLastFrameTime == 0) {
            // First frame
            handler.addOneShotCommitCallback(this);
            if (mStartDelay > 0) {
                startAnimation();
            }
            if (mSeekFraction < 0) {
                mStartTime = frameTime;
            } else {
@@ -1191,6 +1200,7 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio
            }
            mStartTimeCommitted = false; // allow start time to be compensated for jank
        }
        mLastFrameTime = frameTime;
        if (mPaused) {
            if (mPauseTime < 0) {
                mPauseTime = frameTime;