mirror of
https://github.com/Droid-Deck/DroidDeck.git
synced 2026-11-11 02:51:10 +00:00
* chore(i18n): translate every missing string in all locales Adds the 87 strings the bottom-screen Dashboard and in-game stats pages introduced to all 32 locales, plus the 51 older settings strings Japanese and the 50 Chinese locales were still missing. Every locale now has all 3456 translatable strings with the same placeholders as English. Also translates 36 entries that were still English where the language does not use the English word, and makes es-419 touch_app_id use the same %1$s placeholder as English. * chore(patches): drop comments from the lines downstream patches add Removes comment lines and trailing comments from lines our patches add, with hunk headers recounted. Lines that a later patch uses as context and the upstream backport 0123 are left as they are. The gamescope, FEX, proot and xodus series still apply to their pinned sources, and the patched trees differ only in those comments. test_hud_frames now finds the HUD writer by its first declaration. * docs: credit Greenlight, Better xCloud, viture-v2, GameNative and DiRTTelemetryErrorFix These were credited only in source headers and NOTICE files. * chore: remove source comments and unused functions Removes explanatory comments from first-party Kotlin, Java, C, C++, Rust, TypeScript, Python, shell, Gradle, CMake and workflow files. License and attribution headers stay, and vendored third-party trees, generated files and license files are untouched. A shellcheck directive is kept, and udevmon's fallthrough comments became fallthrough attributes. Syntax trees and token streams match the previous sources apart from the comments and Python docstrings. Module docstrings that argparse prints are kept, and device-smoke.sh prints the same --help text from a heredoc. Also removes 37 functions and 4 fields that nothing referenced. * chore: remove comments from the Syncthing integration and the latest main sources * docs: credit Syncthing and the syncthing-android fork * chore(i18n): translate the Syncthing strings in all locales The 107 strings the Syncthing integration added are now in all 32 locales. sync_web_path_locked names the Syncthing tab by its label. * docs: credit @xXJSONDeruloXx for the HUD metric readers The CPU, GPU load, thermal and battery readers come from their PerformanceHudView pull requests #777, #877, #991, #1406 and #1573. The FusionHUD credit line is unchanged. * docs: credit the HUD metric readers to @xXJSONDeruloXx's work
302 lines
12 KiB
Bash
Executable File
302 lines
12 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -u
|
|
export MSYS_NO_PATHCONV=1 MSYS2_ARG_CONV_EXCL='*'
|
|
|
|
usage() {
|
|
cat <<'EOF'
|
|
Smoke test of a DroidDeck build on a real device, over plain adb (no python, no root).
|
|
|
|
What it does, in order, and restores afterwards:
|
|
1. prints the device (model, Android, kernel, page size, SoC);
|
|
2. installs --apk when given and launches the app;
|
|
3. checks that the app starts and that nothing in the crash buffer belongs to it;
|
|
4. changes the display density and the window size and checks the app keeps its process
|
|
(and does not recreate the activity that is on top);
|
|
5. on a foldable cycles the device state (half-opened, and with --closed also closed) through
|
|
`cmd device_state`, then puts the original state back;
|
|
6. reads the newest session folder of a debug build: first frame, last frame rate, the
|
|
memory page size, the proot that session ran, and the last process exits.
|
|
|
|
Usage: tools/device-smoke.sh [--serial SERIAL] [--apk FILE] [--pkg PACKAGE]
|
|
[--no-density] [--no-size] [--no-fold] [--closed]
|
|
Exit status: 0 when no check failed, 1 when one did, 2 for a usage or device problem.
|
|
|
|
Not a replacement for tools/droiddeck-scenario, which drives a game through the agent bridge;
|
|
this covers what that does not: display changes and foldable states.
|
|
EOF
|
|
}
|
|
|
|
pkg=com.droiddeck.launcher
|
|
serial=${ANDROID_SERIAL:-}
|
|
apk=
|
|
do_density=1
|
|
do_size=1
|
|
do_fold=1
|
|
do_closed=0
|
|
adb_bin=${ADB:-adb}
|
|
|
|
while [ $# -gt 0 ]; do
|
|
case $1 in
|
|
--serial) [ $# -ge 2 ] || { echo "--serial needs a value" >&2; exit 2; }; serial=$2; shift ;;
|
|
--apk) [ $# -ge 2 ] || { echo "--apk needs a value" >&2; exit 2; }; apk=$2; shift ;;
|
|
--pkg) [ $# -ge 2 ] || { echo "--pkg needs a value" >&2; exit 2; }; pkg=$2; shift ;;
|
|
--no-density) do_density=0 ;;
|
|
--no-size) do_size=0 ;;
|
|
--no-fold) do_fold=0 ;;
|
|
--closed) do_closed=1 ;;
|
|
-h|--help) usage; exit 0 ;;
|
|
*) echo "unknown option: $1" >&2; exit 2 ;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
adb_cmd=("$adb_bin")
|
|
[ -n "$serial" ] && adb_cmd+=(-s "$serial")
|
|
A() {
|
|
local out rc
|
|
out=$("${adb_cmd[@]}" "$@" 2>&1); rc=$?
|
|
[ -z "$out" ] || printf '%s\n' "$out" | tr -d '\r'
|
|
return $rc
|
|
}
|
|
sh_() {
|
|
local command= arg
|
|
for arg in "$@"; do command+="'${arg//\'/\'\\\'\'}' "; done
|
|
A shell "$command"
|
|
}
|
|
|
|
pass=0 fail=0 skip=0
|
|
ok() { echo " PASS $*"; pass=$((pass + 1)); }
|
|
bad() { echo " FAIL $*"; fail=$((fail + 1)); }
|
|
note() { echo " SKIP $*"; skip=$((skip + 1)); }
|
|
head_() { printf '\n== %s\n' "$*"; }
|
|
|
|
state=$(A get-state)
|
|
if [ "$state" != "device" ]; then
|
|
echo "no authorized device (adb get-state: $state)" >&2
|
|
exit 2
|
|
fi
|
|
|
|
density_snapshot=$(sh_ wm density) || density_snapshot=
|
|
size_snapshot=$(sh_ wm size) || size_snapshot=
|
|
orig_density=$(echo "$density_snapshot" | sed -n 's/.*Physical density: \([0-9]*\).*/\1/p' | head -1)
|
|
override_density=$(echo "$density_snapshot" | sed -n 's/.*Override density: \([0-9]*\).*/\1/p' | head -1)
|
|
override_size=$(echo "$size_snapshot" | sed -n 's/.*Override size: \([0-9]*x[0-9]*\).*/\1/p' | head -1)
|
|
ds=$(sh_ cmd device_state state 2>/dev/null)
|
|
orig_state=$(echo "$ds" | sed -n "s/.*Committed state: DeviceState{identifier=\([0-9]*\),.*/\1/p" | head -1)
|
|
pre_override=$(echo "$ds" | sed -n "s/.*Override state: DeviceState{identifier=\([0-9]*\),.*/\1/p" | head -1)
|
|
|
|
density_changed=0 size_changed=0 fold_changed=0
|
|
wm_override() { sed -n "s/.*Override $1: \\([0-9x]*\\).*/\\1/p" | head -1; }
|
|
restore_density() {
|
|
sh_ wm density "${override_density:-reset}" >/dev/null || return 1
|
|
local current
|
|
current=$(sh_ wm density) || return 1
|
|
echo "$current" | grep -q 'Physical density:' || return 1
|
|
[ "$(echo "$current" | wm_override density)" = "$override_density" ]
|
|
}
|
|
restore_size() {
|
|
sh_ wm size "${override_size:-reset}" >/dev/null || return 1
|
|
local current
|
|
current=$(sh_ wm size) || return 1
|
|
echo "$current" | grep -q 'Physical size:' || return 1
|
|
[ "$(echo "$current" | wm_override size)" = "$override_size" ]
|
|
}
|
|
restore_fold() { if [ -n "$pre_override" ]; then sh_ cmd device_state state "$pre_override" >/dev/null; else sh_ cmd device_state state reset >/dev/null; fi; }
|
|
|
|
restore() {
|
|
local failed=0
|
|
if [ "$density_changed" = 1 ]; then
|
|
if restore_density; then density_changed=0; else bad "could not restore display density"; failed=1; fi
|
|
fi
|
|
if [ "$size_changed" = 1 ]; then
|
|
if restore_size; then size_changed=0; else bad "could not restore window size"; failed=1; fi
|
|
fi
|
|
if [ "$fold_changed" = 1 ]; then
|
|
if restore_fold; then fold_changed=0; else bad "could not restore fold override"; failed=1; fi
|
|
fi
|
|
return "$failed"
|
|
}
|
|
finish() {
|
|
local status=$?
|
|
restore || status=1
|
|
printf '\n%d passed, %d failed, %d skipped\n' "$pass" "$fail" "$skip"
|
|
[ "$fail" = 0 ] || status=1
|
|
exit "$status"
|
|
}
|
|
trap finish EXIT
|
|
trap 'exit 130' INT
|
|
trap 'exit 143' TERM
|
|
|
|
top_activity() {
|
|
sh_ dumpsys activity activities 2>/dev/null | sed -n 's/.*topResumedActivity=ActivityRecord{[^ ]* u[0-9]* \([^ ]*\) .*/\1/p' | head -1
|
|
}
|
|
app_pid() { sh_ pidof "$pkg" | awk '{print $1}'; }
|
|
app_crashes() {
|
|
local out pat
|
|
out=$(sh_ logcat -b crash -d) || return 1
|
|
pat=$(printf '%s' "$pkg" | sed 's/[.[\*^$]/\\&/g')
|
|
printf '%s\n' "$out" | grep -c -E "(Process: |Cmdline: |>>> )$pat([ ,<:]|$)" || true
|
|
}
|
|
relaunches_of() {
|
|
sh_ logcat -b events -d 2>/dev/null | grep -E 'wm_(relaunch|destroy|create)_activity' | grep -c "$1"
|
|
}
|
|
|
|
head_ "Device"
|
|
echo " model $(sh_ getprop ro.product.manufacturer) $(sh_ getprop ro.product.model)"
|
|
echo " android $(sh_ getprop ro.build.version.release) (API $(sh_ getprop ro.build.version.sdk)), One UI $(sh_ getprop ro.build.version.oneui)"
|
|
echo " kernel $(sh_ uname -r)"
|
|
page=$(sh_ getconf PAGE_SIZE)
|
|
echo " page size $page"
|
|
echo " soc $(sh_ getprop ro.soc.manufacturer) $(sh_ getprop ro.soc.model) ($(sh_ getprop ro.board.platform))"
|
|
echo " gpu $(sh_ cat /sys/class/kgsl/kgsl-3d0/gpu_model 2>/dev/null)"
|
|
echo " display $(sh_ wm size | tr '\n' ' ') $(sh_ wm density | tr '\n' ' ')"
|
|
[ "$page" = 4096 ] || [ "$page" = 16384 ] && ok "page size is $page" || bad "page size reads '$page'"
|
|
|
|
head_ "Install and launch"
|
|
sh_ logcat -b crash -c >/dev/null
|
|
sh_ logcat -b events -c >/dev/null
|
|
if [ -n "$apk" ]; then
|
|
r=$(A install -r -t "$apk" | tail -1)
|
|
case $r in *Success*) ok "installed $(basename "$apk")" ;; *) bad "install: $r"; exit 1 ;; esac
|
|
fi
|
|
packages=$(sh_ pm list packages "$pkg") || { echo "could not query installed packages" >&2; exit 2; }
|
|
if ! printf '%s\n' "$packages" | grep -Fxq "package:$pkg"; then echo "package $pkg is not installed" >&2; exit 2; fi
|
|
if ! launch=$(sh_ am start -n "$pkg/.MainActivity") || printf '%s\n' "$launch" | grep -q '^Error'; then
|
|
bad "could not launch $pkg/.MainActivity"
|
|
fi
|
|
sleep 6
|
|
pid=$(app_pid)
|
|
[ -n "$pid" ] && ok "process running (pid $pid)" || bad "the app has no process after launch"
|
|
t=$(top_activity)
|
|
case $t in
|
|
"$pkg"/*|*permissioncontroller*|*GrantPermissions*) ok "top activity: $t" ;;
|
|
*) bad "top activity is '$t'" ;;
|
|
esac
|
|
if c=$(app_crashes); then
|
|
[ "${c:-0}" = 0 ] && ok "nothing in the crash buffer belongs to the app" || bad "$c crash entries mention the app"
|
|
else
|
|
bad "could not read the crash buffer"
|
|
fi
|
|
|
|
if [ "$do_density" = 1 ] && [ -n "$orig_density" ]; then
|
|
head_ "Density change"
|
|
target=$((orig_density * 5 / 4))
|
|
before=$(top_activity); pid0=$(app_pid)
|
|
sh_ logcat -b events -c >/dev/null
|
|
density_changed=1
|
|
wm_status=0
|
|
sh_ wm density "$target" >/dev/null || wm_status=$?
|
|
sleep 6
|
|
applied=$(sh_ wm density) || wm_status=1
|
|
after=$(top_activity); pid1=$(app_pid)
|
|
if [ "$wm_status" -ne 0 ] || [ "$(echo "$applied" | wm_override density)" != "$target" ]; then
|
|
bad "wm density failed"
|
|
else
|
|
if [ -n "$pid1" ] && [ "$pid0" = "$pid1" ]; then
|
|
ok "same process after $orig_density -> $target dpi"
|
|
else
|
|
bad "process changed ($pid0 -> $pid1)"
|
|
fi
|
|
case $before in "$pkg"/*)
|
|
n=$(relaunches_of "${before#*/}")
|
|
[ "${n:-0}" = 0 ] && ok "$before was not recreated" || bad "$before was recreated ${n}x"
|
|
[ "$after" = "$before" ] && ok "same top activity after the change" || bad "top activity changed ($before -> $after)"
|
|
;; *) note "top activity was not the app ($before)" ;; esac
|
|
fi
|
|
if restore_density; then
|
|
density_changed=0
|
|
else
|
|
bad "could not restore display density"
|
|
fi
|
|
sleep 3
|
|
elif [ "$do_density" = 1 ]; then
|
|
note "could not read the original display density"
|
|
fi
|
|
|
|
if [ "$do_size" = 1 ]; then
|
|
head_ "Window size change"
|
|
phys=$(echo "$size_snapshot" | sed -n 's/.*Physical size: \([0-9]*\)x\([0-9]*\).*/\1 \2/p' | head -1)
|
|
set -- $phys
|
|
if [ -n "${1:-}" ]; then
|
|
w=$(( ($2 * 2 / 3) / 2 * 2 )); h=$1
|
|
pid0=$(app_pid)
|
|
size_changed=1
|
|
wm_status=0
|
|
sh_ wm size "${w}x${h}" >/dev/null || wm_status=$?
|
|
sleep 6
|
|
applied=$(sh_ wm size) || wm_status=1
|
|
pid1=$(app_pid)
|
|
if [ "$wm_status" -ne 0 ] || [ "$(echo "$applied" | wm_override size)" != "${w}x${h}" ]; then
|
|
bad "wm size failed"
|
|
elif [ -n "$pid1" ] && [ "$pid0" = "$pid1" ]; then
|
|
ok "same process at ${w}x${h}"
|
|
else
|
|
bad "process changed ($pid0 -> $pid1)"
|
|
fi
|
|
if restore_size; then
|
|
size_changed=0
|
|
else
|
|
bad "could not restore window size"
|
|
fi
|
|
sleep 3
|
|
else
|
|
note "could not read the physical size"
|
|
fi
|
|
fi
|
|
|
|
if [ "$do_fold" = 1 ]; then
|
|
head_ "Foldable states"
|
|
states=$(sh_ cmd device_state print-states 2>/dev/null)
|
|
if ! echo "$states" | grep -q "identifier"; then
|
|
note "no device_state service (not a foldable, or not permitted)"
|
|
elif [ -z "$orig_state" ]; then
|
|
note "could not read the current device_state identifier"
|
|
else
|
|
id_of() { echo "$states" | sed -n "s/.*identifier=\([0-9]*\), name='$1'.*/\1/p" | head -1; }
|
|
half=$(id_of HALF_OPENED); closed=$(id_of CLOSED)
|
|
cycle() {
|
|
pid0=$(app_pid)
|
|
fold_changed=1
|
|
sh_ cmd device_state state "$2" >/dev/null; sleep 8
|
|
got=$(sh_ cmd device_state state | sed -n "s/.*Committed state: DeviceState{identifier=[0-9]*, name='\([A-Z_]*\)'.*/\1/p" | head -1)
|
|
pid1=$(app_pid)
|
|
[ "$got" = "$1" ] && ok "device state is $1" || note "asked for $1, committed '$got'"
|
|
[ -n "$pid1" ] && [ "$pid0" = "$pid1" ] && ok "same process in $1" || bad "process changed in $1 ($pid0 -> $pid1)"
|
|
restore_fold; sleep 6
|
|
}
|
|
if [ -n "$half" ]; then cycle HALF_OPENED "$half"; else note "no HALF_OPENED state"; fi
|
|
if [ "$do_closed" = 1 ] && [ -n "$closed" ]; then
|
|
cycle CLOSED "$closed"
|
|
note "CLOSED turns the screens off: the session pauses (Background behaviour), Resume it from the app"
|
|
fi
|
|
got=$(sh_ cmd device_state state | sed -n "s/.*Committed state: DeviceState{identifier=\([0-9]*\),.*/\1/p" | head -1)
|
|
[ "$got" = "$orig_state" ] && ok "device state restored ($orig_state)" || bad "device state is $got, was $orig_state"
|
|
fi
|
|
fi
|
|
|
|
head_ "Session log (debug builds)"
|
|
dir=$(sh_ run-as "$pkg" ls -t files/logs 2>/dev/null | head -1)
|
|
if [ -z "$dir" ] || echo "$dir" | grep -q -i "not debuggable\|unknown package"; then
|
|
note "no readable session folder (release build, or no session has run)"
|
|
else
|
|
echo " newest session $dir"
|
|
ev=$(sh_ run-as "$pkg" cat "files/logs/$dir/events.jsonl" 2>/dev/null)
|
|
echo "$ev" | grep -q '"frame.first"' && ok "first frame was drawn" || note "no frame.first in $dir"
|
|
echo "$ev" | grep -q '"session.failed"' && bad "session.failed: $(echo "$ev" | grep '"session.failed"' | tail -1 | cut -c1-160)"
|
|
report=$(sh_ run-as "$pkg" cat "files/logs/$dir/device.txt" 2>/dev/null)
|
|
proot_line=$(echo "$report" | grep 'proot binary' | head -1)
|
|
case $proot_line in
|
|
*"rootfs fallback"*|*"missing"*) bad "session proot is not the patched binary ($proot_line)" ;;
|
|
*"apk"*|*"add-on pack"*) ok "patched proot ($proot_line)" ;;
|
|
*) note "device report has no proot binary line (build from before the check)" ;;
|
|
esac
|
|
app_log=$(sh_ run-as "$pkg" cat "files/logs/$dir/app.log" 2>/dev/null)
|
|
echo "$app_log" | grep -Fq 'proot: fast path on (' && ok "proot fast path was on" \
|
|
|| note "proot fast path activation was not recorded ($(echo "$report" | grep 'proot fast path' | tr '\n' '; '))"
|
|
fps=$(sh_ run-as "$pkg" cat "files/logs/$dir/app.log" 2>/dev/null | grep 'last 10 s:' | tail -1 | sed 's/.*last 10 s: //' | cut -c1-70)
|
|
[ -n "$fps" ] && echo " last stats $fps"
|
|
sh_ run-as "$pkg" cat "files/logs/$dir/device.txt" 2>/dev/null | grep -E 'Memory page size|^Kernel' | sed 's/^/ report /'
|
|
fi
|
|
|
|
[ "$fail" = 0 ]
|