Suporte para decorações do sistema

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

Decorações do sistema

O Android 10 adiciona suporte para configurar monitores secundários para mostrar determinadas decorações do sistema, como papel de parede, barra de navegação e iniciador. Por padrão, a tela principal mostra todas as decorações do sistema e as telas secundárias mostram aquelas ativadas opcionalmente. O suporte para um Input Method Editor (IME) pode ser definido separadamente de outras decorações do sistema.

Use DisplayWindowSettings#setShouldShowSystemDecorsLocked() para adicionar suporte para decorações do sistema em uma exibição específica ou fornecer 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 deste método com a intenção de ativar decorações do sistema não adiciona janelas de decoração que estavam faltando anteriormente, nem as remove se estivessem presentes anteriormente. Na maioria dos casos, a alteração do suporte às decorações do sistema só entra em vigor após a reinicialização do dispositivo.

As verificações de suporte de decorações do sistema na base de código do WindowManager geralmente passam por DisplayContent#supportsSystemDecorations() enquanto as verificações de serviços externos (como a 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 IU 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 possibilidades Voltar e Início. Isso será incluído somente se a exibição de destino suportar decorações do sistema (consulte DisplayWindowSettings ).

A barra de status é uma janela do sistema mais complicada, porque também contém Notification Shade, Quick Settings e Lock Screen. No Android 10, a barra de status não é compatível com monitores secundários. Portanto, notificações, configurações e proteção completa do teclado estão disponíveis apenas na tela principal.

A janela do sistema Visão geral/Recentes não é suportada em telas secundárias. No Android 10, o AOSP exibe apenas Recentes na tela padrão e contém atividades de todas as telas. Quando iniciada em Recentes, uma atividade que estava em uma tela secundária é trazida para a frente dessa tela, por padrão. Essa abordagem apresenta alguns problemas conhecidos, como a não atualização imediata quando os aplicativos aparecem em outras telas.

Implementação

Para implementar recursos adicionais da UI do sistema, os fabricantes de dispositivos devem usar um único componente da UI do sistema que detecte a adição/remoção de exibições e apresente o conteúdo apropriado.

Um componente de UI do sistema que suporta Multi-Display (MD) deve lidar com os seguintes casos:

  • Inicialização de vários monitores na inicialização
  • Display adicionado em tempo de execução
  • Tela removida em tempo de execução

Quando a UI 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 UI do sistema quando um display é adicionado em vez de assinar eventos DisplayManager .DisplayListener . Para obter 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 display.
  • IWindowManager#hasNavigationBar() é atualizado para incluir o parâmetro displayId apenas para a UI do sistema.

Lançador

No Android 10, cada monitor configurado para suportar 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 iniciador de vários monitores para platform/development/samples/MultiDisplay

A maioria dos inicializadores existentes não oferece suporte a múltiplas instâncias e não são otimizados para telas 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 introduz a categoria SECONDARY_HOME nos filtros de intent. As instâncias desta atividade são usadas em todos os monitores que suportam 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 múltiplas instâncias e se adapte 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 tela onde a tela inicial é iniciada. RootActivityContainer#resolveSecondaryHomeActivity() contém a lógica para procurar o componente de atividade do inicializador dependendo do inicializador atualmente selecionado 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 às atividades em monitores secundários, para evitar a possibilidade de um aplicativo malicioso 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 de propriedade do sistema. O iniciador 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 monitores secundários:

Figura 2. Papel de parede animado 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 WallpaperInfo . Espera-se também que os desenvolvedores de papéis de parede carreguem ativos usando o contexto de exibição em WallpaperService.Engine#getDisplayContext() .

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

Selecione papéis de parede para telas individuais

O Android 10 não oferece suporte direto de plataforma para seleção de papéis de parede para telas individuais. Para conseguir isso, é necessário um identificador de exibição estável para manter as configurações de papel de parede por exibição. Display#getDisplayId() é dinâmico, portanto 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 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 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 um display específico e usa o contexto correto, quando chamar para definir um papel de parede, o sistema poderá identificar automaticamente o display.

Se houver necessidade de definir 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 monitores 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 do sistema habilitado e ler informações confidenciais 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 display. WallpaperManagerService.DisplayConnector encapsula um mecanismo de papel de parede por exibição 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 suportar vários monitores, o sistema mostrará o papel de parede padrão nas telas secundárias.

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