Настройка автоповорота в зависимости от состояния устройства

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

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

Страница настроек автоповорота на основе состояния устройства

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

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

Чтобы включить и настроить автоматический поворот экрана на основе состояния устройства, создайте наложение устройства для файла config.xml фреймворка, как описано ниже.

  1. Чтобы настроить поведение автоповорота по умолчанию для разных положений устройства, заполните целочисленный массив config_perDeviceStateRotationLockDefaults в оверлее устройства 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 или на панели запуска используйте RotationPolicy#setRotationLock(...).
      • В диспетчере окон используйте DisplayRotation#freezeRotation() или thawRotation().
    • Чтобы изменить параметр блокировки ориентации для определенного состояния устройства (изменяет DEVICE_STATE_ROTATION_LOCK):

Подробная информация о реализации

Ниже описаны настройки и основные ключевые классы, которые управляют автоматическим поворотом экрана на складном устройстве.

Настройки

Для управления автоповоротом используются две настройки:

  • 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: управляет настройкой DEVICE_STATE_ROTATION_LOCK. Он предоставляет методы для обновления настройки, получения ее значения и регистрации слушателей изменений.

  • DeviceStateAutoRotateSettingController (менеджер окон): синхронизирует ACCELEROMETER_ROTATION и DEVICE_STATE_ROTATION_LOCK. При изменении положения устройства ACCELEROMETER_ROTATION обновляется в соответствии с предпочтениями пользователя для нового состояния. Она гарантирует, что любые изменения в ACCELEROMETER_ROTATION будут сохранены в DEVICE_STATE_ROTATION_LOCK для текущего положения устройства, а изменения в DEVICE_STATE_ROTATION_LOCK для текущего положения будут отражены в ACCELEROMETER_ROTATION.

  • DeviceStateAutoRotateSettingController (приложение "Настройки"). Управляет интерфейсом на странице настроек автоповорота на основе состояния устройства.

  • PostureDeviceStateConverter – преобразует общие идентификаторы состояния устройства в идентификаторы положения устройства, используемые этой функцией.

Проверка

Поскольку поведение этой функции сильно зависит от конфигурации OEM, для нее нет специальных тестов CTS. Чтобы убедиться, что настройки автоповорота меняются, как ожидается, когда устройство переходит между разными физическими состояниями, которые вы настроили, необходимо выполнить тестирование вручную.