Loading core/java/android/animation/Animator.java +2 −2 Original line number Diff line number Diff line Loading @@ -568,13 +568,13 @@ public abstract class Animator implements Cloneable { * repetition. lastPlayTime is similar and is used to calculate how many repeats have been * done between the two times. */ void animateValuesInRange(long currentPlayTime, long lastPlayTime, boolean notify) {} void animateValuesInRange(long currentPlayTime, long lastPlayTime) {} /** * Internal use only. This animates any animation that has ended since lastPlayTime. * If an animation hasn't been finished, no change will be made. */ void animateSkipToEnds(long currentPlayTime, long lastPlayTime, boolean notify) {} void animateSkipToEnds(long currentPlayTime, long lastPlayTime) {} /** * Internal use only. Adds all start times (after delay) to and end times to times. Loading core/java/android/animation/AnimatorSet.java +34 −58 Original line number Diff line number Diff line Loading @@ -825,8 +825,7 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim private void animateBasedOnPlayTime( long currentPlayTime, long lastPlayTime, boolean inReverse, boolean notify boolean inReverse ) { if (currentPlayTime < 0 || lastPlayTime < -1) { throw new UnsupportedOperationException("Error: Play time should never be negative."); Loading Loading @@ -857,8 +856,8 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim while (index < endIndex) { long playTime = startEndTimes[index]; if (lastPlayTime != playTime) { animateSkipToEnds(playTime, lastPlayTime, notify); animateValuesInRange(playTime, lastPlayTime, notify); animateSkipToEnds(playTime, lastPlayTime); animateValuesInRange(playTime, lastPlayTime); lastPlayTime = playTime; } index++; Loading @@ -868,15 +867,15 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim index--; long playTime = startEndTimes[index]; if (lastPlayTime != playTime) { animateSkipToEnds(playTime, lastPlayTime, notify); animateValuesInRange(playTime, lastPlayTime, notify); animateSkipToEnds(playTime, lastPlayTime); animateValuesInRange(playTime, lastPlayTime); lastPlayTime = playTime; } } } if (currentPlayTime != lastPlayTime) { animateSkipToEnds(currentPlayTime, lastPlayTime, notify); animateValuesInRange(currentPlayTime, lastPlayTime, notify); animateSkipToEnds(currentPlayTime, lastPlayTime); animateValuesInRange(currentPlayTime, lastPlayTime); } } Loading @@ -896,13 +895,11 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim } @Override void animateSkipToEnds(long currentPlayTime, long lastPlayTime, boolean notify) { void animateSkipToEnds(long currentPlayTime, long lastPlayTime) { initAnimation(); if (lastPlayTime > currentPlayTime) { if (notify) { notifyStartListeners(true); } for (int i = mEvents.size() - 1; i >= 0; i--) { AnimationEvent event = mEvents.get(i); Node node = event.mNode; Loading @@ -916,31 +913,25 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim if (currentPlayTime <= start && start < lastPlayTime) { animator.animateSkipToEnds( 0, lastPlayTime - node.mStartTime, notify lastPlayTime - node.mStartTime ); if (notify) { mPlayingSet.remove(node); } } else if (start <= currentPlayTime && currentPlayTime <= end) { animator.animateSkipToEnds( currentPlayTime - node.mStartTime, lastPlayTime - node.mStartTime, notify lastPlayTime - node.mStartTime ); if (notify && !mPlayingSet.contains(node)) { if (!mPlayingSet.contains(node)) { mPlayingSet.add(node); } } } } if (currentPlayTime <= 0 && notify) { if (currentPlayTime <= 0) { notifyEndListeners(true); } } else { if (notify) { notifyStartListeners(false); } int eventsSize = mEvents.size(); for (int i = 0; i < eventsSize; i++) { AnimationEvent event = mEvents.get(i); Loading @@ -955,35 +946,30 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim if (lastPlayTime < end && end <= currentPlayTime) { animator.animateSkipToEnds( end - node.mStartTime, lastPlayTime - node.mStartTime, notify lastPlayTime - node.mStartTime ); if (notify) { mPlayingSet.remove(node); } } else if (start <= currentPlayTime && currentPlayTime <= end) { animator.animateSkipToEnds( currentPlayTime - node.mStartTime, lastPlayTime - node.mStartTime, notify lastPlayTime - node.mStartTime ); if (notify && !mPlayingSet.contains(node)) { if (!mPlayingSet.contains(node)) { mPlayingSet.add(node); } } } } if (currentPlayTime >= getTotalDuration() && notify) { if (currentPlayTime >= getTotalDuration()) { notifyEndListeners(false); } } } @Override void animateValuesInRange(long currentPlayTime, long lastPlayTime, boolean notify) { void animateValuesInRange(long currentPlayTime, long lastPlayTime) { initAnimation(); if (notify) { if (lastPlayTime < 0 || (lastPlayTime == 0 && currentPlayTime > 0)) { notifyStartListeners(false); } else { Loading @@ -995,7 +981,6 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim notifyStartListeners(true); } } } int eventsSize = mEvents.size(); for (int i = 0; i < eventsSize; i++) { Loading @@ -1014,8 +999,7 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim ) { animator.animateValuesInRange( currentPlayTime - node.mStartTime, Math.max(-1, lastPlayTime - node.mStartTime), notify Math.max(-1, lastPlayTime - node.mStartTime) ); } } Loading Loading @@ -1111,7 +1095,7 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim } } mSeekState.setPlayTime(playTime, mReversing); animateBasedOnPlayTime(playTime, lastPlayTime, mReversing, true); animateBasedOnPlayTime(playTime, lastPlayTime, mReversing); } /** Loading Loading @@ -1144,16 +1128,7 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim private void initChildren() { if (!isInitialized()) { mChildrenInitialized = true; // We have to initialize all the start values so that they are based on the previous // values. long[] times = ensureChildStartAndEndTimes(); long previousTime = -1; for (long time : times) { animateBasedOnPlayTime(time, previousTime, false, false); previousTime = time; } skipToEndValue(false); } } Loading Loading @@ -1489,6 +1464,7 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim anim.mPauseTime = -1; anim.mSeekState = new SeekState(); anim.mSelfPulse = true; anim.mStartListenersCalled = false; anim.mPlayingSet = new ArrayList<Node>(); anim.mNodeMap = new ArrayMap<Animator, Node>(); anim.mNodes = new ArrayList<Node>(nodeCount); Loading core/java/android/animation/ValueAnimator.java +11 −17 Original line number Diff line number Diff line Loading @@ -1417,14 +1417,13 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio * will be called. */ @Override void animateValuesInRange(long currentPlayTime, long lastPlayTime, boolean notify) { void animateValuesInRange(long currentPlayTime, long lastPlayTime) { if (currentPlayTime < 0 || lastPlayTime < -1) { throw new UnsupportedOperationException("Error: Play time should never be negative."); } initAnimation(); long duration = getTotalDuration(); if (notify) { if (lastPlayTime < 0 || (lastPlayTime == 0 && currentPlayTime > 0)) { notifyStartListeners(false); } else if (lastPlayTime > duration Loading @@ -1432,7 +1431,6 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio ) { notifyStartListeners(true); } } if (duration >= 0) { lastPlayTime = Math.min(duration, lastPlayTime); } Loading @@ -1448,7 +1446,7 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio iteration = Math.min(iteration, mRepeatCount); lastIteration = Math.min(lastIteration, mRepeatCount); if (notify && iteration != lastIteration) { if (iteration != lastIteration) { notifyListeners(AnimatorCaller.ON_REPEAT, false); } } Loading @@ -1464,7 +1462,7 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio } @Override void animateSkipToEnds(long currentPlayTime, long lastPlayTime, boolean notify) { void animateSkipToEnds(long currentPlayTime, long lastPlayTime) { boolean inReverse = currentPlayTime < lastPlayTime; boolean doSkip; if (currentPlayTime <= 0 && lastPlayTime > 0) { Loading @@ -1474,15 +1472,11 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio doSkip = duration >= 0 && currentPlayTime >= duration && lastPlayTime < duration; } if (doSkip) { if (notify) { notifyStartListeners(inReverse); } skipToEndValue(inReverse); if (notify) { notifyEndListeners(inReverse); } } } /** * Internal use only. Loading core/tests/coretests/src/android/animation/AnimatorSetActivityTest.java +37 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import android.util.Property; import android.view.View; import androidx.test.annotation.UiThreadTest; Loading Loading @@ -576,6 +577,42 @@ public class AnimatorSetActivityTest { }); } @Test public void testInitializeWithoutReadingValues() throws Throwable { // Some consumers crash while reading values before the animator starts 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[] target1 = new int[1]; int[] target2 = new int[1]; int[] target3 = new int[1]; ObjectAnimator animator1 = ObjectAnimator.ofInt(target1, property, 0, 100); ObjectAnimator animator2 = ObjectAnimator.ofInt(target2, property, 0, 100); ObjectAnimator animator3 = ObjectAnimator.ofInt(target3, property, 0, 100); AnimatorSet set = new AnimatorSet(); set.playSequentially(animator1, animator2, animator3); mActivityRule.runOnUiThread(() -> { set.setCurrentPlayTime(900); assertEquals(100, target1[0]); assertEquals(100, target2[0]); assertEquals(100, target3[0]); set.setCurrentPlayTime(0); assertEquals(0, target1[0]); assertEquals(0, target2[0]); assertEquals(0, target3[0]); }); } /** * Check that the animator list contains exactly the given animators and nothing else. */ Loading Loading
core/java/android/animation/Animator.java +2 −2 Original line number Diff line number Diff line Loading @@ -568,13 +568,13 @@ public abstract class Animator implements Cloneable { * repetition. lastPlayTime is similar and is used to calculate how many repeats have been * done between the two times. */ void animateValuesInRange(long currentPlayTime, long lastPlayTime, boolean notify) {} void animateValuesInRange(long currentPlayTime, long lastPlayTime) {} /** * Internal use only. This animates any animation that has ended since lastPlayTime. * If an animation hasn't been finished, no change will be made. */ void animateSkipToEnds(long currentPlayTime, long lastPlayTime, boolean notify) {} void animateSkipToEnds(long currentPlayTime, long lastPlayTime) {} /** * Internal use only. Adds all start times (after delay) to and end times to times. Loading
core/java/android/animation/AnimatorSet.java +34 −58 Original line number Diff line number Diff line Loading @@ -825,8 +825,7 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim private void animateBasedOnPlayTime( long currentPlayTime, long lastPlayTime, boolean inReverse, boolean notify boolean inReverse ) { if (currentPlayTime < 0 || lastPlayTime < -1) { throw new UnsupportedOperationException("Error: Play time should never be negative."); Loading Loading @@ -857,8 +856,8 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim while (index < endIndex) { long playTime = startEndTimes[index]; if (lastPlayTime != playTime) { animateSkipToEnds(playTime, lastPlayTime, notify); animateValuesInRange(playTime, lastPlayTime, notify); animateSkipToEnds(playTime, lastPlayTime); animateValuesInRange(playTime, lastPlayTime); lastPlayTime = playTime; } index++; Loading @@ -868,15 +867,15 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim index--; long playTime = startEndTimes[index]; if (lastPlayTime != playTime) { animateSkipToEnds(playTime, lastPlayTime, notify); animateValuesInRange(playTime, lastPlayTime, notify); animateSkipToEnds(playTime, lastPlayTime); animateValuesInRange(playTime, lastPlayTime); lastPlayTime = playTime; } } } if (currentPlayTime != lastPlayTime) { animateSkipToEnds(currentPlayTime, lastPlayTime, notify); animateValuesInRange(currentPlayTime, lastPlayTime, notify); animateSkipToEnds(currentPlayTime, lastPlayTime); animateValuesInRange(currentPlayTime, lastPlayTime); } } Loading @@ -896,13 +895,11 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim } @Override void animateSkipToEnds(long currentPlayTime, long lastPlayTime, boolean notify) { void animateSkipToEnds(long currentPlayTime, long lastPlayTime) { initAnimation(); if (lastPlayTime > currentPlayTime) { if (notify) { notifyStartListeners(true); } for (int i = mEvents.size() - 1; i >= 0; i--) { AnimationEvent event = mEvents.get(i); Node node = event.mNode; Loading @@ -916,31 +913,25 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim if (currentPlayTime <= start && start < lastPlayTime) { animator.animateSkipToEnds( 0, lastPlayTime - node.mStartTime, notify lastPlayTime - node.mStartTime ); if (notify) { mPlayingSet.remove(node); } } else if (start <= currentPlayTime && currentPlayTime <= end) { animator.animateSkipToEnds( currentPlayTime - node.mStartTime, lastPlayTime - node.mStartTime, notify lastPlayTime - node.mStartTime ); if (notify && !mPlayingSet.contains(node)) { if (!mPlayingSet.contains(node)) { mPlayingSet.add(node); } } } } if (currentPlayTime <= 0 && notify) { if (currentPlayTime <= 0) { notifyEndListeners(true); } } else { if (notify) { notifyStartListeners(false); } int eventsSize = mEvents.size(); for (int i = 0; i < eventsSize; i++) { AnimationEvent event = mEvents.get(i); Loading @@ -955,35 +946,30 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim if (lastPlayTime < end && end <= currentPlayTime) { animator.animateSkipToEnds( end - node.mStartTime, lastPlayTime - node.mStartTime, notify lastPlayTime - node.mStartTime ); if (notify) { mPlayingSet.remove(node); } } else if (start <= currentPlayTime && currentPlayTime <= end) { animator.animateSkipToEnds( currentPlayTime - node.mStartTime, lastPlayTime - node.mStartTime, notify lastPlayTime - node.mStartTime ); if (notify && !mPlayingSet.contains(node)) { if (!mPlayingSet.contains(node)) { mPlayingSet.add(node); } } } } if (currentPlayTime >= getTotalDuration() && notify) { if (currentPlayTime >= getTotalDuration()) { notifyEndListeners(false); } } } @Override void animateValuesInRange(long currentPlayTime, long lastPlayTime, boolean notify) { void animateValuesInRange(long currentPlayTime, long lastPlayTime) { initAnimation(); if (notify) { if (lastPlayTime < 0 || (lastPlayTime == 0 && currentPlayTime > 0)) { notifyStartListeners(false); } else { Loading @@ -995,7 +981,6 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim notifyStartListeners(true); } } } int eventsSize = mEvents.size(); for (int i = 0; i < eventsSize; i++) { Loading @@ -1014,8 +999,7 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim ) { animator.animateValuesInRange( currentPlayTime - node.mStartTime, Math.max(-1, lastPlayTime - node.mStartTime), notify Math.max(-1, lastPlayTime - node.mStartTime) ); } } Loading Loading @@ -1111,7 +1095,7 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim } } mSeekState.setPlayTime(playTime, mReversing); animateBasedOnPlayTime(playTime, lastPlayTime, mReversing, true); animateBasedOnPlayTime(playTime, lastPlayTime, mReversing); } /** Loading Loading @@ -1144,16 +1128,7 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim private void initChildren() { if (!isInitialized()) { mChildrenInitialized = true; // We have to initialize all the start values so that they are based on the previous // values. long[] times = ensureChildStartAndEndTimes(); long previousTime = -1; for (long time : times) { animateBasedOnPlayTime(time, previousTime, false, false); previousTime = time; } skipToEndValue(false); } } Loading Loading @@ -1489,6 +1464,7 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim anim.mPauseTime = -1; anim.mSeekState = new SeekState(); anim.mSelfPulse = true; anim.mStartListenersCalled = false; anim.mPlayingSet = new ArrayList<Node>(); anim.mNodeMap = new ArrayMap<Animator, Node>(); anim.mNodes = new ArrayList<Node>(nodeCount); Loading
core/java/android/animation/ValueAnimator.java +11 −17 Original line number Diff line number Diff line Loading @@ -1417,14 +1417,13 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio * will be called. */ @Override void animateValuesInRange(long currentPlayTime, long lastPlayTime, boolean notify) { void animateValuesInRange(long currentPlayTime, long lastPlayTime) { if (currentPlayTime < 0 || lastPlayTime < -1) { throw new UnsupportedOperationException("Error: Play time should never be negative."); } initAnimation(); long duration = getTotalDuration(); if (notify) { if (lastPlayTime < 0 || (lastPlayTime == 0 && currentPlayTime > 0)) { notifyStartListeners(false); } else if (lastPlayTime > duration Loading @@ -1432,7 +1431,6 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio ) { notifyStartListeners(true); } } if (duration >= 0) { lastPlayTime = Math.min(duration, lastPlayTime); } Loading @@ -1448,7 +1446,7 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio iteration = Math.min(iteration, mRepeatCount); lastIteration = Math.min(lastIteration, mRepeatCount); if (notify && iteration != lastIteration) { if (iteration != lastIteration) { notifyListeners(AnimatorCaller.ON_REPEAT, false); } } Loading @@ -1464,7 +1462,7 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio } @Override void animateSkipToEnds(long currentPlayTime, long lastPlayTime, boolean notify) { void animateSkipToEnds(long currentPlayTime, long lastPlayTime) { boolean inReverse = currentPlayTime < lastPlayTime; boolean doSkip; if (currentPlayTime <= 0 && lastPlayTime > 0) { Loading @@ -1474,15 +1472,11 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio doSkip = duration >= 0 && currentPlayTime >= duration && lastPlayTime < duration; } if (doSkip) { if (notify) { notifyStartListeners(inReverse); } skipToEndValue(inReverse); if (notify) { notifyEndListeners(inReverse); } } } /** * Internal use only. Loading
core/tests/coretests/src/android/animation/AnimatorSetActivityTest.java +37 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import android.util.Property; import android.view.View; import androidx.test.annotation.UiThreadTest; Loading Loading @@ -576,6 +577,42 @@ public class AnimatorSetActivityTest { }); } @Test public void testInitializeWithoutReadingValues() throws Throwable { // Some consumers crash while reading values before the animator starts 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[] target1 = new int[1]; int[] target2 = new int[1]; int[] target3 = new int[1]; ObjectAnimator animator1 = ObjectAnimator.ofInt(target1, property, 0, 100); ObjectAnimator animator2 = ObjectAnimator.ofInt(target2, property, 0, 100); ObjectAnimator animator3 = ObjectAnimator.ofInt(target3, property, 0, 100); AnimatorSet set = new AnimatorSet(); set.playSequentially(animator1, animator2, animator3); mActivityRule.runOnUiThread(() -> { set.setCurrentPlayTime(900); assertEquals(100, target1[0]); assertEquals(100, target2[0]); assertEquals(100, target3[0]); set.setCurrentPlayTime(0); assertEquals(0, target1[0]); assertEquals(0, target2[0]); assertEquals(0, target3[0]); }); } /** * Check that the animator list contains exactly the given animators and nothing else. */ Loading