Files
SoulStream/handoff/rounds/ins-r47-verify-ground.txt
T
KeelrLeek 9f0601027c android: the handoff — the pending rounds, the pipeline, and what is unverified
Everything written this session that has not been through the device: rounds 43
to 48 (each patch adversarially verified, 43's transient-notice expectation
fixed), a partial round 49, the pipeline scripts, the Android Auto design and
the icon comparison mock. Also the two harness changes that were never A/B'd —
adaptive waits, which may only shorten a declared wait and never lengthen it,
and a ship that runs the mock walk and the deploy at the same time. The A/B and
its 255-step baseline are in handoff/tools; main stays at what the phone has
actually walked.
2026-09-14 07:57:41 -05:00

72 lines
4.9 KiB
Plaintext

# aapt2 is beside the zipalign and apksigner build.sh has just used. Found
# here rather than in the release branch below, because both build types want
# it now: only the resource table can say what <background> resolves to.
SDKU=""
[ -n "${ANDROID_HOME:-}" ] && SDKU="$(cygpath -u "$ANDROID_HOME" 2>/dev/null || echo "")"
[ -z "$SDKU" ] && [ -n "${LOCALAPPDATA:-}" ] && SDKU="$(cygpath -u "$LOCALAPPDATA" 2>/dev/null || echo "")/Android/Sdk"
A2="$(ls -1 "$SDKU"/build-tools/*/aapt2.exe 2>/dev/null | sort -V | tail -1 || true)"
# 2. the ground, in BOTH build types. Not "is the file in the APK" — the
# adaptive icon's <background> is a REFERENCE, so what matters is what it
# resolves to, and that is the one question a stale APK answers wrongly
# while every other check still passes. (build.sh pipes Gradle through
# `| tail -20 || true` and then runs `ls -la "$APK"`, so a Gradle run that
# failed leaves the PREVIOUS build's APK exactly where the next step looks
# for it.) Everything below comes out of the resource table and never out
# of a path: a release APK has had res/mipmap-anydpi-v26/ic_launcher.xml
# renamed to res/BW.xml, and the table is the only thing that still knows.
TBL=""
[ -n "$A2" ] && { TBL="$("$A2" dump resources "$APK" 2>/dev/null)" || bad "aapt2 could not read the resource table of $APK"; }
# name [config] -> the file that resource points at. The config is not
# optional detail: mipmap/ic_launcher has SIX entries — the anydpi adaptive
# XML and five legacy PNGs — so a name-only lookup hands back
# res/mipmap-mdpi-v4/ic_launcher.png and the whole check collapses. An empty
# config means the entry with no qualifier at all, which is what a plain
# drawable has. "anydpi" matches the "anydpi-v26" too, as look() does.
path_of() { echo "$TBL" | awk -v n="$1" -v c="${2:-}" '
$1 == "resource" && $3 == n { f = 1; next }
/^[ \t]*resource 0x/ { f = 0 }
f { cfg = $1; gsub(/[()]/, "", cfg)
if (c == "" || cfg == c || cfg ~ "^" c "-v[0-9]+$")
for (i = 1; i <= NF; i++) if ($i ~ /^res\//) { print $i; exit } }'; }
name_of() { echo "$TBL" | awk -v id="$1" '$1 == "resource" && $2 == id { print $3; exit }'; }
if [ -z "$TBL" ]; then
echo "== ground: NOT CHECKED — no aapt2 under ${SDKU:-(no SDK path)}/build-tools."
echo " What <background> points at is a resource id; only the table reads it."
elif echo "$TBL" | grep -q "0_resource_name_obfuscated"; then
echo "== ground: NOT CHECKED — this APK's resource names are collapsed."
else
ADAPT="$(path_of mipmap/ic_launcher anydpi)"
test -n "$ADAPT" || bad "mipmap/ic_launcher has no anydpi entry in this APK — the adaptive icon is not in it, so $RES never reached src-tauri/gen/android/app/src/main/res"
BGID="$("$A2" dump xmltree "$APK" --file "$ADAPT" 2>/dev/null \
| awk '/E: background/ { f = 1 } f && /android:drawable\(/ { sub(/.*=@?/, ""); print; exit }')"
test -n "$BGID" || bad "the adaptive icon in this APK ($ADAPT) declares no <background>"
BGNAME="$(name_of "$BGID")"
[ "$BGNAME" = "drawable/ic_launcher_ground" ] \
|| bad "the APK's adaptive background is ${BGNAME:-$BGID}, not drawable/ic_launcher_ground — a stale APK, or the overlay did not reach src-tauri/gen/android/app/src/main/res"
# and that what it resolves to is still concept 04 rather than a flat
# fill. aapt:attr lifts each inline <gradient> out into a resource of its
# own, so the two fills are references as well; follow the ids rather than
# the $name__N filenames aapt2 happens to give them this version.
GPATH="$(path_of drawable/ic_launcher_ground)"
test -n "$GPATH" || bad "drawable/ic_launcher_ground resolves to no file in this APK"
GTREE="$("$A2" dump xmltree "$APK" --file "$GPATH" 2>/dev/null)" || bad "aapt2 cannot read $GPATH out of this APK"
IDS="$(echo "$GTREE" | grep -oE 'fillColor\(0x[0-9a-f]+\)=@0x[0-9a-f]+' | grep -oE '0x[0-9a-f]+$')"
NFILL="$(echo "$IDS" | grep -c . || true)"
[ "$NFILL" = 2 ] || bad "the ground in this APK has $NFILL gradient fills, not 2 — concept 04 is a surface and the glow over it"
STOPS=""
for id in $IDS; do
g="$(path_of "$(name_of "$id")")"
test -n "$g" || bad "the ground's gradient $id has no file in the resource table"
STOPS="$STOPS $("$A2" dump xmltree "$APK" --file "$g" | grep -oE 'color\(0x[0-9a-f]+\)=#[0-9a-f]{8}' | grep -oE '[0-9a-f]{8}$' | tr '\n' ' ')"
done
for c in ff0a2330 ff07141f ff040a10 2e31c0cb 0d1f8fc9 0007141f; do
echo "$STOPS" | grep -qw "$c" || bad "the ground in this APK has lost concept 04's stop #$c"
done
echo "== ground: <background> = $BGNAME, concept 04's six stops, read back out of the APK"
fi
# What none of this can see is a pixel. Whether the gradient BANDS on the
# phone's OLED, how the glow reads under the Pixel's mask and how the falcon
# sits on a lit ground rather than a flat one are a launcher screenshot, not a
# resource table.