diff options
| -rw-r--r-- | services/core/java/com/android/server/wm/ActivityStack.java | 36 | ||||
| -rw-r--r-- | services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java | 54 |
2 files changed, 78 insertions, 12 deletions
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java index d18875f9c058..4f40dc43c1b7 100644 --- a/services/core/java/com/android/server/wm/ActivityStack.java +++ b/services/core/java/com/android/server/wm/ActivityStack.java @@ -2640,7 +2640,7 @@ class ActivityStack extends ConfigurationContainer { if (!hasRunningActivity) { // There are no activities left in the stack, let's look somewhere else. - return resumeTopActivityInNextFocusableStack(prev, options, "noMoreActivities"); + return resumeNextFocusableActivityWhenStackIsEmpty(prev, options); } next.delayedResume = false; @@ -3041,21 +3041,33 @@ class ActivityStack extends ConfigurationContainer { return true; } - private boolean resumeTopActivityInNextFocusableStack(ActivityRecord prev, - ActivityOptions options, String reason) { - final ActivityStack nextFocusedStack = adjustFocusToNextFocusableStack(reason); - if (nextFocusedStack != null) { - // Try to move focus to the next visible stack with a running activity if this - // stack is not covering the entire screen or is on a secondary display (with no home - // stack). - return mRootActivityContainer.resumeFocusedStacksTopActivities(nextFocusedStack, prev, - null /* targetOptions */); + /** + * Resume the next eligible activity in a focusable stack when this one does not have any + * running activities left. The focus will be adjusted to the next focusable stack and + * top running activities will be resumed in all focusable stacks. However, if the current stack + * is a home stack - we have to keep it focused, start and resume a home activity on the current + * display instead to make sure that the display is not empty. + */ + private boolean resumeNextFocusableActivityWhenStackIsEmpty(ActivityRecord prev, + ActivityOptions options) { + final String reason = "noMoreActivities"; + + if (!isActivityTypeHome()) { + final ActivityStack nextFocusedStack = adjustFocusToNextFocusableStack(reason); + if (nextFocusedStack != null) { + // Try to move focus to the next visible stack with a running activity if this + // stack is not covering the entire screen or is on a secondary display with no home + // stack. + return mRootActivityContainer.resumeFocusedStacksTopActivities(nextFocusedStack, + prev, null /* targetOptions */); + } } - // Let's just start up the Launcher... + // If the current stack is a home stack, or if focus didn't switch to a different stack - + // just start up the Launcher... ActivityOptions.abort(options); if (DEBUG_STATES) Slog.d(TAG_STATES, - "resumeTopActivityInNextFocusableStack: " + reason + ", go home"); + "resumeNextFocusableActivityWhenStackIsEmpty: " + reason + ", go home"); return mRootActivityContainer.resumeHomeActivity(prev, reason, mDisplayId); } diff --git a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java index c77e25fabf19..8d2c3dd80538 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java @@ -16,6 +16,7 @@ package com.android.server.wm; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; @@ -35,6 +36,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.times; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.android.server.wm.ActivityDisplay.POSITION_TOP; import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING; +import static com.android.server.wm.ActivityStackSupervisor.ON_TOP; import static com.android.server.wm.RootActivityContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE; import static org.junit.Assert.assertEquals; @@ -397,6 +399,58 @@ public class RootActivityContainerTests extends ActivityTestsBase { } /** + * Verify that home activity will be started on a display even if another display has a + * focusable activity. + */ + @Test + public void testResumeFocusedStacksStartsHomeActivity_NoActivities() { + mFullscreenStack.remove(); + mService.mRootActivityContainer.getActivityDisplay(DEFAULT_DISPLAY).getHomeStack().remove(); + mService.mRootActivityContainer.getActivityDisplay(DEFAULT_DISPLAY) + .createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP); + + doReturn(true).when(mRootActivityContainer).resumeHomeActivity(any(), any(), anyInt()); + + mService.setBooted(true); + + // Trigger resume on all displays + mRootActivityContainer.resumeFocusedStacksTopActivities(); + + // Verify that home activity was started on the default display + verify(mRootActivityContainer).resumeHomeActivity(any(), any(), eq(DEFAULT_DISPLAY)); + } + + /** + * Verify that home activity will be started on a display even if another display has a + * focusable activity. + */ + @Test + public void testResumeFocusedStacksStartsHomeActivity_ActivityOnSecondaryScreen() { + mFullscreenStack.remove(); + mService.mRootActivityContainer.getActivityDisplay(DEFAULT_DISPLAY).getHomeStack().remove(); + mService.mRootActivityContainer.getActivityDisplay(DEFAULT_DISPLAY) + .createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP); + + // Create an activity on secondary display. + final TestActivityDisplay secondDisplay = addNewActivityDisplayAt( + ActivityDisplay.POSITION_TOP); + final ActivityStack stack = secondDisplay.createStack(WINDOWING_MODE_FULLSCREEN, + ACTIVITY_TYPE_STANDARD, true /* onTop */); + final TaskRecord task = new TaskBuilder(mSupervisor).setStack(stack).build(); + new ActivityBuilder(mService).setTask(task).build(); + + doReturn(true).when(mRootActivityContainer).resumeHomeActivity(any(), any(), anyInt()); + + mService.setBooted(true); + + // Trigger resume on all displays + mRootActivityContainer.resumeFocusedStacksTopActivities(); + + // Verify that home activity was started on the default display + verify(mRootActivityContainer).resumeHomeActivity(any(), any(), eq(DEFAULT_DISPLAY)); + } + + /** * Verify that a lingering transition is being executed in case the activity to be resumed is * already resumed */ |