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 é usando 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 a 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 WindowManager. WindowManager e envia a superfície ao 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 de o SurfaceFlinger aceitar buffers. O ASurfaceControl combina uma superfície e uma instância SurfaceControl em um pacote de transação que o SurfaceFlinger recebe. ASurfaceControl está associado a uma camada, que os apps atualizam por instâncias ASurfaceTransaction. Os apps recebem informações sobre instâncias de ASurfaceTransaction por callbacks que transmitem ASurfaceTransactionStats com informações, como tempo de bloqueio e de aquisição, por exemplo.

A tabela a seguir descreve ASurfaceControl e os componentes associados:

Componente Descrição
ASurfaceControl Encapsula SurfaceControl e permite que um app crie instâncias SurfaceControl que correspondem 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 lançamento anterior, para um app por um callback pré-registrado.

Embora os apps possam enviar buffers a qualquer momento, o SurfaceFlinger só é ativado para aceitar buffers entre as atualizações da tela, 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 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 ele encontrar um novo buffer, o SurfaceFlinger vai adquiri-lo. Caso contrário, ele continuará usando o buffer adquirido anteriormente. O SurfaceFlinger precisa sempre mostrar algo, então ele se mantém em 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 da camada como composição do cliente, o SurfaceFlinger vai compor essas camadas. Em seguida, o SurfaceFlinger passa o buffer de saída para o HWC.

WindowManager

O WindowManager controla objetos Window, que são contêineres para objetos View. Os objetos Window sempre são apoiados por objetos Surface. 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. 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) em 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 fim 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.