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

Commit a3aae9ab authored by Winson Chung's avatar Winson Chung Committed by Android (Google) Code Review
Browse files

Merge "3b/ Migrate away from finishWCT usage in recents transition" into main

parents 7ae3519a 52ae087d
Loading
Loading
Loading
Loading
+132 −20
Original line number Original line Diff line number Diff line
@@ -34,6 +34,8 @@ import static android.window.TransitionInfo.FLAG_TRANSLUCENT;


import static com.android.wm.shell.shared.ShellSharedConstants.KEY_EXTRA_SHELL_CAN_HAND_OFF_ANIMATION;
import static com.android.wm.shell.shared.ShellSharedConstants.KEY_EXTRA_SHELL_CAN_HAND_OFF_ANIMATION;
import static com.android.wm.shell.shared.split.SplitBounds.KEY_EXTRA_SPLIT_BOUNDS;
import static com.android.wm.shell.shared.split.SplitBounds.KEY_EXTRA_SPLIT_BOUNDS;
import static com.android.wm.shell.transition.Transitions.TRANSIT_END_RECENTS_TRANSITION;
import static com.android.wm.shell.transition.Transitions.TRANSIT_START_RECENTS_TRANSITION;


import android.annotation.Nullable;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.annotation.SuppressLint;
@@ -67,6 +69,7 @@ import androidx.annotation.NonNull;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.IResultReceiver;
import com.android.internal.os.IResultReceiver;
import com.android.internal.protolog.ProtoLog;
import com.android.internal.protolog.ProtoLog;
import com.android.wm.shell.Flags;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.pip.PipUtils;
import com.android.wm.shell.common.pip.PipUtils;
@@ -216,8 +219,11 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler,
                break;
                break;
            }
            }
        }
        }
        final IBinder transition = mTransitions.startTransition(TRANSIT_TO_FRONT, wct,
        final int transitionType = Flags.enableShellTopTaskTracking()
                mixer == null ? this : mixer);
                ? TRANSIT_START_RECENTS_TRANSITION
                : TRANSIT_TO_FRONT;
        final IBinder transition = mTransitions.startTransition(transitionType,
                wct, mixer == null ? this : mixer);
        if (mixer != null) {
        if (mixer != null) {
            setTransitionForMixer.accept(transition);
            setTransitionForMixer.accept(transition);
        }
        }
@@ -300,7 +306,7 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler,
                    "RecentsTransitionHandler.mergeAnimation: no controller found");
                    "RecentsTransitionHandler.mergeAnimation: no controller found");
            return;
            return;
        }
        }
        controller.merge(info, t, finishCallback);
        controller.merge(info, t, mergeTarget, finishCallback);
    }
    }


    @Override
    @Override
@@ -367,6 +373,8 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler,
        private boolean mPausingSeparateHome = false;
        private boolean mPausingSeparateHome = false;
        private ArrayMap<SurfaceControl, SurfaceControl> mLeashMap = null;
        private ArrayMap<SurfaceControl, SurfaceControl> mLeashMap = null;
        private PictureInPictureSurfaceTransaction mPipTransaction = null;
        private PictureInPictureSurfaceTransaction mPipTransaction = null;
        // This is the transition that backs the entire recents transition, and the one that the
        // pending finish transition below will be merged into
        private IBinder mTransition = null;
        private IBinder mTransition = null;
        private boolean mKeyguardLocked = false;
        private boolean mKeyguardLocked = false;
        private boolean mWillFinishToHome = false;
        private boolean mWillFinishToHome = false;
@@ -386,6 +394,10 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler,
        // next called.
        // next called.
        private Pair<int[], TaskSnapshot[]> mPendingPauseSnapshotsForCancel;
        private Pair<int[], TaskSnapshot[]> mPendingPauseSnapshotsForCancel;


        // Used to track a pending finish transition
        private IBinder mPendingFinishTransition;
        private IResultReceiver mPendingRunnerFinishCb;

        RecentsController(IRecentsAnimationRunner listener) {
        RecentsController(IRecentsAnimationRunner listener) {
            mInstanceId = System.identityHashCode(this);
            mInstanceId = System.identityHashCode(this);
            mListener = listener;
            mListener = listener;
@@ -523,6 +535,11 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler,
            mInfo = null;
            mInfo = null;
            mTransition = null;
            mTransition = null;
            mPendingPauseSnapshotsForCancel = null;
            mPendingPauseSnapshotsForCancel = null;
            mPipTaskId = -1;
            mPipTask = null;
            mPipTransaction = null;
            mPendingRunnerFinishCb = null;
            mPendingFinishTransition = null;
            mControllers.remove(this);
            mControllers.remove(this);
            for (int i = 0; i < mStateListeners.size(); i++) {
            for (int i = 0; i < mStateListeners.size(); i++) {
                mStateListeners.get(i).onAnimationStateChanged(false);
                mStateListeners.get(i).onAnimationStateChanged(false);
@@ -734,6 +751,8 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler,
                        // the pausing apps.
                        // the pausing apps.
                        t.setLayer(target.leash, layer);
                        t.setLayer(target.leash, layer);
                    } else if (taskInfo != null && taskInfo.topActivityType == ACTIVITY_TYPE_HOME) {
                    } else if (taskInfo != null && taskInfo.topActivityType == ACTIVITY_TYPE_HOME) {
                        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
                                "  not handling home taskId=%d", taskInfo.taskId);
                        // do nothing
                        // do nothing
                    } else if (TransitionUtil.isOpeningType(change.getMode())) {
                    } else if (TransitionUtil.isOpeningType(change.getMode())) {
                        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
                        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
@@ -872,16 +891,35 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler,
            }
            }
        }
        }


        /**
         * Note: because we use a book-end transition to finish the recents transition, we must
         * either always merge the incoming transition, or always cancel the recents transition
         * if we don't handle the incoming transition to ensure that the end transition is queued
         * before any unhandled transitions.
         */
        @SuppressLint("NewApi")
        @SuppressLint("NewApi")
        void merge(TransitionInfo info, SurfaceControl.Transaction t,
        void merge(TransitionInfo info, SurfaceControl.Transaction t, IBinder mergeTarget,
                Transitions.TransitionFinishCallback finishCallback) {
                Transitions.TransitionFinishCallback finishCallback) {
            if (mFinishCB == null) {
            if (mFinishCB == null) {
                ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
                ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
                        "[%d] RecentsController.merge: skip, no finish callback",
                        "[%d] RecentsController.merge: skip, no finish callback",
                        mInstanceId);
                        mInstanceId);
                // This was no-op'd (likely a repeated start) and we've already sent finish.
                // This was no-op'd (likely a repeated start) and we've already completed finish.
                return;
                return;
            }
            }

            if (Flags.enableShellTopTaskTracking()
                    && info.getType() == TRANSIT_END_RECENTS_TRANSITION
                    && mergeTarget == mTransition) {
                // This is a pending finish, so merge the end transition to trigger completing the
                // cleanup of the recents transition
                ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
                        "[%d] RecentsController.merge: TRANSIT_END_RECENTS_TRANSITION",
                        mInstanceId);
                finishCallback.onTransitionFinished(null /* wct */);
                return;
            }

            if (info.getType() == TRANSIT_SLEEP) {
            if (info.getType() == TRANSIT_SLEEP) {
                ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
                ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
                        "[%d] RecentsController.merge: transit_sleep", mInstanceId);
                        "[%d] RecentsController.merge: transit_sleep", mInstanceId);
@@ -1245,7 +1283,8 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler,
                return;
                return;
            }
            }


            if (mFinishCB == null) {
            if (mFinishCB == null
                    || (Flags.enableShellTopTaskTracking() && mPendingFinishTransition != null)) {
                Slog.e(TAG, "Duplicate call to finish");
                Slog.e(TAG, "Duplicate call to finish");
                return;
                return;
            }
            }
@@ -1254,19 +1293,22 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler,
                    && !mWillFinishToHome
                    && !mWillFinishToHome
                    && mPausingTasks != null
                    && mPausingTasks != null
                    && mState == STATE_NORMAL;
                    && mState == STATE_NORMAL;
            if (!Flags.enableShellTopTaskTracking()) {
                // This is only necessary when the recents transition is finished using a finishWCT,
                // otherwise a new transition will notify the relevant observers
                if (returningToApp && allAppsAreTranslucent(mPausingTasks)) {
                if (returningToApp && allAppsAreTranslucent(mPausingTasks)) {
                    mHomeTransitionObserver.notifyHomeVisibilityChanged(true);
                    mHomeTransitionObserver.notifyHomeVisibilityChanged(true);
                } else if (!toHome) {
                } else if (!toHome) {
                // For some transitions, we may have notified home activity that it became visible.
                    // For some transitions, we may have notified home activity that it became
                // We need to notify the observer that we are no longer going home.
                    // visible. We need to notify the observer that we are no longer going home.
                    mHomeTransitionObserver.notifyHomeVisibilityChanged(false);
                    mHomeTransitionObserver.notifyHomeVisibilityChanged(false);
                }
                }
            }

            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
                    "[%d] RecentsController.finishInner: toHome=%b userLeave=%b "
                    "[%d] RecentsController.finishInner: toHome=%b userLeave=%b "
                            + "willFinishToHome=%b state=%d",
                            + "willFinishToHome=%b state=%d reason=%s",
                    mInstanceId, toHome, sendUserLeaveHint, mWillFinishToHome, mState);
                    mInstanceId, toHome, sendUserLeaveHint, mWillFinishToHome, mState, reason);
            final Transitions.TransitionFinishCallback finishCB = mFinishCB;
            mFinishCB = null;


            final SurfaceControl.Transaction t = mFinishTransaction;
            final SurfaceControl.Transaction t = mFinishTransaction;
            final WindowContainerTransaction wct = new WindowContainerTransaction();
            final WindowContainerTransaction wct = new WindowContainerTransaction();
@@ -1328,6 +1370,7 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler,
                for (int i = 0; i < mClosingTasks.size(); ++i) {
                for (int i = 0; i < mClosingTasks.size(); ++i) {
                    cleanUpPausingOrClosingTask(mClosingTasks.get(i), wct, t, sendUserLeaveHint);
                    cleanUpPausingOrClosingTask(mClosingTasks.get(i), wct, t, sendUserLeaveHint);
                }
                }

                if (mPipTransaction != null && sendUserLeaveHint) {
                if (mPipTransaction != null && sendUserLeaveHint) {
                    SurfaceControl pipLeash = null;
                    SurfaceControl pipLeash = null;
                    TransitionInfo.Change pipChange = null;
                    TransitionInfo.Change pipChange = null;
@@ -1379,15 +1422,50 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler,
                            mTransitions.startTransition(TRANSIT_PIP, wct, null /* handler */);
                            mTransitions.startTransition(TRANSIT_PIP, wct, null /* handler */);
                            // We need to clear the WCT to send finishWCT=null for Recents.
                            // We need to clear the WCT to send finishWCT=null for Recents.
                            wct.clear();
                            wct.clear();

                            if (Flags.enableShellTopTaskTracking()) {
                                // In this case, we've already started the PIP transition, so we can
                                // clean up immediately
                                mPendingRunnerFinishCb = runnerFinishCb;
                                onFinishInner(null);
                                return;
                            }
                            }
                        }
                        }
                    mPipTaskId = -1;
                    mPipTask = null;
                    mPipTransaction = null;
                    }
                    }
                }
                }
            }

            if (Flags.enableShellTopTaskTracking()) {
                if (!wct.isEmpty()) {
                    ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
                            "[%d] RecentsController.finishInner: "
                                    + "Queuing TRANSIT_END_RECENTS_TRANSITION", mInstanceId);
                    mPendingRunnerFinishCb = runnerFinishCb;
                    mPendingFinishTransition = mTransitions.startTransition(
                            TRANSIT_END_RECENTS_TRANSITION, wct,
                            new PendingFinishTransitionHandler());
                } else {
                    // If there's no work to do, just go ahead and clean up
                    mPendingRunnerFinishCb = runnerFinishCb;
                    onFinishInner(null /* wct */);
                }
            } else {
                mPendingRunnerFinishCb = runnerFinishCb;
                onFinishInner(wct);
            }
        }

        /**
         * Runs the actual logic to finish the recents transition.
         */
        private void onFinishInner(@Nullable WindowContainerTransaction wct) {
            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
                    "[%d] RecentsController.finishInner: Completing finish", mInstanceId);
            final Transitions.TransitionFinishCallback finishCb = mFinishCB;
            final IResultReceiver runnerFinishCb = mPendingRunnerFinishCb;

            cleanUp();
            cleanUp();
            finishCB.onTransitionFinished(wct.isEmpty() ? null : wct);
            finishCb.onTransitionFinished(wct);
            if (runnerFinishCb != null) {
            if (runnerFinishCb != null) {
                try {
                try {
                    ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
                    ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
@@ -1472,6 +1550,40 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler,
                }
                }
            });
            });
        }
        }

        /**
         * A temporary transition handler used with the pending finish transition, which runs the
         * cleanup/finish logic once the pending transition is merged/handled.
         * This is only initialized if Flags.enableShellTopTaskTracking() is enabled.
         */
        private class PendingFinishTransitionHandler implements Transitions.TransitionHandler {
            @Override
            public boolean startAnimation(@NonNull IBinder transition,
                    @NonNull TransitionInfo info,
                    @NonNull SurfaceControl.Transaction startTransaction,
                    @NonNull SurfaceControl.Transaction finishTransaction,
                    @NonNull Transitions.TransitionFinishCallback finishCallback) {
                return false;
            }

            @Nullable
            @Override
            public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
                    @NonNull TransitionRequestInfo request) {
                return null;
            }

            @Override
            public void onTransitionConsumed(@NonNull IBinder transition, boolean aborted,
                    @Nullable SurfaceControl.Transaction finishTransaction) {
                // Once we have merged (or not if the WCT didn't result in any changes), then we can
                // run the pending finish logic
                ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
                        "[%d] RecentsController.onTransitionConsumed: "
                                + "Consumed pending finish transition", mInstanceId);
                onFinishInner(null /* wct */);
            }
        };
    };
    };


    /** Utility class to track the state of a task as-seen by recents. */
    /** Utility class to track the state of a task as-seen by recents. */
+8 −0
Original line number Original line Diff line number Diff line
@@ -203,6 +203,12 @@ public class Transitions implements RemoteCallable<Transitions>,
    /** Transition type to minimize a task. */
    /** Transition type to minimize a task. */
    public static final int TRANSIT_MINIMIZE = WindowManager.TRANSIT_FIRST_CUSTOM + 20;
    public static final int TRANSIT_MINIMIZE = WindowManager.TRANSIT_FIRST_CUSTOM + 20;


    /** Transition to start the recents transition */
    public static final int TRANSIT_START_RECENTS_TRANSITION = TRANSIT_FIRST_CUSTOM + 21;

    /** Transition to end the recents transition */
    public static final int TRANSIT_END_RECENTS_TRANSITION = TRANSIT_FIRST_CUSTOM + 22;

    /** Transition type for desktop mode transitions. */
    /** Transition type for desktop mode transitions. */
    public static final int TRANSIT_DESKTOP_MODE_TYPES =
    public static final int TRANSIT_DESKTOP_MODE_TYPES =
            WindowManager.TRANSIT_FIRST_CUSTOM + 100;
            WindowManager.TRANSIT_FIRST_CUSTOM + 100;
@@ -1875,6 +1881,8 @@ public class Transitions implements RemoteCallable<Transitions>,
            case TRANSIT_SPLIT_PASSTHROUGH -> "SPLIT_PASSTHROUGH";
            case TRANSIT_SPLIT_PASSTHROUGH -> "SPLIT_PASSTHROUGH";
            case TRANSIT_CLEANUP_PIP_EXIT -> "CLEANUP_PIP_EXIT";
            case TRANSIT_CLEANUP_PIP_EXIT -> "CLEANUP_PIP_EXIT";
            case TRANSIT_MINIMIZE -> "MINIMIZE";
            case TRANSIT_MINIMIZE -> "MINIMIZE";
            case TRANSIT_START_RECENTS_TRANSITION -> "START_RECENTS_TRANSITION";
            case TRANSIT_END_RECENTS_TRANSITION -> "END_RECENTS_TRANSITION";
            default -> "";
            default -> "";
        };
        };
        return typeStr + "(FIRST_CUSTOM+" + (transitType - TRANSIT_FIRST_CUSTOM) + ")";
        return typeStr + "(FIRST_CUSTOM+" + (transitType - TRANSIT_FIRST_CUSTOM) + ")";
+39 −1
Original line number Original line Diff line number Diff line
@@ -465,6 +465,31 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
        return false;
        return false;
    }
    }


    /**
     * This ensures that all changes for previously transient-hide containers are flagged such that
     * they will report changes and be included in this transition.
     */
    void updateChangesForRestoreTransientHideTasks(Transition transientLaunchTransition) {
        if (transientLaunchTransition.mTransientHideTasks == null) {
            // Skip if the transient-launch transition has no transient-hide tasks
            ProtoLog.v(WmProtoLogGroups.WM_DEBUG_WINDOW_TRANSITIONS,
                    "Skipping update changes for restore transient hide tasks");
            return;
        }

        // For each change, if it was previously transient-hidden, then we should force a flag to
        // ensure that it is included in the next transition
        for (int i = 0; i < mChanges.size(); i++) {
            final WindowContainer container = mChanges.keyAt(i);
            if (transientLaunchTransition.isInTransientHide(container)) {
                ProtoLog.v(WmProtoLogGroups.WM_DEBUG_WINDOW_TRANSITIONS,
                        "Force update transient hide task for restore %d: %s", mSyncId, container);
                final ChangeInfo info = mChanges.valueAt(i);
                info.mRestoringTransientHide = true;
            }
        }
    }

    /** Returns {@code true} if the task should keep visible if this is a transient transition. */
    /** Returns {@code true} if the task should keep visible if this is a transient transition. */
    boolean isTransientVisible(@NonNull Task task) {
    boolean isTransientVisible(@NonNull Task task) {
        if (mTransientLaunches == null) return false;
        if (mTransientLaunches == null) return false;
@@ -3478,6 +3503,10 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {


        // State tracking
        // State tracking
        boolean mExistenceChanged = false;
        boolean mExistenceChanged = false;
        // This state indicates that we are restoring transient order as a part of an
        // end-transition. Because the visibility for transient hide containers has not actually
        // changed, we need to ensure that hasChanged() still reports the relevant changes
        boolean mRestoringTransientHide = false;
        // before change state
        // before change state
        boolean mVisible;
        boolean mVisible;
        int mWindowingMode;
        int mWindowingMode;
@@ -3552,7 +3581,11 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
                    || !mContainer.getBounds().equals(mAbsoluteBounds)
                    || !mContainer.getBounds().equals(mAbsoluteBounds)
                    || mRotation != mContainer.getWindowConfiguration().getRotation()
                    || mRotation != mContainer.getWindowConfiguration().getRotation()
                    || mDisplayId != getDisplayId(mContainer)
                    || mDisplayId != getDisplayId(mContainer)
                    || (mFlags & ChangeInfo.FLAG_CHANGE_MOVED_TO_TOP) != 0;
                    || (mFlags & ChangeInfo.FLAG_CHANGE_MOVED_TO_TOP) != 0
                    // If we are restoring transient-hide containers, then we should consider them
                    // important for the transition as well (their requested visibilities would not
                    // have changed for the checks below to consider it).
                    || mRestoringTransientHide;
        }
        }


        @TransitionInfo.TransitionMode
        @TransitionInfo.TransitionMode
@@ -3565,6 +3598,11 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
            }
            }
            final boolean nowVisible = wc.isVisibleRequested();
            final boolean nowVisible = wc.isVisibleRequested();
            if (nowVisible == mVisible) {
            if (nowVisible == mVisible) {
                if (mRestoringTransientHide) {
                    // The requested visibility has not changed for transient-hide containers, but
                    // we are restoring them so we should considering them moving to front again
                    return TRANSIT_TO_FRONT;
                }
                return TRANSIT_CHANGE;
                return TRANSIT_CHANGE;
            }
            }
            if (mExistenceChanged) {
            if (mExistenceChanged) {
+18 −0
Original line number Original line Diff line number Diff line
@@ -37,6 +37,7 @@ import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.SystemProperties;
import android.util.ArrayMap;
import android.util.ArrayMap;
import android.util.Pair;
import android.util.Slog;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseArray;
import android.util.TimeUtils;
import android.util.TimeUtils;
@@ -524,6 +525,23 @@ class TransitionController {
        return false;
        return false;
    }
    }


    /**
     * @return A pair of the transition and restore-behind target for the given {@param container}.
     * @param container An ancestor of a transient-launch activity
     */
    @Nullable
    Pair<Transition, Task> getTransientLaunchTransitionAndTarget(
            @NonNull WindowContainer container) {
        for (int i = mPlayingTransitions.size() - 1; i >= 0; --i) {
            final Transition transition = mPlayingTransitions.get(i);
            final Task restoreBehindTask = transition.getTransientLaunchRestoreTarget(container);
            if (restoreBehindTask != null) {
                return new Pair<>(transition, restoreBehindTask);
            }
        }
        return null;
    }

    /** Returns {@code true} if the display contains a transient-launch transition. */
    /** Returns {@code true} if the display contains a transient-launch transition. */
    boolean hasTransientLaunch(@NonNull DisplayContent dc) {
    boolean hasTransientLaunch(@NonNull DisplayContent dc) {
        if (mCollectingTransition != null && mCollectingTransition.hasTransientLaunch()
        if (mCollectingTransition != null && mCollectingTransition.hasTransientLaunch()
+46 −5
Original line number Original line Diff line number Diff line
@@ -111,6 +111,7 @@ import android.os.RemoteException;
import android.util.AndroidRuntimeException;
import android.util.AndroidRuntimeException;
import android.util.ArrayMap;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.ArraySet;
import android.util.Pair;
import android.util.Slog;
import android.util.Slog;
import android.view.RemoteAnimationAdapter;
import android.view.RemoteAnimationAdapter;
import android.view.SurfaceControl;
import android.view.SurfaceControl;
@@ -1375,16 +1376,56 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
                break;
                break;
            }
            }
            case HIERARCHY_OP_TYPE_RESTORE_TRANSIENT_ORDER: {
            case HIERARCHY_OP_TYPE_RESTORE_TRANSIENT_ORDER: {
                if (!com.android.wm.shell.Flags.enableShellTopTaskTracking()) {
                    // Only allow restoring transient order when finishing a transition
                    if (!chain.isFinishing()) break;
                    if (!chain.isFinishing()) break;
                }
                // Validate the container
                final WindowContainer container = WindowContainer.fromBinder(hop.getContainer());
                final WindowContainer container = WindowContainer.fromBinder(hop.getContainer());
                if (container == null) break;
                if (container == null) {
                    ProtoLog.v(WmProtoLogGroups.WM_DEBUG_WINDOW_TRANSITIONS,
                            "Restoring transient order: invalid container");
                    break;
                }
                final Task thisTask = container.asActivityRecord() != null
                final Task thisTask = container.asActivityRecord() != null
                        ? container.asActivityRecord().getTask() : container.asTask();
                        ? container.asActivityRecord().getTask() : container.asTask();
                if (thisTask == null) break;
                if (thisTask == null) {
                final Task restoreAt = chain.mTransition.getTransientLaunchRestoreTarget(container);
                    ProtoLog.v(WmProtoLogGroups.WM_DEBUG_WINDOW_TRANSITIONS,
                if (restoreAt == null) break;
                            "Restoring transient order: invalid task");
                    break;
                }

                // Find the task to restore behind
                final Pair<Transition, Task> transientRestore =
                        mTransitionController.getTransientLaunchTransitionAndTarget(container);
                if (transientRestore == null) {
                    ProtoLog.v(WmProtoLogGroups.WM_DEBUG_WINDOW_TRANSITIONS,
                            "Restoring transient order: no restore task");
                    break;
                }
                final Transition transientLaunchTransition = transientRestore.first;
                final Task restoreAt = transientRestore.second;
                ProtoLog.v(WmProtoLogGroups.WM_DEBUG_WINDOW_TRANSITIONS,
                        "Restoring transient order: restoring behind task=%d", restoreAt.mTaskId);

                // Restore the position of the given container behind the target task
                final TaskDisplayArea taskDisplayArea = thisTask.getTaskDisplayArea();
                final TaskDisplayArea taskDisplayArea = thisTask.getTaskDisplayArea();
                taskDisplayArea.moveRootTaskBehindRootTask(thisTask.getRootTask(), restoreAt);
                taskDisplayArea.moveRootTaskBehindRootTask(thisTask.getRootTask(), restoreAt);

                if (com.android.wm.shell.Flags.enableShellTopTaskTracking()) {
                    // Because we are in a transient launch transition, the requested visibility of
                    // tasks does not actually change for the transient-hide tasks, but we do want
                    // the restoration of these transient-hide tasks to top to be a part of this
                    // finish transition
                    final Transition collectingTransition =
                            mTransitionController.getCollectingTransition();
                    if (collectingTransition != null) {
                        collectingTransition.updateChangesForRestoreTransientHideTasks(
                                transientLaunchTransition);
                    }
                }

                effects |= TRANSACT_EFFECTS_LIFECYCLE;
                break;
                break;
            }
            }
            case HIERARCHY_OP_TYPE_ADD_INSETS_FRAME_PROVIDER: {
            case HIERARCHY_OP_TYPE_ADD_INSETS_FRAME_PROVIDER: {