Várias taxas de atualização

O Android 11 adiciona suporte a dispositivos com várias taxas de atualização. Existem três componentes principais desse 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 do NDK para permitir que os apps definam o frame rate desejado

Implementação

Foi adicionado suporte dedicado à troca de taxa de atualização em android.hardware.graphics.composer@2.4 HAL. Recomendamos o uso dessa versão, já que as versões anteriores a HAL do Composer tem suporte limitado à troca de 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 a troca perfeita 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
  • 1.080i 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 muda 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 pode alternar entre 60 Hz e 90 Hz e entre 48 Hz e 72 Hz, mas não entre 60 Hz e 72 Hz, já que isso resultará em uma mudança de configuração em vez de simplesmente alterar a taxa de atualização.

Atualizações da API Composer

getDisplayVsyncPeriod
Para melhor controle e previsibilidade ao mudar as taxas de atualização, getDisplayVsyncPeriod foi adicionado. 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 ao método setActiveConfig e oferece mais informações sobre a alteração de configuração. As restrições são fornecidas como parte dos parâmetros vsyncPeriodChangeConstraints 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 de acordo com os buffers e garante que a transição da taxa de atualização seja a mais suave possível.
    ContínuaRequired
    Se verdadeiro, exige que a mudança do período de vsync ocorra sem problemas sem um artefato visual perceptível. Essa flag é usada pela plataforma quando um a alteração da taxa de atualização é necessária como resultado de uma alteração no conteúdo (por exemplo, a dispositivo está inativo e a animação é iniciada). Isso permite que o fornecedor não permita certas mudanças de configuração quando elas podem resultar em um artefato visual perceptível. Se as configurações não puderem ser alteradas de forma simples seamlessRequired é definido como true, a implementação é deve retornar SEAMLESS_NOT_POSSIBLE como o código de retorno e chame o novo callback onSeamlessPossible quando a mesma configuração a mudança pode ser feita sem problemas.

Após o sucesso, a implementação retorna uma VsyncPeriodChangeTimeline, que informa à plataforma quando esperar a mudança da taxa de atualização. newVsyncAppliedTimeNanos precisam ser definidos como o horário no CLOCK_MONOTONIC em que o a nova tela será atualizada no novo período de vsync. Isso, junto com desiredTimeNanos permite que a plataforma planeje a atualização com antecedência a mudança de taxa e comece a marcar os 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, a HAL tem a propriedade refreshRequired para indicar que um frame de atualização é necessário e refreshTimeNanos para indicar o primeiro vsync em que um frame de atualização precisa ser enviada depois.

onVsyncPeriodTimingChanged [callback]
Um novo callback que pode ser chamado pelo HAL para indicar à plataforma que algum parâmetro da linha do tempo mudou e ela precisa ser ajustada. Espera-se que esse callback seja chamado se, por algum motivo, a linha do tempo antiga tiver sido perdidas por causa de um longo tempo de processamento na HAL ou por uma atualização tardia frame.

Como a plataforma decide alterar 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 torno da 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 limites mínimos e máximos valores para SurfaceFlinger escolher como atualização e a taxa de conversão.
SurfaceFlinger
Determina a taxa de atualização definindo uma configuração que está no mesmo grupo de configuração padrão e com uma taxa de atualização dentro do 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
  • Restringindo o intervalo de valores mínimo e máximo iterando sobre o condições do sistema
    • Configuração da 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 de Settings.System.PEAK_REFRESH_RATE. Esse valor é mudou durante a execução para refletir a configuração atual do dispositivo (como de um menu ). O valor padrão é definido no arquivo Sobreposição de configuração R.integer.config_defaultPeakRefreshRate.
    • Configuração de taxa de atualização mínima: é a taxa de atualização mínima. o valor é lido em Settings.System.MIN_REFRESH_RATE. Esse valor pode ser alterado no tempo de execução para refletir a configuração atual do dispositivo (como de um menu ). O valor padrão é 0, portanto, 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, DisplayManager define o ID de configuração padrão e define 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 de energia, o que é indicado pelo Settings.Global.LOW_POWER_MODE.

Depois que o DisplayManager definir a política, SurfaceFlinger define a taxa de atualização com base nas camadas ativas (camadas que enfileiram) de frames). Se o proprietário da camada definir um frame rate, o SurfaceFlinger tenta definir a taxa de atualização para um multiplicador dessa taxa. Por exemplo, se duas camadas ativas definirem o frame rate como 24 e 60 com SurfaceFlinger escolherá 120 Hz, se disponível. Se a taxa de atualização não estiver disponível para com o SurfaceFlinger, ele tentará escolher a taxa de atualização com a menor do frame rate. Para mais informações, consulte a documentação do desenvolvedor 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 estar pronta com a taxa de atualização padrão para animações.
  • ro.surface_flinger.set_idle_timer_ms: se > 0, taxa de atualização mínima será usado quando não houver atualizações de tela para o tempo limite configurado.
  • ro.surface_flinger.set_display_power_timer_ms: se > 0, os a taxa de atualização padrão será usada ao ligar o visor (ou ao passar fora do AOD) pelo 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 frame rate, 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.