summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/tests/src/androidx/core/animation/AnimatorTestRule2.java174
-rw-r--r--packages/SystemUI/tests/src/androidx/core/animation/AnimatorTestRuleTest.kt77
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImplTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java4
5 files changed, 257 insertions, 6 deletions
diff --git a/packages/SystemUI/tests/src/androidx/core/animation/AnimatorTestRule2.java b/packages/SystemUI/tests/src/androidx/core/animation/AnimatorTestRule2.java
new file mode 100644
index 000000000000..e93e86291535
--- /dev/null
+++ b/packages/SystemUI/tests/src/androidx/core/animation/AnimatorTestRule2.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2023 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 androidx.core.animation;
+
+import android.os.Looper;
+import android.os.SystemClock;
+import android.util.AndroidRuntimeException;
+
+import androidx.annotation.NonNull;
+
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * NOTE: this is a copy of the {@link androidx.core.animation.AnimatorTestRule} which attempts to
+ * circumvent the problems with {@link androidx.core.animation.AnimationHandler} having a static
+ * list of callbacks.
+ *
+ * TODO(b/275602127): remove this and use the original rule once we have the updated androidx code.
+ */
+public final class AnimatorTestRule2 implements TestRule {
+
+ class TestAnimationHandler extends AnimationHandler {
+ TestAnimationHandler() {
+ super(new TestProvider());
+ }
+
+ List<AnimationFrameCallback> animationCallbacks = new ArrayList<>();
+
+ @Override
+ void addAnimationFrameCallback(AnimationFrameCallback callback) {
+ animationCallbacks.add(callback);
+ callback.doAnimationFrame(getCurrentTime());
+ }
+
+ @Override
+ public void removeCallback(AnimationFrameCallback callback) {
+ int id = animationCallbacks.indexOf(callback);
+ if (id >= 0) {
+ animationCallbacks.set(id, null);
+ }
+ }
+
+ void onAnimationFrame(long frameTime) {
+ for (int i = 0; i < animationCallbacks.size(); i++) {
+ final AnimationFrameCallback callback = animationCallbacks.get(i);
+ if (callback == null) {
+ continue;
+ }
+ callback.doAnimationFrame(frameTime);
+ }
+ }
+
+ @Override
+ void autoCancelBasedOn(ObjectAnimator objectAnimator) {
+ for (int i = animationCallbacks.size() - 1; i >= 0; i--) {
+ AnimationFrameCallback cb = animationCallbacks.get(i);
+ if (cb == null) {
+ continue;
+ }
+ if (objectAnimator.shouldAutoCancel(cb)) {
+ ((Animator) animationCallbacks.get(i)).cancel();
+ }
+ }
+ }
+ }
+
+ final TestAnimationHandler mTestHandler;
+ final long mStartTime;
+ private long mTotalTimeDelta = 0;
+ private final Object mLock = new Object();
+
+ public AnimatorTestRule2() {
+ mStartTime = SystemClock.uptimeMillis();
+ mTestHandler = new TestAnimationHandler();
+ }
+
+ @NonNull
+ @Override
+ public Statement apply(@NonNull final Statement base, @NonNull Description description) {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ AnimationHandler.setTestHandler(mTestHandler);
+ try {
+ base.evaluate();
+ } finally {
+ AnimationHandler.setTestHandler(null);
+ }
+ }
+ };
+ }
+
+ /**
+ * Advances the animation clock by the given amount of delta in milliseconds. This call will
+ * produce an animation frame to all the ongoing animations. This method needs to be
+ * called on the same thread as {@link Animator#start()}.
+ *
+ * @param timeDelta the amount of milliseconds to advance
+ */
+ public void advanceTimeBy(long timeDelta) {
+ if (Looper.myLooper() == null) {
+ // Throw an exception
+ throw new AndroidRuntimeException("AnimationTestRule#advanceTimeBy(long) may only be"
+ + "called on Looper threads");
+ }
+ synchronized (mLock) {
+ // Advance time & pulse a frame
+ mTotalTimeDelta += timeDelta < 0 ? 0 : timeDelta;
+ }
+ // produce a frame
+ mTestHandler.onAnimationFrame(getCurrentTime());
+ }
+
+
+ /**
+ * Returns the current time in milliseconds tracked by AnimationHandler. Note that this is a
+ * different time than the time tracked by {@link SystemClock} This method needs to be called on
+ * the same thread as {@link Animator#start()}.
+ */
+ public long getCurrentTime() {
+ if (Looper.myLooper() == null) {
+ // Throw an exception
+ throw new AndroidRuntimeException("AnimationTestRule#getCurrentTime() may only be"
+ + "called on Looper threads");
+ }
+ synchronized (mLock) {
+ return mStartTime + mTotalTimeDelta;
+ }
+ }
+
+
+ private class TestProvider implements AnimationHandler.AnimationFrameCallbackProvider {
+ TestProvider() {
+ }
+
+ @Override
+ public void onNewCallbackAdded(AnimationHandler.AnimationFrameCallback callback) {
+ callback.doAnimationFrame(getCurrentTime());
+ }
+
+ @Override
+ public void postFrameCallback() {
+ }
+
+ @Override
+ public void setFrameDelay(long delay) {
+ }
+
+ @Override
+ public long getFrameDelay() {
+ return 0;
+ }
+ }
+}
+
diff --git a/packages/SystemUI/tests/src/androidx/core/animation/AnimatorTestRuleTest.kt b/packages/SystemUI/tests/src/androidx/core/animation/AnimatorTestRuleTest.kt
new file mode 100644
index 000000000000..bddd60b5970a
--- /dev/null
+++ b/packages/SystemUI/tests/src/androidx/core/animation/AnimatorTestRuleTest.kt
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2023 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 androidx.core.animation
+
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper.RunWithLooper
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.doOnEnd
+import com.google.common.truth.Truth.assertThat
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+@RunWithLooper(setAsMainLooper = true)
+class AnimatorTestRuleTest : SysuiTestCase() {
+
+ @get:Rule val animatorTestRule = AnimatorTestRule2()
+
+ @Test
+ fun testA() {
+ didTouchA = false
+ didTouchB = false
+ ObjectAnimator.ofFloat(0f, 1f).apply {
+ duration = 100
+ doOnEnd { didTouchA = true }
+ start()
+ }
+ ObjectAnimator.ofFloat(0f, 1f).apply {
+ duration = 150
+ doOnEnd { didTouchA = true }
+ start()
+ }
+ animatorTestRule.advanceTimeBy(100)
+ assertThat(didTouchA).isTrue()
+ assertThat(didTouchB).isFalse()
+ }
+
+ @Test
+ fun testB() {
+ didTouchA = false
+ didTouchB = false
+ ObjectAnimator.ofFloat(0f, 1f).apply {
+ duration = 100
+ doOnEnd { didTouchB = true }
+ start()
+ }
+ ObjectAnimator.ofFloat(0f, 1f).apply {
+ duration = 150
+ doOnEnd { didTouchB = true }
+ start()
+ }
+ animatorTestRule.advanceTimeBy(100)
+ assertThat(didTouchA).isFalse()
+ assertThat(didTouchB).isTrue()
+ }
+
+ companion object {
+ var didTouchA = false
+ var didTouchB = false
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImplTest.kt
index 08a9f3139d71..7b59cc284181 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImplTest.kt
@@ -22,7 +22,7 @@ import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper
import android.view.View
import android.widget.FrameLayout
-import androidx.core.animation.AnimatorTestRule
+import androidx.core.animation.AnimatorTestRule2
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
@@ -70,7 +70,7 @@ class SystemStatusAnimationSchedulerImplTest : SysuiTestCase() {
private lateinit var systemStatusAnimationScheduler: SystemStatusAnimationScheduler
private val fakeFeatureFlags = FakeFeatureFlags()
- @get:Rule val animatorTestRule = AnimatorTestRule()
+ @get:Rule val animatorTestRule = AnimatorTestRule2()
@Before
fun setup() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorTest.kt
index aff705f1f3bf..be3b7234a1a2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorTest.kt
@@ -18,7 +18,7 @@ package com.android.systemui.statusbar.notification
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
-import androidx.core.animation.AnimatorTestRule
+import androidx.core.animation.AnimatorTestRule2
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
@@ -51,7 +51,7 @@ import org.mockito.Mockito.verifyNoMoreInteractions
@TestableLooper.RunWithLooper(setAsMainLooper = true)
class NotificationWakeUpCoordinatorTest : SysuiTestCase() {
- @get:Rule val animatorTestRule = AnimatorTestRule()
+ @get:Rule val animatorTestRule = AnimatorTestRule2()
private val dumpManager: DumpManager = mock()
private val headsUpManager: HeadsUpManager = mock()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java
index 0cca7b2aa38c..1880c2bd16a2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java
@@ -62,7 +62,7 @@ import android.window.OnBackInvokedDispatcher;
import android.window.WindowOnBackInvokedDispatcher;
import androidx.annotation.NonNull;
-import androidx.core.animation.AnimatorTestRule;
+import androidx.core.animation.AnimatorTestRule2;
import androidx.test.filters.SmallTest;
import com.android.internal.logging.UiEventLogger;
@@ -110,7 +110,7 @@ public class RemoteInputViewTest extends SysuiTestCase {
private final UiEventLoggerFake mUiEventLoggerFake = new UiEventLoggerFake();
@ClassRule
- public static AnimatorTestRule mAnimatorTestRule = new AnimatorTestRule();
+ public static AnimatorTestRule2 mAnimatorTestRule = new AnimatorTestRule2();
@Before
public void setUp() throws Exception {