Device-state-based auto-rotate setting

For foldable devices, the user experience can be optimized by adapting screen rotation behavior to the device's physical state. For example, you can set the screen to rotate automatically when the device is unfolded in a tablet-like posture, but locked to portrait when the device is folded.

Starting in Android 13, Android has the capability to customize auto-rotate settings based on device states, such as folded, unfolded, or half-folded (tabletop mode).

Device-state-based auto-rotate settings page

Figure 1: Device-state-based auto-rotate settings as seen by the user.

Enable device state based auto rotate setting

To enable and configure device-state-based auto-rotation, create a device overlay for the framework's config.xml file, as follows:

  1. Configure the default auto-rotate behavior for different device postures by populating the config_perDeviceStateRotationLockDefaults integer array in your device's overlay config.xml:

    <!-- In your device overlay, for example,
        device/generic/goldfish/phone/overlay/frameworks/base/core/res/res/values/config.xml -->
    <resources>
        <!-- Map of device posture to rotation lock setting. Each entry must be
            in the format "key:value", or "key:value:fallback_key" for example:
            "0:1" or "2:0:1". The keys are one of
            Settings.Secure.DeviceStateRotationLockKey, and the values are one of
            Settings.Secure.DeviceStateRotationLockSetting. -->
        <integer-array name="config_perDeviceStateRotationLockDefaults">
            <item>0:1</item> <!-- CLOSED -> LOCKED -->
            <item>1:0:2</item> <!-- HALF_OPENED -> IGNORED and fallback to
                device posture OPENED -->
            <item>2:2</item> <!-- OPENED -> UNLOCKED -->
            <item>3:0:0</item> <!-- REAR_DISPLAY -> IGNORED and fallback to
                device posture CLOSED -->
        </integer-array>
    </resources>
    

    fallback-key is a reference to another device posture and you must specify when the value for a posture is Settings.Secure.DEVICE_STATE_ROTATION_LOCK_IGNORED. When a posture is configured this way, any requests to get or set its auto-rotate preference are redirected to the fallback posture.

    For example, if the HALF_OPENED posture falls back to the OPENED posture:

    • Reading the auto-rotate setting for HALF_OPENED returns the current setting for OPENED.
    • Writing a new auto-rotate preference while the device is HALF_OPENED updates the preference for the OPENED posture.
  2. Configure descriptions for each user-settable device postures. Populate the config_settableAutoRotationDeviceStatesDescriptions string array in your device's Settings app overlay:

    <!-- In your device's Settings app overlay -->
    <resources>
        <!-- The settings/preference description for each settable device
            posture defined in the array
            "config_perDeviceStateRotationLockDefaults".
            The item in position "i" describes the auto-rotation setting for the
            device posture also in position "i" in the array
            "config_perDeviceStateRotationLockDefaults". -->
        <string-array name="config_settableAutoRotationDeviceStatesDescriptions">
            <item>Auto-rotate when folded</item>
            <item>@null</item> <!-- No description for state in position 1 (it
            is not settable by the user) -->
            <item>Auto-rotate when unfolded</item>
        </string-array>
    </resources>
    
  3. You must use the correct APIs to modify these settings programmatically, rather than writing to the settings providers directly, to prevent inconsistent behavior:

    • To change the current rotation lock state (modifies ACCELEROMETER_ROTATION):

    • To change the rotation lock preference for a specific device state (modifies DEVICE_STATE_ROTATION_LOCK):

Implementation details

The settings and core key classes that control the auto-rotate behavior for a foldable device are described in the following sections.

Settings

The system uses the following two settings to manage auto-rotation:

  • Settings.System.ACCELEROMETER_ROTATION: This is the primary auto-rotate setting. For a foldable device, its value reflects whether auto-rotate is enabled for the device's current device posture.

  • Settings.Secure.DEVICE_STATE_ROTATION_LOCK: This setting stores the user's auto-rotate preference for each device posture (for example, folded or unfolded). This allows the system to apply the correct preference when the device posture changes.

    The setting is stored as a colon-delimited string. Each pair of values represents a device posture and its corresponding rotation setting. The format is:

    <device_posture_0>:<rotation_value_0>:<device_posture_1>:<rotation_value_1>...

    The values for rotation are:

    • 0: Ignored (the setting for a fallback posture is used)
    • 1: Locked (auto-rotate is off)
    • 2: Unlocked (auto-rotate is on)

    For example, the string "0:2:2:1" means:

    • For the folded state (posture 0), auto-rotate is unlocked (2).
    • For the unfolded state (posture 2), auto-rotate is locked (1).

Key classes

The logic for managing device-state-based auto-rotate settings is handled by the following classes:

  • DeviceStateAutoRotateSettingManagerImpl: Manages the DEVICE_STATE_ROTATION_LOCK setting. It provides methods to update the setting, retrieve its value, and register listeners for changes.

  • DeviceStateAutoRotateSettingController (Window Manager): Synchronizes ACCELEROMETER_ROTATION and DEVICE_STATE_ROTATION_LOCK. When the device posture changes, it updates ACCELEROMETER_ROTATION based on the user's preference for the new state. It makes sure that any change to ACCELEROMETER_ROTATION is saved back to DEVICE_STATE_ROTATION_LOCK for the current device posture and in a similar way changes to DEVICE_STATE_ROTATION_LOCK for the current posture are reflected in ACCELEROMETER_ROTATION.

  • DeviceStateAutoRotateSettingController (Settings app): Control the UI on the device state-based auto-rotate settings page.

  • PostureDeviceStateConverter: Converts between generic device-state identifiers and the device-posture identifiers used by this feature.

Validation

Because this feature's behavior is highly dependent on the OEM's configuration, there are no specific CTS tests for it. You must perform manual testing to verify that the auto-rotate settings change as expected when the device transitions between the different physical states that you have configured.