Do not force seamless rotation with animating rotated recents
The animating recents activity (e.g. home) is set as fixed-rotation- launching-app to reduce extra enable/disable transform because it may be the real top activity later (e.g. swipe to home or enter overview). The actual state is only known when finishing the recents animation. So during animating, it is not really the top activity that will change the rotation of display. If auto-rotate is disabled, there will have a rotation button when device is rotated. And if the device is using gesture navigation, the touch region of button may overlap with the navigation bar. Then when pressing the button while device is in landscape, the recents activity may also be triggered with fixed rotation in portrait, that causes the rotation type is forced to be seamless. But the actual foreground app is not rotated and does not declare to use seamless, therefore the screen looks flickering by updating configuration directly. Fixes: 157208761 Test: DisplayContentTests#testRotateSeamlesslyWithFixedRotation Change-Id: If512ad14420ed7956fe888a0ce9f5d5006eb43a8
This commit is contained in:
@@ -1485,8 +1485,16 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable ActivityRecord getFixedRotationLaunchingApp() {
|
||||
return mFixedRotationLaunchingApp;
|
||||
/** Returns {@code true} if the top activity is transformed with the new rotation of display. */
|
||||
boolean hasTopFixedRotationLaunchingApp() {
|
||||
return mFixedRotationLaunchingApp != null
|
||||
// Ignore animating recents because it hasn't really become the top.
|
||||
&& mFixedRotationLaunchingApp != mFixedRotationTransitionListener.mAnimatingRecents;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
boolean isFixedRotationLaunchingApp(ActivityRecord r) {
|
||||
return mFixedRotationLaunchingApp == r;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
|
||||
@@ -582,7 +582,7 @@ public class DisplayRotation {
|
||||
boolean shouldRotateSeamlessly(int oldRotation, int newRotation, boolean forceUpdate) {
|
||||
// Display doesn't need to be frozen because application has been started in correct
|
||||
// rotation already, so the rest of the windows can use seamless rotation.
|
||||
if (mDisplayContent.getFixedRotationLaunchingApp() != null) {
|
||||
if (mDisplayContent.hasTopFixedRotationLaunchingApp()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1412,7 +1412,7 @@ public class ActivityRecordTests extends ActivityTestsBase {
|
||||
|
||||
// The launching rotated app should not be cleared when waiting for remote rotation.
|
||||
display.continueUpdateOrientationForDiffOrienLaunchingApp();
|
||||
assertNotNull(display.getFixedRotationLaunchingApp());
|
||||
assertTrue(display.isFixedRotationLaunchingApp(mActivity));
|
||||
|
||||
// Simulate the rotation has been updated to previous one, e.g. sensor updates before the
|
||||
// remote rotation is completed.
|
||||
@@ -1441,7 +1441,7 @@ public class ActivityRecordTests extends ActivityTestsBase {
|
||||
display.setFixedRotationLaunchingAppUnchecked(mActivity);
|
||||
display.sendNewConfiguration();
|
||||
|
||||
assertNull(display.getFixedRotationLaunchingApp());
|
||||
assertFalse(display.hasTopFixedRotationLaunchingApp());
|
||||
assertFalse(mActivity.hasFixedRotationTransform());
|
||||
}
|
||||
|
||||
@@ -1497,7 +1497,7 @@ public class ActivityRecordTests extends ActivityTestsBase {
|
||||
// rotation should be applied when creating snapshot surface if the display rotation may be
|
||||
// changed according to the activity orientation.
|
||||
assertTrue(mActivity.hasFixedRotationTransform());
|
||||
assertEquals(mActivity, mActivity.mDisplayContent.getFixedRotationLaunchingApp());
|
||||
assertTrue(mActivity.mDisplayContent.isFixedRotationLaunchingApp(mActivity));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1147,6 +1147,24 @@ public class DisplayContentTests extends WindowTestsBase {
|
||||
assertNull(mDisplayContent.getFixedRotationAnimationController());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRotateSeamlesslyWithFixedRotation() {
|
||||
final DisplayRotation displayRotation = mDisplayContent.getDisplayRotation();
|
||||
final ActivityRecord app = mAppWindow.mActivityRecord;
|
||||
mDisplayContent.setFixedRotationLaunchingAppUnchecked(app);
|
||||
mAppWindow.mAttrs.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE;
|
||||
|
||||
// Use seamless rotation if the top app is rotated.
|
||||
assertTrue(displayRotation.shouldRotateSeamlessly(ROTATION_0 /* oldRotation */,
|
||||
ROTATION_90 /* newRotation */, false /* forceUpdate */));
|
||||
|
||||
mDisplayContent.mFixedRotationTransitionListener.onStartRecentsAnimation(app);
|
||||
|
||||
// Use normal rotation because animating recents is an intermediate state.
|
||||
assertFalse(displayRotation.shouldRotateSeamlessly(ROTATION_0 /* oldRotation */,
|
||||
ROTATION_90 /* newRotation */, false /* forceUpdate */));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoteRotation() {
|
||||
DisplayContent dc = createNewDisplay();
|
||||
|
||||
@@ -343,7 +343,7 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
|
||||
|
||||
initializeRecentsAnimationController(mController, homeActivity);
|
||||
|
||||
assertEquals(homeActivity, mDefaultDisplay.getFixedRotationLaunchingApp());
|
||||
assertTrue(mDefaultDisplay.isFixedRotationLaunchingApp(homeActivity));
|
||||
|
||||
// Check that the home app is in portrait
|
||||
assertEquals(Configuration.ORIENTATION_PORTRAIT,
|
||||
@@ -353,7 +353,7 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
|
||||
// top rotated record should be cleared.
|
||||
mController.cleanupAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION);
|
||||
assertFalse(homeActivity.hasFixedRotationTransform());
|
||||
assertNull(mDefaultDisplay.getFixedRotationLaunchingApp());
|
||||
assertFalse(mDefaultDisplay.hasTopFixedRotationLaunchingApp());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -367,7 +367,7 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
|
||||
(mDefaultDisplay.getRotation() + 1) % 4);
|
||||
|
||||
assertTrue(activity.hasFixedRotationTransform());
|
||||
assertEquals(activity, mDefaultDisplay.getFixedRotationLaunchingApp());
|
||||
assertTrue(mDefaultDisplay.isFixedRotationLaunchingApp(activity));
|
||||
|
||||
// Before the transition is done, the recents animation is triggered.
|
||||
initializeRecentsAnimationController(mController, homeActivity);
|
||||
@@ -377,7 +377,7 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
|
||||
mController.cleanupAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION);
|
||||
// The rotation transform should be cleared after updating orientation with display.
|
||||
assertFalse(activity.hasFixedRotationTransform());
|
||||
assertNull(mDefaultDisplay.getFixedRotationLaunchingApp());
|
||||
assertFalse(mDefaultDisplay.hasTopFixedRotationLaunchingApp());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -436,7 +436,7 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
|
||||
// The transform state should keep because we expect to listen the signal from the
|
||||
// transition executed by moving the task to front.
|
||||
assertTrue(homeActivity.hasFixedRotationTransform());
|
||||
assertEquals(homeActivity, mDefaultDisplay.getFixedRotationLaunchingApp());
|
||||
assertTrue(mDefaultDisplay.isFixedRotationLaunchingApp(homeActivity));
|
||||
|
||||
mDefaultDisplay.mFixedRotationTransitionListener.onAppTransitionFinishedLocked(
|
||||
homeActivity.token);
|
||||
|
||||
Reference in New Issue
Block a user