My Long Road to Running AOSP: Docker, VirtualBox, and Chroot Experiments

Running AOSP (Android Open Source Project) on my personal development environment has been one of the most technically demanding challenges I’ve undertaken. Despite having powerful hardware (an Ubuntu 22.04 machine with 64GB RAM, 1TB NVMe SSD, and a 4TB external SSD), I encountered persistent roadblocks. I hope sharing my experience here on Droid Matrix helps others avoid similar pitfalls or inspires new workarounds.


Docker: Containerized Hope Meets Reality

Docker seemed ideal for keeping the environment clean, reproducible, and isolated. I built a custom Docker image (aosp-ubuntu18) based on Ubuntu 18.04, loaded with all the dependencies: OpenJDK 8, required compilers, libraries, and emulator binaries. I set up volume mounts for source code, .android ADB keys, and X11 GUI forwarding.

Why Docker Looked Promising:

  • Easy to recreate and reset environments
  • Mountable storage for large source trees
  • Built-in network and device sharing features

Where It Failed:

  • X11 GUI Issues: Even though xeyes worked, the emulator wouldn’t show its window. Qt plugins failed to initialize (xcb plugin missing or misconfigured).
  • Authorization Errors: The emulator output was flooded with messages like Authorization required, but no authorization protocol specified, despite all X11 socket mounts and xhost + setup.
  • ADB Connectivity: Emulator booted, but ADB failed to detect it.
  • GPU Acceleration: SwiftShader and Vulkan failed, despite device permissions and passing /dev/dri.

Ultimately, Docker wasn’t a fit for running the emulator GUI in a robust way.


VirtualBox: A Heavyweight Alternative

Next, I tried VirtualBox. It seemed like a natural choice—after all, full VMs can be closer to native behavior.

What I Tried:

  • Created an Ubuntu 18.04 VM.
  • Mounted the external SSD to the guest for AOSP sources.
  • Installed KVM inside the VM to use acceleration.

Where It Struggled:

  • Performance Issues: Even with 32GB RAM assigned, compiling inside a VM was slower and less responsive than on the host.
  • Shared Folder Issues: Passing large data (200GB+) through shared folders or USB passthrough was unreliable.
  • GPU Passthrough: Complicated to configure and still failed to display the emulator properly.

I concluded that the VM overhead and file system challenges weren’t worth the benefit.


Chroot: Old School, Still Hopeful

With Docker and VirtualBox out of the picture, I turned to an older but low-level method: chroot.

Setup Steps:

  • Created a chrooted Ubuntu 18.04 filesystem using debootstrap on my external SSD.
  • Mounted /aosp into the chroot using mount --bind.
  • Installed all dependencies.
  • Downloaded repo, initialized and synced the Android 12 tree.
  • Built AOSP using lunch and m. The build completed successfully.

Remaining Issues:

  • Emulator Display Still Fails: X11 permission problems persist. GUI apps like xeyes fail unless run from the host.
  • Qt Platform Plugin Error: Emulator crashes with Could not load the Qt platform plugin "xcb" despite having the plugin available.
  • Pulseaudio and Audio Driver Fails: Not critical for now, but still notable.
  • ADB Cannot Detect Emulator: Even though the emulator boots (as confirmed by logs), adb devices returns nothing.

Final Thoughts

Each method brought me one step closer:

  • Docker taught me container setup and isolation.
  • VirtualBox reminded me of hardware bottlenecks.
  • Chroot showed me how far low-level techniques can still take you.

I’m still experimenting and optimistic about eventually solving these last hurdles. If you’ve tackled similar AOSP emulator struggles—especially from chroot—I’d love to hear from you. Share your fixes, suggestions, or scripts in the comments!

Full AOSP Setup in chroot (Ubuntu 18.04)

Prerequisites (on host)

Install necessary packages:

sudo apt update
sudo apt install -y debootstrap schroot

Create the chroot directory (you’ve already done this):

sudo mkdir -p /mnt/seagate/part1_2T/chroot-ubuntu18

Bootstrap Ubuntu 18.04 into chroot:

sudo debootstrap bionic /mnt/seagate/part1_2T/chroot-ubuntu18 http://archive.ubuntu.com/ubuntu/

Mount system directories for chroot:

sudo mount --bind /proc /mnt/seagate/part1_2T/chroot-ubuntu18/proc
sudo mount --bind /dev /mnt/seagate/part1_2T/chroot-ubuntu18/dev
sudo mount --bind /sys /mnt/seagate/part1_2T/chroot-ubuntu18/sys

Mount your AOSP source inside chroot:

sudo mkdir -p /mnt/seagate/part1_2T/chroot-ubuntu18/aosp
sudo mount --bind /mnt/seagate/part2_1T/aosp /mnt/seagate/part1_2T/chroot-ubuntu18/aosp

Entering and Configuring the chroot

sudo chroot /mnt/seagate/part1_2T/chroot-ubuntu18 /bin/bash
export LC_ALL=C

Inside chroot: Install AOSP build dependencies

apt update
apt install -y openjdk-8-jdk 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 lib32z1-dev ccache libgl1-mesa-dev libxml2-utils \
xsltproc unzip bc python python3 rsync nano pulseaudio xauth

Downloading AOSP Source (example: Android 12)

cd /aosp/aosp12
curl https://storage.googleapis.com/git-repo-downloads/repo > /usr/local/bin/repo
chmod a+x /usr/local/bin/repo

# Initialize repo
repo init -u https://android.googlesource.com/platform/manifest -b android-12.0.0_r1

# Sync source
repo sync -j4 --force-sync --no-clone-bundle --no-tags

Build AOSP

cd /aosp
source build/envsetup.sh
lunch sdk_phone_x86_64
make -j$(nproc)

Run Emulator (GUI)

Make sure the X11 server is accessible, and in your host:

xhost +local:

Then in chroot:

export DISPLAY=:0
emulator -gpu swiftshader_indirect -no-snapshot -no-boot-anim

If the emulator complains about display: use xeyes to test first. If you still have X11 permission errors: try xhost +SI:localuser:root

Optional Fixes

ADB not detecting emulator:

adb start-server
adb devices

PulseAudio: If audio errors persist, either disable audio or set up a bridge with padsp or PulseAudio config.

Lastly, Summery of my progress:

🐳 Docker (with Ubuntu 18.04 image)

Attempts:

  • Created a custom aosp-ubuntu18 Docker image with all necessary AOSP dependencies.
  • Mounted volumes for /aosp, X11, and .android directory for emulator access.
  • Used --device /dev/kvm, --privileged, and other flags to enable KVM and graphics.

Failures:

  • Emulator GUI wouldn’t launch properly due to missing or misconfigured X11 permissions and Qt plugin errors (xcb).
  • ADB often failed to detect devices or connect to the emulator.
  • Vulkan and SwiftShader fallback generated warnings or crashes.
  • Despite xeyes working, emulator GUI was unstable or aborted with Qt plugin errors.
  • GPU passthrough failed to perform correctly.
  • Emulator often started headlessly or failed with authorization errors.

📦 VirtualBox

Attempts:

  • Considered as an alternative to Docker due to easier GPU passthrough and GUI access.

Failures:

  • AOSP build directory is over 200GB; sharing this with a VirtualBox VM was complex and slow.
  • Required setting up a shared folder or mounting an external SSD, which posed performance bottlenecks.
  • Performance degradation with emulation vs KVM.
  • Networking, file sharing, and display integration were nontrivial.

🧱 Chroot

Current Status: In Progress

Setup Steps:

  • Created a chroot environment on an external SSD (/mnt/seagate/part1_2T/chroot-ubuntu18).
  • Bound /aosp inside the chroot to access AOSP sources from host.
  • Installed all necessary packages, including Java 8, repo, and build dependencies.
  • Successfully performed repo init and repo sync (after retrying with --no-clone-bundle and removing lock files).
  • Built AOSP using lunch and m, resulting in a successful build.

Ongoing Problems:

  • Emulator fails to display GUI due to X11 authorization issues (e.g., “Authorization required, but no authorization protocol specified”).
  • ADB fails to connect (adb devices returns no devices).
  • Pulseaudio and Qt plugin issues persist.
  • Still working on passing GUI access to host from chroot.

Leave a Reply

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