Loading core/java/android/window/WindowContainerTransaction.java +19 −0 Original line number Diff line number Diff line Loading @@ -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}. Loading Loading @@ -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. Loading packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java +15 −5 Original line number Diff line number Diff line Loading @@ -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; } Loading @@ -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 Loading @@ -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()); } Loading Loading @@ -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; Loading @@ -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."); Loading @@ -228,6 +234,7 @@ public class RemoteTransitionCompat implements Parcelable { mFinishCB = finishCB; mPausingTasks = pausingTasks; mPipTask = pipTask; mRecentsTask = recentsTask; mLeashMap = leashMap; mTransition = transition; } Loading Loading @@ -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) { Loading services/core/java/com/android/server/wm/ActivityStarter.java +9 −1 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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, Loading Loading @@ -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) { Loading services/core/java/com/android/server/wm/Transition.java +20 −8 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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; Loading Loading @@ -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; } Loading services/core/java/com/android/server/wm/TransitionController.java +4 −2 Original line number Diff line number Diff line Loading @@ -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 Loading
core/java/android/window/WindowContainerTransaction.java +19 −0 Original line number Diff line number Diff line Loading @@ -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}. Loading Loading @@ -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. Loading
packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java +15 −5 Original line number Diff line number Diff line Loading @@ -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; } Loading @@ -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 Loading @@ -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()); } Loading Loading @@ -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; Loading @@ -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."); Loading @@ -228,6 +234,7 @@ public class RemoteTransitionCompat implements Parcelable { mFinishCB = finishCB; mPausingTasks = pausingTasks; mPipTask = pipTask; mRecentsTask = recentsTask; mLeashMap = leashMap; mTransition = transition; } Loading Loading @@ -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) { Loading
services/core/java/com/android/server/wm/ActivityStarter.java +9 −1 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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, Loading Loading @@ -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) { Loading
services/core/java/com/android/server/wm/Transition.java +20 −8 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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; Loading Loading @@ -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; } Loading
services/core/java/com/android/server/wm/TransitionController.java +4 −2 Original line number Diff line number Diff line Loading @@ -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