Compatibilidade com decorações do sistema

Confira abaixo as atualizações feitas nessas áreas específicas da Rede de Display:

Decorações do sistema

O Android 10 adiciona suporte à configuração de funções para mostrar certas decorações do sistema, como plano de fundo, barra de navegação, e acesso rápido. Por padrão, a tela principal mostra todas as decorações do sistema. telas secundárias mostram as opções ativadas. Suporte a um editor de método de entrada (IME) pode ser definido separadamente de outras decorações do sistema.

Usar o DisplayWindowSettings#setShouldShowSystemDecorsLocked() para adicionar suporte a decorações de sistema em uma tela específica ou fornecer um valor padrão em /data/system/display_settings.xml. Por exemplo, consulte as Configurações da janela de exibição.

Implementação

A DisplayWindowSettings#setShouldShowSystemDecorsLocked() também está exposta em WindowManager#setShouldShowSystemDecors() para teste. Acionamento deste método com a intenção de permitir decorações do sistema não adiciona janelas de decoração que foram que estavam ausentes ou removeram aqueles que estavam presentes. Na maioria casos, a mudança no suporte de decorações do sistema entrará em vigor somente após um o dispositivo será reinicializado.

Verifica o suporte a decorações do sistema na base de código da WindowManager geralmente passam por DisplayContent#supportsSystemDecorations() enquanto Verifica se há serviços externos (como a interface do sistema para conferir se a barra de navegação deve ser exibido), use WindowManager#shouldShowSystemDecors(). Para entender o que é controlado por essa configuração, explore os pontos de chamada de esses métodos.

Janelas de decoração da interface do sistema

O Android 10 adiciona suporte a janelas de decoração do sistema para a barra de navegação apenas, porque a barra de navegação é essencial para navegar entre atividades e apps. Por padrão, a barra de navegação mostra affordances "Voltar" e "Home". Isso será incluído somente se a tela de destino oferecer suporte decorações do sistema (consulte DisplayWindowSettings).

A barra de status é uma janela do 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, as notificações, configurações e um bloqueio de teclado completo estão disponíveis apenas no tela principal.

A janela do sistema Overview/Recents não tem suporte em contas secundárias telas. No Android 10, o AOSP só exibe Recentes na exibição padrão e contém atividades de todas as telas. Quando iniciado pelo Recentes: uma atividade que estava em uma tela secundária é mostrada para a frente exibidos, por padrão. Essa abordagem tem alguns problemas conhecidos, atualizando imediatamente quando aplicativos aparecem em outras telas.

Implementação

Para implementar recursos adicionais de interface do sistema, os fabricantes de dispositivos devem usar uma único componente de interface do sistema que detecta a adição/remoção de telas e apresenta conteúdo apropriado.

Um componente de interface do sistema compatível com várias telas (MD, na sigla em inglês) deve lidar com o seguintes casos:

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

Quando a interface do sistema detecta a adição de uma tela antes da WindowManager, ela cria uma condição de corrida. Para evitar isso, implemente um callback personalizado da WindowManager para a interface do sistema quando uma tela é adicionada em vez da assinatura DisplayManager.DisplayListener. Para uma implementação de referência, consulte CommandQueue.Callbacks#onDisplayReady para suporte à barra de navegação e WallpaperManagerInternal#onDisplayReady para planos de fundo.

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.
  • O TYPE_NAVIGATION_BAR não está mais restrito a um único 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 com suporte as decorações do sistema têm uma pilha de início dedicada para atividades da tela de início com tipo WindowConfiguration#ACTIVITY_TYPE_HOME, por padrão. Cada tela usa uma instância separada da atividade da tela de início.

Figura 1. Exemplo de tela de início com várias telas para platform/development/samples/MultiDisplay

A maioria das telas de início atuais não é compatível com várias instâncias e não é otimizada para tamanhos de tela grandes. Além disso, normalmente se espera um tipo diferente de experiência em telas secundárias/externas. Para fornecer uma atividade dedicada para atividades telas, o Android 10 introduz a categoria SECONDARY_HOME na intent filtros. Instâncias desta atividade são usadas em todas as telas que oferecem suporte ao sistema decorações, uma por 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ários instâncias e espera-se que se adapte a diferentes tamanhos de tela. 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 onde a tela inicial é iniciada. RootActivityContainer#resolveSecondaryHomeActivity() contém a lógica para procurar o componente de atividade do iniciador, dependendo do tela de início selecionada 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 a possibilidade de um app malicioso criar uma tela virtual com o recurso Decorações do sistema e lendo informações sensíveis do usuário a partir da superfície, a tela de início só aparece em telas virtuais de propriedade do sistema. A tela de início não mostra conteúdo e 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 nas partes interna (acima) e externa exibe (abaixo)

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

O framework cria uma instância WallpaperService.Engine por tela, de modo que cada mecanismo tem uma superfície e um contexto de exibição próprios. A o desenvolvedor precisa ter certeza de que cada mecanismo pode ser executado de maneira independente, diferentes frame rates, respeitando o 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 exibição estável necessário para manter as configurações de plano de fundo por tela. 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 um implementação 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. O WallpaperManager é extraído de um Context objeto, e cada Context tem informações sobre os objetos tela (Context#getDisplay()/getDisplayId()). Assim, você pode acessar displayId de uma instância de WallpaperManager sem adicionar novos métodos.
  3. No lado do framework, use o displayId recebido de um objeto Context e o mapeie 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 existentes para seletores de plano de fundo. Se foi aberto em uma tela específica e usa o contexto certo, quando chamadas para definir um plano de fundo, o sistema poderá identificar a tela automaticamente.

Se for necessário definir um plano de fundo para uma tela diferente do atual exibição e, em seguida, criar um novo objeto Context para a exibição de destino (Context#createDisplayContext) e conseguir o 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 se deve a uma preocupação de segurança de que um aplicativo malicioso tela com decorações ativadas do sistema e ler uma mensagem informações da superfície (como uma foto pessoal).

Implementação

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

Algumas das implementações públicas do método WallpaperManager (como WallpaperManager#getDesiredMinimumWidth()) foram atualizados para calcular e fornecer informações para exibições correspondentes. WallpaperInfo#supportsMultipleDisplays() e um atributo de recurso foi adicionado, 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 várias telas, o sistema mostrará o plano de fundo padrão na é exibido.

Figura 3. Lógica de substituição de plano de fundo para telas secundárias