Merge "Adjusting focus starting from sibling rootable app tasks" into rvc-dev

This commit is contained in:
TreeHugger Robot
2020-04-20 01:39:23 +00:00
committed by Android (Google) Code Review
4 changed files with 108 additions and 61 deletions

View File

@@ -2543,23 +2543,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);

View File

@@ -847,7 +847,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.
@@ -2069,7 +2070,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
@@ -2277,48 +2278,6 @@ class ActivityStack extends Task {
return taskTop;
}
/**
* 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.

View File

@@ -2579,6 +2579,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.

View File

@@ -751,6 +751,31 @@ public class ActivityRecordTests extends ActivityTestsBase {
assertTrue(stack1.isTopStackInDisplayArea());
}
/**
* 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.
*/