Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 85fb19a4 authored by Wale Ogunwale's avatar Wale Ogunwale
Browse files

Change Stack to have generic WindowContainer children (76/n)

- Step towards Tasks containing other Tasks.
- There are several places where we want to perform an operation on all
tasks in a branch of the hierarchy. We end up looping based on the
parent knowing what type of children is in the sub-branch. Instead use
forAllTasks() to perfrom the operation on all tasks in the sub-branch.

Bug: 80414790
Test: Existing tests pass
Change-Id: I5551fe440e56bb8d6982002f93037827b00c70fc
parent affe64c6
Loading
Loading
Loading
Loading
+5 −17
Original line number Diff line number Diff line
@@ -468,7 +468,7 @@ class ActivityDisplay extends DisplayContent {
            if (resumedActivity == null || resumedActivity.app == null) {
                // If previously resumed activity doesn't work either - find the topmost running
                // activity that can be focused.
                resumedActivity = focusedStack.topRunningActivityLocked(true /* focusableOnly */);
                resumedActivity = focusedStack.topRunningActivity(true /* focusableOnly */);
            }
        }
        return resumedActivity;
@@ -832,7 +832,7 @@ class ActivityDisplay extends DisplayContent {
        ActivityRecord topRunning = null;
        final ActivityStack focusedStack = getFocusedStack();
        if (focusedStack != null) {
            topRunning = focusedStack.topRunningActivityLocked();
            topRunning = focusedStack.topRunningActivity();
        }

        // Look in other focusable stacks.
@@ -843,7 +843,7 @@ class ActivityDisplay extends DisplayContent {
                if (stack == focusedStack || !stack.isFocusable()) {
                    continue;
                }
                topRunning = stack.topRunningActivityLocked();
                topRunning = stack.topRunningActivity();
                if (topRunning != null) {
                    break;
                }
@@ -961,12 +961,6 @@ class ActivityDisplay extends DisplayContent {
        super.onConfigurationChanged(newParentConfig);
    }

    void onLockTaskPackagesUpdated() {
        for (int i = getStackCount() - 1; i >= 0; --i) {
            getStackAt(i).onLockTaskPackagesUpdated();
        }
    }

    /** Checks whether the given activity is in size compatibility mode and notifies the change. */
    void handleActivitySizeCompatModeIfNeeded(ActivityRecord r) {
        if (!r.isState(RESUMED) || r.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
@@ -1082,7 +1076,7 @@ class ActivityDisplay extends DisplayContent {
        }

        final ActivityStack stack = getStackCount() == 1 ? getStackAt(0) : null;
        if (stack != null && stack.isActivityTypeHome() && stack.getAllTasks().isEmpty()) {
        if (stack != null && stack.isActivityTypeHome() && !stack.hasChild()) {
            // Release this display if an empty home stack is the only thing left.
            // Since it is the last stack, this display will be released along with the stack
            // removal.
@@ -1318,13 +1312,7 @@ class ActivityDisplay extends DisplayContent {

    @VisibleForTesting
    void removeAllTasks() {
        for (int i = getStackCount() - 1; i >= 0; --i) {
            final ActivityStack stack = getStackAt(i);
            final ArrayList<Task> tasks = stack.getAllTasks();
            for (int j = tasks.size() - 1; j >= 0; --j) {
                stack.removeChild(tasks.get(j), "removeAllTasks");
            }
        }
        mDisplayContent.forAllTasks((t) -> { t.getStack().removeChild(t, "removeAllTasks"); });
    }

    public void dump(PrintWriter pw, String prefix) {
+3 −2
Original line number Diff line number Diff line
@@ -2406,7 +2406,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
            // We are finishing the top focused activity and its stack has nothing to be focused so
            // the next focusable stack should be focused.
            if (mayAdjustTop
                    && (stack.topRunningActivityLocked() == null || !stack.isFocusable())) {
                    && (stack.topRunningActivity() == null || !stack.isFocusable())) {
                if (shouldAdjustGlobalFocus) {
                    // Move the entire hierarchy to top with updating global top resumed activity
                    // and focused application if needed.
@@ -3440,7 +3440,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
    }

    @Override
    ActivityRecord getActivity(Predicate<ActivityRecord> callback, boolean traverseTopToBottom) {
    ActivityRecord getActivity(Predicate<ActivityRecord> callback, boolean traverseTopToBottom,
            WindowContainer boundary) {
        return callback.test(this) ? this : null;
    }

+147 −364

File changed.

Preview size limit exceeded, changes collapsed.

+95 −70
Original line number Diff line number Diff line
@@ -165,28 +165,28 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
    static final String TAG_TASKS = TAG + POSTFIX_TASKS;

    /** How long we wait until giving up on the last activity telling us it is idle. */
    static final int IDLE_TIMEOUT = 10 * 1000;
    private static final int IDLE_TIMEOUT = 10 * 1000;

    /** How long we can hold the sleep wake lock before giving up. */
    static final int SLEEP_TIMEOUT = 5 * 1000;
    private static final int SLEEP_TIMEOUT = 5 * 1000;

    // How long we can hold the launch wake lock before giving up.
    static final int LAUNCH_TIMEOUT = 10 * 1000;
    private static final int LAUNCH_TIMEOUT = 10 * 1000;

    /** How long we wait until giving up on the activity telling us it released the top state. */
    static final int TOP_RESUMED_STATE_LOSS_TIMEOUT = 500;

    static final int IDLE_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG;
    static final int IDLE_NOW_MSG = FIRST_SUPERVISOR_STACK_MSG + 1;
    static final int RESUME_TOP_ACTIVITY_MSG = FIRST_SUPERVISOR_STACK_MSG + 2;
    static final int SLEEP_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 3;
    static final int LAUNCH_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 4;
    static final int LAUNCH_TASK_BEHIND_COMPLETE = FIRST_SUPERVISOR_STACK_MSG + 12;
    static final int RESTART_ACTIVITY_PROCESS_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 13;
    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;
    static final int REPORT_HOME_CHANGED_MSG = FIRST_SUPERVISOR_STACK_MSG + 16;
    static final int TOP_RESUMED_STATE_LOSS_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 17;
    private static final int TOP_RESUMED_STATE_LOSS_TIMEOUT = 500;

    private static final int IDLE_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG;
    private static final int IDLE_NOW_MSG = FIRST_SUPERVISOR_STACK_MSG + 1;
    private static final int RESUME_TOP_ACTIVITY_MSG = FIRST_SUPERVISOR_STACK_MSG + 2;
    private static final int SLEEP_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 3;
    private static final int LAUNCH_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 4;
    private static final int LAUNCH_TASK_BEHIND_COMPLETE = FIRST_SUPERVISOR_STACK_MSG + 12;
    private static final int RESTART_ACTIVITY_PROCESS_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 13;
    private static final int REPORT_MULTI_WINDOW_MODE_CHANGED_MSG = FIRST_SUPERVISOR_STACK_MSG + 14;
    private static final int REPORT_PIP_MODE_CHANGED_MSG = FIRST_SUPERVISOR_STACK_MSG + 15;
    private static final int REPORT_HOME_CHANGED_MSG = FIRST_SUPERVISOR_STACK_MSG + 16;
    private static final int TOP_RESUMED_STATE_LOSS_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 17;

    // Used to indicate that windows of activities should be preserved during the resize.
    static final boolean PRESERVE_WINDOWS = true;
@@ -237,7 +237,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {

    // For debugging to make sure the caller when acquiring/releasing our
    // wake lock is the system process.
    static final boolean VALIDATE_WAKE_LOCK_CALLER = false;
    private static final boolean VALIDATE_WAKE_LOCK_CALLER = false;
    /** The number of distinct task ids that can be assigned to the tasks of a single user */
    private static final int MAX_TASK_IDS_PER_USER = UserHandle.PER_USER_RANGE;

@@ -250,11 +250,11 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
    /** Helper class to abstract out logic for fetching the set of currently running tasks */
    private RunningTasks mRunningTasks;

    final ActivityStackSupervisorHandler mHandler;
    private final ActivityStackSupervisorHandler mHandler;
    final Looper mLooper;

    /** Short cut */
    WindowManagerService mWindowManager;
    private WindowManagerService mWindowManager;

     /** Common synchronization logic used to save things to disks. */
    PersisterQueue mPersisterQueue;
@@ -286,11 +286,11 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {

    /** List of activities whose multi-window mode changed that we need to report to the
     * application */
    final ArrayList<ActivityRecord> mMultiWindowModeChangedActivities = new ArrayList<>();
    private final ArrayList<ActivityRecord> mMultiWindowModeChangedActivities = new ArrayList<>();

    /** List of activities whose picture-in-picture mode changed that we need to report to the
     * application */
    final ArrayList<ActivityRecord> mPipModeChangedActivities = new ArrayList<>();
    private final ArrayList<ActivityRecord> mPipModeChangedActivities = new ArrayList<>();

    /**
     * Animations that for the current transition have requested not to
@@ -312,7 +312,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {

    /** The target stack bounds for the picture-in-picture mode changed that we need to report to
     * the application */
    Rect mPipModeChangedTargetStackBounds;
    private Rect mPipModeChangedTargetStackBounds;

    /** Used on user changes */
    final ArrayList<UserState> mStartingUsers = new ArrayList<>();
@@ -398,6 +398,52 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {

    private boolean mInitialized;

    private final MoveTaskToFullscreenHelper mMoveTaskToFullscreenHelper =
            new MoveTaskToFullscreenHelper();
    private class MoveTaskToFullscreenHelper {
        private ActivityDisplay mToDisplay;
        private boolean mOnTop;
        private Task mTopTask;
        private boolean mSchedulePictureInPictureModeChange;

        void process(ActivityStack fromStack, ActivityDisplay toDisplay, boolean onTop,
                boolean schedulePictureInPictureModeChange) {
            mSchedulePictureInPictureModeChange = schedulePictureInPictureModeChange;
            mToDisplay = toDisplay;
            mOnTop = onTop;
            mTopTask = fromStack.getTopMostTask();

            final PooledConsumer c = PooledLambda.obtainConsumer(
                    MoveTaskToFullscreenHelper::processTask, this, PooledLambda.__(Task.class));
            fromStack.forAllTasks(c, false);
            c.recycle();
            mToDisplay = null;
            mTopTask = null;
        }

        private void processTask(Task task) {
            final ActivityStack toStack = mToDisplay.getOrCreateStack(
                    null, mTmpOptions, task, task.getActivityType(), mOnTop);

            if (mOnTop) {
                final boolean isTopTask = task == mTopTask;
                // Defer resume until all the tasks have been moved to the fullscreen stack
                task.reparent(toStack, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, isTopTask /*animate*/,
                        DEFER_RESUME, mSchedulePictureInPictureModeChange,
                        "moveTasksToFullscreenStack - onTop");
                MetricsLoggerWrapper.logPictureInPictureFullScreen(mService.mContext,
                        task.effectiveUid, task.realActivity.flattenToString());
            } else {
                // Position the tasks in the fullscreen stack in order at the bottom of the
                // stack. Also defer resume until all the tasks have been moved to the
                // fullscreen stack.
                task.reparent(toStack, ON_TOP, REPARENT_LEAVE_STACK_IN_PLACE,
                        !ANIMATE, DEFER_RESUME, mSchedulePictureInPictureModeChange,
                        "moveTasksToFullscreenStack - NOT_onTop");
            }
        }
    }

    /**
     * Description of a request to start a new activity, which has been held
     * due to app switches being disabled.
@@ -1522,35 +1568,11 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
            // the picture-in-picture mode.
            final boolean schedulePictureInPictureModeChange =
                    windowingMode == WINDOWING_MODE_PINNED;
            final ArrayList<Task> tasks = fromStack.getAllTasks();

            if (!tasks.isEmpty()) {
            if (fromStack.hasChild()) {
                mTmpOptions.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
                final int size = tasks.size();
                for (int i = 0; i < size; ++i) {
                    final Task task = tasks.get(i);
                    final ActivityStack toStack = toDisplay.getOrCreateStack(
                                null, mTmpOptions, task, task.getActivityType(), onTop);

                    if (onTop) {
                        final boolean isTopTask = i == (size - 1);
                        // Defer resume until all the tasks have been moved to the fullscreen stack
                        task.reparent(toStack, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT,
                                isTopTask /* animate */, DEFER_RESUME,
                                schedulePictureInPictureModeChange,
                                "moveTasksToFullscreenStack - onTop");
                        MetricsLoggerWrapper.logPictureInPictureFullScreen(mService.mContext,
                                task.effectiveUid, task.realActivity.flattenToString());
                    } else {
                        // Position the tasks in the fullscreen stack in order at the bottom of the
                        // stack. Also defer resume until all the tasks have been moved to the
                        // fullscreen stack.
                        task.reparent(toStack, ON_TOP,
                                REPARENT_LEAVE_STACK_IN_PLACE, !ANIMATE, DEFER_RESUME,
                                schedulePictureInPictureModeChange,
                                "moveTasksToFullscreenStack - NOT_onTop");
                    }
                }
                mMoveTaskToFullscreenHelper.process(
                        fromStack, toDisplay, onTop, schedulePictureInPictureModeChange);
            }

            mRootActivityContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
@@ -1562,12 +1584,8 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
    }

    void moveTasksToFullscreenStackLocked(ActivityStack fromStack, boolean onTop) {
        moveTasksToFullscreenStackLocked(fromStack, DEFAULT_DISPLAY, onTop);
    }

    void moveTasksToFullscreenStackLocked(ActivityStack fromStack, int toDisplayId, boolean onTop) {
        mWindowManager.inSurfaceTransaction(() ->
                moveTasksToFullscreenStackInSurfaceTransaction(fromStack, toDisplayId, onTop));
                moveTasksToFullscreenStackInSurfaceTransaction(fromStack, DEFAULT_DISPLAY, onTop));
    }

    void setSplitScreenResizing(boolean resizing) {
@@ -1630,7 +1648,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
        try {
            // Don't allow re-entry while resizing. E.g. due to docked stack detaching.
            mAllowDockedStackResize = false;
            ActivityRecord r = stack.topRunningActivityLocked();
            ActivityRecord r = stack.topRunningActivity();
            stack.resize(dockedBounds, tempDockedTaskBounds, tempDockedTaskInsetBounds,
                    !PRESERVE_WINDOWS, DEFER_RESUME);

@@ -1731,7 +1749,6 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
    }

    private void removeStackInSurfaceTransaction(ActivityStack stack) {
        final ArrayList<Task> tasks = stack.getAllTasks();
        if (stack.getWindowingMode() == WINDOWING_MODE_PINNED) {
            /**
             * Workaround: Force-stop all the activities in the pinned stack before we reparent them
@@ -1746,16 +1763,20 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
            stack.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
            stack.mForceHidden = false;
            activityIdleInternalLocked(null, false /* fromTimeout */,
                    true /* processPausingActivites */, null /* configuration */);
                    true /* processPausingActivities */, null /* configuration */);

            // Move all the tasks to the bottom of the fullscreen stack
            moveTasksToFullscreenStackLocked(stack, !ON_TOP);
        } else {
            for (int i = tasks.size() - 1; i >= 0; i--) {
                removeTaskByIdLocked(tasks.get(i).mTaskId, true /* killProcess */,
                        REMOVE_FROM_RECENTS, "remove-stack");
            final PooledConsumer c = PooledLambda.obtainConsumer(
                    ActivityStackSupervisor::processRemoveTask, this, PooledLambda.__(Task.class));
            stack.forAllTasks(c);
            c.recycle();
        }
    }

    private void processRemoveTask(Task task) {
        removeTask(task, true /* killProcess */, REMOVE_FROM_RECENTS, "remove-stack");
    }

    /**
@@ -1775,11 +1796,19 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
     * @param removeFromRecents Whether to also remove the task from recents.
     * @return Returns true if the given task was found and removed.
     */
    boolean removeTaskByIdLocked(int taskId, boolean killProcess, boolean removeFromRecents,
    boolean removeTaskById(int taskId, boolean killProcess, boolean removeFromRecents,
            String reason) {
        final Task task =
                mRootActivityContainer.anyTaskForId(taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
        if (task != null) {
            removeTask(task, killProcess, removeFromRecents, reason);
            return true;
        }
        Slog.w(TAG, "Request to remove task ignored for non-existent task " + taskId);
        return false;
    }

    void removeTask(Task task, boolean killProcess, boolean removeFromRecents, String reason) {
        task.removeTaskActivitiesLocked(reason);
        cleanUpRemovedTaskLocked(task, killProcess, removeFromRecents);
        mService.getLockTaskController().clearLockedTask(task);
@@ -1787,10 +1816,6 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
        if (task.isPersistable) {
            mService.notifyTaskPersisterLocked(null, true);
        }
            return true;
        }
        Slog.w(TAG, "Request to remove task ignored for non-existent task " + taskId);
        return false;
    }

    void cleanUpRemovedTaskLocked(Task task, boolean killProcess, boolean removeFromRecents) {
@@ -1899,7 +1924,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
        if (wasTrimmed) {
            // Task was trimmed from the recent tasks list -- remove the active task record as well
            // since the user won't really be able to go back to it
            removeTaskByIdLocked(task.mTaskId, killProcess, false /* removeFromRecents */,
            removeTaskById(task.mTaskId, killProcess, false /* removeFromRecents */,
                    "recent-task-trimmed");
        }
        task.removedFromRecents();
+4 −4
Original line number Diff line number Diff line
@@ -1434,7 +1434,7 @@ class ActivityStarter {
                // If there is no state change (e.g. a resumed activity is reparented to top of
                // another display) to trigger a visibility/configuration checking, we have to
                // update the configuration for changing to different display.
                final ActivityRecord currentTop = startedActivityStack.topRunningActivityLocked();
                final ActivityRecord currentTop = startedActivityStack.topRunningActivity();
                if (currentTop != null && currentTop.shouldUpdateConfigForDisplayChanged()) {
                    mRootActivityContainer.ensureVisibilityAndConfig(
                            currentTop, currentTop.getDisplayId(),
@@ -2307,7 +2307,7 @@ class ActivityStarter {
                    ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
            final Task topTask = curTop != null ? curTop.getTask() : null;
            differentTopTask = topTask != intentActivity.getTask()
                    || (focusStack != null && topTask != focusStack.topTask());
                    || (focusStack != null && topTask != focusStack.getTopMostTask());
        } else {
            // The existing task should always be different from those in other displays.
            differentTopTask = true;
@@ -2371,7 +2371,7 @@ class ActivityStarter {
                    mMovedToFront = true;
                }

                if (launchStack != null && launchStack.topTask() == null) {
                if (launchStack != null && launchStack.getTopMostTask() == null) {
                    // The task does not need to be reparented to the launch stack. Remove the
                    // launch stack if there is no activity in it.
                    Slog.w(TAG, "Removing an empty stack: " + launchStack);
@@ -2588,7 +2588,7 @@ class ActivityStarter {
            // If task's parent stack is not focused - use it during adjacent launch.
            return parentStack;
        } else {
            if (focusedStack != null && task == focusedStack.topTask()) {
            if (focusedStack != null && task == focusedStack.getTopMostTask()) {
                // If task is already on top of focused stack - use it. We don't want to move the
                // existing focused task to adjacent stack, just deliver new intent in this case.
                return focusedStack;
Loading