Loading libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java +132 −20 Original line number Original line Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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); } } Loading Loading @@ -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 Loading Loading @@ -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; Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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, Loading Loading @@ -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); Loading Loading @@ -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; } } Loading @@ -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(); Loading Loading @@ -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; Loading Loading @@ -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, Loading Loading @@ -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. */ Loading libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java +8 −0 Original line number Original line Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) + ")"; Loading services/core/java/com/android/server/wm/Transition.java +39 −1 Original line number Original line Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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 Loading @@ -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) { Loading services/core/java/com/android/server/wm/TransitionController.java +18 −0 Original line number Original line Diff line number Diff line Loading @@ -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; Loading Loading @@ -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() Loading services/core/java/com/android/server/wm/WindowOrganizerController.java +46 −5 Original line number Original line Diff line number Diff line Loading @@ -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; Loading Loading @@ -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: { Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java +132 −20 Original line number Original line Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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); } } Loading Loading @@ -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 Loading Loading @@ -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; Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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, Loading Loading @@ -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); Loading Loading @@ -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; } } Loading @@ -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(); Loading Loading @@ -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; Loading Loading @@ -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, Loading Loading @@ -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. */ Loading
libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java +8 −0 Original line number Original line Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) + ")"; Loading
services/core/java/com/android/server/wm/Transition.java +39 −1 Original line number Original line Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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 Loading @@ -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) { Loading
services/core/java/com/android/server/wm/TransitionController.java +18 −0 Original line number Original line Diff line number Diff line Loading @@ -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; Loading Loading @@ -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() Loading
services/core/java/com/android/server/wm/WindowOrganizerController.java +46 −5 Original line number Original line Diff line number Diff line Loading @@ -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; Loading Loading @@ -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: { Loading