Skip to content

Repository files navigation

AOSP 17 for Google Pixel devices

This repository reconstructs reproducible Android 17 userdebug development workflows for bootloader-unlocked Google Pixel devices whose current AOSP build support is no longer published by Google. It builds a standard ARM64 AOSP GSI and complete device products whose proprietary support is extracted locally from the matching stock releases. The target is always selected explicitly with PIXEL_TARGET; it is never inferred from an attached USB device.

Target status

Phone Codename Platform Repository status
Pixel 11 cubs Malibu Real-hardware boot qualified; broader functional qualification remains incomplete
Pixel 10 frankel Laguna Native 192 kHz playback verified on both built-in speaker routes in the September 11 hardware/API tests; see the dated report for limits
Pixel 9 To be established from its own stock package To be established Future target; no build or qualification claim

Read docs/multi-target-layout.md for the target boundary and output-isolation rules. Frankel work is documented in docs/frankel-baseline.md and docs/frankel-build-and-flash.md. The 192 kHz Android application/HAL qualification boundary is documented in docs/frankel-audio-api.md, and the permanent pre-audioserver D10 boot path is in docs/frankel-powerphone-image-integration.md. The final 192 kHz endpoint matrix and evidence boundary are in docs/frankel-powerphone-final-qualification.md. The serial-free qualification record and exact final evidence are in docs/frankel-validation.md.

The September 11 playback report supersedes earlier playback-rate claims: those missed wrong pitch and repeated samples inside AoC despite successful APIs and zero ALSA xruns. The corrected path uses PCM0,D5/source5/EP6, S32 stereo at 192 kHz, coherent 192-frame DSP blocks, and a 12.288 MHz two-slot backend. Intermittent host underruns with 1920x2 ALSA periods led to 192x20 periods with the same 3840-frame buffer and full-buffer start. A dedicated FIFO/95 kernel period worker, FIFO/90 playback writers and 960-frame framework bursts complete the host transport. The September 11 flashed image passed Java AudioTrack on both speaker routes, AAudio for 120 seconds on the bottom speaker and 30 seconds on the earpiece, and intended 54.283 kHz self-loop components through both speakers. The ordinary 48 kHz client reproduces 12 kHz at the correct pitch through the fixed 192 kHz backend. The direct ALSA results and all earlier failed trials remain in the report. This is not a calibrated flat-response claim through 96 kHz or a sample-clock jitter measurement. Signed AoC firmware stays unchanged; guarded boot-time runtime patches apply the corrections. The retained unsigned firmware is not flashable.

The September 12 ordinary-audio investigation addresses a subsequent report of inaudible UI sounds. The ordinary-speaker route had incorrectly overridden donor amplifier gain 17 with the earpiece's gain 6. Restoring the ordinary route's donor gain improves measured playback level; the report distinguishes live trials from post-flash results. The old 66.547 kHz recording was weak evidence, not proof of airborne ultrasonic output. On-device tone correlation and amplifier-off controls alone do not fully separate acoustic output from electrical coupling.

After the user confirmed the UI sound was working but quiet, the UI-volume adjustment retained factory amplifier settings and raised only the SYSTEM/SPEAKER policy curve by 6 dB. This is custom compensation, not a factory curve. The measured click-level increase is larger than the nominal policy change; see the real recordings and limits in the report. Media and research gain settings remain unchanged.

Completed research/ordinary playback handoffs pass after selecting the existing ro.audio.flinger_standbytime_ms=0 setting, which removes a three-second idle hardware hold. Simultaneously active primary and research BUS outputs are not supported: they share hardware and are not mutually arbitrated. Use one output owner at a time. Capture uses its separate, unchanged D10 path.

The current development bundle is artifacts/frankel/powerphone-playback192-bootready-20260912/flash-all.sh, with all images alongside it. Its full-install script wipes userdata; see the bundle README. The boot-streamlining report records two consecutive boots with native audio preparation complete at about 19.8 seconds and boot completion at about 21.1 seconds. Normal boot presentation and input wait for audio readiness; no manual post-launcher warm-up remains. First non-root app playback/recording at 192 kHz produced the correct recorded 20 kHz tone without detected dropouts or phase jumps on both boots. All ten endpoint API checks and eight recorded UI clicks passed their scoped checks. Existing amplifier settings and UI-volume compensation are preserved.

This revision incrementally flashed system, system_ext and vendor, retaining the RT kernel and userdata; it is not a new full-wipe run of every bundled image. No hashes or attestation were required. The previous UI-volume bundle remains available for recovery. Earlier research-route acoustic continuity limitations remain documented; these startup tests are not a renewed full-bandwidth or all-research-path qualification. Reproduction: boot-ready image build and underlying audio build. The September 16 three-microphone experiment adds simultaneous interleaved D10 capture for direct acoustic measurements. It requires an additional kernel image and a reversible, exclusive RAW firmware profile; these changes are not included in the September 12 bundle and do not advertise three-channel Android API capture. The reusable PowerPhone skill records the general hardware-to-API workflow and the measured failure modes.

Pixel 10 stock-compatible baseline qualification (historical)

The hardened complete frankel bundle boots on real hardware. Its guarded runner flashed all 36 packaged A-only images, wiped data/metadata, selected A, and rebooted without a verification bypass. Android 17 reached sys.boot_completed=1 in 20 seconds, then completed a normal 29-second reboot. Both runtime audits recorded 66 passes and zero failures with enforcing SELinux and verity. The eUICC and Pixel Modem Service compatibility faults from the preliminary candidate were absent; delayed checks after both boots found no target-process crash, provider rejection, or tombstone. Rear and front camera captures, Wi-Fi scan, Bluetooth enablement, an active audio track, vibration, storage, sensors, display/touch presence, and NFC/fingerprint service presence passed their recorded smoke checks. SIMs remained NOT_READY, no UWB service was exposed, and the documented end-to-end/manual checks remain unqualified. Physical B was already unbootable; the operator accepted this no-lifeboat exception. The exact tested userdebug system remains booted on A. See docs/frankel-validation.md for hashes and the exact qualification boundary.

Pixel 11 qualification status (Cubs-only)

The corrected complete cubs bundle boots on real hardware, but broader qualification remains incomplete. It was flashed with its packaged production AVB images and no verification-disable bypass. Android 17 reached sys.boot_completed=1 on slot A as userdebug with enforcing dm-verity on the first boot, a 38-second second boot, and a 20-second post-finalization boot. Both audited boots recorded 127 passes, zero failures, and five warnings; the exact flash transaction was then finalized and its active recovery proof was atomically archived. Camera2 opened both exposed devices and each produced a valid JPEG. Wi-Fi scanning and Bluetooth enablement worked; a packaged alarm exercised an active AudioFlinger output stream, and the vibrator HAL accepted a real 500 ms one-shot. Broader manual qualification remains partial: VINTF is still inconclusive, the SIM is not ready, and no UWB binder service was found. Treat every bundle as experimental and review docs/validation.md and docs/recovery.md before any device write.

Pinned baselines

Input Version
AOSP source android-17.0.0_r1 (CP2A.260605.016, SPL 2026-06-05)
Device support tool GrapheneOS adevtool commit b01ccecab3468f3bcfa0d23adc361ad074989674
Repo implementation commit b85886fa9f5b4e2189cc5b2f40bd0a80459d4c77
Node.js 24.20.0
Yarn 1.22.22
Android Platform-Tools 37.0.1
Host tested Ubuntu 26.04.1 x86_64 under WSL2 on a native Linux Btrfs workspace
Windows USB forwarding usbipd-win 5.3.0

The target profiles pin these latest reviewed stable global stock donors as of 2026-08-29:

Phone Target profile Stock donor Vendor SPL
Pixel 11 config/targets/cubs/release.env CD1A.260714.001.A9 2026-08-05
Pixel 10 config/targets/frankel/release.env CP2A.260805.005 2026-08-05
Pixel 9 Not yet defined Not yet selected Not yet established

android-17.0.0_r1 was the newest stable Android 17 tag in Google's official build-number table and manifest remote when rechecked on 2026-08-29.

Device images, AOSP/device-support source, the Repo implementation, Node, Yarn, and Platform-Tools have immutable revisions or filenames and recorded hashes in config/release.env or the resolved Repo manifest. Ubuntu packages are the non-hermetic layer: scripts/install-host-deps.sh uses the caller's currently configured APT sources, and this repository neither selects nor archives an APT snapshot. The exact packages observed on the tested host are an audit record in config/host-packages-ubuntu-26.04.tsv, not an installable lock. Preserve equivalent Ubuntu sources externally and record the resolved package versions when reproducing a release.

The framework is the June AOSP release while both current proprietary vendor/firmware donors carry an August SPL. This is intentional, but neither device build may be described as carrying August framework security coverage. Android's DSU security-patch comparison also prevents qualifying this older-SPL GSI through DSU on the newer stock OS, so device validation uses a carefully isolated raw slot-A flash.

Legal and redistribution boundary

Google publishes separate factory-image and full-OTA downloads for Pixel 11 (cubs) factory images, Pixel 11 full OTAs, Pixel 10 (frankel) factory images, and Pixel 10 full OTAs. The associated terms restrict disassembly, decompilation, reverse engineering, modification, and redistribution except where the applicable device license or law allows it. This workflow necessarily performs local extraction and assembles modified development images. Every builder must review and accept the applicable terms and obtain legal advice where appropriate.

This repository publishes only original scripts/documentation, pinned source manifests, and auditable compatibility patches. It does not publish Google archives, extracted proprietary blobs, generated vendor modules, credentials, or assembled image bundles. Those paths are ignored by Git. Apache-2.0 covers project-authored material only; upstream projects and downloaded files retain their own licenses and terms. See THIRD_PARTY_NOTICES.md.

Host requirements

The supported reproduction path is Ubuntu 26.04.1 x86_64, either native or under WSL2, with at least 64 GiB RAM on a native Linux ext4 or btrfs filesystem. The current host was tested on Btrfs; the host gate accepts both filesystems. It requires 400 GiB to remain free whenever source sync, vendor extraction, or a build starts. This is working headroom, not a total-disk or clean-start capacity estimate: provision that 400 GiB in addition to the space consumed by source, downloads, retained outputs, artifacts, and caches. WSL2 users must keep the workspace in its Linux filesystem rather than on a Windows mount such as /mnt/c. Other Linux distributions may be adaptable, but the installer and tested package names are Ubuntu-specific.

Each output root uses an isolated, ignored ccache with an explicit 50 GiB default cap. Budget 50 GiB per retained output cache: GSI plus Cubs plus Frankel can therefore reserve up to 150 GiB in addition to source and build outputs, and each future device target can add another 50 GiB. Cache contents are acceleration state, not source-lock or release-archive content. Override CCACHE_MAXSIZE or point selected builds at a reviewed shared CCACHE_DIR when storage policy requires a different tradeoff; set USE_CCACHE=0 to disable it explicitly. Never publish a ccache directory, and clear or disable it when investigating a suspected reproducibility failure.

The tested WSL2 USB path also requires the exact x64 usbipd-win 5.3.0 release on the Windows host. The official installer is usbipd-win_5.3.0_x64.msi, whose published SHA-256 is 1c984914aec944de19b64eff232421439629699f8138e3ddc29301175bc6d938. Download and verify that MSI in a Windows temporary directory outside this clone; .msi and .exe payloads are deliberately excluded from publication. The release's arm64 MSI digest, efd7c4eb99b144c1623e616064a7b262f83d0994b0d7fde16c95d4b07528b24d, is recorded for audit context only and is not an accepted substitute on the tested x64 host.

The recovery workflow accepts only the installed x64 payload with size 8803720 bytes, SHA-256 78fd94ca4125db7407c77bd7b985971a1ac95705a331401976f748770035325b, and this exact one-line --version output:

5.3.0-54+Branch.master.Sha.aa3db8b82c4cb5071fd31bc54211606c70886912.aa3db8b82c4cb5071fd31bc54211606c70886912

USBIPD_EXE may select a nondefault absolute installed location, but it never overrides those identity pins. Its elevated AutoBind policy must preserve forwarding across Android, bootloader fastboot, fastbootd, and recovery USB identities. Follow docs/recovery-anchor.md to validate the download, installed payload, Authenticode signature, and policy before any device write.

From a fresh clone on the supported host, replace YOUR_REPOSITORY_URL with the reviewed Git URL and run every command from the repository root:

git clone YOUR_REPOSITORY_URL pixel_aosp_manifest
cd pixel_aosp_manifest
scripts/install-host-deps.sh
PIXEL_TARGET=frankel scripts/check-host.sh  # or PIXEL_TARGET=cubs
scripts/lint.sh

The installer invokes sudo apt-get for the Ubuntu packages, so the caller must have sudo authority and must review the configured APT sources first. It then installs checksum-pinned, workspace-local Node, Yarn, and Platform-Tools.

The setup includes the AOSP host packages, Yarn 1.22.22, image inspection utilities, ShellCheck, and Git LFS. AOSP supplies its own JDK and compiler toolchains. Google's Platform-Tools license applies to the downloaded binary package.

The required Ubuntu package set installed by the script is:

alsa-utils android-sdk-libsparse-utils binutils bison brotli build-essential ca-certificates ccache cpio
curl device-tree-compiler diffutils e2fsprogs erofs-utils f2fs-tools flex
fontconfig git-core git-lfs gnupg gperf kmod lib32z1-dev libc6-dev-i386
libgl1-mesa-dev libx11-dev libxml2-utils jq lz4 openssh-client openssl pkgconf
protobuf-compiler python3 python-is-python3 python3-numpy python3-protobuf python3-scipy repo rsync
python3-matplotlib libsndfile1
shellcheck unzip x11proto-core-dev util-linux xsltproc xxd zip
zlib1g-dev zstd xz-utils 7zip

Node.js, Yarn, and Google Platform-Tools are installed separately under work/toolchains/ at the pinned versions above; they are not taken from APT. Yarn is mapped directly from the recorded, checksum-pinned tarball into the attested local Node tree without package-manager or lifecycle execution. APT supplies only the Repo launcher; scripts/sync-source.sh forces the pinned Repo implementation commit before syncing or serializing the source lock.

Host-toolchain installation holds an exclusive lock on the real work/toolchains/ directory; check-host.sh takes the matching shared lock. Version publication uses a recoverable two-rename transaction: after a crash, an absent version plus .previous is rolled back, while a present version plus .previous means publication committed and the old directory is archived. The version name can be absent only between those two renames while the exclusive lock is held. Convenience symlinks are replaced atomically through a temporary sibling symlink and rename.

Reproduce a selected target

Run target-aware commands with an explicit PIXEL_TARGET. Choose one of the following workflows; do not rely on the temporary legacy default of cubs.

For Pixel 10 (frankel), the current build/integration path is:

PIXEL_TARGET=frankel scripts/check-host.sh
PIXEL_TARGET=frankel scripts/sync-source.sh
PIXEL_TARGET=frankel GOOGLE_PIXEL_TERMS_ACCEPTED=1 scripts/download-stock.sh
PIXEL_TARGET=frankel scripts/extract-stock.sh
PIXEL_TARGET=frankel scripts/extract-vendor.sh
PIXEL_TARGET=frankel scripts/build-device.sh
PIXEL_TARGET=frankel scripts/package-device.sh
# After flashing and reaching Android over ADB:
FRANKEL_EXPECT_DISABLED_AVB=true \
PIXEL_TARGET=frankel scripts/validate-frankel-runtime.sh

The default, stock-audio Frankel bundle is published under artifacts/frankel/device/; its runner is artifacts/frankel/device/flash-all.sh. The bundle is complete for the reviewed Frankel port: 23 donor firmware images, seven source-built physical OS images, six source-built logical images, metadata, attestations, and the guarded runner. These proprietary/local outputs are ignored by Git and are not part of the public source repository.

The Frankel source integration also installs the standard AOSP Wi-Fi Aware and Wi-Fi RTT feature declarations requested by the generated Laguna product and a narrow, read-only eUICC flags provider for the GSF-free product. Its eight missing feature producers use Frankel-prefixed Soong names and retain the original installed filenames, so unchanged Cubs requests do not inherit the adapter. The provider uses the authority expected by the extracted Pixel eUICC support app but is not a general Google Services Framework implementation; see the runbook for its caller and coexistence boundaries.

Frankel acoustic-research builds have five boolean selections and two explicit profile selectors. POWERPHONE_AOC_ALSA_192K=true selects the exact paired kernel closure: the live-qualified AoC ALSA transformation for PCM0,D10 capture and PCM0,D0 / EP1 source-0 playback, plus the required aoc_core.ko zero-write-pointer reset. POWERPHONE_D0_PROGRESS_MODE=mailbox|pure-timer|one-period-lag chooses the D0 progress source after that transform; it defaults to mailbox, while the publishable PowerPhone profile explicitly selects one-period-lag. That mode combines real mailbox progress with the 1 ms counter poll and conservatively reports one physical period behind the real counter. It is the hardware-qualified native-q192 path; selection alone still is not an acoustic-bandwidth claim. POWERPHONE_SIGNED_AOC_FIRMWARE_PROFILE=stock|source0-4s32-allocator-fallback defaults to exact stock firmware; the retained second value is experimental and not bootable because GSA rejects the modified signed firmware. POWERPHONE_AUDIO_SIDECAR=true selects PCM0,D10 input, PCM0,D0 stereo-S32 output, the bounded raw-WRITEI staged player, and the boot certifier, which certifies the F1 speaker profile first and the D10 capture profile last. Speaker certification retains stock A32 when its optional early cache-sync window is unavailable, warms Android audio, allocates/rebases four F1 speaker banks, applies rate/period-guarded H0 192/1536 geometry without changing stock DeepBuffer geometry, and connects the native-q192 F1 profile while leaving UsfDefaultWorker at stock priority. Real-device boots established this order: installing D10 first can prevent the subsequent speaker factory-mailbox transaction from completing. The sidecar gives both directions a 1,920-frame framework queue while preserving D10's 1,920-by-four ALSA ring and D0's 1,920-by-two ALSA ring. Its companion tinyALSA patch exposes the cumulative xrun count, including internally recovered EPIPEs, so the HAL can fail client streams closed. POWERPHONE_CS35L43_192K=true selects the narrow high-rate amplifier transform. POWERPHONE_D5_TIMER=false retains the real-mailbox D5 implementation. POWERPHONE_PRIMARY_HAL_192K=true advertises ordinary primary/deep physical output at 192 kHz so AudioFlinger resamples ordinary clients, redirects both proprietary playback selectors to D5/source 5, and connects the speaker TDM backend to EP6. It also marks the secondary deep-buffer port DIRECT, leaving one persistent primary mixer for UI and media instead of two AudioFlinger threads racing the same AoC source-5 ring. The older rate-only value is retained only for historical comparison; pairing its source-1 route with the native-q192 profile can assert AMixSPKR and must not be used as the normal profile. Use the same explicit values for vendor sanitization, attestation, build, and packaging. Returning the AoC flag to false with POWERPHONE_D0_PROGRESS_MODE=mailbox and POWERPHONE_SIGNED_AOC_FIRMWARE_PROFILE=stock restores both paired modules and the signed firmware to their exact stock bytes without rerunning extraction; see docs/frankel-audio-api.md.

Packaging with the exact seven-selector profile publishes the research bundle at artifacts/frankel/powerphone/flash-all.sh; it never overwrites the boot-qualified baseline in artifacts/frankel/device/. A deliberately partial selection, mailbox progress, or modified cold-firmware experiment is isolated under its own artifacts/frankel/experimental-* directory. BUNDLE_INFO.txt records the profile and all seven selection values so a copied bundle remains self-describing. On the exact integrated image, both individual D0 output routes and all three D10 logical input routes passed direct 192 kHz transport. Java AudioTrack/AAudio passed both outputs and Java AudioRecord/AAudio passed all three UNPROCESSED inputs while the HAL reported exact 192 kHz hardware geometry and AoC counters remained stable. The final single-output source-5/EP6 image survived five UI lock/unlock cycles and opened Sound Settings in 273 ms with AoC restart/coredump counters at 0/0. Three ordinary 48 kHz AudioTrack runs, deliberately overlapped with lock/unlock, Settings, and volume-key sonification, were converted onto the same 192 kHz primary thread. They completed 384,000 client frames in 8.005, 8.015, and 8.008 seconds with zero underruns. Their simultaneous 192 kHz D10 captures contain uninterrupted physical 15 kHz speaker responses: every run had zero missing 20 ms windows between the first and last detected response. The earlier source-1 crash, source-0 transport-only silence, and dual-output source-5 timing corruption remain documented as rejected experiments. Independently calibrated acoustic qualification remains separate: a characterized external ultrasonic source/receiver is still required to assign physical bandwidth to each speaker and enclosure microphone.

Hardware evidence is candidate-specific: a later rebuild or repack is not qualified merely because this exact bundle passed. Follow the real slot-A and post-boot procedure in docs/frankel-build-and-flash.md, and bind each new result to the evidence fields in docs/frankel-validation.md. The Frankel bundle runner writes root vbmeta last with fastboot's --disable-verity --disable-verification options. Its packaged vbmeta.img remains the signed flags-0 source image; runtime validation of a runner-flashed candidate must explicitly set FRANKEL_EXPECT_DISABLED_AVB=true.

For the already boot-qualified Pixel 11 (cubs) device product:

PIXEL_TARGET=cubs scripts/check-host.sh
PIXEL_TARGET=cubs scripts/sync-source.sh
PIXEL_TARGET=cubs GOOGLE_PIXEL_TERMS_ACCEPTED=1 scripts/download-stock.sh
PIXEL_TARGET=cubs scripts/extract-stock.sh
PIXEL_TARGET=cubs scripts/extract-vendor.sh
PIXEL_TARGET=cubs scripts/build-device.sh
PIXEL_TARGET=cubs scripts/package-device.sh

The standard Android 17 ARM64 userdebug GSI build produces system.img, vbmeta.img, and pvmfw.img. Its current recovery-anchored package/flash path is Cubs-only, so select Cubs explicitly:

PIXEL_TARGET=cubs scripts/build-gsi.sh
PIXEL_TARGET=cubs scripts/package-gsi.sh

scripts/sync-source.sh rejects unexpected .repo/local_manifests entries and requires the synced revisions to match the committed manifests/resolved.xml. Only a maintainer intentionally reviewing a revision update should run, for the selected profile, for example:

PIXEL_TARGET=frankel PIXEL_AOSP_UPDATE_SOURCE_LOCK=1 scripts/sync-source.sh

Ordinary reproductions must never refresh the lock implicitly. The legacy CUBS_UPDATE_SOURCE_LOCK spelling is accepted only for migration; new instructions and automation must use PIXEL_AOSP_UPDATE_SOURCE_LOCK.

The patch driver is idempotent and records the smallest known target-aware delta needed by current adevtool; it does not replace AOSP with a downstream OS. Never use adevtool --noVerify or --updateSpec in this workflow.

Pixel 11 vendor, build, and AVB gates (Cubs-only)

Extraction writes an ignored, deterministic attestation at work/attestations/cubs-generated-vendor.attestation. It binds every generated file's content and mode, every directory mode, and every in-tree symlink target to the factory-image digest/build, resolved source manifest, pinned adevtool revision, and reviewed sanitizer. Device build and packaging refuse a changed or unattested vendor tree. The sanitizer removes SELINUX_IGNORE_NEVERALLOWS and BUILD_BROKEN_DUP_RULES. After the unmodified upstream FileTreeSpec passes, the sanitizer removes the stock-derived duplicate of AOSP's standard vndservicemanager transfer rule from both normal and recovery extension CILs, including only its orphaned synthetic attribute. It pins the pristine and post-transform hashes and verifies that pristine AOSP still owns the exact equivalent rule with explicit init and vendor_init exclusions. The sanitizer also removes only the generated hostapd and supplicant XML files and their Soong modules, and replaces their product requests with the corresponding pristine-AOSP fragment modules. Those AOSP modules declare the same HALs at the same vendor paths and remain explicitly installed even though cubs uses proprietary Wi-Fi binaries. The attestation binds these narrow transforms and strict enforcement, and fails if either broad bring-up exception reappears. Because adevtool also collapses named fstab AVB dependencies to root vbmeta, the sanitizer restores the exact stock-shaped child references in both generated fstab.malibu copies: framework partitions use vbmeta_system, vendor uses vbmeta_vendor, and boot/init_boot use their same-named chains; vendor_dlkm remains root-direct. Both pristine and normalized fstab hashes and the normalization helper are attested. Static image validation requires the generated and target-files copies to be byte-identical and derives their allowed child names from the root vbmeta chain descriptors. Build completion then requires exactly one Soong install rule per fragment, owned by the pinned AOSP modules, and attests their exact AOSP hashes in the canonical target-files vendor-manifest paths.

Each build also invalidates its prior completion attestation immediately before invoking the Android build, then recreates it atomically only after every required output is present and hashed. These ignored markers bind the resolved source and patch locks, target identity, release/build ID/SPL/variant, build tools, target-files, and—for cubs—the generated-vendor attestation. Packaging rejects missing or stale markers and includes the verified marker as BUILD_ATTESTATION.txt in the bundle checksum manifest. Packaging then runs the mandatory repository static validator against a complete staging bundle before publication and revalidates the published copy.

For cubs, the completion marker also compensates for the reviewed Soong patch that disables the unsupported generic standalone-system-server dexpreopt check. It binds malibu-plugin-provider.jar and its arm64 ODEX/VDEX files between the live product tree and their exact SYSTEM_EXT/ target-files entries, verifies the generated and installed JAR are identical valid ZIPs, checks their OAT/VDEX magic, and independently pins the effective dexpreopt configuration. The production semantic gate additionally requires the exact 35-record dex2oat invocation, CMC with no verify/profile fallback, the pinned arm64 Cortex-A76/default compiler settings, the 52-entry boot class path, and the 18-entry standalone system-server class-loader context. It runs the source-built, checksum-pinned host oatdump read-only against the JAR/ODEX/VDEX set and requires the exact Android 17 OAT header and checksum-bearing stored class path. These output-validation pins live in config/cubs-dexpreopt.env, deliberately outside the Android build-input identity in config/release.env.

Pixel 11 flashing and recovery (Cubs-only)

Development flashing remains gated until the corresponding package command completes the mandatory staging validation and published-copy revalidation. The exact-stock slot-A recovery path is already available, but it is destructive:

PIXEL_TARGET=cubs scripts/check-device.sh
export CUBS_FASTBOOT_SERIAL='<fastboot-serial>'
export CUBS_ALLOW_DATA_WIPE=1
export CUBS_RESTORE_CONFIRM=RESTORE_STOCK_A_SHARED_SUPER_INVALIDATES_B_ANDROID
PIXEL_TARGET=cubs scripts/restore-stock.sh

Pixel 11's virtual A/B logical _a and _b views share physical super extents. The first development logical-A write invalidates Android B as a fallback even though B boot-control flags remain healthy. The flash and restore workflows preserve B's 25 physical firmware partitions plus its nine boot/recovery/fastbootd partitions, use literal _a partition names, and write logical A before physical A. Before a flash, the bound stock-B verification creates an ignored, mode-0600, one-hour handoff containing only a salted serial digest. The standalone runner verifies its exact stock/OTA and all-34-partition lineage, claims it for the exact bundle, and publishes a salted, bundle-bound slot-A transaction before changing boot control. It then selects untouched stock A, enters A-origin fastbootd, requires the complete A-only logical namespace, and writes the logical payloads. Only after returning to bootloader fastboot does it write physical A, wipe shared data, and reassert A as the final device write. A failed first Android boot therefore keeps both the physical-B restore authority and an exact resumable or abortable journal. After an exact slot-A userdebug boot, the runtime validator can publish a private v2 proof bound to the claimed handoff, bundle checksum manifest, and slot-A transaction hash. Only the separately gated bootloader finalizer may then atomically archive the lineage, claimed handoff, transaction, runtime proof, and retirement receipt; its journal makes host interruption during cleanup recoverable. A historical archive is never accepted as proof of the current slot-A bytes.

The runner locates the pinned Platform-Tools fastboot binary relative to an in-tree bundle and verifies both its version and extracted-binary digest. All ADB-backed attestations and stock-restore checks likewise use the workspace's pinned Platform-Tools ADB binary; a same-named distro tool is rejected. The stock restore enters B-origin fastbootd, journals a same-connection selector and first logical resize to pivot to A metadata, restores all logical A images, and writes physical A only after returning to bootloader. It proves restored stock A first in Android and then in bootloader fastboot before retiring the lifeboat. An expired but never-claimed ready handoff has a guarded archival-and-reissue workflow; claimed handoffs cannot use it. Read docs/recovery-anchor.md, docs/packaging.md, and docs/recovery.md before any device write.

If stock recovery cannot populate inactive B, use the separately audited physical-B fastbootd route in docs/stock-b-physical-preparation.md. It begins from the one exact finalized stock-restore receipt and never boots Android B: restored shared-super metadata exposes an A-only logical namespace even while physical B is current. Its provenance is the claimed terminal restore baseline, six factory-expanded logical sizes, exact pinned physical source manifest, 34 acknowledged flashes, complete vendor_boot_a/b controls, and a one-shot strict fastbootd runtime trial—not an unavailable 34-partition device readback claim.

Publish source safely

This working tree deliberately contains ignored Google archives, extracted proprietary files, build outputs, image bundles, host-specific logs, caches, and private recovery receipts. .gitignore is an accident-prevention layer, not permission to upload the directory. Never archive the working tree, use git add -f, or attach artifacts/ to a GitHub release.

After the status record is final and the intended source files are staged, review the exact Git boundary and create a source archive only from a reviewed commit:

scripts/lint.sh
git status --short --ignored
git diff --check
git diff --cached --check
git ls-files

# Run only after committing the reviewed source set.
git archive --format=tar.gz \
  --output=pixel_aosp_manifest-source.tar.gz HEAD

Inspect git ls-files before every publication. It must not contain anything under work/, out/, downloads/, artifacts/, logs/, .cache/, or a generated proprietary tree, nor any image, executable blob, credential, or private signing key. Push the reviewed commit or upload the git archive result; do not substitute a filesystem ZIP or tarball. The generated source archive is itself ignored and is not an input to later builds.

Repository layout

  • config/release.env: AOSP, Repo, adevtool, Node, Yarn, and Platform-Tools inputs shared by all targets.
  • config/targets/<codename>/release.env: one reviewed stock donor and device identity per supported target; see config/targets/README.md.
  • config/recovery.env and the existing Cubs validation configs: legacy Cubs-only recovery and qualification policy, not reusable Frankel policy.
  • manifests/: pinned Repo projects and the resolved source manifest.
  • patches/: auditable common and platform-specific compatibility patches with upstream provenance.
  • scripts/lib/target-profile.sh: validates PIXEL_TARGET against the fixed allowlist and loads exactly one profile.
  • scripts/: shared setup/sync orchestration plus target-aware extraction, build, packaging, validation, flash, and recovery entry points.
  • scripts/audio/frankel/: guarded, target-scoped tinyALSA speaker/PDM probes and deterministic high-rate WAV generation for Frankel acoustic-sensing work.
  • docs/: shared architecture plus explicitly device-scoped baselines, flashing runbooks, recovery policy, and validation records.
  • skills/android-gsi-device-port/: reusable Codex guidance for bringing AOSP to other bootloader-unlocked phones without maintained OEM device support.
  • skills/powerphone/: reusable layered workflow for maximizing built-in Android speaker/microphone transport rates and separately qualifying physical acoustic bandwidth.
  • work/: ignored source, toolchains, extraction state, and build outputs (work/aosp/out_pixel/gsi/, work/aosp/out_pixel/cubs/, and work/aosp/out_pixel/frankel/).
  • downloads/, artifacts/, logs/: ignored proprietary inputs, local image bundles, and host-specific build/validation logs. Current device bundle roots are the legacy artifacts/cubs/ and the target-scoped artifacts/frankel/device/ (baseline) and artifacts/frankel/powerphone/ (forced-primary-192 research build). The local artifacts/frankel/powerphone-audio192-dev/ tested rate-only build is an intentionally unhashed, unattested bundle with audible 192 kHz primary audio and 192 kHz research BUS endpoints; it is ignored by Git like all image artifacts.
  • .cache/: ignored private recovery journals and attestations; never publish or copy this state between devices.

Start with docs/multi-target-layout.md and docs/architecture.md. For Frankel, continue with docs/frankel-baseline.md and docs/frankel-build-and-flash.md, then record real-device evidence in docs/frankel-validation.md. The existing docs/device-baseline.md, docs/recovery.md, docs/runtime-validation.md, and docs/functional-validation.md describe the Cubs-only baseline, recovery system, and acceptance gates. Neither a completed build nor registered HAL services alone establishes working hardware for a new target.

Primary references

About

Manifest for building AOSP GSI for Pixel phones (WIP)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages