mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-07-04 13:23:15 +02:00
feat(phone): automate BL-9000 fresh-phone recovery after factory reset
- batch3_bloatware_uninstall.sh: rewrite with 42 confirmed BL-9000 packages (39 Blackview OEM + Chrome, YouTube, YouTube Music); batch removal without reboots; --list dry-run; ADB_SERIAL/PHONE_IP support - deploy.sh: ensure_magisk_hosts_module() auto-creates Magisk Systemless Hosts module dir+module.prop and reboots if absent/disabled — no manual Magisk UI interaction required - deploy.sh: fetch_home_coords_from_phone() enables location and captures GPS fix; falls back to stub coords with clear next-step instruction on failure - deploy.sh: --capture-coords action for post-WiFi GPS capture + daemon restart - config.sh: add com.kuhy.workout_app and com.shazam.android to WHITELIST - hosts scripts: broaden Facebook/Messenger unblocking to all subdomains (fbcdn.net, facebook.net, m.facebook.com) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
739d9977bb
commit
dcbfbc3ca4
@ -0,0 +1,17 @@
|
||||
{
|
||||
"title": "BL-9000 fresh-phone recovery automation",
|
||||
"objective": "After a factory reset, deploy.sh runs end-to-end without any manual Magisk UI or coordinate-entry steps: it auto-installs the Magisk Systemless Hosts module (rebooting if needed), captures home GPS coordinates automatically, and deploys all focus mode daemons and hosts blocking. A separate --capture-coords action handles the case where GPS is unavailable at deploy time.",
|
||||
"acceptance_criteria": [
|
||||
"deploy.sh detects missing Magisk Hosts module, creates it, reboots, and continues without user intervention",
|
||||
"deploy.sh captures current GPS as home coords when config_secrets.sh has placeholder values",
|
||||
"On GPS failure, deploy completes with stub coords and prints exact --capture-coords command",
|
||||
"--capture-coords updates phone config_secrets.sh and restarts daemon in one command",
|
||||
"batch3_bloatware_uninstall.sh removes all 42 BL-9000 bloatware packages with 0 errors",
|
||||
"com.kuhy.workout_app and com.shazam.android are never disabled by focus mode"
|
||||
],
|
||||
"out_of_scope": [
|
||||
"Wireless ADB auto-reconnect after reboot (USB reconnect is handled; wireless requires manual re-pairing)",
|
||||
"Launcher enforcement setup (still requires manual Minimalist Phone install + --snapshot-launcher)"
|
||||
],
|
||||
"verifier": "ADB_SERIAL=BL9000EEA0000102 ./deploy.sh && ./deploy.sh --capture-coords && ./deploy.sh --status (Distance: 0m, No apps disabled)"
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
{
|
||||
"intent": "Full fresh-phone recovery after factory reset: bloatware removal, focus mode deploy with auto Magisk Hosts module install, GPS coordinate auto-capture, and whitelist additions.",
|
||||
"scope": [
|
||||
"phone_focus_mode/batch3_bloatware_uninstall.sh",
|
||||
"phone_focus_mode/deploy.sh",
|
||||
"phone_focus_mode/config.sh",
|
||||
"linux_configuration/scripts/periodic_background/hosts/generate_hosts_file.sh",
|
||||
"linux_configuration/scripts/periodic_background/hosts/install.sh"
|
||||
],
|
||||
"changes": [
|
||||
"batch3_bloatware_uninstall.sh: rewritten with 39 confirmed BL-9000 Blackview packages + Chrome/YouTube/YouTube Music; no reboot between removals; supports --list dry-run and ADB_SERIAL/PHONE_IP",
|
||||
"deploy.sh: added ensure_magisk_hosts_module() — auto-creates Magisk Systemless Hosts module dir+module.prop and reboots if absent/disabled, verified working on live device",
|
||||
"deploy.sh: added fetch_home_coords_from_phone() — enables location, waits for fused/network fix, parses 'last location=Location[' format; non-blocking fallback to stub coords on failure",
|
||||
"deploy.sh: added --capture-coords action for post-WiFi GPS capture and daemon restart",
|
||||
"deploy.sh: check_coords() now detects non-numeric placeholder coords and sets NEEDS_GPS_FETCH flag",
|
||||
"config.sh: added com.kuhy.workout_app and com.shazam.android to WHITELIST",
|
||||
"hosts scripts: broadened Facebook/Messenger unblocking to cover all subdomains (fbcdn.net, facebook.net, m.facebook.com)"
|
||||
],
|
||||
"verification": [
|
||||
{
|
||||
"command": "ADB_SERIAL=BL9000EEA0000102 ./batch3_bloatware_uninstall.sh --list",
|
||||
"result": "pass",
|
||||
"evidence": "42 packages detected on live device, 0 not installed"
|
||||
},
|
||||
{
|
||||
"command": "ADB_SERIAL=BL9000EEA0000102 ./batch3_bloatware_uninstall.sh",
|
||||
"result": "pass",
|
||||
"evidence": "42 removed, 0 skipped, 0 errors"
|
||||
},
|
||||
{
|
||||
"command": "ADB_SERIAL=BL9000EEA0000102 ./deploy.sh",
|
||||
"result": "pass",
|
||||
"evidence": "Magisk Hosts absent -> auto-created + rebooted -> active; 177783-line hosts deployed; daemons running PID 9696/22478/25289"
|
||||
},
|
||||
{
|
||||
"command": "ADB_SERIAL=BL9000EEA0000102 ./deploy.sh --capture-coords",
|
||||
"result": "pass",
|
||||
"evidence": "GPS fix acquired 52.229047,20.951483; config_secrets.sh updated; daemon restarted; status shows Distance: 0m"
|
||||
},
|
||||
{
|
||||
"command": "pre-commit run --files phone_focus_mode/batch3_bloatware_uninstall.sh phone_focus_mode/config.sh phone_focus_mode/deploy.sh linux_configuration/scripts/periodic_background/hosts/generate_hosts_file.sh linux_configuration/scripts/periodic_background/hosts/install.sh",
|
||||
"result": "pass",
|
||||
"evidence": "All hooks passed including shellcheck"
|
||||
}
|
||||
],
|
||||
"risks": [
|
||||
"ensure_magisk_hosts_module reboots the phone mid-deploy; if the device fails to reconnect (wireless ADB), deploy must be retried manually",
|
||||
"GPS stub coords (0.000001,0.000001) written on GPS failure mean focus mode stays in normal mode until --capture-coords is run"
|
||||
],
|
||||
"rollback": [
|
||||
"Bloatware: pm install-existing --user 0 <package> restores any removed package",
|
||||
"Focus mode: adb shell su -c 'sh /data/local/tmp/focus_mode/focus_ctl.sh stop' disables all enforcement",
|
||||
"Magisk Hosts module: remove /data/adb/modules/hosts/ and reboot to restore stock /system/etc/hosts"
|
||||
]
|
||||
}
|
||||
@ -84,8 +84,10 @@ sed -i 's/^0\.0\.0\.0 4chan\.org/#0.0.0.0 4chan.org/' "$TMP"
|
||||
sed -i 's/^0\.0\.0\.0 boards\.4chan\.org/#0.0.0.0 boards.4chan.org/' "$TMP"
|
||||
sed -i 's/^0\.0\.0\.0 sys\.4chan\.org/#0.0.0.0 sys.4chan.org/' "$TMP"
|
||||
sed -i 's/^0\.0\.0\.0 www\.4chan\.org/#0.0.0.0 www.4chan.org/' "$TMP"
|
||||
sed -i 's/^0\.0\.0\.0 www\.facebook\.com/#0.0.0.0 www.facebook.com/' "$TMP"
|
||||
sed -i 's/^0\.0\.0\.0 messenger\.com/#0.0.0.0 messenger.com/' "$TMP"
|
||||
sed -i -E 's/^(0\.0\.0\.0[[:space:]]+[a-zA-Z0-9._-]*\.?facebook\.com)/#\1/' "$TMP"
|
||||
sed -i -E 's/^(0\.0\.0\.0[[:space:]]+[a-zA-Z0-9._-]*\.?messenger\.com)/#\1/' "$TMP"
|
||||
sed -i -E 's/^(0\.0\.0\.0[[:space:]]+[a-zA-Z0-9._-]*\.?fbcdn\.net)/#\1/' "$TMP"
|
||||
sed -i -E 's/^(0\.0\.0\.0[[:space:]]+[a-zA-Z0-9._-]*\.?facebook\.net)/#\1/' "$TMP"
|
||||
sed -i 's/^0\.0\.0\.0 delio\.com.pl/#0.0.0.0 delio.com.pl/' "$TMP"
|
||||
sed -i -E 's/^(0\.0\.0\.0[[:space:]]+[a-zA-Z0-9._-]*\.?linkedin\.com)/#\1/' "$TMP"
|
||||
sed -i -E 's/^(0\.0\.0\.0[[:space:]]+[a-zA-Z0-9._-]*\.?licdn\.com)/#\1/' "$TMP"
|
||||
|
||||
@ -180,8 +180,12 @@ fi
|
||||
# boards.4chan.org
|
||||
# sys.4chan.org
|
||||
# www.4chan.org
|
||||
# facebook.com
|
||||
# www.facebook.com
|
||||
# m.facebook.com
|
||||
# messenger.com
|
||||
# fbcdn.net
|
||||
# facebook.net
|
||||
# delio.com.pl
|
||||
# loverslab.com
|
||||
# linkedin.com
|
||||
@ -408,8 +412,10 @@ sudo sed -i 's/^0\.0\.0\.0 4chan\.org/#0.0.0.0 4chan.org/' /etc/hosts
|
||||
sudo sed -i 's/^0\.0\.0\.0 boards\.4chan\.org/#0.0.0.0 boards.4chan.org/' /etc/hosts
|
||||
sudo sed -i 's/^0\.0\.0\.0 sys\.4chan\.org/#0.0.0.0 sys.4chan.org/' /etc/hosts
|
||||
sudo sed -i 's/^0\.0\.0\.0 www\.4chan\.org/#0.0.0.0 www.4chan.org/' /etc/hosts
|
||||
sudo sed -i 's/^0\.0\.0\.0 www\.facebook\.com/#0.0.0.0 www.facebook.com/' /etc/hosts
|
||||
sudo sed -i 's/^0\.0\.0\.0 messenger\.com/#0.0.0.0 messenger.com/' /etc/hosts
|
||||
sudo sed -i -E 's/^(0\.0\.0\.0[[:space:]]+[a-zA-Z0-9._-]*\.?facebook\.com)/#\1/' /etc/hosts
|
||||
sudo sed -i -E 's/^(0\.0\.0\.0[[:space:]]+[a-zA-Z0-9._-]*\.?messenger\.com)/#\1/' /etc/hosts
|
||||
sudo sed -i -E 's/^(0\.0\.0\.0[[:space:]]+[a-zA-Z0-9._-]*\.?fbcdn\.net)/#\1/' /etc/hosts
|
||||
sudo sed -i -E 's/^(0\.0\.0\.0[[:space:]]+[a-zA-Z0-9._-]*\.?facebook\.net)/#\1/' /etc/hosts
|
||||
sudo sed -i 's/^0\.0\.0\.0 delio\.com.pl/#0.0.0.0 delio.com.pl/' /etc/hosts
|
||||
sudo sed -i 's/^0\.0\.0\.0 loverslab\.com/#0.0.0.0 loverslab.com/' /etc/hosts
|
||||
|
||||
|
||||
@ -1,117 +1,181 @@
|
||||
#!/bin/bash
|
||||
DEVICE_SERIAL="BL9000EEA0000102"
|
||||
BACKUP_BASE="/home/kuhy/testsAndMisc_binaries/phone_focus_mode_backups"
|
||||
APPS_TO_UNINSTALL=("com.android.settings" "com.android.systemui" "com.google.android.gms" "com.google.android.apps.docs" "com.google.android.apps.maps")
|
||||
SUBSTITUTE_APPS=("com.android.tv" "com.android.managedprovisioning" "com.google.android.apps.fitness" "com.google.android.apps.books" "com.google.android.apps.wellbeing" "com.google.android.apps.mediashell")
|
||||
# ============================================================
|
||||
# BL-9000 Bloatware Uninstall
|
||||
#
|
||||
# Removes Blackview OEM bloatware and specified Google apps
|
||||
# using `pm uninstall --user 0` (soft-remove, reversible via
|
||||
# `pm install-existing --user 0 <pkg>`). No reboots between
|
||||
# packages — one optional reboot at the end.
|
||||
#
|
||||
# Usage:
|
||||
# ./batch3_bloatware_uninstall.sh [--list] [--reboot]
|
||||
#
|
||||
# --list Dry-run: show which packages would be removed.
|
||||
# --reboot Reboot the phone after all removals.
|
||||
#
|
||||
# Device selection (pick one):
|
||||
# ADB_SERIAL=BL9000EEA0000102 ./batch3_bloatware_uninstall.sh
|
||||
# PHONE_IP=192.168.1.x ./batch3_bloatware_uninstall.sh
|
||||
# ============================================================
|
||||
|
||||
function log_msg() {
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
|
||||
}
|
||||
set -euo pipefail
|
||||
|
||||
function verify_device() {
|
||||
adb -s "$DEVICE_SERIAL" shell echo "Device OK" &>/dev/null
|
||||
[ $? -ne 0 ] && log_msg "ERROR: Device not accessible" && exit 1
|
||||
}
|
||||
DRY_RUN=0
|
||||
DO_REBOOT=0
|
||||
|
||||
function get_app_version() {
|
||||
adb -s "$DEVICE_SERIAL" shell dumpsys package "$1" 2>/dev/null | grep "versionName=" | head -1 | cut -d'=' -f2
|
||||
}
|
||||
|
||||
function app_exists() {
|
||||
adb -s "$DEVICE_SERIAL" shell pm list packages | grep -q "^package:${1}$"
|
||||
}
|
||||
|
||||
function get_substitute() {
|
||||
for sub in "${SUBSTITUTE_APPS[@]}"; do
|
||||
app_exists "$sub" && echo "$sub" && return 0
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
function execute_checkpoint() {
|
||||
local pkg=$1 app_num=$2
|
||||
log_msg "========================================="
|
||||
log_msg "APP #${app_num}: Processing $pkg"
|
||||
log_msg "========================================="
|
||||
|
||||
if ! app_exists "$pkg"; then
|
||||
log_msg "WARNING: $pkg not found. Searching for substitute..."
|
||||
actual_pkg=$(get_substitute "$pkg")
|
||||
[ -z "$actual_pkg" ] && log_msg "ERROR: Could not find substitute. Skipping." && return 1
|
||||
log_msg "SUBSTITUTING: Using $actual_pkg"
|
||||
pkg="$actual_pkg"
|
||||
fi
|
||||
|
||||
TIMESTAMP=$(date +%s)
|
||||
CHECKPOINT_DIR="${BACKUP_BASE}/checkpoint_${TIMESTAMP}_${pkg}"
|
||||
mkdir -p "$CHECKPOINT_DIR"
|
||||
log_msg "Checkpoint: $CHECKPOINT_DIR"
|
||||
|
||||
log_msg "[1/6] Pulling APK..."
|
||||
adb -s "$DEVICE_SERIAL" shell pm path "$pkg" > "$CHECKPOINT_DIR/package_path.txt"
|
||||
if grep -q "^package:" "$CHECKPOINT_DIR/package_path.txt"; then
|
||||
APK_PATH=$(grep "^package:" "$CHECKPOINT_DIR/package_path.txt" | cut -d':' -f2)
|
||||
pull_log="$CHECKPOINT_DIR/pull_output.txt"
|
||||
adb -s "$DEVICE_SERIAL" pull "$APK_PATH" "$CHECKPOINT_DIR/app.apk" > "$pull_log" 2>&1 || true
|
||||
if ! grep -e "Pull" -e "error" "$pull_log"; then
|
||||
log_msg "APK pulled"
|
||||
fi
|
||||
fi
|
||||
|
||||
log_msg "[2/6] Backing up PM state..."
|
||||
adb -s "$DEVICE_SERIAL" shell dumpsys package "$pkg" > "$CHECKPOINT_DIR/pm_state.txt"
|
||||
VNAME=$(get_app_version "$pkg")
|
||||
log_msg "Version: $VNAME"
|
||||
|
||||
log_msg "[3/6] Taking snapshot..."
|
||||
adb -s "$DEVICE_SERIAL" shell dumpsys activity activities > "$CHECKPOINT_DIR/activities_before.txt"
|
||||
adb -s "$DEVICE_SERIAL" shell pm list packages > "$CHECKPOINT_DIR/packages_before.txt"
|
||||
|
||||
log_msg "[4/6] Uninstalling: pm uninstall --user 0 $pkg"
|
||||
adb -s "$DEVICE_SERIAL" shell pm uninstall --user 0 "$pkg" > "$CHECKPOINT_DIR/uninstall_output.txt" 2>&1
|
||||
UNINSTALL_RESULT=$(cat "$CHECKPOINT_DIR/uninstall_output.txt")
|
||||
log_msg "Result: $UNINSTALL_RESULT"
|
||||
|
||||
log_msg "[5/6] Rebooting device..."
|
||||
adb -s "$DEVICE_SERIAL" reboot
|
||||
sleep 5
|
||||
|
||||
REBOOT_TIMEOUT=180
|
||||
WAIT_START=$(date +%s)
|
||||
while true; do
|
||||
adb -s "$DEVICE_SERIAL" shell echo "up" &>/dev/null && break
|
||||
[ $(($(date +%s) - WAIT_START)) -ge $REBOOT_TIMEOUT ] && log_msg "ERROR: Timeout" && break
|
||||
sleep 3
|
||||
echo -n "."
|
||||
done
|
||||
echo ""
|
||||
|
||||
sleep 5
|
||||
adb -s "$DEVICE_SERIAL" shell pm list packages > "$CHECKPOINT_DIR/packages_after.txt"
|
||||
|
||||
if adb -s "$DEVICE_SERIAL" shell pm list packages | grep -q "^package:${pkg}$"; then
|
||||
log_msg "WARNING: $pkg still present"
|
||||
else
|
||||
log_msg "SUCCESS: $pkg uninstalled"
|
||||
fi
|
||||
|
||||
log_msg "[6/6] Generating report..."
|
||||
cat > "$CHECKPOINT_DIR/report.txt" <<< "CHECKPOINT REPORT: $pkg (Timestamp: $TIMESTAMP, Device: $DEVICE_SERIAL) - Version: $VNAME - Result: $UNINSTALL_RESULT - Checkpoint: $CHECKPOINT_DIR"
|
||||
log_msg "✓ Complete"
|
||||
return 0
|
||||
}
|
||||
|
||||
log_msg "========================================="
|
||||
log_msg "BATCH 3: BLOATWARE UNINSTALL"
|
||||
log_msg "========================================="
|
||||
verify_device
|
||||
log_msg "Device verified"
|
||||
|
||||
for i in "${!APPS_TO_UNINSTALL[@]}"; do
|
||||
execute_checkpoint "${APPS_TO_UNINSTALL[$i]}" $((i + 1))
|
||||
[ $((i + 1)) -lt ${#APPS_TO_UNINSTALL[@]} ] && sleep 5
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--list) DRY_RUN=1 ;;
|
||||
--reboot) DO_REBOOT=1 ;;
|
||||
*) echo "Unknown flag: $arg"; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
log_msg "========================================="
|
||||
log_msg "BATCH 3 COMPLETE"
|
||||
log_msg "========================================="
|
||||
# ---- Device targeting (mirrors deploy.sh) ----
|
||||
ADB_TARGET=()
|
||||
if [[ -n "${ADB_SERIAL:-}" ]]; then
|
||||
ADB_TARGET=(-s "${ADB_SERIAL}")
|
||||
elif [[ -n "${PHONE_IP:-}" ]]; then
|
||||
echo "Connecting to ${PHONE_IP}:5555 ..."
|
||||
adb connect "${PHONE_IP}:5555"
|
||||
ADB_TARGET=(-s "${PHONE_IP}:5555")
|
||||
fi
|
||||
|
||||
adb_cmd() { adb "${ADB_TARGET[@]}" "$@"; }
|
||||
|
||||
# Requires --mount-master so the command runs in the global mount namespace.
|
||||
adb_root() {
|
||||
printf '%s\n' "$1" | adb_cmd shell su --mount-master -c "sh -s"
|
||||
}
|
||||
|
||||
# ============================================================
|
||||
# PACKAGES TO REMOVE
|
||||
#
|
||||
# All removed with `pm uninstall --user 0` — the APK stays in
|
||||
# /system so a factory reset or `pm install-existing` restores
|
||||
# it. Safe to run even if a package is absent (skipped).
|
||||
# ============================================================
|
||||
|
||||
# ---- Blackview OEM bloatware (BL-9000 confirmed packages) ----
|
||||
BV_BLOATWARE=(
|
||||
com.blackview.apkupgrade # Blackview OTA updater
|
||||
com.blackview.bvworkspace # BV desktop workspace
|
||||
com.blackview.childmode # Child mode
|
||||
com.blackview.cplog # CPU/hardware logger
|
||||
com.blackview.darkmode.one # Dark mode theme variant
|
||||
com.blackview.darkmode.two
|
||||
com.blackview.darkmode.three
|
||||
com.blackview.easytrans # BV easy-transfer tool
|
||||
com.blackview.filetrans # BV file-transfer tool
|
||||
com.blackview.focusmode # BV own focus mode (replaced by ours)
|
||||
com.blackview.frozenapp # App freezer
|
||||
com.blackview.gamemode # Game mode panel
|
||||
com.blackview.health # BV health tracker
|
||||
com.blackview.helper # BV AI assistant / helper
|
||||
com.blackview.launcher # BV launcher (competitor to Minimalist Phone)
|
||||
com.blackview.launcher.overlay.framework
|
||||
com.blackview.leftscreen # Left swipe panel
|
||||
com.blackview.notebook # BV notes app
|
||||
com.blackview.qrcode # QR scanner (camera does it natively)
|
||||
com.blackview.reversepay # Reverse wireless charging pay
|
||||
com.blackview.smscode # SMS code extractor
|
||||
com.blackview.systemmanager # BV system manager
|
||||
com.blackview.theme.color.mode0 # Color themes (8 variants)
|
||||
com.blackview.theme.color.mode1
|
||||
com.blackview.theme.color.mode2
|
||||
com.blackview.theme.color.mode3
|
||||
com.blackview.theme.color.mode4
|
||||
com.blackview.theme.color.mode5
|
||||
com.blackview.theme.color.mode6
|
||||
com.blackview.theme.color.mode7
|
||||
com.blackview.theme.config
|
||||
com.blackview.theme.icon.clearwave # Icon themes
|
||||
com.blackview.theme.icon.oil
|
||||
com.blackview.tool # BV diagnostic tool
|
||||
com.blackview.userfeedback # BV telemetry / feedback
|
||||
com.blackview.wallpaper # BV wallpaper collection
|
||||
com.blackview.wallpaperpicker
|
||||
com.blackview.wallpaperpicker.overlay
|
||||
com.blackview.weather # BV weather widget
|
||||
)
|
||||
|
||||
# ---- Google apps explicitly requested for removal ----
|
||||
GOOGLE_REMOVE=(
|
||||
com.android.chrome # Google Chrome (Firefox is whitelisted)
|
||||
com.google.android.youtube # YouTube app (hosts-blocked anyway)
|
||||
com.google.android.apps.youtube.music # YouTube Music
|
||||
)
|
||||
|
||||
ALL_PACKAGES=("${BV_BLOATWARE[@]}" "${GOOGLE_REMOVE[@]}")
|
||||
|
||||
# ============================================================
|
||||
# Main
|
||||
# ============================================================
|
||||
echo "============================================================"
|
||||
if [[ $DRY_RUN -eq 1 ]]; then
|
||||
echo "DRY RUN — packages that would be removed:"
|
||||
else
|
||||
echo "BL-9000 bloatware removal"
|
||||
fi
|
||||
echo "============================================================"
|
||||
|
||||
echo ""
|
||||
echo "[1] Verifying device connection..."
|
||||
if ! adb_cmd get-state >/dev/null 2>&1; then
|
||||
echo "ERROR: No ADB device reachable."
|
||||
echo " Set ADB_SERIAL=<serial> or PHONE_IP=<ip> and retry."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[2] Verifying root..."
|
||||
if ! adb_root "id" 2>/dev/null | grep -q "uid=0"; then
|
||||
echo "ERROR: Root shell failed. Ensure Magisk is installed."
|
||||
exit 1
|
||||
fi
|
||||
echo " Root confirmed."
|
||||
echo ""
|
||||
|
||||
removed=0
|
||||
skipped=0
|
||||
errors=0
|
||||
|
||||
for pkg in "${ALL_PACKAGES[@]}"; do
|
||||
# Check presence
|
||||
if ! adb_cmd shell pm list packages 2>/dev/null | grep -qx "package:${pkg}"; then
|
||||
printf ' %-55s [not installed]\n' "$pkg"
|
||||
(( skipped++ )) || true
|
||||
continue
|
||||
fi
|
||||
|
||||
if [[ $DRY_RUN -eq 1 ]]; then
|
||||
printf ' %-55s [would remove]\n' "$pkg"
|
||||
(( removed++ )) || true
|
||||
continue
|
||||
fi
|
||||
|
||||
printf ' Removing %-48s ... ' "$pkg"
|
||||
result="$(adb_cmd shell pm uninstall --user 0 "$pkg" 2>&1 || true)"
|
||||
if echo "$result" | grep -qi "success"; then
|
||||
echo "OK"
|
||||
(( removed++ )) || true
|
||||
else
|
||||
echo "FAILED (${result})"
|
||||
(( errors++ )) || true
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "============================================================"
|
||||
if [[ $DRY_RUN -eq 1 ]]; then
|
||||
echo "Dry-run complete: ${removed} would be removed, ${skipped} not installed."
|
||||
echo "Run without --list to apply."
|
||||
else
|
||||
echo "Done: ${removed} removed, ${skipped} skipped (not installed), ${errors} errors."
|
||||
if [[ $DO_REBOOT -eq 1 ]]; then
|
||||
echo "Rebooting phone..."
|
||||
adb_cmd reboot
|
||||
else
|
||||
echo "Run with --reboot to reboot now, or reboot manually."
|
||||
fi
|
||||
fi
|
||||
echo "============================================================"
|
||||
|
||||
@ -228,6 +228,8 @@ com.kuhy.focusstatus
|
||||
|
||||
# --- User-requested productive apps ---
|
||||
com.stronglifts.app
|
||||
com.kuhy.workout_app
|
||||
com.shazam.android
|
||||
com.ichi2.anki
|
||||
com.metrolist.music
|
||||
org.mozilla.fenix
|
||||
|
||||
@ -18,6 +18,7 @@ PHONE_IP="${1:-}"
|
||||
ACTION="${2:---deploy}"
|
||||
REMOTE_DIR="/data/local/tmp/focus_mode"
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
NEEDS_GPS_FETCH=0 # set to 1 by check_coords when local coords are placeholder
|
||||
|
||||
# Source shared config constants (BROWSER_PACKAGES, REMOTE_DIR, etc.)
|
||||
# shellcheck source=config.sh
|
||||
@ -56,6 +57,7 @@ usage() {
|
||||
echo " --list List all third-party apps and whitelist status"
|
||||
echo " --pull-log Download log file locally"
|
||||
echo " --find-pkg Show installed packages matching a filter (e.g. --find-pkg pomodoro)"
|
||||
echo " --capture-coords Capture current GPS as home location (run after WiFi setup)"
|
||||
echo " --hosts-status Show hosts enforcer status on the phone"
|
||||
echo " --hosts-log Show hosts enforcer log on the phone"
|
||||
echo " --launcher-status Show launcher enforcer status on the phone"
|
||||
@ -84,15 +86,17 @@ check_coords() {
|
||||
local lat lon
|
||||
lat="$(grep '^.*HOME_LAT=' "$SCRIPT_DIR/config.sh" "$SCRIPT_DIR/config_secrets.sh" 2>/dev/null | tail -1 | cut -d'"' -f2)"
|
||||
lon="$(grep '^.*HOME_LON=' "$SCRIPT_DIR/config.sh" "$SCRIPT_DIR/config_secrets.sh" 2>/dev/null | tail -1 | cut -d'"' -f2)"
|
||||
# Allow redacted values locally - real coords live only on the phone
|
||||
if [ "$lat" = "0.000000" ] && [ "$lon" = "0.000000" ]; then
|
||||
echo "ERROR: Home coordinates not set (all zeros). Set them in config_secrets.sh."
|
||||
echo "ERROR: Home coordinates not set (all zeros)."
|
||||
exit 1
|
||||
fi
|
||||
if [ -z "$lat" ] || [ -z "$lon" ]; then
|
||||
echo " Home location: (not set locally - will use values on phone)"
|
||||
else
|
||||
# If both look like valid floats, use them; otherwise auto-capture from phone GPS.
|
||||
if [[ -n "$lat" && "$lat" =~ ^[+-]?[0-9]+\.[0-9]+$ && -n "$lon" && "$lon" =~ ^[+-]?[0-9]+\.[0-9]+$ ]]; then
|
||||
NEEDS_GPS_FETCH=0
|
||||
echo " Home location: $lat, $lon"
|
||||
else
|
||||
NEEDS_GPS_FETCH=1
|
||||
echo " Home location: placeholder — will be captured from phone GPS at deploy time."
|
||||
fi
|
||||
}
|
||||
|
||||
@ -153,6 +157,144 @@ compute_file_hash() {
|
||||
md5sum "$path" | awk '{print $1}'
|
||||
}
|
||||
|
||||
# ============================================================
|
||||
# GPS HOME COORDINATE CAPTURE
|
||||
# ============================================================
|
||||
# Called when config_secrets.sh has placeholder/non-numeric coords.
|
||||
# Enables Android location, waits up to GPS_MAX_WAIT_SECS for a
|
||||
# network/fused fix, and prints "lat lon" on stdout. All progress
|
||||
# messages go to stderr so the caller can capture only the coords.
|
||||
GPS_MAX_WAIT_SECS=90
|
||||
|
||||
fetch_home_coords_from_phone() {
|
||||
echo " Enabling location services on phone..." >&2
|
||||
adb_cmd shell settings put secure location_mode 3 2>/dev/null || true
|
||||
|
||||
echo " Waiting for network/fused location fix (up to ${GPS_MAX_WAIT_SECS}s)..." >&2
|
||||
local waited=0 coords=""
|
||||
while [[ -z "$coords" && $waited -lt $GPS_MAX_WAIT_SECS ]]; do
|
||||
sleep 3
|
||||
waited=$((waited + 3))
|
||||
# Format on Android 10+: " last location=Location[fused LAT,LON ...]"
|
||||
local raw
|
||||
raw="$(adb_cmd shell dumpsys location 2>/dev/null \
|
||||
| grep 'last location=Location\[' \
|
||||
| grep -oE '[+-]?[0-9]+\.[0-9]+,[+-]?[0-9]+\.[0-9]+' \
|
||||
| head -1 || true)"
|
||||
[[ -n "$raw" ]] && coords="$raw"
|
||||
printf '.' >&2
|
||||
done
|
||||
printf '\n' >&2
|
||||
|
||||
if [[ -z "$coords" ]]; then
|
||||
echo "ERROR: No location fix after ${GPS_MAX_WAIT_SECS}s." >&2
|
||||
echo " Make sure the phone has cellular or WiFi data, then retry." >&2
|
||||
echo " Or set HOME_LAT/HOME_LON manually in config_secrets.sh." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
local lat="${coords%,*}"
|
||||
local lon="${coords#*,}"
|
||||
echo " GPS fix acquired: ${lat}, ${lon}" >&2
|
||||
printf '%s %s' "$lat" "$lon"
|
||||
}
|
||||
|
||||
# ============================================================
|
||||
# MAGISK SYSTEMLESS HOSTS AUTO-INSTALL
|
||||
# ============================================================
|
||||
# Creates the module dir+module.prop if absent, removes disable
|
||||
# markers if disabled, then reboots the device and waits up to
|
||||
# HOSTS_MODULE_REBOOT_WAIT_SECS for it to come back with the
|
||||
# magic-mount active. No-ops if the module is already OK.
|
||||
HOSTS_MODULE_REBOOT_WAIT_SECS=180
|
||||
|
||||
ensure_magisk_hosts_module() {
|
||||
local state="absent"
|
||||
if adb_root "test -d /data/adb/modules/hosts" >/dev/null 2>&1; then
|
||||
if adb_root "test -f /data/adb/modules/hosts/disable -o -f /data/adb/modules/hosts/remove" >/dev/null 2>&1; then
|
||||
state="disabled"
|
||||
elif adb_root "test -f /system/etc/hosts" >/dev/null 2>&1; then
|
||||
state="ok"
|
||||
else
|
||||
state="not-mounted"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$state" == "ok" ]]; then
|
||||
echo " Magisk Systemless Hosts: active."
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo " Magisk Systemless Hosts state: ${state} — auto-installing..."
|
||||
|
||||
case "$state" in
|
||||
absent)
|
||||
adb_root "mkdir -p /data/adb/modules/hosts/system/etc"
|
||||
# module.prop is required for Magisk to recognise and process the module.
|
||||
adb_root "printf 'id=hosts\nname=Systemless Hosts\nversion=v1\nversionCode=1\nauthor=Magisk\ndescription=Replace /system/etc/hosts\n' \
|
||||
> /data/adb/modules/hosts/module.prop"
|
||||
# Seed a minimal hosts file so the mount target exists at first boot.
|
||||
adb_root "printf '127.0.0.1 localhost\n::1 localhost\n' \
|
||||
> /data/adb/modules/hosts/system/etc/hosts"
|
||||
adb_root "chmod 644 /data/adb/modules/hosts/system/etc/hosts"
|
||||
;;
|
||||
disabled)
|
||||
adb_root "rm -f /data/adb/modules/hosts/disable \
|
||||
/data/adb/modules/hosts/remove \
|
||||
/data/adb/modules/hosts/update"
|
||||
;;
|
||||
not-mounted)
|
||||
: # module exists and enabled, just needs a reboot
|
||||
;;
|
||||
esac
|
||||
|
||||
echo " Rebooting phone to activate Magisk Hosts module..."
|
||||
adb_cmd reboot
|
||||
# Give the device time to actually begin shutting down before we poll.
|
||||
sleep 20
|
||||
|
||||
echo " Waiting for device to come back (up to ${HOSTS_MODULE_REBOOT_WAIT_SECS}s)..."
|
||||
local waited=0
|
||||
# Re-establish wireless ADB connection if needed.
|
||||
while true; do
|
||||
if [[ -n "${PHONE_IP:-}" ]]; then
|
||||
adb connect "${PHONE_IP}:5555" >/dev/null 2>&1 || true
|
||||
fi
|
||||
if adb_cmd shell echo ok 2>/dev/null | grep -q '^ok$'; then
|
||||
break
|
||||
fi
|
||||
sleep 3
|
||||
waited=$((waited + 3))
|
||||
if [[ $waited -ge $HOSTS_MODULE_REBOOT_WAIT_SECS ]]; then
|
||||
echo "ERROR: Device did not come back after ${HOSTS_MODULE_REBOOT_WAIT_SECS}s."
|
||||
echo " Check USB connection or re-enable wireless ADB, then run deploy again."
|
||||
exit 1
|
||||
fi
|
||||
printf '.'
|
||||
done
|
||||
printf '\n'
|
||||
|
||||
# Wait for Magisk early-init and root to be ready.
|
||||
echo " Waiting for Magisk root to be available..."
|
||||
waited=0
|
||||
while ! adb_root "id" 2>/dev/null | grep -q "uid=0"; do
|
||||
sleep 3
|
||||
waited=$((waited + 3))
|
||||
[[ $waited -ge 60 ]] && echo "ERROR: Root not available after reboot." && exit 1
|
||||
printf '.'
|
||||
done
|
||||
printf '\n'
|
||||
|
||||
# Final assertion: the magic-mount must now be active.
|
||||
if ! adb_root "test -f /system/etc/hosts" >/dev/null 2>&1; then
|
||||
echo "ERROR: /system/etc/hosts is not magic-mounted after reboot."
|
||||
echo " Magisk may not have applied the module correctly."
|
||||
echo " Check the Magisk app for module errors and run deploy again."
|
||||
exit 1
|
||||
fi
|
||||
echo " Magisk Systemless Hosts module is now active."
|
||||
}
|
||||
|
||||
# ============================================================
|
||||
# AURORA STORE
|
||||
# ============================================================
|
||||
@ -216,6 +358,9 @@ do_deploy() {
|
||||
fi
|
||||
echo " Root confirmed."
|
||||
|
||||
echo "[2.5] Ensuring Magisk Systemless Hosts module..."
|
||||
ensure_magisk_hosts_module
|
||||
|
||||
echo "[3/7] Creating directories on device..."
|
||||
# Use world-writable staging dir so non-root adb push works
|
||||
adb_cmd shell "mkdir -p /data/local/tmp/focus_stage"
|
||||
@ -324,6 +469,26 @@ PY_EOF
|
||||
# Only push config_secrets.sh if phone doesn't already have one
|
||||
if adb_root "test -f $REMOTE_DIR/config_secrets.sh" 2>/dev/null; then
|
||||
echo " config_secrets.sh already exists on phone - skipping (preserving real coords)"
|
||||
elif [[ "${NEEDS_GPS_FETCH}" -eq 1 ]]; then
|
||||
# Local config_secrets.sh has placeholder coords — capture current GPS from the phone.
|
||||
# The phone is assumed to be at home during setup, so current location = home location.
|
||||
local gps_result="" gps_lat="" gps_lon=""
|
||||
if gps_result="$(fetch_home_coords_from_phone 2>&1)"; then
|
||||
gps_lat="${gps_result% *}"
|
||||
gps_lon="${gps_result#* }"
|
||||
adb_root "printf '#!/system/bin/sh\n# Home coordinates auto-captured from GPS at deploy time\nexport HOME_LAT=\"${gps_lat}\"\nexport HOME_LON=\"${gps_lon}\"\n' \
|
||||
> $REMOTE_DIR/config_secrets.sh"
|
||||
echo " Home coordinates written to phone: ${gps_lat}, ${gps_lon}"
|
||||
else
|
||||
# GPS unavailable (no WiFi/cellular yet on fresh phone).
|
||||
# Write stub coords — focus mode stays OFF, hosts/DNS blocking still works.
|
||||
# User should run: ./deploy.sh [ip] --capture-coords after configuring WiFi.
|
||||
adb_root "printf '#!/system/bin/sh\n# STUB: run ./deploy.sh --capture-coords after WiFi setup\nexport HOME_LAT=\"0.000001\"\nexport HOME_LON=\"0.000001\"\n' \
|
||||
> $REMOTE_DIR/config_secrets.sh"
|
||||
echo " WARNING: GPS capture failed — focus mode location enforcement is DISABLED."
|
||||
echo " Hosts/DNS blocking is active. After configuring WiFi, run:"
|
||||
echo " ADB_SERIAL=${ADB_SERIAL:-\$PHONE_IP:5555} ./deploy.sh --capture-coords"
|
||||
fi
|
||||
else
|
||||
echo " Pushing config_secrets.sh (first install)..."
|
||||
adb_cmd push "$SCRIPT_DIR/config_secrets.sh" "/data/local/tmp/focus_stage/config_secrets.sh"
|
||||
@ -376,60 +541,10 @@ PY_EOF
|
||||
adb_root "chattr +i $REMOTE_DIR/hosts.sha256.workout 2>/dev/null; true"
|
||||
fi
|
||||
|
||||
# ---- Magisk Systemless Hosts module (REQUIRED) ----
|
||||
# This module magic-mounts /data/adb/modules/hosts/system/etc/hosts
|
||||
# as /system/etc/hosts at boot — the only way to create that file on
|
||||
# this ROM's hardware-read-only system partition.
|
||||
#
|
||||
# The module must be ENABLED in the Magisk app by the user (one-time,
|
||||
# after each factory reset). We CANNOT enable it programmatically.
|
||||
# Without it, no app-level hosts blocking is possible, so we STOP here
|
||||
# and require user action before the deploy can proceed.
|
||||
local magisk_hosts_ok=0
|
||||
local magisk_hosts_state="absent"
|
||||
if adb_root "test -d /data/adb/modules/hosts" 2>/dev/null; then
|
||||
if adb_root "test -f /data/adb/modules/hosts/disable -o -f /data/adb/modules/hosts/remove" 2>/dev/null; then
|
||||
magisk_hosts_state="disabled"
|
||||
elif ! adb_root "test -f /system/etc/hosts" 2>/dev/null; then
|
||||
# Module dir exists, no disable marker, but the magic-mount
|
||||
# has not happened yet. Either the user just enabled it but
|
||||
# has not rebooted, or the module is in a broken state.
|
||||
magisk_hosts_state="not-mounted"
|
||||
else
|
||||
magisk_hosts_ok=1
|
||||
magisk_hosts_state="ok"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$magisk_hosts_ok" -eq 0 ]]; then
|
||||
echo ""
|
||||
echo "╔══════════════════════════════════════════════════════════════════╗"
|
||||
echo "║ ACTION REQUIRED — Deploy cannot continue ║"
|
||||
echo "╠══════════════════════════════════════════════════════════════════╣"
|
||||
if [[ "$magisk_hosts_state" == "not-mounted" ]]; then
|
||||
echo "║ Magisk 'Systemless Hosts' module is enabled on disk but the ║"
|
||||
echo "║ /system/etc/hosts magic-mount has NOT happened yet. ║"
|
||||
echo "║ This means the device has not been rebooted since the module ║"
|
||||
echo "║ was last toggled on. Without the magic-mount, no hosts-file ║"
|
||||
echo "║ blocking is possible (the partition is hardware read-only). ║"
|
||||
echo "║ ║"
|
||||
echo "║ Steps to fix: ║"
|
||||
echo "║ 1. Reboot the phone now (adb reboot, or hold power) ║"
|
||||
echo "║ 2. After reboot, re-run this deploy command ║"
|
||||
else
|
||||
echo "║ The Magisk 'Systemless Hosts' module is not enabled. ║"
|
||||
echo "║ Without it, hosts-file blocking is impossible on this device ║"
|
||||
echo "║ (the system partition is hardware read-only even with root). ║"
|
||||
echo "║ ║"
|
||||
echo "║ Steps to fix: ║"
|
||||
echo "║ 1. Open the Magisk app on the phone ║"
|
||||
echo "║ 2. Tap the Modules tab (puzzle-piece icon) ║"
|
||||
echo "║ 3. Find 'Systemless Hosts' and toggle it ON ║"
|
||||
echo "║ 4. Reboot the phone when prompted ║"
|
||||
echo "║ 5. Re-run this deploy command ║"
|
||||
fi
|
||||
echo "╚══════════════════════════════════════════════════════════════════╝"
|
||||
echo ""
|
||||
# Magisk Systemless Hosts module was ensured (and rebooted if needed) in
|
||||
# step [2.5] above. Sanity-assert it's still active before writing to it.
|
||||
if ! adb_root "test -f /system/etc/hosts" 2>/dev/null; then
|
||||
echo "ERROR: /system/etc/hosts not magic-mounted — run deploy again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@ -604,6 +719,27 @@ do_pull_log() {
|
||||
echo "Done."
|
||||
}
|
||||
|
||||
do_capture_coords() {
|
||||
# Standalone GPS capture for post-WiFi-setup use.
|
||||
# Overwrites config_secrets.sh on the phone with the current location.
|
||||
connect_adb
|
||||
if ! adb_root "id" 2>/dev/null | grep -q "uid=0"; then
|
||||
echo "ERROR: Root not available."
|
||||
exit 1
|
||||
fi
|
||||
echo "Capturing home coordinates from phone GPS..."
|
||||
local gps_result gps_lat gps_lon
|
||||
gps_result="$(fetch_home_coords_from_phone)"
|
||||
gps_lat="${gps_result% *}"
|
||||
gps_lon="${gps_result#* }"
|
||||
adb_root "printf '#!/system/bin/sh\n# Home coordinates auto-captured from GPS\nexport HOME_LAT=\"${gps_lat}\"\nexport HOME_LON=\"${gps_lon}\"\n' \
|
||||
> $REMOTE_DIR/config_secrets.sh"
|
||||
echo "Home coordinates updated on phone: ${gps_lat}, ${gps_lon}"
|
||||
echo "Restarting focus daemon to apply new coordinates..."
|
||||
adb_root "sh $REMOTE_DIR/focus_ctl.sh restart" 2>/dev/null || true
|
||||
echo "Done."
|
||||
}
|
||||
|
||||
do_find_pkg() {
|
||||
local filter="${3:-}"
|
||||
if [ -z "$filter" ]; then
|
||||
@ -656,6 +792,7 @@ case "$ACTION" in
|
||||
--hosts-log) connect_adb; adb_root "sh $REMOTE_DIR/focus_ctl.sh hosts-log 100" ;;
|
||||
--launcher-status) do_control "launcher-status" ;;
|
||||
--launcher-log) connect_adb; adb_root "sh $REMOTE_DIR/focus_ctl.sh launcher-log 100" ;;
|
||||
--capture-coords) do_capture_coords ;;
|
||||
--snapshot-launcher) do_snapshot_launcher ;;
|
||||
--install-aurora) do_install_aurora ;;
|
||||
*) echo "Unknown action: $ACTION"; usage ;;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user