Android Automotive OS 11 on a Raspberry Pi
[Updated on the 19th of Nov 2021 to use an SD Card instead of a USB Stick]
A few weeks ago we announced that we were forming Snapp Automotive to focus on automotive development. At the time we’d created an emulator image based on Android Automotive OS, and today we can announce we’ve gone a step further and the same Android Automotive OS 11 based distribution now runs on a self-contained hardware platform.
Before we get into the details we’d like to set some expectations; Developing a hardware platform from scratch is an extremely expensive undertaking that is well beyond the budget of most start-ups, so, instead of starting from scratch we’ve used off-the-shelf components and built on the existing work of others. This is not an uncommon practice, but we’d like to openly recognize the work of the Raspberry Pi Foundation, who’ve provided an inexpensive compute platform, and the Android RPi group, which created a bootable Android TV implementation on a Raspberry Pi, which allowed us to focus on the Android Automotive specific issues rather than needing to construct an Android supporting BSP and HAL implementation from scratch.
We would also like to call out that this system is in development and it’s not, at the current time, a production-ready distribution that you can install in your vehicle and expect to run issue-free for years. We’re making this available at this point because, for Snapp Automotive, this is a product demonstration. We’re aware there’s significant interest in an Android Automotive Raspberry Pi device, and so we’re making this available so we can collaborate with any interested parties who want to create a Raspberry Pi based Android Automotive distribution.
Update: If you want pre-build images, please look at this article for the download link.
Hardware
We’ve sourced our components from The Pi Hut and we’ll provide links to the relevant pages so you can build the same configuration we’re using. Other suppliers may have the same, or similar, items available which you can use instead.
The platform we’re using is a 4GB Raspberry Pi 4B with a Waveshare 10.1” 1280x800 IPS Touch Screen.
We use the 4GB version of the Raspberry Pi 4B because Google have indicated that Android Go is designed for devices with 2GB and lower of RAM, and Android Automotive is based on the full version of Android. The choice of the Waveshare touch screen was based on it offering an HDMI input for the display and a USB output for touch events, which is more widely supported than a solution which uses the Raspberry Pi GPIO and display connectors.
The Waveshare screen is an all-in-one package; It comes with a power supply, an HDMI cable, a USB cable, and a micro HDMI to HDMI adapter. A small warning though; after some pretty heavy use over the last few weeks, I managed to break the adapter, so I’d recommend an all-in-one cable in case, like me, you can be a bit clumsy at times.
The final things on the shopping list are an SD Card, an SD Card reader for your build machine, and the Raspberry Pi 4B power supply. We’ve found the 4B to be quite power hungry, so we recommend buying the 3 amp Raspberry Pi 4 power supply rather than using a mobile phone charger because most ‘phone chargers are limited to 2.4 amps which can cause problems.
The total cost of all of that hardware comes to around GBP180/USD200/EUR200 including taxes.
Setting up a build machine
To build Android 11 you need reasonably powerful hardware. On an average desktop it will take multiple hours so you should be prepared for that.
We use machines running Debian 10 and run the following command to install the additional packages we need;
apt-get install -y git-core gnupg flex bison build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z1-dev libgl1-mesa-dev libxml2-utils xsltproc unzip fontconfig libncurses5 procps libssl-dev bc fdisk eject
apt-get install -y gcc-aarch64-linux-gnu
Once those have been installed we check out the source code from Google’s repository for the release labeled android11-qpr2-release
by following the instructions from Google and when we reach the repo init
stage we run;
repo init -u https://android.googlesource.com/platform/manifest -b android11-qpr2-release
After running repo init
we add the Android RPi and Snapp Automotive changes to the build. We’ve deliberately tried to stick as closely as possible to the Android RPi way of doing things to make it easier for folk to switch between the two, and to encourage folk to upstream any improvements to the Android RPi project.
To get the modifications we need we need to add a local manifest to the build which we do by running;
git clone https://github.com/snappautomotive/firmware_rpi-local_manifests.git .repo/local_manifests -b sa-arpi-11
Now we run repo sync
as recommended in Google’s instructions.
Once repo sync
has completed there are currently a set of manual modifications you will need to make. You can find the instructions for those in the Android RPi Wiki at https://github.com/android-rpi/device_arpi_rpi4/wiki/arpi-11-:-framework-patch.
Building the Android Linux kernel
The Android RPi project has already created a working, Android compatible, kernel build which will be in your source code tree. To build the kernel you should run the following commands;
$ 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.dtbo
$ cd ../..
Building the Android Automotive OS Image
We’ve created a “lunch” target for the AAOS build so you can create a complete build using the following commands;
$ source build/envsetup.sh
$ lunch snapp_car_rpi4-userdebug
$ make -j6 ramdisk systemimage vendorimage
We use -j6
on machines with four CPU cores. If you have a machine with more cores you can increase this number. As a guide we use 1.5 times the number of physical CPU cores with a limit of the machines memory in gigabytes divided by two. So for a 12 physical core, 48 GB machine, we use -j18
(12 cores times 1.5), but for a 12 physical core 32 GB machine we would use -j16
(32GB of RAM divided by 2).
Preparing the U̶S̶B̶ ̶M̶e̶m̶o̶r̶y̶ ̶S̶t̶i̶c̶k̶ SD Card
Updated 19-Nov-2021: After a number of people hit issues using a USB Memory Stick we’ve updated our build to use the onboard SD Card reader instead.
We now need to put the build onto a bootable SD Card. I would recommend a capacity of at least 16GB, and any space above that will be used by apps, so the bigger the better.
The partitions should be created using fdisk
with sizes and types as follows;
Partition 1: W95 FAT32(LBA), 128MB, Bootable
Partition 2: Linux, 2GB
Partition 3: Linux, 128MB
Partition 4: Linux, All remaining space
On your build machine your SD Card will, most likely, appear as a device starting /dev/sd
. We’ll refer to the partitions as /dev/sdX1
from here on and you’ll need to replace the X
with the appropriate letter your build machine assigns to the device.
The next step is to create the file system on the two partitions which will have files written to them (sdX1
and sdX4
). We will be writing a disk image to the other two partitions so we don’t need to manually create the file systems for them. To create the filesystems run the following;
$ mkfs.vfat /dev/sdX1
$ mkfs.ext4 /dev/sdX4
We now need to mount the first partition and add all of the files needed to get the Raspberry Pi to boot. To do this we run the following commands from within the source code checkout;
$ mount /dev/sdX1 /mnt
$ mkdir /mnt/overlays
$ cp device/snappautomotive/rpi/boot/* /mnt
$ cp kernel/arpi/arch/arm64/boot/Image.gz /mnt
$ cp kernel/arpi/arch/arm64/boot/dts/broadcom/bcm2711-rpi-4-b.dtb /mnt
$ cp kernel/arpi/arch/arm64/boot/dts/overlays/vc4-kms-v3d-pi4.dtbo /mnt/overlays/
$ cp out/target/product/rpi/ramdisk.img /mnt
$ umount /mnt
$ sync
The final step is to copy the system and vendor images into the sdX2
and sdX3
partitions on the SD Card. We can do this by running the following commands from inside the source code checkout;
$ dd if=out/target/product/rpi/system.img of=/dev/sdX2 bs=1M
$ dd if=out/target/product/rpi/vendor.img of=/dev/sdX3 bs=1M
$ sync
$ eject /dev/sdX
We can now remove the SD Card, place it into the SD Card slot of the Raspberry Pi, and boot it up. The first boot may take a couple of minutes or so while Android optimises the apps, but this is normal, so don’t worry if the first boot takes a long time.
Debugging
As mentioned in the beginning this is still a work in progress. If you want to try some changes which may trigger some boot time issues we’ve got you covered; the build supports the Raspberry Pi’s serial console which you can access using some additional hardware and the GPIO pins.
We’ve used the Adafruit FT232H breakout board, but any adapter which exposes the serial Ground, TX, and RX pins will work. In the photos below the orange cable goes to the ground (GND) pin on the serial adapter, the green goes to the receive (RX) pin on the serial adapter, and the yellow goes to the transmit (TX) pin on the serial adapter. On the Adafruit board the RX pin is labelled D1, TX is D0, and the GND pin is beside D0.
When this is connected you can use a piece of software like PuTTY to interact with the console. By default you will only see a limited set of log messages, but, if you hit return and run logcat
, you will have access to the same output as you would get from running adb logcat
on a development machine
Wrap-Up
Hopefully by now you’ll have all the information you need to get an Android Automotive OS 11 build running on a Raspberry Pi with a touch screen. If you have any questions please reach out to us on Twitter, and we’ll help where we can.