Fix animation glitch with overlapping orientation changes.
Imagine the following scenario: 1. We want to begin a new app transition to an app which will change the orientation. 2. A rotation animation from a previous rotation change is in progress. 3. Windows have finished drawing the first orientation change, so the display is already unfrozen. In this case, we won't have a chance to select the new orientation which our pending transition requires, because updateRotationUncheckedLocked will bail due to the existing animation being in progress. This causes the app behind to be revealed in the incorrect orientation (sometimes creating landscape launchers) and the transition to be interrupted halfway by the screenshot. In this case we can just defer the app transition until the rotation animation has had a chance to complete. Bug: 31098404 Change-Id: I1ae1041d3018d5681b46cd39c2d582861f0b014e
This commit is contained in:
@@ -3859,6 +3859,19 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
// If this is true we have updated our desired orientation, but not yet
|
||||
// changed the real orientation our applied our screen rotation animation.
|
||||
// For example, because a previous screen rotation was in progress.
|
||||
boolean rotationNeedsUpdateLocked() {
|
||||
int rotation = mPolicy.rotationForOrientationLw(mLastOrientation, mRotation);
|
||||
boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw(
|
||||
mLastOrientation, rotation);
|
||||
if (mRotation == rotation && mAltOrientation == altOrientation) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] setNewConfiguration(Configuration config) {
|
||||
if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
|
||||
|
||||
@@ -1353,8 +1353,25 @@ class WindowSurfacePlacer {
|
||||
"Checking " + appsCount + " opening apps (frozen="
|
||||
+ mService.mDisplayFrozen + " timeout="
|
||||
+ mService.mAppTransition.isTimeout() + ")...");
|
||||
final ScreenRotationAnimation screenRotationAnimation =
|
||||
mService.mAnimator.getScreenRotationAnimationLocked(
|
||||
Display.DEFAULT_DISPLAY);
|
||||
|
||||
int reason = APP_TRANSITION_TIMEOUT;
|
||||
if (!mService.mAppTransition.isTimeout()) {
|
||||
// Imagine the case where we are changing orientation due to an app transition, but a previous
|
||||
// orientation change is still in progress. We won't process the orientation change
|
||||
// for our transition because we need to wait for the rotation animation to finish.
|
||||
// If we start the app transition at this point, we will interrupt it halfway with a new rotation
|
||||
// animation after the old one finally finishes. It's better to defer the
|
||||
// app transition.
|
||||
if (screenRotationAnimation != null && screenRotationAnimation.isAnimating() &&
|
||||
mService.rotationNeedsUpdateLocked()) {
|
||||
if (DEBUG_APP_TRANSITIONS) {
|
||||
Slog.v(TAG, "Delaying app transition for screen rotation animation to finish");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < appsCount; i++) {
|
||||
AppWindowToken wtoken = mService.mOpeningApps.valueAt(i);
|
||||
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
|
||||
|
||||
Reference in New Issue
Block a user