No Android 13 e versões mais recentes, os novos framebuffers, usados durante a composição do cliente, são alocados sempre que a resolução da tela muda. Essa alocação é realizada pelo SurfaceFlinger 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 seguintes cenários:
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, os identificadores dos framebuffers antigos são liberados quando os dados de exibição antigos são desalocados.
Uma mudança de modo de exibição iniciada pelo SurfaceFlinger, que ocorre quando o usuário muda a resolução com as configurações do usuário, ou quando um app muda a resolução com
preferredDisplayModeId
.Durante uma mudança de modo de exibição, os identificadores para framebuffers de clientes existentes são liberados pelo SurfaceFlinger antes de chamar
setActiveConfig
ousetActiveConfigWithConstraints
.
Para evitar problemas catastróficos, como fragmentação de memória, em dispositivos que não reservam memória suficiente para os framebuffers antigos e novos, é fundamental que o HWC deixe de usar os framebuffers antigos e libere todos os identificadores para esses framebuffers, conforme mostrado nos seguintes casos:
Para eventos de hotplug, imediatamente antes de chamar
onHotplug
.Para alternar o modo, imediatamente após a chamada para
setActiveConfig
ousetActiveConfigWithConstraints
.
A liberação dos identificadores permite que a memória do framebuffer seja totalmente desalocada antes da alocação de novos framebuffers que o SurfaceFlinger realiza durante o próximo ciclo de invalidação.
Recomendações para o gerenciamento de framebuffer
Se o HWC não liberar os identificadores para framebuffers antigos a tempo, a nova alocação de framebuffer ocorrerá antes da dealocação do framebuffer antigo. Isso pode causar problemas catastróficos quando a nova alocação falhar 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 de alocação catastróficas, siga estas recomendações:
Se o HWC precisar continuar usando os framebuffers de cliente antigos até que os novos sejam fornecidos, será essencial 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.
Aloque um pool de memória dedicado para os framesbuffers, separado do restante da memória do buffer gráfico. Isso é importante porque, entre a desalocação e a realocação dos framebuffers, um processo de terceiros pode tentar alocar 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 poderá ocupar a memória gráfica alocada anteriormente por um framebuffer, deixando memória insuficiente para a realocação do framebuffer ou, possivelmente, fragmentando o espaço de memória.
Testar o gerenciamento de framebuffer
Os OEMs são aconselhados a testar o gerenciamento adequado da memória de framebuffer do cliente em interruptores de resolução para o dispositivo, conforme descrito abaixo:
Para eventos de hotplug, basta desconectar e reconectar duas telas diferentes com resoluções diferentes.
Para alternar entre modos, use o teste do verificador CTS
ModeSwitchingTestActivity
para iniciar uma troca de modo para testar o comportamento da memória do framebuffer. Esse teste pode identificar visualmente problemas difíceis de detectar programaticamente.