Android Emulator Development, Anbox, & Waydroid

Inside AVD System Images: Customizing Android Kernel and Bootloader for Advanced Emulation

Google AdSense Native Placement - Horizontal Top-Post banner

Introduction: Unlocking Advanced Android Emulation with Custom AVD Images

Android Virtual Devices (AVDs) are indispensable tools for app development, testing, and security research. While stock AVD images offer a baseline environment, advanced use cases often demand deeper control over the emulated hardware and software stack. This expert-level guide delves into the intricate process of customizing AVD system images, focusing specifically on modifying the Android kernel and bootloader components. By building these critical pieces from the Android Open Source Project (AOSP) source, you can tailor your emulation environment to meet unique requirements, debug low-level issues, or simulate specific hardware behaviors.

This tutorial is ideal for developers, researchers, and system integrators looking to push the boundaries of Android emulation beyond typical application-level interaction. We will cover setting up your AOSP build environment, locating relevant source code, applying modifications, and integrating your custom components into a functional AVD.

Understanding the Anatomy of an AVD System Image

Before diving into customization, it’s crucial to understand the core components that constitute an AVD system image. These are typically packaged as several `.img` files:

  • kernel-qemu (or bzImage for x86/x86_64): The Linux kernel responsible for managing hardware resources and providing core system services. For AVDs, this is often a specially compiled kernel (like goldfish or ranchu kernels).
  • ramdisk.img: A small filesystem loaded into memory during boot. It contains the initial root filesystem, including the init process and early boot scripts (e.g., init.rc). This is where the bootloader’s initial setup resides.
  • system.img: Contains the Android framework, system applications, libraries, and services. This is the largest component, representing the core Android OS.
  • vendor.img: Houses vendor-specific HAL (Hardware Abstraction Layer) implementations and libraries, isolating them from the generic Android system partition.
  • userdata.img: Stores user data, installed applications, and user-specific settings. This is usually created dynamically or copied from a base image.

Our focus will be on kernel-qemu/bzImage and ramdisk.img, as these directly control the boot process and fundamental system behavior.

Setting Up Your AOSP Build Environment

To build custom kernel and bootloader components, you’ll need a robust AOSP build environment. This process can be resource-intensive, requiring significant disk space (200GB+) and RAM (16GB+).

Prerequisites:

  1. Ubuntu LTS (20.04 or later) or Debian: Recommended operating system.
  2. Java Development Kit (JDK): Specific versions required for different Android versions. For Android 13/14, OpenJDK 11.
  3. Essential Build Tools: Git, Repo, make, GCC, G++, Python, etc.

Install Build Dependencies:

sudo apt update && sudo apt upgrade -y
sudo apt install -y git-core gnupg flex bison build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 libncurses5 lib32ncurses5-dev x11proto-core-dev libx11-dev libgl1-mesa-dev libxml2-utils xsltproc fontconfig openjdk-11-jdk

Initialize and Sync AOSP Source:

Create a working directory and use the repo tool to download the AOSP source. Choose a specific branch, e.g., Android 13 (`android-13.0.0_rXX`).

mkdir ~/aosp
cd ~/aosp
repo init -u https://android.googlesource.com/platform/manifest -b android-13.0.0_r56 --git-lfs
repo sync -j$(nproc)

This step will take several hours depending on your internet connection.

Customizing the Android Kernel (Goldfish/Ranchu)

For AVDs, Android typically uses the goldfish or ranchu kernels, which are specialized Linux kernels designed to run within QEMU. These kernels are located within the AOSP source tree, often under kernel/goldfish or kernel/ranchu, and their build configurations are in device/generic/goldfish or device/generic/ranchu.

Locating and Configuring the Kernel:

Navigate to the kernel source directory. For AVD x86_64, it’s typically:

cd ~/aosp/kernel/goldfish

Before building, you need to set up the environment and configuration:

export ARCH=x86_64
export SUBARCH=x86_64
export CROSS_COMPILE=~/aosp/prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/bin/x86_64-linux-android-
make goldfish_defconfig

This creates a default configuration file (`.config`). To customize kernel features, you can use `make menuconfig`:

make menuconfig

This will launch a text-based configuration interface where you can enable/disable modules, features, and debugging options. For example, you might want to enable specific network drivers, add Ftrace support, or adjust memory management parameters.

Applying Kernel Modifications:

You can apply patches to introduce new features, fix bugs, or add custom drivers. Let’s assume you have a small patch file `my_custom_feature.patch`:

patch -p1 < my_custom_feature.patch

For direct code modification, simply edit the relevant C files (e.g., `drivers/char/goldfish_pipe.c` for QEMU communication) using your preferred editor.

Building the Custom Kernel:

Once modifications are complete, build the kernel:

make -j$(nproc)

The compiled kernel image, typically named `bzImage` (for x86/x86_64) or `zImage` (for ARM), will be located in `arch/x86_64/boot/bzImage` or `arch/arm/boot/zImage` within your kernel source directory.

Customizing the Android Bootloader (Ramdisk)

The `ramdisk.img` contains the initial root filesystem and the crucial `init.rc` script, which defines the very first processes and services that Android starts. Modifying this allows you to execute custom commands early in the boot sequence, integrate custom binaries, or change system properties.

Locating and Modifying the Ramdisk Source:

The ramdisk content is generated as part of the overall AOSP build. Its source components are spread across various directories, but the most important for customization are often:

  • `system/core/rootdir`: Contains the base `init.rc` and other core root filesystem files.
  • `device/generic/goldfish` or `device/generic/ranchu`: May contain device-specific `init.rc` fragments or overlay files.

To integrate changes into the ramdisk, you’ll typically modify files in these locations and then rebuild the entire AOSP project to generate a new `ramdisk.img`.

Example: Adding a Custom Service to init.rc

Let’s say you want to run a simple shell script at boot. First, create your script:

# ~/aosp/system/core/rootdir/myservice.sh
#!/system/bin/sh

echo "My custom service started!" > /data/local/tmp/myservice_log.txt
sleep 10
echo "My custom service finished!" >> /data/local/tmp/myservice_log.txt

Make it executable:

chmod +x ~/aosp/system/core/rootdir/myservice.sh

Now, edit `~/aosp/system/core/rootdir/init.rc` (or `init.goldfish.rc` if it exists and is used by your target) to add a service definition:

# ... existing init.rc content ...

service myservice /system/bin/sh /myservice.sh
    class main
    user root
    group root
    oneshot
    disabled

on boot
    start myservice

# ... rest of init.rc content ...

This defines a service `myservice` that runs your script as `root` and starts automatically on boot.

Building and Integrating Custom AVD Images

With your custom kernel and ramdisk modifications, you now need to build the full AOSP system image and then launch your AVD with these custom components.

Full AOSP Build:

From your `~/aosp` directory:

source build/envsetup.sh
lunch aosp_x86_64-userdebug  # Or aosp_x86-userdebug, aosp_arm64-userdebug, etc.
make -j$(nproc)

The `lunch` command configures the build environment for a specific target. `aosp_x86_64-userdebug` is a common choice for AVDs running on x86_64 architectures. The `make -j$(nproc)` command will compile the entire AOSP, including your custom kernel and ramdisk. This step can take several hours.

Locating Generated Images:

Upon successful compilation, your custom images will be in the output directory, typically:

~/aosp/out/target/product/generic_x86_64/

Look for `ramdisk.img`, `system.img`, `vendor.img`, and your compiled kernel (e.g., `kernel-qemu` or `bzImage`). Note that the main AOSP build typically outputs `kernel-qemu` for AVDs, even if you built `bzImage` separately.

Launching AVD with Custom Components:

You can use the Android Emulator from your SDK to launch an AVD with your custom kernel and ramdisk. You can either replace existing AVD files or specify them directly:

emulator -avd YOUR_AVD_NAME -kernel ~/aosp/out/target/product/generic_x86_64/kernel-qemu -ramdisk ~/aosp/out/target/product/generic_x86_64/ramdisk.img -system ~/aosp/out/target/product/generic_x86_64/system.img -vendor ~/aosp/out/target/product/generic_x86_64/vendor.img

Replace `YOUR_AVD_NAME` with an existing AVD name. Alternatively, you can copy your custom `kernel-qemu` and `ramdisk.img` into an existing AVD directory (e.g., `~/.android/avd/YOUR_AVD_NAME.avd/`) and launch the AVD normally. However, directly specifying paths provides more flexibility for testing different builds.

Conclusion: Empowering Advanced Android Emulation

Customizing Android AVD system images, particularly the kernel and bootloader, opens up a world of possibilities for advanced emulation scenarios. From integrating custom drivers and enabling low-level debugging features in the kernel to modifying boot sequences and adding custom services via the ramdisk, you gain unparalleled control over your virtual Android environment. This capability is invaluable for security researchers analyzing system vulnerabilities, developers optimizing device-specific code, or anyone needing a deeply specialized Android testing platform. By following these steps, you’ve equipped yourself with the knowledge to craft tailored AVD experiences that go far beyond what stock images provide.

Android Mobile Specs & Compare Directory

Are you researching mobile hardware properties, processor SoCs, GPU chipsets, or RAM configurations? Access our complete specs catalog to compare up to 5 devices side-by-side!

Compare Devices Specs →
Google AdSense Inline Placement - Content Footer banner