Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 42769fff authored by Robert Carr's avatar Robert Carr
Browse files

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
parent d031d57c
Loading
Loading
Loading
Loading
+13 −0
Original line number Original line Diff line number Diff line
@@ -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
    @Override
    public int[] setNewConfiguration(Configuration config) {
    public int[] setNewConfiguration(Configuration config) {
        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
+17 −0
Original line number Original line Diff line number Diff line
@@ -1353,8 +1353,25 @@ class WindowSurfacePlacer {
                "Checking " + appsCount + " opening apps (frozen="
                "Checking " + appsCount + " opening apps (frozen="
                        + mService.mDisplayFrozen + " timeout="
                        + mService.mDisplayFrozen + " timeout="
                        + mService.mAppTransition.isTimeout() + ")...");
                        + mService.mAppTransition.isTimeout() + ")...");
        final ScreenRotationAnimation screenRotationAnimation =
            mService.mAnimator.getScreenRotationAnimationLocked(
                    Display.DEFAULT_DISPLAY);

        int reason = APP_TRANSITION_TIMEOUT;
        int reason = APP_TRANSITION_TIMEOUT;
        if (!mService.mAppTransition.isTimeout()) {
        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++) {
            for (int i = 0; i < appsCount; i++) {
                AppWindowToken wtoken = mService.mOpeningApps.valueAt(i);
                AppWindowToken wtoken = mService.mOpeningApps.valueAt(i);
                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,