diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json index 909ca3988c5d0..d9653512d7308 100644 --- a/data/etc/services.core.protolog.json +++ b/data/etc/services.core.protolog.json @@ -2371,12 +2371,6 @@ "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "457951957": { - "message": "\tNot visible=%s", - "level": "DEBUG", - "group": "WM_DEBUG_REMOTE_ANIMATIONS", - "at": "com\/android\/server\/wm\/WallpaperAnimationAdapter.java" - }, "463993897": { "message": "Aborted waiting for drawn: %s", "level": "WARN", @@ -3697,6 +3691,12 @@ "group": "WM_DEBUG_REMOTE_ANIMATIONS", "at": "com\/android\/server\/wm\/RemoteAnimationController.java" }, + "2024493888": { + "message": "\tWallpaper of display=%s is not visible", + "level": "DEBUG", + "group": "WM_DEBUG_REMOTE_ANIMATIONS", + "at": "com\/android\/server\/wm\/WallpaperAnimationAdapter.java" + }, "2028163120": { "message": "applyAnimation: anim=%s nextAppTransition=ANIM_SCALE_UP transit=%s isEntrance=%s Callers=%s", "level": "VERBOSE", @@ -3721,12 +3721,6 @@ "group": "WM_DEBUG_APP_TRANSITIONS", "at": "com\/android\/server\/wm\/AppTransitionController.java" }, - "2057434754": { - "message": "\tvisible=%s", - "level": "DEBUG", - "group": "WM_DEBUG_REMOTE_ANIMATIONS", - "at": "com\/android\/server\/wm\/WallpaperAnimationAdapter.java" - }, "2060978050": { "message": "moveWindowTokenToDisplay: Attempted to move token: %s to non-exiting displayId=%d", "level": "WARN", diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java index ffaf710523eeb..535a061ee4aba 100644 --- a/services/core/java/com/android/server/wm/AppTransitionController.java +++ b/services/core/java/com/android/server/wm/AppTransitionController.java @@ -124,6 +124,7 @@ public class AppTransitionController { @interface TransitContainerType {} private final ArrayMap mTempTransitionReasons = new ArrayMap<>(); + private final ArrayList mTempTransitionWindows = new ArrayList<>(); AppTransitionController(WindowManagerService service, DisplayContent displayContent) { mService = service; @@ -523,26 +524,44 @@ public class AppTransitionController { } } + private boolean transitionMayContainNonAppWindows(@TransitionOldType int transit) { + // We don't want to have the client to animate any non-app windows. + // Having {@code transit} of those types doesn't mean it will contain non-app windows, but + // non-app windows will only be included with those transition types. And we don't currently + // have any use case of those for TaskFragment transition. + // @see NonAppWindowAnimationAdapter#startNonAppWindowAnimations + if (transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY + || transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER + || transit == TRANSIT_OLD_TASK_OPEN || transit == TRANSIT_OLD_TASK_TO_FRONT + || transit == TRANSIT_OLD_WALLPAPER_CLOSE) { + return true; + } + + // Check if the wallpaper is going to participate in the transition. We don't want to have + // the client to animate the wallpaper windows. + // @see WallpaperAnimationAdapter#startWallpaperAnimations + return mDisplayContent.mWallpaperController.isWallpaperVisible(); + } + /** - * Overrides the pending transition with the remote animation defined by the - * {@link ITaskFragmentOrganizer} if all windows in the transition are children of - * {@link TaskFragment} that are organized by the same organizer. - * - * @return {@code true} if the transition is overridden. + * Finds the common {@link android.window.TaskFragmentOrganizer} that organizes all app windows + * in the current transition. + * @return {@code null} if there is no such organizer, or if there are more than one. */ - private boolean overrideWithTaskFragmentRemoteAnimation(@TransitionOldType int transit, - ArraySet activityTypes) { - final ArrayList allWindows = new ArrayList<>(); - allWindows.addAll(mDisplayContent.mClosingApps); - allWindows.addAll(mDisplayContent.mOpeningApps); - allWindows.addAll(mDisplayContent.mChangingContainers); + @Nullable + private ITaskFragmentOrganizer findTaskFragmentOrganizerForAllWindows() { + mTempTransitionWindows.clear(); + mTempTransitionWindows.addAll(mDisplayContent.mClosingApps); + mTempTransitionWindows.addAll(mDisplayContent.mOpeningApps); + mTempTransitionWindows.addAll(mDisplayContent.mChangingContainers); // It should only animated by the organizer if all windows are below the same leaf Task. Task leafTask = null; - for (int i = allWindows.size() - 1; i >= 0; i--) { - final ActivityRecord r = getAppFromContainer(allWindows.get(i)); + for (int i = mTempTransitionWindows.size() - 1; i >= 0; i--) { + final ActivityRecord r = getAppFromContainer(mTempTransitionWindows.get(i)); if (r == null) { - return false; + leafTask = null; + break; } // The activity may be a child of embedded Task, but we want to find the owner Task. // As a result, find the organized TaskFragment first. @@ -561,26 +580,31 @@ public class AppTransitionController { ? organizedTaskFragment.getTask() : r.getTask(); if (task == null) { - return false; + leafTask = null; + break; } // We don't want the organizer to handle transition of other non-embedded Task. if (leafTask != null && leafTask != task) { - return false; + leafTask = null; + break; } final ActivityRecord rootActivity = task.getRootActivity(); // We don't want the organizer to handle transition when the whole app is closing. if (rootActivity == null) { - return false; + leafTask = null; + break; } // We don't want the organizer to handle transition of non-embedded activity of other // app. if (r.getUid() != rootActivity.getUid() && !r.isEmbedded()) { - return false; + leafTask = null; + break; } leafTask = task; } + mTempTransitionWindows.clear(); if (leafTask == null) { - return false; + return null; } // We don't support remote animation for Task with multiple TaskFragmentOrganizers. @@ -599,12 +623,28 @@ public class AppTransitionController { if (hasMultipleOrganizers) { ProtoLog.e(WM_DEBUG_APP_TRANSITIONS, "We don't support remote animation for" + " Task with multiple TaskFragmentOrganizers."); + return null; + } + return organizer[0]; + } + + /** + * Overrides the pending transition with the remote animation defined by the + * {@link ITaskFragmentOrganizer} if all windows in the transition are children of + * {@link TaskFragment} that are organized by the same organizer. + * + * @return {@code true} if the transition is overridden. + */ + private boolean overrideWithTaskFragmentRemoteAnimation(@TransitionOldType int transit, + ArraySet activityTypes) { + if (transitionMayContainNonAppWindows(transit)) { return false; } - final RemoteAnimationDefinition definition = organizer[0] != null + final ITaskFragmentOrganizer organizer = findTaskFragmentOrganizerForAllWindows(); + final RemoteAnimationDefinition definition = organizer != null ? mDisplayContent.mAtmService.mTaskFragmentOrganizerController - .getRemoteAnimationDefinition(organizer[0]) + .getRemoteAnimationDefinition(organizer) : null; final RemoteAnimationAdapter adapter = definition != null ? definition.getAdapter(transit, activityTypes) diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java index a663c62b40e58..22c84590fcfc0 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimationController.java +++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java @@ -793,7 +793,7 @@ public class RecentsAnimationController implements DeathRecipient { private RemoteAnimationTarget[] createWallpaperAnimations() { ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "createWallpaperAnimations()"); - return WallpaperAnimationAdapter.startWallpaperAnimations(mService, 0L, 0L, + return WallpaperAnimationAdapter.startWallpaperAnimations(mDisplayContent, 0L, 0L, adapter -> { synchronized (mService.mGlobalLock) { // If the wallpaper animation is canceled, continue with the recents diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java index 16a45fe7cec7e..ca1aed52fe047 100644 --- a/services/core/java/com/android/server/wm/RemoteAnimationController.java +++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java @@ -207,7 +207,7 @@ class RemoteAnimationController implements DeathRecipient { if (wrappers.mThumbnailAdapter != null && wrappers.mThumbnailAdapter.mCapturedFinishCallback != null) { wrappers.mThumbnailAdapter.mCapturedFinishCallback - .onAnimationFinished(wrappers.mAdapter.mAnimationType, + .onAnimationFinished(wrappers.mThumbnailAdapter.mAnimationType, wrappers.mThumbnailAdapter); } mPendingAnimations.remove(i); @@ -218,7 +218,7 @@ class RemoteAnimationController implements DeathRecipient { private RemoteAnimationTarget[] createWallpaperAnimations() { ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "createWallpaperAnimations()"); - return WallpaperAnimationAdapter.startWallpaperAnimations(mService, + return WallpaperAnimationAdapter.startWallpaperAnimations(mDisplayContent, mRemoteAnimationAdapter.getDuration(), mRemoteAnimationAdapter.getStatusBarTransitionDelay(), adapter -> { @@ -260,7 +260,7 @@ class RemoteAnimationController implements DeathRecipient { } if (adapters.mThumbnailAdapter != null) { adapters.mThumbnailAdapter.mCapturedFinishCallback - .onAnimationFinished(adapters.mAdapter.mAnimationType, + .onAnimationFinished(adapters.mThumbnailAdapter.mAnimationType, adapters.mThumbnailAdapter); } mPendingAnimations.remove(i); diff --git a/services/core/java/com/android/server/wm/WallpaperAnimationAdapter.java b/services/core/java/com/android/server/wm/WallpaperAnimationAdapter.java index 25f7269effe8f..0b20f37eea0f4 100644 --- a/services/core/java/com/android/server/wm/WallpaperAnimationAdapter.java +++ b/services/core/java/com/android/server/wm/WallpaperAnimationAdapter.java @@ -64,18 +64,17 @@ class WallpaperAnimationAdapter implements AnimationAdapter { * * @return RemoteAnimationTarget[] targets for all the visible wallpaper windows */ - public static RemoteAnimationTarget[] startWallpaperAnimations(WindowManagerService service, + public static RemoteAnimationTarget[] startWallpaperAnimations(DisplayContent displayContent, long durationHint, long statusBarTransitionDelay, Consumer animationCanceledRunnable, ArrayList adaptersOut) { + if (!displayContent.mWallpaperController.isWallpaperVisible()) { + ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, + "\tWallpaper of display=%s is not visible", displayContent); + return new RemoteAnimationTarget[0]; + } final ArrayList targets = new ArrayList<>(); - service.mRoot.forAllWallpaperWindows(wallpaperWindow -> { - if (!wallpaperWindow.getDisplayContent().mWallpaperController.isWallpaperVisible()) { - ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "\tNot visible=%s", wallpaperWindow); - return; - } - - ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "\tvisible=%s", wallpaperWindow); + displayContent.forAllWallpaperWindows(wallpaperWindow -> { final WallpaperAnimationAdapter wallpaperAdapter = new WallpaperAnimationAdapter( wallpaperWindow, durationHint, statusBarTransitionDelay, animationCanceledRunnable); diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java index 82140f4d965ce..5d0e34a80f3fb 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java @@ -43,6 +43,7 @@ import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.doCallRealMethod; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; @@ -892,6 +893,33 @@ public class AppTransitionControllerTest extends WindowTestsBase { .overridePendingAppTransitionRemote(adapter, false /* sync */); } + @Test + public void testOverrideTaskFragmentAdapter_noOverrideWithWallpaper() { + final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run); + final RemoteAnimationAdapter adapter = new RemoteAnimationAdapter( + new TestRemoteAnimationRunner(), 10, 1); + setupTaskFragmentRemoteAnimation(organizer, adapter); + + // Create a TaskFragment with embedded activity. + final TaskFragment taskFragment = createTaskFragmentWithEmbeddedActivity( + createTask(mDisplayContent), organizer); + final ActivityRecord activity = taskFragment.getTopMostActivity(); + activity.allDrawn = true; + // Set wallpaper as visible. + final WallpaperWindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm, + mock(IBinder.class), true, mDisplayContent, true /* ownerCanManageAppTokens */); + spyOn(mDisplayContent.mWallpaperController); + doReturn(true).when(mDisplayContent.mWallpaperController).isWallpaperVisible(); + spyOn(mDisplayContent.mAppTransition); + + // Prepare a transition. + prepareAndTriggerAppTransition(activity, null /* closingActivity */, taskFragment); + + // Should not be overridden when there is wallpaper in the transition. + verify(mDisplayContent.mAppTransition, never()) + .overridePendingAppTransitionRemote(adapter, false /* sync */); + } + @Test public void testTransitionGoodToGoForTaskFragments() { final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);