Gráficos

Ícone do 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:

canvas (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. 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 na tela. 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 IU, 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 de drawable: arquivos XML ou bitmap que descrevem a imagem. Os recursos de drawable são compilados em subclasses de android.graphics.drawable. Para saber mais sobre drawables e outros recursos, consulte Recursos.
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 do Android (NDK). Os pacotes android.opengl e javax.microedition.khronos.opengles expõem a funcionalidade do OpenGL ES.
surface (termo genérico), Surface (elemento da API)
Uma superfície representa um bloco de memória composto na tela. Uma superfície evita que uma tela desenhe 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. Um SurfaceView 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 SurfaceView oferece suporte a gráficos de tela e OpenGL ES. A classe de base de 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ção (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ção 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ção estão no pacote widget, mas estendem a classe ViewGroup.
hierarquia de visualização
Uma hierarquia de visualizações é uma organização de objetos de visualização e de grupo de visualização que define a interface do usuário para cada componente de um app. A hierarquia consiste em grupos de visualização que contêm uma ou mais visualizações filhas ou grupos de visualização. 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 IU, como uma caixa de texto ou um menu pop-up. Como um widget é totalmente implementado, ele processa a medição, o desenho por conta própria e responde a eventos de tela. Os widgets estão no pacote android.widget.
window (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 imagem

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

Os principais componentes são descritos abaixo:

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. O SurfaceFlinger usa o OpenGL e o compositor de hardware 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 Hardware Composer 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 está usando o OpenGL ES. Isso faz com que a composição consuma menos energia do que a GPU realizar toda a computação.

O Hardware Composer HAL conduz a outra metade do trabalho e é o ponto central de toda a renderização de gráficos do Android. O compositor de hardware precisa oferecer suporte a eventos, um deles é VSYNC (outro é hotplug para suporte plug-and-playHDMI).

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 HAL do Gralloc.

Fluxo de dados

Consulte o diagrama a seguir para conferir uma representação do 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. O SurfaceFlinger é o compositor e o Hardware Composer é o compositor.

BufferQueue

As BufferQueues fornecem a união 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.

Confira o diagrama a seguir para o processo de comunicação do BufferQueue.

Processo de comunicação do BufferQueue

Figura 3. Processo de comunicação BufferQueue

O BufferQueue contém a lógica que vincula os 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 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 para alguém que quer gerar buffers gráficos, é IGraphicBufferProducer (parte de SurfaceTexture). O BufferQueue é usado com frequência para renderizar em uma plataforma e consumir com um consumidor 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 para o consumidor. Nenhum buffer é descartado nesse modo. E se o produtor for muito rápido e criar buffers mais rápido do que eles estão sendo drenados, ele vai bloquear e aguardar buffers livres.

Modo não de bloqueio: a BufferQueue também pode operar em um modo não de bloqueio, em que gera um erro em vez de esperar por um buffer nesses casos. Nenhum buffer é descartado nesse modo. Isso é útil para evitar possíveis deadlocks em softwares de aplicativos que podem não entender as dependências complexas do framework gráfico.

Modo de descarte: por fim, a BufferQueue pode ser configurada para descartar buffers antigos em vez de gerar erros ou esperar. Por exemplo, se a renderização GL for realizada em uma visualização de textura e renderização 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 está usando o OpenGL ES.

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