init: Lawnchair build bridge — prebuilt and AOSP-source build modes
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
* text=auto
|
||||
*.sh text eol=lf
|
||||
@@ -0,0 +1,116 @@
|
||||
# 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.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
./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.jar` ← `framework-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
|
||||
|
||||
```bash
|
||||
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.
|
||||
Executable
+120
@@ -0,0 +1,120 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# gen-aidl-sourceset.sh — overwrites Lawnchair's vendored launcher<->SystemUI
|
||||
# AIDL sources with the copies from PawletOS's local frameworks/base, so the
|
||||
# binder surface Lawnchair compiles against matches what the device's
|
||||
# SystemUI actually exposes.
|
||||
#
|
||||
# VERIFIED LAYOUT (Lawnchair 16-dev, checked 2026-07):
|
||||
# The AIDLs that are compiled FROM SOURCE live in systemUI/shared/src
|
||||
# (module ':shared' -> systemUI/shared, aidl.srcDirs includes its src dir).
|
||||
# That includes the TouchInteractionService handshake interfaces:
|
||||
# ISystemUiProxy, ILauncherProxy (and the vendored-only IOverviewProxy).
|
||||
#
|
||||
# The wm.shell interfaces (IPip, ISplitScreen, IRecentsAnimation*, ...)
|
||||
# under wmshell/src are NOT compiled — wmshell's sourceSet only includes
|
||||
# wmshell/shared/src; the real wm.shell classes ship precompiled in
|
||||
# prebuilts/libs/WindowManager-Shell-16.jar. Touching wmshell/src does
|
||||
# nothing; that jar is handled by gen-framework-jars.sh --wmshell instead.
|
||||
#
|
||||
# Usage:
|
||||
# gen-aidl-sourceset.sh <AOSP_ROOT> <LAWNCHAIR_ROOT>
|
||||
# DRY_RUN=1 gen-aidl-sourceset.sh <AOSP_ROOT> <LAWNCHAIR_ROOT> # report only
|
||||
# gen-aidl-sourceset.sh --restore # undo via manifest
|
||||
#
|
||||
# Files are COPIED (not symlinked) so the result works regardless of where
|
||||
# the Lawnchair checkout lives; originals are kept as <file>.orig and listed
|
||||
# in the manifest for --restore.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
log() { printf '\033[1;33m[gen-aidl]\033[0m %s\n' "$*"; }
|
||||
err() { printf '\033[1;31m[gen-aidl]\033[0m %s\n' "$*" >&2; }
|
||||
|
||||
MANIFEST_NAME=".aosp-bridge-aidl-backup.tsv"
|
||||
DRY_RUN="${DRY_RUN:-0}"
|
||||
|
||||
# --- restore mode ------------------------------------------------------
|
||||
if [ "${1:-}" = "--restore" ]; then
|
||||
ROOT="${LAWNCHAIR_ROOT:-.}"
|
||||
MANIFEST="$ROOT/$MANIFEST_NAME"
|
||||
[ -f "$MANIFEST" ] || { log "no AIDL backup manifest at $MANIFEST — nothing to restore"; exit 0; }
|
||||
while IFS=$'\t' read -r target backup; do
|
||||
[ -z "$target" ] && continue
|
||||
if [ -e "$backup" ]; then
|
||||
mv -f "$backup" "$target"
|
||||
log "restored: $target"
|
||||
fi
|
||||
done < "$MANIFEST"
|
||||
rm -f "$MANIFEST"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
AOSP_ROOT="${1:?usage: gen-aidl-sourceset.sh <AOSP_ROOT> <LAWNCHAIR_ROOT>}"
|
||||
LAWNCHAIR_ROOT="${2:?usage: gen-aidl-sourceset.sh <AOSP_ROOT> <LAWNCHAIR_ROOT>}"
|
||||
MANIFEST="$LAWNCHAIR_ROOT/$MANIFEST_NAME"
|
||||
|
||||
# Lawnchair source-compiled AIDL root -> candidate AOSP roots for the same
|
||||
# package-relative path. core/java catches android.os / com.android.internal
|
||||
# files that SystemUI/shared borrows from framework core.
|
||||
LAWN_AIDL_ROOT="$LAWNCHAIR_ROOT/systemUI/shared/src"
|
||||
AOSP_CANDIDATE_ROOTS=(
|
||||
"$AOSP_ROOT/frameworks/base/packages/SystemUI/shared/src"
|
||||
"$AOSP_ROOT/frameworks/base/core/java"
|
||||
)
|
||||
|
||||
[ -d "$LAWN_AIDL_ROOT" ] || { err "expected $LAWN_AIDL_ROOT to exist — Lawnchair layout changed, re-verify before using this script"; exit 1; }
|
||||
|
||||
[ "$DRY_RUN" = "1" ] || : > "$MANIFEST"
|
||||
|
||||
swapped=0
|
||||
identical=0
|
||||
vendored_only=()
|
||||
|
||||
while IFS= read -r lawn_file; do
|
||||
rel="${lawn_file#"$LAWN_AIDL_ROOT/"}"
|
||||
|
||||
aosp_file=""
|
||||
for root in "${AOSP_CANDIDATE_ROOTS[@]}"; do
|
||||
[ -f "$root/$rel" ] && { aosp_file="$root/$rel"; break; }
|
||||
done
|
||||
|
||||
if [ -z "$aosp_file" ]; then
|
||||
vendored_only+=("$rel")
|
||||
continue
|
||||
fi
|
||||
|
||||
if cmp -s "$lawn_file" "$aosp_file"; then
|
||||
identical=$((identical + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
log "DIFFERS: $rel"
|
||||
log " <- $aosp_file"
|
||||
if [ "$DRY_RUN" != "1" ]; then
|
||||
cp -a "$lawn_file" "${lawn_file}.orig"
|
||||
printf '%s\t%s\n' "$lawn_file" "${lawn_file}.orig" >> "$MANIFEST"
|
||||
cp "$aosp_file" "$lawn_file"
|
||||
fi
|
||||
swapped=$((swapped + 1))
|
||||
done < <(find "$LAWN_AIDL_ROOT" -name '*.aidl' | sort)
|
||||
|
||||
log "----------------------------------------------------------------"
|
||||
log "swapped: $swapped identical (no action): $identical"
|
||||
|
||||
if [ "${#vendored_only[@]}" -gt 0 ]; then
|
||||
err "Vendored-only AIDLs with NO counterpart in this AOSP tag (left untouched):"
|
||||
for v in "${vendored_only[@]}"; do err " - $v"; done
|
||||
err "If Lawnchair code implements one of these but the device SystemUI binds its"
|
||||
err "renamed successor (e.g. IOverviewProxy vs ILauncherProxy in android-16),"
|
||||
err "that's a likely source of the bind failure — needs a source-level look."
|
||||
fi
|
||||
|
||||
if [ "$DRY_RUN" = "1" ]; then
|
||||
log "DRY_RUN=1 — nothing was modified."
|
||||
elif [ "$swapped" -gt 0 ]; then
|
||||
log "Backup manifest: $MANIFEST (undo with --restore)"
|
||||
else
|
||||
rm -f "$MANIFEST"
|
||||
log "No differing files — vendored AIDL already matches this AOSP tree."
|
||||
fi
|
||||
Executable
+118
@@ -0,0 +1,118 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# gen-framework-jars.sh — replaces Lawnchair's vendored prebuilt jars with
|
||||
# the ones compiled from PawletOS's local AOSP tree. (Successor to the
|
||||
# planned gen-hidden-api-jar.sh — the destination wiring turned out to be
|
||||
# much simpler than the plan assumed.)
|
||||
#
|
||||
# VERIFIED WIRING (Lawnchair 16-dev root build.gradle, checked 2026-07):
|
||||
# addFrameworkJar('framework-16.jar') prepends
|
||||
# prebuilts/libs/framework-16.jar to the compile classpath of the root
|
||||
# module and ~25 submodules, and it is resolved BY FILE NAME in
|
||||
# prebuilts/libs. So the hidden-API swap is a drop-in replacement of that
|
||||
# one file — no Gradle edits needed, and no quickstep/libs/ dir exists.
|
||||
#
|
||||
# WindowManager-Shell-16.jar is wired as `implementation` (bundled into
|
||||
# the APK!) and carries the compiled wm.shell binder stubs (IPip,
|
||||
# ISplitScreen, IRecentsAnimation*, ...). Swapping it aligns those
|
||||
# transaction surfaces too, but drags in more of the diverged class graph
|
||||
# — opt in with --wmshell only if the framework jar swap alone isn't enough.
|
||||
#
|
||||
# Usage:
|
||||
# gen-framework-jars.sh [--wmshell] <AOSP_ROOT> <LAWNCHAIR_ROOT>
|
||||
# gen-framework-jars.sh --restore
|
||||
#
|
||||
# Originals are kept as <jar>.orig and recorded in a manifest for --restore.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
log() { printf '\033[1;33m[gen-jars]\033[0m %s\n' "$*"; }
|
||||
err() { printf '\033[1;31m[gen-jars]\033[0m %s\n' "$*" >&2; }
|
||||
|
||||
MANIFEST_NAME=".aosp-bridge-jars-backup.tsv"
|
||||
|
||||
# --- restore mode ------------------------------------------------------
|
||||
if [ "${1:-}" = "--restore" ]; then
|
||||
ROOT="${LAWNCHAIR_ROOT:-.}"
|
||||
MANIFEST="$ROOT/$MANIFEST_NAME"
|
||||
[ -f "$MANIFEST" ] || { log "no jar backup manifest at $MANIFEST — nothing to restore"; exit 0; }
|
||||
while IFS=$'\t' read -r target backup; do
|
||||
[ -z "$target" ] && continue
|
||||
if [ -e "$backup" ]; then
|
||||
mv -f "$backup" "$target"
|
||||
log "restored: $target"
|
||||
fi
|
||||
done < "$MANIFEST"
|
||||
rm -f "$MANIFEST"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
WMSHELL=0
|
||||
if [ "${1:-}" = "--wmshell" ]; then WMSHELL=1; shift; fi
|
||||
|
||||
AOSP_ROOT="${1:?usage: gen-framework-jars.sh [--wmshell] <AOSP_ROOT> <LAWNCHAIR_ROOT>}"
|
||||
LAWNCHAIR_ROOT="${2:?usage: gen-framework-jars.sh [--wmshell] <AOSP_ROOT> <LAWNCHAIR_ROOT>}"
|
||||
|
||||
PREBUILTS_DIR="$LAWNCHAIR_ROOT/prebuilts/libs"
|
||||
MANIFEST="$LAWNCHAIR_ROOT/$MANIFEST_NAME"
|
||||
INTERMEDIATES="$AOSP_ROOT/out/soong/.intermediates/frameworks/base"
|
||||
|
||||
[ -d "$PREBUILTS_DIR" ] || { err "$PREBUILTS_DIR not found — Lawnchair layout changed, re-verify"; exit 1; }
|
||||
|
||||
# Locate a module's compiled jar in Soong output. Exact intermediate layout
|
||||
# varies between AOSP versions, so prefer known paths then fall back to find.
|
||||
find_module_jar() {
|
||||
local module="$1" search_root="$2"
|
||||
local candidates=(
|
||||
"$search_root/$module/android_common/combined/$module.jar"
|
||||
"$search_root/$module/android_common/javac/$module.jar"
|
||||
)
|
||||
for c in "${candidates[@]}"; do
|
||||
[ -f "$c" ] && { echo "$c"; return 0; }
|
||||
done
|
||||
find "$INTERMEDIATES" -maxdepth 6 -path "*/$module/android_common*" -name "$module.jar" 2>/dev/null | head -1
|
||||
}
|
||||
|
||||
swap_jar() {
|
||||
local src="$1" dest_name="$2"
|
||||
local dest="$PREBUILTS_DIR/$dest_name"
|
||||
[ -f "$dest" ] || { err "expected vendored jar $dest to exist — aborting this swap"; return 1; }
|
||||
if [ ! -f "${dest}.orig" ]; then
|
||||
cp -a "$dest" "${dest}.orig"
|
||||
printf '%s\t%s\n' "$dest" "${dest}.orig" >> "$MANIFEST"
|
||||
fi
|
||||
cp "$src" "$dest"
|
||||
log "swapped $dest_name <- $src ($(du -h "$src" | cut -f1))"
|
||||
}
|
||||
|
||||
touch "$MANIFEST"
|
||||
|
||||
# --- framework-16.jar (the hidden-API classpath jar) --------------------
|
||||
# framework-minus-apex is the right module: the full app-facing framework
|
||||
# including @hide APIs, minus mainline-module classes Lawnchair can't see
|
||||
# anyway. Plain 'framework' is a thin wrapper around it in android-16.
|
||||
src_jar="$(find_module_jar framework-minus-apex "$INTERMEDIATES")"
|
||||
if [ -z "$src_jar" ]; then
|
||||
src_jar="$(find_module_jar framework "$INTERMEDIATES")"
|
||||
fi
|
||||
if [ -z "$src_jar" ]; then
|
||||
err "No compiled framework jar found under $INTERMEDIATES"
|
||||
err "Run a framework build first: lunch <target>-bp4a-userdebug && m framework-minus-apex"
|
||||
err "Then locate it manually if this still fails:"
|
||||
err " find \"$AOSP_ROOT/out/soong/.intermediates\" -name 'framework-minus-apex.jar'"
|
||||
exit 1
|
||||
fi
|
||||
swap_jar "$src_jar" "framework-16.jar"
|
||||
|
||||
# --- WindowManager-Shell-16.jar (opt-in) --------------------------------
|
||||
if [ "$WMSHELL" -eq 1 ]; then
|
||||
wm_jar="$(find_module_jar WindowManager-Shell "$INTERMEDIATES/libs/WindowManager/Shell")"
|
||||
[ -z "$wm_jar" ] && wm_jar="$(find_module_jar WindowManager-Shell "$INTERMEDIATES")"
|
||||
if [ -z "$wm_jar" ]; then
|
||||
err "WindowManager-Shell jar not found — build it with 'm WindowManager-Shell' and re-run"
|
||||
exit 1
|
||||
fi
|
||||
swap_jar "$wm_jar" "WindowManager-Shell-16.jar"
|
||||
fi
|
||||
|
||||
log "Done. Undo with --restore (manifest: $MANIFEST)"
|
||||
Executable
+94
@@ -0,0 +1,94 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# build-aosp.sh — builds Lawnchair against the local PawletOS AOSP checkout
|
||||
# instead of the vendored AIDL/stub jars. Fixes NoSuchMethodError-style
|
||||
# crashes in TouchInteractionService caused by Lawnchair's upstream stub
|
||||
# surface (QPR1-derived) drifting from PawletOS's actual frameworks/base
|
||||
# (android-16.0.0_r4).
|
||||
#
|
||||
# Two swaps, both reversible via 'build.sh restore':
|
||||
# 1. AIDL: systemUI/shared/src AIDL files <- frameworks/base copies
|
||||
# 2. Jars: prebuilts/libs/framework-16.jar <- compiled framework jar from out/
|
||||
# (+ optionally WindowManager-Shell-16.jar with --wmshell)
|
||||
#
|
||||
# Called via: build.sh aosp [--clean] [--skip-aidl] [--skip-jars] [--wmshell]
|
||||
|
||||
set -euo pipefail
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
AOSP_ROOT="${AOSP_ROOT:?AOSP_ROOT not set}"
|
||||
LAWNCHAIR_ROOT="${LAWNCHAIR_ROOT:?LAWNCHAIR_ROOT not set}"
|
||||
GRADLE_TASK="${GRADLE_TASK:-assembleLawnWithQuickstepGithubRelease}"
|
||||
|
||||
SKIP_AIDL=0
|
||||
SKIP_JARS=0
|
||||
WMSHELL=0
|
||||
CLEAN=0
|
||||
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--skip-aidl) SKIP_AIDL=1 ;;
|
||||
--skip-jars|--skip-hidden-api) SKIP_JARS=1 ;;
|
||||
--wmshell) WMSHELL=1 ;;
|
||||
--clean) CLEAN=1 ;;
|
||||
*) echo "unknown flag: $arg" >&2; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
log() { printf '\033[1;36m[build-aosp.sh]\033[0m %s\n' "$*"; }
|
||||
die() { printf '\033[1;31m[build-aosp.sh]\033[0m %s\n' "$*" >&2; exit 1; }
|
||||
|
||||
# Fail fast if the AOSP tree has never produced framework artifacts —
|
||||
# the jar swap needs a compiled framework, and a half-applied bridge is
|
||||
# worse than no bridge.
|
||||
if [ "$SKIP_JARS" -eq 0 ]; then
|
||||
if ! find "$AOSP_ROOT/out/soong/.intermediates/frameworks/base" \
|
||||
-maxdepth 4 -name 'framework-minus-apex.jar' -print -quit 2>/dev/null | grep -q .; then
|
||||
die "No compiled framework jar under \$AOSP_ROOT/out — run a framework build first
|
||||
(e.g. 'lunch <target>-bp4a-userdebug && m framework-minus-apex'), or pass
|
||||
--skip-jars to apply only the AIDL swap."
|
||||
fi
|
||||
fi
|
||||
|
||||
cd "$LAWNCHAIR_ROOT"
|
||||
|
||||
if [ "$CLEAN" -eq 1 ]; then
|
||||
log "Cleaning previous AOSP-bridge artifacts"
|
||||
"$SCRIPT_DIR/aosp-bridge/gen-aidl-sourceset.sh" --restore || true
|
||||
"$SCRIPT_DIR/aosp-bridge/gen-framework-jars.sh" --restore || true
|
||||
rm -f ./aosp-bridge.state
|
||||
fi
|
||||
|
||||
if [ "$SKIP_AIDL" -eq 0 ]; then
|
||||
log "Step 1/2: syncing AIDL sources from local AOSP tree"
|
||||
"$SCRIPT_DIR/aosp-bridge/gen-aidl-sourceset.sh" "$AOSP_ROOT" "$LAWNCHAIR_ROOT"
|
||||
else
|
||||
log "Step 1/2: skipped (--skip-aidl)"
|
||||
fi
|
||||
|
||||
if [ "$SKIP_JARS" -eq 0 ]; then
|
||||
log "Step 2/2: swapping prebuilt framework jar(s) from local AOSP build output"
|
||||
jar_flags=()
|
||||
[ "$WMSHELL" -eq 1 ] && jar_flags+=(--wmshell)
|
||||
"$SCRIPT_DIR/aosp-bridge/gen-framework-jars.sh" ${jar_flags[@]+"${jar_flags[@]}"} "$AOSP_ROOT" "$LAWNCHAIR_ROOT"
|
||||
else
|
||||
log "Step 2/2: skipped (--skip-jars)"
|
||||
fi
|
||||
|
||||
echo "aosp" > ./aosp-bridge.state
|
||||
|
||||
log "Running ./gradlew $GRADLE_TASK"
|
||||
if ! ./gradlew "$GRADLE_TASK"; then
|
||||
log "Build failed. Triage guide:"
|
||||
log " - Wall of missing-class/missing-method COMPILE errors: that IS the version skew,"
|
||||
log " now surfacing at build time instead of crashing at runtime. Each one needs a"
|
||||
log " source fix in Lawnchair (or the call removed) to match PawletOS's framework."
|
||||
log " - If it's unmanageable, retry with --skip-jars to isolate the AIDL swap alone,"
|
||||
log " or fall back to './build.sh prebuilt'."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log "Done. APK(s):"
|
||||
find . -path '*/outputs/apk/*' -name '*.apk' -newer ./gradlew 2>/dev/null | head -5
|
||||
log "NOTE: the swapped AIDL files and jars persist in the Lawnchair tree until you run"
|
||||
log "'./build.sh restore' — do that before committing anything in the lawnchair repo."
|
||||
Executable
+30
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# build-prebuilt.sh — plain Gradle build using the AIDL/hidden-API stubs
|
||||
# vendored in the Lawnchair repo (prebuilts/libs/framework-16.jar etc.).
|
||||
# This is the path PawletOS has used up to now: build the APK standalone,
|
||||
# drop it into vendor/pawlet prebuilts. Kept as the known-good fallback and
|
||||
# the only mode that works on machines without an AOSP checkout.
|
||||
|
||||
set -euo pipefail
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
LAWNCHAIR_ROOT="${LAWNCHAIR_ROOT:?LAWNCHAIR_ROOT not set}"
|
||||
GRADLE_TASK="${GRADLE_TASK:-assembleLawnWithQuickstepGithubRelease}"
|
||||
|
||||
log() { printf '\033[1;36m[build-prebuilt.sh]\033[0m %s\n' "$*"; }
|
||||
|
||||
cd "$LAWNCHAIR_ROOT"
|
||||
|
||||
if [ -f ./aosp-bridge.state ]; then
|
||||
log "Leftover AOSP-bridge artifacts detected — restoring vendored originals first"
|
||||
"$SCRIPT_DIR/aosp-bridge/gen-aidl-sourceset.sh" --restore || true
|
||||
"$SCRIPT_DIR/aosp-bridge/gen-framework-jars.sh" --restore || true
|
||||
rm -f ./aosp-bridge.state
|
||||
fi
|
||||
|
||||
log "Running ./gradlew $GRADLE_TASK"
|
||||
./gradlew "$GRADLE_TASK"
|
||||
|
||||
log "Done. APK(s):"
|
||||
find . -path '*/outputs/apk/*' -name '*.apk' -newer ./gradlew 2>/dev/null | head -5
|
||||
@@ -0,0 +1,95 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# build.sh — PawletOS Lawnchair build dispatcher
|
||||
#
|
||||
# Usage:
|
||||
# ./build.sh prebuilt # known-good flow: plain Gradle, vendored AIDL + stub jars
|
||||
# ./build.sh aosp # build against a local AOSP checkout (requires one on THIS machine)
|
||||
# ./build.sh aosp --skip-jars # AIDL swap only, keep Lawnchair's vendored framework-16.jar
|
||||
# ./build.sh aosp --wmshell # also swap WindowManager-Shell-16.jar (heavier, see README)
|
||||
# ./build.sh aosp --clean # restore originals first, then re-apply swaps and build
|
||||
# ./build.sh restore # undo all AOSP-bridge changes, back to pristine prebuilt state
|
||||
# ./build.sh clone # clone the Lawnchair repo next to this folder if missing
|
||||
#
|
||||
# Env vars:
|
||||
# AOSP_ROOT AOSP checkout root. If unset, auto-detected (including the
|
||||
# case where this repo is checked out inside the AOSP tree at
|
||||
# external/build-tools/lawnchair/build).
|
||||
# LAWNCHAIR_ROOT Lawnchair checkout. If unset, first existing of
|
||||
# ../source (in-tree manifest layout) or ../lawnchair
|
||||
# (PawletOS Windows working-copy layout).
|
||||
# GRADLE_TASK Gradle task (default: assembleLawnWithQuickstepGithubRelease)
|
||||
|
||||
set -euo pipefail
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
MODE="${1:-}"
|
||||
shift || true
|
||||
|
||||
if [ -z "${LAWNCHAIR_ROOT:-}" ]; then
|
||||
if [ -d "$SCRIPT_DIR/../source" ]; then
|
||||
LAWNCHAIR_ROOT="$SCRIPT_DIR/../source"
|
||||
else
|
||||
LAWNCHAIR_ROOT="$SCRIPT_DIR/../lawnchair"
|
||||
fi
|
||||
fi
|
||||
export LAWNCHAIR_ROOT
|
||||
export GRADLE_TASK="${GRADLE_TASK:-assembleLawnWithQuickstepGithubRelease}"
|
||||
|
||||
LAWNCHAIR_REMOTE="https://git.oxmc.me/PawletOS/Lawnchair"
|
||||
LAWNCHAIR_BRANCH="16-dev"
|
||||
|
||||
log() { printf '\033[1;36m[build.sh]\033[0m %s\n' "$*"; }
|
||||
die() { printf '\033[1;31m[build.sh]\033[0m %s\n' "$*" >&2; exit 1; }
|
||||
|
||||
# Find an AOSP build environment on this machine. AOSP mode only works where
|
||||
# the tree (and ideally its build output) actually lives — on any other
|
||||
# machine we error out rather than half-work. When this repo is checked out
|
||||
# in-tree (external/build-tools/lawnchair/build), the tree root is 4 levels up.
|
||||
detect_aosp_root() {
|
||||
local candidates=(
|
||||
"${AOSP_ROOT:-}"
|
||||
"$SCRIPT_DIR/../../../.."
|
||||
"$HOME/PawletOS-Build/AOSP-Source"
|
||||
"/mnt/ssd/AOSP-Source"
|
||||
)
|
||||
for c in "${candidates[@]}"; do
|
||||
[ -n "$c" ] && [ -f "$c/build/envsetup.sh" ] && { cd "$c" && pwd; return 0; }
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
case "$MODE" in
|
||||
aosp)
|
||||
AOSP_ROOT="$(detect_aosp_root)" || die \
|
||||
"No AOSP build environment found on this machine.
|
||||
Checked: \$AOSP_ROOT, 4 dirs above this script (in-tree checkout),
|
||||
~/PawletOS-Build/AOSP-Source, /mnt/ssd/AOSP-Source.
|
||||
AOSP mode must run where the PawletOS AOSP tree lives (ubuntu-server-01);
|
||||
use './build.sh prebuilt' for a purely local build."
|
||||
export AOSP_ROOT
|
||||
[ -d "$LAWNCHAIR_ROOT" ] || die "Lawnchair checkout not found at $LAWNCHAIR_ROOT — run './build.sh clone' or set LAWNCHAIR_ROOT"
|
||||
log "AOSP env: $AOSP_ROOT"
|
||||
exec "$SCRIPT_DIR/build-aosp.sh" "$@"
|
||||
;;
|
||||
prebuilt)
|
||||
[ -d "$LAWNCHAIR_ROOT" ] || die "Lawnchair checkout not found at $LAWNCHAIR_ROOT — run './build.sh clone' or set LAWNCHAIR_ROOT"
|
||||
log "Prebuilt mode: vendored AIDL + stub jars (no AOSP checkout needed)"
|
||||
exec "$SCRIPT_DIR/build-prebuilt.sh" "$@"
|
||||
;;
|
||||
restore)
|
||||
[ -d "$LAWNCHAIR_ROOT" ] || die "Lawnchair checkout not found at $LAWNCHAIR_ROOT"
|
||||
"$SCRIPT_DIR/aosp-bridge/gen-aidl-sourceset.sh" --restore
|
||||
"$SCRIPT_DIR/aosp-bridge/gen-framework-jars.sh" --restore
|
||||
rm -f "$LAWNCHAIR_ROOT/aosp-bridge.state"
|
||||
log "All AOSP-bridge changes restored."
|
||||
;;
|
||||
clone)
|
||||
[ -d "$LAWNCHAIR_ROOT" ] && die "Lawnchair already exists at $LAWNCHAIR_ROOT"
|
||||
log "Cloning $LAWNCHAIR_REMOTE ($LAWNCHAIR_BRANCH) -> $LAWNCHAIR_ROOT"
|
||||
git clone --branch "$LAWNCHAIR_BRANCH" "$LAWNCHAIR_REMOTE" "$LAWNCHAIR_ROOT"
|
||||
;;
|
||||
*)
|
||||
die "usage: $0 [aosp|prebuilt|restore|clone] [flags]"
|
||||
;;
|
||||
esac
|
||||
Reference in New Issue
Block a user