Extensões do WindowManager

A biblioteca Jetpack WindowManager permite que os desenvolvedores de aplicativos ofereçam suporte a novos formatos de dispositivos e ambientes de múltiplas janelas.

WindowManager Extensions (Extensões) é um módulo opcional da plataforma Android que permite uma variedade de recursos do Jetpack WindowManager. O módulo é implementado no AOSP em frameworks/base/libs/WindowManager/Jetpack e enviado em dispositivos que suportam os 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 em um dispositivo se as extensões estiverem habilitadas no makefile do dispositivo.

Para ativar 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-os para processos de aplicação. Normalmente os módulos são carregados e executados como parte do processo da aplicação em tempo de execução quando usados ​​pela biblioteca Jetpack WindowManager, o que torna sua operação semelhante ao código da estrutura do lado do cliente, conforme mostrado na figura a seguir:

Figura 1. Extensões do WindowManager carregadas no processo de aplicação 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 fornecem recursos de janelas para dispositivos dobráveis ​​de tela grande e dispositivos que suportam janelas em monitores externos. As áreas de recursos incluem:

Implementações 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 suportar os 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 WindowManager Extensions fornece sua própria superfície de API, além das APIs da plataforma pública. O módulo Extensions é desenvolvido publicamente em uma biblioteca Jetpack androidx.window.extensions que não é voltada para desenvolvedores, para que o Jetpack WindowManager ( androidx.window ) possa vincular-se a ele em tempo de compilação. A superfície da API de extensões normalmente fornece APIs de nível inferior.

As APIs fornecidas pelas extensões devem ser usadas apenas pela biblioteca Jetpack WindowManager. As APIs de extensões não devem ser chamadas diretamente pelos desenvolvedores de aplicativos. A biblioteca de extensões não deve ser adicionada como uma dependência de um aplicativo no arquivo de compilação do Gradle para garantir a funcionalidade correta. Evite pré-compilar a biblioteca de extensões diretamente em um aplicativo; em vez disso, confie no carregamento do tempo de execução para evitar o caso de carregar uma combinação de classes de extensões pré-compiladas e fornecidas em tempo de execução.

O Jetpack WindowManager ( androidx.window ) deve ser adicionado como uma dependência do aplicativo e fornece APIs públicas voltadas para o desenvolvedor, incluindo aquelas para recursos de extensões do WindowManager. A biblioteca WindowManager carrega extensões automaticamente no processo do aplicativo e agrupa as APIs de extensões de nível inferior em abstrações de nível superior e interfaces mais focadas. As APIs WindowManager Jetpack seguem os padrões de desenvolvimento de aplicativos Android modernos e têm como objetivo fornecer interoperabilidade conveniente, integrando-se bem com bases de código que usam outras bibliotecas AndroidX.

Versões e atualizações de extensões

O módulo 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 de extensões seja aumentado entre as atualizações da API da plataforma Android, permitindo uma iteração mais rápida e fornecendo aos OEMs a oportunidade de adicionar acesso oficial à API a novos recursos próximo ao lançamento de hardware.

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

Versão da plataforma Android Nível da API de extensões do WindowManager Versão da API androidx.window.extensions
Andróide 14 3 1.2.0
Android 13 QPR3 2 1.1.0
Andróide 13 1 1.0.0
Android 12L 1 1.0.0

O nível da API de extensões (coluna central) aumenta sempre que há uma adição à superfície da API estável existente (coluna da direita).

Compatibilidade com versões anteriores e futuras

O Jetpack WindowManager lida com a complexidade de lidar com atualizações frequentes no 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 de aplicação, a biblioteca verifica o nível declarado da API de extensões e fornece acesso aos recursos de acordo com o nível declarado.

Para proteger um aplicativo contra travamentos em tempo de execução, o WindowManager também executa uma verificação de reflexão Java em tempo de execução das APIs de extensões disponíveis de acordo com o nível de API de extensões declarado. Se houver uma incompatibilidade, o WindowManager pode desabilitar o uso de extensões (parcial ou completamente) e relatar os recursos relevantes como não disponíveis para o aplicativo.

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

A compatibilidade pode não ser mantida com versões de pré-lançamento de Extensões anteriores ao lançamento trimestral ou anual da plataforma Android correspondente com o qual as versões são finalizadas. O histórico completo das APIs de extensões pode ser encontrado no branch de lançamento window:extensions:extensions API text files .

As versões mais recentes das extensões devem 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 de extensões apenas adiciona novas APIs e não remove as mais antigas. Como resultado, os aplicativos com versões mais antigas do WindowManager podem continuar usando as APIs de extensões mais antigas nas quais os aplicativos foram compilados.

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

Desempenho

O módulo Extensions é armazenado em cache em carregadores de classes do sistema que não são bootclasspath por padrão, começando com o Android 14 (API de nível 34), portanto, não há impacto no desempenho devido ao carregamento do módulo na memória na inicialização do aplicativo. O uso de recursos de módulos individuais pode ter uma ligeira influência nas características de desempenho dos aplicativos quando chamadas IPC adicionais são realizadas entre o cliente e o servidor.

Módulos

Incorporação de atividades

O componente de incorporação de atividades fornece um conjunto de recursos que permitem que os aplicativos organizem a apresentação da janela de atividades dentro dos limites do aplicativo pai. Isso inclui mostrar duas atividades simultaneamente, lado a lado, em um layout de vários painéis, facilitando a otimização de telas grandes para aplicativos legados.

O componente de incorporação de atividades deve estar disponível em todos os dispositivos que possuem uma tela integrada de tamanho igual ou maior que sw600 dp . A incorporação de atividades também deve ser habilitada em dispositivos que suportam conexões de monitores externos, pois o aplicativo pode ser mostrado em um tamanho maior quando monitores externos são conectados em tempo de execução.

Configuração do dispositivo

Nenhuma configuração específica do dispositivo é necessária além de ativar o módulo de extensões conforme descrito na seção Distribuição do módulo de extensões . Faz sentido ativar extensões em todos os dispositivos que suportam o modo de múltiplas janelas. Versões futuras do Android provavelmente exigirão extensões em configurações comuns de dispositivos portáteis e de tela grande.

Informações de layout da janela

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

Dispositivos Android dobráveis ​​que incluem uma dobradiça que conecta áreas do painel de exibição separadas ou contínuas devem disponibilizar as informações sobre a dobradiça para aplicativos por meio de WindowLayoutComponent .

A posição e os limites da dobradiça devem ser relatados em relação à janela do aplicativo identificada por um Context passado para a API. Se os limites da janela do aplicativo não cruzarem com os limites da dobradiça, o DisplayFeature da dobradiça não deverá ser relatado. Também é aceitável não relatar os recursos de exibição quando sua posição não puder ser informada de forma confiável, como quando uma janela de aplicativo pode ser movida livremente pelo usuário no modo de múltiplas janelas ou no modo letterbox de compatibilidade.

Para recursos dobráveis , as atualizações de estado devem ser relatadas quando a posição da dobradiça muda entre os estados estáveis. Por padrão, em um estado de exibição simples, a API deve reportar FoldingFeature.State.FLAT . Se o hardware do dispositivo puder ser deixado no modo meio dobrado em um estado estável, a API deverá relatar FoldingFeature.State.HALF_OPENED . Não há estado fechado na API, pois nesse caso a janela do aplicativo não estaria visível ou não ultrapassaria os limites da dobradiça.

Configuração do dispositivo

Para dar suporte à implementação do recurso dobrável, os OEMs devem fazer o seguinte:

  • Configure os estados do dispositivo em device_state_configuration.xml a 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.

  • Habilite o módulo Extensões conforme descrito na seção Distribuição do módulo 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 de dispositivo).

    O formato esperado para a string é:

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

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

    Por exemplo:

    <!-- Jetpack WindowManager display features -->
    <string name="config_display_features" translatable="false">fold-[1000,0,1000,2000]</string>
    
  • Defina o mapeamento entre os identificadores de estado do dispositivo interno usados ​​em DeviceStateManager e as constantes de estado público 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 suportados são:

    • COMMON_STATE_NO_FOLDING_FEATURES = 1 : o estado não possui recursos de dobramento para relatar. Por exemplo, pode ser o estado fechado de um 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 dobramento é plano. Por exemplo, pode ser o estado aberto de um 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 de dobradiça é derivado usando o estado base, conforme definido em CommonFoldingFeature.java

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

    Por 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 de janela fornece um conjunto de recursos que dão aos aplicativos acesso a telas e áreas de exibição adicionais em alguns dispositivos dobráveis ​​e com vários monitores.

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

No Android 14, o modo de exibição dupla permite que aplicativos executados na tela interna de um dispositivo dobrável mostrem conteúdo adicional na tela externa voltado para outros usuários; por exemplo, a tela externa pode mostrar a visualização da câmera para a pessoa que está sendo fotografada ou gravada.

Configuração do dispositivo

Para dar suporte à implementação do recurso dobrável, os OEMs devem fazer o seguinte:

  • Configure os estados do dispositivo em device_state_configuration.xml a serem usados ​​por DeviceStateManagerService . Consulte DeviceStateProviderImpl.java para obter 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 simples, especifique os identificadores de estado correspondentes em com.android.internal.R.array.config_openDeviceStates .

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

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

  • Para dispositivos compatíveis com o modo de exibição traseira:

    • Liste os estados correspondentes em com.android.internal.R.array.config_rearDisplayDeviceStates para DeviceStateManager .
    • Especifique o endereço de exibição física da tela traseira em com.android.internal.R.string.config_rearDisplayPhysicalAddress .
    • Especifique o identificador de estado em com.android.internal.R.integer.config_deviceStateRearDisplay a 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 compatíveis com o modo de exibição dupla (simultânea):

    • Defina com.android.internal.R.bool.config_supportsConcurrentInternalDisplays como true .
    • Especifique o endereço de exibição física da tela traseira em com.android.internal.R.config_deviceStateConcurrentRearDisplay .
    • Especifique o identificador de estado em com.android.internal.R.integer.config_deviceStateConcurrentRearDisplay a 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 devem verificar suas implementações para garantir o comportamento esperado em cenários comuns. Testes CTS e testes usando Jetpack WindowManager estão disponíveis para OEMs para testar implementações.

Testes CTS

Para executar os testes CTS, consulte Executar testes 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 baixar os 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/window/src/androidTest/ .

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

  1. Conecte um dispositivo que tenha opções de desenvolvedor e depuração USB ativada.
  2. Permita 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 do Android Studio, faça o seguinte:

  1. Abra o Android Studio.
  2. Conecte um dispositivo que tenha opções de desenvolvedor e depuração USB ativada.
  3. Permita 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.

Alternativamente, 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 ignorados 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.