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

Commit ba183358 authored by Vishnu Nair's avatar Vishnu Nair
Browse files

WM: Track waitForConfig per display

If a virtual display is present while the screen is rotated, reconfiguring the virtual display
will set the global mWaitingForConfig flag and can prevent window relayouts and
surface placements for windows on the primary display. This will cause windows to be
drawn incorrectly in the old rotation and get stuck in this state until there is another rotation.

Bug: b/117770934
Test: go/wm-smoke
Test: Test rotation with huddle presenting
Change-Id: I14034a8e8aac857b46702c0108e07adcb4eb8ac5
parent 9d03c64c
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -352,6 +352,14 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
    int pendingLayoutChanges;
    int mDeferredRotationPauseCount;

    /**
     * Used to gate application window layout until we have sent the complete configuration.
     * TODO: There are still scenarios where we may be out of sync with the client. Ideally
     *       we want to replace this flag with a mechanism that will confirm the configuration
     *       applied by the client is the one expected by the system server.
     */
    boolean mWaitingForConfig;

    // TODO(multi-display): remove some of the usages.
    @VisibleForTesting
    boolean isDefaultDisplay;
@@ -1284,7 +1292,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
                + (oldAltOrientation ? " (alt)" : "") + ", lastOrientation=" + lastOrientation);

        if (DisplayContent.deltaRotation(rotation, oldRotation) != 2) {
            mService.mWaitingForConfig = true;
            mWaitingForConfig = true;
        }

        mRotation = rotation;
@@ -3675,6 +3683,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
            }
            mTmpWindow = w;
            w.setDisplayLayoutNeeded();
            w.finishSeamlessRotation(true /* timeout */);
            mService.markForSeamlessRotation(w, false);
        }, true /* traverseTopToBottom */);

+5 −2
Original line number Diff line number Diff line
@@ -89,13 +89,16 @@ public class SeamlessRotator {
     * Removing the transform and the result of the {@link WindowState} layout are both tied to the
     * {@link WindowState} next frame, such that they apply at the same time the client draws the
     * window in the new orientation.
     *
     * In the case of a rotation timeout, we want to remove the transform immediately and not defer
     * it.
     */
    public void finish(WindowState win) {
    public void finish(WindowState win, boolean timeout) {
        mTransform.reset();
        final Transaction t = win.getPendingTransaction();
        t.setMatrix(win.mSurfaceControl, mTransform, mFloat9);
        t.setPosition(win.mSurfaceControl, win.mLastSurfacePosition.x, win.mLastSurfacePosition.y);
        if (win.mWinAnimator.mSurfaceController != null) {
        if (win.mWinAnimator.mSurfaceController != null && !timeout) {
            t.deferTransactionUntil(win.mSurfaceControl,
                    win.mWinAnimator.mSurfaceController.getHandle(), win.getFrameNumber());
            t.deferTransactionUntil(win.mWinAnimator.mSurfaceController.mSurfaceControl,
+24 −22
Original line number Diff line number Diff line
@@ -599,7 +599,6 @@ public class WindowManagerService extends IWindowManager.Stub
    long mDisplayFreezeTime = 0;
    int mLastDisplayFreezeDuration = 0;
    Object mLastFinishedFreezeSource = null;
    boolean mWaitingForConfig = false;
    boolean mSwitchingUser = false;

    final static int WINDOWS_FREEZING_SCREENS_NONE = 0;
@@ -1870,7 +1869,7 @@ public class WindowManagerService extends IWindowManager.Stub
        long origId = Binder.clearCallingIdentity();
        final int displayId;
        synchronized (mGlobalLock) {
            WindowState win = windowForClientLocked(session, client, false);
            final WindowState win = windowForClientLocked(session, client, false);
            if (win == null) {
                return 0;
            }
@@ -1885,8 +1884,9 @@ public class WindowManagerService extends IWindowManager.Stub

            win.setFrameNumber(frameNumber);

            if (!mWaitingForConfig) {
                win.finishSeamlessRotation();
            final DisplayContent dc = win.getDisplayContent();
            if (!dc.mWaitingForConfig) {
                win.finishSeamlessRotation(false /* timeout */);
            }

            int attrChanges = 0;
@@ -2438,7 +2438,7 @@ public class WindowManagerService extends IWindowManager.Stub
            final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
            displayContent.computeScreenConfiguration(mTempConfiguration);
            if (currentConfig.diff(mTempConfiguration) != 0) {
                mWaitingForConfig = true;
                displayContent.mWaitingForConfig = true;
                displayContent.setLayoutNeeded();
                int anim[] = new int[2];
                displayContent.getDisplayPolicy().selectRotationAnimationLw(anim);
@@ -2451,9 +2451,10 @@ public class WindowManagerService extends IWindowManager.Stub
        return config;
    }

    void setNewDisplayOverrideConfiguration(Configuration overrideConfig, DisplayContent dc) {
        if (mWaitingForConfig) {
            mWaitingForConfig = false;
    void setNewDisplayOverrideConfiguration(Configuration overrideConfig,
            @NonNull DisplayContent dc) {
        if (dc.mWaitingForConfig) {
            dc.mWaitingForConfig = false;
            mLastFinishedFreezeSource = "new-config";
        }

@@ -4181,13 +4182,11 @@ public class WindowManagerService extends IWindowManager.Stub
                // placement to unfreeze the display since we froze it when the rotation was updated
                // in DisplayContent#updateRotationUnchecked.
                synchronized (mGlobalLock) {
                    if (mWaitingForConfig) {
                        mWaitingForConfig = false;
                        mLastFinishedFreezeSource = "config-unchanged";
                    final DisplayContent dc = mRoot.getDisplayContent(displayId);
                        if (dc != null) {
                    if (dc != null && dc.mWaitingForConfig) {
                        dc.mWaitingForConfig = false;
                        mLastFinishedFreezeSource = "config-unchanged";
                        dc.setLayoutNeeded();
                        }
                        mWindowPlacerLocked.performSurfacePlacement();
                    }
                }
@@ -5136,7 +5135,7 @@ public class WindowManagerService extends IWindowManager.Stub
        configChanged |= currentDisplayConfig.diff(mTempConfiguration) != 0;

        if (configChanged) {
            mWaitingForConfig = true;
            displayContent.mWaitingForConfig = true;
            startFreezingDisplayLocked(0 /* exitAnim */,
                    0 /* enterAnim */, displayContent);
            displayContent.sendNewConfiguration();
@@ -5396,23 +5395,24 @@ public class WindowManagerService extends IWindowManager.Stub
            return;
        }

        final DisplayContent dc = mRoot.getDisplayContent(mFrozenDisplayId);
        if (mWaitingForConfig || mAppsFreezingScreen > 0
        final DisplayContent displayContent = mRoot.getDisplayContent(mFrozenDisplayId);
        final boolean waitingForConfig = displayContent != null && displayContent.mWaitingForConfig;
        final int numOpeningApps = displayContent != null ? displayContent.mOpeningApps.size() : 0;
        if (waitingForConfig || mAppsFreezingScreen > 0
                || mWindowsFreezingScreen == WINDOWS_FREEZING_SCREENS_ACTIVE
                || mClientFreezingScreen || (dc != null && !dc.mOpeningApps.isEmpty())) {
                || mClientFreezingScreen || numOpeningApps > 0) {
            if (DEBUG_ORIENTATION) Slog.d(TAG_WM,
                "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig
                "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + waitingForConfig
                + ", mAppsFreezingScreen=" + mAppsFreezingScreen
                + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen
                + ", mClientFreezingScreen=" + mClientFreezingScreen
                + ", mOpeningApps.size()=" + (dc != null ? dc.mOpeningApps.size() : 0));
                + ", mOpeningApps.size()=" + numOpeningApps);
            return;
        }

        if (DEBUG_ORIENTATION) Slog.d(TAG_WM,
                "stopFreezingDisplayLocked: Unfreezing now");

        final DisplayContent displayContent = mRoot.getDisplayContent(mFrozenDisplayId);

        // We must make a local copy of the displayId as it can be potentially overwritten later on
        // in this method. For example, {@link startFreezingDisplayLocked} may be called as a result
@@ -6033,7 +6033,6 @@ public class WindowManagerService extends IWindowManager.Stub
                    pw.print(" windows="); pw.print(mWindowsFreezingScreen);
                    pw.print(" client="); pw.print(mClientFreezingScreen);
                    pw.print(" apps="); pw.print(mAppsFreezingScreen);
                    pw.print(" waitingForConfig="); pw.println(mWaitingForConfig);
            final DisplayContent defaultDisplayContent = getDefaultDisplayContentLocked();
            pw.print("  mRotation="); pw.print(defaultDisplayContent.getRotation());
                    pw.print(" mAltOrientation=");
@@ -6042,6 +6041,9 @@ public class WindowManagerService extends IWindowManager.Stub
                    pw.print(defaultDisplayContent.getLastWindowForcedOrientation());
                    pw.print(" mLastOrientation=");
                            pw.println(defaultDisplayContent.getLastOrientation());
                    pw.print(" waitingForConfig=");
                            pw.println(defaultDisplayContent.mWaitingForConfig);

            pw.print("  Animation settings: disabled="); pw.print(mAnimationsDisabled);
                    pw.print(" window="); pw.print(mWindowAnimationScaleSetting);
                    pw.print(" transition="); pw.print(mTransitionAnimationScaleSetting);
+5 −4
Original line number Diff line number Diff line
@@ -180,6 +180,7 @@ import android.view.InputChannel;
import android.view.InputEvent;
import android.view.InputEventReceiver;
import android.view.InputWindowHandle;
import android.view.Surface.Rotation;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
import android.view.View;
@@ -579,8 +580,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP

    private static final float DEFAULT_DIM_AMOUNT_DEAD_WINDOW = 0.5f;

    void seamlesslyRotateIfAllowed(Transaction transaction, int oldRotation, int rotation,
            boolean requested) {
    void seamlesslyRotateIfAllowed(Transaction transaction, @Rotation int oldRotation,
            @Rotation int rotation, boolean requested) {
        // Invisible windows and the wallpaper do not participate in the seamless rotation animation
        if (!isVisibleNow() || mIsWallpaper) {
            return;
@@ -597,9 +598,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
        }
    }

    void finishSeamlessRotation() {
    void finishSeamlessRotation(boolean timeout) {
        if (mPendingSeamlessRotate != null) {
            mPendingSeamlessRotate.finish(this);
            mPendingSeamlessRotate.finish(this, timeout);
            mFinishSeamlessRotateFrameNumber = getFrameNumber();
            mPendingSeamlessRotate = null;
            mService.markForSeamlessRotation(this, false);
+3 −1
Original line number Diff line number Diff line
@@ -113,7 +113,9 @@ class WindowSurfacePlacer {
            return;
        }

        if (mService.mWaitingForConfig) {
        // TODO(multi-display):
        final DisplayContent defaultDisplay = mService.getDefaultDisplayContentLocked();
        if (defaultDisplay.mWaitingForConfig) {
            // Our configuration has changed (most likely rotation), but we
            // don't yet have the complete configuration to report to
            // applications.  Don't do any window layout until we have it.