Loading services/core/java/com/android/server/wm/BackNavigationController.java +155 −158 Original line number Diff line number Diff line Loading @@ -629,7 +629,7 @@ class BackNavigationController { final ActivityRecord ar = openApps.valueAt(i); if (mAnimationHandler.isTarget(ar, true /* open */)) { openApps.removeAt(i); mAnimationHandler.markStartingSurfaceMatch(); mAnimationHandler.markStartingSurfaceMatch(null /* reparentTransaction */); } } for (int i = closeApps.size() - 1; i >= 0; --i) { Loading Loading @@ -773,10 +773,15 @@ class BackNavigationController { for (int i = mTmpOpenApps.size() - 1; i >= 0; --i) { final WindowContainer wc = mTmpOpenApps.get(i); if (mAnimationHandler.isTarget(wc, true /* open */)) { mAnimationHandler.markStartingSurfaceMatch(); mAnimationHandler.markStartingSurfaceMatch(startTransaction); break; } } // release animation leash if (mAnimationHandler.mOpenAnimAdaptor.mCloseTransaction != null) { startTransaction.merge(mAnimationHandler.mOpenAnimAdaptor.mCloseTransaction); mAnimationHandler.mOpenAnimAdaptor.mCloseTransaction = null; } // Because the target will reparent to transition root, so it cannot be controlled by // animation leash. Hide the close target when transition starts. startTransaction.hide(mAnimationHandler.mCloseAdaptor.mTarget.getSurfaceControl()); Loading Loading @@ -993,7 +998,7 @@ class BackNavigationController { } final RemoteAnimationTarget[] targets = new RemoteAnimationTarget[2]; targets[0] = mCloseAdaptor.mAnimationTarget; targets[1] = mOpenAnimAdaptor.getOrCreateAnimationTarget(); targets[1] = mOpenAnimAdaptor.mRemoteAnimationTarget; return targets; } Loading Loading @@ -1067,11 +1072,12 @@ class BackNavigationController { } } void markStartingSurfaceMatch() { mStartingSurfaceTargetMatch = true; for (int i = mOpenAnimAdaptor.mAdaptors.length - 1; i >= 0; --i) { mOpenAnimAdaptor.mAdaptors[i].reparentWindowlessSurfaceToTarget(); void markStartingSurfaceMatch(SurfaceControl.Transaction reparentTransaction) { if (mStartingSurfaceTargetMatch) { return; } mStartingSurfaceTargetMatch = true; mOpenAnimAdaptor.reparentWindowlessSurfaceToTarget(reparentTransaction); } void clearBackAnimateTarget() { Loading Loading @@ -1140,14 +1146,23 @@ class BackNavigationController { private static class BackWindowAnimationAdaptorWrapper { final BackWindowAnimationAdaptor[] mAdaptors; // The highest remote animation target, which can be a wrapper if multiple adaptors, // or the single opening target. final RemoteAnimationTarget mRemoteAnimationTarget; SurfaceControl.Transaction mCloseTransaction; // The starting surface task Id. Used to clear the starting surface if the animation has // requested one during animating. private int mRequestedStartingSurfaceId = INVALID_TASK_ID; private SurfaceControl mStartingSurface; BackWindowAnimationAdaptorWrapper(boolean isOpen, int switchType, @NonNull WindowContainer... targets) { mAdaptors = new BackWindowAnimationAdaptor[targets.length]; for (int i = targets.length - 1; i >= 0; --i) { mAdaptors[i] = createAdaptor(targets[i], isOpen, switchType); } mRemoteAnimationTarget = targets.length > 1 ? createWrapTarget() : mAdaptors[0].mAnimationTarget; } boolean isValid() { Loading @@ -1160,40 +1175,23 @@ class BackNavigationController { } void cleanUp(boolean startingSurfaceMatch) { cleanUpWindowlessSurface(startingSurfaceMatch); for (int i = mAdaptors.length - 1; i >= 0; --i) { mAdaptors[i].cleanUpWindowlessSurface(startingSurfaceMatch); mAdaptors[i].mTarget.cancelAnimation(); } mRequestedStartingSurfaceId = INVALID_TASK_ID; mStartingSurface = null; if (mCloseTransaction != null) { mCloseTransaction.apply(); mCloseTransaction = null; } } void onAnimationFinish() { final SurfaceControl.Transaction pt = mAdaptors[0].mTarget.getPendingTransaction(); if (mCloseTransaction != null) { pt.merge(mCloseTransaction); mCloseTransaction = null; } if (mAdaptors.length > 1) { for (int i = mAdaptors.length - 1; i >= 0; --i) { final WindowContainer wc = mAdaptors[i].mTarget; final WindowContainer parent = wc.getParent(); if (parent != null) { pt.reparent(wc.getSurfaceControl(), parent.getSurfaceControl()); } } } } @NonNull RemoteAnimationTarget getOrCreateAnimationTarget() { private RemoteAnimationTarget createWrapTarget() { // Special handle for opening two activities together. // If we animate both activities separately, the animation area and rounded corner // would also being handled separately. To make them seem like "open" together, wrap // their leash with another animation leash. if (mAdaptors.length > 1 && mCloseTransaction == null) { final Rect unionBounds = new Rect(); for (int i = mAdaptors.length - 1; i >= 0; --i) { unionBounds.union(mAdaptors[i].mAnimationTarget.localBounds); Loading @@ -1208,16 +1206,23 @@ class BackNavigationController { .setHidden(false) .setParent(task.getSurfaceControl()) .build(); final SurfaceControl.Transaction pt = wc.getPendingTransaction(); pt.setLayer(leashSurface, wc.getParent().getLastLayer()); mCloseTransaction = new SurfaceControl.Transaction(); mCloseTransaction.reparent(leashSurface, null); final SurfaceControl.Transaction pt = wc.getPendingTransaction(); pt.setLayer(leashSurface, wc.getParent().getLastLayer()); for (int i = mAdaptors.length - 1; i >= 0; --i) { BackWindowAnimationAdaptor adaptor = mAdaptors[i]; pt.reparent(adaptor.mAnimationTarget.leash, leashSurface); pt.setPosition(adaptor.mAnimationTarget.leash, adaptor.mAnimationTarget.localBounds.left, adaptor.mAnimationTarget.localBounds.top); // For adjacent activity embedded, reparent Activity to TaskFragment when // animation finish final WindowContainer parent = adaptor.mTarget.getParent(); if (parent != null) { mCloseTransaction.reparent(adaptor.mTarget.getSurfaceControl(), parent.getSurfaceControl()); } } return new RemoteAnimationTarget(represent.taskId, represent.mode, leashSurface, represent.isTranslucent, represent.clipRect, represent.contentInsets, Loading @@ -1226,9 +1231,95 @@ class BackNavigationController { unionBounds, unionBounds, represent.windowConfiguration, true /* isNotInRecents */, null, null, represent.taskInfo, represent.allowEnterPip); } void createStartingSurface(@NonNull WindowContainer closeWindow, ActivityRecord[] visibleOpenActivities) { if (mAdaptors[0].mSwitchType == DIALOG_CLOSE) { return; } final WindowContainer mainOpen = mAdaptors[0].mTarget; final int switchType = mAdaptors[0].mSwitchType; final Task openTask = switchType == TASK_SWITCH ? mainOpen.asTask() : switchType == ACTIVITY_SWITCH ? mainOpen.asActivityRecord().getTask() : null; if (openTask == null) { return; } final ActivityRecord mainActivity = switchType == ACTIVITY_SWITCH ? mainOpen.asActivityRecord() : openTask.getTopNonFinishingActivity(); if (mainActivity == null) { return; } final TaskSnapshot snapshot = getSnapshot(mainOpen, visibleOpenActivities); mRequestedStartingSurfaceId = openTask.mAtmService.mTaskOrganizerController .addWindowlessStartingSurface(openTask, mainActivity, // Choose configuration from closeWindow, because the configuration // of opening target may not update before resume, so the starting // surface should occlude it entirely. mRemoteAnimationTarget.leash, snapshot, closeWindow.getConfiguration(), new IWindowlessStartingSurfaceCallback.Stub() { // Once the starting surface has been created in shell, it will call // onSurfaceAdded to pass the created surface to core, so if a // transition is triggered by the back gesture, there doesn't need to // create another starting surface for the opening target, just reparent // the starting surface to the opening target. // Note if cleanUpWindowlessSurface happen prior than onSurfaceAdded // called, there won't be able to reparent the starting surface on // opening target. But if that happens and transition target is matched, // the app window should already draw. @Override public void onSurfaceAdded(SurfaceControl sc) { synchronized (openTask.mWmService.mGlobalLock) { if (mRequestedStartingSurfaceId != INVALID_TASK_ID) { mStartingSurface = sc; } } } }); } // When back gesture has triggered and transition target matches navigation target, // reparent the starting surface to the opening target as it's starting window. void reparentWindowlessSurfaceToTarget(SurfaceControl.Transaction reparentTransaction) { if (mRequestedStartingSurfaceId == INVALID_TASK_ID) { return; } // If open target matches, reparent to open activity or task if (mStartingSurface != null && mStartingSurface.isValid()) { SurfaceControl.Transaction transaction = reparentTransaction != null ? reparentTransaction : mAdaptors[0].mTarget.getPendingTransaction(); if (mAdaptors.length == 1) { transaction.reparent(mStartingSurface, mAdaptors[0].mTarget.getSurfaceControl()); } else { return mAdaptors[0].mAnimationTarget; // More than one opening window, reparent starting surface to leaf task. final WindowContainer wc = mAdaptors[0].mTarget; final Task task = wc.asActivityRecord() != null ? wc.asActivityRecord().getTask() : wc.asTask(); transaction.reparent(mStartingSurface, task != null ? task.getSurfaceControl() : mAdaptors[0].mTarget.getSurfaceControl()); } // remove starting surface. mStartingSurface = null; } } /** * Ask shell to clear the starting surface. * @param openTransitionMatch if true, shell will play the remove starting window * animation, otherwise remove it directly. */ void cleanUpWindowlessSurface(boolean openTransitionMatch) { if (mRequestedStartingSurfaceId == INVALID_TASK_ID) { return; } mAdaptors[0].mTarget.mWmService.mAtmService.mTaskOrganizerController .removeWindowlessStartingSurface(mRequestedStartingSurfaceId, !openTransitionMatch); mRequestedStartingSurfaceId = INVALID_TASK_ID; } } Loading @@ -1240,11 +1331,6 @@ class BackNavigationController { private RemoteAnimationTarget mAnimationTarget; private final int mSwitchType; // The starting surface task Id. Used to clear the starting surface if the animation has // requested one during animating. private int mRequestedStartingSurfaceId = INVALID_TASK_ID; private SurfaceControl mStartingSurface; BackWindowAnimationAdaptor(@NonNull WindowContainer target, boolean isOpen, int switchType) { mBounds.set(target.getBounds()); Loading Loading @@ -1276,8 +1362,6 @@ class BackNavigationController { public void onAnimationCancelled(SurfaceControl animationLeash) { if (mCapturedLeash == animationLeash) { mCapturedLeash = null; mRequestedStartingSurfaceId = INVALID_TASK_ID; mStartingSurface = null; } } Loading Loading @@ -1345,84 +1429,6 @@ class BackNavigationController { r.checkEnterPictureInPictureAppOpsState()); return mAnimationTarget; } void createStartingSurface(@NonNull WindowContainer closeWindow, @NonNull ActivityRecord[] visibleOpenActivities) { if (!mIsOpen) { return; } if (mSwitchType == DIALOG_CLOSE) { return; } final Task openTask = mSwitchType == TASK_SWITCH ? mTarget.asTask() : mSwitchType == ACTIVITY_SWITCH ? mTarget.asActivityRecord().getTask() : null; if (openTask == null) { return; } final ActivityRecord mainActivity = mSwitchType == ACTIVITY_SWITCH ? mTarget.asActivityRecord() : openTask.getTopNonFinishingActivity(); if (mainActivity == null) { return; } final TaskSnapshot snapshot = getSnapshot(mTarget, visibleOpenActivities); mRequestedStartingSurfaceId = openTask.mAtmService.mTaskOrganizerController .addWindowlessStartingSurface(openTask, mainActivity, // Choose configuration from closeWindow, because the configuration // of opening target may not update before resume, so the starting // surface should occlude it entirely. mAnimationTarget.leash, snapshot, closeWindow.getConfiguration(), new IWindowlessStartingSurfaceCallback.Stub() { // Once the starting surface has been created in shell, it will call // onSurfaceAdded to pass the created surface to core, so if a // transition is triggered by the back gesture, there doesn't need to // create another starting surface for the opening target, just reparent // the starting surface to the opening target. // Note if cleanUpWindowlessSurface happen prior than onSurfaceAdded // called, there won't be able to reparent the starting surface on // opening target. But if that happens and transition target is matched, // the app window should already draw. @Override public void onSurfaceAdded(SurfaceControl sc) { synchronized (mTarget.mWmService.mGlobalLock) { if (mRequestedStartingSurfaceId != INVALID_TASK_ID) { mStartingSurface = sc; } } } }); } // When back gesture has triggered and transition target matches navigation target, // reparent the starting surface to the opening target as it's starting window. void reparentWindowlessSurfaceToTarget() { if (mRequestedStartingSurfaceId == INVALID_TASK_ID) { return; } // If open target matches, reparent to open activity or task if (mStartingSurface != null && mStartingSurface.isValid()) { mTarget.getPendingTransaction() .reparent(mStartingSurface, mTarget.getSurfaceControl()); // remove starting surface. mStartingSurface = null; } } /** * Ask shell to clear the starting surface. * @param openTransitionMatch if true, shell will play the remove starting window * animation, otherwise remove it directly. */ void cleanUpWindowlessSurface(boolean openTransitionMatch) { if (mRequestedStartingSurfaceId == INVALID_TASK_ID) { return; } mTarget.mWmService.mAtmService.mTaskOrganizerController .removeWindowlessStartingSurface(mRequestedStartingSurfaceId, !openTransitionMatch); mRequestedStartingSurfaceId = INVALID_TASK_ID; } } ScheduleAnimationBuilder prepareAnimation( Loading Loading @@ -1499,18 +1505,10 @@ class BackNavigationController { * @param visibleOpenActivities The visible activities in opening targets. */ private void applyPreviewStrategy(@NonNull WindowContainer closeWindow, @NonNull BackWindowAnimationAdaptor[] openAnimationAdaptor, @NonNull BackWindowAnimationAdaptorWrapper openAnimationAdaptor, @NonNull ActivityRecord[] visibleOpenActivities) { if (isSupportWindowlessSurface() && mShowWindowlessSurface && !mIsLaunchBehind // TODO (b/274997067) Draw two snapshot in a single starting surface. // We are using TaskId as the key of // StartingSurfaceDrawer#StartingWindowRecordManager, so we cannot create // two activity snapshot with WindowlessStartingWindow. // Try to draw two snapshot within a WindowlessStartingWindow, or find // another key for StartingWindowRecordManager. && openAnimationAdaptor.length == 1) { openAnimationAdaptor[0].createStartingSurface(closeWindow, visibleOpenActivities); if (isSupportWindowlessSurface() && mShowWindowlessSurface && !mIsLaunchBehind) { openAnimationAdaptor.createStartingSurface(closeWindow, visibleOpenActivities); } else { for (int i = visibleOpenActivities.length - 1; i >= 0; --i) { setLaunchBehind(visibleOpenActivities[i]); Loading Loading @@ -1541,7 +1539,7 @@ class BackNavigationController { } mCloseTarget.mTransitionController.mSnapshotController .mActivitySnapshotController.clearOnBackPressedActivities(); applyPreviewStrategy(mCloseTarget, mOpenAnimAdaptor.mAdaptors, openingActivities); applyPreviewStrategy(mCloseTarget, mOpenAnimAdaptor, openingActivities); final IBackAnimationFinishedCallback callback = makeAnimationFinishedCallback(); final RemoteAnimationTarget[] targets = getAnimationTargets(); Loading @@ -1565,7 +1563,6 @@ class BackNavigationController { // animation was canceled return; } mOpenAnimAdaptor.onAnimationFinish(); if (!triggerBack) { clearBackAnimateTarget(); } else { Loading Loading
services/core/java/com/android/server/wm/BackNavigationController.java +155 −158 Original line number Diff line number Diff line Loading @@ -629,7 +629,7 @@ class BackNavigationController { final ActivityRecord ar = openApps.valueAt(i); if (mAnimationHandler.isTarget(ar, true /* open */)) { openApps.removeAt(i); mAnimationHandler.markStartingSurfaceMatch(); mAnimationHandler.markStartingSurfaceMatch(null /* reparentTransaction */); } } for (int i = closeApps.size() - 1; i >= 0; --i) { Loading Loading @@ -773,10 +773,15 @@ class BackNavigationController { for (int i = mTmpOpenApps.size() - 1; i >= 0; --i) { final WindowContainer wc = mTmpOpenApps.get(i); if (mAnimationHandler.isTarget(wc, true /* open */)) { mAnimationHandler.markStartingSurfaceMatch(); mAnimationHandler.markStartingSurfaceMatch(startTransaction); break; } } // release animation leash if (mAnimationHandler.mOpenAnimAdaptor.mCloseTransaction != null) { startTransaction.merge(mAnimationHandler.mOpenAnimAdaptor.mCloseTransaction); mAnimationHandler.mOpenAnimAdaptor.mCloseTransaction = null; } // Because the target will reparent to transition root, so it cannot be controlled by // animation leash. Hide the close target when transition starts. startTransaction.hide(mAnimationHandler.mCloseAdaptor.mTarget.getSurfaceControl()); Loading Loading @@ -993,7 +998,7 @@ class BackNavigationController { } final RemoteAnimationTarget[] targets = new RemoteAnimationTarget[2]; targets[0] = mCloseAdaptor.mAnimationTarget; targets[1] = mOpenAnimAdaptor.getOrCreateAnimationTarget(); targets[1] = mOpenAnimAdaptor.mRemoteAnimationTarget; return targets; } Loading Loading @@ -1067,11 +1072,12 @@ class BackNavigationController { } } void markStartingSurfaceMatch() { mStartingSurfaceTargetMatch = true; for (int i = mOpenAnimAdaptor.mAdaptors.length - 1; i >= 0; --i) { mOpenAnimAdaptor.mAdaptors[i].reparentWindowlessSurfaceToTarget(); void markStartingSurfaceMatch(SurfaceControl.Transaction reparentTransaction) { if (mStartingSurfaceTargetMatch) { return; } mStartingSurfaceTargetMatch = true; mOpenAnimAdaptor.reparentWindowlessSurfaceToTarget(reparentTransaction); } void clearBackAnimateTarget() { Loading Loading @@ -1140,14 +1146,23 @@ class BackNavigationController { private static class BackWindowAnimationAdaptorWrapper { final BackWindowAnimationAdaptor[] mAdaptors; // The highest remote animation target, which can be a wrapper if multiple adaptors, // or the single opening target. final RemoteAnimationTarget mRemoteAnimationTarget; SurfaceControl.Transaction mCloseTransaction; // The starting surface task Id. Used to clear the starting surface if the animation has // requested one during animating. private int mRequestedStartingSurfaceId = INVALID_TASK_ID; private SurfaceControl mStartingSurface; BackWindowAnimationAdaptorWrapper(boolean isOpen, int switchType, @NonNull WindowContainer... targets) { mAdaptors = new BackWindowAnimationAdaptor[targets.length]; for (int i = targets.length - 1; i >= 0; --i) { mAdaptors[i] = createAdaptor(targets[i], isOpen, switchType); } mRemoteAnimationTarget = targets.length > 1 ? createWrapTarget() : mAdaptors[0].mAnimationTarget; } boolean isValid() { Loading @@ -1160,40 +1175,23 @@ class BackNavigationController { } void cleanUp(boolean startingSurfaceMatch) { cleanUpWindowlessSurface(startingSurfaceMatch); for (int i = mAdaptors.length - 1; i >= 0; --i) { mAdaptors[i].cleanUpWindowlessSurface(startingSurfaceMatch); mAdaptors[i].mTarget.cancelAnimation(); } mRequestedStartingSurfaceId = INVALID_TASK_ID; mStartingSurface = null; if (mCloseTransaction != null) { mCloseTransaction.apply(); mCloseTransaction = null; } } void onAnimationFinish() { final SurfaceControl.Transaction pt = mAdaptors[0].mTarget.getPendingTransaction(); if (mCloseTransaction != null) { pt.merge(mCloseTransaction); mCloseTransaction = null; } if (mAdaptors.length > 1) { for (int i = mAdaptors.length - 1; i >= 0; --i) { final WindowContainer wc = mAdaptors[i].mTarget; final WindowContainer parent = wc.getParent(); if (parent != null) { pt.reparent(wc.getSurfaceControl(), parent.getSurfaceControl()); } } } } @NonNull RemoteAnimationTarget getOrCreateAnimationTarget() { private RemoteAnimationTarget createWrapTarget() { // Special handle for opening two activities together. // If we animate both activities separately, the animation area and rounded corner // would also being handled separately. To make them seem like "open" together, wrap // their leash with another animation leash. if (mAdaptors.length > 1 && mCloseTransaction == null) { final Rect unionBounds = new Rect(); for (int i = mAdaptors.length - 1; i >= 0; --i) { unionBounds.union(mAdaptors[i].mAnimationTarget.localBounds); Loading @@ -1208,16 +1206,23 @@ class BackNavigationController { .setHidden(false) .setParent(task.getSurfaceControl()) .build(); final SurfaceControl.Transaction pt = wc.getPendingTransaction(); pt.setLayer(leashSurface, wc.getParent().getLastLayer()); mCloseTransaction = new SurfaceControl.Transaction(); mCloseTransaction.reparent(leashSurface, null); final SurfaceControl.Transaction pt = wc.getPendingTransaction(); pt.setLayer(leashSurface, wc.getParent().getLastLayer()); for (int i = mAdaptors.length - 1; i >= 0; --i) { BackWindowAnimationAdaptor adaptor = mAdaptors[i]; pt.reparent(adaptor.mAnimationTarget.leash, leashSurface); pt.setPosition(adaptor.mAnimationTarget.leash, adaptor.mAnimationTarget.localBounds.left, adaptor.mAnimationTarget.localBounds.top); // For adjacent activity embedded, reparent Activity to TaskFragment when // animation finish final WindowContainer parent = adaptor.mTarget.getParent(); if (parent != null) { mCloseTransaction.reparent(adaptor.mTarget.getSurfaceControl(), parent.getSurfaceControl()); } } return new RemoteAnimationTarget(represent.taskId, represent.mode, leashSurface, represent.isTranslucent, represent.clipRect, represent.contentInsets, Loading @@ -1226,9 +1231,95 @@ class BackNavigationController { unionBounds, unionBounds, represent.windowConfiguration, true /* isNotInRecents */, null, null, represent.taskInfo, represent.allowEnterPip); } void createStartingSurface(@NonNull WindowContainer closeWindow, ActivityRecord[] visibleOpenActivities) { if (mAdaptors[0].mSwitchType == DIALOG_CLOSE) { return; } final WindowContainer mainOpen = mAdaptors[0].mTarget; final int switchType = mAdaptors[0].mSwitchType; final Task openTask = switchType == TASK_SWITCH ? mainOpen.asTask() : switchType == ACTIVITY_SWITCH ? mainOpen.asActivityRecord().getTask() : null; if (openTask == null) { return; } final ActivityRecord mainActivity = switchType == ACTIVITY_SWITCH ? mainOpen.asActivityRecord() : openTask.getTopNonFinishingActivity(); if (mainActivity == null) { return; } final TaskSnapshot snapshot = getSnapshot(mainOpen, visibleOpenActivities); mRequestedStartingSurfaceId = openTask.mAtmService.mTaskOrganizerController .addWindowlessStartingSurface(openTask, mainActivity, // Choose configuration from closeWindow, because the configuration // of opening target may not update before resume, so the starting // surface should occlude it entirely. mRemoteAnimationTarget.leash, snapshot, closeWindow.getConfiguration(), new IWindowlessStartingSurfaceCallback.Stub() { // Once the starting surface has been created in shell, it will call // onSurfaceAdded to pass the created surface to core, so if a // transition is triggered by the back gesture, there doesn't need to // create another starting surface for the opening target, just reparent // the starting surface to the opening target. // Note if cleanUpWindowlessSurface happen prior than onSurfaceAdded // called, there won't be able to reparent the starting surface on // opening target. But if that happens and transition target is matched, // the app window should already draw. @Override public void onSurfaceAdded(SurfaceControl sc) { synchronized (openTask.mWmService.mGlobalLock) { if (mRequestedStartingSurfaceId != INVALID_TASK_ID) { mStartingSurface = sc; } } } }); } // When back gesture has triggered and transition target matches navigation target, // reparent the starting surface to the opening target as it's starting window. void reparentWindowlessSurfaceToTarget(SurfaceControl.Transaction reparentTransaction) { if (mRequestedStartingSurfaceId == INVALID_TASK_ID) { return; } // If open target matches, reparent to open activity or task if (mStartingSurface != null && mStartingSurface.isValid()) { SurfaceControl.Transaction transaction = reparentTransaction != null ? reparentTransaction : mAdaptors[0].mTarget.getPendingTransaction(); if (mAdaptors.length == 1) { transaction.reparent(mStartingSurface, mAdaptors[0].mTarget.getSurfaceControl()); } else { return mAdaptors[0].mAnimationTarget; // More than one opening window, reparent starting surface to leaf task. final WindowContainer wc = mAdaptors[0].mTarget; final Task task = wc.asActivityRecord() != null ? wc.asActivityRecord().getTask() : wc.asTask(); transaction.reparent(mStartingSurface, task != null ? task.getSurfaceControl() : mAdaptors[0].mTarget.getSurfaceControl()); } // remove starting surface. mStartingSurface = null; } } /** * Ask shell to clear the starting surface. * @param openTransitionMatch if true, shell will play the remove starting window * animation, otherwise remove it directly. */ void cleanUpWindowlessSurface(boolean openTransitionMatch) { if (mRequestedStartingSurfaceId == INVALID_TASK_ID) { return; } mAdaptors[0].mTarget.mWmService.mAtmService.mTaskOrganizerController .removeWindowlessStartingSurface(mRequestedStartingSurfaceId, !openTransitionMatch); mRequestedStartingSurfaceId = INVALID_TASK_ID; } } Loading @@ -1240,11 +1331,6 @@ class BackNavigationController { private RemoteAnimationTarget mAnimationTarget; private final int mSwitchType; // The starting surface task Id. Used to clear the starting surface if the animation has // requested one during animating. private int mRequestedStartingSurfaceId = INVALID_TASK_ID; private SurfaceControl mStartingSurface; BackWindowAnimationAdaptor(@NonNull WindowContainer target, boolean isOpen, int switchType) { mBounds.set(target.getBounds()); Loading Loading @@ -1276,8 +1362,6 @@ class BackNavigationController { public void onAnimationCancelled(SurfaceControl animationLeash) { if (mCapturedLeash == animationLeash) { mCapturedLeash = null; mRequestedStartingSurfaceId = INVALID_TASK_ID; mStartingSurface = null; } } Loading Loading @@ -1345,84 +1429,6 @@ class BackNavigationController { r.checkEnterPictureInPictureAppOpsState()); return mAnimationTarget; } void createStartingSurface(@NonNull WindowContainer closeWindow, @NonNull ActivityRecord[] visibleOpenActivities) { if (!mIsOpen) { return; } if (mSwitchType == DIALOG_CLOSE) { return; } final Task openTask = mSwitchType == TASK_SWITCH ? mTarget.asTask() : mSwitchType == ACTIVITY_SWITCH ? mTarget.asActivityRecord().getTask() : null; if (openTask == null) { return; } final ActivityRecord mainActivity = mSwitchType == ACTIVITY_SWITCH ? mTarget.asActivityRecord() : openTask.getTopNonFinishingActivity(); if (mainActivity == null) { return; } final TaskSnapshot snapshot = getSnapshot(mTarget, visibleOpenActivities); mRequestedStartingSurfaceId = openTask.mAtmService.mTaskOrganizerController .addWindowlessStartingSurface(openTask, mainActivity, // Choose configuration from closeWindow, because the configuration // of opening target may not update before resume, so the starting // surface should occlude it entirely. mAnimationTarget.leash, snapshot, closeWindow.getConfiguration(), new IWindowlessStartingSurfaceCallback.Stub() { // Once the starting surface has been created in shell, it will call // onSurfaceAdded to pass the created surface to core, so if a // transition is triggered by the back gesture, there doesn't need to // create another starting surface for the opening target, just reparent // the starting surface to the opening target. // Note if cleanUpWindowlessSurface happen prior than onSurfaceAdded // called, there won't be able to reparent the starting surface on // opening target. But if that happens and transition target is matched, // the app window should already draw. @Override public void onSurfaceAdded(SurfaceControl sc) { synchronized (mTarget.mWmService.mGlobalLock) { if (mRequestedStartingSurfaceId != INVALID_TASK_ID) { mStartingSurface = sc; } } } }); } // When back gesture has triggered and transition target matches navigation target, // reparent the starting surface to the opening target as it's starting window. void reparentWindowlessSurfaceToTarget() { if (mRequestedStartingSurfaceId == INVALID_TASK_ID) { return; } // If open target matches, reparent to open activity or task if (mStartingSurface != null && mStartingSurface.isValid()) { mTarget.getPendingTransaction() .reparent(mStartingSurface, mTarget.getSurfaceControl()); // remove starting surface. mStartingSurface = null; } } /** * Ask shell to clear the starting surface. * @param openTransitionMatch if true, shell will play the remove starting window * animation, otherwise remove it directly. */ void cleanUpWindowlessSurface(boolean openTransitionMatch) { if (mRequestedStartingSurfaceId == INVALID_TASK_ID) { return; } mTarget.mWmService.mAtmService.mTaskOrganizerController .removeWindowlessStartingSurface(mRequestedStartingSurfaceId, !openTransitionMatch); mRequestedStartingSurfaceId = INVALID_TASK_ID; } } ScheduleAnimationBuilder prepareAnimation( Loading Loading @@ -1499,18 +1505,10 @@ class BackNavigationController { * @param visibleOpenActivities The visible activities in opening targets. */ private void applyPreviewStrategy(@NonNull WindowContainer closeWindow, @NonNull BackWindowAnimationAdaptor[] openAnimationAdaptor, @NonNull BackWindowAnimationAdaptorWrapper openAnimationAdaptor, @NonNull ActivityRecord[] visibleOpenActivities) { if (isSupportWindowlessSurface() && mShowWindowlessSurface && !mIsLaunchBehind // TODO (b/274997067) Draw two snapshot in a single starting surface. // We are using TaskId as the key of // StartingSurfaceDrawer#StartingWindowRecordManager, so we cannot create // two activity snapshot with WindowlessStartingWindow. // Try to draw two snapshot within a WindowlessStartingWindow, or find // another key for StartingWindowRecordManager. && openAnimationAdaptor.length == 1) { openAnimationAdaptor[0].createStartingSurface(closeWindow, visibleOpenActivities); if (isSupportWindowlessSurface() && mShowWindowlessSurface && !mIsLaunchBehind) { openAnimationAdaptor.createStartingSurface(closeWindow, visibleOpenActivities); } else { for (int i = visibleOpenActivities.length - 1; i >= 0; --i) { setLaunchBehind(visibleOpenActivities[i]); Loading Loading @@ -1541,7 +1539,7 @@ class BackNavigationController { } mCloseTarget.mTransitionController.mSnapshotController .mActivitySnapshotController.clearOnBackPressedActivities(); applyPreviewStrategy(mCloseTarget, mOpenAnimAdaptor.mAdaptors, openingActivities); applyPreviewStrategy(mCloseTarget, mOpenAnimAdaptor, openingActivities); final IBackAnimationFinishedCallback callback = makeAnimationFinishedCallback(); final RemoteAnimationTarget[] targets = getAnimationTargets(); Loading @@ -1565,7 +1563,6 @@ class BackNavigationController { // animation was canceled return; } mOpenAnimAdaptor.onAnimationFinish(); if (!triggerBack) { clearBackAnimateTarget(); } else { Loading