Os recursos de exibição (como modos de exibição e tipos de HDR compatíveis) podem ser alterados dinamicamente em dispositivos que possuem monitores conectados externamente (via HDMI ou DisplayPort), como decodificadores de TV Android (STB) e over-the-top (OTT) dispositivos. Essa alteração pode ocorrer como resultado de um sinal HDMI hot plug, como quando o usuário alterna de um monitor para outro ou inicializa o dispositivo sem um monitor conectado. A partir do Android 12, foram feitas alterações na estrutura para lidar com hot plugging e recursos de exibição dinâmica.
Esta página aborda como lidar com hot plugs de exibição e alterações nos recursos de exibição na implementação do Composer HAL. Além disso, discute como gerenciar o framebuffer associado e evitar condições de corrida nessas situações.
Atualizando recursos de exibição
Esta seção descreve como a estrutura do Android lida com as alterações nos recursos de exibição iniciadas pelo Composer HAL.
Antes que o Android possa lidar com as alterações nos recursos de exibição corretamente, o OEM deve implementar o Composer HAL de forma que ele use um onHotplug(display, connection=CONNECTED)
para notificar a estrutura sobre quaisquer alterações nos recursos de exibição. Depois que isso for implementado, o Android lidará com as alterações nos recursos de exibição da seguinte maneira:
- Ao detectar uma alteração nos recursos de exibição, a estrutura recebe uma
onHotplug(display, connection=CONNECTED)
. - Ao receber a notificação, a estrutura descarta seu estado de exibição e o recria com os novos recursos do HAL usando os
getActiveConfig
,getDisplayConfigs
,getDisplayAttribute
,getColorModes
,getHdrCapabilities
egetDisplayCapabilities
. - Depois que a estrutura recria um novo estado de exibição, ela envia o retorno de chamada
onDisplayChanged
para os aplicativos que estão ouvindo esses eventos.
A estrutura realoca os framebuffers em onHotplug(display, connection=CONNECTED)
subsequentes. Consulte Gerenciando a memória do framebuffer para obter mais informações sobre como lidar com isso.
Lidando com cenários de conexão comuns
Esta seção aborda como lidar adequadamente com vários cenários de conexão em suas implementações quando a tela principal está conectada e desconectada.
Tendo sido criado para dispositivos móveis, a estrutura do Android não possui suporte integrado para uma tela principal desconectada. Em vez disso, o HAL deve substituir a exibição principal por uma exibição de espaço reservado em suas interações com a estrutura no caso de uma exibição principal estar fisicamente desconectada.
Os cenários a seguir podem ocorrer em decodificadores e dongles de TV que possuem telas conectadas externamente que podem ser desconectadas. Para implementar o suporte para esses cenários, use as informações da tabela abaixo:
Cenário | Manipulação |
---|---|
Nenhum monitor conectado no momento da inicialização |
|
O monitor principal está fisicamente conectado |
|
A tela principal está fisicamente desconectada |
|
Gerenciando a memória do framebuffer
Quando um monitor já conectado recebe um evento de notificação onHotplug(display, connection=CONNECTED)
subsequente, a estrutura realoca os framebuffers associados a esse monitor. As implementações de dispositivos devem antecipar esse comportamento e gerenciar adequadamente a memória do framebuffer. Use as seguintes diretrizes em sua implementação:
Antes de enviar eventos de notificação
onHotplug(display, connection=CONNECTED)
subsequentes, certifique-se de liberar handles para os framebuffers para que o sistema possa desalocá-los adequadamente, antes de realocá-los. Se a desalocação não for bem-sucedida, a realocação poderá falhar devido à falta de memória.Recomendamos alocar um pool de memória dedicado para os framebuffers separados do restante do buffer de memória gráfica.
Isso é importante porque entre a desalocação e a realocação dos framebuffers, um processo de terceiros pode tentar alocar a memória gráfica. Se o mesmo pool de memória gráfica for usado pelo framebuffer e se a memória gráfica estiver cheia, o processo de terceiros pode ocupar a memória gráfica previamente alocada por um framebuffer, deixando memória insuficiente para a realocação do framebuffer (ou possivelmente fragmentando o espaço de memória) .
Usando IDs de configuração sequenciais para evitar condições de corrida
As condições de corrida podem surgir se o Composer HAL atualizar as configurações de exibição suportadas simultaneamente com a estrutura que chama setActiveConfig
ou setActiveConfigWithConstraints
. A solução é implementar o Composer HAL para usar IDs sequenciais e evitar esse problema.
Esta seção descreve como as condições de corrida podem ocorrer, seguida de detalhes sobre como implementar o Composer HAL para que ele use IDs sequenciais para evitar tais condições.
Considere a seguinte sequência de eventos, quando novos IDs sequenciais NÃO são atribuídos às novas configurações de exibição, causando uma condição de corrida:
Os IDs de configuração de exibição compatíveis são:
- id=1 , 1080x1920 60hz
- id=2 , 1080x1920 50hz
A estrutura chama
setActiveConfig(display, config=1)
.Concomitantemente, o Composer HAL processa uma mudança nas configurações de exibição e atualiza seu estado interno para um novo conjunto de configurações de exibição, mostrado a seguir:
- id=1 , 2160x3840 60hz
- id=2 , 2160x3840 50hz
- id=3 , 1080x1920 60hz
- id=4 , 1080x1920 50hz
O Composer HAL envia um evento
onHotplug
para o framework, para notificar que o conjunto de modos suportados foi alterado.O Composer HAL recebe
setActiveConfig(display, config=1)
(da etapa 2).O HAL interpreta que o framework solicitou uma alteração de configuração para 2160x3840 60hz , embora na realidade fosse desejado 1080x1920 60hz .
O processo usando atribuições de ID não sequenciais termina aqui com uma má interpretação da alteração de configuração desejada.
Configurando o Composer HAL para usar IDs sequenciais
Para evitar tais condições de corrida, o OEM deve implementar o Composer HAL da seguinte forma:
- Quando o Composer HAL atualiza as configurações de exibição suportadas, ele atribui novos IDs sequenciais às novas configurações de exibição.
- Quando a estrutura chama
setActiveConfig
ousetActiveConfigWithConstraints
com um ID de configuração inválido, o Composer HAL ignora a chamada.
Essas etapas servem para evitar condições de corrida, conforme mostrado na discussão a seguir.
Considere a seguinte sequência de eventos, quando novos IDs sequenciais são atribuídos às novas configurações de exibição:
Os IDs de configuração de exibição compatíveis são:
- id=1 , 1080x1920 60hz
- id=2 , 1080x1920 50hz
A estrutura chama
setActiveConfig(display, config=1)
.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 inteiro não utilizado, mostrado a seguir:
id=3 , 2160x3840 60hz
id=4 , 2160x3840 50hz
id=5 , 1080x1920 60hz
id=6 , 1080x1920 50hz
O Composer HAL envia um evento
onHotplug
para o framework, para notificar que o conjunto de modos suportados foi alterado.O Composer HAL recebe
setActiveConfig(display, config=1)
(da etapa 2).O Composer HAL ignora a chamada, pois o ID não é mais válido.
O framework recebe e processa o evento
onHotplug
da etapa 4. Ele chama o Composer HAL usando as funçõesgetDisplayConfigs
egetDisplayAttribute
. Com essas funções o framework identifica o novo ID (5) para a resolução desejada e taxa de atualização de 1080x1920 e 60Hz.A estrutura envia outro evento
setActiveConfig
com um ID atualizado de 5.O Composer HAL recebe
setActiveConfig(display, config=5)
da etapa 5.O HAL interpreta corretamente que a estrutura solicitou uma alteração de configuração para 1080x1920 60hz.
Conforme mostrado no exemplo acima, o processo usando atribuições de ID sequenciais garante que a condição de corrida seja evitada e que a alteração de configuração de exibição correta seja atualizada.