Настройка автоматического поворота на основе состояния устройства

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

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

Страница настроек автоматического поворота экрана в зависимости от состояния устройства

Рисунок 1: Настройки автоматического поворота экрана в зависимости от состояния устройства, как их видит пользователь.

Включить настройку автоматического поворота экрана в зависимости от состояния устройства

Для включения и настройки автоматического поворота экрана на основе состояния устройства создайте наложение устройства для файла config.xml фреймворка следующим образом:

  1. Настройте поведение автоматического поворота по умолчанию для различных положений устройства, заполнив массив целых чисел [ 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 .
  2. Настройте описания для каждого положения устройства, задаваемого пользователем. Заполните строковый массив 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>
    
  3. Для программного изменения этих настроек необходимо использовать соответствующие API, а не записывать данные непосредственно в поставщики настроек, чтобы избежать несогласованного поведения:

    • Чтобы изменить текущее состояние блокировки вращения (изменяет ACCELEROMETER_ROTATION ):

      • В SystemUI или Launcher используйте [ RotationPolicy#setRotationLock(...) ][5].
      • В диспетчере окон используйте DisplayRotation#freezeRotation() или thawRotation() .
    • Чтобы изменить предпочтительный режим блокировки поворота для конкретного состояния устройства (изменяет значение 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