Gerenciamento de hotplug

Os recursos de exibição, como modos de exibição e tipos HDR com suporte, podem mudar dinamicamente em dispositivos com telas conectadas externamente (com HDMI ou DisplayPort), como conversores do Android TV (STBs) e dispositivos over-the-top (OTT). Essa mudança pode acontecer como resultado de um sinal de hotplug HDMI, como quando o usuário alterna de uma tela para outra ou inicializa o dispositivo sem uma tela conectada. O Android 12 e versões mais recentes incluem mudanças no framework para processar recursos de hotpluging e de exibição dinâmica.

Nesta página, descrevemos o processamento de hotplugs de exibição e as mudanças nos recursos de exibição na implementação da HAL do Composer. Além disso, discute como gerenciar o framebuffer associado e evitar disputas nessas situações.

Atualizar recursos de exibição

Esta seção descreve como o framework do Android processa mudanças nos recursos de exibição iniciadas pela HAL do Composer.

Antes que o Android possa processar corretamente as mudanças nos recursos de exibição, o OEM precisa implementar a HAL do Composer para usar onHotplug(display, connection=CONNECTED) para notificar o framework sobre qualquer mudança nos recursos de exibição. Depois da implementação, o Android processa as mudanças nos recursos de exibição da seguinte forma:

  1. Ao detectar uma mudança nos recursos de exibição, o framework recebe uma notificação onHotplug(display, connection=CONNECTED).
  2. Ao receber a notificação, o framework descarta o estado de exibição e o recria com os novos recursos da HAL usando os métodos getActiveConfig, getDisplayConfigs, getDisplayAttribute, getColorModes, getHdrCapabilities e getDisplayCapabilities.
  3. Depois que o framework recria um novo estado de exibição, ele envia o callback onDisplayChanged para os apps que estão detectando esses eventos.

O framework realoca os framebuffers nos eventos onHotplug(display, connection=CONNECTED) subsequentes. Consulte Gerenciamento de framebuffer do cliente para mais informações sobre como gerenciar corretamente a memória do framebuffer para evitar falhas durante a alocação de novos framebuffers.

Lidar com cenários de conexão comuns

Esta seção aborda como processar corretamente vários cenários de conexão nas implementações quando a tela principal estiver conectada e desconectada.

Criado para dispositivos móveis, o framework do Android não tem suporte integrado a uma tela principal desconectada. Em vez disso, a HAL precisa substituir a tela principal por uma tela de marcador nas interações com o framework, caso uma tela principal esteja fisicamente desconectada.

Os cenários a seguir podem ocorrer em STBs e dongles de TV que têm telas conectadas externamente que podem ser desconectadas. Para implementar o suporte a esses cenários, use as informações da tabela abaixo:

Situação Manuseio
Nenhuma tela conectada no momento da inicialização
  • Enviar um sinal onHotplug(display, connection=CONNECTED) da HAL do Composer para o framework.
  • Substitua o estado de exibição física dentro da HAL do Composer por um estado de exibição de marcador.
A tela principal está fisicamente conectada
A tela principal está fisicamente desconectada
  • Envie outro evento onHotplug(display, connection=CONNECTED) da HAL do Composer para o framework.
  • Substitua o estado de exibição física dentro da HAL do Composer por um estado de exibição de marcador. A exibição do marcador precisa ter um único modo de exibição para que o framework envie o callback onDisplayChanged aos apps, porque o conjunto de modos compatíveis mudou. Esse modo de exibição única precisa corresponder ao último modo ativo da tela física antes da desconexão para que os apps não recebam eventos de mudança de configuração.

Considerações sobre conexões não HDMI

O Android TV só é compatível com as seguintes resoluções:

  • 720 x 1.280
  • 1.080 x 1.920
  • 2.160 x 3.840
  • 4.320 x 7.680

Quando um STB ou dongle de TV tentar exibir uma resolução não compatível, como 480i em uma conexão CVBS, uma mensagem de erro será apresentada ao usuário.

Se o STB ou dongle da TV tiver conexões HDMI e não HDMI, a conexão HDMI será a tela principal, e a conexão não HDMI ficará inativa. Como resultado, se a conexão HDMI for desconectada enquanto a não HDMI ainda estiver conectada, um evento será enviado ao SurfaceFlinger, e os recursos da tela não HDMI precisarão ser refletidos por getDisplayAttribute e outras APIs iComposerClient (como getHdrCapabilities).

Use IDs de configuração sequenciais para evitar disputas

Pode haver disputas se a HAL do Composer atualizar as configurações de exibição com suporte simultaneamente com o framework chamando setActiveConfig ou setActiveConfigWithConstraints. A solução é implementar a HAL do Composer para usar IDs sequenciais e evitar esse problema.

Esta seção descreve como as condições de corrida podem ocorrer, seguida por detalhes sobre como implementar a HAL do Composer para que ela use IDs sequenciais para evitar essas condições.

Considere a seguinte sequência de eventos, quando novos IDs sequenciais NÃO forem atribuídos às novas configurações de exibição, causando uma disputa:

  1. Os IDs de configuração de exibição compatíveis são:

    • id=1, 1.080 x 1.920 60 Hz
    • id=2, 1.080 x 1.920 50 Hz
  2. O framework chama setActiveConfig(display, config=1).

  3. Ao mesmo tempo, a HAL do Composer processa uma alteração das configurações de exibição e atualiza o estado interno para um novo conjunto de configurações de exibição, conforme mostrado a seguir:

    • id=1, 2.160 x 3.840 60 Hz
    • id=2, 2.160 x 3.840 50 Hz
    • id=3, 1.080 x 1.920 60 Hz
    • id=4, 1.080 x 1.920, 50 Hz
  4. A HAL do Composer envia um evento onHotplug ao framework para notificar que o conjunto de modos com suporte mudou.

  5. A HAL do Composer recebe setActiveConfig(display, config=1) (da etapa 2).

  6. A HAL interpreta que o framework solicitou uma alteração na configuração para 2160x3840 60 Hz, embora, na realidade, 1080x1920 60 Hz.

O processo que usa atribuições de IDs não sequenciais termina aqui com uma interpretação incorreta da alteração de configuração desejada.

Configurar a HAL do Composer para usar IDs sequenciais

Para evitar essas disputas, o OEM precisa implementar a HAL do Composer desta maneira:

  • Quando a HAL do Composer atualiza as configurações de exibição com suporte, ela atribui novos IDs sequenciais às novas configurações de exibição.
  • Quando o framework chama setActiveConfig ou setActiveConfigWithConstraints com um ID de configuração inválido, a HAL do Composer ignora a chamada.

Essas etapas servem para evitar disputas, conforme mostrado na discussão a seguir.

Considere a seguinte sequência de eventos quando novos IDs sequenciais forem atribuídos às novas configurações de exibição:

  1. Os IDs de configuração de exibição compatíveis são:

    • id=1, 1.080 x 1.920 60 Hz
    • id=2, 1.080 x 1.920 50 Hz
  2. O framework chama setActiveConfig(display, config=1).

  3. Quando uma alteração das configurações de exibição é processada, o próximo conjunto de IDs de configuração é atribuído a partir do próximo número inteiro não utilizado, mostrado da seguinte maneira:

    • id=3, 2.160 x 3.840 60 Hz

    • id=4, 2.160 x 3.840 50 Hz

    • id=5, 1.080 x 1.920, 60 Hz

    • id=6, 1.080 x 1.920 50 Hz

  4. A HAL do Composer envia um evento onHotplug ao framework para notificar que o conjunto de modos com suporte mudou.

  5. A HAL do Composer recebe setActiveConfig(display, config=1) (da etapa 2).

  6. A HAL do Composer ignora a chamada porque o ID não é mais válido.

  7. O framework recebe e processa o evento onHotplug da etapa 4. Ela chama a HAL do Composer usando as funções getDisplayConfigs e getDisplayAttribute. Com essas funções, o framework identifica o novo ID (5) para a resolução e a taxa de atualização desejadas de 1.080 x 1.920 e 60 Hz.

  8. O framework envia outro evento setActiveConfig com um ID atualizado de 5.

  9. A HAL do Composer recebe setActiveConfig(display, config=5) da etapa 5.

  10. A HAL interpreta corretamente que o framework solicitou uma mudança de configuração para 1.080 x 1.920 60 Hz.

Conforme mostrado no exemplo acima, o processo que usa atribuições de ID sequenciais garante que a disputa seja impedida e a alteração correta na configuração de exibição seja atualizada.