Add androidx Animator isolation checks to SysuiTestCase

Bug: 291645410
Test: atest SystemUITests
Change-Id: I638d983939d3ba2ee29c6ea994a13e700ec34ac4
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemEventChipAnimationControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemEventChipAnimationControllerTest.kt
index 0b2da8b..0cfca61 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemEventChipAnimationControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemEventChipAnimationControllerTest.kt
@@ -24,6 +24,7 @@
 import android.view.Gravity
 import android.view.View
 import android.widget.FrameLayout
+import androidx.core.animation.AnimatorTestRule
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.flags.FakeFeatureFlags
@@ -38,6 +39,7 @@
 import org.junit.Assert.assertFalse
 import org.junit.Assert.assertTrue
 import org.junit.Before
+import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.Mock
@@ -50,6 +52,7 @@
 class SystemEventChipAnimationControllerTest : SysuiTestCase() {
     private lateinit var controller: SystemEventChipAnimationController
 
+    @get:Rule val animatorTestRule = AnimatorTestRule()
     @Mock private lateinit var sbWindowController: StatusBarWindowController
     @Mock private lateinit var insetsProvider: StatusBarContentInsetsProvider
 
diff --git a/packages/SystemUI/tests/utils/src/androidx/core/animation/AndroidXAnimatorIsolationRule.kt b/packages/SystemUI/tests/utils/src/androidx/core/animation/AndroidXAnimatorIsolationRule.kt
new file mode 100644
index 0000000..026372f
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/androidx/core/animation/AndroidXAnimatorIsolationRule.kt
@@ -0,0 +1,55 @@
+/*
+ * 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 org.junit.rules.TestRule
+import org.junit.runner.Description
+import org.junit.runners.model.Statement
+
+class AndroidXAnimatorIsolationRule : TestRule {
+
+    private class TestAnimationHandler : AnimationHandler(null) {
+        override fun addAnimationFrameCallback(callback: AnimationFrameCallback?) = doFail()
+        override fun removeCallback(callback: AnimationFrameCallback?) = doFail()
+        override fun onAnimationFrame(frameTime: Long) = doFail()
+        override fun setFrameDelay(frameDelay: Long) = doFail()
+        override fun getFrameDelay(): Long = doFail()
+    }
+
+    override fun apply(base: Statement, description: Description): Statement {
+        return object : Statement() {
+            @Throws(Throwable::class)
+            override fun evaluate() {
+                AnimationHandler.setTestHandler(testHandler)
+                try {
+                    base.evaluate()
+                } finally {
+                    AnimationHandler.setTestHandler(null)
+                }
+            }
+        }
+    }
+
+    companion object {
+        private val testHandler = TestAnimationHandler()
+        private fun doFail(): Nothing =
+            error(
+                "Test's animations are not isolated! " +
+                    "Did you forget to add an AnimatorTestRule to your test class?"
+            )
+    }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java
index de177168..28b7d41 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java
@@ -33,6 +33,7 @@
 import android.testing.TestableLooper;
 import android.util.Log;
 
+import androidx.core.animation.AndroidXAnimatorIsolationRule;
 import androidx.test.InstrumentationRegistry;
 import androidx.test.uiautomator.UiDevice;
 
@@ -52,6 +53,7 @@
 import org.junit.After;
 import org.junit.AfterClass;
 import org.junit.Before;
+import org.junit.ClassRule;
 import org.junit.Rule;
 import org.mockito.Mockito;
 
@@ -69,6 +71,12 @@
     private static final String TAG = "SysuiTestCase";
 
     private Handler mHandler;
+
+    // set the lowest order so it's the outermost rule
+    @ClassRule(order = Integer.MIN_VALUE)
+    public static AndroidXAnimatorIsolationRule mAndroidXAnimatorIsolationRule =
+            new AndroidXAnimatorIsolationRule();
+
     @Rule
     public SysuiTestableContext mContext = new SysuiTestableContext(
             InstrumentationRegistry.getContext(), getLeakCheck());