Android Embarcado

O Android é, sem sombra de dúvidas, um dos sistemas operacionais mais dominantes do mundo. Ele está presente em smartphones, tablets, smart TVs, smart watches, veículos, etc., fazendo assim parte do nosso dia-a-dia. Uma das maiores razões desta popularização massiva do Android foi o fato de o mesmo ser open-source: o código-fonte do Android “mais puro”, isto é, sem customizações dos fabricantes, é disponibilizado na forma open-source, sendo este chamado de AOSP (Android Open-Source Project). Logo, os fabricantes de dispositivos que utilizam o Android aproveitam o máximo possível do AOSP, inserindo suas customizações (para adaptar o Android ao hardware desejado) criando, assim, seu Android próprio / “não-puro”.

O Instituto de Pesquisas ELDORADO possui sólida experiência em Android Embarcado, abrangendo toda a cadeia de camadas presentes no Android, indo desde desenvolvimento em camada nativa até desenvolvimentos em framework e aplicações alto-nível. Sendo assim, como forma de contribuição de conhecimento para com a comunidade de desenvolvimento brasileira, nós disponibilizamos este artigo, que mostra o passo a passo do desenvolvimento da primeira aplicação em C nativa para o Android.

Além disso, esse artigo visa explicar os fundamentos para se entender o AOSP e a divisão em camadas do Android em termos de software.

Pré-requisitos

Para compreender e conseguir fazer sua primeira aplicação em C nativa para o Android, você deve ter as seguintes habilidades:

  • Ter certa vivência com Linux (estar acostumado a utilizar o terminal e dominar os comandos mais comuns);
  • Ter bom conhecimento em programação C e C++ em Linux (para escrita de programas, leitura de códigos-fontes de complexidades distintas e, ainda, ter noções de estruturação de um makefile no Linux);
  • Possuir conhecimentos básicos de comunicação de um computador com sistemas Android via ferramenta adb.

Em termos de software, você precisará ter instalado no computador host (que irá fazer as compilações) o seguinte:

  • Ferramentas para comunicação com Android. Se quiser instalar todas de uma vez e ainda ter um ambiente preparado para desenvolvimento futuro de aplicações Android (em Java ou Kotlin), instale o Android Studio;
  • O computador que fará as compilações deverá ter como sistema operacional o Ubuntu 14.04 64-bits. Existem outras distribuições que também suportam a compilação do Android (incluindo a 18.04 64-bits), porém o Ubuntu 14.04 64-bits é considerada a principal / referência.

Já em termos de hardware, o computador que fará as compilações deverá ter como requisitos mínimos de hardware: processador com oito núcleos/cores, memória RAM de 16GB e grande espaço de armazenamento (recomendação mínima: 100 GB). Preferencialmente, a unidade de armazenamento deve ser do tipo SSD, uma vez que o número de acessos à unidade de armazenamento durante a compilação do Android é gigantesco, logo um  SSD tornará o tempo de compilação muito menor (em relação a um disco rígido comum).

 Pontos de atenção

O Android Embarcado (e seu desenvolvimento em si) possui os seguintes pontos de atenção:

  • AOSP: o AOSP (Android Open-Source Project) consiste, basicamente, no código-fonte base do Android. Ele é fornecido pelo Google e mantido com a ajuda da comunidade, o que faz com que hajam sempre evoluções.

 

  • É preciso um computador com configurações de hardware muito boas: para compilar o Android, conforme dito, é preciso de um bom computador. Como alternativa, caso não se disponha de um computador do porte exigido, é possível locar uma VPS para servir como build-server Android.

 

  • Apesar de se poder compilar o Android com o AOSP, não se pode diretamente gravar a versão que você compilou em seu dispositivo físico: o AOSP se comporta como uma espinha dorsal do Android, ou seja, é a base de tudo em se tratando de Android. Porém, sozinha, não é suficiente para gerar uma build Android apta a ser executada em um dispositivo físico (um smartphone, por exemplo). O processo de portar um Android para um dispositivo físico (processo este feito pelos fabricantes) é algo extremamente dependente do hardware do dispositivo e, além disso, exige customizações de software a nível de Kernel, algo nada trivial para um iniciante em Android Embarcado.

 

  • A documentação oficial é relativamente pobre, exigindo muita leitura de código-fonte: infelizmente, a documentação oficial do Android é relativamente pobre. É bem complicado (para não dizer impossível) conhecer com grande nível de detalhes o Android somente com a documentação oficial. Logo, se deseja trabalhar com Android Embarcado, ter proficiência em ler códigos escritos em C, C++ e Java faz grande diferença para entender, em detalhes, como o sistema operacional funciona.

 

  • O Android não possui forte padronização: infelizmente, padronização de códigos-fonte (nomenclaturas, fluxos de funcionamento, etc.) e documentação em geral não é um ponto forte do Android. Por essa razão, o aprendizado pode ser um pouco mais lento do que se espera. Um dos possíveis motivos disso é o grande número de pessoas contribuindo para o AOSP, gerando um crescimento muito grande em funcionalidades e, consequentemente, deixando a desejar na documentação das features implementadas e da codificação como um todo.

 

  • A comunidade é sua amiga: você pode (e deve) contar com a comunidade de desenvolvedores Android para aprender com profundidade e também ver soluções de bugs conhecidos do Android. Portanto, frequentar fóruns e listas de discussão sobre o assunto é altamente recomendado.

 

  • O Android possui sua própria lib C e sistema de build C: na linha de que padronização não é um ponto forte do Android, o Android não utiliza as bibliotecas nem sistemas de build C padrão do Linux. Por exemplo, como lib C, ele faz uso da bionic.

Overview – Android Embarcado e AOSP

Antes de prosseguir, é necessário se habituar com conceitos básicos de arquitetura e ferramentas de desenvolvimento do AOSP. Veja isso em detalhes nos tópicos a seguir.

O Android é semelhante ao Linux?

De início, é importante ter em mente que o Android é um sistema operacional baseado no Linux. A semelhança com o Linux se dá na questão dos sub-sistemas/componentes envolvidos (bootloader, kernel e file system) e por grande parte do Kernel Android ser uma customização do Kernel Linux. E a semelhança para por aí. Ou seja, o Android é semelhante em algumas coisas ao Linux em questões mais internas/baixo-nível, já para coisas em um nível mais alto (como estrutura de pastas e mecanismos de inicialização automática de serviços, por exemplo), o Android possui sua própria estruturação.

Aqui vale ressaltar que os comandos Linux suportados no Android (via adb, por exemplo) são, na verdade, um subset dos comandos disponíveis no Linux por padrão. Para ter acesso à grande maioria dos comandos padrão do Linux, é preciso utilizar algo adicional, como o BusyBox ou Toybox.

Arquitetura do AOSP/Android

Em termos de arquitetura de software, o Android pode ser representado pela figura 1. Nela, é possível observar que a Plataforma Android propriamente dita (ou seja, o que desenvolvedores alto-nível de aplicações/aplicativos que utilizam framework do Android) é a parte com maior nível de abstração (de bibliotecas, daemons e tools). O restante (baixo-nível), apesar de ter suas peculiaridades, é fortemente baseado no que já existe em Linux.

Android Embarcado

Em termos de diagrama de blocos, a divisão entre as camadas do Android pode ser representada pela figura 2. Nela, destaca-se a questão do Kernel Linux (baixo-nível) e do framework de aplicação (alto-nível) muito rico, o qual permite o desenvolvimento de aplicações altamente portáveis e versáteis (interagindo facilmente com recursos do dispositivo Android em questão). O projeto deste artigo será ambientado no nível mais baixo, chamada de camada nativa ou, no diagrama, de Linux Kernel.

Android Embarcado

Onde obter o AOSP? E como ele é composto?

O código-fonte do AOSP pode ser obtido em: http://source.android.com/source/index.html. O AOSP é versionado através do git, mas, por ser formado por centenas ou milhares de repositórios distintos, o Google criou uma ferramenta chamada repo para gerenciar todos estes repositórios necessários para compor o AOSP. Para instalar tal ferramenta, siga os passos abaixo:

  • Crie um diretório chamado bin no seu home e entre neste diretório:
cd ~

mkdir bin

cd bin

 

  • Baixe a ferramenta conforme abaixo:
wget https://storage.googleapis.com/git-repo-downloads/repo -O repo

 

  • Modifique as permissões para todos os arquivos de ~/bin/repo:
chmod a+x ~/bin/repo

 

  • Por fim, acrescente a sua variável de ambiente PATH o caminho para o diretório bin:
export PATH=~/bin:$PATH

 

Nesta ferramenta, quem diz quais repositórios irão compor o AOSP é um arquivo chamado manifest.xml. Inclusive, uma das primeiras etapas de customização dos fabricantes que embarcam o Android em seus produtos é filtrar quais repositórios devem e não devem compor a base do AOSP desejada.

Como obter o AOSP?

 Para obter o AOSP, siga os passos abaixo:

  • Crie em seu home um diretório para baixar o código-fonte do AOSP e entre neste diretório. Supondo que tal diretório se chame android_aosp_source_code, execute o seguinte comando:
cd ~

mkdir android_aosp_source_code

cd android_aosp_source_code

  • Faça o repo init. O repo init consiste em baixar o manifest.xml em um diretório oculto .repo, além de preparar o terreno para baixar os repositórios (algo a ser feito no próximo passo).
repo init -u https://android.googlesource.com/platform/manifest
  • Uma vez feito o repo init, tudo está preparado para baixar de fato os repositórios (listados no manifest). Para isso execute o comando repo sync e aguarde. O download demora bastante, uma vez que pode vir, facilmente, mais de 30 GB de conteúdo.
repo sync -j4

Compilação do AOSP

Assim que a execução do repo sync for terminada, todo o código-fonte do AOSP já estará à sua disposição. O próximo passo é, portanto, fazer a compilação do AOSP. A compilação do Android é formada por duas etapas distintas: preparação do ambiente de compilação (onde as variáveis de ambiente necessárias são configuradas) e a compilação propriamente dita.

  • Preparação do ambiente de compilação: para isso, é utilizado um script para preparação das variáveis de ambiente e uma ferramenta (já contida no AOSP) chamada lunch. Essa ferramenta tem como utilidade permitir se escolher para qual dispositivo o AOSP será compilado e o tipo de Android a ser compilado (como, por exemplo, o tipo eng: um Android com privilégios de engenharia/root). Portanto, para preparar o ambiente de compilação, esteja na pasta em que o código-fonte do AOSP foi baixado (este artigo faz a suposição que esteja na pasta ~/android_aosp_source_code) e execute o comando abaixo:
source build/envsetup.sh

 

Agora é a hora de se escolher o dispositivo-alvo (target) e tipo de compilação de Android (build) com a ferramenta lunch. Como aqui buscamos testar tudo em emulador e não pretendemos criar uma build com restrições de execução e acessos, será escolhido como target uma plataforma genérica em modo eng. Para isso, execute o comando abaixo e escolha a opção correspondente a aosp_arm-eng.

lunch
  • Compilação do AOSP: para compilar, utilize o comando make. É altamente recomendável que você especifique o máximo número de jobs possíveis (atributo atrelado ao processador do computador host/que irá compilar). Para um computador com processador de 8 núcleos/cores, um bom número de jobs é 4.
make -j4

 

A compilação é um processo bem demorado e com desempenho altamente dependente da quantidade de memória RAM disponível e tipo de unidade de armazenamento do computador host.

Ao final do processo de compilação, a build Android gerada estará disponível em: ~/android_aosp_source_code/out/target/product/generic/

 Emulação do AOSP

O AOSP já vem com um emulador, o que facilita muito o aprendizado, testes e desenvolvimento com Android Embarcado.

Este emulador, na verdade, consiste em um qemu customizado para rodar builds Android. Antes de utilizá-lo, assegure-se de ter rodado o script de preparação de variáveis de ambiente. Isto é importante para que o emulador saiba qual plataforma emular e onde está a build Android compilada.

source build/envsetup.sh

Feito isso, utilize o comando abaixo para emular o Android que você compilou:

emulator &

O emulador ainda dá acesso, via adb, ao console do Android.

Construindo sua primeira aplicação C nativa do Android

Uma vez com o código baixado, compilado e apto a rodar no emulador, podemos finalmente iniciar o desenvolvimento da primeira aplicação em C para rodar na camada nativa do Android.

Considerações sobre compilação de aplicações nativas no Android

A compilação de qualquer aplicação / módulo nativo no Android é feita junto com a compilação do Android ou separadamente (e, posteriormente, adicionada às respectivas imagens na build Android final).

É importante relembrar que o Android tem seu próprio sistema de build, o que significa dizer que o programador não pode “mandar” o Android compilar algo com parâmetros específicos, mas sim deve se limitar a escrever o código-fonte da aplicação e um makefile para a mesma, e o sistema de build do Android se encarrega de compilar. Obrigatoriamente, todos os makefiles de aplicações nativas no Android devem se chamar Android.mk. Visando maior organização e modularização, makefiles com nomes diferentes podem ser utilizados, desde que incluídos, em algum ponto, por algum makefile chamado Android.mk.

Projeto da primeira aplicação em C nativa no Android

Esta aplicação, para fins de exemplo, será um Hello World. Para isso, siga o procedimento abaixo:

  • Assumindo que você esteja com o código-fonte do AOSP baixado em ~/android_aosp_source_code, vá até o diretório device/generic/aosp_arm:
cd ~/android_aosp_source_code/device/generic/aosp_arm

 

  • Neste diretório, crie um diretório específico para sua aplicação. Aqui será considerado o nome hello_world como nome do diretório:
mkdir hello_world

 

  • Crie no diretório específico da sua aplicação (ou seja, o diretório ~/android_aosp_source_code/device/generic/aosp_arm/hello_world) um arquivo chamado hello_world.c (código-fonte de sua aplicação C) com o seguinte conteúdo:
/* Primeira aplicacao nativa em C para Android */

#include <stdio.h>

 

int main(void)

{

printf(“\r\nHello world\n”);

printf(“\r\nEsta eh minha primeira aplicacao em C nativa para Android!!!\n”);

return 0;

}

 

  • Agora, é hora de criar o makefile de sua aplicação. Para isso, no mesmo diretório (~/android_aosp_source_code/device/generic/aosp_arm/hello_world), crie um arquivo chamado Android.mk com o seguinte conteúdo:
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

 

LOCAL_SRC_FILES = hello_world.c

LOCAL_MODULE = hello_world

 

#define que sua aplicacao somente sera incluida em builds do tipo eng e/ou quando for

#explicitamente solicitada em scripts init.rc

LOCAL_MODULE_TAGS = optional

 

#define que sua aplicacao sera um executavel no Android

include $(BUILD_EXECUTABLE)

 

  • Agora, é preciso especificar que sua aplicação deve estar presente na build Android a ser compilada, uma vez que ela foi definida como opcional. Para isso, edite o arquivo ~/android_aosp_source_code/device/generic/aosp_arm/common.mk de forma a adicionar o seguinte trecho após a definição original de PRODUCT_PACKAGES:
PRODUCT_PACKAGES += \

hello_world

 

Observação: infelizmente, nomes de makefiles podem sofrer alterações de tempos em tempos (devido à falta de padrões no AOSP em alguns aspectos, conforme já mencionado anteriormente neste artigo). Se o makefile common.mk não existir neste diretório, o makefile correspondente (neste mesmo diretório) é aquele onde está definido o PRODUCT_PACKAGES (só haverá um makefile nesta pasta com esta definição).

Pronto! Agora basta compilar o AOSP (conforme explicado no tópico “Compilação do AOSP” deste artigo) e a sua aplicação já estará contida na build Android compilada.

Testando a aplicação desenvolvida

Finalmente, é hora de testar a aplicação desenvolvida rodando na build Android compilada. Para isso, siga o procedimento abaixo:

  1. Execute o emulador (veja como no tópico “Emulação do AOSP” deste artigo).
  2. Comunique-se com o Emulador através da ferramenta adb. Para isso, execute o comando adb wait-for-device no terminal Linux de seu computador host. Assim que a execução do comando for terminada, execute o comando adb devices e certifique-se que o emulador Android consta na lista de dispositivos exibida.
  3. Execute o comando abaixo para abrir uma sessão de terminal com o Android do emulador:
adb shell

 

  • Execute a sua aplicação pelo seu nome (no caso, o makefile construído neste artigo a nomeia como hello_world).
hello_world

 

 Considerações finais sobre Android Embarcado

O Android é um sistema operacional dominante, sendo parte integrante de muitos dispositivos que utilizamos rotineiramente, como, por exemplo: smartphones, tablets, smart TVs, smart watches e veículos. Além disso, é um sistema operacional, em essência, open-source, o que faz com que sua aplicação e evolução aumentem exponencialmente.

Porém, talvez devido ao crescimento exponencial de desenvolvedores e ferramentas para o Android, o AOSP (Android Open-Source Project) possui um grande ponto negativo: documentação fraca. Isso dificulta o aprendizado rápido e força a leitura de códigos-fonte para completo entendimento do funcionamento de um módulo. Apesar disso, é um sistema com arquitetura muito bem definida e robusta.

Referências

 

Leia também: Segurança da informação no desenvolvimento Android