No Android 13 e versões mais recentes, o sistema aloca novos framebuffers, usados durante a composição do cliente, sempre que a resolução da tela muda. O SurfaceFlinger realiza essa alocação no próximo ciclo de invalidação após uma mudança de resolução.
Gerenciamento de framebuffer durante trocas de resolução
As mudanças de resolução ocorrem devido a um dos dois cenários a seguir:
Um evento de hotplug, iniciado pelo Hardware Composer (HWC), que ocorre ao trocar de uma tela externa para outra com uma resolução padrão diferente.
Durante um evento de hotplug, o HWC libera os identificadores dos framebuffers antigos quando desaloca os dados de exibição antigos.
Uma troca de modo de exibição iniciada pelo SurfaceFlinger, que ocorre quando você muda a resolução usando as configurações do usuário ou quando um app muda a resolução usando
preferredDisplayModeId
.Durante uma troca de modo de exibição, o SurfaceFlinger libera os identificadores para framebuffers de clientes atuais antes de chamar
setActiveConfig
ousetActiveConfigWithConstraints
.
Para evitar problemas catastróficos, como a fragmentação da memória em dispositivos sem memória de framebuffer suficiente, o HWC precisa liberar identificadores para framebuffers antigos. Isso é fundamental nos seguintes casos:
Para eventos de hotplug, imediatamente antes de chamar
onHotplug
.Para mudanças de modo, imediatamente após chamar
setActiveConfig
ousetActiveConfigWithConstraints
.
A liberação dos identificadores permite que a memória do framebuffer seja totalmente desalocada antes que o SurfaceFlinger aloque novos framebuffers durante o próximo ciclo de invalidação.
Recomendações para gerenciamento de framebuffer
Se o HWC não liberar os identificadores para os framebuffers antigos a tempo, a nova alocação de framebuffer ocorrerá antes da desalocação do framebuffer antigo. Isso pode causar problemas graves quando a nova alocação falha devido à fragmentação ou outros problemas. Pior ainda, se o HWC não liberar esses identificadores, poderá ocorrer um vazamento de memória.
Para evitar falhas catastróficas de alocação, siga estas recomendações:
Se o HWC precisar continuar usando os framebuffers de cliente antigos até que novos sejam fornecidos, é fundamental reservar memória suficiente para os framebuffers antigos e novos e, possivelmente, executar algoritmos de desfragmentação no espaço de memória do framebuffer.
Alocar um pool de memória dedicado para os framebuffers separado do restante da memória do buffer gráfico. Isso é importante porque um processo de terceiros pode tentar alocar memória gráfica entre a desalocação e a realocação do framebuffer. Se o framebuffer usar o mesmo pool de memória gráfica e se a memória gráfica estiver cheia, o processo de terceiros poderá ocupar a memória alocada anteriormente por um framebuffer. Isso pode levar à memória insuficiente para realocação do framebuffer ou fragmentação da memória.
Testar o gerenciamento de framebuffer
Recomendamos que os OEMs testem o gerenciamento adequado da memória do framebuffer do cliente em trocas de resolução para o dispositivo, conforme descrito abaixo:
Para eventos de hotplug, desconecte e reconecte duas telas diferentes com resoluções diferentes.
Para mudanças de modo, use o teste
ModeSwitchingTestActivity
do CTS Verifier para iniciar uma mudança de modo e testar o comportamento da memória do framebuffer. Esse teste pode identificar visualmente problemas difíceis de detectar de forma programática.