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

Commit ccf09404 authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Centralize rotation control to DisplayRotation

- Move seamless rotation logic. The scattered conditions
  (mayRotateSeamlessly) are also combined into shouldRotateSeamlessly.
- Move DisplayContent#updateRotationUnchecked and the related fields.
- Consolidate DisplayContent#updateOrientationFromAppTokens and
  DisplayRotation#setCurrentOrientation to DR#updateOrientation.

Bug: 117593656
Test: go/wm-smoke
Test: atest DisplayContentTests DisplayPolicyTests DisplayRotationTests

Change-Id: Ifd978a20a2773a39000a90edf683e6459adf0d2d
parent 6f9af935
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -462,7 +462,7 @@ public class AppTransitionController {
            // new rotation animation after the old one finally finishes. It's better to defer the
            // app transition.
            if (screenRotationAnimation != null && screenRotationAnimation.isAnimating() &&
                    mService.getDefaultDisplayContentLocked().rotationNeedsUpdate()) {
                    mDisplayContent.getDisplayRotation().needsUpdate()) {
                if (DEBUG_APP_TRANSITIONS) {
                    Slog.v(TAG, "Delaying app transition for screen rotation animation to finish");
                }
+64 −286

File changed.

Preview size limit exceeded, changes collapsed.

+14 −126
Original line number Diff line number Diff line
@@ -57,10 +57,6 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANS
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;
import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE;
import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_JUMPCUT;
import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE;
import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
@@ -257,7 +253,6 @@ public class DisplayPolicy {
    private volatile boolean mNavigationBarCanMove;
    private volatile boolean mNavigationBarLetsThroughTaps;
    private volatile boolean mNavigationBarAlwaysShowOnSideGesture;
    private volatile boolean mAllowSeamlessRotationDespiteNavBarMoving;

    // Written by vr manager thread, only read in this class.
    private volatile boolean mPersistentVrModeEnabled;
@@ -1150,81 +1145,6 @@ public class DisplayPolicy {
        }
    }

    /**
     * Determine the animation to run for a rotation transition based on the
     * top fullscreen windows {@link WindowManager.LayoutParams#rotationAnimation}
     * and whether it is currently fullscreen and frontmost.
     *
     * @param anim The exiting animation resource id is stored in anim[0], the
     * entering animation resource id is stored in anim[1].
     */
    public void selectRotationAnimationLw(int anim[]) {
        // If the screen is off or non-interactive, force a jumpcut.
        final boolean forceJumpcut = !mScreenOnFully || !mService.mPolicy.okToAnimate();
        if (DEBUG_ANIM) Slog.i(TAG, "selectRotationAnimation mTopFullscreen="
                + mTopFullscreenOpaqueWindowState + " rotationAnimation="
                + (mTopFullscreenOpaqueWindowState == null
                ? "0" : mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation)
                + " forceJumpcut=" + forceJumpcut);
        if (forceJumpcut) {
            anim[0] = R.anim.rotation_animation_jump_exit;
            anim[1] = R.anim.rotation_animation_enter;
            return;
        }
        if (mTopFullscreenOpaqueWindowState != null) {
            int animationHint = mTopFullscreenOpaqueWindowState.getRotationAnimationHint();
            if (animationHint < 0 && mTopIsFullscreen) {
                animationHint = mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation;
            }
            switch (animationHint) {
                case ROTATION_ANIMATION_CROSSFADE:
                case ROTATION_ANIMATION_SEAMLESS: // Crossfade is fallback for seamless.
                    anim[0] = R.anim.rotation_animation_xfade_exit;
                    anim[1] = R.anim.rotation_animation_enter;
                    break;
                case ROTATION_ANIMATION_JUMPCUT:
                    anim[0] = R.anim.rotation_animation_jump_exit;
                    anim[1] = R.anim.rotation_animation_enter;
                    break;
                case ROTATION_ANIMATION_ROTATE:
                default:
                    anim[0] = anim[1] = 0;
                    break;
            }
        } else {
            anim[0] = anim[1] = 0;
        }
    }

    /**
     * Validate whether the current top fullscreen has specified the same
     * {@link WindowManager.LayoutParams#rotationAnimation} value as that
     * being passed in from the previous top fullscreen window.
     *
     * @param exitAnimId exiting resource id from the previous window.
     * @param enterAnimId entering resource id from the previous window.
     * @param forceDefault For rotation animations only, if true ignore the
     * animation values and just return false.
     * @return true if the previous values are still valid, false if they
     * should be replaced with the default.
     */
    public boolean validateRotationAnimationLw(int exitAnimId, int enterAnimId,
            boolean forceDefault) {
        switch (exitAnimId) {
            case R.anim.rotation_animation_xfade_exit:
            case R.anim.rotation_animation_jump_exit:
                // These are the only cases that matter.
                if (forceDefault) {
                    return false;
                }
                int anim[] = new int[2];
                selectRotationAnimationLw(anim);
                return (exitAnimId == anim[0] && enterAnimId == anim[1]);
            default:
                return true;
        }
    }

    /**
     * Called when a new system UI visibility is being reported, allowing
     * the policy to adjust what is actually reported.
@@ -2388,6 +2308,14 @@ public class DisplayPolicy {
        displayFrames.mVoiceContent.bottom = Math.min(displayFrames.mVoiceContent.bottom, top);
    }

    WindowState getTopFullscreenOpaqueWindow() {
        return mTopFullscreenOpaqueWindowState;
    }

    boolean isTopLayoutFullscreen() {
        return mTopIsFullscreen;
    }

    /**
     * Called following layout of all windows before each window has policy applied.
     */
@@ -2773,8 +2701,7 @@ public class DisplayPolicy {
        mNavigationBarCanMove =
                mDisplayContent.mBaseDisplayWidth != mDisplayContent.mBaseDisplayHeight
                        && res.getBoolean(R.bool.config_navBarCanMove);
        mAllowSeamlessRotationDespiteNavBarMoving =
                res.getBoolean(R.bool.config_allowSeamlessRotationDespiteNavBarMoving);
        mDisplayContent.getDisplayRotation().updateUserDependentConfiguration(res);
    }

    /**
@@ -3562,45 +3489,6 @@ public class DisplayPolicy {
        return (systemUiFlags & disableNavigationBar) == disableNavigationBar;
    }

    boolean shouldRotateSeamlessly(DisplayRotation displayRotation, int oldRotation,
            int newRotation) {
        // For the upside down rotation we don't rotate seamlessly as the navigation
        // bar moves position.
        // Note most apps (using orientation:sensor or user as opposed to fullSensor)
        // will not enter the reverse portrait orientation, so actually the
        // orientation won't change at all.
        if (oldRotation == displayRotation.getUpsideDownRotation()
                || newRotation == displayRotation.getUpsideDownRotation()) {
            return false;
        }
        // If the navigation bar can't change sides, then it will
        // jump when we change orientations and we don't rotate
        // seamlessly - unless that is allowed, eg. with gesture
        // navigation where the navbar is low-profile enough that this isn't very noticeable.
        if (!navigationBarCanMove() && !mAllowSeamlessRotationDespiteNavBarMoving) {
            return false;
        }

        final WindowState w = mTopFullscreenOpaqueWindowState;
        if (w == null || w != mFocusedWindow) {
            return false;
        }
        // If the bounds of activity window is different from its parent, then reject to be seamless
        // because the window position may change after rotation that will look like a sudden jump.
        if (w.mAppToken != null && !w.mAppToken.matchParentBounds()) {
            return false;
        }

        // We only enable seamless rotation if the top window has requested
        // it and is in the fullscreen opaque state. Seamless rotation
        // requires freezing various Surface states and won't work well
        // with animations, so we disable it in the animation case for now.
        if (!w.isAnimatingLw() && w.getAttrs().rotationAnimation == ROTATION_ANIMATION_SEAMLESS) {
            return true;
        }
        return false;
    }

    private final Runnable mHiddenNavPanic = new Runnable() {
        @Override
        public void run() {
@@ -3665,7 +3553,7 @@ public class DisplayPolicy {
    }

    void dump(String prefix, PrintWriter pw) {
        pw.print(prefix); pw.print("DisplayPolicy");
        pw.print(prefix); pw.println("DisplayPolicy");
        prefix += "  ";
        pw.print(prefix);
        pw.print("mCarDockEnablesAccelerometer="); pw.print(mCarDockEnablesAccelerometer);
@@ -3724,12 +3612,12 @@ public class DisplayPolicy {
            pw.print(prefix); pw.print("mForcingShowNavBarLayer=");
            pw.println(mForcingShowNavBarLayer);
        }
        pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen);
        pw.print(prefix); pw.print("mTopIsFullscreen="); pw.println(mTopIsFullscreen);
        pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar);
        pw.print(" mForceStatusBarFromKeyguard="); pw.println(mForceStatusBarFromKeyguard);
        pw.print(" mForceShowSystemBarsFromExternal=");
        pw.println(mForceShowSystemBarsFromExternal);
        pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.println(mAllowLockscreenWhenOn);
        pw.print(prefix); pw.print("mForceShowSystemBarsFromExternal=");
        pw.print(mForceShowSystemBarsFromExternal);
        pw.print(" mAllowLockscreenWhenOn="); pw.println(mAllowLockscreenWhenOn);
        mStatusBarController.dump(pw, prefix);
        mNavigationBarController.dump(pw, prefix);

+461 −28

File changed.

Preview size limit exceeded, changes collapsed.

+2 −2
Original line number Diff line number Diff line
@@ -305,7 +305,7 @@ class DragState {
            if (DEBUG_ORIENTATION) {
                Slog.d(TAG_WM, "Pausing rotation during drag");
            }
            mDisplayContent.pauseRotationLocked();
            mDisplayContent.getDisplayRotation().pause();
        }

        void tearDown() {
@@ -324,7 +324,7 @@ class DragState {
            if (DEBUG_ORIENTATION) {
                Slog.d(TAG_WM, "Resuming rotation after drag");
            }
            mDisplayContent.resumeRotationLocked();
            mDisplayContent.getDisplayRotation().resume();
        }
    }

Loading