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

Commit f7eeb3d6 authored by Mariia Sandrikova's avatar Mariia Sandrikova
Browse files

Add a way to disable auto rotation for immersive apps

Provide a way to always show a rotation button instead of auto rotating for immersive applications when the following conditions are met:
1) Top activity requests to hide status and navigation bars
2) Top activity is fullscreen and in optimal orientation (without letterboxing)
3) Rotation will lead to letterboxing due to fixed orientation.
4) ignoreOrientationRequest is enabled and config_letterboxIsDisplayRotationImmersiveAppCompatPolicyEnabled is enabled

This is needed because immersive apps, such as games, are often not optimized for all orientations and can have a poor UX when rotated. Additionally, some games relying on sensors for the gameplay so users can trigger such rotations accidentally when auto rotation is on.

Test: atest LetterboxConfigurationDeviceConfigTests DisplayRotationCompatPolicyForImmersiveAppsTests
Bug: 251404186
Change-Id: I0b5d8f666b8bec9bd9d6fb5303986d3c288e283f
Merged-In: I0b5d8f666b8bec9bd9d6fb5303986d3c288e283f
parent bc2a6556
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -5213,6 +5213,14 @@
         having a separating hinge. -->
    <bool name="config_isDisplayHingeAlwaysSeparating">false</bool>

    <!-- Whether enabling rotation compat policy for immersive apps that prevents auto rotation
         into non-optimal screen orientation while in fullscreen. This is needed because immersive
         apps, such as games, are often not optimized for all orientations and can have a poor UX
         when rotated. Additionally, some games rely on sensors for the gameplay so users can
         trigger such rotations accidentally when auto rotation is on.
         Applicable only if ignoreOrientationRequest is enabled. -->
    <bool name="config_letterboxIsDisplayRotationImmersiveAppCompatPolicyEnabled">false</bool>

    <!-- Aspect ratio of letterboxing for fixed orientation. Values <= 1.0 will be ignored.
         Note: Activity min/max aspect ratio restrictions will still be respected.
         Therefore this override can control the maximum screen area that can be occupied by
+1 −0
Original line number Diff line number Diff line
@@ -4441,6 +4441,7 @@
  <java-symbol type="dimen" name="controls_thumbnail_image_max_height" />
  <java-symbol type="dimen" name="controls_thumbnail_image_max_width" />

  <java-symbol type="bool" name="config_letterboxIsDisplayRotationImmersiveAppCompatPolicyEnabled" />
  <java-symbol type="dimen" name="config_fixedOrientationLetterboxAspectRatio" />
  <java-symbol type="dimen" name="config_letterboxBackgroundWallpaperBlurRadius" />
  <java-symbol type="integer" name="config_letterboxActivityCornersRadius" />
+2 −1
Original line number Diff line number Diff line
@@ -249,7 +249,8 @@ public class RotationButtonController {
    }

    public void setRotationLockedAtAngle(int rotationSuggestion) {
        RotationPolicy.setRotationLockAtAngle(mContext, true, rotationSuggestion);
        RotationPolicy.setRotationLockAtAngle(mContext, /* enabled= */ isRotationLocked(),
                /* rotation= */ rotationSuggestion);
    }

    public boolean isRotationLocked() {
+1 −0
Original line number Diff line number Diff line
@@ -5948,6 +5948,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
        }
    }

    @Nullable
    ActivityRecord topRunningActivity() {
        return topRunningActivity(false /* considerKeyguardState */);
    }
+27 −9
Original line number Diff line number Diff line
@@ -100,6 +100,8 @@ public class DisplayRotation {
    private final DisplayWindowSettings mDisplayWindowSettings;
    private final Context mContext;
    private final Object mLock;
    @Nullable
    private final DisplayRotationImmersiveAppCompatPolicy mCompatPolicyForImmersiveApps;

    public final boolean isDefaultDisplay;
    private final boolean mSupportAutoRotation;
@@ -205,7 +207,7 @@ public class DisplayRotation {

    /**
     * A flag to indicate if the display rotation should be fixed to user specified rotation
     * regardless of all other states (including app requrested orientation). {@code true} the
     * regardless of all other states (including app requested orientation). {@code true} the
     * display rotation should be fixed to user specified rotation, {@code false} otherwise.
     */
    private int mFixedToUserRotation = IWindowManager.FIXED_TO_USER_ROTATION_DEFAULT;
@@ -232,6 +234,7 @@ public class DisplayRotation {
        mContext = context;
        mLock = lock;
        isDefaultDisplay = displayContent.isDefaultDisplay;
        mCompatPolicyForImmersiveApps = initImmersiveAppCompatPolicy(service, displayContent);

        mSupportAutoRotation =
                mContext.getResources().getBoolean(R.bool.config_supportAutoRotation);
@@ -255,6 +258,14 @@ public class DisplayRotation {
        }
    }

    @VisibleForTesting
    @Nullable
    DisplayRotationImmersiveAppCompatPolicy initImmersiveAppCompatPolicy(
                WindowManagerService service, DisplayContent displayContent) {
        return DisplayRotationImmersiveAppCompatPolicy.createIfNeeded(
                service.mLetterboxConfiguration, this, displayContent);
    }

    // Change the default value to the value specified in the sysprop
    // ro.bootanim.set_orientation_<display_id>. Four values are supported: ORIENTATION_0,
    // ORIENTATION_90, ORIENTATION_180 and ORIENTATION_270.
@@ -1305,11 +1316,11 @@ public class DisplayRotation {
        return mAllowAllRotations;
    }

    private boolean isLandscapeOrSeascape(int rotation) {
    boolean isLandscapeOrSeascape(@Surface.Rotation final int rotation) {
        return rotation == mLandscapeRotation || rotation == mSeascapeRotation;
    }

    private boolean isAnyPortrait(int rotation) {
    boolean isAnyPortrait(@Surface.Rotation final int rotation) {
        return rotation == mPortraitRotation || rotation == mUpsideDownRotation;
    }

@@ -1348,9 +1359,16 @@ public class DisplayRotation {
        return mFoldController != null && mFoldController.overrideFrozenRotation();
    }

    private boolean isRotationChoicePossible(int orientation) {
        // Rotation choice is only shown when the user is in locked mode.
        if (mUserRotationMode != WindowManagerPolicy.USER_ROTATION_LOCKED) return false;
    private boolean isRotationChoiceAllowed(@Surface.Rotation final int proposedRotation) {
        final boolean isRotationLockEnforced = mCompatPolicyForImmersiveApps != null
                && mCompatPolicyForImmersiveApps.isRotationLockEnforced(proposedRotation);

        // Don't show rotation choice button if
        if (!isRotationLockEnforced // not enforcing locked rotation
                // and the screen rotation is not locked by the user.
                && mUserRotationMode != WindowManagerPolicy.USER_ROTATION_LOCKED) {
            return false;
        }

        // Don't show rotation choice if we are in tabletop or book modes.
        if (isTabletopAutoRotateOverrideEnabled()) return false;
@@ -1402,7 +1420,7 @@ public class DisplayRotation {
        }

        // Ensure that some rotation choice is possible for the given orientation.
        switch (orientation) {
        switch (mCurrentAppOrientation) {
            case ActivityInfo.SCREEN_ORIENTATION_FULL_USER:
            case ActivityInfo.SCREEN_ORIENTATION_USER:
            case ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED:
@@ -1719,11 +1737,11 @@ public class DisplayRotation {


        @Override
        public void onProposedRotationChanged(int rotation) {
        public void onProposedRotationChanged(@Surface.Rotation int rotation) {
            ProtoLog.v(WM_DEBUG_ORIENTATION, "onProposedRotationChanged, rotation=%d", rotation);
            // Send interaction power boost to improve redraw performance.
            mService.mPowerManagerInternal.setPowerBoost(Boost.INTERACTION, 0);
            if (isRotationChoicePossible(mCurrentAppOrientation)) {
            if (isRotationChoiceAllowed(rotation)) {
                final boolean isValid = isValidRotationChoice(rotation);
                sendProposedRotationChangeToStatusBarInternal(rotation, isValid);
            } else {
Loading