Loading services/core/java/com/android/server/am/ActivityStackSupervisor.java +22 −13 Original line number Diff line number Diff line Loading @@ -2305,17 +2305,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D mUserLeaving = true; } // TODO(b/111363427): The moving-to-top task may not be on the top display, so it could be // different from where the prev activity stays on. final ActivityRecord prev = topRunningActivityLocked(); if ((flags & ActivityManager.MOVE_TASK_WITH_HOME) != 0 || (prev != null && prev.isActivityTypeRecents())) { // Caller wants the home activity moved with it or the previous task is recents in which // case we always return home from the task we are moving to the front. currentStack.getDisplay().moveHomeStackToFront("findTaskToMoveToFront"); } reason = reason + " findTaskToMoveToFront"; boolean reparented = false; if (task.isResizeable() && canUseActivityOptionsLaunchBounds(options)) { final Rect bounds = options.getLaunchBounds(); task.updateOverrideConfiguration(bounds); Loading @@ -2323,10 +2314,12 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D ActivityStack stack = getLaunchStack(null, options, task, ON_TOP); if (stack != currentStack) { moveHomeStackToFrontIfNeeded(flags, stack.getDisplay(), reason); task.reparent(stack, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, !ANIMATE, DEFER_RESUME, "findTaskToMoveToFront"); reason); currentStack = stack; // moveTaskToStackUncheckedLocked() should already placed the task on top, reparented = true; // task.reparent() should already placed the task on top, // still need moveTaskToFrontLocked() below for any transition settings. } if (stack.resizeStackWithLaunchBounds()) { Loading @@ -2341,6 +2334,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } } if (!reparented) { moveHomeStackToFrontIfNeeded(flags, currentStack.getDisplay(), reason); } final ActivityRecord r = task.getTopActivity(); currentStack.moveTaskToFrontLocked(task, false /* noAnimation */, options, r == null ? null : r.appTimeTracker, reason); Loading @@ -2352,6 +2349,18 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D currentStack, forceNonResizeable); } private void moveHomeStackToFrontIfNeeded(int flags, ActivityDisplay display, String reason) { final ActivityStack focusedStack = display.getFocusedStack(); if ((display.getWindowingMode() == WINDOWING_MODE_FULLSCREEN && (flags & ActivityManager.MOVE_TASK_WITH_HOME) != 0) || (focusedStack != null && focusedStack.isActivityTypeRecents())) { // We move home stack to front when we are on a fullscreen display and caller has // requested the home activity to move with it. Or the previous stack is recents. display.moveHomeStackToFront(reason); } } boolean canUseActivityOptionsLaunchBounds(ActivityOptions options) { // We use the launch bounds in the activity options is the device supports freeform // window management or is launching into the pinned stack. Loading services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java +54 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.server.am; import static android.app.ActivityManager.START_DELIVERED_TO_TOP; import static android.app.ActivityManager.START_TASK_TO_FRONT; import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY; Loading @@ -34,9 +35,11 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.contains; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; Loading Loading @@ -406,6 +409,57 @@ public class ActivityStackSupervisorTests extends ActivityTestsBase { assertEquals(task.getBounds(), TASK_SIZE); } /** * Verify that home stack would be moved to front when the top activity is Recents. */ @Test public void testFindTaskToMoveToFrontWhenRecentsOnTop() throws Exception { // Create stack/task on default display. final ActivityDisplay display = mSupervisor.getDefaultDisplay(); final ActivityStack targetStack = display.createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */); final TaskRecord targetTask = new TaskBuilder(mSupervisor).setStack(targetStack).build(); // Create Recents on top of the display. final ActivityStack stack = display.createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_RECENTS, true /* onTop */); final TaskRecord task = new TaskBuilder(mSupervisor).setStack(stack).build(); new ActivityBuilder(mService).setTask(task).build(); final String reason = "findTaskToMoveToFront"; mSupervisor.findTaskToMoveToFront(targetTask, 0, ActivityOptions.makeBasic(), reason, false); verify(display).moveHomeStackToFront(contains(reason)); } /** * Verify that home stack won't be moved to front if the top activity on other display is * Recents. */ @Test public void testFindTaskToMoveToFrontWhenRecentsOnOtherDisplay() throws Exception { // Create stack/task on default display. final ActivityDisplay display = mSupervisor.getDefaultDisplay(); final ActivityStack targetStack = display.createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */); final TaskRecord targetTask = new TaskBuilder(mSupervisor).setStack(targetStack).build(); // Create Recents on secondary display. final TestActivityDisplay secondDisplay = addNewActivityDisplayAt( ActivityDisplay.POSITION_TOP); final ActivityStack stack = secondDisplay.createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_RECENTS, true /* onTop */); final TaskRecord task = new TaskBuilder(mSupervisor).setStack(stack).build(); new ActivityBuilder(mService).setTask(task).build(); final String reason = "findTaskToMoveToFront"; mSupervisor.findTaskToMoveToFront(targetTask, 0, ActivityOptions.makeBasic(), reason, false); verify(display, never()).moveHomeStackToFront(contains(reason)); } /** * Verify if a stack is not at the topmost position, it should be able to resume its activity if * the stack is the top focused. Loading Loading
services/core/java/com/android/server/am/ActivityStackSupervisor.java +22 −13 Original line number Diff line number Diff line Loading @@ -2305,17 +2305,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D mUserLeaving = true; } // TODO(b/111363427): The moving-to-top task may not be on the top display, so it could be // different from where the prev activity stays on. final ActivityRecord prev = topRunningActivityLocked(); if ((flags & ActivityManager.MOVE_TASK_WITH_HOME) != 0 || (prev != null && prev.isActivityTypeRecents())) { // Caller wants the home activity moved with it or the previous task is recents in which // case we always return home from the task we are moving to the front. currentStack.getDisplay().moveHomeStackToFront("findTaskToMoveToFront"); } reason = reason + " findTaskToMoveToFront"; boolean reparented = false; if (task.isResizeable() && canUseActivityOptionsLaunchBounds(options)) { final Rect bounds = options.getLaunchBounds(); task.updateOverrideConfiguration(bounds); Loading @@ -2323,10 +2314,12 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D ActivityStack stack = getLaunchStack(null, options, task, ON_TOP); if (stack != currentStack) { moveHomeStackToFrontIfNeeded(flags, stack.getDisplay(), reason); task.reparent(stack, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, !ANIMATE, DEFER_RESUME, "findTaskToMoveToFront"); reason); currentStack = stack; // moveTaskToStackUncheckedLocked() should already placed the task on top, reparented = true; // task.reparent() should already placed the task on top, // still need moveTaskToFrontLocked() below for any transition settings. } if (stack.resizeStackWithLaunchBounds()) { Loading @@ -2341,6 +2334,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } } if (!reparented) { moveHomeStackToFrontIfNeeded(flags, currentStack.getDisplay(), reason); } final ActivityRecord r = task.getTopActivity(); currentStack.moveTaskToFrontLocked(task, false /* noAnimation */, options, r == null ? null : r.appTimeTracker, reason); Loading @@ -2352,6 +2349,18 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D currentStack, forceNonResizeable); } private void moveHomeStackToFrontIfNeeded(int flags, ActivityDisplay display, String reason) { final ActivityStack focusedStack = display.getFocusedStack(); if ((display.getWindowingMode() == WINDOWING_MODE_FULLSCREEN && (flags & ActivityManager.MOVE_TASK_WITH_HOME) != 0) || (focusedStack != null && focusedStack.isActivityTypeRecents())) { // We move home stack to front when we are on a fullscreen display and caller has // requested the home activity to move with it. Or the previous stack is recents. display.moveHomeStackToFront(reason); } } boolean canUseActivityOptionsLaunchBounds(ActivityOptions options) { // We use the launch bounds in the activity options is the device supports freeform // window management or is launching into the pinned stack. Loading
services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java +54 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.server.am; import static android.app.ActivityManager.START_DELIVERED_TO_TOP; import static android.app.ActivityManager.START_TASK_TO_FRONT; import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY; Loading @@ -34,9 +35,11 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.contains; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; Loading Loading @@ -406,6 +409,57 @@ public class ActivityStackSupervisorTests extends ActivityTestsBase { assertEquals(task.getBounds(), TASK_SIZE); } /** * Verify that home stack would be moved to front when the top activity is Recents. */ @Test public void testFindTaskToMoveToFrontWhenRecentsOnTop() throws Exception { // Create stack/task on default display. final ActivityDisplay display = mSupervisor.getDefaultDisplay(); final ActivityStack targetStack = display.createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */); final TaskRecord targetTask = new TaskBuilder(mSupervisor).setStack(targetStack).build(); // Create Recents on top of the display. final ActivityStack stack = display.createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_RECENTS, true /* onTop */); final TaskRecord task = new TaskBuilder(mSupervisor).setStack(stack).build(); new ActivityBuilder(mService).setTask(task).build(); final String reason = "findTaskToMoveToFront"; mSupervisor.findTaskToMoveToFront(targetTask, 0, ActivityOptions.makeBasic(), reason, false); verify(display).moveHomeStackToFront(contains(reason)); } /** * Verify that home stack won't be moved to front if the top activity on other display is * Recents. */ @Test public void testFindTaskToMoveToFrontWhenRecentsOnOtherDisplay() throws Exception { // Create stack/task on default display. final ActivityDisplay display = mSupervisor.getDefaultDisplay(); final ActivityStack targetStack = display.createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */); final TaskRecord targetTask = new TaskBuilder(mSupervisor).setStack(targetStack).build(); // Create Recents on secondary display. final TestActivityDisplay secondDisplay = addNewActivityDisplayAt( ActivityDisplay.POSITION_TOP); final ActivityStack stack = secondDisplay.createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_RECENTS, true /* onTop */); final TaskRecord task = new TaskBuilder(mSupervisor).setStack(stack).build(); new ActivityBuilder(mService).setTask(task).build(); final String reason = "findTaskToMoveToFront"; mSupervisor.findTaskToMoveToFront(targetTask, 0, ActivityOptions.makeBasic(), reason, false); verify(display, never()).moveHomeStackToFront(contains(reason)); } /** * Verify if a stack is not at the topmost position, it should be able to resume its activity if * the stack is the top focused. Loading