mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-08 20:28:32 +09:00
- bench.sh and session.sh are invoked as ./tools/device_bench/bench.sh in their own README and are the harness for the paired two-device A/B the GO/NO-GO asks for; a previous commit in this package dropped the bit and every check invoked them through bash, so nothing saw it
142 lines
6.5 KiB
Bash
Executable File
142 lines
6.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Launch the game into the benchmark world and leave it running (for profiling
|
|
# or ad-hoc probing). Handles the flaky-launch failure mode seen on Odin Lite:
|
|
# the JVM occasionally dies with "exited due to signal 34" right after
|
|
# JLI_Launch (~40% of launches, cause unknown) — so launching retries up to
|
|
# --retries times before giving up.
|
|
#
|
|
# Usage: session.sh --device devices/odinlite.env [--backend magma|espryt|mobileglues]
|
|
# [--settle 150] [--retries 3] [--no-pin]
|
|
# [--allow-unverified-profile]
|
|
# Exits 0 with the game in-world (after settle seconds), 1 otherwise.
|
|
# NOTE: leaves the game running AND the frequency pins active (that is the
|
|
# point of a session). When done: am force-stop the game and unpin via
|
|
# `echo <cluster> -1 > /proc/ppm/policy/hard_userlimit_{min,max}_cpu_freq`
|
|
# and `echo 0 > /proc/gpufreq/gpufreq_opp_freq` (or run a bench.sh, whose
|
|
# cleanup unpins).
|
|
|
|
set -u -o pipefail
|
|
# Remembered BEFORE the cd, so a --device path written relative to the caller's directory still
|
|
# resolves instead of being reported as an unverified profile (see bench.sh).
|
|
INVOKED_FROM=$PWD
|
|
cd "$(dirname "$0")"
|
|
export MSYS_NO_PATHCONV=1 MSYS2_ARG_CONV_EXCL='*'
|
|
|
|
PKG=com.tungsten.fcl.mgdebug.debug
|
|
ACTIVITY=$PKG/com.tungsten.fcl.activity.SplashActivity
|
|
RENDERER_ESPRYT=5e273ee2-baca-4c81-8e48-b63feefb9ba8
|
|
RENDERER_MAGMA=2be0dc10-1eef-4ce2-b512-b266dd33fd9e
|
|
RENDERER_MOBILEGLUES=com.fcl.plugin.mobileglues
|
|
|
|
DEVICE_ENV="" BACKEND="" SETTLE=150 RETRIES=3 DO_PIN=1 ALLOW_UNVERIFIED_PROFILE=0
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
--device) DEVICE_ENV=$2; shift 2 ;;
|
|
--backend) BACKEND=$2; shift 2 ;;
|
|
--settle) SETTLE=$2; shift 2 ;;
|
|
--retries) RETRIES=$2; shift 2 ;;
|
|
--no-pin) DO_PIN=0; shift ;;
|
|
--allow-unverified-profile) ALLOW_UNVERIFIED_PROFILE=1; shift ;;
|
|
*) echo "unknown arg: $1" >&2; exit 2 ;;
|
|
esac
|
|
done
|
|
[ -n "$DEVICE_ENV" ] || { echo "need --device" >&2; exit 2; }
|
|
case "$DEVICE_ENV" in
|
|
/*) ;;
|
|
*) [ -r "$DEVICE_ENV" ] || [ ! -r "$INVOKED_FROM/$DEVICE_ENV" ] || DEVICE_ENV="$INVOKED_FROM/$DEVICE_ENV" ;;
|
|
esac
|
|
[ -r "$DEVICE_ENV" ] || {
|
|
echo "cannot read the device profile: $DEVICE_ENV" >&2
|
|
echo "(tried it relative to $(pwd) and to $INVOKED_FROM)" >&2
|
|
exit 2
|
|
}
|
|
# The profile, and ONLY the profile, gets to say whether it has been verified: reset before the
|
|
# source, so an exported PROFILE_VERIFIED=1 cannot answer for a profile that says nothing.
|
|
PROFILE_VERIFIED=0
|
|
# shellcheck disable=SC1090
|
|
. "$DEVICE_ENV"
|
|
|
|
# A device profile that has not been read off its device yet is refused here rather than acted
|
|
# on. The failure it prevents is silent and expensive: the pin path below is MediaTek-specific
|
|
# (/proc/ppm, /proc/gpufreq), `su -c 'echo ... > /proc/...'` fails without a non-zero exit, and a
|
|
# run against a profile whose nodes do not exist reports numbers it believes were taken under a
|
|
# frequency pin. The pin-integrity fields sampled at window end are the only clue, and they are
|
|
# read after the run rather than before it.
|
|
#
|
|
# PROFILE_VERIFIED=1 means: somebody read the cpufreq policies, the GPU OPP and the thermal zone
|
|
# TYPE off THIS device, ran one pinned window, and checked big_cur/little_cur/gpu_cur_khz in the
|
|
# result JSON against the pins. Nothing else earns it.
|
|
require_verified_profile() {
|
|
# The default is UNVERIFIED. A profile that simply omits the key is a profile nobody has
|
|
# confirmed against its device, and defaulting it to "verified" would hand exactly the
|
|
# fail-open behaviour this guard exists to prevent to the most likely way a new profile is
|
|
# written - by copying an existing one and editing the serial. The variable is reset to 0
|
|
# immediately before the profile is sourced, so this test reads the FILE and not the shell.
|
|
if [ "${PROFILE_VERIFIED:-0}" = "1" ]; then return 0; fi
|
|
if [ "$ALLOW_UNVERIFIED_PROFILE" = "1" ]; then
|
|
echo "[warn] $DEVICE_ENV does not carry PROFILE_VERIFIED=1 and --allow-unverified-profile was passed:" >&2
|
|
echo "[warn] the frequency pins and the thermal gate in it are UNCONFIRMED, so any number this" >&2
|
|
echo "[warn] run produces is not comparable with a pinned one." >&2
|
|
return 0
|
|
fi
|
|
echo "$DEVICE_ENV does not carry PROFILE_VERIFIED=1 (it says 0, or says nothing at all): its" >&2
|
|
echo "sysfs nodes and OPPs have not been read off the device, so pinning would fail silently" >&2
|
|
echo "and the run would look pinned but not be." >&2
|
|
echo "Fill in the TODO_VERIFY_ON_DEVICE fields, confirm one pinned window, set PROFILE_VERIFIED=1 -" >&2
|
|
echo "or pass --allow-unverified-profile to measure anyway and label the result unpinned." >&2
|
|
exit 2
|
|
}
|
|
require_verified_profile
|
|
ADB="adb -s $DEVICE_SERIAL"
|
|
log() { echo "[session] $*" >&2; }
|
|
|
|
if [ -n "$BACKEND" ]; then
|
|
case "$BACKEND" in
|
|
espryt) RENDERER=$RENDERER_ESPRYT ;;
|
|
magma) RENDERER=$RENDERER_MAGMA ;;
|
|
mobileglues) RENDERER=$RENDERER_MOBILEGLUES ;;
|
|
*) echo "unknown backend: $BACKEND" >&2; exit 2 ;;
|
|
esac
|
|
for known in $RENDERER_ESPRYT $RENDERER_MAGMA $RENDERER_MOBILEGLUES; do
|
|
[ "$known" = "$RENDERER" ] && continue
|
|
$ADB shell run-as $PKG sed -i "s/$known/$RENDERER/g" files/config.json
|
|
done
|
|
fi
|
|
|
|
$ADB shell "input keyevent KEYCODE_WAKEUP; sleep 1; input keyevent 82; svc power stayon true; settings put global fan_mode 3"
|
|
if [ "$DO_PIN" = 1 ]; then
|
|
$ADB shell "su -c 'echo 1 $CPU_BIG_FREQ > /proc/ppm/policy/hard_userlimit_max_cpu_freq;
|
|
echo 1 $CPU_BIG_FREQ > /proc/ppm/policy/hard_userlimit_min_cpu_freq;
|
|
echo 0 $CPU_LITTLE_FREQ > /proc/ppm/policy/hard_userlimit_max_cpu_freq;
|
|
echo 0 $CPU_LITTLE_FREQ > /proc/ppm/policy/hard_userlimit_min_cpu_freq;
|
|
echo $GPU_PIN_KHZ > /proc/gpufreq/gpufreq_opp_freq'"
|
|
fi
|
|
|
|
MCLOG=/storage/emulated/0/FCL/.minecraft/versions/1.21.4/logs/latest.log
|
|
for attempt in $(seq 1 "$RETRIES"); do
|
|
$ADB shell am force-stop $PKG
|
|
sleep 5
|
|
$ADB shell "rm -f $MCLOG"
|
|
$ADB shell am start -n $ACTIVITY >/dev/null
|
|
log "attempt $attempt: launched"
|
|
DEADLINE=$((SECONDS + 300))
|
|
while [ $SECONDS -lt $DEADLINE ]; do
|
|
sleep 5
|
|
if $ADB shell "grep -q 'joined the game' $MCLOG" 2>/dev/null; then
|
|
log "world up (attempt $attempt); settling ${SETTLE}s"
|
|
sleep "$SETTLE"
|
|
exit 0
|
|
fi
|
|
if ! $ADB shell pidof $PKG >/dev/null; then
|
|
# process may still be between splash and JVM start briefly; confirm twice
|
|
sleep 3
|
|
if ! $ADB shell pidof $PKG >/dev/null; then
|
|
log "attempt $attempt: process died (signal-34 flake?); retrying"
|
|
break
|
|
fi
|
|
fi
|
|
done
|
|
done
|
|
log "no world after $RETRIES attempts"
|
|
exit 1
|