Loading services/core/java/com/android/server/wm/ActivityStack.java +24 −12 Original line number Diff line number Diff line Loading @@ -2639,7 +2639,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; Loading Loading @@ -3040,21 +3040,33 @@ class ActivityStack extends ConfigurationContainer { return true; } private boolean resumeTopActivityInNextFocusableStack(ActivityRecord prev, ActivityOptions options, String reason) { /** * 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 */); // 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); } Loading services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java +54 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -396,6 +398,58 @@ public class RootActivityContainerTests extends ActivityTestsBase { eq(activity), eq(null /* targetOptions */)); } /** * 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 Loading Loading
services/core/java/com/android/server/wm/ActivityStack.java +24 −12 Original line number Diff line number Diff line Loading @@ -2639,7 +2639,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; Loading Loading @@ -3040,21 +3040,33 @@ class ActivityStack extends ConfigurationContainer { return true; } private boolean resumeTopActivityInNextFocusableStack(ActivityRecord prev, ActivityOptions options, String reason) { /** * 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 */); // 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); } Loading
services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java +54 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -396,6 +398,58 @@ public class RootActivityContainerTests extends ActivityTestsBase { eq(activity), eq(null /* targetOptions */)); } /** * 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 Loading