Gerenciamento de framebuffer do cliente

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 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, os identificadores dos framebuffers antigos são liberados quando os dados de exibição antigos são desalocados.

  • Uma troca de modo de exibição iniciada pelo SurfaceFlinger, que ocorre quando o usuário muda a resolução nas configurações do usuário ou um app muda a resolução com preferredDisplayModeId.

    Durante uma troca de modo de exibição, os identificadores dos framebuffers do cliente atuais são liberados pelo SurfaceFlinger antes de chamar setActiveConfig ou setActiveConfigWithConstraints.

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 pare de usar os framebuffers antigos e libere todos os handles para esses framebuffers, conforme mostrado nos casos a seguir:

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 gerenciamento de framebuffer

Se o HWC não liberar os identificadores para os framebuffers antigos a tempo, a nova alocação de framebuffer vai ocorrer antes da desalocação do framebuffer antigo. Isso pode causar problemas catastróficos 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 os 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, entre a desalocação e a realocação dos buffers de frame, 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 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

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, basta desconectar e reconectar 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.