Loading services/core/java/com/android/server/wm/ActivityStack.java +1 −1 Original line number Diff line number Diff line Loading @@ -813,7 +813,7 @@ class ActivityStack extends Task { /** Resume next focusable stack after reparenting to another display. */ void postReparent() { adjustFocusToNextFocusableTask("reparent", true /* allowFocusSelf */, true /* moveParentsToTop */); true /* moveDisplayToTop */); mRootWindowContainer.resumeFocusedStacksTopActivities(); // Update visibility of activities before notifying WM. This way it won't try to resize // windows that are no longer visible. Loading services/core/java/com/android/server/wm/Task.java +13 −6 Original line number Diff line number Diff line Loading @@ -2638,7 +2638,7 @@ class Task extends WindowContainer<WindowContainer> { */ ActivityStack adjustFocusToNextFocusableTask(String reason) { return adjustFocusToNextFocusableTask(reason, false /* allowFocusSelf */, true /* moveParentsToTop */); true /* moveDisplayToTop */); } /** Return the next focusable task by looking from the siblings and parent tasks */ Loading @@ -2661,11 +2661,11 @@ class Task extends WindowContainer<WindowContainer> { * 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. * @param moveDisplayToTop Whether to move display 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) { boolean moveDisplayToTop) { ActivityStack focusableTask = (ActivityStack) getNextFocusableTask(allowFocusSelf); if (focusableTask == null) { focusableTask = mRootWindowContainer.getNextFocusableStack((ActivityStack) this, Loading @@ -2676,10 +2676,17 @@ class Task extends WindowContainer<WindowContainer> { } final ActivityStack rootTask = (ActivityStack) focusableTask.getRootTask(); if (!moveParentsToTop) { // Only move the next stack to top in its task container. if (!moveDisplayToTop) { // There may be multiple task layers above this task, so when relocating the task to the // top, we should move this task and each of its parent task that below display area to // the top of each layer. WindowContainer parent = focusableTask.getParent(); parent.positionChildAt(POSITION_TOP, focusableTask, false /* includingParents */); WindowContainer next = focusableTask; do { parent.positionChildAt(POSITION_TOP, next, false /* includingParents */); next = parent; parent = next.getParent(); } while (next.asTask() != null && parent != null); return rootTask; } Loading services/core/java/com/android/server/wm/TaskDisplayArea.java +21 −20 Original line number Diff line number Diff line Loading @@ -299,8 +299,17 @@ final class TaskDisplayArea extends DisplayArea<ActivityStack> { @Override void positionChildAt(int position, ActivityStack child, boolean includingParents) { final boolean moveToTop = (position == POSITION_TOP || position == getChildCount()); final boolean moveToTop = position >= getChildCount() - 1; final boolean moveToBottom = (position == POSITION_BOTTOM || position == 0); // Reset mPreferredTopFocusableStack before positioning to top or {@link // ActivityStackSupervisor#updateTopResumedActivityIfNeeded()} won't update the top // resumed activity. final boolean wasContained = mChildren.contains(child); if (moveToTop && wasContained && child.isFocusable()) { mPreferredTopFocusableStack = null; } if (child.getWindowConfiguration().isAlwaysOnTop() && !moveToTop) { // This stack is always-on-top, override the default behavior. Slog.w(TAG_WM, "Ignoring move of always-on-top stack=" + this + " to bottom"); Loading Loading @@ -330,6 +339,17 @@ final class TaskDisplayArea extends DisplayArea<ActivityStack> { child.updateTaskMovement(moveToTop); mDisplayContent.setLayoutNeeded(); // The insert position may be adjusted to non-top when there is always-on-top stack. Since // the original position is preferred to be top, the stack should have higher priority when // we are looking for top focusable stack. The condition {@code wasContained} restricts the // preferred stack is set only when moving an existing stack to top instead of adding a new // stack that may be too early (e.g. in the middle of launching or reparenting). if (moveToTop && child.isFocusableAndVisible()) { mPreferredTopFocusableStack = child; } else if (mPreferredTopFocusableStack == child) { mPreferredTopFocusableStack = null; } } /** Loading Loading @@ -727,29 +747,10 @@ final class TaskDisplayArea extends DisplayArea<ActivityStack> { "positionStackAt: Can only have one task on display=" + this); } final boolean movingToTop = wasContained && position >= getStackCount() - 1; // Reset mPreferredTopFocusableStack before positioning to top or {@link // ActivityStackSupervisor#updateTopResumedActivityIfNeeded()} won't update the top // resumed activity. if (movingToTop && stack.isFocusable()) { mPreferredTopFocusableStack = null; } // Since positionChildAt() is called during the creation process of pinned stacks, // ActivityStack#getStack() can be null. positionStackAt(position, stack, includingParents); // The insert position may be adjusted to non-top when there is always-on-top stack. Since // the original position is preferred to be top, the stack should have higher priority when // we are looking for top focusable stack. The condition {@code wasContained} restricts the // preferred stack is set only when moving an existing stack to top instead of adding a new // stack that may be too early (e.g. in the middle of launching or reparenting). if (movingToTop && stack.isFocusableAndVisible()) { mPreferredTopFocusableStack = stack; } else if (mPreferredTopFocusableStack == stack) { mPreferredTopFocusableStack = null; } if (updateLastFocusedStackReason != null) { final ActivityStack currentFocusedStack = getFocusedStack(); if (currentFocusedStack != prevFocusedStack) { Loading services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +33 −0 Original line number Diff line number Diff line Loading @@ -793,6 +793,39 @@ public class ActivityRecordTests extends ActivityTestsBase { assertEquals(mTask, mStack.getTopMostTask()); } /** * Verify that when top focused activity is on secondary display, when finishing the top focused * activity on default display, the preferred top stack on default display should be changed by * adjusting focus. */ @Test public void testFinishActivityIfPossible_PreferredTopStackChanged() { final ActivityRecord topActivityOnNonTopDisplay = createActivityOnDisplay(true /* defaultDisplay */, null /* process */); ActivityStack topRootableTask = topActivityOnNonTopDisplay.getRootTask(); topRootableTask.moveToFront("test"); assertTrue(topRootableTask.isTopStackInDisplayArea()); assertEquals(topRootableTask, topActivityOnNonTopDisplay.getDisplayArea() .mPreferredTopFocusableStack); final ActivityRecord secondaryDisplayActivity = createActivityOnDisplay(false /* defaultDisplay */, null /* process */); topRootableTask = secondaryDisplayActivity.getRootTask(); topRootableTask.moveToFront("test"); assertTrue(topRootableTask.isTopStackInDisplayArea()); assertEquals(topRootableTask, secondaryDisplayActivity.getDisplayArea().mPreferredTopFocusableStack); // The global top focus activity is on secondary display now. // Finish top activity on default display and verify the next preferred top focusable stack // on default display has changed. topActivityOnNonTopDisplay.setState(RESUMED, "test"); topActivityOnNonTopDisplay.finishIfPossible(0 /* resultCode */, null /* resultData */, null /* resultGrants */, "test", false /* oomAdj */); assertEquals(mTask, mStack.getTopMostTask()); assertEquals(mStack, mActivity.getDisplayArea().mPreferredTopFocusableStack); } /** * Verify that resumed activity is paused due to finish request. */ Loading Loading
services/core/java/com/android/server/wm/ActivityStack.java +1 −1 Original line number Diff line number Diff line Loading @@ -813,7 +813,7 @@ class ActivityStack extends Task { /** Resume next focusable stack after reparenting to another display. */ void postReparent() { adjustFocusToNextFocusableTask("reparent", true /* allowFocusSelf */, true /* moveParentsToTop */); true /* moveDisplayToTop */); mRootWindowContainer.resumeFocusedStacksTopActivities(); // Update visibility of activities before notifying WM. This way it won't try to resize // windows that are no longer visible. Loading
services/core/java/com/android/server/wm/Task.java +13 −6 Original line number Diff line number Diff line Loading @@ -2638,7 +2638,7 @@ class Task extends WindowContainer<WindowContainer> { */ ActivityStack adjustFocusToNextFocusableTask(String reason) { return adjustFocusToNextFocusableTask(reason, false /* allowFocusSelf */, true /* moveParentsToTop */); true /* moveDisplayToTop */); } /** Return the next focusable task by looking from the siblings and parent tasks */ Loading @@ -2661,11 +2661,11 @@ class Task extends WindowContainer<WindowContainer> { * 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. * @param moveDisplayToTop Whether to move display 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) { boolean moveDisplayToTop) { ActivityStack focusableTask = (ActivityStack) getNextFocusableTask(allowFocusSelf); if (focusableTask == null) { focusableTask = mRootWindowContainer.getNextFocusableStack((ActivityStack) this, Loading @@ -2676,10 +2676,17 @@ class Task extends WindowContainer<WindowContainer> { } final ActivityStack rootTask = (ActivityStack) focusableTask.getRootTask(); if (!moveParentsToTop) { // Only move the next stack to top in its task container. if (!moveDisplayToTop) { // There may be multiple task layers above this task, so when relocating the task to the // top, we should move this task and each of its parent task that below display area to // the top of each layer. WindowContainer parent = focusableTask.getParent(); parent.positionChildAt(POSITION_TOP, focusableTask, false /* includingParents */); WindowContainer next = focusableTask; do { parent.positionChildAt(POSITION_TOP, next, false /* includingParents */); next = parent; parent = next.getParent(); } while (next.asTask() != null && parent != null); return rootTask; } Loading
services/core/java/com/android/server/wm/TaskDisplayArea.java +21 −20 Original line number Diff line number Diff line Loading @@ -299,8 +299,17 @@ final class TaskDisplayArea extends DisplayArea<ActivityStack> { @Override void positionChildAt(int position, ActivityStack child, boolean includingParents) { final boolean moveToTop = (position == POSITION_TOP || position == getChildCount()); final boolean moveToTop = position >= getChildCount() - 1; final boolean moveToBottom = (position == POSITION_BOTTOM || position == 0); // Reset mPreferredTopFocusableStack before positioning to top or {@link // ActivityStackSupervisor#updateTopResumedActivityIfNeeded()} won't update the top // resumed activity. final boolean wasContained = mChildren.contains(child); if (moveToTop && wasContained && child.isFocusable()) { mPreferredTopFocusableStack = null; } if (child.getWindowConfiguration().isAlwaysOnTop() && !moveToTop) { // This stack is always-on-top, override the default behavior. Slog.w(TAG_WM, "Ignoring move of always-on-top stack=" + this + " to bottom"); Loading Loading @@ -330,6 +339,17 @@ final class TaskDisplayArea extends DisplayArea<ActivityStack> { child.updateTaskMovement(moveToTop); mDisplayContent.setLayoutNeeded(); // The insert position may be adjusted to non-top when there is always-on-top stack. Since // the original position is preferred to be top, the stack should have higher priority when // we are looking for top focusable stack. The condition {@code wasContained} restricts the // preferred stack is set only when moving an existing stack to top instead of adding a new // stack that may be too early (e.g. in the middle of launching or reparenting). if (moveToTop && child.isFocusableAndVisible()) { mPreferredTopFocusableStack = child; } else if (mPreferredTopFocusableStack == child) { mPreferredTopFocusableStack = null; } } /** Loading Loading @@ -727,29 +747,10 @@ final class TaskDisplayArea extends DisplayArea<ActivityStack> { "positionStackAt: Can only have one task on display=" + this); } final boolean movingToTop = wasContained && position >= getStackCount() - 1; // Reset mPreferredTopFocusableStack before positioning to top or {@link // ActivityStackSupervisor#updateTopResumedActivityIfNeeded()} won't update the top // resumed activity. if (movingToTop && stack.isFocusable()) { mPreferredTopFocusableStack = null; } // Since positionChildAt() is called during the creation process of pinned stacks, // ActivityStack#getStack() can be null. positionStackAt(position, stack, includingParents); // The insert position may be adjusted to non-top when there is always-on-top stack. Since // the original position is preferred to be top, the stack should have higher priority when // we are looking for top focusable stack. The condition {@code wasContained} restricts the // preferred stack is set only when moving an existing stack to top instead of adding a new // stack that may be too early (e.g. in the middle of launching or reparenting). if (movingToTop && stack.isFocusableAndVisible()) { mPreferredTopFocusableStack = stack; } else if (mPreferredTopFocusableStack == stack) { mPreferredTopFocusableStack = null; } if (updateLastFocusedStackReason != null) { final ActivityStack currentFocusedStack = getFocusedStack(); if (currentFocusedStack != prevFocusedStack) { Loading
services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +33 −0 Original line number Diff line number Diff line Loading @@ -793,6 +793,39 @@ public class ActivityRecordTests extends ActivityTestsBase { assertEquals(mTask, mStack.getTopMostTask()); } /** * Verify that when top focused activity is on secondary display, when finishing the top focused * activity on default display, the preferred top stack on default display should be changed by * adjusting focus. */ @Test public void testFinishActivityIfPossible_PreferredTopStackChanged() { final ActivityRecord topActivityOnNonTopDisplay = createActivityOnDisplay(true /* defaultDisplay */, null /* process */); ActivityStack topRootableTask = topActivityOnNonTopDisplay.getRootTask(); topRootableTask.moveToFront("test"); assertTrue(topRootableTask.isTopStackInDisplayArea()); assertEquals(topRootableTask, topActivityOnNonTopDisplay.getDisplayArea() .mPreferredTopFocusableStack); final ActivityRecord secondaryDisplayActivity = createActivityOnDisplay(false /* defaultDisplay */, null /* process */); topRootableTask = secondaryDisplayActivity.getRootTask(); topRootableTask.moveToFront("test"); assertTrue(topRootableTask.isTopStackInDisplayArea()); assertEquals(topRootableTask, secondaryDisplayActivity.getDisplayArea().mPreferredTopFocusableStack); // The global top focus activity is on secondary display now. // Finish top activity on default display and verify the next preferred top focusable stack // on default display has changed. topActivityOnNonTopDisplay.setState(RESUMED, "test"); topActivityOnNonTopDisplay.finishIfPossible(0 /* resultCode */, null /* resultData */, null /* resultGrants */, "test", false /* oomAdj */); assertEquals(mTask, mStack.getTopMostTask()); assertEquals(mStack, mActivity.getDisplayArea().mPreferredTopFocusableStack); } /** * Verify that resumed activity is paused due to finish request. */ Loading