Loading services/core/java/com/android/server/wm/DisplayContent.java +10 −14 Original line number Diff line number Diff line Loading @@ -2260,9 +2260,12 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp taskDisplayArea.getRootTask(rootTaskId)); } protected int getRootTaskCount() { return reduceOnAllTaskDisplayAreas((taskDisplayArea, count) -> count + taskDisplayArea.getRootTaskCount(), 0 /* initValue */); int getRootTaskCount() { final int[] count = new int[1]; forAllRootTasks(task -> { count[0]++; }); return count[0]; } @VisibleForTesting Loading Loading @@ -5353,19 +5356,12 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } // Check if all task display areas have only the empty home stacks left. boolean hasNonEmptyHomeStack = forAllTaskDisplayAreas(taskDisplayArea -> { if (taskDisplayArea.getRootTaskCount() != 1) { return true; } final Task stack = taskDisplayArea.getRootTaskAt(0); return !stack.isActivityTypeHome() || stack.hasChild(); }); if (!hasNonEmptyHomeStack) { boolean hasNonEmptyHomeStack = forAllRootTasks(stack -> !stack.isActivityTypeHome() || stack.hasChild()); if (!hasNonEmptyHomeStack && getRootTaskCount() > 0) { // Release this display if only empty home stack(s) are left. This display will be // released along with the stack(s) removal. forAllTaskDisplayAreas(taskDisplayArea -> { taskDisplayArea.getRootTaskAt(0).removeIfPossible(); }); forAllRootTasks(Task::removeIfPossible); } else if (getTopRootTask() == null) { removeIfPossible(); mRootWindowContainer.mTaskSupervisor Loading services/core/java/com/android/server/wm/KeyguardController.java +2 −10 Original line number Diff line number Diff line Loading @@ -594,16 +594,8 @@ class KeyguardController { */ @Nullable private Task getRootTaskForControllingOccluding(DisplayContent display) { return display.getItemFromTaskDisplayAreas(taskDisplayArea -> { for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { final Task task = taskDisplayArea.getRootTaskAt(sNdx); if (task != null && task.isFocusableAndVisible() && !task.inPinnedWindowingMode()) { return task; } } return null; }); return display.getRootTask(task -> task != null && task.isFocusableAndVisible() && !task.inPinnedWindowingMode()); } void dumpStatus(PrintWriter pw, String prefix) { Loading services/core/java/com/android/server/wm/RecentsAnimation.java +2 −8 Original line number Diff line number Diff line Loading @@ -468,14 +468,8 @@ class RecentsAnimation implements RecentsAnimationCallbacks, OnRootTaskOrderChan * @return The top stack that is not always-on-top. */ private Task getTopNonAlwaysOnTopStack() { for (int i = mDefaultTaskDisplayArea.getRootTaskCount() - 1; i >= 0; i--) { final Task s = mDefaultTaskDisplayArea.getRootTaskAt(i); if (s.getWindowConfiguration().isAlwaysOnTop()) { continue; } return s; } return null; return mDefaultTaskDisplayArea.getRootTask(task -> !task.getWindowConfiguration().isAlwaysOnTop()); } /** Loading services/core/java/com/android/server/wm/RootWindowContainer.java +150 −208 Original line number Diff line number Diff line Loading @@ -1835,10 +1835,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> final ArrayList<IBinder> topActivityTokens = new ArrayList<>(); final Task topFocusedStack = getTopDisplayFocusedRootTask(); // Traverse all displays. forAllTaskDisplayAreas(taskDisplayArea -> { // Traverse all stacks on a display area. for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { final Task stack = taskDisplayArea.getRootTaskAt(sNdx); forAllRootTasks(stack -> { // Get top activity from a visible stack and add it to the list. if (stack.shouldBeVisible(null /* starting */)) { final ActivityRecord top = stack.getTopNonFinishingActivity(); Loading @@ -1850,7 +1847,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } } } } }); return topActivityTokens; } Loading Loading @@ -1892,21 +1888,17 @@ class RootWindowContainer extends WindowContainer<DisplayContent> // 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 = reduceOnAllTaskDisplayAreas((taskDisplayArea, app) -> { for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { final Task stack = taskDisplayArea.getRootTaskAt(sNdx); WindowProcessController fgApp = getItemFromRootTasks(stack -> { if (isTopDisplayFocusedRootTask(stack)) { final ActivityRecord resumedActivity = stack.getResumedActivity(); if (resumedActivity != null) { app = resumedActivity.app; return resumedActivity.app; } else if (stack.mPausingActivity != null) { app = stack.mPausingActivity.app; } break; return stack.mPausingActivity.app; } } return app; }, null /* initValue */); return null; }); // Now set this one as the previous process, only if that really makes sense to. if (r.hasProcess() && fgApp != null && r.app != fgApp Loading @@ -1923,15 +1915,13 @@ class RootWindowContainer extends WindowContainer<DisplayContent> mTmpRemoteException = null; mTmpBoolean = false; // Set to true if an activity was started. final DisplayContent display = getChildAt(displayNdx); display.forAllTaskDisplayAreas(displayArea -> { display.forAllRootTasks(rootTask -> { if (mTmpRemoteException != null) { return; } for (int taskNdx = displayArea.getRootTaskCount() - 1; taskNdx >= 0; --taskNdx) { final Task rootTask = displayArea.getRootTaskAt(taskNdx); if (rootTask.getVisibility(null /*starting*/) == TASK_VISIBILITY_INVISIBLE) { break; return; } final PooledFunction c = PooledLambda.obtainFunction( Loading @@ -1940,10 +1930,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent> rootTask.topRunningActivity()); rootTask.forAllActivities(c); c.recycle(); if (mTmpRemoteException != null) { return; } } }); if (mTmpRemoteException != null) { throw mTmpRemoteException; Loading Loading @@ -2027,11 +2013,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent> mCurrentUser = userId; mTaskSupervisor.mStartingUsers.add(uss); forAllTaskDisplayAreas(taskDisplayArea -> { for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { final Task stack = taskDisplayArea.getRootTaskAt(sNdx); forAllRootTasks(stack -> { stack.switchUser(userId); } }); final int restoreStackId = mUserRootTaskInFront.get(userId); Loading Loading @@ -2294,20 +2277,14 @@ class RootWindowContainer extends WindowContainer<DisplayContent> */ int finishTopCrashedActivities(WindowProcessController app, String reason) { Task focusedStack = getTopDisplayFocusedRootTask(); Task finishedTask = reduceOnAllTaskDisplayAreas((taskDisplayArea, task) -> { // 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 < taskDisplayArea.getRootTaskCount(); ++stackNdx) { final Task stack = taskDisplayArea.getRootTaskAt(stackNdx); final Task[] finishedTask = new Task[1]; forAllTasks(stack -> { final Task t = stack.finishTopCrashedActivityLocked(app, reason); if (stack == focusedStack || task == null) { task = t; } if (stack == focusedStack || finishedTask[0] == null) { finishedTask[0] = t; } return task; }, null /* initValue */); return finishedTask != null ? finishedTask.mTaskId : INVALID_TASK_ID; }); return finishedTask[0] != null ? finishedTask[0].mTaskId : INVALID_TASK_ID; } boolean resumeFocusedTasksTopActivities() { Loading @@ -2330,36 +2307,32 @@ class RootWindowContainer extends WindowContainer<DisplayContent> for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) { final DisplayContent display = getChildAt(displayNdx); final boolean curResult = result; boolean resumedOnDisplay = display.reduceOnAllTaskDisplayAreas( (taskDisplayArea, resumed) -> { for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { final Task rootTask = taskDisplayArea.getRootTaskAt(sNdx); boolean[] resumedOnDisplay = new boolean[1]; display.forAllRootTasks(rootTask -> { final ActivityRecord topRunningActivity = rootTask.topRunningActivity(); if (!rootTask.isFocusableAndVisible() || topRunningActivity == null) { continue; return; } if (rootTask == targetRootTask) { // Simply update the result for targetStack because the targetStack // had already resumed in above. We don't want to resume it again, // especially in some cases, it would cause a second launch failure // if app process was dead. resumed |= curResult; continue; resumedOnDisplay[0] |= curResult; return; } if (taskDisplayArea.isTopRootTask(rootTask) if (rootTask.getDisplayArea().isTopRootTask(rootTask) && topRunningActivity.isState(RESUMED)) { // Kick off any lingering app transitions form the MoveTaskToFront // operation, but only consider the top task and stack on that // display. rootTask.executeAppTransition(targetOptions); } else { resumed |= topRunningActivity.makeActiveIfNeeded(target); resumedOnDisplay[0] |= topRunningActivity.makeActiveIfNeeded(target); } } return resumed; }, false /* initValue */); result |= resumedOnDisplay; if (!resumedOnDisplay) { }); result |= resumedOnDisplay[0]; if (!resumedOnDisplay[0]) { // In cases when there are no valid activities (e.g. device just booted or launcher // crashed) it's possible that nothing was resumed on a display. Requesting resume // of top activity in focused stack explicitly will make sure that at least home Loading Loading @@ -2392,9 +2365,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } // Set the sleeping state of the stacks on the display. display.forAllTaskDisplayAreas(taskDisplayArea -> { for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { final Task stack = taskDisplayArea.getRootTaskAt(sNdx); display.forAllRootTasks(stack -> { if (displayShouldSleep) { stack.goToSleepIfPossible(false /* shuttingDown */); } else { Loading @@ -2416,7 +2387,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent> stack.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */, false /* preserveWindows */); } } }); } } Loading Loading @@ -2512,13 +2482,10 @@ class RootWindowContainer extends WindowContainer<DisplayContent> /** If displayId == INVALID_DISPLAY, this will get root task infos on all displays */ ArrayList<RootTaskInfo> getAllRootTaskInfos(int displayId) { ArrayList<RootTaskInfo> list = new ArrayList<>(); final ArrayList<RootTaskInfo> list = new ArrayList<>(); if (displayId == INVALID_DISPLAY) { forAllTaskDisplayAreas(taskDisplayArea -> { for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { final Task stack = taskDisplayArea.getRootTaskAt(sNdx); forAllRootTasks(stack -> { list.add(getRootTaskInfo(stack)); } }); return list; } Loading @@ -2526,11 +2493,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent> if (display == null) { return list; } display.forAllTaskDisplayAreas(taskDisplayArea -> { for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { final Task stack = taskDisplayArea.getRootTaskAt(sNdx); display.forAllRootTasks(stack -> { list.add(getRootTaskInfo(stack)); } }); return list; } Loading Loading @@ -2603,10 +2567,17 @@ class RootWindowContainer extends WindowContainer<DisplayContent> Task findRootTaskBehind(Task rootTask) { final TaskDisplayArea taskDisplayArea = rootTask.getDisplayArea(); if (taskDisplayArea != null) { for (int i = taskDisplayArea.getRootTaskCount() - 1; i >= 0; i--) { if (taskDisplayArea.getRootTaskAt(i) == rootTask && i > 0) { return taskDisplayArea.getRootTaskAt(i - 1); final boolean[] hasFound = new boolean[1]; // TODO(b/175136051): should this be only the direct child root task? final Task rootTaskBehind = taskDisplayArea.getRootTask(task -> { if (hasFound[0]) { return true; } hasFound[0] = task == rootTask; return false; }); if (rootTaskBehind != null) { return rootTaskBehind; } } throw new IllegalStateException("Failed to find a root task behind root task =" + rootTask Loading Loading @@ -2748,24 +2719,16 @@ class RootWindowContainer extends WindowContainer<DisplayContent> // Tries to put all activity tasks to sleep. Returns true if all tasks were // successfully put to sleep. boolean putTasksToSleep(boolean allowDelay, boolean shuttingDown) { return reduceOnAllTaskDisplayAreas((taskDisplayArea, result) -> { for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { // Stacks and activities could be removed while putting activities to sleep if // the app process was gone. This prevents us getting exception by accessing an // invalid stack index. if (sNdx >= taskDisplayArea.getRootTaskCount()) { continue; } final Task task = taskDisplayArea.getRootTaskAt(sNdx); final boolean[] result = {true}; forAllRootTasks(task -> { if (allowDelay) { result &= task.goToSleepIfPossible(shuttingDown); result[0] &= task.goToSleepIfPossible(shuttingDown); } else { task.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */, !PRESERVE_WINDOWS); } } return result; }, true /* initValue */); }); return result[0]; } void handleAppCrash(WindowProcessController app) { Loading Loading @@ -3021,11 +2984,11 @@ class RootWindowContainer extends WindowContainer<DisplayContent> r.getActivityType()); // Return the topmost valid stack on the display. for (int i = taskDisplayArea.getRootTaskCount() - 1; i >= 0; --i) { final Task stack = taskDisplayArea.getRootTaskAt(i); if (isValidLaunchRootTask(stack, r, windowingMode)) { return stack; } final int targetWindowingMode = windowingMode; final Task topmostValidStack = taskDisplayArea.getRootTask(stack -> isValidLaunchRootTask(stack, r, targetWindowingMode)); if (topmostValidStack != null) { return topmostValidStack; } // If there is no valid stack on the secondary display area - check if new dynamic stack Loading Loading @@ -3260,12 +3223,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } void finishVoiceTask(IVoiceInteractionSession session) { forAllTaskDisplayAreas(taskDisplayArea -> { final int numStacks = taskDisplayArea.getRootTaskCount(); for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { final Task stack = taskDisplayArea.getRootTaskAt(stackNdx); forAllRootTasks(stack -> { stack.finishVoiceTask(session); } }); } Loading Loading @@ -3324,10 +3283,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> boolean allResumedActivitiesVisible() { boolean[] foundResumed = {false}; final boolean foundInvisibleResumedActivity = forAllTaskDisplayAreas( taskDisplayArea -> { for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { final Task stack = taskDisplayArea.getRootTaskAt(sNdx); final boolean foundInvisibleResumedActivity = forAllRootTasks(stack -> { final ActivityRecord r = stack.getResumedActivity(); if (r != null) { if (!r.nowVisible) { Loading @@ -3335,7 +3291,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } foundResumed[0] = true; } } return false; }); if (foundInvisibleResumedActivity) { Loading @@ -3346,10 +3301,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> boolean allPausedActivitiesComplete() { boolean[] pausing = {true}; final boolean hasActivityNotCompleted = forAllTaskDisplayAreas( taskDisplayArea -> { for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { final Task stack = taskDisplayArea.getRootTaskAt(sNdx); final boolean hasActivityNotCompleted = forAllRootTasks(stack -> { final ActivityRecord r = stack.mPausingActivity; if (r != null && !r.isState(PAUSED, STOPPED, STOPPING, FINISHING)) { ProtoLog.d(WM_DEBUG_STATES, "allPausedActivitiesComplete: " Loading @@ -3360,7 +3312,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent> return true; } } } return false; }); if (hasActivityNotCompleted) { Loading Loading @@ -3413,13 +3364,10 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } void cancelInitializingActivities() { forAllTaskDisplayAreas(taskDisplayArea -> { for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { forAllRootTasks(task -> { // We don't want to clear starting window for activities that aren't occluded // as we need to display their starting window until they are done initializing. taskDisplayArea.getRootTaskAt(sNdx).forAllOccludedActivities( ActivityRecord::cancelInitializing); } task.forAllOccludedActivities(ActivityRecord::cancelInitializing); }); } Loading Loading @@ -3579,14 +3527,11 @@ class RootWindowContainer extends WindowContainer<DisplayContent> return new ArrayList<>(); } } else { ArrayList<ActivityRecord> activities = new ArrayList<>(); forAllTaskDisplayAreas(taskDisplayArea -> { for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { final Task stack = taskDisplayArea.getRootTaskAt(sNdx); final ArrayList<ActivityRecord> activities = new ArrayList<>(); forAllRootTasks(stack -> { if (!dumpVisibleStacksOnly || stack.shouldBeVisible(null)) { activities.addAll(stack.getDumpActivitiesLocked(name)); } } }); return activities; } Loading Loading @@ -3635,15 +3580,12 @@ class RootWindowContainer extends WindowContainer<DisplayContent> pw.print("Display #"); pw.print(displayContent.mDisplayId); pw.println(" (activities from top to bottom):"); displayContent.forAllTaskDisplayAreas(taskDisplayArea -> { for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { final Task stack = taskDisplayArea.getRootTaskAt(sNdx); displayContent.forAllRootTasks(stack -> { if (needSep[0]) { pw.println(); } needSep[0] = stack.dump(fd, pw, dumpAll, dumpClient, dumpPackage, false); printed[0] |= needSep[0]; } }); displayContent.forAllTaskDisplayAreas(taskDisplayArea -> { printed[0] |= printThisActivity(pw, taskDisplayArea.getFocusedActivity(), Loading services/core/java/com/android/server/wm/Task.java +24 −0 Original line number Diff line number Diff line Loading @@ -3877,6 +3877,13 @@ class Task extends WindowContainer<WindowContainer> { callback.accept(this); } @Override void forAllRootTasks(Consumer<Task> callback, boolean traverseTopToBottom) { if (isRootTask()) { callback.accept(this); } } @Override boolean forAllTasks(Function<Task, Boolean> callback) { if (super.forAllTasks(callback)) return true; Loading @@ -3901,6 +3908,11 @@ class Task extends WindowContainer<WindowContainer> { return false; } @Override boolean forAllRootTasks(Function<Task, Boolean> callback, boolean traverseTopToBottom) { return isRootTask() ? callback.apply(this) : false; } @Override Task getTask(Predicate<Task> callback, boolean traverseTopToBottom) { final Task t = super.getTask(callback, traverseTopToBottom); Loading @@ -3908,6 +3920,18 @@ class Task extends WindowContainer<WindowContainer> { return callback.test(this) ? this : null; } @Nullable @Override Task getRootTask(Predicate<Task> callback, boolean traverseTopToBottom) { return isRootTask() && callback.test(this) ? this : null; } @Nullable @Override <R> R getItemFromRootTasks(Function<Task, R> callback, boolean traverseTopToBottom) { return isRootTask() ? callback.apply(this) : null; } /** * @param canAffectSystemUiFlags If false, all windows in this task can not affect SystemUI * flags. See {@link WindowState#canAffectSystemUiFlags()}. Loading Loading
services/core/java/com/android/server/wm/DisplayContent.java +10 −14 Original line number Diff line number Diff line Loading @@ -2260,9 +2260,12 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp taskDisplayArea.getRootTask(rootTaskId)); } protected int getRootTaskCount() { return reduceOnAllTaskDisplayAreas((taskDisplayArea, count) -> count + taskDisplayArea.getRootTaskCount(), 0 /* initValue */); int getRootTaskCount() { final int[] count = new int[1]; forAllRootTasks(task -> { count[0]++; }); return count[0]; } @VisibleForTesting Loading Loading @@ -5353,19 +5356,12 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } // Check if all task display areas have only the empty home stacks left. boolean hasNonEmptyHomeStack = forAllTaskDisplayAreas(taskDisplayArea -> { if (taskDisplayArea.getRootTaskCount() != 1) { return true; } final Task stack = taskDisplayArea.getRootTaskAt(0); return !stack.isActivityTypeHome() || stack.hasChild(); }); if (!hasNonEmptyHomeStack) { boolean hasNonEmptyHomeStack = forAllRootTasks(stack -> !stack.isActivityTypeHome() || stack.hasChild()); if (!hasNonEmptyHomeStack && getRootTaskCount() > 0) { // Release this display if only empty home stack(s) are left. This display will be // released along with the stack(s) removal. forAllTaskDisplayAreas(taskDisplayArea -> { taskDisplayArea.getRootTaskAt(0).removeIfPossible(); }); forAllRootTasks(Task::removeIfPossible); } else if (getTopRootTask() == null) { removeIfPossible(); mRootWindowContainer.mTaskSupervisor Loading
services/core/java/com/android/server/wm/KeyguardController.java +2 −10 Original line number Diff line number Diff line Loading @@ -594,16 +594,8 @@ class KeyguardController { */ @Nullable private Task getRootTaskForControllingOccluding(DisplayContent display) { return display.getItemFromTaskDisplayAreas(taskDisplayArea -> { for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { final Task task = taskDisplayArea.getRootTaskAt(sNdx); if (task != null && task.isFocusableAndVisible() && !task.inPinnedWindowingMode()) { return task; } } return null; }); return display.getRootTask(task -> task != null && task.isFocusableAndVisible() && !task.inPinnedWindowingMode()); } void dumpStatus(PrintWriter pw, String prefix) { Loading
services/core/java/com/android/server/wm/RecentsAnimation.java +2 −8 Original line number Diff line number Diff line Loading @@ -468,14 +468,8 @@ class RecentsAnimation implements RecentsAnimationCallbacks, OnRootTaskOrderChan * @return The top stack that is not always-on-top. */ private Task getTopNonAlwaysOnTopStack() { for (int i = mDefaultTaskDisplayArea.getRootTaskCount() - 1; i >= 0; i--) { final Task s = mDefaultTaskDisplayArea.getRootTaskAt(i); if (s.getWindowConfiguration().isAlwaysOnTop()) { continue; } return s; } return null; return mDefaultTaskDisplayArea.getRootTask(task -> !task.getWindowConfiguration().isAlwaysOnTop()); } /** Loading
services/core/java/com/android/server/wm/RootWindowContainer.java +150 −208 Original line number Diff line number Diff line Loading @@ -1835,10 +1835,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> final ArrayList<IBinder> topActivityTokens = new ArrayList<>(); final Task topFocusedStack = getTopDisplayFocusedRootTask(); // Traverse all displays. forAllTaskDisplayAreas(taskDisplayArea -> { // Traverse all stacks on a display area. for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { final Task stack = taskDisplayArea.getRootTaskAt(sNdx); forAllRootTasks(stack -> { // Get top activity from a visible stack and add it to the list. if (stack.shouldBeVisible(null /* starting */)) { final ActivityRecord top = stack.getTopNonFinishingActivity(); Loading @@ -1850,7 +1847,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } } } } }); return topActivityTokens; } Loading Loading @@ -1892,21 +1888,17 @@ class RootWindowContainer extends WindowContainer<DisplayContent> // 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 = reduceOnAllTaskDisplayAreas((taskDisplayArea, app) -> { for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { final Task stack = taskDisplayArea.getRootTaskAt(sNdx); WindowProcessController fgApp = getItemFromRootTasks(stack -> { if (isTopDisplayFocusedRootTask(stack)) { final ActivityRecord resumedActivity = stack.getResumedActivity(); if (resumedActivity != null) { app = resumedActivity.app; return resumedActivity.app; } else if (stack.mPausingActivity != null) { app = stack.mPausingActivity.app; } break; return stack.mPausingActivity.app; } } return app; }, null /* initValue */); return null; }); // Now set this one as the previous process, only if that really makes sense to. if (r.hasProcess() && fgApp != null && r.app != fgApp Loading @@ -1923,15 +1915,13 @@ class RootWindowContainer extends WindowContainer<DisplayContent> mTmpRemoteException = null; mTmpBoolean = false; // Set to true if an activity was started. final DisplayContent display = getChildAt(displayNdx); display.forAllTaskDisplayAreas(displayArea -> { display.forAllRootTasks(rootTask -> { if (mTmpRemoteException != null) { return; } for (int taskNdx = displayArea.getRootTaskCount() - 1; taskNdx >= 0; --taskNdx) { final Task rootTask = displayArea.getRootTaskAt(taskNdx); if (rootTask.getVisibility(null /*starting*/) == TASK_VISIBILITY_INVISIBLE) { break; return; } final PooledFunction c = PooledLambda.obtainFunction( Loading @@ -1940,10 +1930,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent> rootTask.topRunningActivity()); rootTask.forAllActivities(c); c.recycle(); if (mTmpRemoteException != null) { return; } } }); if (mTmpRemoteException != null) { throw mTmpRemoteException; Loading Loading @@ -2027,11 +2013,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent> mCurrentUser = userId; mTaskSupervisor.mStartingUsers.add(uss); forAllTaskDisplayAreas(taskDisplayArea -> { for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { final Task stack = taskDisplayArea.getRootTaskAt(sNdx); forAllRootTasks(stack -> { stack.switchUser(userId); } }); final int restoreStackId = mUserRootTaskInFront.get(userId); Loading Loading @@ -2294,20 +2277,14 @@ class RootWindowContainer extends WindowContainer<DisplayContent> */ int finishTopCrashedActivities(WindowProcessController app, String reason) { Task focusedStack = getTopDisplayFocusedRootTask(); Task finishedTask = reduceOnAllTaskDisplayAreas((taskDisplayArea, task) -> { // 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 < taskDisplayArea.getRootTaskCount(); ++stackNdx) { final Task stack = taskDisplayArea.getRootTaskAt(stackNdx); final Task[] finishedTask = new Task[1]; forAllTasks(stack -> { final Task t = stack.finishTopCrashedActivityLocked(app, reason); if (stack == focusedStack || task == null) { task = t; } if (stack == focusedStack || finishedTask[0] == null) { finishedTask[0] = t; } return task; }, null /* initValue */); return finishedTask != null ? finishedTask.mTaskId : INVALID_TASK_ID; }); return finishedTask[0] != null ? finishedTask[0].mTaskId : INVALID_TASK_ID; } boolean resumeFocusedTasksTopActivities() { Loading @@ -2330,36 +2307,32 @@ class RootWindowContainer extends WindowContainer<DisplayContent> for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) { final DisplayContent display = getChildAt(displayNdx); final boolean curResult = result; boolean resumedOnDisplay = display.reduceOnAllTaskDisplayAreas( (taskDisplayArea, resumed) -> { for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { final Task rootTask = taskDisplayArea.getRootTaskAt(sNdx); boolean[] resumedOnDisplay = new boolean[1]; display.forAllRootTasks(rootTask -> { final ActivityRecord topRunningActivity = rootTask.topRunningActivity(); if (!rootTask.isFocusableAndVisible() || topRunningActivity == null) { continue; return; } if (rootTask == targetRootTask) { // Simply update the result for targetStack because the targetStack // had already resumed in above. We don't want to resume it again, // especially in some cases, it would cause a second launch failure // if app process was dead. resumed |= curResult; continue; resumedOnDisplay[0] |= curResult; return; } if (taskDisplayArea.isTopRootTask(rootTask) if (rootTask.getDisplayArea().isTopRootTask(rootTask) && topRunningActivity.isState(RESUMED)) { // Kick off any lingering app transitions form the MoveTaskToFront // operation, but only consider the top task and stack on that // display. rootTask.executeAppTransition(targetOptions); } else { resumed |= topRunningActivity.makeActiveIfNeeded(target); resumedOnDisplay[0] |= topRunningActivity.makeActiveIfNeeded(target); } } return resumed; }, false /* initValue */); result |= resumedOnDisplay; if (!resumedOnDisplay) { }); result |= resumedOnDisplay[0]; if (!resumedOnDisplay[0]) { // In cases when there are no valid activities (e.g. device just booted or launcher // crashed) it's possible that nothing was resumed on a display. Requesting resume // of top activity in focused stack explicitly will make sure that at least home Loading Loading @@ -2392,9 +2365,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } // Set the sleeping state of the stacks on the display. display.forAllTaskDisplayAreas(taskDisplayArea -> { for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { final Task stack = taskDisplayArea.getRootTaskAt(sNdx); display.forAllRootTasks(stack -> { if (displayShouldSleep) { stack.goToSleepIfPossible(false /* shuttingDown */); } else { Loading @@ -2416,7 +2387,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent> stack.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */, false /* preserveWindows */); } } }); } } Loading Loading @@ -2512,13 +2482,10 @@ class RootWindowContainer extends WindowContainer<DisplayContent> /** If displayId == INVALID_DISPLAY, this will get root task infos on all displays */ ArrayList<RootTaskInfo> getAllRootTaskInfos(int displayId) { ArrayList<RootTaskInfo> list = new ArrayList<>(); final ArrayList<RootTaskInfo> list = new ArrayList<>(); if (displayId == INVALID_DISPLAY) { forAllTaskDisplayAreas(taskDisplayArea -> { for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { final Task stack = taskDisplayArea.getRootTaskAt(sNdx); forAllRootTasks(stack -> { list.add(getRootTaskInfo(stack)); } }); return list; } Loading @@ -2526,11 +2493,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent> if (display == null) { return list; } display.forAllTaskDisplayAreas(taskDisplayArea -> { for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { final Task stack = taskDisplayArea.getRootTaskAt(sNdx); display.forAllRootTasks(stack -> { list.add(getRootTaskInfo(stack)); } }); return list; } Loading Loading @@ -2603,10 +2567,17 @@ class RootWindowContainer extends WindowContainer<DisplayContent> Task findRootTaskBehind(Task rootTask) { final TaskDisplayArea taskDisplayArea = rootTask.getDisplayArea(); if (taskDisplayArea != null) { for (int i = taskDisplayArea.getRootTaskCount() - 1; i >= 0; i--) { if (taskDisplayArea.getRootTaskAt(i) == rootTask && i > 0) { return taskDisplayArea.getRootTaskAt(i - 1); final boolean[] hasFound = new boolean[1]; // TODO(b/175136051): should this be only the direct child root task? final Task rootTaskBehind = taskDisplayArea.getRootTask(task -> { if (hasFound[0]) { return true; } hasFound[0] = task == rootTask; return false; }); if (rootTaskBehind != null) { return rootTaskBehind; } } throw new IllegalStateException("Failed to find a root task behind root task =" + rootTask Loading Loading @@ -2748,24 +2719,16 @@ class RootWindowContainer extends WindowContainer<DisplayContent> // Tries to put all activity tasks to sleep. Returns true if all tasks were // successfully put to sleep. boolean putTasksToSleep(boolean allowDelay, boolean shuttingDown) { return reduceOnAllTaskDisplayAreas((taskDisplayArea, result) -> { for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { // Stacks and activities could be removed while putting activities to sleep if // the app process was gone. This prevents us getting exception by accessing an // invalid stack index. if (sNdx >= taskDisplayArea.getRootTaskCount()) { continue; } final Task task = taskDisplayArea.getRootTaskAt(sNdx); final boolean[] result = {true}; forAllRootTasks(task -> { if (allowDelay) { result &= task.goToSleepIfPossible(shuttingDown); result[0] &= task.goToSleepIfPossible(shuttingDown); } else { task.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */, !PRESERVE_WINDOWS); } } return result; }, true /* initValue */); }); return result[0]; } void handleAppCrash(WindowProcessController app) { Loading Loading @@ -3021,11 +2984,11 @@ class RootWindowContainer extends WindowContainer<DisplayContent> r.getActivityType()); // Return the topmost valid stack on the display. for (int i = taskDisplayArea.getRootTaskCount() - 1; i >= 0; --i) { final Task stack = taskDisplayArea.getRootTaskAt(i); if (isValidLaunchRootTask(stack, r, windowingMode)) { return stack; } final int targetWindowingMode = windowingMode; final Task topmostValidStack = taskDisplayArea.getRootTask(stack -> isValidLaunchRootTask(stack, r, targetWindowingMode)); if (topmostValidStack != null) { return topmostValidStack; } // If there is no valid stack on the secondary display area - check if new dynamic stack Loading Loading @@ -3260,12 +3223,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } void finishVoiceTask(IVoiceInteractionSession session) { forAllTaskDisplayAreas(taskDisplayArea -> { final int numStacks = taskDisplayArea.getRootTaskCount(); for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { final Task stack = taskDisplayArea.getRootTaskAt(stackNdx); forAllRootTasks(stack -> { stack.finishVoiceTask(session); } }); } Loading Loading @@ -3324,10 +3283,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> boolean allResumedActivitiesVisible() { boolean[] foundResumed = {false}; final boolean foundInvisibleResumedActivity = forAllTaskDisplayAreas( taskDisplayArea -> { for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { final Task stack = taskDisplayArea.getRootTaskAt(sNdx); final boolean foundInvisibleResumedActivity = forAllRootTasks(stack -> { final ActivityRecord r = stack.getResumedActivity(); if (r != null) { if (!r.nowVisible) { Loading @@ -3335,7 +3291,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } foundResumed[0] = true; } } return false; }); if (foundInvisibleResumedActivity) { Loading @@ -3346,10 +3301,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> boolean allPausedActivitiesComplete() { boolean[] pausing = {true}; final boolean hasActivityNotCompleted = forAllTaskDisplayAreas( taskDisplayArea -> { for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { final Task stack = taskDisplayArea.getRootTaskAt(sNdx); final boolean hasActivityNotCompleted = forAllRootTasks(stack -> { final ActivityRecord r = stack.mPausingActivity; if (r != null && !r.isState(PAUSED, STOPPED, STOPPING, FINISHING)) { ProtoLog.d(WM_DEBUG_STATES, "allPausedActivitiesComplete: " Loading @@ -3360,7 +3312,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent> return true; } } } return false; }); if (hasActivityNotCompleted) { Loading Loading @@ -3413,13 +3364,10 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } void cancelInitializingActivities() { forAllTaskDisplayAreas(taskDisplayArea -> { for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { forAllRootTasks(task -> { // We don't want to clear starting window for activities that aren't occluded // as we need to display their starting window until they are done initializing. taskDisplayArea.getRootTaskAt(sNdx).forAllOccludedActivities( ActivityRecord::cancelInitializing); } task.forAllOccludedActivities(ActivityRecord::cancelInitializing); }); } Loading Loading @@ -3579,14 +3527,11 @@ class RootWindowContainer extends WindowContainer<DisplayContent> return new ArrayList<>(); } } else { ArrayList<ActivityRecord> activities = new ArrayList<>(); forAllTaskDisplayAreas(taskDisplayArea -> { for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { final Task stack = taskDisplayArea.getRootTaskAt(sNdx); final ArrayList<ActivityRecord> activities = new ArrayList<>(); forAllRootTasks(stack -> { if (!dumpVisibleStacksOnly || stack.shouldBeVisible(null)) { activities.addAll(stack.getDumpActivitiesLocked(name)); } } }); return activities; } Loading Loading @@ -3635,15 +3580,12 @@ class RootWindowContainer extends WindowContainer<DisplayContent> pw.print("Display #"); pw.print(displayContent.mDisplayId); pw.println(" (activities from top to bottom):"); displayContent.forAllTaskDisplayAreas(taskDisplayArea -> { for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { final Task stack = taskDisplayArea.getRootTaskAt(sNdx); displayContent.forAllRootTasks(stack -> { if (needSep[0]) { pw.println(); } needSep[0] = stack.dump(fd, pw, dumpAll, dumpClient, dumpPackage, false); printed[0] |= needSep[0]; } }); displayContent.forAllTaskDisplayAreas(taskDisplayArea -> { printed[0] |= printThisActivity(pw, taskDisplayArea.getFocusedActivity(), Loading
services/core/java/com/android/server/wm/Task.java +24 −0 Original line number Diff line number Diff line Loading @@ -3877,6 +3877,13 @@ class Task extends WindowContainer<WindowContainer> { callback.accept(this); } @Override void forAllRootTasks(Consumer<Task> callback, boolean traverseTopToBottom) { if (isRootTask()) { callback.accept(this); } } @Override boolean forAllTasks(Function<Task, Boolean> callback) { if (super.forAllTasks(callback)) return true; Loading @@ -3901,6 +3908,11 @@ class Task extends WindowContainer<WindowContainer> { return false; } @Override boolean forAllRootTasks(Function<Task, Boolean> callback, boolean traverseTopToBottom) { return isRootTask() ? callback.apply(this) : false; } @Override Task getTask(Predicate<Task> callback, boolean traverseTopToBottom) { final Task t = super.getTask(callback, traverseTopToBottom); Loading @@ -3908,6 +3920,18 @@ class Task extends WindowContainer<WindowContainer> { return callback.test(this) ? this : null; } @Nullable @Override Task getRootTask(Predicate<Task> callback, boolean traverseTopToBottom) { return isRootTask() && callback.test(this) ? this : null; } @Nullable @Override <R> R getItemFromRootTasks(Function<Task, R> callback, boolean traverseTopToBottom) { return isRootTask() ? callback.apply(this) : null; } /** * @param canAffectSystemUiFlags If false, all windows in this task can not affect SystemUI * flags. See {@link WindowState#canAffectSystemUiFlags()}. Loading