Merge "Moving all hierarchy chain to top when adjust focusable task." into rvc-dev

This commit is contained in:
Wei Sheng Shih
2020-06-15 09:43:05 +00:00
committed by Android (Google) Code Review
4 changed files with 68 additions and 27 deletions

View File

@@ -813,7 +813,7 @@ class ActivityStack extends Task {
/** Resume next focusable stack after reparenting to another display. */ /** Resume next focusable stack after reparenting to another display. */
void postReparent() { void postReparent() {
adjustFocusToNextFocusableTask("reparent", true /* allowFocusSelf */, adjustFocusToNextFocusableTask("reparent", true /* allowFocusSelf */,
true /* moveParentsToTop */); true /* moveDisplayToTop */);
mRootWindowContainer.resumeFocusedStacksTopActivities(); mRootWindowContainer.resumeFocusedStacksTopActivities();
// Update visibility of activities before notifying WM. This way it won't try to resize // Update visibility of activities before notifying WM. This way it won't try to resize
// windows that are no longer visible. // windows that are no longer visible.

View File

@@ -2638,7 +2638,7 @@ class Task extends WindowContainer<WindowContainer> {
*/ */
ActivityStack adjustFocusToNextFocusableTask(String reason) { ActivityStack adjustFocusToNextFocusableTask(String reason) {
return adjustFocusToNextFocusableTask(reason, false /* allowFocusSelf */, return adjustFocusToNextFocusableTask(reason, false /* allowFocusSelf */,
true /* moveParentsToTop */); true /* moveDisplayToTop */);
} }
/** Return the next focusable task by looking from the siblings and parent tasks */ /** Return the next focusable task by looking from the siblings and parent tasks */
@@ -2661,11 +2661,11 @@ class Task extends WindowContainer<WindowContainer> {
* Find next proper focusable task and make it focused. * Find next proper focusable task and make it focused.
* @param reason The reason of making the adjustment. * @param reason The reason of making the adjustment.
* @param allowFocusSelf Is the focus allowed to remain on the same task. * @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. * @return The root task that now got the focus, {@code null} if none found.
*/ */
ActivityStack adjustFocusToNextFocusableTask(String reason, boolean allowFocusSelf, ActivityStack adjustFocusToNextFocusableTask(String reason, boolean allowFocusSelf,
boolean moveParentsToTop) { boolean moveDisplayToTop) {
ActivityStack focusableTask = (ActivityStack) getNextFocusableTask(allowFocusSelf); ActivityStack focusableTask = (ActivityStack) getNextFocusableTask(allowFocusSelf);
if (focusableTask == null) { if (focusableTask == null) {
focusableTask = mRootWindowContainer.getNextFocusableStack((ActivityStack) this, focusableTask = mRootWindowContainer.getNextFocusableStack((ActivityStack) this,
@@ -2676,10 +2676,17 @@ class Task extends WindowContainer<WindowContainer> {
} }
final ActivityStack rootTask = (ActivityStack) focusableTask.getRootTask(); final ActivityStack rootTask = (ActivityStack) focusableTask.getRootTask();
if (!moveParentsToTop) { if (!moveDisplayToTop) {
// Only move the next stack to top in its task container. // 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(); 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; return rootTask;
} }

View File

@@ -299,8 +299,17 @@ final class TaskDisplayArea extends DisplayArea<ActivityStack> {
@Override @Override
void positionChildAt(int position, ActivityStack child, boolean includingParents) { 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); 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) { if (child.getWindowConfiguration().isAlwaysOnTop() && !moveToTop) {
// This stack is always-on-top, override the default behavior. // This stack is always-on-top, override the default behavior.
Slog.w(TAG_WM, "Ignoring move of always-on-top stack=" + this + " to bottom"); Slog.w(TAG_WM, "Ignoring move of always-on-top stack=" + this + " to bottom");
@@ -330,6 +339,17 @@ final class TaskDisplayArea extends DisplayArea<ActivityStack> {
child.updateTaskMovement(moveToTop); child.updateTaskMovement(moveToTop);
mDisplayContent.setLayoutNeeded(); 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;
}
} }
/** /**
@@ -727,29 +747,10 @@ final class TaskDisplayArea extends DisplayArea<ActivityStack> {
"positionStackAt: Can only have one task on display=" + this); "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, // Since positionChildAt() is called during the creation process of pinned stacks,
// ActivityStack#getStack() can be null. // ActivityStack#getStack() can be null.
positionStackAt(position, stack, includingParents); 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) { if (updateLastFocusedStackReason != null) {
final ActivityStack currentFocusedStack = getFocusedStack(); final ActivityStack currentFocusedStack = getFocusedStack();
if (currentFocusedStack != prevFocusedStack) { if (currentFocusedStack != prevFocusedStack) {

View File

@@ -793,6 +793,39 @@ public class ActivityRecordTests extends ActivityTestsBase {
assertEquals(mTask, mStack.getTopMostTask()); 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. * Verify that resumed activity is paused due to finish request.
*/ */