O Android Automotive é uma modificação do AOSP (Android Open Source Project) feita oficialmente pelo Google e anunciada no Google I/O de 2017[1]. Este sistema de código aberto, livre para qualquer pessoa baixar e modificar da forma que preferir, possui interface amigável e implementação de uma HAL (Hardware Abstraction Layer) específica para a comunicação com veículos: VHAL (Vehicle Hardware Abstraction Layer).
Os grandes fabricantes de carros têm demonstrado interesse em desenvolver produtos a partir dessa modificação. Pode-se citar como exemplos a Volvo, que foi a primeira fabricante a anunciar um carro com Android Automotive em 2019, o Volvo XC40 [2], e a Honda, que anunciou em setembro desse ano que lançará modelos com o Sistema Operacional da Google em 2022. [3]
Este artigo tem como objetivo ensinar o passo a passo de como utilizar o Android Automotive em uma plataforma popular como um Raspberry Pi.
Android Automotive x Android Auto
Já é comum encontrar carros que são anunciados com o Android Auto, mas cuidado: Android Auto e Android Automotive não são a mesma coisa.
O Android Auto é uma aplicação do Android disponível para celular e que necessita do suporte da central multimídia do carro. Dessa forma o seu celular terá uma segunda tela, a do carro, em modo Android Auto, que lhe permitirá usar aplicativos que estão instalados em seu celular, como Google Maps, Spotify, Waze etc. [4]
O Android Automotive, diferente do Android Auto, não é apenas uma aplicação e sim um sistema Android por completo, feito para ser tanto computador de bordo quanto central multimídia. Além de executar as aplicações como o Android Auto, o Android Automotive realiza a coleta de diversas informações do carro como velocidade, temperatura de motor e rodas, RPM, controlar vidros e ar-condicionado. [5]
O objeto deste artigo é Android Automotive, um sistema Android completo que será instalado em uma Raspberry Pi.
Raspberry Pi 4 Modelo B
Popular no mundo dos makers, a Raspberry Pi é uma placa de desenvolvimento modelada pela Raspberry Foundation, feita com SoC’s da Broadcom que possuem o núcleo ARM.
Se tratando de Android puro, nesta versão de Android Automotive para Raspberry é utilizado o Android 11, na qual o Google recomenda uma quantidade acima de 2GB de memória RAM. Logo, as duas únicas opções disponíveis para esse projeto são a Raspberry Pi 4 Modelo B de 4GB e a de 8GB de RAM.
Para mais informações sobre a Raspberry 4, recomendo o artigo do Fábio Souza [9].
Pré-requisitos
Para colocar em prática o passo a passo contido neste artigo, será necessário:
- Um computador de 64-bits com pelo menos 150GB de espaço em disco e no mínimo 16GB de memória RAM.
- Ubuntu 18.04 (Bionic Beaver) é o SO recomendado e testado pelo Google. Nada impede de você usar outra distribuição, mas talvez seja necessária alguma adaptação.
- Raspberry Pi 4 Modelo B de 4GB ou 8GB de RAM
- Um pendrive ou cartão SD de pelo menos 16GB para armazenar as imagens geradas
- Um display de pelo menos 1024×600 de densidade de pixels ou um monitor HD
- Conhecimento intermediário em uso de terminal no Linux
- Conhecimento intermediário com uso de Git
Esta versão de Android Automotive para Raspberry foi desenvolvida pela empresa Snapp Automotive[6] com código-fonte disponível no GitHub [7], e este, por si, foi baseado no projeto Android on Raspberry que também está disponível no GitHub [8].
Configuração inicial
Bibliotecas e Toolchain
Antes de baixar e compilar o Android, é necessária a instalação de algumas bibliotecas e da toolchain para compilação do kernel. Você pode utilizar os comandos abaixo para instalá-las.
$ sudo apt install git-core gnupg flex bison build-essential zip curl zlib1g-dev x11proto-core-dev libx11-dev libgl1-mesa-dev libxml2-utils xsltproc unzip fontconfig libncurses5 procps libssl-dev bc fdisk eject
$ sudo apt install gcc-aarch64-linux-gnu
Repo
Instale a ferramenta repo que baixa e agrupa todos os repositórios git do Android.
$ sudo curl https://storage.googleapis.com/git-repo-downloads/repo > /bin/repo
$ sudo chmod a+x ~/bin/repoVerifique se foi instalado corretamente usando o seguinte comando:
$ repo versionBaixando o código-fonte
Para baixar o código-fonte do Android Automotive, primeiramente crie uma pasta para o seu projeto:
$ mkdir android-automotive
$ cd android-automotive
Agora é preciso baixar a versão oficial Android 11 diretamente dos repositórios do Google. A label utilizada será a android11-qpr2-release executada no comando a seguir:
$ repo init -u https://android.googlesource.com/platform/manifest -b android11-qpr2-releaseApós concluir o init, os arquivos de manifest dos projetos Android on Raspberry e Snapp Automotive devem ser clonados para dentro da pasta android-automotive/.repo/local_manifests, seguindo o comando:
$ git clone https://github.com/snappautomotive/firmware_rpi-local_manifests.git .repo/local_manifests -b sa-mainEntão é o momento de sincronizar o código. Esta é a etapa mais demorada, pois o seu computador estará baixando em torno de 100GB de arquivos. Então, pode deixar durante a noite e ir dormir. O comando para sincronizar é o seguinte:
$ repo syncAjustes de código
Após sincronizar o código, alguns ajustes serão necessários
Pendrive ou Cartão SD
No projeto da Snapp Automotive, por padrão está configurado para iniciar o sistema utilizando um pendrive. Já no projeto Android on Raspberry o padrão é o cartão SD. Caso deseje, essa configuração pode ser alterada no arquivo fstab.rpi4 localizada na pasta device/snappautomotive/rpi/. Basta copiar o arquivo fstab do projeto arpi e sobreescrever no projeto snappautomotive para trocar as opções de pendrive para cartão SD, a partir do comando abaixo:
$ cp device/arpi/rpi4/fstab.rpi4 device/snappautomotive/rpi/Caso prefira iniciar o sistema pelo pendrive não é preciso realizar nenhuma alteração.
Ajustes de Framework
Para conseguir compilar o Android, o projeto Android on Raspberry necessita de alguns ajustes relacionados ao Framework, mais especificamente nos códigos de Bluetooth, Audio e Camera [11]. Seguem os caminhos dos arquivos e os patches que devem ser aplicados:
Remover resolv_gold_test de platform_testing
Aplique o patch abaixo na pasta platform_testing/
diff --git a/build/tasks/tests/native_test_list.mk b/build/tasks/tests/native_test_list.mk
index b1565ecf..b73ab0ac 100644
--- a/build/tasks/tests/native_test_list.mk
+++ b/build/tasks/tests/native_test_list.mk
@@ -110,7 +110,6 @@ native_tests := \
prioritydumper_test \
puffin_unittest \
recovery_unit_test \
- resolv_gold_test \
resolv_integration_test \
resolv_unit_test \
scrape_mmap_addr \Adicionar Hardware Reset ao Bluetooth HCI
Aplique o patch abaixo na pasta system/bt/
diff --git a/hci/src/hci_layer.cc b/hci/src/hci_layer.cc
index 976d91d56..5bed58b4c 100644
--- a/hci/src/hci_layer.cc
+++ b/hci/src/hci_layer.cc
@@ -375,6 +375,18 @@ static void event_finish_startup(UNUSED_ATTR void* context) {
startup_future = NULL;
}
+#include <fcntl.h>
+#include <sys/ioctl.h>
+static void hw_reset(bool reset) {
+ unsigned buf[8] = { 8 * 4, 0, 0x38041, 8, 8, 128, 0, 0};
+ buf[6] = reset ? 0 : 1;
+ int fd = open("/dev/vcio", 0);
+ if (fd >= 0) {
+ ioctl(fd, _IOWR(100, 0, char *), buf);
+ close(fd);
+ }
+}
+
static void startup_timer_expired(UNUSED_ATTR void* context) {
LOG_ERROR(LOG_TAG, "%s", __func__);
@@ -385,7 +397,9 @@ static void startup_timer_expired(UNUSED_ATTR void* context) {
LOG_ERROR(LOG_TAG, "%s: waiting for abort_timer", __func__);
return;
}
-
+ hw_reset(true);
+ sleep(2);
+ hw_reset(false);
abort();
}Desabilitar o Low Power mode do Bluetooth e habilitar compilação para HAL de Camera e Audio
Aplique o patch abaixo na pasta hardware/interfaces/
diff --git a/audio/common/all-versions/default/service/Android.bp b/audio/common/all-versions/default/service/Android.bp
index 3e8b71570..6c934e355 100644
--- a/audio/common/all-versions/default/service/Android.bp
+++ b/audio/common/all-versions/default/service/Android.bp
@@ -8,7 +8,6 @@ cc_binary {
// location for init to start it and the build system does not support
// having two binaries installable to the same location even if they are
// not installed in the same build.
- compile_multilib: "32",
srcs: ["service.cpp"],
cflags: [
diff --git a/bluetooth/1.0/default/vendor_interface.cc b/bluetooth/1.0/default/vendor_interface.cc
index d809313db..d63c51856 100644
--- a/bluetooth/1.0/default/vendor_interface.cc
+++ b/bluetooth/1.0/default/vendor_interface.cc
@@ -343,7 +343,7 @@ void VendorInterface::OnFirmwareConfigured(uint8_t result) {
lib_interface_->op(BT_VND_OP_GET_LPM_IDLE_TIMEOUT, &lpm_timeout_ms);
ALOGI("%s: lpm_timeout_ms %d", __func__, lpm_timeout_ms);
- bt_vendor_lpm_mode_t mode = BT_VND_LPM_ENABLE;
+ bt_vendor_lpm_mode_t mode = BT_VND_LPM_DISABLE;
lib_interface_->op(BT_VND_OP_LPM_SET_MODE, &mode);
ALOGD("%s Calling StartLowPowerWatchdog()", __func__);
diff --git a/camera/provider/2.5/default/Android.bp b/camera/provider/2.5/default/Android.bp
index 9ddf65144..27bf32b43 100644
--- a/camera/provider/2.5/default/Android.bp
+++ b/camera/provider/2.5/default/Android.bp
@@ -154,7 +154,6 @@ cc_binary {
proprietary: true,
relative_install_path: "hw",
srcs: ["external-service.cpp"],
- compile_multilib: "32",
init_rc: ["android.hardware.camera.provider@2.5-external-service.rc"],
shared_libs: [
"android.hardware.camera.common@1.0",Compilando o Código-fonte
Após todos os ajustes de código necessários chegou o momento de compilar tudo e gerar as imagens necessárias para executar o Android [12].
Compilando o Linux
O Android é um sistema operacional que usa o núcleo Linux para o controle de hardware, logo, é necessário gerar as imagens do Linux para que o Raspberry consiga executar o Android. Para compilar o Linux kernel use os comandos a seguir:
$ cd kernel/arpi
$ ARCH=arm64 scripts/kconfig/merge_config.sh arch/arm64/configs/bcm2711_defconfig kernel/configs/android-base.config kernel/configs/android-recommended.config
$ ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make Image.gz
$ ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- DTC_FLAGS="-@" make broadcom/bcm2711-rpi-4-b.dtb
$ ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- DTC_FLAGS="-@" make overlays/vc4-kms-v3d-pi4.dtboVocê pode usar o comando –j[n] junto ao comando make para indicar a quantidade de threads do processador que você quer usar e assim deixar a compilação mais rápida.
Com isso, são geradas três imagens:
- Image.gz: Imagem principal do Linux
- bcm2711-rpi-4-b.dtb: Imagem de Device Tree para o Raspberry
- vc4-kms-v3d-pi4.dtbo: Imagem de Device Tree Overlays para o Raspberry
Agora volte para a raiz do projeto:
$ cd ../..Compilando o Android Automotive
E agora continue a compilação do Android com os comandos a seguir:
$ source build/envsetup.sh
$ lunch snapp_car_rpi4-userdebug
$ make ramdisk systemimage vendorimage
O comando make de compilação do Android também permite usar o –j[n].
Com isso, são geradas mais três imagens:
- ramdisk.img: Possui aplicações básicas e arquivos de inicialização do sistema
- system.img: Contém binários, bibliotecas nativas, bibliotecas Java, arquivos de configuração e de aplicações padrão
- vendor.img: Assim como a system.img, contém binários e bibliotecas, porém essas fornecidas pelos desenvolvedores de softwares proprietários.
Preparando o Dispositivo de Memória
Tendo todas as imagens geradas, agora podemos organizar o nosso dispositivo de memória.
A partir deste momento será mencionado somente cartão SD, mas se você estiver utilizando pendrive a configuração é a mesma.
O cartão deve ser formatado em 4 partições, configurado conforme indicado abaixo:
- Partição 1: FAT32 – 128MB – Partição Primária – Flags de BOOT e LBA
- Partição 2: EXT4 – 2048MB – Partição Primária
- Partição 3: EXT4 – 128MB – Partição Primária
- Partição 4: EXT4 – Restante da memória – Partição primária
Você pode usar o software GParted para formatar o cartão. Para verificar as partições em seu terminal use o comando lsblk, o seu cartão estará mais ou menos como a figura 3 a seguir:
Tendo o cartão devidamente formatado, neste caso sendo sdb, agora transfira os arquivos e imagens necessários para ligar o Android na Raspberry. A partição 1 é responsável pela inicialização do sistema, onde estará o bootloader, o kernel, a ramdisk etc.
Primeiramente monte a partição no sistema com o comando mount:
$ sudo mount /dev/sdb1 /mntAgora comece a copiar todos os arquivos necessários para a partição, seguindo a ordem abaixo:
$ sudo cp device/snappautomotive/rpi/boot/* /mnt
$ sudo cp kernel/arpi/arch/arm64/boot/Image.gz /mnt
$ sudo cp kernel/arpi/arch/arm64/boot/dts/broadcom/bcm2711-rpi-4-b.dtb /mnt
$ sudo cp out/target/product/rpi/ramdisk.img /mnt
$ sudo mkdir /mnt/overlays
$ sudo cp kernel/arpi/arch/arm64/boot/dts/overlays/vc4-kms-v3d-pi4.dtbo /mnt/overlaysApós copiar todos os arquivos, a partição 1 está devidamente configurada, agora desmonte-a.
$ sudo umount /mntAs partições 2 e 3, recebem os arquivos que estão nas imagens system.img e vendor.img respectivamente. Para transferir os arquivos, use o comando dd, conforme abaxo:
$ sudo dd if=out/target/product/rpi/system.img of=/dev/sdb2 bs=1M
$ sudo dd if=out/target/product/rpi/vendor.img of=/dev/sdb3 bs=1M
A partição 4 será responsável pelos dados de usuário, então, não é necessário copiar arquivos para ela e pode ser deixada em branco.
Ligando e Depurando o Android Automotive
Neste momento tudo está configurado corretamente e pronto pra iniciar, agora conecte o Raspberry ao seu display e ligue em uma fonte de 5V e 3A. Se tudo ocorrer como o esperado serão mostradas as seguintes telas iniciais do Android Automotive nas figuras 4, 5 e 6:
Para facilitar o uso e desenvolvimento de aplicações, duas formas de depuração são úteis:
- Comunicação serial via UART
- Comunicação com o Android via adb.
Comunicação via UART
A comunicação serial via UART, disponível na Raspberry, necessita de um conversor TTL para que as informações enviadas ou recebidas sejam capturadas pelo computador. Este conversor deve ser conectado à Raspberry conforme a figura 7 a seguir:
Conecte o USB ao seu computador e abra uma aplicação de comunicação serial de sua preferência, a que mostrarei a seguir é a aplicação minicom. As informações que aparecerão são relacionadas ao kernel e ainda é possível acessar o sistema de arquivos, como mostram as figuras 8 e 9 a seguir:
Comunicação via adb
A comunicação via adb (Android Debug Bridge) é uma funcionalidade oficial, desenvolvida para o usuário se comunicar diretamente, via comandos, com o Android, podendo assim acessar o sistema de arquivos, instalar e desinstalar aplicativos, verificar informações de bateria e etc. Como o Raspberry não tem um conector USB device, o adb é acessado via wifi, então, na interface do Android Automotive conecte a uma rede wifi e verifique qual endereço IP ficou configurado, de acordo com as figuras 10 e 11 a seguir:
Com um computador conectado à mesma rede wifi do Android Automotive, utilize o comando ‘adb connect <Endereço IP>’ e o computador estará apto a usar os comandos adb. A figura 12 ilustra um terminal conectado ao dispositivo via wifi, e utilizando alguns comandos.
Considerações Finais
O Android já é o sistema operacional mais usado no mundo [13] em dispositivos como smartphones, tablets, smartwatches e televisões, um novo caminho agora são carros inteligentes. Então por que não aproveitar o assunto do momento da tecnologia e testar em uma placa acessível.
Este artigo abordou a instalação do Android Automotive, versão do Android para carros, em uma Raspberry Pi, e mostrou como baixar o código fonte, fazer ajustes de código necessários, configurar o dispositivo de memória e ligar e depurar o Android Automotive pela UART e por adb.
Referências
- [1] https://www.youtube.com/watch?v=yYRy4_4aA3w
- [2] https://www.media.volvocars.com/global/en-gb/media/pressreleases/258928/fully-electric-volvo-xc40-introduces-brand-new-infotainment-system-powered-by-android-with-google-te
- [3] https://www.theverge.com/2021/9/23/22688309/honda-google-android-auto-assistant-driving-mode-gas
- [4] https://www.android.com/intl/pt-BR_br/auto/
- [5] https://developers.google.com/cars/design/automotive-os
- [6] https://snappautomotive.io/
- [7] https://github.com/snappautomotive/firmware_rpi-local_manifests
- [8] https://github.com/android-rpi/device_arpi_rpi4
- [9] https://embarcados.com.br/nova-raspberry-pi-4/
- [10] https://github.com/snappautomotive/firmware_rpi-local_manifests
- [11] https://github.com/android-rpi/device_arpi_rpi4/wiki/arpi-11-:-framework-patch
- [12] https://github.com/snappautomotive/firmware-device_snappautomotive_rpi/tree/sa-main





sabe se é possível rodar esse sistema em um telefone android?
Minha visão é tipo o android auto quando rodava no telefone, aí para quem não tem multimídia em um veículo como moto fica mais fácil rodar no telefone
Android Automotive é diferente de android auto
Muito Bom !!!
Parabéns pelo artigo!
Satisfação de ter te conhecido na faculdade, grande abraço!
Valeu Gabriel, qualquer coisa só avisar que estamos aí! 😀
Excelente artigo, muito interessante. Não entendi se o carro já deve ter o Android Automotive, ou em quais carros posso conectar a Raspberry com a instalação mostrada no texto?
Olá Luiz, tudo bem? Alguns carros já estão vindo de fábrica com o Android Automotive, como o Volvo XC40, mas existe sim a possibilidade de ligar a Raspberry com o AAOS em seu carro, os pontos são: Seu carro necessita suportar comunicação CAN Você precisa ter um controlador CAN para comunicar o carro com a Raspberry (uso o MCP2515), Informações sobre PIDs do carro (isso muda de carro para carro) Alguns ajustes de código do AAOS pra receber as informações do barramento CAN e popular na sua tela Com esses pontos já é possível ligar a Raspberry com uma tela… Leia mais »
E quais seriam essas alterações necessárias no AAOS? Eu percebi que só ajustando o kernel não habilitei a minha rede can
Abraço!