Something went wrong. Try again.
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182#!/usr/bin/env bash# Host-only tests for launcher-apply.sh and launcher-restore.sh against a fake adb that keeps# package and Home state in files. Not device evidence.set -euo pipefailroot=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)tmp=$(mktemp -d)trap 'rm -rf -- "$tmp"' EXITmkdir "$tmp/bin" "$tmp/state"export ADB_LOG="$tmp/adb.log" FAKE_STATE="$tmp/state" FAKE_MODE=okcat > "$tmp/bin/adb" <<'FAKE'#!/usr/bin/env bashset -euo pipefailprintf '%s\n' "$*" >> "$ADB_LOG"launcherx=com.google.android.apps.tv.launcherxsetupwraith=com.google.android.tungsten.setupwraithapp=dev.hzz.streamer.debuginstalled=(android com.android.tv.settings "$launcherx" "$setupwraith" com.google.android.gms)[[ "$FAKE_MODE" == noapp ]] || installed+=("$app")disabled() { grep -Fxq "$1" "$FAKE_STATE/disabled"; }installed() { printf '%s\n' "${installed[@]}" | grep -Fxq "$1"; }# Home candidates, highest priority first.candidates=("$launcherx/.home.HomeActivity" "$setupwraith/.RecoveryActivity")[[ "$FAKE_MODE" == noapp || "$FAKE_MODE" == nohome ]] || candidates+=("$app/tv.streamer.app.home.HomeActivity")candidates+=(com.android.tv.settings/.system.FallbackHome)home_query='-a android.intent.action.MAIN -c android.intent.category.HOME'case "$*" in get-state) [[ "$FAKE_MODE" != offline ]] || { echo 'error: no devices/emulators found' >&2; exit 1; } echo device ;; 'shell pm list packages --user 0') for p in "${installed[@]}"; do printf 'package:%s\r\n' "$p"; done ;; 'shell pm list packages -e --user 0') for p in "${installed[@]}"; do disabled "$p" || printf 'package:%s\r\n' "$p"; done ;; "shell cmd package query-activities --brief --user 0 $home_query") # Shaped like the device's output (docs/spikes/launcher.md "Dry runs over the bridge"): # a count line, then per activity a two-space header and four-space detail lines. enabled=() for c in "${candidates[@]}"; do disabled "${c%%/*}" || enabled+=("$c"); done printf '%s activities found:\r\n' "${#enabled[@]}" i=0 for c in "${enabled[@]}"; do printf ' Activity #%s:\r\n priority=0 preferredOrder=0 match=0x108000 specificIndex=-1 isDefault=true\r\n %s\r\n' "$i" "$c" i=$((i + 1)) done ;; "shell cmd package resolve-activity --brief --user 0 $home_query") home=$(cat "$FAKE_STATE/home") for c in "${candidates[@]}"; do if [[ "${c%%/*}" == "$home" ]] && ! disabled "$home"; then printf 'priority=0 preferredOrder=0 match=0x108000 specificIndex=-1 isDefault=true\r\n%s\r\n' "$c"; exit fi done for c in "${candidates[@]}"; do disabled "${c%%/*}" || { printf 'priority=0 preferredOrder=0 match=0x108000 specificIndex=-1 isDefault=true\r\n%s\r\n' "$c"; exit; } done ;; 'shell cmd package set-home-activity --user 0 '*) args="$*"; package=${args##* } # Like the real command: an error is printed with a zero exit code. if installed "$package" && ! disabled "$package" \ && printf '%s\n' "${candidates[@]}" | grep -q "^$package/"; then echo "$package" > "$FAKE_STATE/home"; echo Success else echo 'Error: Failed to set default home.' fi ;; 'shell pm disable-user --user 0 '*) args="$*"; package=${args##* } [[ "$FAKE_MODE" != failsetup || "$package" != "$setupwraith" ]] \ || { echo "Error: java.lang.SecurityException: Cannot disable $package"; exit 0; } installed "$package" || { echo "Error: Unknown package: $package"; exit 0; } disabled "$package" || echo "$package" >> "$FAKE_STATE/disabled" echo "Package $package new state: disabled-user" ;; 'shell pm enable --user 0 '*) args="$*"; package=${args##* } installed "$package" || { echo "Error: Unknown package: $package"; exit 0; } grep -Fxv "$package" "$FAKE_STATE/disabled" > "$FAKE_STATE/disabled.new" || true mv "$FAKE_STATE/disabled.new" "$FAKE_STATE/disabled" echo "Package $package new state: enabled" ;; *) echo "FORBIDDEN adb command: $*" >&2; exit 99 ;;esacFAKEchmod +x "$tmp/bin/adb"export PATH="$tmp/bin:$PATH"apply="$root/scripts/launcher-apply.sh"restore="$root/scripts/launcher-restore.sh"launcherx=com.google.android.apps.tv.launcherxsetupwraith=com.google.android.tungsten.setupwraith
reset_device() { : > "$FAKE_STATE/disabled" echo "$launcherx" > "$FAKE_STATE/home" rm -f -- "$ADB_LOG"}snapshot() { cat "$FAKE_STATE/disabled" "$FAKE_STATE/home"; }expect_failure() { if bash "$@" > "$tmp/stdout" 2> "$tmp/stderr"; then echo "Expected failure: $*" >&2; exit 1 fi}mutating='set-home-activity|disable-user|pm enable|uninstall|install|reboot|role'# `! grep` does not stop a set -e script, so a match has to exit explicitly.no_changes_logged() { if grep -Eq "$mutating" "$ADB_LOG"; then echo 'unexpected changing adb command' >&2; exit 1; fi}home_now() { "$tmp/bin/adb" shell cmd package resolve-activity --brief --user 0 -a android.intent.action.MAIN -c android.intent.category.HOME | tr -d '\r' | tail -n 1; }
# Unknown, partial, duplicate or malformed package names are refused before adb runs.reset_deviceexpect_failure "$apply" com.google.android.katnissexpect_failure "$apply" "$launcherx"expect_failure "$apply" "$launcherx" "$launcherx"expect_failure "$apply" "$launcherx" "$setupwraith" com.google.android.videosexpect_failure "$apply" "$launcherx" 'evil;reboot'expect_failure "$apply" --app 'evil;reboot'expect_failure "$apply" --app "$launcherx"expect_failure "$apply" --unknownexpect_failure "$restore" --unknown[[ ! -e "$ADB_LOG" ]]expect_failure "$apply" com.google.android.katnissgrep -q 'refusing unknown stock package' "$tmp/stderr"
# Dry run, the default, changes nothing and runs no changing command.reset_devicebefore=$(snapshot)bash "$apply" > "$tmp/stdout"bash "$apply" --dry-run "$setupwraith" "$launcherx" >> "$tmp/stdout"bash "$restore" --dry-run >> "$tmp/stdout"[[ "$(snapshot)" == "$before" ]]no_changes_loggedgrep -q '^DRY RUN' "$tmp/stdout"grep -Fq 'Restore: ADB=adb bash scripts/launcher-restore.sh' "$tmp/stdout"
# Refusals on the device side change nothing.for mode in offline noapp nohome; do reset_device export FAKE_MODE=$mode expect_failure "$apply" --apply [[ "$(snapshot)" == "$before" ]] if [[ -e "$ADB_LOG" ]]; then no_changes_logged; fidoneexport FAKE_MODE=ok
# Apply sets Home first, then disables the two packages one at a time, with times.reset_devicebash "$apply" --apply > "$tmp/stdout"[[ "$(home_now)" == dev.hzz.streamer.debug/* ]][[ "$(sort "$FAKE_STATE/disabled")" == "$(printf '%s\n' "$launcherx" "$setupwraith")" ]]grep -En 'set-home-activity|disable-user' "$ADB_LOG" > "$tmp/order"[[ $(wc -l < "$tmp/order") == 3 ]]sed -n 1p "$tmp/order" | grep -q 'set-home-activity --user 0 dev.hzz.streamer.debug'grep -Eq '^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9:]{8}Z disable-user done: Package com.google.android.tungsten.setupwraith new state: disabled-user$' "$tmp/stdout"grep -q '^APPLIED' "$tmp/stdout"grep -Fq 'Restore: ADB=adb bash scripts/launcher-restore.sh' "$tmp/stdout"
# Restore undoes apply: both packages enabled and Google TV answers Home.bash "$restore" > "$tmp/stdout"[[ "$(snapshot)" == "$before" ]][[ "$(home_now)" == "$launcherx/.home.HomeActivity" ]]grep -q '^RESTORED' "$tmp/stdout"# Google TV is chosen as Home only after it is enabled again.grep -En "pm enable --user 0 $launcherx|set-home-activity --user 0 $launcherx" "$ADB_LOG" | cut -d: -f1 > "$tmp/lines"[[ $(wc -l < "$tmp/lines") == 2 && $(sed -n 1p "$tmp/lines") -lt $(sed -n 2p "$tmp/lines") ]]
# A failure part-way through apply stops, says so, and names the restore command.reset_deviceexport FAKE_MODE=failsetupexpect_failure "$apply" --applygrep -q 'APPLY FAILED' "$tmp/stderr"grep -Fq 'launcher-restore.sh' "$tmp/stderr"export FAKE_MODE=okbash "$restore" > /dev/null[[ "$(snapshot)" == "$before" ]]
# Restore is safe to run when nothing was changed, and ADB may be a multi-word command.reset_deviceprintf '#!/usr/bin/env bash\nshift\nexec "$@"\n' > "$tmp/bin/wrapper"chmod +x "$tmp/bin/wrapper"ADB="wrapper box adb" bash "$restore" > "$tmp/stdout"[[ "$(snapshot)" == "$before" ]]# An offline device makes restore fail loudly rather than claim success.export FAKE_MODE=offlineexpect_failure "$restore"echo 'PASS: launcher apply and restore tests (fake adb only)'