6.9 KiB
Android distro layer
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.
Layout
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.
Emulator + build entry point
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.
Boot experience: splash + launcher
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.
AOSP assistant/full-control contract
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.
Whitelabel — building a downstream brand
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-validate
See 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.