This directory contains the brand vendor tree for building a privileged-system-app Android distribution (Cuttlefish for CI validation, Pixel codenames for real devices). The toolchain is brand-aware: any downstream brand can build its own distribution by supplying a JSON brand config + vendor tree.
packages/os/android/
└── vendor/
└── <brand>/ # Vendor tree for brand <brand>
├── AndroidProducts.mk
├── <brand>_common.mk
├── apps/<AppName>/Android.bp
├── bootanimation/{desc.txt,README.md}
├── init/init.<brand>.rc
├── overlays/frameworks/base/core/res/res/values/config.xml
├── permissions/{Android.bp,default-permissions-<pkg>.xml,privapp-permissions-<pkg>.xml}
├── products/<brand>_*_phone.mk
└── sepolicy/{file_contexts,<brand>_agent.te,README.md}
The default brand shipped here is eliza (vendor/eliza/). The brand
configs live at packages/scripts/distro-android/brand.eliza*.json — one per
arch (brand.eliza.json = x86_64, brand.eliza-arm64.json,
brand.eliza-riscv64.json), all pointing at this package's
vendor/eliza/ overlay and the matching eliza_cf_<arch>_phone product.
Makefile here is the front door for the AOSP fork, parallel to
packages/os/linux/Justfile for the canonical Debian fork. ARCH selects
the brand config + Cuttlefish device dir; the eliza overlay (launcher,
splash, permissions) is arch-agnostic and shared across all three:
make build ARCH=x86_64 # build + launch + boot-validate a Cuttlefish image
make build ARCH=arm64
make build ARCH=riscv64
make sim ARCH=riscv64 # bring up + validate an already-built image
make bootanimation # render + pack the elizaOS boot splash (needs ImageMagick)Each target drives the brand-aware orchestrator in
packages/scripts/distro-android/ (build-aosp.mjs, sim.mjs,
build-bootanimation.mjs), which is the stack CI uses
(.github/workflows/elizaos-cuttlefish.yml). Real builds need a Linux
x86_64 host with KVM and a synced AOSP checkout (AOSP_ROOT, default
$HOME/aosp); riscv64 Cuttlefish runs under QEMU TCG (no KVM) and boots
slower — sim.mjs sizes its boot timeout for that automatically.
make build syncs vendor/eliza, validates the product layer against the
AOSP source, runs lunch eliza_cf_<arch>_phone-trunk_staging-userdebug && m,
launches Cuttlefish, and then runs the boot validator. The underlying
command is node packages/scripts/distro-android/build-aosp.mjs --brand-config <arch-config> --aosp-root <root> --launch --boot-validate.
Note on orchestration: a second, divergent AOSP build/emulator stack exists at
packages/app-core/scripts/aosp/(wired into app-core's vitest
- agent-payload staging). It currently ships only an x86_64 product path, so the eliza arm64/riscv64 images come from the
distro-androidstack that this Makefile drives. The two stacks share an identical-purpose core of ~11 files that have drifted; collapsing them to one canonical core is tracked as follow-up cleanup.
Every eliza image boots straight into the elizaOS launcher with the elizaOS boot splash:
- Launcher —
eliza_common.mkstrips the stock launchers and the Eliza APKoverrides: ["Launcher3", "Launcher3QuickStep", "Trebuchet", …], so Eliza (ai.elizaos.app) is the only HOME app. The overlay setsconfig_defaultHome(alongside dialer/sms/assistant/browser) andro.elizaos.home, and SetupWizard is disabled — no Google "Welcome" flow. - Splash —
scripts/generate-eliza-bootanimation.mjsrenders the white elizaOS logo on the elizaOS blue field (#0B35F1) intovendor/eliza/bootanimation/from the canonical brand SVG usingsharp(the repo's image toolchain — no external ImageMagick needed), andbuild-bootanimation.mjspacks it into the uncompressedbootanimation.zipAOSP's bootanimation daemon requires. The rendered frames + zip are gitignored; runmake bootanimationbeforemake buildto bake the splash in. If the zip is absent,eliza_common.mkguards the copy and the image falls through to the stock AOSP animation.
The AOSP image makes ai.elizaos.app the device assistant, not just another
app that can answer an intent. The product overlay sets
config_defaultAssistant, the APK declares ElizaAssistActivity for both
android.intent.action.ASSIST and android.intent.action.VOICE_COMMAND, and
the boot validator checks the role holder plus both activity resolutions.
The machine-readable contract lives at
vendor/eliza/manifests/aosp-assistant-full-control.json and is copied into
the image at /product/etc/eliza/aosp-assistant-full-control.json. It records
the full AOSP-only control surface:
RoleManager.ROLE_ASSISTANT,Intent.ACTION_ASSIST, andIntent.ACTION_VOICE_COMMANDownership and their concrete platform values.- Concrete AOSP-only
ElizaAccessibilityServiceandElizaNotificationListenerServicedeclarations. The Play/cloud build strips the services, Java sources, and accessibility-service XML resource. - Usage stats through
PACKAGE_USAGE_STATSplus the boot-timeGET_USAGE_STATSappop grant path. - MediaProjection/foreground-service screen capture for user-consented paths
and privileged
READ_FRAME_BUFFERcapture for system images. - Input control through accessibility gestures on user-consented paths and
INJECT_EVENTSon privileged system images. - Direct-boot receiver coverage for
LOCKED_BOOT_COMPLETED,BOOT_COMPLETED, and package replacement. - Foreground service declarations for the local agent runtime, gateway sync, background voice capture, and screen capture.
- System-image requirements:
/system/priv-app/Eliza/Eliza.apk, platform certificate,privileged: true, default-permissions XML, and privapp XML.
Google Play builds must use android-cloud. Static checks assert that the
cloud build strips assistant/default-role components, boot/direct-boot
receivers, RECEIVE_BOOT_COMPLETED, background microphone foreground service,
MediaProjection service permission, privileged permissions, and native
system-control plugins.
Provide a brand config and a corresponding vendor tree, then drive every
script in packages/scripts/distro-android/ with --brand-config <path>:
node packages/scripts/distro-android/build-aosp.mjs \
--brand-config /path/to/your-brand.json \
--source-vendor /path/to/your-vendor-tree \
--aosp-root /path/to/aosp \
--launch --boot-validateSee packages/scripts/distro-android/README.md for the brand config schema and the
GitHub Actions workflow .github/workflows/elizaos-cuttlefish.yml for a
reusable workflow that downstream brands can call.