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

Commit 1347d67e authored by Riddle Hsu's avatar Riddle Hsu Committed by Android (Google) Code Review
Browse files

Merge "Remove legacy window level seamless rotation" into main

parents d89610c3 19be81cc
Loading
Loading
Loading
Loading
+10 −27
Original line number Diff line number Diff line
@@ -2161,7 +2161,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
    /** Re-show the previously hidden windows if all seamless rotated windows are done. */
    void finishAsyncRotationIfPossible() {
        final AsyncRotationController controller = mAsyncRotationController;
        if (controller != null && !mDisplayRotation.hasSeamlessRotatingWindow()) {
        if (controller != null) {
            controller.completeAll();
            mAsyncRotationController = null;
        }
@@ -2238,11 +2238,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
     */
    private void applyRotation(final int oldRotation, final int rotation) {
        mDisplayRotation.applyCurrentRotation(rotation);
        final boolean shellTransitions = mTransitionController.getTransitionPlayer() != null;
        final boolean rotateSeamlessly =
                mDisplayRotation.isRotatingSeamlessly() && !shellTransitions;
        final Transaction transaction =
                shellTransitions ? getSyncTransaction() : getPendingTransaction();

        // We need to update our screen size information to match the new rotation. If the rotation
        // has actually changed then this method will return true and, according to the comment at
        // the top of the method, the caller is obligated to call computeNewConfigurationLocked().
@@ -2250,25 +2246,13 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
        // #computeScreenConfiguration() later.
        updateDisplayAndOrientation(null /* outConfig */);

        if (!shellTransitions) {
            forAllWindows(w -> {
                w.seamlesslyRotateIfAllowed(transaction, oldRotation, rotation, rotateSeamlessly);
            }, true /* traverseTopToBottom */);
            mPinnedTaskController.startSeamlessRotationIfNeeded(transaction, oldRotation, rotation);
            if (!mDisplayRotation.hasSeamlessRotatingWindow()) {
                // Make sure DisplayRotation#isRotatingSeamlessly() will return false.
                mDisplayRotation.cancelSeamlessRotation();
            }
        }

        if (shellTransitions) {
        // Before setDisplayProjection is applied by the start transaction of transition,
        // set the transform hint to avoid using surface in old rotation.
        setFixedTransformHint(getPendingTransaction(), mSurfaceControl, rotation);
        // The sync transaction should already contains setDisplayProjection, so unset the
        // hint to restore the natural state when the transaction is applied.
            transaction.unsetFixedTransformHint(mSurfaceControl);
        }
        getSyncTransaction().unsetFixedTransformHint(mSurfaceControl);

        scheduleAnimation();

        mWmService.mRotationWatcherController.dispatchDisplayRotationChange(mDisplayId, rotation);
@@ -2870,8 +2854,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
        // If the transition finished callback cannot match the token for some reason, make sure the
        // rotated state is cleared if it is already invisible.
        if (mFixedRotationLaunchingApp != null && !mFixedRotationLaunchingApp.isVisibleRequested()
                && !mFixedRotationLaunchingApp.isVisible()
                && !mDisplayRotation.isRotatingSeamlessly()) {
                && !mFixedRotationLaunchingApp.isVisible()) {
            clearFixedRotationLaunchingApp();
        }
        // If there won't be a transition to notify the launch is done, then it should be ready to
@@ -5072,7 +5055,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
        }

        mLastHasContent = mTmpApplySurfaceChangesTransactionState.displayHasContent;
        if (!inTransition() && !mDisplayRotation.isRotatingSeamlessly()) {
        if (!inTransition()) {
            mWmService.mDisplayManagerInternal.setDisplayProperties(mDisplayId,
                    mLastHasContent,
                    mTmpApplySurfaceChangesTransactionState.preferredRefreshRate,
+0 −87
Original line number Diff line number Diff line
@@ -167,19 +167,6 @@ public class DisplayRotation {

    private int mDeferredRotationPauseCount;

    /**
     * A count of the windows which are 'seamlessly rotated', e.g. a surface at an old orientation
     * is being transformed. We freeze orientation updates while any windows are seamlessly rotated,
     * so we need to track when this hits zero so we can apply deferred orientation updates.
     */
    private int mSeamlessRotationCount;

    /**
     * True in the interval from starting seamless rotation until the last rotated window draws in
     * the new orientation.
     */
    private boolean mRotatingSeamlessly;

    /**
     * Behavior of rotation suggestions.
     *
@@ -630,15 +617,6 @@ public class DisplayRotation {
            return true;
        }

        if (shouldRotateSeamlessly(oldRotation, rotation, forceUpdate)) {
            // The screen rotation animation uses a screenshot to freeze the screen while windows
            // resize underneath. When we are rotating seamlessly, we allow the elements to
            // transition to their rotated state independently and without a freeze required.
            prepareSeamlessRotation();
        } else {
            cancelSeamlessRotation();
        }

        // Give a remote handler (system ui) some time to reposition things.
        startRemoteRotation(oldRotation, mRotation);

@@ -677,42 +655,6 @@ public class DisplayRotation {
        }
    }

    /**
     * This ensures that normal rotation animation is used. E.g. {@link #mRotatingSeamlessly} was
     * set by previous {@link #updateRotationUnchecked}, but another orientation change happens
     * before calling {@link DisplayContent#sendNewConfiguration} (remote rotation hasn't finished)
     * and it doesn't choose seamless rotation.
     */
    void cancelSeamlessRotation() {
        if (!mRotatingSeamlessly) {
            return;
        }
        mDisplayContent.forAllWindows(w -> {
            if (w.mSeamlesslyRotated) {
                w.cancelSeamlessRotation();
                w.mSeamlesslyRotated = false;
            }
        }, true /* traverseTopToBottom */);
        mSeamlessRotationCount = 0;
        mRotatingSeamlessly = false;
        mDisplayContent.finishAsyncRotationIfPossible();
    }

    private void prepareSeamlessRotation() {
        // We are careful to reset this in case a window was removed before it finished
        // seamless rotation.
        mSeamlessRotationCount = 0;
        mRotatingSeamlessly = true;
    }

    boolean isRotatingSeamlessly() {
        return mRotatingSeamlessly;
    }

    boolean hasSeamlessRotatingWindow() {
        return mSeamlessRotationCount > 0;
    }

    @VisibleForTesting
    boolean shouldRotateSeamlessly(int oldRotation, int newRotation, boolean forceUpdate) {
        // Display doesn't need to be frozen because application has been started in correct
@@ -750,13 +692,6 @@ public class DisplayRotation {
            return false;
        }

        // 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
        // mSeamlessRotationCount but that could be incorrect in the case of window-removal.
        if (!forceUpdate && mDisplayContent.getWindow(win -> win.mSeamlesslyRotated) != null) {
            return false;
        }

        return true;
    }

@@ -774,28 +709,6 @@ public class DisplayRotation {
        return oldRotation != Surface.ROTATION_180 && newRotation != Surface.ROTATION_180;
    }

    void markForSeamlessRotation(WindowState w, boolean seamlesslyRotated) {
        if (seamlesslyRotated == w.mSeamlesslyRotated || w.mForceSeamlesslyRotate) {
            return;
        }

        w.mSeamlesslyRotated = seamlesslyRotated;
        if (seamlesslyRotated) {
            mSeamlessRotationCount++;
        } else {
            mSeamlessRotationCount--;
        }
        if (mSeamlessRotationCount == 0) {
            ProtoLog.i(WM_DEBUG_ORIENTATION,
                    "Performing post-rotate rotation after seamless rotation");
            // Finish seamless rotation.
            mRotatingSeamlessly = false;
            mDisplayContent.finishAsyncRotationIfPossible();

            updateRotationAndSendNewConfigIfChanged();
        }
    }

    void restoreSettings(int userRotationMode, int userRotation, int fixedToUserRotation) {
        mFixedToUserRotation = fixedToUserRotation;

+5 −97
Original line number Diff line number Diff line
@@ -21,20 +21,13 @@ import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;

import android.app.PictureInPictureParams;
import android.content.res.Resources;
import android.graphics.Insets;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.util.RotationUtils;
import android.util.Slog;
import android.view.IPinnedTaskListener;
import android.view.Surface;
import android.view.SurfaceControl;
import android.window.PictureInPictureSurfaceTransaction;

import java.io.PrintWriter;

@@ -71,11 +64,7 @@ class PinnedTaskController {
     * based on the new rotation.
     */
    private Rect mDestRotatedBounds;
    /**
     * Non-null if the entering PiP task from recents animation will cause display rotation to
     * change. The transaction is based on the old rotation.
     */
    private PictureInPictureSurfaceTransaction mPipTransaction;

    /** Whether to skip task configuration change once. */
    private boolean mFreezingTaskConfig;
    /** Defer display orientation change if the PiP task is animating across orientations. */
@@ -212,14 +201,12 @@ class PinnedTaskController {
    }

    /**
     * Sets the transaction for {@link #startSeamlessRotationIfNeeded} if the orientation of display
     * will be changed. This is only called when finishing recents animation with pending
     * orientation change that will be handled by
     * {@link DisplayContent.FixedRotationTransitionListener#onFinishRecentsAnimation}.
     * Sets a hint if the orientation of display will be changed. This is only called when
     * finishing recents animation with pending orientation change that will be handled by
     * {@link DisplayContent.FixedRotationTransitionListener}.
     */
    void setEnterPipTransaction(PictureInPictureSurfaceTransaction tx) {
    void setEnterPipWithRotatedTransientLaunch() {
        mFreezingTaskConfig = true;
        mPipTransaction = tx;
    }

    /** Called when the activity in PiP task has PiP windowing mode (at the end of animation). */
@@ -232,81 +219,6 @@ class PinnedTaskController {
        }
    }

    /**
     * Resets rotation and applies scale and position to PiP task surface to match the current
     * rotation of display. The final surface matrix will be replaced by PiPTaskOrganizer after it
     * receives the callback of fixed rotation completion.
     */
    void startSeamlessRotationIfNeeded(SurfaceControl.Transaction t,
            int oldRotation, int newRotation) {
        final Rect bounds = mDestRotatedBounds;
        final PictureInPictureSurfaceTransaction pipTx = mPipTransaction;
        final boolean emptyPipPositionTx = pipTx == null || pipTx.mPosition == null;
        if (bounds == null && emptyPipPositionTx) {
            return;
        }
        final TaskDisplayArea taskArea = mDisplayContent.getDefaultTaskDisplayArea();
        final Task pinnedTask = taskArea.getRootPinnedTask();
        if (pinnedTask == null) {
            return;
        }

        mDestRotatedBounds = null;
        mPipTransaction = null;
        final Rect areaBounds = taskArea.getBounds();
        if (!emptyPipPositionTx) {
            // The transaction from recents animation is in old rotation. So the position needs to
            // be rotated.
            float dx = pipTx.mPosition.x;
            float dy = pipTx.mPosition.y;
            final Matrix matrix = pipTx.getMatrix();
            if (pipTx.mRotation == 90) {
                dx = pipTx.mPosition.y;
                dy = areaBounds.right - pipTx.mPosition.x;
                matrix.postRotate(-90);
            } else if (pipTx.mRotation == -90) {
                dx = areaBounds.bottom - pipTx.mPosition.y;
                dy = pipTx.mPosition.x;
                matrix.postRotate(90);
            }
            matrix.postTranslate(dx, dy);
            final SurfaceControl leash = pinnedTask.getSurfaceControl();
            t.setMatrix(leash, matrix, new float[9]);
            if (pipTx.hasCornerRadiusSet()) {
                t.setCornerRadius(leash, pipTx.mCornerRadius);
            }
            Slog.i(TAG, "Seamless rotation PiP tx=" + pipTx + " pos=" + dx + "," + dy);
            return;
        }

        final PictureInPictureParams params = pinnedTask.getPictureInPictureParams();
        final Rect sourceHintRect = params != null && params.hasSourceBoundsHint()
                ? params.getSourceRectHint()
                : null;
        Slog.i(TAG, "Seamless rotation PiP bounds=" + bounds + " hintRect=" + sourceHintRect);
        final int rotationDelta = RotationUtils.deltaRotation(oldRotation, newRotation);
        // Adjust for display cutout if applicable.
        if (sourceHintRect != null && rotationDelta == Surface.ROTATION_270) {
            if (pinnedTask.getDisplayCutoutInsets() != null) {
                final int rotationBackDelta = RotationUtils.deltaRotation(newRotation, oldRotation);
                final Rect displayCutoutInsets = RotationUtils.rotateInsets(
                        Insets.of(pinnedTask.getDisplayCutoutInsets()), rotationBackDelta).toRect();
                sourceHintRect.offset(displayCutoutInsets.left, displayCutoutInsets.top);
            }
        }
        final Rect contentBounds = sourceHintRect != null && areaBounds.contains(sourceHintRect)
                ? sourceHintRect : areaBounds;
        final int w = contentBounds.width();
        final int h = contentBounds.height();
        final float scale = w <= h ? (float) bounds.width() / w : (float) bounds.height() / h;
        final int insetLeft = (int) ((contentBounds.left - areaBounds.left) * scale + .5f);
        final int insetTop = (int) ((contentBounds.top - areaBounds.top) * scale + .5f);
        final Matrix matrix = new Matrix();
        matrix.setScale(scale, scale);
        matrix.postTranslate(bounds.left - insetLeft, bounds.top - insetTop);
        t.setMatrix(pinnedTask.getSurfaceControl(), matrix, new float[9]);
    }

    /**
     * Returns {@code true} to skip {@link Task#onConfigurationChanged} because it is expected that
     * there will be a orientation change and a PiP configuration change.
@@ -321,7 +233,6 @@ class PinnedTaskController {
        mFreezingTaskConfig = false;
        mDeferOrientationChanging = false;
        mDestRotatedBounds = null;
        mPipTransaction = null;
    }

    /**
@@ -381,9 +292,6 @@ class PinnedTaskController {
        if (mDestRotatedBounds != null) {
            pw.println(prefix + "  mPendingBounds=" + mDestRotatedBounds);
        }
        if (mPipTransaction != null) {
            pw.println(prefix + "  mPipTransaction=" + mPipTransaction);
        }
        pw.println(prefix + "  mIsImeShowing=" + mIsImeShowing);
        pw.println(prefix + "  mImeHeight=" + mImeHeight);
        pw.println(prefix + "  mMinAspectRatio=" + mMinAspectRatio);
+1 −1
Original line number Diff line number Diff line
@@ -1249,7 +1249,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
                // Skip dispatching the change for PiP task to avoid its activity drawing for the
                // intermediate state which will cause flickering. The final PiP bounds in new
                // rotation will be applied by PipTransition.
                ar.mDisplayContent.mPinnedTaskController.setEnterPipTransaction(null);
                ar.mDisplayContent.mPinnedTaskController.setEnterPipWithRotatedTransientLaunch();
            }
            return inPip;
        }
+0 −1
Original line number Diff line number Diff line
@@ -2132,7 +2132,6 @@ public class WindowManagerService extends IWindowManager.Stub
        }

        final DisplayContent dc = win.getDisplayContent();
        dc.getDisplayRotation().markForSeamlessRotation(win, false /* seamlesslyRotated */);

        win.resetAppOpsState();

Loading