Loading services/core/java/com/android/server/wm/DisplayContent.java +19 −2 Original line number Diff line number Diff line Loading @@ -5405,6 +5405,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp */ private ActivityRecord mAnimatingRecents; /** Whether {@link #mAnimatingRecents} is going to be the top activity. */ private boolean mRecentsWillBeTop; /** * If the recents activity has a fixed orientation which is different from the current top * activity, it will be rotated before being shown so we avoid a screen rotation animation Loading @@ -5430,10 +5433,12 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp * If {@link #mAnimatingRecents} still has fixed rotation, it should be moved to top so we * don't clear {@link #mFixedRotationLaunchingApp} that will be handled by transition. */ void onFinishRecentsAnimation(boolean moveRecentsToBack) { void onFinishRecentsAnimation() { final ActivityRecord animatingRecents = mAnimatingRecents; final boolean recentsWillBeTop = mRecentsWillBeTop; mAnimatingRecents = null; if (!moveRecentsToBack) { mRecentsWillBeTop = false; if (recentsWillBeTop) { // The recents activity will be the top, such as staying at recents list or // returning to home (if home and recents are the same activity). return; Loading @@ -5456,6 +5461,10 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } } void notifyRecentsWillBeTop() { mRecentsWillBeTop = true; } /** * Return {@code true} if there is an ongoing animation to the "Recents" activity and this * activity as a fixed orientation so shouldn't be rotated. Loading @@ -5476,6 +5485,14 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp if (r == null || r == mAnimatingRecents) { return; } if (mAnimatingRecents != null && mRecentsWillBeTop) { // The activity is not the recents and it should be moved to back later, so it is // better to keep its current appearance for the next transition. Otherwise the // display orientation may be updated too early and the layout procedures at the // end of finishing recents animation is skipped. That causes flickering because // the surface of closing app hasn't updated to invisible. return; } if (mFixedRotationLaunchingApp == null) { // In most cases this is a no-op if the activity doesn't have fixed rotation. // Otherwise it could be from finishing recents animation while the display has Loading services/core/java/com/android/server/wm/RecentsAnimationController.java +6 −2 Original line number Diff line number Diff line Loading @@ -702,6 +702,11 @@ public class RecentsAnimationController implements DeathRecipient { "cleanupAnimation(): Notify animation finished mPendingAnimations=%d " + "reorderMode=%d", mPendingAnimations.size(), reorderMode); if (reorderMode != REORDER_MOVE_TO_ORIGINAL_POSITION) { // Notify the state at the beginning because the removeAnimation may notify the // transition is finished. This is a signal that there will be a next transition. mDisplayContent.mFixedRotationTransitionListener.notifyRecentsWillBeTop(); } for (int i = mPendingAnimations.size() - 1; i >= 0; i--) { final TaskAnimationAdapter taskAdapter = mPendingAnimations.get(i); if (reorderMode == REORDER_MOVE_TO_TOP || reorderMode == REORDER_KEEP_IN_PLACE) { Loading Loading @@ -742,8 +747,7 @@ public class RecentsAnimationController implements DeathRecipient { mTargetActivityRecord.token); } } mDisplayContent.mFixedRotationTransitionListener.onFinishRecentsAnimation( reorderMode == REORDER_MOVE_TO_ORIGINAL_POSITION /* moveRecentsToBack */); mDisplayContent.mFixedRotationTransitionListener.onFinishRecentsAnimation(); // Notify that the animation has ended if (mStatusBar != null) { Loading services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +1 −1 Original line number Diff line number Diff line Loading @@ -1354,7 +1354,7 @@ public class DisplayContentTests extends WindowTestsBase { assertFalse(displayRotation.updateRotationUnchecked(false)); // Rotation can be updated if the recents animation is finished. mDisplayContent.mFixedRotationTransitionListener.onFinishRecentsAnimation(false); mDisplayContent.mFixedRotationTransitionListener.onFinishRecentsAnimation(); assertTrue(displayRotation.updateRotationUnchecked(false)); // Rotation can be updated if the recents animation is animating but it is not on top, e.g. Loading services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java +27 −3 Original line number Diff line number Diff line Loading @@ -362,13 +362,14 @@ public class RecentsAnimationControllerTest extends WindowTestsBase { assertFalse(homeActivity.hasFixedRotationTransform()); } @Test public void testClearFixedRotationLaunchingAppAfterCleanupAnimation() { unblockDisplayRotation(mDefaultDisplay); private ActivityRecord prepareFixedRotationLaunchingAppWithRecentsAnim() { final ActivityRecord homeActivity = createHomeActivity(); homeActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); final ActivityRecord activity = createActivityRecord(mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD); // Add a window so it can be animated by the recents. final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, activity, "win"); activity.addWindow(win); // Assume an activity is launching to different rotation. mDefaultDisplay.setFixedRotationLaunchingApp(activity, (mDefaultDisplay.getRotation() + 1) % 4); Loading @@ -379,6 +380,14 @@ public class RecentsAnimationControllerTest extends WindowTestsBase { // Before the transition is done, the recents animation is triggered. initializeRecentsAnimationController(mController, homeActivity); assertFalse(homeActivity.hasFixedRotationTransform()); assertTrue(mController.isAnimatingTask(activity.getTask())); return activity; } @Test public void testClearFixedRotationLaunchingAppAfterCleanupAnimation() { final ActivityRecord activity = prepareFixedRotationLaunchingAppWithRecentsAnim(); // Simulate giving up the swipe up gesture to keep the original activity as top. mController.cleanupAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION); Loading @@ -387,6 +396,21 @@ public class RecentsAnimationControllerTest extends WindowTestsBase { assertFalse(mDefaultDisplay.hasTopFixedRotationLaunchingApp()); } @Test public void testKeepFixedRotationWhenMovingRecentsToTop() { final ActivityRecord activity = prepareFixedRotationLaunchingAppWithRecentsAnim(); // Assume a transition animation has started running before recents animation. Then the // activity will receive onAnimationFinished that notifies app transition finished when // removing the recents animation of task. activity.getTask().getAnimationSources().add(activity); // Simulate swiping to home/recents before the transition is done. mController.cleanupAnimation(REORDER_MOVE_TO_TOP); // The rotation transform should be preserved. In real case, it will be cleared by the next // move-to-top transition. assertTrue(activity.hasFixedRotationTransform()); } @Test public void testWallpaperHasFixedRotationApplied() { unblockDisplayRotation(mDefaultDisplay); Loading Loading
services/core/java/com/android/server/wm/DisplayContent.java +19 −2 Original line number Diff line number Diff line Loading @@ -5405,6 +5405,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp */ private ActivityRecord mAnimatingRecents; /** Whether {@link #mAnimatingRecents} is going to be the top activity. */ private boolean mRecentsWillBeTop; /** * If the recents activity has a fixed orientation which is different from the current top * activity, it will be rotated before being shown so we avoid a screen rotation animation Loading @@ -5430,10 +5433,12 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp * If {@link #mAnimatingRecents} still has fixed rotation, it should be moved to top so we * don't clear {@link #mFixedRotationLaunchingApp} that will be handled by transition. */ void onFinishRecentsAnimation(boolean moveRecentsToBack) { void onFinishRecentsAnimation() { final ActivityRecord animatingRecents = mAnimatingRecents; final boolean recentsWillBeTop = mRecentsWillBeTop; mAnimatingRecents = null; if (!moveRecentsToBack) { mRecentsWillBeTop = false; if (recentsWillBeTop) { // The recents activity will be the top, such as staying at recents list or // returning to home (if home and recents are the same activity). return; Loading @@ -5456,6 +5461,10 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } } void notifyRecentsWillBeTop() { mRecentsWillBeTop = true; } /** * Return {@code true} if there is an ongoing animation to the "Recents" activity and this * activity as a fixed orientation so shouldn't be rotated. Loading @@ -5476,6 +5485,14 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp if (r == null || r == mAnimatingRecents) { return; } if (mAnimatingRecents != null && mRecentsWillBeTop) { // The activity is not the recents and it should be moved to back later, so it is // better to keep its current appearance for the next transition. Otherwise the // display orientation may be updated too early and the layout procedures at the // end of finishing recents animation is skipped. That causes flickering because // the surface of closing app hasn't updated to invisible. return; } if (mFixedRotationLaunchingApp == null) { // In most cases this is a no-op if the activity doesn't have fixed rotation. // Otherwise it could be from finishing recents animation while the display has Loading
services/core/java/com/android/server/wm/RecentsAnimationController.java +6 −2 Original line number Diff line number Diff line Loading @@ -702,6 +702,11 @@ public class RecentsAnimationController implements DeathRecipient { "cleanupAnimation(): Notify animation finished mPendingAnimations=%d " + "reorderMode=%d", mPendingAnimations.size(), reorderMode); if (reorderMode != REORDER_MOVE_TO_ORIGINAL_POSITION) { // Notify the state at the beginning because the removeAnimation may notify the // transition is finished. This is a signal that there will be a next transition. mDisplayContent.mFixedRotationTransitionListener.notifyRecentsWillBeTop(); } for (int i = mPendingAnimations.size() - 1; i >= 0; i--) { final TaskAnimationAdapter taskAdapter = mPendingAnimations.get(i); if (reorderMode == REORDER_MOVE_TO_TOP || reorderMode == REORDER_KEEP_IN_PLACE) { Loading Loading @@ -742,8 +747,7 @@ public class RecentsAnimationController implements DeathRecipient { mTargetActivityRecord.token); } } mDisplayContent.mFixedRotationTransitionListener.onFinishRecentsAnimation( reorderMode == REORDER_MOVE_TO_ORIGINAL_POSITION /* moveRecentsToBack */); mDisplayContent.mFixedRotationTransitionListener.onFinishRecentsAnimation(); // Notify that the animation has ended if (mStatusBar != null) { Loading
services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +1 −1 Original line number Diff line number Diff line Loading @@ -1354,7 +1354,7 @@ public class DisplayContentTests extends WindowTestsBase { assertFalse(displayRotation.updateRotationUnchecked(false)); // Rotation can be updated if the recents animation is finished. mDisplayContent.mFixedRotationTransitionListener.onFinishRecentsAnimation(false); mDisplayContent.mFixedRotationTransitionListener.onFinishRecentsAnimation(); assertTrue(displayRotation.updateRotationUnchecked(false)); // Rotation can be updated if the recents animation is animating but it is not on top, e.g. Loading
services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java +27 −3 Original line number Diff line number Diff line Loading @@ -362,13 +362,14 @@ public class RecentsAnimationControllerTest extends WindowTestsBase { assertFalse(homeActivity.hasFixedRotationTransform()); } @Test public void testClearFixedRotationLaunchingAppAfterCleanupAnimation() { unblockDisplayRotation(mDefaultDisplay); private ActivityRecord prepareFixedRotationLaunchingAppWithRecentsAnim() { final ActivityRecord homeActivity = createHomeActivity(); homeActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); final ActivityRecord activity = createActivityRecord(mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD); // Add a window so it can be animated by the recents. final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, activity, "win"); activity.addWindow(win); // Assume an activity is launching to different rotation. mDefaultDisplay.setFixedRotationLaunchingApp(activity, (mDefaultDisplay.getRotation() + 1) % 4); Loading @@ -379,6 +380,14 @@ public class RecentsAnimationControllerTest extends WindowTestsBase { // Before the transition is done, the recents animation is triggered. initializeRecentsAnimationController(mController, homeActivity); assertFalse(homeActivity.hasFixedRotationTransform()); assertTrue(mController.isAnimatingTask(activity.getTask())); return activity; } @Test public void testClearFixedRotationLaunchingAppAfterCleanupAnimation() { final ActivityRecord activity = prepareFixedRotationLaunchingAppWithRecentsAnim(); // Simulate giving up the swipe up gesture to keep the original activity as top. mController.cleanupAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION); Loading @@ -387,6 +396,21 @@ public class RecentsAnimationControllerTest extends WindowTestsBase { assertFalse(mDefaultDisplay.hasTopFixedRotationLaunchingApp()); } @Test public void testKeepFixedRotationWhenMovingRecentsToTop() { final ActivityRecord activity = prepareFixedRotationLaunchingAppWithRecentsAnim(); // Assume a transition animation has started running before recents animation. Then the // activity will receive onAnimationFinished that notifies app transition finished when // removing the recents animation of task. activity.getTask().getAnimationSources().add(activity); // Simulate swiping to home/recents before the transition is done. mController.cleanupAnimation(REORDER_MOVE_TO_TOP); // The rotation transform should be preserved. In real case, it will be cleared by the next // move-to-top transition. assertTrue(activity.hasFixedRotationTransform()); } @Test public void testWallpaperHasFixedRotationApplied() { unblockDisplayRotation(mDefaultDisplay); Loading