From fc246d16466053eac5ef83ca310f40265843ef9c Mon Sep 17 00:00:00 2001 From: Riddle Hsu Date: Fri, 20 Mar 2020 18:28:11 +0800 Subject: [PATCH] Cancel animation in previous rotation The local animations are cancelled if fixed rotation transform is going to be finished to perform seamless display rotation. That avoids a case: a closing animation in landscape moved outside the bottom of the screen, and it still has unfinished alpha animation (e.g. wallpaper_open_exit is 250+167=417ms which is longer than than wallpaper_open_enter 225ms). Then if the display is rotated to portrait, the animation out of view becomes visible. The reason not waiting for all animations to finish is that will increase the latency to rotate display, and touching won't work in the waiting state because the rotation of top activity (rotated surface) is different than the display. Bug: 151709552 Test: atest DisplayContentTests#testApplyTopFixedRotationTransform Test: Enable fixed_rotation_transform, return from a task in different orientation to home with default animation. Change-Id: I7c268de1f9061a7ac11fc42a70f02000faba7106 --- .../com/android/server/wm/DisplayContent.java | 39 +++++++++++++++---- .../server/wm/DisplayContentTests.java | 10 +++++ 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 4a7edee7beac6..4ccc07efba8e0 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -5176,14 +5176,7 @@ class DisplayContent extends WindowContainer applyRotation(currRotation, overrideRotation)); - // Clear the record because the display will sync to current rotation. - mFixedRotationLaunchingApp = null; - } else { - applyRotation(currRotation, overrideRotation); - } + applyRotationAndClearFixedRotation(currRotation, overrideRotation); } mCurrentOverrideConfigurationChanges = currOverrideConfig.diff(overrideConfiguration); super.onRequestedOverrideConfigurationChanged(overrideConfiguration); @@ -5193,6 +5186,36 @@ class DisplayContent extends WindowContainer { + if (a.nowVisible && a != mFixedRotationLaunchingApp + && a.getWindowConfiguration().getRotation() != newRotation) { + final WindowContainer w = a.getAnimatingContainer(); + if (w != null) { + w.cancelAnimation(); + } + } + }); + + mFixedRotationLaunchingApp.clearFixedRotationTransform( + () -> applyRotation(oldRotation, newRotation)); + mFixedRotationLaunchingApp = null; + } + /** Checks whether the given activity is in size compatibility mode and notifies the change. */ void handleActivitySizeCompatModeIfNeeded(ActivityRecord r) { if (!r.isState(RESUMED) || r.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) { diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index 5b96c4372abca..c1b5be2ef0392 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -56,6 +56,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.same; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.times; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; +import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION; import static com.android.server.wm.WindowContainer.POSITION_TOP; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL; @@ -1006,6 +1007,13 @@ public class DisplayContentTests extends WindowTestsBase { mDisplayContent.computeScreenConfiguration(config); mDisplayContent.onRequestedOverrideConfigurationChanged(config); + final ActivityRecord closingApp = new ActivityTestsBase.StackBuilder(mWm.mRoot) + .setDisplay(mDisplayContent).setOnTop(false).build().getTopMostActivity(); + closingApp.nowVisible = true; + closingApp.startAnimation(closingApp.getPendingTransaction(), mock(AnimationAdapter.class), + false /* hidden */, ANIMATION_TYPE_APP_TRANSITION); + assertTrue(closingApp.isAnimating()); + final ActivityRecord app = mAppWindow.mActivityRecord; mDisplayContent.prepareAppTransition(WindowManager.TRANSIT_ACTIVITY_OPEN, false /* alwaysKeepCurrent */); @@ -1033,6 +1041,8 @@ public class DisplayContentTests extends WindowTestsBase { mDisplayContent.mAppTransition.notifyAppTransitionFinishedLocked(app.token); + // The animation in old rotation should be cancelled. + assertFalse(closingApp.isAnimating()); // The display should be rotated after the launch is finished. assertFalse(app.hasFixedRotationTransform()); assertEquals(config90.orientation, mDisplayContent.getConfiguration().orientation);