/*
 * Copyright (C) 2012 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.cts;

import static com.android.compatibility.common.util.CtsMockitoUtils.within;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.os.SystemClock;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.LinearInterpolator;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

@MediumTest
@RunWith(AndroidJUnit4.class)
public class AnimatorSetTest {
    private AnimationActivity mActivity;
    private AnimatorSet mAnimatorSet;
    private float mPreviousDurationScale = 1.0f;
    private long mDuration = 1000;
    private Object object;
    private ObjectAnimator yAnimator;
    private ObjectAnimator xAnimator;
    Set<Integer> identityHashes = new HashSet<>();
    private static final float EPSILON = 0.001f;

    @Rule
    public ActivityTestRule<AnimationActivity> mActivityRule =
            new ActivityTestRule<>(AnimationActivity.class);

    @Before
    public void setup() {
        InstrumentationRegistry.getInstrumentation().setInTouchMode(false);
        mActivity = mActivityRule.getActivity();
        mPreviousDurationScale = ValueAnimator.getDurationScale();
        ValueAnimator.setDurationScale(1.0f);
        object = mActivity.view.newBall;
        yAnimator = getYAnimator(object);
        xAnimator = getXAnimator(object);
    }

    @After
    public void tearDown() {
        ValueAnimator.setDurationScale(mPreviousDurationScale);
    }

    @Test
    public void testPlaySequentially() throws Throwable {
        xAnimator.setRepeatCount(0);
        yAnimator.setRepeatCount(0);
        xAnimator.setDuration(50);
        yAnimator.setDuration(50);
        List<Animator> animators = new ArrayList<Animator>();
        animators.add(xAnimator);
        animators.add(yAnimator);
        mAnimatorSet = new AnimatorSet();
        mAnimatorSet.playSequentially(animators);
        verifySequentialPlayOrder(mAnimatorSet, new Animator[] {xAnimator, yAnimator});

        ValueAnimator anim1 = ValueAnimator.ofFloat(0f, 1f);
        ValueAnimator anim2 = ValueAnimator.ofInt(0, 100);
        anim1.setDuration(50);
        anim2.setDuration(50);
        AnimatorSet set = new AnimatorSet();
        set.playSequentially(anim1, anim2);
        verifySequentialPlayOrder(set, new Animator[] {anim1, anim2});
    }

    /**
     * Start the animator, and verify the animators are played sequentially in the order that is
     * defined in the array.
     *
     * @param set AnimatorSet to be started and verified
     * @param animators animators that we put in the AnimatorSet, in the order that they'll play
     */
    private void verifySequentialPlayOrder(final AnimatorSet set, Animator[] animators)
            throws Throwable {

        final MyListener[] listeners = new MyListener[animators.length];
        for (int i = 0; i < animators.length; i++) {
            if (i == 0) {
                listeners[i] = new MyListener();
            } else {
                final int current = i;
                listeners[i] = new MyListener() {
                    @Override
                    public void onAnimationStart(Animator anim) {
                        super.onAnimationStart(anim);
                        // Check that the previous animator has finished.
                        assertTrue(listeners[current - 1].mEndIsCalled);
                    }
                };
            }
            animators[i].addListener(listeners[i]);
        }

        final CountDownLatch startLatch = new CountDownLatch(1);
        final CountDownLatch endLatch = new CountDownLatch(1);

        set.addListener(new MyListener() {
            @Override
            public void onAnimationEnd(Animator anim) {
                endLatch.countDown();
            }
        });

        long totalDuration = set.getTotalDuration();
        assertFalse(set.isRunning());
        mActivityRule.runOnUiThread(() -> {
            set.start();
            startLatch.countDown();
        });

        // Set timeout to 100ms, if current count reaches 0 before the timeout, startLatch.await(...)
        // will return immediately.
        assertTrue(startLatch.await(100, TimeUnit.MILLISECONDS));
        assertTrue(set.isRunning());
        assertTrue(endLatch.await(totalDuration * 2, TimeUnit.MILLISECONDS));
        // Check that all the animators have finished.
        for (int i = 0; i < listeners.length; i++) {
            assertTrue(listeners[i].mEndIsCalled);
        }

        // Now reverse the animations and verify whether the play order is reversed.
        for (int i = 0; i < animators.length; i++) {
            if (i == animators.length - 1) {
                listeners[i] = new MyListener();
            } else {
                final int current = i;
                listeners[i] = new MyListener() {
                    @Override
                    public void onAnimationStart(Animator anim) {
                        super.onAnimationStart(anim);
                        // Check that the previous animator has finished.
                        assertTrue(listeners[current + 1].mEndIsCalled);
                    }
                };
            }
            animators[i].removeAllListeners();
            animators[i].addListener(listeners[i]);
        }

        mActivityRule.runOnUiThread(() -> {
            set.reverse();
            startLatch.countDown();
        });

        // Set timeout to 100ms, if current count reaches 0 before the timeout, startLatch.await(..)
        // will return immediately.
        assertTrue(startLatch.await(100, TimeUnit.MILLISECONDS));
        assertTrue(set.isRunning());
        assertTrue(endLatch.await(totalDuration * 2, TimeUnit.MILLISECONDS));

    }

    @Test
    public void testPlayTogether() throws Throwable {
        xAnimator.setRepeatCount(ValueAnimator.INFINITE);
        Animator[] animatorArray = {xAnimator, yAnimator};

        mAnimatorSet = new AnimatorSet();
        mAnimatorSet.playTogether(animatorArray);

        assertFalse(mAnimatorSet.isRunning());
        assertFalse(xAnimator.isRunning());
        assertFalse(yAnimator.isRunning());
        startAnimation(mAnimatorSet);
        SystemClock.sleep(100);
        assertTrue(mAnimatorSet.isRunning());
        assertTrue(xAnimator.isRunning());
        assertTrue(yAnimator.isRunning());

        // Now assemble another animator set
        ValueAnimator anim1 = ValueAnimator.ofFloat(0f, 100f);
        ValueAnimator anim2 = ValueAnimator.ofFloat(10f, 100f);
        AnimatorSet set = new AnimatorSet();
        set.playTogether(anim1, anim2);

        assertFalse(set.isRunning());
        assertFalse(anim1.isRunning());
        assertFalse(anim2.isRunning());
        startAnimation(set);
        SystemClock.sleep(100);
        assertTrue(set.isRunning());
        assertTrue(anim1.isRunning());
        assertTrue(anim2.isRunning());
    }

    @Test
    public void testPlayBeforeAfter() throws Throwable {
        xAnimator.setRepeatCount(0);
        yAnimator.setRepeatCount(0);
        final ValueAnimator zAnimator = ValueAnimator.ofFloat(0f, 100f);

        xAnimator.setDuration(50);
        yAnimator.setDuration(50);
        zAnimator.setDuration(50);

        AnimatorSet set = new AnimatorSet();
        set.play(yAnimator).before(zAnimator).after(xAnimator);

        verifySequentialPlayOrder(set, new Animator[] {xAnimator, yAnimator, zAnimator});
    }

    @Test
    public void testListenerCallbackOnEmptySet() throws Throwable {
        // Create an AnimatorSet that only contains one empty AnimatorSet, and checks the callback
        // sequence by checking the time stamps of the callbacks.
        final AnimatorSet emptySet = new AnimatorSet();
        final AnimatorSet set = new AnimatorSet();
        set.play(emptySet);
        MyListener listener = new MyListener() {
            long startTime = 0;
            long endTime = 0;
            @Override
            public void onAnimationStart(Animator animation) {
                super.onAnimationStart(animation);
                startTime = SystemClock.currentThreadTimeMillis();
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                endTime = SystemClock.currentThreadTimeMillis();
                assertTrue(endTime >= startTime);
                assertTrue(startTime != 0);
            }
        };
        set.addListener(listener);
        mActivityRule.runOnUiThread(() -> {
            set.start();
        });
        assertTrue(listener.mStartIsCalled);
        assertTrue(listener.mEndIsCalled);
    }

    @Test
    public void testPauseAndResume() throws Throwable {
        final AnimatorSet set = new AnimatorSet();
        ValueAnimator a1 = ValueAnimator.ofFloat(0f, 100f);
        a1.setDuration(50);
        ValueAnimator a2 = ValueAnimator.ofFloat(0f, 100f);
        a2.setDuration(50);
        a1.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                // Pause non-delayed set once the child animator starts
                set.pause();
            }
        });
        set.playTogether(a1, a2);

        final AnimatorSet delayedSet = new AnimatorSet();
        ValueAnimator a3 = ValueAnimator.ofFloat(0f, 100f);
        a3.setDuration(50);
        ValueAnimator a4 = ValueAnimator.ofFloat(0f, 100f);
        a4.setDuration(50);
        delayedSet.playSequentially(a3, a4);
        delayedSet.setStartDelay(50);

        MyListener l1 = new MyListener();
        MyListener l2 = new MyListener();
        set.addListener(l1);
        delayedSet.addListener(l2);

        mActivityRule.runOnUiThread(() -> {
            set.start();
            delayedSet.start();

            // Pause the delayed set during start delay
            delayedSet.pause();
        });

        // Sleep long enough so that if the sets are not properly paused, they would have
        // finished.
        SystemClock.sleep(300);
        // Verify that both sets have been paused and *not* finished.
        assertTrue(set.isPaused());
        assertTrue(delayedSet.isPaused());
        assertTrue(l1.mStartIsCalled);
        assertTrue(l2.mStartIsCalled);
        assertFalse(l1.mEndIsCalled);
        assertFalse(l2.mEndIsCalled);

        mActivityRule.runOnUiThread(() -> {
            set.resume();
            delayedSet.resume();
        });
        SystemClock.sleep(300);

        assertFalse(set.isPaused());
        assertFalse(delayedSet.isPaused());
        assertTrue(l1.mEndIsCalled);
        assertTrue(l2.mEndIsCalled);
    }

    @Test
    public void testPauseBeforeStart() throws Throwable {
        final AnimatorSet set = new AnimatorSet();
        ValueAnimator a1 = ValueAnimator.ofFloat(0f, 100f);
        a1.setDuration(50);
        ValueAnimator a2 = ValueAnimator.ofFloat(0f, 100f);
        a2.setDuration(50);
        set.setStartDelay(50);
        set.playSequentially(a1, a2);

        final MyListener listener = new MyListener();
        set.addListener(listener);

        mActivityRule.runOnUiThread(() -> {
            // Pause animator set before calling start()
            set.pause();
            // Verify that pause should have no effect on a not-yet-started animator.
            assertFalse(set.isPaused());
            set.start();
        });
        SystemClock.sleep(300);

        // Animator set should finish running by now since it's not paused.
        assertTrue(listener.mStartIsCalled);
        assertTrue(listener.mEndIsCalled);
    }

    @Test
    public void testDuration() throws Throwable {
        xAnimator.setRepeatCount(ValueAnimator.INFINITE);
        Animator[] animatorArray = { xAnimator, yAnimator };

        mAnimatorSet = new AnimatorSet();
        mAnimatorSet.playTogether(animatorArray);
        mAnimatorSet.setDuration(1000);

        startAnimation(mAnimatorSet);
        SystemClock.sleep(100);
        assertEquals(mAnimatorSet.getDuration(), 1000);
    }

    @Test
    public void testStartDelay() throws Throwable {
        xAnimator.setRepeatCount(ValueAnimator.INFINITE);
        Animator[] animatorArray = { xAnimator, yAnimator };

        mAnimatorSet = new AnimatorSet();
        mAnimatorSet.playTogether(animatorArray);
        mAnimatorSet.setStartDelay(10);

        startAnimation(mAnimatorSet);
        SystemClock.sleep(100);
        assertEquals(mAnimatorSet.getStartDelay(), 10);
    }

    /**
     * This test sets up an AnimatorSet with start delay. One of the child animators also has
     * start delay. We then verify that start delay was handled correctly on both AnimatorSet
     * and individual animator level.
     */
    @Test
    public void testReverseWithStartDelay() throws Throwable {
        ValueAnimator a1 = ValueAnimator.ofFloat(0f, 1f);
        a1.setDuration(200);
        Animator.AnimatorListener listener1 = mock(AnimatorListenerAdapter.class);
        a1.addListener(listener1);

        ValueAnimator a2 = ValueAnimator.ofFloat(1f, 2f);
        a2.setDuration(200);
        // Set start delay on a2 so that the delay is passed 100ms after a1 is finished.
        a2.setStartDelay(300);
        Animator.AnimatorListener listener = mock(AnimatorListenerAdapter.class);
        a2.addListener(listener);

        a2.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation, boolean inReverse) {
                assertTrue(inReverse);
                // By the time a2 finishes reversing, a1 should not have started.
                assertFalse(a1.isStarted());
            }
        });

        AnimatorSet set = new AnimatorSet();
        set.playTogether(a1, a2);
        set.setStartDelay(1000);
        Animator.AnimatorListener setListener = mock(AnimatorListenerAdapter.class);
        set.addListener(setListener);
        mActivityRule.runOnUiThread(() -> {
            set.reverse();
            assertTrue(a2.isStarted());
            assertTrue(a2.isRunning());
        });

        // a2 should finish 200ms after reverse started
        verify(listener, within(300)).onAnimationEnd(a2, true);
        // When a2 finishes, a1 should not have started yet
        verify(listener1, never()).onAnimationStart(a1, true);

        // The whole set should finish within 500ms, i.e. 300ms after a2 is finished. This verifies
        // that the AnimatorSet didn't mistakenly use its start delay in the reverse run.
        verify(setListener, within(400)).onAnimationEnd(set, true);
        verify(listener1, times(1)).onAnimationEnd(a1, true);

    }

    /**
     * Test that duration scale is handled correctly in the AnimatorSet.
     */
    @Test
    public void testZeroDurationScale() throws Throwable {
        ValueAnimator.setDurationScale(0);

        ValueAnimator a1 = ValueAnimator.ofFloat(0f, 1f);
        a1.setDuration(200);
        Animator.AnimatorListener listener1 = mock(AnimatorListenerAdapter.class);
        a1.addListener(listener1);

        ValueAnimator a2 = ValueAnimator.ofFloat(1f, 2f);
        a2.setDuration(200);
        // Set start delay on a2 so that the delay is passed 100ms after a1 is finished.
        a2.setStartDelay(300);
        Animator.AnimatorListener listener2 = mock(AnimatorListenerAdapter.class);
        a2.addListener(listener2);

        AnimatorSet set = new AnimatorSet();
        set.playSequentially(a1, a2);
        set.setStartDelay(1000);
        Animator.AnimatorListener setListener = mock(AnimatorListenerAdapter.class);
        set.addListener(setListener);

        mActivityRule.runOnUiThread(() -> {
            set.start();
            verify(setListener, times(0)).onAnimationEnd(any(AnimatorSet.class),
                    any(boolean.class));
        });
        verify(setListener, within(100)).onAnimationEnd(set, false);
        verify(listener1, times(1)).onAnimationEnd(a1, false);
        verify(listener2, times(1)).onAnimationEnd(a2, false);
    }

    /**
     * Test that non-zero duration scale is handled correctly in the AnimatorSet.
     */
    @Test
    public void testDurationScale() throws Throwable {
        // Change the duration scale to 3
        ValueAnimator.setDurationScale(3f);

        ValueAnimator a1 = ValueAnimator.ofFloat(0f, 1f);
        a1.setDuration(100);
        Animator.AnimatorListener listener1 = mock(AnimatorListenerAdapter.class);
        a1.addListener(listener1);

        ValueAnimator a2 = ValueAnimator.ofFloat(1f, 2f);
        a2.setDuration(100);
        // Set start delay on a2 so that the delay is passed 100ms after a1 is finished.
        a2.setStartDelay(200);
        Animator.AnimatorListener listener2 = mock(AnimatorListenerAdapter.class);
        a2.addListener(listener2);

        AnimatorSet set = new AnimatorSet();
        set.playSequentially(a1, a2);
        Animator.AnimatorListener setListener = mock(AnimatorListenerAdapter.class);
        set.addListener(setListener);
        set.setStartDelay(200);

        mActivityRule.runOnUiThread(() -> {
            set.start();
        });

        // Sleep for part of the start delay and check that no child animator has started, to verify
        // that the duration scale has been properly scaled.
        SystemClock.sleep(400);
        // start delay of the set should be scaled to 600ms
        verify(listener1, never()).onAnimationStart(a1, false);
        verify(listener2, never()).onAnimationStart(a2, false);

        verify(listener1, within(400)).onAnimationStart(a1, false);
        // Sleep for part of a2's start delay and verify that a2 is still in the delayed stage. This
        // is to make sure child animator's start delay is also properly scaled.
        SystemClock.sleep(400);
        assertTrue(a2.isStarted());
        assertFalse(a2.isRunning());

        // Sleep past the start delay
        SystemClock.sleep(350);
        assertTrue(a2.isRunning());

        // Verify that the AnimatorSet has finished within 1650ms since the start of the animation.
        // The duration of the set is 500ms, duration scale = 3.
        verify(setListener, within(500)).onAnimationEnd(set, false);
        verify(listener1, times(1)).onAnimationEnd(a1, false);
        verify(listener2, times(1)).onAnimationEnd(a2, false);
    }

    /**
     * This test sets up 10 animators playing together. We expect the start time for all animators
     * to be the same.
     */
    @Test
    public void testMultipleAnimatorsPlayTogether() throws Throwable {
        Animator[] animators = new Animator[10];
        for (int i = 0; i < 10; i++) {
            animators[i] = ValueAnimator.ofFloat(0f, 1f);
        }
        AnimatorSet set = new AnimatorSet();
        set.playTogether(animators);
        set.setStartDelay(80);

        Animator.AnimatorListener setListener = mock(AnimatorListenerAdapter.class);
        set.addListener(setListener);
        mActivityRule.runOnUiThread(() -> {
            set.start();
        });
        SystemClock.sleep(150);
        for (int i = 0; i < 10; i++) {
            assertTrue(animators[i].isRunning());
        }

        verify(setListener, within(400)).onAnimationEnd(set, false);
    }

    @Test
    public void testGetChildAnimations() throws Throwable {
        Animator[] animatorArray = { xAnimator, yAnimator };

        mAnimatorSet = new AnimatorSet();
        mAnimatorSet.getChildAnimations();
        assertEquals(0, mAnimatorSet.getChildAnimations().size());
        mAnimatorSet.playSequentially(animatorArray);
        assertEquals(2, mAnimatorSet.getChildAnimations().size());
    }

    @Test
    public void testSetInterpolator() throws Throwable {
        xAnimator.setRepeatCount(ValueAnimator.INFINITE);
        Animator[] animatorArray = {xAnimator, yAnimator};
        TimeInterpolator interpolator = new AccelerateDecelerateInterpolator();
        mAnimatorSet = new AnimatorSet();
        mAnimatorSet.playTogether(animatorArray);
        mAnimatorSet.setInterpolator(interpolator);

        assertFalse(mAnimatorSet.isRunning());
        startAnimation(mAnimatorSet);
        SystemClock.sleep(100);

        ArrayList<Animator> animatorList = mAnimatorSet.getChildAnimations();
        assertEquals(interpolator, animatorList.get(0).getInterpolator());
        assertEquals(interpolator, animatorList.get(1).getInterpolator());
    }

    private ObjectAnimator getXAnimator(Object object) {
        String propertyX = "x";
        float startX = mActivity.mStartX;
        float endX = mActivity.mStartX + mActivity.mDeltaX;
        ObjectAnimator xAnimator = ObjectAnimator.ofFloat(object, propertyX, startX, endX);
        xAnimator.setDuration(mDuration);
        xAnimator.setRepeatCount(ValueAnimator.INFINITE);
        xAnimator.setInterpolator(new AccelerateInterpolator());
        xAnimator.setRepeatMode(ValueAnimator.REVERSE);
        return xAnimator;
    }

    private ObjectAnimator getYAnimator(Object object) {
         String property = "y";
         float startY = mActivity.mStartY;
         float endY = mActivity.mStartY + mActivity.mDeltaY;
         ObjectAnimator yAnimator = ObjectAnimator.ofFloat(object, property, startY, endY);
         yAnimator.setDuration(mDuration);
         yAnimator.setRepeatCount(2);
         yAnimator.setInterpolator(new AccelerateInterpolator());
         yAnimator.setRepeatMode(ValueAnimator.REVERSE);
        return yAnimator;
    }

    private void startAnimation(final AnimatorSet animatorSet) throws Throwable {
        mActivityRule.runOnUiThread(() -> mActivity.startAnimatorSet(animatorSet));
    }

    private void assertUnique(Object object) {
        assertUnique(object, "");
    }

    private void assertUnique(Object object, String msg) {
        final int code = System.identityHashCode(object);
        assertTrue("object should be unique " + msg + ", obj:" + object, identityHashes.add(code));

    }

    @Test
    public void testClone() throws Throwable {
        final AnimatorSet set1 = new AnimatorSet();
        final AnimatorListenerAdapter setListener = new AnimatorListenerAdapter() {};
        set1.addListener(setListener);
        ObjectAnimator animator1 = new ObjectAnimator();
        animator1.setDuration(100);
        animator1.setPropertyName("x");
        animator1.setIntValues(5);
        animator1.setInterpolator(new LinearInterpolator());
        AnimatorListenerAdapter listener1 = new AnimatorListenerAdapter(){};
        AnimatorListenerAdapter listener2 = new AnimatorListenerAdapter(){};
        animator1.addListener(listener1);

        ObjectAnimator animator2 = new ObjectAnimator();
        animator2.setDuration(100);
        animator2.setInterpolator(new LinearInterpolator());
        animator2.addListener(listener2);
        animator2.setPropertyName("y");
        animator2.setIntValues(10);

        set1.playTogether(animator1, animator2);

        AnimateObject target = new AnimateObject();
        set1.setTarget(target);
        mActivityRule.runOnUiThread(set1::start);
        assertTrue(set1.isStarted());

        animator1.getListeners();
        AnimatorSet set2 = set1.clone();
        assertFalse(set2.isStarted());

        assertUnique(set1);
        assertUnique(animator1);
        assertUnique(animator2);

        assertUnique(set2);
        assertEquals(2, set2.getChildAnimations().size());

        Animator clone1 = set2.getChildAnimations().get(0);
        Animator clone2 = set2.getChildAnimations().get(1);

        for (Animator animator : set2.getChildAnimations()) {
            assertUnique(animator);
        }

        assertTrue(clone1.getListeners().contains(listener1));
        assertTrue(clone2.getListeners().contains(listener2));

        assertTrue(set2.getListeners().contains(setListener));

        for (Animator.AnimatorListener listener : set1.getListeners()) {
            assertTrue(set2.getListeners().contains(listener));
        }

        assertEquals(animator1.getDuration(), clone1.getDuration());
        assertEquals(animator2.getDuration(), clone2.getDuration());
        assertSame(animator1.getInterpolator(), clone1.getInterpolator());
        assertSame(animator2.getInterpolator(), clone2.getInterpolator());
    }

    /**
     * Testing seeking in an AnimatorSet containing sequential animators.
     */
    @Test
    public void testSeeking() throws Throwable {
        final AnimatorSet set = new AnimatorSet();
        final ValueAnimator a1 = ValueAnimator.ofFloat(0f, 150f);
        a1.setDuration(150);
        final ValueAnimator a2 = ValueAnimator.ofFloat(150f, 250f);
        a2.setDuration(100);
        final ValueAnimator a3 = ValueAnimator.ofFloat(250f, 300f);
        a3.setDuration(50);

        a1.setInterpolator(null);
        a2.setInterpolator(null);
        a3.setInterpolator(null);

        set.playSequentially(a1, a2, a3);

        set.setCurrentPlayTime(100);
        assertEquals(100f, (Float) a1.getAnimatedValue(), EPSILON);
        assertEquals(150f, (Float) a2.getAnimatedValue(), EPSILON);
        assertEquals(250f, (Float) a3.getAnimatedValue(), EPSILON);

        set.setCurrentPlayTime(280);
        assertEquals(150f, (Float) a1.getAnimatedValue(), EPSILON);
        assertEquals(250f, (Float) a2.getAnimatedValue(), EPSILON);
        assertEquals(280f, (Float) a3.getAnimatedValue(), EPSILON);

        AnimatorListenerAdapter setListener = new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                assertEquals(150f, (Float) a1.getAnimatedValue(), EPSILON);
                assertEquals(250f, (Float) a2.getAnimatedValue(), EPSILON);
                assertEquals(300f, (Float) a3.getAnimatedValue(), EPSILON);

            }
        };
        AnimatorListenerAdapter mockListener = mock(AnimatorListenerAdapter.class);
        set.addListener(setListener);
        set.addListener(mockListener);
        mActivityRule.runOnUiThread(() -> {
            set.start();
        });

        verify(mockListener, within(300)).onAnimationEnd(set, false);

        // Seek after a run to the middle-ish, and verify the first animator is at the end
        // value and the 3rd at beginning value, and the 2nd animator is at the seeked value.
        set.setCurrentPlayTime(200);
        assertEquals(150f, (Float) a1.getAnimatedValue(), EPSILON);
        assertEquals(200f, (Float) a2.getAnimatedValue(), EPSILON);
        assertEquals(250f, (Float) a3.getAnimatedValue(), EPSILON);
    }

    /**
     * Testing seeking in an AnimatorSet containing infinite animators.
     */
    @Test
    public void testSeekingInfinite() {
        final AnimatorSet set = new AnimatorSet();
        final ValueAnimator a1 = ValueAnimator.ofFloat(0f, 100f);
        a1.setDuration(100);
        final ValueAnimator a2 = ValueAnimator.ofFloat(100f, 200f);
        a2.setDuration(100);
        a2.setRepeatCount(ValueAnimator.INFINITE);
        a2.setRepeatMode(ValueAnimator.RESTART);

        final ValueAnimator a3 = ValueAnimator.ofFloat(100f, 200f);
        a3.setDuration(100);
        a3.setRepeatCount(ValueAnimator.INFINITE);
        a3.setRepeatMode(ValueAnimator.REVERSE);

        a1.setInterpolator(null);
        a2.setInterpolator(null);
        a3.setInterpolator(null);
        set.play(a1).before(a2);
        set.play(a1).before(a3);

        set.setCurrentPlayTime(50);
        assertEquals(50f, (Float) a1.getAnimatedValue(), EPSILON);
        assertEquals(100f, (Float) a2.getAnimatedValue(), EPSILON);
        assertEquals(100f, (Float) a3.getAnimatedValue(), EPSILON);

        set.setCurrentPlayTime(100);
        assertEquals(100f, (Float) a1.getAnimatedValue(), EPSILON);
        assertEquals(100f, (Float) a2.getAnimatedValue(), EPSILON);
        assertEquals(100f, (Float) a3.getAnimatedValue(), EPSILON);

        // Seek to the 1st iteration of the infinite repeat animators, and they should have the
        // same value.
        set.setCurrentPlayTime(180);
        assertEquals(100f, (Float) a1.getAnimatedValue(), EPSILON);
        assertEquals(180f, (Float) a2.getAnimatedValue(), EPSILON);
        assertEquals(180f, (Float) a3.getAnimatedValue(), EPSILON);

        // Seek to the 2nd iteration of the infinite repeat animators, and they should have
        // different values as they have different repeat mode.
        set.setCurrentPlayTime(280);
        assertEquals(100f, (Float) a1.getAnimatedValue(), EPSILON);
        assertEquals(180f, (Float) a2.getAnimatedValue(), EPSILON);
        assertEquals(120f, (Float) a3.getAnimatedValue(), EPSILON);

    }

    /**
     * This test verifies that getCurrentPlayTime() returns the right value.
     */
    @Test
    public void testGetCurrentPlayTime() throws Throwable {
        // Setup an AnimatorSet with start delay
        final AnimatorSet set = new AnimatorSet();
        final ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f).setDuration(300);
        anim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation, boolean inReverse) {
                assertFalse(inReverse);
                assertTrue(set.getCurrentPlayTime() >= 200);
            }
        });
        set.play(anim);
        set.setStartDelay(100);

        Animator.AnimatorListener setListener = mock(AnimatorListenerAdapter.class);
        set.addListener(setListener);

        // Set a seek time and verify, before start
        set.setCurrentPlayTime(20);
        assertEquals(20, set.getCurrentPlayTime());

        // Now start() should start right away from the seeked position, skipping the delay.
        mActivityRule.runOnUiThread(() -> {
            set.setCurrentPlayTime(200);
            set.start();
            assertEquals(200, set.getCurrentPlayTime());
        });

        // When animation is seeked to 200ms, it should take another 100ms to end.
        verify(setListener, within(200)).onAnimationEnd(set, false);
    }

    @Test
    public void testNotifiesAfterEnd() throws Throwable {
        final ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
        Animator.AnimatorListener listener = new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                assertTrue(animation.isStarted());
                assertTrue(animation.isRunning());
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                assertFalse(animation.isRunning());
                assertFalse(animation.isStarted());
                super.onAnimationEnd(animation);
            }
        };
        animator.addListener(listener);
        final AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.playTogether(animator);
        animatorSet.addListener(listener);
        mActivityRule.runOnUiThread(() -> {
            animatorSet.start();
            animator.end();
            assertFalse(animator.isStarted());
        });
    }

    /**
     *
     * This test verifies that custom ValueAnimators will be start()'ed in a set.
     */
    @Test
    public void testChildAnimatorStartCalled() throws Throwable {
        MyValueAnimator a1 = new MyValueAnimator();
        MyValueAnimator a2 = new MyValueAnimator();
        AnimatorSet set = new AnimatorSet();
        set.playTogether(a1, a2);
        mActivityRule.runOnUiThread(() -> {
            set.start();
            assertTrue(a1.mStartCalled);
            assertTrue(a2.mStartCalled);
        });

    }

    /**
     * This test sets up an AnimatorSet that contains two sequential animations. The first animation
     * is infinite, the second animation therefore has an infinite start time. This test verifies
     * that the infinite start time is handled correctly.
     */
    @Test
    public void testInfiniteStartTime() throws Throwable {
        ValueAnimator a1 = ValueAnimator.ofFloat(0f, 1f);
        a1.setRepeatCount(ValueAnimator.INFINITE);
        ValueAnimator a2 = ValueAnimator.ofFloat(0f, 1f);

        AnimatorSet set = new AnimatorSet();
        set.playSequentially(a1, a2);

        mActivityRule.runOnUiThread(() -> {
            set.start();
        });

        assertEquals(Animator.DURATION_INFINITE, set.getTotalDuration());

        mActivityRule.runOnUiThread(() -> {
            set.end();
        });
    }

    static class TargetObj {
        public float value = 0;

        public void setVal(float value) {
            this.value = value;
        }
    }

    class AnimateObject {
        int x = 1;
        int y = 2;
    }

    static class MyListener extends AnimatorListenerAdapter {
        boolean mStartIsCalled = false;
        boolean mEndIsCalled = false;

        public void onAnimationStart(Animator animation) {
            mStartIsCalled = true;
        }

        public void onAnimationEnd(Animator animation) {
            mEndIsCalled = true;
        }
    }

    static class MyValueAnimator extends ValueAnimator {
        boolean mStartCalled = false;
        @Override
        public void start() {
            // Do not call super intentionally.
            mStartCalled = true;
        }
    }
}
