Das Repo ist anonym lesbar; Zugangsdaten braucht nur der Push, und der findet auf dem PC statt. Stand der Benutzername trotzdem in der URL, fragte git auf dem Telefon nach einem Passwort — auf einer Bildschirmtastatur eine unnötige Quälerei für einen Zugriff, der gar keine Anmeldung erfordert. provision.sh entfernt ihn beim Einsetzen der Adresse, init-phone.sh zusätzlich beim Ausführen — so ist auch eine von Hand übergebene Adresse abgedeckt. Die Ersetzung greift nur bei http(s); SSH-Adressen bleiben unberührt, dort ist git@ zwingend. Damit entfällt auch das Angebot, Zugangsdaten auf dem Telefon zu speichern. Der credential.helper wird dort stattdessen ausdrücklich geleert: das Telefon liest nur und soll nie versehentlich zurückschreiben wollen. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
338 lines
14 KiB
Bash
Executable File
338 lines
14 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"
|
|
fi
|
|
|
|
# Mehrere Geräte sind kein Fehler, sondern der Normalfall beim Gerätewechsel:
|
|
# altes und neues Telefon müssen gleichzeitig erreichbar sein. Statt abzubrechen
|
|
# wird gefragt — und die Auswahl gilt danach für ALLE folgenden Befehle, weil die
|
|
# adb-Hülle in lib.sh selbsttätig -s ergänzt.
|
|
if ! geraet_waehlen; then
|
|
fehl "Es ist kein Gerät verbunden."
|
|
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
|
|
hinweis "Ziel: ${ADB_SERIAL:-(einziges Gerät)}"
|
|
[ "$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."
|
|
cat <<'TEXT'
|
|
|
|
Termux muss zuerst aufs Telefon. WICHTIG: nicht aus dem Play Store — die
|
|
Fassung dort ist seit Jahren nicht mehr gepflegt und für dieses Projekt
|
|
unbrauchbar. Alle Bestandteile müssen aus derselben Quelle stammen, sonst
|
|
passen die Signaturen nicht zusammen und die Zusatz-Apps verweigern den Dienst.
|
|
|
|
Empfohlen — F-Droid:
|
|
Termux https://f-droid.org/packages/com.termux/
|
|
Termux:API https://f-droid.org/packages/com.termux.api/
|
|
Termux:Boot https://f-droid.org/packages/com.termux.boot/
|
|
|
|
Oder direkt von GitHub:
|
|
Termux https://github.com/termux/termux-app/releases/latest
|
|
Termux:API https://github.com/termux/termux-api/releases/latest
|
|
Termux:Boot https://github.com/termux/termux-boot/releases/latest
|
|
|
|
Termux:X11 gibt es nur bei GitHub (Nightly, app-universal-debug.apk):
|
|
https://github.com/termux/termux-x11/releases
|
|
|
|
Auf dem Telefon einfach im Browser öffnen und die APK installieren.
|
|
"Installation aus unbekannten Quellen" muss für den Browser erlaubt sein.
|
|
TEXT
|
|
if [ "$TROCKEN" != 1 ] && [ -x "$HIER/install-termux.sh" ]; then
|
|
cat <<'TEXT'
|
|
|
|
Das muss aber niemand von Hand machen: install-termux.sh lädt alle vier
|
|
Apps von GitHub und installiert sie über die bestehende adb-Verbindung —
|
|
per WLAN genauso wie per Kabel.
|
|
TEXT
|
|
printf '\n Jetzt automatisch installieren? [J/n] > '
|
|
read -r AUTOINSTALL </dev/tty || AUTOINSTALL=n
|
|
case "${AUTOINSTALL:-j}" in
|
|
j|J|"")
|
|
if ADB_SERIAL="$ADB_SERIAL" "$HIER/install-termux.sh"; then
|
|
ok "Termux ist installiert — weiter mit der Einrichtung."
|
|
hinweis "Bitte Termux einmal öffnen, damit es sein Dateisystem anlegt."
|
|
printf ' Wenn das erledigt ist, Enter drücken > '
|
|
read -r _ </dev/tty
|
|
else
|
|
fehl "Automatische Installation fehlgeschlagen."
|
|
exit 1
|
|
fi
|
|
;;
|
|
*)
|
|
hinweis "Dann von Hand — danach dieses Skript erneut aufrufen."
|
|
exit 1
|
|
;;
|
|
esac
|
|
else
|
|
printf '\n'
|
|
hinweis "Danach dieses Skript erneut aufrufen."
|
|
exit 1
|
|
fi
|
|
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"
|
|
# Termux selbst braucht RECORD_AUDIO und Speicherzugriff — nicht nur Termux:API.
|
|
# PulseAudio läuft IM Termux-Prozess und öffnet das Mikrofon über OpenSL ES von
|
|
# dort aus. Eine Berechtigung, die nur Termux:API hat, nützt ihm nichts: das
|
|
# Modul lädt dann zwar, liefert aber keinen brauchbaren Ton.
|
|
for perm in \
|
|
android.permission.RECORD_AUDIO \
|
|
android.permission.READ_EXTERNAL_STORAGE \
|
|
android.permission.WRITE_EXTERNAL_STORAGE
|
|
do
|
|
adbs "${perm##*.} für Termux" pm grant "$TERMUX" "$perm" 2>/dev/null || true
|
|
done
|
|
|
|
# Termux:API bedient Kamera, Sensoren, Standort und Taschenlampe.
|
|
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 "${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."
|
|
hinweis "Eine App, die eine Berechtigung gar nicht anmeldet, lässt sich nicht beschenken."
|
|
|
|
# ── 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
|
|
|
|
# ── Startskript aufs Telefon ─────────────────────────────────────────────────
|
|
# Bewusst NUR dieses eine Skript, nicht das ganze Repo. Es installiert git und
|
|
# klont die Quellen — danach ist auf dem Telefon eine Arbeitskopie, keine Kopie.
|
|
# Aktualisieren heißt dann 'git pull' statt jedes Mal wieder den PC anzuwerfen.
|
|
kopf "Startskript aufs Telefon"
|
|
REPO_ROOT="$(cd "$HIER/.." && pwd)"
|
|
REPO_URL="$(git -C "$REPO_ROOT" remote get-url origin 2>/dev/null || true)"
|
|
ZIEL=/sdcard/hpos-init.sh
|
|
|
|
if [ -z "$REPO_URL" ]; then
|
|
warn "Keine Repo-Adresse gefunden (kein origin-Remote gesetzt)."
|
|
hinweis "Ohne sie kann das Telefon die Quellen nicht holen."
|
|
printf ' Adresse von Hand eingeben (leer = überspringen) > '
|
|
read -r REPO_URL </dev/tty || REPO_URL=""
|
|
fi
|
|
|
|
# Benutzernamen entfernen: das Telefon liest nur, und Lesen geht anonym. Bliebe
|
|
# der Name in der Adresse, fragte git dort nach einem Passwort — auf einer
|
|
# Bildschirmtastatur eine unnötige Quälerei.
|
|
if [ -n "$REPO_URL" ]; then
|
|
REPO_URL_ROH="$REPO_URL"
|
|
REPO_URL=$(printf '%s' "$REPO_URL" | sed -E 's#^(https?://)[^/@]+@#\1#')
|
|
[ "$REPO_URL" != "$REPO_URL_ROH" ] && hinweis "Benutzername für das Telefon entfernt (Lesen geht anonym)"
|
|
fi
|
|
|
|
if [ "$TROCKEN" = 1 ]; then
|
|
warn "Trockenlauf — es wird nichts übertragen."
|
|
elif [ -z "$REPO_URL" ]; then
|
|
hinweis "Übersprungen."
|
|
else
|
|
hinweis "Repo: $REPO_URL"
|
|
printf ' Startskript nach %s übertragen? [J/n] > ' "$ZIEL"
|
|
read -r UEBERTRAGEN </dev/tty || UEBERTRAGEN=n
|
|
case "${UEBERTRAGEN:-j}" in
|
|
j|J|"")
|
|
# Adresse fest ins Skript schreiben, damit auf dem Telefon nichts
|
|
# abgetippt werden muss. sed mit | als Trenner, weil URLs Schrägstriche
|
|
# enthalten.
|
|
TMP=$(mktemp)
|
|
sed "s|@@REPO_URL@@|$REPO_URL|" "$HIER/init-phone.sh" >"$TMP"
|
|
if adb push "$TMP" "$ZIEL" >/dev/null 2>&1; then
|
|
ok "Übertragen nach $ZIEL"
|
|
else
|
|
warn "Übertragung fehlgeschlagen."
|
|
fi
|
|
rm -f "$TMP"
|
|
;;
|
|
*) hinweis "Übersprungen." ;;
|
|
esac
|
|
fi
|
|
|
|
kopf "Fertig"
|
|
cat <<TEXT
|
|
Nächste Schritte auf dem Telefon, in Termux:
|
|
|
|
bash /sdcard/hpos-init.sh # installiert git und klont das Repo
|
|
cd ~/hpos
|
|
bash spike/00-bootstrap-termux.sh
|
|
|
|
Ab dann genügt zum Aktualisieren:
|
|
|
|
cd ~/hpos && git pull
|
|
|
|
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
|