lawnchair-build — PawletOS Lawnchair build bridge

Builds Lawnchair (16-dev) either the current known-good way (vendored prebuilt stubs) or against PawletOS's actual AOSP android-16.0.0_r4 checkout, to eliminate the framework version-skew crash in TouchInteractionService (NoSuchMethodError at startup → OverviewProxyService never binds → no nav pill/gestures).

Kept separate from the lawnchair repo on purpose: the bridge mutates the Lawnchair tree reversibly, and this way a failed experiment can't dirty the launcher history.

Three-repo layout

Repo Role Where
PawletOS/prebuilt_lawnchair pre-built APK shipped in the ROM vendor/Lawnchair/LawnchairLauncher (Soong build)
PawletOS/Lawnchair (16-dev) launcher source external/build-tools/lawnchair/source (in-tree)
PawletOS/lawnchair-build this repo — build scripts external/build-tools/lawnchair/build (in-tree)

The in-tree paths are wired in android_local_manifest/common/pawletos.xml and synced by environ.py --forceResync. Neither source nor build repo is part of the Soong build — the output APK is committed to prebuilt_lawnchair, which is what the ROM actually packages.

The scripts find the Lawnchair checkout as a sibling automatically, in either layout:

AOSP tree (build server)                 PawletOS working copy (Windows)
external/build-tools/lawnchair/          PawletOS/
  source/   <- Lawnchair 16-dev            lawnchair/        <- Lawnchair 16-dev
  build/    <- this repo                   lawnchair-build/  <- this repo

In-tree, build.sh aosp also derives AOSP_ROOT from its own location (4 levels up), so no env vars are needed on the server.

Hybrid mode (build on a machine without the AOSP tree)

aosp-bridge/fetch-aosp-cache.sh <LAWNCHAIR_ROOT> pulls the bridge's inputs from the build server over ssh into .aosp-cache/ shaped like an AOSP root (the vendored-AIDL counterparts + the compiled framework jar, ~48 MB), then:

AOSP_ROOT="$PWD/.aosp-cache" ./build.sh aosp

Requires m framework-minus-apex to have been run on the server first (AIDL-only --skip-jars works without it).

Server Gradle toolchain

The build server has no system JDK/SDK. Gradle needs:

  • JAVA_HOME=~/PawletOS-Build/AOSP-Source/prebuilts/jdk/jdk21/linux-x86 (AOSP's prebuilt JDK 21 — nothing installed)
  • ANDROID_HOME=~/android-sdk — cmdline-tools + platforms;android-37.0
    • build-tools;37.0.0 (note: the package is android-37.0, not android-37 — minor-versioned platform naming)

Usage

./build.sh prebuilt          # plain Gradle, vendored stubs — works anywhere
./build.sh aosp              # both swaps + Gradle — needs an AOSP env on THIS machine
./build.sh aosp --skip-jars  # AIDL swap only (try this first)
./build.sh aosp --wmshell    # additionally swap WindowManager-Shell-16.jar
./build.sh restore           # undo all bridge changes in the lawnchair tree
./build.sh clone             # clone Lawnchair next to this folder if missing

aosp mode auto-detects the AOSP tree ($AOSP_ROOT, ~/PawletOS-Build/AOSP-Source, /mnt/ssd/AOSP-Source) and errors out if none exists — so it effectively only runs on ubuntu-server-01, while prebuilt works on any machine with a JDK/Android SDK.

What the bridge actually swaps (verified against the real tree, 2026-07)

The original plan guessed at Lawnchair's layout; the real wiring is:

Plan assumed Reality
quickstep/build.gradle.kts with its own aidl sourceSet One Groovy root build.gradle; quickstep is the withQuickstep sourceSet
Hidden-API jar at quickstep/libs/, needs Gradle edit addFrameworkJar('framework-16.jar') resolves prebuilts/libs/framework-16.jar by name into ~25 modules — drop-in file replacement, zero Gradle edits
Symlink IPip/ISplitScreen/IRecentsAnimation* .aidl Those files under wmshell/src are dead source — the compiled wm.shell stubs ship in prebuilts/libs/WindowManager-Shell-16.jar (an implementation dep, bundled into the APK). Swapping the jar (--wmshell) is the real lever
assembleLawnWithQuickstepRelease Three flavor dimensions → assembleLawnWithQuickstepGithubRelease

So the two swaps are:

  1. AIDL sources (aosp-bridge/gen-aidl-sourceset.sh) — every .aidl under systemUI/shared/src that has a same-path counterpart in frameworks/base/packages/SystemUI/shared/src (or core/java) is replaced by the AOSP copy. Copies, not symlinks; originals kept as .orig + manifest.
  2. Prebuilt jars (aosp-bridge/gen-framework-jars.sh) — prebuilts/libs/framework-16.jarframework-minus-apex.jar from out/soong/.intermediates. --wmshell additionally swaps WindowManager-Shell-16.jar.

Known skew already found

Lawnchair vendors both IOverviewProxy.aidl and ILauncherProxy.aidl in systemUI/shared/src/com/android/systemui/shared/recents/; the r4 tree has only ILauncherProxy + ISystemUiProxy (IOverviewProxy is the pre-rename QPR name). If Lawnchair's TouchInteractionService still hands SystemUI an IOverviewProxy binder, that alone explains the bind failure — the AIDL swap script flags this case but can't fix it; it needs a source look in Lawnchair's quickstep code.

Suggested order of operations

  1. Fix the current AOSP build blocker first (last build died in Soong generation: TWRP theme selection — TW_THEME unset, likely from the new recovery_toolkit in android_vendor_pawlet), then at minimum m framework-minus-apex.
  2. DRY_RUN=1 ./aosp-bridge/gen-aidl-sourceset.sh <AOSP_ROOT> <LAWNCHAIR_ROOT> — read what differs before anything is touched.
  3. ./build.sh aosp --skip-jars — test whether the AIDL swap alone fixes the crash.
  4. Full ./build.sh aosp, then --wmshell on top, escalating only as needed — each step pulls in more of the diverged class graph, and compile errors from the jar swaps are the skew surfacing at build time (fix in Lawnchair source, don't paper over).
  5. If it balloons: ./build.sh prebuilt still works (it auto-restores any bridge leftovers), and pinning to Lawnchair 15 stable remains the fallback plan.

Verifying the fix on device

adb connect 10.0.0.236:5555
adb logcat -c
# restart Lawnchair / reboot
adb logcat | grep -iE "TouchInteractionService|app.lawnchair|FATAL EXCEPTION|OverviewProxyService"

Success: no NoSuchMethodError/NoSuchFieldError, an OverviewProxy bind log line, and the nav pill/gesture affordances actually rendering.

S
Description
No description provided
Readme 80 KiB
Languages
Shell 100%