Merge "Finish fixed rotation after recents moved to top"

This commit is contained in:
Riddle Hsu
2020-07-31 05:32:10 +00:00
committed by Android (Google) Code Review
4 changed files with 53 additions and 8 deletions

View File

@@ -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
@@ -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;
@@ -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.
@@ -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

View File

@@ -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) {
@@ -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) {

View File

@@ -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.

View File

@@ -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);
@@ -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);
@@ -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);