Extensões do WindowManager

A biblioteca Jetpack WindowManager permite que os desenvolvedores de aplicativos ofereçam suporte a novos formatos de dispositivo e a ambientes de várias janelas.

As extensões do WindowManager (Extensions) são um módulo opcional da plataforma Android que ativa vários recursos do WindowManager do Jetpack. O módulo é implementado no AOSP em frameworks/base/libs/WindowManager/Jetpack e enviado em dispositivos com suporte aos recursos do WindowManager.

Distribuição do módulo de extensões

As extensões são compiladas em uma biblioteca .jar e colocadas na partição system_ext de um dispositivo se as extensões estiverem ativadas no makefile do dispositivo.

Para ativar as extensões em um dispositivo, adicione o seguinte ao makefile do dispositivo do produto:

$(call inherit-product, $(SRC_TARGET_DIR)/product/window_extensions.mk)

Isso ativa os pacotes androidx.window.extensions e androidx.window.sidecar no dispositivo e define a propriedade persist.wm.extensions.enabled. A inclusão desses pacotes no makefile também coloca declarações em etc/permissions/, disponibilizando-as para os processos do aplicativo. Normalmente, os módulos são carregados e executados como parte do processo do aplicativo no tempo de execução quando usados pela biblioteca WindowManager do Jetpack, o que torna a operação semelhante ao código do framework do lado do cliente, conforme mostrado na figura a seguir:

Figura 1. Extensões do WindowManager carregadas no processo do aplicativo de forma semelhante ao código da plataforma.

O módulo androidx.window.extensions é o módulo de extensões atual em desenvolvimento ativo. O módulo androidx.window.sidecar é um módulo legado incluído para compatibilidade com as versões mais antigas do Jetpack WindowManager, mas o sidecar não é mais mantido ativamente.

A figura a seguir mostra a lógica para determinar o uso de androidx.window.extensions ou androidx.window.sidecar.

Figura 2. Árvore de decisão para acessar androidx.window.extensions ou androidx.window.sidecar.

Módulos de extensões

As extensões oferecem recursos de janelas para dispositivos dobráveis de tela grande e dispositivos que oferecem suporte a janelas em telas externas. As áreas de recursos incluem:

As implementações de OEM de extensões podem fornecer componentes nulos ou componentes com implementações padrão ou stub dos métodos na interface WindowExtensions se o hardware do dispositivo não oferecer suporte aos recursos correspondentes, a menos que o recurso seja solicitado especificamente no Documento de definição de compatibilidade (CDD) 7.1.1.1.

Extensões e APIs do Jetpack

O módulo de extensões do WindowManager fornece a própria plataforma de API, além das APIs públicas da plataforma. O módulo de extensões é desenvolvido publicamente em uma biblioteca Jetpack androidx.window.extensions não voltada a desenvolvedores, para que o WindowManager do Jetpack (androidx.window) possa se vincular a ela no momento da compilação. A plataforma da API Extensions geralmente oferece APIs de nível inferior.

As APIs fornecidas pelas extensões são destinadas apenas à biblioteca WindowManager do Jetpack. As APIs Extensions não são destinadas a ser chamadas diretamente pelos desenvolvedores de aplicativos. A biblioteca Extensions não pode ser adicionada como uma dependência de um aplicativo no arquivo de build do Gradle para garantir a funcionalidade correta. Evite pré-compilar a biblioteca Extensions em um aplicativo diretamente. Em vez disso, use o carregamento no momento da execução para evitar o carregamento de uma mistura de classes de extensões pré-compiladas e fornecidas no momento da execução.

A Jetpack WindowManager (androidx.window) precisa ser adicionada como uma dependência do aplicativo e fornece as APIs públicas voltadas para desenvolvedores, incluindo as para recursos de extensões da WindowManager. A biblioteca WindowManager carrega automaticamente as extensões no processo do aplicativo e agrupa as APIs Extensions de nível inferior em abstrações de nível superior e interfaces mais focadas. As APIs WindowManager do Jetpack seguem os padrões de desenvolvimento moderno de aplicativos Android e têm como objetivo oferecer interoperabilidade conveniente ao se integrarem bem com bases de código que usam outras bibliotecas do AndroidX.

Versões e atualizações das extensões

O módulo de extensões pode ser atualizado junto com as atualizações anuais ou trimestrais da plataforma Android. As atualizações trimestrais permitem que o nível da API Extensions seja aumentado entre as atualizações da API da plataforma Android, permitindo iterações mais rápidas e oferecendo aos OEMs a oportunidade de adicionar acesso oficial da API a novos recursos perto dos lançamentos de hardware.

A tabela a seguir lista as versões da API androidx.window.extensions para várias versões do Android.

Versão da plataforma Android Nível da API Extensions do WindowManager Versão da API androidx.window.extensions
Android 15 6 1.5.0 (em breve)
Android 14 QPR3 5 1.4.0 (em breve)
Android 14 QPR1 4 1.3.0
Android 14 3 1.2.0
Android 13 QPR3 2 1.1.0
Android 13 1 1.0.0
Android 12L 1 1.0.0

O nível da API Extensions (coluna central) é aumentado sempre que há uma adição à superfície de API estável (coluna à direita).

Compatibilidade com versões anteriores e futuras

O Jetpack WindowManager lida com a complexidade de lidar com atualizações frequentes do nível da API, evolução rápida da API e compatibilidade com versões anteriores. Quando o código da biblioteca é executado no processo do aplicativo, ela verifica o nível declarado da API Extensions e fornece acesso aos recursos de acordo com o nível declarado.

Para evitar que um aplicativo falhe no momento da execução, o WindowManager também executa uma verificação de reflexão Java no momento da execução das APIs Extensions disponíveis de acordo com o nível declarado da API Extensions. Se houver uma incompatibilidade, o WindowManager poderá desativar o uso de extensões (parcial ou completamente) e informar que os recursos relevantes não estão disponíveis para o aplicativo.

As extensões do WindowManager são implementadas como um módulo system_ext que usa APIs de plataforma privadas para chamar o núcleo do WindowManager, DeviceStateManager e outros serviços do sistema na implementação dos recursos das extensões.

A compatibilidade pode não ser mantida com versões de pré-lançamento das extensões antes da versão trimestral ou anual correspondente da plataforma Android em que as versões são finalizadas. O histórico completo das APIs Extensions pode ser encontrado nos arquivos de texto da API window:extensions:extensions da versão.

As versões mais recentes das extensões precisam continuar funcionando com versões mais antigas do WindowManager compiladas em aplicativos para manter a compatibilidade futura. Para garantir isso, qualquer nova versão da API Extensions só adiciona novas APIs e não remove as versões mais antigas. Como resultado, os aplicativos com versões mais antigas do WindowManager podem continuar usando as APIs Extensions mais antigas com que os apps foram compilados.

A verificação do CTS garante que, para qualquer versão declarada das APIs de extensão no dispositivo, todas as APIs para essa e versões anteriores estejam presentes e funcionando.

Desempenho

O módulo de extensões é armazenado em cache em carregadores de classe do sistema que não são bootclasspath por padrão a partir do Android 14 (nível 34 da API). Portanto, não há impacto no desempenho devido ao carregamento do módulo na memória na inicialização do app. O uso de recursos de módulos individuais pode ter uma pequena influência nas características de desempenho dos apps quando outras chamadas de IPC são realizadas entre o cliente e o servidor.

Módulos

Incorporação de atividades

O componente de incorporação de atividades permite que os aplicativos otimizem a interface para dispositivos de tela grande e telas externas. A incorporação de atividades permite a apresentação de duas atividades lado a lado em um layout de vários painéis, facilitando o desenvolvimento de apps adaptáveis para aplicativos legados.

O componente de incorporação de atividades precisa estar disponível em todos os dispositivos com uma tela integrada igual ou maior que sw600dp. A incorporação de atividades também precisa ser ativada em dispositivos com suporte a conexões de tela externa, já que o app pode ser mostrado em um tamanho maior quando as telas externas são conectadas no momento da execução.

Configuração do dispositivo

Nenhuma configuração específica do dispositivo é necessária, exceto ativar o módulo de extensões, conforme descrito na seção Distribuição do módulo de extensões. É recomendável ativar as extensões em todos os dispositivos com suporte ao modo de várias janelas. Futuras versões do Android provavelmente vão exigir extensões em configurações comuns de dispositivos portáteis e de tela grande.

Informações sobre o layout da janela

O componente de informações do layout da janela identifica a posição e o estado da dobradiça em um dispositivo dobrável quando ela cruza uma janela do aplicativo. As informações de layout da janela permitem que os aplicativos respondam e mostrem layouts otimizados no modo de mesa em dispositivos dobráveis. Consulte Fazer com que seu app reconheça um dispositivo dobrável para conferir detalhes de uso.

Dispositivos Android dobráveis que incluem uma articulação que conecta áreas separadas ou contínuas do painel de exibição precisam disponibilizar as informações sobre a articulação para os aplicativos usando WindowLayoutComponent.

A posição e os limites da articulação precisam ser informados em relação à janela do aplicativo identificada por um Context transmitido para a API. Se os limites da janela do aplicativo não se cruzarem com os limites da articulação, a articulação DisplayFeature não poderá ser informada. Também é aceitável não informar os recursos de exibição quando a posição deles não puder ser informada com confiabilidade, como quando uma janela do aplicativo pode ser movida livremente pelo usuário no modo de várias janelas ou no modo de letterbox de compatibilidade.

Para recursos de dobramento, as atualizações de estado precisam ser informadas quando a posição da articulação muda entre os estados estáveis. Por padrão, em um estado de exibição plano, a API precisa informar FoldingFeature.State.FLAT. Se o hardware do dispositivo puder ser deixado em um modo semidobrado em um estado estável, a API precisará informar FoldingFeature.State.HALF_OPENED. Não há um estado fechado na API, já que, nesse caso, a janela do aplicativo não estaria visível ou não estaria cruzando os limites da articulação.

Configuração do dispositivo

Para oferecer suporte à implementação do recurso de dobramento, os OEMs precisam fazer o seguinte:

  • Configure os estados do dispositivo em device_state_configuration.xml para serem usados por DeviceStateManagerService. Consulte DeviceStateProviderImpl.java para referência.

    Se as implementações padrão de DeviceStateProvider ou DeviceStatePolicy não forem adequadas para o dispositivo, uma implementação personalizada poderá ser usada.

  • Ative o módulo de extensões conforme descrito na seção Distribuição do módulo de extensões.

  • Especifique o local dos recursos de exibição no recurso de string com.android.internal.R.string.config_display_features (geralmente em frameworks/base/core/res/res/values/config.xml na sobreposição do dispositivo).

    O formato esperado para a string é:

    <type>-[<left>,<top>,<right>,<bottom>]

    O type pode ser fold ou hinge. Os valores de left, top, right e bottom são coordenadas de pixel inteiro no espaço de coordenadas de tela na orientação de tela natural. A string de configuração pode conter vários recursos de exibição separados por ponto e vírgula.

    Exemplo:

    <!-- Jetpack WindowManager display features -->
    <string name="config_display_features" translatable="false">fold-[1000,0,1000,2000]</string>
    
  • Define o mapeamento entre os identificadores de estado do dispositivo interno usados em DeviceStateManager e as constantes de estado públicas enviadas aos desenvolvedores em com.android.internal.R.array.config_device_state_postures.

    O formato esperado para cada entrada é:

    <device_specific_state_identifier>:<Jetpack WindowManager state identifier>

    Os identificadores de estado aceitos são:

    • COMMON_STATE_NO_FOLDING_FEATURES = 1: o estado não tem recursos de dobramento para informar. Por exemplo, pode ser o estado fechado do dispositivo dobrável típico com a tela principal no lado interno.
    • COMMON_STATE_HALF_OPENED = 2: o recurso de dobra está meio aberto.
    • COMMON_STATE_FLAT = 3: o recurso de dobra está plano. Por exemplo, pode ser o estado aberto do dispositivo dobrável típico com a tela principal no lado interno.
    • COMMON_STATE_USE_BASE_STATE = 1000: no Android 14, um valor que pode ser usado para estados emulados em que o estado da articulação é derivado usando o estado base, conforme definido em CommonFoldingFeature.java.

    Consulte DeviceStateManager.DeviceStateCallback#onBaseStateChanged(int) para mais informações.

    Exemplo:

    <!-- Map of System DeviceState supplied by DeviceStateManager to WindowManager posture.-->
    <string-array name="config_device_state_postures" translatable="false">
      <item>0:1</item>    <!-- CLOSED       : COMMON_STATE_NO_FOLDING_FEATURES -->
      <item>1:2</item>    <!-- HALF_OPENED  : COMMON_STATE_HALF_OPENED -->
      <item>2:3</item>    <!-- OPENED       : COMMON_STATE_FLAT -->
      <item>3:1</item>    <!-- REAR_DISPLAY : COMMON_STATE_NO_FOLDING_FEATURES -->
      <item>4:1000</item> <!-- CONCURRENT   : COMMON_STATE_USE_BASE_STATE -->
    </string-array>
    

Área da janela

O componente de área da janela fornece um conjunto de recursos que dão aos aplicativos acesso a outras telas e áreas de exibição em alguns dispositivos dobráveis e multitelas.

O modo de tela traseira permite que um aplicativo mostre a interface de visualização da câmera na tela de cobertura de um dispositivo dobrável para permitir o uso da câmera principal para selfies e vídeos. Dispositivos com uma tela compatível com o Android (conforme definido pelo CDD do Android em termos de atributos, como tamanho, densidade e recursos de navegação disponíveis) que cobrem a tela que se alinha com as câmeras traseiras do dispositivo precisam fornecer acesso ao modo de tela traseira.

No Android 14, o modo Dual Screen permite que apps executados na tela interna de um dispositivo dobrável mostrem mais conteúdo na tela de cobertura voltada para outros usuários. Por exemplo, a tela de cobertura pode mostrar a visualização da câmera para a pessoa que está sendo fotografada ou gravada.

Configuração do dispositivo

Para oferecer suporte à implementação do recurso de dobramento, os OEMs precisam fazer o seguinte:

  • Configure os estados do dispositivo em device_state_configuration.xml para serem usados por DeviceStateManagerService. Consulte DeviceStateProviderImpl.java para mais informações.

    Se a implementação padrão de DeviceStateProvider ou DeviceStatePolicy não for adequada para o dispositivo, uma implementação personalizada poderá ser usada.

  • Para dispositivos dobráveis compatíveis com o modo aberto ou plano, especifique os identificadores de estado correspondentes em com.android.internal.R.array.config_openDeviceStates.

  • Para dispositivos dobráveis que oferecem suporte a estados dobrados, liste os identificadores de estado correspondentes em com.android.internal.R.array.config_foldedDeviceStates.

  • Para dispositivos dobráveis que oferecem suporte a um estado meio dobrado (a dobradiça está aberta pela metade, como um laptop), liste os estados correspondentes em com.android.internal.R.array.config_halfFoldedDeviceStates.

  • Para dispositivos com suporte ao modo de tela traseira:

    • Liste os estados correspondentes em com.android.internal.R.array.config_rearDisplayDeviceStates para DeviceStateManager.
    • Especifique o endereço da tela física traseira em com.android.internal.R.string.config_rearDisplayPhysicalAddress.
    • Especifique o identificador de estado em com.android.internal.R.integer.config_deviceStateRearDisplay para ser usado pelas extensões.
    • Adicione o identificador de estado em com.android.internal.R.array.config_deviceStatesAvailableForAppRequests para disponibilizá-lo aos aplicativos.
  • No Android 14, para dispositivos com suporte ao modo de tela dupla (simultâneo):

    • Defina com.android.internal.R.bool.config_supportsConcurrentInternalDisplays como true.
    • Especifique o endereço da tela física traseira em com.android.internal.R.config_deviceStateConcurrentRearDisplay.
    • Especifique o identificador de estado em com.android.internal.R.integer.config_deviceStateConcurrentRearDisplay para ser usado pelas extensões, se o identificador for disponibilizado para aplicativos.
    • Adicione o identificador de estado em com.android.internal.R.array.config_deviceStatesAvailableForAppRequests para disponibilizá-lo aos aplicativos.

Verificação

Os OEMs precisam verificar as implementações para garantir o comportamento esperado em cenários comuns. Os testes do CTS e os testes que usam a Jetpack WindowManager estão disponíveis para OEMs para testar implementações.

Testes CTS

Para executar os testes do CTS, consulte Executar testes do CTS. Os testes CTS relacionados ao Jetpack WindowManager estão em cts/tests/framework/base/windowmanager/jetpack/. O nome do módulo de teste é CtsWindowManagerJetpackTestCases.

Testes do WindowManager

Para fazer o download dos testes do Jetpack WindowManager, siga as instruções do Android Jetpack. Os testes estão localizados na biblioteca de janelas no módulo window:window: window/window/src/androidTest/.

Para executar os testes de dispositivo do módulo window:window na linha de comando, faça o seguinte:

  1. Conecte um dispositivo com as opções do desenvolvedor e a depuração USB ativadas.
  2. Permitir que o computador depure o dispositivo.
  3. Abra um shell no diretório raiz do repositório androidx.
  4. Mude o diretório para framework/support.
  5. Execute o seguinte comando: ./gradlew window:window:connectedAndroidTest.
  6. Analise os resultados.

Para executar os testes no Android Studio, faça o seguinte:

  1. Abra o Android Studio.
  2. Conecte um dispositivo com as opções do desenvolvedor e a depuração USB ativadas.
  3. Permitir que o computador depure o dispositivo.
  4. Navegue até um teste na biblioteca de janelas do módulo de janela.
  5. Abra uma classe de teste e execute usando as setas verdes no lado direito do editor.

Como alternativa, você pode criar uma configuração no Android Studio para executar um método de teste, uma classe de teste ou todos os testes em um módulo.

Os resultados podem ser analisados manualmente, observando a saída do shell. Alguns testes são pulados se o dispositivo não atender a determinadas suposições. Os resultados são salvos em um local padrão, e os analistas podem escrever um script para automatizar a análise dos resultados.