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

Commit b3985501 authored by Nick Chameyev's avatar Nick Chameyev Committed by Android (Google) Code Review
Browse files

Merge "Prevent autorotation during hinge movement" into udc-dev

parents d384523f f50f8dcb
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -680,6 +680,20 @@
     rotation. -->
    <bool name="config_windowManagerHalfFoldAutoRotateOverride">false</bool>

    <!-- Indicates whether the window manager pauses autorotation when folding or unfolding
     a foldable device based on hinge angle sensor events and physical display switch events. -->
    <bool name="config_windowManagerPauseRotationWhenUnfolding">false</bool>

    <!-- Amount of time during which autorotation will be disabled since last hinge angle event -->
    <integer name="config_pauseRotationWhenUnfolding_maxHingeAngle">0</integer>

    <!-- Maximum hinge angle event to be considered to disable autorotation when folding or
     unfolding -->
    <integer name="config_pauseRotationWhenUnfolding_hingeEventTimeout">0</integer>

    <!-- Amount of time during which autorotation will be disabled since last display switch -->
    <integer name="config_pauseRotationWhenUnfolding_displaySwitchTimeout">0</integer>

    <!-- When a device enters any of these states, it should be woken up. States are defined in
         device_state_configuration.xml. -->
    <integer-array name="config_deviceStatesOnWhichToWakeUp">
+4 −0
Original line number Diff line number Diff line
@@ -4017,6 +4017,10 @@
  <java-symbol type="array" name="config_halfFoldedDeviceStates" />
  <java-symbol type="array" name="config_rearDisplayDeviceStates" />
  <java-symbol type="bool" name="config_windowManagerHalfFoldAutoRotateOverride" />
  <java-symbol type="bool" name="config_windowManagerPauseRotationWhenUnfolding" />
  <java-symbol type="integer" name="config_pauseRotationWhenUnfolding_hingeEventTimeout" />
  <java-symbol type="integer" name="config_pauseRotationWhenUnfolding_maxHingeAngle" />
  <java-symbol type="integer" name="config_pauseRotationWhenUnfolding_displaySwitchTimeout" />
  <java-symbol type="array" name="config_deviceStatesOnWhichToWakeUp" />
  <java-symbol type="array" name="config_deviceStatesOnWhichToSleep" />
  <java-symbol type="string" name="config_foldedArea" />
+2 −1
Original line number Diff line number Diff line
@@ -2921,6 +2921,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
                        /* includeRotationSettings */ false);
                mDisplaySwitchTransitionLauncher.requestDisplaySwitchTransitionIfNeeded(mDisplayId,
                        mInitialDisplayWidth, mInitialDisplayHeight, newWidth, newHeight);
                mDisplayRotation.physicalDisplayChanged();
            }

            // If there is an override set for base values - use it, otherwise use new values.
@@ -3291,7 +3292,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
            mTransitionController.unregisterLegacyListener(mFixedRotationTransitionListener);
            handleAnimatingStoppedAndTransition();
            mWmService.stopFreezingDisplayLocked();
            mDisplayRotation.removeDefaultDisplayRotationChangedCallback();
            mDeviceStateController.unregisterDeviceStateCallback(mDeviceStateConsumer);
            super.removeImmediately();
            if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + this);
@@ -3305,6 +3305,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
            mWindowingLayer.release();
            mInputMonitor.onDisplayRemoved();
            mWmService.mDisplayNotificationController.dispatchDisplayRemoved(this);
            mDisplayRotation.onDisplayRemoved();
            mWmService.mAccessibilityController.onDisplayRemoved(mDisplayId);
            mRootWindowContainer.mTaskSupervisor
                    .getKeyguardController().onDisplayRemoved(mDisplayId);
+182 −1
Original line number Diff line number Diff line
@@ -51,8 +51,13 @@ import android.content.pm.ActivityInfo.ScreenOrientation;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.hardware.power.Boost;
import android.os.Handler;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.provider.Settings;
@@ -1085,6 +1090,10 @@ public class DisplayRotation {
            return false;
        }

        if (mFoldController != null && mFoldController.shouldDisableRotationSensor()) {
            return false;
        }

        if (mSupportAutoRotation) {
            if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
                    || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
@@ -1183,6 +1192,9 @@ public class DisplayRotation {
        int sensorRotation = mOrientationListener != null
                ? mOrientationListener.getProposedRotation() // may be -1
                : -1;
        if (mFoldController != null && mFoldController.shouldIgnoreSensorRotation()) {
            sensorRotation = -1;
        }
        if (mDeviceStateController.shouldReverseRotationDirectionAroundZAxis()) {
            sensorRotation = RotationUtils.reverseRotationDirectionAroundZAxis(sensorRotation);
        }
@@ -1425,6 +1437,11 @@ public class DisplayRotation {
            return false;
        }

        // Do not show rotation choice when fold controller blocks rotation sensor
        if (mFoldController != null && mFoldController.shouldIgnoreSensorRotation()) {
            return false;
        }

        // Don't show rotation choice if we are in tabletop or book modes.
        if (isTabletopAutoRotateOverrideEnabled()) return false;

@@ -1527,6 +1544,13 @@ public class DisplayRotation {
        }
    }

    void onDisplayRemoved() {
        removeDefaultDisplayRotationChangedCallback();
        if (mFoldController != null) {
            mFoldController.onDisplayRemoved();
        }
    }

    /** Return whether the rotation settings has changed. */
    private boolean updateSettings() {
        final ContentResolver resolver = mContext.getContentResolver();
@@ -1622,6 +1646,22 @@ public class DisplayRotation {
        pw.println(prefix + "  mLidOpenRotation=" + Surface.rotationToString(mLidOpenRotation));
        pw.println(prefix + "  mFixedToUserRotation=" + isFixedToUserRotation());

        if (mFoldController != null) {
            pw.println(prefix + "FoldController");
            pw.println(prefix + "  mPauseAutorotationDuringUnfolding="
                    + mFoldController.mPauseAutorotationDuringUnfolding);
            pw.println(prefix + "  mShouldDisableRotationSensor="
                    + mFoldController.mShouldDisableRotationSensor);
            pw.println(prefix + "  mShouldIgnoreSensorRotation="
                    + mFoldController.mShouldIgnoreSensorRotation);
            pw.println(prefix + "  mLastDisplaySwitchTime="
                    + mFoldController.mLastDisplaySwitchTime);
            pw.println(prefix + "  mLastHingeAngleEventTime="
                    + mFoldController.mLastHingeAngleEventTime);
            pw.println(prefix + "  mDeviceState="
                    + mFoldController.mDeviceState);
        }

        if (!mRotationHistory.mRecords.isEmpty()) {
            pw.println();
            pw.println(prefix + "  RotationHistory");
@@ -1663,13 +1703,37 @@ public class DisplayRotation {
        }
    }

    private class FoldController {
    /**
     * Called by the DisplayContent when the physical display changes
     */
    void physicalDisplayChanged() {
        if (mFoldController != null) {
            mFoldController.onPhysicalDisplayChanged();
        }
    }

    @VisibleForTesting
    long uptimeMillis() {
        return SystemClock.uptimeMillis();
    }

    class FoldController {
        private final boolean mPauseAutorotationDuringUnfolding;
        @Surface.Rotation
        private int mHalfFoldSavedRotation = -1; // No saved rotation
        private DeviceStateController.DeviceState mDeviceState =
                DeviceStateController.DeviceState.UNKNOWN;
        private long mLastHingeAngleEventTime = 0;
        private long mLastDisplaySwitchTime = 0;
        private boolean mShouldIgnoreSensorRotation;
        private boolean mShouldDisableRotationSensor;
        private boolean mInHalfFoldTransition = false;
        private int mDisplaySwitchRotationBlockTimeMs;
        private int mHingeAngleRotationBlockTimeMs;
        private int mMaxHingeAngle;
        private final boolean mIsDisplayAlwaysSeparatingHinge;
        private SensorManager mSensorManager;
        private SensorEventListener mHingeAngleSensorEventListener;
        private final Set<Integer> mTabletopRotations;
        private final Runnable mActivityBoundsUpdateCallback;

@@ -1726,6 +1790,48 @@ public class DisplayRotation {
                    }
                }
            };

            mPauseAutorotationDuringUnfolding = mContext.getResources().getBoolean(
                    R.bool.config_windowManagerPauseRotationWhenUnfolding);

            if (mPauseAutorotationDuringUnfolding) {
                mDisplaySwitchRotationBlockTimeMs = mContext.getResources().getInteger(
                        R.integer.config_pauseRotationWhenUnfolding_displaySwitchTimeout);
                mHingeAngleRotationBlockTimeMs = mContext.getResources().getInteger(
                        R.integer.config_pauseRotationWhenUnfolding_hingeEventTimeout);
                mMaxHingeAngle = mContext.getResources().getInteger(
                        R.integer.config_pauseRotationWhenUnfolding_maxHingeAngle);
                registerSensorManager();
            }
        }

        private void registerSensorManager() {
            mSensorManager = mContext.getSystemService(SensorManager.class);
            if (mSensorManager != null) {
                final Sensor hingeAngleSensor = mSensorManager
                        .getDefaultSensor(Sensor.TYPE_HINGE_ANGLE);

                if (hingeAngleSensor != null) {
                    mHingeAngleSensorEventListener = new SensorEventListener() {
                        @Override
                        public void onSensorChanged(SensorEvent event) {
                            onHingeAngleChanged(event.values[0]);
                        }

                        @Override
                        public void onAccuracyChanged(Sensor sensor, int accuracy) {
                        }
                    };
                    mSensorManager.registerListener(mHingeAngleSensorEventListener,
                            hingeAngleSensor, SensorManager.SENSOR_DELAY_FASTEST, getHandler());
                }
            }
        }

        void onDisplayRemoved() {
            if (mSensorManager != null && mHingeAngleSensorEventListener != null) {
                mSensorManager.unregisterListener(mHingeAngleSensorEventListener);
            }
        }

        boolean isDeviceInPosture(DeviceStateController.DeviceState state, boolean isTabletop) {
@@ -1755,6 +1861,7 @@ public class DisplayRotation {
        boolean shouldRevertOverriddenRotation() {
            // When transitioning to open.
            return mDeviceState == DeviceStateController.DeviceState.OPEN
                    && !mShouldIgnoreSensorRotation // Ignore if the hinge angle still moving
                    && mInHalfFoldTransition
                    && mHalfFoldSavedRotation != -1 // Ignore if we've already reverted.
                    && mUserRotationMode
@@ -1801,6 +1908,80 @@ public class DisplayRotation {
            UiThread.getHandler().postDelayed(mActivityBoundsUpdateCallback,
                    FOLDING_RECOMPUTE_CONFIG_DELAY_MS);
        }

        boolean shouldIgnoreSensorRotation() {
            return mShouldIgnoreSensorRotation;
        }

        boolean shouldDisableRotationSensor() {
            return mShouldDisableRotationSensor;
        }

        private void updateSensorRotationBlockIfNeeded() {
            final long currentTime = uptimeMillis();
            final boolean newShouldIgnoreRotation =
                    currentTime - mLastDisplaySwitchTime < mDisplaySwitchRotationBlockTimeMs
                    || currentTime - mLastHingeAngleEventTime < mHingeAngleRotationBlockTimeMs;

            if (newShouldIgnoreRotation != mShouldIgnoreSensorRotation) {
                mShouldIgnoreSensorRotation = newShouldIgnoreRotation;

                // Resuming the autorotation
                if (!mShouldIgnoreSensorRotation) {
                    if (mShouldDisableRotationSensor) {
                        // Sensor was disabled, let's re-enable it
                        mShouldDisableRotationSensor = false;
                        updateOrientationListenerLw();
                    } else {
                        // Sensor was not disabled, let's update the rotation in case if we received
                        // some rotation sensor updates when autorotate was disabled
                        updateRotationAndSendNewConfigIfChanged();
                    }
                }
            }
        }

        void onPhysicalDisplayChanged() {
            if (!mPauseAutorotationDuringUnfolding) return;

            mLastDisplaySwitchTime = uptimeMillis();

            final boolean isUnfolding =
                    mDeviceState == DeviceStateController.DeviceState.OPEN
                    || mDeviceState == DeviceStateController.DeviceState.HALF_FOLDED;

            if (isUnfolding) {
                // Temporary disable rotation sensor updates when unfolding
                mShouldDisableRotationSensor = true;
                updateOrientationListenerLw();
            }

            updateSensorRotationBlockIfNeeded();
            getHandler().postDelayed(() -> {
                synchronized (mLock) {
                    updateSensorRotationBlockIfNeeded();
                };
            }, mDisplaySwitchRotationBlockTimeMs);
        }

        void onHingeAngleChanged(float hingeAngle) {
            if (hingeAngle < mMaxHingeAngle) {
                mLastHingeAngleEventTime = uptimeMillis();

                updateSensorRotationBlockIfNeeded();

                getHandler().postDelayed(() -> {
                    synchronized (mLock) {
                        updateSensorRotationBlockIfNeeded();
                    };
                }, mHingeAngleRotationBlockTimeMs);
            }
        }
    }

    @VisibleForTesting
    Handler getHandler() {
        return mService.mH;
    }

    private class OrientationListener extends WindowOrientationListener implements Runnable {
+212 −2

File changed.

Preview size limit exceeded, changes collapsed.