Configuração de rotação automática com base no estado do dispositivo

Em dispositivos dobráveis, a experiência do usuário pode ser otimizada adaptando o comportamento de rotação da tela ao estado físico do dispositivo. Por exemplo, é possível definir a rotação automática da tela quando o dispositivo é aberto em uma posição semelhante a um tablet, mas bloqueada no modo retrato quando o dispositivo está dobrado.

No Android 13 e versões mais recentes, é possível personalizar as configurações de rotação automática com base nos estados do dispositivo, como dobrado, aberto ou semiaberto (modo de mesa).

Página de configurações de rotação automática com base no estado do dispositivo

Figura 1. Configurações de rotação automática baseadas no estado do dispositivo, conforme mostrado ao usuário.

Ativar a configuração de rotação automática baseada no estado do dispositivo

Para ativar e configurar a rotação automática baseada no estado do dispositivo, crie uma sobreposição de dispositivo para o arquivo config.xml do framework, da seguinte maneira:

  1. Configure o comportamento de rotação automática padrão para diferentes posições do dispositivo preenchendo a matriz de números inteiros config_perDeviceStateRotationLockDefaults na sobreposição config.xml do dispositivo:

    <!-- 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 é uma referência a outra posição do dispositivo, e você precisa especificar quando o valor de uma posição é Settings.Secure.DEVICE_STATE_ROTATION_LOCK_IGNORED. Quando uma posição é configurada dessa forma, todas as solicitações para receber ou definir a preferência de rotação automática são redirecionadas para a posição de fallback.

    Por exemplo, se a postura HALF_OPENED voltar para a OPENED postura:

    • A leitura da configuração de rotação automática para HALF_OPENED retorna a configuração atual para OPENED.
    • A gravação de uma nova preferência de rotação automática enquanto o dispositivo está HALF_OPENED atualiza a preferência para a posição OPENED
  2. Configure descrições para cada posição do dispositivo que pode ser definida pelo usuário. Preencha a matriz de strings config_settableAutoRotationDeviceStatesDescriptions na sobreposição do app Configurações do dispositivo:

    <!-- 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. Use as APIs corretas para modificar essas configurações de maneira programática, em vez de gravar diretamente nos provedores de configurações, para evitar comportamentos inconsistentes:

    • Para mudar o estado atual do bloqueio de rotação (modifica ACCELEROMETER_ROTATION):

    • Para mudar a preferência de bloqueio de rotação para um estado específico do dispositivo (modifica DEVICE_STATE_ROTATION_LOCK):

Detalhes de implementação

As configurações e as classes de chave principais que controlam o comportamento de rotação automática de um dispositivo dobrável são descritas nas seções a seguir.

Configurações

O sistema usa as duas configurações a seguir para gerenciar a rotação automática:

  • Settings.System.ACCELEROMETER_ROTATION: essa é a configuração principal de rotação automática. Para um dispositivo dobrável, o valor dela reflete se a rotação automática está ativada para a posição atual do dispositivo.

  • Settings.Secure.DEVICE_STATE_ROTATION_LOCK: essa configuração armazena a preferência de rotação automática do usuário para cada posição do dispositivo (por exemplo, dobrado ou aberto). Isso permite que o sistema aplique a preferência correta quando a posição do dispositivo muda.

    A configuração é armazenada como uma string delimitada por dois pontos. Cada par de valores representa uma posição do dispositivo e a configuração de rotação correspondente. O formato é:

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

    Os valores de rotação são:

    • 0: ignorado (a configuração de uma posição de fallback é usada)
    • 1: bloqueado (a rotação automática está desativada)
    • 2: desbloqueado (a rotação automática está ativada)

    Por exemplo, a string "0:2:2:1" significa:

    • Para o estado dobrado (posição 0), a rotação automática está desbloqueada (2).
    • Para o estado aberto (posição 2), a rotação automática está bloqueada (1).

Classes principais

A lógica para gerenciar as configurações de rotação automática baseadas no estado do dispositivo é processada pelas seguintes classes:

  • DeviceStateAutoRotateSettingManagerImpl: gerencia a configuração DEVICE_STATE_ROTATION_LOCK. Ela oferece métodos para atualizar a configuração, recuperar o valor dela e registrar listeners para mudanças.

  • DeviceStateAutoRotateSettingController (Gerenciador de janelas): Sincroniza ACCELEROMETER_ROTATION e DEVICE_STATE_ROTATION_LOCK. Quando a posição do dispositivo muda, ela atualiza ACCELEROMETER_ROTATION com base na preferência do usuário para o novo estado. Ela garante que qualquer mudança em ACCELEROMETER_ROTATION seja salva de volta em DEVICE_STATE_ROTATION_LOCK para a posição atual do dispositivo e, da mesma forma, as mudanças em DEVICE_STATE_ROTATION_LOCK para a posição atual sejam refletidas em ACCELEROMETER_ROTATION.

  • DeviceStateAutoRotateSettingController (app Configurações): controla a interface na página de configurações de rotação automática baseada no estado do dispositivo.

  • PostureDeviceStateConverter: converte entre identificadores genéricos de estado do dispositivo e os identificadores de posição do dispositivo usados por esse recurso.

Validação

Como o comportamento desse recurso depende muito da configuração do OEM, não há testes CTS específicos para ele. É necessário realizar testes manuais para verificar se as configurações de rotação automática mudam conforme o esperado quando o dispositivo faz a transição entre os diferentes estados físicos configurados.