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.
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.
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.
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
Compilando Android para Raspberry PI 2 B by Cleiton Bueno is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.