Merge "Adjusting focus starting from sibling rootable app tasks" into rvc-dev am: d4fdca6e39 am: e2f710fa40
Change-Id: I9824fb8765af84c1e8432b74a46e30fe24dc190e
This commit is contained in:
@@ -2543,23 +2543,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
|||||||
|
|
||||||
pauseKeyDispatchingLocked();
|
pauseKeyDispatchingLocked();
|
||||||
|
|
||||||
// We are finishing the top focused activity and its stack has nothing to be focused so
|
// We are finishing the top focused activity and its task has nothing to be focused so
|
||||||
// the next focusable stack should be focused.
|
// the next focusable task should be focused.
|
||||||
if (mayAdjustTop
|
if (mayAdjustTop && ((ActivityStack) task).topRunningActivity(true /* focusableOnly */)
|
||||||
&& (stack.topRunningActivity() == null || !stack.isTopActivityFocusable())) {
|
== null) {
|
||||||
if (shouldAdjustGlobalFocus) {
|
task.adjustFocusToNextFocusableTask("finish-top", false /* allowFocusSelf */,
|
||||||
// Move the entire hierarchy to top with updating global top resumed activity
|
shouldAdjustGlobalFocus);
|
||||||
// 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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
finishActivityResults(resultCode, resultData);
|
finishActivityResults(resultCode, resultData);
|
||||||
|
|||||||
@@ -847,7 +847,8 @@ 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() {
|
||||||
adjustFocusToNextFocusableStack("reparent", true /* allowFocusSelf */);
|
adjustFocusToNextFocusableTask("reparent", true /* allowFocusSelf */,
|
||||||
|
true /* moveParentsToTop */);
|
||||||
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.
|
||||||
@@ -2069,7 +2070,7 @@ class ActivityStack extends Task {
|
|||||||
final String reason = "noMoreActivities";
|
final String reason = "noMoreActivities";
|
||||||
|
|
||||||
if (!isActivityTypeHome()) {
|
if (!isActivityTypeHome()) {
|
||||||
final ActivityStack nextFocusedStack = adjustFocusToNextFocusableStack(reason);
|
final ActivityStack nextFocusedStack = adjustFocusToNextFocusableTask(reason);
|
||||||
if (nextFocusedStack != null) {
|
if (nextFocusedStack != null) {
|
||||||
// Try to move focus to the next visible stack with a running activity if this
|
// 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 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;
|
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
|
* 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.
|
* that requested launch of the crashed one to prevent launch-crash loop.
|
||||||
|
|||||||
@@ -2579,6 +2579,80 @@ class Task extends WindowContainer<WindowContainer> {
|
|||||||
return currentCount[0];
|
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.
|
/** 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.
|
* The minimum position will be above all other tasks that can't be shown.
|
||||||
* @param minPosition The minimum position the caller is suggesting.
|
* @param minPosition The minimum position the caller is suggesting.
|
||||||
|
|||||||
@@ -751,6 +751,31 @@ public class ActivityRecordTests extends ActivityTestsBase {
|
|||||||
assertTrue(stack1.isTopStackInDisplayArea());
|
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.
|
* Verify that resumed activity is paused due to finish request.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user