Gráficos

Ícone da HAL de gráficos do Android

O framework do Android oferece várias APIs de renderização gráfica para 2D e 3D que interagem com as implementações de drivers gráficos do fabricante. Portanto, é importante entender bem como essas APIs funcionam em um nível mais alto. Esta página apresenta a camada de abstração de hardware gráfico (HAL) em que esses drivers são criados. Antes de continuar com esta seção, familiarize-se com os seguintes termos:

tela (termo genérico), Canvas (elemento da API)
Uma tela é uma superfície de desenho que processa a composição dos bits reais de acordo com um bitmap ou um objeto Surface. A classe Canvas tem métodos para desenhos computacionais padrão de bitmaps, linhas, círculos, retângulos, texto e muito mais, além de ser vinculada a um bitmap ou Surface. Uma tela é a maneira mais simples e fácil de desenhar objetos 2D no display. A classe de base é Canvas.
drawable
Um drawable é um recurso visual compilado que pode ser usado como segundo plano, título ou outra parte da tela. Normalmente, um drawable é carregado em outro elemento da interface, como uma imagem de plano de fundo. Um drawable não pode receber eventos, mas atribui várias outras propriedades, como estado e programação, para ativar subclasses, como objetos de animação ou bibliotecas de imagens. Muitos objetos drawable são carregados de arquivos de recurso drawable: arquivos XML ou bitmap que descrevem a imagem. Os recursos drawable são compilados em subclasses de android.graphics.drawable. Para saber mais sobre drawables e outros recursos, consulte Visão geral dos recursos de app.
recurso de layout
Um recurso de layout é um arquivo XML que descreve o layout de uma tela de atividade. Para mais informações, consulte Recurso de layout.
nine-patch (9-patch, NinePatch)
Um nine-patch é um recurso de bitmap redimensionável que pode ser usado para planos de fundo ou outras imagens no dispositivo. Para mais informações, consulte Nine-patch.
OpenGL ES
O OpenGL ES é uma API multiplataforma para renderizar gráficos 2D e 3D. O Android oferece bibliotecas OpenGL ES para renderização 3D com aceleração de hardware. Para renderização 2D, uma tela é a opção mais simples. O OpenGL ES está disponível no Kit de desenvolvimento nativo (NDK) do Android. Os pacotes android.opengl e javax.microedition.khronos.opengles expõem a funcionalidade do OpenGL ES.
superfície (termo genérico), Surface (elemento da API)
Uma superfície representa um bloco de memória composto na tela. Uma superfície comporta uma tela onde elementos podem ser desenhados e oferece vários métodos auxiliares para desenhar camadas e redimensionar o objeto Surface. Use a classe SurfaceView em vez da classe Surface diretamente.
visualização de superfície (termo genérico), SurfaceView (elemento da API)
Uma visualização de superfície é um objeto View que une um objeto Surface para fazer desenhos e expõe métodos para especificar o tamanho e o formato dinamicamente. Ela permite desenhar de maneira independente da linha de execução de interface para operações com uso intenso de recursos, como jogos ou visualizações de câmera. No entanto, essa opção consome mais memória. Uma visualização de superfície oferece suporte a gráficos de tela e OpenGL ES. A classe de base para um objeto SurfaceView é SurfaceView.
tema
Um tema é um conjunto de propriedades, como tamanho de texto e cor de plano de fundo, agrupadas para definir várias configurações padrão de exibição. O Android oferece alguns temas padrão, listados em R.style e com prefácio Theme_.
visualização (termo genérico), View (elemento da API)
Uma visualização desenha uma área retangular na tela e processa cliques, pressionamento de teclas e outros eventos de interação. A classe View é a classe base para a maioria dos componentes de layout de uma atividade ou tela de diálogo, como caixas de texto e janelas. Um objeto View recebe chamadas do objeto pai (consulte ViewGroup) para se desenhar e informa ao objeto pai sobre o tamanho e a localização preferidos, que podem não ser respeitados pelo pai. Para mais informações, consulte View.
grupo de visualizações (termo genérico), ViewGroup (elemento da API)
Um grupo de visualizações agrupa um conjunto de visualizações filhas. O grupo de visualizações é responsável por decidir onde as visualizações filhas são posicionadas e qual pode ser o tamanho delas, bem como por chamar cada uma para fazer o próprio desenho quando apropriado. Alguns grupos de visualizações são invisíveis e servem apenas para layout, enquanto outros têm uma interface intrínseca, como uma caixa de listagem de rolagem. Os grupos de visualizações estão no pacote android.widget, mas estendem a classe ViewGroup.
hierarquia de visualizações
Uma hierarquia de visualizações é uma organização de objetos de visualização e de grupos de visualizações que definem a interface do usuário para cada componente de um app. A hierarquia consiste em grupos de visualizações que contêm uma ou mais visualizações filhas ou grupos de visualizações. Você pode conseguir uma representação visual de uma hierarquia de visualizações para depuração e otimização usando o Hierarchy Viewer, que é fornecido com o SDK do Android.
Vulkan
O Vulkan é uma API multiplataforma de baixa sobrecarga para gráficos 3D de alto desempenho.
widget
Um widget é um dos conjuntos de subclasses de visualização totalmente implementadas que renderizam elementos de formulário e outros componentes de interface, como uma caixa de texto ou um menu pop-up. Como um widget é totalmente implementado, ele processa a medição, o próprio desenho e respostas a eventos de tela. Os widgets estão no pacote android.widget.
janela (termo genérico), Window (elemento da API)
Em um app Android, uma janela é um objeto derivado da classe abstrata Window, que especifica os elementos de uma janela genérica, como aparência, texto da barra de título, local e conteúdo dos menus. As caixas de diálogo e as atividades usam uma implementação da classe Window para renderizar um objeto Window. Não é necessário implementar a classe Window ou usar janelas no app.

Os desenvolvedores de apps desenham imagens na tela de três maneiras: com o Canvas, o OpenGL ES ou o Vulkan.

Componentes gráficos do Android

Não importa qual API de renderização os desenvolvedores usam, tudo é renderizado em uma superfície. A superfície representa o lado do produtor de uma fila de buffer que é frequentemente consumida pelo SurfaceFlinger. Todas as janelas que são criadas na plataforma Android são apoiadas por uma superfície. Todas as superfícies visíveis renderizadas são compostas na tela pelo SurfaceFlinger.

O diagrama a seguir mostra como os principais componentes funcionam juntos:

componentes de renderização de imagens

Figura 1. Como as superfícies são renderizadas.

Os componentes principais são descritos nas seções a seguir.

Produtores de fluxos de imagens

Um produtor de stream de imagem pode ser qualquer coisa que produz buffers gráficos para consumo. Exemplos incluem OpenGL ES, Canvas 2D e decodificadores de vídeo do mediaserver.

Consumidores de fluxos de imagens

O consumidor mais comum de streams de imagem é o SurfaceFlinger, o serviço do sistema que consome as superfícies visíveis no momento e as compõe na tela usando informações fornecidas pelo gerenciador de janelas. O SurfaceFlinger é o único serviço que pode modificar o conteúdo da tela. Ele usa o OpenGL e o Hardware Composer (HWC) para compor um grupo de superfícies.

Outros apps OpenGL ES também podem consumir streams de imagem, como o app de câmera que consome um stream de imagem de visualização da câmera. Apps que não são GL também podem ser consumidores, por exemplo, a classe ImageReader.

Hardware Composer

A abstração de hardware para o subsistema de exibição. O SurfaceFlinger pode delegar determinados trabalhos de composição ao HWC para reduzir o trabalho do OpenGL e da GPU. O SurfaceFlinger atua como apenas mais um cliente do OpenGL ES. Portanto, quando o SurfaceFlinger está compondo ativamente um ou dois buffers em um terceiro, por exemplo, ele usa o OpenGL ES. Isso faz com que a composição consuma menos energia do que a GPU realizar toda a computação.

A HAL do Hardware Composer conduz a outra metade do trabalho e é o ponto central de toda a renderização de gráficos do Android. O HWC precisa oferecer suporte a eventos, como VSync ou hotplug para suporte plug-and-play a HDMI.

Gralloc

O alocador de memória gráfica (Gralloc) é necessário para alocar a memória solicitada pelos produtores de imagens. Para mais detalhes, consulte BufferQueue e Gralloc.

Fluxo de dados

O diagrama a seguir mostra o pipeline de gráficos do Android:

fluxo de dados gráficos

Figura 2. Fluxo de dados gráficos pelo Android.

Os objetos à esquerda são renderizadores que produzem buffers gráficos, como a tela inicial, a barra de status e a interface do sistema. Tanto o SurfaceFlinger quanto o HWC atuam como compositores.

BufferQueue

As BufferQueues fornecem a liga entre os componentes gráficos do Android. Elas são um par de filas que mediam o ciclo constante de buffers do produtor para o consumidor. Depois que os produtores entregam os buffers, o SurfaceFlinger é responsável por compor tudo na tela.

O diagrama a seguir ilustra o processo de comunicação da BufferQueue:

Processo de comunicação da BufferQueue

Figura 3. Processo de comunicação da BufferQueue.

A BufferQueue contém a lógica que vincula produtores e consumidores de fluxos de imagens. Alguns exemplos de produtores de imagens são as visualizações produzidas pelo HAL da câmera ou pelos jogos OpenGL ES. Alguns exemplos de consumidores de imagens são o SurfaceFlinger ou outro app que exibe um stream OpenGL ES, como o app de câmera que mostra o visor da câmera.

A BufferQueue é uma estrutura de dados que combina um pool de buffers com uma fila e usa o IPC do Binder para transmitir buffers entre processos. A interface do produtor, ou o que você transmite a alguém que quer gerar buffers gráficos, é IGraphicBufferProducer (parte de SurfaceTexture). A BufferQueue é usada com frequência para renderizar em uma superfície e consumir com um Consumer GL, entre outras tarefas.

A BufferQueue pode operar em três modos diferentes:

modo semelhante ao síncrono
Por padrão, a BufferQueue opera em um modo semelhante ao síncrono, em que cada buffer que vem do produtor é enviado ao consumidor. Nenhum buffer é descartado nesse modo. Se o produtor for muito rápido e criar buffers mais rápido do que eles estão sendo drenados, ele bloqueia e aguarda buffers livres.
modo sem bloqueio
A BufferQueue também pode operar em um modo não bloqueante, em que gera um erro em vez de esperar por um buffer nesses casos. Nenhum buffer é descartado nesse modo também. Isso é útil para evitar possíveis impasses em softwares de aplicativos que podem não entender as dependências complexas do framework gráfico.
modo de descarte
A BufferQueue pode ser configurada para descartar buffers antigos em vez de gerar erros ou aguardar. Por exemplo, se a renderização GL for realizada em uma visualização de textura e estiver desenhando o mais rápido possível, os buffers precisarão ser abandonados.

Para realizar a maior parte desse trabalho, o SurfaceFlinger atua como apenas outro cliente do OpenGL ES. Portanto, quando o SurfaceFlinger está compondo ativamente um ou dois buffers em um terceiro, por exemplo, ele usa o OpenGL ES.

A HAL do Hardware Composer realiza a outra metade do trabalho. Essa HAL atua como o ponto central de toda a renderização de gráficos do Android.