Files
linux-on-android-without-root/provision/provision.sh
T
StefanandClaude Opus 5 410cf01973 adb gezielt auswählen statt der PATH-Reihenfolge zu vertrauen
Debians Paket android-tools-adb liefert Version 29 und kennt kein 'adb pair' —
das kam erst mit platform-tools 30. Wer beides installiert hat, bekommt je nach
PATH-Reihenfolge und Alter der Terminalsitzung mal das eine und mal das andere,
und die WLAN-Kopplung scheitert scheinbar grundlos.

provision/lib.sh sucht deshalb gezielt eine Fassung, die 'pair' beherrscht, und
schiebt eine Shell-Funktion 'adb' davor, sodass die Aufrufstellen unverändert
bleiben. Eine ausdrücklich gesetzte Vorgabe ADB= gilt absolut, auch wenn sie
kein pair kann — stillschweigend etwas anderes zu nehmen wäre die unangenehmere
Überraschung. Fehlt pair, läuft provision.sh mit einer Warnung weiter (für USB
reicht es), adb-wireless.sh bricht sauber ab.

Die Prüfung kommt bewusst ohne Pipe aus: 'adb pair' ohne Argumente endet mit
Code 1, weil es ein Aufruffehler ist. Unter 'set -o pipefail' hätte das die
gesamte Pipeline als fehlgeschlagen gelten lassen, obwohl grep den Hilfetext
gefunden hatte — die Erkennung meldete dadurch selbst adb 36 als zu alt.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-09 17:53:41 +02:00

241 lines
10 KiB
Bash
Executable File

#!/usr/bin/env bash
# HPOS — Ersteinrichtung vom PC aus, per ADB.
#
# ADB wird ausschließlich hier gebraucht, einmalig. Im Dauerbetrieb kommt das
# System mit gewöhnlichen App-Berechtigungen aus — das ist eine harte Regel des
# Projekts, siehe CONTRIBUTING.md.
#
# Voraussetzung: Entwickleroptionen aktiv. Die Verbindung geht per USB-Kabel ODER
# per WLAN (Android 11 und neuer) — das Skript fragt danach, wenn kein Gerät da ist.
#
# Aufruf: ./provision/provision.sh [--dry-run]
set -uo pipefail
TERMUX=com.termux
TROCKEN=0
[ "${1:-}" = "--dry-run" ] && TROCKEN=1
source "$(dirname "$0")/lib.sh"
# Wählt eine adb-Fassung aus, statt sich auf die Reihenfolge in PATH zu verlassen:
# Debians Paket ist Version 29 und kennt kein 'adb pair'. Rückgabewert 2 heißt
# "gefunden, aber zu alt für WLAN" — für USB reicht es trotzdem.
ADB_KANN_WLAN=1
adb_einrichten || ADB_KANN_WLAN=0
# Führt ein adb-Kommando aus und meldet das Ergebnis, ohne bei Fehlschlag
# abzubrechen: Hersteller-ROMs kennen nicht jedes appops-Ziel, und ein fehlendes
# ist kein Grund, die restliche Einrichtung liegen zu lassen.
adbs() {
local beschreibung="$1"; shift
if [ "$TROCKEN" = 1 ]; then
printf '%s ? %s%s (adb shell %s)\n' "$C_DIM" "$beschreibung" "$C_OFF" "$*"
return 0
fi
local aus
if aus=$(adb shell "$@" 2>&1); then
if printf '%s' "$aus" | grep -qiE 'error|exception|denied|unknown'; then
warn "$beschreibung — ROM hat abgelehnt"
hinweis "$(printf '%s' "$aus" | head -1)"
return 1
fi
ok "$beschreibung"
return 0
fi
warn "$beschreibung — fehlgeschlagen"
hinweis "$(printf '%s' "$aus" | head -1)"
return 1
}
# ── Gerät ────────────────────────────────────────────────────────────────────
kopf "Gerät"
hinweis "adb $(adb_version "$ADB_BIN")$ADB_BIN"
HIER="$(cd "$(dirname "$0")" && pwd)"
ANZAHL=$(adb devices | grep -cw 'device$' || true)
# Ohne Gerät nicht einfach abbrechen: der häufigste Fall ist, dass gar kein Kabel
# zur Hand ist. Android 11+ kann Wireless Debugging, das reicht für alles hier.
if [ "$ANZAHL" -eq 0 ]; then
warn "Kein Gerät verbunden."
if [ ! -t 0 ]; then
hinweis "Keine Eingabe möglich — bitte erst ./provision/adb-wireless.sh ausführen."
exit 1
fi
cat <<'TEXT'
Wie soll verbunden werden?
[u] USB-Kabel
Entwickleroptionen und USB-Debugging aktiv, Dialog "Diesem Computer
vertrauen" auf dem Telefon bestätigt.
[w] WLAN, ohne Kabel (Android 11 und neuer)
Einmalige Kopplung per sechsstelligem Code. Danach läuft alles
über das Netz — ein Kabel wird nie gebraucht.
[a] Abbrechen
TEXT
[ "$ADB_KANN_WLAN" = 0 ] && warn "Achtung: das gefundene adb kann kein WLAN — [w] wird scheitern."
printf '\n Auswahl > '
read -r WAHL </dev/tty
case "$WAHL" in
w|W)
if [ ! -x "$HIER/adb-wireless.sh" ]; then
fehl "adb-wireless.sh nicht gefunden neben diesem Skript."
exit 1
fi
"$HIER/adb-wireless.sh" || exit 1
ANZAHL=$(adb devices | grep -cw 'device$' || true)
;;
u|U)
printf ' Kabel anschließen und Enter drücken > '
read -r _ </dev/tty
adb wait-for-device &
WARTE=$!
# Nicht ewig hängen bleiben, falls das Kabel nur lädt und keine Daten überträgt.
( sleep 60; kill "$WARTE" 2>/dev/null ) >/dev/null 2>&1 &
wait "$WARTE" 2>/dev/null
ANZAHL=$(adb devices | grep -cw 'device$' || true)
;;
*)
hinweis "Abgebrochen."
exit 0
;;
esac
if [ "$ANZAHL" -eq 0 ]; then
fehl "Es ist weiterhin kein Gerät verbunden."
adb devices | sed 's/^/ /'
hinweis "Steht dort 'unauthorized', den Dialog auf dem Telefon bestätigen."
exit 1
fi
ok "Gerät verbunden"
elif [ "$ANZAHL" -gt 1 ]; then
fehl "Mehrere Geräte verbunden — bitte nur eines aktiv lassen."
adb devices | sed 's/^/ /'
hinweis "Überzählige trennen, per WLAN verbundene mit: adb disconnect <ip:port>"
exit 1
fi
for p in ro.product.manufacturer ro.product.model ro.product.device \
ro.build.version.release ro.board.platform; do
printf ' %-28s %s\n' "$p" "$(adb shell getprop "$p" 2>/dev/null | tr -d '\r')"
done
[ "$TROCKEN" = 1 ] && warn "Trockenlauf — es wird nichts verändert."
# ── Termux vorhanden? ────────────────────────────────────────────────────────
kopf "Termux"
if adb shell pm list packages 2>/dev/null | tr -d '\r' | grep -q "^package:$TERMUX$"; then
ok "$TERMUX ist installiert"
else
fehl "$TERMUX ist nicht installiert."
hinweis "Termux von F-Droid oder GitHub installieren, dann dieses Skript erneut laufen lassen."
hinweis "Nicht aus dem Play Store — die dortige Fassung ist veraltet und unbrauchbar."
exit 1
fi
# ── Hintergrundbetrieb, Android-Standardebene ────────────────────────────────
# Der Punkt, an dem das Konzept in der Praxis scheitern kann. Diese Maßnahmen
# überleben Neustarts. Die Entwickleroptionen helfen hier NICHT — sie betreffen
# nur gecachte Prozesse, nicht Vordergrunddienste.
kopf "Hintergrundbetrieb (Android-Standardebene)"
adbs "Aus der Doze-Beschränkung ausgenommen" dumpsys deviceidle whitelist "+$TERMUX"
adbs "RUN_IN_BACKGROUND erlaubt" cmd appops set "$TERMUX" RUN_IN_BACKGROUND allow
adbs "RUN_ANY_IN_BACKGROUND erlaubt" cmd appops set "$TERMUX" RUN_ANY_IN_BACKGROUND allow
adbs "Standby-Bucket auf 'never' gesetzt" am set-standby-bucket "$TERMUX" never
adbs "Adaptive Akkunutzung abgeschaltet" settings put global adaptive_battery_management_enabled 0
adbs "Akku-Optimierung ignoriert" cmd appops set "$TERMUX" REQUEST_IGNORE_BATTERY_OPTIMIZATIONS allow
# Die Zusatz-APKs, sofern schon installiert. Fehlen sie, ist das hier kein Problem.
for extra in com.termux.api com.termux.x11 com.termux.boot; do
if adb shell pm list packages 2>/dev/null | tr -d '\r' | grep -q "^package:$extra$"; then
adbs " $extra aus der Doze-Beschränkung" dumpsys deviceidle whitelist "+$extra"
adbs " $extra darf im Hintergrund laufen" cmd appops set "$extra" RUN_ANY_IN_BACKGROUND allow
fi
done
# ── Berechtigungen ───────────────────────────────────────────────────────────
kopf "Berechtigungen"
for perm in \
android.permission.RECORD_AUDIO \
android.permission.CAMERA \
android.permission.ACCESS_FINE_LOCATION \
android.permission.READ_EXTERNAL_STORAGE \
android.permission.WRITE_EXTERNAL_STORAGE
do
adbs "$(basename "${perm//./\/}") für Termux:API" pm grant com.termux.api "$perm" 2>/dev/null || true
done
hinweis "Fehlschläge sind normal, solange Termux:API noch nicht installiert ist."
# ── Was ADB nicht kann ───────────────────────────────────────────────────────
kopf "Von Hand zu erledigen"
HERSTELLER=$(adb shell getprop ro.product.manufacturer 2>/dev/null | tr -d '\r')
cat <<TEXT
Die folgenden Punkte liegen unterhalb der Android-Mechanismen und sind per
ADB nicht zuverlässig erreichbar. Ohne sie beendet das ROM den Stack über Nacht.
1. Einstellungen → Apps → Termux → Akku → "Nicht optimieren"
2. Einstellungen → Akku → "Sleep Standby Optimization" ausschalten
3. Einstellungen → Akku → adaptive Akkunutzung ausschalten
4. Termux im Task-Manager anpinnen (Schloss-Symbol)
5. Für Overlay-Begleit-Apps: "Über anderen Apps anzeigen" erlauben
TEXT
case "$HERSTELLER" in
[Oo]ne[Pp]lus|OPPO|oppo|realme)
printf '\n%s Zu deinem Gerät:%s\n' "$C_WARN" "$C_OFF"
hinweis "OxygenOS/ColorOS friert Apps besonders aggressiv ein."
hinweis "Zusätzlich unter Einstellungen → Akku → Akkuoptimierung die"
hinweis "erweiterte bzw. 'intelligente' Optimierung für Termux abschalten."
;;
[Xx]iaomi|[Rr]edmi|[Pp]oco|samsung|Samsung)
printf '\n%s Zu deinem Gerät:%s\n' "$C_WARN" "$C_OFF"
hinweis "Dieser Hersteller ist für aggressives Beenden bekannt."
hinweis "Zusätzlich Autostart erlauben und die App von der Speicherbereinigung ausnehmen."
;;
esac
# ── Repo aufs Telefon ────────────────────────────────────────────────────────
# adb push funktioniert auch über WLAN. Das erspart es, auf dem Telefon Zugangsdaten
# für ein privates Repo eintippen zu müssen — auf einer Bildschirmtastatur eine Qual.
kopf "Skripte aufs Telefon"
REPO_ROOT="$(cd "$HIER/.." && pwd)"
ZIEL=/sdcard/hpos
if [ "$TROCKEN" = 1 ]; then
warn "Trockenlauf — es wird nichts übertragen."
else
printf ' Die Spike-Skripte jetzt nach %s übertragen? [J/n] > ' "$ZIEL"
read -r UEBERTRAGEN </dev/tty || UEBERTRAGEN=n
case "${UEBERTRAGEN:-j}" in
j|J|"")
adb shell rm -rf "$ZIEL" >/dev/null 2>&1
if adb push "$REPO_ROOT" "$ZIEL" >/dev/null 2>&1; then
ok "Übertragen nach $ZIEL"
hinweis "In Termux nach ~ kopieren, damit die Dateien ausführbar sein können:"
hinweis " cp -r /sdcard/hpos ~/hpos && cd ~/hpos"
hinweis "(auf /sdcard gibt es keine Ausführungsrechte — das ist normal)"
else
warn "Übertragung fehlgeschlagen — dann per git clone auf dem Telefon."
fi
;;
*) hinweis "Übersprungen." ;;
esac
fi
kopf "Fertig"
cat <<TEXT
Nächste Schritte auf dem Telefon, in Termux:
cp -r /sdcard/hpos ~/hpos && cd ~/hpos # falls oben übertragen
# oder: pkg install -y git && git clone <repo-url> hpos && cd hpos
bash spike/00-bootstrap-termux.sh
Danach die Beweise der Reihe nach — S1 zuerst, weil er der wackligste ist.
Ergebnisse gehören nach docs/spike-protokoll.md.
Nicht vergessen: die oben genannten Handgriffe von Hand erledigen.
Ohne sie beendet das ROM den Stack über Nacht.
TEXT