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

Commit 1273dc51 authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Prevent timeout of async rotation by invisible windows

This avoids a delay to re-show the bars when an async window
is removed during rotation (e.g. volume panel) since shell
transition disables the usages of setOrientationChanging.

This is also a step to be able to completely remove
get/setOrientationChanging in the future.

Also simplify prepareSurfaceLocked:
 - showRobustly always returns true, so the corresponding
   "else" can be removed.
 - isParentWindowHidden is already checked in isOnScreen.

Bug: 270123439
Test: TransitionTests#testDisplayRotationChange
Change-Id: I53bae0d937d63e4b600aed3a005a3f8c7d5b68b5
parent 7137d916
Loading
Loading
Loading
Loading
+28 −0
Original line number Diff line number Diff line
@@ -217,6 +217,34 @@ class AsyncRotationController extends FadeAnimationController implements Consume
        if (DEBUG) Slog.d(TAG, "Requested to sync draw transaction");
    }

    /**
     * If an async window is not requested to redraw or its surface is removed, then complete its
     * operation directly to avoid waiting until timeout.
     */
    void updateTargetWindows() {
        if (mTransitionOp == OP_LEGACY || !mIsStartTransactionCommitted) return;
        for (int i = mTargetWindowTokens.size() - 1; i >= 0; i--) {
            final Operation op = mTargetWindowTokens.valueAt(i);
            if (op.mIsCompletionPending || op.mAction == Operation.ACTION_SEAMLESS) {
                // Skip completed target. And seamless windows use the signal from blast sync.
                continue;
            }
            final WindowToken token = mTargetWindowTokens.keyAt(i);
            int readyCount = 0;
            final int childCount = token.getChildCount();
            for (int j = childCount - 1; j >= 0; j--) {
                final WindowState w = token.getChildAt(j);
                // If the token no longer contains pending drawn windows, then it is ready.
                if (w.isDrawn() || !w.mWinAnimator.getShown()) {
                    readyCount++;
                }
            }
            if (readyCount == childCount) {
                mDisplayContent.finishAsyncRotation(token);
            }
        }
    }

    /** Lets the window fit in new rotation naturally. */
    private void finishOp(WindowToken windowToken) {
        final Operation op = mTargetWindowTokens.remove(windowToken);
+3 −0
Original line number Diff line number Diff line
@@ -4761,6 +4761,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp

    void updateWindowsForAnimator() {
        forAllWindows(mUpdateWindowsForAnimator, true /* traverseTopToBottom */);
        if (mAsyncRotationController != null) {
            mAsyncRotationController.updateTargetWindows();
        }
    }

    boolean isInputMethodClientFocus(int uid, int pid) {
+14 −38
Original line number Diff line number Diff line
@@ -32,7 +32,6 @@ import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION;
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
@@ -424,7 +423,7 @@ class WindowStateAnimator {

        computeShownFrameLocked();

        if (w.isParentWindowHidden() || !w.isOnScreen()) {
        if (!w.isOnScreen()) {
            hide(t, "prepareSurfaceLocked");
            mWallpaperControllerLocked.hideWallpapers(w);

@@ -449,7 +448,7 @@ class WindowStateAnimator {

            if (prepared && mDrawState == HAS_DRAWN) {
                if (mLastHidden) {
                    if (showSurfaceRobustlyLocked(t)) {
                    mSurfaceController.showRobustly(t);
                    mAnimator.requestRemovalOfReplacedWindows(w);
                    mLastHidden = false;
                    final DisplayContent displayContent = w.getDisplayContent();
@@ -464,16 +463,9 @@ class WindowStateAnimator {
                                    displayContent.pendingLayoutChanges);
                        }
                    }
                    } else {
                        w.setOrientationChanging(false);
                }
            }
        }
        } else {
            if (mWin.isAnimating(TRANSITION | PARENTS)) {
                ProtoLog.v(WM_DEBUG_ANIM, "prepareSurface: No changes in animation for %s", this);
            }
        }

        if (w.getOrientationChanging()) {
            if (!w.isDrawn()) {
@@ -511,22 +503,6 @@ class WindowStateAnimator {
        mSurfaceController.setColorSpaceAgnostic(mWin.getPendingTransaction(), agnostic);
    }

    /**
     * Have the surface flinger show a surface, robustly dealing with
     * error conditions.  In particular, if there is not enough memory
     * to show the surface, then we will try to get rid of other surfaces
     * in order to succeed.
     *
     * @return Returns true if the surface was successfully shown.
     */
    private boolean showSurfaceRobustlyLocked(SurfaceControl.Transaction t) {
        boolean shown = mSurfaceController.showRobustly(t);
        if (!shown)
            return false;

        return true;
    }

    void applyEnterAnimationLocked() {
        // If we are the new part of a window replacement transition and we have requested
        // not to animate, we instead want to make it seamless, so we don't want to apply
+2 −3
Original line number Diff line number Diff line
@@ -245,13 +245,13 @@ class WindowSurfaceController {
        t.setColorSpaceAgnostic(mSurfaceControl, agnostic);
    }

    boolean showRobustly(SurfaceControl.Transaction t) {
    void showRobustly(SurfaceControl.Transaction t) {
        ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE SHOW (performLayout): %s", title);
        if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + this
                + " during relayout");

        if (mSurfaceShown) {
            return true;
            return;
        }

        setShown(true);
@@ -262,7 +262,6 @@ class WindowSurfaceController {
                    dc.mDisplayId, 1 /* request shown */,
                    String.valueOf(dc.mWallpaperController.getWallpaperTarget()));
        }
        return true;
    }

    boolean clearWindowContentFrameStats() {
+6 −1
Original line number Diff line number Diff line
@@ -1018,6 +1018,10 @@ public class TransitionTests extends WindowTestsBase {

    @Test
    public void testDisplayRotationChange() {
        final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy();
        spyOn(displayPolicy);
        // Simulate gesture navigation (non-movable) so it is not seamless.
        doReturn(false).when(displayPolicy).navigationBarCanMove();
        final Task task = createActivityRecord(mDisplayContent).getTask();
        final WindowState statusBar = createWindow(null, TYPE_STATUS_BAR, "statusBar");
        final WindowState navBar = createWindow(null, TYPE_NAVIGATION_BAR, "navBar");
@@ -1072,7 +1076,8 @@ public class TransitionTests extends WindowTestsBase {

        // Navigation bar finishes drawing after the start transaction, so its fade-in animation
        // can execute directly.
        asyncRotationController.handleFinishDrawing(navBar, mMockT);
        navBar.mWinAnimator.mDrawState = WindowStateAnimator.HAS_DRAWN;
        asyncRotationController.updateTargetWindows();
        assertFalse(asyncRotationController.isTargetToken(navBar.mToken));
        assertNull(mDisplayContent.getAsyncRotationController());
    }