Suporte para decorações do sistema

As atualizações feitas nessas áreas específicas de exibição são fornecidas abaixo:

Decorações do sistema

O Android 10 adiciona suporte para configurar telas secundárias para mostrar certas decorações do sistema, como papel de parede, barra de navegação e inicializador. Por padrão, a tela principal mostra todas as decorações do sistema e as telas secundárias mostram aquelas habilitadas opcionalmente. O suporte para um editor de método de entrada (IME) pode ser definido separadamente de outras decorações do sistema.

Use DisplayWindowSettings#setShouldShowSystemDecorsLocked() para adicionar suporte para decorações do sistema em uma tela específica ou forneça um valor padrão em /data/system/display_settings.xml . Para obter exemplos, consulte Configurações da janela de exibição .

Implementação

DisplayWindowSettings#setShouldShowSystemDecorsLocked() também é exposto em WindowManager#setShouldShowSystemDecors() para teste. O acionamento desse método com a intenção de habilitar as decorações do sistema não adiciona janelas de decoração que estavam ausentes anteriormente, nem as remove se estiverem presentes anteriormente. Na maioria dos casos, a alteração do suporte às decorações do sistema tem efeito total somente após a reinicialização do dispositivo.

As verificações de suporte de decorações do sistema na base de código WindowManager geralmente passam por DisplayContent#supportsSystemDecorations() enquanto verificações de serviços externos (como UI do sistema para verificar se a barra de navegação deve ser mostrada) usam WindowManager#shouldShowSystemDecors() . Para entender o que é controlado por essa configuração, explore os pontos de chamada desses métodos.

Janelas de decoração da interface do usuário do sistema

O Android 10 adiciona suporte à janela de decoração do sistema apenas para a barra de navegação, porque a barra de navegação é essencial para navegar entre atividades e aplicativos. Por padrão, a barra de navegação mostra as affordances Back e Home. Isso é incluído apenas se a exibição de destino oferecer suporte a decorações do sistema (consulte DisplayWindowSettings ).

A barra de status é uma janela de sistema mais complicada, porque também contém Sombra de Notificação, Configurações Rápidas e Tela de Bloqueio. No Android 10, a barra de status não é compatível com telas secundárias. Portanto, notificações, configurações e uma proteção de teclado completa estão disponíveis apenas na tela principal.

A janela do sistema Visão geral/Recentes não é compatível com telas secundárias. No Android 10, o AOSP exibe apenas Recentes na tela padrão e contém atividades de todas as telas. Quando iniciado a partir de Recentes, uma atividade que estava em uma tela secundária é trazida para a frente dessa tela, por padrão. Essa abordagem tem alguns problemas conhecidos, como não atualizar imediatamente quando os aplicativos aparecem em outras telas.

Implementação

Para implementar recursos adicionais da interface do usuário do sistema, os fabricantes de dispositivos devem usar um único componente da interface do usuário do sistema que detecte a adição/remoção de telas e apresente o conteúdo apropriado.

Um componente de interface do usuário do sistema que oferece suporte a vários monitores (MD) deve lidar com os seguintes casos:

  • Inicialização de vários monitores na inicialização
  • Exibição adicionada em tempo de execução
  • Exibição removida em tempo de execução

Quando a interface do usuário do sistema detecta a adição de uma exibição antes do WindowManager, ela cria uma condição de corrida. Isso pode ser evitado implementando um retorno de chamada personalizado do WindowManager para a interface do usuário do sistema quando uma exibição é adicionada em vez de assinar eventos DisplayManager .DisplayListener . Para uma implementação de referência, consulte CommandQueue.Callbacks#onDisplayReady para suporte à barra de navegação e WallpaperManagerInternal#onDisplayReady para papéis de parede.

Além disso, o Android 10 fornece estas atualizações:

  • A classe NavigationBarController controla todas as funcionalidades específicas das barras de navegação.
  • Para visualizar uma barra de navegação personalizada, consulte CarStatusBar .
  • TYPE_NAVIGATION_BAR não está mais restrito a uma única instância e pode ser usado por exibição.
  • IWindowManager#hasNavigationBar() é atualizado para incluir o parâmetro displayId apenas para a interface do usuário do sistema.

Iniciador

No Android 10, cada tela configurada para oferecer suporte a decorações do sistema tem uma pilha inicial dedicada para atividades do iniciador com o tipo WindowConfiguration#ACTIVITY_TYPE_HOME , por padrão. Cada exibição usa uma instância separada da atividade do iniciador.

Figura 1. Exemplo de lançador de vários monitores para platform/development/samples/MultiDisplay

A maioria dos inicializadores existentes não oferece suporte a várias instâncias e não é otimizada para tamanhos de tela grandes. Além disso, muitas vezes é esperado um tipo diferente de experiência em monitores secundários/externos. Para fornecer uma atividade dedicada para telas secundárias, o Android 10 apresenta a categoria SECONDARY_HOME nos filtros de intent. As instâncias desta atividade são usadas em todos os monitores que suportam as decorações do sistema, uma por monitor.

<activity>
    ...
    <intent-filter>
        <category android:name="android.intent.category.SECONDARY_HOME" />
        ...
    </intent-filter>
</activity>

A atividade deve ter um modo de inicialização que não impeça várias instâncias e deve se adaptar a diferentes tamanhos de tela. O modo de inicialização não pode ser singleInstance ou singleTask .

Implementação

No Android 10, RootActivityContainer#startHomeOnDisplay() seleciona automaticamente o componente e a intenção desejados, dependendo da exibição em que a tela inicial é iniciada. RootActivityContainer#resolveSecondaryHomeActivity() contém a lógica para pesquisar o componente de atividade do iniciador dependendo do iniciador selecionado no momento e pode usar o padrão do sistema, se necessário (consulte ActivityTaskManagerService#getSecondaryHomeIntent() ).

Restrições de segurança

Além das restrições que se aplicam a atividades em monitores secundários, para evitar a possibilidade de um aplicativo mal-intencionado criar um monitor virtual com decorações do sistema habilitadas e ler informações confidenciais do usuário na superfície, o inicializador aparece apenas em monitores virtuais pertencentes ao sistema. O inicializador não exibe conteúdo em monitores virtuais que não sejam do sistema.

Papeis de parede

No Android 10 (e superior), os papéis de parede são compatíveis com telas secundárias:

Figura 2. Papel de parede ao vivo em monitores internos (acima) e externos (abaixo)

Os desenvolvedores podem declarar suporte para o recurso de papel de parede fornecendo android:supportsMultipleDisplays="true" na definição XML do WallpaperInfo . Os desenvolvedores de papel de parede também devem carregar ativos usando o contexto de exibição em WallpaperService.Engine#getDisplayContext() .

A estrutura cria uma instância WallpaperService.Engine por exibição, para que cada mecanismo tenha sua própria superfície e contexto de exibição. O desenvolvedor precisa garantir que cada mecanismo possa desenhar de forma independente, em diferentes taxas de quadros, respeitando o VSYNC.

Selecionando papéis de parede para telas individuais

O Android 10 não oferece suporte direto à plataforma para selecionar papéis de parede para telas individuais. Para fazer isso, é necessário um identificador de tela estável para manter as configurações de papel de parede por tela. Display#getDisplayId() é dinâmico, então não há garantia de que um display físico terá o mesmo ID após a reinicialização.

No entanto, o Android 10 adicionou DisplayInfo.mAddress , que contém identificadores estáveis ​​para exibições físicas e pode ser usado para uma implementação completa no futuro. Infelizmente, é tarde demais para implementar a lógica do Android 10. A solução sugerida:

  1. Use a API do WallpaperManager para definir os papéis de parede.
  2. WallpaperManager é obtido de um objeto Context , e cada objeto Context possui informações sobre a exibição correspondente ( Context#getDisplay()/getDisplayId() ). Portanto, você pode obter displayId de uma instância do WallpaperManager sem adicionar novos métodos.
  3. No lado da estrutura, use displayId obtido de um objeto Context e mapeie-o para um identificador estático (como uma porta de um display físico). Use o identificador estático para persistir o papel de parede escolhido.

Esta solução alternativa usa implementações existentes para seletores de papel de parede. Se ele foi aberto em uma tela específica e usa o contexto correto, quando ele chama para definir um papel de parede, o sistema pode identificar automaticamente a tela.

Se houver necessidade de definir o papel de parede para uma exibição diferente da exibição atual, crie um novo objeto Context para a exibição de destino ( Context#createDisplayContext ) e obtenha a instância WallpaperManager dessa exibição.

Restrições de segurança

O sistema não mostrará papéis de parede em telas virtuais que não sejam de sua propriedade. Isso se deve a uma preocupação de segurança de que um aplicativo malicioso possa criar uma exibição virtual com suporte a decorações de sistema habilitadas e ler informações confidenciais do usuário da superfície (como uma foto pessoal).

Implementação

No Android 10, as IWallpaperConnection#attachEngine() e IWallpaperService#attach() aceitam o parâmetro displayId para criar conexões por exibição. WallpaperManagerService.DisplayConnector encapsula um mecanismo de papel de parede por tela e uma conexão. No WindowManager, os controladores de papel de parede são criados para cada objeto DisplayContent na construção, em vez de um único WallpaperController para todos os monitores.

Algumas das implementações públicas do método WallpaperManager (como WallpaperManager#getDesiredMinimumWidth() ) foram atualizadas para calcular e fornecer informações para exibições correspondentes. WallpaperInfo#supportsMultipleDisplays() e um atributo de recurso correspondente foram adicionados, para que os desenvolvedores de aplicativos possam relatar quais papéis de parede estão prontos para várias telas.

Se o serviço de papel de parede mostrado na tela padrão não oferecer suporte a várias telas, o sistema mostrará o papel de parede padrão nas telas secundárias.

Figura 3. Lógica de fallback de papel de parede para monitores secundários