diff options
14 files changed, 207 insertions, 140 deletions
diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto index ebf751c861bf..52c76ccaa639 100644 --- a/core/proto/android/server/activitymanagerservice.proto +++ b/core/proto/android/server/activitymanagerservice.proto @@ -62,6 +62,8 @@ message ActivityStackSupervisorProto { optional .com.android.server.wm.ConfigurationContainerProto configuration_container = 1; repeated ActivityDisplayProto displays = 2; optional KeyguardControllerProto keyguard_controller = 3; + // TODO(b/111541062): Focused stack and resumed activity are now per-display. Topmost instances + // can be obtained from top display and these fields can be removed. optional int32 focused_stack_id = 4; optional .com.android.server.wm.IdentifierProto resumed_activity = 5; // Whether or not the home activity is the recents activity. This is needed for the CTS tests to @@ -77,6 +79,8 @@ message ActivityDisplayProto { optional .com.android.server.wm.ConfigurationContainerProto configuration_container = 1; optional int32 id = 2; repeated ActivityStackProto stacks = 3; + optional int32 focused_stack_id = 4; + optional .com.android.server.wm.IdentifierProto resumed_activity = 5; } message ActivityStackProto { diff --git a/services/core/java/com/android/server/am/ActivityDisplay.java b/services/core/java/com/android/server/am/ActivityDisplay.java index acdc73886357..f98650b380cb 100644 --- a/services/core/java/com/android/server/am/ActivityDisplay.java +++ b/services/core/java/com/android/server/am/ActivityDisplay.java @@ -16,6 +16,7 @@ package com.android.server.am; +import static android.app.ActivityTaskManager.INVALID_STACK_ID; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; @@ -31,13 +32,18 @@ import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.FLAG_PRIVATE; import static android.view.Display.REMOVE_MODE_DESTROY_CONTENT; import static com.android.server.am.ActivityDisplayProto.CONFIGURATION_CONTAINER; +import static com.android.server.am.ActivityDisplayProto.FOCUSED_STACK_ID; import static com.android.server.am.ActivityDisplayProto.ID; +import static com.android.server.am.ActivityDisplayProto.RESUMED_ACTIVITY; import static com.android.server.am.ActivityDisplayProto.STACKS; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK; +import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STATES; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STACK; import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; +import static com.android.server.am.ActivityStackSupervisor.TAG_STATES; +import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityOptions; import android.app.WindowConfiguration; @@ -350,6 +356,45 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> return null; } + ActivityStack getNextFocusableStack() { + return getNextFocusableStack(null /* currentFocus */, false /* ignoreCurrent */); + } + + ActivityStack getNextFocusableStack(ActivityStack currentFocus, boolean ignoreCurrent) { + final int currentWindowingMode = currentFocus != null + ? currentFocus.getWindowingMode() : WINDOWING_MODE_UNDEFINED; + + ActivityStack candidate = null; + for (int i = mStacks.size() - 1; i >= 0; --i) { + final ActivityStack stack = mStacks.get(i); + if (ignoreCurrent && stack == currentFocus) { + continue; + } + if (!stack.isFocusable() || !stack.shouldBeVisible(null)) { + continue; + } + + if (currentWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY + && candidate == null && stack.inSplitScreenPrimaryWindowingMode()) { + // If the currently focused stack is in split-screen secondary we save off the + // top primary split-screen stack as a candidate for focus because we might + // prefer focus to move to an other stack to avoid primary split-screen stack + // overlapping with a fullscreen stack when a fullscreen stack is higher in z + // than the next split-screen stack. Assistant stack, I am looking at you... + // We only move the focus to the primary-split screen stack if there isn't a + // better alternative. + candidate = stack; + continue; + } + if (candidate != null && stack.inSplitScreenSecondaryWindowingMode()) { + // Use the candidate stack since we are now at the secondary split-screen. + return candidate; + } + return stack; + } + return candidate; + } + ActivityRecord getResumedActivity() { final ActivityStack focusedStack = getFocusedStack(); if (focusedStack == null) { @@ -372,6 +417,30 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> } /** + * Pause all activities in either all of the stacks or just the back stacks. + * @param userLeaving Passed to pauseActivity() to indicate whether to call onUserLeaving(). + * @param resuming The resuming activity. + * @param dontWait The resuming activity isn't going to wait for all activities to be paused + * before resuming. + * @return true if any activity was paused as a result of this call. + */ + boolean pauseBackStacks(boolean userLeaving, ActivityRecord resuming, boolean dontWait) { + boolean someActivityPaused = false; + for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = mStacks.get(stackNdx); + // TODO(b/111541062): Check if resumed activity on this display instead + if (!mSupervisor.isTopDisplayFocusedStack(stack) + && stack.getResumedActivity() != null) { + if (DEBUG_STATES) Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack + + " mResumedActivity=" + stack.getResumedActivity()); + someActivityPaused |= stack.startPausingLocked(userLeaving, false, resuming, + dontWait); + } + } + return someActivityPaused; + } + + /** * Removes stacks in the input windowing modes from the system if they are of activity type * ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED */ @@ -898,6 +967,16 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> final long token = proto.start(fieldId); super.writeToProto(proto, CONFIGURATION_CONTAINER, false /* trim */); proto.write(ID, mDisplayId); + final ActivityStack focusedStack = getFocusedStack(); + if (focusedStack != null) { + proto.write(FOCUSED_STACK_ID, focusedStack.mStackId); + final ActivityRecord focusedActivity = focusedStack.getDisplay().getResumedActivity(); + if (focusedActivity != null) { + focusedActivity.writeIdentifierToProto(proto, RESUMED_ACTIVITY); + } + } else { + proto.write(FOCUSED_STACK_ID, INVALID_STACK_ID); + } for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { final ActivityStack stack = mStacks.get(stackNdx); stack.writeToProto(proto, STACKS); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index aa0315ab3214..9f2fd4a0dee2 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -4380,7 +4380,7 @@ public class ActivityManagerService extends IActivityManager.Stub mWindowManager.deferSurfaceLayout(); try { if (!restarting && hasVisibleActivities - && !mStackSupervisor.resumeFocusedStackTopActivityLocked()) { + && !mStackSupervisor.resumeFocusedStacksTopActivitiesLocked()) { // If there was nothing to resume, and we are not already restarting this process, but // there is a visible activity that is hosted by the process... then make sure all // visible activities are running, taking care of restarting this process. @@ -5468,7 +5468,7 @@ public class ActivityManagerService extends IActivityManager.Stub // Clean-up disabled activities. if (mStackSupervisor.finishDisabledPackageActivitiesLocked( packageName, disabledClasses, true, false, userId) && mBooted) { - mStackSupervisor.resumeFocusedStackTopActivityLocked(); + mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); mStackSupervisor.scheduleIdleLocked(); } @@ -5642,7 +5642,7 @@ public class ActivityManagerService extends IActivityManager.Stub } } if (mBooted) { - mStackSupervisor.resumeFocusedStackTopActivityLocked(); + mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); mStackSupervisor.scheduleIdleLocked(); } } @@ -10198,7 +10198,7 @@ public class ActivityManagerService extends IActivityManager.Stub } finally { Binder.restoreCallingIdentity(ident); } - mStackSupervisor.resumeFocusedStackTopActivityLocked(); + mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); mUserController.sendUserSwitchBroadcasts(-1, currentUserId); BinderInternal.nSetBinderProxyCountWatermarks(6000,5500); diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index bd621edeeedd..67abedc96eed 100644 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -1941,7 +1941,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo } else { if (deferRelaunchUntilPaused) { stack.destroyActivityLocked(this, true /* removeFromApp */, "stop-config"); - mStackSupervisor.resumeFocusedStackTopActivityLocked(); + mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); } else { mStackSupervisor.updatePreviousProcessLocked(this); } @@ -2362,7 +2362,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo frozenBeforeDestroy = true; if (!service.updateDisplayOverrideConfigurationLocked(config, this, false /* deferResume */, displayId)) { - mStackSupervisor.resumeFocusedStackTopActivityLocked(); + mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); } } service.getTaskChangeNotificationController().notifyActivityRequestedOrientationChanged( diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index cbce3f4798b8..faa499b9e739 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -497,7 +497,10 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai if (DEBUG_STACK) Slog.v(TAG_STACK, "set resumed activity to:" + record + " reason:" + reason); setResumedActivity(record, reason + " - onActivityStateChanged"); - mService.setResumedActivityUncheckLocked(record, reason); + if (record == mStackSupervisor.getTopResumedActivity()) { + // TODO(b/111541062): Support tracking multiple resumed activities + mService.setResumedActivityUncheckLocked(record, reason); + } mStackSupervisor.mRecentTasks.add(record.getTask()); } } @@ -663,7 +666,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai if (!deferEnsuringVisibility) { mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, PRESERVE_WINDOWS); - mStackSupervisor.resumeFocusedStackTopActivityLocked(); + mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); } } @@ -696,7 +699,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai mWindowContainerController.reparent(activityDisplay.mDisplayId, mTmpRect2, onTop); postAddToDisplay(activityDisplay, mTmpRect2.isEmpty() ? null : mTmpRect2, onTop); adjustFocusToNextFocusableStack("reparent", true /* allowFocusSelf */); - mStackSupervisor.resumeFocusedStackTopActivityLocked(); + mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); // Update visibility of activities before notifying WM. This way it won't try to resize // windows that are no longer visible. mStackSupervisor.ensureActivitiesVisibleLocked(null /* starting */, 0 /* configChanges */, @@ -1445,7 +1448,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai if (prev == null) { if (resuming == null) { Slog.wtf(TAG, "Trying to pause when nothing is resumed"); - mStackSupervisor.resumeFocusedStackTopActivityLocked(); + mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); } return false; } @@ -1525,7 +1528,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // pause, so just treat it as being paused now. if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Activity not running, resuming next."); if (resuming == null) { - mStackSupervisor.resumeFocusedStackTopActivityLocked(); + mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); } return false; } @@ -1619,7 +1622,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai if (resumeNext) { final ActivityStack topStack = mStackSupervisor.getTopDisplayFocusedStack(); if (!topStack.shouldSleepOrShutDownActivities()) { - mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null); + mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(topStack, prev, null); } else { checkReadyForSleep(); ActivityRecord top = topStack.topRunningActivityLocked(); @@ -1628,7 +1631,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // something. Also if the top activity on the stack is not the just paused // activity, we need to go ahead and resume it to ensure we complete an // in-flight app switch. - mStackSupervisor.resumeFocusedStackTopActivityLocked(); + mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); } } } @@ -2307,7 +2310,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai * * NOTE: It is not safe to call this method directly as it can cause an activity in a * non-focused stack to be resumed. - * Use {@link ActivityStackSupervisor#resumeFocusedStackTopActivityLocked} to resume the + * Use {@link ActivityStackSupervisor#resumeFocusedStacksTopActivitiesLocked} to resume the * right activity for the current system state. */ @GuardedBy("mService") @@ -2470,7 +2473,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai final boolean resumeWhilePausing = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0 && !lastResumedCanPip; - boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false); + boolean pausing = getDisplay().pauseBackStacks(userLeaving, next, false); if (mResumedActivity != null) { if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Pausing " + mResumedActivity); @@ -2659,7 +2662,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // the screen based on the new activity order. boolean notUpdated = true; - if (mStackSupervisor.isTopDisplayFocusedStack(this)) { + if (isFocusedStackOnDisplay()) { // We have special rotation behavior when here is some active activity that // requests specific orientation or Keyguard is locked. Make sure all activity // visibilities are set correctly as well as the transition is updated if needed @@ -2791,12 +2794,13 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai private boolean resumeTopActivityInNextFocusableStack(ActivityRecord prev, ActivityOptions options, String reason) { - if (adjustFocusToNextFocusableStack(reason)) { + final ActivityStack nextFocusedStack = adjustFocusToNextFocusableStack(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 // stack). - return mStackSupervisor.resumeFocusedStackTopActivityLocked( - mStackSupervisor.getTopDisplayFocusedStack(), prev, null); + return mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(nextFocusedStack, prev, + null /* targetOptions */); } // Let's just start up the Launcher... @@ -2809,20 +2813,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai mStackSupervisor.resumeHomeStackTask(prev, reason); } - private TaskRecord getNextTask(TaskRecord targetTask) { - final int index = mTaskHistory.indexOf(targetTask); - if (index >= 0) { - final int numTasks = mTaskHistory.size(); - for (int i = index + 1; i < numTasks; ++i) { - TaskRecord task = mTaskHistory.get(i); - if (task.userId == targetTask.userId) { - return task; - } - } - } - return null; - } - /** Returns the position the input task should be placed in this stack. */ int getAdjustedPositionForTask(TaskRecord task, int suggestedPosition, ActivityRecord starting) { @@ -3437,7 +3427,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } // Move focus to next focusable stack if possible. - if (adjustFocusToNextFocusableStack(myReason)) { + if (adjustFocusToNextFocusableStack(myReason) != null) { return; } @@ -3445,21 +3435,25 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai mStackSupervisor.moveHomeStackTaskToTop(myReason); } - /** Find next proper focusable stack and make it focused. */ - boolean adjustFocusToNextFocusableStack(String reason) { + /** + * 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 boolean adjustFocusToNextFocusableStack(String reason, boolean allowFocusSelf) { + private ActivityStack adjustFocusToNextFocusableStack(String reason, boolean allowFocusSelf) { final ActivityStack stack = mStackSupervisor.getNextFocusableStackLocked(this, !allowFocusSelf); final String myReason = reason + " adjustFocusToNextFocusableStack"; if (stack == null) { - return false; + return null; } final ActivityRecord top = stack.topRunningActivityLocked(); @@ -3467,11 +3461,12 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai if (stack.isActivityTypeHome() && (top == null || !top.visible)) { // 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. - return mStackSupervisor.moveHomeStackTaskToTop(reason); + mStackSupervisor.moveHomeStackTaskToTop(reason); + return stack; } stack.moveToFront(myReason); - return true; + return stack; } final void stopActivityLocked(ActivityRecord r) { @@ -3877,7 +3872,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai false /* markFrozenIfConfigChanged */, true /* deferResume */); } if (activityRemoved) { - mStackSupervisor.resumeFocusedStackTopActivityLocked(); + mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); } if (DEBUG_CONTAINERS) Slog.d(TAG_CONTAINERS, "destroyActivityLocked: finishCurrentActivityLocked r=" + r + @@ -3890,7 +3885,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai if (DEBUG_ALL) Slog.v(TAG, "Enqueueing pending finish: " + r); mStackSupervisor.mFinishingActivities.add(r); r.resumeKeyDispatchingLocked(); - mStackSupervisor.resumeFocusedStackTopActivityLocked(); + mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); return r; } @@ -4236,7 +4231,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } } if (activityRemoved) { - mStackSupervisor.resumeFocusedStackTopActivityLocked(); + mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); } } @@ -4431,7 +4426,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } } - mStackSupervisor.resumeFocusedStackTopActivityLocked(); + mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); } private void removeHistoryRecordsForAppLocked(ArrayList<ActivityRecord> list, @@ -4664,7 +4659,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai topActivity.supportsEnterPipOnTaskSwitch = true; } - mStackSupervisor.resumeFocusedStackTopActivityLocked(); + mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, tr.taskId); mService.getTaskChangeNotificationController().notifyTaskMovedToFront(tr.taskId); @@ -4735,7 +4730,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai return true; } - mStackSupervisor.resumeFocusedStackTopActivityLocked(); + mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); return true; } @@ -4782,7 +4777,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai if (updatedConfig) { // Ensure the resumed state of the focus activity if we updated the configuration of // any activity. - mStackSupervisor.resumeFocusedStackTopActivityLocked(); + mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); } } @@ -5182,7 +5177,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai if (isOnHomeDisplay() && mode != REMOVE_TASK_MODE_MOVING_TO_TOP && mStackSupervisor.isTopDisplayFocusedStack(this)) { String myReason = reason + " leftTaskHistoryEmpty"; - if (!inMultiWindowMode() || !adjustFocusToNextFocusableStack(myReason)) { + if (!inMultiWindowMode() || adjustFocusToNextFocusableStack(myReason) == null) { mStackSupervisor.moveHomeStackToFront(myReason); } } @@ -5287,7 +5282,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // The task might have already been running and its visibility needs to be synchronized with // the visibility of the stack / windows. ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); - mStackSupervisor.resumeFocusedStackTopActivityLocked(); + mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); } private ActivityStack preAddTask(TaskRecord task, String reason, boolean toTop) { diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 002f718a3905..65ed8b707d71 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -17,10 +17,8 @@ package com.android.server.am; import static android.Manifest.permission.ACTIVITY_EMBEDDING; -import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS; import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW; import static android.Manifest.permission.START_ANY_ACTIVITY; -import static android.Manifest.permission.START_TASKS_FROM_RECENTS; import static android.app.ActivityManager.LOCK_TASK_MODE_LOCKED; import static android.app.ActivityManager.START_DELIVERED_TO_TOP; import static android.app.ActivityManager.START_TASK_TO_FRONT; @@ -76,7 +74,6 @@ import static com.android.server.am.ActivityManagerService.ANIMATE; import static com.android.server.am.ActivityManagerService.FIRST_SUPERVISOR_STACK_MSG; import static com.android.server.am.ActivityRecord.RELAUNCH_REASON_NONE; import static com.android.server.am.ActivityStack.ActivityState.DESTROYED; -import static com.android.server.am.ActivityStack.ActivityState.DESTROYING; import static com.android.server.am.ActivityStack.ActivityState.INITIALIZING; import static com.android.server.am.ActivityStack.ActivityState.PAUSED; import static com.android.server.am.ActivityStack.ActivityState.PAUSING; @@ -201,8 +198,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS; private static final String TAG_RELEASE = TAG + POSTFIX_RELEASE; private static final String TAG_STACK = TAG + POSTFIX_STACK; - private static final String TAG_STATES = TAG + POSTFIX_STATES; private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH; + static final String TAG_STATES = TAG + POSTFIX_STATES; static final String TAG_TASKS = TAG + POSTFIX_TASKS; /** How long we wait until giving up on the last activity telling us it is idle. */ @@ -821,7 +818,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D // Only resume home activity if isn't finishing. if (r != null && !r.finishing) { moveFocusableActivityStackToFrontLocked(r, myReason); - return resumeFocusedStackTopActivityLocked(mHomeStack, prev, null); + return resumeFocusedStacksTopActivitiesLocked(mHomeStack, prev, null); } return mService.mAm.startHomeActivityLocked(mCurrentUser, myReason); } @@ -1119,16 +1116,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D boolean pauseBackStacks(boolean userLeaving, ActivityRecord resuming, boolean dontWait) { boolean someActivityPaused = false; for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { - final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx); - for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = display.getChildAt(stackNdx); - if (!isTopDisplayFocusedStack(stack) && stack.getResumedActivity() != null) { - if (DEBUG_STATES) Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack + - " mResumedActivity=" + stack.getResumedActivity()); - someActivityPaused |= stack.startPausingLocked(userLeaving, false, resuming, - dontWait); - } - } + someActivityPaused |= mActivityDisplays.valueAt(displayNdx) + .pauseBackStacks(userLeaving, resuming, dontWait); } return someActivityPaused; } @@ -2175,7 +2164,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D //mWindowManager.dump(); if (activityRemoved) { - resumeFocusedStackTopActivityLocked(); + resumeFocusedStacksTopActivitiesLocked(); } return r; @@ -2271,28 +2260,35 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } } - boolean resumeFocusedStackTopActivityLocked() { - return resumeFocusedStackTopActivityLocked(null, null, null); + boolean resumeFocusedStacksTopActivitiesLocked() { + return resumeFocusedStacksTopActivitiesLocked(null, null, null); } - boolean resumeFocusedStackTopActivityLocked( + boolean resumeFocusedStacksTopActivitiesLocked( ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) { if (!readyToResume()) { return false; } - if (targetStack != null && isTopDisplayFocusedStack(targetStack)) { + if (targetStack != null && targetStack.isTopStackOnDisplay()) { return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions); } - final ActivityStack focusedStack = getTopDisplayFocusedStack(); - final ActivityRecord r = focusedStack.topRunningActivityLocked(); - if (r == null || !r.isState(RESUMED)) { - focusedStack.resumeTopActivityUncheckedLocked(null, null); - } else if (r.isState(RESUMED)) { - // Kick off any lingering app transitions form the MoveTaskToFront operation. - focusedStack.executeAppTransition(targetOptions); + // Resume all top activities in focused stacks on all displays. + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx); + final ActivityStack focusedStack = display.getFocusedStack(); + if (focusedStack == null) { + continue; + } + final ActivityRecord r = focusedStack.topRunningActivityLocked(); + if (r == null || !r.isState(RESUMED)) { + focusedStack.resumeTopActivityUncheckedLocked(null, null); + } else if (r.isState(RESUMED)) { + // Kick off any lingering app transitions form the MoveTaskToFront operation. + focusedStack.executeAppTransition(targetOptions); + } } return false; @@ -2628,58 +2624,48 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } /** - * Get next focusable stack in the system. This will search across displays and stacks - * in last-focused order for a focusable and visible stack, different from the target stack. + * Get next focusable stack in the system. This will search through the stack on the same + * display as the current focused stack, looking for a focusable and visible stack, different + * from the target stack. If no valid candidates will be found, it will then go through all + * displays and stacks in last-focused order. * * @param currentFocus The stack that previously had focus. * @param ignoreCurrent If we should ignore {@param currentFocus} when searching for next * candidate. - * @return Next focusable {@link ActivityStack}, null if not found. + * @return Next focusable {@link ActivityStack}, {@code null} if not found. */ - ActivityStack getNextFocusableStackLocked(ActivityStack currentFocus, boolean ignoreCurrent) { - mWindowManager.getDisplaysInFocusOrder(mTmpOrderedDisplayIds); + ActivityStack getNextFocusableStackLocked(@NonNull ActivityStack currentFocus, + boolean ignoreCurrent) { + // First look for next focusable stack on the same display + final ActivityDisplay preferredDisplay = currentFocus.getDisplay(); + final ActivityStack preferredFocusableStack = preferredDisplay.getNextFocusableStack( + currentFocus, ignoreCurrent); + if (preferredFocusableStack != null) { + return preferredFocusableStack; + } - final int currentWindowingMode = currentFocus != null - ? currentFocus.getWindowingMode() : WINDOWING_MODE_UNDEFINED; - ActivityStack candidate = null; + // Now look through all displays + mWindowManager.getDisplaysInFocusOrder(mTmpOrderedDisplayIds); for (int i = mTmpOrderedDisplayIds.size() - 1; i >= 0; --i) { final int displayId = mTmpOrderedDisplayIds.get(i); + if (displayId == preferredDisplay.mDisplayId) { + // We've already checked this one + continue; + } // If a display is registered in WM, it must also be available in AM. final ActivityDisplay display = getActivityDisplayOrCreateLocked(displayId); if (display == null) { // Looks like the display no longer exists in the system... continue; } - for (int j = display.getChildCount() - 1; j >= 0; --j) { - final ActivityStack stack = display.getChildAt(j); - if (ignoreCurrent && stack == currentFocus) { - continue; - } - if (!stack.isFocusable() || !stack.shouldBeVisible(null)) { - continue; - } - - if (currentWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY - && candidate == null && stack.inSplitScreenPrimaryWindowingMode()) { - // If the currently focused stack is in split-screen secondary we save off the - // top primary split-screen stack as a candidate for focus because we might - // prefer focus to move to an other stack to avoid primary split-screen stack - // overlapping with a fullscreen stack when a fullscreen stack is higher in z - // than the next split-screen stack. Assistant stack, I am looking at you... - // We only move the focus to the primary-split screen stack if there isn't a - // better alternative. - candidate = stack; - continue; - } - if (candidate != null && stack.inSplitScreenSecondaryWindowingMode()) { - // Use the candidate stack since we are now at the secondary split-screen. - return candidate; - } - return stack; + final ActivityStack nextFocusableStack = display.getNextFocusableStack(currentFocus, + ignoreCurrent); + if (nextFocusableStack != null) { + return nextFocusableStack; } } - return candidate; + return null; } /** @@ -2878,7 +2864,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } ensureActivitiesVisibleLocked(null, 0, PRESERVE_WINDOWS); - resumeFocusedStackTopActivityLocked(); + resumeFocusedStacksTopActivitiesLocked(); } finally { mAllowDockedStackResize = true; mWindowManager.continueSurfaceLayout(); @@ -3435,7 +3421,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D // drawn signal is scheduled after the bounds animation start call on the bounds animator // thread. ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); - resumeFocusedStackTopActivityLocked(); + resumeFocusedStacksTopActivitiesLocked(); mService.getTaskChangeNotificationController().notifyActivityPinned(r); } @@ -3466,6 +3452,11 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D "moveActivityStackToFront: r=" + r); stack.moveToFront(reason, task); + // Report top activity change to tracking services and WM + if (r == getTopResumedActivity()) { + // TODO(b/111541062): Support tracking multiple resumed activities + mService.setResumedActivityUncheckLocked(r, reason); + } return true; } @@ -3622,7 +3613,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D // It is possible that the display will not be awake at the time we // process the keyguard going away, which can happen before the sleep token // is released. As a result, it is important we resume the activity here. - resumeFocusedStackTopActivityLocked(); + resumeFocusedStacksTopActivitiesLocked(); } } } @@ -4728,7 +4719,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } break; case RESUME_TOP_ACTIVITY_MSG: { synchronized (mService.mGlobalLock) { - resumeFocusedStackTopActivityLocked(); + resumeFocusedStacksTopActivitiesLocked(); } } break; case SLEEP_TIMEOUT_MSG: { diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java index 0a1b26c968b4..05fae837364a 100644 --- a/services/core/java/com/android/server/am/ActivityStarter.java +++ b/services/core/java/com/android/server/am/ActivityStarter.java @@ -1367,7 +1367,7 @@ class ActivityStarter { // For paranoia, make sure we have correctly resumed the top activity. topStack.mLastPausedActivity = null; if (mDoResume) { - mSupervisor.resumeFocusedStackTopActivityLocked(); + mSupervisor.resumeFocusedStacksTopActivitiesLocked(); } ActivityOptions.abort(mOptions); if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) { @@ -1451,7 +1451,7 @@ class ActivityStarter { && !mSupervisor.isTopDisplayFocusedStack(mTargetStack)) { mTargetStack.moveToFront("startActivityUnchecked"); } - mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity, + mSupervisor.resumeFocusedStacksTopActivitiesLocked(mTargetStack, mStartActivity, mOptions); } } else if (mStartActivity != null) { @@ -2023,7 +2023,7 @@ class ActivityStarter { private void resumeTargetStackIfNeeded() { if (mDoResume) { - mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions); + mSupervisor.resumeFocusedStacksTopActivitiesLocked(mTargetStack, null, mOptions); } else { ActivityOptions.abort(mOptions); } @@ -2139,7 +2139,7 @@ class ActivityStarter { // For paranoia, make sure we have correctly resumed the top activity. mTargetStack.mLastPausedActivity = null; if (mDoResume) { - mSupervisor.resumeFocusedStackTopActivityLocked(); + mSupervisor.resumeFocusedStacksTopActivitiesLocked(); } ActivityOptions.abort(mOptions); return START_DELIVERED_TO_TOP; @@ -2157,7 +2157,7 @@ class ActivityStarter { deliverNewIntent(top); mTargetStack.mLastPausedActivity = null; if (mDoResume) { - mSupervisor.resumeFocusedStackTopActivityLocked(); + mSupervisor.resumeFocusedStacksTopActivitiesLocked(); } return START_DELIVERED_TO_TOP; } diff --git a/services/core/java/com/android/server/am/ActivityTaskManagerService.java b/services/core/java/com/android/server/am/ActivityTaskManagerService.java index 91f2b5f6f00c..3b3263c06852 100644 --- a/services/core/java/com/android/server/am/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/am/ActivityTaskManagerService.java @@ -1624,7 +1624,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { final ActivityRecord r = stack.topRunningActivityLocked(); if (mStackSupervisor.moveFocusableActivityStackToFrontLocked( r, "setFocusedStack")) { - mStackSupervisor.resumeFocusedStackTopActivityLocked(); + mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); } } } finally { @@ -1645,7 +1645,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } final ActivityRecord r = task.topRunningActivityLocked(); if (mStackSupervisor.moveFocusableActivityStackToFrontLocked(r, "setFocusedTask")) { - mStackSupervisor.resumeFocusedStackTopActivityLocked(); + mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); } } } finally { @@ -4735,6 +4735,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { updateResumedAppTrace(r); mLastResumedActivity = r; + // TODO(b/111541062): Support multiple focused apps in WM mWindowManager.setFocusedApp(r.appToken, true); applyUpdateLockStateLocked(r); @@ -5149,7 +5150,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } if (mStackSupervisor.moveFocusableActivityStackToFrontLocked( r, "setFocusedActivity")) { - mStackSupervisor.resumeFocusedStackTopActivityLocked(); + mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); } } } diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java index 2c580944926a..3b98f373d817 100644 --- a/services/core/java/com/android/server/am/AppErrors.java +++ b/services/core/java/com/android/server/am/AppErrors.java @@ -503,7 +503,7 @@ class AppErrors { mService.mStackSupervisor.handleAppCrashLocked(r.getWindowProcessController()); if (!r.isPersistent()) { mService.removeProcessLocked(r, false, false, "crash"); - mService.mStackSupervisor.resumeFocusedStackTopActivityLocked(); + mService.mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); } } finally { Binder.restoreCallingIdentity(orig); @@ -743,12 +743,12 @@ class AppErrors { // annoy the user repeatedly. Unless it is persistent, since those // processes run critical code. mService.removeProcessLocked(app, false, tryAgain, "crash"); - mService.mStackSupervisor.resumeFocusedStackTopActivityLocked(); + mService.mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); if (!showBackground) { return false; } } - mService.mStackSupervisor.resumeFocusedStackTopActivityLocked(); + mService.mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); } else { final TaskRecord affectedTask = mService.mStackSupervisor.finishTopCrashedActivitiesLocked(app.getWindowProcessController(), reason); diff --git a/services/core/java/com/android/server/am/KeyguardController.java b/services/core/java/com/android/server/am/KeyguardController.java index e345b4d61cc1..ee4e36ff1fd1 100644 --- a/services/core/java/com/android/server/am/KeyguardController.java +++ b/services/core/java/com/android/server/am/KeyguardController.java @@ -163,7 +163,7 @@ class KeyguardController { updateKeyguardSleepToken(); // Some stack visibility might change (e.g. docked stack) - mStackSupervisor.resumeFocusedStackTopActivityLocked(); + mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); mStackSupervisor.addStartingWindowsForVisibleActivities(true /* taskSwitch */); mWindowManager.executeAppTransition(); diff --git a/services/core/java/com/android/server/am/LockTaskController.java b/services/core/java/com/android/server/am/LockTaskController.java index 4fd01cdeaa3b..643c922ad2ca 100644 --- a/services/core/java/com/android/server/am/LockTaskController.java +++ b/services/core/java/com/android/server/am/LockTaskController.java @@ -446,7 +446,7 @@ public class LockTaskController { return; } task.performClearTaskLocked(); - mSupervisor.resumeFocusedStackTopActivityLocked(); + mSupervisor.resumeFocusedStacksTopActivitiesLocked(); } /** @@ -578,7 +578,7 @@ public class LockTaskController { if (andResume) { mSupervisor.findTaskToMoveToFront(task, 0, null, reason, lockTaskModeState != LOCK_TASK_MODE_NONE); - mSupervisor.resumeFocusedStackTopActivityLocked(); + mSupervisor.resumeFocusedStacksTopActivitiesLocked(); mWindowManager.executeAppTransition(); } else if (lockTaskModeState != LOCK_TASK_MODE_NONE) { mSupervisor.handleNonResizableTaskIfNeeded(task, WINDOWING_MODE_UNDEFINED, @@ -653,7 +653,7 @@ public class LockTaskController { } if (taskChanged) { - mSupervisor.resumeFocusedStackTopActivityLocked(); + mSupervisor.resumeFocusedStacksTopActivitiesLocked(); } } diff --git a/services/core/java/com/android/server/am/RecentsAnimation.java b/services/core/java/com/android/server/am/RecentsAnimation.java index 1c7ad3f33310..c5586bbc3e82 100644 --- a/services/core/java/com/android/server/am/RecentsAnimation.java +++ b/services/core/java/com/android/server/am/RecentsAnimation.java @@ -287,7 +287,7 @@ class RecentsAnimation implements RecentsAnimationCallbacks, mWindowManager.prepareAppTransition(TRANSIT_NONE, false); mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, false); - mStackSupervisor.resumeFocusedStackTopActivityLocked(); + mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); // No reason to wait for the pausing activity in this case, as the hiding of // surfaces needs to be done immediately. diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java index 2d0c2a86b7b7..ed5cc2e2ce9f 100644 --- a/services/core/java/com/android/server/am/TaskRecord.java +++ b/services/core/java/com/android/server/am/TaskRecord.java @@ -16,9 +16,9 @@ package com.android.server.am; +import static android.app.ActivityTaskManager.INVALID_STACK_ID; import static android.app.ActivityTaskManager.RESIZE_MODE_FORCED; import static android.app.ActivityTaskManager.RESIZE_MODE_SYSTEM; -import static android.app.ActivityTaskManager.INVALID_STACK_ID; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; @@ -63,6 +63,7 @@ import static com.android.server.am.ActivityStackSupervisor.ON_TOP; import static com.android.server.am.ActivityStackSupervisor.PAUSE_IMMEDIATELY; import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS; import static com.android.server.am.TaskRecordProto.ACTIVITIES; +import static com.android.server.am.TaskRecordProto.ACTIVITY_TYPE; import static com.android.server.am.TaskRecordProto.BOUNDS; import static com.android.server.am.TaskRecordProto.CONFIGURATION_CONTAINER; import static com.android.server.am.TaskRecordProto.FULLSCREEN; @@ -74,7 +75,6 @@ import static com.android.server.am.TaskRecordProto.ORIG_ACTIVITY; import static com.android.server.am.TaskRecordProto.REAL_ACTIVITY; import static com.android.server.am.TaskRecordProto.RESIZE_MODE; import static com.android.server.am.TaskRecordProto.STACK_ID; -import static com.android.server.am.TaskRecordProto.ACTIVITY_TYPE; import static java.lang.Integer.MAX_VALUE; @@ -87,7 +87,6 @@ import android.app.ActivityManager.TaskSnapshot; import android.app.ActivityOptions; import android.app.ActivityTaskManager; import android.app.AppGlobals; -import android.app.IActivityManager; import android.app.TaskInfo; import android.content.ComponentName; import android.content.Intent; @@ -478,7 +477,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi mResizeMode = resizeMode; mWindowContainerController.setResizeable(resizeMode); mService.mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); - mService.mStackSupervisor.resumeFocusedStackTopActivityLocked(); + mService.mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); } void setTaskDockedResizing(boolean resizing) { @@ -552,7 +551,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi mService.mStackSupervisor.ensureActivitiesVisibleLocked(r, 0, preserveWindow); if (!kept) { - mService.mStackSupervisor.resumeFocusedStackTopActivityLocked(); + mService.mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); } } } @@ -752,7 +751,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi // The task might have already been running and its visibility needs to be synchronized // with the visibility of the stack / windows. supervisor.ensureActivitiesVisibleLocked(null, 0, !mightReplaceWindow); - supervisor.resumeFocusedStackTopActivityLocked(); + supervisor.resumeFocusedStacksTopActivitiesLocked(); } // TODO: Handle incorrect request to move before the actual move, not after. diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java index ba604e08a061..f854df663e2e 100644 --- a/services/core/java/com/android/server/am/UserController.java +++ b/services/core/java/com/android/server/am/UserController.java @@ -104,11 +104,9 @@ import com.android.server.wm.WindowManagerService; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Objects; -import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; /** @@ -2243,7 +2241,7 @@ class UserController implements Handler.Callback { protected void stackSupervisorResumeFocusedStackTopActivity() { synchronized (mService) { - mService.mStackSupervisor.resumeFocusedStackTopActivityLocked(); + mService.mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); } } |