Merge "Always start launcher when empty home stack is being resumed" into qt-dev am: 331eb26c1c am: 2561483cbf
am: 124ac25d5d
Change-Id: I3d6db55c44034ed8d25c9ea504001df2e39bb70b
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index d18875f..4f40dc4 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 @@
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 @@
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 c77e25f..8d2c3dd 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.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 @@
}
/**
+ * 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
*/