Include INVISIBLE views in animations by the ViewHierarchyAnimator.

If we exclude them, they behave incorrectly as they fade in and out
while moving. They still take up space on screen while invisible, so they
should be animated along with the rest of the views.

Bug: 234337113
Test: included
Change-Id: Ifa31bd0b526a504b8f60ff8893d3d1caa673eb90
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt
index 4b0c62b..cc7d23e 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt
@@ -106,7 +106,7 @@
             ephemeral: Boolean
         ): Boolean {
             if (
-                !isVisible(
+                !occupiesSpace(
                     rootView.visibility,
                     rootView.left,
                     rootView.top,
@@ -177,7 +177,7 @@
             fadeInInterpolator: Interpolator = DEFAULT_FADE_IN_INTERPOLATOR
         ): Boolean {
             if (
-                isVisible(
+                occupiesSpace(
                     rootView.visibility,
                     rootView.left,
                     rootView.top,
@@ -295,7 +295,7 @@
 
                     (view.getTag(R.id.tag_animator) as? ObjectAnimator)?.cancel()
 
-                    if (!isVisible(view.visibility, left, top, right, bottom)) {
+                    if (!occupiesSpace(view.visibility, left, top, right, bottom)) {
                         setBound(view, Bound.LEFT, left)
                         setBound(view, Bound.TOP, top)
                         setBound(view, Bound.RIGHT, right)
@@ -362,7 +362,7 @@
             duration: Long = DEFAULT_DURATION
         ): Boolean {
             if (
-                !isVisible(
+                !occupiesSpace(
                     rootView.visibility,
                     rootView.left,
                     rootView.top,
@@ -530,17 +530,17 @@
         }
 
         /**
-         * Returns whether the given [visibility] and bounds are consistent with a view being
-         * currently visible on screen.
+         * Returns whether the given [visibility] and bounds are consistent with a view being a
+         * contributing part of the hierarchy.
          */
-        private fun isVisible(
+        private fun occupiesSpace(
             visibility: Int,
             left: Int,
             top: Int,
             right: Int,
             bottom: Int
         ): Boolean {
-            return visibility == View.VISIBLE && left != right && top != bottom
+            return visibility != View.GONE && left != right && top != bottom
         }
 
         /**
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/ViewHierarchyAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/ViewHierarchyAnimatorTest.kt
index b61fbbe..273786d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/ViewHierarchyAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/animation/ViewHierarchyAnimatorTest.kt
@@ -207,6 +207,25 @@
     }
 
     @Test
+    fun animatesInvisibleViews() {
+        rootView.layout(10 /* l */, 10 /* t */, 50 /* r */, 50 /* b */)
+        rootView.visibility = View.INVISIBLE
+
+        val success = ViewHierarchyAnimator.animate(rootView)
+        // Change all bounds.
+        rootView.layout(0 /* l */, 15 /* t */, 70 /* r */, 80 /* b */)
+
+        assertTrue(success)
+        assertNotNull(rootView.getTag(R.id.tag_animator))
+        // The initial values should be those of the previous layout.
+        checkBounds(rootView, l = 10, t = 10, r = 50, b = 50)
+        endAnimation(rootView)
+        assertNull(rootView.getTag(R.id.tag_animator))
+        // The end values should be those of the latest layout.
+        checkBounds(rootView, l = 0, t = 15, r = 70, b = 80)
+    }
+
+    @Test
     fun animatesAppearingViewsFromStartToEnd() {
         // Starting GONE.
         rootView.visibility = View.GONE
@@ -222,20 +241,6 @@
         assertNull(rootView.getTag(R.id.tag_animator))
         checkBounds(rootView, l = 0, t = 100, r = 100, b = 200)
 
-        // Starting INVISIBLE.
-        rootView.visibility = View.INVISIBLE
-        rootView.layout(0 /* l */, 50 /* t */, 50 /* r */, 100 /* b */)
-        success = ViewHierarchyAnimator.animateAddition(rootView)
-        rootView.visibility = View.VISIBLE
-        rootView.layout(0 /* l */, 100 /* t */, 100 /* r */, 200 /* b */)
-
-        assertTrue(success)
-        assertNotNull(rootView.getTag(R.id.tag_animator))
-        checkBounds(rootView, l = 50, t = 150, r = 50, b = 150)
-        endAnimation(rootView)
-        assertNull(rootView.getTag(R.id.tag_animator))
-        checkBounds(rootView, l = 0, t = 100, r = 100, b = 200)
-
         // Starting with nothing.
         rootView.layout(0 /* l */, 0 /* t */, 0 /* r */, 0 /* b */)
         success = ViewHierarchyAnimator.animateAddition(rootView)
@@ -937,7 +942,7 @@
     }
 
     @Test
-    fun doesNotAnimateInvisibleViews() {
+    fun doesNotAnimateGoneViews() {
         rootView.layout(10 /* l */, 10 /* t */, 50 /* r */, 50 /* b */)
 
         // GONE
@@ -948,15 +953,6 @@
         assertFalse(success)
         assertNull(rootView.getTag(R.id.tag_animator))
         checkBounds(rootView, l = 0, t = 15, r = 55, b = 80)
-
-        // INVISIBLE.
-        rootView.visibility = View.INVISIBLE
-        success = ViewHierarchyAnimator.animate(rootView)
-        rootView.layout(0 /* l */, 20 /* t */, 10 /* r */, 50 /* b */)
-
-        assertFalse(success)
-        assertNull(rootView.getTag(R.id.tag_animator))
-        checkBounds(rootView, l = 0, t = 20, r = 10, b = 50)
     }
 
     @Test