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

Commit 28a72fba authored by Louis Chang's avatar Louis Chang
Browse files

Allowing leaf Task to contain both Activity and TaskFragment

Allowing a leaf Task to both contains ActivityRecord and
TaskFragment as the direct children.

For example:
   Task
      - TaskFragment
         - Activity C
      - TaskFragment
         - Activity B
      - Activity A

Bug: 189385903
Test: wm presubmit
Change-Id: I79667df70dcbbefbf5a5cce1a24165247f403e69
parent a5b25288
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -1627,6 +1627,12 @@
      "group": "WM_DEBUG_ORIENTATION",
      "at": "com\/android\/server\/wm\/ActivityRecord.java"
    },
    "-248761393": {
      "message": "startPausing: taskFrag =%s mResumedActivity=%s",
      "level": "DEBUG",
      "group": "WM_DEBUG_STATES",
      "at": "com\/android\/server\/wm\/TaskFragment.java"
    },
    "-240296576": {
      "message": "handleAppTransitionReady: displayId=%d appTransition={%s} openingApps=[%s] closingApps=[%s] transit=%s",
      "level": "VERBOSE",
@@ -3349,12 +3355,6 @@
      "group": "WM_DEBUG_APP_TRANSITIONS",
      "at": "com\/android\/server\/wm\/ActivityRecord.java"
    },
    "1814259538": {
      "message": "pauseBackTasks: taskFrag=%s mResumedActivity=%s",
      "level": "DEBUG",
      "group": "WM_DEBUG_STATES",
      "at": "com\/android\/server\/wm\/TaskDisplayArea.java"
    },
    "1822314934": {
      "message": "Expected target rootTask=%s to restored behind rootTask=%s but it is behind rootTask=%s",
      "level": "WARN",
+4 −4
Original line number Diff line number Diff line
@@ -3058,12 +3058,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
                // Tell window manager to prepare for this one to be removed.
                setVisibility(false);

                if (task.getTopPausingActivity() == null) {
                if (getTaskFragment().getPausingActivity() == null) {
                    ProtoLog.v(WM_DEBUG_STATES, "Finish needs to pause: %s", this);
                    if (DEBUG_USER_LEAVING) {
                        Slog.v(TAG_USER_LEAVING, "finish() => pause with userLeaving=false");
                    }
                    task.startPausing(false /* userLeaving */, false /* uiSleeping */,
                    getTaskFragment().startPausing(false /* userLeaving */, false /* uiSleeping */,
                            null /* resuming */, "finish");
                }

@@ -5406,7 +5406,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        if (!task.hasChild(this)) {
            throw new IllegalStateException("Activity not found in its task");
        }
        return task.topRunningActivity() == this;
        return getTaskFragment().topRunningActivity() == this;
    }

    void handleAlreadyVisible() {
+26 −13
Original line number Diff line number Diff line
@@ -29,7 +29,7 @@ class EnsureActivitiesVisibleHelper {
    private ActivityRecord mStarting;
    private boolean mAboveTop;
    private boolean mContainerShouldBeVisible;
    private boolean mBehindFullscreenActivity;
    private boolean mBehindFullyOccludedContainer;
    private int mConfigChanges;
    private boolean mPreserveWindows;
    private boolean mNotifyClients;
@@ -56,7 +56,7 @@ class EnsureActivitiesVisibleHelper {
        // are now visible.
        mAboveTop = mTop != null;
        mContainerShouldBeVisible = mTaskFragment.shouldBeVisible(mStarting);
        mBehindFullscreenActivity = !mContainerShouldBeVisible;
        mBehindFullyOccludedContainer = !mContainerShouldBeVisible;
        mConfigChanges = configChanges;
        mPreserveWindows = preserveWindows;
        mNotifyClients = notifyClients;
@@ -97,9 +97,21 @@ class EnsureActivitiesVisibleHelper {
                && mTaskFragment.isTopActivityFocusable()
                && (starting == null || !starting.isDescendantOf(mTaskFragment));

        mTaskFragment.forAllActivities(a -> {
            setActivityVisibilityState(a, starting, resumeTopActivity);
        });
        for (int i = mTaskFragment.mChildren.size() - 1; i >= 0; --i) {
            final WindowContainer child = mTaskFragment.mChildren.get(i);
            if (child.asTaskFragment() != null) {
                final TaskFragment childTaskFragment = child.asTaskFragment();
                childTaskFragment.updateActivityVisibilities(starting, configChanges,
                        preserveWindows, notifyClients);
                mBehindFullyOccludedContainer = childTaskFragment.getBounds().equals(
                        mTaskFragment.getBounds());
                if (mAboveTop && mTop.getTaskFragment() == childTaskFragment) {
                    mAboveTop = false;
                }
            } else if (child.asActivityRecord() != null) {
                setActivityVisibilityState(child.asActivityRecord(), starting, resumeTopActivity);
            }
        }
        if (mTaskFragment.mAtmService.getTransitionController().getTransitionPlayer() != null) {
            mTaskFragment.getDisplayContent().mWallpaperController.adjustWallpaperWindows();
        }
@@ -113,7 +125,7 @@ class EnsureActivitiesVisibleHelper {
        }
        mAboveTop = false;

        r.updateVisibilityIgnoringKeyguard(mBehindFullscreenActivity);
        r.updateVisibilityIgnoringKeyguard(mBehindFullyOccludedContainer);
        final boolean reallyVisible = r.shouldBeVisibleUnchecked();

        // Check whether activity should be visible without Keyguard influence
@@ -123,11 +135,11 @@ class EnsureActivitiesVisibleHelper {
                if (DEBUG_VISIBILITY) {
                    Slog.v(TAG_VISIBILITY, "Fullscreen: at " + r
                            + " containerVisible=" + mContainerShouldBeVisible
                            + " behindFullscreen=" + mBehindFullscreenActivity);
                            + " behindFullyOccluded=" + mBehindFullyOccludedContainer);
                }
                mBehindFullscreenActivity = true;
                mBehindFullyOccludedContainer = true;
            } else {
                mBehindFullscreenActivity = false;
                mBehindFullyOccludedContainer = false;
            }
        }

@@ -174,24 +186,25 @@ class EnsureActivitiesVisibleHelper {
                Slog.v(TAG_VISIBILITY, "Make invisible? " + r
                        + " finishing=" + r.finishing + " state=" + r.getState()
                        + " containerShouldBeVisible=" + mContainerShouldBeVisible
                        + " behindFullscreenActivity=" + mBehindFullscreenActivity
                        + " behindFullyOccludedContainer=" + mBehindFullyOccludedContainer
                        + " mLaunchTaskBehind=" + r.mLaunchTaskBehind);
            }
            r.makeInvisible();
        }

        if (!mBehindFullscreenActivity && mTaskFragment.isActivityTypeHome() && r.isRootOfTask()) {
        if (!mBehindFullyOccludedContainer && mTaskFragment.isActivityTypeHome()
                && r.isRootOfTask()) {
            if (DEBUG_VISIBILITY) {
                Slog.v(TAG_VISIBILITY, "Home task: at " + mTaskFragment
                        + " containerShouldBeVisible=" + mContainerShouldBeVisible
                        + " behindFullscreenActivity=" + mBehindFullscreenActivity);
                        + " behindOccludedParentContainer=" + mBehindFullyOccludedContainer);
            }
            // No other task in the root home task should be visible behind the home activity.
            // Home activities is usually a translucent activity with the wallpaper behind
            // them. However, when they don't have the wallpaper behind them, we want to
            // show activities in the next application root task behind them vs. another
            // task in the root home task like recents.
            mBehindFullscreenActivity = true;
            mBehindFullyOccludedContainer = true;
        }
    }

+1 −1
Original line number Diff line number Diff line
@@ -2377,7 +2377,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
                if (displayShouldSleep) {
                    rootTask.goToSleepIfPossible(false /* shuttingDown */);
                } else {
                    rootTask.forAllLeafTaskFragments(
                    rootTask.forAllLeafTasksAndLeafTaskFragments(
                            taskFragment -> taskFragment.awakeFromSleeping(),
                            true /* traverseTopToBottom */);
                    if (rootTask.isFocusedRootTaskOnDisplay()
+102 −44
Original line number Diff line number Diff line
@@ -1258,22 +1258,35 @@ class Task extends TaskFragment {
    /** Returns the currently topmost resumed activity. */
    @Nullable
    ActivityRecord getTopResumedActivity() {
        if (isLeafTask()) {
        if (!isLeafTask()) {
            for (int i = mChildren.size() - 1; i >= 0; --i) {
                ActivityRecord resumedActivity = mChildren.get(i).asTask().getTopResumedActivity();
                if (resumedActivity != null) {
                    return resumedActivity;
                }
            }
        }

        final ActivityRecord taskResumedActivity = getResumedActivity();
        ActivityRecord topResumedActivity = null;
        for (int i = mChildren.size() - 1; i >= 0; --i) {
            final WindowContainer child = mChildren.get(i);
            if (child.asTaskFragment() != null) {
                final ActivityRecord[] resumedActivity = new ActivityRecord[1];
            forAllLeafTaskFragments(fragment -> {
                child.asTaskFragment().forAllLeafTaskFragments(fragment -> {
                    if (fragment.getResumedActivity() != null) {
                        resumedActivity[0] = fragment.getResumedActivity();
                        return true;
                    }
                    return false;
                });
            return resumedActivity[0];
                topResumedActivity = resumedActivity[0];
            } else if (taskResumedActivity != null
                    && child.asActivityRecord() == taskResumedActivity) {
                topResumedActivity = taskResumedActivity;
            }

        for (int i = mChildren.size() - 1; i >= 0; --i) {
            ActivityRecord resumedActivity = mChildren.get(i).asTask().getTopResumedActivity();
            if (resumedActivity != null) {
                return resumedActivity;
            if (topResumedActivity != null) {
                return topResumedActivity;
            }
        }
        return null;
@@ -1284,22 +1297,35 @@ class Task extends TaskFragment {
     */
    @Nullable
    ActivityRecord getTopPausingActivity() {
        if (isLeafTask()) {
        if (!isLeafTask()) {
            for (int i = mChildren.size() - 1; i >= 0; --i) {
                ActivityRecord pausingActivity = mChildren.get(i).asTask().getTopPausingActivity();
                if (pausingActivity != null) {
                    return pausingActivity;
                }
            }
        }

        final ActivityRecord taskPausingActivity = getPausingActivity();
        ActivityRecord topPausingActivity = null;
        for (int i = mChildren.size() - 1; i >= 0; --i) {
            final WindowContainer child = mChildren.get(i);
            if (child.asTaskFragment() != null) {
                final ActivityRecord[] pausingActivity = new ActivityRecord[1];
            forAllLeafTaskFragments(fragment -> {
                child.asTaskFragment().forAllLeafTaskFragments(fragment -> {
                    if (fragment.getPausingActivity() != null) {
                        pausingActivity[0] = fragment.getPausingActivity();
                        return true;
                    }
                    return false;
                });
            return pausingActivity[0];
                topPausingActivity = pausingActivity[0];
            } else if (taskPausingActivity != null
                    && child.asActivityRecord() == taskPausingActivity) {
                topPausingActivity = taskPausingActivity;
            }

        for (int i = mChildren.size() - 1; i >= 0; --i) {
            ActivityRecord pausingActivity = mChildren.get(i).asTask().getTopPausingActivity();
            if (pausingActivity != null) {
                return pausingActivity;
            if (topPausingActivity != null) {
                return topPausingActivity;
            }
        }
        return null;
@@ -1450,12 +1476,6 @@ class Task extends TaskFragment {

    @Override
    void addChild(WindowContainer child, int index) {
        // If this task had any child before we added this one.
        boolean hadChild = hasChild();
        // getActivityType() looks at the top child, so we need to read the type before adding
        // a new child in case the new child is on top and UNDEFINED.
        final int activityType = getActivityType();

        index = getAdjustedChildPosition(child, index);
        super.addChild(child, index);

@@ -1470,11 +1490,11 @@ class Task extends TaskFragment {
        // Make sure the list of display UID allowlists is updated
        // now that this record is in a new task.
        mRootWindowContainer.updateUIDsPresentOnDisplay();
    }

        final ActivityRecord r = child.asActivityRecord();
        if (r == null) return;

        r.inHistory = true;
    /** Called when an {@link ActivityRecord} is added as a descendant */
    void onDescendantActivityAdded(boolean hadChild, int activityType, ActivityRecord r) {
        warnForNonLeafTask("onDescendantActivityAdded");

        // Only set this based on the first activity
        if (!hadChild) {
@@ -1501,10 +1521,6 @@ class Task extends TaskFragment {
        updateEffectiveIntent();
    }

    void addChild(ActivityRecord r) {
        addChild(r, Integer.MAX_VALUE /* add on top */);
    }

    @Override
    void removeChild(WindowContainer child) {
        removeChild(child, "removeChild");
@@ -3088,6 +3104,41 @@ class Task extends TaskFragment {
        return false;
    }

    /** Iterates through all leaf task fragments and the leaf tasks. */
    void forAllLeafTasksAndLeafTaskFragments(final Consumer<TaskFragment> callback,
            boolean traverseTopToBottom) {
        forAllLeafTasks(task -> {
            if (task.isLeafTaskFragment()) {
                callback.accept(task);
                return;
            }

            // A leaf task that may contains both activities and task fragments.
            boolean consumed = false;
            if (traverseTopToBottom) {
                for (int i = task.mChildren.size() - 1; i >= 0; --i) {
                    final WindowContainer child = mChildren.get(i);
                    if (child.asTaskFragment() != null) {
                        child.forAllLeafTaskFragments(callback, traverseTopToBottom);
                    } else if (child.asActivityRecord() != null && !consumed) {
                        callback.accept(task);
                        consumed = true;
                    }
                }
            } else {
                for (int i = 0; i < task.mChildren.size(); i++) {
                    final WindowContainer child = mChildren.get(i);
                    if (child.asTaskFragment() != null) {
                        child.forAllLeafTaskFragments(callback, traverseTopToBottom);
                    } else if (child.asActivityRecord() != null && !consumed) {
                        callback.accept(task);
                        consumed = true;
                    }
                }
            }
        }, traverseTopToBottom);
    }

    @Override
    boolean forAllRootTasks(Function<Task, Boolean> callback, boolean traverseTopToBottom) {
        return isRootTask() ? callback.apply(this) : false;
@@ -4618,11 +4669,11 @@ class Task extends TaskFragment {
     */
    boolean goToSleepIfPossible(boolean shuttingDown) {
        final int[] sleepInProgress = {0};
        forAllLeafTaskFragments((f) -> {
            if (!f.sleepIfPossible(shuttingDown)) {
        forAllLeafTasksAndLeafTaskFragments(taskFragment -> {
            if (!taskFragment.sleepIfPossible(shuttingDown)) {
                sleepInProgress[0]++;
            }
        }, true);
        }, true /* traverseTopToBottom */);
        return sleepInProgress[0] == 0;
    }

@@ -4677,8 +4728,8 @@ class Task extends TaskFragment {
            boolean preserveWindows, boolean notifyClients) {
        mTaskSupervisor.beginActivityVisibilityUpdate();
        try {
            forAllLeafTaskFragments(fragment -> {
                fragment.updateActivityVisibilities(starting, configChanges, preserveWindows,
            forAllLeafTasks(task -> {
                task.updateActivityVisibilities(starting, configChanges, preserveWindows,
                        notifyClients);
            }, true /* traverseTopToBottom */);

@@ -4845,13 +4896,20 @@ class Task extends TaskFragment {

        mRootWindowContainer.cancelInitializingActivities();

        if (topRunningActivity(true /* focusableOnly */) == null) {
        final ActivityRecord topActivity = topRunningActivity(true /* focusableOnly */);
        if (topActivity == null) {
            // There are no activities left in this task, let's look somewhere else.
            return resumeNextFocusableActivityWhenRootTaskIsEmpty(prev, options);
        }

        final boolean[] resumed = new boolean[1];
        final TaskFragment topFragment = topActivity.getTaskFragment();
        resumed[0] = topFragment.resumeTopActivity(prev, options, deferPause);
        forAllLeafTaskFragments(f -> {
            if (topFragment == f) {
                return;
            }

            resumed[0] |= f.resumeTopActivity(prev, options, deferPause);
        }, true);
        return resumed[0];
Loading