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

Commit 88f50dbc authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Use blast sync for changing screen resolution

Windows with PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY will be put
on top layer and by default it is excluded from screenshot.
So before the animation starts, their drawn result should not be
shown immediately. In other words, make them sync with the start
of animation.

Also
- Fix typo for scale of resolution change animation.
- Clear blast sync timeout from draw handler because
  Navbar may remove and add again while InsetsSourceProvider
  called applyWithNextDraw for it.

Bug: 273874648
Test: Change screen resolution in settings.
      The cutout won't be flickering.
Change-Id: I5c56ee362fe915e16870b4c15c958e19f0504abe
parent 0674cd7e
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -230,7 +230,7 @@ class ScreenRotationAnimation {
        } else if ((mEndWidth > mStartWidth) == (mEndHeight > mStartHeight)
                && (mEndWidth != mStartWidth || mEndHeight != mStartHeight)) {
            // Display resizes without rotation change.
            final float scale = Math.max((float) mEndWidth / mStartHeight,
            final float scale = Math.max((float) mEndWidth / mStartWidth,
                    (float) mEndHeight / mStartHeight);
            matrix.setScale(scale, scale);
        }
+8 −1
Original line number Diff line number Diff line
@@ -1567,7 +1567,14 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
        if (configChanged) {
            mWaitingForConfig = true;
            if (mTransitionController.isShellTransitionsEnabled()) {
                requestChangeTransitionIfNeeded(changes, null /* displayChange */);
                final TransitionRequestInfo.DisplayChange change =
                        mTransitionController.isCollecting()
                                ? null : new TransitionRequestInfo.DisplayChange(mDisplayId);
                if (change != null) {
                    change.setStartAbsBounds(currentDisplayConfig.windowConfiguration.getBounds());
                    change.setEndAbsBounds(mTmpConfiguration.windowConfiguration.getBounds());
                }
                requestChangeTransitionIfNeeded(changes, change);
            } else if (mLastHasContent) {
                mWmService.startFreezingDisplay(0 /* exitAnim */, 0 /* enterAnim */, this);
            }
+24 −6
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.IApplicationThread;
import android.app.WindowConfiguration;
import android.graphics.Rect;
import android.os.Handler;
import android.os.IBinder;
import android.os.IRemoteCallback;
@@ -465,6 +466,28 @@ class TransitionController {
        return type == TRANSIT_OPEN || type == TRANSIT_CLOSE;
    }

    /** Whether the display change should run with blast sync. */
    private static boolean shouldSync(@NonNull TransitionRequestInfo.DisplayChange displayChange) {
        if ((displayChange.getStartRotation() + displayChange.getEndRotation()) % 2 == 0) {
            // 180 degrees rotation change may not change screen size. So the clients may draw
            // some frames before and after the display projection transaction is applied by the
            // remote player. That may cause some buffers to show in different rotation. So use
            // sync method to pause clients drawing until the projection transaction is applied.
            return true;
        }
        final Rect startBounds = displayChange.getStartAbsBounds();
        final Rect endBounds = displayChange.getEndAbsBounds();
        if (startBounds == null || endBounds == null) return false;
        final int startWidth = startBounds.width();
        final int startHeight = startBounds.height();
        final int endWidth = endBounds.width();
        final int endHeight = endBounds.height();
        // This is changing screen resolution. Because the screen decor layers are excluded from
        // screenshot, their draw transactions need to run with the start transaction.
        return (endWidth > startWidth) == (endHeight > startHeight)
                && (endWidth != startWidth || endHeight != startHeight);
    }

    /**
     * If a transition isn't requested yet, creates one and asks the TransitionPlayer (Shell) to
     * start it. Collection can start immediately.
@@ -494,12 +517,7 @@ class TransitionController {
        } else {
            newTransition = requestStartTransition(createTransition(type, flags),
                    trigger != null ? trigger.asTask() : null, remoteTransition, displayChange);
            if (newTransition != null && displayChange != null && (displayChange.getStartRotation()
                    + displayChange.getEndRotation()) % 2 == 0) {
                // 180 degrees rotation change may not change screen size. So the clients may draw
                // some frames before and after the display projection transaction is applied by the
                // remote player. That may cause some buffers to show in different rotation. So use
                // sync method to pause clients drawing until the projection transaction is applied.
            if (newTransition != null && displayChange != null && shouldSync(displayChange)) {
                mAtm.mWindowManager.mSyncEngine.setSyncMethod(newTransition.getSyncId(),
                        BLASTSyncEngine.METHOD_BLAST);
            }
+3 −0
Original line number Diff line number Diff line
@@ -2343,6 +2343,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
        // to be removed before the parent (so that the sync-engine tracking works). Since
        // WindowStateAnimator is a "virtual" child, we have to do it manually here.
        mWinAnimator.destroySurfaceLocked(getSyncTransaction());
        if (!mDrawHandlers.isEmpty()) {
            mWmService.mH.removeMessages(WINDOW_STATE_BLAST_SYNC_TIMEOUT, this);
        }
        super.removeImmediately();

        final DisplayContent dc = getDisplayContent();