Confira abaixo as atualizações feitas nessas áreas específicas da Rede de Display:
- Redimensionar atividades e telas
- Tamanhos e proporções de exibição
- Políticas de display
- Configurações da janela de exibição
- Identificadores de exibição estáticos
- Usar mais de duas telas
- Foco por tela
Redimensionar atividades e telas
Para indicar que um app pode não oferecer suporte ao modo de várias janelas ou ao redimensionamento,
atividades usam o atributo resizeableActivity=false
. Comum
Os problemas encontrados por aplicativos quando as atividades são redimensionadas incluem:
- Uma atividade pode ter uma configuração diferente do app ou de outra componente não visual. Um erro comum é ler as métricas de exibição do app contexto. Os valores retornados não serão ajustados para as métricas de área visível no qual atividade é exibida.
- Uma atividade pode não processar o redimensionamento e falhar, mostrar uma interface distorcida, ou perder o estado devido ao reinício sem salvar o estado da instância.
- Um aplicativo pode tentar usar coordenadas de entrada absolutas (em vez dessas em relação à posição da janela), o que pode interromper a entrada várias janelas.
No Android 7 (e versões mais recentes), é possível configurar um app
resizeableActivity=false
para executar sempre no modo de tela cheia. Em
neste caso, a plataforma impede que atividades não redimensionáveis sejam divididas
tela. Se o usuário tentar invocar uma atividade não redimensionável da tela de início
enquanto já está no modo de tela dividida, a plataforma sai desse modo e
inicia a atividade não redimensionável no modo de tela cheia.
Apps que definem explicitamente esse atributo como false
no
manifesto não pode ser iniciado no modo de várias janelas, a menos que a compatibilidade
for aplicado:
- A mesma configuração é aplicada ao processo, que contém todas as atividades e não atividade.
- A configuração aplicada atende aos requisitos do CDD para compatibilidade com apps é exibido.
No Android 10, a plataforma ainda impede atividades não redimensionáveis passem para o modo de tela dividida, mas podem ser escalonado temporariamente se a atividade declarar um aspecto ou uma orientação fixa proporção. Caso contrário, a atividade será redimensionada para preencher toda a tela, como no Android. 9 e inferior.
A implementação padrão aplica a seguinte política:
Quando uma atividade declarada como incompatível com o modo de várias janelas por
o uso do atributo android:resizeableActivity
e quando isso
de atividade atende a uma das condições descritas abaixo, quando a aplicação
configuração de tela deve mudar, a atividade e o processo são salvos com o
configuração original, e o usuário tem affordance para reiniciar
o processo do app para usar a configuração de tela atualizada.
- É uma orientação fixa pela aplicação de
android:screenOrientation
- O app tem uma proporção máxima ou mínima padrão por nível de segmentação da API ou declare a proporção explicitamente
Essa figura mostra uma atividade não redimensionável com uma proporção declarada. Ao dobrar o dispositivo, a janela é reduzida para se ajustar à área, enquanto mantendo a proporção com o efeito letterbox adequado. Além disso, um será fornecida ao usuário sempre que a área de exibição do a atividade for alterada.
Ao desdobrar o dispositivo, a configuração, o tamanho e a proporção do atividade não mudam, mas a opção de reiniciar a atividade é exibida.
Quando resizeableActivity
não estiver definido (ou estiver definido como
true
), o app é totalmente compatível com redimensionamento.
Implementação
Uma atividade não redimensionável com orientação ou proporção fixa é chamada
Modo de compatibilidade de tamanho (SCM) no código. A condição é definida em
ActivityRecord#shouldUseSizeCompatMode()
: Quando uma atividade do SCM é
for iniciado, a configuração relacionada à tela (como tamanho ou densidade) será fixa
na configuração de substituição solicitada, para que a atividade não seja mais dependente
na configuração de tela atual.
Se a atividade do SCM não puder preencher toda a tela, ela será alinhada na parte superior e
centralizada horizontalmente. Os limites de atividade são calculados
AppWindowToken#calculateCompatBoundsTransformation()
:
Quando uma atividade do SCM usa uma configuração de tela diferente da
contêiner (por exemplo, a tela é redimensionada ou a atividade é movida para outro
display), ActivityRecord#inSizeCompatMode()
é verdadeiro e
SizeCompatModeActivityController
(na interface do sistema) recebe o
para mostrar o botão de reinicialização do processo.
Tamanhos e proporções de exibição
O Android 10 oferece suporte a novas proporções
desde altas proporções de telas longas e finas para proporções de 1:1. Os apps podem definir
ApplicationInfo#maxAspectRatio
e os ApplicationInfo#minAspectRatio
da tela em que
ser capaz de lidar.
Figura 1. Exemplos de proporções de apps com suporte no Android 10
As implementações de dispositivos podem ter telas secundárias com tamanhos e
resoluções menores do que as exigidas pelo Android 9 e anteriores (mínimo de 2.5
polegadas de largura ou altura, mínimo de 320 DP para smallestScreenWidth
),
mas apenas atividades que sejam compatíveis com essas telas pequenas podem ser posicionadas
ali.
Os aplicativos podem aceitar declarando um tamanho mínimo compatível menor que
ou igual ao tamanho de exibição de destino. Use as APIs android:minHeight
e
Atributos de layout da atividade android:minWidth
no
AndroidManifest para fazer isso.
Políticas de display
O Android 10 separa e move algumas telas
políticas da implementação padrão de WindowManagerPolicy
no
PhoneWindowManager
para classes por tela, como:
- Estado e rotação da tela
- Algumas teclas e rastreamento de eventos de movimento
- Interface do sistema e janelas de decoração
No Android 9 e versões anteriores, a classe PhoneWindowManager
processava
políticas de exibição, estado e configurações, rotação, frame de janela decorativa
e muito mais. O Android 10 move a maior parte disso para
a classe DisplayPolicy
, exceto para rastreamento de rotação, que tem
foi movido para DisplayRotation
.
Configurações da janela de exibição
No Android 10, a configuração por tela configuração de janelamento foi expandida para incluir:
- Modo de janelamento de exibição padrão
- Valores de overscan
- Rotação do usuário e modo de rotação
- Modo de tamanho, densidade e dimensionamento forçados
- Modo de remoção de conteúdo (quando a tela é removida)
- Suporte a decorações do sistema e IME
A classe DisplayWindowSettings
contém configurações para estas
. Eles são mantidos no disco da partição /data
da
display_settings.xml
sempre que uma configuração for alterada. Para
detalhes, consulte DisplayWindowSettings.AtomicFileStorage
e
DisplayWindowSettings#writeSettings()
. Os fabricantes de dispositivos podem
fornecer valores padrão em display_settings.xml
para o dispositivo
configuração do Terraform. No entanto, como o arquivo está armazenado em /data
,
lógica adicional pode ser necessária para restaurar o arquivo se ele for apagado por uma exclusão permanente.
Por padrão, o Android 10 usa
DisplayInfo#uniqueId
como um identificador para uma tela ao persistir
nas configurações. uniqueId
deve ser preenchido em todas as telas. Em
Além disso, ele é estável para telas físicas e de rede. Também é possível
usar a porta de uma tela física como identificador, que pode ser definido em
DisplayWindowSettings#mIdentifier
: A cada gravação, todas as configurações
são gravadas, para que seja seguro atualizar a chave usada para uma entrada de exibição
armazenamento. Para mais detalhes, consulte
Identificadores de exibição estáticos.
As configurações são mantidas no diretório /data
para fins de histórico
motivos. Originalmente, eles eram usados para manter configurações definidas pelo usuário, como
rotação da tela.
Identificadores de exibição estáticos
O Android 9 (e versões anteriores) não fornecia identificadores estáveis para telas no
de análise de dados em nuvem. Quando uma tela foi adicionada ao sistema,
Display#mDisplayId
ou DisplayInfo#displayId
eram
gerada para essa tela, incrementando um contador estático. Se o sistema
e removermos a mesma tela, resultou em um ID diferente.
Se um dispositivo tiver várias telas disponíveis na inicialização, elas poderão ser
recebe identificadores diferentes, dependendo do tempo. Enquanto o Android 9 (e
antes) incluía DisplayInfo#uniqueId
, não tinha
informações para diferenciar as telas porque as telas físicas eram
identificados como local:0
ou local:1
, para representar
e o monitor integrado e o externo.
O Android 10 muda a DisplayInfo#uniqueId
para adicionar um identificador estável e diferenciar entre ambientes locais,
exibições virtuais.
Tipo de exibição | Formato |
---|---|
Local | local:<stable-id> |
Rede | network:<mac-address> |
Virtual | virtual:<package-name-and-name> |
Além das atualizações no uniqueId
,
DisplayInfo.address
contém DisplayAddress
, um
identificador de exibição estável durante as reinicializações. No Android
10, DisplayAddress
oferece suporte a imagens
e telas de rede. DisplayAddress.Physical
contém uma versão estável
ID de exibição (igual ao uniqueId
) e pode ser criada com
DisplayAddress#fromPhysicalDisplayId()
O Android 10 também oferece um método conveniente para receber
informações da porta (Physical#getPort()
). Esse método pode ser usado
o framework para identificar telas estaticamente. Por exemplo, ele é usado em
DisplayWindowSettings
). DisplayAddress.Network
contém o endereço MAC e pode ser criado com
DisplayAddress#fromMacAddress()
Essas adições permitem que os fabricantes de dispositivos identifiquem telas em imagens estáticas
configurações de várias telas e para definir diferentes configurações e recursos do sistema
usando identificadores de exibição estáticos, como portas para telas físicas. Esses
estão ocultos e devem ser usados somente dentro de
system_server
:
Com um ID de tela HWC (que pode ser opaco e nem sempre estável), esse
retorna o número da porta de 8 bits (específico da plataforma) que identifica uma
conector físico para saída de exibição, bem como o blob EDID da tela.
O SurfaceFlinger extrai informações do fabricante ou do modelo do EDID para
gerar os IDs de exibição estáveis de 64 bits expostos ao framework. Se esse método
não for compatível ou ocorrer erros, o SurfaceFlinger voltará para o modo MD legado,
em que DisplayInfo#address
é nulo e
DisplayInfo#uniqueId
está codificado, conforme descrito acima.
Para verificar se esse recurso é compatível, execute:
$ dumpsys SurfaceFlinger --display-id # Example output. Display 21691504607621632 (HWC display 0): port=0 pnpId=SHP displayName="LQ123P1JX32" Display 9834494747159041 (HWC display 2): port=1 pnpId=HWP displayName="HP Z24i" Display 1886279400700944 (HWC display 1): port=2 pnpId=AUS displayName="ASUS MB16AP"
Usar mais de duas telas
No Android 9 (e versões anteriores), o SurfaceFlinger e o DisplayManagerService
presumiu a existência de no máximo duas telas físicas com IDs codificados como 0
e 1.
A partir do Android 10, o SurfaceFlinger poderia aproveitar uma API Hardware Composer (HWC) para gerar IDs de exibição estáveis, o que permite gerenciar um número arbitrário de telas físicas. Para saber mais, consulte Identificadores de exibição estáticos.
O framework pode procurar o token IBinder
de um endereço físico
exibidas por SurfaceControl#getPhysicalDisplayToken
após a obtenção
o ID de tela de 64 bits de SurfaceControl#getPhysicalDisplayIds
ou
de um evento de hotplug DisplayEventReceiver
.
No Android 10 (e versões anteriores), a tela interna principal é
TYPE_INTERNAL
e todas as telas secundárias estão sinalizadas como TYPE_EXTERNAL
independentemente do tipo de conexão. Portanto, telas internas adicionais são tratadas como externas.
Como solução alternativa, o código específico do dispositivo pode fazer suposições sobre
DisplayAddress.Physical#getPort
se o HWC for conhecido e a alocação da porta
é previsível.
Essa limitação foi removida no Android 11 (e versões mais recentes).
- No Android 11, a primeira tela relatada durante a inicialização é a tela principal. O tipo de conexão (interna ou externa) é irrelevante. No entanto, ainda é verdade que a tela principal não pode ser desconectada e segue esse ele deve, na prática, ser uma tela interna. Alguns smartphones dobráveis têm várias telas internas.
- As telas secundárias estão categorizadas corretamente como
Display.TYPE_INTERNAL
ouDisplay.TYPE_EXTERNAL
(anteriormente conhecido comoDisplay.TYPE_BUILT_IN
eDisplay.TYPE_HDMI
, respectivamente), dependendo do tipo de conexão.
Implementação
No Android 9 e versões anteriores, as telas são identificadas por IDs de 32 bits,
em que 0 é a tela interna, 1 é a tela externa, [2, INT32_MAX]
são telas virtuais HWC, e -1 representa uma tela inválida ou não HWC.
No Android 10 e versões mais recentes, as telas têm versões estáveis
e IDs persistentes, que permitem o SurfaceFlinger e o DisplayManagerService
para rastrear mais de duas telas e reconhecer telas já vistas. Se o dispositivo HWC
oferece suporte a IComposerClient.getDisplayIdentificationData
e fornece
de identificação, o SurfaceFlinger analisa a estrutura EDID e aloca os dados
IDs de exibição de 64 bits para telas físicas e virtuais de HWC. Os IDs são expressos usando
um tipo de opção, em que o valor nulo representa uma tela inválida ou uma veiculação
exibição. Sem suporte a HWC, o SurfaceFlinger retorna ao comportamento legado com pelo menos
na maioria das duas telas físicas.
Foco por tela
Para oferecer suporte a várias origens de entrada que segmentam telas individuais ao mesmo momento, o Android 10 pode ser configurado para oferecer suporte a vários janelas em foco, no máximo uma por tela. Isso é destinado apenas a usuários tipos de dispositivos quando vários usuários interagem com o mesmo dispositivo ao mesmo tempo, tempo e usar diferentes métodos ou dispositivos de entrada, como o Android Automotivo.
É altamente recomendável que esse recurso não esteja ativado para dispositivos comuns, incluindo dispositivos multitelas ou aqueles usados para desktops experiências Isso ocorre principalmente devido a uma preocupação com a segurança que pode fazer com que os usuários para saber qual janela tem o foco de entrada.
Imagine o usuário que insere informações seguras em um campo de entrada de texto, talvez fazendo login em um app bancário ou digitando texto que contenha dados confidenciais informações imprecisas ou inadequadas. Um aplicativo malicioso pode criar uma exibição virtual fora da tela com onde executar uma atividade, também com um campo de entrada de texto. Legítimos e atividades maliciosas têm foco e exibem um indicador de entrada ativo (cursor piscando).
No entanto, como a entrada de um teclado (hardware ou software) é inserida apenas a atividade principal (o aplicativo que foi lançado mais recentemente), por criando uma tela virtual escondida, um aplicativo malicioso pode captar a entrada do usuário, mesmo ao usar um teclado de software na tela principal do dispositivo.
Usar o com.android.internal.R.bool.config_perDisplayFocusEnabled
para definir o foco por tela.
Compatibilidade
Problema:no Android 9 e versões anteriores, no máximo uma janela no tem foco de cada vez.
Solução: no caso raro em que duas janelas do mesmo processo seria focado, o sistema fornece foco apenas para a janela que está mais acima na ordem Z. Essa restrição foi removida para apps que segmentam A partir do Android 10, espera-se que eles possam oferecem suporte a várias janelas sendo focadas simultaneamente.
Implementação
WindowManagerService#mPerDisplayFocusEnabled
controla o
disponibilidade desse recurso. Em ActivityManager
,
ActivityDisplay#getFocusedStack()
agora é usado em vez de global
o rastreamento em uma variável. ActivityDisplay#getFocusedStack()
determina o foco com base na ordem Z em vez de armazenar o valor em cache. Isso é para que
apenas uma origem, a WindowManager, precisa rastrear a ordem Z das atividades.
ActivityStackSupervisor#getTopDisplayFocusedStack()
faz uma
abordagem semelhante nos casos em que a pilha mais focada no sistema
precisam ser identificados. As pilhas são percorridas de cima para baixo, buscando
para a primeira pilha qualificada.
O app InputDispatcher
agora pode ter várias janelas em foco
(uma por tela). Se um evento de entrada for específico da tela, ele será despachado
para a janela em foco na tela correspondente. Caso contrário, será enviado
para a janela em foco na tela em foco, que é a tela que o usuário
tenha interagido mais recentemente.
Consulte InputDispatcher::mFocusedWindowHandlesByDisplay
e
InputDispatcher::setFocusedDisplay()
. Os apps focados também são atualizados.
separadamente em InputManagerService por meio de
NativeInputManager::setFocusedApplication()
:
No WindowManager
, as janelas em foco também são rastreadas separadamente.
Consulte DisplayContent#mCurrentFocus
e
DisplayContent#mFocusedApp
e os respectivos usos. Foco relacionado
os métodos de rastreamento e atualização foram movidos
WindowManagerService
para DisplayContent
.