#!/usr/bin/env bash # Repeatable on-device smoke test for the ARM32-in-ARM64 prototype (see # /ARM64_TRANSLATION_LAYER.md). Replaces the manual adb-shell archaeology # this project's live debugging sessions have needed up to now: install, # launch, watch logcat for a bounded window, then report the same signals # those sessions kept hand-checking - onCreate timing, MEM FAULT count (see # guest_engine.cpp's mem_fault_hook_cb), and process-death cause (ANR / OOM / # MIUI SwipeUpClean / other) - as one command, so every future interface- # layer change gets checked against the same baseline instead of a fresh # investigation each time. # # Usage: mpcore/scripts/test_on_device.sh [device-serial] [watch-seconds] # device-serial defaults to the first device `adb devices` lists. # watch-seconds defaults to 180 (most observed onCreate runs finish in # 100-120s; this leaves headroom to also see the post-onCreate lifecycle # calls that previously kept faulting). set -uo pipefail # Script lives at mpcore/scripts/ - project root (where app/ and mpcore/ are # siblings) is two levels up. cd "$(dirname "$0")/../.." PKG="com.ea.games.nfs13_arm" ACTIVITY="com.ea.ironmonkey.GameActivityMain" # "translated" (the emulated arm64-v8a path) - see app/build.gradle.kts's # product flavors, added for the native ARM32 tracing investigation # (ARM64_TRANSLATION_LAYER.md). The pre-flavor-split path # (app/build/outputs/apk/debug/app-debug.apk) is now a STALE, never-updated # file left over from before that split - silently reinstalling it here # instead of the real current build wasted real debugging time confirming # this fix, so this path is now the single source of truth. APK="app/build/outputs/apk/translated/debug/app-translated-debug.apk" SERIAL="${1:-$(adb devices | awk 'NR==2{print $1}')}" WATCH_SECONDS="${2:-180}" if [[ -z "$SERIAL" ]]; then echo "No adb device found. Connect the device and retry." >&2 exit 1 fi ADB="adb -s $SERIAL" if [[ ! -f "$APK" ]]; then echo "APK not found at $APK - build it first (./gradlew :app:assembleDebug)." >&2 exit 1 fi echo "== Installing $APK on $SERIAL ==" $ADB install -r "$APK" || { echo "install failed" >&2; exit 1; } echo "== Launching ==" $ADB shell am force-stop "$PKG" $ADB logcat -c $ADB shell monkey -p "$PKG" -c android.intent.category.LAUNCHER 1 >/dev/null sleep 2 PID=$($ADB shell pidof "$PKG" | tr -d '\r') if [[ -z "$PID" ]]; then echo "Process did not start." >&2 exit 1 fi echo "pid=$PID" echo "== Watching logcat for ${WATCH_SECONDS}s ==" LOG="$(mktemp)" timeout "${WATCH_SECONDS}s" $ADB logcat --pid="$PID" > "$LOG" 2>/dev/null || true echo "" echo "===================== RESULTS =====================" ONCREATE_LINE=$(grep "GameActivityMain onCreate took" "$LOG" | tail -1) if [[ -n "$ONCREATE_LINE" ]]; then echo "onCreate: $(echo "$ONCREATE_LINE" | grep -oE '[0-9]+ms')" else echo "onCreate: did not complete within ${WATCH_SECONDS}s" fi FAULT_COUNT=$(grep -c "MEM FAULT" "$LOG" || true) echo "MEM FAULT lines: $FAULT_COUNT" if [[ "$FAULT_COUNT" -gt 0 ]]; then echo " first: $(grep "MEM FAULT" "$LOG" | head -1)" echo " last: $(grep "MEM FAULT" "$LOG" | tail -1)" fi CRASHED_LINE=$(grep -c "refusing to run - engine already crashed" "$LOG" || true) echo "engine crashed (fail-fast tripped): $([[ "$CRASHED_LINE" -gt 0 ]] && echo yes || echo no)" STILL_ALIVE=$($ADB shell "pidof $PKG" | tr -d '\r') if [[ -n "$STILL_ALIVE" ]]; then echo "process status: alive (pid=$STILL_ALIVE) at end of watch window" else echo "process status: DEAD" DEATH_LINE=$($ADB logcat -d 2>/dev/null | grep -E "Killing $PID:|$PID.*died->background" | tail -3) if [[ -n "$DEATH_LINE" ]]; then echo " cause:" echo "$DEATH_LINE" | sed 's/^/ /' else echo " cause: unknown (no ActivityManager kill/death line found - check for a FATAL crash instead)" $ADB logcat -d --pid="$PID" 2>/dev/null | grep -iE "FATAL|AndroidRuntime" | sed 's/^/ /' fi fi echo "=====================================================" echo "Full log: $LOG"