Why This Document Exists
Building AAOS (Android Automotive OS) for the Google Pixel Tablet is poorly documented. The official guide is a single page with 10 commands, but actually getting it to work requires navigating rate limits, bootloader version mismatches, missing Vehicle HAL services, and a critical adb sync vendor step that isn’t mentioned anywhere obvious.
This document covers everything: what worked, what failed, why, and how to fix it. Written so that future-me (or anyone else) can reproduce this in one session without the 6 hours of debugging.
Overview
What we’re building: Android Automotive OS 14 for the Google Pixel Tablet (codename tangorpro). This turns a consumer tablet into an AAOS development device with a full car UI — launcher, media, phone, settings, and Vehicle HAL simulation.
Build environment: Throwaway Hetzner Cloud server (CCX63: 48 vCPU, 192 GB RAM, 960 GB NVMe). Cost: ~1-2 EUR per build.
Total time: ~2-3 hours build + 30 min setup + 15 min flash = ~3-4 hours end to end.
Part 1: The Build Server
Why a Cloud Server?
AOSP builds require ~200 GB disk, 32+ GB RAM, and many CPU cores. A cloud server with 48 vCPU / 192 GB RAM builds in ~2 hours. On a MacBook it would take 8+ hours (if it even has enough RAM).
Creating the Server
brew install hcloud # Hetzner CLI
hcloud ssh-key create --name my-key --public-key-from-file=~/.ssh/id_ed25519.pub
hcloud server create \
--name aaos-build \
--type ccx63 \
--image ubuntu-24.04 \
--location nbg1 \
--ssh-key my-key
Note the IP address. Add to ~/.ssh/config:
Host aaos-build
HostName <IP>
User root
IdentityFile ~/.ssh/id_ed25519
Port 22
Installing Build Dependencies
ssh aaos-build
apt-get update && apt-get install -y \
git-core gnupg flex bison build-essential zip curl \
zlib1g-dev libc6-dev-i386 x11proto-core-dev libx11-dev \
lib32z1-dev libgl1-mesa-dev libxml2-utils xsltproc unzip \
fontconfig python3 python-is-python3 repo rsync
git config --global user.email "build@aaos.local"
git config --global user.name "AAOS Builder"
git config --global color.ui false
Lesson Learned: Don’t Use Cloud-Init
We initially tried automating server setup with cloud-init YAML. It broke repeatedly:
- YAML indentation errors silently skip file creation
- No way to debug locally (cloud-init only runs on the server)
- For a server that lives 3 hours, hardening (fail2ban, UFW) is overkill
Use a shell script or manual setup. It’s faster and debuggable.
Part 2: Syncing the Source
Authenticated Access (Mandatory)
Google’s AOSP git servers rate-limit unauthenticated access. With -j32 (32 parallel fetches), you’ll hit HTTP 429 errors within minutes:
remote: RESOURCE_EXHAUSTED: Resource has been exhausted (e.g. check quota)
fatal: unable to access '...': The requested URL returned error: 429
Fix: Use authenticated access via /a/ URLs.
- Go to https://android.googlesource.com/new-password
- Log in with your Google account
- Copy the shell commands and run them on the build server
This sets up ~/.gitcookies for authenticated access. Then use the /a/ URL in repo init:
mkdir ~/aaos_on_pixel && cd ~/aaos_on_pixel
REPO_ALLOW_SHALLOW=0 repo init -c \
-u https://android.googlesource.com/a/platform/manifest \
-b android-14.0.0_r30 \
--use-superproject \
--partial-clone \
--partial-clone-exclude=platform/frameworks/base \
--clone-filter=blob:limit=10M
Repo Sync
repo sync -j32
With authenticated access, -j32 works fine. Takes ~30-60 minutes.
Part 3: Vendor Binaries
The Pixel Tablet has proprietary hardware drivers (camera, GPU, sensors) that aren’t part of AOSP. Download them separately:
cd ~/aaos_on_pixel
curl --output - \
https://dl.google.com/dl/android/aosp/google_devices-tangorpro-ap1a.240405.002-8d141153.tgz \
| tar -xzvf -
tail -n +315 extract-google_devices-tangorpro.sh | tar -zxvf -
The tail -n +315 trick skips the license header in the self-extracting shell script and directly extracts the embedded tar archive.
Important: The vendor binary version must match the AOSP branch. We use AP1A.240405.002 for branch android-14.0.0_r30.
Part 4: Audio Fix Patch
Without this patch, the audio service crashes on boot:
cd packages/services/Car
git fetch https://android.googlesource.com/platform/packages/services/Car \
refs/changes/83/3037383/2 && git cherry-pick FETCH_HEAD
cd ~/aaos_on_pixel
This is a known issue documented in the official guide.
Part 5: Building
source build/envsetup.sh
lunch aosp_tangorpro_car-ap1a-userdebug
m
Notes:
lunchsets the build target. Without it,mdoesn’t know what to build.m(without-j) automatically uses all available CPUs.- After a new SSH session, you must re-run
source build/envsetup.shandlunch. - The build takes ~2-3 hours on CCX63.
What m Builds
The build produces images in out/target/product/tangorpro/:
boot.img,system.img,product.img,vendor.img— the OS partitionsvbmeta*.img— verified boot metadataandroid-info.txt— device compatibility infovendor/— the unpacked vendor filesystem tree (critical for flashing!)
Part 6: Downloading Artifacts
This is where we made our biggest mistake the first time. You need to download TWO things:
1. The Image Files (for fastboot flash)
mkdir -p ~/Development/pixel-tablet-aaos/flash
cd ~/Development/pixel-tablet-aaos/flash
scp "aaos-build:~/aaos_on_pixel/out/target/product/tangorpro/*.img" .
scp aaos-build:~/aaos_on_pixel/out/target/product/tangorpro/android-info.txt .
2. The Vendor Folder (for adb sync vendor)
scp -r aaos-build:~/aaos_on_pixel/out/target/product/tangorpro/vendor/ vendor/
Why both? The vendor.img contains the base vendor partition (hardware drivers). But the Vehicle HAL service — which AAOS needs to function — must be synced separately via adb sync vendor. Without the vendor folder on your local machine, adb sync vendor fails with “don’t know how to sync vendor partition”.
What Happens If You Skip the Vendor Folder
CarService crash-loops with:
java.lang.IllegalStateException: Vehicle HAL service is not available.
The AAOS home screen appears empty. CarLauncher, CarSettings, and all car apps exist on the device but can’t start because CarService (which depends on the Vehicle HAL) is dead.
Part 7: Flashing
Prepare the Tablet
-
Unlock the bootloader (one-time):
- Settings → About Tablet → tap “Build Number” 7 times
- Settings → Developer Options → enable “OEM unlocking”
- Reboot into Fastboot: power off, hold Power + Volume Down
fastboot flashing unlock— confirm on screen
-
Check bootloader version:
fastboot getvar version-bootloaderIf it shows
tangorpro-14.4-*, you’re good — skip to step 3.If it shows a different version (e.g.,
tangorpro-16.4from a newer stock Android), you need to flash the matching stock image first:- Go to Google’s factory images for Pixel Tablet (tangorpro)
- Important: Select the build for Pixel Tablet (tangorpro) specifically — there are multiple devices with the same build ID, pick the one labeled “tangorpro”
- Download
AP1A.240405.002for tangorpro - Extract and flash:
cd tangorpro-ap1a.240405.002 && ./flash-all.sh - Or even easier: Use the Android Flash Tool — select your device in Chrome, pick the correct build, and flash directly from the browser. No command line needed.
- This sets the bootloader to
tangorpro-14.4which matches our AAOS build - Boot into Fastboot again: power off, hold Power + Volume Down
-
Boot into Fastboot (if not already there):
- Power off the tablet
- Hold Power + Volume Down simultaneously
- Release when Fastboot screen appears
Flash the AAOS Images
cd ~/Development/pixel-tablet-aaos/flash
ANDROID_PRODUCT_OUT=. fastboot -w flashall
The -w flag wipes userdata (clean install). This takes ~90 seconds.
The Critical Step: Sync Vendor
After flashing, the tablet boots but AAOS doesn’t fully work. You MUST sync the vendor tree:
export ANDROID_PRODUCT_OUT=~/Development/pixel-tablet-aaos/flash
adb wait-for-device
adb root
adb remount
adb sync vendor
adb reboot
Wait 3-5 minutes after the final reboot. AAOS should start with the full car UI.
Lesson Learned: Bootloader Version Must Match
The Pixel Tablet’s bootloader and system image must be from the same build. If you previously flashed a newer stock Android (e.g., AP2A), the bootloader gets upgraded and won’t boot an older AAOS image.
Fix: Flash the matching stock factory image first:
- Download
AP1A.240405.002from https://developers.google.com/android/images#tangorpro - Extract and run
./flash-all.sh - This downgrades the bootloader to match
- Then flash the AAOS image
You can check the bootloader version with:
fastboot getvar version-bootloader
For our build, the correct bootloader is tangorpro-14.4-*.
Lesson Learned: fastboot flashall vs Google’s flash-all.sh
fastboot flashallflashes system partitions only (NOT the bootloader)- Google’s
flash-all.shflashes bootloader + system together
If you need to change the bootloader version, use Google’s script. For re-flashing AAOS after the bootloader is already correct, fastboot flashall is fine.
Part 8: Verifying the Installation
After the final reboot, you should see:
- AAOS car launcher with app grid
- Settings app (car-specific)
- Media app
- Phone/Dialer app
- Maps placeholder
Verify CarService is running:
adb shell "ps -A | grep -i car"
Should show com.android.car and com.android.car.shell among others.
Verify Vehicle HAL is running:
adb shell "ps -A | grep -i vehicle"
Should show the vehicle HAL process.
Part 9: Cleanup
Delete the build server:
hcloud server delete aaos-build
Cost: CCX63 at ~0.69 EUR/h. A full build session (setup + build + download) takes ~2-3 hours = ~1.50-2.00 EUR.
Part 10: Installing Your Own Apps
With AAOS running on the tablet, install apps via:
adb install -t your-app.apk
Or from Android Studio: select the Pixel Tablet as deployment target.
The tablet has no GPS hardware. For location-dependent apps, use a mock location provider or set coordinates via:
adb shell appops set <package> android:mock_location allow
Quick Reference
Full Build Sequence (Server)
# 1. Setup
apt-get install -y git-core gnupg flex bison build-essential zip curl \
zlib1g-dev libc6-dev-i386 x11proto-core-dev libx11-dev \
lib32z1-dev libgl1-mesa-dev libxml2-utils xsltproc unzip \
fontconfig python3 python-is-python3 repo rsync
# 2. Sync
mkdir ~/aaos_on_pixel && cd ~/aaos_on_pixel
# Configure git cookies from https://android.googlesource.com/new-password
REPO_ALLOW_SHALLOW=0 repo init -c \
-u https://android.googlesource.com/a/platform/manifest \
-b android-14.0.0_r30 \
--use-superproject --partial-clone \
--partial-clone-exclude=platform/frameworks/base \
--clone-filter=blob:limit=10M
repo sync -j32
# 3. Vendor binaries
curl --output - https://dl.google.com/dl/android/aosp/google_devices-tangorpro-ap1a.240405.002-8d141153.tgz | tar -xzvf -
tail -n +315 extract-google_devices-tangorpro.sh | tar -zxvf -
# 4. Audio patch
cd packages/services/Car
git fetch https://android.googlesource.com/platform/packages/services/Car refs/changes/83/3037383/2 && git cherry-pick FETCH_HEAD
cd ~/aaos_on_pixel
# 5. Build
source build/envsetup.sh
lunch aosp_tangorpro_car-ap1a-userdebug
m
Full Flash Sequence (Mac)
# 1. Download
cd ~/Development/pixel-tablet-aaos/flash
scp "aaos-build:~/aaos_on_pixel/out/target/product/tangorpro/*.img" .
scp aaos-build:~/aaos_on_pixel/out/target/product/tangorpro/android-info.txt .
scp -r aaos-build:~/aaos_on_pixel/out/target/product/tangorpro/vendor/ vendor/
# 2. Flash (tablet in Fastboot mode: Power + Volume Down)
ANDROID_PRODUCT_OUT=. fastboot -w flashall
# 3. Sync vendor (after tablet boots)
export ANDROID_PRODUCT_OUT=~/Development/pixel-tablet-aaos/flash
adb wait-for-device
adb root
adb remount
adb sync vendor
adb reboot
# 4. Wait 3-5 min, AAOS starts
# 5. Delete server
hcloud server delete aaos-build
Cost Summary
| Item | Cost |
|---|---|
| Hetzner CCX63, ~2h | ~1.40 EUR |
| Network egress (~100 GB sync + ~2 GB download) | included |
| Total | ~1.50 EUR |