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

Commit 0d7d665e authored by Jeff DeCew's avatar Jeff DeCew
Browse files

Ensure AnimatorTestRule timing is perfectly synchronized.

Bug: 302149604
Test: atest AnimatorTestRuleOrderTest
Change-Id: Idda613f9cf953b2b3492dbc26181b75f813c1d0b
parent 27eab0bc
Loading
Loading
Loading
Loading
+17 −4
Original line number Diff line number Diff line
@@ -68,13 +68,26 @@ public final class AnimatorTestRule implements TestRule {

    private final Object mLock = new Object();
    private final TestHandler mTestHandler = new TestHandler();
    private final long mStartTime;
    private long mTotalTimeDelta = 0;

    /**
     * Construct an AnimatorTestRule with a custom start time.
     * @see #AnimatorTestRule()
     */
    public AnimatorTestRule(long startTime) {
        mStartTime = startTime;
    }

    /**
     * initializing the start time with {@link SystemClock#uptimeMillis()} reduces the discrepancies
     * with various internals of classes like ValueAnimator which can sometimes read that clock via
     * Construct an AnimatorTestRule with a start time of {@link SystemClock#uptimeMillis()}.
     * Initializing the start time with this clock reduces the discrepancies with various internals
     * of classes like ValueAnimator which can sometimes read that clock via
     * {@link android.view.animation.AnimationUtils#currentAnimationTimeMillis()}.
     */
    private final long mStartTime = SystemClock.uptimeMillis();
    private long mTotalTimeDelta = 0;
    public AnimatorTestRule() {
        this(SystemClock.uptimeMillis());
    }

    @NonNull
    @Override
+18 −1
Original line number Diff line number Diff line
@@ -28,11 +28,21 @@ import org.junit.runners.model.Statement
 * advanced together.
 */
class AnimatorTestRule : TestRule {
    // Create the androidx rule, which initializes start time to SystemClock.uptimeMillis(),
    // then copy that time to the platform rule so that the two clocks are in sync.
    private val androidxRule = androidx.core.animation.AnimatorTestRule()
    private val platformRule = android.animation.AnimatorTestRule()
    private val platformRule = android.animation.AnimatorTestRule(androidxRule.startTime)
    private val advanceAndroidXTimeBy =
        Consumer<Long> { timeDelta -> androidxRule.advanceTimeBy(timeDelta) }

    /** Access the mStartTime field; bypassing the restriction of being on a looper thread. */
    private val androidx.core.animation.AnimatorTestRule.startTime: Long
        get() =
            javaClass.getDeclaredField("mStartTime").let { field ->
                field.isAccessible = true
                field.getLong(this)
            }

    /**
     * Chain is for simplicity not to force a particular order; order should not matter, because
     * each rule affects a different AnimationHandler classes, and no callbacks to code under test
@@ -55,4 +65,11 @@ class AnimatorTestRule : TestRule {
        //  animation from one to start later than the other.
        platformRule.advanceTimeBy(timeDelta, advanceAndroidXTimeBy)
    }

    /**
     * Returns the current time in milliseconds tracked by the AnimationHandlers. Note that this is
     * a different time than the time tracked by {@link SystemClock}.
     */
    val currentTime: Long
        get() = androidxRule.currentTime
}