Files
linux-on-android-without-root/provision/provision.sh
T
StefanandClaude Opus 5 a58754dbfc Nur ein Startskript per adb, Rest über git; Berechtigungen beim Installieren
Bisher schob provision.sh das ganze Repo nach /sdcard. Auf dem Telefon lag damit
eine Kopie, und jede Änderung hätte wieder den PC gebraucht. Jetzt kommt per adb
nur init-phone.sh: es installiert git und klont die Quellen nach ~/hpos. Danach
ist das eine echte Arbeitskopie und Aktualisieren heißt

    cd ~/hpos && git pull

Die Repo-Adresse liest provision.sh aus dem origin-Remote und schreibt sie fest
ins übertragene Skript, damit auf einer Bildschirmtastatur nichts abgetippt
werden muss. Bei privaten Repos bietet init-phone.sh an, das Passwort zu
speichern — mit dem ausdrücklichen Hinweis, dass das im Klartext geschieht.

Die Berechtigungen wandern von provision.sh nach install-termux.sh, direkt hinter
die Installation. Eine frisch installierte App ohne Berechtigungen ist eine Falle,
die erst Stunden später zuschnappt: im ersten Gerätelauf als stumme Tonaufnahme
in Beweis S2. RECORD_AUDIO für com.termux wird danach ausdrücklich nachgeprüft,
weil genau daran der Beweis hängt.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-10 16:52:50 +02:00

329 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
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