O Android 11 adiciona suporte a dispositivos com várias taxas de atualização. Há três componentes principais para esse recurso:
- Novas APIs HAL introduzidas em
android.hardware.graphics.composer@2.4
. - Código da plataforma para analisar as configurações do dispositivo para diferentes taxas de atualização e definir a taxa de atualização desejada
- Novas APIs do SDK e NDK para permitir que os apps definam a taxa de frames desejada
Implementação
Foi adicionado suporte dedicado à troca de taxa de atualização para
android.hardware.graphics.composer@2.4 HAL
.
Recomendamos o uso dessa versão, porque as versões anteriores da
HAL do compositor têm suporte limitado à troca da taxa de atualização.
Grupos de configuração
Um novo atributo CONFIG_GROUP
foi adicionado a
IComposerClient::Attribute
, que pode ser consultado usando a
API getDisplayAttribute_2_4
. Esse atributo permite que os fornecedores agrupem
configurações de exibição. Configurações no mesmo grupo permitem
alternar entre elas na maioria dos casos. O grupo de configuração é usado
pela plataforma para diferenciar quais configurações podem ser alternadas entre
elas para alternar a taxa de atualização e não outros atributos de uma
configuração.
Considere o exemplo a seguir, que demonstra os benefícios do uso de grupos de configuração com um dispositivo compatível com quatro configurações de exibição:
- 1080p a 60 Hz
- 1080p a 90 Hz
- 1080i a 72 Hz
- 1080i a 48 Hz
Mesmo que o dispositivo ofereça suporte a taxas de atualização de 48 Hz, 60 Hz, 72 Hz e 90 Hz, a tela opera em um modo diferente, e a mudança de 60 Hz para 72 Hz altera a configuração de exibição de 1080p para 1080i, o que pode não ser o comportamento desejado. Isso é resolvido usando grupos de configuração. Agrupando 60 Hz e 90 Hz em um grupo de configuração e 48 Hz e 72 Hz em outro. A plataforma sabe que ela pode alternar entre 60 Hz e 90 Hz e entre 48 Hz e 72 Hz, mas não entre 60 Hz e 72 Hz, porque isso resultaria em uma mudança de configuração em vez de simplesmente mudar a taxa de atualização.
Atualizações da API Composer
- getDisplayVsyncPeriod
- Para melhorar o controle e a previsibilidade ao alterar as taxas de atualização,
foi adicionada
getDisplayVsyncPeriod
.getDisplayVsyncPeriod
retorna a taxa de atualização atual (em termos de período de vsync) em que a tela opera. Isso é especialmente útil durante a transição entre a taxa de atualização e a taxa de atualização atual necessária pela plataforma para decidir quando iniciar o próximo frame. - setActiveConfigWithConstraints
- O método
setActiveConfigWithConstraints
é uma nova extensão do métodosetActiveConfig
existente e fornece mais informações sobre a alteração da configuração. As restrições são fornecidas como parte dos parâmetrosvsyncPeriodChangeConstraints
e contêm os seguintes parâmetros. - desiredTimeNanos
- O tempo em
CLOCK_MONOTONIC
após o qual o período de VSync pode mudar. Ou seja, o período de VSync não pode mudar antes desse tempo. Isso é útil quando a plataforma quer se preparar para uma mudança na taxa de atualização, mas já tem alguns buffers na fila para apresentar. A plataforma define esse tempo corretamente para considerar esses buffers e garantir que a transição da taxa de atualização seja a mais tranquila possível. - seamlessRequired
- Se verdadeiro, exige que a mudança do período de vsync aconteça perfeitamente, sem um artefato visual perceptível. Essa flag é usada pela plataforma quando uma
mudança na taxa de atualização é necessária como resultado de uma mudança de conteúdo (por exemplo, o
dispositivo está inativo e a animação começa). Isso dá ao fornecedor a oportunidade de
não permitir determinadas mudanças de configuração quando elas puderem resultar em um artefato
visual perceptível. Se não for possível mudar as configurações sem problemas e
seamlessRequired
estiver definido comotrue
, a implementação vai retornarSEAMLESS_NOT_POSSIBLE
como o código de retorno e chamar o novo callbackonSeamlessPossible
quando a mesma mudança de configuração puder ser feita sem problemas. Se o processo for bem-sucedido, a implementação retornará uma
VsyncPeriodChangeTimeline
que informa à plataforma quando esperar a mudança na taxa de atualização. Os parâmetrosnewVsyncAppliedTimeNanos
precisam ser definidos como o horário emCLOCK_MONOTONIC
em que a nova tela vai começar a ser atualizada no novo período de vsync. Isso, junto comdesiredTimeNanos
, permite que a plataforma planeje com antecedência a mudança de taxa de atualização e comece a marcar apps para a nova taxa de atualização com antecedência. Isso permite uma transição perfeita da taxa de atualização.Algumas implementações exigem que um frame de atualização seja enviado antes que a taxa de atualização possa ser enviada. Para isso, o HAL tem o parâmetro
refreshRequired
para indicar que um frame de atualização é necessário erefreshTimeNanos
para indicar o primeiro vsync em que um frame de atualização precisa ser enviado depois.- onVsyncPeriodTimingChanged [callback]
- Um novo callback que pode ser chamado pela HAL para indicar à plataforma que algum parâmetro da linha do tempo mudou e que a plataforma precisa ajustar a linha do tempo. Esse callback será chamado se, por algum motivo, a linha do tempo antiga tiver sido perdida devido a um longo tempo de processamento no HAL ou a um frame de atualização atrasado.
Como a plataforma decide mudar a taxa de atualização?
A seleção da taxa de atualização acontece nos dois serviços de sistema a seguir:
- DisplayManager
- O
DisplayManager
define a política de alto nível em relação à taxa de atualização. Ele define uma configuração de exibição padrão, que é a mesma que a configuração HAL do compositor. Além disso, ele define um intervalo de valores mínimo e máximo para queSurfaceFlinger
escolha como a taxa de atualização. - SurfaceFlinger
- Determina a taxa de atualização definindo uma configuração que está no mesmo grupo que a configuração padrão e com uma taxa de atualização no intervalo mínimo/máximo.
O Gerenciador de exibição segue as etapas abaixo para determinar a política:
- Encontra o ID de configuração padrão consultando a configuração ativa de
SurfaceFlinger
- Restringir o intervalo de valores mínimo e máximo iterando sobre as
condições do sistema
- Configuração de taxa de atualização padrão: o valor padrão da taxa de atualização
é definido na sobreposição de configuração
R.integer.config_defaultRefreshRate
. Esse valor é usado para determinar a taxa de atualização padrão do dispositivo para animações e interações por toque. - Configuração da taxa de atualização máxima: o valor da taxa de atualização máxima
é lido em
Settings.System.PEAK_REFRESH_RATE
. Esse valor é mudado durante a execução para refletir a configuração atual do dispositivo (como em uma opção de menu). O valor padrão é definido na sobreposição de configuraçãoR.integer.config_defaultPeakRefreshRate
. - Configuração mínima da taxa de atualização: o valor mínimo da taxa de atualização
é lido em
Settings.System.MIN_REFRESH_RATE
. Esse valor pode ser alterado no momento da execução para refletir a configuração atual do dispositivo, por exemplo, uma opção de menu. O valor padrão é 0, então não há um mínimo padrão. - ModeId solicitado pelo aplicativo: os apps podem definir
WindowManager.LayoutParams.preferredDisplayModeId
para refletir uma configuração preferencial em que a tela deve operar. Na maioria das condições, oDisplayManager
define o ID de configuração padrão e a taxa de atualização mínima e máxima para corresponder à taxa de atualização da configuração. - Economia de bateria: a taxa de atualização é restrita a 60 Hz ou
menor quando o dispositivo está no modo de baixo consumo, o que é indicado por
Settings.Global.LOW_POWER_MODE.
- Configuração de taxa de atualização padrão: o valor padrão da taxa de atualização
é definido na sobreposição de configuração
Depois que DisplayManager
define a política,
SurfaceFlinger
define a taxa de atualização com base nas camadas ativas (camadas que enfileiram
atualizações de frame). Se o proprietário da camada definir um frame rate, o SurfaceFlinger
tentará definir a taxa de atualização como um multiplicador dessa taxa.
Por exemplo, se duas camadas ativas definirem a taxa de frames como 24 e 60, o SurfaceFlinger
escolherá 120 Hz se estiver disponível. Se essa taxa de atualização não estiver disponível para
o SurfaceFlinger, ele tentará escolher a taxa que tiver o erro mínimo
para o frame rate. Para mais informações, consulte a documentação para desenvolvedores em developer.android.com.
SurfaceFlinger
mantém as seguintes flags para
controlar como a taxa de atualização é decidida:
ro.surface_flinger.use_content_detection_for_refresh_rate:
Se definido, a taxa de atualização é decidida com base nas camadas ativas, mesmo que uma taxa de frames não tenha sido definida. O SurfaceFlinger mantém uma heurística em que encontra a taxa de fps média que a camada está publicando buffers analisando o carimbo de data/hora de apresentação anexado ao buffer.ro.surface_flinger.set_touch_timer_ms
: se for > 0, a taxa de atualização padrão será usada quando um usuário tocar na tela para o tempo limite configurado. Essa heurística é feita para ficar pronta com a taxa de atualização padrão para animações.ro.surface_flinger.set_idle_timer_ms
: se for > 0, a taxa de atualização mínima será usada quando não houver atualizações de tela para o tempo limite configurado.ro.surface_flinger.set_display_power_timer_ms
: se for > 0, a taxa de atualização padrão será usada ao ligar a tela (ou ao sair do AOD) para o tempo limite configurado.
API Frame Rate
A API de frame rate permite que os apps informem à plataforma Android o frame rate pretendido e está disponível em apps direcionados ao Android 11. Para saber mais sobre a API de taxa de frames, confira a documentação para desenvolvedores em developer.android.com.
Opções do desenvolvedor
Uma nova opção para desenvolvedores foi adicionada ao menu que alterna uma sobreposição na tela com a taxa de atualização atual. A nova opção está em Configurações > Sistema > Opções do desenvolvedor > Mostrar taxa de atualização.