Taxa de atualização múltipla

O Android 11 adiciona suporte a dispositivos com várias taxas de atualização. Esse recurso tem três componentes principais:

  • Novas APIs HAL introduzidas no android.hardware.graphics.composer@2.4.
  • Código da plataforma para analisar configurações de dispositivos com diferentes taxas de atualização e definir a taxa de atualização desejada
  • Novas APIs de SDK e NDK para permitir que os apps definam o frame rate desejado

Implementação

Adicionamos suporte dedicado à troca de taxa de atualização em …Recomendamos usar essa versão porque as anteriores do HAL do compositor têm suporte limitado para 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. Com esse atributo, os fornecedores podem agrupar configurações de exibição. As configurações no mesmo grupo permitem alternar entre elas sem problemas na maioria dos casos. A plataforma usa o grupo de configuração para diferenciar quais configurações podem ser alternadas para mudar a taxa de atualização e não outros atributos de uma configuração.

Considere o exemplo a seguir, que demonstra os benefícios de usar grupos de configuração com um dispositivo que oferece suporte a quatro configurações de tela:

  • 1080p a 60 Hz
  • 1080p a 90 Hz
  • 1080i a 72 Hz
  • 1080i a 48 Hz

Embora o dispositivo seja compatível com taxas de atualização de 48 Hz, 60 Hz, 72 Hz e 90 Hz, a tela opera em um modo diferente. A troca de 60 Hz para 72 Hz muda a configuração da tela de 1080p para 1080i, o que pode não ser o comportamento desejado. Os grupos de configuração resolvem isso. Ao agrupar 60 Hz e 90 Hz em um grupo de configuração e 48 Hz e 72 Hz em outro, a plataforma sabe que 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 resulta em uma mudança de configuração em vez de apenas alterar a taxa de atualização.

Atualizações da API Composer

getDisplayVsyncPeriod
Para melhorar o controle e a previsibilidade ao mudar as taxas de atualização, 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 plataforma precisa da taxa de atualização atual para decidir quando iniciar o próximo frame.
setActiveConfigWithConstraints
O método setActiveConfigWithConstraints é uma nova extensão do método setActiveConfig atual e fornece mais informações sobre a mudança 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 horário). Isso é útil quando a plataforma quer planejar 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 esses buffers para garantir que a transição da taxa de atualização seja a mais suave possível.
    seamlessRequired
    Se for verdadeiro, exige que a mudança no período de vsync aconteça sem problemas e sem um artefato visual perceptível. A plataforma usa essa flag 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 uma animação é iniciada). Isso dá ao fornecedor a oportunidade de não permitir determinadas mudanças de configuração quando elas podem resultar em um artefato visual perceptível. Se as configurações não puderem ser alteradas sem problemas e seamlessRequired estiver definido como true, espera-se que a implementação retorne SEAMLESS_NOT_POSSIBLE como o código de retorno e chame o novo callback onSeamlessPossible quando a mesma mudança de configuração puder ser feita sem problemas.

Em caso de sucesso, a implementação retorna um VsyncPeriodChangeTimeline que informa à plataforma quando esperar a mudança na taxa de atualização. Os parâmetros newVsyncAppliedTimeNanos precisam ser definidos para o tempo em CLOCK_MONOTONIC quando a nova tela começar a ser atualizada no novo período de vsync. Isso, junto com desiredTimeNanos, permite que a plataforma planeje com antecedência a troca da taxa de atualização 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 o envio de um frame de atualização antes da taxa de atualização. Para isso, a HAL tem o parâmetro refreshRequired, que indica que um frame de atualização é necessário, e refreshTimeNanos, que indica o primeiro vsync em que um frame de atualização precisa ser enviado depois.

onVsyncPeriodTimingChanged [callback]
Um novo callback que o HAL pode chamar para indicar à plataforma que algum parâmetro da linha do tempo mudou e que a plataforma precisa ajustar a linha do tempo. Espera-se que esse callback seja chamado se, por algum motivo, a linha do tempo antiga não for encontrada 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 do 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 da configuração do HAL do compositor. Além disso, ele define um intervalo de valores mínimo e máximo para SurfaceFlinger escolher como taxa de atualização.
SurfaceFlinger
Determina a taxa de atualização definindo uma configuração que está no mesmo grupo da configuração padrão e com uma taxa de atualização dentro do intervalo mínimo/máximo.

O Display Manager passa pelas seguintes etapas para determinar a política:

  • Encontra o ID da configuração padrão consultando a configuração ativa de SurfaceFlinger
  • Restringir o intervalo de valores mínimo e máximo iterando nas 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 é alterado no ambiente de execução para refletir a configuração atual do dispositivo (como uma opção de menu). O valor padrão é definido na sobreposição de configuração R.integer.config_defaultPeakRefreshRate.
    • Configuração de taxa de atualização mínima: o valor da taxa de atualização mínima é lido de Settings.System.MIN_REFRESH_RATE. Esse valor pode ser mudado durante a execução para refletir a configuração atual do dispositivo (por exemplo, em 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 preferida em que a tela deve operar. Na maioria das condições, o DisplayManager define o ID de configuração padrão de acordo 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 menos quando o dispositivo está no modo de baixo consumo de energia, indicado por Settings.Global.LOW_POWER_MODE.

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 frames). Se o proprietário da camada definir uma taxa de frames, o SurfaceFlinger tentará definir a taxa de atualização como um múltiplo dessa taxa. Por exemplo, se duas camadas ativas definirem as taxas 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 de atualização com o menor erro para a taxa de frames. 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 será 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 o fps médio que a camada está postando 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 pelo 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 for > 0, a taxa mínima de atualização será usada quando não houver atualizações de tela durante 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, consulte a documentação para desenvolvedores em developer.android.com.

Opções do desenvolvedor

Uma nova opção de desenvolvedor 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.