Gerenciamento de framebuffer do cliente

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 ou setActiveConfigWithConstraints.

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:

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.