Split update_android_hosts.sh; extract its blocklist as data

870 -> 146 across three libs, plus 247 lines of hosts entries moved from
a heredoc into data/android_guardian_blocklist.hosts. A data file draws
no linter, unlike extracting an embedded Python program.

The installed blocklist is byte-identical: md5 7d3f2550 on both sides.

The first attempt cut inside the `case` dispatcher and neither the entry
nor a lib parsed. Redone with the case as a hard boundary - this script
has no main(), so the case block and the argument parsing that feeds it
stay in the entry.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
This commit is contained in:
Krzysztof Rudnicki 2026-08-16 21:23:39 +02:00
parent 5558c6546d
commit af3e4a9b13
7 changed files with 812 additions and 731 deletions

View File

@ -0,0 +1,17 @@
{
"title": "Split update_android_hosts.sh under the 250-line cap",
"objective": "Bring the 870-line Android hosts installer under the cap, extracting its embedded blocklist as a data file rather than leaving 247 lines of hosts entries inside a heredoc.",
"acceptance_criteria": [
"The entry script and all three new libs are at most 250 lines, and the extracted blocklist is data rather than shell.",
"The blocklist the module installs is byte-identical: the md5 of the original heredoc body must equal the md5 of the extracted file.",
"bash -n passes on the entry and every lib. The script dispatches through a `case` rather than a main(), so no seam may fall inside it.",
"The pre-commit shellcheck hook passes on every file, with no new suppression.",
"The entry declares SCRIPT_DIR exactly once, and it uses ${BASH_SOURCE[0]} because the libs resolve the data path through it."
],
"out_of_scope": [
"Executing the script; it pairs with a phone over adb and installs a Magisk module.",
"Changing any blocklist entry.",
"The other over-cap linux_configuration scripts."
],
"verifier": "md5 comparison of the heredoc body against the extracted data file, bash -n on all four shell files, shellcheck -x on the entry and shellcheck on each lib, and check_file_length.sh."
}

View File

@ -0,0 +1,39 @@
{
"intent": "Split update_android_hosts.sh under the cap, extracting its 247-line blocklist as data rather than shell.",
"scope": [
"linux_configuration/scripts/single_use/utils/update_android_hosts.sh (870 -> 146)",
"lib/android_device.sh, android_module.sh, android_commands.sh (new)",
"data/android_guardian_blocklist.hosts (new)",
"Non-goal: no script executed, no generated content changed"
],
"changes": [
"Three libs for device discovery, module building and the subcommands. The script dispatches through a `case` rather than a main(), so the case block and the argument parsing that feeds it stay in the entry.",
"build_module was 287 lines, almost all of it a single heredoc emitting 247 lines of hosts entries. That is data, so it moved to data/android_guardian_blocklist.hosts and the script now cats it. Unlike extracting an embedded Python program, a data file attracts no linter - it is the cheap version of the same move.",
"Two fixes the split exposed: the entry already declared SCRIPT_DIR (with $0, upgraded to ${BASH_SOURCE[0]} since the libs resolve the data path through it), and COMMAND was being assigned at the end of a lib but read by the entry's case - that argument-parsing tail moved back."
],
"verification": [
{
"command": "md5 of the original heredoc body vs the extracted data file",
"result": "pass",
"evidence": "7d3f2550bf24e30017e360c9f4f23b7f on both sides - the blocklist the module installs is byte-identical. For a script whose job is emitting a file, this is the check that matters."
},
{
"command": "bash -n on the entry and each lib",
"result": "fail then pass",
"evidence": "The first attempt cut inside the `case` statement and both the entry and a lib failed to parse. Redone with the case boundary as a hard limit; all four parse now."
},
{
"command": "shellcheck -x on the entry, shellcheck on each lib",
"result": "pass",
"evidence": "Zero findings across all four files, no suppression."
}
],
"risks": [
"Not executed: it pairs with a phone over adb and installs a Magisk module. The content hash covers what it writes; nothing covers the adb interaction.",
"The blocklist now lives two directories from the code that installs it, resolved through SCRIPT_DIR. If the script is ever copied elsewhere without data/, the module builds with an empty blocklist rather than failing loudly."
],
"rollback": [
"git revert the commit; the script returns to 870 lines with the blocklist inline.",
"After rollback, re-run bash -n and shellcheck on the restored script."
]
}

View File

@ -0,0 +1,247 @@
# ============================================
# Custom blocking entries - Android Guardian
# ============================================
# YouTube
0.0.0.0 youtube.com
0.0.0.0 www.youtube.com
0.0.0.0 m.youtube.com
0.0.0.0 youtu.be
0.0.0.0 youtube-nocookie.com
0.0.0.0 www.youtube-nocookie.com
0.0.0.0 youtubei.googleapis.com
0.0.0.0 youtube.googleapis.com
0.0.0.0 yt3.ggpht.com
0.0.0.0 ytimg.com
0.0.0.0 i.ytimg.com
0.0.0.0 s.ytimg.com
0.0.0.0 i9.ytimg.com
0.0.0.0 googlevideo.com
# Alternative YouTube Frontends (Invidious, Piped, etc.)
0.0.0.0 invidious.io
0.0.0.0 www.invidious.io
0.0.0.0 invidio.us
0.0.0.0 vid.puffyan.us
0.0.0.0 invidious.snopyta.org
0.0.0.0 yewtu.be
0.0.0.0 invidious.kavin.rocks
0.0.0.0 inv.riverside.rocks
0.0.0.0 invidious.namazso.eu
0.0.0.0 invidious.nerdvpn.de
0.0.0.0 invidious.projectsegfau.lt
0.0.0.0 invidious.slipfox.xyz
0.0.0.0 invidious.privacydev.net
0.0.0.0 invidious.perennialte.ch
0.0.0.0 invidious.protokoll-11.de
0.0.0.0 invidious.einfachzocken.eu
0.0.0.0 invidious.fdn.fr
0.0.0.0 inv.in.projectsegfau.lt
0.0.0.0 invidious.tiekoetter.com
0.0.0.0 invidious.lunar.icu
0.0.0.0 iv.ggtyler.dev
0.0.0.0 iv.melmac.space
0.0.0.0 piped.video
0.0.0.0 www.piped.video
0.0.0.0 piped.kavin.rocks
0.0.0.0 piped.mha.fi
0.0.0.0 piped.mint.lgbt
0.0.0.0 piped.projectsegfau.lt
0.0.0.0 piped.privacydev.net
0.0.0.0 piped.smnz.de
0.0.0.0 piped.adminforge.de
0.0.0.0 watch.whatever.social
0.0.0.0 piped.lunar.icu
0.0.0.0 viewtube.io
0.0.0.0 www.viewtube.io
0.0.0.0 freetube.io
0.0.0.0 www.freetube.io
0.0.0.0 tubo.media
0.0.0.0 www.tubo.media
0.0.0.0 materialious.nadeko.net
0.0.0.0 clipious.org
0.0.0.0 www.clipious.org
0.0.0.0 newpipe.net
0.0.0.0 www.newpipe.net
0.0.0.0 newpipe.schabi.org
0.0.0.0 grayjay.app
0.0.0.0 www.grayjay.app
0.0.0.0 libretube.dev
0.0.0.0 www.libretube.dev
0.0.0.0 hyperion.deishelon.com
0.0.0.0 inv.n8pjl.ca
0.0.0.0 inv.zzls.xyz
0.0.0.0 inv.tux.pizza
0.0.0.0 invidious.incogniweb.net
0.0.0.0 invidious.drgns.space
0.0.0.0 invidious.io.lol
# Discord (media only - voice chat allowed)
0.0.0.0 cdn.discordapp.com
0.0.0.0 media.discordapp.net
0.0.0.0 images-ext-1.discordapp.net
0.0.0.0 images-ext-2.discordapp.net
0.0.0.0 tenor.com
0.0.0.0 giphy.com
# Food Delivery Services
# Polish services
0.0.0.0 pyszne.pl
0.0.0.0 www.pyszne.pl
0.0.0.0 m.pyszne.pl
0.0.0.0 api.pyszne.pl
0.0.0.0 app.pyszne.pl
0.0.0.0 glovo.com
0.0.0.0 www.glovo.com
0.0.0.0 m.glovo.com
0.0.0.0 api.glovo.com
0.0.0.0 glovoapp.com
0.0.0.0 www.glovoapp.com
0.0.0.0 bolt.eu
:: bolt.eu
0.0.0.0 www.bolt.eu
:: www.bolt.eu
0.0.0.0 food.bolt.eu
:: food.bolt.eu
0.0.0.0 m.bolt.eu
:: m.bolt.eu
0.0.0.0 api.bolt.eu
:: api.bolt.eu
0.0.0.0 node.bolt.eu
:: node.bolt.eu
0.0.0.0 gw.bolt.eu
:: gw.bolt.eu
0.0.0.0 client-api.bolt.eu
:: client-api.bolt.eu
0.0.0.0 auth.bolt.eu
:: auth.bolt.eu
0.0.0.0 cdn.bolt.eu
:: cdn.bolt.eu
0.0.0.0 images.bolt.eu
:: images.bolt.eu
0.0.0.0 static.bolt.eu
:: static.bolt.eu
0.0.0.0 assets.bolt.eu
:: assets.bolt.eu
0.0.0.0 fleet.bolt.eu
:: fleet.bolt.eu
0.0.0.0 user.bolt.eu
:: user.bolt.eu
0.0.0.0 courier.bolt.eu
:: courier.bolt.eu
0.0.0.0 rider.bolt.eu
:: rider.bolt.eu
0.0.0.0 restaurant.bolt.eu
:: restaurant.bolt.eu
0.0.0.0 partner-food.bolt.eu
:: partner-food.bolt.eu
0.0.0.0 wolt.com
0.0.0.0 www.wolt.com
0.0.0.0 m.wolt.com
0.0.0.0 api.wolt.com
0.0.0.0 restaurant-api.wolt.com
0.0.0.0 consumer-api.wolt.com
0.0.0.0 woltwojta.pl
0.0.0.0 www.woltwojta.pl
0.0.0.0 jush.pl
0.0.0.0 www.jush.pl
0.0.0.0 m.jush.pl
0.0.0.0 api.jush.pl
0.0.0.0 delio.pl
0.0.0.0 www.delio.pl
0.0.0.0 m.delio.pl
0.0.0.0 api.delio.pl
0.0.0.0 delio.com
0.0.0.0 www.delio.com
0.0.0.0 delio.com.pl
0.0.0.0 www.delio.com.pl
0.0.0.0 api.delio.com.pl
0.0.0.0 lisek.app
0.0.0.0 www.lisek.app
0.0.0.0 api.lisek.app
0.0.0.0 stava.app
0.0.0.0 www.stava.app
0.0.0.0 api.stava.app
0.0.0.0 barbora.pl
0.0.0.0 www.barbora.pl
0.0.0.0 api.barbora.pl
0.0.0.0 frisco.pl
0.0.0.0 www.frisco.pl
0.0.0.0 api.frisco.pl
0.0.0.0 szama.pl
0.0.0.0 www.szama.pl
0.0.0.0 api.szama.pl
0.0.0.0 auchandirect.pl
0.0.0.0 www.auchandirect.pl
0.0.0.0 zakupy.biedronka.pl
0.0.0.0 ezakupy.tesco.pl
0.0.0.0 www.ezakupy.tesco.pl
# International services
0.0.0.0 ubereats.com
0.0.0.0 www.ubereats.com
0.0.0.0 m.ubereats.com
0.0.0.0 api.ubereats.com
0.0.0.0 uber.com
0.0.0.0 www.uber.com
0.0.0.0 m.uber.com
0.0.0.0 api.uber.com
0.0.0.0 login.uber.com
0.0.0.0 auth.uber.com
0.0.0.0 deliveroo.com
0.0.0.0 www.deliveroo.com
0.0.0.0 m.deliveroo.com
0.0.0.0 api.deliveroo.com
0.0.0.0 deliveroo.co.uk
0.0.0.0 www.deliveroo.co.uk
0.0.0.0 foodpanda.com
0.0.0.0 www.foodpanda.com
0.0.0.0 m.foodpanda.com
0.0.0.0 api.foodpanda.com
0.0.0.0 grubhub.com
0.0.0.0 www.grubhub.com
0.0.0.0 m.grubhub.com
0.0.0.0 api.grubhub.com
0.0.0.0 doordash.com
0.0.0.0 www.doordash.com
0.0.0.0 m.doordash.com
0.0.0.0 api.doordash.com
0.0.0.0 justeat.com
0.0.0.0 www.justeat.com
0.0.0.0 m.justeat.com
0.0.0.0 justeat.co.uk
0.0.0.0 www.justeat.co.uk
0.0.0.0 postmates.com
0.0.0.0 www.postmates.com
0.0.0.0 seamless.com
0.0.0.0 www.seamless.com
0.0.0.0 getir.com
0.0.0.0 www.getir.com
0.0.0.0 api.getir.com
0.0.0.0 flink.com
0.0.0.0 www.flink.com
0.0.0.0 gorillas.io
0.0.0.0 www.gorillas.io
0.0.0.0 gopuff.com
0.0.0.0 www.gopuff.com
0.0.0.0 instacart.com
0.0.0.0 www.instacart.com
0.0.0.0 takeaway.com
0.0.0.0 www.takeaway.com
0.0.0.0 api.takeaway.com
# Fast Food
0.0.0.0 mcdonalds.com
0.0.0.0 www.mcdonalds.com
0.0.0.0 mcdonalds.pl
0.0.0.0 www.mcdonalds.pl
0.0.0.0 kfc.com
0.0.0.0 www.kfc.com
0.0.0.0 kfc.pl
0.0.0.0 www.kfc.pl
0.0.0.0 burgerking.com
0.0.0.0 www.burgerking.com
0.0.0.0 pizzahut.com
0.0.0.0 www.pizzahut.com
0.0.0.0 dominos.com
0.0.0.0 www.dominos.com

View File

@ -0,0 +1,243 @@
#!/bin/bash
# The install, status, disable and app-blocking subcommands.
#
# Sourced by update_android_hosts.sh; split out to keep it under the 250-line cap.
# Sourced rather than run, so it inherits the caller's strict mode.
# Install/update the guardian module
cmd_install() {
ensure_device_ready
local module_zip
module_zip=$(build_module)
log "Pushing module to device..."
adb push "$module_zip" /sdcard/android_guardian.zip || die "Failed to push module"
log "Installing module..."
adb shell "su -c 'mkdir -p $MODULE_DEST'" || die "Failed to create module directory"
adb shell "su -c 'cd $MODULE_DEST && unzip -o /sdcard/android_guardian.zip'" || die "Failed to extract module"
adb shell "su -c 'chmod 755 $MODULE_DEST/*.sh'"
adb shell "su -c 'rm /sdcard/android_guardian.zip'"
# Set up guardian data directory
log "Setting up guardian data..."
adb shell "su -c 'mkdir -p $GUARDIAN_DATA_DIR'"
adb shell "su -c 'echo ENABLED > $GUARDIAN_DATA_DIR/control'"
# Copy blocked apps list
adb push "$GUARDIAN_MODULE_DIR/blocked_apps.txt" /sdcard/blocked_apps.txt || die "Failed to push blocked apps list"
adb shell "su -c 'cp /sdcard/blocked_apps.txt $GUARDIAN_DATA_DIR/blocked_apps.txt'"
adb shell "su -c 'rm /sdcard/blocked_apps.txt'"
# Create hosts backup for tamper protection
adb shell "su -c 'cp $MODULE_DEST/system/etc/hosts $GUARDIAN_DATA_DIR/hosts.backup'"
# Immediately uninstall any currently installed blocked apps
log "Checking for blocked apps to remove..."
uninstall_blocked_apps
echo ""
echo "=========================================="
echo " ✓ Android Guardian installed!"
echo "=========================================="
echo ""
echo "Features enabled:"
echo " • Hosts-based ad/tracker blocking"
echo " • App installation blocking"
echo " • Tamper protection"
echo ""
echo "⚠️ This can ONLY be controlled via ADB:"
echo " Disable: $0 disable"
echo " Enable: $0 enable"
echo " Status: $0 status"
echo ""
echo "Reboot your device to activate the module."
echo ""
}
# Uninstall currently installed blocked apps
uninstall_blocked_apps() {
local blocked_apps
blocked_apps=$(grep -v '^#' "$GUARDIAN_MODULE_DIR/blocked_apps.txt" | grep -v '^$' || true)
for package in $blocked_apps; do
if adb shell "pm list packages" 2>/dev/null | grep -q "package:$package"; then
log "Uninstalling blocked app: $package"
adb shell "pm uninstall $package" 2>/dev/null || true
fi
done
}
# Show status
cmd_status() {
ensure_device_ready
echo ""
echo "=== Android Guardian Status ==="
echo ""
# Check if module is installed
if adb shell "su -c 'test -d $MODULE_DEST'" 2>/dev/null; then
echo "Module: INSTALLED"
else
echo "Module: NOT INSTALLED"
return
fi
# Check control status
local status
status=$(adb shell "su -c 'cat $GUARDIAN_DATA_DIR/control 2>/dev/null || echo UNKNOWN'" | tr -d '\r')
echo "Status: $status"
# Check if module is "disabled" in Magisk UI (should be auto-fixed by watchdog)
local magisk_disabled
if adb shell "su -c 'test -f $MODULE_DEST/disable'" 2>/dev/null; then
magisk_disabled="YES (watchdog should fix this)"
else
magisk_disabled="No"
fi
echo "Magisk UI disabled: $magisk_disabled"
# Check if watchdog is running
local watchdog_running
watchdog_running=$(adb shell "su -c 'pgrep -f watchdog.sh 2>/dev/null | wc -l'" | tr -d '\r')
if [ "$watchdog_running" -gt 0 ] 2>/dev/null; then
echo "Watchdog: RUNNING ($watchdog_running processes)"
else
echo "Watchdog: NOT RUNNING (reboot phone to start)"
fi
# Check hosts file
local hosts_entries
hosts_entries=$(adb shell "su -c 'grep -c \"^0.0.0.0\" /system/etc/hosts 2>/dev/null || echo 0'" | tr -d '\r')
echo "Blocked domains: $hosts_entries"
# Check blocked apps count
local blocked_count
blocked_count=$(adb shell "su -c 'grep -v \"^#\" $GUARDIAN_DATA_DIR/blocked_apps.txt 2>/dev/null | grep -v \"^$\" | wc -l || echo 0'" | tr -d '\r')
echo "Blocked app rules: $blocked_count packages"
echo ""
echo "Protection: Module cannot be disabled from Magisk UI"
echo " Only controllable via: $0 disable/enable"
echo ""
}
# Disable guardian
cmd_disable() {
ensure_device_ready
log "Disabling Android Guardian..."
adb shell "su -c 'echo DISABLED > $GUARDIAN_DATA_DIR/control'" || die "Failed to disable guardian"
echo ""
echo "✓ Guardian DISABLED"
echo " Hosts blocking still active until reboot"
echo " App blocking service paused"
echo ""
echo "To re-enable: $0 enable"
echo ""
}
# Enable guardian
cmd_enable() {
ensure_device_ready
log "Enabling Android Guardian..."
adb shell "su -c 'echo ENABLED > $GUARDIAN_DATA_DIR/control'" || die "Failed to enable guardian"
echo ""
echo "✓ Guardian ENABLED"
echo ""
}
# Uninstall module
cmd_uninstall() {
ensure_device_ready
# Check if disabled first
local status
status=$(adb shell "su -c 'cat $GUARDIAN_DATA_DIR/control 2>/dev/null || echo ENABLED'" | tr -d '\r')
if [[ $status != "DISABLED" ]]; then
echo ""
echo "⚠️ Guardian must be disabled before uninstalling!"
echo " Run: $0 disable"
echo " Then: $0 uninstall"
echo ""
exit 1
fi
log "Removing Android Guardian..."
adb shell "su -c 'rm -rf $MODULE_DEST'"
adb shell "su -c 'rm -rf $GUARDIAN_DATA_DIR'"
echo ""
echo "✓ Guardian uninstalled"
echo " Reboot to remove hosts blocking"
echo ""
}
# Show logs
cmd_logs() {
ensure_device_ready
echo "=== Guardian Logs ==="
adb shell "su -c 'cat $GUARDIAN_DATA_DIR/guardian.log 2>/dev/null || echo \"No logs yet\"'"
}
# Block an app
cmd_block_app() {
local package="${1:-}"
if [[ -z $package ]]; then
echo "Usage: $0 block-app <package.name>"
echo "Example: $0 block-app com.ubercab.eats"
exit 1
fi
ensure_device_ready
log "Adding $package to block list..."
adb shell "su -c 'echo \"$package\" >> $GUARDIAN_DATA_DIR/blocked_apps.txt'"
# Also add to local file
echo "$package" >>"$GUARDIAN_MODULE_DIR/blocked_apps.txt"
# Try to uninstall if currently installed
if adb shell "pm list packages" 2>/dev/null | grep -q "package:$package"; then
log "Uninstalling $package..."
adb shell "pm uninstall $package" 2>/dev/null || true
fi
echo "✓ $package added to block list"
}
# Unblock an app
cmd_unblock_app() {
local package="${1:-}"
if [[ -z $package ]]; then
echo "Usage: $0 unblock-app <package.name>"
exit 1
fi
ensure_device_ready
log "Removing $package from block list..."
adb shell "su -c 'grep -v \"^$package\$\" $GUARDIAN_DATA_DIR/blocked_apps.txt > $GUARDIAN_DATA_DIR/blocked_apps.tmp && mv $GUARDIAN_DATA_DIR/blocked_apps.tmp $GUARDIAN_DATA_DIR/blocked_apps.txt'"
# Also remove from local file
grep -v "^$package$" "$GUARDIAN_MODULE_DIR/blocked_apps.txt" >"$GUARDIAN_MODULE_DIR/blocked_apps.tmp" && mv "$GUARDIAN_MODULE_DIR/blocked_apps.tmp" "$GUARDIAN_MODULE_DIR/blocked_apps.txt"
echo "✓ $package removed from block list"
}
# List blocked apps
cmd_list_blocked() {
ensure_device_ready
echo "=== Blocked Apps ==="
adb shell "su -c 'cat $GUARDIAN_DATA_DIR/blocked_apps.txt 2>/dev/null'" | grep -v "^#" | grep -v "^$" || echo "No blocked apps"
}

View File

@ -0,0 +1,210 @@
#!/bin/bash
# Device discovery, pairing and connection.
#
# Sourced by update_android_hosts.sh; split out to keep it under the 250-line cap.
# Sourced rather than run, so it inherits the caller's strict mode.
# Discover Android devices on the network using mDNS
discover_android_device() {
local found_address=""
# Ensure avahi-browse is available
if ! command -v avahi-browse &>/dev/null; then
if command -v pacman &>/dev/null; then
echo "Installing avahi for device discovery..." >&2
sudo pacman -S --noconfirm avahi nss-mdns &>/dev/null || true
sudo systemctl enable --now avahi-daemon &>/dev/null || true
elif command -v apt-get &>/dev/null; then
sudo apt-get install -y avahi-utils &>/dev/null || true
fi
fi
if command -v avahi-browse &>/dev/null; then
echo "Scanning for Android devices (5 seconds)..." >&2
# Android wireless debugging advertises as _adb-tls-connect._tcp
local discovery_result
discovery_result=$(timeout 5 avahi-browse -rpt _adb-tls-connect._tcp 2>/dev/null | grep "^=" | head -1)
if [[ -n $discovery_result ]]; then
# Parse: =;eth0;IPv4;adb-...;_adb-tls-connect._tcp;local;hostname.local;192.168.x.x;port;...
local ip port
ip=$(echo "$discovery_result" | cut -d';' -f8)
port=$(echo "$discovery_result" | cut -d';' -f9)
if [[ -n $ip && -n $port ]]; then
found_address="$ip:$port"
echo "✓ Found device: $found_address" >&2
fi
fi
fi
# Fallback: try adb's mdns discovery
if [[ -z $found_address ]]; then
echo "Trying adb mdns discovery..." >&2
# adb can discover devices via mdns
local mdns_result
mdns_result=$(timeout 5 adb mdns services 2>/dev/null | grep -E "adb-tls-connect|_adb\._tcp" | head -1)
if [[ -n $mdns_result ]]; then
# Try to extract IP:port from the result
local service_name
service_name=$(echo "$mdns_result" | awk '{print $1}')
if [[ -n $service_name ]]; then
# Try connecting via service name
echo "Found service: $service_name" >&2
fi
fi
fi
# Return found address (or empty)
echo "$found_address"
}
# Pair with device over WiFi (Android 11+)
cmd_pair() {
ensure_adb_installed
echo ""
echo "=== Wireless ADB Pairing (Android 11+) ==="
echo ""
echo "On your phone:"
echo " 1. Go to Settings > Developer Options > Wireless debugging"
echo " 2. Enable Wireless debugging"
echo " 3. Tap 'Pair device with pairing code'"
echo " 4. Note the IP:port and pairing code shown"
echo ""
read -rp "Enter pairing IP:port (e.g., 192.168.1.100:37123): " pair_address
read -rp "Enter pairing code: " pair_code
if [[ -z $pair_address || -z $pair_code ]]; then
die "Pairing address and code are required"
fi
log "Pairing with device at $pair_address..."
if adb pair "$pair_address" "$pair_code"; then
echo ""
echo "✓ Pairing successful!"
echo ""
echo "Now get the connection address:"
echo " On phone: Wireless debugging screen shows IP:port under 'IP address & Port'"
echo " (This is DIFFERENT from the pairing port)"
echo ""
read -rp "Enter connection IP:port (e.g., 192.168.1.100:41567): " connect_address
if [[ -n $connect_address ]]; then
# Save for future connections
mkdir -p "$(dirname "$WIRELESS_CONFIG")"
echo "$connect_address" >"$WIRELESS_CONFIG"
log "Saved connection address for future use"
# Connect now
cmd_connect
fi
else
die "Pairing failed. Make sure the code is correct and you're on the same network."
fi
}
# Connect to already-paired device
cmd_connect() {
ensure_adb_installed
local connect_address=""
# Check for saved address
if [[ -f $WIRELESS_CONFIG ]]; then
connect_address=$(cat "$WIRELESS_CONFIG")
log "Using saved address: $connect_address"
fi
# Try auto-discovery if no saved address
if [[ -z $connect_address ]]; then
echo ""
log "Searching for Android devices on network..."
connect_address=$(discover_android_device)
fi
# Manual fallback
if [[ -z $connect_address ]]; then
echo ""
echo "Auto-discovery failed. Enter address manually."
echo "On phone: Settings > Developer Options > Wireless debugging"
echo "Look for IP address & Port (NOT the pairing port)"
echo ""
read -rp "Enter connection IP:port (e.g., 192.168.1.100:41567): " connect_address
if [[ -z $connect_address ]]; then
die "Connection address is required"
fi
fi
# Save for future
mkdir -p "$(dirname "$WIRELESS_CONFIG")"
echo "$connect_address" >"$WIRELESS_CONFIG"
log "Connecting to $connect_address..."
if adb connect "$connect_address" | grep -q "connected"; then
echo ""
echo "✓ Connected to device wirelessly!"
echo ""
# Verify connection
if adb devices | grep -q "$connect_address"; then
echo "Device ready. You can now run other commands."
fi
else
echo ""
echo "Connection failed. Possible issues:"
echo " - Wireless debugging not enabled on phone"
echo " - Phone and PC not on same WiFi network"
echo " - Port changed (check Wireless debugging screen)"
echo " - May need to pair first: $0 pair"
echo ""
# Clear saved config since it failed
rm -f "$WIRELESS_CONFIG"
exit 1
fi
}
# Disconnect wireless ADB
cmd_disconnect() {
ensure_adb_installed
log "Disconnecting all wireless devices..."
adb disconnect
echo "✓ Disconnected"
}
# Check device connection and root
ensure_device_ready() {
ensure_adb_installed
# Check if any device is connected
if ! adb devices | grep -qE "device$|:.*device$"; then
echo ""
echo "No device connected!"
echo ""
echo "Options:"
echo " 1. Connect USB cable with debugging enabled"
echo " 2. Use wireless: $0 pair (first time) or $0 connect"
echo ""
# Check if we have a saved wireless config
if [[ -f $WIRELESS_CONFIG ]]; then
read -rp "Try connecting to saved wireless device? [Y/n]: " try_wireless
if [[ ${try_wireless,,} != "n" ]]; then
cmd_connect
else
exit 1
fi
else
exit 1
fi
fi
check_adb_device
check_adb_root
}

View File

@ -0,0 +1,49 @@
#!/bin/bash
# Building the Magisk hosts module.
#
# Sourced by update_android_hosts.sh; split out to keep it under the 250-line cap.
# Sourced rather than run, so it inherits the caller's strict mode.
# Build the module zip
build_module() {
local tmp_dir="$WORK_DIR/guardian_module"
local module_zip="$WORK_DIR/android_guardian.zip"
echo "[BUILD] Building Android Guardian module..." >&2
rm -rf "$tmp_dir"
mkdir -p "$tmp_dir/system/etc"
# Copy module files
cp "$GUARDIAN_MODULE_DIR/module.prop" "$tmp_dir/"
cp "$GUARDIAN_MODULE_DIR/service.sh" "$tmp_dir/"
cp "$GUARDIAN_MODULE_DIR/post-fs-data.sh" "$tmp_dir/"
cp "$GUARDIAN_MODULE_DIR/uninstall.sh" "$tmp_dir/"
# Build hosts file
local hosts_file="$tmp_dir/system/etc/hosts"
if [[ -f /etc/hosts.stevenblack ]]; then
echo "[BUILD] Using StevenBlack hosts cache..." >&2
cp /etc/hosts.stevenblack "$hosts_file"
elif [[ -f /etc/hosts ]]; then
echo "[BUILD] Using /etc/hosts..." >&2
cp /etc/hosts "$hosts_file"
else
die "No hosts file found"
fi
# Append custom blocking entries
# The blocklist is a data file, not a heredoc: 248 lines of hosts
# entries that belong under data/ where they can be diffed and edited
# without touching shell.
cat "$SCRIPT_DIR/data/android_guardian_blocklist.hosts" >>"$hosts_file"
local total_entries
total_entries=$(grep -c "^0\.0\.0\.0 " "$hosts_file" || echo 0)
echo "[BUILD] Hosts file contains $total_entries blocked domains" >&2
# Create zip
(cd "$tmp_dir" && zip -r "$module_zip" . -x "*.DS_Store") >/dev/null
echo "$module_zip"
}

View File

@ -4,7 +4,7 @@
set -euo pipefail
# Source common library
SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
SCRIPT_DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"
# shellcheck source=../../lib/common.sh
source "$SCRIPT_DIR/../../lib/common.sh"
# shellcheck source=../../lib/android.sh
@ -83,737 +83,13 @@ EOF
# Wireless ADB connection file
WIRELESS_CONFIG="$HOME/.config/android_guardian_wireless"
# Discover Android devices on the network using mDNS
discover_android_device() {
local found_address=""
# shellcheck source=lib/android_device.sh
source "$SCRIPT_DIR/lib/android_device.sh"
# shellcheck source=lib/android_module.sh
source "$SCRIPT_DIR/lib/android_module.sh"
# shellcheck source=lib/android_commands.sh
source "$SCRIPT_DIR/lib/android_commands.sh"
# Ensure avahi-browse is available
if ! command -v avahi-browse &>/dev/null; then
if command -v pacman &>/dev/null; then
echo "Installing avahi for device discovery..." >&2
sudo pacman -S --noconfirm avahi nss-mdns &>/dev/null || true
sudo systemctl enable --now avahi-daemon &>/dev/null || true
elif command -v apt-get &>/dev/null; then
sudo apt-get install -y avahi-utils &>/dev/null || true
fi
fi
if command -v avahi-browse &>/dev/null; then
echo "Scanning for Android devices (5 seconds)..." >&2
# Android wireless debugging advertises as _adb-tls-connect._tcp
local discovery_result
discovery_result=$(timeout 5 avahi-browse -rpt _adb-tls-connect._tcp 2>/dev/null | grep "^=" | head -1)
if [[ -n $discovery_result ]]; then
# Parse: =;eth0;IPv4;adb-...;_adb-tls-connect._tcp;local;hostname.local;192.168.x.x;port;...
local ip port
ip=$(echo "$discovery_result" | cut -d';' -f8)
port=$(echo "$discovery_result" | cut -d';' -f9)
if [[ -n $ip && -n $port ]]; then
found_address="$ip:$port"
echo "✓ Found device: $found_address" >&2
fi
fi
fi
# Fallback: try adb's mdns discovery
if [[ -z $found_address ]]; then
echo "Trying adb mdns discovery..." >&2
# adb can discover devices via mdns
local mdns_result
mdns_result=$(timeout 5 adb mdns services 2>/dev/null | grep -E "adb-tls-connect|_adb\._tcp" | head -1)
if [[ -n $mdns_result ]]; then
# Try to extract IP:port from the result
local service_name
service_name=$(echo "$mdns_result" | awk '{print $1}')
if [[ -n $service_name ]]; then
# Try connecting via service name
echo "Found service: $service_name" >&2
fi
fi
fi
# Return found address (or empty)
echo "$found_address"
}
# Pair with device over WiFi (Android 11+)
cmd_pair() {
ensure_adb_installed
echo ""
echo "=== Wireless ADB Pairing (Android 11+) ==="
echo ""
echo "On your phone:"
echo " 1. Go to Settings > Developer Options > Wireless debugging"
echo " 2. Enable Wireless debugging"
echo " 3. Tap 'Pair device with pairing code'"
echo " 4. Note the IP:port and pairing code shown"
echo ""
read -rp "Enter pairing IP:port (e.g., 192.168.1.100:37123): " pair_address
read -rp "Enter pairing code: " pair_code
if [[ -z $pair_address || -z $pair_code ]]; then
die "Pairing address and code are required"
fi
log "Pairing with device at $pair_address..."
if adb pair "$pair_address" "$pair_code"; then
echo ""
echo "✓ Pairing successful!"
echo ""
echo "Now get the connection address:"
echo " On phone: Wireless debugging screen shows IP:port under 'IP address & Port'"
echo " (This is DIFFERENT from the pairing port)"
echo ""
read -rp "Enter connection IP:port (e.g., 192.168.1.100:41567): " connect_address
if [[ -n $connect_address ]]; then
# Save for future connections
mkdir -p "$(dirname "$WIRELESS_CONFIG")"
echo "$connect_address" >"$WIRELESS_CONFIG"
log "Saved connection address for future use"
# Connect now
cmd_connect
fi
else
die "Pairing failed. Make sure the code is correct and you're on the same network."
fi
}
# Connect to already-paired device
cmd_connect() {
ensure_adb_installed
local connect_address=""
# Check for saved address
if [[ -f $WIRELESS_CONFIG ]]; then
connect_address=$(cat "$WIRELESS_CONFIG")
log "Using saved address: $connect_address"
fi
# Try auto-discovery if no saved address
if [[ -z $connect_address ]]; then
echo ""
log "Searching for Android devices on network..."
connect_address=$(discover_android_device)
fi
# Manual fallback
if [[ -z $connect_address ]]; then
echo ""
echo "Auto-discovery failed. Enter address manually."
echo "On phone: Settings > Developer Options > Wireless debugging"
echo "Look for IP address & Port (NOT the pairing port)"
echo ""
read -rp "Enter connection IP:port (e.g., 192.168.1.100:41567): " connect_address
if [[ -z $connect_address ]]; then
die "Connection address is required"
fi
fi
# Save for future
mkdir -p "$(dirname "$WIRELESS_CONFIG")"
echo "$connect_address" >"$WIRELESS_CONFIG"
log "Connecting to $connect_address..."
if adb connect "$connect_address" | grep -q "connected"; then
echo ""
echo "✓ Connected to device wirelessly!"
echo ""
# Verify connection
if adb devices | grep -q "$connect_address"; then
echo "Device ready. You can now run other commands."
fi
else
echo ""
echo "Connection failed. Possible issues:"
echo " - Wireless debugging not enabled on phone"
echo " - Phone and PC not on same WiFi network"
echo " - Port changed (check Wireless debugging screen)"
echo " - May need to pair first: $0 pair"
echo ""
# Clear saved config since it failed
rm -f "$WIRELESS_CONFIG"
exit 1
fi
}
# Disconnect wireless ADB
cmd_disconnect() {
ensure_adb_installed
log "Disconnecting all wireless devices..."
adb disconnect
echo "✓ Disconnected"
}
# Check device connection and root
ensure_device_ready() {
ensure_adb_installed
# Check if any device is connected
if ! adb devices | grep -qE "device$|:.*device$"; then
echo ""
echo "No device connected!"
echo ""
echo "Options:"
echo " 1. Connect USB cable with debugging enabled"
echo " 2. Use wireless: $0 pair (first time) or $0 connect"
echo ""
# Check if we have a saved wireless config
if [[ -f $WIRELESS_CONFIG ]]; then
read -rp "Try connecting to saved wireless device? [Y/n]: " try_wireless
if [[ ${try_wireless,,} != "n" ]]; then
cmd_connect
else
exit 1
fi
else
exit 1
fi
fi
check_adb_device
check_adb_root
}
# Build the module zip
build_module() {
local tmp_dir="$WORK_DIR/guardian_module"
local module_zip="$WORK_DIR/android_guardian.zip"
echo "[BUILD] Building Android Guardian module..." >&2
rm -rf "$tmp_dir"
mkdir -p "$tmp_dir/system/etc"
# Copy module files
cp "$GUARDIAN_MODULE_DIR/module.prop" "$tmp_dir/"
cp "$GUARDIAN_MODULE_DIR/service.sh" "$tmp_dir/"
cp "$GUARDIAN_MODULE_DIR/post-fs-data.sh" "$tmp_dir/"
cp "$GUARDIAN_MODULE_DIR/uninstall.sh" "$tmp_dir/"
# Build hosts file
local hosts_file="$tmp_dir/system/etc/hosts"
if [[ -f /etc/hosts.stevenblack ]]; then
echo "[BUILD] Using StevenBlack hosts cache..." >&2
cp /etc/hosts.stevenblack "$hosts_file"
elif [[ -f /etc/hosts ]]; then
echo "[BUILD] Using /etc/hosts..." >&2
cp /etc/hosts "$hosts_file"
else
die "No hosts file found"
fi
# Append custom blocking entries
cat >>"$hosts_file" <<'CUSTOM_EOF'
# ============================================
# Custom blocking entries - Android Guardian
# ============================================
# YouTube
0.0.0.0 youtube.com
0.0.0.0 www.youtube.com
0.0.0.0 m.youtube.com
0.0.0.0 youtu.be
0.0.0.0 youtube-nocookie.com
0.0.0.0 www.youtube-nocookie.com
0.0.0.0 youtubei.googleapis.com
0.0.0.0 youtube.googleapis.com
0.0.0.0 yt3.ggpht.com
0.0.0.0 ytimg.com
0.0.0.0 i.ytimg.com
0.0.0.0 s.ytimg.com
0.0.0.0 i9.ytimg.com
0.0.0.0 googlevideo.com
# Alternative YouTube Frontends (Invidious, Piped, etc.)
0.0.0.0 invidious.io
0.0.0.0 www.invidious.io
0.0.0.0 invidio.us
0.0.0.0 vid.puffyan.us
0.0.0.0 invidious.snopyta.org
0.0.0.0 yewtu.be
0.0.0.0 invidious.kavin.rocks
0.0.0.0 inv.riverside.rocks
0.0.0.0 invidious.namazso.eu
0.0.0.0 invidious.nerdvpn.de
0.0.0.0 invidious.projectsegfau.lt
0.0.0.0 invidious.slipfox.xyz
0.0.0.0 invidious.privacydev.net
0.0.0.0 invidious.perennialte.ch
0.0.0.0 invidious.protokoll-11.de
0.0.0.0 invidious.einfachzocken.eu
0.0.0.0 invidious.fdn.fr
0.0.0.0 inv.in.projectsegfau.lt
0.0.0.0 invidious.tiekoetter.com
0.0.0.0 invidious.lunar.icu
0.0.0.0 iv.ggtyler.dev
0.0.0.0 iv.melmac.space
0.0.0.0 piped.video
0.0.0.0 www.piped.video
0.0.0.0 piped.kavin.rocks
0.0.0.0 piped.mha.fi
0.0.0.0 piped.mint.lgbt
0.0.0.0 piped.projectsegfau.lt
0.0.0.0 piped.privacydev.net
0.0.0.0 piped.smnz.de
0.0.0.0 piped.adminforge.de
0.0.0.0 watch.whatever.social
0.0.0.0 piped.lunar.icu
0.0.0.0 viewtube.io
0.0.0.0 www.viewtube.io
0.0.0.0 freetube.io
0.0.0.0 www.freetube.io
0.0.0.0 tubo.media
0.0.0.0 www.tubo.media
0.0.0.0 materialious.nadeko.net
0.0.0.0 clipious.org
0.0.0.0 www.clipious.org
0.0.0.0 newpipe.net
0.0.0.0 www.newpipe.net
0.0.0.0 newpipe.schabi.org
0.0.0.0 grayjay.app
0.0.0.0 www.grayjay.app
0.0.0.0 libretube.dev
0.0.0.0 www.libretube.dev
0.0.0.0 hyperion.deishelon.com
0.0.0.0 inv.n8pjl.ca
0.0.0.0 inv.zzls.xyz
0.0.0.0 inv.tux.pizza
0.0.0.0 invidious.incogniweb.net
0.0.0.0 invidious.drgns.space
0.0.0.0 invidious.io.lol
# Discord (media only - voice chat allowed)
0.0.0.0 cdn.discordapp.com
0.0.0.0 media.discordapp.net
0.0.0.0 images-ext-1.discordapp.net
0.0.0.0 images-ext-2.discordapp.net
0.0.0.0 tenor.com
0.0.0.0 giphy.com
# Food Delivery Services
# Polish services
0.0.0.0 pyszne.pl
0.0.0.0 www.pyszne.pl
0.0.0.0 m.pyszne.pl
0.0.0.0 api.pyszne.pl
0.0.0.0 app.pyszne.pl
0.0.0.0 glovo.com
0.0.0.0 www.glovo.com
0.0.0.0 m.glovo.com
0.0.0.0 api.glovo.com
0.0.0.0 glovoapp.com
0.0.0.0 www.glovoapp.com
0.0.0.0 bolt.eu
:: bolt.eu
0.0.0.0 www.bolt.eu
:: www.bolt.eu
0.0.0.0 food.bolt.eu
:: food.bolt.eu
0.0.0.0 m.bolt.eu
:: m.bolt.eu
0.0.0.0 api.bolt.eu
:: api.bolt.eu
0.0.0.0 node.bolt.eu
:: node.bolt.eu
0.0.0.0 gw.bolt.eu
:: gw.bolt.eu
0.0.0.0 client-api.bolt.eu
:: client-api.bolt.eu
0.0.0.0 auth.bolt.eu
:: auth.bolt.eu
0.0.0.0 cdn.bolt.eu
:: cdn.bolt.eu
0.0.0.0 images.bolt.eu
:: images.bolt.eu
0.0.0.0 static.bolt.eu
:: static.bolt.eu
0.0.0.0 assets.bolt.eu
:: assets.bolt.eu
0.0.0.0 fleet.bolt.eu
:: fleet.bolt.eu
0.0.0.0 user.bolt.eu
:: user.bolt.eu
0.0.0.0 courier.bolt.eu
:: courier.bolt.eu
0.0.0.0 rider.bolt.eu
:: rider.bolt.eu
0.0.0.0 restaurant.bolt.eu
:: restaurant.bolt.eu
0.0.0.0 partner-food.bolt.eu
:: partner-food.bolt.eu
0.0.0.0 wolt.com
0.0.0.0 www.wolt.com
0.0.0.0 m.wolt.com
0.0.0.0 api.wolt.com
0.0.0.0 restaurant-api.wolt.com
0.0.0.0 consumer-api.wolt.com
0.0.0.0 woltwojta.pl
0.0.0.0 www.woltwojta.pl
0.0.0.0 jush.pl
0.0.0.0 www.jush.pl
0.0.0.0 m.jush.pl
0.0.0.0 api.jush.pl
0.0.0.0 delio.pl
0.0.0.0 www.delio.pl
0.0.0.0 m.delio.pl
0.0.0.0 api.delio.pl
0.0.0.0 delio.com
0.0.0.0 www.delio.com
0.0.0.0 delio.com.pl
0.0.0.0 www.delio.com.pl
0.0.0.0 api.delio.com.pl
0.0.0.0 lisek.app
0.0.0.0 www.lisek.app
0.0.0.0 api.lisek.app
0.0.0.0 stava.app
0.0.0.0 www.stava.app
0.0.0.0 api.stava.app
0.0.0.0 barbora.pl
0.0.0.0 www.barbora.pl
0.0.0.0 api.barbora.pl
0.0.0.0 frisco.pl
0.0.0.0 www.frisco.pl
0.0.0.0 api.frisco.pl
0.0.0.0 szama.pl
0.0.0.0 www.szama.pl
0.0.0.0 api.szama.pl
0.0.0.0 auchandirect.pl
0.0.0.0 www.auchandirect.pl
0.0.0.0 zakupy.biedronka.pl
0.0.0.0 ezakupy.tesco.pl
0.0.0.0 www.ezakupy.tesco.pl
# International services
0.0.0.0 ubereats.com
0.0.0.0 www.ubereats.com
0.0.0.0 m.ubereats.com
0.0.0.0 api.ubereats.com
0.0.0.0 uber.com
0.0.0.0 www.uber.com
0.0.0.0 m.uber.com
0.0.0.0 api.uber.com
0.0.0.0 login.uber.com
0.0.0.0 auth.uber.com
0.0.0.0 deliveroo.com
0.0.0.0 www.deliveroo.com
0.0.0.0 m.deliveroo.com
0.0.0.0 api.deliveroo.com
0.0.0.0 deliveroo.co.uk
0.0.0.0 www.deliveroo.co.uk
0.0.0.0 foodpanda.com
0.0.0.0 www.foodpanda.com
0.0.0.0 m.foodpanda.com
0.0.0.0 api.foodpanda.com
0.0.0.0 grubhub.com
0.0.0.0 www.grubhub.com
0.0.0.0 m.grubhub.com
0.0.0.0 api.grubhub.com
0.0.0.0 doordash.com
0.0.0.0 www.doordash.com
0.0.0.0 m.doordash.com
0.0.0.0 api.doordash.com
0.0.0.0 justeat.com
0.0.0.0 www.justeat.com
0.0.0.0 m.justeat.com
0.0.0.0 justeat.co.uk
0.0.0.0 www.justeat.co.uk
0.0.0.0 postmates.com
0.0.0.0 www.postmates.com
0.0.0.0 seamless.com
0.0.0.0 www.seamless.com
0.0.0.0 getir.com
0.0.0.0 www.getir.com
0.0.0.0 api.getir.com
0.0.0.0 flink.com
0.0.0.0 www.flink.com
0.0.0.0 gorillas.io
0.0.0.0 www.gorillas.io
0.0.0.0 gopuff.com
0.0.0.0 www.gopuff.com
0.0.0.0 instacart.com
0.0.0.0 www.instacart.com
0.0.0.0 takeaway.com
0.0.0.0 www.takeaway.com
0.0.0.0 api.takeaway.com
# Fast Food
0.0.0.0 mcdonalds.com
0.0.0.0 www.mcdonalds.com
0.0.0.0 mcdonalds.pl
0.0.0.0 www.mcdonalds.pl
0.0.0.0 kfc.com
0.0.0.0 www.kfc.com
0.0.0.0 kfc.pl
0.0.0.0 www.kfc.pl
0.0.0.0 burgerking.com
0.0.0.0 www.burgerking.com
0.0.0.0 pizzahut.com
0.0.0.0 www.pizzahut.com
0.0.0.0 dominos.com
0.0.0.0 www.dominos.com
CUSTOM_EOF
local total_entries
total_entries=$(grep -c "^0\.0\.0\.0 " "$hosts_file" || echo 0)
echo "[BUILD] Hosts file contains $total_entries blocked domains" >&2
# Create zip
(cd "$tmp_dir" && zip -r "$module_zip" . -x "*.DS_Store") >/dev/null
echo "$module_zip"
}
# Install/update the guardian module
cmd_install() {
ensure_device_ready
local module_zip
module_zip=$(build_module)
log "Pushing module to device..."
adb push "$module_zip" /sdcard/android_guardian.zip || die "Failed to push module"
log "Installing module..."
adb shell "su -c 'mkdir -p $MODULE_DEST'" || die "Failed to create module directory"
adb shell "su -c 'cd $MODULE_DEST && unzip -o /sdcard/android_guardian.zip'" || die "Failed to extract module"
adb shell "su -c 'chmod 755 $MODULE_DEST/*.sh'"
adb shell "su -c 'rm /sdcard/android_guardian.zip'"
# Set up guardian data directory
log "Setting up guardian data..."
adb shell "su -c 'mkdir -p $GUARDIAN_DATA_DIR'"
adb shell "su -c 'echo ENABLED > $GUARDIAN_DATA_DIR/control'"
# Copy blocked apps list
adb push "$GUARDIAN_MODULE_DIR/blocked_apps.txt" /sdcard/blocked_apps.txt || die "Failed to push blocked apps list"
adb shell "su -c 'cp /sdcard/blocked_apps.txt $GUARDIAN_DATA_DIR/blocked_apps.txt'"
adb shell "su -c 'rm /sdcard/blocked_apps.txt'"
# Create hosts backup for tamper protection
adb shell "su -c 'cp $MODULE_DEST/system/etc/hosts $GUARDIAN_DATA_DIR/hosts.backup'"
# Immediately uninstall any currently installed blocked apps
log "Checking for blocked apps to remove..."
uninstall_blocked_apps
echo ""
echo "=========================================="
echo " ✓ Android Guardian installed!"
echo "=========================================="
echo ""
echo "Features enabled:"
echo " • Hosts-based ad/tracker blocking"
echo " • App installation blocking"
echo " • Tamper protection"
echo ""
echo "⚠️ This can ONLY be controlled via ADB:"
echo " Disable: $0 disable"
echo " Enable: $0 enable"
echo " Status: $0 status"
echo ""
echo "Reboot your device to activate the module."
echo ""
}
# Uninstall currently installed blocked apps
uninstall_blocked_apps() {
local blocked_apps
blocked_apps=$(grep -v '^#' "$GUARDIAN_MODULE_DIR/blocked_apps.txt" | grep -v '^$' || true)
for package in $blocked_apps; do
if adb shell "pm list packages" 2>/dev/null | grep -q "package:$package"; then
log "Uninstalling blocked app: $package"
adb shell "pm uninstall $package" 2>/dev/null || true
fi
done
}
# Show status
cmd_status() {
ensure_device_ready
echo ""
echo "=== Android Guardian Status ==="
echo ""
# Check if module is installed
if adb shell "su -c 'test -d $MODULE_DEST'" 2>/dev/null; then
echo "Module: INSTALLED"
else
echo "Module: NOT INSTALLED"
return
fi
# Check control status
local status
status=$(adb shell "su -c 'cat $GUARDIAN_DATA_DIR/control 2>/dev/null || echo UNKNOWN'" | tr -d '\r')
echo "Status: $status"
# Check if module is "disabled" in Magisk UI (should be auto-fixed by watchdog)
local magisk_disabled
if adb shell "su -c 'test -f $MODULE_DEST/disable'" 2>/dev/null; then
magisk_disabled="YES (watchdog should fix this)"
else
magisk_disabled="No"
fi
echo "Magisk UI disabled: $magisk_disabled"
# Check if watchdog is running
local watchdog_running
watchdog_running=$(adb shell "su -c 'pgrep -f watchdog.sh 2>/dev/null | wc -l'" | tr -d '\r')
if [ "$watchdog_running" -gt 0 ] 2>/dev/null; then
echo "Watchdog: RUNNING ($watchdog_running processes)"
else
echo "Watchdog: NOT RUNNING (reboot phone to start)"
fi
# Check hosts file
local hosts_entries
hosts_entries=$(adb shell "su -c 'grep -c \"^0.0.0.0\" /system/etc/hosts 2>/dev/null || echo 0'" | tr -d '\r')
echo "Blocked domains: $hosts_entries"
# Check blocked apps count
local blocked_count
blocked_count=$(adb shell "su -c 'grep -v \"^#\" $GUARDIAN_DATA_DIR/blocked_apps.txt 2>/dev/null | grep -v \"^$\" | wc -l || echo 0'" | tr -d '\r')
echo "Blocked app rules: $blocked_count packages"
echo ""
echo "Protection: Module cannot be disabled from Magisk UI"
echo " Only controllable via: $0 disable/enable"
echo ""
}
# Disable guardian
cmd_disable() {
ensure_device_ready
log "Disabling Android Guardian..."
adb shell "su -c 'echo DISABLED > $GUARDIAN_DATA_DIR/control'" || die "Failed to disable guardian"
echo ""
echo "✓ Guardian DISABLED"
echo " Hosts blocking still active until reboot"
echo " App blocking service paused"
echo ""
echo "To re-enable: $0 enable"
echo ""
}
# Enable guardian
cmd_enable() {
ensure_device_ready
log "Enabling Android Guardian..."
adb shell "su -c 'echo ENABLED > $GUARDIAN_DATA_DIR/control'" || die "Failed to enable guardian"
echo ""
echo "✓ Guardian ENABLED"
echo ""
}
# Uninstall module
cmd_uninstall() {
ensure_device_ready
# Check if disabled first
local status
status=$(adb shell "su -c 'cat $GUARDIAN_DATA_DIR/control 2>/dev/null || echo ENABLED'" | tr -d '\r')
if [[ $status != "DISABLED" ]]; then
echo ""
echo "⚠️ Guardian must be disabled before uninstalling!"
echo " Run: $0 disable"
echo " Then: $0 uninstall"
echo ""
exit 1
fi
log "Removing Android Guardian..."
adb shell "su -c 'rm -rf $MODULE_DEST'"
adb shell "su -c 'rm -rf $GUARDIAN_DATA_DIR'"
echo ""
echo "✓ Guardian uninstalled"
echo " Reboot to remove hosts blocking"
echo ""
}
# Show logs
cmd_logs() {
ensure_device_ready
echo "=== Guardian Logs ==="
adb shell "su -c 'cat $GUARDIAN_DATA_DIR/guardian.log 2>/dev/null || echo \"No logs yet\"'"
}
# Block an app
cmd_block_app() {
local package="${1:-}"
if [[ -z $package ]]; then
echo "Usage: $0 block-app <package.name>"
echo "Example: $0 block-app com.ubercab.eats"
exit 1
fi
ensure_device_ready
log "Adding $package to block list..."
adb shell "su -c 'echo \"$package\" >> $GUARDIAN_DATA_DIR/blocked_apps.txt'"
# Also add to local file
echo "$package" >>"$GUARDIAN_MODULE_DIR/blocked_apps.txt"
# Try to uninstall if currently installed
if adb shell "pm list packages" 2>/dev/null | grep -q "package:$package"; then
log "Uninstalling $package..."
adb shell "pm uninstall $package" 2>/dev/null || true
fi
echo "✓ $package added to block list"
}
# Unblock an app
cmd_unblock_app() {
local package="${1:-}"
if [[ -z $package ]]; then
echo "Usage: $0 unblock-app <package.name>"
exit 1
fi
ensure_device_ready
log "Removing $package from block list..."
adb shell "su -c 'grep -v \"^$package\$\" $GUARDIAN_DATA_DIR/blocked_apps.txt > $GUARDIAN_DATA_DIR/blocked_apps.tmp && mv $GUARDIAN_DATA_DIR/blocked_apps.tmp $GUARDIAN_DATA_DIR/blocked_apps.txt'"
# Also remove from local file
grep -v "^$package$" "$GUARDIAN_MODULE_DIR/blocked_apps.txt" >"$GUARDIAN_MODULE_DIR/blocked_apps.tmp" && mv "$GUARDIAN_MODULE_DIR/blocked_apps.tmp" "$GUARDIAN_MODULE_DIR/blocked_apps.txt"
echo "✓ $package removed from block list"
}
# List blocked apps
cmd_list_blocked() {
ensure_device_ready
echo "=== Blocked Apps ==="
adb shell "su -c 'cat $GUARDIAN_DATA_DIR/blocked_apps.txt 2>/dev/null'" | grep -v "^#" | grep -v "^$" || echo "No blocked apps"
}
# Main
# Initialize Android script (handles sudo, sets WORK_DIR)