Merge "Avoid applying closing animation for invisible activity." into sc-dev
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 8514f35..542ec80 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -4593,7 +4593,7 @@
             if (visible) {
                 displayContent.mOpeningApps.add(this);
                 mEnteringAnimation = true;
-            } else {
+            } else if (mVisible) {
                 displayContent.mClosingApps.add(this);
                 mEnteringAnimation = false;
             }
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 8216830..b7713a9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -2699,6 +2699,85 @@
         assertFalse("Starting window should not be present", activity.hasStartingWindow());
     }
 
+    @Test
+    public void testSetVisibility_visibleToVisible() {
+        final ActivityRecord activity = new ActivityBuilder(mAtm)
+                .setCreateTask(true).build();
+        // By default, activity is visible.
+        assertTrue(activity.isVisible());
+        assertTrue(activity.mVisibleRequested);
+        assertTrue(activity.mDisplayContent.mOpeningApps.contains(activity));
+        assertFalse(activity.mDisplayContent.mClosingApps.contains(activity));
+
+        // Request the activity to be visible. Although the activity is already visible, app
+        // transition animation should be applied on this activity. This might be unnecessary, but
+        // until we verify no logic relies on this behavior, we'll keep this as is.
+        activity.setVisibility(true);
+        assertTrue(activity.isVisible());
+        assertTrue(activity.mVisibleRequested);
+        assertTrue(activity.mDisplayContent.mOpeningApps.contains(activity));
+        assertFalse(activity.mDisplayContent.mClosingApps.contains(activity));
+    }
+
+    @Test
+    public void testSetVisibility_visibleToInvisible() {
+        final ActivityRecord activity = new ActivityBuilder(mAtm)
+                .setCreateTask(true).build();
+        // By default, activity is visible.
+        assertTrue(activity.isVisible());
+        assertTrue(activity.mVisibleRequested);
+        assertTrue(activity.mDisplayContent.mOpeningApps.contains(activity));
+        assertFalse(activity.mDisplayContent.mClosingApps.contains(activity));
+
+        // Request the activity to be invisible. Since the visibility changes, app transition
+        // animation should be applied on this activity.
+        activity.setVisibility(false);
+        assertTrue(activity.isVisible());
+        assertFalse(activity.mVisibleRequested);
+        assertFalse(activity.mDisplayContent.mOpeningApps.contains(activity));
+        assertTrue(activity.mDisplayContent.mClosingApps.contains(activity));
+    }
+
+    @Test
+    public void testSetVisibility_invisibleToVisible() {
+        final ActivityRecord activity = new ActivityBuilder(mAtm)
+                .setCreateTask(true).setVisible(false).build();
+        // Activiby is invisible. However ATMS requests it to become visible, since this is a top
+        // activity.
+        assertFalse(activity.isVisible());
+        assertTrue(activity.mVisibleRequested);
+        assertTrue(activity.mDisplayContent.mOpeningApps.contains(activity));
+        assertFalse(activity.mDisplayContent.mClosingApps.contains(activity));
+
+        // Request the activity to be visible. Since the visibility changes, app transition
+        // animation should be applied on this activity.
+        activity.setVisibility(true);
+        assertFalse(activity.isVisible());
+        assertTrue(activity.mVisibleRequested);
+        assertTrue(activity.mDisplayContent.mOpeningApps.contains(activity));
+        assertFalse(activity.mDisplayContent.mClosingApps.contains(activity));
+    }
+
+    @Test
+    public void testSetVisibility_invisibleToInvisible() {
+        final ActivityRecord activity = new ActivityBuilder(mAtm)
+                .setCreateTask(true).setVisible(false).build();
+        // Activiby is invisible. However ATMS requests it to become visible, since this is a top
+        // activity.
+        assertFalse(activity.isVisible());
+        assertTrue(activity.mVisibleRequested);
+        assertTrue(activity.mDisplayContent.mOpeningApps.contains(activity));
+        assertFalse(activity.mDisplayContent.mClosingApps.contains(activity));
+
+        // Request the activity to be invisible. Since the activity is already invisible, no app
+        // transition should be applied on this activity.
+        activity.setVisibility(false);
+        assertFalse(activity.isVisible());
+        assertFalse(activity.mVisibleRequested);
+        assertFalse(activity.mDisplayContent.mOpeningApps.contains(activity));
+        assertFalse(activity.mDisplayContent.mClosingApps.contains(activity));
+    }
+
     private void assertHasStartingWindow(ActivityRecord atoken) {
         assertNotNull(atoken.mStartingSurface);
         assertNotNull(atoken.mStartingData);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index 111449d..5880899 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -805,6 +805,7 @@
         private Bundle mIntentExtras;
         private boolean mOnTop = false;
         private ActivityInfo.WindowLayout mWindowLayout;
+        private boolean mVisible = true;
 
         ActivityBuilder(ActivityTaskManagerService service) {
             mService = service;
@@ -930,6 +931,11 @@
             return this;
         }
 
+        ActivityBuilder setVisible(boolean visible) {
+            mVisible = visible;
+            return this;
+        }
+
         ActivityRecord build() {
             SystemServicesTestRule.checkHoldsLock(mService.mGlobalLock);
             try {
@@ -1012,9 +1018,10 @@
                     // root tasks (e.g. home root task).
                     mTask.moveToFront("createActivity");
                 }
-                // Make visible by default...
-                activity.mVisibleRequested = true;
-                activity.setVisible(true);
+                if (mVisible) {
+                    activity.mVisibleRequested = true;
+                    activity.setVisible(true);
+                }
             }
 
             final WindowProcessController wpc;