diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 8514f3599832c..542ec809c4842 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 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A 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 821683043804c..b7713a9338de8 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 @@ public class ActivityRecordTests extends WindowTestsBase { 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 111449d2c1003..588089996d6c8 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 @@ class WindowTestsBase extends SystemServiceTestsBase { private Bundle mIntentExtras; private boolean mOnTop = false; private ActivityInfo.WindowLayout mWindowLayout; + private boolean mVisible = true; ActivityBuilder(ActivityTaskManagerService service) { mService = service; @@ -930,6 +931,11 @@ class WindowTestsBase extends SystemServiceTestsBase { return this; } + ActivityBuilder setVisible(boolean visible) { + mVisible = visible; + return this; + } + ActivityRecord build() { SystemServicesTestRule.checkHoldsLock(mService.mGlobalLock); try { @@ -1012,9 +1018,10 @@ class WindowTestsBase extends SystemServiceTestsBase { // 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;