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).
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:
Configure the default auto-rotate behavior for different device postures by populating the
config_perDeviceStateRotationLockDefaultsinteger array in your device's overlayconfig.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-keyis a reference to another device posture and you must specify when the value for a posture isSettings.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_OPENEDposture falls back to theOPENEDposture:- Reading the auto-rotate setting for
HALF_OPENEDreturns the current setting forOPENED. - Writing a new auto-rotate preference while the device is
HALF_OPENEDupdates the preference for theOPENEDposture.
- Reading the auto-rotate setting for
Configure descriptions for each user-settable device postures. Populate the
config_settableAutoRotationDeviceStatesDescriptionsstring 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>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):- From SystemUI or Launcher, use
RotationPolicy#setRotationLock(...). - From Window Manager, use
DisplayRotation#freezeRotation()orthawRotation().
- From SystemUI or Launcher, use
To change the rotation lock preference for a specific device state (modifies
DEVICE_STATE_ROTATION_LOCK):- Use
requestDeviceStateAutoRotateSettingChange(...)from eitherRotationPolicyorDeviceStateAutoRotateSettingManager.
- Use
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 theDEVICE_STATE_ROTATION_LOCKsetting. It provides methods to update the setting, retrieve its value, and register listeners for changes.DeviceStateAutoRotateSettingController(Window Manager): SynchronizesACCELEROMETER_ROTATIONandDEVICE_STATE_ROTATION_LOCK. When the device posture changes, it updatesACCELEROMETER_ROTATIONbased on the user's preference for the new state. It makes sure that any change toACCELEROMETER_ROTATIONis saved back toDEVICE_STATE_ROTATION_LOCKfor the current device posture and in a similar way changes toDEVICE_STATE_ROTATION_LOCKfor the current posture are reflected inACCELEROMETER_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.