/*
 * Copyright (C) 2010 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.
 */

package android.animation;

import android.app.ActivityThread;
import android.app.Application;
import android.os.Build;
import android.os.Looper;
import android.util.AndroidRuntimeException;
import android.util.ArrayMap;
import android.util.Log;
import android.view.animation.Animation;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;

/**
 * This class plays a set of {@link Animator} objects in the specified order. Animations
 * can be set up to play together, in sequence, or after a specified delay.
 *
 * <p>There are two different approaches to adding animations to a <code>AnimatorSet</code>:
 * either the {@link AnimatorSet#playTogether(Animator[]) playTogether()} or
 * {@link AnimatorSet#playSequentially(Animator[]) playSequentially()} methods can be called to add
 * a set of animations all at once, or the {@link AnimatorSet#play(Animator)} can be
 * used in conjunction with methods in the {@link AnimatorSet.Builder Builder}
 * class to add animations
 * one by one.</p>
 *
 * <p>It is possible to set up a <code>AnimatorSet</code> with circular dependencies between
 * its animations. For example, an animation a1 could be set up to start before animation a2, a2
 * before a3, and a3 before a1. The results of this configuration are undefined, but will typically
 * result in none of the affected animations being played. Because of this (and because
 * circular dependencies do not make logical sense anyway), circular dependencies
 * should be avoided, and the dependency flow of animations should only be in one direction.
 *
 * <div class="special reference">
 * <h3>Developer Guides</h3>
 * <p>For more information about animating with {@code AnimatorSet}, read the
 * <a href="{@docRoot}guide/topics/graphics/prop-animation.html#choreography">Property
 * Animation</a> developer guide.</p>
 * </div>
 */
public final class AnimatorSet extends Animator implements AnimationHandler.AnimationFrameCallback {

    private static final String TAG = "AnimatorSet";
    /**
     * Internal variables
     * NOTE: This object implements the clone() method, making a deep copy of any referenced
     * objects. As other non-trivial fields are added to this class, make sure to add logic
     * to clone() to make deep copies of them.
     */

    /**
     * Tracks animations currently being played, so that we know what to
     * cancel or end when cancel() or end() is called on this AnimatorSet
     */
    private ArrayList<Node> mPlayingSet = new ArrayList<Node>();

    /**
     * Contains all nodes, mapped to their respective Animators. When new
     * dependency information is added for an Animator, we want to add it
     * to a single node representing that Animator, not create a new Node
     * if one already exists.
     */
    private ArrayMap<Animator, Node> mNodeMap = new ArrayMap<Animator, Node>();

    /**
     * Contains the start and end events of all the nodes. All these events are sorted in this list.
     */
    private ArrayList<AnimationEvent> mEvents = new ArrayList<>();

    /**
     * Set of all nodes created for this AnimatorSet. This list is used upon
     * starting the set, and the nodes are placed in sorted order into the
     * sortedNodes collection.
     */
    private ArrayList<Node> mNodes = new ArrayList<Node>();

    /**
     * Tracks whether any change has been made to the AnimatorSet, which is then used to
     * determine whether the dependency graph should be re-constructed.
     */
    private boolean mDependencyDirty = false;

    /**
     * Indicates whether an AnimatorSet has been start()'d, whether or
     * not there is a nonzero startDelay.
     */
    private boolean mStarted = false;

    // The amount of time in ms to delay starting the animation after start() is called
    private long mStartDelay = 0;

    // Animator used for a nonzero startDelay
    private ValueAnimator mDelayAnim = ValueAnimator.ofFloat(0f, 1f).setDuration(0);

    // Root of the dependency tree of all the animators in the set. In this tree, parent-child
    // relationship captures the order of animation (i.e. parent and child will play sequentially),
    // and sibling relationship indicates "with" relationship, as sibling animators start at the
    // same time.
    private Node mRootNode = new Node(mDelayAnim);

    // How long the child animations should last in ms. The default value is negative, which
    // simply means that there is no duration set on the AnimatorSet. When a real duration is
    // set, it is passed along to the child animations.
    private long mDuration = -1;

    // Records the interpolator for the set. Null value indicates that no interpolator
    // was set on this AnimatorSet, so it should not be passed down to the children.
    private TimeInterpolator mInterpolator = null;

    // The total duration of finishing all the Animators in the set.
    private long mTotalDuration = 0;

    // In pre-N releases, calling end() before start() on an animator set is no-op. But that is not
    // consistent with the behavior for other animator types. In order to keep the behavior
    // consistent within Animation framework, when end() is called without start(), we will start
    // the animator set and immediately end it for N and forward.
    private final boolean mShouldIgnoreEndWithoutStart;

    // In pre-O releases, calling start() doesn't reset all the animators values to start values.
    // As a result, the start of the animation is inconsistent with what setCurrentPlayTime(0) would
    // look like on O. Also it is inconsistent with what reverse() does on O, as reverse would
    // advance all the animations to the right beginning values for before starting to reverse.
    // From O and forward, we will add an additional step of resetting the animation values (unless
    // the animation was previously seeked and therefore doesn't start from the beginning).
    private final boolean mShouldResetValuesAtStart;

    // In pre-O releases, end() may never explicitly called on a child animator. As a result, end()
    // may not even be properly implemented in a lot of cases. After a few apps crashing on this,
    // it became necessary to use an sdk target guard for calling end().
    private final boolean mEndCanBeCalled;

    // The time, in milliseconds, when last frame of the animation came in. -1 when the animation is
    // not running.
    private long mLastFrameTime = -1;

    // The time, in milliseconds, when the first frame of the animation came in. This is the
    // frame before we start counting down the start delay, if any.
    // -1 when the animation is not running.
    private long mFirstFrame = -1;

    // The time, in milliseconds, when the first frame of the animation came in.
    // -1 when the animation is not running.
    private int mLastEventId = -1;

    // Indicates whether the animation is reversing.
    private boolean mReversing = false;

    // Indicates whether the animation should register frame callbacks. If false, the animation will
    // passively wait for an AnimatorSet to pulse it.
    private boolean mSelfPulse = true;

    // SeekState stores the last seeked play time as well as seek direction.
    private SeekState mSeekState = new SeekState();

    // Indicates where children animators are all initialized with their start values captured.
    private boolean mChildrenInitialized = false;

    /**
     * Set on the next frame after pause() is called, used to calculate a new startTime
     * or delayStartTime which allows the animator set to continue from the point at which
     * it was paused. If negative, has not yet been set.
     */
    private long mPauseTime = -1;

    // This is to work around a bug in b/34736819. This needs to be removed once app team
    // fixes their side.
    private AnimatorListenerAdapter mDummyListener = new AnimatorListenerAdapter() {
        @Override
        public void onAnimationEnd(Animator animation) {
            if (mNodeMap.get(animation) == null) {
                throw new AndroidRuntimeException("Error: animation ended is not in the node map");
            }
            mNodeMap.get(animation).mEnded = true;

        }
    };

    public AnimatorSet() {
        super();
        mNodeMap.put(mDelayAnim, mRootNode);
        mNodes.add(mRootNode);
        boolean isPreO;
        // Set the flag to ignore calling end() without start() for pre-N releases
        Application app = ActivityThread.currentApplication();
        if (app == null || app.getApplicationInfo() == null) {
            mShouldIgnoreEndWithoutStart = true;
            isPreO = true;
        } else {
            if (app.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N) {
                mShouldIgnoreEndWithoutStart = true;
            } else {
                mShouldIgnoreEndWithoutStart = false;
            }

            isPreO = app.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.O;
        }
        mShouldResetValuesAtStart = !isPreO;
        mEndCanBeCalled = !isPreO;
    }

    /**
     * Sets up this AnimatorSet to play all of the supplied animations at the same time.
     * This is equivalent to calling {@link #play(Animator)} with the first animator in the
     * set and then {@link Builder#with(Animator)} with each of the other animators. Note that
     * an Animator with a {@link Animator#setStartDelay(long) startDelay} will not actually
     * start until that delay elapses, which means that if the first animator in the list
     * supplied to this constructor has a startDelay, none of the other animators will start
     * until that first animator's startDelay has elapsed.
     *
     * @param items The animations that will be started simultaneously.
     */
    public void playTogether(Animator... items) {
        if (items != null) {
            Builder builder = play(items[0]);
            for (int i = 1; i < items.length; ++i) {
                builder.with(items[i]);
            }
        }
    }

    /**
     * Sets up this AnimatorSet to play all of the supplied animations at the same time.
     *
     * @param items The animations that will be started simultaneously.
     */
    public void playTogether(Collection<Animator> items) {
        if (items != null && items.size() > 0) {
            Builder builder = null;
            for (Animator anim : items) {
                if (builder == null) {
                    builder = play(anim);
                } else {
                    builder.with(anim);
                }
            }
        }
    }

    /**
     * Sets up this AnimatorSet to play each of the supplied animations when the
     * previous animation ends.
     *
     * @param items The animations that will be started one after another.
     */
    public void playSequentially(Animator... items) {
        if (items != null) {
            if (items.length == 1) {
                play(items[0]);
            } else {
                for (int i = 0; i < items.length - 1; ++i) {
                    play(items[i]).before(items[i + 1]);
                }
            }
        }
    }

    /**
     * Sets up this AnimatorSet to play each of the supplied animations when the
     * previous animation ends.
     *
     * @param items The animations that will be started one after another.
     */
    public void playSequentially(List<Animator> items) {
        if (items != null && items.size() > 0) {
            if (items.size() == 1) {
                play(items.get(0));
            } else {
                for (int i = 0; i < items.size() - 1; ++i) {
                    play(items.get(i)).before(items.get(i + 1));
                }
            }
        }
    }

    /**
     * Returns the current list of child Animator objects controlled by this
     * AnimatorSet. This is a copy of the internal list; modifications to the returned list
     * will not affect the AnimatorSet, although changes to the underlying Animator objects
     * will affect those objects being managed by the AnimatorSet.
     *
     * @return ArrayList<Animator> The list of child animations of this AnimatorSet.
     */
    public ArrayList<Animator> getChildAnimations() {
        ArrayList<Animator> childList = new ArrayList<Animator>();
        int size = mNodes.size();
        for (int i = 0; i < size; i++) {
            Node node = mNodes.get(i);
            if (node != mRootNode) {
                childList.add(node.mAnimation);
            }
        }
        return childList;
    }

    /**
     * Sets the target object for all current {@link #getChildAnimations() child animations}
     * of this AnimatorSet that take targets ({@link ObjectAnimator} and
     * AnimatorSet).
     *
     * @param target The object being animated
     */
    @Override
    public void setTarget(Object target) {
        int size = mNodes.size();
        for (int i = 0; i < size; i++) {
            Node node = mNodes.get(i);
            Animator animation = node.mAnimation;
            if (animation instanceof AnimatorSet) {
                ((AnimatorSet)animation).setTarget(target);
            } else if (animation instanceof ObjectAnimator) {
                ((ObjectAnimator)animation).setTarget(target);
            }
        }
    }

    /**
     * @hide
     */
    @Override
    public int getChangingConfigurations() {
        int conf = super.getChangingConfigurations();
        final int nodeCount = mNodes.size();
        for (int i = 0; i < nodeCount; i ++) {
            conf |= mNodes.get(i).mAnimation.getChangingConfigurations();
        }
        return conf;
    }

    /**
     * Sets the TimeInterpolator for all current {@link #getChildAnimations() child animations}
     * of this AnimatorSet. The default value is null, which means that no interpolator
     * is set on this AnimatorSet. Setting the interpolator to any non-null value
     * will cause that interpolator to be set on the child animations
     * when the set is started.
     *
     * @param interpolator the interpolator to be used by each child animation of this AnimatorSet
     */
    @Override
    public void setInterpolator(TimeInterpolator interpolator) {
        mInterpolator = interpolator;
    }

    @Override
    public TimeInterpolator getInterpolator() {
        return mInterpolator;
    }

    /**
     * This method creates a <code>Builder</code> object, which is used to
     * set up playing constraints. This initial <code>play()</code> method
     * tells the <code>Builder</code> the animation that is the dependency for
     * the succeeding commands to the <code>Builder</code>. For example,
     * calling <code>play(a1).with(a2)</code> sets up the AnimatorSet to play
     * <code>a1</code> and <code>a2</code> at the same time,
     * <code>play(a1).before(a2)</code> sets up the AnimatorSet to play
     * <code>a1</code> first, followed by <code>a2</code>, and
     * <code>play(a1).after(a2)</code> sets up the AnimatorSet to play
     * <code>a2</code> first, followed by <code>a1</code>.
     *
     * <p>Note that <code>play()</code> is the only way to tell the
     * <code>Builder</code> the animation upon which the dependency is created,
     * so successive calls to the various functions in <code>Builder</code>
     * will all refer to the initial parameter supplied in <code>play()</code>
     * as the dependency of the other animations. For example, calling
     * <code>play(a1).before(a2).before(a3)</code> will play both <code>a2</code>
     * and <code>a3</code> when a1 ends; it does not set up a dependency between
     * <code>a2</code> and <code>a3</code>.</p>
     *
     * @param anim The animation that is the dependency used in later calls to the
     * methods in the returned <code>Builder</code> object. A null parameter will result
     * in a null <code>Builder</code> return value.
     * @return Builder The object that constructs the AnimatorSet based on the dependencies
     * outlined in the calls to <code>play</code> and the other methods in the
     * <code>Builder</code object.
     */
    public Builder play(Animator anim) {
        if (anim != null) {
            return new Builder(anim);
        }
        return null;
    }

    /**
     * {@inheritDoc}
     *
     * <p>Note that canceling a <code>AnimatorSet</code> also cancels all of the animations that it
     * is responsible for.</p>
     */
    @SuppressWarnings("unchecked")
    @Override
    public void cancel() {
        if (Looper.myLooper() == null) {
            throw new AndroidRuntimeException("Animators may only be run on Looper threads");
        }
        if (isStarted()) {
            ArrayList<AnimatorListener> tmpListeners = null;
            if (mListeners != null) {
                tmpListeners = (ArrayList<AnimatorListener>) mListeners.clone();
                int size = tmpListeners.size();
                for (int i = 0; i < size; i++) {
                    tmpListeners.get(i).onAnimationCancel(this);
                }
            }
            ArrayList<Node> playingSet = new ArrayList<>(mPlayingSet);
            int setSize = playingSet.size();
            for (int i = 0; i < setSize; i++) {
                playingSet.get(i).mAnimation.cancel();
            }
            mPlayingSet.clear();
            endAnimation();
        }
    }

    // Force all the animations to end when the duration scale is 0.
    private void forceToEnd() {
        if (mEndCanBeCalled) {
            end();
            return;
        }

        // Note: we don't want to combine this case with the end() method below because in
        // the case of developer calling end(), we still need to make sure end() is explicitly
        // called on the child animators to maintain the old behavior.
        if (mReversing) {
            handleAnimationEvents(mLastEventId, 0, getTotalDuration());
        } else {
            long zeroScalePlayTime = getTotalDuration();
            if (zeroScalePlayTime == DURATION_INFINITE) {
                // Use a large number for the play time.
                zeroScalePlayTime = Integer.MAX_VALUE;
            }
            handleAnimationEvents(mLastEventId, mEvents.size() - 1, zeroScalePlayTime);
        }
        mPlayingSet.clear();
        endAnimation();
    }

    /**
     * {@inheritDoc}
     *
     * <p>Note that ending a <code>AnimatorSet</code> also ends all of the animations that it is
     * responsible for.</p>
     */
    @Override
    public void end() {
        if (Looper.myLooper() == null) {
            throw new AndroidRuntimeException("Animators may only be run on Looper threads");
        }
        if (mShouldIgnoreEndWithoutStart && !isStarted()) {
            return;
        }
        if (isStarted()) {
            // Iterate the animations that haven't finished or haven't started, and end them.
            if (mReversing) {
                // Between start() and first frame, mLastEventId would be unset (i.e. -1)
                mLastEventId = mLastEventId == -1 ? mEvents.size() : mLastEventId;
                while (mLastEventId > 0) {
                    mLastEventId = mLastEventId - 1;
                    AnimationEvent event = mEvents.get(mLastEventId);
                    Animator anim = event.mNode.mAnimation;
                    if (mNodeMap.get(anim).mEnded) {
                        continue;
                    }
                    if (event.mEvent == AnimationEvent.ANIMATION_END) {
                        anim.reverse();
                    } else if (event.mEvent == AnimationEvent.ANIMATION_DELAY_ENDED
                            && anim.isStarted()) {
                        // Make sure anim hasn't finished before calling end() so that we don't end
                        // already ended animations, which will cause start and end callbacks to be
                        // triggered again.
                        anim.end();
                    }
                }
            } else {
                while (mLastEventId < mEvents.size() - 1) {
                    // Avoid potential reentrant loop caused by child animators manipulating
                    // AnimatorSet's lifecycle (i.e. not a recommended approach).
                    mLastEventId = mLastEventId + 1;
                    AnimationEvent event = mEvents.get(mLastEventId);
                    Animator anim = event.mNode.mAnimation;
                    if (mNodeMap.get(anim).mEnded) {
                        continue;
                    }
                    if (event.mEvent == AnimationEvent.ANIMATION_START) {
                        anim.start();
                    } else if (event.mEvent == AnimationEvent.ANIMATION_END && anim.isStarted()) {
                        // Make sure anim hasn't finished before calling end() so that we don't end
                        // already ended animations, which will cause start and end callbacks to be
                        // triggered again.
                        anim.end();
                    }
                }
            }
            mPlayingSet.clear();
        }
        endAnimation();
    }

    /**
     * Returns true if any of the child animations of this AnimatorSet have been started and have
     * not yet ended. Child animations will not be started until the AnimatorSet has gone past
     * its initial delay set through {@link #setStartDelay(long)}.
     *
     * @return Whether this AnimatorSet has gone past the initial delay, and at least one child
     *         animation has been started and not yet ended.
     */
    @Override
    public boolean isRunning() {
        if (mStartDelay == 0) {
            return mStarted;
        }
        return mLastFrameTime > 0;
    }

    @Override
    public boolean isStarted() {
        return mStarted;
    }

    /**
     * The amount of time, in milliseconds, to delay starting the animation after
     * {@link #start()} is called.
     *
     * @return the number of milliseconds to delay running the animation
     */
    @Override
    public long getStartDelay() {
        return mStartDelay;
    }

    /**
     * The amount of time, in milliseconds, to delay starting the animation after
     * {@link #start()} is called. Note that the start delay should always be non-negative. Any
     * negative start delay will be clamped to 0 on N and above.
     *
     * @param startDelay The amount of the delay, in milliseconds
     */
    @Override
    public void setStartDelay(long startDelay) {
        // Clamp start delay to non-negative range.
        if (startDelay < 0) {
            Log.w(TAG, "Start delay should always be non-negative");
            startDelay = 0;
        }
        long delta = startDelay - mStartDelay;
        if (delta == 0) {
            return;
        }
        mStartDelay = startDelay;
        if (!mDependencyDirty) {
            // Dependency graph already constructed, update all the nodes' start/end time
            int size = mNodes.size();
            for (int i = 0; i < size; i++) {
                Node node = mNodes.get(i);
                if (node == mRootNode) {
                    node.mEndTime = mStartDelay;
                } else {
                    node.mStartTime = node.mStartTime == DURATION_INFINITE ?
                            DURATION_INFINITE : node.mStartTime + delta;
                    node.mEndTime = node.mEndTime == DURATION_INFINITE ?
                            DURATION_INFINITE : node.mEndTime + delta;
                }
            }
            // Update total duration, if necessary.
            if (mTotalDuration != DURATION_INFINITE) {
                mTotalDuration += delta;
            }
        }
    }

    /**
     * Gets the length of each of the child animations of this AnimatorSet. This value may
     * be less than 0, which indicates that no duration has been set on this AnimatorSet
     * and each of the child animations will use their own duration.
     *
     * @return The length of the animation, in milliseconds, of each of the child
     * animations of this AnimatorSet.
     */
    @Override
    public long getDuration() {
        return mDuration;
    }

    /**
     * Sets the length of each of the current child animations of this AnimatorSet. By default,
     * each child animation will use its own duration. If the duration is set on the AnimatorSet,
     * then each child animation inherits this duration.
     *
     * @param duration The length of the animation, in milliseconds, of each of the child
     * animations of this AnimatorSet.
     */
    @Override
    public AnimatorSet setDuration(long duration) {
        if (duration < 0) {
            throw new IllegalArgumentException("duration must be a value of zero or greater");
        }
        mDependencyDirty = true;
        // Just record the value for now - it will be used later when the AnimatorSet starts
        mDuration = duration;
        return this;
    }

    @Override
    public void setupStartValues() {
        int size = mNodes.size();
        for (int i = 0; i < size; i++) {
            Node node = mNodes.get(i);
            if (node != mRootNode) {
                node.mAnimation.setupStartValues();
            }
        }
    }

    @Override
    public void setupEndValues() {
        int size = mNodes.size();
        for (int i = 0; i < size; i++) {
            Node node = mNodes.get(i);
            if (node != mRootNode) {
                node.mAnimation.setupEndValues();
            }
        }
    }

    @Override
    public void pause() {
        if (Looper.myLooper() == null) {
            throw new AndroidRuntimeException("Animators may only be run on Looper threads");
        }
        boolean previouslyPaused = mPaused;
        super.pause();
        if (!previouslyPaused && mPaused) {
            mPauseTime = -1;
        }
    }

    @Override
    public void resume() {
        if (Looper.myLooper() == null) {
            throw new AndroidRuntimeException("Animators may only be run on Looper threads");
        }
        boolean previouslyPaused = mPaused;
        super.resume();
        if (previouslyPaused && !mPaused) {
            if (mPauseTime >= 0) {
                addAnimationCallback(0);
            }
        }
    }

    /**
     * {@inheritDoc}
     *
     * <p>Starting this <code>AnimatorSet</code> will, in turn, start the animations for which
     * it is responsible. The details of when exactly those animations are started depends on
     * the dependency relationships that have been set up between the animations.
     *
     * <b>Note:</b> Manipulating AnimatorSet's lifecycle in the child animators' listener callbacks
     * will lead to undefined behaviors. Also, AnimatorSet will ignore any seeking in the child
     * animators once {@link #start()} is called.
     */
    @SuppressWarnings("unchecked")
    @Override
    public void start() {
        start(false, true);
    }

    @Override
    void startWithoutPulsing(boolean inReverse) {
        start(inReverse, false);
    }

    private void initAnimation() {
        if (mInterpolator != null) {
            for (int i = 0; i < mNodes.size(); i++) {
                Node node = mNodes.get(i);
                node.mAnimation.setInterpolator(mInterpolator);
            }
        }
        updateAnimatorsDuration();
        createDependencyGraph();
    }

    private void start(boolean inReverse, boolean selfPulse) {
        if (Looper.myLooper() == null) {
            throw new AndroidRuntimeException("Animators may only be run on Looper threads");
        }
        mStarted = true;
        mSelfPulse = selfPulse;
        mPaused = false;
        mPauseTime = -1;

        int size = mNodes.size();
        for (int i = 0; i < size; i++) {
            Node node = mNodes.get(i);
            node.mEnded = false;
            node.mAnimation.setAllowRunningAsynchronously(false);
        }

        initAnimation();
        if (inReverse && !canReverse()) {
            throw new UnsupportedOperationException("Cannot reverse infinite AnimatorSet");
        }

        mReversing = inReverse;

        // Now that all dependencies are set up, start the animations that should be started.
        boolean isEmptySet = isEmptySet(this);
        if (!isEmptySet) {
            startAnimation();
        }

        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, inReverse);
            }
        }
        if (isEmptySet) {
            // In the case of empty AnimatorSet, or 0 duration scale, we will trigger the
            // onAnimationEnd() right away.
            end();
        }
    }

    // Returns true if set is empty or contains nothing but animator sets with no start delay.
    private static boolean isEmptySet(AnimatorSet set) {
        if (set.getStartDelay() > 0) {
            return false;
        }
        for (int i = 0; i < set.getChildAnimations().size(); i++) {
            Animator anim = set.getChildAnimations().get(i);
            if (!(anim instanceof AnimatorSet)) {
                // Contains non-AnimatorSet, not empty.
                return false;
            } else {
                if (!isEmptySet((AnimatorSet) anim)) {
                    return false;
                }
            }
        }
        return true;
    }

    private void updateAnimatorsDuration() {
        if (mDuration >= 0) {
            // If the duration was set on this AnimatorSet, pass it along to all child animations
            int size = mNodes.size();
            for (int i = 0; i < size; i++) {
                Node node = mNodes.get(i);
                // TODO: don't set the duration of the timing-only nodes created by AnimatorSet to
                // insert "play-after" delays
                node.mAnimation.setDuration(mDuration);
            }
        }
        mDelayAnim.setDuration(mStartDelay);
    }

    @Override
    void skipToEndValue(boolean inReverse) {
        if (!isInitialized()) {
            throw new UnsupportedOperationException("Children must be initialized.");
        }

        // This makes sure the animation events are sorted an up to date.
        initAnimation();

        // Calling skip to the end in the sequence that they would be called in a forward/reverse
        // run, such that the sequential animations modifying the same property would have
        // the right value in the end.
        if (inReverse) {
            for (int i = mEvents.size() - 1; i >= 0; i--) {
                if (mEvents.get(i).mEvent == AnimationEvent.ANIMATION_DELAY_ENDED) {
                    mEvents.get(i).mNode.mAnimation.skipToEndValue(true);
                }
            }
        } else {
            for (int i = 0; i < mEvents.size(); i++) {
                if (mEvents.get(i).mEvent == AnimationEvent.ANIMATION_END) {
                    mEvents.get(i).mNode.mAnimation.skipToEndValue(false);
                }
            }
        }
    }

    /**
     * Internal only.
     *
     * This method sets the animation values based on the play time. It also fast forward or
     * backward all the child animations progress accordingly.
     *
     * This method is also responsible for calling
     * {@link android.view.animation.Animation.AnimationListener#onAnimationRepeat(Animation)},
     * as needed, based on the last play time and current play time.
     */
    @Override
    void animateBasedOnPlayTime(long currentPlayTime, long lastPlayTime, boolean inReverse) {
        if (currentPlayTime < 0 || lastPlayTime < 0) {
            throw new UnsupportedOperationException("Error: Play time should never be negative.");
        }
        // TODO: take into account repeat counts and repeat callback when repeat is implemented.
        // Clamp currentPlayTime and lastPlayTime

        // TODO: Make this more efficient

        // Convert the play times to the forward direction.
        if (inReverse) {
            if (getTotalDuration() == DURATION_INFINITE) {
                throw new UnsupportedOperationException("Cannot reverse AnimatorSet with infinite"
                        + " duration");
            }
            long duration = getTotalDuration() - mStartDelay;
            currentPlayTime = Math.min(currentPlayTime, duration);
            currentPlayTime = duration - currentPlayTime;
            lastPlayTime = duration - lastPlayTime;
            inReverse = false;
        }
        // Skip all values to start, and iterate mEvents to get animations to the right fraction.
        skipToStartValue(false);

        ArrayList<Node> unfinishedNodes = new ArrayList<>();
        // Assumes forward playing from here on.
        for (int i = 0; i < mEvents.size(); i++) {
            AnimationEvent event = mEvents.get(i);
            if (event.getTime() > currentPlayTime || event.getTime() == DURATION_INFINITE) {
                break;
            }

            // This animation started prior to the current play time, and won't finish before the
            // play time, add to the unfinished list.
            if (event.mEvent == AnimationEvent.ANIMATION_DELAY_ENDED) {
                if (event.mNode.mEndTime == DURATION_INFINITE
                        || event.mNode.mEndTime > currentPlayTime) {
                    unfinishedNodes.add(event.mNode);
                }
            }
            // For animations that do finish before the play time, end them in the sequence that
            // they would in a normal run.
            if (event.mEvent == AnimationEvent.ANIMATION_END) {
                // Skip to the end of the animation.
                event.mNode.mAnimation.skipToEndValue(false);
            }
        }

        // Seek unfinished animation to the right time.
        for (int i = 0; i < unfinishedNodes.size(); i++) {
            Node node = unfinishedNodes.get(i);
            long playTime = getPlayTimeForNode(currentPlayTime, node, inReverse);
            if (!inReverse) {
                playTime -= node.mAnimation.getStartDelay();
            }
            node.mAnimation.animateBasedOnPlayTime(playTime, lastPlayTime, inReverse);
        }
    }

    @Override
    boolean isInitialized() {
        if (mChildrenInitialized) {
            return true;
        }

        boolean allInitialized = true;
        for (int i = 0; i < mNodes.size(); i++) {
            if (!mNodes.get(i).mAnimation.isInitialized()) {
                allInitialized = false;
                break;
            }
        }
        mChildrenInitialized = allInitialized;
        return mChildrenInitialized;
    }

    private void skipToStartValue(boolean inReverse) {
        skipToEndValue(!inReverse);
    }

    /**
     * Sets the position of the animation to the specified point in time. This time should
     * be between 0 and the total duration of the animation, including any repetition. If
     * the animation has not yet been started, then it will not advance forward after it is
     * set to this time; it will simply set the time to this value and perform any appropriate
     * actions based on that time. If the animation is already running, then setCurrentPlayTime()
     * will set the current playing time to this value and continue playing from that point.
     *
     * @param playTime The time, in milliseconds, to which the animation is advanced or rewound.
     *                 Unless the animation is reversing, the playtime is considered the time since
     *                 the end of the start delay of the AnimatorSet in a forward playing direction.
     *
     */
    public void setCurrentPlayTime(long playTime) {
        if (mReversing && getTotalDuration() == DURATION_INFINITE) {
            // Should never get here
            throw new UnsupportedOperationException("Error: Cannot seek in reverse in an infinite"
                    + " AnimatorSet");
        }

        if ((getTotalDuration() != DURATION_INFINITE && playTime > getTotalDuration() - mStartDelay)
                || playTime < 0) {
            throw new UnsupportedOperationException("Error: Play time should always be in between"
                    + "0 and duration.");
        }

        initAnimation();

        if (!isStarted()) {
            if (mReversing) {
                throw new UnsupportedOperationException("Error: Something went wrong. mReversing"
                        + " should not be set when AnimatorSet is not started.");
            }
            if (!mSeekState.isActive()) {
                findLatestEventIdForTime(0);
                // Set all the values to start values.
                initChildren();
                skipToStartValue(mReversing);
                mSeekState.setPlayTime(0, mReversing);
            }
            animateBasedOnPlayTime(playTime, 0, mReversing);
            mSeekState.setPlayTime(playTime, mReversing);
        } else {
            // If the animation is running, just set the seek time and wait until the next frame
            // (i.e. doAnimationFrame(...)) to advance the animation.
            mSeekState.setPlayTime(playTime, mReversing);
        }
    }

    /**
     * Returns the milliseconds elapsed since the start of the animation.
     *
     * <p>For ongoing animations, this method returns the current progress of the animation in
     * terms of play time. For an animation that has not yet been started: if the animation has been
     * seeked to a certain time via {@link #setCurrentPlayTime(long)}, the seeked play time will
     * be returned; otherwise, this method will return 0.
     *
     * @return the current position in time of the animation in milliseconds
     */
    public long getCurrentPlayTime() {
        if (mSeekState.isActive()) {
            return mSeekState.getPlayTime();
        }
        if (mLastFrameTime == -1) {
            // Not yet started or during start delay
            return 0;
        }
        float durationScale = ValueAnimator.getDurationScale();
        durationScale = durationScale == 0 ? 1 : durationScale;
        if (mReversing) {
            return (long) ((mLastFrameTime - mFirstFrame) / durationScale);
        } else {
            return (long) ((mLastFrameTime - mFirstFrame - mStartDelay) / durationScale);
        }
    }

    private void initChildren() {
        if (!isInitialized()) {
            mChildrenInitialized = true;
            // Forcefully initialize all children based on their end time, so that if the start
            // value of a child is dependent on a previous animation, the animation will be
            // initialized after the the previous animations have been advanced to the end.
            skipToEndValue(false);
        }
    }

    /**
     * @param frameTime The frame start time, in the {@link SystemClock#uptimeMillis()} time
     *                  base.
     * @return
     * @hide
     */
    @Override
    public boolean doAnimationFrame(long frameTime) {
        float durationScale = ValueAnimator.getDurationScale();
        if (durationScale == 0f) {
            // Duration scale is 0, end the animation right away.
            forceToEnd();
            return true;
        }

        // After the first frame comes in, we need to wait for start delay to pass before updating
        // any animation values.
        if (mFirstFrame < 0) {
            mFirstFrame = frameTime;
        }

        // Handle pause/resume
        if (mPaused) {
            // Note: Child animations don't receive pause events. Since it's never a contract that
            // the child animators will be paused when set is paused, this is unlikely to be an
            // issue.
            mPauseTime = frameTime;
            removeAnimationCallback();
            return false;
        } else if (mPauseTime > 0) {
                // Offset by the duration that the animation was paused
            mFirstFrame += (frameTime - mPauseTime);
            mPauseTime = -1;
        }

        // Continue at seeked position
        if (mSeekState.isActive()) {
            mSeekState.updateSeekDirection(mReversing);
            if (mReversing) {
                mFirstFrame = (long) (frameTime - mSeekState.getPlayTime() * durationScale);
            } else {
                mFirstFrame = (long) (frameTime - (mSeekState.getPlayTime() + mStartDelay)
                        * durationScale);
            }
            mSeekState.reset();
        }

        if (!mReversing && frameTime < mFirstFrame + mStartDelay * durationScale) {
            // Still during start delay in a forward playing case.
            return false;
        }

        // From here on, we always use unscaled play time. Note this unscaled playtime includes
        // the start delay.
        long unscaledPlayTime = (long) ((frameTime - mFirstFrame) / durationScale);
        mLastFrameTime = frameTime;

        // 1. Pulse the animators that will start or end in this frame
        // 2. Pulse the animators that will finish in a later frame
        int latestId = findLatestEventIdForTime(unscaledPlayTime);
        int startId = mLastEventId;

        handleAnimationEvents(startId, latestId, unscaledPlayTime);

        mLastEventId = latestId;

        // Pump a frame to the on-going animators
        for (int i = 0; i < mPlayingSet.size(); i++) {
            Node node = mPlayingSet.get(i);
            if (!node.mEnded) {
                pulseFrame(node, getPlayTimeForNode(unscaledPlayTime, node));
            }
        }

        // Remove all the finished anims
        for (int i = mPlayingSet.size() - 1; i >= 0; i--) {
            if (mPlayingSet.get(i).mEnded) {
                mPlayingSet.remove(i);
            }
        }

        boolean finished = false;
        if (mReversing) {
            if (mPlayingSet.size() == 1 && mPlayingSet.get(0) == mRootNode) {
                // The only animation that is running is the delay animation.
                finished = true;
            } else if (mPlayingSet.isEmpty() && mLastEventId < 3) {
                // The only remaining animation is the delay animation
                finished = true;
            }
        } else {
            finished = mPlayingSet.isEmpty() && mLastEventId == mEvents.size() - 1;
        }

        if (finished) {
            endAnimation();
            return true;
        }
        return false;
    }

    /**
     * @hide
     */
    @Override
    public void commitAnimationFrame(long frameTime) {
        // No op.
    }

    @Override
    boolean pulseAnimationFrame(long frameTime) {
        return doAnimationFrame(frameTime);
    }

    /**
     * When playing forward, we call start() at the animation's scheduled start time, and make sure
     * to pump a frame at the animation's scheduled end time.
     *
     * When playing in reverse, we should reverse the animation when we hit animation's end event,
     * and expect the animation to end at the its delay ended event, rather than start event.
     */
    private void handleAnimationEvents(int startId, int latestId, long playTime) {
        if (mReversing) {
            startId = startId == -1 ? mEvents.size() : startId;
            for (int i = startId - 1; i >= latestId; i--) {
                AnimationEvent event = mEvents.get(i);
                Node node = event.mNode;
                if (event.mEvent == AnimationEvent.ANIMATION_END) {
                    if (node.mAnimation.isStarted()) {
                        // If the animation has already been started before its due time (i.e.
                        // the child animator is being manipulated outside of the AnimatorSet), we
                        // need to cancel the animation to reset the internal state (e.g. frame
                        // time tracking) and remove the self pulsing callbacks
                        node.mAnimation.cancel();
                    }
                    node.mEnded = false;
                    mPlayingSet.add(event.mNode);
                    node.mAnimation.startWithoutPulsing(true);
                    pulseFrame(node, 0);
                } else if (event.mEvent == AnimationEvent.ANIMATION_DELAY_ENDED && !node.mEnded) {
                    // end event:
                    pulseFrame(node, getPlayTimeForNode(playTime, node));
                }
            }
        } else {
            for (int i = startId + 1; i <= latestId; i++) {
                AnimationEvent event = mEvents.get(i);
                Node node = event.mNode;
                if (event.mEvent == AnimationEvent.ANIMATION_START) {
                    mPlayingSet.add(event.mNode);
                    if (node.mAnimation.isStarted()) {
                        // If the animation has already been started before its due time (i.e.
                        // the child animator is being manipulated outside of the AnimatorSet), we
                        // need to cancel the animation to reset the internal state (e.g. frame
                        // time tracking) and remove the self pulsing callbacks
                        node.mAnimation.cancel();
                    }
                    node.mEnded = false;
                    node.mAnimation.startWithoutPulsing(false);
                    pulseFrame(node, 0);
                } else if (event.mEvent == AnimationEvent.ANIMATION_END && !node.mEnded) {
                    // start event:
                    pulseFrame(node, getPlayTimeForNode(playTime, node));
                }
            }
        }
    }

    /**
     * This method pulses frames into child animations. It scales the input animation play time
     * with the duration scale and pass that to the child animation via pulseAnimationFrame(long).
     *
     * @param node child animator node
     * @param animPlayTime unscaled play time (including start delay) for the child animator
     */
    private void pulseFrame(Node node, long animPlayTime) {
        if (!node.mEnded) {
            float durationScale = ValueAnimator.getDurationScale();
            durationScale = durationScale == 0  ? 1 : durationScale;
            node.mEnded = node.mAnimation.pulseAnimationFrame(
                    (long) (animPlayTime * durationScale));
        }
    }

    private long getPlayTimeForNode(long overallPlayTime, Node node) {
        return getPlayTimeForNode(overallPlayTime, node, mReversing);
    }

    private long getPlayTimeForNode(long overallPlayTime, Node node, boolean inReverse) {
        if (inReverse) {
            overallPlayTime = getTotalDuration() - overallPlayTime;
            return node.mEndTime - overallPlayTime;
        } else {
            return overallPlayTime - node.mStartTime;
        }
    }

    private void startAnimation() {
        addDummyListener();

        // Register animation callback
        addAnimationCallback(0);

        if (mSeekState.getPlayTimeNormalized() == 0 && mReversing) {
            // Maintain old behavior, if seeked to 0 then call reverse, we'll treat the case
            // the same as no seeking at all.
            mSeekState.reset();
        }
        // Set the child animators to the right end:
        if (mShouldResetValuesAtStart) {
            if (isInitialized()) {
                skipToEndValue(!mReversing);
            } else if (mReversing) {
                // Reversing but haven't initialized all the children yet.
                initChildren();
                skipToEndValue(!mReversing);
            } else {
                // If not all children are initialized and play direction is forward
                for (int i = mEvents.size() - 1; i >= 0; i--) {
                    if (mEvents.get(i).mEvent == AnimationEvent.ANIMATION_DELAY_ENDED) {
                        Animator anim = mEvents.get(i).mNode.mAnimation;
                        // Only reset the animations that have been initialized to start value,
                        // so that if they are defined without a start value, they will get the
                        // values set at the right time (i.e. the next animation run)
                        if (anim.isInitialized()) {
                            anim.skipToEndValue(true);
                        }
                    }
                }
            }
        }

        if (mReversing || mStartDelay == 0 || mSeekState.isActive()) {
            long playTime;
            // If no delay, we need to call start on the first animations to be consistent with old
            // behavior.
            if (mSeekState.isActive()) {
                mSeekState.updateSeekDirection(mReversing);
                playTime = mSeekState.getPlayTime();
            } else {
                playTime = 0;
            }
            int toId = findLatestEventIdForTime(playTime);
            handleAnimationEvents(-1, toId, playTime);
            for (int i = mPlayingSet.size() - 1; i >= 0; i--) {
                if (mPlayingSet.get(i).mEnded) {
                    mPlayingSet.remove(i);
                }
            }
            mLastEventId = toId;
        }
    }

    // This is to work around the issue in b/34736819, as the old behavior in AnimatorSet had
    // masked a real bug in play movies. TODO: remove this and below once the root cause is fixed.
    private void addDummyListener() {
        for (int i = 1; i < mNodes.size(); i++) {
            mNodes.get(i).mAnimation.addListener(mDummyListener);
        }
    }

    private void removeDummyListener() {
        for (int i = 1; i < mNodes.size(); i++) {
            mNodes.get(i).mAnimation.removeListener(mDummyListener);
        }
    }

    private int findLatestEventIdForTime(long currentPlayTime) {
        int size = mEvents.size();
        int latestId = mLastEventId;
        // Call start on the first animations now to be consistent with the old behavior
        if (mReversing) {
            currentPlayTime = getTotalDuration() - currentPlayTime;
            mLastEventId = mLastEventId == -1 ? size : mLastEventId;
            for (int j = mLastEventId - 1; j >= 0; j--) {
                AnimationEvent event = mEvents.get(j);
                if (event.getTime() >= currentPlayTime) {
                    latestId = j;
                }
            }
        } else {
            for (int i = mLastEventId + 1; i < size; i++) {
                AnimationEvent event = mEvents.get(i);
                // TODO: need a function that accounts for infinite duration to compare time
                if (event.getTime() != DURATION_INFINITE && event.getTime() <= currentPlayTime) {
                    latestId = i;
                }
            }
        }
        return latestId;
    }

    private void endAnimation() {
        mStarted = false;
        mLastFrameTime = -1;
        mFirstFrame = -1;
        mLastEventId = -1;
        mPaused = false;
        mPauseTime = -1;
        mSeekState.reset();
        mPlayingSet.clear();

        // No longer receive callbacks
        removeAnimationCallback();
        // Call end listener
        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, mReversing);
            }
        }
        removeDummyListener();
        mSelfPulse = true;
        mReversing = false;
    }

    private void removeAnimationCallback() {
        if (!mSelfPulse) {
            return;
        }
        AnimationHandler handler = AnimationHandler.getInstance();
        handler.removeCallback(this);
    }

    private void addAnimationCallback(long delay) {
        if (!mSelfPulse) {
            return;
        }
        AnimationHandler handler = AnimationHandler.getInstance();
        handler.addAnimationFrameCallback(this, delay);
    }

    @Override
    public AnimatorSet clone() {
        final AnimatorSet anim = (AnimatorSet) super.clone();
        /*
         * The basic clone() operation copies all items. This doesn't work very well for
         * AnimatorSet, because it will copy references that need to be recreated and state
         * that may not apply. What we need to do now is put the clone in an uninitialized
         * state, with fresh, empty data structures. Then we will build up the nodes list
         * manually, as we clone each Node (and its animation). The clone will then be sorted,
         * and will populate any appropriate lists, when it is started.
         */
        final int nodeCount = mNodes.size();
        anim.mStarted = false;
        anim.mLastFrameTime = -1;
        anim.mFirstFrame = -1;
        anim.mLastEventId = -1;
        anim.mPaused = false;
        anim.mPauseTime = -1;
        anim.mSeekState = new SeekState();
        anim.mSelfPulse = true;
        anim.mPlayingSet = new ArrayList<Node>();
        anim.mNodeMap = new ArrayMap<Animator, Node>();
        anim.mNodes = new ArrayList<Node>(nodeCount);
        anim.mEvents = new ArrayList<AnimationEvent>();
        anim.mDummyListener = new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                if (anim.mNodeMap.get(animation) == null) {
                    throw new AndroidRuntimeException("Error: animation ended is not in the node"
                            + " map");
                }
                anim.mNodeMap.get(animation).mEnded = true;

            }
        };
        anim.mReversing = false;
        anim.mDependencyDirty = true;

        // Walk through the old nodes list, cloning each node and adding it to the new nodemap.
        // One problem is that the old node dependencies point to nodes in the old AnimatorSet.
        // We need to track the old/new nodes in order to reconstruct the dependencies in the clone.

        HashMap<Node, Node> clonesMap = new HashMap<>(nodeCount);
        for (int n = 0; n < nodeCount; n++) {
            final Node node = mNodes.get(n);
            Node nodeClone = node.clone();
            // Remove the old internal listener from the cloned child
            nodeClone.mAnimation.removeListener(mDummyListener);
            clonesMap.put(node, nodeClone);
            anim.mNodes.add(nodeClone);
            anim.mNodeMap.put(nodeClone.mAnimation, nodeClone);
        }

        anim.mRootNode = clonesMap.get(mRootNode);
        anim.mDelayAnim = (ValueAnimator) anim.mRootNode.mAnimation;

        // Now that we've cloned all of the nodes, we're ready to walk through their
        // dependencies, mapping the old dependencies to the new nodes
        for (int i = 0; i < nodeCount; i++) {
            Node node = mNodes.get(i);
            // Update dependencies for node's clone
            Node nodeClone = clonesMap.get(node);
            nodeClone.mLatestParent = node.mLatestParent == null
                    ? null : clonesMap.get(node.mLatestParent);
            int size = node.mChildNodes == null ? 0 : node.mChildNodes.size();
            for (int j = 0; j < size; j++) {
                nodeClone.mChildNodes.set(j, clonesMap.get(node.mChildNodes.get(j)));
            }
            size = node.mSiblings == null ? 0 : node.mSiblings.size();
            for (int j = 0; j < size; j++) {
                nodeClone.mSiblings.set(j, clonesMap.get(node.mSiblings.get(j)));
            }
            size = node.mParents == null ? 0 : node.mParents.size();
            for (int j = 0; j < size; j++) {
                nodeClone.mParents.set(j, clonesMap.get(node.mParents.get(j)));
            }
        }
        return anim;
    }


    /**
     * AnimatorSet is only reversible when the set contains no sequential animation, and no child
     * animators have a start delay.
     * @hide
     */
    @Override
    public boolean canReverse() {
        return getTotalDuration() != DURATION_INFINITE;
    }

    /**
     * Plays the AnimatorSet in reverse. If the animation has been seeked to a specific play time
     * using {@link #setCurrentPlayTime(long)}, it will play backwards from the point seeked when
     * reverse was called. Otherwise, then it will start from the end and play backwards. This
     * behavior is only set for the current animation; future playing of the animation will use the
     * default behavior of playing forward.
     * <p>
     * Note: reverse is not supported for infinite AnimatorSet.
     */
    @Override
    public void reverse() {
        start(true, true);
    }

    @Override
    public String toString() {
        String returnVal = "AnimatorSet@" + Integer.toHexString(hashCode()) + "{";
        int size = mNodes.size();
        for (int i = 0; i < size; i++) {
            Node node = mNodes.get(i);
            returnVal += "\n    " + node.mAnimation.toString();
        }
        return returnVal + "\n}";
    }

    private void printChildCount() {
        // Print out the child count through a level traverse.
        ArrayList<Node> list = new ArrayList<>(mNodes.size());
        list.add(mRootNode);
        Log.d(TAG, "Current tree: ");
        int index = 0;
        while (index < list.size()) {
            int listSize = list.size();
            StringBuilder builder = new StringBuilder();
            for (; index < listSize; index++) {
                Node node = list.get(index);
                int num = 0;
                if (node.mChildNodes != null) {
                    for (int i = 0; i < node.mChildNodes.size(); i++) {
                        Node child = node.mChildNodes.get(i);
                        if (child.mLatestParent == node) {
                            num++;
                            list.add(child);
                        }
                    }
                }
                builder.append(" ");
                builder.append(num);
            }
            Log.d(TAG, builder.toString());
        }
    }

    private void createDependencyGraph() {
        if (!mDependencyDirty) {
            // Check whether any duration of the child animations has changed
            boolean durationChanged = false;
            for (int i = 0; i < mNodes.size(); i++) {
                Animator anim = mNodes.get(i).mAnimation;
                if (mNodes.get(i).mTotalDuration != anim.getTotalDuration()) {
                    durationChanged = true;
                    break;
                }
            }
            if (!durationChanged) {
                return;
            }
        }

        mDependencyDirty = false;
        // Traverse all the siblings and make sure they have all the parents
        int size = mNodes.size();
        for (int i = 0; i < size; i++) {
            mNodes.get(i).mParentsAdded = false;
        }
        for (int i = 0; i < size; i++) {
            Node node = mNodes.get(i);
            if (node.mParentsAdded) {
                continue;
            }

            node.mParentsAdded = true;
            if (node.mSiblings == null) {
                continue;
            }

            // Find all the siblings
            findSiblings(node, node.mSiblings);
            node.mSiblings.remove(node);

            // Get parents from all siblings
            int siblingSize = node.mSiblings.size();
            for (int j = 0; j < siblingSize; j++) {
                node.addParents(node.mSiblings.get(j).mParents);
            }

            // Now make sure all siblings share the same set of parents
            for (int j = 0; j < siblingSize; j++) {
                Node sibling = node.mSiblings.get(j);
                sibling.addParents(node.mParents);
                sibling.mParentsAdded = true;
            }
        }

        for (int i = 0; i < size; i++) {
            Node node = mNodes.get(i);
            if (node != mRootNode && node.mParents == null) {
                node.addParent(mRootNode);
            }
        }

        // Do a DFS on the tree
        ArrayList<Node> visited = new ArrayList<Node>(mNodes.size());
        // Assign start/end time
        mRootNode.mStartTime = 0;
        mRootNode.mEndTime = mDelayAnim.getDuration();
        updatePlayTime(mRootNode, visited);

        sortAnimationEvents();
        mTotalDuration = mEvents.get(mEvents.size() - 1).getTime();
    }

    private void sortAnimationEvents() {
        // Sort the list of events in ascending order of their time
        // Create the list including the delay animation.
        mEvents.clear();
        for (int i = 1; i < mNodes.size(); i++) {
            Node node = mNodes.get(i);
            mEvents.add(new AnimationEvent(node, AnimationEvent.ANIMATION_START));
            mEvents.add(new AnimationEvent(node, AnimationEvent.ANIMATION_DELAY_ENDED));
            mEvents.add(new AnimationEvent(node, AnimationEvent.ANIMATION_END));
        }
        mEvents.sort(new Comparator<AnimationEvent>() {
            @Override
            public int compare(AnimationEvent e1, AnimationEvent e2) {
                long t1 = e1.getTime();
                long t2 = e2.getTime();
                if (t1 == t2) {
                    // For events that happen at the same time, we need them to be in the sequence
                    // (end, start, start delay ended)
                    if (e2.mEvent + e1.mEvent == AnimationEvent.ANIMATION_START
                            + AnimationEvent.ANIMATION_DELAY_ENDED) {
                        // Ensure start delay happens after start
                        return e1.mEvent - e2.mEvent;
                    } else {
                        return e2.mEvent - e1.mEvent;
                    }
                }
                if (t2 == DURATION_INFINITE) {
                    return -1;
                }
                if (t1 == DURATION_INFINITE) {
                    return 1;
                }
                // When neither event happens at INFINITE time:
                return (int) (t1 - t2);
            }
        });

        int eventSize = mEvents.size();
        // For the same animation, start event has to happen before end.
        for (int i = 0; i < eventSize;) {
            AnimationEvent event = mEvents.get(i);
            if (event.mEvent == AnimationEvent.ANIMATION_END) {
                boolean needToSwapStart;
                if (event.mNode.mStartTime == event.mNode.mEndTime) {
                    needToSwapStart = true;
                } else if (event.mNode.mEndTime == event.mNode.mStartTime
                        + event.mNode.mAnimation.getStartDelay()) {
                    // Swapping start delay
                    needToSwapStart = false;
                } else {
                    i++;
                    continue;
                }

                int startEventId = eventSize;
                int startDelayEndId = eventSize;
                for (int j = i + 1; j < eventSize; j++) {
                    if (startEventId < eventSize && startDelayEndId < eventSize) {
                        break;
                    }
                    if (mEvents.get(j).mNode == event.mNode) {
                        if (mEvents.get(j).mEvent == AnimationEvent.ANIMATION_START) {
                            // Found start event
                            startEventId = j;
                        } else if (mEvents.get(j).mEvent == AnimationEvent.ANIMATION_DELAY_ENDED) {
                            startDelayEndId = j;
                        }
                    }

                }
                if (needToSwapStart && startEventId == mEvents.size()) {
                    throw new UnsupportedOperationException("Something went wrong, no start is"
                            + "found after stop for an animation that has the same start and end"
                            + "time.");

                }
                if (startDelayEndId == mEvents.size()) {
                    throw new UnsupportedOperationException("Something went wrong, no start"
                            + "delay end is found after stop for an animation");

                }

                // We need to make sure start is inserted before start delay ended event,
                // because otherwise inserting start delay ended events first would change
                // the start event index.
                if (needToSwapStart) {
                    AnimationEvent startEvent = mEvents.remove(startEventId);
                    mEvents.add(i, startEvent);
                    i++;
                }

                AnimationEvent startDelayEndEvent = mEvents.remove(startDelayEndId);
                mEvents.add(i, startDelayEndEvent);
                i += 2;
            } else {
                i++;
            }
        }

        if (!mEvents.isEmpty() && mEvents.get(0).mEvent != AnimationEvent.ANIMATION_START) {
            throw new UnsupportedOperationException(
                    "Sorting went bad, the start event should always be at index 0");
        }

        // Add AnimatorSet's start delay node to the beginning
        mEvents.add(0, new AnimationEvent(mRootNode, AnimationEvent.ANIMATION_START));
        mEvents.add(1, new AnimationEvent(mRootNode, AnimationEvent.ANIMATION_DELAY_ENDED));
        mEvents.add(2, new AnimationEvent(mRootNode, AnimationEvent.ANIMATION_END));

        if (mEvents.get(mEvents.size() - 1).mEvent == AnimationEvent.ANIMATION_START
                || mEvents.get(mEvents.size() - 1).mEvent == AnimationEvent.ANIMATION_DELAY_ENDED) {
            throw new UnsupportedOperationException(
                    "Something went wrong, the last event is not an end event");
        }
    }

    /**
     * Based on parent's start/end time, calculate children's start/end time. If cycle exists in
     * the graph, all the nodes on the cycle will be marked to start at {@link #DURATION_INFINITE},
     * meaning they will ever play.
     */
    private void updatePlayTime(Node parent,  ArrayList<Node> visited) {
        if (parent.mChildNodes == null) {
            if (parent == mRootNode) {
                // All the animators are in a cycle
                for (int i = 0; i < mNodes.size(); i++) {
                    Node node = mNodes.get(i);
                    if (node != mRootNode) {
                        node.mStartTime = DURATION_INFINITE;
                        node.mEndTime = DURATION_INFINITE;
                    }
                }
            }
            return;
        }

        visited.add(parent);
        int childrenSize = parent.mChildNodes.size();
        for (int i = 0; i < childrenSize; i++) {
            Node child = parent.mChildNodes.get(i);
            child.mTotalDuration = child.mAnimation.getTotalDuration();  // Update cached duration.

            int index = visited.indexOf(child);
            if (index >= 0) {
                // Child has been visited, cycle found. Mark all the nodes in the cycle.
                for (int j = index; j < visited.size(); j++) {
                    visited.get(j).mLatestParent = null;
                    visited.get(j).mStartTime = DURATION_INFINITE;
                    visited.get(j).mEndTime = DURATION_INFINITE;
                }
                child.mStartTime = DURATION_INFINITE;
                child.mEndTime = DURATION_INFINITE;
                child.mLatestParent = null;
                Log.w(TAG, "Cycle found in AnimatorSet: " + this);
                continue;
            }

            if (child.mStartTime != DURATION_INFINITE) {
                if (parent.mEndTime == DURATION_INFINITE) {
                    child.mLatestParent = parent;
                    child.mStartTime = DURATION_INFINITE;
                    child.mEndTime = DURATION_INFINITE;
                } else {
                    if (parent.mEndTime >= child.mStartTime) {
                        child.mLatestParent = parent;
                        child.mStartTime = parent.mEndTime;
                    }

                    child.mEndTime = child.mTotalDuration == DURATION_INFINITE
                            ? DURATION_INFINITE : child.mStartTime + child.mTotalDuration;
                }
            }
            updatePlayTime(child, visited);
        }
        visited.remove(parent);
    }

    // Recursively find all the siblings
    private void findSiblings(Node node, ArrayList<Node> siblings) {
        if (!siblings.contains(node)) {
            siblings.add(node);
            if (node.mSiblings == null) {
                return;
            }
            for (int i = 0; i < node.mSiblings.size(); i++) {
                findSiblings(node.mSiblings.get(i), siblings);
            }
        }
    }

    /**
     * @hide
     * TODO: For animatorSet defined in XML, we can use a flag to indicate what the play order
     * if defined (i.e. sequential or together), then we can use the flag instead of calculating
     * dynamically. Note that when AnimatorSet is empty this method returns true.
     * @return whether all the animators in the set are supposed to play together
     */
    public boolean shouldPlayTogether() {
        updateAnimatorsDuration();
        createDependencyGraph();
        // All the child nodes are set out to play right after the delay animation
        return mRootNode.mChildNodes == null || mRootNode.mChildNodes.size() == mNodes.size() - 1;
    }

    @Override
    public long getTotalDuration() {
        updateAnimatorsDuration();
        createDependencyGraph();
        return mTotalDuration;
    }

    private Node getNodeForAnimation(Animator anim) {
        Node node = mNodeMap.get(anim);
        if (node == null) {
            node = new Node(anim);
            mNodeMap.put(anim, node);
            mNodes.add(node);
        }
        return node;
    }

    /**
     * A Node is an embodiment of both the Animator that it wraps as well as
     * any dependencies that are associated with that Animation. This includes
     * both dependencies upon other nodes (in the dependencies list) as
     * well as dependencies of other nodes upon this (in the nodeDependents list).
     */
    private static class Node implements Cloneable {
        Animator mAnimation;

        /**
         * Child nodes are the nodes associated with animations that will be played immediately
         * after current node.
         */
        ArrayList<Node> mChildNodes = null;

        /**
         * Flag indicating whether the animation in this node is finished. This flag
         * is used by AnimatorSet to check, as each animation ends, whether all child animations
         * are mEnded and it's time to send out an end event for the entire AnimatorSet.
         */
        boolean mEnded = false;

        /**
         * Nodes with animations that are defined to play simultaneously with the animation
         * associated with this current node.
         */
        ArrayList<Node> mSiblings;

        /**
         * Parent nodes are the nodes with animations preceding current node's animation. Parent
         * nodes here are derived from user defined animation sequence.
         */
        ArrayList<Node> mParents;

        /**
         * Latest parent is the parent node associated with a animation that finishes after all
         * the other parents' animations.
         */
        Node mLatestParent = null;

        boolean mParentsAdded = false;
        long mStartTime = 0;
        long mEndTime = 0;
        long mTotalDuration = 0;

        /**
         * Constructs the Node with the animation that it encapsulates. A Node has no
         * dependencies by default; dependencies are added via the addDependency()
         * method.
         *
         * @param animation The animation that the Node encapsulates.
         */
        public Node(Animator animation) {
            this.mAnimation = animation;
        }

        @Override
        public Node clone() {
            try {
                Node node = (Node) super.clone();
                node.mAnimation = mAnimation.clone();
                if (mChildNodes != null) {
                    node.mChildNodes = new ArrayList<>(mChildNodes);
                }
                if (mSiblings != null) {
                    node.mSiblings = new ArrayList<>(mSiblings);
                }
                if (mParents != null) {
                    node.mParents = new ArrayList<>(mParents);
                }
                node.mEnded = false;
                return node;
            } catch (CloneNotSupportedException e) {
               throw new AssertionError();
            }
        }

        void addChild(Node node) {
            if (mChildNodes == null) {
                mChildNodes = new ArrayList<>();
            }
            if (!mChildNodes.contains(node)) {
                mChildNodes.add(node);
                node.addParent(this);
            }
        }

        public void addSibling(Node node) {
            if (mSiblings == null) {
                mSiblings = new ArrayList<Node>();
            }
            if (!mSiblings.contains(node)) {
                mSiblings.add(node);
                node.addSibling(this);
            }
        }

        public void addParent(Node node) {
            if (mParents == null) {
                mParents =  new ArrayList<Node>();
            }
            if (!mParents.contains(node)) {
                mParents.add(node);
                node.addChild(this);
            }
        }

        public void addParents(ArrayList<Node> parents) {
            if (parents == null) {
                return;
            }
            int size = parents.size();
            for (int i = 0; i < size; i++) {
                addParent(parents.get(i));
            }
        }
    }

    /**
     * This class is a wrapper around a node and an event for the animation corresponding to the
     * node. The 3 types of events represent the start of an animation, the end of a start delay of
     * an animation, and the end of an animation. When playing forward (i.e. in the non-reverse
     * direction), start event marks when start() should be called, and end event corresponds to
     * when the animation should finish. When playing in reverse, start delay will not be a part
     * of the animation. Therefore, reverse() is called at the end event, and animation should end
     * at the delay ended event.
     */
    private static class AnimationEvent {
        static final int ANIMATION_START = 0;
        static final int ANIMATION_DELAY_ENDED = 1;
        static final int ANIMATION_END = 2;
        final Node mNode;
        final int mEvent;

        AnimationEvent(Node node, int event) {
            mNode = node;
            mEvent = event;
        }

        long getTime() {
            if (mEvent == ANIMATION_START) {
                return mNode.mStartTime;
            } else if (mEvent == ANIMATION_DELAY_ENDED) {
                return mNode.mStartTime == DURATION_INFINITE
                        ? DURATION_INFINITE : mNode.mStartTime + mNode.mAnimation.getStartDelay();
            } else {
                return mNode.mEndTime;
            }
        }

        public String toString() {
            String eventStr = mEvent == ANIMATION_START ? "start" : (
                    mEvent == ANIMATION_DELAY_ENDED ? "delay ended" : "end");
            return eventStr + " " + mNode.mAnimation.toString();
        }
    }

    private class SeekState {
        private long mPlayTime = -1;
        private boolean mSeekingInReverse = false;
        void reset() {
            mPlayTime = -1;
            mSeekingInReverse = false;
        }

        void setPlayTime(long playTime, boolean inReverse) {
            // TODO: This can be simplified.

            // Clamp the play time
            if (getTotalDuration() != DURATION_INFINITE) {
                mPlayTime = Math.min(playTime, getTotalDuration() - mStartDelay);
            }
            mPlayTime = Math.max(0, mPlayTime);
            mSeekingInReverse = inReverse;
        }

        void updateSeekDirection(boolean inReverse) {
            // Change seek direction without changing the overall fraction
            if (inReverse && getTotalDuration() == DURATION_INFINITE) {
                throw new UnsupportedOperationException("Error: Cannot reverse infinite animator"
                        + " set");
            }
            if (mPlayTime >= 0) {
                if (inReverse != mSeekingInReverse) {
                    mPlayTime = getTotalDuration() - mStartDelay - mPlayTime;
                    mSeekingInReverse = inReverse;
                }
            }
        }

        long getPlayTime() {
            return mPlayTime;
        }

        /**
         * Returns the playtime assuming the animation is forward playing
         */
        long getPlayTimeNormalized() {
            if (mReversing) {
                return getTotalDuration() - mStartDelay - mPlayTime;
            }
            return mPlayTime;
        }

        boolean isActive() {
            return mPlayTime != -1;
        }
    }

    /**
     * The <code>Builder</code> object is a utility class to facilitate adding animations to a
     * <code>AnimatorSet</code> along with the relationships between the various animations. The
     * intention of the <code>Builder</code> methods, along with the {@link
     * AnimatorSet#play(Animator) play()} method of <code>AnimatorSet</code> is to make it possible
     * to express the dependency relationships of animations in a natural way. Developers can also
     * use the {@link AnimatorSet#playTogether(Animator[]) playTogether()} and {@link
     * AnimatorSet#playSequentially(Animator[]) playSequentially()} methods if these suit the need,
     * but it might be easier in some situations to express the AnimatorSet of animations in pairs.
     * <p/>
     * <p>The <code>Builder</code> object cannot be constructed directly, but is rather constructed
     * internally via a call to {@link AnimatorSet#play(Animator)}.</p>
     * <p/>
     * <p>For example, this sets up a AnimatorSet to play anim1 and anim2 at the same time, anim3 to
     * play when anim2 finishes, and anim4 to play when anim3 finishes:</p>
     * <pre>
     *     AnimatorSet s = new AnimatorSet();
     *     s.play(anim1).with(anim2);
     *     s.play(anim2).before(anim3);
     *     s.play(anim4).after(anim3);
     * </pre>
     * <p/>
     * <p>Note in the example that both {@link Builder#before(Animator)} and {@link
     * Builder#after(Animator)} are used. These are just different ways of expressing the same
     * relationship and are provided to make it easier to say things in a way that is more natural,
     * depending on the situation.</p>
     * <p/>
     * <p>It is possible to make several calls into the same <code>Builder</code> object to express
     * multiple relationships. However, note that it is only the animation passed into the initial
     * {@link AnimatorSet#play(Animator)} method that is the dependency in any of the successive
     * calls to the <code>Builder</code> object. For example, the following code starts both anim2
     * and anim3 when anim1 ends; there is no direct dependency relationship between anim2 and
     * anim3:
     * <pre>
     *   AnimatorSet s = new AnimatorSet();
     *   s.play(anim1).before(anim2).before(anim3);
     * </pre>
     * If the desired result is to play anim1 then anim2 then anim3, this code expresses the
     * relationship correctly:</p>
     * <pre>
     *   AnimatorSet s = new AnimatorSet();
     *   s.play(anim1).before(anim2);
     *   s.play(anim2).before(anim3);
     * </pre>
     * <p/>
     * <p>Note that it is possible to express relationships that cannot be resolved and will not
     * result in sensible results. For example, <code>play(anim1).after(anim1)</code> makes no
     * sense. In general, circular dependencies like this one (or more indirect ones where a depends
     * on b, which depends on c, which depends on a) should be avoided. Only create AnimatorSets
     * that can boil down to a simple, one-way relationship of animations starting with, before, and
     * after other, different, animations.</p>
     */
    public class Builder {

        /**
         * This tracks the current node being processed. It is supplied to the play() method
         * of AnimatorSet and passed into the constructor of Builder.
         */
        private Node mCurrentNode;

        /**
         * package-private constructor. Builders are only constructed by AnimatorSet, when the
         * play() method is called.
         *
         * @param anim The animation that is the dependency for the other animations passed into
         * the other methods of this Builder object.
         */
        Builder(Animator anim) {
            mDependencyDirty = true;
            mCurrentNode = getNodeForAnimation(anim);
        }

        /**
         * Sets up the given animation to play at the same time as the animation supplied in the
         * {@link AnimatorSet#play(Animator)} call that created this <code>Builder</code> object.
         *
         * @param anim The animation that will play when the animation supplied to the
         * {@link AnimatorSet#play(Animator)} method starts.
         */
        public Builder with(Animator anim) {
            Node node = getNodeForAnimation(anim);
            mCurrentNode.addSibling(node);
            return this;
        }

        /**
         * Sets up the given animation to play when the animation supplied in the
         * {@link AnimatorSet#play(Animator)} call that created this <code>Builder</code> object
         * ends.
         *
         * @param anim The animation that will play when the animation supplied to the
         * {@link AnimatorSet#play(Animator)} method ends.
         */
        public Builder before(Animator anim) {
            Node node = getNodeForAnimation(anim);
            mCurrentNode.addChild(node);
            return this;
        }

        /**
         * Sets up the given animation to play when the animation supplied in the
         * {@link AnimatorSet#play(Animator)} call that created this <code>Builder</code> object
         * to start when the animation supplied in this method call ends.
         *
         * @param anim The animation whose end will cause the animation supplied to the
         * {@link AnimatorSet#play(Animator)} method to play.
         */
        public Builder after(Animator anim) {
            Node node = getNodeForAnimation(anim);
            mCurrentNode.addParent(node);
            return this;
        }

        /**
         * Sets up the animation supplied in the
         * {@link AnimatorSet#play(Animator)} call that created this <code>Builder</code> object
         * to play when the given amount of time elapses.
         *
         * @param delay The number of milliseconds that should elapse before the
         * animation starts.
         */
        public Builder after(long delay) {
            // setup dummy ValueAnimator just to run the clock
            ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
            anim.setDuration(delay);
            after(anim);
            return this;
        }

    }

}
