Compilando Android para Raspberry PI 2 B

Neste artigo iremos ver como preparar o ambiente, sincronizar e baixar dos repositórios tudo que é necessário para a construção bem sucedida do Android 6.0 Marshmallow para uma placa Raspberry PI 2 B.

Podemos pular a parte do que se trata Android certo? Pois imagino que você que esteja lendo no mínimo possua, já possuiu ou lida com equipamentos com sistema operacional Android, seja em Celulares, Tablets, TV’s, Relógios ou até mesmo em Automóveis.

O Android desde quando surgiu possui um parentesco com o Linux, pois compartilhando do mesmo Kernel do Linux incluindo algumas adaptações para o Android. Se assimilou de outras características como o Toolbox que lembra muito o Busybox e a Comunicação entre Processos IPC que poderia utilizar o conhecido System V IPC, mas possui um próprio chamado Binder que realiza a comunicação via socket entre a API e as aplicações.

O que mais me chamou atenção ao conhecer o Android por dentro, foi de saber que não utilizam glibc, uclibc, dietlibc, e sim Bionic, pelo que entendi a decisão por utilizar esta lib e não as citadas foi Small Size e Speed e segundo fontes foi uma grande diferença comparado as padrões, mas houve comentários sobre licenças, pois neste caso a Bionic é BSD.

Em um artigo futuro entraremos em mais detalhes sobre esta estrutura interna, além de conhecer o Zygote e o que seria a Dalvik/ART e qual a relação entre ambos, caso queira se aprofundar neste assunto um excelente artigo é o Introdução ao Funcionamento Interno do Android do Sergio Prado.

 

Porte Android para Raspberry Pi 2 B

O AOSP(Android Open-Source Project), possui toda estrutura interna para a construção de um Android para um celular/tablet Nexus. Com o AOSP em mãos qualquer fabricante pode/deverá portar o Android para seu produto, muito importante obter este suporte do fabricante ou alguma empresa especializada em realizar este porte, pois envolve na criação do produto, adaptação e novas informações para o device, hardware e principalmente o kernel que é em comum do Linux com adaptações para o Android.

Neste caso, um excelente trabalho foi o Peter Yoon, que fez o port do Android 6 Marshmallow para a Raspberry PI 2 B, recentemente sendo trabalhado para a Raspberry PI 3.

Então iremos utilizar o porte do Peter Yoon para RaspPI2.

 

Preparando o ambiente host

Para construir o Android deve-se preparar o computador(host) para realizar compilação-cruzada, no Linux temos ferramentas de Build como Yocto Project, Buildroot e PTX Dist no caso do Android é uma ferramenta própria, unindo repo e muito Makefile.

Primeiro vamos instalar o Repo para realizar download de todos os repositórios para construir o Android, o procedimento encontra-se em Installing Repo em Source Android.

$ mkdir ~/bin
$ PATH=~/bin:$PATH
$ curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
$ chmod a+x ~/bin/repo

É recomendado o uso de um Linux 64-bits, além da instalação do OpenJDK8, no meu caso utilizando um Ubuntu 14.04LTS e os pacotes abaixo:

$ sudo apt-get install git-core gnupg flex bison gperf build-essential \
  zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 \
  lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z-dev ccache \
  libgl1-mesa-dev libxml2-utils xsltproc unzip

Agora algumas ferramentas que acho importante possuir também:

$ sudo apt-get install dosfstools gparted

Mais informações e detalhes sobre dependências para outras distribuições Linux acesse Establishing a Build Environment.

 

Repositórios Android

Agora vamos seguir o procedimento do Peter Yoon e baixar o manifest para Android 6 Marshmallow e sincronizar os repositórios, estarei utilizando um diretório em meu /home chamado android-rpi.

$ mkdir ~/android-rpi ; cd ~/android-rpi
$ repo init -u https://android.googlesource.com/platform/manifest -b android-6.0.1_r13
$ cd .repo
$ git clone https://github.com/peyo-hd/local_manifests -b marshmallow
$ repo sync

No momento que executar o sync, será feito download de todo código-fonte, segue abaixo o tamanho total do diretório após o final da sincronização.

   30,7GiB [##########]/.repo
    6,5GiB [##        ] /prebuilts
    2,6GiB [          ] /external
    1,6GiB [          ] /kernel
    1,4GiB [          ] /frameworks
  685,7MiB [          ] /tools
  497,3MiB [          ] /cts
  409,8MiB [          ] /packages
  307,6MiB [          ] /development
  277,2MiB [          ] /developers
  115,1MiB [          ] /hardware
   93,5MiB [          ] /device
   83,8MiB [          ] /ndk
   52,4MiB [          ] /libcore
   30,4MiB [          ] /sdk
   30,4MiB [          ] /system
   29,6MiB [          ] /docs
   28,8MiB [          ] /bionic
   28,2MiB [          ] /art
   15,6MiB [          ] /build
   10,2MiB [          ] /dalvik
    5,7MiB [          ] /bootable
  948,0KiB [          ] /platform_testing
  900,0KiB [          ] /pdk
  232,0KiB [          ] /libnativehelper
  128,0KiB [          ] /abi
    4,0KiB [          ]  Makefile

Então tenha uma partição com uma espaço livre que segundo o Source Android deve ser de 50G a 100G.

 

Construindo o Android para Raspberry PI 2

Agora a parte divertida, construir o Android propriamente dito, primeiro instalar mais algumas ferramentas caso já não tenha.

$ sudo apt-get install gcc-arm-linux-gnueabihf python-mako

Construindo Kernel:

 $ cd kernel/rpi
 $ ARCH=arm scripts/kconfig/merge_config.sh arch/arm/configs/bcm2709_defconfig \
android/configs/android-base.cfg android/configs/android-recommended.cfg
 $ ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- make zImage
 $ ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- make dtbs

Construindo o Android, esta etapa levara algumas horas para ser concluída.

$ source build/envsetup.sh
$ lunch rpi2-eng
$ make

Procedimento este que pode ser visto em Build for Rapsberry PI 2 do Peter Yoon.

No final, teremos os seguintes diretórios e seus respectivos tamanhos.

   30,7GiB [##########]/.repo
   20,2GiB [######    ] /out
    6,5GiB [##        ] /prebuilts
    2,6GiB [          ] /external
    1,6GiB [          ] /kernel
    1,4GiB [          ] /frameworks
  685,7MiB [          ] /tools
  497,3MiB [          ] /cts
  409,8MiB [          ] /packages
  307,6MiB [          ] /development
  277,2MiB [          ] /developers
  115,1MiB [          ] /hardware
   93,5MiB [          ] /device
   83,8MiB [          ] /ndk
   52,4MiB [          ] /libcore
   30,4MiB [          ] /sdk
   30,4MiB [          ] /system
   29,6MiB [          ] /docs
   28,8MiB [          ] /bionic
   28,2MiB [          ] /art
   15,6MiB [          ] /build
   10,2MiB [          ] /dalvik
    5,7MiB [          ] /bootable
  948,0KiB [          ] /platform_testing
  900,0KiB [          ] /pdk
  232,0KiB [          ] /libnativehelper
  128,0KiB [          ] /abi
    4,0KiB [          ]  Makefile

As imagens do Android encontram-se em:

~/android-rpi/out/target/product/rpi2 $ ls -1
android-info.txt
cache
cache.img
clean_steps.mk
data
gen
installed-files.txt
obj
previous_build_config.mk
ramdisk.img
recovery
root
symbols
system
system.img
userdata.img

Dos arquivos construídos, inicialmente precisamos conhecer e utilizaremos os arquivos a seguir, onde comento para que seria cada “imagem”.

ramdisk.img Contem o rootfs propriamente dito do Android, montado em /
system.img Possui os componentes gerados pelo AOSP durante a construção como frameworks, aplicações e os daemons, montado em /system
cache.img Para armazenamento temporário durante o funcionamento
userdata.img Possui os arquivos que são gerados durante a execução do Android, e as aplicações instaladas pelo usuário, montado em /data, inicialmente este diretório é vazio.

Dependendo da descrição do Produto, outros arquivos podem surgir como recovery.img e ramdisk-recovery.img partições estas usadas para recuperar dados do usuário ou mesmo do sistema caso algo der errado.

 

 

Preparando o microSD

Agora vamos criar as partições no microSD, estarei usando um de 4G de capacidade mas daria para usar em um de 2G, precisamos criar as seguintes partições, sistema de arquivos e tamanho:

Partição Sistema de Arquivos Tamanho Uso
Partição 1 FAT32 (b) 512MB Arquivos de boot[bootloader, kernel, ramdisk(initrd) e Device tree
Partição 2 EXT4 (83) 512MB /system
Partição 3 EXT4 (83) 512MB /cache
Partição 4 EXT4 (83) 512MB ou restante /data

A Partição 1 e Partição 3 podem ser de 128M ou mais, mas a Partição 2 e Partição 4 é bom ser de pelo menos 512M, principalmente Partição 4 o /data que pode crescer conforme uso do Android e instalação de aplicativos.

Usando o GParted e criando as partições acima, teremos algo como a imagem a seguir.

gparted_Android_cleitonbueno

Uma observação muito importante é marcar a Partição 1 como boot, para isso, cliquei com o botão direito em cima da linha da Partição 1 no meu caso /dev/sdb1 e selecione Manage Flags em seguida seleciona boot, como a imagem abaixo.

gparted_flags_boot_Android_cleitonbueno

O mesmo pode ser feito com o comando fdisk, logo mais as etapas com fdisk usando o meu microSD reconhecido como /dev/sdb, a ultima letra pode variar conforme as unidades utilizadas, para saber qual device esta para seu microSD, pode usar o comando a seguir.

$ export LC_ALL=C; sudo fdisk -l | grep ^"Disk /"
Disk /dev/sda: 500.1 GB, 500107862016 bytes
Disk /dev/sdc: 1000.2 GB, 1000204886016 bytes
Disk /dev/sdb: 3963 MB, 3963617280 bytes

Como o meu é de 4G, então é o device /dev/sdb. Agora vamos as etapas com fdisk.

$ sudo fdisk /dev/sdb

Command (m for help): p

Disk /dev/sdb: 3963 MB, 3963617280 bytes
122 heads, 62 sectors/track, 1023 cylinders, total 7741440 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x209eb7b6

   Device Boot      Start         End      Blocks   Id  System

Command (m for help): 

Command (m for help): n
Partition type:
   p   primary (0 primary, 0 extended, 4 free)
   e   extended
Select (default p): p
Partition number (1-4, default 1): 
Using default value 1
First sector (2048-7741439, default 2048): 
Using default value 2048
Last sector, +sectors or +size{K,M,G} (2048-7741439, default 7741439): +512M

Command (m for help): n       
Partition type:
   p   primary (1 primary, 0 extended, 3 free)
   e   extended
Select (default p): p
Partition number (1-4, default 2): 
Using default value 2
First sector (1050624-7741439, default 1050624): 
Using default value 1050624
Last sector, +sectors or +size{K,M,G} (1050624-7741439, default 7741439): +512M

Command (m for help): n
Partition type:
   p   primary (2 primary, 0 extended, 2 free)
   e   extended
Select (default p): 
Using default response p
Partition number (1-4, default 3): 
Using default value 3
First sector (2099200-7741439, default 2099200): +512M
Value out of range.
First sector (2099200-7741439, default 2099200): 
Using default value 2099200
Last sector, +sectors or +size{K,M,G} (2099200-7741439, default 7741439): +512M

Command (m for help): n
Partition type:
   p   primary (3 primary, 0 extended, 1 free)
   e   extended
Select (default e): p
Selected partition 4
First sector (3147776-7741439, default 3147776): 
Using default value 3147776
Last sector, +sectors or +size{K,M,G} (3147776-7741439, default 7741439): 
Using default value 7741439

Command (m for help): t
Partition number (1-5): 1
Hex code (type L to list codes): b
Changed system type of partition 1 to b (W95 FAT32)

Command (m for help): t
Partition number (1-5): 2
Hex code (type L to list codes): 83

Command (m for help): t
Partition number (1-5): 3
Hex code (type L to list codes): 83

Command (m for help): t           
Partition number (1-4): 4
Hex code (type L to list codes): 83

Command (m for help): p

Disk /dev/sdb: 3963 MB, 3963617280 bytes
122 heads, 62 sectors/track, 1023 cylinders, total 7741440 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x209eb7b6

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1            2048     1050623      524288    b  W95 FAT32
/dev/sdb2         1050624     2099199      524288   83  Linux
/dev/sdb3         2099200     3147775      524288   83  Linux
/dev/sdb4         3147776     7741439     2296832   83  Linux

Command (m for help): a
Partition number (1-4): 1

Command (m for help): p

Disk /dev/sdb: 3963 MB, 3963617280 bytes
122 heads, 62 sectors/track, 1023 cylinders, total 7741440 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x209eb7b6

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1   *        2048     1050623      524288    b  W95 FAT32
/dev/sdb2         1050624     2099199      524288   83  Linux
/dev/sdb3         2099200     3147775      524288   83  Linux
/dev/sdb4         3147776     7741439     2296832   83  Linux

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.

Syncing disks.

Em caso de duvidas sobre as opções ou queria saber mais, digite m para abrir o menu de ajuda.

O GParted cria e formata as partições de acordo com o Sistema de Arquivos especificado, com o fdisk apenas criamos as partições e agora vamos formatá-las e adicionar um nome(Label) para cada partição.

$ sudo mkfs.vfat -n BOOT /dev/sdb1
mkfs.vfat 3.0.14 (23 Jan 2023)

$ sudo mkfs.ext4 -L SYSTEM /dev/sdb2
mke2fs 1.42.5 (29-Jul-2012)
Filesystem label=SYSTEM

$ sudo mkfs.ext4 -L CACHE /dev/sdb3
mke2fs 1.42.5 (29-Jul-2012)
Filesystem label=CACHE

$ sudo mkfs.ext4 -L DATA /dev/sdb4
mke2fs 1.42.5 (29-Jul-2012)
Filesystem label=DATA

Pronto! Até aqui vimos duas maneiras de preparar as partições no microSD.

 

Copiando as imagens/arquivos do Android

Nesta etapa iremos copiar os arquivos gerados pelo processo de construção do Android e gravar as imagens nas partições relacionadas a cada uma, como adicionamos nomes(Labels) para as partições, após inserir o cartão ficara fácil reconhecer cada partição e seu uso através do nome no ponto de montagem.

/dev/sdb1 on /media/cleiton/BOOT type vfat
/dev/sdb2 on /media/cleiton/SYSTEM type ext4 
/dev/sdb3 on /media/cleiton/CACHE type ext4
/dev/sdb4 on /media/cleiton/DATA type ext4

Primeiro vamos copiar os arquivos necessários para o processo de boot para /media/$USER/BOOT, a variável $USER referenciando ao nome do seu usuário, acesse os diretórios abaixo e copiando os arquivos.

~/android-rpi/device/brcm/rpi2/boot $ cp -ra * /media/$USER/BOOT/
~/android-rpi/kernel/rpi/arch/arm/boot $ cp -ra zImage /media/$USER/BOOT/
~/android-rpi/kernel/rpi/arch/arm/boot $ cp -ra dts/bcm2709-rpi-2-b.dtb /media/$USER/BOOT/
~/android-rpi/out/target/product/rpi2 $ cp -ra ramdisk.img /media/$USER/BOOT/

Próximo passo é gravar a imagem system.img na partição que possui ponto de montagem SYSTEM.

~/android-rpi/out/target/product/rpi2 $ sudo umount /media/$USER/SYSTEM 
~/android-rpi/out/target/product/rpi2 $ sudo dd if=system.img of=/dev/sdb2 bs=1M ; sync 
512+0 records in
512+0 records out
536870912 bytes (537 MB) copied, 15,5698 s, 34,5 MB/s

As partições com nome DATA e CACHE ficaram vazias, não iremos gravar o cache.img e o userdata.img.

Nosso microSD esta preparado e com o básico para iniciar o Android na Raspberry PI 2 B.

 

Primeiro boot

Inserindo o microSD e alimentando a placa, o primeiro boot levou pouco mais de 1 minuto, as demais inicializações ficaram entre 40s a 50s. Algumas imagens do boot e algumas informações do Android 6 na Raspberry PI 2 B.

 

Android6_RaspberryPI2_Boot_cleitonbueno.com

Android6_RaspberryPI2_Infos

Android6_RaspberryPI2_Memory_cleitonbueno.com

A seguir o video com o processo de boot.

 

Até a próxima!

 

Referencias

http://source.android.com/source/initializing.html

https://github.com/peyo-hd/local_manifests

https://github.com/peyo-hd/device_brcm_rpi2

sergioprado.org/introducao-ao-funcionamento-interno-do-android/

http://tldp.org/HOWTO/Partition/fdisk_partitioning.html

Share Button

CC BY-NC-SA 4.0 Compilando Android para Raspberry PI 2 B by Cleiton Bueno is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.