summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java23
-rw-r--r--services/core/java/com/android/server/wm/ActivityStack.java47
-rw-r--r--services/core/java/com/android/server/wm/Task.java74
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java25
4 files changed, 108 insertions, 61 deletions
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 521ffa50f869..1bf070f4bf3c 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -2536,23 +2536,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
pauseKeyDispatchingLocked();
- // We are finishing the top focused activity and its stack has nothing to be focused so
- // the next focusable stack should be focused.
- if (mayAdjustTop
- && (stack.topRunningActivity() == null || !stack.isTopActivityFocusable())) {
- if (shouldAdjustGlobalFocus) {
- // Move the entire hierarchy to top with updating global top resumed activity
- // and focused application if needed.
- stack.adjustFocusToNextFocusableStack("finish-top");
- } else {
- // Only move the next stack to top in its task container.
- final TaskDisplayArea taskDisplayArea = stack.getDisplayArea();
- next = taskDisplayArea.topRunningActivity();
- if (next != null) {
- taskDisplayArea.positionStackAtTop(next.getRootTask(),
- false /* includingParents */, "finish-display-top");
- }
- }
+ // We are finishing the top focused activity and its task has nothing to be focused so
+ // the next focusable task should be focused.
+ if (mayAdjustTop && ((ActivityStack) task).topRunningActivity(true /* focusableOnly */)
+ == null) {
+ task.adjustFocusToNextFocusableTask("finish-top", false /* allowFocusSelf */,
+ shouldAdjustGlobalFocus);
}
finishActivityResults(resultCode, resultData);
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 5968eede0a27..265b5e26720e 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -856,7 +856,8 @@ class ActivityStack extends Task {
/** Resume next focusable stack after reparenting to another display. */
void postReparent() {
- adjustFocusToNextFocusableStack("reparent", true /* allowFocusSelf */);
+ adjustFocusToNextFocusableTask("reparent", true /* allowFocusSelf */,
+ true /* moveParentsToTop */);
mRootWindowContainer.resumeFocusedStacksTopActivities();
// Update visibility of activities before notifying WM. This way it won't try to resize
// windows that are no longer visible.
@@ -2282,7 +2283,7 @@ class ActivityStack extends Task {
final String reason = "noMoreActivities";
if (!isActivityTypeHome()) {
- final ActivityStack nextFocusedStack = adjustFocusToNextFocusableStack(reason);
+ final ActivityStack nextFocusedStack = adjustFocusToNextFocusableTask(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
@@ -2491,48 +2492,6 @@ class ActivityStack extends Task {
}
/**
- * Find next proper focusable stack and make it focused.
- * @return The stack that now got the focus, {@code null} if none found.
- */
- ActivityStack adjustFocusToNextFocusableStack(String reason) {
- return adjustFocusToNextFocusableStack(reason, false /* allowFocusSelf */);
- }
-
- /**
- * Find next proper focusable stack and make it focused.
- * @param allowFocusSelf Is the focus allowed to remain on the same stack.
- * @return The stack that now got the focus, {@code null} if none found.
- */
- private ActivityStack adjustFocusToNextFocusableStack(String reason, boolean allowFocusSelf) {
- final ActivityStack stack =
- mRootWindowContainer.getNextFocusableStack(this, !allowFocusSelf);
- final String myReason = reason + " adjustFocusToNextFocusableStack";
- if (stack == null) {
- return null;
- }
-
- final ActivityRecord top = stack.topRunningActivity();
-
- if (stack.isActivityTypeHome() && (top == null || !top.mVisibleRequested)) {
- // If we will be focusing on the home stack next and its current top activity isn't
- // visible, then use the move the home stack task to top to make the activity visible.
- stack.getDisplayArea().moveHomeActivityToTop(reason);
- return stack;
- }
-
- stack.moveToFront(myReason);
- // Top display focused stack is changed, update top resumed activity if needed.
- if (stack.mResumedActivity != null) {
- mStackSupervisor.updateTopResumedActivityIfNeeded();
- // Set focused app directly because if the next focused activity is already resumed
- // (e.g. the next top activity is on a different display), there won't have activity
- // state change to update it.
- mAtmService.setResumedActivityUncheckLocked(stack.mResumedActivity, reason);
- }
- return stack;
- }
-
- /**
* Finish the topmost activity that belongs to the crashed app. We may also finish the activity
* that requested launch of the crashed one to prevent launch-crash loop.
* @param app The app that crashed.
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 1ffa01c2bd66..7d43d0014853 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -2572,6 +2572,80 @@ class Task extends WindowContainer<WindowContainer> {
return currentCount[0];
}
+ /**
+ * Find next proper focusable stack and make it focused.
+ * @return The stack that now got the focus, {@code null} if none found.
+ */
+ ActivityStack adjustFocusToNextFocusableTask(String reason) {
+ return adjustFocusToNextFocusableTask(reason, false /* allowFocusSelf */,
+ true /* moveParentsToTop */);
+ }
+
+ /** Return the next focusable task by looking from the siblings and parent tasks */
+ private Task getNextFocusableTask(boolean allowFocusSelf) {
+ final WindowContainer parent = getParent();
+ if (parent == null) {
+ return null;
+ }
+
+ final Task focusableTask = parent.getTask((task) -> (allowFocusSelf || task != this)
+ && ((ActivityStack) task).isFocusableAndVisible());
+ if (focusableTask == null && parent.asTask() != null) {
+ return parent.asTask().getNextFocusableTask(allowFocusSelf);
+ } else {
+ return focusableTask;
+ }
+ }
+
+ /**
+ * Find next proper focusable task and make it focused.
+ * @param reason The reason of making the adjustment.
+ * @param allowFocusSelf Is the focus allowed to remain on the same task.
+ * @param moveParentsToTop Whether to move parents to top while making the task focused.
+ * @return The root task that now got the focus, {@code null} if none found.
+ */
+ ActivityStack adjustFocusToNextFocusableTask(String reason, boolean allowFocusSelf,
+ boolean moveParentsToTop) {
+ ActivityStack focusableTask = (ActivityStack) getNextFocusableTask(allowFocusSelf);
+ if (focusableTask == null) {
+ focusableTask = mRootWindowContainer.getNextFocusableStack((ActivityStack) this,
+ !allowFocusSelf);
+ }
+ if (focusableTask == null) {
+ return null;
+ }
+
+ final String myReason = reason + " adjustFocusToNextFocusableStack";
+ final ActivityRecord top = focusableTask.topRunningActivity();
+ final ActivityStack rootTask = (ActivityStack) focusableTask.getRootTask();
+ if (focusableTask.isActivityTypeHome() && (top == null || !top.mVisibleRequested)) {
+ // If we will be focusing on the home stack next and its current top activity isn't
+ // visible, then use the move the home stack task to top to make the activity visible.
+ focusableTask.getDisplayArea().moveHomeActivityToTop(myReason);
+ return rootTask;
+ }
+
+ if (!moveParentsToTop) {
+ // Only move the next stack to top in its task container.
+ WindowContainer parent = focusableTask.getParent();
+ parent.positionChildAt(POSITION_TOP, focusableTask, false /* includingParents */);
+ return rootTask;
+ }
+
+ // Move the entire hierarchy to top with updating global top resumed activity
+ // and focused application if needed.
+ focusableTask.moveToFront(myReason);
+ // Top display focused stack is changed, update top resumed activity if needed.
+ if (rootTask.mResumedActivity != null) {
+ mStackSupervisor.updateTopResumedActivityIfNeeded();
+ // Set focused app directly because if the next focused activity is already resumed
+ // (e.g. the next top activity is on a different display), there won't have activity
+ // state change to update it.
+ mAtmService.setResumedActivityUncheckLocked(rootTask.mResumedActivity, reason);
+ }
+ return rootTask;
+ }
+
/** Calculate the minimum possible position for a task that can be shown to the user.
* The minimum position will be above all other tasks that can't be shown.
* @param minPosition The minimum position the caller is suggesting.
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 5bbb4d9e712c..6a28918eab00 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -752,6 +752,31 @@ public class ActivityRecordTests extends ActivityTestsBase {
}
/**
+ * Verify that when finishing the top focused activity while root task was created by organizer,
+ * the stack order will be changed by adjusting focus.
+ */
+ @Test
+ public void testFinishActivityIfPossible_adjustStackOrderOrganizedRoot() {
+ // Make mStack be a the root task that created by task organizer
+ mStack.mCreatedByOrganizer = true;
+
+ // Have two tasks (topRootableTask and mTask) as the children of mStack.
+ ActivityRecord topActivity = new ActivityBuilder(mActivity.mAtmService)
+ .setCreateTask(true)
+ .setStack(mStack)
+ .build();
+ ActivityStack topRootableTask = (ActivityStack) topActivity.getTask();
+ topRootableTask.moveToFront("test");
+ assertTrue(mStack.isTopStackInDisplayArea());
+
+ // Finish top activity and verify the next focusable rootable task has adjusted to top.
+ topActivity.setState(RESUMED, "test");
+ topActivity.finishIfPossible(0 /* resultCode */, null /* resultData */, "test",
+ false /* oomAdj */);
+ assertEquals(mTask, mStack.getTopMostTask());
+ }
+
+ /**
* Verify that resumed activity is paused due to finish request.
*/
@Test