As atualizações feitas nessas áreas específicas da tela são fornecidas nesta página.
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 secundárias mostram aquelas ativadas opcionalmente. É possível definir o suporte para um editor de método de entrada (IME) 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 ver exemplos, consulte Configurações da janela de exibição.
Implementaçã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 nem remove janelas de decoração que estavam
ausentes ou presentes anteriormente. Na maioria dos casos, a mudança de 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 do WindowManager
geralmente passam por DisplayContent#supportsSystemDecorations()
, enquanto
as verificações de serviços externos (como a interface 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, confira 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
para a barra de navegação apenas, porque ela é essencial
para navegar entre atividades e apps. Por padrão, a barra de navegação mostra
as opções "Voltar" e "Início". Isso só será incluído se a tela de destino for compatível com
decorações do sistema (consulte
DisplayWindowSettings
).
A barra de status é uma janela de 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 é 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 só mostra os apps recentes na tela padrão e contém atividades de todas as telas. Quando iniciada na tela "Recentes", uma atividade que estava em uma tela secundária é trazida para a frente nessa 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 interface do sistema, os fabricantes de dispositivos precisam usar um único componente da interface do sistema que detecta a adição ou remoção de telas e apresenta o conteúdo adequado.
Um componente da interface do sistema que oferece suporte a várias telas (MD) precisa processar os seguintes casos:
- Inicialização de várias telas na inicialização
- Tela adicionada durante a execução
- Tela removida durante a execução
Quando a interface do sistema detecta a adição de uma tela antes do WindowManager, ela cria
uma condição de corrida. Para evitar isso, implemente um callback personalizado do
WindowManager para a interface do sistema quando uma tela for adicionada em vez de se inscrever em
eventos DisplayManager.DisplayListener
. Para uma implementação de referência,
consulte CommandQueue.Callbacks#onDisplayAddSystemDecorations
para suporte à barra de navegação
e WallpaperManagerInternal#onDisplayAddSystemDecorations
para planos de fundo.
Além disso, o Android 10 oferece estas atualizações:
- A classe
NavigationBarController
controla todas as funcionalidades específicas das barras de navegação. - Para ver 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()
é atualizado para incluir o parâmetrodisplayId
somente 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 de inicialização com o tipo
WindowConfiguration#ACTIVITY_TYPE_HOME
, por padrão. Cada tela usa uma instância separada da atividade de inicialização:
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 telas grandes. Além disso, um tipo diferente de experiência é esperado em telas secundárias/externas. Para fornecer uma atividade dedicada a telas
secundárias, o Android 10 introduziu a categoria SECONDARY_HOME
em filtros de
intent. 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>
É necessário que a atividade tenha 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, o 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 pesquisar o componente de atividade da tela de início dependendo da tela
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 aplicadas às atividades em telas secundárias, para evitar a possibilidade de um app malicioso criar uma tela virtual com decorações do sistema ativadas e ler informações sensíveis do usuário na superfície, o iniciador só aparece em telas virtuais pertencentes ao sistema. O iniciador não mostra conteúdo em displays virtuais que não são do sistema.
Planos de fundo
No Android 10 e versões mais recentes, os planos de fundo são compatíveis com telas secundárias:
Figura 2. Plano de fundo interativo nas telas interna (acima) e externa (abaixo).
Os desenvolvedores podem declarar suporte ao recurso de papel de parede fornecendo
android:supportsMultipleDisplays="true"
na
definição XML WallpaperInfo
. Os desenvolvedores de papéis de parede também precisam carregar recursos usando o contexto de exibição em WallpaperService.Engine#getDisplayContext()
.
A biblioteca cria uma instância WallpaperService.Engine
por tela. Assim, cada mecanismo tem a 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 frames, respeitando o VSync.
Selecionar planos de fundo para telas individuais
O Android 10 não oferece suporte direto à plataforma para selecionar papéis de parede
para telas individuais. Para isso, é necessário um identificador de tela estável 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 uma implementação
completa no futuro. Infelizmente, é tarde demais para implementar a lógica
no Android 10. A solução sugerida:
- Use a classe
WallpaperManager
para definir os papéis de parede.WallpaperManager
é obtido de um objetoContext
, e cada objetoContext
tem informações sobre a exibição correspondente (Context#getDisplay()/getDisplayId()
). Portanto, é possível obterdisplayId
de uma instânciaWallpaperManager
sem adicionar novos métodos. - No lado do framework, use
displayId
obtido de um objetoContext
e mapeie para um identificador estático, como uma porta de um display físico. 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 foi aberto em uma tela específica e usa o contexto certo, quando ele chama para definir um papel de parede, o sistema pode identificar automaticamente a tela.
Se for necessário definir um plano de fundo para uma tela diferente da atual, crie um novo objeto Context
para a tela de destino (Context#createDisplayContext
) e extraia a instância WallpaperManager
dessa tela.
Restrições de segurança
O sistema não mostra papéis de parede em telas virtuais que não são dele. Isso ocorre devido a uma questão de segurança: um app malicioso pode criar uma tela virtual com suporte a decorações do sistema ativado 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 e uma conexão de plano de fundo por tela. No WindowManager, os controladores de tela 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 públicas do método WallpaperManager
(como
WallpaperManager#getDesiredMinimumWidth()
) foram atualizadas para calcular
e fornecer informações para as telas correspondentes.
WallpaperInfo#supportsMultipleDisplays()
e um atributo de recurso correspondente foram adicionados para que os desenvolvedores de apps possam informar 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 for compatível com várias telas, o sistema vai mostrar o papel de parede padrão nas telas secundárias:
Figura 3. Lógica de substituição de plano de fundo para telas secundárias.