mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-10 20:27:02 +01:00
Location/curfew goes to daemon_location.sh, the derived state files to daemon_state.sh, the app layer to daemon_apps.sh. All 23 functions moved verbatim -- nothing restructured, which matters more here than anywhere else in this session. focus_daemon.sh has five `while IFS= read -r pkg; do ... done <file` loops and EVERY body calls pm. Piping any of them in lets pm inherit and drain the loop's stdin, so it would process one package instead of all of them -- measured elsewhere in this repo as 1 of 54. That audit ran BEFORE the extraction, not after coverage came back short, and all five moved untouched with a note above them saying why. CURRENT_MODE and _CURFEW_TICK_CACHED are each written in both the entry script and a library, so both stay declared with main, same call as NET_BUILT in the curfew split. 110 assertions and 33 mutations, all killed. Two survived the first run and both were defects in my own tests: the whitelist and sysprotect exactness checks used a SUPERSTRING of a listed entry, which fails under grep -qF and grep -qxF alike and so proved nothing about which was in use. Two subjects are NOT at 100%, and the numbers are reported as measured: daemon_state.sh 67/67 = 100.00% daemon_location.sh 26/40 = 65.00% daemon_apps.sh 71/76 = 93.42% Both shortfalls are kcov attribution failures, shown to be artifacts rather than gaps. daemon_location.sh's missing lines are all inside the embedded awk Haversine; mutating the Earth radius and dropping the longitude term both fail the suite, and an isolated probe shows a one-line awk measuring 100% where the identical multi-line one measures 0%. Collapsing the formula to satisfy the tool would cost the readability of the only real mathematics in the repo, so it stays. daemon_apps.sh's five are the trailing `done <file` of the very loops described above. That is the same artifact piping fixed in curfew_net.sh, and it is exactly what must NOT be done here. Redirecting two of them from /dev/null fails the suite, so the lines run; all three are pinned in the mutation spec instead. Over-cap count 19 -> 18. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
141 lines
6.2 KiB
Bash
Executable File
141 lines
6.2 KiB
Bash
Executable File
#!/system/bin/sh
|
|
# shellcheck shell=ash
|
|
# daemon_state.sh — the state files focus_daemon.sh derives from config: the
|
|
# whitelists, the system-protect and blocked-system lists, the cached default
|
|
# intent handlers, and the JSON status snapshot the companion app reads.
|
|
#
|
|
# A flat sibling, not lib/: deploy.sh pushes phone scripts into one directory.
|
|
#
|
|
# Sourced by focus_daemon.sh, which owns log() and the config.sh globals these
|
|
# read ($WHITELIST, $NIGHT_WHITELIST, $SYSTEM_NEVER_DISABLE,
|
|
# $BLOCKED_SYSTEM_APPS, $STATE_DIR, $STATUS_FILE, $RADIUS). Nothing here is
|
|
# assigned, so there is no global to keep in step.
|
|
|
|
build_whitelist_file() {
|
|
echo "$WHITELIST" | grep -v '^[[:space:]]*#' | grep -v '^[[:space:]]*$' |
|
|
sed 's/^[[:space:]]*//;s/[[:space:]]*$//' >"$STATE_DIR/whitelist.txt"
|
|
# Sanity check: the WHITELIST string in config.sh is fragile - any
|
|
# literal double-quote inside a comment will close the heredoc and
|
|
# silently truncate the variable. Log the parsed line count so any
|
|
# future regression is visible in the log, and warn loudly if it
|
|
# falls below a known floor (we always have ~70+ entries).
|
|
local n
|
|
n=$(wc -l <"$STATE_DIR/whitelist.txt" 2>/dev/null | tr -d ' ')
|
|
log "Whitelist parsed: $n entries"
|
|
if [ "${n:-0}" -lt 30 ]; then
|
|
log "WARN: whitelist suspiciously small ($n lines) - check config.sh for stray quotes inside WHITELIST string"
|
|
fi
|
|
}
|
|
|
|
build_night_whitelist_file() {
|
|
# Strict allow-list used while the night curfew is active (see config.sh
|
|
# NIGHT_WHITELIST and is_curfew_now()). Parsed exactly like the day list.
|
|
echo "$NIGHT_WHITELIST" | grep -v '^[[:space:]]*#' | grep -v '^[[:space:]]*$' |
|
|
sed 's/^[[:space:]]*//;s/[[:space:]]*$//' >"$STATE_DIR/night_whitelist.txt"
|
|
local n
|
|
n=$(wc -l <"$STATE_DIR/night_whitelist.txt" 2>/dev/null | tr -d ' ')
|
|
log "Night-curfew whitelist parsed: $n entries"
|
|
if [ "${n:-0}" -lt 10 ]; then
|
|
log "WARN: night whitelist suspiciously small ($n lines) - check config.sh for stray quotes inside NIGHT_WHITELIST string"
|
|
fi
|
|
}
|
|
|
|
build_sysprotect_file() {
|
|
echo "$SYSTEM_NEVER_DISABLE" | grep -v '^[[:space:]]*$' |
|
|
sed 's/^[[:space:]]*//;s/[[:space:]]*$//' >"$STATE_DIR/sysprotect.txt"
|
|
}
|
|
|
|
# $BLOCKED_SYSTEM_APPS is a static config value (never changes without a
|
|
# daemon restart), so - like build_sysprotect_file above - this only needs
|
|
# to run once at startup, not every enable_focus_mode() sweep.
|
|
build_blocked_sys_file() {
|
|
echo "$BLOCKED_SYSTEM_APPS" | grep -v '^[[:space:]]*#' | grep -v '^[[:space:]]*$' |
|
|
sed 's/^[[:space:]]*//;s/[[:space:]]*$//' >"$STATE_DIR/blocked_sys.txt"
|
|
}
|
|
|
|
# ---- Default handler detection ----
|
|
# Refreshed once per focus_daemon tick into $STATE_DIR/default_handlers.txt.
|
|
# Each line is a package name. Lookup is a cheap grep against this file.
|
|
refresh_default_handlers() {
|
|
local f="$STATE_DIR/default_handlers.txt"
|
|
local tmp="$f.tmp"
|
|
: >"$tmp"
|
|
# Default Home (launcher). resolve-activity prints "Activity Resolver Table:"
|
|
# on line 1 and "<pkg>/<.Activity>" on line 2 in --brief mode.
|
|
cmd package resolve-activity --brief \
|
|
-c android.intent.category.HOME -a android.intent.action.MAIN 2>/dev/null |
|
|
awk -F/ 'NR==2 && $1 != "" {print $1}' >>"$tmp"
|
|
# Default Dialer
|
|
local dialer
|
|
dialer="$(cmd telecom get-default-dialer 2>/dev/null | tr -d '[:space:]')"
|
|
[ -n "$dialer" ] && echo "$dialer" >>"$tmp"
|
|
# Default SMS handler (settings provider key)
|
|
local sms
|
|
sms="$(settings get secure sms_default_application 2>/dev/null | tr -d '[:space:]')"
|
|
[ -n "$sms" ] && [ "$sms" != "null" ] && echo "$sms" >>"$tmp"
|
|
# Default input method (active keyboard). Disabling the active IME with
|
|
# pm disable-user PERSISTS across reboot; a 1am reboot would then leave no
|
|
# keyboard to type any recovery command. Protect it day and night so the
|
|
# curfew can never lock you out of typing.
|
|
local ime
|
|
ime="$(settings get secure default_input_method 2>/dev/null | cut -d/ -f1)"
|
|
[ -n "$ime" ] && [ "$ime" != "null" ] && echo "$ime" >>"$tmp"
|
|
sort -u "$tmp" -o "$f"
|
|
rm -f "$tmp"
|
|
|
|
# Default Browser handler is tracked SEPARATELY and guarded only OUTSIDE
|
|
# the curfew window (see is_allowed). During curfew the whole point is to
|
|
# disable browsers, so the default-handler guard must not resurrect them.
|
|
local bf="$STATE_DIR/default_browser.txt"
|
|
cmd package resolve-activity --brief \
|
|
-a android.intent.action.VIEW -d http://example.com 2>/dev/null |
|
|
awk -F/ 'NR==2 && $1 != "" {print $1}' >"$bf.tmp" 2>/dev/null
|
|
mv "$bf.tmp" "$bf" 2>/dev/null || : >"$bf"
|
|
}
|
|
|
|
is_default_handler() {
|
|
local pkg="$1"
|
|
grep -qxF "$pkg" "$STATE_DIR/default_handlers.txt" 2>/dev/null
|
|
}
|
|
|
|
# ---- Status snapshot for companion notification app ----
|
|
# Writes a tiny JSON file that focus_status_app reads every few seconds.
|
|
# Fields: mode, lat, lon, distance_m, threshold_m, radius_m, disabled_count,
|
|
# last_check_ts (unix), last_check_iso (human).
|
|
write_status_snapshot() {
|
|
local mode="$1" lat="$2" lon="$3" dist="$4" thr="$5"
|
|
local count iso ts cf ov frc
|
|
count="$(wc -l <"$DISABLED_APPS_FILE" 2>/dev/null | tr -d ' ' || echo 0)"
|
|
[ -z "$count" ] && count=0
|
|
ts="$(date +%s)"
|
|
iso="$(date '+%Y-%m-%d %H:%M:%S')"
|
|
# Curfew state for the companion app: 1/0 so it slots into the existing
|
|
# numeric JSON path. "curfew" = restrictions active now; "curfew_override"
|
|
# = the escape-hatch file is set (curfew suspended).
|
|
if curfew_active; then cf=1; else cf=0; fi
|
|
if [ -e "$CURFEW_OVERRIDE_FILE" ]; then ov=1; else ov=0; fi
|
|
# "curfew_force" = the demo/test force file is set (curfew forced on
|
|
# regardless of clock). Lets the companion app show Start/Stop demo.
|
|
if [ -e "$CURFEW_FORCE_FILE" ]; then frc=1; else frc=0; fi
|
|
local tmp="$STATUS_FILE.tmp"
|
|
# Shell-emitted JSON — keep values numeric where possible, strings quoted.
|
|
{
|
|
printf '{'
|
|
printf '"mode":"%s",' "$mode"
|
|
printf '"lat":"%s",' "${lat:-}"
|
|
printf '"lon":"%s",' "${lon:-}"
|
|
printf '"distance_m":%s,' "${dist:-null}"
|
|
printf '"threshold_m":%s,' "${thr:-null}"
|
|
printf '"radius_m":%s,' "$RADIUS"
|
|
printf '"disabled_count":%s,' "$count"
|
|
printf '"curfew":%s,' "$cf"
|
|
printf '"curfew_override":%s,' "$ov"
|
|
printf '"curfew_force":%s,' "$frc"
|
|
printf '"last_check_ts":%s,' "$ts"
|
|
printf '"last_check_iso":"%s"' "$iso"
|
|
printf '}\n'
|
|
} >"$tmp" 2>/dev/null || return 0
|
|
mv "$tmp" "$STATUS_FILE" 2>/dev/null || true
|
|
chmod 644 "$STATUS_FILE" 2>/dev/null || true
|
|
}
|