build Android for Raspberry Pi from source code

  • Raspberry Pi 4

  • Linux computer (officially recommended) use Ubuntu)

  • USB-C cable

  • microSD card reader and the card itself

  • (optional, but highly recommended) Raspberry Pi Debug Probe or other UART adapter

Build environment setup

At this stage we will need install packagesrequired for assembly. All of them are available in standard repositories, so there will be nothing interesting in this section.

In addition to the packages from the documentation, I needed to install pkg-config, meson and module mako for python3.

Cloning a repository

AOSP consists of more than a thousand git repositories + device-specific repositories (in our case, this is a project android-rpi). To manage a local copy of git repositories, use the utility repos.

Key commands we will need:

repo init -u https://android.googlesource.com/platform/manifest -b android-13.0.0_r66
git clone https://github.com/android-rpi/local_manifests .repo/local_manifests -b arpi-13
repo sync

The first command clones the AOSP manifest repository, which stores information about all the repositories provided by Google.
The second command adds a manifest with device-specific repositories, and the third will execute git clone for all repositories specified in one of the manifests.

Build Android

Environment initialization

IN documentation the commands are described in more detail, here I will give only those that we need to build the OS image.

. build/envsetup.sh

Lunch target

The same copy of the AOSP source code supports build options for an arbitrary number of devices. This is achieved with the help lunch targets (or lunch combos, pun intended), which consist of the device name and firmware type (eng, userdebug or user).

lunch rpi4-eng

Compilation

During the compilation process, several build systems are used: make, soong, ninja, and starting from Android 13, this zoo has also added Basel. In this article, we will not go into details of how these systems interact with each other, and will simply call the make targets to build the final OS images:

make ramdisk systemimage vendorimage

On my old i5-9600k, a clean build takes about two and a half hours, so at this stage you can stop and go for lunch 🙂

Compilation errors can also occur at this stage, but usually they are associated with missing dependencies in the system. After receiving the message “Build completed successfully”, you can proceed to the next step – partitioning the SD card.

Building the Linux Kernel

Usually, the kernel in Android projects is not built at the same time as the rest of the OS, but is delivered as a pre-built binary artifact. In our case, there is no such artifact, and later in the article we will see that we need to build an additional kernel module.

mkdir kernel
cd kernel
repo init -u https://github.com/android-rpi/kernel_manifest -b arpi-5.15
repo sync
build/build.sh

Since the kernel is usually built separately, it has its own manifest and its own set of repositories.

Section structure

Unlike traditional Linux, where both the OS and user files can reside on the same partition, Android requires multiple partitions for different purposes:

  • boot contains a Linux kernel image

  • system contains the Android Framework, which includes everything that we are used to working with from ordinary applications – system services, Java libraries and system resources.

  • vendor contains (usually) proprietary services developed by the SoC vendor the device is running

  • data contains user data, including installed applications and their data

In order to partition the entire SD card with one command, I wrote a small shell script that uses the artifacts collected in the previous steps:

#!/usr/bin/env bash

set -ex

AOSP_ROOT="android-rpi"
AOSP_OUT="android-rpi/out/target/product/rpi4" 
KERNEL_OUT="kernel/out/arpi-5.15/dist"

DEVICE=${1:?Device not set}
SYSTEM_PARTITION="${DEVICE}2"
VENDOR_PARTITION="${DEVICE}3"
BOOT_MOUNTPOINT=/media/$USER/android_boot

wipefs -a $DEVICE*
sfdisk /dev/sdb < partitions.sfdisk
mkfs -t vfat /dev/sdb1
mkfs -t ext4 -L userdata /dev/sdb4

dd if=$AOSP_OUT/system.img of=$SYSTEM_PARTITION bs=1M
dd if=$AOSP_OUT/vendor.img of=$VENDOR_PARTITION bs=1M

mkdir -p $BOOT_MOUNTPOINT
mount /dev/sdb1 $BOOT_MOUNTPOINT
# copy firmware & ramdisk
cp $AOSP_ROOT/device/arpi/rpi4/boot/* $BOOT_MOUNTPOINT
cp $AOSP_OUT/ramdisk.img $BOOT_MOUNTPOINT

# copy kernel binaries
cp $KERNEL_OUT/Image.gz $BOOT_MOUNTPOINT
cp $KERNEL_OUT/bcm2711-rpi-*.dtb $BOOT_MOUNTPOINT
mkdir $BOOT_MOUNTPOINT/overlays
cp $KERNEL_OUT/vc4-kms-v3d-pi4.dtbo $BOOT_MOUNTPOINT/overlays

# enable adb over usb
# cp $KERNEL_OUT/dwc2.dtbo $BOOT_MOUNTPOINT/overlays
# echo 'dtoverlay=dwc2,dr_mode=peripheral' >> $BOOT_MOUNTPOINT/config.txt

umount $BOOT_MOUNTPOINT
rmdir $BOOT_MOUNTPOINT

The partition scheme is stored side by side in partitions.sfdisk:

label: dos
label-id: 0xa35ef4be
device: /dev/sdb
unit: sectors
sector-size: 512

/dev/sdb1 : start=        2048, size=      262144, type=c, bootable
/dev/sdb2 : start=      264192, size=     2097152, type=83
/dev/sdb3 : start=     2361344, size=      262144, type=83
/dev/sdb4 : start=     2623488, size=    58493952, type=83

That’s all! After that, you can insert the SD card into the Raspberry Pi, connect the power and HDMI, and wait for the download to complete.

Bonus track: enable adb over USB

When I wrote this article, I could not connect to the Pi via adb, although in eng– adb firmware is always available, and I was able to connect over the network using Ethernet. It turned out that the android-rpi developers turned off support for USB device mode by default, which caused both the computer and the Raspberry Pi to think that they could only be a USB host.

In order to enable device mode support, we need to do the following:

  1. Uncomment the first line in init.rpi4.rc. init.rc is an init process in Linux terms, that is, a process with PID 1 that starts all other processes. In Android, init is responsible for monitoring USB-FFS and running adbd, among other things.

  2. Add kernel module assembly dwc2 V <kernel_dir>/common/build.config.arpi

  1. Uncomment two lines after comment enable adb over usb in my script above.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *