mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-04-24 02:02:09 +00:00
323 lines
12 KiB
Bash
Executable file
323 lines
12 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
# Nuvio Debug Log Viewer
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
# Streams live ADB logcat for the Nuvio debug build, colour-coded by log
|
|
# level. Press C to clear all logs on screen. Press Q to quit.
|
|
#
|
|
# Usage:
|
|
# ./scripts/nuvio_debug_logs.sh [options]
|
|
#
|
|
# Options:
|
|
# -s, --serial <id> ADB device serial (optional, for multi-device)
|
|
# -t, --tag <regex> Additional logcat tag filter regex (default: all app)
|
|
# -c, --clear Clear logcat buffer before streaming
|
|
# -h, --help Show help
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
set -uo pipefail
|
|
|
|
PACKAGE="com.nuvio.app"
|
|
SERIAL=""
|
|
CLEAR_BUFFER=false
|
|
TAG_FILTER=""
|
|
STREAM_PID=""
|
|
USER_QUIT=false
|
|
|
|
# ── Log file ────────────────────────────────────────────────────────────────
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
|
|
LOG_DIR="${PROJECT_DIR}/logs"
|
|
mkdir -p "$LOG_DIR"
|
|
LOG_FILE="${LOG_DIR}/debug_$(date +%Y%m%d_%H%M%S).log"
|
|
|
|
# ── Noise suppression ───────────────────────────────────────────────────────
|
|
NOISE_TAGS='EGL_emulation|OpenGLRenderer|eglCodecCommon|goldfish|gralloc|hwcomposer|SurfaceFlinger|chatty|ConfigStore|libEGL|MediaCodec|AudioTrack|AudioFlinger|BufferQueueProducer|GraphicBufferSource|OMXClient'
|
|
|
|
# ── ANSI colour codes ───────────────────────────────────────────────────────
|
|
RST='\033[0m'
|
|
BOLD='\033[1m'
|
|
DIM='\033[2m'
|
|
|
|
CLR_V='\033[36m'
|
|
CLR_D='\033[34m'
|
|
CLR_I='\033[32m'
|
|
CLR_W='\033[33m'
|
|
CLR_E='\033[31m'
|
|
CLR_F='\033[35m'
|
|
|
|
CLR_HEADER='\033[38;5;141m'
|
|
CLR_ACCENT='\033[38;5;75m'
|
|
CLR_META='\033[38;5;245m'
|
|
CLR_HOTKEY='\033[38;5;220m'
|
|
|
|
# ── Helpers ──────────────────────────────────────────────────────────────────
|
|
usage() {
|
|
cat <<'EOF'
|
|
Usage: ./scripts/nuvio_debug_logs.sh [options]
|
|
|
|
Stream live colour-coded ADB logs for Nuvio debug builds.
|
|
|
|
Options:
|
|
-s, --serial <id> ADB device serial (optional)
|
|
-t, --tag <regex> Additional grep regex to filter log tags
|
|
-c, --clear Clear logcat buffer before streaming
|
|
-h, --help Show this help
|
|
|
|
Hotkeys (while running):
|
|
C Clear all logs currently shown in the terminal
|
|
Q Quit the log viewer
|
|
|
|
Examples:
|
|
./scripts/nuvio_debug_logs.sh
|
|
./scripts/nuvio_debug_logs.sh --serial emulator-5554
|
|
./scripts/nuvio_debug_logs.sh --tag 'MetaDetailsRepo|SeriesContent'
|
|
./scripts/nuvio_debug_logs.sh --clear --tag 'Sync|Auth'
|
|
EOF
|
|
}
|
|
|
|
# ── Parse arguments ──────────────────────────────────────────────────────────
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
-s|--serial) SERIAL="${2:-}"; shift 2 ;;
|
|
-t|--tag) TAG_FILTER="${2:-}"; shift 2 ;;
|
|
-c|--clear) CLEAR_BUFFER=true; shift ;;
|
|
-h|--help) usage; exit 0 ;;
|
|
*) echo "Unknown option: $1" >&2; usage; exit 1 ;;
|
|
esac
|
|
done
|
|
|
|
# ── ADB setup ────────────────────────────────────────────────────────────────
|
|
ADB=(adb)
|
|
if [[ -n "$SERIAL" ]]; then
|
|
ADB+=( -s "$SERIAL" )
|
|
fi
|
|
|
|
if ! "${ADB[@]}" get-state >/dev/null 2>&1; then
|
|
echo -e "${CLR_E}✗ No ADB device detected. Connect a device or start an emulator first.${RST}" >&2
|
|
"${ADB[@]}" devices 2>/dev/null || true
|
|
exit 1
|
|
fi
|
|
|
|
DEVICE_MODEL=$("${ADB[@]}" shell getprop ro.product.model 2>/dev/null | tr -d '\r' || echo "unknown")
|
|
ANDROID_VER=$("${ADB[@]}" shell getprop ro.build.version.release 2>/dev/null | tr -d '\r' || echo "?")
|
|
|
|
if $CLEAR_BUFFER; then
|
|
"${ADB[@]}" logcat -c
|
|
fi
|
|
|
|
# ── Resolve app UID ──────────────────────────────────────────────────────────
|
|
uid_from_pm() {
|
|
"${ADB[@]}" shell cmd package list packages -U "$PACKAGE" 2>/dev/null \
|
|
| tr -d '\r' \
|
|
| sed -nE 's/.*uid:([0-9]+).*/\1/p' \
|
|
| head -n1
|
|
}
|
|
|
|
uid_from_dumpsys() {
|
|
"${ADB[@]}" shell dumpsys package "$PACKAGE" 2>/dev/null \
|
|
| tr -d '\r' \
|
|
| sed -nE 's/.*userId=([0-9]+).*/\1/p' \
|
|
| head -n1
|
|
}
|
|
|
|
APP_UID="$(uid_from_pm || true)"
|
|
if [[ -z "$APP_UID" ]]; then
|
|
APP_UID="$(uid_from_dumpsys || true)"
|
|
fi
|
|
|
|
# ── Colour-coding function ──────────────────────────────────────────────────
|
|
colorize_line() {
|
|
local line="$1"
|
|
local level="${line:0:1}"
|
|
local clr=""
|
|
case "$level" in
|
|
V) clr="$CLR_V" ;;
|
|
D) clr="$CLR_D" ;;
|
|
I) clr="$CLR_I" ;;
|
|
W) clr="$CLR_W" ;;
|
|
E) clr="$CLR_E" ;;
|
|
F) clr="$CLR_F" ;;
|
|
*) clr="$DIM" ;;
|
|
esac
|
|
|
|
local badge=""
|
|
case "$level" in
|
|
V) badge="${CLR_V}${BOLD} VRB ${RST}" ;;
|
|
D) badge="${CLR_D}${BOLD} DBG ${RST}" ;;
|
|
I) badge="${CLR_I}${BOLD} INF ${RST}" ;;
|
|
W) badge="${CLR_W}${BOLD} WRN ${RST}" ;;
|
|
E) badge="${CLR_E}${BOLD} ERR ${RST}" ;;
|
|
F) badge="${CLR_F}${BOLD} FTL ${RST}" ;;
|
|
*) badge="${DIM} ??? ${RST}" ;;
|
|
esac
|
|
|
|
echo -e "${badge} ${clr}${line}${RST}"
|
|
}
|
|
|
|
# ── Stream logcat with colour ───────────────────────────────────────────────
|
|
stream_logcat_colored() {
|
|
local mode="$1"
|
|
local value="$2"
|
|
local noise_re="$NOISE_TAGS"
|
|
|
|
"${ADB[@]}" logcat -v brief "$mode" "$value" 2>/dev/null \
|
|
| while IFS= read -r raw_line; do
|
|
if [[ "$raw_line" =~ $noise_re ]]; then
|
|
continue
|
|
fi
|
|
if [[ -n "$TAG_FILTER" ]]; then
|
|
if [[ ! "$raw_line" =~ $TAG_FILTER ]]; then
|
|
continue
|
|
fi
|
|
fi
|
|
echo "$raw_line" >> "$LOG_FILE"
|
|
colorize_line "$raw_line"
|
|
done
|
|
}
|
|
|
|
# ── Process management ───────────────────────────────────────────────────────
|
|
stop_stream() {
|
|
if [[ -n "$STREAM_PID" ]] && kill -0 "$STREAM_PID" 2>/dev/null; then
|
|
kill -- -"$STREAM_PID" 2>/dev/null || kill "$STREAM_PID" 2>/dev/null || true
|
|
wait "$STREAM_PID" 2>/dev/null || true
|
|
fi
|
|
STREAM_PID=""
|
|
}
|
|
|
|
start_stream() {
|
|
local mode="$1"
|
|
local value="$2"
|
|
set -m
|
|
stream_logcat_colored "$mode" "$value" &
|
|
STREAM_PID=$!
|
|
set +m
|
|
}
|
|
|
|
clear_terminal() {
|
|
if [[ -t 1 ]]; then
|
|
printf '\033[2J\033[3J\033[H'
|
|
print_banner
|
|
fi
|
|
}
|
|
|
|
# ── Pretty banner ───────────────────────────────────────────────────────────
|
|
print_banner() {
|
|
echo -e ""
|
|
echo -e "${CLR_HEADER}${BOLD} ╔══════════════════════════════════════════════════════╗${RST}"
|
|
echo -e "${CLR_HEADER}${BOLD} ║ 📺 Nuvio Debug Log Viewer ║${RST}"
|
|
echo -e "${CLR_HEADER}${BOLD} ╚══════════════════════════════════════════════════════╝${RST}"
|
|
echo -e ""
|
|
echo -e " ${CLR_META}Device:${RST} ${CLR_ACCENT}${DEVICE_MODEL}${RST} ${CLR_META}(Android ${ANDROID_VER})${RST}"
|
|
echo -e " ${CLR_META}Package:${RST} ${CLR_ACCENT}${PACKAGE}${RST}"
|
|
echo -e " ${CLR_META}Log file:${RST} ${CLR_ACCENT}${LOG_FILE}${RST}"
|
|
if [[ -n "$TAG_FILTER" ]]; then
|
|
echo -e " ${CLR_META}Tag filter:${RST} ${CLR_ACCENT}${TAG_FILTER}${RST}"
|
|
fi
|
|
echo -e ""
|
|
echo -e " ${CLR_META}Log levels:${RST} ${CLR_V}█ VRB${RST} ${CLR_D}█ DBG${RST} ${CLR_I}█ INF${RST} ${CLR_W}█ WRN${RST} ${CLR_E}█ ERR${RST} ${CLR_F}█ FTL${RST}"
|
|
echo -e ""
|
|
echo -e " ${CLR_HOTKEY}[C]${RST} ${CLR_META}Clear logs${RST} ${CLR_HOTKEY}[Q]${RST} ${CLR_META}Quit${RST} ${CLR_META}Ctrl+C to force stop${RST}"
|
|
echo -e "${CLR_META} ──────────────────────────────────────────────────────${RST}"
|
|
echo -e ""
|
|
}
|
|
|
|
# ── Handle hotkeys in the run loop ──────────────────────────────────────────
|
|
run_with_hotkeys() {
|
|
local mode="$1"
|
|
local value="$2"
|
|
start_stream "$mode" "$value"
|
|
|
|
if [[ ! -t 0 ]]; then
|
|
wait "$STREAM_PID" 2>/dev/null || true
|
|
return 0
|
|
fi
|
|
|
|
while true; do
|
|
if [[ -z "$STREAM_PID" ]] || ! kill -0 "$STREAM_PID" 2>/dev/null; then
|
|
wait "$STREAM_PID" 2>/dev/null || true
|
|
STREAM_PID=""
|
|
return 0
|
|
fi
|
|
|
|
local key=""
|
|
if read -r -s -n1 -t 1 key; then
|
|
case "$key" in
|
|
c|C)
|
|
"${ADB[@]}" logcat -c >/dev/null 2>&1 || true
|
|
: > "$LOG_FILE"
|
|
clear_terminal
|
|
;;
|
|
q|Q)
|
|
USER_QUIT=true
|
|
stop_stream
|
|
echo -e "\n${CLR_META}${BOLD} ✓ Log viewer stopped.${RST}"
|
|
echo -e " ${CLR_META}Full log saved:${RST} ${CLR_ACCENT}${LOG_FILE}${RST}\n"
|
|
return 0
|
|
;;
|
|
esac
|
|
fi
|
|
done
|
|
}
|
|
|
|
# ── Cleanup on exit ─────────────────────────────────────────────────────────
|
|
cleanup() {
|
|
stop_stream
|
|
jobs -p 2>/dev/null | xargs -r kill 2>/dev/null || true
|
|
stty sane 2>/dev/null || true
|
|
echo "" 2>/dev/null || true
|
|
}
|
|
trap cleanup EXIT INT TERM
|
|
|
|
# ── Main ─────────────────────────────────────────────────────────────────────
|
|
print_banner
|
|
|
|
if [[ -n "$APP_UID" ]]; then
|
|
echo -e " ${CLR_META}Mode:${RST} ${CLR_ACCENT}UID filter${RST} ${CLR_META}(uid=${APP_UID})${RST}"
|
|
echo -e ""
|
|
|
|
run_with_hotkeys --uid "$APP_UID"
|
|
rc=$?
|
|
|
|
if $USER_QUIT; then
|
|
exit 0
|
|
fi
|
|
|
|
if [[ $rc -eq 0 ]]; then
|
|
exit 0
|
|
fi
|
|
|
|
echo -e "${CLR_W} ⚠ UID filter not supported on this device. Falling back to PID mode...${RST}"
|
|
fi
|
|
|
|
echo -e " ${CLR_META}Mode:${RST} ${CLR_ACCENT}PID tracking${RST}"
|
|
echo -e ""
|
|
|
|
last_pid=""
|
|
while true; do
|
|
pid="$("${ADB[@]}" shell pidof -s "$PACKAGE" 2>/dev/null | tr -d '\r' || true)"
|
|
|
|
if [[ -z "$pid" ]]; then
|
|
if [[ -n "$last_pid" ]]; then
|
|
echo -e "${CLR_W} ⏸ Process stopped. Waiting for ${PACKAGE} to start...${RST}"
|
|
last_pid=""
|
|
fi
|
|
sleep 1
|
|
continue
|
|
fi
|
|
|
|
if [[ "$pid" != "$last_pid" ]]; then
|
|
echo -e "${CLR_I}${BOLD} ▶ Attached to PID ${pid}${RST}"
|
|
last_pid="$pid"
|
|
fi
|
|
|
|
run_with_hotkeys --pid "$pid"
|
|
rc=$?
|
|
|
|
if $USER_QUIT; then
|
|
exit 0
|
|
fi
|
|
|
|
if [[ $rc -ne 0 ]]; then
|
|
sleep 1
|
|
fi
|
|
done
|