diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 6acd9b5be0c42..4ecc62923c5df 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -460,7 +460,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { private final ClientLifecycleManager mLifecycleManager; @Nullable - private final BackNavigationController mBackNavigationController; + final BackNavigationController mBackNavigationController; private TaskChangeNotificationController mTaskChangeNotificationController; /** The controller for all operations related to locktask. */ diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java index d15f954333231..d42ad58f6f217 100644 --- a/services/core/java/com/android/server/wm/BackNavigationController.java +++ b/services/core/java/com/android/server/wm/BackNavigationController.java @@ -57,6 +57,9 @@ class BackNavigationController { private static final String TAG = "BackNavigationController"; private WindowManagerService mWindowManagerService; private IWindowFocusObserver mFocusObserver; + private boolean mBackAnimationInProgress; + private boolean mShowWallpaper; + private Runnable mPendingAnimation; /** * Returns true if the back predictability feature is enabled @@ -208,6 +211,7 @@ class BackNavigationController { return infoBuilder.setType(backType).build(); } + mBackAnimationInProgress = true; // We don't have an application callback, let's find the destination of the back gesture Task finalTask = currentTask; prevActivity = currentTask.getActivity( @@ -228,6 +232,7 @@ class BackNavigationController { // Our Task should bring back to home removedWindowContainer = currentTask; backType = BackNavigationInfo.TYPE_RETURN_TO_HOME; + mShowWallpaper = true; } else if (currentActivity.isRootOfTask()) { // TODO(208789724): Create single source of truth for this, maybe in // RootWindowContainer @@ -240,6 +245,7 @@ class BackNavigationController { } else { backType = BackNavigationInfo.TYPE_CROSS_TASK; } + mShowWallpaper = true; } infoBuilder.setType(backType); @@ -369,6 +375,13 @@ class BackNavigationController { } } + if (mShowWallpaper) { + currentTask.getDisplayContent().mWallpaperController.adjustWallpaperWindows(); + // TODO(b/241808055): If the current animation need to show wallpaper and animate the + // wallpaper, start the wallpaper animation to collect wallpaper target and deliver it + // to the back animation controller. + } + final RemoteAnimationTarget[] targets = (behindAppTarget == null) ? new RemoteAnimationTarget[] {topAppTarget} : new RemoteAnimationTarget[] {topAppTarget, behindAppTarget}; @@ -399,7 +412,7 @@ class BackNavigationController { } }; - startAnimation(backType, targets, adapter, callback); + scheduleAnimationLocked(backType, targets, adapter, callback); } @NonNull @@ -445,17 +458,38 @@ class BackNavigationController { } @VisibleForTesting - void startAnimation(@BackNavigationInfo.BackTargetType int type, + void scheduleAnimationLocked(@BackNavigationInfo.BackTargetType int type, RemoteAnimationTarget[] targets, BackAnimationAdapter backAnimationAdapter, IBackAnimationFinishedCallback callback) { - mWindowManagerService.mAnimator.addAfterPrepareSurfacesRunnable(() -> { + mPendingAnimation = () -> { try { backAnimationAdapter.getRunner().onAnimationStart(type, targets, null, null, callback); } catch (RemoteException e) { e.printStackTrace(); } - }); + }; + mWindowManagerService.mWindowPlacerLocked.requestTraversal(); + } + + void checkAnimationReady(WallpaperController wallpaperController) { + if (!mBackAnimationInProgress) { + return; + } + + final boolean wallpaperReady = !mShowWallpaper + || (wallpaperController.getWallpaperTarget() != null + && wallpaperController.wallpaperTransitionReady()); + if (wallpaperReady && mPendingAnimation != null) { + startAnimation(); + } + } + + void startAnimation() { + if (mPendingAnimation != null) { + mPendingAnimation.run(); + mPendingAnimation = null; + } } private void onBackNavigationDone(Bundle result, WindowState focusedWindow, int backType) { @@ -468,6 +502,8 @@ class BackNavigationController { focusedWindow.unregisterFocusObserver(mFocusObserver); mFocusObserver = null; } + mBackAnimationInProgress = false; + mShowWallpaper = false; } private HardwareBuffer getActivitySnapshot(@NonNull Task task, @@ -544,4 +580,11 @@ class BackNavigationController { "Setting Activity.mLauncherTaskBehind to false. Activity=%s", activity); } + + boolean isWallpaperVisible(WindowState w) { + if (mBackAnimationInProgress && w.isFocused()) { + return mShowWallpaper; + } + return false; + } } diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index b2ec3f369e9e6..38c75954e6bb8 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -837,6 +837,11 @@ class RootWindowContainer extends WindowContainer if (recentsAnimationController != null) { recentsAnimationController.checkAnimationReady(defaultDisplay.mWallpaperController); } + final BackNavigationController backNavigationController = + mWmService.mAtmService.mBackNavigationController; + if (backNavigationController != null) { + backNavigationController.checkAnimationReady(defaultDisplay.mWallpaperController); + } for (int displayNdx = 0; displayNdx < mChildren.size(); ++displayNdx) { final DisplayContent displayContent = mChildren.get(displayNdx); diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java index 0fd3e9b4abae3..81d67952afaef 100644 --- a/services/core/java/com/android/server/wm/WallpaperController.java +++ b/services/core/java/com/android/server/wm/WallpaperController.java @@ -197,7 +197,7 @@ class WallpaperController { && animatingContainer.getAnimation() != null && animatingContainer.getAnimation().getShowWallpaper(); final boolean hasWallpaper = w.hasWallpaper() || animationWallpaper; - if (isRecentsTransitionTarget(w)) { + if (isRecentsTransitionTarget(w) || isBackNavigationTarget(w)) { if (DEBUG_WALLPAPER) Slog.v(TAG, "Found recents animation wallpaper target: " + w); mFindResults.setWallpaperTarget(w); return true; @@ -237,6 +237,12 @@ class WallpaperController { return controller != null && controller.isWallpaperVisible(w); } + private boolean isBackNavigationTarget(WindowState w) { + // The window is in animating by back navigation and set to show wallpaper. + final BackNavigationController controller = mService.mAtmService.mBackNavigationController; + return controller != null && controller.isWallpaperVisible(w); + } + /** * @see #computeLastWallpaperZoomOut() */ @@ -822,6 +828,12 @@ class WallpaperController { if (mService.getRecentsAnimationController() != null) { mService.getRecentsAnimationController().startAnimation(); } + + // If there was a pending back navigation animation that would show wallpaper, start + // the animation due to it was skipped in previous surface placement. + if (mService.mAtmService.mBackNavigationController != null) { + mService.mAtmService.mBackNavigationController.startAnimation(); + } return true; } return false; diff --git a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java index 7847e7a4dd13f..c3d49e1e5152f 100644 --- a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java @@ -90,7 +90,7 @@ public class BackNavigationControllerTests extends WindowTestsBase { .isEqualTo(typeToString(BackNavigationInfo.TYPE_RETURN_TO_HOME)); // verify if back animation would start. - verify(mBackNavigationController).startAnimation( + verify(mBackNavigationController).scheduleAnimationLocked( eq(BackNavigationInfo.TYPE_RETURN_TO_HOME), any(), eq(mBackAnimationAdapter), any()); }