SurfaceFlinger e WindowManager

O SurfaceFlinger aceita, compõe e envia buffers para a tela. O WindowManager fornece ao SurfaceFlinger buffers e metadados de janela, que o SurfaceFlinger usa para compor superfícies na tela.

SurfaceFlinger

O SurfaceFlinger pode aceitar buffers de duas maneiras: pelo BufferQueue e SurfaceControl, ou pelo ASurfaceControl.

Uma maneira de o SurfaceFlinger aceitar buffers é pelo BufferQueue e SurfaceControl. Quando um app aparece em primeiro plano, ele solicita buffers de WindowManager. Em seguida, o WindowManager solicita uma camada do SurfaceFlinger. Uma camada é uma combinação de uma superfície, que contém o BufferQueue, e uma instância SurfaceControl, que contém os metadados da camada, como o frame de exibição. O SurfaceFlinger cria a camada e a envia para o WindowManager. Em seguida, o WindowManager envia a superfície para o app, mas mantém a instância SurfaceControl para manipular a aparência do app na tela.

A partir do Android 10, o ASurfaceControl oferece outra maneira para o SurfaceFlinger aceitar buffers. ASurfaceControl combina uma superfície e uma instância SurfaceControl em um pacote de transação que o SurfaceFlinger recebe. O ASurfaceControl está associado a uma camada, que os apps atualizam usando instâncias ASurfaceTransaction. Em seguida, os apps recebem informações sobre ASurfaceTransaction instâncias por meio de callbacks que transmitem ASurfaceTransactionStats contendo informações, como tempo de trava e tempos de aquisição, por exemplo.

A tabela a seguir descreve o ASurfaceControl e os componentes associados a ele:

Componente Descrição
ASurfaceControl Encapsula SurfaceControl e permite que um app crie instâncias SurfaceControl que correspondam a camadas na tela.
Pode ser criado como filho de ANativeWindow ou de outra instância ASurfaceControl.
ASurfaceTransaction Encapsula Transaction para permitir que o cliente edite as propriedades descritivas de uma camada, como geometria, e envia os buffers atualizados para o SurfaceFlinger.
ASurfaceTransactionStats Envia informações sobre transações apresentadas, como tempo de trava, tempos de aquisição e cerca de versão anterior, para um app por meio de um callback pré-registrado.

Embora os apps possam enviar buffers a qualquer momento, o SurfaceFlinger só é ativado para aceitar buffers entre as atualizações de exibição, que podem variar dependendo do dispositivo. Isso minimiza o uso da memória e evita o tearing visível na tela, que pode ocorrer ao atualizar a tela no meio da atualização.

Quando a tela está entre as atualizações, ela envia o sinal VSync para o SurfaceFlinger. O sinal VSync indica que ele pode atualizar a tela sem tearing. Quando o SurfaceFlinger recebe o sinal VSync, ele percorre a lista de camadas procurando novos buffers. Se encontrar um novo buffer, o SurfaceFlinger o adquire. Caso contrário, ele continua usando o buffer adquirido anteriormente. O SurfaceFlinger sempre precisa mostrar algo, então ele fica preso a um buffer. Se nenhum buffer tiver sido enviado em uma camada, o SurfaceFlinger vai ignorá-la.

Depois que o SurfaceFlinger coleta todos os buffers para camadas visíveis, ele pergunta ao Hardware Composer (HWC) como realizar a composição. Se o HWC marcar o tipo de composição de camada como composição do cliente, o SurfaceFlinger vai compor essas camadas. Em seguida, o SurfaceFlinger transmite o buffer de saída para o HWC.

WindowManager

WindowManager controla objetos Window, que são contêineres para objetos View. Window objetos são sempre apoiados por Surface objetos. O WindowManager supervisiona ciclos de vida, eventos de entrada e foco, orientação da tela, transições, animações, posição, transformações, ordem z e muitos outros aspectos de uma janela. O WindowManager envia todos os metadados da janela para o SurfaceFlinger para que ele possa usar esses dados para compor superfícies na tela.

Pré-rotação

Muitas sobreposições de hardware não oferecem suporte à rotação (e, mesmo que ofereçam, isso custa poder de processamento). A solução é transformar o buffer antes que ele chegue ao SurfaceFlinger. O Android oferece suporte a uma dica de consulta (NATIVE_WINDOW_TRANSFORM_HINT) no ANativeWindow para representar a transformação mais provável que o SurfaceFlinger vai aplicar ao buffer. Os drivers GL podem usar essa dica para pré-transformar o buffer antes que ele chegue ao SurfaceFlinger. Assim, quando o buffer chegar, ele será transformado corretamente.

Por exemplo, ao receber uma dica para girar 90 graus, gere e aplique uma matriz ao buffer para evitar que ele saia do final da página. Para economizar energia, faça essa pré-rotação. Para mais detalhes, consulte a interface ANativeWindow definida em system/core/include/system/window.h.