#!/usr/bin/env bash set -euo pipefail ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)" FLUTTER_DOCKER_SCRIPT="$ROOT_DIR/scripts/flutter-docker.sh" HOST_ADB_SCRIPT="${TDC114_HOST_ADB_SCRIPT:-$ROOT_DIR/scripts/host-adb.sh}" LOCAL_ENV_FILE="${TDC114_SMOKE_ENV_FILE:-$ROOT_DIR/scripts/.env.android-device.local}" if [ -f "$LOCAL_ENV_FILE" ]; then # shellcheck disable=SC1090 source "$LOCAL_ENV_FILE" fi ADB_SOCKET="${ADB_SERVER_SOCKET:-}" DEVICE_ID="${TDC114_FLUTTER_DEVICE_ID:-}" API_BASE="${TDC114_API_BASE:-}" AUTH_API_BASE="${TDC114_AUTH_API_BASE:-}" REVERSE_PORT="${TDC114_ANDROID_REVERSE_PORT:-5000}" AUTH_REVERSE_PORT="${TDC114_AUTH_ANDROID_REVERSE_PORT:-5001}" is_reverse_mode() { [ "$API_BASE" = "http://127.0.0.1:${REVERSE_PORT}" ] } is_auth_reverse_mode() { [ "$AUTH_API_BASE" = "http://127.0.0.1:${AUTH_REVERSE_PORT}" ] } print_header() { echo "[android-device-preflight]" if [ -n "$ADB_SOCKET" ]; then echo "ADB server socket: $ADB_SOCKET" else echo "ADB server socket: default container adb server" fi if [ -n "$DEVICE_ID" ]; then echo "Target device id: $DEVICE_ID" else echo "Target device id: first physical device in adb devices" fi if [ -n "$API_BASE" ]; then echo "TDC114_API_BASE: $API_BASE" if is_reverse_mode; then echo "Connection mode: local adb-reverse" else echo "Connection mode: direct HTTPS/LAN" fi fi if [ -n "$AUTH_API_BASE" ]; then echo "TDC114_AUTH_API_BASE: $AUTH_API_BASE" if is_auth_reverse_mode; then echo "Auth connection mode: local adb-reverse" else echo "Auth connection mode: direct HTTPS/LAN" fi fi echo } fail_with_help() { local reason="$1" print_header echo "FAIL $reason" echo echo "Windows-side checklist:" echo "1. Connect the Android phone by USB." echo "2. Enable Developer options > USB debugging." echo "3. Accept the RSA debugging prompt on the phone." echo "4. In Windows PowerShell, run adb.exe devices and confirm the phone is device." echo "5. If using local API through adb reverse, run adb reverse tcp:${REVERSE_PORT} tcp:${REVERSE_PORT} from the same ADB server path." if is_auth_reverse_mode; then echo " Also run adb reverse tcp:${AUTH_REVERSE_PORT} tcp:${AUTH_REVERSE_PORT} for the local auth server." fi echo "6. If using direct staging/production HTTPS mode, confirm TDC114_API_BASE points to the public app API host." if [ -n "$ADB_SOCKET" ]; then echo "7. If WSL reports connection refused to ${ADB_SOCKET}, recreate the Windows 5037 portproxy and firewall rule first." fi echo echo "Recommended WSL command:" echo " ADB_SERVER_SOCKET=tcp::5037 \\" echo " TDC114_FLUTTER_DEVICE_ID= \\" echo " TDC114_SMOKE_ENV_FILE=scripts/.env.android-device.local \\" echo " ./scripts/manual-postlogin-run.sh" } fail_with_adb_help() { local reason="$1" print_header echo "FAIL $reason" echo echo "WSL host-adb checklist:" echo "1. Confirm $HOST_ADB_SCRIPT exists and is executable." echo "2. If host adb is missing, run ./scripts/install-host-adb-from-docker.sh once." echo "3. Confirm ADB_SERVER_SOCKET points to the Windows ADB server, usually tcp:172.21.128.1:5037." echo "4. After host adb access recovers, rerun this script." echo echo "Recommended WSL command:" echo " ADB_SERVER_SOCKET=tcp:172.21.128.1:5037 ./scripts/host-adb.sh devices" } if [ ! -x "$HOST_ADB_SCRIPT" ]; then echo "Missing executable script: $HOST_ADB_SCRIPT" >&2 exit 1 fi if [[ "$DEVICE_ID" == emulator-* ]]; then fail_with_help "TDC114_FLUTTER_DEVICE_ID points to an emulator, not a physical Android device." exit 1 fi env_args=() if [ -n "$ADB_SOCKET" ]; then env_args+=("ADB_SERVER_SOCKET=$ADB_SOCKET") fi set +e if [ "${#env_args[@]}" -gt 0 ]; then OUTPUT="$(env "${env_args[@]}" "$HOST_ADB_SCRIPT" devices 2>&1)" else OUTPUT="$("$HOST_ADB_SCRIPT" devices 2>&1)" fi STATUS=$? set -e if [ "$STATUS" -ne 0 ]; then if printf '%s\n' "$OUTPUT" | grep -Fq "Host adb is not available"; then fail_with_adb_help "Host adb is not ready." printf '%s\n' "$OUTPUT" exit "$STATUS" fi fail_with_help "ADB devices command failed." if printf '%s\n' "$OUTPUT" | grep -Fq "Connection refused"; then echo echo "Hint: Windows ADB itself may be alive, but WSL shared access to port 5037 is blocked." echo "Rebuild portproxy: 0.0.0.0:5037 -> 127.0.0.1:5037, then retry." fi if printf '%s\n' "$OUTPUT" | grep -Fq "protocol fault (couldn't read status)"; then echo echo "Hint: Windows port 5037 may be owned by portproxy before adb.exe starts." echo "In Windows Administrator PowerShell: delete the 5037 portproxy, start adb.exe, confirm adb.exe devices, then recreate the portproxy." fi if printf '%s\n' "$OUTPUT" | grep -Fq "failed to read response from server"; then echo echo "Hint: Windows adb.exe may be talking to a stale or non-ADB listener on port 5037." echo "In Windows Administrator PowerShell: inspect netstat -ano | findstr 5037 before restarting adb.exe." fi printf '%s\n' "$OUTPUT" exit "$STATUS" fi if [ -n "$DEVICE_ID" ]; then DEVICE_PATTERN="^${DEVICE_ID}[[:space:]]+device$" OFFLINE_PATTERN="^${DEVICE_ID}[[:space:]]+offline$" UNAUTHORIZED_PATTERN="^${DEVICE_ID}[[:space:]]+unauthorized$" else DEVICE_PATTERN="^[[:alnum:]_.:-]+[[:space:]]+device$" OFFLINE_PATTERN="^[[:alnum:]_.:-]+[[:space:]]+offline$" UNAUTHORIZED_PATTERN="^[[:alnum:]_.:-]+[[:space:]]+unauthorized$" fi if [ -z "$DEVICE_ID" ]; then DETECTED_UNAUTHORIZED_ID="$(printf '%s\n' "$OUTPUT" | awk '$2 == "unauthorized" && $1 !~ /^emulator-/ {print $1; exit}')" if [ -n "$DETECTED_UNAUTHORIZED_ID" ]; then fail_with_help "Physical Android device is unauthorized." printf '%s\n' "$OUTPUT" exit 1 fi DETECTED_OFFLINE_ID="$(printf '%s\n' "$OUTPUT" | awk '$2 == "offline" && $1 !~ /^emulator-/ {print $1; exit}')" if [ -n "$DETECTED_OFFLINE_ID" ]; then fail_with_help "Physical Android device is offline." printf '%s\n' "$OUTPUT" exit 1 fi DETECTED_DEVICE_ID="$(printf '%s\n' "$OUTPUT" | awk '$2 == "device" && $1 !~ /^emulator-/ {print $1; exit}')" if [ -z "$DETECTED_DEVICE_ID" ]; then fail_with_help "No usable physical Android device was detected." printf '%s\n' "$OUTPUT" exit 1 fi DEVICE_ID="$DETECTED_DEVICE_ID" else if printf '%s\n' "$OUTPUT" | grep -Eq "$UNAUTHORIZED_PATTERN"; then fail_with_help "Physical Android device is unauthorized." printf '%s\n' "$OUTPUT" exit 1 fi if printf '%s\n' "$OUTPUT" | grep -Eq "$OFFLINE_PATTERN"; then fail_with_help "Physical Android device is offline." printf '%s\n' "$OUTPUT" exit 1 fi if ! printf '%s\n' "$OUTPUT" | grep -Eq "$DEVICE_PATTERN"; then fail_with_help "No usable physical Android device was detected." printf '%s\n' "$OUTPUT" exit 1 fi fi if [ -z "$DEVICE_ID" ]; then fail_with_help "No usable physical Android device was detected." printf '%s\n' "$OUTPUT" exit 1 fi if is_reverse_mode || is_auth_reverse_mode; then reverse_args=("adb") if [ -n "$DEVICE_ID" ]; then reverse_args+=("-s" "$DEVICE_ID") fi reverse_args+=("reverse" "--list") set +e if [ "${#env_args[@]}" -gt 0 ]; then REVERSE_OUTPUT="$(env "${env_args[@]}" "$HOST_ADB_SCRIPT" "${reverse_args[@]:1}" 2>&1)" else REVERSE_OUTPUT="$("$HOST_ADB_SCRIPT" "${reverse_args[@]:1}" 2>&1)" fi REVERSE_STATUS=$? set -e if [ "$REVERSE_STATUS" -ne 0 ]; then fail_with_help "adb reverse tcp:${REVERSE_PORT} tcp:${REVERSE_PORT} is not active." printf '%s\n' "$OUTPUT" printf '%s\n' "$REVERSE_OUTPUT" exit 1 fi if is_reverse_mode && ! printf '%s\n' "$REVERSE_OUTPUT" | grep -Fq "tcp:${REVERSE_PORT} tcp:${REVERSE_PORT}"; then fail_with_help "adb reverse tcp:${REVERSE_PORT} tcp:${REVERSE_PORT} is not active." printf '%s\n' "$OUTPUT" printf '%s\n' "$REVERSE_OUTPUT" exit 1 fi if is_auth_reverse_mode && ! printf '%s\n' "$REVERSE_OUTPUT" | grep -Fq "tcp:${AUTH_REVERSE_PORT} tcp:${AUTH_REVERSE_PORT}"; then fail_with_help "adb reverse tcp:${AUTH_REVERSE_PORT} tcp:${AUTH_REVERSE_PORT} is not active." printf '%s\n' "$OUTPUT" printf '%s\n' "$REVERSE_OUTPUT" exit 1 fi fi print_header echo "PASS Physical Android device is ready for Docker/WSL Flutter checks." printf '%s\n' "$OUTPUT"