#!/usr/bin/env bash # Wireless adb discovery + reconnect helpers (sourced by rebuild.sh). # Discovers endpoints via: connected devices, adb mdns, HTTP :5039/adb.json, cache, static hints. : "${ADB_CONNECT_RETRIES:=4}" : "${ADB_CONNECT_DELAY_SEC:=2}" : "${DEV_ADB_HTTP_PORT:=5039}" : "${ADB_CONNECT_CACHE:=$ROOT/.adb_connect_cache}" : "${ADB_RECONNECT_POKE_DELAY_SEC:=2}" declare -gA CONNECTIONS_LIST_HINTS adb_reconnect_init_hints() { CONNECTIONS_LIST_HINTS["192_168_33_153"]="[A13] Android Projector" CONNECTIONS_LIST_HINTS["192_168_33_39"]="[A16] Doogee Tab G6 Max / P8_EEA" CONNECTIONS_LIST_HINTS["192_168_33_106"]="[A11] BlackView BL6000Pro / BL6000Pro_EEA" CONNECTIONS_LIST_HINTS["192_168_33_173"]="[A11] BlackView BL6000Pro / BL6000Pro" } adb_hint_key_for_ip() { local ip=${1} ip="$(echo "${ip}" | sed -e 's@\.@_@g' -e 's@:.*@@' | tr -d '\n')" printf '%s' "${ip}" } adb_ip_for_hint_key() { local ip=${1} ip="$(echo "${ip}" | sed -e 's/@_@/./g' -e 's/:.*//' | tr -d '\n')" printf '%s' "${ip}" } adb_hint_for_endpoint() { local endpoint=${1} local key key="$(adb_hint_key_for_ip "${endpoint}")" printf '%s' "${CONNECTIONS_LIST_HINTS[${key}]:-}" } adb_collect_candidate_ips() { local ip endpoint key if [[ -f "$ADB_CONNECT_CACHE" ]]; then while IFS= read -r endpoint; do [[ -z "$endpoint" ]] && continue ip="${endpoint%%:*}" [[ -n "$ip" ]] && printf '%s\n' "$ip" done < "$ADB_CONNECT_CACHE" fi for key in "${!CONNECTIONS_LIST_HINTS[@]}"; do adb_ip_for_hint_key "$key" done adb devices -l 2>/dev/null | awk '/^[^ ]+ +device/ { print $1 }' | while read -r serial; do [[ "$serial" == *:* ]] || continue printf '%s\n' "${serial%%:*}" done } adb_json_connect_lines() { local json=${1} [[ -n "$json" ]] || return 0 printf '%s' "$json" | python3 -c ' import json, sys raw = sys.stdin.read() if not raw.strip(): raise SystemExit(0) try: data = json.loads(raw) except json.JSONDecodeError: raise SystemExit(0) for item in data.get("connect") or []: if item: print(item) for item in data.get("commands") or []: if isinstance(item, str) and item.startswith("adb connect "): print(item[len("adb connect "):]) ' 2>/dev/null || true } adb_fetch_http_endpoints() { local ip json for ip in $(adb_collect_candidate_ips | sort -u); do [[ -z "$ip" ]] && continue json="$(curl -m 3 -sf "http://${ip}:${DEV_ADB_HTTP_PORT}/adb.json" 2>/dev/null || true)" [[ -z "$json" ]] && continue adb_json_connect_lines "$json" done } adb_discover_mdns_endpoints() { local line name service hostport while IFS= read -r line; do [[ "$line" == *"_adb._tcp"* ]] || continue hostport="$(awk '{print $NF}' <<<"$line")" [[ "$hostport" == *:* ]] || continue printf '%s\n' "$hostport" done < <(adb mdns services 2>/dev/null || true) } adb_pull_device_json_endpoints() { local serial json tmp while IFS= read -r serial; do [[ -z "$serial" ]] && continue tmp="$(mktemp)" if adb -s "$serial" exec-out run-as com.foxx.androidcast cat files/dev/adb_connect.json \ >"$tmp" 2>/dev/null; then json="$(cat "$tmp")" rm -f "$tmp" adb_json_connect_lines "$json" else rm -f "$tmp" fi done < <(adb devices 2>/dev/null | awk 'NR > 1 && $2 == "device" { print $1 }') } adb_discover_endpoints() { local endpoint declare -A seen=() local -a ordered=() add_endpoint() { local e=${1} [[ -z "$e" ]] && return 0 [[ -n "${seen[$e]:-}" ]] && return 0 seen["$e"]=1 ordered+=("$e") } while IFS= read -r endpoint; do add_endpoint "$endpoint" done < <(adb_discover_mdns_endpoints) while IFS= read -r endpoint; do add_endpoint "$endpoint" done < <(adb_fetch_http_endpoints) while IFS= read -r endpoint; do add_endpoint "$endpoint" done < <(adb_pull_device_json_endpoints) if [[ -f "$ADB_CONNECT_CACHE" ]]; then while IFS= read -r endpoint; do add_endpoint "$endpoint" done < "$ADB_CONNECT_CACHE" fi local key ip for key in "${!CONNECTIONS_LIST_HINTS[@]}"; do ip="$(adb_ip_for_hint_key "$key")" add_endpoint "${ip}:5555" add_endpoint "${ip}" done printf '%s\n' "${ordered[@]}" } adb_poke_refresh_broadcast() { local serial while IFS= read -r serial; do [[ -z "$serial" ]] && continue adb -s "$serial" shell am broadcast \ -a com.foxx.androidcast.dev.REFRESH_ADB_WIFI \ -n com.foxx.androidcast/.dev.DevAdbWifiReceiver >/dev/null 2>&1 || true done < <(adb devices 2>/dev/null | awk 'NR > 1 && $2 == "device" { print $1 }') } adb_reconnect_endpoint() { local endpoint="$1" [[ -z "$endpoint" ]] && return 1 local attempt out hint hint="$(adb_hint_for_endpoint "${endpoint}")" [[ -n "${hint}" ]] && hint="(${hint})" echo " adb connect ${endpoint} ${hint}" adb disconnect "$endpoint" >/dev/null 2>&1 || true for (( attempt = 1; attempt <= ADB_CONNECT_RETRIES; attempt++ )); do out="$(adb connect "$endpoint" 2>&1)" || true if grep -qiE 'connected|already' <<<"$out"; then if adb -s "$endpoint" get-state 2>/dev/null | grep -q '^device$'; then echo " ${endpoint} — ready" return 0 fi fi if [[ "$attempt" -lt "$ADB_CONNECT_RETRIES" ]]; then sleep "$ADB_CONNECT_DELAY_SEC" fi done echo " ${endpoint} — not reachable (${out})" >&2 return 1 } adb_update_connect_cache() { local serial mkdir -p "$(dirname "$ADB_CONNECT_CACHE")" : >"$ADB_CONNECT_CACHE" while IFS= read -r serial; do [[ "$serial" == *:* ]] || continue echo "$serial" >>"$ADB_CONNECT_CACHE" done < <(adb devices 2>/dev/null | awk 'NR > 1 && $2 == "device" { print $1 }') } adb_reconnect_all() { echo "==> Reconnecting wireless adb targets" adb start-server >/dev/null 2>&1 || true adb reconnect offline >/dev/null 2>&1 || true adb_poke_refresh_broadcast if [[ "${ADB_RECONNECT_POKE_DELAY_SEC:-0}" -gt 0 ]]; then sleep "$ADB_RECONNECT_POKE_DELAY_SEC" fi local endpoint connected=0 while IFS= read -r endpoint; do [[ -z "$endpoint" ]] && continue if adb_reconnect_endpoint "$endpoint"; then connected=$((connected + 1)) fi done < <(adb_discover_endpoints) adb_update_connect_cache adb devices -l if [[ "$connected" -gt 0 ]]; then return 0 fi return 1 } adb_count_ready_devices() { adb devices 2>/dev/null | awk 'NR > 1 && $2 == "device" { c++ } END { print c+0 }' }