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

Commit 6cdcfe4e authored by Andrii Kulian's avatar Andrii Kulian
Browse files

Force-update the orientation of before sending to client

The changes in this topic focus on cases when we ensure visibility
and config when making some activity visible. Sometimes in WM we
might skip updating orientation because we're waiting for something
(checks marked with !forceUpdate), which results in configuration of
the previously visible activity being applied to the newly visible
one.

Bug: 76011287
Test: ActivityManagerAppConfigurationTests
Change-Id: I16b1de5ea9e38883692a4658f305518facaf98e9
parent f4479eef
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1641,7 +1641,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
        final Configuration config = mWindowManager.updateOrientationFromAppTokens(
                getDisplayOverrideConfiguration(displayId),
                r != null && r.mayFreezeScreenLocked(r.app) ? r.appToken : null,
                displayId);
                displayId, true /* forceUpdate */);
        if (r != null && markFrozenIfConfigChanged && config != null) {
            r.frozenBeforeDestroy = true;
        }
+42 −25
Original line number Diff line number Diff line
@@ -944,10 +944,26 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
    /**
     * Update rotation of the display.
     *
     * Returns true if the rotation has been changed.  In this case YOU MUST CALL
     * @return {@code true} if the rotation has been changed.  In this case YOU MUST CALL
     *         {@link WindowManagerService#sendNewConfiguration(int)} TO UNFREEZE THE SCREEN.
     */
    boolean updateRotationUnchecked() {
        return updateRotationUnchecked(false /* forceUpdate */);
    }

    /**
     * Update rotation of the display with an option to force the update.
     * @param forceUpdate Force the rotation update. Sometimes in WM we might skip updating
     *                    orientation because we're waiting for some rotation to finish or display
     *                    to unfreeze, which results in configuration of the previously visible
     *                    activity being applied to a newly visible one. Forcing the rotation
     *                    update allows to workaround this issue.
     * @return {@code true} if the rotation has been changed.  In this case YOU MUST CALL
     *         {@link WindowManagerService#sendNewConfiguration(int)} TO UNFREEZE THE SCREEN.
     */
    boolean updateRotationUnchecked(boolean forceUpdate) {
        ScreenRotationAnimation screenRotationAnimation;
        if (!forceUpdate) {
            if (mService.mDeferredRotationPauseCount > 0) {
                // Rotation updates have been paused temporarily.  Defer the update until
                // updates have been resumed.
@@ -955,7 +971,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
                return false;
            }

        ScreenRotationAnimation screenRotationAnimation =
            screenRotationAnimation =
                    mService.mAnimator.getScreenRotationAnimationLocked(mDisplayId);
            if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
                // Rotation updates cannot be performed while the previous rotation change
@@ -972,6 +988,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
                        "Deferring rotation, still finishing previous rotation");
                return false;
            }
        }

        if (!mService.mDisplayEnabled) {
            // No point choosing a rotation if the display is not enabled.
@@ -992,7 +1009,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo

        if (mayRotateSeamlessly) {
            final WindowState seamlessRotated = getWindow((w) -> w.mSeamlesslyRotated);
            if (seamlessRotated != null) {
            if (seamlessRotated != null && !forceUpdate) {
                // We can't rotate (seamlessly or not) while waiting for the last seamless rotation
                // to complete (that is, waiting for windows to redraw). It's tempting to check
                // w.mSeamlessRotationCount but that could be incorrect in the case of
+15 −9
Original line number Diff line number Diff line
@@ -2372,6 +2372,12 @@ public class WindowManagerService extends IWindowManager.Stub
    @Override
    public Configuration updateOrientationFromAppTokens(Configuration currentConfig,
            IBinder freezeThisOneIfNeeded, int displayId) {
        return updateOrientationFromAppTokens(currentConfig, freezeThisOneIfNeeded, displayId,
                false /* forceUpdate */);
    }

    public Configuration updateOrientationFromAppTokens(Configuration currentConfig,
            IBinder freezeThisOneIfNeeded, int displayId, boolean forceUpdate) {
        if (!checkCallingPermission(MANAGE_APP_TOKENS, "updateOrientationFromAppTokens()")) {
            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
        }
@@ -2381,7 +2387,7 @@ public class WindowManagerService extends IWindowManager.Stub
        try {
            synchronized(mWindowMap) {
                config = updateOrientationFromAppTokensLocked(currentConfig, freezeThisOneIfNeeded,
                        displayId);
                        displayId, forceUpdate);
            }
        } finally {
            Binder.restoreCallingIdentity(ident);
@@ -2391,13 +2397,13 @@ public class WindowManagerService extends IWindowManager.Stub
    }

    private Configuration updateOrientationFromAppTokensLocked(Configuration currentConfig,
            IBinder freezeThisOneIfNeeded, int displayId) {
            IBinder freezeThisOneIfNeeded, int displayId, boolean forceUpdate) {
        if (!mDisplayReady) {
            return null;
        }
        Configuration config = null;

        if (updateOrientationFromAppTokensLocked(displayId)) {
        if (updateOrientationFromAppTokensLocked(displayId, forceUpdate)) {
            // If we changed the orientation but mOrientationChangeComplete is already true,
            // we used seamless rotation, and we don't need to freeze the screen.
            if (freezeThisOneIfNeeded != null && !mRoot.mOrientationChangeComplete) {
@@ -2445,11 +2451,15 @@ public class WindowManagerService extends IWindowManager.Stub
     * @see android.view.IWindowManager#updateOrientationFromAppTokens(Configuration, IBinder, int)
     */
    boolean updateOrientationFromAppTokensLocked(int displayId) {
        return updateOrientationFromAppTokensLocked(displayId, false /* forceUpdate */);
    }

    boolean updateOrientationFromAppTokensLocked(int displayId, boolean forceUpdate) {
        long ident = Binder.clearCallingIdentity();
        try {
            final DisplayContent dc = mRoot.getDisplayContent(displayId);
            final int req = dc.getOrientation();
            if (req != dc.getLastOrientation()) {
            if (req != dc.getLastOrientation() || forceUpdate) {
                dc.setLastOrientation(req);
                //send a message to Policy indicating orientation change to take
                //action like disabling/enabling sensors etc.,
@@ -2457,12 +2467,8 @@ public class WindowManagerService extends IWindowManager.Stub
                if (dc.isDefaultDisplay) {
                    mPolicy.setCurrentOrientationLw(req);
                }
                if (dc.updateRotationUnchecked()) {
                    // changed
                    return true;
                }
                return dc.updateRotationUnchecked(forceUpdate);
            }

            return false;
        } finally {
            Binder.restoreCallingIdentity(ident);