Для складных устройств пользовательский опыт можно оптимизировать, адаптируя поведение поворота экрана к физическому состоянию устройства. Например, можно настроить автоматический поворот экрана при разворачивании устройства в планшетное положение, но зафиксировать его в портретном режиме при складывании.
Начиная с Android 13, Android получил возможность настраивать параметры автоматического поворота экрана в зависимости от состояния устройства, например, в сложенном, разложенном или полусложенном (режим настольного компьютера).

Рисунок 1: Настройки автоматического поворота экрана в зависимости от состояния устройства, как их видит пользователь.
Включить настройку автоматического поворота экрана в зависимости от состояния устройства
Для включения и настройки автоматического поворота экрана на основе состояния устройства создайте наложение устройства для файла config.xml фреймворка следующим образом:
Настройте поведение автоматического поворота по умолчанию для различных положений устройства, заполнив массив целых чисел [
config_perDeviceStateRotationLockDefaults][7] в файле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является ссылкой на другой параметр состояния устройства, и его необходимо указывать, когда значение параметра состояния устройства равноSettings.Secure.DEVICE_STATE_ROTATION_LOCK_IGNORED. При такой настройке состояния устройства любые запросы на получение или установку параметра автоматического поворота экрана перенаправляются на резервный параметр состояния.Например, если состояние
HALF_OPENEDвернется в состояниеOPENED:- Считывание параметра автоматического поворота для
HALF_OPENEDвозвращает текущий параметр дляOPENED. - Запись нового параметра автоматического поворота экрана при положении устройства
HALF_OPENEDобновляет параметр для положенияOPENED.
- Считывание параметра автоматического поворота для
Настройте описания для каждого положения устройства, задаваемого пользователем. Заполните строковый массив
config_settableAutoRotationDeviceStatesDescriptionsв окне настроек вашего устройства:<!-- 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>Для программного изменения этих настроек необходимо использовать соответствующие API, а не записывать данные непосредственно в поставщики настроек, чтобы избежать несогласованного поведения:
Чтобы изменить текущее состояние блокировки вращения (изменяет
ACCELEROMETER_ROTATION):- В SystemUI или Launcher используйте [
RotationPolicy#setRotationLock(...)][5]. - В диспетчере окон используйте
DisplayRotation#freezeRotation()илиthawRotation().
- В SystemUI или Launcher используйте [
Чтобы изменить предпочтительный режим блокировки поворота для конкретного состояния устройства (изменяет значение
DEVICE_STATE_ROTATION_LOCK):- Используйте
requestDeviceStateAutoRotateSettingChange(...)либо изRotationPolicy, либо из [DeviceStateAutoRotateSettingManager][6].
- Используйте
Детали реализации
Настройки и основные ключевые классы, управляющие автоматическим вращением складного устройства, описаны в следующих разделах.
Настройки
Для управления автоматическим поворотом система использует следующие два параметра:
Settings.System.ACCELEROMETER_ROTATION: Это основная настройка автоматического поворота экрана. Для складных устройств её значение указывает, включен ли автоматический поворот экрана для текущего положения устройства.Settings.Secure.DEVICE_STATE_ROTATION_LOCK: Этот параметр сохраняет предпочтения пользователя относительно автоматического поворота устройства для каждого положения (например, в сложенном или разложенном состоянии). Это позволяет системе применять правильные настройки при изменении положения устройства.Настройки хранятся в виде строки, разделённой двоеточиями. Каждая пара значений представляет собой положение устройства и соответствующую ему настройку поворота. Формат следующий:
<device_posture_0>:<rotation_value_0>:<device_posture_1>:<rotation_value_1>...Значения для вращения следующие:
-
0: Игнорируется (используется настройка резервного режима) -
1: Заблокировано (автоматический поворот отключен) -
2: Разблокировано (автоматический поворот включен)
Например, строка
"0:2:2:1"означает:- В сложенном состоянии (положение
0) функция автоматического вращения разблокирована (2). - В развернутом состоянии (положение
2) авторотация заблокирована (1).
-
Ключевые классы
Логика управления настройками автоматического поворота экрана на основе состояния устройства обрабатывается следующими классами:
[
DeviceStateAutoRotateSettingManagerImpl][1]: Управляет параметромDEVICE_STATE_ROTATION_LOCK. Предоставляет методы для обновления параметра, получения его значения и регистрации слушателей изменений.[
DeviceStateAutoRotateSettingController(Window Manager)][2]: СинхронизируетACCELEROMETER_ROTATIONиDEVICE_STATE_ROTATION_LOCK. При изменении состояния устройства обновляетсяACCELEROMETER_ROTATIONв соответствии с предпочтениями пользователя относительно нового состояния. Это гарантирует, что любые измененияACCELEROMETER_ROTATIONсохраняются вDEVICE_STATE_ROTATION_LOCKдля текущего состояния устройства, и аналогично измененияDEVICE_STATE_ROTATION_LOCKдля текущего состояния отражаются вACCELEROMETER_ROTATION.[
DeviceStateAutoRotateSettingController(приложение «Настройки»)][3]: Управление пользовательским интерфейсом на странице настроек автоматического поворота экрана на основе состояния устройства.PostureDeviceStateConverter: Преобразует идентификаторы состояния устройства между общими идентификаторами состояния устройства и идентификаторами состояния устройства, используемыми этой функцией.
Проверка
Поскольку работа этой функции в значительной степени зависит от конфигурации производителя оборудования, специальных тестов CTS для неё нет. Необходимо выполнить ручное тестирование, чтобы убедиться, что настройки автоматического поворота экрана изменяются должным образом при переходе устройства между различными физическими состояниями, которые вы настроили.
[1]: https://cs.android.com/android/platform/superproject/+/android-latest-release:frameworks/base/packages/SettingsLib/DeviceStateRotationLock/src/com/android/settingslib/devicestate/DeviceStateAutoRotateSettingManagerImpl.java [2]: https://cs.android.com/android/platform/superproject/+/android-latest-release:frameworks/base/services/core/java/com/android/server/wm/DeviceStateAutoRotateSettingController.java [3]: https://cs.android.com/android/platform/superproject/+/android-latest-release:packages/apps/Settings/src/com/android/settings/display/DeviceStateAutoRotateSettingController.java [4]: https://cs.android.com/android/platform/superproject/+/android-latest-release:frameworks/base/core/java/android/provider/Settings.java [5]: https://cs.android.com/android/platform/superproject/+/android-latest-release:frameworks/base/core/java/com/android/internal/view/RotationPolicy.java;bpv=0 [6]: https://cs.android.com/android/platform/superproject/+/android-latest-release:frameworks/base/packages/SettingsLib/DeviceStateRotationLock/src/com/android/settingslib/devicestate/DeviceStateAutoRotateSettingManager.java [7]: https://cs.android.com/android/platform/superproject/+/android-latest-release:packages/apps/Settings/res/values/config.xml;l=674;drc=485b59a37c1cd0af72ca706e0ba1094f4e7fef0e;l=674