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

Commit 291f038d authored by George Mount's avatar George Mount Committed by Cherrypicker Worker
Browse files

Fix initialization of AnimatorSet

Bug: 289165914

When I previously changed the initialization code for AnimatorSet,
I had simplified a section because the initialization contained
all of the complexity. I later reverted the change to how I
initialized the child animators, but did not revert a part of
the code.

This reverts the change to initialization during start.

Test: broken animation sample, new test
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:466f64288de4052960d188526dc5bfce70ff3ca1)
Merged-In: I7333865f677f42964b023bcd9ee768ff4ec0137d
Change-Id: I7333865f677f42964b023bcd9ee768ff4ec0137d
parent ff651d3a
Loading
Loading
Loading
Loading
+20 −2
Original line number Original line Diff line number Diff line
@@ -1346,8 +1346,26 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim
        }
        }
        // Set the child animators to the right end:
        // Set the child animators to the right end:
        if (mShouldResetValuesAtStart) {
        if (mShouldResetValuesAtStart) {
            if (isInitialized()) {
                skipToEndValue(!mReversing);
            } else if (mReversing) {
                // Reversing but haven't initialized all the children yet.
                initChildren();
                initChildren();
                skipToEndValue(!mReversing);
                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()) {
        if (mReversing || mStartDelay == 0 || mSeekState.isActive()) {
+65 −0
Original line number Original line Diff line number Diff line
@@ -24,6 +24,7 @@ import static org.junit.Assert.assertTrue;
import android.util.Property;
import android.util.Property;
import android.view.View;
import android.view.View;


import androidx.annotation.NonNull;
import androidx.test.annotation.UiThreadTest;
import androidx.test.annotation.UiThreadTest;
import androidx.test.filters.SmallTest;
import androidx.test.filters.SmallTest;
import androidx.test.rule.ActivityTestRule;
import androidx.test.rule.ActivityTestRule;
@@ -36,6 +37,8 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.Test;


import java.util.ArrayList;
import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;


@SmallTest
@SmallTest
public class AnimatorSetActivityTest {
public class AnimatorSetActivityTest {
@@ -613,6 +616,68 @@ public class AnimatorSetActivityTest {
        });
        });
    }
    }


    @Test
    public void initAfterStartNotification() throws Throwable {
        Property<int[], Integer> property = new Property<>(Integer.class, "firstValue") {
            @Override
            public Integer get(int[] target) {
                throw new IllegalStateException("Shouldn't be called");
            }

            @Override
            public void set(int[] target, Integer value) {
                target[0] = value;
            }
        };
        int[] target = new int[1];
        ObjectAnimator animator1 = ObjectAnimator.ofInt(target, property, 0, 100);
        ObjectAnimator animator2 = ObjectAnimator.ofInt(target, property, 0, 100);
        ObjectAnimator animator3 = ObjectAnimator.ofInt(target, property, 0, 100);
        animator1.setDuration(10);
        animator2.setDuration(10);
        animator3.setDuration(10);
        AnimatorSet set = new AnimatorSet();
        set.playSequentially(animator1, animator2, animator3);
        final int[] values = new int[4];
        animator2.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(@NonNull Animator animation, boolean isReverse) {
                values[0] = target[0];
                animator2.setIntValues(target[0], target[0] + 100);
            }

            @Override
            public void onAnimationEnd(@NonNull Animator animation, boolean isReverse) {
                values[1] = target[0];
            }
        });
        animator3.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(@NonNull Animator animation, boolean isReverse) {
                values[2] = target[0];
                animator3.setIntValues(target[0], target[0] + 100);
            }

            @Override
            public void onAnimationEnd(@NonNull Animator animation, boolean isReverse) {
                values[3] = target[0];
            }
        });
        final CountDownLatch latch = new CountDownLatch(1);
        set.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(@NonNull Animator animation, boolean isReverse) {
                latch.countDown();
            }
        });
        mActivityRule.runOnUiThread(() -> set.start());
        assertTrue(latch.await(1, TimeUnit.SECONDS));
        assertEquals(100, values[0]);
        assertEquals(200, values[1]);
        assertEquals(200, values[2]);
        assertEquals(300, values[3]);
    }

    /**
    /**
     * Check that the animator list contains exactly the given animators and nothing else.
     * Check that the animator list contains exactly the given animators and nothing else.
     */
     */