This repository has been archived on 2025-03-20. You can view files and clone it, but cannot push or open issues or pull requests.
The-Powder-Toy/android/debug.sh
Tamás Bálint Misius ee2e53958a
Make android/install-apk always stale
This effectively leaves the staleness checking to adb install, as it should be done: adb has insight into the state of the system, we don't. Newer versions of android can do incremental installs too, so reinstalling the same thing is essentially free.

Also invoke android/install-apk in the debug script to make sure that the app being debugged is up to date.
2024-01-12 20:11:03 +01:00

236 lines
5.9 KiB
Bash
Executable File

#!/usr/bin/env bash
# mainly based on https://www.sh-zam.com/2019/05/debugging-krita-on-android.html
set -euo pipefail
IFS=$'\n\t'
function get_buildoption() {
jq -r '.[] | select(.name == "'$1'") | .value' < meson-info/intro-buildoptions.json
}
# customize
default_app_id=uk.co.powdertoy.tpt
default_app_exe=powder
in_build_site=no
if which jq >/dev/null && [[ -f meson-info/intro-buildoptions.json ]]; then
# pwd is most likely a build site
in_build_site=yes
default_app_id=$(get_buildoption app_id)
default_app_exe=$(get_buildoption app_exe)
fi
app_id=${APP_ID:-$default_app_id}
app_exe=${APP_EXE:-$default_app_exe}
lldb_server=${LLDB_SERVER:-/opt/android-ndk/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/17/lib/linux/aarch64/lldb-server}
lldb_server_port=${LLDB_SERVER_PORT:-9998}
jdb_port=${JDB_PORT:-13456}
lldb_client=${LLDB_CLIENT:-/opt/android-ndk/toolchains/llvm/prebuilt/linux-x86_64/bin/lldb.sh}
adb=${ADB:-adb}
jdb=${JDB:-jdb}
# don't customize unless necessary
app_activity=${APP_ACTIVITY:-PowderActivity}
lldb_server_staging=${LLDB_SERVER_STAGING:-/data/local/tmp/lldb-server}
lldb_server_remote=${LLDB_SERVER_REMOTE:-lldb-server}
pidof_retry_count=${PIDOF_RETRY_COUNT:-20}
pidof_retry_delay=${PIDOF_RETRY_DELAY:-0.1}
function check_which() {
if ! which $1 >/dev/null; then
>&2 echo "[-] can't run $1"
return 1
fi
}
function check_env() {
if ! [[ -f $lldb_server ]]; then
>&2 echo "[-] $lldb_server doesn't exist"
return 1
fi
check_which $lldb_client
check_which $adb
check_which $jdb
}
function check_adb() {
$adb shell whoami >/dev/null
}
function maybe_install_app() {
if [[ $in_build_site != yes ]]; then
>&2 echo "[+] not in a build site, not adb installing anything"
return 0
fi
android_keystore=$(get_buildoption android_keystore)
android_keyalias=$(get_buildoption android_keyalias)
if [[ -z ${ANDROID_KEYSTORE_PASS-} ]]; then
>&2 cat << HELP
The current directory seems to be a build site, but ANDROID_KEYSTORE_PASS is not set, so android/$app_exe.apk cannot be invoked. If you don't have a keystore yet, create one with:
ANDROID_KEYSTORE_PASS=bagelsbagels keytool -genkey \\
-keystore $android_keystore \\
-alias $android_keyalias \\
-storepass:env ANDROID_KEYSTORE_PASS \\
-keypass:env ANDROID_KEYSTORE_PASS \\
-dname CN=bagels
Then try again with:
ANDROID_KEYSTORE_PASS=bagelsbagels $0
Naturally, replace bagelsbagels with an appropriate password.
HELP
exit 1
fi
>&2 echo "[+] adb installing android/$app_exe.apk"
if ! $adb install android/$app_exe.apk; then
>&2 echo "[-] failed"
return 1
fi
}
function check_debuggable() {
$adb shell run-as $app_id whoami >/dev/null
}
function find_lldb_server() {
$adb shell run-as $app_id pgrep $lldb_server_remote >/dev/null
}
function kill_lldb_server() {
if ! $adb shell run-as $app_id pkill $lldb_server_remote; then
>&2 echo "[-] failed"
return 1
fi
}
function adb_forward() {
>&2 echo "[+] adb forwarding tcp:$jdb_port jdwp:$pid"
if ! ($adb forward tcp:$jdb_port jdwp:$pid | grep $jdb_port >/dev/null); then
>&2 echo "[+] failed"
return 1
fi
}
function adb_unforward() {
$adb forward --remove tcp:$jdb_port
}
function undo_current_adb_forward() {
>&2 echo "[+] adb un-forwarding orphaned tcp:$jdb_port"
adb_unforward
}
function maybe_undo_previous_adb_forward() {
if $adb forward --list | grep tcp:$jdb_port; then
>&2 echo "[+] adb un-forwarding orphaned tcp:$jdb_port"
adb_unforward
fi
}
function maybe_kill_previous_lldb_server() {
if find_lldb_server; then
>&2 echo "[+] killing orphaned $lldb_server_remote"
kill_lldb_server
fi
}
function kill_current_lldb_server() {
>&2 echo "[+] killing $lldb_server_remote"
kill_lldb_server
}
function start_app() {
>&2 echo "[+] starting $app_id/.$app_activity"
set +e
$adb shell am start -D -n "$app_id/.$app_activity" >/dev/null
set -e
local i
local maybe_pid
local pidof_result
for ((i = 0; i <= $pidof_retry_count; i++)); do
set +e
maybe_pid=$($adb shell pidof $app_id)
pidof_result=$?
set -e
if [[ $pidof_result == 0 ]]; then
pid=$maybe_pid
break
fi
sleep $pidof_retry_delay
done
if [[ -z ${pid-} ]]; then
>&2 echo "[-] failed"
return 1
fi
echo $pid
}
function jdb_attach() {
>&2 echo "[+] attaching jdb in the background"
$jdb -attach localhost:$jdb_port >/dev/null 2>/dev/null &
disown $!
# at some point jdb exits because it doesn't have an stdin... fine by me
}
function maybe_deploy_lldb_server() {
if ! $adb shell [[ -f $lldb_server_staging ]]; then
>&2 echo "[+] $lldb_server_remote not present on host, deploying"
if ! ($adb push $lldb_server $lldb_server_staging && $adb shell chmod +x $lldb_server_staging); then
>&2 echo "[-] failed"
fi
fi
}
function start_lldb_server() {
if ! $adb shell run-as $app_id pgrep $lldb_server_remote >/dev/null; then
>&2 echo "[+] $lldb_server_remote not running on host, starting"
$adb shell run-as $app_id cp $lldb_server_staging /data/data/$app_id/$lldb_server_remote
$adb shell run-as $app_id ./$lldb_server_remote platform --server --listen "*:$lldb_server_port" >/dev/null 2>/dev/null &
disown $!
if ! $adb shell run-as $app_id pgrep $lldb_server_remote >/dev/null; then
>&2 echo "[-] failed"
return 1
fi
fi
}
function start_lldb() {
local pid=$1
>&2 echo "[+] starting $lldb_client"
local lldb_init=$(mktemp)
cat - << LLDB_INIT > $lldb_init
platform select remote-android
platform connect connect://localhost:$lldb_server_port
attach $pid
continue
LLDB_INIT
local lldb_status
set +e
$lldb_client --source $lldb_init
lldb_status=$?
set -e
>&2 echo "[+] $lldb_client exited with status $lldb_status"
rm $lldb_init
}
check_env
check_adb
maybe_install_app
check_debuggable
maybe_kill_previous_lldb_server
maybe_undo_previous_adb_forward
if [[ ${1-} == clean ]]; then
>&2 echo "[+] done"
exit 0
fi
maybe_deploy_lldb_server
start_lldb_server
pid=$(start_app)
adb_forward
jdb_attach
start_lldb $pid
kill_current_lldb_server
undo_current_adb_forward
>&2 echo "[+] done"