diff options
| author | 2018-11-28 23:30:25 +0000 | |
|---|---|---|
| committer | 2018-11-28 23:30:25 +0000 | |
| commit | d95f59d624d78b22fa3f22c14895a8d27fdab760 (patch) | |
| tree | b6699cbb95d4cefff5c276229bdb04b85288daf1 | |
| parent | 57ae24c633d93568322f94b4218c00f419c64463 (diff) | |
| parent | d32da477cc911b6926176780669381933857f3fb (diff) | |
Merge "Remove root window hierarchy logic from ActivityStackSupervior (40/n)"
35 files changed, 3325 insertions, 3161 deletions
diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java index ed366453028e..33584d4a1710 100644 --- a/services/core/java/com/android/server/wm/ActivityDisplay.java +++ b/services/core/java/com/android/server/wm/ActivityDisplay.java @@ -39,8 +39,6 @@ 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.wm.ActivityStack.ActivityState.RESUMED; -import static com.android.server.wm.ActivityStackSupervisor.FindTaskResult; -import static com.android.server.wm.ActivityStackSupervisor.TAG_STATES; import static com.android.server.wm.ActivityStackSupervisor.TAG_TASKS; import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STACK; import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES; @@ -48,6 +46,8 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS; import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_STACK; import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM; import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; +import static com.android.server.wm.RootActivityContainer.FindTaskResult; +import static com.android.server.wm.RootActivityContainer.TAG_STATES; import android.annotation.Nullable; import android.app.ActivityOptions; @@ -84,7 +84,8 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> */ private static int sNextFreeStackId = 0; - private ActivityStackSupervisor mSupervisor; + private ActivityTaskManagerService mService; + private RootActivityContainer mRootActivityContainer; /** Actual Display this object tracks. */ int mDisplayId; Display mDisplay; @@ -141,8 +142,9 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> private final FindTaskResult mTmpFindTaskResult = new FindTaskResult(); - ActivityDisplay(ActivityStackSupervisor supervisor, Display display) { - mSupervisor = supervisor; + ActivityDisplay(RootActivityContainer root, Display display) { + mRootActivityContainer = root; + mService = root.mService; mDisplayId = display.getDisplayId(); mDisplay = display; mWindowContainerController = createWindowContainerController(); @@ -168,7 +170,7 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> if (displayId != DEFAULT_DISPLAY) { final int displayState = mDisplay.getState(); if (displayState == Display.STATE_OFF && mOffToken == null) { - mOffToken = mSupervisor.mService.acquireSleepToken("Display-off", displayId); + mOffToken = mService.acquireSleepToken("Display-off", displayId); } else if (displayState == Display.STATE_ON && mOffToken != null) { mOffToken.release(); mOffToken = null; @@ -189,7 +191,7 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> + " to displayId=" + mDisplayId + " position=" + position); addStackReferenceIfNeeded(stack); positionChildAt(stack, position); - mSupervisor.mService.updateSleepIfNeededLocked(); + mService.updateSleepIfNeededLocked(); } void removeChild(ActivityStack stack) { @@ -201,7 +203,7 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> } removeStackReferenceIfNeeded(stack); releaseSelfIfNeeded(); - mSupervisor.mService.updateSleepIfNeededLocked(); + mService.updateSleepIfNeededLocked(); onStackOrderChanged(); } @@ -252,7 +254,7 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> final ActivityStack currentFocusedStack = getFocusedStack(); if (currentFocusedStack != prevFocusedStack) { mLastFocusedStack = prevFocusedStack; - EventLogTags.writeAmFocusedStack(mSupervisor.mCurrentUser, mDisplayId, + EventLogTags.writeAmFocusedStack(mRootActivityContainer.mCurrentUser, mDisplayId, currentFocusedStack == null ? -1 : currentFocusedStack.getStackId(), mLastFocusedStack == null ? -1 : mLastFocusedStack.getStackId(), updateLastFocusedStackReason); @@ -409,10 +411,10 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> } } - final ActivityTaskManagerService service = mSupervisor.mService; - if (!isWindowingModeSupported(windowingMode, service.mSupportsMultiWindow, - service.mSupportsSplitScreenMultiWindow, service.mSupportsFreeformWindowManagement, - service.mSupportsPictureInPicture, activityType)) { + if (!isWindowingModeSupported(windowingMode, mService.mSupportsMultiWindow, + mService.mSupportsSplitScreenMultiWindow, + mService.mSupportsFreeformWindowManagement, mService.mSupportsPictureInPicture, + activityType)) { throw new IllegalArgumentException("Can't create stack for unsupported windowingMode=" + windowingMode); } @@ -425,10 +427,12 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> <T extends ActivityStack> T createStackUnchecked(int windowingMode, int activityType, int stackId, boolean onTop) { if (windowingMode == WINDOWING_MODE_PINNED) { - return (T) new PinnedActivityStack(this, stackId, mSupervisor, onTop); + return (T) new PinnedActivityStack(this, stackId, + mRootActivityContainer.mStackSupervisor, onTop); } - return (T) new ActivityStack( - this, stackId, mSupervisor, windowingMode, activityType, onTop); + return (T) new ActivityStack(this, stackId, + mRootActivityContainer.mStackSupervisor, windowingMode, activityType, + onTop); } /** @@ -543,7 +547,7 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> 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) + if (!mRootActivityContainer.isTopDisplayFocusedStack(stack) && stack.getResumedActivity() != null) { if (DEBUG_STATES) Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack + " mResumedActivity=" + stack.getResumedActivity()); @@ -608,7 +612,7 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> if (stack.getWindowingMode() != windowingMode) { continue; } - mSupervisor.removeStack(stack); + mRootActivityContainer.mStackSupervisor.removeStack(stack); } } } @@ -623,7 +627,7 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> for (int i = mStacks.size() - 1; i >= 0; --i) { final ActivityStack stack = mStacks.get(i); if (stack.getActivityType() == activityType) { - mSupervisor.removeStack(stack); + mRootActivityContainer.mStackSupervisor.removeStack(stack); } } } @@ -685,7 +689,7 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> } private void onSplitScreenModeDismissed() { - mSupervisor.mWindowManager.deferSurfaceLayout(); + mRootActivityContainer.mWindowManager.deferSurfaceLayout(); try { // Adjust the windowing mode of any stack in secondary split-screen to fullscreen. for (int i = mStacks.size() - 1; i >= 0; --i) { @@ -709,12 +713,12 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> mHomeStack.moveToFront("onSplitScreenModeDismissed"); topFullscreenStack.moveToFront("onSplitScreenModeDismissed"); } - mSupervisor.mWindowManager.continueSurfaceLayout(); + mRootActivityContainer.mWindowManager.continueSurfaceLayout(); } } private void onSplitScreenModeActivated() { - mSupervisor.mWindowManager.deferSurfaceLayout(); + mRootActivityContainer.mWindowManager.deferSurfaceLayout(); try { // Adjust the windowing mode of any affected by split-screen to split-screen secondary. for (int i = mStacks.size() - 1; i >= 0; --i) { @@ -729,7 +733,7 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> false /* creating */); } } finally { - mSupervisor.mWindowManager.continueSurfaceLayout(); + mRootActivityContainer.mWindowManager.continueSurfaceLayout(); } } @@ -824,11 +828,10 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> int validateWindowingMode(int windowingMode, @Nullable ActivityRecord r, @Nullable TaskRecord task, int activityType) { // Make sure the windowing mode we are trying to use makes sense for what is supported. - final ActivityTaskManagerService service = mSupervisor.mService; - boolean supportsMultiWindow = service.mSupportsMultiWindow; - boolean supportsSplitScreen = service.mSupportsSplitScreenMultiWindow; - boolean supportsFreeform = service.mSupportsFreeformWindowManagement; - boolean supportsPip = service.mSupportsPictureInPicture; + boolean supportsMultiWindow = mService.mSupportsMultiWindow; + boolean supportsSplitScreen = mService.mSupportsSplitScreenMultiWindow; + boolean supportsFreeform = mService.mSupportsFreeformWindowManagement; + boolean supportsPip = mService.mSupportsPictureInPicture; if (supportsMultiWindow) { if (task != null) { supportsMultiWindow = task.isResizeable(); @@ -932,7 +935,7 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> // This activity can be considered the top running activity if we are not considering // the locked state, the keyguard isn't locked, or we can show when locked. if (topRunning != null && considerKeyguardState - && mSupervisor.getKeyguardController().isKeyguardLocked() + && mRootActivityContainer.mStackSupervisor.getKeyguardController().isKeyguardLocked() && !topRunning.canShowWhenLocked()) { return null; } @@ -1010,7 +1013,7 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> @Override protected ConfigurationContainer getParent() { - return mSupervisor; + return mRootActivityContainer; } boolean isPrivate() { @@ -1043,8 +1046,8 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> // released (no more ActivityStack). But, we cannot release it at that moment or the // related WindowContainer and WindowContainerController will also be removed. So, we // set display as removed after reparenting stack finished. - final ActivityDisplay toDisplay = mSupervisor.getDefaultDisplay(); - mSupervisor.beginDeferResume(); + final ActivityDisplay toDisplay = mRootActivityContainer.getDefaultDisplay(); + mRootActivityContainer.mStackSupervisor.beginDeferResume(); try { int numStacks = mStacks.size(); // Keep the order from bottom to top. @@ -1070,7 +1073,7 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> numStacks = mStacks.size(); } } finally { - mSupervisor.endDeferResume(); + mRootActivityContainer.mStackSupervisor.endDeferResume(); } mRemoved = true; @@ -1082,9 +1085,9 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> releaseSelfIfNeeded(); if (!mAllSleepTokens.isEmpty()) { - mSupervisor.mSleepTokens.removeAll(mAllSleepTokens); + mRootActivityContainer.mSleepTokens.removeAll(mAllSleepTokens); mAllSleepTokens.clear(); - mSupervisor.mService.updateSleepIfNeededLocked(); + mService.updateSleepIfNeededLocked(); } } @@ -1092,8 +1095,9 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> if (mStacks.isEmpty() && mRemoved) { mWindowContainerController.removeContainer(); mWindowContainerController = null; - mSupervisor.removeChild(this); - mSupervisor.getKeyguardController().onDisplayRemoved(mDisplayId); + mRootActivityContainer.removeChild(this); + mRootActivityContainer.mStackSupervisor + .getKeyguardController().onDisplayRemoved(mDisplayId); } } @@ -1122,7 +1126,7 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> boolean shouldSleep() { return (mStacks.isEmpty() || !mAllSleepTokens.isEmpty()) - && (mSupervisor.mService.mRunningVoice == null); + && (mService.mRunningVoice == null); } void setFocusedApp(ActivityRecord r, boolean moveFocusNow) { @@ -1213,7 +1217,7 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> @Nullable ActivityRecord getHomeActivity() { - return getHomeActivityForUser(mSupervisor.mCurrentUser); + return getHomeActivityForUser(mRootActivityContainer.mCurrentUser); } @Nullable diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java index 1c08d039207b..0c0c818e0baa 100644 --- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java +++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java @@ -277,7 +277,8 @@ class ActivityMetricsLogger { mLastLogTimeSecs = now; mWindowState = WINDOW_STATE_INVALID; - ActivityStack stack = mSupervisor.getTopDisplayFocusedStack(); + ActivityStack stack = + mSupervisor.mRootActivityContainer.getTopDisplayFocusedStack(); if (stack == null) { return; } @@ -289,7 +290,7 @@ class ActivityMetricsLogger { @WindowingMode int windowingMode = stack.getWindowingMode(); if (windowingMode == WINDOWING_MODE_PINNED) { - stack = mSupervisor.findStackBehind(stack); + stack = mSupervisor.mRootActivityContainer.findStackBehind(stack); windowingMode = stack.getWindowingMode(); } switch (windowingMode) { diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 5e92b9e4d46a..61168ec26430 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -322,6 +322,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo private boolean inHistory; // are we in the history stack? final ActivityStackSupervisor mStackSupervisor; + final RootActivityContainer mRootActivityContainer; static final int STARTING_WINDOW_NOT_SHOWN = 0; static final int STARTING_WINDOW_SHOWN = 1; @@ -844,6 +845,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo boolean _rootVoiceInteraction, ActivityStackSupervisor supervisor, ActivityOptions options, ActivityRecord sourceRecord) { service = _service; + mRootActivityContainer = _service.mRootActivityContainer; appToken = new Token(this, _intent); info = aInfo; launchedFromPid = _launchedFromPid; @@ -1200,7 +1202,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo } boolean isFocusable() { - return mStackSupervisor.isFocusable(this, isAlwaysFocusable()); + return mRootActivityContainer.isFocusable(this, isAlwaysFocusable()); } boolean isResizeable() { @@ -1353,7 +1355,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo return false; } - if (mStackSupervisor.getTopResumedActivity() == this) { + if (mRootActivityContainer.getTopResumedActivity() == this) { if (DEBUG_FOCUS) { Slog.d(TAG_FOCUS, "moveActivityStackToFront: already on top, activity=" + this); } @@ -1366,7 +1368,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo stack.moveToFront(reason, task); // Report top activity change to tracking services and WM - if (mStackSupervisor.getTopResumedActivity() == this) { + if (mRootActivityContainer.getTopResumedActivity() == this) { // TODO(b/111361570): Support multiple focused apps in WM service.setResumedActivityUncheckLocked(this, reason); } @@ -1864,9 +1866,9 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo } else { if (deferRelaunchUntilPaused) { stack.destroyActivityLocked(this, true /* removeFromApp */, "stop-config"); - mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); + mRootActivityContainer.resumeFocusedStacksTopActivities(); } else { - mStackSupervisor.updatePreviousProcessLocked(this); + mRootActivityContainer.updatePreviousProcess(this); } } } @@ -2036,7 +2038,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo // another activity to start or has stopped, then the key dispatching // timeout should not be caused by this. if (mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(this) || stopped) { - final ActivityStack stack = mStackSupervisor.getTopDisplayFocusedStack(); + final ActivityStack stack = mRootActivityContainer.getTopDisplayFocusedStack(); // Try to use the one which is closest to top. ActivityRecord r = stack.getResumedActivity(); if (r == null) { @@ -2224,7 +2226,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo void setRequestedOrientation(int requestedOrientation) { final int displayId = getDisplayId(); final Configuration displayConfig = - mStackSupervisor.getDisplayOverrideConfiguration(displayId); + mRootActivityContainer.getDisplayOverrideConfiguration(displayId); final Configuration config = mWindowContainerController.setOrientation(requestedOrientation, displayId, displayConfig, mayFreezeScreenLocked(app)); @@ -2232,7 +2234,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo frozenBeforeDestroy = true; if (!service.updateDisplayOverrideConfigurationLocked(config, this, false /* deferResume */, displayId)) { - mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); + mRootActivityContainer.resumeFocusedStacksTopActivities(); } } service.getTaskChangeNotificationController().notifyActivityRequestedOrientationChanged( @@ -2867,7 +2869,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo void setShowWhenLocked(boolean showWhenLocked) { mShowWhenLocked = showWhenLocked; - mStackSupervisor.ensureActivitiesVisibleLocked(null, 0 /* configChanges */, + mRootActivityContainer.ensureActivitiesVisible(null, 0 /* configChanges */, false /* preserveWindows */); } @@ -2905,7 +2907,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo } boolean isTopRunningActivity() { - return mStackSupervisor.topRunningActivityLocked() == this; + return mRootActivityContainer.topRunningActivity() == this; } /** diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java index bd3e43c380b6..f49c689d0a9f 100644 --- a/services/core/java/com/android/server/wm/ActivityStack.java +++ b/services/core/java/com/android/server/wm/ActivityStack.java @@ -63,7 +63,6 @@ import static com.android.server.wm.ActivityStack.ActivityState.PAUSING; import static com.android.server.wm.ActivityStack.ActivityState.RESUMED; import static com.android.server.wm.ActivityStack.ActivityState.STOPPED; import static com.android.server.wm.ActivityStack.ActivityState.STOPPING; -import static com.android.server.wm.ActivityStackSupervisor.FindTaskResult; import static com.android.server.wm.ActivityStackSupervisor.PAUSE_IMMEDIATELY; import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS; import static com.android.server.wm.ActivityStackSupervisor.REMOVE_FROM_RECENTS; @@ -103,6 +102,7 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLAS import static com.android.server.wm.ActivityTaskManagerService.H.FIRST_ACTIVITY_STACK_MSG; import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE; import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE; +import static com.android.server.wm.RootActivityContainer.FindTaskResult; import static java.lang.Integer.MAX_VALUE; @@ -267,7 +267,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai mStackSupervisor.resizeDockedStackLocked( getOverrideBounds(), mTmpRect2, mTmpRect2, null, null, PRESERVE_WINDOWS); } - mStackSupervisor.updateUIDsPresentOnDisplay(); + mRootActivityContainer.updateUIDsPresentOnDisplay(); } enum ActivityState { @@ -390,6 +390,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai /** Run all ActivityStacks through this */ protected final ActivityStackSupervisor mStackSupervisor; + protected final RootActivityContainer mRootActivityContainer; private boolean mTopActivityOccludesKeyguard; private ActivityRecord mTopDismissingKeyguardActivity; @@ -489,6 +490,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai int windowingMode, int activityType, boolean onTop) { mStackSupervisor = supervisor; mService = supervisor.mService; + mRootActivityContainer = mService.mRootActivityContainer; mHandler = new ActivityStackHandler(supervisor.mLooper); mWindowManager = mService.mWindowManager; mStackId = stackId; @@ -508,7 +510,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai T createStackWindowController(int displayId, boolean onTop, Rect outBounds) { return (T) new StackWindowController(mStackId, this, displayId, onTop, outBounds, - mStackSupervisor.mWindowManager); + mRootActivityContainer.mWindowManager); } T getWindowContainerController() { @@ -532,7 +534,7 @@ 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"); - if (record == mStackSupervisor.getTopResumedActivity()) { + if (record == mRootActivityContainer.getTopResumedActivity()) { // TODO(b/111361570): Support multiple focused apps in WM mService.setResumedActivityUncheckLocked(record, reason); } @@ -622,7 +624,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai display.onStackWindowingModeChanged(this); } if (hasNewOverrideBounds) { - mStackSupervisor.resizeStackLocked(this, mTmpRect2, null, null, PRESERVE_WINDOWS, + mRootActivityContainer.resizeStack(this, mTmpRect2, null, null, PRESERVE_WINDOWS, true /* allowResizeInDockedMode */, true /* deferResume */); } if (prevIsAlwaysOnTop != isAlwaysOnTop()) { @@ -819,8 +821,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } if (!deferEnsuringVisibility) { - mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, PRESERVE_WINDOWS); - mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); + mRootActivityContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS); + mRootActivityContainer.resumeFocusedStacksTopActivities(); } } @@ -854,10 +856,10 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai /** Resume next focusable stack after reparenting to another display. */ void postReparent() { adjustFocusToNextFocusableStack("reparent", true /* allowFocusSelf */); - mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); + mRootActivityContainer.resumeFocusedStacksTopActivities(); // 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 */, + mRootActivityContainer.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */, !PRESERVE_WINDOWS); } @@ -882,7 +884,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } ActivityDisplay getDisplay() { - return mStackSupervisor.getActivityDisplay(mDisplayId); + return mRootActivityContainer.getActivityDisplay(mDisplayId); } /** @@ -1034,7 +1036,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } /** - * This is a simplified version of topRunningActivityLocked that provides a number of + * This is a simplified version of topRunningActivity that provides a number of * optional skip-over modes. It is intended for use with the ActivityController hook only. * * @param token If non-null, any history records matching this token will be skipped. @@ -1236,7 +1238,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai boolean isFocusable() { final ActivityRecord r = topRunningActivityLocked(); - return mStackSupervisor.isFocusable(this, r != null && r.isFocusable()); + return mRootActivityContainer.isFocusable(this, r != null && r.isFocusable()); } boolean isFocusableAndVisible() { @@ -1398,7 +1400,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai final TaskRecord task = mTaskHistory.get(i); if (task.okToShowLocked()) { - if (DEBUG_TASKS) Slog.d(TAG_TASKS, "switchUserLocked: stack=" + getStackId() + + if (DEBUG_TASKS) Slog.d(TAG_TASKS, "switchUser: stack=" + getStackId() + " moving " + task + " to top"); mTaskHistory.remove(i); mTaskHistory.add(task); @@ -1587,7 +1589,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.resumeFocusedStacksTopActivitiesLocked(); + mRootActivityContainer.resumeFocusedStacksTopActivities(); } return false; } @@ -1665,7 +1667,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.resumeFocusedStacksTopActivitiesLocked(); + mRootActivityContainer.resumeFocusedStacksTopActivities(); } return false; } @@ -1704,7 +1706,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } } } - mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); + mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS); } private void completePauseLocked(boolean resumeNext, ActivityRecord resuming) { @@ -1757,9 +1759,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } if (resumeNext) { - final ActivityStack topStack = mStackSupervisor.getTopDisplayFocusedStack(); + final ActivityStack topStack = mRootActivityContainer.getTopDisplayFocusedStack(); if (!topStack.shouldSleepOrShutDownActivities()) { - mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(topStack, prev, null); + mRootActivityContainer.resumeFocusedStacksTopActivities(topStack, prev, null); } else { checkReadyForSleep(); ActivityRecord top = topStack.topRunningActivityLocked(); @@ -1768,7 +1770,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.resumeFocusedStacksTopActivitiesLocked(); + mRootActivityContainer.resumeFocusedStacksTopActivities(); } } } @@ -1799,7 +1801,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = false; } - mStackSupervisor.ensureActivitiesVisibleLocked(resuming, 0, !PRESERVE_WINDOWS); + mRootActivityContainer.ensureActivitiesVisible(resuming, 0, !PRESERVE_WINDOWS); } private void addToStopping(ActivityRecord r, boolean scheduleIdle, boolean idleDelayed) { @@ -2011,7 +2013,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai /** * Ensure visibility with an option to also update the configuration of visible activities. * @see #ensureActivitiesVisibleLocked(ActivityRecord, int, boolean) - * @see ActivityStackSupervisor#ensureActivitiesVisibleLocked(ActivityRecord, int, boolean) + * @see RootActivityContainer#ensureActivitiesVisible(ActivityRecord, int, boolean) */ // TODO: Should be re-worked based on the fact that each task as a stack in most cases. final void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges, @@ -2032,7 +2034,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai boolean aboveTop = top != null; final boolean stackShouldBeVisible = shouldBeVisible(starting); boolean behindFullscreenActivity = !stackShouldBeVisible; - boolean resumeNextActivity = mStackSupervisor.isTopDisplayFocusedStack(this) + boolean resumeNextActivity = mRootActivityContainer.isTopDisplayFocusedStack(this) && (isInStackLocked(starting) == null); final boolean isTopNotPinnedStack = isAttached() && getDisplay().isTopNotPinnedStack(this); @@ -2443,7 +2445,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#resumeFocusedStacksTopActivitiesLocked} to resume the + * Use {@link RootActivityContainer#resumeFocusedStacksTopActivities} to resume the * right activity for the current system state. */ @GuardedBy("mService") @@ -2513,7 +2515,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai return false; } - mStackSupervisor.cancelInitializingActivities(); + mRootActivityContainer.cancelInitializingActivities(); // Remember how we'll process this pause/resume situation, and ensure // that the state is reset however we wind up proceeding. @@ -2536,7 +2538,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai executeAppTransition(options); if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Top activity resumed " + next); - if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return false; } @@ -2544,7 +2545,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // activity is paused, well that is the state we want. if (shouldSleepOrShutDownActivities() && mLastPausedActivity == next - && mStackSupervisor.allPausedActivitiesComplete()) { + && mRootActivityContainer.allPausedActivitiesComplete()) { // If the current top activity may be able to occlude keyguard but the occluded state // has not been set, update visibility and check again if we should continue to resume. boolean nothingToResume = true; @@ -2565,7 +2566,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai executeAppTransition(options); if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Going to sleep and all paused"); - if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return false; } } @@ -2576,7 +2576,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai if (!mService.mAmInternal.hasStartedUserState(next.userId)) { Slog.w(TAG, "Skipping resume of top activity " + next + ": user " + next.userId + " is stopped"); - if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return false; } @@ -2590,10 +2589,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next); // If we are currently pausing an activity, then don't do anything until that is done. - if (!mStackSupervisor.allPausedActivitiesComplete()) { + if (!mRootActivityContainer.allPausedActivitiesComplete()) { if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE, "resumeTopActivityLocked: Skip resume: some activity pausing."); - if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return false; } @@ -2640,7 +2638,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai next.app.updateProcessInfo(false /* updateServiceConnectionActivities */, true /* updateLru */, true /* activityChange */, false /* updateOomAdj */); } - if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); if (lastResumed != null) { lastResumed.setWillCloseOrEnterPip(true); } @@ -2655,7 +2652,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai executeAppTransition(options); if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Top activity resumed (dontWaitForPause) " + next); - if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return true; } @@ -2673,7 +2669,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai if (prev != null && prev != next) { if (!mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(prev) - && next != null && !next.nowVisible) { + && !next.nowVisible) { mStackSupervisor.mActivitiesWaitingForVisibleActivity.add(prev); if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming top, waiting visible to hide: " + prev); @@ -2814,7 +2810,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // result of invisible window resize. // TODO: Remove this once visibilities are set correctly immediately when // starting an activity. - notUpdated = !mStackSupervisor.ensureVisibilityAndConfig(next, mDisplayId, + notUpdated = !mRootActivityContainer.ensureVisibilityAndConfig(next, mDisplayId, true /* markFrozenIfConfigChanged */, false /* deferResume */); } @@ -2836,7 +2832,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai next.setVisibility(true); } next.completeResumeLocked(); - if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return true; } @@ -2899,7 +2894,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai false /* taskSwitch */); } mStackSupervisor.startSpecificActivityLocked(next, true, false); - if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return true; } @@ -2913,7 +2907,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai Slog.w(TAG, "Exception thrown during resume of " + next, e); requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null, "resume-exception", true); - if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return true; } } else { @@ -2931,7 +2924,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai mStackSupervisor.startSpecificActivityLocked(next, true, true); } - if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return true; } @@ -2942,7 +2934,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // 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.resumeFocusedStacksTopActivitiesLocked(nextFocusedStack, prev, + return mRootActivityContainer.resumeFocusedStacksTopActivities(nextFocusedStack, prev, null /* targetOptions */); } @@ -2950,8 +2942,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai ActivityOptions.abort(options); if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityInNextFocusableStack: " + reason + ", go home"); - if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); - return mStackSupervisor.resumeHomeActivity(prev, reason, mDisplayId); + return mRootActivityContainer.resumeHomeActivity(prev, reason, mDisplayId); } /** Returns the position the input task should be placed in this stack. */ @@ -3536,7 +3527,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } private void adjustFocusedActivityStack(ActivityRecord r, String reason) { - if (!mStackSupervisor.isTopDisplayFocusedStack(this) || + if (!mRootActivityContainer.isTopDisplayFocusedStack(this) || ((mResumedActivity != r) && (mResumedActivity != null))) { return; } @@ -3545,7 +3536,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai final String myReason = reason + " adjustFocus"; if (next == r) { - final ActivityRecord top = mStackSupervisor.topRunningActivityLocked(); + final ActivityRecord top = mRootActivityContainer.topRunningActivity(); if (top != null) { top.moveFocusableActivityToTop(myReason); } @@ -3569,7 +3560,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai final ActivityStack nextFocusableStack = adjustFocusToNextFocusableStack(myReason); if (nextFocusableStack != null) { final ActivityRecord top = nextFocusableStack.topRunningActivityLocked(); - if (top != null && top == mStackSupervisor.getTopResumedActivity()) { + if (top != null && top == mRootActivityContainer.getTopResumedActivity()) { // TODO(b/111361570): Remove this and update focused app per-display in // WindowManager every time an activity becomes resumed in // ActivityTaskManagerService#setResumedActivityUncheckLocked(). @@ -3597,7 +3588,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai */ private ActivityStack adjustFocusToNextFocusableStack(String reason, boolean allowFocusSelf) { final ActivityStack stack = - mStackSupervisor.getNextFocusableStackLocked(this, !allowFocusSelf); + mRootActivityContainer.getNextFocusableStack(this, !allowFocusSelf); final String myReason = reason + " adjustFocusToNextFocusableStack"; if (stack == null) { return null; @@ -4018,11 +4009,11 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // stack, need to make something visible in its place. Also if the display does not // have running activity, the configuration may need to be updated for restoring // original orientation of the display. - mStackSupervisor.ensureVisibilityAndConfig(next, mDisplayId, + mRootActivityContainer.ensureVisibilityAndConfig(next, mDisplayId, false /* markFrozenIfConfigChanged */, true /* deferResume */); } if (activityRemoved) { - mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); + mRootActivityContainer.resumeFocusedStacksTopActivities(); } if (DEBUG_CONTAINERS) Slog.d(TAG_CONTAINERS, "destroyActivityLocked: finishCurrentActivityLocked r=" + r + @@ -4035,7 +4026,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.resumeFocusedStacksTopActivitiesLocked(); + mRootActivityContainer.resumeFocusedStacksTopActivities(); return r; } @@ -4377,7 +4368,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } } if (activityRemoved) { - mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); + mRootActivityContainer.resumeFocusedStacksTopActivities(); } } @@ -4568,7 +4559,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } } - mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); + mRootActivityContainer.resumeFocusedStacksTopActivities(); } private void removeHistoryRecordsForAppLocked(ArrayList<ActivityRecord> list, @@ -4712,7 +4703,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai task.mLastTimeMoved *= -1; } } - mStackSupervisor.invalidateTaskLayers(); + mRootActivityContainer.invalidateTaskLayers(); } final void moveTaskToFrontLocked(TaskRecord tr, boolean noAnimation, ActivityOptions options, @@ -4788,7 +4779,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai topActivity.supportsEnterPipOnTaskSwitch = true; } - mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); + mRootActivityContainer.resumeFocusedStacksTopActivities(); EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, tr.taskId); mService.getTaskChangeNotificationController().notifyTaskMovedToFront(tr.taskId); @@ -4860,7 +4851,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai return true; } - mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); + mRootActivityContainer.resumeFocusedStacksTopActivities(); return true; } @@ -4907,7 +4898,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.resumeFocusedStacksTopActivitiesLocked(); + mRootActivityContainer.resumeFocusedStacksTopActivities(); } } @@ -5099,7 +5090,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai */ void getRunningTasks(List<TaskRecord> tasksOut, @ActivityType int ignoreActivityType, @WindowingMode int ignoreWindowingMode, int callingUid, boolean allowed) { - boolean focusedStack = mStackSupervisor.getTopDisplayFocusedStack() == this; + boolean focusedStack = mRootActivityContainer.getTopDisplayFocusedStack() == this; boolean topTask = true; for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { final TaskRecord task = mTaskHistory.get(taskNdx); @@ -5164,7 +5155,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai return removeHistoryRecordsForAppLocked(app); } - void handleAppCrashLocked(WindowProcessController app) { + void handleAppCrash(WindowProcessController app) { for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { @@ -5311,7 +5302,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // We only need to adjust focused stack if this stack is in focus and we are not in the // process of moving the task to the top of the stack that will be focused. if (mode != REMOVE_TASK_MODE_MOVING_TO_TOP - && mStackSupervisor.isTopDisplayFocusedStack(this)) { + && mRootActivityContainer.isTopDisplayFocusedStack(this)) { String myReason = reason + " leftTaskHistoryEmpty"; if (!inMultiWindowMode() || adjustFocusToNextFocusableStack(myReason) == null) { getDisplay().moveHomeStackToFront(myReason); @@ -5417,7 +5408,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.resumeFocusedStacksTopActivitiesLocked(); + mRootActivityContainer.resumeFocusedStacksTopActivities(); } private ActivityStack preAddTask(TaskRecord task, String reason, boolean toTop) { @@ -5484,7 +5475,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai moveToFront(reason); // If the original state is resumed, there is no state change to update focused app. // So here makes sure the activity focus is set if it is the top. - if (origState == RESUMED && r == mStackSupervisor.getTopResumedActivity()) { + if (origState == RESUMED && r == mRootActivityContainer.getTopResumedActivity()) { // TODO(b/111361570): Support multiple focused apps in WM mService.setResumedActivityUncheckLocked(r, reason); } diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java index c517bd70cbf5..a71f5f3999a2 100644 --- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java @@ -25,28 +25,18 @@ import static android.app.ActivityManager.START_FLAG_DEBUG; import static android.app.ActivityManager.START_FLAG_NATIVE_DEBUGGING; import static android.app.ActivityManager.START_FLAG_TRACK_ALLOCATION; import static android.app.ActivityManager.START_TASK_TO_FRONT; -import static android.app.ActivityTaskManager.INVALID_STACK_ID; -import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY; import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SPLIT_SCREEN; import static android.app.WaitResult.INVALID_DELAY; -import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; -import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; -import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; -import static android.app.WindowConfiguration.activityTypeToString; -import static android.app.WindowConfiguration.windowingModeToString; -import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; -import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE; -import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK; import static android.content.pm.PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY; import static android.content.pm.PackageManager.PERMISSION_DENIED; import static android.content.pm.PackageManager.PERMISSION_GRANTED; @@ -59,26 +49,13 @@ import static android.view.Display.INVALID_DISPLAY; import static android.view.Display.TYPE_VIRTUAL; import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS; -import static com.android.server.am.ActivityStackSupervisorProto.CONFIGURATION_CONTAINER; -import static com.android.server.am.ActivityStackSupervisorProto.DISPLAYS; -import static com.android.server.am.ActivityStackSupervisorProto.FOCUSED_STACK_ID; -import static com.android.server.am.ActivityStackSupervisorProto.IS_HOME_RECENTS_COMPONENT; -import static com.android.server.am.ActivityStackSupervisorProto.KEYGUARD_CONTROLLER; -import static com.android.server.am.ActivityStackSupervisorProto.PENDING_ACTIVITIES; -import static com.android.server.am.ActivityStackSupervisorProto.RESUMED_ACTIVITY; -import static com.android.server.wm.ActivityStack.ActivityState.DESTROYED; -import static com.android.server.wm.ActivityStack.ActivityState.INITIALIZING; import static com.android.server.wm.ActivityStack.ActivityState.PAUSED; import static com.android.server.wm.ActivityStack.ActivityState.PAUSING; -import static com.android.server.wm.ActivityStack.ActivityState.RESUMED; -import static com.android.server.wm.ActivityStack.ActivityState.STOPPED; -import static com.android.server.wm.ActivityStack.ActivityState.STOPPING; import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING; import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ALL; import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_IDLE; import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_PAUSE; import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RECENTS; -import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RELEASE; import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STACK; import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES; import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH; @@ -86,9 +63,7 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS; import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_IDLE; import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_PAUSE; import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RECENTS; -import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RELEASE; import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_STACK; -import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_STATES; import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_SWITCH; import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TASKS; import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM; @@ -96,6 +71,10 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLAS import static com.android.server.wm.ActivityTaskManagerService.ANIMATE; import static com.android.server.wm.ActivityTaskManagerService.H.FIRST_SUPERVISOR_STACK_MSG; import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE; +import static com.android.server.wm.RootActivityContainer.MATCH_TASK_IN_STACKS_ONLY; +import static com.android.server.wm.RootActivityContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS; +import static com.android.server.wm.RootActivityContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE; +import static com.android.server.wm.RootActivityContainer.TAG_STATES; import static com.android.server.wm.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE; import static com.android.server.wm.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV; import static com.android.server.wm.TaskRecord.LOCK_TASK_AUTH_WHITELISTED; @@ -103,20 +82,11 @@ import static com.android.server.wm.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT; import static com.android.server.wm.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE; import static com.android.server.wm.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT; -import static java.lang.Integer.MAX_VALUE; - import android.Manifest; -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.UserIdInt; import android.app.Activity; import android.app.ActivityManager; -import android.app.ActivityManager.RunningTaskInfo; -import android.app.ActivityManager.StackInfo; import android.app.ActivityManagerInternal; import android.app.ActivityOptions; -import android.app.AppGlobals; import android.app.AppOpsManager; import android.app.ProfilerInfo; import android.app.ResultInfo; @@ -139,17 +109,11 @@ import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; import android.content.res.Configuration; -import android.content.res.Resources; import android.graphics.Rect; -import android.hardware.display.DisplayManager; -import android.hardware.display.DisplayManager.DisplayListener; -import android.hardware.display.DisplayManagerInternal; -import android.hardware.power.V1_0.PowerHint; import android.os.Binder; import android.os.Build; import android.os.Bundle; import android.os.Debug; -import android.os.FactoryTest; import android.os.Handler; import android.os.IBinder; import android.os.Looper; @@ -163,20 +127,13 @@ import android.os.UserHandle; import android.os.UserManager; import android.os.WorkSource; import android.provider.MediaStore; -import android.service.voice.IVoiceInteractionSession; import android.util.ArrayMap; import android.util.ArraySet; -import android.util.DisplayMetrics; import android.util.EventLog; -import android.util.IntArray; import android.util.MergedConfiguration; import android.util.Slog; import android.util.SparseArray; import android.util.SparseIntArray; -import android.util.TimeUtils; -import android.util.proto.ProtoOutputStream; -import android.view.Display; -import android.view.DisplayInfo; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; @@ -185,34 +142,28 @@ import com.android.internal.os.TransferPipe; import com.android.internal.os.logging.MetricsLoggerWrapper; import com.android.internal.util.ArrayUtils; import com.android.internal.util.function.pooled.PooledLambda; -import com.android.server.LocalServices; import com.android.server.am.ActivityManagerService; -import com.android.server.am.AppTimeTracker; import com.android.server.am.EventLogTags; import com.android.server.am.UserState; -import com.android.server.wm.ActivityStack.ActivityState; -import com.android.server.wm.ActivityTaskManagerInternal.SleepToken; import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; -import java.util.Set; -public class ActivityStackSupervisor extends ConfigurationContainer implements DisplayListener, - RecentTasks.Callbacks, RootWindowContainerListener { +// TODO: This class has become a dumping ground. Let's +// - Move things relating to the hierarchy to RootWindowContainer +// - Move things relating to activity life cycles to maybe a new class called ActivityLifeCycler +// - Move interface things to ActivityTaskManagerService. +// - All other little things to other files. +public class ActivityStackSupervisor implements RecentTasks.Callbacks { private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStackSupervisor" : TAG_ATM; private static final String TAG_IDLE = TAG + POSTFIX_IDLE; private static final String TAG_PAUSE = TAG + POSTFIX_PAUSE; 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_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. */ @@ -233,12 +184,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D static final int REPORT_MULTI_WINDOW_MODE_CHANGED_MSG = FIRST_SUPERVISOR_STACK_MSG + 14; static final int REPORT_PIP_MODE_CHANGED_MSG = FIRST_SUPERVISOR_STACK_MSG + 15; - private static final String VIRTUAL_DISPLAY_BASE_NAME = "ActivityViewVirtualDisplay"; - - // Used to indicate if an object (e.g. stack) that we are trying to get - // should be created if it doesn't exist already. - static final boolean CREATE_IF_NEEDED = true; - // Used to indicate that windows of activities should be preserved during the resize. static final boolean PRESERVE_WINDOWS = true; @@ -270,25 +215,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D private Rect mPendingTempOtherTaskBounds; private Rect mPendingTempOtherTaskInsetBounds; - /** - * The modes which affect which tasks are returned when calling - * {@link ActivityStackSupervisor#anyTaskForIdLocked(int)}. - */ - @Retention(RetentionPolicy.SOURCE) - @IntDef({ - MATCH_TASK_IN_STACKS_ONLY, - MATCH_TASK_IN_STACKS_OR_RECENT_TASKS, - MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE - }) - public @interface AnyTaskForIdMatchTaskMode {} - // Match only tasks in the current stacks - static final int MATCH_TASK_IN_STACKS_ONLY = 0; - // Match either tasks in the current stacks, or in the recent tasks if not found in the stacks - static final int MATCH_TASK_IN_STACKS_OR_RECENT_TASKS = 1; - // Match either tasks in the current stacks, or in the recent tasks, restoring it to the - // provided stack id - static final int MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE = 2; - // Activity actions an app cannot start if it uses a permission which is not granted. private static final ArrayMap<String, String> ACTION_TO_RUNTIME_PERMISSION = new ArrayMap<>(); @@ -316,19 +242,19 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D private static final int MAX_TASK_IDS_PER_USER = UserHandle.PER_USER_RANGE; final ActivityTaskManagerService mService; + RootActivityContainer mRootActivityContainer; /** The historial list of recent tasks including inactive tasks */ RecentTasks mRecentTasks; /** Helper class to abstract out logic for fetching the set of currently running tasks */ - private RunningTasks mRunningTasks; + RunningTasks mRunningTasks; final ActivityStackSupervisorHandler mHandler; final Looper mLooper; /** Short cut */ WindowManagerService mWindowManager; - DisplayManager mDisplayManager; /** Common synchronization logic used to save things to disks. */ PersisterQueue mPersisterQueue; @@ -341,9 +267,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D */ private final SparseIntArray mCurTaskIdForUser = new SparseIntArray(20); - /** The current user */ - int mCurrentUser; - /** List of activities that are waiting for a new activity to become visible before completing * whatever operation they are supposed to do. */ // TODO: Remove mActivitiesWaitingForVisibleActivity list and just remove activity from @@ -392,9 +315,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D * is being brought in front of us. */ boolean mUserLeaving = false; - /** Set when a power hint has started, but not ended. */ - private boolean mPowerHintSent; - /** * We don't want to allow the device to go to sleep while in the process * of launching an activity. This is primarily to allow alarm intent @@ -410,29 +330,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D */ PowerManager.WakeLock mGoingToSleep; - /** - * A list of tokens that cause the top activity to be put to sleep. - * They are used by components that may hide and block interaction with underlying - * activities. - */ - final ArrayList<SleepToken> mSleepTokens = new ArrayList<>(); - - /** Stack id of the front stack when user switched, indexed by userId. */ - SparseIntArray mUserStackInFront = new SparseIntArray(2); - - /** Reference to default display so we can quickly look it up. */ - private ActivityDisplay mDefaultDisplay; - - /** - * List of displays which contain activities, sorted by z-order. - * The last entry in the list is the topmost. - */ - private final ArrayList<ActivityDisplay> mActivityDisplays = new ArrayList<>(); - - private final SparseArray<IntArray> mDisplayAccessUIDs = new SparseArray<>(); - - private DisplayManagerInternal mDisplayManagerInternal; - /** Used to keep resumeTopActivityUncheckedLocked() from being entered recursively */ boolean inResumeTopActivity; @@ -443,50 +340,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D private final Rect tempRect = new Rect(); private final ActivityOptions mTmpOptions = ActivityOptions.makeBasic(); - // The default minimal size that will be used if the activity doesn't specify its minimal size. - // It will be calculated when the default display gets added. - int mDefaultMinSizeOfResizeableTaskDp = -1; - - // Whether tasks have moved and we need to rank the tasks before next OOM scoring - private boolean mTaskLayersChanged = true; - private ActivityMetricsLogger mActivityMetricsLogger; - private final ArrayList<ActivityRecord> mTmpActivityList = new ArrayList<>(); - - @Override - protected int getChildCount() { - return mActivityDisplays.size(); - } - - @Override - protected ActivityDisplay getChildAt(int index) { - return mActivityDisplays.get(index); - } - - @Override - protected ConfigurationContainer getParent() { - return null; - } - - Configuration getDisplayOverrideConfiguration(int displayId) { - final ActivityDisplay activityDisplay = getActivityDisplayOrCreateLocked(displayId); - if (activityDisplay == null) { - throw new IllegalArgumentException("No display found with id: " + displayId); - } - - return activityDisplay.getOverrideConfiguration(); - } - - void setDisplayOverrideConfiguration(Configuration overrideConfiguration, int displayId) { - final ActivityDisplay activityDisplay = getActivityDisplayOrCreateLocked(displayId); - if (activityDisplay == null) { - throw new IllegalArgumentException("No display found with id: " + displayId); - } - - activityDisplay.onOverrideConfigurationChanged(overrideConfiguration); - } - /** Check if placing task or activity on specified display is allowed. */ boolean canPlaceEntityOnDisplay(int displayId, int callingPid, int callingUid, ActivityInfo activityInfo) { @@ -508,44 +363,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } /** - * Check if configuration of specified display matches current global config. - * Used to check if we can put a non-resizeable activity on a secondary display and it will get - * the same config as on the default display. - * @param displayId Id of the display to check. - * @return {@code true} if configuration matches. - */ - private boolean displayConfigMatchesGlobal(int displayId) { - if (displayId == DEFAULT_DISPLAY) { - return true; - } - if (displayId == INVALID_DISPLAY) { - return false; - } - final ActivityDisplay targetDisplay = getActivityDisplayOrCreateLocked(displayId); - if (targetDisplay == null) { - throw new IllegalArgumentException("No display found with id: " + displayId); - } - return getConfiguration().equals(targetDisplay.getConfiguration()); - } - - static class FindTaskResult { - ActivityRecord mRecord; - boolean mIdealMatch; - - void clear() { - mRecord = null; - mIdealMatch = false; - } - - void setTo(FindTaskResult result) { - mRecord = result.mRecord; - mIdealMatch = result.mIdealMatch; - } - } - - private final FindTaskResult mTmpFindTaskResult = new FindTaskResult(); - - /** * Used to keep track whether app visibilities got changed since the last pause. Useful to * determine whether to invoke the task stack change listener after pausing. */ @@ -565,11 +382,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D */ private boolean mAllowDockedStackResize = true; - /** - * Is dock currently minimized. - */ - boolean mIsDockMinimized; - private KeyguardController mKeyguardController; private PowerManager mPowerManager; @@ -577,8 +389,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D private boolean mInitialized; - private RootWindowContainerController mWindowContainerController; - /** * Description of a request to start a new activity, which has been held * due to app switches being disabled. @@ -617,11 +427,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D mHandler = new ActivityStackSupervisorHandler(looper); } - @VisibleForTesting - void setWindowContainerController(RootWindowContainerController controller) { - mWindowContainerController = controller; - } - public void initialize() { if (mInitialized) { return; @@ -676,321 +481,16 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D void setWindowManager(WindowManagerService wm) { mWindowManager = wm; getKeyguardController().setWindowManager(wm); - setWindowContainerController(new RootWindowContainerController(this)); - - mDisplayManager = mService.mContext.getSystemService(DisplayManager.class); - mDisplayManager.registerDisplayListener(this, mHandler); - mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); - - final Display[] displays = mDisplayManager.getDisplays(); - for (int displayNdx = 0; displayNdx < displays.length; ++displayNdx) { - final Display display = displays[displayNdx]; - final ActivityDisplay activityDisplay = new ActivityDisplay(this, display); - if (activityDisplay.mDisplayId == DEFAULT_DISPLAY) { - mDefaultDisplay = activityDisplay; - } - addChild(activityDisplay, ActivityDisplay.POSITION_TOP); - } - calculateDefaultMinimalSizeOfResizeableTasks(); - - final ActivityDisplay defaultDisplay = getDefaultDisplay(); - - defaultDisplay.getOrCreateStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP); - positionChildAt(defaultDisplay, ActivityDisplay.POSITION_TOP); - } - - /** Change the z-order of the given display. */ - private void positionChildAt(ActivityDisplay display, int position) { - if (position >= mActivityDisplays.size()) { - position = mActivityDisplays.size() - 1; - } else if (position < 0) { - position = 0; - } - - if (mActivityDisplays.isEmpty()) { - mActivityDisplays.add(display); - } else if (mActivityDisplays.get(position) != display) { - mActivityDisplays.remove(display); - mActivityDisplays.add(position, display); - } - } - - @Override - public void onChildPositionChanged(DisplayWindowController childController, int position) { - // Assume AM lock is held from positionChildAt of controller in each hierarchy. - final ActivityDisplay display = getActivityDisplay(childController.getDisplayId()); - if (display != null) { - positionChildAt(display, position); - } - } - - ActivityStack getTopDisplayFocusedStack() { - for (int i = mActivityDisplays.size() - 1; i >= 0; --i) { - final ActivityStack focusedStack = mActivityDisplays.get(i).getFocusedStack(); - if (focusedStack != null) { - return focusedStack; - } - } - return null; - } - - ActivityRecord getTopResumedActivity() { - final ActivityStack focusedStack = getTopDisplayFocusedStack(); - if (focusedStack == null) { - return null; - } - final ActivityRecord resumedActivity = focusedStack.getResumedActivity(); - if (resumedActivity != null && resumedActivity.app != null) { - return resumedActivity; - } - // The top focused stack might not have a resumed activity yet - look on all displays in - // focus order. - for (int i = mActivityDisplays.size() - 1; i >= 0; --i) { - final ActivityDisplay display = mActivityDisplays.get(i); - final ActivityRecord resumedActivityOnDisplay = display.getResumedActivity(); - if (resumedActivityOnDisplay != null) { - return resumedActivityOnDisplay; - } - } - return null; - } - - boolean isFocusable(ConfigurationContainer container, boolean alwaysFocusable) { - if (container.inSplitScreenPrimaryWindowingMode() && mIsDockMinimized) { - return false; - } - - return container.getWindowConfiguration().canReceiveKeys() || alwaysFocusable; - } - - boolean isTopDisplayFocusedStack(ActivityStack stack) { - return stack != null && stack == getTopDisplayFocusedStack(); } void moveRecentsStackToFront(String reason) { - final ActivityStack recentsStack = getDefaultDisplay().getStack( + final ActivityStack recentsStack = mRootActivityContainer.getDefaultDisplay().getStack( WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_RECENTS); if (recentsStack != null) { recentsStack.moveToFront(reason); } } - boolean resumeHomeActivity(ActivityRecord prev, String reason, int displayId) { - if (!mService.isBooting() && !mService.isBooted()) { - // Not ready yet! - return false; - } - - if (displayId == INVALID_DISPLAY) { - displayId = DEFAULT_DISPLAY; - } - - final ActivityRecord r = getActivityDisplay(displayId).getHomeActivity(); - final String myReason = reason + " resumeHomeActivity"; - - // Only resume home activity if isn't finishing. - if (r != null && !r.finishing) { - r.moveFocusableActivityToTop(myReason); - return resumeFocusedStacksTopActivitiesLocked(r.getStack(), prev, null); - } - return startHomeOnDisplay(mCurrentUser, myReason, displayId); - } - - /** - * Check if home activity start should be allowed on a display. - * @param homeInfo {@code ActivityInfo} of the home activity that is going to be launched. - * @param displayId The id of the target display. - * @param allowInstrumenting Whether launching home should be allowed if being instrumented. - * @return {@code true} if allow to launch, {@code false} otherwise. - */ - boolean canStartHomeOnDisplay(ActivityInfo homeInfo, int displayId, - boolean allowInstrumenting) { - if (mService.mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL - && mService.mTopAction == null) { - // We are running in factory test mode, but unable to find the factory test app, so - // just sit around displaying the error message and don't try to start anything. - return false; - } - - final WindowProcessController app = - mService.getProcessController(homeInfo.processName, homeInfo.applicationInfo.uid); - if (!allowInstrumenting && app != null && app.isInstrumenting()) { - // Don't do this if the home app is currently being instrumented. - return false; - } - - if (displayId == DEFAULT_DISPLAY || (displayId != INVALID_DISPLAY - && displayId == mService.mVr2dDisplayId)) { - // No restrictions to default display or vr 2d display. - return true; - } - - final ActivityDisplay display = getActivityDisplay(displayId); - if (display == null || display.isRemoved() || !display.supportsSystemDecorations()) { - // Can't launch home on display that doesn't support system decorations. - return false; - } - - final boolean supportMultipleInstance = homeInfo.launchMode != LAUNCH_SINGLE_TASK - && homeInfo.launchMode != LAUNCH_SINGLE_INSTANCE - && homeInfo.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q; - if (!supportMultipleInstance) { - // Can't launch home on other displays if it requested to be single instance. Also we - // don't allow home applications that target before Q to have multiple home activity - // instances because they may not be expected to have multiple home scenario and - // haven't explicitly request for single instance. - return false; - } - - return true; - } - - TaskRecord anyTaskForIdLocked(int id) { - return anyTaskForIdLocked(id, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE); - } - - TaskRecord anyTaskForIdLocked(int id, @AnyTaskForIdMatchTaskMode int matchMode) { - return anyTaskForIdLocked(id, matchMode, null, !ON_TOP); - } - - /** - * Returns a {@link TaskRecord} for the input id if available. {@code null} otherwise. - * @param id Id of the task we would like returned. - * @param matchMode The mode to match the given task id in. - * @param aOptions The activity options to use for restoration. Can be null. - * @param onTop If the stack for the task should be the topmost on the display. - */ - TaskRecord anyTaskForIdLocked(int id, @AnyTaskForIdMatchTaskMode int matchMode, - @Nullable ActivityOptions aOptions, boolean onTop) { - // If options are set, ensure that we are attempting to actually restore a task - if (matchMode != MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE && aOptions != null) { - throw new IllegalArgumentException("Should not specify activity options for non-restore" - + " lookup"); - } - - int numDisplays = mActivityDisplays.size(); - for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { - final ActivityDisplay display = mActivityDisplays.get(displayNdx); - for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = display.getChildAt(stackNdx); - final TaskRecord task = stack.taskForIdLocked(id); - if (task == null) { - continue; - } - if (aOptions != null) { - // Resolve the stack the task should be placed in now based on options - // and reparent if needed. - final ActivityStack launchStack = getLaunchStack(null, aOptions, task, onTop); - if (launchStack != null && stack != launchStack) { - final int reparentMode = onTop - ? REPARENT_MOVE_STACK_TO_FRONT : REPARENT_LEAVE_STACK_IN_PLACE; - task.reparent(launchStack, onTop, reparentMode, ANIMATE, DEFER_RESUME, - "anyTaskForIdLocked"); - } - } - return task; - } - } - - // If we are matching stack tasks only, return now - if (matchMode == MATCH_TASK_IN_STACKS_ONLY) { - return null; - } - - // Otherwise, check the recent tasks and return if we find it there and we are not restoring - // the task from recents - if (DEBUG_RECENTS) Slog.v(TAG_RECENTS, "Looking for task id=" + id + " in recents"); - final TaskRecord task = mRecentTasks.getTask(id); - - if (task == null) { - if (DEBUG_RECENTS) { - Slog.d(TAG_RECENTS, "\tDidn't find task id=" + id + " in recents"); - } - - return null; - } - - if (matchMode == MATCH_TASK_IN_STACKS_OR_RECENT_TASKS) { - return task; - } - - // Implicitly, this case is MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE - if (!restoreRecentTaskLocked(task, aOptions, onTop)) { - if (DEBUG_RECENTS) Slog.w(TAG_RECENTS, - "Couldn't restore task id=" + id + " found in recents"); - return null; - } - if (DEBUG_RECENTS) Slog.w(TAG_RECENTS, "Restored task id=" + id + " from in recents"); - return task; - } - - ActivityRecord isInAnyStackLocked(IBinder token) { - int numDisplays = mActivityDisplays.size(); - for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { - final ActivityDisplay display = mActivityDisplays.get(displayNdx); - for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = display.getChildAt(stackNdx); - final ActivityRecord r = stack.isInStackLocked(token); - if (r != null) { - return r; - } - } - } - return null; - } - - /** - * Detects whether we should show a lock screen in front of this task for a locked user. - * <p> - * We'll do this if either of the following holds: - * <ul> - * <li>The top activity explicitly belongs to {@param userId}.</li> - * <li>The top activity returns a result to an activity belonging to {@param userId}.</li> - * </ul> - * - * @return {@code true} if the top activity looks like it belongs to {@param userId}. - */ - private boolean taskTopActivityIsUser(TaskRecord task, @UserIdInt int userId) { - // To handle the case that work app is in the task but just is not the top one. - final ActivityRecord activityRecord = task.getTopActivity(); - final ActivityRecord resultTo = (activityRecord != null ? activityRecord.resultTo : null); - - return (activityRecord != null && activityRecord.userId == userId) - || (resultTo != null && resultTo.userId == userId); - } - - /** - * Find all visible task stacks containing {@param userId} and intercept them with an activity - * to block out the contents and possibly start a credential-confirming intent. - * - * @param userId user handle for the locked managed profile. - */ - void lockAllProfileTasks(@UserIdInt int userId) { - mWindowManager.deferSurfaceLayout(); - try { - for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { - final ActivityDisplay display = mActivityDisplays.get(displayNdx); - for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = display.getChildAt(stackNdx); - final List<TaskRecord> tasks = stack.getAllTasks(); - for (int taskNdx = tasks.size() - 1; taskNdx >= 0; taskNdx--) { - final TaskRecord task = tasks.get(taskNdx); - - // Check the task for a top activity belonging to userId, or returning a - // result to an activity belonging to userId. Example case: a document - // picker for personal files, opened by a work app, should still get locked. - if (taskTopActivityIsUser(task, userId)) { - mService.getTaskChangeNotificationController().notifyTaskProfileLocked( - task.taskId, userId); - } - } - } - } - } finally { - mWindowManager.continueSurfaceLayout(); - } - } - void setNextTaskIdForUserLocked(int taskId, int userId) { final int currentTaskId = mCurTaskIdForUser.get(userId, -1); if (taskId > currentTaskId) { @@ -1014,7 +514,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D // was 10, user 0 could only have taskIds 0 to 9, user 1: 10 to 19, user 2: 20 to 29, so on. int candidateTaskId = nextTaskIdForUser(currentTaskId, userId); while (mRecentTasks.containsTaskId(candidateTaskId, userId) - || anyTaskForIdLocked( + || mRootActivityContainer.anyTaskForId( candidateTaskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS) != null) { candidateTaskId = nextTaskIdForUser(candidateTaskId, userId); if (candidateTaskId == currentTaskId) { @@ -1029,142 +529,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return candidateTaskId; } - boolean attachApplicationLocked(WindowProcessController app) throws RemoteException { - final String processName = app.mName; - boolean didSomething = false; - for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { - final ActivityDisplay display = mActivityDisplays.get(displayNdx); - final ActivityStack stack = display.getFocusedStack(); - if (stack != null) { - stack.getAllRunningVisibleActivitiesLocked(mTmpActivityList); - final ActivityRecord top = stack.topRunningActivityLocked(); - final int size = mTmpActivityList.size(); - for (int i = 0; i < size; i++) { - final ActivityRecord activity = mTmpActivityList.get(i); - if (activity.app == null && app.mUid == activity.info.applicationInfo.uid - && processName.equals(activity.processName)) { - try { - if (realStartActivityLocked(activity, app, - top == activity /* andResume */, true /* checkConfig */)) { - didSomething = true; - } - } catch (RemoteException e) { - Slog.w(TAG, "Exception in new application when starting activity " - + top.intent.getComponent().flattenToShortString(), e); - throw e; - } - } - } - } - } - if (!didSomething) { - ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); - } - return didSomething; - } - - boolean allResumedActivitiesIdle() { - for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { - // TODO(b/117135575): Check resumed activities on all visible stacks. - final ActivityDisplay display = mActivityDisplays.get(displayNdx); - if (display.isSleeping()) { - // No resumed activities while display is sleeping. - continue; - } - - // If the focused stack is not null or not empty, there should have some activities - // resuming or resumed. Make sure these activities are idle. - final ActivityStack stack = display.getFocusedStack(); - if (stack == null || stack.numActivities() == 0) { - continue; - } - final ActivityRecord resumedActivity = stack.getResumedActivity(); - if (resumedActivity == null || !resumedActivity.idle) { - if (DEBUG_STATES) { - Slog.d(TAG_STATES, "allResumedActivitiesIdle: stack=" - + stack.mStackId + " " + resumedActivity + " not idle"); - } - return false; - } - } - // Send launch end powerhint when idle - sendPowerHintForLaunchEndIfNeeded(); - return true; - } - - private boolean allResumedActivitiesVisible() { - boolean foundResumed = false; - for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { - final ActivityDisplay display = mActivityDisplays.get(displayNdx); - for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = display.getChildAt(stackNdx); - final ActivityRecord r = stack.getResumedActivity(); - if (r != null) { - if (!r.nowVisible || mActivitiesWaitingForVisibleActivity.contains(r)) { - return false; - } - foundResumed = true; - } - } - } - return foundResumed; - } - - private void executeAppTransitionForAllDisplay() { - for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { - final ActivityDisplay display = mActivityDisplays.get(displayNdx); - display.getWindowContainerController().executeAppTransition(); - } - } - - /** - * 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 displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { - someActivityPaused |= mActivityDisplays.get(displayNdx) - .pauseBackStacks(userLeaving, resuming, dontWait); - } - return someActivityPaused; - } - - boolean allPausedActivitiesComplete() { - boolean pausing = true; - for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { - final ActivityDisplay display = mActivityDisplays.get(displayNdx); - for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = display.getChildAt(stackNdx); - final ActivityRecord r = stack.mPausingActivity; - if (r != null && !r.isState(PAUSED, STOPPED, STOPPING)) { - if (DEBUG_STATES) { - Slog.d(TAG_STATES, - "allPausedActivitiesComplete: r=" + r + " state=" + r.getState()); - pausing = false; - } else { - return false; - } - } - } - } - return pausing; - } - - void cancelInitializingActivities() { - for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { - final ActivityDisplay display = mActivityDisplays.get(displayNdx); - for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = display.getChildAt(stackNdx); - stack.cancelInitializingActivities(); - } - } - } - void waitActivityVisible(ComponentName name, WaitResult result, long startTimeMs) { final WaitInfo waitInfo = new WaitInfo(name, result, startTimeMs); mWaitingForActivityVisible.add(waitInfo); @@ -1255,24 +619,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } } - ActivityRecord topRunningActivityLocked() { - for (int i = mActivityDisplays.size() - 1; i >= 0; --i) { - final ActivityRecord topActivity = mActivityDisplays.get(i).topRunningActivity(); - if (topActivity != null) { - return topActivity; - } - } - return null; - } - - @VisibleForTesting - void getRunningTasks(int maxNum, List<RunningTaskInfo> list, - @ActivityType int ignoreActivityType, @WindowingMode int ignoreWindowingMode, - int callingUid, boolean allowed) { - mRunningTasks.getTasks(maxNum, list, ignoreActivityType, ignoreWindowingMode, - mActivityDisplays, callingUid, allowed); - } - ActivityInfo resolveActivity(Intent intent, ResolveInfo rInfo, int startFlags, ProfilerInfo profilerInfo) { final ActivityInfo aInfo = rInfo != null ? rInfo.activityInfo : null; @@ -1352,10 +698,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return resolveActivity(intent, rInfo, startFlags, profilerInfo); } - private boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc, + boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc, boolean andResume, boolean checkConfig) throws RemoteException { - if (!allPausedActivitiesComplete()) { + if (!mRootActivityContainer.allPausedActivitiesComplete()) { // While there are activities pausing we skipping starting any new activities until // pauses are complete. NOTE: that we also do this for activities that are starting in // the paused state because they will first be resumed then paused on the client side. @@ -1390,7 +736,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D // Deferring resume here because we're going to launch new activity shortly. // We don't want to perform a redundant launch of the same record while ensuring // configurations and trying to resume top activity of focused stack. - ensureVisibilityAndConfig(r, r.getDisplayId(), + mRootActivityContainer.ensureVisibilityAndConfig(r, r.getDisplayId(), false /* markFrozenIfConfigChanged */, true /* deferResume */); } @@ -1560,7 +906,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D // launching the initial activity (that is, home), so that it can have // a chance to initialize itself while in the background, making the // switch back to it faster and look better. - if (isTopDisplayFocusedStack(stack)) { + if (mRootActivityContainer.isTopDisplayFocusedStack(stack)) { mService.getActivityStartController().startSetupActivity(); } @@ -1573,47 +919,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return true; } - /** - * Ensure all activities visibility, update orientation and configuration. - * - * @param starting The currently starting activity or {@code null} if there is none. - * @param displayId The id of the display where operation is executed. - * @param markFrozenIfConfigChanged Whether to set {@link ActivityRecord#frozenBeforeDestroy} to - * {@code true} if config changed. - * @param deferResume Whether to defer resume while updating config. - * @return 'true' if starting activity was kept or wasn't provided, 'false' if it was relaunched - * because of configuration update. - */ - boolean ensureVisibilityAndConfig(ActivityRecord starting, int displayId, - boolean markFrozenIfConfigChanged, boolean deferResume) { - // First ensure visibility without updating the config just yet. We need this to know what - // activities are affecting configuration now. - // Passing null here for 'starting' param value, so that visibility of actual starting - // activity will be properly updated. - ensureActivitiesVisibleLocked(null /* starting */, 0 /* configChanges */, - false /* preserveWindows */, false /* notifyClients */); - - if (displayId == INVALID_DISPLAY) { - // The caller didn't provide a valid display id, skip updating config. - return true; - } - - // Force-update the orientation from the WindowManager, since we need the true configuration - // to send to the client now. - final Configuration config = mWindowManager.updateOrientationFromAppTokens( - getDisplayOverrideConfiguration(displayId), - starting != null && starting.mayFreezeScreenLocked(starting.app) - ? starting.appToken : null, - displayId, true /* forceUpdate */); - if (starting != null && markFrozenIfConfigChanged && config != null) { - starting.frozenBeforeDestroy = true; - } - - // Update the configuration of the activities on the display. - return mService.updateDisplayOverrideConfigurationLocked(config, starting, deferResume, - displayId); - } - private void logIfTransactionTooLarge(Intent intent, Bundle icicle) { int extrasSize = 0; if (intent != null) { @@ -1669,47 +974,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D mService.mH.sendMessage(msg); } - void sendPowerHintForLaunchStartIfNeeded(boolean forceSend, ActivityRecord targetActivity) { - boolean sendHint = forceSend; - - if (!sendHint) { - // Send power hint if we don't know what we're launching yet - sendHint = targetActivity == null || targetActivity.app == null; - } - - if (!sendHint) { // targetActivity != null - // Send power hint when the activity's process is different than the current resumed - // activity on all displays, or if there are no resumed activities in the system. - boolean noResumedActivities = true; - boolean allFocusedProcessesDiffer = true; - for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) { - final ActivityDisplay activityDisplay = mActivityDisplays.get(displayNdx); - final ActivityRecord resumedActivity = activityDisplay.getResumedActivity(); - final WindowProcessController resumedActivityProcess = - resumedActivity == null ? null : resumedActivity.app; - - noResumedActivities &= resumedActivityProcess == null; - if (resumedActivityProcess != null) { - allFocusedProcessesDiffer &= !resumedActivityProcess.equals(targetActivity.app); - } - } - sendHint = noResumedActivities || allFocusedProcessesDiffer; - } - - if (sendHint && mService.mPowerManagerInternal != null) { - mService.mPowerManagerInternal.powerHint(PowerHint.LAUNCH, 1); - mPowerHintSent = true; - } - } - - void sendPowerHintForLaunchEndIfNeeded() { - // Trigger launch power hint if activity is launched - if (mPowerHintSent && mService.mPowerManagerInternal != null) { - mService.mPowerManagerInternal.powerHint(PowerHint.LAUNCH, 0); - mPowerHintSent = false; - } - } - boolean checkStartAnyActivityPermission(Intent intent, ActivityInfo aInfo, String resultWho, int requestCode, int callingPid, int callingUid, String callingPackage, boolean ignoreTargetSecurity, boolean launchingInTask, @@ -1788,7 +1052,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return true; } - final ActivityDisplay activityDisplay = getActivityDisplayOrCreateLocked(launchDisplayId); + final ActivityDisplay activityDisplay = + mRootActivityContainer.getActivityDisplayOrCreate(launchDisplayId); if (activityDisplay == null || activityDisplay.isRemoved()) { Slog.w(TAG, "Launch on display check: display not found"); return false; @@ -1850,21 +1115,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return false; } - /** Update lists of UIDs that are present on displays and have access to them. */ - void updateUIDsPresentOnDisplay() { - mDisplayAccessUIDs.clear(); - for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { - final ActivityDisplay activityDisplay = mActivityDisplays.get(displayNdx); - // Only bother calculating the whitelist for private displays - if (activityDisplay.isPrivate()) { - mDisplayAccessUIDs.append( - activityDisplay.mDisplayId, activityDisplay.getPresentUIDs()); - } - } - // Store updated lists in DisplayManager. Callers from outside of AM should get them there. - mDisplayManagerInternal.setDisplayAccessUIDs(mDisplayAccessUIDs); - } - UserInfo getUserInfo(int userId) { final long identity = Binder.clearCallingIdentity(); try { @@ -2016,7 +1266,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D // Check if able to finish booting when device is booting and all resumed activities // are idle. - if ((mService.isBooting() && allResumedActivitiesIdle()) || fromTimeout) { + if ((mService.isBooting() && mRootActivityContainer.allResumedActivitiesIdle()) + || fromTimeout) { booting = checkFinishBootingLocked(); } @@ -2025,7 +1276,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D r.mRelaunchReason = RELAUNCH_REASON_NONE; } - if (allResumedActivitiesIdle()) { + if (mRootActivityContainer.allResumedActivitiesIdle()) { if (r != null) { mService.scheduleAppGcsLocked(); } @@ -2038,7 +1289,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } mLaunchingActivity.release(); } - ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); + mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS); } // Atomically retrieve all of the other things to do. @@ -2094,186 +1345,13 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D //mWindowManager.dump(); if (activityRemoved) { - resumeFocusedStacksTopActivitiesLocked(); + mRootActivityContainer.resumeFocusedStacksTopActivities(); } return r; } - boolean handleAppDiedLocked(WindowProcessController app) { - boolean hasVisibleActivities = false; - for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { - final ActivityDisplay display = mActivityDisplays.get(displayNdx); - for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = display.getChildAt(stackNdx); - hasVisibleActivities |= stack.handleAppDiedLocked(app); - } - } - return hasVisibleActivities; - } - - void closeSystemDialogsLocked() { - for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { - final ActivityDisplay display = mActivityDisplays.get(displayNdx); - for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = display.getChildAt(stackNdx); - stack.closeSystemDialogsLocked(); - } - } - } - - void removeUserLocked(int userId) { - mUserStackInFront.delete(userId); - } - - /** - * Update the last used stack id for non-current user (current user's last - * used stack is the focused stack) - */ - void updateUserStackLocked(int userId, ActivityStack stack) { - if (userId != mCurrentUser) { - mUserStackInFront.put(userId, stack != null ? stack.getStackId() - : getDefaultDisplay().getHomeStack().mStackId); - } - } - - /** - * @return true if some activity was finished (or would have finished if doit were true). - */ - boolean finishDisabledPackageActivitiesLocked(String packageName, Set<String> filterByClasses, - boolean doit, boolean evenPersistent, int userId) { - boolean didSomething = false; - for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { - final ActivityDisplay display = mActivityDisplays.get(displayNdx); - for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = display.getChildAt(stackNdx); - if (stack.finishDisabledPackageActivitiesLocked( - packageName, filterByClasses, doit, evenPersistent, userId)) { - didSomething = true; - } - } - } - return didSomething; - } - - void updatePreviousProcessLocked(ActivityRecord r) { - // Now that this process has stopped, we may want to consider - // it to be the previous app to try to keep around in case - // the user wants to return to it. - - // First, found out what is currently the foreground app, so that - // we don't blow away the previous app if this activity is being - // hosted by the process that is actually still the foreground. - WindowProcessController fgApp = null; - for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { - final ActivityDisplay display = mActivityDisplays.get(displayNdx); - for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = display.getChildAt(stackNdx); - if (isTopDisplayFocusedStack(stack)) { - final ActivityRecord resumedActivity = stack.getResumedActivity(); - if (resumedActivity != null) { - fgApp = resumedActivity.app; - } else if (stack.mPausingActivity != null) { - fgApp = stack.mPausingActivity.app; - } - break; - } - } - } - - // Now set this one as the previous process, only if that really - // makes sense to. - if (r.hasProcess() && fgApp != null && r.app != fgApp - && r.lastVisibleTime > mService.mPreviousProcessVisibleTime - && r.app != mService.mHomeProcess) { - mService.mPreviousProcess = r.app; - mService.mPreviousProcessVisibleTime = r.lastVisibleTime; - } - } - - boolean resumeFocusedStacksTopActivitiesLocked() { - return resumeFocusedStacksTopActivitiesLocked(null, null, null); - } - - boolean resumeFocusedStacksTopActivitiesLocked( - ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) { - - if (!readyToResume()) { - return false; - } - - if (targetStack != null && (targetStack.isTopStackOnDisplay() - || getTopDisplayFocusedStack() == targetStack)) { - return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions); - } - - // Resume all top activities in focused stacks on all displays. - for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { - final ActivityDisplay display = mActivityDisplays.get(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; - } - - void updateActivityApplicationInfoLocked(ApplicationInfo aInfo) { - for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { - final ActivityDisplay display = mActivityDisplays.get(displayNdx); - for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = display.getChildAt(stackNdx); - stack.updateActivityApplicationInfoLocked(aInfo); - } - } - } - - /** - * Finish the topmost activities in all stacks that belong to the crashed app. - * @param app The app that crashed. - * @param reason Reason to perform this action. - * @return The task id that was finished in this stack, or INVALID_TASK_ID if none was finished. - */ - int finishTopCrashedActivitiesLocked(WindowProcessController app, String reason) { - TaskRecord finishedTask = null; - ActivityStack focusedStack = getTopDisplayFocusedStack(); - for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { - final ActivityDisplay display = mActivityDisplays.get(displayNdx); - // It is possible that request to finish activity might also remove its task and stack, - // so we need to be careful with indexes in the loop and check child count every time. - for (int stackNdx = 0; stackNdx < display.getChildCount(); ++stackNdx) { - final ActivityStack stack = display.getChildAt(stackNdx); - final TaskRecord t = stack.finishTopCrashedActivityLocked(app, reason); - if (stack == focusedStack || finishedTask == null) { - finishedTask = t; - } - } - } - return finishedTask != null ? finishedTask.taskId : INVALID_TASK_ID; - } - - void finishVoiceTask(IVoiceInteractionSession session) { - for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { - final ActivityDisplay display = mActivityDisplays.get(displayNdx); - final int numStacks = display.getChildCount(); - for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { - final ActivityStack stack = display.getChildAt(stackNdx); - stack.finishVoiceTask(session); - } - } - } - - /** - * This doesn't just find a task, it also moves the task to front. - */ + /** This doesn't just find a task, it also moves the task to front. */ void findTaskToMoveToFront(TaskRecord task, int flags, ActivityOptions options, String reason, boolean forceNonResizeable) { ActivityStack currentStack = task.getStack(); @@ -2293,7 +1371,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D final Rect bounds = options.getLaunchBounds(); task.updateOverrideConfiguration(bounds); - ActivityStack stack = getLaunchStack(null, options, task, ON_TOP); + ActivityStack stack = + mRootActivityContainer.getLaunchStack(null, options, task, ON_TOP); if (stack != currentStack) { moveHomeStackToFrontIfNeeded(flags, stack.getDisplay(), reason); @@ -2305,7 +1384,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D // still need moveTaskToFrontLocked() below for any transition settings. } if (stack.resizeStackWithLaunchBounds()) { - resizeStackLocked(stack, bounds, null /* tempTaskBounds */, + mRootActivityContainer.resizeStack(stack, bounds, null /* tempTaskBounds */, null /* tempTaskInsetBounds */, !PRESERVE_WINDOWS, true /* allowResizeInDockedMode */, !DEFER_RESUME); } else { @@ -2358,388 +1437,22 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return mLaunchParamsController; } - protected <T extends ActivityStack> T getStack(int stackId) { - for (int i = mActivityDisplays.size() - 1; i >= 0; --i) { - final T stack = mActivityDisplays.get(i).getStack(stackId); - if (stack != null) { - return stack; - } - } - return null; - } - - /** @see ActivityDisplay#getStack(int, int) */ - private <T extends ActivityStack> T getStack(int windowingMode, int activityType) { - for (int i = mActivityDisplays.size() - 1; i >= 0; --i) { - final T stack = mActivityDisplays.get(i).getStack(windowingMode, activityType); - if (stack != null) { - return stack; - } - } - return null; - } - - int resolveActivityType(@Nullable ActivityRecord r, @Nullable ActivityOptions options, - @Nullable TaskRecord task) { - // Preference is given to the activity type for the activity then the task since the type - // once set shouldn't change. - int activityType = r != null ? r.getActivityType() : ACTIVITY_TYPE_UNDEFINED; - if (activityType == ACTIVITY_TYPE_UNDEFINED && task != null) { - activityType = task.getActivityType(); - } - if (activityType != ACTIVITY_TYPE_UNDEFINED) { - return activityType; - } - if (options != null) { - activityType = options.getLaunchActivityType(); - } - return activityType != ACTIVITY_TYPE_UNDEFINED ? activityType : ACTIVITY_TYPE_STANDARD; - } - - <T extends ActivityStack> T getLaunchStack(@Nullable ActivityRecord r, - @Nullable ActivityOptions options, @Nullable TaskRecord candidateTask, boolean onTop) { - return getLaunchStack(r, options, candidateTask, onTop, null /* launchParams */); + private void deferUpdateRecentsHomeStackBounds() { + mRootActivityContainer.deferUpdateBounds(ACTIVITY_TYPE_RECENTS); + mRootActivityContainer.deferUpdateBounds(ACTIVITY_TYPE_HOME); } - /** - * Returns the right stack to use for launching factoring in all the input parameters. - * - * @param r The activity we are trying to launch. Can be null. - * @param options The activity options used to the launch. Can be null. - * @param candidateTask The possible task the activity might be launched in. Can be null. - * @params launchParams The resolved launch params to use. - * - * @return The stack to use for the launch or INVALID_STACK_ID. - */ - <T extends ActivityStack> T getLaunchStack(@Nullable ActivityRecord r, - @Nullable ActivityOptions options, @Nullable TaskRecord candidateTask, boolean onTop, - @Nullable LaunchParamsController.LaunchParams launchParams) { - int taskId = INVALID_TASK_ID; - int displayId = INVALID_DISPLAY; - //Rect bounds = null; - - // We give preference to the launch preference in activity options. - if (options != null) { - taskId = options.getLaunchTaskId(); - displayId = options.getLaunchDisplayId(); - } - - // First preference for stack goes to the task Id set in the activity options. Use the stack - // associated with that if possible. - if (taskId != INVALID_TASK_ID) { - // Temporarily set the task id to invalid in case in re-entry. - options.setLaunchTaskId(INVALID_TASK_ID); - final TaskRecord task = anyTaskForIdLocked(taskId, - MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, options, onTop); - options.setLaunchTaskId(taskId); - if (task != null) { - return task.getStack(); - } - } - - final int activityType = resolveActivityType(r, options, candidateTask); - T stack; - - // Next preference for stack goes to the display Id set the candidate display. - if (launchParams != null && launchParams.mPreferredDisplayId != INVALID_DISPLAY) { - displayId = launchParams.mPreferredDisplayId; - } - if (displayId != INVALID_DISPLAY && canLaunchOnDisplay(r, displayId)) { - if (r != null) { - stack = (T) getValidLaunchStackOnDisplay(displayId, r, candidateTask, options, - launchParams); - if (stack != null) { - return stack; - } - } - final ActivityDisplay display = getActivityDisplayOrCreateLocked(displayId); - if (display != null) { - stack = display.getOrCreateStack(r, options, candidateTask, activityType, onTop); - if (stack != null) { - return stack; - } - } - } - - // Give preference to the stack and display of the input task and activity if they match the - // mode we want to launch into. - stack = null; - ActivityDisplay display = null; - if (candidateTask != null) { - stack = candidateTask.getStack(); - } - if (stack == null && r != null) { - stack = r.getStack(); - } - if (stack != null) { - display = stack.getDisplay(); - if (display != null && canLaunchOnDisplay(r, display.mDisplayId)) { - int windowingMode = launchParams != null ? launchParams.mWindowingMode - : WindowConfiguration.WINDOWING_MODE_UNDEFINED; - if (windowingMode == WindowConfiguration.WINDOWING_MODE_UNDEFINED) { - windowingMode = display.resolveWindowingMode(r, options, candidateTask, - activityType); - } - if (stack.isCompatible(windowingMode, activityType)) { - return stack; - } - if (windowingMode == WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY - && display.getSplitScreenPrimaryStack() == stack - && candidateTask == stack.topTask()) { - // This is a special case when we try to launch an activity that is currently on - // top of split-screen primary stack, but is targeting split-screen secondary. - // In this case we don't want to move it to another stack. - // TODO(b/78788972): Remove after differentiating between preferred and required - // launch options. - return stack; - } - } - } - - if (display == null || !canLaunchOnDisplay(r, display.mDisplayId)) { - display = getDefaultDisplay(); - } - - return display.getOrCreateStack(r, options, candidateTask, activityType, onTop); - } - - /** @return true if activity record is null or can be launched on provided display. */ - private boolean canLaunchOnDisplay(ActivityRecord r, int displayId) { - if (r == null) { - return true; - } - return r.canBeLaunchedOnDisplay(displayId); - } - - /** - * Get a topmost stack on the display, that is a valid launch stack for specified activity. - * If there is no such stack, new dynamic stack can be created. - * @param displayId Target display. - * @param r Activity that should be launched there. - * @param candidateTask The possible task the activity might be put in. - * @return Existing stack if there is a valid one, new dynamic stack if it is valid or null. - */ - private ActivityStack getValidLaunchStackOnDisplay(int displayId, @NonNull ActivityRecord r, - @Nullable TaskRecord candidateTask, @Nullable ActivityOptions options, - @Nullable LaunchParamsController.LaunchParams launchParams) { - final ActivityDisplay activityDisplay = getActivityDisplayOrCreateLocked(displayId); - if (activityDisplay == null) { - throw new IllegalArgumentException( - "Display with displayId=" + displayId + " not found."); - } - - if (!r.canBeLaunchedOnDisplay(displayId)) { - return null; - } - - // If {@code r} is already in target display and its task is the same as the candidate task, - // the intention should be getting a launch stack for the reusable activity, so we can use - // the existing stack. - if (r.getDisplayId() == displayId && r.getTask() == candidateTask) { - return candidateTask.getStack(); - } - - // Return the topmost valid stack on the display. - for (int i = activityDisplay.getChildCount() - 1; i >= 0; --i) { - final ActivityStack stack = activityDisplay.getChildAt(i); - if (isValidLaunchStack(stack, displayId, r)) { - return stack; - } - } - - // If there is no valid stack on the external display - check if new dynamic stack will do. - if (displayId != DEFAULT_DISPLAY) { - final int windowingMode; - if (launchParams != null) { - // When launch params is not null, we always defer to its windowing mode. Sometimes - // it could be unspecified, which indicates it should inherit windowing mode from - // display. - windowingMode = launchParams.mWindowingMode; - } else { - windowingMode = options != null ? options.getLaunchWindowingMode() - : r.getWindowingMode(); - } - final int activityType = - options != null && options.getLaunchActivityType() != ACTIVITY_TYPE_UNDEFINED - ? options.getLaunchActivityType() : r.getActivityType(); - return activityDisplay.createStack(windowingMode, activityType, true /*onTop*/); - } - - Slog.w(TAG, "getValidLaunchStackOnDisplay: can't launch on displayId " + displayId); - return null; - } - - ActivityStack getValidLaunchStackOnDisplay(int displayId, @NonNull ActivityRecord r, - @Nullable ActivityOptions options, - @Nullable LaunchParamsController.LaunchParams launchParams) { - return getValidLaunchStackOnDisplay(displayId, r, null /* candidateTask */, options, - launchParams); - } - - // TODO: Can probably be consolidated into getLaunchStack()... - private boolean isValidLaunchStack(ActivityStack stack, int displayId, ActivityRecord r) { - switch (stack.getActivityType()) { - case ACTIVITY_TYPE_HOME: return r.isActivityTypeHome(); - case ACTIVITY_TYPE_RECENTS: return r.isActivityTypeRecents(); - case ACTIVITY_TYPE_ASSISTANT: return r.isActivityTypeAssistant(); - } - // There is a 1-to-1 relationship between stack and task when not in - // primary split-windowing mode. - if (stack.getWindowingMode() != WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) { - return false; - } else { - return r.supportsSplitScreenWindowingMode(); - } - } - - /** - * 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}, {@code null} if not found. - */ - 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; - } - if (preferredDisplay.supportsSystemDecorations()) { - // Stop looking for focusable stack on other displays because the preferred display - // supports system decorations. Home activity would be launched on the same display if - // no focusable stack found. - return null; - } - - // Now look through all displays - for (int i = mActivityDisplays.size() - 1; i >= 0; --i) { - final ActivityDisplay display = mActivityDisplays.get(i); - if (display == preferredDisplay) { - // We've already checked this one - continue; - } - final ActivityStack nextFocusableStack = display.getNextFocusableStack(currentFocus, - ignoreCurrent); - if (nextFocusableStack != null) { - return nextFocusableStack; - } - } - - return null; - } - - /** - * Get next valid stack for launching provided activity in the system. This will search across - * displays and stacks in last-focused order for a focusable and visible stack, except those - * that are on a currently focused display. - * - * @param r The activity that is being launched. - * @param currentFocus The display that previously had focus and thus needs to be ignored when - * searching for the next candidate. - * @return Next valid {@link ActivityStack}, null if not found. - */ - ActivityStack getNextValidLaunchStackLocked(@NonNull ActivityRecord r, int currentFocus) { - for (int i = mActivityDisplays.size() - 1; i >= 0; --i) { - final ActivityDisplay display = mActivityDisplays.get(i); - if (display.mDisplayId == currentFocus) { - continue; - } - final ActivityStack stack = getValidLaunchStackOnDisplay(display.mDisplayId, r, - null /* options */, null /* launchParams */); - if (stack != null) { - return stack; - } - } - return null; - } - - ActivityRecord getDefaultDisplayHomeActivity() { - return getDefaultDisplayHomeActivityForUser(mCurrentUser); - } - - ActivityRecord getDefaultDisplayHomeActivityForUser(int userId) { - return getActivityDisplay(DEFAULT_DISPLAY).getHomeActivityForUser(userId); - } - - void resizeStackLocked(ActivityStack stack, Rect bounds, Rect tempTaskBounds, - Rect tempTaskInsetBounds, boolean preserveWindows, boolean allowResizeInDockedMode, - boolean deferResume) { - - if (stack.inSplitScreenPrimaryWindowingMode()) { - resizeDockedStackLocked(bounds, tempTaskBounds, tempTaskInsetBounds, null, null, - preserveWindows, deferResume); - return; - } - - final boolean splitScreenActive = getDefaultDisplay().hasSplitScreenPrimaryStack(); - if (!allowResizeInDockedMode - && !stack.getWindowConfiguration().tasksAreFloating() && splitScreenActive) { - // If the docked stack exists, don't resize non-floating stacks independently of the - // size computed from the docked stack size (otherwise they will be out of sync) - return; - } - - Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeStack_" + stack.mStackId); - mWindowManager.deferSurfaceLayout(); - try { - if (stack.affectedBySplitScreenResize()) { - if (bounds == null && stack.inSplitScreenWindowingMode()) { - // null bounds = fullscreen windowing mode...at least for now. - stack.setWindowingMode(WINDOWING_MODE_FULLSCREEN); - } else if (splitScreenActive) { - // If we are in split-screen mode and this stack support split-screen, then - // it should be split-screen secondary mode. i.e. adjacent to the docked stack. - stack.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY); - } - } - stack.resize(bounds, tempTaskBounds, tempTaskInsetBounds); - if (!deferResume) { - stack.ensureVisibleActivitiesConfigurationLocked( - stack.topRunningActivityLocked(), preserveWindows); - } - } finally { - mWindowManager.continueSurfaceLayout(); - Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); - } - } - - void deferUpdateRecentsHomeStackBounds() { - deferUpdateBounds(ACTIVITY_TYPE_RECENTS); - deferUpdateBounds(ACTIVITY_TYPE_HOME); - } - - void deferUpdateBounds(int activityType) { - final ActivityStack stack = getStack(WINDOWING_MODE_UNDEFINED, activityType); - if (stack != null) { - stack.deferUpdateBounds(); - } - } - - void continueUpdateRecentsHomeStackBounds() { - continueUpdateBounds(ACTIVITY_TYPE_RECENTS); - continueUpdateBounds(ACTIVITY_TYPE_HOME); - } - - void continueUpdateBounds(int activityType) { - final ActivityStack stack = getStack(WINDOWING_MODE_UNDEFINED, activityType); - if (stack != null) { - stack.continueUpdateBounds(); - } + private void continueUpdateRecentsHomeStackBounds() { + mRootActivityContainer.continueUpdateBounds(ACTIVITY_TYPE_RECENTS); + mRootActivityContainer.continueUpdateBounds(ACTIVITY_TYPE_HOME); } void notifyAppTransitionDone() { continueUpdateRecentsHomeStackBounds(); for (int i = mResizingTasksDuringAnimation.size() - 1; i >= 0; i--) { final int taskId = mResizingTasksDuringAnimation.valueAt(i); - final TaskRecord task = anyTaskForIdLocked(taskId, MATCH_TASK_IN_STACKS_ONLY); + final TaskRecord task = + mRootActivityContainer.anyTaskForId(taskId, MATCH_TASK_IN_STACKS_ONLY); if (task != null) { task.setTaskDockedResizing(false); } @@ -2758,7 +1471,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D try { final int windowingMode = fromStack.getWindowingMode(); final boolean inPinnedWindowingMode = windowingMode == WINDOWING_MODE_PINNED; - final ActivityDisplay toDisplay = getActivityDisplay(toDisplayId); + final ActivityDisplay toDisplay = + mRootActivityContainer.getActivityDisplay(toDisplayId); if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) { // Tell the display we are exiting split-screen mode. @@ -2815,8 +1529,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } } - ensureActivitiesVisibleLocked(null, 0, PRESERVE_WINDOWS); - resumeFocusedStacksTopActivitiesLocked(); + mRootActivityContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS); + mRootActivityContainer.resumeFocusedStacksTopActivities(); } finally { mAllowDockedStackResize = true; mWindowManager.continueSurfaceLayout(); @@ -2862,7 +1576,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D false /* deferResume */); } - private void resizeDockedStackLocked(Rect dockedBounds, Rect tempDockedTaskBounds, + void resizeDockedStackLocked(Rect dockedBounds, Rect tempDockedTaskBounds, Rect tempDockedTaskInsetBounds, Rect tempOtherTaskBounds, Rect tempOtherTaskInsetBounds, boolean preserveWindows, boolean deferResume) { @@ -2871,7 +1585,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return; } - final ActivityStack stack = getDefaultDisplay().getSplitScreenPrimaryStack(); + final ActivityStack stack = + mRootActivityContainer.getDefaultDisplay().getSplitScreenPrimaryStack(); if (stack == null) { Slog.w(TAG, "resizeDockedStackLocked: docked stack not found"); return; @@ -2910,7 +1625,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D // static stacks need to be adjusted so they don't overlap with the docked stack. // We get the bounds to use from window manager which has been adjusted for any // screen controls and is also the same for all stacks. - final ActivityDisplay display = getDefaultDisplay(); + final ActivityDisplay display = mRootActivityContainer.getDefaultDisplay(); final Rect otherTaskRect = new Rect(); for (int i = display.getChildCount() - 1; i >= 0; --i) { final ActivityStack current = display.getChildAt(i); @@ -2930,7 +1645,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D tempRect /* outStackBounds */, otherTaskRect /* outTempTaskBounds */); - resizeStackLocked(current, !tempRect.isEmpty() ? tempRect : null, + mRootActivityContainer.resizeStack(current, + !tempRect.isEmpty() ? tempRect : null, !otherTaskRect.isEmpty() ? otherTaskRect : tempOtherTaskBounds, tempOtherTaskInsetBounds, preserveWindows, true /* allowResizeInDockedMode */, deferResume); @@ -2948,7 +1664,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D void resizePinnedStackLocked(Rect pinnedBounds, Rect tempPinnedTaskBounds) { // TODO(multi-display): Pinned stack display should be passed in. - final PinnedActivityStack stack = getDefaultDisplay().getPinnedStack(); + final PinnedActivityStack stack = + mRootActivityContainer.getDefaultDisplay().getPinnedStack(); if (stack == null) { Slog.w(TAG, "resizePinnedStackLocked: pinned stack not found"); return; @@ -3029,22 +1746,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } /** - * Removes stacks in the input windowing modes from the system if they are of activity type - * ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED - */ - void removeStacksInWindowingModes(int... windowingModes) { - for (int i = mActivityDisplays.size() - 1; i >= 0; --i) { - mActivityDisplays.get(i).removeStacksInWindowingModes(windowingModes); - } - } - - void removeStacksWithActivityTypes(int... activityTypes) { - for (int i = mActivityDisplays.size() - 1; i >= 0; --i) { - mActivityDisplays.get(i).removeStacksWithActivityTypes(activityTypes); - } - } - - /** * See {@link #removeTaskByIdLocked(int, boolean, boolean, boolean)} */ boolean removeTaskByIdLocked(int taskId, boolean killProcess, boolean removeFromRecents, @@ -3065,7 +1766,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D */ boolean removeTaskByIdLocked(int taskId, boolean killProcess, boolean removeFromRecents, boolean pauseImmediately, String reason) { - final TaskRecord tr = anyTaskForIdLocked(taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS); + final TaskRecord tr = + mRootActivityContainer.anyTaskForId(taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS); if (tr != null) { tr.removeTaskActivitiesLocked(pauseImmediately, reason); cleanUpRemovedTaskLocked(tr, killProcess, removeFromRecents); @@ -3154,7 +1856,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D * @return true if the task has been restored successfully. */ boolean restoreRecentTaskLocked(TaskRecord task, ActivityOptions aOptions, boolean onTop) { - final ActivityStack stack = getLaunchStack(null, aOptions, task, onTop); + final ActivityStack stack = + mRootActivityContainer.getLaunchStack(null, aOptions, task, onTop); final ActivityStack currentStack = task.getStack(); if (currentStack != null) { // Task has already been restored once. See if we need to do anything more @@ -3196,39 +1899,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } /** - * Move stack with all its existing content to specified display. - * @param stackId Id of stack to move. - * @param displayId Id of display to move stack to. - * @param onTop Indicates whether container should be place on top or on bottom. - */ - void moveStackToDisplayLocked(int stackId, int displayId, boolean onTop) { - final ActivityDisplay activityDisplay = getActivityDisplayOrCreateLocked(displayId); - if (activityDisplay == null) { - throw new IllegalArgumentException("moveStackToDisplayLocked: Unknown displayId=" - + displayId); - } - final ActivityStack stack = getStack(stackId); - if (stack == null) { - throw new IllegalArgumentException("moveStackToDisplayLocked: Unknown stackId=" - + stackId); - } - - final ActivityDisplay currentDisplay = stack.getDisplay(); - if (currentDisplay == null) { - throw new IllegalStateException("moveStackToDisplayLocked: Stack with stack=" + stack - + " is not attached to any display."); - } - - if (currentDisplay.mDisplayId == displayId) { - throw new IllegalArgumentException("Trying to move stack=" + stack - + " to its current displayId=" + displayId); - } - - stack.reparent(activityDisplay, onTop, false /* displayRemoved */); - // TODO(multi-display): resize stacks properly if moved from split-screen. - } - - /** * Returns the reparent target stack, creating the stack if necessary. This call also enforces * the various checks on tasks that are going to be reparented from one stack to another. */ @@ -3280,159 +1950,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return stack; } - boolean moveTopStackActivityToPinnedStackLocked(int stackId, Rect destBounds) { - final ActivityStack stack = getStack(stackId); - if (stack == null) { - throw new IllegalArgumentException( - "moveTopStackActivityToPinnedStackLocked: Unknown stackId=" + stackId); - } - - final ActivityRecord r = stack.topRunningActivityLocked(); - if (r == null) { - Slog.w(TAG, "moveTopStackActivityToPinnedStackLocked: No top running activity" - + " in stack=" + stack); - return false; - } - - if (!mService.mForceResizableActivities && !r.supportsPictureInPicture()) { - Slog.w(TAG, - "moveTopStackActivityToPinnedStackLocked: Picture-In-Picture not supported for " - + " r=" + r); - return false; - } - - moveActivityToPinnedStackLocked(r, null /* sourceBounds */, 0f /* aspectRatio */, - "moveTopActivityToPinnedStack"); - return true; - } - - void moveActivityToPinnedStackLocked(ActivityRecord r, Rect sourceHintBounds, float aspectRatio, - String reason) { - - mWindowManager.deferSurfaceLayout(); - - final ActivityDisplay display = r.getStack().getDisplay(); - PinnedActivityStack stack = display.getPinnedStack(); - - // This will clear the pinned stack by moving an existing task to the full screen stack, - // ensuring only one task is present. - if (stack != null) { - moveTasksToFullscreenStackLocked(stack, !ON_TOP); - } - - // Need to make sure the pinned stack exist so we can resize it below... - stack = display.getOrCreateStack(WINDOWING_MODE_PINNED, r.getActivityType(), ON_TOP); - - // Calculate the target bounds here before the task is reparented back into pinned windowing - // mode (which will reset the saved bounds) - final Rect destBounds = stack.getDefaultPictureInPictureBounds(aspectRatio); - - try { - final TaskRecord task = r.getTask(); - // Resize the pinned stack to match the current size of the task the activity we are - // going to be moving is currently contained in. We do this to have the right starting - // animation bounds for the pinned stack to the desired bounds the caller wants. - resizeStackLocked(stack, task.getOverrideBounds(), null /* tempTaskBounds */, - null /* tempTaskInsetBounds */, !PRESERVE_WINDOWS, - true /* allowResizeInDockedMode */, !DEFER_RESUME); - - if (task.mActivities.size() == 1) { - // Defer resume until below, and do not schedule PiP changes until we animate below - task.reparent(stack, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, !ANIMATE, DEFER_RESUME, - false /* schedulePictureInPictureModeChange */, reason); - } else { - // There are multiple activities in the task and moving the top activity should - // reveal/leave the other activities in their original task. - - // Currently, we don't support reparenting activities across tasks in two different - // stacks, so instead, just create a new task in the same stack, reparent the - // activity into that task, and then reparent the whole task to the new stack. This - // ensures that all the necessary work to migrate states in the old and new stacks - // is also done. - final TaskRecord newTask = task.getStack().createTaskRecord( - getNextTaskIdForUserLocked(r.userId), r.info, r.intent, null, null, true); - r.reparent(newTask, MAX_VALUE, "moveActivityToStack"); - - // Defer resume until below, and do not schedule PiP changes until we animate below - newTask.reparent(stack, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, !ANIMATE, - DEFER_RESUME, false /* schedulePictureInPictureModeChange */, reason); - } - - // Reset the state that indicates it can enter PiP while pausing after we've moved it - // to the pinned stack - r.supportsEnterPipOnTaskSwitch = false; - } finally { - mWindowManager.continueSurfaceLayout(); - } - - stack.animateResizePinnedStack(sourceHintBounds, destBounds, -1 /* animationDuration */, - true /* fromFullscreen */); - - // Update the visibility of all activities after the they have been reparented to the new - // stack. This MUST run after the animation above is scheduled to ensure that the windows - // drawn signal is scheduled after the bounds animation start call on the bounds animator - // thread. - ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); - resumeFocusedStacksTopActivitiesLocked(); - - mService.getTaskChangeNotificationController().notifyActivityPinned(r); - } - - ActivityRecord findTaskLocked(ActivityRecord r, int preferredDisplayId) { - if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Looking for task of " + r); - mTmpFindTaskResult.clear(); - - // Looking up task on preferred display first - final ActivityDisplay preferredDisplay = getActivityDisplay(preferredDisplayId); - if (preferredDisplay != null) { - preferredDisplay.findTaskLocked(r, true /* isPreferredDisplay */, mTmpFindTaskResult); - if (mTmpFindTaskResult.mIdealMatch) { - return mTmpFindTaskResult.mRecord; - } - } - - for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { - final ActivityDisplay display = mActivityDisplays.get(displayNdx); - if (display.mDisplayId == preferredDisplayId) { - continue; - } - - display.findTaskLocked(r, false /* isPreferredDisplay */, mTmpFindTaskResult); - if (mTmpFindTaskResult.mIdealMatch) { - return mTmpFindTaskResult.mRecord; - } - } - - if (DEBUG_TASKS && mTmpFindTaskResult.mRecord == null) Slog.d(TAG_TASKS, "No task found"); - return mTmpFindTaskResult.mRecord; - } - - ActivityRecord findActivityLocked(Intent intent, ActivityInfo info, - boolean compareIntentFilters) { - for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { - final ActivityDisplay display = mActivityDisplays.get(displayNdx); - for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = display.getChildAt(stackNdx); - final ActivityRecord ar = stack.findActivityLocked( - intent, info, compareIntentFilters); - if (ar != null) { - return ar; - } - } - } - return null; - } - - boolean hasAwakeDisplay() { - for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { - final ActivityDisplay display = mActivityDisplays.get(displayNdx); - if (!display.shouldSleep()) { - return true; - } - } - return false; - } - void goingToSleepLocked() { scheduleSleepTimeout(); if (!mGoingToSleep.isHeld()) { @@ -3446,24 +1963,19 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } } - applySleepTokensLocked(false /* applyToStacks */); + mRootActivityContainer.applySleepTokens(false /* applyToStacks */); checkReadyForSleepLocked(true /* allowDelay */); } - void prepareForShutdownLocked() { - for (int i = 0; i < mActivityDisplays.size(); i++) { - createSleepTokenLocked("shutdown", mActivityDisplays.get(i).mDisplayId); - } - } - boolean shutdownLocked(int timeout) { goingToSleepLocked(); boolean timedout = false; final long endTime = System.currentTimeMillis() + timeout; while (true) { - if (!putStacksToSleepLocked(true /* allowDelay */, true /* shuttingDown */)) { + if (!mRootActivityContainer.putStacksToSleep( + true /* allowDelay */, true /* shuttingDown */)) { long timeRemaining = endTime - System.currentTimeMillis(); if (timeRemaining > 0) { try { @@ -3493,51 +2005,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } } - void applySleepTokensLocked(boolean applyToStacks) { - for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { - // Set the sleeping state of the display. - final ActivityDisplay display = mActivityDisplays.get(displayNdx); - final boolean displayShouldSleep = display.shouldSleep(); - if (displayShouldSleep == display.isSleeping()) { - continue; - } - display.setIsSleeping(displayShouldSleep); - - if (!applyToStacks) { - continue; - } - - // Set the sleeping state of the stacks on the display. - for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = display.getChildAt(stackNdx); - if (displayShouldSleep) { - stack.goToSleepIfPossible(false /* shuttingDown */); - } else { - stack.awakeFromSleepingLocked(); - if (stack.isFocusedStackOnDisplay() && !getKeyguardController() - .isKeyguardOrAodShowing(display.mDisplayId)) { - // If the keyguard is unlocked - resume immediately. - // 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. - resumeFocusedStacksTopActivitiesLocked(); - } - } - } - - if (displayShouldSleep || mGoingToSleepActivities.isEmpty()) { - continue; - } - // The display is awake now, so clean up the going to sleep list. - for (Iterator<ActivityRecord> it = mGoingToSleepActivities.iterator(); it.hasNext(); ) { - final ActivityRecord r = it.next(); - if (r.getDisplayId() == display.mDisplayId) { - it.remove(); - } - } - } - } - void activitySleptLocked(ActivityRecord r) { mGoingToSleepActivities.remove(r); final ActivityStack s = r.getStack(); @@ -3554,12 +2021,13 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return; } - if (!putStacksToSleepLocked(allowDelay, false /* shuttingDown */)) { + if (!mRootActivityContainer.putStacksToSleep( + allowDelay, false /* shuttingDown */)) { return; } // Send launch end powerhint before going sleep - sendPowerHintForLaunchEndIfNeeded(); + mRootActivityContainer.sendPowerHintForLaunchEndIfNeeded(); removeSleepTimeouts(); @@ -3571,52 +2039,24 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } } - // Tries to put all activity stacks to sleep. Returns true if all stacks were - // successfully put to sleep. - private boolean putStacksToSleepLocked(boolean allowDelay, boolean shuttingDown) { - boolean allSleep = true; - for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { - final ActivityDisplay display = mActivityDisplays.get(displayNdx); - for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = display.getChildAt(stackNdx); - if (allowDelay) { - allSleep &= stack.goToSleepIfPossible(shuttingDown); - } else { - stack.goToSleep(); - } - } - } - return allSleep; - } - boolean reportResumedActivityLocked(ActivityRecord r) { // A resumed activity cannot be stopping. remove from list mStoppingActivities.remove(r); final ActivityStack stack = r.getStack(); - if (isTopDisplayFocusedStack(stack)) { + if (mRootActivityContainer.isTopDisplayFocusedStack(stack)) { mService.updateUsageStats(r, true); } if (stack.getDisplay().allResumedActivitiesComplete()) { - ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); + mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS); // Make sure activity & window visibility should be identical // for all displays in this stage. - executeAppTransitionForAllDisplay(); + mRootActivityContainer.executeAppTransitionForAllDisplay(); return true; } return false; } - void handleAppCrashLocked(WindowProcessController app) { - for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { - final ActivityDisplay display = mActivityDisplays.get(displayNdx); - for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = display.getChildAt(stackNdx); - stack.handleAppCrashLocked(app); - } - } - } - // Called when WindowManager has finished animating the launchingBehind activity to the back. private void handleLaunchTaskBehindCompleteLocked(ActivityRecord r) { final TaskRecord task = r.getTask(); @@ -3639,157 +2079,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D mHandler.obtainMessage(LAUNCH_TASK_BEHIND_COMPLETE, token).sendToTarget(); } - /** - * Make sure that all activities that need to be visible in the system actually are and update - * their configuration. - */ - void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges, - boolean preserveWindows) { - ensureActivitiesVisibleLocked(starting, configChanges, preserveWindows, - true /* notifyClients */); - } - - /** - * @see #ensureActivitiesVisibleLocked(ActivityRecord, int, boolean) - */ - void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges, - boolean preserveWindows, boolean notifyClients) { - getKeyguardController().beginActivityVisibilityUpdate(); - try { - // First the front stacks. In case any are not fullscreen and are in front of home. - for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { - final ActivityDisplay display = mActivityDisplays.get(displayNdx); - for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = display.getChildAt(stackNdx); - stack.ensureActivitiesVisibleLocked(starting, configChanges, preserveWindows, - notifyClients); - } - } - } finally { - getKeyguardController().endActivityVisibilityUpdate(); - } - } - - void addStartingWindowsForVisibleActivities(boolean taskSwitch) { - for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { - final ActivityDisplay display = mActivityDisplays.get(displayNdx); - for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = display.getChildAt(stackNdx); - stack.addStartingWindowsForVisibleActivities(taskSwitch); - } - } - } - - void invalidateTaskLayers() { - mTaskLayersChanged = true; - } - - void rankTaskLayersIfNeeded() { - if (!mTaskLayersChanged) { - return; - } - mTaskLayersChanged = false; - for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); displayNdx++) { - final ActivityDisplay display = mActivityDisplays.get(displayNdx); - int baseLayer = 0; - for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = display.getChildAt(stackNdx); - baseLayer += stack.rankTaskLayers(baseLayer); - } - } - } - - void clearOtherAppTimeTrackers(AppTimeTracker except) { - for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { - final ActivityDisplay display = mActivityDisplays.get(displayNdx); - for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = display.getChildAt(stackNdx); - stack.clearOtherAppTimeTrackers(except); - } - } - } - - void scheduleDestroyAllActivities(WindowProcessController app, String reason) { - for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { - final ActivityDisplay display = mActivityDisplays.get(displayNdx); - for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = display.getChildAt(stackNdx); - stack.scheduleDestroyActivities(app, reason); - } - } - } - - void releaseSomeActivitiesLocked(WindowProcessController app, String reason) { - // Tasks is non-null only if two or more tasks are found. - ArraySet<TaskRecord> tasks = app.getReleaseSomeActivitiesTasks(); - if (tasks == null) { - if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Didn't find two or more tasks to release"); - return; - } - // If we have activities in multiple tasks that are in a position to be destroyed, - // let's iterate through the tasks and release the oldest one. - final int numDisplays = mActivityDisplays.size(); - for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { - final ActivityDisplay display = mActivityDisplays.get(displayNdx); - final int stackCount = display.getChildCount(); - // Step through all stacks starting from behind, to hit the oldest things first. - for (int stackNdx = 0; stackNdx < stackCount; stackNdx++) { - final ActivityStack stack = display.getChildAt(stackNdx); - // Try to release activities in this stack; if we manage to, we are done. - if (stack.releaseSomeActivitiesLocked(app, tasks, reason) > 0) { - return; - } - } - } - } - - boolean switchUserLocked(int userId, UserState uss) { - final int focusStackId = getTopDisplayFocusedStack().getStackId(); - // We dismiss the docked stack whenever we switch users. - final ActivityStack dockedStack = getDefaultDisplay().getSplitScreenPrimaryStack(); - if (dockedStack != null) { - moveTasksToFullscreenStackLocked(dockedStack, dockedStack.isFocusedStackOnDisplay()); - } - // Also dismiss the pinned stack whenever we switch users. Removing the pinned stack will - // also cause all tasks to be moved to the fullscreen stack at a position that is - // appropriate. - removeStacksInWindowingModes(WINDOWING_MODE_PINNED); - - mUserStackInFront.put(mCurrentUser, focusStackId); - final int restoreStackId = - mUserStackInFront.get(userId, getDefaultDisplay().getHomeStack().mStackId); - mCurrentUser = userId; - - mStartingUsers.add(uss); - for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { - final ActivityDisplay display = mActivityDisplays.get(displayNdx); - for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = display.getChildAt(stackNdx); - stack.switchUserLocked(userId); - TaskRecord task = stack.topTask(); - if (task != null) { - stack.positionChildWindowContainerAtTop(task); - } - } - } - - ActivityStack stack = getStack(restoreStackId); - if (stack == null) { - stack = getDefaultDisplay().getHomeStack(); - } - final boolean homeInFront = stack.isActivityTypeHome(); - if (stack.isOnHomeDisplay()) { - stack.moveToFront("switchUserOnHomeDisplay"); - } else { - // Stack was moved to another display while user was swapped out. - resumeHomeActivity(null, "switchUserOnOtherDisplay", DEFAULT_DISPLAY); - } - return homeInFront; - } - /** Checks whether the userid is a profile of the current user. */ boolean isCurrentProfileLocked(int userId) { - if (userId == mCurrentUser) return true; + if (userId == mRootActivityContainer.mCurrentUser) return true; return mService.mAmInternal.isCurrentProfile(userId); } @@ -3814,7 +2106,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D boolean remove, boolean processPausingActivities) { ArrayList<ActivityRecord> stops = null; - final boolean nowVisible = allResumedActivitiesVisible(); + final boolean nowVisible = mRootActivityContainer.allResumedActivitiesVisible(); for (int activityNdx = mStoppingActivities.size() - 1; activityNdx >= 0; --activityNdx) { ActivityRecord s = mStoppingActivities.get(activityNdx); boolean waitingVisible = mActivitiesWaitingForVisibleActivity.contains(s); @@ -3864,134 +2156,26 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return stops; } - void validateTopActivitiesLocked() { - for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { - final ActivityDisplay display = mActivityDisplays.get(displayNdx); - for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = display.getChildAt(stackNdx); - final ActivityRecord r = stack.topRunningActivityLocked(); - final ActivityState state = r == null ? DESTROYED : r.getState(); - if (isTopDisplayFocusedStack(stack)) { - if (r == null) Slog.e(TAG, - "validateTop...: null top activity, stack=" + stack); - else { - final ActivityRecord pausing = stack.mPausingActivity; - if (pausing != null && pausing == r) Slog.e(TAG, - "validateTop...: top stack has pausing activity r=" + r - + " state=" + state); - if (state != INITIALIZING && state != RESUMED) Slog.e(TAG, - "validateTop...: activity in front not resumed r=" + r - + " state=" + state); - } - } else { - final ActivityRecord resumed = stack.getResumedActivity(); - if (resumed != null && resumed == r) Slog.e(TAG, - "validateTop...: back stack has resumed activity r=" + r - + " state=" + state); - if (r != null && (state == INITIALIZING || state == RESUMED)) Slog.e(TAG, - "validateTop...: activity in back resumed r=" + r + " state=" + state); - } - } - } - } - - public void dumpDisplays(PrintWriter pw) { - for (int i = mActivityDisplays.size() - 1; i >= 0; --i) { - final ActivityDisplay display = mActivityDisplays.get(i); - pw.print("[id:" + display.mDisplayId + " stacks:"); - display.dumpStacks(pw); - pw.print("]"); - } - } - public void dump(PrintWriter pw, String prefix) { pw.println(); pw.println("ActivityStackSupervisor state:"); - pw.print(prefix); - pw.println("topDisplayFocusedStack=" + getTopDisplayFocusedStack()); + mRootActivityContainer.dump(pw, prefix); pw.print(prefix); pw.println("mCurTaskIdForUser=" + mCurTaskIdForUser); - pw.print(prefix); pw.println("mUserStackInFront=" + mUserStackInFront); - for (int i = mActivityDisplays.size() - 1; i >= 0; --i) { - final ActivityDisplay display = mActivityDisplays.get(i); - display.dump(pw, prefix); - } + pw.println(prefix + "mUserStackInFront=" + mRootActivityContainer.mUserStackInFront); if (!mWaitingForActivityVisible.isEmpty()) { - pw.print(prefix); pw.println("mWaitingForActivityVisible="); + pw.println(prefix + "mWaitingForActivityVisible="); for (int i = 0; i < mWaitingForActivityVisible.size(); ++i) { - pw.print(prefix); pw.print(prefix); mWaitingForActivityVisible.get(i).dump(pw, prefix); + pw.print(prefix + prefix); mWaitingForActivityVisible.get(i).dump(pw, prefix); } } pw.print(prefix); pw.print("isHomeRecentsComponent="); - pw.print(mRecentTasks.isRecentsComponentHomeActivity(mCurrentUser)); + pw.print(mRecentTasks.isRecentsComponentHomeActivity(mRootActivityContainer.mCurrentUser)); getKeyguardController().dump(pw, prefix); mService.getLockTaskController().dump(pw, prefix); } - public void writeToProto(ProtoOutputStream proto, long fieldId) { - final long token = proto.start(fieldId); - super.writeToProto(proto, CONFIGURATION_CONTAINER, false /* trim */); - for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) { - final ActivityDisplay activityDisplay = mActivityDisplays.get(displayNdx); - activityDisplay.writeToProto(proto, DISPLAYS); - } - getKeyguardController().writeToProto(proto, KEYGUARD_CONTROLLER); - // TODO(b/111541062): Update tests to look for resumed activities on all displays - final ActivityStack focusedStack = getTopDisplayFocusedStack(); - 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); - } - proto.write(IS_HOME_RECENTS_COMPONENT, - mRecentTasks.isRecentsComponentHomeActivity(mCurrentUser)); - mService.getActivityStartController().writeToProto(proto, PENDING_ACTIVITIES); - proto.end(token); - } - - /** - * Dump all connected displays' configurations. - * @param prefix Prefix to apply to each line of the dump. - */ - void dumpDisplayConfigs(PrintWriter pw, String prefix) { - pw.print(prefix); pw.println("Display override configurations:"); - final int displayCount = mActivityDisplays.size(); - for (int i = 0; i < displayCount; i++) { - final ActivityDisplay activityDisplay = mActivityDisplays.get(i); - pw.print(prefix); pw.print(" "); pw.print(activityDisplay.mDisplayId); pw.print(": "); - pw.println(activityDisplay.getOverrideConfiguration()); - } - } - - /** - * Dumps the activities matching the given {@param name} in the either the focused stack - * or all visible stacks if {@param dumpVisibleStacks} is true. - */ - ArrayList<ActivityRecord> getDumpActivitiesLocked(String name, boolean dumpVisibleStacksOnly, - boolean dumpFocusedStackOnly) { - if (dumpFocusedStackOnly) { - return getTopDisplayFocusedStack().getDumpActivitiesLocked(name); - } else { - ArrayList<ActivityRecord> activities = new ArrayList<>(); - int numDisplays = mActivityDisplays.size(); - for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { - final ActivityDisplay display = mActivityDisplays.get(displayNdx); - for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = display.getChildAt(stackNdx); - if (!dumpVisibleStacksOnly || stack.shouldBeVisible(null)) { - activities.addAll(stack.getDumpActivitiesLocked(name)); - } - } - } - return activities; - } - } - static boolean printThisActivity(PrintWriter pw, ActivityRecord activity, String dumpPackage, boolean needSep, String prefix) { if (activity != null) { @@ -4007,73 +2191,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return false; } - boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll, - boolean dumpClient, String dumpPackage) { - boolean printed = false; - boolean needSep = false; - for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { - ActivityDisplay activityDisplay = mActivityDisplays.get(displayNdx); - pw.print("Display #"); pw.print(activityDisplay.mDisplayId); - pw.println(" (activities from top to bottom):"); - final ActivityDisplay display = mActivityDisplays.get(displayNdx); - for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = display.getChildAt(stackNdx); - pw.println(); - pw.println(" Stack #" + stack.mStackId - + ": type=" + activityTypeToString(stack.getActivityType()) - + " mode=" + windowingModeToString(stack.getWindowingMode())); - pw.println(" isSleeping=" + stack.shouldSleepActivities()); - pw.println(" mBounds=" + stack.getOverrideBounds()); - - printed |= stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage, - needSep); - - printed |= dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false, - !dumpAll, false, dumpPackage, true, - " Running activities (most recent first):", null); - - needSep = printed; - boolean pr = printThisActivity(pw, stack.mPausingActivity, dumpPackage, needSep, - " mPausingActivity: "); - if (pr) { - printed = true; - needSep = false; - } - pr = printThisActivity(pw, stack.getResumedActivity(), dumpPackage, needSep, - " mResumedActivity: "); - if (pr) { - printed = true; - needSep = false; - } - if (dumpAll) { - pr = printThisActivity(pw, stack.mLastPausedActivity, dumpPackage, needSep, - " mLastPausedActivity: "); - if (pr) { - printed = true; - needSep = true; - } - printed |= printThisActivity(pw, stack.mLastNoHistoryActivity, dumpPackage, - needSep, " mLastNoHistoryActivity: "); - } - needSep = printed; - } - printThisActivity(pw, activityDisplay.getResumedActivity(), dumpPackage, needSep, - " ResumedActivity:"); - } - - printed |= dumpHistoryList(fd, pw, mFinishingActivities, " ", "Fin", false, !dumpAll, - false, dumpPackage, true, " Activities waiting to finish:", null); - printed |= dumpHistoryList(fd, pw, mStoppingActivities, " ", "Stop", false, !dumpAll, - false, dumpPackage, true, " Activities waiting to stop:", null); - printed |= dumpHistoryList(fd, pw, mActivitiesWaitingForVisibleActivity, " ", "Wait", - false, !dumpAll, false, dumpPackage, true, - " Activities waiting for another to become visible:", null); - printed |= dumpHistoryList(fd, pw, mGoingToSleepActivities, " ", "Sleep", false, !dumpAll, - false, dumpPackage, true, " Activities waiting to sleep:", null); - - return printed; - } - static boolean dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list, String prefix, String label, boolean complete, boolean brief, boolean client, String dumpPackage, boolean needNL, String header, TaskRecord lastTask) { @@ -4183,294 +2300,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D mHandler.sendEmptyMessageDelayed(SLEEP_TIMEOUT_MSG, SLEEP_TIMEOUT); } - @Override - public void onDisplayAdded(int displayId) { - if (DEBUG_STACK) Slog.v(TAG, "Display added displayId=" + displayId); - synchronized (mService.mGlobalLock) { - getActivityDisplayOrCreateLocked(displayId); - // Do not start home before booting, or it may accidentally finish booting before it - // starts. Instead, we expect home activities to be launched when the system is ready - // (ActivityManagerService#systemReady). - if (mService.isBooted() || mService.isBooting()) { - startHomeOnDisplay(mCurrentUser, "displayAdded", displayId); - } - } - } - - @Override - public void onDisplayRemoved(int displayId) { - if (DEBUG_STACK) Slog.v(TAG, "Display removed displayId=" + displayId); - if (displayId == DEFAULT_DISPLAY) { - throw new IllegalArgumentException("Can't remove the primary display."); - } - - synchronized (mService.mGlobalLock) { - final ActivityDisplay activityDisplay = getActivityDisplay(displayId); - if (activityDisplay == null) { - return; - } - - activityDisplay.remove(); - } - } - - @Override - public void onDisplayChanged(int displayId) { - if (DEBUG_STACK) Slog.v(TAG, "Display changed displayId=" + displayId); - synchronized (mService.mGlobalLock) { - final ActivityDisplay activityDisplay = getActivityDisplay(displayId); - if (activityDisplay != null) { - activityDisplay.onDisplayChanged(); - } - } - } - - /** Check if display with specified id is added to the list. */ - boolean isDisplayAdded(int displayId) { - return getActivityDisplayOrCreateLocked(displayId) != null; - } - - // TODO: Look into consolidating with getActivityDisplayOrCreateLocked() - ActivityDisplay getActivityDisplay(int displayId) { - for (int i = mActivityDisplays.size() - 1; i >= 0; --i) { - final ActivityDisplay activityDisplay = mActivityDisplays.get(i); - if (activityDisplay.mDisplayId == displayId) { - return activityDisplay; - } - } - return null; - } - - // TODO(multi-display): Look at all callpoints to make sure they make sense in multi-display. - ActivityDisplay getDefaultDisplay() { - return mDefaultDisplay; - } - - /** - * Get an existing instance of {@link ActivityDisplay} or create new if there is a - * corresponding record in display manager. - */ - // TODO: Look into consolidating with getActivityDisplay() - ActivityDisplay getActivityDisplayOrCreateLocked(int displayId) { - ActivityDisplay activityDisplay = getActivityDisplay(displayId); - if (activityDisplay != null) { - return activityDisplay; - } - if (mDisplayManager == null) { - // The system isn't fully initialized yet. - return null; - } - final Display display = mDisplayManager.getDisplay(displayId); - if (display == null) { - // The display is not registered in DisplayManager. - return null; - } - // The display hasn't been added to ActivityManager yet, create a new record now. - activityDisplay = new ActivityDisplay(this, display); - addChild(activityDisplay, ActivityDisplay.POSITION_BOTTOM); - return activityDisplay; - } - - /** - * Get an existing instance of {@link ActivityDisplay} that has the given uniqueId. Unique ID is - * defined in {@link DisplayInfo#uniqueId}. - * - * @param uniqueId the unique ID of the display - * @return the {@link ActivityDisplay} or {@code null} if nothing is found. - */ - ActivityDisplay getActivityDisplay(String uniqueId) { - for (int i = mActivityDisplays.size() - 1; i >= 0; --i) { - final ActivityDisplay display = mActivityDisplays.get(i); - final boolean isValid = display.mDisplay.isValid(); - if (isValid && display.mDisplay.getUniqueId().equals(uniqueId)) { - return display; - } - } - - return null; - } - - boolean startHomeOnAllDisplays(int userId, String reason) { - boolean homeStarted = false; - for (int i = mActivityDisplays.size() - 1; i >= 0; i--) { - final int displayId = mActivityDisplays.get(i).mDisplayId; - homeStarted |= startHomeOnDisplay(userId, reason, displayId); - } - return homeStarted; - } - - /** - * This starts home activity on displays that can have system decorations and only if the - * home activity can have multiple instances. - */ - boolean startHomeOnDisplay(int userId, String reason, int displayId) { - final Intent homeIntent = mService.getHomeIntent(); - final ActivityInfo aInfo = resolveHomeActivity(userId, homeIntent); - if (aInfo == null) { - return false; - } - - if (!canStartHomeOnDisplay(aInfo, displayId, false /* allowInstrumenting */)) { - return false; - } - - // Update the reason for ANR debugging to verify if the user activity is the one that - // actually launched. - final String myReason = reason + ":" + userId + ":" + UserHandle.getUserId( - aInfo.applicationInfo.uid); - mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason, - displayId); - return true; - } - - /** - * This resolves the home activity info and updates the home component of the given intent. - * @return the home activity info if any. - */ - private ActivityInfo resolveHomeActivity(int userId, Intent homeIntent) { - final int flags = ActivityManagerService.STOCK_PM_FLAGS; - final ComponentName comp = homeIntent.getComponent(); - ActivityInfo aInfo = null; - try { - if (comp != null) { - // Factory test. - aInfo = AppGlobals.getPackageManager().getActivityInfo(comp, flags, userId); - } else { - final String resolvedType = - homeIntent.resolveTypeIfNeeded(mService.mContext.getContentResolver()); - final ResolveInfo info = AppGlobals.getPackageManager() - .resolveIntent(homeIntent, resolvedType, flags, userId); - if (info != null) { - aInfo = info.activityInfo; - } - } - } catch (RemoteException e) { - // ignore - } - - if (aInfo == null) { - Slog.wtf(TAG, "No home screen found for " + homeIntent, new Throwable()); - return null; - } - - homeIntent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name)); - aInfo = new ActivityInfo(aInfo); - aInfo.applicationInfo = mService.getAppInfoForUser(aInfo.applicationInfo, userId); - homeIntent.setFlags(homeIntent.getFlags() | FLAG_ACTIVITY_NEW_TASK); - return aInfo; - } - - @VisibleForTesting - void addChild(ActivityDisplay activityDisplay, int position) { - positionChildAt(activityDisplay, position); - mWindowContainerController.positionChildAt( - activityDisplay.getWindowContainerController(), position); - } - - void removeChild(ActivityDisplay activityDisplay) { - // The caller must tell the controller of {@link ActivityDisplay} to release its container - // {@link DisplayContent}. That is done in {@link ActivityDisplay#releaseSelfIfNeeded}). - mActivityDisplays.remove(activityDisplay); - } - - private void calculateDefaultMinimalSizeOfResizeableTasks() { - final Resources res = mService.mContext.getResources(); - final float minimalSize = res.getDimension( - com.android.internal.R.dimen.default_minimal_size_resizable_task); - final DisplayMetrics dm = res.getDisplayMetrics(); - - mDefaultMinSizeOfResizeableTaskDp = (int) (minimalSize / dm.density); - } - - SleepToken createSleepTokenLocked(String tag, int displayId) { - final ActivityDisplay display = getActivityDisplay(displayId); - if (display == null) { - throw new IllegalArgumentException("Invalid display: " + displayId); - } - - final SleepTokenImpl token = new SleepTokenImpl(tag, displayId); - mSleepTokens.add(token); - display.mAllSleepTokens.add(token); - return token; - } - - private void removeSleepTokenLocked(SleepTokenImpl token) { - mSleepTokens.remove(token); - - final ActivityDisplay display = getActivityDisplay(token.mDisplayId); - if (display != null) { - display.mAllSleepTokens.remove(token); - if (display.mAllSleepTokens.isEmpty()) { - mService.updateSleepIfNeededLocked(); - } - } - } - - private StackInfo getStackInfo(ActivityStack stack) { - final int displayId = stack.mDisplayId; - final ActivityDisplay display = getActivityDisplay(displayId); - StackInfo info = new StackInfo(); - stack.getWindowContainerBounds(info.bounds); - info.displayId = displayId; - info.stackId = stack.mStackId; - info.userId = stack.mCurrentUser; - info.visible = stack.shouldBeVisible(null); - // A stack might be not attached to a display. - info.position = display != null ? display.getIndexOf(stack) : 0; - info.configuration.setTo(stack.getConfiguration()); - - ArrayList<TaskRecord> tasks = stack.getAllTasks(); - final int numTasks = tasks.size(); - int[] taskIds = new int[numTasks]; - String[] taskNames = new String[numTasks]; - Rect[] taskBounds = new Rect[numTasks]; - int[] taskUserIds = new int[numTasks]; - for (int i = 0; i < numTasks; ++i) { - final TaskRecord task = tasks.get(i); - taskIds[i] = task.taskId; - taskNames[i] = task.origActivity != null ? task.origActivity.flattenToString() - : task.realActivity != null ? task.realActivity.flattenToString() - : task.getTopActivity() != null ? task.getTopActivity().packageName - : "unknown"; - taskBounds[i] = new Rect(); - task.getWindowContainerBounds(taskBounds[i]); - taskUserIds[i] = task.userId; - } - info.taskIds = taskIds; - info.taskNames = taskNames; - info.taskBounds = taskBounds; - info.taskUserIds = taskUserIds; - - final ActivityRecord top = stack.topRunningActivityLocked(); - info.topActivity = top != null ? top.intent.getComponent() : null; - return info; - } - - StackInfo getStackInfo(int stackId) { - ActivityStack stack = getStack(stackId); - if (stack != null) { - return getStackInfo(stack); - } - return null; - } - - StackInfo getStackInfo(int windowingMode, int activityType) { - final ActivityStack stack = getStack(windowingMode, activityType); - return (stack != null) ? getStackInfo(stack) : null; - } - - ArrayList<StackInfo> getAllStackInfosLocked() { - ArrayList<StackInfo> list = new ArrayList<>(); - for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) { - final ActivityDisplay display = mActivityDisplays.get(displayNdx); - for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = display.getChildAt(stackNdx); - list.add(getStackInfo(stack)); - } - } - return list; - } - void handleNonResizableTaskIfNeeded(TaskRecord task, int preferredWindowingMode, int preferredDisplayId, ActivityStack actualStack) { handleNonResizableTaskIfNeeded(task, preferredWindowingMode, preferredDisplayId, @@ -4616,21 +2445,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } } - void setDockedStackMinimized(boolean minimized) { - // Get currently focused stack before setting mIsDockMinimized. We do this because if - // split-screen is active, primary stack will not be focusable (see #isFocusable) while - // still occluding other stacks. This will cause getTopDisplayFocusedStack() to return null. - final ActivityStack current = getTopDisplayFocusedStack(); - mIsDockMinimized = minimized; - if (mIsDockMinimized) { - if (current.inSplitScreenPrimaryWindowingMode()) { - // The primary split-screen stack can't be focused while it is minimize, so move - // focus to something else. - current.adjustFocusToNextFocusableStack("setDockedStackMinimized"); - } - } - } - void wakeUp(String reason) { mPowerManager.wakeUp(SystemClock.uptimeMillis(), "android.server.am:TURN_ON:" + reason); } @@ -4649,10 +2463,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D mDeferResumeCount--; } - /** - * @return True if resume can be called. - */ - private boolean readyToResume() { + /** @return True if resume can be called. */ + boolean readyToResume() { return mDeferResumeCount == 0; } @@ -4704,7 +2516,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } break; case RESUME_TOP_ACTIVITY_MSG: { synchronized (mService.mGlobalLock) { - resumeFocusedStacksTopActivitiesLocked(); + mRootActivityContainer.resumeFocusedStacksTopActivities(); } } break; case SLEEP_TIMEOUT_MSG: { @@ -4740,19 +2552,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } } - ActivityStack findStackBehind(ActivityStack stack) { - final ActivityDisplay display = getActivityDisplay(stack.mDisplayId); - if (display != null) { - for (int i = display.getChildCount() - 1; i >= 0; i--) { - if (display.getChildAt(i) == stack && i > 0) { - return display.getChildAt(i - 1); - } - } - } - throw new IllegalStateException("Failed to find a stack behind stack=" + stack - + " in=" + display); - } - /** * Puts a task into resizing mode during the next app transition. * @@ -4797,8 +2596,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D mWindowManager.prepareAppTransition(TRANSIT_DOCK_TASK_FROM_RECENTS, false); } - task = anyTaskForIdLocked(taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, - activityOptions, ON_TOP); + task = mRootActivityContainer.anyTaskForId(taskId, + MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, activityOptions, ON_TOP); if (task == null) { continueUpdateRecentsHomeStackBounds(); mWindowManager.executeAppTransition(); @@ -4811,7 +2610,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D // from whatever is started from the recents activity, so move the home stack // forward. // TODO (b/115289124): Multi-display supports for recents. - getDefaultDisplay().moveHomeStackToFront("startActivityFromRecents"); + mRootActivityContainer.getDefaultDisplay().moveHomeStackToFront( + "startActivityFromRecents"); } // If the user must confirm credentials (e.g. when first launching a work app and the @@ -4820,7 +2620,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D && task.getRootActivity() != null) { final ActivityRecord targetActivity = task.getTopActivity(); - sendPowerHintForLaunchStartIfNeeded(true /* forceSend */, targetActivity); + mRootActivityContainer.sendPowerHintForLaunchStartIfNeeded( + true /* forceSend */, targetActivity); mActivityMetricsLogger.notifyActivityLaunching(task.intent); try { mService.moveTaskToFrontLocked(task.taskId, 0, options, @@ -4873,35 +2674,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } /** - * @return a list of activities which are the top ones in each visible stack. The first - * entry will be the focused activity. - */ - List<IBinder> getTopVisibleActivities() { - final ArrayList<IBinder> topActivityTokens = new ArrayList<>(); - final ActivityStack topFocusedStack = getTopDisplayFocusedStack(); - // Traverse all displays. - for (int i = mActivityDisplays.size() - 1; i >= 0; i--) { - final ActivityDisplay display = mActivityDisplays.get(i); - // Traverse all stacks on a display. - for (int j = display.getChildCount() - 1; j >= 0; --j) { - final ActivityStack stack = display.getChildAt(j); - // Get top activity from a visible stack and add it to the list. - if (stack.shouldBeVisible(null /* starting */)) { - final ActivityRecord top = stack.getTopActivity(); - if (top != null) { - if (stack == topFocusedStack) { - topActivityTokens.add(0, top.appToken); - } else { - topActivityTokens.add(top.appToken); - } - } - } - } - } - return topActivityTokens; - } - - /** * Internal container to store a match qualifier alongside a WaitResult. */ static class WaitInfo { @@ -4939,30 +2711,4 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D mResult.dump(pw, prefix); } } - - private final class SleepTokenImpl extends SleepToken { - private final String mTag; - private final long mAcquireTime; - private final int mDisplayId; - - public SleepTokenImpl(String tag, int displayId) { - mTag = tag; - mDisplayId = displayId; - mAcquireTime = SystemClock.uptimeMillis(); - } - - @Override - public void release() { - synchronized (mService.mGlobalLock) { - removeSleepTokenLocked(this); - } - } - - @Override - public String toString() { - return "{\"" + mTag + "\", display " + mDisplayId - + ", acquire at " + TimeUtils.formatUptime(mAcquireTime) + "}"; - } - } - } diff --git a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java index ee5a43ce0edb..54a63a168588 100644 --- a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java +++ b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java @@ -70,6 +70,7 @@ class ActivityStartInterceptor { private final ActivityTaskManagerService mService; private final ActivityStackSupervisor mSupervisor; + private final RootActivityContainer mRootActivityContainer; private final Context mServiceContext; // UserManager cannot be final as it's not ready when this class is instantiated during boot @@ -102,14 +103,15 @@ class ActivityStartInterceptor { ActivityStartInterceptor( ActivityTaskManagerService service, ActivityStackSupervisor supervisor) { - this(service, supervisor, service.mContext); + this(service, supervisor, service.mRootActivityContainer, service.mContext); } @VisibleForTesting ActivityStartInterceptor(ActivityTaskManagerService service, ActivityStackSupervisor supervisor, - Context context) { + RootActivityContainer root, Context context) { mService = service; mSupervisor = supervisor; + mRootActivityContainer = root; mServiceContext = context; } @@ -279,7 +281,7 @@ class ActivityStartInterceptor { mActivityOptions = ActivityOptions.makeBasic(); } - ActivityRecord homeActivityRecord = mSupervisor.getDefaultDisplayHomeActivity(); + ActivityRecord homeActivityRecord = mRootActivityContainer.getDefaultDisplayHomeActivity(); if (homeActivityRecord != null && homeActivityRecord.getTask() != null) { // Showing credential confirmation activity in home task to avoid stopping multi-windowed // mode after showing the full-screen credential confirmation activity. diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index 90f3ff84a027..d22623eeb14d 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -137,6 +137,7 @@ class ActivityStarter { private static final int INVALID_LAUNCH_MODE = -1; private final ActivityTaskManagerService mService; + private final RootActivityContainer mRootActivityContainer; private final ActivityStackSupervisor mSupervisor; private final ActivityStartInterceptor mInterceptor; private final ActivityStartController mController; @@ -421,6 +422,7 @@ class ActivityStarter { ActivityStackSupervisor supervisor, ActivityStartInterceptor interceptor) { mController = controller; mService = service; + mRootActivityContainer = service.mRootActivityContainer; mSupervisor = supervisor; mInterceptor = interceptor; reset(true); @@ -617,7 +619,7 @@ class ActivityStarter { ActivityRecord sourceRecord = null; ActivityRecord resultRecord = null; if (resultTo != null) { - sourceRecord = mSupervisor.isInAnyStackLocked(resultTo); + sourceRecord = mRootActivityContainer.isInAnyStack(resultTo); if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, "Will send result to " + resultTo + " " + sourceRecord); if (sourceRecord != null) { @@ -811,7 +813,8 @@ class ActivityStarter { null /*profilerInfo*/); if (DEBUG_PERMISSIONS_REVIEW) { - final ActivityStack focusedStack = mSupervisor.getTopDisplayFocusedStack(); + final ActivityStack focusedStack = + mRootActivityContainer.getTopDisplayFocusedStack(); Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false) + "} from uid " + callingUid + " on display " + (focusedStack == null ? DEFAULT_DISPLAY : focusedStack.mDisplayId)); @@ -847,7 +850,7 @@ class ActivityStarter { r.appTimeTracker = sourceRecord.appTimeTracker; } - final ActivityStack stack = mSupervisor.getTopDisplayFocusedStack(); + final ActivityStack stack = mRootActivityContainer.getTopDisplayFocusedStack(); // If we are starting an activity that is not from the same uid as the currently resumed // one, check whether app switches are allowed. @@ -1063,7 +1066,7 @@ class ActivityStarter { ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo); synchronized (mService.mGlobalLock) { - final ActivityStack stack = mSupervisor.getTopDisplayFocusedStack(); + final ActivityStack stack = mRootActivityContainer.getTopDisplayFocusedStack(); stack.mConfigWillChange = globalConfig != null && mService.getGlobalConfiguration().diff(globalConfig) != 0; if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, @@ -1249,7 +1252,8 @@ class ActivityStarter { final ActivityRecord currentTop = startedActivityStack.topRunningActivityLocked(); if (currentTop != null && currentTop.shouldUpdateConfigForDisplayChanged()) { - mSupervisor.ensureVisibilityAndConfig(currentTop, currentTop.getDisplayId(), + mRootActivityContainer.ensureVisibilityAndConfig( + currentTop, currentTop.getDisplayId(), true /* markFrozenIfConfigChanged */, false /* deferResume */); } } @@ -1284,7 +1288,7 @@ class ActivityStarter { // Do not start home activity if it cannot be launched on preferred display. We are not // doing this in ActivityStackSupervisor#canPlaceEntityOnDisplay because it might // fallback to launch on other displays. - if (r.isActivityTypeHome() && !mSupervisor.canStartHomeOnDisplay(r.info, + if (r.isActivityTypeHome() && !mRootActivityContainer.canStartHomeOnDisplay(r.info, mPreferredDisplayId, true /* allowInstrumenting */)) { Slog.w(TAG, "Cannot launch home on display " + mPreferredDisplayId); return START_CANCELED; @@ -1361,7 +1365,8 @@ class ActivityStarter { } } - mSupervisor.sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, reusedActivity); + mRootActivityContainer.sendPowerHintForLaunchStartIfNeeded + (false /* forceSend */, reusedActivity); reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity); @@ -1413,7 +1418,7 @@ class ActivityStarter { // If the activity being launched is the same as the one currently at the top, then // we need to check if it should only be launched once. - final ActivityStack topStack = mSupervisor.getTopDisplayFocusedStack(); + final ActivityStack topStack = mRootActivityContainer.getTopDisplayFocusedStack(); final ActivityRecord topFocused = topStack.getTopActivity(); final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop); final boolean dontStart = top != null && mStartActivity.resultTo == null @@ -1430,7 +1435,7 @@ class ActivityStarter { // For paranoia, make sure we have correctly resumed the top activity. topStack.mLastPausedActivity = null; if (mDoResume) { - mSupervisor.resumeFocusedStacksTopActivitiesLocked(); + mRootActivityContainer.resumeFocusedStacksTopActivities(); } ActivityOptions.abort(mOptions); if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) { @@ -1485,7 +1490,8 @@ class ActivityStarter { EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTask()); mTargetStack.mLastPausedActivity = null; - mSupervisor.sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, mStartActivity); + mRootActivityContainer.sendPowerHintForLaunchStartIfNeeded( + false /* forceSend */, mStartActivity); mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition, mOptions); @@ -1512,16 +1518,16 @@ class ActivityStarter { // task stack to be focusable, then ensure that we now update the focused stack // accordingly. if (mTargetStack.isFocusable() - && !mSupervisor.isTopDisplayFocusedStack(mTargetStack)) { + && !mRootActivityContainer.isTopDisplayFocusedStack(mTargetStack)) { mTargetStack.moveToFront("startActivityUnchecked"); } - mSupervisor.resumeFocusedStacksTopActivitiesLocked(mTargetStack, mStartActivity, - mOptions); + mRootActivityContainer.resumeFocusedStacksTopActivities( + mTargetStack, mStartActivity, mOptions); } } else if (mStartActivity != null) { mSupervisor.mRecentTasks.add(mStartActivity.getTask()); } - mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack); + mRootActivityContainer.updateUserStack(mStartActivity.userId, mTargetStack); mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredWindowingMode, mPreferredDisplayId, mTargetStack); @@ -1642,7 +1648,7 @@ class ActivityStarter { if (mOptions.getLaunchTaskId() != -1 && mOptions.getTaskOverlay()) { r.mTaskOverlay = true; if (!mOptions.canTaskOverlayResume()) { - final TaskRecord task = mSupervisor.anyTaskForIdLocked( + final TaskRecord task = mRootActivityContainer.anyTaskForId( mOptions.getLaunchTaskId()); final ActivityRecord top = task != null ? task.getTopActivity() : null; if (top != null && !top.isState(RESUMED)) { @@ -1678,7 +1684,7 @@ class ActivityStarter { if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) { ActivityRecord checkedCaller = sourceRecord; if (checkedCaller == null) { - checkedCaller = mSupervisor.getTopDisplayFocusedStack() + checkedCaller = mRootActivityContainer.getTopDisplayFocusedStack() .topRunningNonDelayedActivityLocked(mNotTop); } if (!checkedCaller.realActivity.equals(r.realActivity)) { @@ -1840,22 +1846,23 @@ class ActivityStarter { putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null; ActivityRecord intentActivity = null; if (mOptions != null && mOptions.getLaunchTaskId() != -1) { - final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId()); + final TaskRecord task = mRootActivityContainer.anyTaskForId(mOptions.getLaunchTaskId()); intentActivity = task != null ? task.getTopActivity() : null; } else if (putIntoExistingTask) { if (LAUNCH_SINGLE_INSTANCE == mLaunchMode) { // There can be one and only one instance of single instance activity in the // history, and it is always in its own unique task, so we do a special search. - intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info, + intentActivity = mRootActivityContainer.findActivity(mIntent, mStartActivity.info, mStartActivity.isActivityTypeHome()); } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) { // For the launch adjacent case we only want to put the activity in an existing // task if the activity already exists in the history. - intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info, + intentActivity = mRootActivityContainer.findActivity(mIntent, mStartActivity.info, !(LAUNCH_SINGLE_TASK == mLaunchMode)); } else { // Otherwise find the best task to put the activity in. - intentActivity = mSupervisor.findTaskLocked(mStartActivity, mPreferredDisplayId); + intentActivity = + mRootActivityContainer.findTask(mStartActivity, mPreferredDisplayId); } } @@ -2067,11 +2074,11 @@ class ActivityStarter { private void resumeTargetStackIfNeeded() { if (mDoResume) { - mSupervisor.resumeFocusedStacksTopActivitiesLocked(mTargetStack, null, mOptions); + mRootActivityContainer.resumeFocusedStacksTopActivities(mTargetStack, null, mOptions); } else { ActivityOptions.abort(mOptions); } - mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack); + mRootActivityContainer.updateUserStack(mStartActivity.userId, mTargetStack); } private int setTaskFromReuseOrCreateNewTask(TaskRecord taskToAffiliate) { @@ -2145,13 +2152,13 @@ class ActivityStarter { // be not suitable. Let's check other displays. if (mTargetStack == null && targetDisplayId != sourceStack.mDisplayId) { // Can't use target display, lets find a stack on the source display. - mTargetStack = mSupervisor.getValidLaunchStackOnDisplay( + mTargetStack = mRootActivityContainer.getValidLaunchStackOnDisplay( sourceStack.mDisplayId, mStartActivity, mOptions, mLaunchParams); } if (mTargetStack == null) { // There are no suitable stacks on the target and source display(s). Look on all // displays. - mTargetStack = mSupervisor.getNextValidLaunchStackLocked( + mTargetStack = mRootActivityContainer.getNextValidLaunchStack( mStartActivity, -1 /* currentFocus */); } } @@ -2182,7 +2189,7 @@ class ActivityStarter { // For paranoia, make sure we have correctly resumed the top activity. mTargetStack.mLastPausedActivity = null; if (mDoResume) { - mSupervisor.resumeFocusedStacksTopActivitiesLocked(); + mRootActivityContainer.resumeFocusedStacksTopActivities(); } ActivityOptions.abort(mOptions); return START_DELIVERED_TO_TOP; @@ -2200,7 +2207,7 @@ class ActivityStarter { deliverNewIntent(top); mTargetStack.mLastPausedActivity = null; if (mDoResume) { - mSupervisor.resumeFocusedStacksTopActivitiesLocked(); + mRootActivityContainer.resumeFocusedStacksTopActivities(); } return START_DELIVERED_TO_TOP; } @@ -2254,7 +2261,8 @@ class ActivityStarter { if (!mLaunchParams.mBounds.isEmpty()) { // TODO: Shouldn't we already know what stack to use by the time we get here? - ActivityStack stack = mSupervisor.getLaunchStack(null, null, mInTask, ON_TOP); + ActivityStack stack = mRootActivityContainer.getLaunchStack( + null, null, mInTask, ON_TOP); if (stack != mInTask.getStack()) { mInTask.reparent(stack, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, !ANIMATE, DEFER_RESUME, "inTaskToFront"); @@ -2348,7 +2356,7 @@ class ActivityStarter { } final ActivityStack currentStack = task != null ? task.getStack() : null; - final ActivityStack focusedStack = mSupervisor.getTopDisplayFocusedStack(); + final ActivityStack focusedStack = mRootActivityContainer.getTopDisplayFocusedStack(); if (currentStack != null) { if (focusedStack != currentStack) { if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, @@ -2369,18 +2377,18 @@ class ActivityStarter { if (mPreferredDisplayId != DEFAULT_DISPLAY) { // Try to put the activity in a stack on a secondary display. - stack = mSupervisor.getValidLaunchStackOnDisplay(mPreferredDisplayId, r, aOptions, - mLaunchParams); + stack = mRootActivityContainer.getValidLaunchStackOnDisplay( + mPreferredDisplayId, r, aOptions, mLaunchParams); if (stack == null) { // If source display is not suitable - look for topmost valid stack in the system. if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: Can't launch on mPreferredDisplayId=" + mPreferredDisplayId + ", looking on all displays."); - stack = mSupervisor.getNextValidLaunchStackLocked(r, mPreferredDisplayId); + stack = mRootActivityContainer.getNextValidLaunchStack(r, mPreferredDisplayId); } } if (stack == null) { - stack = mSupervisor.getLaunchStack(r, aOptions, task, ON_TOP); + stack = mRootActivityContainer.getLaunchStack(r, aOptions, task, ON_TOP); } if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r=" + r + " stackId=" + stack.mStackId); @@ -2390,7 +2398,7 @@ class ActivityStarter { /** Check if provided activity record can launch in currently focused stack. */ // TODO: This method can probably be consolidated into getLaunchStack() below. private boolean canLaunchIntoFocusedStack(ActivityRecord r, boolean newTask) { - final ActivityStack focusedStack = mSupervisor.getTopDisplayFocusedStack(); + final ActivityStack focusedStack = mRootActivityContainer.getTopDisplayFocusedStack(); final boolean canUseFocusedStack; if (focusedStack.isActivityTypeAssistant()) { canUseFocusedStack = r.isActivityTypeAssistant(); @@ -2436,14 +2444,14 @@ class ActivityStarter { // full resolution. mLaunchParams.mPreferredDisplayId = mPreferredDisplayId != DEFAULT_DISPLAY ? mPreferredDisplayId : INVALID_DISPLAY; - final ActivityStack stack = mSupervisor.getLaunchStack(r, aOptions, task, ON_TOP, - mLaunchParams); + final ActivityStack stack = + mRootActivityContainer.getLaunchStack(r, aOptions, task, ON_TOP, mLaunchParams); mLaunchParams.mPreferredDisplayId = mPreferredDisplayId; return stack; } // Otherwise handle adjacent launch. - final ActivityStack focusedStack = mSupervisor.getTopDisplayFocusedStack(); + final ActivityStack focusedStack = mRootActivityContainer.getTopDisplayFocusedStack(); // The parent activity doesn't want to launch the activity on top of itself, but // instead tries to put it onto other side in side-by-side mode. final ActivityStack parentStack = task != null ? task.getStack(): focusedStack; @@ -2461,7 +2469,8 @@ class ActivityStarter { if (parentStack != null && parentStack.inSplitScreenPrimaryWindowingMode()) { // If parent was in docked stack, the natural place to launch another activity // will be fullscreen, so it can appear alongside the docked window. - final int activityType = mSupervisor.resolveActivityType(r, mOptions, task); + final int activityType = + mRootActivityContainer.resolveActivityType(r, mOptions, task); return parentStack.getDisplay().getOrCreateStack( WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, activityType, ON_TOP); } else { @@ -2469,10 +2478,10 @@ class ActivityStarter { // and if yes, we will launch into that stack. If not, we just put the new // activity into parent's stack, because we can't find a better place. final ActivityStack dockedStack = - mSupervisor.getDefaultDisplay().getSplitScreenPrimaryStack(); + mRootActivityContainer.getDefaultDisplay().getSplitScreenPrimaryStack(); if (dockedStack != null && !dockedStack.shouldBeVisible(r)) { // There is a docked stack, but it isn't visible, so we can't launch into that. - return mSupervisor.getLaunchStack(r, aOptions, task, ON_TOP); + return mRootActivityContainer.getLaunchStack(r, aOptions, task, ON_TOP); } else { return dockedStack; } @@ -2660,7 +2669,7 @@ class ActivityStarter { prefix = prefix + " "; pw.print(prefix); pw.print("mCurrentUser="); - pw.println(mSupervisor.mCurrentUser); + pw.println(mRootActivityContainer.mCurrentUser); pw.print(prefix); pw.print("mLastStartReason="); pw.println(mLastStartReason); diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index d0e3fb47730e..d480fb732df3 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -91,8 +91,6 @@ import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.Scr .PACKAGE; import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING; import static com.android.server.wm.ActivityStackSupervisor.DEFER_RESUME; -import static com.android.server.wm.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_ONLY; -import static com.android.server.wm.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS; import static com.android.server.wm.ActivityStackSupervisor.ON_TOP; import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS; import static com.android.server.wm.ActivityStackSupervisor.REMOVE_FROM_RECENTS; @@ -122,6 +120,8 @@ import static com.android.server.wm.ActivityTaskManagerService.H.REPORT_TIME_TRA import static com.android.server.wm.ActivityTaskManagerService.UiHandler.DISMISS_DIALOG_UI_MSG; import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE; import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_ORIGINAL_POSITION; +import static com.android.server.wm.RootActivityContainer.MATCH_TASK_IN_STACKS_ONLY; +import static com.android.server.wm.RootActivityContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS; import static com.android.server.wm.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK; import static com.android.server.wm.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT; import static com.android.server.wm.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE; @@ -352,6 +352,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { /* Global service lock used by the package the owns this service. */ final WindowManagerGlobalLock mGlobalLock = new WindowManagerGlobalLock(); ActivityStackSupervisor mStackSupervisor; + RootActivityContainer mRootActivityContainer; WindowManagerService mWindowManager; private UserManagerService mUserManager; private AppOpsService mAppOpsService; @@ -766,7 +767,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { mTempConfig.setLocales(LocaleList.getDefault()); mConfigurationSeq = mTempConfig.seq = 1; mStackSupervisor = createStackSupervisor(); - mStackSupervisor.onConfigurationChanged(mTempConfig); + mRootActivityContainer = new RootActivityContainer(this); + mRootActivityContainer.onConfigurationChanged(mTempConfig); mTaskChangeNotificationController = new TaskChangeNotificationController(mGlobalLock, mStackSupervisor, mH); @@ -801,6 +803,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { mWindowManager = wm; mLockTaskController.setWindowManager(wm); mStackSupervisor.setWindowManager(wm); + mRootActivityContainer.setWindowManager(wm); } } @@ -1255,7 +1258,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { sourceToken = resultTo; } - sourceRecord = mStackSupervisor.isInAnyStackLocked(sourceToken); + sourceRecord = mRootActivityContainer.isInAnyStack(sourceToken); if (sourceRecord == null) { throw new SecurityException("Called with bad activity token: " + sourceToken); } @@ -1799,7 +1802,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } final boolean translucentChanged = r.changeWindowTranslucency(true); if (translucentChanged) { - mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); + mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS); } mWindowManager.setAppFullscreen(token, true); return translucentChanged; @@ -1829,7 +1832,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { if (translucentChanged) { r.getStack().convertActivityToTranslucent(r); } - mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); + mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS); mWindowManager.setAppFullscreen(token, false); return translucentChanged; } @@ -1842,7 +1845,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { public void notifyActivityDrawn(IBinder token) { if (DEBUG_VISIBILITY) Slog.d(TAG_VISIBILITY, "notifyActivityDrawn: token=" + token); synchronized (mGlobalLock) { - ActivityRecord r = mStackSupervisor.isInAnyStackLocked(token); + ActivityRecord r = mRootActivityContainer.isInAnyStack(token); if (r != null) { r.getStack().notifyActivityDrawnLocked(r); } @@ -1879,7 +1882,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { synchronized (mGlobalLock) { ActivityStack focusedStack = getTopDisplayFocusedStack(); if (focusedStack != null) { - return mStackSupervisor.getStackInfo(focusedStack.mStackId); + return mRootActivityContainer.getStackInfo(focusedStack.mStackId); } return null; } @@ -1895,14 +1898,14 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { final long callingId = Binder.clearCallingIdentity(); try { synchronized (mGlobalLock) { - final ActivityStack stack = mStackSupervisor.getStack(stackId); + final ActivityStack stack = mRootActivityContainer.getStack(stackId); if (stack == null) { Slog.w(TAG, "setFocusedStack: No stack with id=" + stackId); return; } final ActivityRecord r = stack.topRunningActivityLocked(); if (r != null && r.moveFocusableActivityToTop("setFocusedStack")) { - mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); + mRootActivityContainer.resumeFocusedStacksTopActivities(); } } } finally { @@ -1917,14 +1920,14 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { final long callingId = Binder.clearCallingIdentity(); try { synchronized (mGlobalLock) { - final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId, + final TaskRecord task = mRootActivityContainer.anyTaskForId(taskId, MATCH_TASK_IN_STACKS_ONLY); if (task == null) { return; } final ActivityRecord r = task.topRunningActivityLocked(); if (r != null && r.moveFocusableActivityToTop("setFocusedTask")) { - mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); + mRootActivityContainer.resumeFocusedStacksTopActivities(); } } } finally { @@ -2009,7 +2012,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { final long origId = Binder.clearCallingIdentity(); try { int taskId = ActivityRecord.getTaskForActivityLocked(token, !nonRoot); - final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId); + final TaskRecord task = mRootActivityContainer.anyTaskForId(taskId); if (task != null) { return ActivityRecord.getStackLocked(token).moveTaskToBackLocked(taskId); } @@ -2027,7 +2030,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { Rect rect = new Rect(); try { synchronized (mGlobalLock) { - final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId, + final TaskRecord task = mRootActivityContainer.anyTaskForId(taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS); if (task == null) { Slog.w(TAG, "getTaskBounds: taskId=" + taskId + " not found"); @@ -2058,7 +2061,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { synchronized (mGlobalLock) { enforceCallerIsRecentsOrHasPermission( MANAGE_ACTIVITY_STACKS, "getTaskDescription()"); - final TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(id, + final TaskRecord tr = mRootActivityContainer.anyTaskForId(id, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS); if (tr != null) { return tr.lastTaskDescription; @@ -2078,7 +2081,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { synchronized (mGlobalLock) { final long ident = Binder.clearCallingIdentity(); try { - final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId, + final TaskRecord task = mRootActivityContainer.anyTaskForId(taskId, MATCH_TASK_IN_STACKS_ONLY); if (task == null) { Slog.w(TAG, "setTaskWindowingMode: No task for id=" + taskId); @@ -2167,7 +2170,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } final long origId = Binder.clearCallingIdentity(); try { - final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId); + final TaskRecord task = mRootActivityContainer.anyTaskForId(taskId); if (task == null) { Slog.d(TAG, "Could not find task for id: "+ taskId); SafeActivityOptions.abort(options); @@ -2284,7 +2287,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { final boolean allowed = isGetTasksAllowed("getTasks", Binder.getCallingPid(), callingUid); - mStackSupervisor.getRunningTasks(maxNum, list, ignoreActivityType, + mRootActivityContainer.getRunningTasks(maxNum, list, ignoreActivityType, ignoreWindowingMode, callingUid, allowed); } @@ -2320,7 +2323,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { synchronized (mGlobalLock) { final long ident = Binder.clearCallingIdentity(); try { - final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId); + final TaskRecord task = mRootActivityContainer.anyTaskForId(taskId); if (task == null) { Slog.w(TAG, "moveTaskToStack: No task for id=" + taskId); return; @@ -2329,7 +2332,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { if (DEBUG_STACK) Slog.d(TAG_STACK, "moveTaskToStack: moving task=" + taskId + " to stackId=" + stackId + " toTop=" + toTop); - final ActivityStack stack = mStackSupervisor.getStack(stackId); + final ActivityStack stack = mRootActivityContainer.getStack(stackId); if (stack == null) { throw new IllegalStateException( "moveTaskToStack: No stack for stackId=" + stackId); @@ -2359,7 +2362,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { try { synchronized (mGlobalLock) { if (animate) { - final PinnedActivityStack stack = mStackSupervisor.getStack(stackId); + final PinnedActivityStack stack = mRootActivityContainer.getStack(stackId); if (stack == null) { Slog.w(TAG, "resizeStack: stackId " + stackId + " not found."); return; @@ -2371,12 +2374,12 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { stack.animateResizePinnedStack(null /* sourceHintBounds */, destBounds, animationDuration, false /* fromFullscreen */); } else { - final ActivityStack stack = mStackSupervisor.getStack(stackId); + final ActivityStack stack = mRootActivityContainer.getStack(stackId); if (stack == null) { Slog.w(TAG, "resizeStack: stackId " + stackId + " not found."); return; } - mStackSupervisor.resizeStackLocked(stack, destBounds, + mRootActivityContainer.resizeStack(stack, destBounds, null /* tempTaskBounds */, null /* tempTaskInsetBounds */, preserveWindows, allowResizeInDockedMode, !DEFER_RESUME); } @@ -2410,7 +2413,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { synchronized (mGlobalLock) { final long ident = Binder.clearCallingIdentity(); try { - final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId, + final TaskRecord task = mRootActivityContainer.anyTaskForId(taskId, MATCH_TASK_IN_STACKS_ONLY); if (task == null) { Slog.w(TAG, "setTaskWindowingModeSplitScreenPrimary: No task for id=" + taskId); @@ -2452,7 +2455,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { synchronized (mGlobalLock) { final long ident = Binder.clearCallingIdentity(); try { - mStackSupervisor.removeStacksInWindowingModes(windowingModes); + mRootActivityContainer.removeStacksInWindowingModes(windowingModes); } finally { Binder.restoreCallingIdentity(ident); } @@ -2467,7 +2470,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { synchronized (mGlobalLock) { final long ident = Binder.clearCallingIdentity(); try { - mStackSupervisor.removeStacksWithActivityTypes(activityTypes); + mRootActivityContainer.removeStacksWithActivityTypes(activityTypes); } finally { Binder.restoreCallingIdentity(ident); } @@ -2498,7 +2501,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { long ident = Binder.clearCallingIdentity(); try { synchronized (mGlobalLock) { - return mStackSupervisor.getAllStackInfosLocked(); + return mRootActivityContainer.getAllStackInfos(); } } finally { Binder.restoreCallingIdentity(ident); @@ -2511,7 +2514,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { long ident = Binder.clearCallingIdentity(); try { synchronized (mGlobalLock) { - return mStackSupervisor.getStackInfo(windowingMode, activityType); + return mRootActivityContainer.getStackInfo(windowingMode, activityType); } } finally { Binder.restoreCallingIdentity(ident); @@ -2553,7 +2556,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { long ident = Binder.clearCallingIdentity(); try { synchronized (mGlobalLock) { - final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId, + final TaskRecord task = mRootActivityContainer.anyTaskForId(taskId, MATCH_TASK_IN_STACKS_ONLY); if (task == null) { return; @@ -2595,7 +2598,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { return; } - final ActivityStack stack = mStackSupervisor.getTopDisplayFocusedStack(); + final ActivityStack stack = mRootActivityContainer.getTopDisplayFocusedStack(); if (stack == null || task != stack.topTask()) { throw new IllegalArgumentException("Invalid task, not in foreground"); } @@ -2610,7 +2613,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { long ident = Binder.clearCallingIdentity(); try { // When a task is locked, dismiss the pinned stack if it exists - mStackSupervisor.removeStacksInWindowingModes(WINDOWING_MODE_PINNED); + mRootActivityContainer.removeStacksInWindowingModes(WINDOWING_MODE_PINNED); getLockTaskController().startLockTaskMode(task, isSystemCaller, callingUid); } finally { @@ -2712,7 +2715,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { try { // TODO: VI Consider treating local voice interactions and voice tasks // differently here - mStackSupervisor.finishVoiceTask(session); + mRootActivityContainer.finishVoiceTask(session); } finally { Binder.restoreCallingIdentity(origId); } @@ -2902,7 +2905,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { @Override public void setTaskResizeable(int taskId, int resizeableMode) { synchronized (mGlobalLock) { - final TaskRecord task = mStackSupervisor.anyTaskForIdLocked( + final TaskRecord task = mRootActivityContainer.anyTaskForId( taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS); if (task == null) { Slog.w(TAG, "setTaskResizeable: taskId=" + taskId + " not found"); @@ -2918,7 +2921,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { long ident = Binder.clearCallingIdentity(); try { synchronized (mGlobalLock) { - final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId, + final TaskRecord task = mRootActivityContainer.anyTaskForId(taskId, MATCH_TASK_IN_STACKS_ONLY); if (task == null) { Slog.w(TAG, "resizeTask: taskId=" + taskId + " not found"); @@ -2983,7 +2986,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { final long origId = Binder.clearCallingIdentity(); try { final WindowProcessController app = getProcessController(appInt); - mStackSupervisor.releaseSomeActivitiesLocked(app, "low-mem"); + mRootActivityContainer.releaseSomeActivitiesLocked(app, "low-mem"); } finally { Binder.restoreCallingIdentity(origId); } @@ -3077,7 +3080,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { synchronized (mGlobalLock) { final long ident = Binder.clearCallingIdentity(); try { - final ActivityStack stack = mStackSupervisor.getStack(stackId); + final ActivityStack stack = mRootActivityContainer.getStack(stackId); if (stack == null) { Slog.w(TAG, "removeStack: No stack with id=" + stackId); return; @@ -3102,7 +3105,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { try { if (DEBUG_STACK) Slog.d(TAG_STACK, "moveStackToDisplay: moving stackId=" + stackId + " to displayId=" + displayId); - mStackSupervisor.moveStackToDisplayLocked(stackId, displayId, ON_TOP); + mRootActivityContainer.moveStackToDisplay(stackId, displayId, ON_TOP); } finally { Binder.restoreCallingIdentity(ident); } @@ -3564,13 +3567,13 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { try { if (DEBUG_STACK) Slog.d(TAG_STACK, "positionTaskInStack: positioning task=" + taskId + " in stackId=" + stackId + " at position=" + position); - final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId); + final TaskRecord task = mRootActivityContainer.anyTaskForId(taskId); if (task == null) { throw new IllegalArgumentException("positionTaskInStack: no task for id=" + taskId); } - final ActivityStack stack = mStackSupervisor.getStack(stackId); + final ActivityStack stack = mRootActivityContainer.getStack(stackId); if (stack == null) { throw new IllegalArgumentException("positionTaskInStack: no stack for id=" @@ -3625,7 +3628,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { try { synchronized (mGlobalLock) { final ActivityStack stack = - mStackSupervisor.getDefaultDisplay().getSplitScreenPrimaryStack(); + mRootActivityContainer.getDefaultDisplay().getSplitScreenPrimaryStack(); if (stack == null) { Slog.w(TAG, "dismissSplitScreenMode: primary split-screen stack not found."); return; @@ -3635,7 +3638,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { // Caller wants the current split-screen primary stack to be the top stack after // it goes fullscreen, so move it to the front. stack.moveToFront("dismissSplitScreenMode"); - } else if (mStackSupervisor.isTopDisplayFocusedStack(stack)) { + } else if (mRootActivityContainer.isTopDisplayFocusedStack(stack)) { // In this case the current split-screen primary stack shouldn't be the top // stack after it goes fullscreen, but it current has focus, so we move the // focus to the top-most split-screen secondary stack next to it. @@ -3666,7 +3669,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { try { synchronized (mGlobalLock) { final PinnedActivityStack stack = - mStackSupervisor.getDefaultDisplay().getPinnedStack(); + mRootActivityContainer.getDefaultDisplay().getPinnedStack(); if (stack == null) { Slog.w(TAG, "dismissPip: pinned stack not found."); return; @@ -3708,7 +3711,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { synchronized (mGlobalLock) { final long origId = Binder.clearCallingIdentity(); try { - final ActivityStack stack = mStackSupervisor.getStack(fromStackId); + final ActivityStack stack = mRootActivityContainer.getStack(fromStackId); if (stack != null){ if (!stack.isActivityTypeStandardOrUndefined()) { throw new IllegalArgumentException( @@ -3743,7 +3746,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { long ident = Binder.clearCallingIdentity(); try { - return mStackSupervisor.moveTopStackActivityToPinnedStackLocked(stackId, bounds); + return mRootActivityContainer.moveTopStackActivityToPinnedStack(stackId); } finally { Binder.restoreCallingIdentity(ident); } @@ -3821,7 +3824,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { // Adjust the source bounds by the insets for the transition down final Rect sourceBounds = new Rect( r.pictureInPictureArgs.getSourceRectHint()); - mStackSupervisor.moveActivityToPinnedStackLocked( + mRootActivityContainer.moveActivityToPinnedStack( r, sourceBounds, aspectRatio, "enterPictureInPictureMode"); final PinnedActivityStack stack = r.getStack(); stack.setPictureInPictureAspectRatio(aspectRatio); @@ -4100,7 +4103,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { synchronized (mGlobalLock) { // Check if display is initialized in AM. - if (!mStackSupervisor.isDisplayAdded(displayId)) { + if (!mRootActivityContainer.isDisplayAdded(displayId)) { // Call might come when display is not yet added or has already been removed. if (DEBUG_CONFIGURATION) { Slog.w(TAG, "Trying to update display configuration for non-existing displayId=" @@ -4190,7 +4193,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { final long ident = Binder.clearCallingIdentity(); try { synchronized (mGlobalLock) { - final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId, + final TaskRecord task = mRootActivityContainer.anyTaskForId(taskId, MATCH_TASK_IN_STACKS_ONLY); if (task == null) { Slog.w(TAG, "cancelTaskWindowTransition: taskId=" + taskId + " not found"); @@ -4210,7 +4213,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { try { final TaskRecord task; synchronized (mGlobalLock) { - task = mStackSupervisor.anyTaskForIdLocked(taskId, + task = mRootActivityContainer.anyTaskForId(taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS); if (task == null) { Slog.w(TAG, "getTaskSnapshot: taskId=" + taskId + " not found"); @@ -4430,7 +4433,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { if (r.requestedVrComponent != null && r.getDisplayId() != DEFAULT_DISPLAY) { Slog.i(TAG, "Moving " + r.shortComponentName + " from stack " + r.getStackId() + " to main stack for VR"); - final ActivityStack stack = mStackSupervisor.getDefaultDisplay().getOrCreateStack( + final ActivityStack stack = mRootActivityContainer.getDefaultDisplay().getOrCreateStack( WINDOWING_MODE_FULLSCREEN, r.getActivityType(), true /* toTop */); moveTaskToStack(r.getTask().taskId, stack.mStackId, true /* toTop */); } @@ -4444,7 +4447,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { if (disableNonVrUi) { // If we are in a VR mode where Picture-in-Picture mode is unsupported, // then remove the pinned stack. - mStackSupervisor.removeStacksInWindowingModes(WINDOWING_MODE_PINNED); + mRootActivityContainer.removeStacksInWindowingModes(WINDOWING_MODE_PINNED); } } }); @@ -4496,7 +4499,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } ActivityStack getTopDisplayFocusedStack() { - return mStackSupervisor.getTopDisplayFocusedStack(); + return mRootActivityContainer.getTopDisplayFocusedStack(); } /** Pokes the task persister. */ @@ -4557,12 +4560,12 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { int opti, boolean dumpAll, boolean dumpClient, String dumpPackage, String header) { pw.println(header); - boolean printedAnything = mStackSupervisor.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, + boolean printedAnything = mRootActivityContainer.dumpActivities(fd, pw, dumpAll, dumpClient, dumpPackage); boolean needSep = printedAnything; boolean printed = ActivityStackSupervisor.printThisActivity(pw, - mStackSupervisor.getTopResumedActivity(), dumpPackage, needSep, + mRootActivityContainer.getTopResumedActivity(), dumpPackage, needSep, " ResumedActivity: "); if (printed) { printedAnything = true; @@ -4584,7 +4587,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { void dumpActivityContainersLocked(PrintWriter pw) { pw.println("ACTIVITY MANAGER STARTER (dumpsys activity containers)"); - mStackSupervisor.dumpChildrenNames(pw, " "); + mRootActivityContainer.dumpChildrenNames(pw, " "); pw.println(" "); } @@ -4608,7 +4611,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { ArrayList<ActivityRecord> activities; synchronized (mGlobalLock) { - activities = mStackSupervisor.getDumpActivitiesLocked(name, dumpVisibleStacksOnly, + activities = mRootActivityContainer.getDumpActivities(name, dumpVisibleStacksOnly, dumpFocusedStackOnly); } @@ -4683,7 +4686,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } void writeSleepStateToProto(ProtoOutputStream proto) { - for (ActivityTaskManagerInternal.SleepToken st : mStackSupervisor.mSleepTokens) { + for (ActivityTaskManagerInternal.SleepToken st : mRootActivityContainer.mSleepTokens) { proto.write(ActivityManagerServiceDumpProcessesProto.SleepStatus.SLEEP_TOKENS, st.toString()); } @@ -4728,7 +4731,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { * also corresponds to the merged configuration of the default display. */ Configuration getGlobalConfiguration() { - return mStackSupervisor.getConfiguration(); + return mRootActivityContainer.getConfiguration(); } boolean updateConfigurationLocked(Configuration values, ActivityRecord starting, @@ -4860,7 +4863,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { mTempConfig.seq = increaseConfigurationSeqLocked(); // Update stored global config and notify everyone about the change. - mStackSupervisor.onConfigurationChanged(mTempConfig); + mRootActivityContainer.onConfigurationChanged(mTempConfig); Slog.i(TAG, "Config changes=" + Integer.toHexString(changes) + " " + mTempConfig); // TODO(multi-display): Update UsageEvents#Event to include displayId. @@ -4907,7 +4910,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { // Override configuration of the default display duplicates global config, so we need to // update it also. This will also notify WindowManager about changes. - performDisplayOverrideConfigUpdate(mStackSupervisor.getConfiguration(), deferResume, + performDisplayOverrideConfigUpdate(mRootActivityContainer.getConfiguration(), deferResume, DEFAULT_DISPLAY); return changes; @@ -4961,12 +4964,12 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { private int performDisplayOverrideConfigUpdate(Configuration values, boolean deferResume, int displayId) { - mTempConfig.setTo(mStackSupervisor.getDisplayOverrideConfiguration(displayId)); + mTempConfig.setTo(mRootActivityContainer.getDisplayOverrideConfiguration(displayId)); final int changes = mTempConfig.updateFrom(values); if (changes != 0) { Slog.i(TAG, "Override config changes=" + Integer.toHexString(changes) + " " + mTempConfig + " for displayId=" + displayId); - mStackSupervisor.setDisplayOverrideConfiguration(mTempConfig, displayId); + mRootActivityContainer.setDisplayOverrideConfiguration(mTempConfig, displayId); final boolean isDensityChange = (changes & ActivityInfo.CONFIG_DENSITY) != 0; if (isDensityChange && displayId == DEFAULT_DISPLAY) { @@ -5096,7 +5099,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { mCurAppTimeTracker.stop(); mH.obtainMessage( REPORT_TIME_TRACKER_MSG, mCurAppTimeTracker).sendToTarget(); - mStackSupervisor.clearOtherAppTimeTrackers(r.appTimeTracker); + mRootActivityContainer.clearOtherAppTimeTrackers(r.appTimeTracker); mCurAppTimeTracker = null; } if (r.appTimeTracker != null) { @@ -5157,14 +5160,15 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { ActivityTaskManagerInternal.SleepToken acquireSleepToken(String tag, int displayId) { synchronized (mGlobalLock) { - final ActivityTaskManagerInternal.SleepToken token = mStackSupervisor.createSleepTokenLocked(tag, displayId); + final ActivityTaskManagerInternal.SleepToken token = + mRootActivityContainer.createSleepToken(tag, displayId); updateSleepIfNeededLocked(); return token; } } void updateSleepIfNeededLocked() { - final boolean shouldSleep = !mStackSupervisor.hasAwakeDisplay(); + final boolean shouldSleep = !mRootActivityContainer.hasAwakeDisplay(); final boolean wasSleeping = mSleeping; boolean updateOomAdj = false; @@ -5180,7 +5184,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { mTopProcessState = ActivityManager.PROCESS_STATE_TOP; mStackSupervisor.comeOutOfSleepIfNeededLocked(); } - mStackSupervisor.applySleepTokensLocked(true /* applyToStacks */); + mRootActivityContainer.applySleepTokens(true /* applyToStacks */); if (wasSleeping) { updateOomAdj = true; } @@ -5356,7 +5360,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { // TODO(b/111541062): Update app time tracking to make it aware of multiple resumed activities private void startTimeTrackingFocusedActivityLocked() { - final ActivityRecord resumedActivity = mStackSupervisor.getTopResumedActivity(); + final ActivityRecord resumedActivity = mRootActivityContainer.getTopResumedActivity(); if (!mSleeping && mCurAppTimeTracker != null && resumedActivity != null) { mCurAppTimeTracker.start(resumedActivity.packageName); } @@ -5381,7 +5385,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { /** Applies latest configuration and/or visibility updates if needed. */ private boolean ensureConfigAndVisibilityAfterUpdate(ActivityRecord starting, int changes) { boolean kept = true; - final ActivityStack mainStack = mStackSupervisor.getTopDisplayFocusedStack(); + final ActivityStack mainStack = mRootActivityContainer.getTopDisplayFocusedStack(); // mainStack is null during startup. if (mainStack != null) { if (changes != 0 && starting == null) { @@ -5396,7 +5400,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { false /* preserveWindow */); // And we need to make sure at this point that all other activities // are made visible with the correct configuration. - mStackSupervisor.ensureActivitiesVisibleLocked(starting, changes, + mRootActivityContainer.ensureActivitiesVisible(starting, changes, !PRESERVE_WINDOWS); } } @@ -5612,8 +5616,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { @Override public ComponentName getHomeActivityForUser(int userId) { synchronized (mGlobalLock) { - ActivityRecord homeActivity = - mStackSupervisor.getDefaultDisplayHomeActivityForUser(userId); + final ActivityRecord homeActivity = + mRootActivityContainer.getDefaultDisplayHomeActivityForUser(userId); return homeActivity == null ? null : homeActivity.realActivity; } } @@ -5651,14 +5655,14 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { @Override public List<IBinder> getTopVisibleActivities() { synchronized (mGlobalLock) { - return mStackSupervisor.getTopVisibleActivities(); + return mRootActivityContainer.getTopVisibleActivities(); } } @Override public void notifyDockedStackMinimizedChanged(boolean minimized) { synchronized (mGlobalLock) { - mStackSupervisor.setDockedStackMinimized(minimized); + mRootActivityContainer.setDockedStackMinimized(minimized); } } @@ -5739,7 +5743,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { // We might change the visibilities here, so prepare an empty app transition which // might be overridden later if we actually change visibilities. final ActivityDisplay activityDisplay = - mStackSupervisor.getActivityDisplay(displayId); + mRootActivityContainer.getActivityDisplay(displayId); if (activityDisplay == null) { return; } @@ -5748,7 +5752,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { if (!wasTransitionSet) { dwc.prepareAppTransition(TRANSIT_NONE, false /* alwaysKeepCurrent */); } - mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); + mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS); // If there was a transition set already we don't want to interfere with it as we // might be starting it too early. @@ -5765,7 +5769,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { public void notifyKeyguardTrustedChanged() { synchronized (mGlobalLock) { if (mKeyguardController.isKeyguardShowing(DEFAULT_DISPLAY)) { - mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); + mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS); } } } @@ -5792,7 +5796,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { "setFocusedActivity: No activity record matching token=" + token); } if (r.moveFocusableActivityToTop("setFocusedActivity")) { - mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); + mRootActivityContainer.resumeFocusedStacksTopActivities(); } } } @@ -5943,7 +5947,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { public boolean shuttingDown(boolean booted, int timeout) { synchronized (mGlobalLock) { mShuttingDown = true; - mStackSupervisor.prepareForShutdownLocked(); + mRootActivityContainer.prepareForShutdown(); updateEventDispatchingLocked(booted); notifyTaskPersisterLocked(null, true); return mStackSupervisor.shutdownLocked(timeout); @@ -6050,7 +6054,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { @Override public void onPackageReplaced(ApplicationInfo aInfo) { synchronized (mGlobalLock) { - mStackSupervisor.updateActivityApplicationInfoLocked(aInfo); + mRootActivityContainer.updateActivityApplicationInfo(aInfo); } } @@ -6080,7 +6084,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { mH.post(() -> { synchronized (mGlobalLock) { final ActivityDisplay activityDisplay = - mStackSupervisor.getActivityDisplay(displayId); + mRootActivityContainer.getActivityDisplay(displayId); if (activityDisplay == null) { // Call might come when display is not yet added or has been removed. if (DEBUG_CONFIGURATION) { @@ -6163,14 +6167,14 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { @Override public boolean startHomeActivity(int userId, String reason) { synchronized (mGlobalLock) { - return mStackSupervisor.startHomeOnDisplay(userId, reason, DEFAULT_DISPLAY); + return mRootActivityContainer.startHomeOnDisplay(userId, reason, DEFAULT_DISPLAY); } } @Override public boolean startHomeOnAllDisplays(int userId, String reason) { synchronized (mGlobalLock) { - return mStackSupervisor.startHomeOnAllDisplays(userId, reason); + return mRootActivityContainer.startHomeOnAllDisplays(userId, reason); } } @@ -6234,7 +6238,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { Runnable finishInstrumentationCallback) { synchronized (mGlobalLock) { // Remove this application's activities from active lists. - boolean hasVisibleActivities = mStackSupervisor.handleAppDiedLocked(wpc); + boolean hasVisibleActivities = mRootActivityContainer.handleAppDied(wpc); wpc.clearRecentTasks(); wpc.clearActivities(); @@ -6246,12 +6250,12 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { mWindowManager.deferSurfaceLayout(); try { if (!restarting && hasVisibleActivities - && !mStackSupervisor.resumeFocusedStacksTopActivitiesLocked()) { + && !mRootActivityContainer.resumeFocusedStacksTopActivities()) { // 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. - mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); + mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS); } } finally { mWindowManager.continueSurfaceLayout(); @@ -6280,7 +6284,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } mWindowManager.closeSystemDialogs(reason); - mStackSupervisor.closeSystemDialogsLocked(); + mRootActivityContainer.closeSystemDialogs(); } // Call into AM outside the synchronized block. mAmInternal.broadcastCloseSystemDialogs(reason); @@ -6294,9 +6298,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { String packageName, Set<String> disabledClasses, int userId, boolean booted) { synchronized (mGlobalLock) { // Clean-up disabled activities. - if (mStackSupervisor.finishDisabledPackageActivitiesLocked( + if (mRootActivityContainer.finishDisabledPackageActivities( packageName, disabledClasses, true, false, userId) && booted) { - mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); + mRootActivityContainer.resumeFocusedStacksTopActivities(); mStackSupervisor.scheduleIdleLocked(); } @@ -6313,7 +6317,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { boolean didSomething = getActivityStartController().clearPendingActivityLaunches(packageName); - didSomething |= mStackSupervisor.finishDisabledPackageActivitiesLocked(packageName, + didSomething |= mRootActivityContainer.finishDisabledPackageActivities(packageName, null, doit, evenPersistent, userId); return didSomething; } @@ -6322,7 +6326,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { @Override public void resumeTopActivities(boolean scheduleIdle) { synchronized (mGlobalLock) { - mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); + mRootActivityContainer.resumeFocusedStacksTopActivities(); if (scheduleIdle) { mStackSupervisor.scheduleIdleLocked(); } @@ -6339,7 +6343,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { @Override public boolean attachApplication(WindowProcessController wpc) throws RemoteException { synchronized (mGlobalLock) { - return mStackSupervisor.attachApplicationLocked(wpc); + return mRootActivityContainer.attachApplication(wpc); } } @@ -6361,7 +6365,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { // Showing launcher to avoid user entering credential twice. startHomeActivity(currentUserId, "notifyLockedProfile"); } - mStackSupervisor.lockAllProfileTasks(userId); + mRootActivityContainer.lockAllProfileTasks(userId); } } finally { Binder.restoreCallingIdentity(ident); @@ -6382,7 +6386,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { ActivityOptions activityOptions = options != null ? new ActivityOptions(options) : ActivityOptions.makeBasic(); final ActivityRecord homeActivity = - mStackSupervisor.getDefaultDisplayHomeActivity(); + mRootActivityContainer.getDefaultDisplayHomeActivity(); if (homeActivity != null) { activityOptions.setLaunchTaskId(homeActivity.getTask().taskId); } @@ -6399,7 +6403,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { synchronized (mGlobalLock) { // The output proto of "activity --proto activities" // is ActivityManagerServiceDumpActivitiesProto - mStackSupervisor.writeToProto(proto, + mRootActivityContainer.writeToProto(proto, ActivityManagerServiceDumpActivitiesProto.ACTIVITY_STACK_SUPERVISOR); } } @@ -6494,7 +6498,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } if (dumpPackage == null) { pw.println(" mGlobalConfiguration: " + getGlobalConfiguration()); - mStackSupervisor.dumpDisplayConfigs(pw, " "); + mRootActivityContainer.dumpDisplayConfigs(pw, " "); } if (dumpAll) { if (dumpPackage == null) { @@ -6522,7 +6526,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { if (dumpPackage == null) { pw.println(" mWakefulness=" + PowerManagerInternal.wakefulnessToString(wakefulness)); - pw.println(" mSleepTokens=" + mStackSupervisor.mSleepTokens); + pw.println(" mSleepTokens=" + mRootActivityContainer.mSleepTokens); if (mRunningVoice != null) { pw.println(" mRunningVoice=" + mRunningVoice); pw.println(" mVoiceWakeLock" + mVoiceWakeLock); @@ -6649,14 +6653,14 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { @Override public boolean canGcNow() { synchronized (mGlobalLock) { - return isSleeping() || mStackSupervisor.allResumedActivitiesIdle(); + return isSleeping() || mRootActivityContainer.allResumedActivitiesIdle(); } } @Override public WindowProcessController getTopApp() { synchronized (mGlobalLock) { - final ActivityRecord top = mStackSupervisor.getTopResumedActivity(); + final ActivityRecord top = mRootActivityContainer.getTopResumedActivity(); return top != null ? top.app : null; } } @@ -6664,8 +6668,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { @Override public void rankTaskLayersIfNeeded() { synchronized (mGlobalLock) { - if (mStackSupervisor != null) { - mStackSupervisor.rankTaskLayersIfNeeded(); + if (mRootActivityContainer != null) { + mRootActivityContainer.rankTaskLayersIfNeeded(); } } } @@ -6673,35 +6677,35 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { @Override public void scheduleDestroyAllActivities(String reason) { synchronized (mGlobalLock) { - mStackSupervisor.scheduleDestroyAllActivities(null, reason); + mRootActivityContainer.scheduleDestroyAllActivities(null, reason); } } @Override public void removeUser(int userId) { synchronized (mGlobalLock) { - mStackSupervisor.removeUserLocked(userId); + mRootActivityContainer.removeUser(userId); } } @Override public boolean switchUser(int userId, UserState userState) { synchronized (mGlobalLock) { - return mStackSupervisor.switchUserLocked(userId, userState); + return mRootActivityContainer.switchUser(userId, userState); } } @Override public void onHandleAppCrash(WindowProcessController wpc) { synchronized (mGlobalLock) { - mStackSupervisor.handleAppCrashLocked(wpc); + mRootActivityContainer.handleAppCrash(wpc); } } @Override public int finishTopCrashedActivities(WindowProcessController crashedApp, String reason) { synchronized (mGlobalLock) { - return mStackSupervisor.finishTopCrashedActivitiesLocked(crashedApp, reason); + return mRootActivityContainer.finishTopCrashedActivities(crashedApp, reason); } } diff --git a/services/core/java/com/android/server/wm/AppTaskImpl.java b/services/core/java/com/android/server/wm/AppTaskImpl.java index 04fef02cd3b4..441c5935a507 100644 --- a/services/core/java/com/android/server/wm/AppTaskImpl.java +++ b/services/core/java/com/android/server/wm/AppTaskImpl.java @@ -16,8 +16,8 @@ package com.android.server.wm; -import static com.android.server.wm.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS; import static com.android.server.wm.ActivityStackSupervisor.REMOVE_FROM_RECENTS; +import static com.android.server.wm.RootActivityContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS; import android.app.ActivityManager; import android.app.IAppTask; @@ -77,7 +77,7 @@ class AppTaskImpl extends IAppTask.Stub { synchronized (mService.mGlobalLock) { long origId = Binder.clearCallingIdentity(); try { - TaskRecord tr = mService.mStackSupervisor.anyTaskForIdLocked(mTaskId, + TaskRecord tr = mService.mRootActivityContainer.anyTaskForId(mTaskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS); if (tr == null) { throw new IllegalArgumentException("Unable to find task ID " + mTaskId); @@ -115,7 +115,7 @@ class AppTaskImpl extends IAppTask.Stub { TaskRecord tr; IApplicationThread appThread; synchronized (mService.mGlobalLock) { - tr = mService.mStackSupervisor.anyTaskForIdLocked(mTaskId, + tr = mService.mRootActivityContainer.anyTaskForId(mTaskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS); if (tr == null) { throw new IllegalArgumentException("Unable to find task ID " + mTaskId); @@ -143,7 +143,7 @@ class AppTaskImpl extends IAppTask.Stub { synchronized (mService.mGlobalLock) { long origId = Binder.clearCallingIdentity(); try { - TaskRecord tr = mService.mStackSupervisor.anyTaskForIdLocked(mTaskId, + TaskRecord tr = mService.mRootActivityContainer.anyTaskForId(mTaskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS); if (tr == null) { throw new IllegalArgumentException("Unable to find task ID " + mTaskId); diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java index c91af73dc6dd..4ef351390c16 100644 --- a/services/core/java/com/android/server/wm/KeyguardController.java +++ b/services/core/java/com/android/server/wm/KeyguardController.java @@ -72,6 +72,7 @@ class KeyguardController { private int mVisibilityTransactionDepth; private final SparseArray<KeyguardDisplayState> mDisplayStates = new SparseArray<>(); private final ActivityTaskManagerService mService; + private RootActivityContainer mRootActivityContainer; KeyguardController(ActivityTaskManagerService service, ActivityStackSupervisor stackSupervisor) { @@ -81,6 +82,7 @@ class KeyguardController { void setWindowManager(WindowManagerService windowManager) { mWindowManager = windowManager; + mRootActivityContainer = mService.mRootActivityContainer; } /** @@ -146,7 +148,7 @@ class KeyguardController { mDismissalRequested = false; } } - mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); + mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS); updateKeyguardSleepToken(); } @@ -172,16 +174,17 @@ class KeyguardController { mWindowManager.deferSurfaceLayout(); try { setKeyguardGoingAway(true); - mStackSupervisor.getDefaultDisplay().getWindowContainerController() + mRootActivityContainer.getDefaultDisplay().getWindowContainerController() .prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY, false /* alwaysKeepCurrent */, convertTransitFlags(flags), false /* forceOverride */); updateKeyguardSleepToken(); // Some stack visibility might change (e.g. docked stack) - mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); - mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); - mStackSupervisor.addStartingWindowsForVisibleActivities(true /* taskSwitch */); + mRootActivityContainer.resumeFocusedStacksTopActivities(); + mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS); + mRootActivityContainer.addStartingWindowsForVisibleActivities( + true /* taskSwitch */); mWindowManager.executeAppTransition(); } finally { Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "keyguardGoingAway: surfaceLayout"); @@ -277,8 +280,9 @@ class KeyguardController { private void visibilitiesUpdated() { boolean requestDismissKeyguard = false; - for (int displayNdx = mStackSupervisor.getChildCount() - 1; displayNdx >= 0; displayNdx--) { - final ActivityDisplay display = mStackSupervisor.getChildAt(displayNdx); + for (int displayNdx = mRootActivityContainer.getChildCount() - 1; + displayNdx >= 0; displayNdx--) { + final ActivityDisplay display = mRootActivityContainer.getChildAt(displayNdx); final KeyguardDisplayState state = getDisplay(display.mDisplayId); state.visibilitiesUpdated(this, display); requestDismissKeyguard |= state.mRequestDismissKeyguard; @@ -298,12 +302,12 @@ class KeyguardController { if (isKeyguardLocked()) { mWindowManager.deferSurfaceLayout(); try { - mStackSupervisor.getDefaultDisplay().getWindowContainerController() + mRootActivityContainer.getDefaultDisplay().getWindowContainerController() .prepareAppTransition(resolveOccludeTransit(), false /* alwaysKeepCurrent */, 0 /* flags */, true /* forceOverride */); updateKeyguardSleepToken(); - mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); + mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS); mWindowManager.executeAppTransition(); } finally { mWindowManager.continueSurfaceLayout(); @@ -319,21 +323,23 @@ class KeyguardController { // We only allow dismissing Keyguard via the flag when Keyguard is secure for legacy // reasons, because that's how apps used to dismiss Keyguard in the secure case. In the // insecure case, we actually show it on top of the lockscreen. See #canShowWhileOccluded. - if (mWindowManager.isKeyguardSecure()) { - mWindowManager.dismissKeyguard(null /* callback */, null /* message */); - mDismissalRequested = true; - - // If we are about to unocclude the Keyguard, but we can dismiss it without security, - // we immediately dismiss the Keyguard so the activity gets shown without a flicker. - final DisplayWindowController dwc = - mStackSupervisor.getDefaultDisplay().getWindowContainerController(); - if (mKeyguardShowing && canDismissKeyguard() - && dwc.getPendingAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE) { - dwc.prepareAppTransition(mBeforeUnoccludeTransit, false /* alwaysKeepCurrent */, - 0 /* flags */, true /* forceOverride */); - mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); - mWindowManager.executeAppTransition(); - } + if (!mWindowManager.isKeyguardSecure()) { + return; + } + + mWindowManager.dismissKeyguard(null /* callback */, null /* message */); + mDismissalRequested = true; + + // If we are about to unocclude the Keyguard, but we can dismiss it without security, + // we immediately dismiss the Keyguard so the activity gets shown without a flicker. + final DisplayWindowController dwc = + mRootActivityContainer.getDefaultDisplay().getWindowContainerController(); + if (mKeyguardShowing && canDismissKeyguard() + && dwc.getPendingAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE) { + dwc.prepareAppTransition(mBeforeUnoccludeTransit, false /* alwaysKeepCurrent */, + 0 /* flags */, true /* forceOverride */); + mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS); + mWindowManager.executeAppTransition(); } } @@ -350,7 +356,7 @@ class KeyguardController { private int resolveOccludeTransit() { final DisplayWindowController dwc = - mStackSupervisor.getDefaultDisplay().getWindowContainerController(); + mRootActivityContainer.getDefaultDisplay().getWindowContainerController(); if (mBeforeUnoccludeTransit != TRANSIT_UNSET && dwc.getPendingAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE // TODO(b/113840485): Handle app transition for individual display. @@ -377,7 +383,8 @@ class KeyguardController { // show on top of the lock screen. In this can we want to dismiss the docked // stack since it will be complicated/risky to try to put the activity on top // of the lock screen in the right fullscreen configuration. - final ActivityStack stack = mStackSupervisor.getDefaultDisplay().getSplitScreenPrimaryStack(); + final ActivityStack stack = + mRootActivityContainer.getDefaultDisplay().getSplitScreenPrimaryStack(); if (stack == null) { return; } @@ -387,8 +394,9 @@ class KeyguardController { } private void updateKeyguardSleepToken() { - for (int displayNdx = mStackSupervisor.getChildCount() - 1; displayNdx >= 0; displayNdx--) { - final ActivityDisplay display = mStackSupervisor.getChildAt(displayNdx); + for (int displayNdx = mRootActivityContainer.getChildCount() - 1; + displayNdx >= 0; displayNdx--) { + final ActivityDisplay display = mRootActivityContainer.getChildAt(displayNdx); final KeyguardDisplayState state = getDisplay(display.mDisplayId); if (isKeyguardOrAodShowing(display.mDisplayId) && state.mSleepToken == null) { state.acquiredSleepToken(); diff --git a/services/core/java/com/android/server/wm/LaunchParamsPersister.java b/services/core/java/com/android/server/wm/LaunchParamsPersister.java index 72d51439d9f7..da9a5071b100 100644 --- a/services/core/java/com/android/server/wm/LaunchParamsPersister.java +++ b/services/core/java/com/android/server/wm/LaunchParamsPersister.java @@ -223,7 +223,8 @@ class LaunchParamsPersister { private boolean saveTaskToLaunchParam(TaskRecord task, PersistableLaunchParams params) { final ActivityStack<?> stack = task.getStack(); final int displayId = stack.mDisplayId; - final ActivityDisplay display = mSupervisor.getActivityDisplay(displayId); + final ActivityDisplay display = + mSupervisor.mRootActivityContainer.getActivityDisplay(displayId); final DisplayInfo info = new DisplayInfo(); display.mDisplay.getDisplayInfo(info); @@ -259,7 +260,7 @@ class LaunchParamsPersister { return; } - final ActivityDisplay display = mSupervisor.getActivityDisplay( + final ActivityDisplay display = mSupervisor.mRootActivityContainer.getActivityDisplay( persistableParams.mDisplayUniqueId); if (display != null) { outParams.mPreferredDisplayId = display.mDisplayId; diff --git a/services/core/java/com/android/server/wm/LockTaskController.java b/services/core/java/com/android/server/wm/LockTaskController.java index 41d0777d1c78..80dc2458d7f5 100644 --- a/services/core/java/com/android/server/wm/LockTaskController.java +++ b/services/core/java/com/android/server/wm/LockTaskController.java @@ -447,7 +447,7 @@ public class LockTaskController { return; } task.performClearTaskLocked(); - mSupervisor.resumeFocusedStacksTopActivitiesLocked(); + mSupervisor.mRootActivityContainer.resumeFocusedStacksTopActivities(); } /** @@ -579,7 +579,7 @@ public class LockTaskController { if (andResume) { mSupervisor.findTaskToMoveToFront(task, 0, null, reason, lockTaskModeState != LOCK_TASK_MODE_NONE); - mSupervisor.resumeFocusedStacksTopActivitiesLocked(); + mSupervisor.mRootActivityContainer.resumeFocusedStacksTopActivities(); final ActivityStack stack = task.getStack(); if (stack != null) { stack.getDisplay().getWindowContainerController().executeAppTransition(); @@ -641,11 +641,12 @@ public class LockTaskController { taskChanged = true; } - for (int displayNdx = mSupervisor.getChildCount() - 1; displayNdx >= 0; --displayNdx) { - mSupervisor.getChildAt(displayNdx).onLockTaskPackagesUpdated(); + for (int displayNdx = mSupervisor.mRootActivityContainer.getChildCount() - 1; + displayNdx >= 0; --displayNdx) { + mSupervisor.mRootActivityContainer.getChildAt(displayNdx).onLockTaskPackagesUpdated(); } - final ActivityRecord r = mSupervisor.topRunningActivityLocked(); + final ActivityRecord r = mSupervisor.mRootActivityContainer.topRunningActivity(); final TaskRecord task = (r != null) ? r.getTask() : null; if (mLockTaskModeTasks.isEmpty() && task!= null && task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE) { @@ -657,7 +658,7 @@ public class LockTaskController { } if (taskChanged) { - mSupervisor.resumeFocusedStacksTopActivitiesLocked(); + mSupervisor.mRootActivityContainer.resumeFocusedStacksTopActivities(); } } diff --git a/services/core/java/com/android/server/wm/PinnedActivityStack.java b/services/core/java/com/android/server/wm/PinnedActivityStack.java index 3ef42e7be8d7..1c7ebd63dfb3 100644 --- a/services/core/java/com/android/server/wm/PinnedActivityStack.java +++ b/services/core/java/com/android/server/wm/PinnedActivityStack.java @@ -41,7 +41,7 @@ class PinnedActivityStack extends ActivityStack<PinnedStackWindowController> PinnedStackWindowController createStackWindowController(int displayId, boolean onTop, Rect outBounds) { return new PinnedStackWindowController(mStackId, this, displayId, onTop, outBounds, - mStackSupervisor.mWindowManager); + mRootActivityContainer.mWindowManager); } Rect getDefaultPictureInPictureBounds(float aspectRatio) { diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java index 476c1f972fa9..24c5228ce0ec 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimation.java +++ b/services/core/java/com/android/server/wm/RecentsAnimation.java @@ -79,7 +79,7 @@ class RecentsAnimation implements RecentsAnimationCallbacks, int callingPid) { mService = atm; mStackSupervisor = stackSupervisor; - mDefaultDisplay = stackSupervisor.getDefaultDisplay(); + mDefaultDisplay = mService.mRootActivityContainer.getDefaultDisplay(); mActivityStartController = activityStartController; mWindowManager = wm; mCallingPid = callingPid; @@ -94,7 +94,7 @@ class RecentsAnimation implements RecentsAnimationCallbacks, // TODO(multi-display) currently only support recents animation in default display. final DisplayWindowController dwc = - mStackSupervisor.getDefaultDisplay().getWindowContainerController(); + mService.mRootActivityContainer.getDefaultDisplay().getWindowContainerController(); if (!mWindowManager.canStartRecentsAnimation()) { notifyAnimationCancelBeforeStart(recentsAnimationRunner); if (DEBUG) Slog.d(TAG, "Can't start recents animation, nextAppTransition=" @@ -124,8 +124,8 @@ class RecentsAnimation implements RecentsAnimationCallbacks, // Send launch hint if we are actually launching the target. If it's already visible // (shouldn't happen in general) we don't need to send it. if (targetActivity == null || !targetActivity.visible) { - mStackSupervisor.sendPowerHintForLaunchStartIfNeeded(true /* forceSend */, - targetActivity); + mService.mRootActivityContainer.sendPowerHintForLaunchStartIfNeeded( + true /* forceSend */, targetActivity); } mStackSupervisor.getActivityMetricsLogger().notifyActivityLaunching(intent); @@ -192,7 +192,7 @@ class RecentsAnimation implements RecentsAnimationCallbacks, // If we updated the launch-behind state, update the visibility of the activities after // we fetch the visible tasks to be controlled by the animation - mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, PRESERVE_WINDOWS); + mService.mRootActivityContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS); mStackSupervisor.getActivityMetricsLogger().notifyActivityLaunched(START_TASK_TO_FRONT, targetActivity); @@ -215,7 +215,8 @@ class RecentsAnimation implements RecentsAnimationCallbacks, @Deprecated IAssistDataReceiver assistDataReceiver, int userId) { final AppOpsManager appOpsManager = (AppOpsManager) mService.mContext.getSystemService(Context.APP_OPS_SERVICE); - final List<IBinder> topActivities = mStackSupervisor.getTopVisibleActivities(); + final List<IBinder> topActivities = + mService.mRootActivityContainer.getTopVisibleActivities(); final AssistDataRequester.AssistDataRequesterCallbacks assistDataCallbacks; if (assistDataReceiver != null) { assistDataCallbacks = new AssistDataReceiverProxy(assistDataReceiver, @@ -283,7 +284,7 @@ class RecentsAnimation implements RecentsAnimationCallbacks, // Just to be sure end the launch hint in case the target activity was never launched. // However, if we're keeping the activity and making it visible, we can leave it on. if (reorderMode != REORDER_KEEP_IN_PLACE) { - mStackSupervisor.sendPowerHintForLaunchEndIfNeeded(); + mService.mRootActivityContainer.sendPowerHintForLaunchEndIfNeeded(); } mService.mH.post( @@ -343,8 +344,8 @@ class RecentsAnimation implements RecentsAnimationCallbacks, } mWindowManager.prepareAppTransition(TRANSIT_NONE, false); - mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, false); - mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); + mService.mRootActivityContainer.ensureActivitiesVisible(null, 0, false); + mService.mRootActivityContainer.resumeFocusedStacksTopActivities(); // 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/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java new file mode 100644 index 000000000000..bdfbc1495b30 --- /dev/null +++ b/services/core/java/com/android/server/wm/RootActivityContainer.java @@ -0,0 +1,2295 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.server.wm; + +import static android.app.ActivityTaskManager.INVALID_STACK_ID; +import static android.app.ActivityTaskManager.INVALID_TASK_ID; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; +import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; +import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY; +import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; +import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; +import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; +import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; +import static android.app.WindowConfiguration.activityTypeToString; +import static android.app.WindowConfiguration.windowingModeToString; +import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; +import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE; +import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK; +import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; +import static android.view.Display.DEFAULT_DISPLAY; +import static android.view.Display.INVALID_DISPLAY; + +import static com.android.server.am.ActivityStackSupervisorProto.CONFIGURATION_CONTAINER; +import static com.android.server.am.ActivityStackSupervisorProto.DISPLAYS; +import static com.android.server.am.ActivityStackSupervisorProto.FOCUSED_STACK_ID; +import static com.android.server.am.ActivityStackSupervisorProto.IS_HOME_RECENTS_COMPONENT; +import static com.android.server.am.ActivityStackSupervisorProto.KEYGUARD_CONTROLLER; +import static com.android.server.am.ActivityStackSupervisorProto.PENDING_ACTIVITIES; +import static com.android.server.am.ActivityStackSupervisorProto.RESUMED_ACTIVITY; +import static com.android.server.wm.ActivityStack.ActivityState.PAUSED; +import static com.android.server.wm.ActivityStack.ActivityState.RESUMED; +import static com.android.server.wm.ActivityStack.ActivityState.STOPPED; +import static com.android.server.wm.ActivityStack.ActivityState.STOPPING; +import static com.android.server.wm.ActivityStackSupervisor.DEFER_RESUME; +import static com.android.server.wm.ActivityStackSupervisor.ON_TOP; +import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS; +import static com.android.server.wm.ActivityStackSupervisor.dumpHistoryList; +import static com.android.server.wm.ActivityStackSupervisor.printThisActivity; +import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RECENTS; +import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RELEASE; +import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STACK; +import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES; +import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS; +import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RECENTS; +import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RELEASE; +import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_STATES; +import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TASKS; +import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM; +import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; +import static com.android.server.wm.ActivityTaskManagerService.ANIMATE; +import static com.android.server.wm.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE; +import static com.android.server.wm.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT; + +import static java.lang.Integer.MAX_VALUE; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.UserIdInt; +import android.app.ActivityManager; +import android.app.ActivityOptions; +import android.app.AppGlobals; +import android.app.WindowConfiguration; +import android.content.ComponentName; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; +import android.content.pm.ResolveInfo; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.graphics.Rect; +import android.hardware.display.DisplayManager; +import android.hardware.display.DisplayManagerInternal; +import android.hardware.power.V1_0.PowerHint; +import android.os.Build; +import android.os.FactoryTest; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.SystemClock; +import android.os.Trace; +import android.os.UserHandle; +import android.service.voice.IVoiceInteractionSession; +import android.util.ArraySet; +import android.util.DisplayMetrics; +import android.util.IntArray; +import android.util.Slog; +import android.util.SparseArray; +import android.util.SparseIntArray; +import android.util.TimeUtils; +import android.util.proto.ProtoOutputStream; +import android.view.Display; +import android.view.DisplayInfo; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.server.LocalServices; +import com.android.server.am.ActivityManagerService; +import com.android.server.am.AppTimeTracker; +import com.android.server.am.UserState; + +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +/** + * Root node for activity containers. + * TODO: This class is mostly temporary to separate things out of ActivityStackSupervisor.java. The + * intention is to have this merged with RootWindowContainer.java as part of unifying the hierarchy. + */ +class RootActivityContainer extends ConfigurationContainer implements + DisplayManager.DisplayListener, RootWindowContainerListener { + + private static final String TAG = TAG_WITH_CLASS_NAME ? "RootActivityContainer" : TAG_ATM; + static final String TAG_TASKS = TAG + POSTFIX_TASKS; + private static final String TAG_RELEASE = TAG + POSTFIX_RELEASE; + static final String TAG_STATES = TAG + POSTFIX_STATES; + private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS; + + /** + * The modes which affect which tasks are returned when calling + * {@link RootActivityContainer#anyTaskForId(int)}. + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({ + MATCH_TASK_IN_STACKS_ONLY, + MATCH_TASK_IN_STACKS_OR_RECENT_TASKS, + MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE + }) + public @interface AnyTaskForIdMatchTaskMode {} + // Match only tasks in the current stacks + static final int MATCH_TASK_IN_STACKS_ONLY = 0; + // Match either tasks in the current stacks, or in the recent tasks if not found in the stacks + static final int MATCH_TASK_IN_STACKS_OR_RECENT_TASKS = 1; + // Match either tasks in the current stacks, or in the recent tasks, restoring it to the + // provided stack id + static final int MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE = 2; + + ActivityTaskManagerService mService; + ActivityStackSupervisor mStackSupervisor; + WindowManagerService mWindowManager; + DisplayManager mDisplayManager; + private DisplayManagerInternal mDisplayManagerInternal; + private RootWindowContainerController mWindowContainerController; + + /** + * List of displays which contain activities, sorted by z-order. + * The last entry in the list is the topmost. + */ + private final ArrayList<ActivityDisplay> mActivityDisplays = new ArrayList<>(); + + /** Reference to default display so we can quickly look it up. */ + private ActivityDisplay mDefaultDisplay; + private final SparseArray<IntArray> mDisplayAccessUIDs = new SparseArray<>(); + + /** The current user */ + int mCurrentUser; + /** Stack id of the front stack when user switched, indexed by userId. */ + SparseIntArray mUserStackInFront = new SparseIntArray(2); + + /** + * A list of tokens that cause the top activity to be put to sleep. + * They are used by components that may hide and block interaction with underlying + * activities. + */ + final ArrayList<ActivityTaskManagerInternal.SleepToken> mSleepTokens = new ArrayList<>(); + + /** Is dock currently minimized. */ + boolean mIsDockMinimized; + + /** Set when a power hint has started, but not ended. */ + private boolean mPowerHintSent; + + // The default minimal size that will be used if the activity doesn't specify its minimal size. + // It will be calculated when the default display gets added. + int mDefaultMinSizeOfResizeableTaskDp = -1; + + // Whether tasks have moved and we need to rank the tasks before next OOM scoring + private boolean mTaskLayersChanged = true; + + private final ArrayList<ActivityRecord> mTmpActivityList = new ArrayList<>(); + + private final FindTaskResult mTmpFindTaskResult = new FindTaskResult(); + static class FindTaskResult { + ActivityRecord mRecord; + boolean mIdealMatch; + + void clear() { + mRecord = null; + mIdealMatch = false; + } + + void setTo(FindTaskResult result) { + mRecord = result.mRecord; + mIdealMatch = result.mIdealMatch; + } + } + + RootActivityContainer(ActivityTaskManagerService service) { + mService = service; + mStackSupervisor = service.mStackSupervisor; + mStackSupervisor.mRootActivityContainer = this; + } + + @VisibleForTesting + void setWindowContainerController(RootWindowContainerController controller) { + mWindowContainerController = controller; + } + + void setWindowManager(WindowManagerService wm) { + mWindowManager = wm; + setWindowContainerController(new RootWindowContainerController(this)); + mDisplayManager = mService.mContext.getSystemService(DisplayManager.class); + mDisplayManager.registerDisplayListener(this, mService.mH); + mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); + + final Display[] displays = mDisplayManager.getDisplays(); + for (int displayNdx = 0; displayNdx < displays.length; ++displayNdx) { + final Display display = displays[displayNdx]; + final ActivityDisplay activityDisplay = new ActivityDisplay(this, display); + if (activityDisplay.mDisplayId == DEFAULT_DISPLAY) { + mDefaultDisplay = activityDisplay; + } + addChild(activityDisplay, ActivityDisplay.POSITION_TOP); + } + calculateDefaultMinimalSizeOfResizeableTasks(); + + final ActivityDisplay defaultDisplay = getDefaultDisplay(); + + defaultDisplay.getOrCreateStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP); + positionChildAt(defaultDisplay, ActivityDisplay.POSITION_TOP); + } + + // TODO(multi-display): Look at all callpoints to make sure they make sense in multi-display. + ActivityDisplay getDefaultDisplay() { + return mDefaultDisplay; + } + + /** + * Get an existing instance of {@link ActivityDisplay} that has the given uniqueId. Unique ID is + * defined in {@link DisplayInfo#uniqueId}. + * + * @param uniqueId the unique ID of the display + * @return the {@link ActivityDisplay} or {@code null} if nothing is found. + */ + ActivityDisplay getActivityDisplay(String uniqueId) { + for (int i = mActivityDisplays.size() - 1; i >= 0; --i) { + final ActivityDisplay display = mActivityDisplays.get(i); + final boolean isValid = display.mDisplay.isValid(); + if (isValid && display.mDisplay.getUniqueId().equals(uniqueId)) { + return display; + } + } + + return null; + } + + // TODO: Look into consolidating with getActivityDisplayOrCreate() + ActivityDisplay getActivityDisplay(int displayId) { + for (int i = mActivityDisplays.size() - 1; i >= 0; --i) { + final ActivityDisplay activityDisplay = mActivityDisplays.get(i); + if (activityDisplay.mDisplayId == displayId) { + return activityDisplay; + } + } + return null; + } + + /** + * Get an existing instance of {@link ActivityDisplay} or create new if there is a + * corresponding record in display manager. + */ + // TODO: Look into consolidating with getActivityDisplay() + ActivityDisplay getActivityDisplayOrCreate(int displayId) { + ActivityDisplay activityDisplay = getActivityDisplay(displayId); + if (activityDisplay != null) { + return activityDisplay; + } + if (mDisplayManager == null) { + // The system isn't fully initialized yet. + return null; + } + final Display display = mDisplayManager.getDisplay(displayId); + if (display == null) { + // The display is not registered in DisplayManager. + return null; + } + // The display hasn't been added to ActivityManager yet, create a new record now. + activityDisplay = new ActivityDisplay(this, display); + addChild(activityDisplay, ActivityDisplay.POSITION_BOTTOM); + return activityDisplay; + } + + /** Check if display with specified id is added to the list. */ + boolean isDisplayAdded(int displayId) { + return getActivityDisplayOrCreate(displayId) != null; + } + + ActivityRecord getDefaultDisplayHomeActivity() { + return getDefaultDisplayHomeActivityForUser(mCurrentUser); + } + + ActivityRecord getDefaultDisplayHomeActivityForUser(int userId) { + return getActivityDisplay(DEFAULT_DISPLAY).getHomeActivityForUser(userId); + } + + boolean startHomeOnAllDisplays(int userId, String reason) { + boolean homeStarted = false; + for (int i = mActivityDisplays.size() - 1; i >= 0; i--) { + final int displayId = mActivityDisplays.get(i).mDisplayId; + homeStarted |= startHomeOnDisplay(userId, reason, displayId); + } + return homeStarted; + } + + /** + * This starts home activity on displays that can have system decorations and only if the + * home activity can have multiple instances. + */ + boolean startHomeOnDisplay(int userId, String reason, int displayId) { + final Intent homeIntent = mService.getHomeIntent(); + final ActivityInfo aInfo = resolveHomeActivity(userId, homeIntent); + if (aInfo == null) { + return false; + } + + if (!canStartHomeOnDisplay(aInfo, displayId, + false /* allowInstrumenting */)) { + return false; + } + + // Update the reason for ANR debugging to verify if the user activity is the one that + // actually launched. + final String myReason = reason + ":" + userId + ":" + UserHandle.getUserId( + aInfo.applicationInfo.uid); + mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason, + displayId); + return true; + } + + /** + * This resolves the home activity info and updates the home component of the given intent. + * @return the home activity info if any. + */ + private ActivityInfo resolveHomeActivity(int userId, Intent homeIntent) { + final int flags = ActivityManagerService.STOCK_PM_FLAGS; + final ComponentName comp = homeIntent.getComponent(); + ActivityInfo aInfo = null; + try { + if (comp != null) { + // Factory test. + aInfo = AppGlobals.getPackageManager().getActivityInfo(comp, flags, userId); + } else { + final String resolvedType = + homeIntent.resolveTypeIfNeeded(mService.mContext.getContentResolver()); + final ResolveInfo info = AppGlobals.getPackageManager() + .resolveIntent(homeIntent, resolvedType, flags, userId); + if (info != null) { + aInfo = info.activityInfo; + } + } + } catch (RemoteException e) { + // ignore + } + + if (aInfo == null) { + Slog.wtf(TAG, "No home screen found for " + homeIntent, new Throwable()); + return null; + } + + homeIntent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name)); + aInfo = new ActivityInfo(aInfo); + aInfo.applicationInfo = mService.getAppInfoForUser(aInfo.applicationInfo, userId); + homeIntent.setFlags(homeIntent.getFlags() | FLAG_ACTIVITY_NEW_TASK); + return aInfo; + } + + boolean resumeHomeActivity(ActivityRecord prev, String reason, int displayId) { + if (!mService.isBooting() && !mService.isBooted()) { + // Not ready yet! + return false; + } + + if (displayId == INVALID_DISPLAY) { + displayId = DEFAULT_DISPLAY; + } + + final ActivityRecord r = getActivityDisplay(displayId).getHomeActivity(); + final String myReason = reason + " resumeHomeActivity"; + + // Only resume home activity if isn't finishing. + if (r != null && !r.finishing) { + r.moveFocusableActivityToTop(myReason); + return resumeFocusedStacksTopActivities(r.getStack(), prev, null); + } + return startHomeOnDisplay(mCurrentUser, myReason, displayId); + } + + /** + * Check if home activity start should be allowed on a display. + * @param homeInfo {@code ActivityInfo} of the home activity that is going to be launched. + * @param displayId The id of the target display. + * @param allowInstrumenting Whether launching home should be allowed if being instrumented. + * @return {@code true} if allow to launch, {@code false} otherwise. + */ + boolean canStartHomeOnDisplay(ActivityInfo homeInfo, int displayId, + boolean allowInstrumenting) { + if (mService.mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL + && mService.mTopAction == null) { + // We are running in factory test mode, but unable to find the factory test app, so + // just sit around displaying the error message and don't try to start anything. + return false; + } + + final WindowProcessController app = + mService.getProcessController(homeInfo.processName, homeInfo.applicationInfo.uid); + if (!allowInstrumenting && app != null && app.isInstrumenting()) { + // Don't do this if the home app is currently being instrumented. + return false; + } + + if (displayId == DEFAULT_DISPLAY || (displayId != INVALID_DISPLAY + && displayId == mService.mVr2dDisplayId)) { + // No restrictions to default display or vr 2d display. + return true; + } + + final ActivityDisplay display = getActivityDisplay(displayId); + if (display == null || display.isRemoved() || !display.supportsSystemDecorations()) { + // Can't launch home on display that doesn't support system decorations. + return false; + } + + final boolean supportMultipleInstance = homeInfo.launchMode != LAUNCH_SINGLE_TASK + && homeInfo.launchMode != LAUNCH_SINGLE_INSTANCE + && homeInfo.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q; + if (!supportMultipleInstance) { + // Can't launch home on other displays if it requested to be single instance. Also we + // don't allow home applications that target before Q to have multiple home activity + // instances because they may not be expected to have multiple home scenario and + // haven't explicitly request for single instance. + return false; + } + + return true; + } + + /** + * Ensure all activities visibility, update orientation and configuration. + * + * @param starting The currently starting activity or {@code null} if there is none. + * @param displayId The id of the display where operation is executed. + * @param markFrozenIfConfigChanged Whether to set {@link ActivityRecord#frozenBeforeDestroy} to + * {@code true} if config changed. + * @param deferResume Whether to defer resume while updating config. + * @return 'true' if starting activity was kept or wasn't provided, 'false' if it was relaunched + * because of configuration update. + */ + boolean ensureVisibilityAndConfig(ActivityRecord starting, int displayId, + boolean markFrozenIfConfigChanged, boolean deferResume) { + // First ensure visibility without updating the config just yet. We need this to know what + // activities are affecting configuration now. + // Passing null here for 'starting' param value, so that visibility of actual starting + // activity will be properly updated. + ensureActivitiesVisible(null /* starting */, 0 /* configChanges */, + false /* preserveWindows */, false /* notifyClients */); + + if (displayId == INVALID_DISPLAY) { + // The caller didn't provide a valid display id, skip updating config. + return true; + } + + // Force-update the orientation from the WindowManager, since we need the true configuration + // to send to the client now. + final Configuration config = mWindowManager.updateOrientationFromAppTokens( + getDisplayOverrideConfiguration(displayId), + starting != null && starting.mayFreezeScreenLocked(starting.app) + ? starting.appToken : null, + displayId, true /* forceUpdate */); + if (starting != null && markFrozenIfConfigChanged && config != null) { + starting.frozenBeforeDestroy = true; + } + + // Update the configuration of the activities on the display. + return mService.updateDisplayOverrideConfigurationLocked(config, starting, deferResume, + displayId); + } + + /** + * @return a list of activities which are the top ones in each visible stack. The first + * entry will be the focused activity. + */ + List<IBinder> getTopVisibleActivities() { + final ArrayList<IBinder> topActivityTokens = new ArrayList<>(); + final ActivityStack topFocusedStack = getTopDisplayFocusedStack(); + // Traverse all displays. + for (int i = mActivityDisplays.size() - 1; i >= 0; i--) { + final ActivityDisplay display = mActivityDisplays.get(i); + // Traverse all stacks on a display. + for (int j = display.getChildCount() - 1; j >= 0; --j) { + final ActivityStack stack = display.getChildAt(j); + // Get top activity from a visible stack and add it to the list. + if (stack.shouldBeVisible(null /* starting */)) { + final ActivityRecord top = stack.getTopActivity(); + if (top != null) { + if (stack == topFocusedStack) { + topActivityTokens.add(0, top.appToken); + } else { + topActivityTokens.add(top.appToken); + } + } + } + } + } + return topActivityTokens; + } + + ActivityStack getTopDisplayFocusedStack() { + for (int i = mActivityDisplays.size() - 1; i >= 0; --i) { + final ActivityStack focusedStack = mActivityDisplays.get(i).getFocusedStack(); + if (focusedStack != null) { + return focusedStack; + } + } + return null; + } + + ActivityRecord getTopResumedActivity() { + final ActivityStack focusedStack = getTopDisplayFocusedStack(); + if (focusedStack == null) { + return null; + } + final ActivityRecord resumedActivity = focusedStack.getResumedActivity(); + if (resumedActivity != null && resumedActivity.app != null) { + return resumedActivity; + } + // The top focused stack might not have a resumed activity yet - look on all displays in + // focus order. + for (int i = mActivityDisplays.size() - 1; i >= 0; --i) { + final ActivityDisplay display = mActivityDisplays.get(i); + final ActivityRecord resumedActivityOnDisplay = display.getResumedActivity(); + if (resumedActivityOnDisplay != null) { + return resumedActivityOnDisplay; + } + } + return null; + } + + boolean isFocusable(ConfigurationContainer container, boolean alwaysFocusable) { + if (container.inSplitScreenPrimaryWindowingMode() && mIsDockMinimized) { + return false; + } + + return container.getWindowConfiguration().canReceiveKeys() || alwaysFocusable; + } + + boolean isTopDisplayFocusedStack(ActivityStack stack) { + return stack != null && stack == getTopDisplayFocusedStack(); + } + + void updatePreviousProcess(ActivityRecord r) { + // Now that this process has stopped, we may want to consider it to be the previous app to + // try to keep around in case the user wants to return to it. + + // First, found out what is currently the foreground app, so that we don't blow away the + // previous app if this activity is being hosted by the process that is actually still the + // foreground. + WindowProcessController fgApp = null; + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ActivityDisplay display = mActivityDisplays.get(displayNdx); + for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = display.getChildAt(stackNdx); + if (isTopDisplayFocusedStack(stack)) { + final ActivityRecord resumedActivity = stack.getResumedActivity(); + if (resumedActivity != null) { + fgApp = resumedActivity.app; + } else if (stack.mPausingActivity != null) { + fgApp = stack.mPausingActivity.app; + } + break; + } + } + } + + // Now set this one as the previous process, only if that really makes sense to. + if (r.hasProcess() && fgApp != null && r.app != fgApp + && r.lastVisibleTime > mService.mPreviousProcessVisibleTime + && r.app != mService.mHomeProcess) { + mService.mPreviousProcess = r.app; + mService.mPreviousProcessVisibleTime = r.lastVisibleTime; + } + } + + boolean attachApplication(WindowProcessController app) throws RemoteException { + final String processName = app.mName; + boolean didSomething = false; + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ActivityDisplay display = mActivityDisplays.get(displayNdx); + final ActivityStack stack = display.getFocusedStack(); + if (stack != null) { + stack.getAllRunningVisibleActivitiesLocked(mTmpActivityList); + final ActivityRecord top = stack.topRunningActivityLocked(); + final int size = mTmpActivityList.size(); + for (int i = 0; i < size; i++) { + final ActivityRecord activity = mTmpActivityList.get(i); + if (activity.app == null && app.mUid == activity.info.applicationInfo.uid + && processName.equals(activity.processName)) { + try { + if (mStackSupervisor.realStartActivityLocked(activity, app, + top == activity /* andResume */, true /* checkConfig */)) { + didSomething = true; + } + } catch (RemoteException e) { + Slog.w(TAG, "Exception in new application when starting activity " + + top.intent.getComponent().flattenToShortString(), e); + throw e; + } + } + } + } + } + if (!didSomething) { + ensureActivitiesVisible(null, 0, false /* preserve_windows */); + } + return didSomething; + } + + /** + * Make sure that all activities that need to be visible in the system actually are and update + * their configuration. + */ + void ensureActivitiesVisible(ActivityRecord starting, int configChanges, + boolean preserveWindows) { + ensureActivitiesVisible(starting, configChanges, preserveWindows, true /* notifyClients */); + } + + /** + * @see #ensureActivitiesVisible(ActivityRecord, int, boolean) + */ + void ensureActivitiesVisible(ActivityRecord starting, int configChanges, + boolean preserveWindows, boolean notifyClients) { + mStackSupervisor.getKeyguardController().beginActivityVisibilityUpdate(); + try { + // First the front stacks. In case any are not fullscreen and are in front of home. + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ActivityDisplay display = mActivityDisplays.get(displayNdx); + for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = display.getChildAt(stackNdx); + stack.ensureActivitiesVisibleLocked(starting, configChanges, preserveWindows, + notifyClients); + } + } + } finally { + mStackSupervisor.getKeyguardController().endActivityVisibilityUpdate(); + } + } + + boolean switchUser(int userId, UserState uss) { + final int focusStackId = getTopDisplayFocusedStack().getStackId(); + // We dismiss the docked stack whenever we switch users. + final ActivityStack dockedStack = getDefaultDisplay().getSplitScreenPrimaryStack(); + if (dockedStack != null) { + mStackSupervisor.moveTasksToFullscreenStackLocked( + dockedStack, dockedStack.isFocusedStackOnDisplay()); + } + // Also dismiss the pinned stack whenever we switch users. Removing the pinned stack will + // also cause all tasks to be moved to the fullscreen stack at a position that is + // appropriate. + removeStacksInWindowingModes(WINDOWING_MODE_PINNED); + + mUserStackInFront.put(mCurrentUser, focusStackId); + final int restoreStackId = + mUserStackInFront.get(userId, getDefaultDisplay().getHomeStack().mStackId); + mCurrentUser = userId; + + mStackSupervisor.mStartingUsers.add(uss); + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ActivityDisplay display = mActivityDisplays.get(displayNdx); + for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = display.getChildAt(stackNdx); + stack.switchUserLocked(userId); + TaskRecord task = stack.topTask(); + if (task != null) { + stack.positionChildWindowContainerAtTop(task); + } + } + } + + ActivityStack stack = getStack(restoreStackId); + if (stack == null) { + stack = getDefaultDisplay().getHomeStack(); + } + final boolean homeInFront = stack.isActivityTypeHome(); + if (stack.isOnHomeDisplay()) { + stack.moveToFront("switchUserOnHomeDisplay"); + } else { + // Stack was moved to another display while user was swapped out. + resumeHomeActivity(null, "switchUserOnOtherDisplay", DEFAULT_DISPLAY); + } + return homeInFront; + } + + void removeUser(int userId) { + mUserStackInFront.delete(userId); + } + + /** + * Update the last used stack id for non-current user (current user's last + * used stack is the focused stack) + */ + void updateUserStack(int userId, ActivityStack stack) { + if (userId != mCurrentUser) { + mUserStackInFront.put(userId, stack != null ? stack.getStackId() + : getDefaultDisplay().getHomeStack().mStackId); + } + } + + void resizeStack(ActivityStack stack, Rect bounds, Rect tempTaskBounds, + Rect tempTaskInsetBounds, boolean preserveWindows, boolean allowResizeInDockedMode, + boolean deferResume) { + + if (stack.inSplitScreenPrimaryWindowingMode()) { + mStackSupervisor.resizeDockedStackLocked(bounds, tempTaskBounds, + tempTaskInsetBounds, null, null, preserveWindows, deferResume); + return; + } + + final boolean splitScreenActive = getDefaultDisplay().hasSplitScreenPrimaryStack(); + if (!allowResizeInDockedMode + && !stack.getWindowConfiguration().tasksAreFloating() && splitScreenActive) { + // If the docked stack exists, don't resize non-floating stacks independently of the + // size computed from the docked stack size (otherwise they will be out of sync) + return; + } + + Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeStack_" + stack.mStackId); + mWindowManager.deferSurfaceLayout(); + try { + if (stack.affectedBySplitScreenResize()) { + if (bounds == null && stack.inSplitScreenWindowingMode()) { + // null bounds = fullscreen windowing mode...at least for now. + stack.setWindowingMode(WINDOWING_MODE_FULLSCREEN); + } else if (splitScreenActive) { + // If we are in split-screen mode and this stack support split-screen, then + // it should be split-screen secondary mode. i.e. adjacent to the docked stack. + stack.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY); + } + } + stack.resize(bounds, tempTaskBounds, tempTaskInsetBounds); + if (!deferResume) { + stack.ensureVisibleActivitiesConfigurationLocked( + stack.topRunningActivityLocked(), preserveWindows); + } + } finally { + mWindowManager.continueSurfaceLayout(); + Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); + } + } + + /** + * Move stack with all its existing content to specified display. + * @param stackId Id of stack to move. + * @param displayId Id of display to move stack to. + * @param onTop Indicates whether container should be place on top or on bottom. + */ + void moveStackToDisplay(int stackId, int displayId, boolean onTop) { + final ActivityDisplay activityDisplay = getActivityDisplayOrCreate(displayId); + if (activityDisplay == null) { + throw new IllegalArgumentException("moveStackToDisplay: Unknown displayId=" + + displayId); + } + final ActivityStack stack = getStack(stackId); + if (stack == null) { + throw new IllegalArgumentException("moveStackToDisplay: Unknown stackId=" + + stackId); + } + + final ActivityDisplay currentDisplay = stack.getDisplay(); + if (currentDisplay == null) { + throw new IllegalStateException("moveStackToDisplay: Stack with stack=" + stack + + " is not attached to any display."); + } + + if (currentDisplay.mDisplayId == displayId) { + throw new IllegalArgumentException("Trying to move stack=" + stack + + " to its current displayId=" + displayId); + } + + stack.reparent(activityDisplay, onTop, false /* displayRemoved */); + // TODO(multi-display): resize stacks properly if moved from split-screen. + } + + boolean moveTopStackActivityToPinnedStack(int stackId) { + final ActivityStack stack = getStack(stackId); + if (stack == null) { + throw new IllegalArgumentException( + "moveTopStackActivityToPinnedStack: Unknown stackId=" + stackId); + } + + final ActivityRecord r = stack.topRunningActivityLocked(); + if (r == null) { + Slog.w(TAG, "moveTopStackActivityToPinnedStack: No top running activity" + + " in stack=" + stack); + return false; + } + + if (!mService.mForceResizableActivities && !r.supportsPictureInPicture()) { + Slog.w(TAG, "moveTopStackActivityToPinnedStack: Picture-In-Picture not supported for " + + " r=" + r); + return false; + } + + moveActivityToPinnedStack(r, null /* sourceBounds */, 0f /* aspectRatio */, + "moveTopActivityToPinnedStack"); + return true; + } + + void moveActivityToPinnedStack(ActivityRecord r, Rect sourceHintBounds, float aspectRatio, + String reason) { + + mWindowManager.deferSurfaceLayout(); + + final ActivityDisplay display = r.getStack().getDisplay(); + PinnedActivityStack stack = display.getPinnedStack(); + + // This will clear the pinned stack by moving an existing task to the full screen stack, + // ensuring only one task is present. + if (stack != null) { + mStackSupervisor.moveTasksToFullscreenStackLocked(stack, !ON_TOP); + } + + // Need to make sure the pinned stack exist so we can resize it below... + stack = display.getOrCreateStack(WINDOWING_MODE_PINNED, r.getActivityType(), ON_TOP); + + // Calculate the target bounds here before the task is reparented back into pinned windowing + // mode (which will reset the saved bounds) + final Rect destBounds = stack.getDefaultPictureInPictureBounds(aspectRatio); + + try { + final TaskRecord task = r.getTask(); + // Resize the pinned stack to match the current size of the task the activity we are + // going to be moving is currently contained in. We do this to have the right starting + // animation bounds for the pinned stack to the desired bounds the caller wants. + resizeStack(stack, task.getOverrideBounds(), null /* tempTaskBounds */, + null /* tempTaskInsetBounds */, !PRESERVE_WINDOWS, + true /* allowResizeInDockedMode */, !DEFER_RESUME); + + if (task.mActivities.size() == 1) { + // Defer resume until below, and do not schedule PiP changes until we animate below + task.reparent(stack, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, !ANIMATE, DEFER_RESUME, + false /* schedulePictureInPictureModeChange */, reason); + } else { + // There are multiple activities in the task and moving the top activity should + // reveal/leave the other activities in their original task. + + // Currently, we don't support reparenting activities across tasks in two different + // stacks, so instead, just create a new task in the same stack, reparent the + // activity into that task, and then reparent the whole task to the new stack. This + // ensures that all the necessary work to migrate states in the old and new stacks + // is also done. + final TaskRecord newTask = task.getStack().createTaskRecord( + mStackSupervisor.getNextTaskIdForUserLocked(r.userId), r.info, + r.intent, null, null, true); + r.reparent(newTask, MAX_VALUE, "moveActivityToStack"); + + // Defer resume until below, and do not schedule PiP changes until we animate below + newTask.reparent(stack, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, !ANIMATE, + DEFER_RESUME, false /* schedulePictureInPictureModeChange */, reason); + } + + // Reset the state that indicates it can enter PiP while pausing after we've moved it + // to the pinned stack + r.supportsEnterPipOnTaskSwitch = false; + } finally { + mWindowManager.continueSurfaceLayout(); + } + + stack.animateResizePinnedStack(sourceHintBounds, destBounds, -1 /* animationDuration */, + true /* fromFullscreen */); + + // Update the visibility of all activities after the they have been reparented to the new + // stack. This MUST run after the animation above is scheduled to ensure that the windows + // drawn signal is scheduled after the bounds animation start call on the bounds animator + // thread. + ensureActivitiesVisible(null, 0, false /* preserveWindows */); + resumeFocusedStacksTopActivities(); + + mService.getTaskChangeNotificationController().notifyActivityPinned(r); + } + + void executeAppTransitionForAllDisplay() { + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ActivityDisplay display = mActivityDisplays.get(displayNdx); + display.getWindowContainerController().executeAppTransition(); + } + } + + void setDockedStackMinimized(boolean minimized) { + // Get currently focused stack before setting mIsDockMinimized. We do this because if + // split-screen is active, primary stack will not be focusable (see #isFocusable) while + // still occluding other stacks. This will cause getTopDisplayFocusedStack() to return null. + final ActivityStack current = getTopDisplayFocusedStack(); + mIsDockMinimized = minimized; + if (mIsDockMinimized) { + if (current.inSplitScreenPrimaryWindowingMode()) { + // The primary split-screen stack can't be focused while it is minimize, so move + // focus to something else. + current.adjustFocusToNextFocusableStack("setDockedStackMinimized"); + } + } + } + + ActivityRecord findTask(ActivityRecord r, int preferredDisplayId) { + if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Looking for task of " + r); + mTmpFindTaskResult.clear(); + + // Looking up task on preferred display first + final ActivityDisplay preferredDisplay = getActivityDisplay(preferredDisplayId); + if (preferredDisplay != null) { + preferredDisplay.findTaskLocked(r, true /* isPreferredDisplay */, mTmpFindTaskResult); + if (mTmpFindTaskResult.mIdealMatch) { + return mTmpFindTaskResult.mRecord; + } + } + + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ActivityDisplay display = mActivityDisplays.get(displayNdx); + if (display.mDisplayId == preferredDisplayId) { + continue; + } + + display.findTaskLocked(r, false /* isPreferredDisplay */, mTmpFindTaskResult); + if (mTmpFindTaskResult.mIdealMatch) { + return mTmpFindTaskResult.mRecord; + } + } + + if (DEBUG_TASKS && mTmpFindTaskResult.mRecord == null) Slog.d(TAG_TASKS, "No task found"); + return mTmpFindTaskResult.mRecord; + } + + /** + * Finish the topmost activities in all stacks that belong to the crashed app. + * @param app The app that crashed. + * @param reason Reason to perform this action. + * @return The task id that was finished in this stack, or INVALID_TASK_ID if none was finished. + */ + int finishTopCrashedActivities(WindowProcessController app, String reason) { + TaskRecord finishedTask = null; + ActivityStack focusedStack = getTopDisplayFocusedStack(); + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ActivityDisplay display = mActivityDisplays.get(displayNdx); + // It is possible that request to finish activity might also remove its task and stack, + // so we need to be careful with indexes in the loop and check child count every time. + for (int stackNdx = 0; stackNdx < display.getChildCount(); ++stackNdx) { + final ActivityStack stack = display.getChildAt(stackNdx); + final TaskRecord t = stack.finishTopCrashedActivityLocked(app, reason); + if (stack == focusedStack || finishedTask == null) { + finishedTask = t; + } + } + } + return finishedTask != null ? finishedTask.taskId : INVALID_TASK_ID; + } + + boolean resumeFocusedStacksTopActivities() { + return resumeFocusedStacksTopActivities(null, null, null); + } + + boolean resumeFocusedStacksTopActivities( + ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) { + + if (!mStackSupervisor.readyToResume()) { + return false; + } + + if (targetStack != null && (targetStack.isTopStackOnDisplay() + || getTopDisplayFocusedStack() == targetStack)) { + return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions); + } + + // Resume all top activities in focused stacks on all displays. + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ActivityDisplay display = mActivityDisplays.get(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; + } + + void applySleepTokens(boolean applyToStacks) { + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + // Set the sleeping state of the display. + final ActivityDisplay display = mActivityDisplays.get(displayNdx); + final boolean displayShouldSleep = display.shouldSleep(); + if (displayShouldSleep == display.isSleeping()) { + continue; + } + display.setIsSleeping(displayShouldSleep); + + if (!applyToStacks) { + continue; + } + + // Set the sleeping state of the stacks on the display. + for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = display.getChildAt(stackNdx); + if (displayShouldSleep) { + stack.goToSleepIfPossible(false /* shuttingDown */); + } else { + stack.awakeFromSleepingLocked(); + if (stack.isFocusedStackOnDisplay() + && !mStackSupervisor.getKeyguardController() + .isKeyguardOrAodShowing(display.mDisplayId)) { + // If the keyguard is unlocked - resume immediately. + // 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. + resumeFocusedStacksTopActivities(); + } + } + } + + if (displayShouldSleep || mStackSupervisor.mGoingToSleepActivities.isEmpty()) { + continue; + } + // The display is awake now, so clean up the going to sleep list. + for (Iterator<ActivityRecord> it = + mStackSupervisor.mGoingToSleepActivities.iterator(); it.hasNext(); ) { + final ActivityRecord r = it.next(); + if (r.getDisplayId() == display.mDisplayId) { + it.remove(); + } + } + } + } + + protected <T extends ActivityStack> T getStack(int stackId) { + for (int i = mActivityDisplays.size() - 1; i >= 0; --i) { + final T stack = mActivityDisplays.get(i).getStack(stackId); + if (stack != null) { + return stack; + } + } + return null; + } + + /** @see ActivityDisplay#getStack(int, int) */ + private <T extends ActivityStack> T getStack(int windowingMode, int activityType) { + for (int i = mActivityDisplays.size() - 1; i >= 0; --i) { + final T stack = mActivityDisplays.get(i).getStack(windowingMode, activityType); + if (stack != null) { + return stack; + } + } + return null; + } + + private ActivityManager.StackInfo getStackInfo(ActivityStack stack) { + final int displayId = stack.mDisplayId; + final ActivityDisplay display = getActivityDisplay(displayId); + ActivityManager.StackInfo info = new ActivityManager.StackInfo(); + stack.getWindowContainerBounds(info.bounds); + info.displayId = displayId; + info.stackId = stack.mStackId; + info.userId = stack.mCurrentUser; + info.visible = stack.shouldBeVisible(null); + // A stack might be not attached to a display. + info.position = display != null ? display.getIndexOf(stack) : 0; + info.configuration.setTo(stack.getConfiguration()); + + ArrayList<TaskRecord> tasks = stack.getAllTasks(); + final int numTasks = tasks.size(); + int[] taskIds = new int[numTasks]; + String[] taskNames = new String[numTasks]; + Rect[] taskBounds = new Rect[numTasks]; + int[] taskUserIds = new int[numTasks]; + for (int i = 0; i < numTasks; ++i) { + final TaskRecord task = tasks.get(i); + taskIds[i] = task.taskId; + taskNames[i] = task.origActivity != null ? task.origActivity.flattenToString() + : task.realActivity != null ? task.realActivity.flattenToString() + : task.getTopActivity() != null ? task.getTopActivity().packageName + : "unknown"; + taskBounds[i] = new Rect(); + task.getWindowContainerBounds(taskBounds[i]); + taskUserIds[i] = task.userId; + } + info.taskIds = taskIds; + info.taskNames = taskNames; + info.taskBounds = taskBounds; + info.taskUserIds = taskUserIds; + + final ActivityRecord top = stack.topRunningActivityLocked(); + info.topActivity = top != null ? top.intent.getComponent() : null; + return info; + } + + ActivityManager.StackInfo getStackInfo(int stackId) { + ActivityStack stack = getStack(stackId); + if (stack != null) { + return getStackInfo(stack); + } + return null; + } + + ActivityManager.StackInfo getStackInfo(int windowingMode, int activityType) { + final ActivityStack stack = getStack(windowingMode, activityType); + return (stack != null) ? getStackInfo(stack) : null; + } + + ArrayList<ActivityManager.StackInfo> getAllStackInfos() { + ArrayList<ActivityManager.StackInfo> list = new ArrayList<>(); + for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) { + final ActivityDisplay display = mActivityDisplays.get(displayNdx); + for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = display.getChildAt(stackNdx); + list.add(getStackInfo(stack)); + } + } + return list; + } + + void deferUpdateBounds(int activityType) { + final ActivityStack stack = getStack(WINDOWING_MODE_UNDEFINED, activityType); + if (stack != null) { + stack.deferUpdateBounds(); + } + } + + void continueUpdateBounds(int activityType) { + final ActivityStack stack = getStack(WINDOWING_MODE_UNDEFINED, activityType); + if (stack != null) { + stack.continueUpdateBounds(); + } + } + + @Override + public void onDisplayAdded(int displayId) { + if (DEBUG_STACK) Slog.v(TAG, "Display added displayId=" + displayId); + synchronized (mService.mGlobalLock) { + getActivityDisplayOrCreate(displayId); + // Do not start home before booting, or it may accidentally finish booting before it + // starts. Instead, we expect home activities to be launched when the system is ready + // (ActivityManagerService#systemReady). + if (mService.isBooted() || mService.isBooting()) { + startHomeOnDisplay(mCurrentUser, "displayAdded", displayId); + } + } + } + + @Override + public void onDisplayRemoved(int displayId) { + if (DEBUG_STACK) Slog.v(TAG, "Display removed displayId=" + displayId); + if (displayId == DEFAULT_DISPLAY) { + throw new IllegalArgumentException("Can't remove the primary display."); + } + + synchronized (mService.mGlobalLock) { + final ActivityDisplay activityDisplay = getActivityDisplay(displayId); + if (activityDisplay == null) { + return; + } + + activityDisplay.remove(); + } + } + + @Override + public void onDisplayChanged(int displayId) { + if (DEBUG_STACK) Slog.v(TAG, "Display changed displayId=" + displayId); + synchronized (mService.mGlobalLock) { + final ActivityDisplay activityDisplay = getActivityDisplay(displayId); + if (activityDisplay != null) { + activityDisplay.onDisplayChanged(); + } + } + } + + /** Update lists of UIDs that are present on displays and have access to them. */ + void updateUIDsPresentOnDisplay() { + mDisplayAccessUIDs.clear(); + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ActivityDisplay activityDisplay = mActivityDisplays.get(displayNdx); + // Only bother calculating the whitelist for private displays + if (activityDisplay.isPrivate()) { + mDisplayAccessUIDs.append( + activityDisplay.mDisplayId, activityDisplay.getPresentUIDs()); + } + } + // Store updated lists in DisplayManager. Callers from outside of AM should get them there. + mDisplayManagerInternal.setDisplayAccessUIDs(mDisplayAccessUIDs); + } + + ActivityStack findStackBehind(ActivityStack stack) { + final ActivityDisplay display = getActivityDisplay(stack.mDisplayId); + if (display != null) { + for (int i = display.getChildCount() - 1; i >= 0; i--) { + if (display.getChildAt(i) == stack && i > 0) { + return display.getChildAt(i - 1); + } + } + } + throw new IllegalStateException("Failed to find a stack behind stack=" + stack + + " in=" + display); + } + + @Override + protected int getChildCount() { + return mActivityDisplays.size(); + } + + @Override + protected ActivityDisplay getChildAt(int index) { + return mActivityDisplays.get(index); + } + + @Override + protected ConfigurationContainer getParent() { + return null; + } + + @Override + public void onChildPositionChanged(DisplayWindowController childController, int position) { + // Assume AM lock is held from positionChildAt of controller in each hierarchy. + final ActivityDisplay display = getActivityDisplay(childController.getDisplayId()); + if (display != null) { + positionChildAt(display, position); + } + } + + /** Change the z-order of the given display. */ + private void positionChildAt(ActivityDisplay display, int position) { + if (position >= mActivityDisplays.size()) { + position = mActivityDisplays.size() - 1; + } else if (position < 0) { + position = 0; + } + + if (mActivityDisplays.isEmpty()) { + mActivityDisplays.add(display); + } else if (mActivityDisplays.get(position) != display) { + mActivityDisplays.remove(display); + mActivityDisplays.add(position, display); + } + } + + @VisibleForTesting + void addChild(ActivityDisplay activityDisplay, int position) { + positionChildAt(activityDisplay, position); + mWindowContainerController.positionChildAt( + activityDisplay.getWindowContainerController(), position); + } + + void removeChild(ActivityDisplay activityDisplay) { + // The caller must tell the controller of {@link ActivityDisplay} to release its container + // {@link DisplayContent}. That is done in {@link ActivityDisplay#releaseSelfIfNeeded}). + mActivityDisplays.remove(activityDisplay); + } + + Configuration getDisplayOverrideConfiguration(int displayId) { + final ActivityDisplay activityDisplay = getActivityDisplayOrCreate(displayId); + if (activityDisplay == null) { + throw new IllegalArgumentException("No display found with id: " + displayId); + } + + return activityDisplay.getOverrideConfiguration(); + } + + void setDisplayOverrideConfiguration(Configuration overrideConfiguration, int displayId) { + final ActivityDisplay activityDisplay = getActivityDisplayOrCreate(displayId); + if (activityDisplay == null) { + throw new IllegalArgumentException("No display found with id: " + displayId); + } + + activityDisplay.onOverrideConfigurationChanged(overrideConfiguration); + } + + void prepareForShutdown() { + for (int i = 0; i < mActivityDisplays.size(); i++) { + createSleepToken("shutdown", mActivityDisplays.get(i).mDisplayId); + } + } + + ActivityTaskManagerInternal.SleepToken createSleepToken(String tag, int displayId) { + final ActivityDisplay display = getActivityDisplay(displayId); + if (display == null) { + throw new IllegalArgumentException("Invalid display: " + displayId); + } + + final SleepTokenImpl token = new SleepTokenImpl(tag, displayId); + mSleepTokens.add(token); + display.mAllSleepTokens.add(token); + return token; + } + + private void removeSleepToken(SleepTokenImpl token) { + mSleepTokens.remove(token); + + final ActivityDisplay display = getActivityDisplay(token.mDisplayId); + if (display != null) { + display.mAllSleepTokens.remove(token); + if (display.mAllSleepTokens.isEmpty()) { + mService.updateSleepIfNeededLocked(); + } + } + } + + void addStartingWindowsForVisibleActivities(boolean taskSwitch) { + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ActivityDisplay display = mActivityDisplays.get(displayNdx); + for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = display.getChildAt(stackNdx); + stack.addStartingWindowsForVisibleActivities(taskSwitch); + } + } + } + + void invalidateTaskLayers() { + mTaskLayersChanged = true; + } + + void rankTaskLayersIfNeeded() { + if (!mTaskLayersChanged) { + return; + } + mTaskLayersChanged = false; + for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); displayNdx++) { + final ActivityDisplay display = mActivityDisplays.get(displayNdx); + int baseLayer = 0; + for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = display.getChildAt(stackNdx); + baseLayer += stack.rankTaskLayers(baseLayer); + } + } + } + + void clearOtherAppTimeTrackers(AppTimeTracker except) { + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ActivityDisplay display = mActivityDisplays.get(displayNdx); + for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = display.getChildAt(stackNdx); + stack.clearOtherAppTimeTrackers(except); + } + } + } + + void scheduleDestroyAllActivities(WindowProcessController app, String reason) { + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ActivityDisplay display = mActivityDisplays.get(displayNdx); + for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = display.getChildAt(stackNdx); + stack.scheduleDestroyActivities(app, reason); + } + } + } + + void releaseSomeActivitiesLocked(WindowProcessController app, String reason) { + // Tasks is non-null only if two or more tasks are found. + ArraySet<TaskRecord> tasks = app.getReleaseSomeActivitiesTasks(); + if (tasks == null) { + if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Didn't find two or more tasks to release"); + return; + } + // If we have activities in multiple tasks that are in a position to be destroyed, + // let's iterate through the tasks and release the oldest one. + final int numDisplays = mActivityDisplays.size(); + for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { + final ActivityDisplay display = mActivityDisplays.get(displayNdx); + final int stackCount = display.getChildCount(); + // Step through all stacks starting from behind, to hit the oldest things first. + for (int stackNdx = 0; stackNdx < stackCount; stackNdx++) { + final ActivityStack stack = display.getChildAt(stackNdx); + // Try to release activities in this stack; if we manage to, we are done. + if (stack.releaseSomeActivitiesLocked(app, tasks, reason) > 0) { + return; + } + } + } + } + + // Tries to put all activity stacks to sleep. Returns true if all stacks were + // successfully put to sleep. + boolean putStacksToSleep(boolean allowDelay, boolean shuttingDown) { + boolean allSleep = true; + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ActivityDisplay display = mActivityDisplays.get(displayNdx); + for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = display.getChildAt(stackNdx); + if (allowDelay) { + allSleep &= stack.goToSleepIfPossible(shuttingDown); + } else { + stack.goToSleep(); + } + } + } + return allSleep; + } + + void handleAppCrash(WindowProcessController app) { + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ActivityDisplay display = mActivityDisplays.get(displayNdx); + for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = display.getChildAt(stackNdx); + stack.handleAppCrash(app); + } + } + } + + ActivityRecord findActivity(Intent intent, ActivityInfo info, boolean compareIntentFilters) { + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ActivityDisplay display = mActivityDisplays.get(displayNdx); + for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = display.getChildAt(stackNdx); + final ActivityRecord ar = stack.findActivityLocked( + intent, info, compareIntentFilters); + if (ar != null) { + return ar; + } + } + } + return null; + } + + boolean hasAwakeDisplay() { + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ActivityDisplay display = mActivityDisplays.get(displayNdx); + if (!display.shouldSleep()) { + return true; + } + } + return false; + } + + <T extends ActivityStack> T getLaunchStack(@Nullable ActivityRecord r, + @Nullable ActivityOptions options, @Nullable TaskRecord candidateTask, boolean onTop) { + return getLaunchStack(r, options, candidateTask, onTop, null /* launchParams */); + } + + /** + * Returns the right stack to use for launching factoring in all the input parameters. + * + * @param r The activity we are trying to launch. Can be null. + * @param options The activity options used to the launch. Can be null. + * @param candidateTask The possible task the activity might be launched in. Can be null. + * @params launchParams The resolved launch params to use. + * + * @return The stack to use for the launch or INVALID_STACK_ID. + */ + <T extends ActivityStack> T getLaunchStack(@Nullable ActivityRecord r, + @Nullable ActivityOptions options, @Nullable TaskRecord candidateTask, boolean onTop, + @Nullable LaunchParamsController.LaunchParams launchParams) { + int taskId = INVALID_TASK_ID; + int displayId = INVALID_DISPLAY; + //Rect bounds = null; + + // We give preference to the launch preference in activity options. + if (options != null) { + taskId = options.getLaunchTaskId(); + displayId = options.getLaunchDisplayId(); + } + + // First preference for stack goes to the task Id set in the activity options. Use the stack + // associated with that if possible. + if (taskId != INVALID_TASK_ID) { + // Temporarily set the task id to invalid in case in re-entry. + options.setLaunchTaskId(INVALID_TASK_ID); + final TaskRecord task = anyTaskForId(taskId, + MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, options, onTop); + options.setLaunchTaskId(taskId); + if (task != null) { + return task.getStack(); + } + } + + final int activityType = resolveActivityType(r, options, candidateTask); + T stack; + + // Next preference for stack goes to the display Id set the candidate display. + if (launchParams != null && launchParams.mPreferredDisplayId != INVALID_DISPLAY) { + displayId = launchParams.mPreferredDisplayId; + } + if (displayId != INVALID_DISPLAY && canLaunchOnDisplay(r, displayId)) { + if (r != null) { + stack = (T) getValidLaunchStackOnDisplay(displayId, r, candidateTask, options, + launchParams); + if (stack != null) { + return stack; + } + } + final ActivityDisplay display = getActivityDisplayOrCreate(displayId); + if (display != null) { + stack = display.getOrCreateStack(r, options, candidateTask, activityType, onTop); + if (stack != null) { + return stack; + } + } + } + + // Give preference to the stack and display of the input task and activity if they match the + // mode we want to launch into. + stack = null; + ActivityDisplay display = null; + if (candidateTask != null) { + stack = candidateTask.getStack(); + } + if (stack == null && r != null) { + stack = r.getStack(); + } + if (stack != null) { + display = stack.getDisplay(); + if (display != null && canLaunchOnDisplay(r, display.mDisplayId)) { + int windowingMode = launchParams != null ? launchParams.mWindowingMode + : WindowConfiguration.WINDOWING_MODE_UNDEFINED; + if (windowingMode == WindowConfiguration.WINDOWING_MODE_UNDEFINED) { + windowingMode = display.resolveWindowingMode(r, options, candidateTask, + activityType); + } + if (stack.isCompatible(windowingMode, activityType)) { + return stack; + } + if (windowingMode == WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY + && display.getSplitScreenPrimaryStack() == stack + && candidateTask == stack.topTask()) { + // This is a special case when we try to launch an activity that is currently on + // top of split-screen primary stack, but is targeting split-screen secondary. + // In this case we don't want to move it to another stack. + // TODO(b/78788972): Remove after differentiating between preferred and required + // launch options. + return stack; + } + } + } + + if (display == null || !canLaunchOnDisplay(r, display.mDisplayId)) { + display = getDefaultDisplay(); + } + + return display.getOrCreateStack(r, options, candidateTask, activityType, onTop); + } + + /** @return true if activity record is null or can be launched on provided display. */ + private boolean canLaunchOnDisplay(ActivityRecord r, int displayId) { + if (r == null) { + return true; + } + return r.canBeLaunchedOnDisplay(displayId); + } + + /** + * Get a topmost stack on the display, that is a valid launch stack for specified activity. + * If there is no such stack, new dynamic stack can be created. + * @param displayId Target display. + * @param r Activity that should be launched there. + * @param candidateTask The possible task the activity might be put in. + * @return Existing stack if there is a valid one, new dynamic stack if it is valid or null. + */ + private ActivityStack getValidLaunchStackOnDisplay(int displayId, @NonNull ActivityRecord r, + @Nullable TaskRecord candidateTask, @Nullable ActivityOptions options, + @Nullable LaunchParamsController.LaunchParams launchParams) { + final ActivityDisplay activityDisplay = getActivityDisplayOrCreate(displayId); + if (activityDisplay == null) { + throw new IllegalArgumentException( + "Display with displayId=" + displayId + " not found."); + } + + if (!r.canBeLaunchedOnDisplay(displayId)) { + return null; + } + + // If {@code r} is already in target display and its task is the same as the candidate task, + // the intention should be getting a launch stack for the reusable activity, so we can use + // the existing stack. + if (r.getDisplayId() == displayId && r.getTask() == candidateTask) { + return candidateTask.getStack(); + } + + // Return the topmost valid stack on the display. + for (int i = activityDisplay.getChildCount() - 1; i >= 0; --i) { + final ActivityStack stack = activityDisplay.getChildAt(i); + if (isValidLaunchStack(stack, r)) { + return stack; + } + } + + // If there is no valid stack on the external display - check if new dynamic stack will do. + if (displayId != DEFAULT_DISPLAY) { + final int windowingMode; + if (launchParams != null) { + // When launch params is not null, we always defer to its windowing mode. Sometimes + // it could be unspecified, which indicates it should inherit windowing mode from + // display. + windowingMode = launchParams.mWindowingMode; + } else { + windowingMode = options != null ? options.getLaunchWindowingMode() + : r.getWindowingMode(); + } + final int activityType = + options != null && options.getLaunchActivityType() != ACTIVITY_TYPE_UNDEFINED + ? options.getLaunchActivityType() : r.getActivityType(); + return activityDisplay.createStack(windowingMode, activityType, true /*onTop*/); + } + + Slog.w(TAG, "getValidLaunchStackOnDisplay: can't launch on displayId " + displayId); + return null; + } + + ActivityStack getValidLaunchStackOnDisplay(int displayId, @NonNull ActivityRecord r, + @Nullable ActivityOptions options, + @Nullable LaunchParamsController.LaunchParams launchParams) { + return getValidLaunchStackOnDisplay(displayId, r, null /* candidateTask */, options, + launchParams); + } + + // TODO: Can probably be consolidated into getLaunchStack()... + private boolean isValidLaunchStack(ActivityStack stack, ActivityRecord r) { + switch (stack.getActivityType()) { + case ACTIVITY_TYPE_HOME: return r.isActivityTypeHome(); + case ACTIVITY_TYPE_RECENTS: return r.isActivityTypeRecents(); + case ACTIVITY_TYPE_ASSISTANT: return r.isActivityTypeAssistant(); + } + // There is a 1-to-1 relationship between stack and task when not in + // primary split-windowing mode. + if (stack.getWindowingMode() != WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) { + return false; + } else { + return r.supportsSplitScreenWindowingMode(); + } + } + + int resolveActivityType(@Nullable ActivityRecord r, @Nullable ActivityOptions options, + @Nullable TaskRecord task) { + // Preference is given to the activity type for the activity then the task since the type + // once set shouldn't change. + int activityType = r != null ? r.getActivityType() : ACTIVITY_TYPE_UNDEFINED; + if (activityType == ACTIVITY_TYPE_UNDEFINED && task != null) { + activityType = task.getActivityType(); + } + if (activityType != ACTIVITY_TYPE_UNDEFINED) { + return activityType; + } + if (options != null) { + activityType = options.getLaunchActivityType(); + } + return activityType != ACTIVITY_TYPE_UNDEFINED ? activityType : ACTIVITY_TYPE_STANDARD; + } + + /** + * 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}, {@code null} if not found. + */ + ActivityStack getNextFocusableStack(@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; + } + if (preferredDisplay.supportsSystemDecorations()) { + // Stop looking for focusable stack on other displays because the preferred display + // supports system decorations. Home activity would be launched on the same display if + // no focusable stack found. + return null; + } + + // Now look through all displays + for (int i = mActivityDisplays.size() - 1; i >= 0; --i) { + final ActivityDisplay display = mActivityDisplays.get(i); + if (display == preferredDisplay) { + // We've already checked this one + continue; + } + final ActivityStack nextFocusableStack = display.getNextFocusableStack(currentFocus, + ignoreCurrent); + if (nextFocusableStack != null) { + return nextFocusableStack; + } + } + + return null; + } + + /** + * Get next valid stack for launching provided activity in the system. This will search across + * displays and stacks in last-focused order for a focusable and visible stack, except those + * that are on a currently focused display. + * + * @param r The activity that is being launched. + * @param currentFocus The display that previously had focus and thus needs to be ignored when + * searching for the next candidate. + * @return Next valid {@link ActivityStack}, null if not found. + */ + ActivityStack getNextValidLaunchStack(@NonNull ActivityRecord r, int currentFocus) { + for (int i = mActivityDisplays.size() - 1; i >= 0; --i) { + final ActivityDisplay display = mActivityDisplays.get(i); + if (display.mDisplayId == currentFocus) { + continue; + } + final ActivityStack stack = getValidLaunchStackOnDisplay(display.mDisplayId, r, + null /* options */, null /* launchParams */); + if (stack != null) { + return stack; + } + } + return null; + } + + boolean handleAppDied(WindowProcessController app) { + boolean hasVisibleActivities = false; + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ActivityDisplay display = mActivityDisplays.get(displayNdx); + for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = display.getChildAt(stackNdx); + hasVisibleActivities |= stack.handleAppDiedLocked(app); + } + } + return hasVisibleActivities; + } + + void closeSystemDialogs() { + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ActivityDisplay display = mActivityDisplays.get(displayNdx); + for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = display.getChildAt(stackNdx); + stack.closeSystemDialogsLocked(); + } + } + } + + /** @return true if some activity was finished (or would have finished if doit were true). */ + boolean finishDisabledPackageActivities(String packageName, Set<String> filterByClasses, + boolean doit, boolean evenPersistent, int userId) { + boolean didSomething = false; + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ActivityDisplay display = mActivityDisplays.get(displayNdx); + for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = display.getChildAt(stackNdx); + if (stack.finishDisabledPackageActivitiesLocked( + packageName, filterByClasses, doit, evenPersistent, userId)) { + didSomething = true; + } + } + } + return didSomething; + } + + void updateActivityApplicationInfo(ApplicationInfo aInfo) { + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ActivityDisplay display = mActivityDisplays.get(displayNdx); + for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = display.getChildAt(stackNdx); + stack.updateActivityApplicationInfoLocked(aInfo); + } + } + } + + void finishVoiceTask(IVoiceInteractionSession session) { + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ActivityDisplay display = mActivityDisplays.get(displayNdx); + final int numStacks = display.getChildCount(); + for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { + final ActivityStack stack = display.getChildAt(stackNdx); + stack.finishVoiceTask(session); + } + } + } + + /** + * Removes stacks in the input windowing modes from the system if they are of activity type + * ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED + */ + void removeStacksInWindowingModes(int... windowingModes) { + for (int i = mActivityDisplays.size() - 1; i >= 0; --i) { + mActivityDisplays.get(i).removeStacksInWindowingModes(windowingModes); + } + } + + void removeStacksWithActivityTypes(int... activityTypes) { + for (int i = mActivityDisplays.size() - 1; i >= 0; --i) { + mActivityDisplays.get(i).removeStacksWithActivityTypes(activityTypes); + } + } + + ActivityRecord topRunningActivity() { + for (int i = mActivityDisplays.size() - 1; i >= 0; --i) { + final ActivityRecord topActivity = mActivityDisplays.get(i).topRunningActivity(); + if (topActivity != null) { + return topActivity; + } + } + return null; + } + + boolean allResumedActivitiesIdle() { + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + // TODO(b/117135575): Check resumed activities on all visible stacks. + final ActivityDisplay display = mActivityDisplays.get(displayNdx); + if (display.isSleeping()) { + // No resumed activities while display is sleeping. + continue; + } + + // If the focused stack is not null or not empty, there should have some activities + // resuming or resumed. Make sure these activities are idle. + final ActivityStack stack = display.getFocusedStack(); + if (stack == null || stack.numActivities() == 0) { + continue; + } + final ActivityRecord resumedActivity = stack.getResumedActivity(); + if (resumedActivity == null || !resumedActivity.idle) { + if (DEBUG_STATES) { + Slog.d(TAG_STATES, "allResumedActivitiesIdle: stack=" + + stack.mStackId + " " + resumedActivity + " not idle"); + } + return false; + } + } + // Send launch end powerhint when idle + sendPowerHintForLaunchEndIfNeeded(); + return true; + } + + boolean allResumedActivitiesVisible() { + boolean foundResumed = false; + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ActivityDisplay display = mActivityDisplays.get(displayNdx); + for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = display.getChildAt(stackNdx); + final ActivityRecord r = stack.getResumedActivity(); + if (r != null) { + if (!r.nowVisible + || mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(r)) { + return false; + } + foundResumed = true; + } + } + } + return foundResumed; + } + + boolean allPausedActivitiesComplete() { + boolean pausing = true; + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ActivityDisplay display = mActivityDisplays.get(displayNdx); + for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = display.getChildAt(stackNdx); + final ActivityRecord r = stack.mPausingActivity; + if (r != null && !r.isState(PAUSED, STOPPED, STOPPING)) { + if (DEBUG_STATES) { + Slog.d(TAG_STATES, + "allPausedActivitiesComplete: r=" + r + " state=" + r.getState()); + pausing = false; + } else { + return false; + } + } + } + } + return pausing; + } + + /** + * Find all visible task stacks containing {@param userId} and intercept them with an activity + * to block out the contents and possibly start a credential-confirming intent. + * + * @param userId user handle for the locked managed profile. + */ + void lockAllProfileTasks(@UserIdInt int userId) { + mWindowManager.deferSurfaceLayout(); + try { + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ActivityDisplay display = mActivityDisplays.get(displayNdx); + for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = display.getChildAt(stackNdx); + final List<TaskRecord> tasks = stack.getAllTasks(); + for (int taskNdx = tasks.size() - 1; taskNdx >= 0; taskNdx--) { + final TaskRecord task = tasks.get(taskNdx); + + // Check the task for a top activity belonging to userId, or returning a + // result to an activity belonging to userId. Example case: a document + // picker for personal files, opened by a work app, should still get locked. + if (taskTopActivityIsUser(task, userId)) { + mService.getTaskChangeNotificationController().notifyTaskProfileLocked( + task.taskId, userId); + } + } + } + } + } finally { + mWindowManager.continueSurfaceLayout(); + } + } + + /** + * Detects whether we should show a lock screen in front of this task for a locked user. + * <p> + * We'll do this if either of the following holds: + * <ul> + * <li>The top activity explicitly belongs to {@param userId}.</li> + * <li>The top activity returns a result to an activity belonging to {@param userId}.</li> + * </ul> + * + * @return {@code true} if the top activity looks like it belongs to {@param userId}. + */ + private boolean taskTopActivityIsUser(TaskRecord task, @UserIdInt int userId) { + // To handle the case that work app is in the task but just is not the top one. + final ActivityRecord activityRecord = task.getTopActivity(); + final ActivityRecord resultTo = (activityRecord != null ? activityRecord.resultTo : null); + + return (activityRecord != null && activityRecord.userId == userId) + || (resultTo != null && resultTo.userId == userId); + } + + void cancelInitializingActivities() { + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ActivityDisplay display = mActivityDisplays.get(displayNdx); + for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = display.getChildAt(stackNdx); + stack.cancelInitializingActivities(); + } + } + } + + TaskRecord anyTaskForId(int id) { + return anyTaskForId(id, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE); + } + + TaskRecord anyTaskForId(int id, @AnyTaskForIdMatchTaskMode int matchMode) { + return anyTaskForId(id, matchMode, null, !ON_TOP); + } + + /** + * Returns a {@link TaskRecord} for the input id if available. {@code null} otherwise. + * @param id Id of the task we would like returned. + * @param matchMode The mode to match the given task id in. + * @param aOptions The activity options to use for restoration. Can be null. + * @param onTop If the stack for the task should be the topmost on the display. + */ + TaskRecord anyTaskForId(int id, @AnyTaskForIdMatchTaskMode int matchMode, + @Nullable ActivityOptions aOptions, boolean onTop) { + // If options are set, ensure that we are attempting to actually restore a task + if (matchMode != MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE && aOptions != null) { + throw new IllegalArgumentException("Should not specify activity options for non-restore" + + " lookup"); + } + + int numDisplays = mActivityDisplays.size(); + for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { + final ActivityDisplay display = mActivityDisplays.get(displayNdx); + for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = display.getChildAt(stackNdx); + final TaskRecord task = stack.taskForIdLocked(id); + if (task == null) { + continue; + } + if (aOptions != null) { + // Resolve the stack the task should be placed in now based on options + // and reparent if needed. + final ActivityStack launchStack = + getLaunchStack(null, aOptions, task, onTop); + if (launchStack != null && stack != launchStack) { + final int reparentMode = onTop + ? REPARENT_MOVE_STACK_TO_FRONT : REPARENT_LEAVE_STACK_IN_PLACE; + task.reparent(launchStack, onTop, reparentMode, ANIMATE, DEFER_RESUME, + "anyTaskForId"); + } + } + return task; + } + } + + // If we are matching stack tasks only, return now + if (matchMode == MATCH_TASK_IN_STACKS_ONLY) { + return null; + } + + // Otherwise, check the recent tasks and return if we find it there and we are not restoring + // the task from recents + if (DEBUG_RECENTS) Slog.v(TAG_RECENTS, "Looking for task id=" + id + " in recents"); + final TaskRecord task = mStackSupervisor.mRecentTasks.getTask(id); + + if (task == null) { + if (DEBUG_RECENTS) { + Slog.d(TAG_RECENTS, "\tDidn't find task id=" + id + " in recents"); + } + + return null; + } + + if (matchMode == MATCH_TASK_IN_STACKS_OR_RECENT_TASKS) { + return task; + } + + // Implicitly, this case is MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE + if (!mStackSupervisor.restoreRecentTaskLocked(task, aOptions, onTop)) { + if (DEBUG_RECENTS) Slog.w(TAG_RECENTS, + "Couldn't restore task id=" + id + " found in recents"); + return null; + } + if (DEBUG_RECENTS) Slog.w(TAG_RECENTS, "Restored task id=" + id + " from in recents"); + return task; + } + + ActivityRecord isInAnyStack(IBinder token) { + int numDisplays = mActivityDisplays.size(); + for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { + final ActivityDisplay display = mActivityDisplays.get(displayNdx); + for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = display.getChildAt(stackNdx); + final ActivityRecord r = stack.isInStackLocked(token); + if (r != null) { + return r; + } + } + } + return null; + } + + @VisibleForTesting + void getRunningTasks(int maxNum, List<ActivityManager.RunningTaskInfo> list, + @WindowConfiguration.ActivityType int ignoreActivityType, + @WindowConfiguration.WindowingMode int ignoreWindowingMode, int callingUid, + boolean allowed) { + mStackSupervisor.mRunningTasks.getTasks(maxNum, list, ignoreActivityType, + ignoreWindowingMode, mActivityDisplays, callingUid, allowed); + } + + void sendPowerHintForLaunchStartIfNeeded(boolean forceSend, ActivityRecord targetActivity) { + boolean sendHint = forceSend; + + if (!sendHint) { + // Send power hint if we don't know what we're launching yet + sendHint = targetActivity == null || targetActivity.app == null; + } + + if (!sendHint) { // targetActivity != null + // Send power hint when the activity's process is different than the current resumed + // activity on all displays, or if there are no resumed activities in the system. + boolean noResumedActivities = true; + boolean allFocusedProcessesDiffer = true; + for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) { + final ActivityDisplay activityDisplay = mActivityDisplays.get(displayNdx); + final ActivityRecord resumedActivity = activityDisplay.getResumedActivity(); + final WindowProcessController resumedActivityProcess = + resumedActivity == null ? null : resumedActivity.app; + + noResumedActivities &= resumedActivityProcess == null; + if (resumedActivityProcess != null) { + allFocusedProcessesDiffer &= !resumedActivityProcess.equals(targetActivity.app); + } + } + sendHint = noResumedActivities || allFocusedProcessesDiffer; + } + + if (sendHint && mService.mPowerManagerInternal != null) { + mService.mPowerManagerInternal.powerHint(PowerHint.LAUNCH, 1); + mPowerHintSent = true; + } + } + + void sendPowerHintForLaunchEndIfNeeded() { + // Trigger launch power hint if activity is launched + if (mPowerHintSent && mService.mPowerManagerInternal != null) { + mService.mPowerManagerInternal.powerHint(PowerHint.LAUNCH, 0); + mPowerHintSent = false; + } + } + + private void calculateDefaultMinimalSizeOfResizeableTasks() { + final Resources res = mService.mContext.getResources(); + final float minimalSize = res.getDimension( + com.android.internal.R.dimen.default_minimal_size_resizable_task); + final DisplayMetrics dm = res.getDisplayMetrics(); + + mDefaultMinSizeOfResizeableTaskDp = (int) (minimalSize / dm.density); + } + + /** + * Dumps the activities matching the given {@param name} in the either the focused stack + * or all visible stacks if {@param dumpVisibleStacks} is true. + */ + ArrayList<ActivityRecord> getDumpActivities(String name, boolean dumpVisibleStacksOnly, + boolean dumpFocusedStackOnly) { + if (dumpFocusedStackOnly) { + return getTopDisplayFocusedStack().getDumpActivitiesLocked(name); + } else { + ArrayList<ActivityRecord> activities = new ArrayList<>(); + int numDisplays = mActivityDisplays.size(); + for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { + final ActivityDisplay display = mActivityDisplays.get(displayNdx); + for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = display.getChildAt(stackNdx); + if (!dumpVisibleStacksOnly || stack.shouldBeVisible(null)) { + activities.addAll(stack.getDumpActivitiesLocked(name)); + } + } + } + return activities; + } + } + + public void dump(PrintWriter pw, String prefix) { + pw.print(prefix); + pw.println("topDisplayFocusedStack=" + getTopDisplayFocusedStack()); + for (int i = mActivityDisplays.size() - 1; i >= 0; --i) { + final ActivityDisplay display = mActivityDisplays.get(i); + display.dump(pw, prefix); + } + } + + /** + * Dump all connected displays' configurations. + * @param prefix Prefix to apply to each line of the dump. + */ + void dumpDisplayConfigs(PrintWriter pw, String prefix) { + pw.print(prefix); pw.println("Display override configurations:"); + final int displayCount = mActivityDisplays.size(); + for (int i = 0; i < displayCount; i++) { + final ActivityDisplay activityDisplay = mActivityDisplays.get(i); + pw.print(prefix); pw.print(" "); pw.print(activityDisplay.mDisplayId); pw.print(": "); + pw.println(activityDisplay.getOverrideConfiguration()); + } + } + + public void dumpDisplays(PrintWriter pw) { + for (int i = mActivityDisplays.size() - 1; i >= 0; --i) { + final ActivityDisplay display = mActivityDisplays.get(i); + pw.print("[id:" + display.mDisplayId + " stacks:"); + display.dumpStacks(pw); + pw.print("]"); + } + } + + boolean dumpActivities(FileDescriptor fd, PrintWriter pw, boolean dumpAll, boolean dumpClient, + String dumpPackage) { + boolean printed = false; + boolean needSep = false; + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + ActivityDisplay activityDisplay = mActivityDisplays.get(displayNdx); + pw.print("Display #"); pw.print(activityDisplay.mDisplayId); + pw.println(" (activities from top to bottom):"); + final ActivityDisplay display = mActivityDisplays.get(displayNdx); + for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = display.getChildAt(stackNdx); + pw.println(); + pw.println(" Stack #" + stack.mStackId + + ": type=" + activityTypeToString(stack.getActivityType()) + + " mode=" + windowingModeToString(stack.getWindowingMode())); + pw.println(" isSleeping=" + stack.shouldSleepActivities()); + pw.println(" mBounds=" + stack.getOverrideBounds()); + + printed |= stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage, + needSep); + + printed |= dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false, + !dumpAll, false, dumpPackage, true, + " Running activities (most recent first):", null); + + needSep = printed; + boolean pr = printThisActivity(pw, stack.mPausingActivity, dumpPackage, needSep, + " mPausingActivity: "); + if (pr) { + printed = true; + needSep = false; + } + pr = printThisActivity(pw, stack.getResumedActivity(), dumpPackage, needSep, + " mResumedActivity: "); + if (pr) { + printed = true; + needSep = false; + } + if (dumpAll) { + pr = printThisActivity(pw, stack.mLastPausedActivity, dumpPackage, needSep, + " mLastPausedActivity: "); + if (pr) { + printed = true; + needSep = true; + } + printed |= printThisActivity(pw, stack.mLastNoHistoryActivity, dumpPackage, + needSep, " mLastNoHistoryActivity: "); + } + needSep = printed; + } + printThisActivity(pw, activityDisplay.getResumedActivity(), dumpPackage, needSep, + " ResumedActivity:"); + } + + printed |= dumpHistoryList(fd, pw, mStackSupervisor.mFinishingActivities, " ", + "Fin", false, !dumpAll, + false, dumpPackage, true, " Activities waiting to finish:", null); + printed |= dumpHistoryList(fd, pw, mStackSupervisor.mStoppingActivities, " ", + "Stop", false, !dumpAll, + false, dumpPackage, true, " Activities waiting to stop:", null); + printed |= dumpHistoryList(fd, pw, + mStackSupervisor.mActivitiesWaitingForVisibleActivity, " ", "Wait", + false, !dumpAll, false, dumpPackage, true, + " Activities waiting for another to become visible:", null); + printed |= dumpHistoryList(fd, pw, mStackSupervisor.mGoingToSleepActivities, + " ", "Sleep", false, !dumpAll, + false, dumpPackage, true, " Activities waiting to sleep:", null); + + return printed; + } + + void writeToProto(ProtoOutputStream proto, long fieldId) { + final long token = proto.start(fieldId); + super.writeToProto(proto, CONFIGURATION_CONTAINER, false /* trim */); + for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) { + final ActivityDisplay activityDisplay = mActivityDisplays.get(displayNdx); + activityDisplay.writeToProto(proto, DISPLAYS); + } + mStackSupervisor.getKeyguardController().writeToProto(proto, KEYGUARD_CONTROLLER); + // TODO(b/111541062): Update tests to look for resumed activities on all displays + final ActivityStack focusedStack = getTopDisplayFocusedStack(); + 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); + } + proto.write(IS_HOME_RECENTS_COMPONENT, + mStackSupervisor.mRecentTasks.isRecentsComponentHomeActivity(mCurrentUser)); + mService.getActivityStartController().writeToProto(proto, PENDING_ACTIVITIES); + proto.end(token); + } + + private final class SleepTokenImpl extends ActivityTaskManagerInternal.SleepToken { + private final String mTag; + private final long mAcquireTime; + private final int mDisplayId; + + public SleepTokenImpl(String tag, int displayId) { + mTag = tag; + mDisplayId = displayId; + mAcquireTime = SystemClock.uptimeMillis(); + } + + @Override + public void release() { + synchronized (mService.mGlobalLock) { + removeSleepToken(this); + } + } + + @Override + public String toString() { + return "{\"" + mTag + "\", display " + mDisplayId + + ", acquire at " + TimeUtils.formatUptime(mAcquireTime) + "}"; + } + } +} diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java index 117984af67e7..4ae2a79e2697 100644 --- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java +++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java @@ -138,7 +138,7 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { // STEP 1: Determine the display to launch the activity/task. final int displayId = getPreferredLaunchDisplay(task, options, source, currentParams); outParams.mPreferredDisplayId = displayId; - ActivityDisplay display = mSupervisor.getActivityDisplay(displayId); + ActivityDisplay display = mSupervisor.mRootActivityContainer.getActivityDisplay(displayId); if (DEBUG) { appendLog("display-id=" + outParams.mPreferredDisplayId + " display-windowing-mode=" + display.getWindowingMode()); @@ -300,12 +300,14 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { displayId = stack.mDisplayId; } - if (displayId != INVALID_DISPLAY && mSupervisor.getActivityDisplay(displayId) == null) { + if (displayId != INVALID_DISPLAY + && mSupervisor.mRootActivityContainer.getActivityDisplay(displayId) == null) { displayId = currentParams.mPreferredDisplayId; } displayId = (displayId == INVALID_DISPLAY) ? currentParams.mPreferredDisplayId : displayId; - return (displayId != INVALID_DISPLAY && mSupervisor.getActivityDisplay(displayId) != null) + return (displayId != INVALID_DISPLAY + && mSupervisor.mRootActivityContainer.getActivityDisplay(displayId) != null) ? displayId : DEFAULT_DISPLAY; } @@ -606,7 +608,8 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { || displayBounds.height() < inOutBounds.height()) { // There is no way for us to fit the bounds in the display without changing width // or height. Just move the start to align with the display. - final int layoutDirection = mSupervisor.getConfiguration().getLayoutDirection(); + final int layoutDirection = + mSupervisor.mRootActivityContainer.getConfiguration().getLayoutDirection(); final int left = layoutDirection == View.LAYOUT_DIRECTION_RTL ? displayBounds.width() - inOutBounds.width() : 0; diff --git a/services/core/java/com/android/server/wm/TaskPersister.java b/services/core/java/com/android/server/wm/TaskPersister.java index 8120dec7e48f..d50af385865e 100644 --- a/services/core/java/com/android/server/wm/TaskPersister.java +++ b/services/core/java/com/android/server/wm/TaskPersister.java @@ -16,7 +16,7 @@ package com.android.server.wm; -import static com.android.server.wm.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS; +import static com.android.server.wm.RootActivityContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS; import android.annotation.NonNull; import android.graphics.Bitmap; @@ -330,7 +330,7 @@ public class TaskPersister implements PersisterQueue.Listener { // mWriteQueue.add(new TaskWriteQueueItem(task)); final int taskId = task.taskId; - if (mStackSupervisor.anyTaskForIdLocked(taskId, + if (mService.mRootActivityContainer.anyTaskForId(taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS) != null) { // Should not happen. Slog.wtf(TAG, "Existing task with taskId " + taskId + "found"); diff --git a/services/core/java/com/android/server/wm/TaskRecord.java b/services/core/java/com/android/server/wm/TaskRecord.java index eec10aba5df2..a28b8759fb5b 100644 --- a/services/core/java/com/android/server/wm/TaskRecord.java +++ b/services/core/java/com/android/server/wm/TaskRecord.java @@ -472,8 +472,8 @@ public class TaskRecord extends ConfigurationContainer implements TaskWindowCont } mResizeMode = resizeMode; mWindowContainerController.setResizeable(resizeMode); - mService.mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); - mService.mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); + mService.mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS); + mService.mRootActivityContainer.resumeFocusedStacksTopActivities(); } void setTaskDockedResizing(boolean resizing) { @@ -544,10 +544,9 @@ public class TaskRecord extends ConfigurationContainer implements TaskWindowCont // this won't cause tons of irrelevant windows being preserved because only // activities in this task may experience a bounds change. Configs for other // activities stay the same. - mService.mStackSupervisor.ensureActivitiesVisibleLocked(r, 0, - preserveWindow); + mService.mRootActivityContainer.ensureActivitiesVisible(r, 0, preserveWindow); if (!kept) { - mService.mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(); + mService.mRootActivityContainer.resumeFocusedStacksTopActivities(); } } } @@ -623,6 +622,7 @@ public class TaskRecord extends ConfigurationContainer implements TaskWindowCont @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume, boolean schedulePictureInPictureModeChange, String reason) { final ActivityStackSupervisor supervisor = mService.mStackSupervisor; + final RootActivityContainer root = mService.mRootActivityContainer; final WindowManagerService windowManager = mService.mWindowManager; final ActivityStack sourceStack = getStack(); final ActivityStack toStack = supervisor.getReparentTargetStack(this, preferredStack, @@ -655,7 +655,7 @@ public class TaskRecord extends ConfigurationContainer implements TaskWindowCont boolean kept = true; try { final ActivityRecord r = topRunningActivityLocked(); - final boolean wasFocused = r != null && supervisor.isTopDisplayFocusedStack(sourceStack) + final boolean wasFocused = r != null && root.isTopDisplayFocusedStack(sourceStack) && (topRunningActivityLocked() == r); final boolean wasResumed = r != null && sourceStack.getResumedActivity() == r; final boolean wasPaused = r != null && sourceStack.mPausingActivity == r; @@ -748,8 +748,8 @@ public class TaskRecord extends ConfigurationContainer implements TaskWindowCont if (!deferResume) { // 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.resumeFocusedStacksTopActivitiesLocked(); + root.ensureActivitiesVisible(null, 0, !mightReplaceWindow); + root.resumeFocusedStacksTopActivities(); } // TODO: Handle incorrect request to move before the actual move, not after. @@ -982,7 +982,7 @@ public class TaskRecord extends ConfigurationContainer implements TaskWindowCont @Override protected void onParentChanged() { super.onParentChanged(); - mService.mStackSupervisor.updateUIDsPresentOnDisplay(); + mService.mRootActivityContainer.updateUIDsPresentOnDisplay(); } // Close up recents linked list. @@ -1143,7 +1143,7 @@ public class TaskRecord extends ConfigurationContainer implements TaskWindowCont } boolean okToShowLocked() { - // NOTE: If {@link TaskRecord#topRunningActivityLocked} return is not null then it is + // NOTE: If {@link TaskRecord#topRunningActivity} return is not null then it is // okay to show the activity when locked. return mService.mStackSupervisor.isCurrentProfileLocked(userId) || topRunningActivityLocked() != null; @@ -1274,7 +1274,7 @@ public class TaskRecord extends ConfigurationContainer implements TaskWindowCont // Make sure the list of display UID whitelists is updated // now that this record is in a new task. - mService.mStackSupervisor.updateUIDsPresentOnDisplay(); + mService.mRootActivityContainer.updateUIDsPresentOnDisplay(); } /** @@ -1683,9 +1683,9 @@ public class TaskRecord extends ConfigurationContainer implements TaskWindowCont // to do this for the pinned stack as the bounds are controlled by the system. if (!inPinnedWindowingMode()) { final int defaultMinSizeDp = - mService.mStackSupervisor.mDefaultMinSizeOfResizeableTaskDp; + mService.mRootActivityContainer.mDefaultMinSizeOfResizeableTaskDp; final ActivityDisplay display = - mService.mStackSupervisor.getActivityDisplay(mStack.mDisplayId); + mService.mRootActivityContainer.getActivityDisplay(mStack.mDisplayId); final float density = (float) display.getConfiguration().densityDpi / DisplayMetrics.DENSITY_DEFAULT; final int defaultMinSize = (int) (defaultMinSizeDp * density); diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java index 484bd8c30462..578af2eebe88 100644 --- a/services/core/java/com/android/server/wm/WindowProcessController.java +++ b/services/core/java/com/android/server/wm/WindowProcessController.java @@ -755,9 +755,9 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio return; } final ActivityDisplay activityDisplay = - mAtm.mStackSupervisor.getActivityDisplay(mDisplayId); + mAtm.mRootActivityContainer.getActivityDisplay(mDisplayId); if (activityDisplay != null) { - mAtm.mStackSupervisor.getActivityDisplay( + mAtm.mRootActivityContainer.getActivityDisplay( mDisplayId).unregisterConfigurationChangeListener(this); } mDisplayId = INVALID_DISPLAY; diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java index cb2a8ec8a274..5bf3d2dabe24 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java @@ -62,8 +62,9 @@ public class ActivityDisplayTests extends ActivityTestsBase { @Test public void testLastFocusedStackIsUpdatedWhenMovingStack() { // Create a stack at bottom. - final ActivityDisplay display = mSupervisor.getDefaultDisplay(); - final ActivityStack stack = new StackBuilder(mSupervisor).setOnTop(!ON_TOP).build(); + final ActivityDisplay display = mRootActivityContainer.getDefaultDisplay(); + final ActivityStack stack = + new StackBuilder(mRootActivityContainer).setOnTop(!ON_TOP).build(); final ActivityStack prevFocusedStack = display.getFocusedStack(); stack.moveToFront("moveStackToFront"); @@ -83,7 +84,7 @@ public class ActivityDisplayTests extends ActivityTestsBase { @Test public void testFullscreenStackCanBeFocusedWhenFocusablePinnedStackExists() { // Create a pinned stack and move to front. - final ActivityStack pinnedStack = mSupervisor.getDefaultDisplay().createStack( + final ActivityStack pinnedStack = mRootActivityContainer.getDefaultDisplay().createStack( WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, ON_TOP); final TaskRecord pinnedTask = new TaskBuilder(mService.mStackSupervisor) .setStack(pinnedStack).build(); @@ -96,7 +97,7 @@ public class ActivityDisplayTests extends ActivityTestsBase { // Create a fullscreen stack and move to front. final ActivityStack fullscreenStack = createFullscreenStackWithSimpleActivityAt( - mSupervisor.getDefaultDisplay()); + mRootActivityContainer.getDefaultDisplay()); fullscreenStack.moveToFront("moveFullscreenStackToFront"); // The focused stack should be the fullscreen stack. @@ -138,7 +139,7 @@ public class ActivityDisplayTests extends ActivityTestsBase { final ActivityDisplay display = spy(createNewActivityDisplay()); doReturn(false).when(display).shouldDestroyContentOnRemove(); doReturn(true).when(display).supportsSystemDecorations(); - mSupervisor.addChild(display, ActivityDisplay.POSITION_TOP); + mRootActivityContainer.addChild(display, ActivityDisplay.POSITION_TOP); // Put home stack on the display. final ActivityStack homeStack = display.createStack( @@ -175,14 +176,14 @@ public class ActivityDisplayTests extends ActivityTestsBase { */ @Test public void testTopRunningActivity() { - final ActivityDisplay display = mSupervisor.getDefaultDisplay(); + final ActivityDisplay display = mRootActivityContainer.getDefaultDisplay(); final KeyguardController keyguard = mSupervisor.getKeyguardController(); - final ActivityStack stack = new StackBuilder(mSupervisor).build(); + final ActivityStack stack = new StackBuilder(mRootActivityContainer).build(); final ActivityRecord activity = stack.getTopActivity(); // Create empty stack on top. final ActivityStack emptyStack = - new StackBuilder(mSupervisor).setCreateActivity(false).build(); + new StackBuilder(mRootActivityContainer).setCreateActivity(false).build(); // Make sure the top running activity is not affected when keyguard is not locked. assertTopRunningActivity(activity, display); @@ -225,7 +226,7 @@ public class ActivityDisplayTests extends ActivityTestsBase { */ @Test public void testAlwaysOnTopStackLocation() { - final ActivityDisplay display = mSupervisor.getDefaultDisplay(); + final ActivityDisplay display = mRootActivityContainer.getDefaultDisplay(); final ActivityStack alwaysOnTopStack = display.createStack(WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, true /* onTop */); final ActivityRecord activity = new ActivityBuilder(mService).setCreateTask(true) diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java index c7f0521adb7b..0e30037bde6c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java @@ -74,7 +74,7 @@ public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase { // Sometimes we need an ActivityRecord for ActivityMetricsLogger to do anything useful. // This seems to be the easiest way to create an ActivityRecord. - mStack = mSupervisor.getDefaultDisplay().createStack( + mStack = mRootActivityContainer.getDefaultDisplay().createStack( WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); mTask = new TaskBuilder(mSupervisor).setStack(mStack).build(); mActivityRecord = new ActivityBuilder(mService).setTask(mTask).build(); diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java index 170bd3311de2..b15b8c1977cb 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -65,7 +65,7 @@ public class ActivityRecordTests extends ActivityTestsBase { @Before public void setUp() throws Exception { setupActivityTaskManagerService(); - mStack = new StackBuilder(mSupervisor).build(); + mStack = new StackBuilder(mRootActivityContainer).build(); mTask = mStack.getChildAt(0); mActivity = mTask.getTopActivity(); } @@ -86,7 +86,7 @@ public class ActivityRecordTests extends ActivityTestsBase { public void testStackCleanupOnTaskRemoval() { mStack.removeTask(mTask, null /*reason*/, REMOVE_TASK_MODE_MOVING); // Stack should be gone on task removal. - assertNull(mService.mStackSupervisor.getStack(mStack.mStackId)); + assertNull(mService.mRootActivityContainer.getStack(mStack.mStackId)); } @Test @@ -116,7 +116,7 @@ public class ActivityRecordTests extends ActivityTestsBase { assertFalse(pauseFound.value); // Clear focused stack - final ActivityDisplay display = mActivity.mStackSupervisor.getDefaultDisplay(); + final ActivityDisplay display = mRootActivityContainer.getDefaultDisplay(); when(display.getFocusedStack()).thenReturn(null); // In the unfocused stack, the activity should move to paused. diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java index 8a6d5873927a..78a67d212f24 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java @@ -38,8 +38,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.times; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.android.server.wm.ActivityDisplay.POSITION_TOP; import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING; -import static com.android.server.wm.ActivityStackSupervisor - .MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE; +import static com.android.server.wm.RootActivityContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE; import static com.google.common.truth.Truth.assertThat; @@ -83,78 +82,11 @@ public class ActivityStackSupervisorTests extends ActivityTestsBase { @Before public void setUp() throws Exception { setupActivityTaskManagerService(); - mFullscreenStack = mService.mStackSupervisor.getDefaultDisplay().createStack( + mFullscreenStack = mRootActivityContainer.getDefaultDisplay().createStack( WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); } /** - * This test ensures that we do not try to restore a task based off an invalid task id. We - * should expect {@code null} to be returned in this case. - */ - @Test - public void testRestoringInvalidTask() { - ((TestActivityDisplay) mSupervisor.getDefaultDisplay()).removeAllTasks(); - TaskRecord task = mSupervisor.anyTaskForIdLocked(0 /*taskId*/, - MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, null, false /* onTop */); - assertNull(task); - } - - /** - * This test ensures that an existing task in the pinned stack is moved to the fullscreen - * activity stack when a new task is added. - */ - @Test - public void testReplacingTaskInPinnedStack() { - final ActivityRecord firstActivity = new ActivityBuilder(mService).setCreateTask(true) - .setStack(mFullscreenStack).build(); - final TaskRecord firstTask = firstActivity.getTask(); - - final ActivityRecord secondActivity = new ActivityBuilder(mService).setCreateTask(true) - .setStack(mFullscreenStack).build(); - final TaskRecord secondTask = secondActivity.getTask(); - - mFullscreenStack.moveToFront("testReplacingTaskInPinnedStack"); - - // Ensure full screen stack has both tasks. - ensureStackPlacement(mFullscreenStack, firstTask, secondTask); - - // Move first activity to pinned stack. - final Rect sourceBounds = new Rect(); - mSupervisor.moveActivityToPinnedStackLocked(firstActivity, sourceBounds, - 0f /*aspectRatio*/, "initialMove"); - - final ActivityDisplay display = mFullscreenStack.getDisplay(); - ActivityStack pinnedStack = display.getPinnedStack(); - // Ensure a task has moved over. - ensureStackPlacement(pinnedStack, firstTask); - ensureStackPlacement(mFullscreenStack, secondTask); - - // Move second activity to pinned stack. - mSupervisor.moveActivityToPinnedStackLocked(secondActivity, sourceBounds, - 0f /*aspectRatio*/, "secondMove"); - - // Need to get stacks again as a new instance might have been created. - pinnedStack = display.getPinnedStack(); - mFullscreenStack = display.getStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD); - // Ensure stacks have swapped tasks. - ensureStackPlacement(pinnedStack, secondTask); - ensureStackPlacement(mFullscreenStack, firstTask); - } - - private static void ensureStackPlacement(ActivityStack stack, TaskRecord... tasks) { - final ArrayList<TaskRecord> stackTasks = stack.getAllTasks(); - assertEquals(stackTasks.size(), tasks != null ? tasks.length : 0); - - if (tasks == null) { - return; - } - - for (TaskRecord task : tasks) { - assertTrue(stackTasks.contains(task)); - } - } - - /** * Ensures that an activity is removed from the stopping activities list once it is resumed. */ @Test @@ -179,7 +111,7 @@ public class ActivityStackSupervisorTests extends ActivityTestsBase { // #notifyAll will be called on the ActivityManagerService. we must hold the object lock // when this happens. - synchronized (mSupervisor.mService.mGlobalLock) { + synchronized (mService.mGlobalLock) { final WaitResult taskToFrontWait = new WaitResult(); mSupervisor.mWaitingActivityLaunched.add(taskToFrontWait); mSupervisor.reportWaitingActivityLaunchedIfNeeded(firstActivity, START_TASK_TO_FRONT); @@ -198,334 +130,4 @@ public class ActivityStackSupervisorTests extends ActivityTestsBase { assertEquals(deliverToTopWait.who, firstActivity.realActivity); } } - - @Test - public void testApplySleepTokensLocked() { - final ActivityDisplay display = mSupervisor.getDefaultDisplay(); - final KeyguardController keyguard = mSupervisor.getKeyguardController(); - final ActivityStack stack = mock(ActivityStack.class); - display.addChild(stack, 0 /* position */); - - // Make sure we wake and resume in the case the display is turning on and the keyguard is - // not showing. - verifySleepTokenBehavior(display, keyguard, stack, true /*displaySleeping*/, - false /* displayShouldSleep */, true /* isFocusedStack */, - false /* keyguardShowing */, true /* expectWakeFromSleep */, - true /* expectResumeTopActivity */); - - // Make sure we wake and don't resume when the display is turning on and the keyguard is - // showing. - verifySleepTokenBehavior(display, keyguard, stack, true /*displaySleeping*/, - false /* displayShouldSleep */, true /* isFocusedStack */, - true /* keyguardShowing */, true /* expectWakeFromSleep */, - false /* expectResumeTopActivity */); - - // Make sure we wake and don't resume when the display is turning on and the keyguard is - // not showing as unfocused. - verifySleepTokenBehavior(display, keyguard, stack, true /*displaySleeping*/, - false /* displayShouldSleep */, false /* isFocusedStack */, - false /* keyguardShowing */, true /* expectWakeFromSleep */, - false /* expectResumeTopActivity */); - - // Should not do anything if the display state hasn't changed. - verifySleepTokenBehavior(display, keyguard, stack, false /*displaySleeping*/, - false /* displayShouldSleep */, true /* isFocusedStack */, - false /* keyguardShowing */, false /* expectWakeFromSleep */, - false /* expectResumeTopActivity */); - } - - private void verifySleepTokenBehavior(ActivityDisplay display, KeyguardController keyguard, - ActivityStack stack, boolean displaySleeping, boolean displayShouldSleep, - boolean isFocusedStack, boolean keyguardShowing, boolean expectWakeFromSleep, - boolean expectResumeTopActivity) { - reset(stack); - - doReturn(displayShouldSleep).when(display).shouldSleep(); - doReturn(displaySleeping).when(display).isSleeping(); - doReturn(keyguardShowing).when(keyguard).isKeyguardOrAodShowing(anyInt()); - - doReturn(isFocusedStack).when(stack).isFocusedStackOnDisplay(); - doReturn(isFocusedStack ? stack : null).when(display).getFocusedStack(); - mSupervisor.applySleepTokensLocked(true); - verify(stack, times(expectWakeFromSleep ? 1 : 0)).awakeFromSleepingLocked(); - verify(stack, times(expectResumeTopActivity ? 1 : 0)).resumeTopActivityUncheckedLocked( - null /* target */, null /* targetOptions */); - } - - /** - * Verifies that removal of activity with task and stack is done correctly. - */ - @Test - public void testRemovingStackOnAppCrash() { - final ActivityDisplay defaultDisplay = mService.mStackSupervisor.getDefaultDisplay(); - final int originalStackCount = defaultDisplay.getChildCount(); - final ActivityStack stack = mService.mStackSupervisor.getDefaultDisplay().createStack( - WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */); - final ActivityRecord firstActivity = new ActivityBuilder(mService).setCreateTask(true) - .setStack(stack).build(); - - assertEquals(originalStackCount + 1, defaultDisplay.getChildCount()); - - // Let's pretend that the app has crashed. - firstActivity.app.setThread(null); - mService.mStackSupervisor.finishTopCrashedActivitiesLocked(firstActivity.app, "test"); - - // Verify that the stack was removed. - assertEquals(originalStackCount, defaultDisplay.getChildCount()); - } - - @Test - public void testFocusability() { - final ActivityStack stack = mService.mStackSupervisor.getDefaultDisplay().createStack( - WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, true /* onTop */); - final ActivityRecord activity = new ActivityBuilder(mService).setCreateTask(true) - .setStack(stack).build(); - - // Under split screen primary we should be focusable when not minimized - mService.mStackSupervisor.setDockedStackMinimized(false); - assertTrue(stack.isFocusable()); - assertTrue(activity.isFocusable()); - - // Under split screen primary we should not be focusable when minimized - mService.mStackSupervisor.setDockedStackMinimized(true); - assertFalse(stack.isFocusable()); - assertFalse(activity.isFocusable()); - - final ActivityStack pinnedStack = mService.mStackSupervisor.getDefaultDisplay().createStack( - WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */); - final ActivityRecord pinnedActivity = new ActivityBuilder(mService).setCreateTask(true) - .setStack(pinnedStack).build(); - - // We should not be focusable when in pinned mode - assertFalse(pinnedStack.isFocusable()); - assertFalse(pinnedActivity.isFocusable()); - - // Add flag forcing focusability. - pinnedActivity.info.flags |= FLAG_ALWAYS_FOCUSABLE; - - // We should not be focusable when in pinned mode - assertTrue(pinnedStack.isFocusable()); - assertTrue(pinnedActivity.isFocusable()); - - // Without the overridding activity, stack should not be focusable. - pinnedStack.removeTask(pinnedActivity.getTask(), "testFocusability", - REMOVE_TASK_MODE_DESTROYING); - assertFalse(pinnedStack.isFocusable()); - } - - /** - * Verify that split-screen primary stack will be chosen if activity is launched that targets - * split-screen secondary, but a matching existing instance is found on top of split-screen - * primary stack. - */ - @Test - public void testSplitScreenPrimaryChosenWhenTopActivityLaunchedToSecondary() { - // Create primary split-screen stack with a task and an activity. - final ActivityStack primaryStack = mService.mStackSupervisor.getDefaultDisplay() - .createStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, - true /* onTop */); - final TaskRecord task = new TaskBuilder(mSupervisor).setStack(primaryStack).build(); - final ActivityRecord r = new ActivityBuilder(mService).setTask(task).build(); - - // Find a launch stack for the top activity in split-screen primary, while requesting - // split-screen secondary. - final ActivityOptions options = ActivityOptions.makeBasic(); - options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY); - final ActivityStack result = mSupervisor.getLaunchStack(r, options, task, true /* onTop */); - - // Assert that the primary stack is returned. - assertEquals(primaryStack, result); - } - - /** - * Verify split-screen primary stack & task can resized by - * {@link android.app.IActivityTaskManager#resizeDockedStack} as expect. - */ - @Test - public void testResizeDockedStackForSplitScreenPrimary() { - final Rect taskSize = new Rect(0, 0, 600, 600); - final Rect stackSize = new Rect(0, 0, 300, 300); - - // Create primary split-screen stack with a task. - final ActivityStack primaryStack = mService.mStackSupervisor.getDefaultDisplay() - .createStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, - true /* onTop */); - final TaskRecord task = new TaskBuilder(mSupervisor).setStack(primaryStack).build(); - - // Resize dock stack. - mService.resizeDockedStack(stackSize, taskSize, null, null, null); - - // Verify dock stack & its task bounds if is equal as resized result. - assertEquals(primaryStack.getBounds(), stackSize); - assertEquals(task.getBounds(), taskSize); - } - - /** - * Verify that home stack would be moved to front when the top activity is Recents. - */ - @Test - public void testFindTaskToMoveToFrontWhenRecentsOnTop() { - // Create stack/task on default display. - final ActivityDisplay display = mSupervisor.getDefaultDisplay(); - final TestActivityStack targetStack = new StackBuilder(mSupervisor).setOnTop(false).build(); - final TaskRecord targetTask = targetStack.getChildAt(0); - - // Create Recents on top of the display. - final ActivityStack stack = - new StackBuilder(mSupervisor).setActivityType(ACTIVITY_TYPE_RECENTS).build(); - - final String reason = "findTaskToMoveToFront"; - mSupervisor.findTaskToMoveToFront(targetTask, 0, ActivityOptions.makeBasic(), reason, - false); - - verify(display).moveHomeStackToFront(contains(reason)); - } - - /** - * Verify that home stack won't be moved to front if the top activity on other display is - * Recents. - */ - @Test - public void testFindTaskToMoveToFrontWhenRecentsOnOtherDisplay() { - // Create stack/task on default display. - final ActivityDisplay display = mSupervisor.getDefaultDisplay(); - final ActivityStack targetStack = display.createStack(WINDOWING_MODE_FULLSCREEN, - ACTIVITY_TYPE_STANDARD, false /* onTop */); - final TaskRecord targetTask = new TaskBuilder(mSupervisor).setStack(targetStack).build(); - - // Create Recents on secondary display. - final TestActivityDisplay secondDisplay = addNewActivityDisplayAt( - ActivityDisplay.POSITION_TOP); - final ActivityStack stack = secondDisplay.createStack(WINDOWING_MODE_FULLSCREEN, - ACTIVITY_TYPE_RECENTS, true /* onTop */); - final TaskRecord task = new TaskBuilder(mSupervisor).setStack(stack).build(); - new ActivityBuilder(mService).setTask(task).build(); - - final String reason = "findTaskToMoveToFront"; - mSupervisor.findTaskToMoveToFront(targetTask, 0, ActivityOptions.makeBasic(), reason, - false); - - verify(display, never()).moveHomeStackToFront(contains(reason)); - } - - /** - * Verify if a stack is not at the topmost position, it should be able to resume its activity if - * the stack is the top focused. - */ - @Test - public void testResumeActivityWhenNonTopmostStackIsTopFocused() { - // Create a stack at bottom. - final ActivityDisplay display = mSupervisor.getDefaultDisplay(); - final ActivityStack targetStack = spy(display.createStack(WINDOWING_MODE_FULLSCREEN, - ACTIVITY_TYPE_STANDARD, false /* onTop */)); - final TaskRecord task = new TaskBuilder(mSupervisor).setStack(targetStack).build(); - final ActivityRecord activity = new ActivityBuilder(mService).setTask(task).build(); - display.positionChildAtBottom(targetStack); - - // Assume the stack is not at the topmost position (e.g. behind always-on-top stacks) but it - // is the current top focused stack. - assertFalse(targetStack.isTopStackOnDisplay()); - doReturn(targetStack).when(mSupervisor).getTopDisplayFocusedStack(); - - // Use the stack as target to resume. - mSupervisor.resumeFocusedStacksTopActivitiesLocked( - targetStack, activity, null /* targetOptions */); - - // Verify the target stack should resume its activity. - verify(targetStack, times(1)).resumeTopActivityUncheckedLocked( - eq(activity), eq(null /* targetOptions */)); - } - - /** - * Tests home activities that targeted sdk before Q cannot start on secondary display. - */ - @Test - public void testStartHomeTargetSdkBeforeQ() throws Exception { - final TestActivityDisplay secondDisplay = spy(createNewActivityDisplay()); - mSupervisor.addChild(secondDisplay, POSITION_TOP); - doReturn(true).when(secondDisplay).supportsSystemDecorations(); - - final ActivityInfo info = new ActivityInfo(); - info.launchMode = LAUNCH_MULTIPLE; - info.applicationInfo = new ApplicationInfo(); - info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.Q; - assertTrue(mSupervisor.canStartHomeOnDisplay(info, secondDisplay.mDisplayId, - false /* allowInstrumenting */)); - - info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.P; - assertFalse(mSupervisor.canStartHomeOnDisplay(info, secondDisplay.mDisplayId, - false /* allowInstrumenting */)); - } - - /** - * Tests that home activities can be started on the displays that supports system decorations. - */ - @Test - public void testStartHomeOnAllDisplays() { - // Create secondary displays. - final TestActivityDisplay secondDisplay = spy(createNewActivityDisplay()); - mSupervisor.addChild(secondDisplay, POSITION_TOP); - doReturn(true).when(secondDisplay).supportsSystemDecorations(); - - // Create mock tasks and other necessary mocks. - TaskBuilder taskBuilder = new TaskBuilder(mService.mStackSupervisor).setCreateStack(false); - final TaskRecord.TaskRecordFactory factory = mock(TaskRecord.TaskRecordFactory.class); - TaskRecord.setTaskRecordFactory(factory); - doAnswer(i -> taskBuilder.build()).when(factory) - .create(any(), anyInt(), any(), any(), any(), any()); - doReturn(true).when(mService.mStackSupervisor) - .ensureVisibilityAndConfig(any(), anyInt(), anyBoolean(), anyBoolean()); - doReturn(true).when(mSupervisor).canStartHomeOnDisplay(any(), anyInt(), anyBoolean()); - - mSupervisor.startHomeOnAllDisplays(0, "testStartHome"); - - assertTrue(mSupervisor.getDefaultDisplay().getTopStack().isActivityTypeHome()); - assertNotNull(secondDisplay.getTopStack()); - assertTrue(secondDisplay.getTopStack().isActivityTypeHome()); - } - - /** - * Tests that home activities won't be started before booting when display added. - */ - @Test - public void testNotStartHomeBeforeBoot() { - final int displayId = 1; - final boolean isBooting = mService.mAmInternal.isBooting(); - final boolean isBooted = mService.mAmInternal.isBooted(); - try { - mService.mAmInternal.setBooting(false); - mService.mAmInternal.setBooted(false); - mSupervisor.onDisplayAdded(displayId); - verify(mSupervisor, never()).startHomeOnDisplay(anyInt(), any(), anyInt()); - } finally { - mService.mAmInternal.setBooting(isBooting); - mService.mAmInternal.setBooted(isBooted); - } - } - - /** - * Tests whether home can be started if being instrumented. - */ - @Test - public void testCanStartHomeWhenInstrumented() { - final ActivityInfo info = new ActivityInfo(); - info.applicationInfo = new ApplicationInfo(); - final WindowProcessController app = mock(WindowProcessController.class); - doReturn(app).when(mService).getProcessController(any(), anyInt()); - - // Can not start home if we don't want to start home while home is being instrumented. - doReturn(true).when(app).isInstrumenting(); - assertFalse(mSupervisor.canStartHomeOnDisplay(info, DEFAULT_DISPLAY, - false /* allowInstrumenting*/)); - - // Can start home for other cases. - assertTrue(mSupervisor.canStartHomeOnDisplay(info, DEFAULT_DISPLAY, - true /* allowInstrumenting*/)); - - doReturn(false).when(app).isInstrumenting(); - assertTrue(mSupervisor.canStartHomeOnDisplay(info, DEFAULT_DISPLAY, - false /* allowInstrumenting*/)); - assertTrue(mSupervisor.canStartHomeOnDisplay(info, DEFAULT_DISPLAY, - true /* allowInstrumenting*/)); - } } diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java index 2fe45b86df4a..0da0b247b60c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java @@ -74,7 +74,7 @@ public class ActivityStackTests extends ActivityTestsBase { @Before public void setUp() throws Exception { setupActivityTaskManagerService(); - mDefaultDisplay = mSupervisor.getDefaultDisplay(); + mDefaultDisplay = mRootActivityContainer.getDefaultDisplay(); mStack = spy(mDefaultDisplay.createStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, true /* onTop */)); mTask = new TaskBuilder(mSupervisor).setStack(mStack).build(); @@ -112,7 +112,7 @@ public class ActivityStackTests extends ActivityTestsBase { r.setState(RESUMED, "testResumedActivityFromTaskReparenting"); assertEquals(r, mStack.getResumedActivity()); - final ActivityStack destStack = mService.mStackSupervisor.getDefaultDisplay().createStack( + final ActivityStack destStack = mRootActivityContainer.getDefaultDisplay().createStack( WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); mTask.reparent(destStack, true /* toTop */, TaskRecord.REPARENT_KEEP_STACK_AT_FRONT, @@ -130,7 +130,7 @@ public class ActivityStackTests extends ActivityTestsBase { r.setState(RESUMED, "testResumedActivityFromActivityReparenting"); assertEquals(r, mStack.getResumedActivity()); - final ActivityStack destStack = mService.mStackSupervisor.getDefaultDisplay().createStack( + final ActivityStack destStack = mRootActivityContainer.getDefaultDisplay().createStack( WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); final TaskRecord destTask = new TaskBuilder(mSupervisor).setStack(destStack).build(); @@ -239,8 +239,8 @@ public class ActivityStackTests extends ActivityTestsBase { .setUid(UserHandle.PER_USER_RANGE * 2).build(); taskOverlay.mTaskOverlay = true; - final ActivityStackSupervisor.FindTaskResult result = - new ActivityStackSupervisor.FindTaskResult(); + final RootActivityContainer.FindTaskResult result = + new RootActivityContainer.FindTaskResult(); mStack.findTaskLocked(r, result); assertEquals(r, task.getTopActivity(false /* includeOverlays */)); @@ -700,7 +700,7 @@ public class ActivityStackTests extends ActivityTestsBase { // should be destroyed immediately with updating configuration to restore original state. final ActivityRecord activity1 = finishCurrentActivity(stack1); assertEquals(DESTROYING, activity1.getState()); - verify(mSupervisor).ensureVisibilityAndConfig(eq(null) /* starting */, + verify(mRootActivityContainer).ensureVisibilityAndConfig(eq(null) /* starting */, eq(display.mDisplayId), anyBoolean(), anyBoolean()); } @@ -778,7 +778,7 @@ public class ActivityStackTests extends ActivityTestsBase { final ActivityDisplay display = mock(ActivityDisplay.class); final KeyguardController keyguardController = mSupervisor.getKeyguardController(); - doReturn(display).when(mSupervisor).getActivityDisplay(anyInt()); + doReturn(display).when(mRootActivityContainer).getActivityDisplay(anyInt()); doReturn(keyguardGoingAway).when(keyguardController).isKeyguardGoingAway(); doReturn(displaySleeping).when(display).isSleeping(); doReturn(focusedStack).when(mStack).isFocusedStackOnDisplay(); diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java index 9d93c85480bc..2ba2fdbcb959 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java @@ -74,7 +74,7 @@ public class ActivityStartControllerTests extends ActivityTestsBase { final ActivityRecord activity = new ActivityBuilder(mService).build(); final ActivityRecord source = new ActivityBuilder(mService).build(); final int startFlags = random.nextInt(); - final ActivityStack stack = mService.mStackSupervisor.getDefaultDisplay().createStack( + final ActivityStack stack = mService.mRootActivityContainer.getDefaultDisplay().createStack( WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); final WindowProcessController wpc = new WindowProcessController(mService, mService.mContext.getApplicationInfo(), "name", 12345, diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java index 27fa20b91a80..350114c792bf 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java @@ -90,6 +90,8 @@ public class ActivityStartInterceptorTest { @Mock private ActivityTaskManagerService mService; @Mock + private RootActivityContainer mRootActivityContainer; + @Mock private ActivityStackSupervisor mSupervisor; @Mock private DevicePolicyManagerInternal mDevicePolicyManager; @@ -111,7 +113,8 @@ public class ActivityStartInterceptorTest { public void setUp() { MockitoAnnotations.initMocks(this); mService.mAmInternal = mAmInternal; - mInterceptor = new ActivityStartInterceptor(mService, mSupervisor, mContext); + mInterceptor = new ActivityStartInterceptor( + mService, mSupervisor, mRootActivityContainer, mContext); mInterceptor.setStates(TEST_USER_ID, TEST_REAL_CALLING_PID, TEST_REAL_CALLING_UID, TEST_START_FLAGS, TEST_CALLING_PACKAGE); diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java index 50aa541a9549..4840a64bcbb4 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java @@ -125,7 +125,7 @@ public class ActivityStarterTests extends ActivityTestsBase { public void testUpdateLaunchBounds() { // When in a non-resizeable stack, the task bounds should be updated. final TaskRecord task = new TaskBuilder(mService.mStackSupervisor) - .setStack(mService.mStackSupervisor.getDefaultDisplay().createStack( + .setStack(mService.mRootActivityContainer.getDefaultDisplay().createStack( WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */)) .build(); final Rect bounds = new Rect(10, 10, 100, 100); @@ -136,7 +136,7 @@ public class ActivityStarterTests extends ActivityTestsBase { // When in a resizeable stack, the stack bounds should be updated as well. final TaskRecord task2 = new TaskBuilder(mService.mStackSupervisor) - .setStack(mService.mStackSupervisor.getDefaultDisplay().createStack( + .setStack(mService.mRootActivityContainer.getDefaultDisplay().createStack( WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */)) .build(); assertThat((Object) task2.getStack()).isInstanceOf(PinnedActivityStack.class); @@ -314,7 +314,7 @@ public class ActivityStarterTests extends ActivityTestsBase { * Creates a {@link ActivityStarter} with default parameters and necessary mocks. * * @param launchFlags The intent flags to launch activity. - * @param mockGetLaunchStack Whether to mock {@link ActivityStackSupervisor#getLaunchStack} for + * @param mockGetLaunchStack Whether to mock {@link RootActivityContainer#getLaunchStack} for * always launching to the testing stack. Set to false when allowing * the activity can be launched to any stack that is decided by real * implementation. @@ -323,14 +323,14 @@ public class ActivityStarterTests extends ActivityTestsBase { private ActivityStarter prepareStarter(@Intent.Flags int launchFlags, boolean mockGetLaunchStack) { // always allow test to start activity. - doReturn(true).when(mService.mStackSupervisor).checkStartAnyActivityPermission( + doReturn(true).when(mSupervisor).checkStartAnyActivityPermission( any(), any(), any(), anyInt(), anyInt(), anyInt(), any(), anyBoolean(), anyBoolean(), any(), any(), any()); // instrument the stack and task used. - final ActivityStack stack = mService.mStackSupervisor.getDefaultDisplay().createStack( + final ActivityStack stack = mRootActivityContainer.getDefaultDisplay().createStack( WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); - final TaskRecord task = new TaskBuilder(mService.mStackSupervisor) + final TaskRecord task = new TaskBuilder(mSupervisor) .setCreateStack(false) .build(); @@ -343,9 +343,9 @@ public class ActivityStarterTests extends ActivityTestsBase { if (mockGetLaunchStack) { // Direct starter to use spy stack. - doReturn(stack).when(mService.mStackSupervisor) + doReturn(stack).when(mRootActivityContainer) .getLaunchStack(any(), any(), any(), anyBoolean()); - doReturn(stack).when(mService.mStackSupervisor) + doReturn(stack).when(mRootActivityContainer) .getLaunchStack(any(), any(), any(), anyBoolean(), any()); } @@ -441,7 +441,7 @@ public class ActivityStarterTests extends ActivityTestsBase { final ActivityStack focusStack = focusActivity.getStack(); focusStack.moveToFront("testSplitScreenDeliverToTop"); - doReturn(reusableActivity).when(mService.mStackSupervisor).findTaskLocked(any(), anyInt()); + doReturn(reusableActivity).when(mRootActivityContainer).findTask(any(), anyInt()); final int result = starter.setReason("testSplitScreenDeliverToTop").execute(); @@ -473,7 +473,7 @@ public class ActivityStarterTests extends ActivityTestsBase { // Enter split-screen. Primary stack should have focus. focusActivity.getStack().setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); - doReturn(reusableActivity).when(mService.mStackSupervisor).findTaskLocked(any(), anyInt()); + doReturn(reusableActivity).when(mRootActivityContainer).findTask(any(), anyInt()); final int result = starter.setReason("testSplitScreenMoveToFront").execute(); @@ -486,7 +486,7 @@ public class ActivityStarterTests extends ActivityTestsBase { */ @Test public void testTaskModeViolation() { - final ActivityDisplay display = mService.mStackSupervisor.getDefaultDisplay(); + final ActivityDisplay display = mService.mRootActivityContainer.getDefaultDisplay(); ((TestActivityDisplay) display).removeAllTasks(); assertNoTasks(display); @@ -562,7 +562,7 @@ public class ActivityStarterTests extends ActivityTestsBase { // Create a secondary display at bottom. final TestActivityDisplay secondaryDisplay = spy(createNewActivityDisplay()); - mSupervisor.addChild(secondaryDisplay, POSITION_BOTTOM); + mRootActivityContainer.addChild(secondaryDisplay, POSITION_BOTTOM); final ActivityStack stack = secondaryDisplay.createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); @@ -600,7 +600,7 @@ public class ActivityStarterTests extends ActivityTestsBase { // Create a secondary display with an activity. final TestActivityDisplay secondaryDisplay = spy(createNewActivityDisplay()); - mSupervisor.addChild(secondaryDisplay, POSITION_TOP); + mRootActivityContainer.addChild(secondaryDisplay, POSITION_TOP); final ActivityRecord singleTaskActivity = createSingleTaskActivityOn( secondaryDisplay.createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */)); diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java index c2ab3acd4933..4fc73bc201b3 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java @@ -94,6 +94,7 @@ class ActivityTestsBase { final TestInjector mTestInjector = new TestInjector(); ActivityTaskManagerService mService; + RootActivityContainer mRootActivityContainer; ActivityStackSupervisor mSupervisor; // Default package name @@ -120,6 +121,7 @@ class ActivityTestsBase { ActivityTaskManagerService createActivityTaskManagerService() { mService = new TestActivityTaskManagerService(mContext); mSupervisor = mService.mStackSupervisor; + mRootActivityContainer = mService.mRootActivityContainer; return mService; } @@ -139,7 +141,7 @@ class ActivityTestsBase { /** Creates and adds a {@link TestActivityDisplay} to supervisor at the given position. */ TestActivityDisplay addNewActivityDisplayAt(int position) { final TestActivityDisplay display = createNewActivityDisplay(); - mSupervisor.addChild(display, position); + mRootActivityContainer.addChild(display, position); return display; } @@ -317,7 +319,7 @@ class ActivityTestsBase { TaskRecord build() { if (mStack == null && mCreateStack) { - mStack = mSupervisor.getDefaultDisplay().createStack( + mStack = mSupervisor.mRootActivityContainer.getDefaultDisplay().createStack( WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); } @@ -375,6 +377,8 @@ class ActivityTestsBase { // We keep the reference in order to prevent creating it twice. ActivityStackSupervisor mTestStackSupervisor; + ActivityDisplay mDefaultDisplay; + TestActivityTaskManagerService(Context context) { super(context); spyOn(this); @@ -390,15 +394,6 @@ class ActivityTestsBase { final TestActivityManagerService am = new TestActivityManagerService(mTestInjector, this); - // Put a home stack on the default display, so that we'll always have something - // focusable. - final TestActivityStackSupervisor supervisor = - (TestActivityStackSupervisor) mStackSupervisor; - supervisor.mDisplay.createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP); - final TaskRecord task = new TaskBuilder(mStackSupervisor) - .setStack(supervisor.getDefaultDisplay().getHomeStack()).build(); - new ActivityBuilder(this).setTask(task).build(); - spyOn(getLifecycleManager()); spyOn(getLockTaskController()); doReturn(mock(IPackageManager.class)).when(this).getPackageManager(); @@ -409,9 +404,39 @@ class ActivityTestsBase { WindowManagerService wm) { mAmInternal = amInternal; setActivityManagerService(intentFirewall, intentController); + initRootActivityContainerMocks(wm); setWindowManager(wm); } + void initRootActivityContainerMocks(WindowManagerService wm) { + spyOn(mRootActivityContainer); + mRootActivityContainer.setWindowContainerController( + mock(RootWindowContainerController.class)); + mRootActivityContainer.mWindowManager = wm; + mRootActivityContainer.mDisplayManager = + (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE); + doNothing().when(mRootActivityContainer).setWindowManager(any()); + // Invoked during {@link ActivityStack} creation. + doNothing().when(mRootActivityContainer).updateUIDsPresentOnDisplay(); + // Always keep things awake. + doReturn(true).when(mRootActivityContainer).hasAwakeDisplay(); + // Called when moving activity to pinned stack. + doNothing().when(mRootActivityContainer).ensureActivitiesVisible(any(), anyInt(), + anyBoolean()); + + // Create a default display and put a home stack on it so that we'll always have + // something focusable. + mDefaultDisplay = TestActivityDisplay.create(mStackSupervisor, DEFAULT_DISPLAY); + spyOn(mDefaultDisplay); + mRootActivityContainer.addChild(mDefaultDisplay, ActivityDisplay.POSITION_TOP); + mDefaultDisplay.createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP); + final TaskRecord task = new TaskBuilder(mStackSupervisor) + .setStack(mDefaultDisplay.getHomeStack()).build(); + new ActivityBuilder(this).setTask(task).build(); + + doReturn(mDefaultDisplay).when(mRootActivityContainer).getDefaultDisplay(); + } + @Override int handleIncomingUser(int callingPid, int callingUid, int userId, String name) { return userId; @@ -508,25 +533,14 @@ class ActivityTestsBase { * setup not available in the test environment. Also specifies an injector for */ protected class TestActivityStackSupervisor extends ActivityStackSupervisor { - private ActivityDisplay mDisplay; private KeyguardController mKeyguardController; TestActivityStackSupervisor(ActivityTaskManagerService service, Looper looper) { super(service, looper); spyOn(this); - mDisplayManager = - (DisplayManager) mService.mContext.getSystemService(Context.DISPLAY_SERVICE); mWindowManager = prepareMockWindowManager(); mKeyguardController = mock(KeyguardController.class); - setWindowContainerController(mock(RootWindowContainerController.class)); - // Invoked during {@link ActivityStack} creation. - doNothing().when(this).updateUIDsPresentOnDisplay(); - // Always keep things awake. - doReturn(true).when(this).hasAwakeDisplay(); - // Called when moving activity to pinned stack. - doNothing().when(this).ensureActivitiesVisibleLocked(any(), anyInt(), - anyBoolean()); // Do not schedule idle timeouts doNothing().when(this).scheduleIdleTimeoutLocked(any()); // unit test version does not handle launch wake lock @@ -537,24 +551,11 @@ class ActivityTestsBase { } @Override - public void initialize() { - super.initialize(); - mDisplay = TestActivityDisplay.create(this, DEFAULT_DISPLAY); - spyOn(mDisplay); - addChild(mDisplay, ActivityDisplay.POSITION_TOP); - } - - @Override public KeyguardController getKeyguardController() { return mKeyguardController; } @Override - ActivityDisplay getDefaultDisplay() { - return mDisplay; - } - - @Override void setWindowManager(WindowManagerService wm) { mWindowManager = wm; } @@ -571,7 +572,7 @@ class ActivityTestsBase { DisplayInfo info) { if (displayId == DEFAULT_DISPLAY) { return new TestActivityDisplay(supervisor, - supervisor.mDisplayManager.getDisplay(displayId)); + supervisor.mRootActivityContainer.mDisplayManager.getDisplay(displayId)); } final Display display = new Display(DisplayManagerGlobal.getInstance(), displayId, info, DEFAULT_DISPLAY_ADJUSTMENTS); @@ -579,7 +580,7 @@ class ActivityTestsBase { } TestActivityDisplay(ActivityStackSupervisor supervisor, Display display) { - super(supervisor, display); + super(supervisor.mService.mRootActivityContainer, display); // Normally this comes from display-properties as exposed by WM. Without that, just // hard-code to FULLSCREEN for tests. setWindowingMode(WINDOWING_MODE_FULLSCREEN); @@ -590,7 +591,7 @@ class ActivityTestsBase { @Override <T extends ActivityStack> T createStackUnchecked(int windowingMode, int activityType, int stackId, boolean onTop) { - return new StackBuilder(mSupervisor).setDisplay(this) + return new StackBuilder(mSupervisor.mRootActivityContainer).setDisplay(this) .setWindowingMode(windowingMode).setActivityType(activityType) .setStackId(stackId).setOnTop(onTop).setCreateActivity(false).build(); } @@ -732,8 +733,8 @@ class ActivityTestsBase { } } - protected static class StackBuilder { - private final ActivityStackSupervisor mSupervisor; + static class StackBuilder { + private final RootActivityContainer mRootActivityContainer; private ActivityDisplay mDisplay; private int mStackId = -1; private int mWindowingMode = WINDOWING_MODE_FULLSCREEN; @@ -741,9 +742,9 @@ class ActivityTestsBase { private boolean mOnTop = true; private boolean mCreateActivity = true; - StackBuilder(ActivityStackSupervisor supervisor) { - mSupervisor = supervisor; - mDisplay = mSupervisor.getDefaultDisplay(); + StackBuilder(RootActivityContainer root) { + mRootActivityContainer = root; + mDisplay = mRootActivityContainer.getDefaultDisplay(); } StackBuilder setWindowingMode(int windowingMode) { @@ -780,7 +781,8 @@ class ActivityTestsBase { <T extends ActivityStack> T build() { final int stackId = mStackId >= 0 ? mStackId : mDisplay.getNextStackId(); if (mWindowingMode == WINDOWING_MODE_PINNED) { - return (T) new PinnedActivityStack(mDisplay, stackId, mSupervisor, mOnTop) { + return (T) new PinnedActivityStack(mDisplay, stackId, + mRootActivityContainer.mStackSupervisor, mOnTop) { @Override Rect getDefaultPictureInPictureBounds(float aspectRatio) { return new Rect(50, 50, 100, 100); @@ -796,7 +798,8 @@ class ActivityTestsBase { } }; } else { - return (T) new TestActivityStack(mDisplay, stackId, mSupervisor, mWindowingMode, + return (T) new TestActivityStack(mDisplay, stackId, + mRootActivityContainer.mStackSupervisor, mWindowingMode, mActivityType, mOnTop, mCreateActivity); } } diff --git a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java index dc22bc1d5820..2c3c66be6248 100644 --- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java @@ -110,8 +110,9 @@ public class LaunchParamsPersisterTests extends ActivityTestsBase { final DisplayInfo info = new DisplayInfo(); info.uniqueId = mDisplayUniqueId; mTestDisplay = createNewActivityDisplay(info); - mSupervisor.addChild(mTestDisplay, ActivityDisplay.POSITION_TOP); - when(mSupervisor.getActivityDisplay(eq(mDisplayUniqueId))).thenReturn(mTestDisplay); + mRootActivityContainer.addChild(mTestDisplay, ActivityDisplay.POSITION_TOP); + when(mRootActivityContainer.getActivityDisplay(eq(mDisplayUniqueId))) + .thenReturn(mTestDisplay); ActivityStack stack = mTestDisplay.createStack(TEST_WINDOWING_MODE, ACTIVITY_TYPE_STANDARD, /* onTop */ true); @@ -184,7 +185,7 @@ public class LaunchParamsPersisterTests extends ActivityTestsBase { public void testReturnsEmptyDisplayIfDisplayIsNotFound() { mTarget.saveTask(mTestTask); - when(mSupervisor.getActivityDisplay(eq(mDisplayUniqueId))).thenReturn(null); + when(mRootActivityContainer.getActivityDisplay(eq(mDisplayUniqueId))).thenReturn(null); mTarget.getLaunchParams(mTestTask, null, mResult); diff --git a/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java index 33e6063bbb97..6259fa669ce8 100644 --- a/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java @@ -104,6 +104,7 @@ public class LockTaskControllerTest { new DexmakerShareClassLoaderRule(); @Mock private ActivityStackSupervisor mSupervisor; + @Mock private RootActivityContainer mRootActivityContainer; @Mock private IDevicePolicyManager mDevicePolicyManager; @Mock private IStatusBarService mStatusBarService; @Mock private WindowManagerService mWindowManager; @@ -129,6 +130,7 @@ public class LockTaskControllerTest { } mSupervisor.mRecentTasks = mRecentTasks; + mSupervisor.mRootActivityContainer = mRootActivityContainer; mLockTaskController = new LockTaskController(mContext, mSupervisor, new ImmediatelyExecuteHandler()); diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java index 8596c77bc73a..3c7b4b1248b5 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java @@ -113,9 +113,10 @@ public class RecentTasksTest extends ActivityTestsBase { mTestService = new MyTestActivityTaskManagerService(mContext); mRecentTasks = (TestRecentTasks) mTestService.getRecentTasks(); mRecentTasks.loadParametersFromResources(mContext.getResources()); - mHomeStack = mTestService.mStackSupervisor.getDefaultDisplay().getOrCreateStack( + mRunningTasks = (TestRunningTasks) mTestService.mStackSupervisor.mRunningTasks; + mHomeStack = mTestService.mRootActivityContainer.getDefaultDisplay().getOrCreateStack( WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */); - mStack = mTestService.mStackSupervisor.getDefaultDisplay().createStack( + mStack = mTestService.mRootActivityContainer.getDefaultDisplay().createStack( WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); mCallbacksRecorder = new CallbacksRecorder(); mRecentTasks.registerCallback(mCallbacksRecorder); @@ -872,6 +873,15 @@ public class RecentTasksTest extends ActivityTestsBase { } return mTestStackSupervisor; } + + @Override + void initRootActivityContainerMocks(WindowManagerService wm) { + super.initRootActivityContainerMocks(wm); + mDisplay = mRootActivityContainer.getActivityDisplay(DEFAULT_DISPLAY); + mOtherDisplay = TestActivityDisplay.create(mTestStackSupervisor, DEFAULT_DISPLAY + 1); + mRootActivityContainer.addChild(mOtherDisplay, ActivityDisplay.POSITION_TOP); + mRootActivityContainer.addChild(mDisplay, ActivityDisplay.POSITION_TOP); + } } private class MyTestActivityStackSupervisor extends TestActivityStackSupervisor { @@ -880,15 +890,6 @@ public class RecentTasksTest extends ActivityTestsBase { } @Override - public void initialize() { - super.initialize(); - mDisplay = getActivityDisplay(DEFAULT_DISPLAY); - mOtherDisplay = TestActivityDisplay.create(this, DEFAULT_DISPLAY + 1); - addChild(mOtherDisplay, ActivityDisplay.POSITION_TOP); - addChild(mDisplay, ActivityDisplay.POSITION_TOP); - } - - @Override RunningTasks createRunningTasks() { mRunningTasks = new TestRunningTasks(); return mRunningTasks; diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java index 070f0731ba2f..0ff67d7b1f83 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java @@ -67,9 +67,9 @@ public class RecentsAnimationTest extends ActivityTestsBase { @Test public void testCancelAnimationOnStackOrderChange() { ActivityStack fullscreenStack = - mService.mStackSupervisor.getDefaultDisplay().createStack( + mService.mRootActivityContainer.getDefaultDisplay().createStack( WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); - ActivityStack recentsStack = mService.mStackSupervisor.getDefaultDisplay().createStack( + ActivityStack recentsStack = mService.mRootActivityContainer.getDefaultDisplay().createStack( WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_RECENTS, true /* onTop */); ActivityRecord recentsActivity = new ActivityBuilder(mService) .setComponent(mRecentsComponent) @@ -77,7 +77,7 @@ public class RecentsAnimationTest extends ActivityTestsBase { .setStack(recentsStack) .build(); ActivityStack fullscreenStack2 = - mService.mStackSupervisor.getDefaultDisplay().createStack( + mService.mRootActivityContainer.getDefaultDisplay().createStack( WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); ActivityRecord fsActivity = new ActivityBuilder(mService) .setComponent(new ComponentName(mContext.getPackageName(), "App1")) diff --git a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java new file mode 100644 index 000000000000..631de99dc3ad --- /dev/null +++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java @@ -0,0 +1,483 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.server.wm; + +import static android.app.ActivityManager.START_DELIVERED_TO_TOP; +import static android.app.ActivityManager.START_TASK_TO_FRONT; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; +import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; +import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY; +import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; +import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; +import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE; +import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE; +import static android.view.Display.DEFAULT_DISPLAY; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.never; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.times; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; +import static com.android.server.wm.ActivityDisplay.POSITION_TOP; +import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING; +import static com.android.server.wm.RootActivityContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE; +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.contains; +import static org.mockito.ArgumentMatchers.eq; + +import android.app.ActivityOptions; +import android.app.WaitResult; +import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; +import android.graphics.Rect; +import android.os.Build; +import android.platform.test.annotations.Presubmit; +import androidx.test.filters.MediumTest; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; + +/** + * Tests for the {@link ActivityStackSupervisor} class. + * + * Build/Install/Run: + * atest WmTests:ActivityStackSupervisorTests + */ +@MediumTest +@Presubmit +public class RootActivityContainerTests extends ActivityTestsBase { + private ActivityStack mFullscreenStack; + + @Before + public void setUp() throws Exception { + setupActivityTaskManagerService(); + mFullscreenStack = mRootActivityContainer.getDefaultDisplay().createStack( + WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); + } + + /** + * This test ensures that we do not try to restore a task based off an invalid task id. We + * should expect {@code null} to be returned in this case. + */ + @Test + public void testRestoringInvalidTask() { + ((TestActivityDisplay) mRootActivityContainer.getDefaultDisplay()).removeAllTasks(); + TaskRecord task = mRootActivityContainer.anyTaskForId(0 /*taskId*/, + MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, null, false /* onTop */); + assertNull(task); + } + + /** + * This test ensures that an existing task in the pinned stack is moved to the fullscreen + * activity stack when a new task is added. + */ + @Test + public void testReplacingTaskInPinnedStack() { + final ActivityRecord firstActivity = new ActivityBuilder(mService).setCreateTask(true) + .setStack(mFullscreenStack).build(); + final TaskRecord firstTask = firstActivity.getTask(); + + final ActivityRecord secondActivity = new ActivityBuilder(mService).setCreateTask(true) + .setStack(mFullscreenStack).build(); + final TaskRecord secondTask = secondActivity.getTask(); + + mFullscreenStack.moveToFront("testReplacingTaskInPinnedStack"); + + // Ensure full screen stack has both tasks. + ensureStackPlacement(mFullscreenStack, firstTask, secondTask); + + // Move first activity to pinned stack. + final Rect sourceBounds = new Rect(); + mRootActivityContainer.moveActivityToPinnedStack(firstActivity, sourceBounds, + 0f /*aspectRatio*/, "initialMove"); + + final ActivityDisplay display = mFullscreenStack.getDisplay(); + ActivityStack pinnedStack = display.getPinnedStack(); + // Ensure a task has moved over. + ensureStackPlacement(pinnedStack, firstTask); + ensureStackPlacement(mFullscreenStack, secondTask); + + // Move second activity to pinned stack. + mRootActivityContainer.moveActivityToPinnedStack(secondActivity, sourceBounds, + 0f /*aspectRatio*/, "secondMove"); + + // Need to get stacks again as a new instance might have been created. + pinnedStack = display.getPinnedStack(); + mFullscreenStack = display.getStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD); + // Ensure stacks have swapped tasks. + ensureStackPlacement(pinnedStack, secondTask); + ensureStackPlacement(mFullscreenStack, firstTask); + } + + private static void ensureStackPlacement(ActivityStack stack, TaskRecord... tasks) { + final ArrayList<TaskRecord> stackTasks = stack.getAllTasks(); + assertEquals(stackTasks.size(), tasks != null ? tasks.length : 0); + + if (tasks == null) { + return; + } + + for (TaskRecord task : tasks) { + assertTrue(stackTasks.contains(task)); + } + } + + @Test + public void testApplySleepTokens() { + final ActivityDisplay display = mRootActivityContainer.getDefaultDisplay(); + final KeyguardController keyguard = mSupervisor.getKeyguardController(); + final ActivityStack stack = mock(ActivityStack.class); + display.addChild(stack, 0 /* position */); + + // Make sure we wake and resume in the case the display is turning on and the keyguard is + // not showing. + verifySleepTokenBehavior(display, keyguard, stack, true /*displaySleeping*/, + false /* displayShouldSleep */, true /* isFocusedStack */, + false /* keyguardShowing */, true /* expectWakeFromSleep */, + true /* expectResumeTopActivity */); + + // Make sure we wake and don't resume when the display is turning on and the keyguard is + // showing. + verifySleepTokenBehavior(display, keyguard, stack, true /*displaySleeping*/, + false /* displayShouldSleep */, true /* isFocusedStack */, + true /* keyguardShowing */, true /* expectWakeFromSleep */, + false /* expectResumeTopActivity */); + + // Make sure we wake and don't resume when the display is turning on and the keyguard is + // not showing as unfocused. + verifySleepTokenBehavior(display, keyguard, stack, true /*displaySleeping*/, + false /* displayShouldSleep */, false /* isFocusedStack */, + false /* keyguardShowing */, true /* expectWakeFromSleep */, + false /* expectResumeTopActivity */); + + // Should not do anything if the display state hasn't changed. + verifySleepTokenBehavior(display, keyguard, stack, false /*displaySleeping*/, + false /* displayShouldSleep */, true /* isFocusedStack */, + false /* keyguardShowing */, false /* expectWakeFromSleep */, + false /* expectResumeTopActivity */); + } + + private void verifySleepTokenBehavior(ActivityDisplay display, KeyguardController keyguard, + ActivityStack stack, boolean displaySleeping, boolean displayShouldSleep, + boolean isFocusedStack, boolean keyguardShowing, boolean expectWakeFromSleep, + boolean expectResumeTopActivity) { + reset(stack); + + doReturn(displayShouldSleep).when(display).shouldSleep(); + doReturn(displaySleeping).when(display).isSleeping(); + doReturn(keyguardShowing).when(keyguard).isKeyguardOrAodShowing(anyInt()); + + doReturn(isFocusedStack).when(stack).isFocusedStackOnDisplay(); + doReturn(isFocusedStack ? stack : null).when(display).getFocusedStack(); + mRootActivityContainer.applySleepTokens(true); + verify(stack, times(expectWakeFromSleep ? 1 : 0)).awakeFromSleepingLocked(); + verify(stack, times(expectResumeTopActivity ? 1 : 0)).resumeTopActivityUncheckedLocked( + null /* target */, null /* targetOptions */); + } + + /** + * Verifies that removal of activity with task and stack is done correctly. + */ + @Test + public void testRemovingStackOnAppCrash() { + final ActivityDisplay defaultDisplay = mRootActivityContainer.getDefaultDisplay(); + final int originalStackCount = defaultDisplay.getChildCount(); + final ActivityStack stack = mRootActivityContainer.getDefaultDisplay().createStack( + WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */); + final ActivityRecord firstActivity = new ActivityBuilder(mService).setCreateTask(true) + .setStack(stack).build(); + + assertEquals(originalStackCount + 1, defaultDisplay.getChildCount()); + + // Let's pretend that the app has crashed. + firstActivity.app.setThread(null); + mRootActivityContainer.finishTopCrashedActivities(firstActivity.app, "test"); + + // Verify that the stack was removed. + assertEquals(originalStackCount, defaultDisplay.getChildCount()); + } + + @Test + public void testFocusability() { + final ActivityStack stack = mRootActivityContainer.getDefaultDisplay().createStack( + WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, true /* onTop */); + final ActivityRecord activity = new ActivityBuilder(mService).setCreateTask(true) + .setStack(stack).build(); + + // Under split screen primary we should be focusable when not minimized + mRootActivityContainer.setDockedStackMinimized(false); + assertTrue(stack.isFocusable()); + assertTrue(activity.isFocusable()); + + // Under split screen primary we should not be focusable when minimized + mRootActivityContainer.setDockedStackMinimized(true); + assertFalse(stack.isFocusable()); + assertFalse(activity.isFocusable()); + + final ActivityStack pinnedStack = mRootActivityContainer.getDefaultDisplay().createStack( + WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */); + final ActivityRecord pinnedActivity = new ActivityBuilder(mService).setCreateTask(true) + .setStack(pinnedStack).build(); + + // We should not be focusable when in pinned mode + assertFalse(pinnedStack.isFocusable()); + assertFalse(pinnedActivity.isFocusable()); + + // Add flag forcing focusability. + pinnedActivity.info.flags |= FLAG_ALWAYS_FOCUSABLE; + + // We should not be focusable when in pinned mode + assertTrue(pinnedStack.isFocusable()); + assertTrue(pinnedActivity.isFocusable()); + + // Without the overridding activity, stack should not be focusable. + pinnedStack.removeTask(pinnedActivity.getTask(), "testFocusability", + REMOVE_TASK_MODE_DESTROYING); + assertFalse(pinnedStack.isFocusable()); + } + + /** + * Verify that split-screen primary stack will be chosen if activity is launched that targets + * split-screen secondary, but a matching existing instance is found on top of split-screen + * primary stack. + */ + @Test + public void testSplitScreenPrimaryChosenWhenTopActivityLaunchedToSecondary() { + // Create primary split-screen stack with a task and an activity. + final ActivityStack primaryStack = mRootActivityContainer.getDefaultDisplay() + .createStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, + true /* onTop */); + final TaskRecord task = new TaskBuilder(mSupervisor).setStack(primaryStack).build(); + final ActivityRecord r = new ActivityBuilder(mService).setTask(task).build(); + + // Find a launch stack for the top activity in split-screen primary, while requesting + // split-screen secondary. + final ActivityOptions options = ActivityOptions.makeBasic(); + options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY); + final ActivityStack result = + mRootActivityContainer.getLaunchStack(r, options, task, true /* onTop */); + + // Assert that the primary stack is returned. + assertEquals(primaryStack, result); + } + + /** + * Verify split-screen primary stack & task can resized by + * {@link android.app.IActivityTaskManager#resizeDockedStack} as expect. + */ + @Test + public void testResizeDockedStackForSplitScreenPrimary() { + final Rect taskSize = new Rect(0, 0, 600, 600); + final Rect stackSize = new Rect(0, 0, 300, 300); + + // Create primary split-screen stack with a task. + final ActivityStack primaryStack = mRootActivityContainer.getDefaultDisplay() + .createStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, + true /* onTop */); + final TaskRecord task = new TaskBuilder(mSupervisor).setStack(primaryStack).build(); + + // Resize dock stack. + mService.resizeDockedStack(stackSize, taskSize, null, null, null); + + // Verify dock stack & its task bounds if is equal as resized result. + assertEquals(primaryStack.getBounds(), stackSize); + assertEquals(task.getBounds(), taskSize); + } + + /** + * Verify that home stack would be moved to front when the top activity is Recents. + */ + @Test + public void testFindTaskToMoveToFrontWhenRecentsOnTop() { + // Create stack/task on default display. + final ActivityDisplay display = mRootActivityContainer.getDefaultDisplay(); + final TestActivityStack targetStack = + new StackBuilder(mRootActivityContainer).setOnTop(false).build(); + final TaskRecord targetTask = targetStack.getChildAt(0); + + // Create Recents on top of the display. + final ActivityStack stack = new StackBuilder(mRootActivityContainer).setActivityType( + ACTIVITY_TYPE_RECENTS).build(); + + final String reason = "findTaskToMoveToFront"; + mSupervisor.findTaskToMoveToFront(targetTask, 0, ActivityOptions.makeBasic(), reason, + false); + + verify(display).moveHomeStackToFront(contains(reason)); + } + + /** + * Verify that home stack won't be moved to front if the top activity on other display is + * Recents. + */ + @Test + public void testFindTaskToMoveToFrontWhenRecentsOnOtherDisplay() { + // Create stack/task on default display. + final ActivityDisplay display = mRootActivityContainer.getDefaultDisplay(); + final ActivityStack targetStack = display.createStack(WINDOWING_MODE_FULLSCREEN, + ACTIVITY_TYPE_STANDARD, false /* onTop */); + final TaskRecord targetTask = new TaskBuilder(mSupervisor).setStack(targetStack).build(); + + // Create Recents on secondary display. + final TestActivityDisplay secondDisplay = addNewActivityDisplayAt( + ActivityDisplay.POSITION_TOP); + final ActivityStack stack = secondDisplay.createStack(WINDOWING_MODE_FULLSCREEN, + ACTIVITY_TYPE_RECENTS, true /* onTop */); + final TaskRecord task = new TaskBuilder(mSupervisor).setStack(stack).build(); + new ActivityBuilder(mService).setTask(task).build(); + + final String reason = "findTaskToMoveToFront"; + mSupervisor.findTaskToMoveToFront(targetTask, 0, ActivityOptions.makeBasic(), reason, + false); + + verify(display, never()).moveHomeStackToFront(contains(reason)); + } + + /** + * Verify if a stack is not at the topmost position, it should be able to resume its activity if + * the stack is the top focused. + */ + @Test + public void testResumeActivityWhenNonTopmostStackIsTopFocused() { + // Create a stack at bottom. + final ActivityDisplay display = mRootActivityContainer.getDefaultDisplay(); + final ActivityStack targetStack = spy(display.createStack(WINDOWING_MODE_FULLSCREEN, + ACTIVITY_TYPE_STANDARD, false /* onTop */)); + final TaskRecord task = new TaskBuilder(mSupervisor).setStack(targetStack).build(); + final ActivityRecord activity = new ActivityBuilder(mService).setTask(task).build(); + display.positionChildAtBottom(targetStack); + + // Assume the stack is not at the topmost position (e.g. behind always-on-top stacks) but it + // is the current top focused stack. + assertFalse(targetStack.isTopStackOnDisplay()); + doReturn(targetStack).when(mRootActivityContainer).getTopDisplayFocusedStack(); + + // Use the stack as target to resume. + mRootActivityContainer.resumeFocusedStacksTopActivities( + targetStack, activity, null /* targetOptions */); + + // Verify the target stack should resume its activity. + verify(targetStack, times(1)).resumeTopActivityUncheckedLocked( + eq(activity), eq(null /* targetOptions */)); + } + + /** + * Tests home activities that targeted sdk before Q cannot start on secondary display. + */ + @Test + public void testStartHomeTargetSdkBeforeQ() throws Exception { + final TestActivityDisplay secondDisplay = spy(createNewActivityDisplay()); + mRootActivityContainer.addChild(secondDisplay, POSITION_TOP); + doReturn(true).when(secondDisplay).supportsSystemDecorations(); + + final ActivityInfo info = new ActivityInfo(); + info.launchMode = LAUNCH_MULTIPLE; + info.applicationInfo = new ApplicationInfo(); + info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.Q; + assertTrue(mRootActivityContainer.canStartHomeOnDisplay(info, secondDisplay.mDisplayId, + false /* allowInstrumenting */)); + + info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.P; + assertFalse(mRootActivityContainer.canStartHomeOnDisplay(info, secondDisplay.mDisplayId, + false /* allowInstrumenting */)); + } + + /** + * Tests that home activities can be started on the displays that supports system decorations. + */ + @Test + public void testStartHomeOnAllDisplays() { + // Create secondary displays. + final TestActivityDisplay secondDisplay = spy(createNewActivityDisplay()); + mRootActivityContainer.addChild(secondDisplay, POSITION_TOP); + doReturn(true).when(secondDisplay).supportsSystemDecorations(); + + // Create mock tasks and other necessary mocks. + TaskBuilder taskBuilder = new TaskBuilder(mService.mStackSupervisor).setCreateStack(false); + final TaskRecord.TaskRecordFactory factory = mock(TaskRecord.TaskRecordFactory.class); + TaskRecord.setTaskRecordFactory(factory); + doAnswer(i -> taskBuilder.build()).when(factory) + .create(any(), anyInt(), any(), any(), any(), any()); + doReturn(true).when(mRootActivityContainer) + .ensureVisibilityAndConfig(any(), anyInt(), anyBoolean(), anyBoolean()); + doReturn(true).when(mRootActivityContainer).canStartHomeOnDisplay( + any(), anyInt(), anyBoolean()); + + mRootActivityContainer.startHomeOnAllDisplays(0, "testStartHome"); + + assertTrue(mRootActivityContainer.getDefaultDisplay().getTopStack().isActivityTypeHome()); + assertNotNull(secondDisplay.getTopStack()); + assertTrue(secondDisplay.getTopStack().isActivityTypeHome()); + } + + /** + * Tests that home activities won't be started before booting when display added. + */ + @Test + public void testNotStartHomeBeforeBoot() { + final int displayId = 1; + final boolean isBooting = mService.mAmInternal.isBooting(); + final boolean isBooted = mService.mAmInternal.isBooted(); + try { + mService.mAmInternal.setBooting(false); + mService.mAmInternal.setBooted(false); + mRootActivityContainer.onDisplayAdded(displayId); + verify(mRootActivityContainer, never()).startHomeOnDisplay(anyInt(), any(), anyInt()); + } finally { + mService.mAmInternal.setBooting(isBooting); + mService.mAmInternal.setBooted(isBooted); + } + } + + /** + * Tests whether home can be started if being instrumented. + */ + @Test + public void testCanStartHomeWhenInstrumented() { + final ActivityInfo info = new ActivityInfo(); + info.applicationInfo = new ApplicationInfo(); + final WindowProcessController app = mock(WindowProcessController.class); + doReturn(app).when(mService).getProcessController(any(), anyInt()); + + // Can not start home if we don't want to start home while home is being instrumented. + doReturn(true).when(app).isInstrumenting(); + assertFalse(mRootActivityContainer.canStartHomeOnDisplay(info, DEFAULT_DISPLAY, + false /* allowInstrumenting*/)); + + // Can start home for other cases. + assertTrue(mRootActivityContainer.canStartHomeOnDisplay(info, DEFAULT_DISPLAY, + true /* allowInstrumenting*/)); + + doReturn(false).when(app).isInstrumenting(); + assertTrue(mRootActivityContainer.canStartHomeOnDisplay(info, DEFAULT_DISPLAY, + false /* allowInstrumenting*/)); + assertTrue(mRootActivityContainer.canStartHomeOnDisplay(info, DEFAULT_DISPLAY, + true /* allowInstrumenting*/)); + } +} diff --git a/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java index 0e1624ebef63..a8b6dc373cbf 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java @@ -63,7 +63,7 @@ public class RunningTasksTest extends ActivityTestsBase { final int numStacks = 2; for (int stackIndex = 0; stackIndex < numStacks; stackIndex++) { final ActivityStack stack = - new StackBuilder(mSupervisor).setCreateActivity(false).build(); + new StackBuilder(mRootActivityContainer).setCreateActivity(false).build(); display.addChild(stack, POSITION_BOTTOM); } diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java index 6638eeb8af19..bd8cd1f37f5e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java @@ -888,10 +888,10 @@ public class TaskLaunchParamsModifierTests extends ActivityTestsBase { @Test public void testAdjustBoundsToFitNewDisplay_LargerThanDisplay_RTL() { - final Configuration overrideConfig = mSupervisor.getOverrideConfiguration(); + final Configuration overrideConfig = mRootActivityContainer.getOverrideConfiguration(); // Egyptian Arabic is a RTL language. overrideConfig.setLayoutDirection(new Locale("ar", "EG")); - mSupervisor.onOverrideConfigurationChanged(overrideConfig); + mRootActivityContainer.onOverrideConfigurationChanged(overrideConfig); final TestActivityDisplay freeformDisplay = createNewActivityDisplay( WINDOWING_MODE_FREEFORM); |