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

Commit 3c8a920a authored by Evan Rosky's avatar Evan Rosky
Browse files

Support restoring the original task ordering of transient-launches

Like legacy recents, we need to be able to restore the home task
back to where it was in the task-ordering when recents doesn't
actually switch to home.

This CL records the "restore-below" task during activity-start
and stores in the associated transition. There is a new WCT op
that will "restore" a container back to where it was.

Bug: 210014802
Test: launch a task chain (task followed by task), then go to
      recents, then restore the top task. observe task order
      remains as it was before recents.
Change-Id: I9f9da7d35ffe69099e6431b7a0d5a527e33c5a74
parent 429c0a97
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -570,6 +570,24 @@ public final class WindowContainerTransaction implements Parcelable {
        return this;
    }

    /**
     * If `container` was brought to front as a transient-launch (eg. recents), this will reorder
     * the container back to where it was prior to the transient-launch. This way if a transient
     * launch is "aborted", the z-ordering of containers in WM should be restored to before the
     * launch.
     * @hide
     */
    @NonNull
    public WindowContainerTransaction restoreTransientOrder(
            @NonNull WindowContainerToken container) {
        final HierarchyOp hierarchyOp =
                new HierarchyOp.Builder(HierarchyOp.HIERARCHY_OP_TYPE_RESTORE_TRANSIENT_ORDER)
                        .setContainer(container.asBinder())
                        .build();
        mHierarchyOps.add(hierarchyOp);
        return this;
    }

    /**
     * When this {@link WindowContainerTransaction} failed to finish on the server side, it will
     * trigger callback with this {@param errorCallbackToken}.
@@ -974,6 +992,7 @@ public final class WindowContainerTransaction implements Parcelable {
        public static final int HIERARCHY_OP_TYPE_PENDING_INTENT = 12;
        public static final int HIERARCHY_OP_TYPE_SET_ADJACENT_TASK_FRAGMENTS = 13;
        public static final int HIERARCHY_OP_TYPE_START_SHORTCUT = 14;
        public static final int HIERARCHY_OP_TYPE_RESTORE_TRANSIENT_ORDER = 15;

        // The following key(s) are for use with mLaunchOptions:
        // When launching a task (eg. from recents), this is the taskId to be launched.
+15 −5
Original line number Diff line number Diff line
@@ -132,12 +132,13 @@ public class RemoteTransitionCompat implements Parcelable {
                // the current going-away task on top of recents, though, so move it to front
                final ArrayList<WindowContainerToken> pausingTasks = new ArrayList<>();
                WindowContainerToken pipTask = null;
                WindowContainerToken recentsTask = null;
                for (int i = info.getChanges().size() - 1; i >= 0; --i) {
                    final TransitionInfo.Change change = info.getChanges().get(i);
                    final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
                    if (change.getMode() == TRANSIT_CLOSE || change.getMode() == TRANSIT_TO_BACK) {
                        t.setLayer(leashMap.get(change.getLeash()),
                                info.getChanges().size() * 3 - i);
                        final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
                        if (taskInfo == null) {
                            continue;
                        }
@@ -147,11 +148,14 @@ public class RemoteTransitionCompat implements Parcelable {
                                && taskInfo.pictureInPictureParams.isAutoEnterEnabled()) {
                            pipTask = taskInfo.token;
                        }
                    } else if (change.getTaskInfo() != null
                            && change.getTaskInfo().topActivityType == ACTIVITY_TYPE_RECENTS) {
                    } else if (taskInfo != null
                            && taskInfo.topActivityType == ACTIVITY_TYPE_RECENTS) {
                        // This task is for recents, keep it on top.
                        t.setLayer(leashMap.get(change.getLeash()),
                                info.getChanges().size() * 3 - i);
                        recentsTask = taskInfo.token;
                    } else if (taskInfo != null && taskInfo.topActivityType == ACTIVITY_TYPE_HOME) {
                        recentsTask = taskInfo.token;
                    }
                }
                // Also make all the wallpapers opaque since we want the visible from the start
@@ -160,7 +164,7 @@ public class RemoteTransitionCompat implements Parcelable {
                }
                t.apply();
                mRecentsSession.setup(controller, info, finishedCallback, pausingTasks, pipTask,
                        leashMap, mToken);
                        recentsTask, leashMap, mToken);
                recents.onAnimationStart(mRecentsSession, apps, wallpapers, new Rect(0, 0, 0, 0),
                        new Rect());
            }
@@ -209,6 +213,7 @@ public class RemoteTransitionCompat implements Parcelable {
        private IRemoteTransitionFinishedCallback mFinishCB = null;
        private ArrayList<WindowContainerToken> mPausingTasks = null;
        private WindowContainerToken mPipTask = null;
        private WindowContainerToken mRecentsTask = null;
        private TransitionInfo mInfo = null;
        private ArrayList<SurfaceControl> mOpeningLeashes = null;
        private ArrayMap<SurfaceControl, SurfaceControl> mLeashMap = null;
@@ -218,7 +223,8 @@ public class RemoteTransitionCompat implements Parcelable {
        void setup(RecentsAnimationControllerCompat wrapped, TransitionInfo info,
                IRemoteTransitionFinishedCallback finishCB,
                ArrayList<WindowContainerToken> pausingTasks, WindowContainerToken pipTask,
                ArrayMap<SurfaceControl, SurfaceControl> leashMap, IBinder transition) {
                WindowContainerToken recentsTask, ArrayMap<SurfaceControl, SurfaceControl> leashMap,
                IBinder transition) {
            if (mInfo != null) {
                throw new IllegalStateException("Trying to run a new recents animation while"
                        + " recents is already active.");
@@ -228,6 +234,7 @@ public class RemoteTransitionCompat implements Parcelable {
            mFinishCB = finishCB;
            mPausingTasks = pausingTasks;
            mPipTask = pipTask;
            mRecentsTask = recentsTask;
            mLeashMap = leashMap;
            mTransition = transition;
        }
@@ -329,6 +336,9 @@ public class RemoteTransitionCompat implements Parcelable {
                    wct.reorder(mPausingTasks.get(i), true /* onTop */);
                    t.show(mInfo.getChange(mPausingTasks.get(i)).getLeash());
                }
                if (mRecentsTask != null) {
                    wct.restoreTransientOrder(mRecentsTask);
                }
            } else {
                wct = null;
                if (mPipTask != null && mPipTransaction != null) {
+9 −1
Original line number Diff line number Diff line
@@ -208,6 +208,9 @@ class ActivityStarter {
    private boolean mAvoidMoveToFront;
    private boolean mFrozeTaskList;
    private boolean mTransientLaunch;
    // The task which was above the targetTask before starting this activity. null if the targetTask
    // was already on top or if the activity is in a new task.
    private Task mPriorAboveTask;

    // We must track when we deliver the new intent since multiple code paths invoke
    // {@link #deliverNewIntent}. This is due to early returns in the code path. This flag is used
@@ -1666,7 +1669,8 @@ class ActivityStarter {
                if (isTransient) {
                    // `r` isn't guaranteed to be the actual relevant activity, so we must wait
                    // until after we launched to identify the relevant activity.
                    transitionController.setTransientLaunch(mLastStartActivityRecord);
                    transitionController.setTransientLaunch(mLastStartActivityRecord,
                            mPriorAboveTask);
                }
                if (newTransition != null) {
                    transitionController.requestStartTransition(newTransition,
@@ -1785,6 +1789,10 @@ class ActivityStarter {
            return startResult;
        }

        if (targetTask != null) {
            mPriorAboveTask = TaskDisplayArea.getRootTaskAbove(targetTask.getRootTask());
        }

        final ActivityRecord targetTaskTop = newTask
                ? null : targetTask.getTopNonFinishingActivity();
        if (targetTaskTop != null) {
+20 −8
Original line number Diff line number Diff line
@@ -167,8 +167,11 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
     */
    private final ArraySet<WindowToken> mVisibleAtTransitionEndTokens = new ArraySet<>();

    /** Set of transient activities (lifecycle initially tied to this transition). */
    private ArraySet<ActivityRecord> mTransientLaunches = null;
    /**
     * Set of transient activities (lifecycle initially tied to this transition) and their
     * restore-below tasks.
     */
    private ArrayMap<ActivityRecord, Task> mTransientLaunches = null;

    /** Custom activity-level animation options and callbacks. */
    private TransitionInfo.AnimationOptions mOverrideOptions;
@@ -196,17 +199,26 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
    }

    /** Records an activity as transient-launch. This activity must be already collected. */
    void setTransientLaunch(@NonNull ActivityRecord activity) {
    void setTransientLaunch(@NonNull ActivityRecord activity, @Nullable Task restoreBelow) {
        if (mTransientLaunches == null) {
            mTransientLaunches = new ArraySet<>();
            mTransientLaunches = new ArrayMap<>();
        }
        mTransientLaunches.add(activity);
        mTransientLaunches.put(activity, restoreBelow);
        ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Transition %d: Set %s as "
                + "transient-launch", mSyncId, activity);
    }

    boolean isTransientLaunch(@NonNull ActivityRecord activity) {
        return mTransientLaunches != null && mTransientLaunches.contains(activity);
        return mTransientLaunches != null && mTransientLaunches.containsKey(activity);
    }

    Task getTransientLaunchRestoreTarget(@NonNull WindowContainer container) {
        for (int i = 0; i < mTransientLaunches.size(); ++i) {
            if (mTransientLaunches.keyAt(i).isDescendantOf(container)) {
                return mTransientLaunches.valueAt(i);
            }
        }
        return null;
    }

    boolean isOnDisplay(@NonNull DisplayContent dc) {
@@ -464,7 +476,7 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
                                && ar.pictureInPictureArgs.isAutoEnterEnabled()) {
                            if (mTransientLaunches != null) {
                                for (int j = 0; j < mTransientLaunches.size(); ++j) {
                                    if (mTransientLaunches.valueAt(j).isVisibleRequested()) {
                                    if (mTransientLaunches.keyAt(j).isVisibleRequested()) {
                                        // force enable pip-on-task-switch now that we've committed
                                        // to actually launching to the transient activity.
                                        ar.supportsEnterPipOnTaskSwitch = true;
@@ -543,7 +555,7 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
                // Transient-launch activities cannot be IME target (WindowState#canBeImeTarget),
                // so re-compute in case the IME target is changed after transition.
                for (int t = 0; t < mTransientLaunches.size(); ++t) {
                    if (mTransientLaunches.valueAt(t).getDisplayContent() == dc) {
                    if (mTransientLaunches.keyAt(t).getDisplayContent() == dc) {
                        dc.computeImeTarget(true /* updateImeTarget */);
                        break;
                    }
+4 −2
Original line number Diff line number Diff line
@@ -520,10 +520,12 @@ class TransitionController {
    /**
     * Record that the launch of {@param activity} is transient (meaning its lifecycle is currently
     * tied to the transition).
     * @param restoreBelowTask If non-null, the activity's task will be ordered right below this
     *                         task if requested.
     */
    void setTransientLaunch(@NonNull ActivityRecord activity) {
    void setTransientLaunch(@NonNull ActivityRecord activity, @Nullable Task restoreBelowTask) {
        if (mCollectingTransition == null) return;
        mCollectingTransition.setTransientLaunch(activity);
        mCollectingTransition.setTransientLaunch(activity, restoreBelowTask);

        // TODO(b/188669821): Remove once legacy recents behavior is moved to shell.
        // Also interpret HOME transient launch as recents
Loading