Compatibilidade com decorações do sistema

Confira abaixo as atualizações feitas nessas áreas específicas de exibição:

Decorações do sistema

O Android 10 adiciona suporte para configurar telas secundárias para mostrar determinadas decorações do sistema, como plano de fundo, barra de navegação e tela de início. Por padrão, a tela principal mostra todas as decorações do sistema, e as telas secundárias mostram as que estão ativadas. O suporte a um editor de método de entrada (IME) pode ser definido separadamente de outras decorações do sistema.

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

Implementação

O DisplayWindowSettings#setShouldShowSystemDecorsLocked() também é exposto em WindowManager#setShouldShowSystemDecors() para testes. Acionar esse método com a intenção de ativar decorações do sistema não adiciona janelas de decoração que estavam ausentes anteriormente nem as remove se elas estavam presentes. Na maioria dos casos, a mudança no suporte a decorações do sistema só entra em vigor após a reinicialização do dispositivo.

As verificações de suporte a decorações do sistema na base de código da WindowManager geralmente passam por DisplayContent#supportsSystemDecorations(), enquanto as verificações de serviços externos (como a interface do sistema para conferir se a barra de navegação precisa 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 IU do sistema

O Android 10 adiciona suporte a janelas de decoração do sistema apenas para a barra de navegação, porque ela é essencial para navegar entre atividades e apps. Por padrão, a barra de navegação mostra as affordances "Voltar" e "Página inicial". Essa inclusão só será incluída se a tela de destino oferecer suporte a decorações do sistema (consulte DisplayWindowSettings).

A barra de status é uma janela do sistema mais complicada, porque também contém a aba de notificações, as configurações rápidas e a tela de bloqueio. No Android 10, a barra de status não tem suporte para telas secundárias. Portanto, as notificações, as configurações e a proteção de teclado completa estão disponíveis apenas na tela principal.

A janela do sistema Visão geral/Recentes não tem suporte em telas secundárias. No Android 10, o AOSP só mostra Recents na tela padrão e contém atividades de todas as telas. Quando iniciada a partir de "Recentes", uma atividade que estava em uma tela secundária é mostrada na parte frontal dessa tela por padrão. Essa abordagem tem alguns problemas conhecidos, como não atualizar imediatamente quando os apps aparecem em outras telas.

Implementação

Para implementar outros recursos da IU do sistema, os fabricantes de dispositivos precisam usar um único componente da IU do sistema que detecta a adição/remoção de telas e apresenta o conteúdo apropriado.

Um componente da IU do sistema que oferece suporte a várias telas (MD, na sigla em inglês) precisa processar os seguintes casos:

  • Inicialização de várias telas na inicialização
  • Tela adicionada durante a execução
  • Tela removida no momento da execução

Quando a interface do sistema detecta a adição de uma tela antes da WindowManager, ela cria uma condição de corrida. Isso pode ser evitado implementando um callback personalizado do WindowManager para a interface do sistema quando uma tela é adicionada em vez de se inscrever em 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 oferece estas atualizações:

  • A classe NavigationBarController controla todas as funcionalidades específicas para barras de navegação.
  • Para conferir 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 tela.
  • IWindowManager#hasNavigationBar() foi atualizado para incluir o parâmetro displayId apenas para a interface do sistema.

Tela de início

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

Figura 1. Exemplo de inicializador de várias telas para platform/development/samples/MultiDisplay

A maioria das telas de início atuais não oferece suporte a várias instâncias e não é otimizada para tamanhos de tela grandes. Além disso, um tipo diferente de experiência é esperado em telas secundárias/externas. Para fornecer uma atividade dedicada para telas secundárias, o Android 10 apresenta a categoria SECONDARY_HOME em filtros de intent. As instâncias dessa atividade são usadas em todas as telas compatíveis com decorações do sistema, uma para cada tela.

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

A atividade precisa ter um modo de inicialização que não impeça várias instâncias e que possa 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 intent desejados, dependendo da tela em que a tela inicial é iniciada. RootActivityContainer#resolveSecondaryHomeActivity() contém a lógica para procurar o componente de atividade da tela de início, dependendo da tela de início selecionada 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 telas secundárias, para evitar que um app malicioso crie uma tela virtual com decorações do sistema ativadas e leia informações sensíveis do usuário da plataforma, o iniciador aparece apenas em telas virtuais pertencentes ao sistema. O iniciador não exibe conteúdo em telas virtuais que não são do sistema.

Planos de fundo

No Android 10 (e versões mais recentes), os planos de fundo têm suporte em telas secundárias:

Figura 2. Plano de fundo interativo em telas internas (acima) e externas (abaixo)

Os desenvolvedores podem declarar suporte ao recurso de plano de fundo fornecendo android:supportsMultipleDisplays="true" na definição XML WallpaperInfo. Os desenvolvedores de plano de fundo também precisam carregar recursos usando o contexto de exibição em WallpaperService.Engine#getDisplayContext().

O framework cria uma instância de WallpaperService.Engine por tela, de modo que cada mecanismo tenha a própria superfície e contexto de exibição. O desenvolvedor precisa garantir que cada mecanismo possa ser renderizado de forma independente, em taxas de frames diferentes, respeitando a VSYNC.

Selecionar planos de fundo para telas individuais

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

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

  1. Use a API WallpaperManager para definir os planos de fundo.
  2. WallpaperManager é obtido de um objeto Context, e cada objeto Context tem informações sobre a tela correspondente (Context#getDisplay()/getDisplayId()). Portanto, é possível extrair displayId de uma instância WallpaperManager sem adicionar novos métodos.
  3. No framework, use displayId obtido de um objeto Context e mapeie-o para um identificador estático (como uma porta de uma tela física). Use o identificador estático para manter o plano de fundo escolhido.

Essa solução alternativa usa implementações atuais para seletores de plano de fundo. Se ele for aberto em uma tela específica e usar o contexto correto, quando ele for chamado para definir um plano de fundo, o sistema poderá identificar automaticamente a tela.

Se for necessário definir o plano de fundo para uma tela que não seja a atual, crie um novo objeto Context para a tela de destino (Context#createDisplayContext) e receba a instância WallpaperManager dessa tela.

Restrições de segurança

O sistema não vai mostrar planos de fundo em telas virtuais que não sejam dele. Isso ocorre devido a uma preocupação de segurança de que um app malicioso possa criar uma tela virtual com suporte a decorações do sistema ativadas e ler informações sensíveis do usuário na superfície (como uma foto pessoal).

Implementação

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

Algumas das implementações de método WallpaperManager públicas (como WallpaperManager#getDesiredMinimumWidth()) foram atualizadas para calcular e fornecer informações para as exibições correspondentes. A WallpaperInfo#supportsMultipleDisplays() e um atributo de recurso correspondente foram adicionados para que os desenvolvedores de apps possam informar quais planos de fundo estão prontos para várias telas.

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

Figura 3. Lógica de plano de fundo alternativo para telas secundárias