mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-28 23:06:48 +00:00
231 lines
6.2 KiB
Bash
Executable File
231 lines
6.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)"
|
|
ANDROID_DIR="$ROOT_DIR/apps/android"
|
|
PACKAGE_NAME="ai.openclaw.app"
|
|
RECEIVER="$PACKAGE_NAME/.VoiceE2eReceiver"
|
|
RUN_ACTION="ai.openclaw.app.debug.RUN_VOICE_E2E"
|
|
OPEN_ACTION="ai.openclaw.app.debug.OPEN_VOICE_E2E"
|
|
PORT=18789
|
|
HOST="127.0.0.1"
|
|
MODE="both"
|
|
TRANSCRIPT="Reply exactly: Android voice e2e normal path ok."
|
|
REALTIME_ASSISTANT="Android realtime voice e2e relay path ok."
|
|
TIMEOUT_MS=60000
|
|
INSTALL=1
|
|
CONNECT=1
|
|
CLEANUP=0
|
|
START_GATEWAY=0
|
|
|
|
usage() {
|
|
cat <<'USAGE'
|
|
Usage: apps/android/scripts/voice-e2e.sh [options]
|
|
|
|
Options:
|
|
--mode connect|normal|realtime|both
|
|
Gateway probe or voice path to test. Default: both.
|
|
--transcript TEXT Synthetic user transcript for the voice turn.
|
|
--realtime-assistant TEXT Synthetic realtime assistant relay text.
|
|
--host HOST Gateway host visible from Android. Default: 127.0.0.1.
|
|
--port PORT Gateway port. Default: 18789.
|
|
--timeout-ms MS Per-mode timeout. Default: 60000.
|
|
--skip-install Reuse the installed debug app.
|
|
--no-connect Do not rewrite manual gateway settings.
|
|
--start-gateway Start a temporary local gateway with bws_get_secret.
|
|
--cleanup Stop voice capture after screenshots.
|
|
USAGE
|
|
}
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--mode)
|
|
MODE="$2"
|
|
shift 2
|
|
;;
|
|
--transcript)
|
|
TRANSCRIPT="$2"
|
|
shift 2
|
|
;;
|
|
--realtime-assistant)
|
|
REALTIME_ASSISTANT="$2"
|
|
shift 2
|
|
;;
|
|
--host)
|
|
HOST="$2"
|
|
shift 2
|
|
;;
|
|
--port)
|
|
PORT="$2"
|
|
shift 2
|
|
;;
|
|
--timeout-ms)
|
|
TIMEOUT_MS="$2"
|
|
shift 2
|
|
;;
|
|
--skip-install)
|
|
INSTALL=0
|
|
shift
|
|
;;
|
|
--no-connect)
|
|
CONNECT=0
|
|
shift
|
|
;;
|
|
--start-gateway)
|
|
START_GATEWAY=1
|
|
shift
|
|
;;
|
|
--cleanup)
|
|
CLEANUP=1
|
|
shift
|
|
;;
|
|
-h|--help)
|
|
usage
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo "unknown option: $1" >&2
|
|
usage >&2
|
|
exit 2
|
|
;;
|
|
esac
|
|
done
|
|
|
|
export JAVA_HOME="${JAVA_HOME:-/opt/homebrew/opt/openjdk@17/libexec/openjdk.jdk/Contents/Home}"
|
|
export ANDROID_HOME="${ANDROID_HOME:-/opt/homebrew/share/android-commandlinetools}"
|
|
export ANDROID_SDK_ROOT="${ANDROID_SDK_ROOT:-$ANDROID_HOME}"
|
|
export PATH="/opt/homebrew/opt/openjdk@17/bin:$ANDROID_HOME/platform-tools:$ANDROID_HOME/cmdline-tools/latest/bin:$PATH"
|
|
|
|
ARTIFACT_DIR="/tmp/openclaw-android-voice-e2e-$(date +%Y%m%d-%H%M%S)"
|
|
mkdir -p "$ARTIFACT_DIR"
|
|
|
|
cleanup_gateway() {
|
|
if [[ -n "${GATEWAY_PID:-}" ]]; then
|
|
kill "$GATEWAY_PID" >/dev/null 2>&1 || true
|
|
fi
|
|
}
|
|
trap cleanup_gateway EXIT
|
|
|
|
if ! adb devices -l | awk 'NR > 1 && $2 == "device" { found = 1 } END { exit(found ? 0 : 1) }'; then
|
|
echo "no authorized Android device found" >&2
|
|
adb devices -l >&2
|
|
exit 1
|
|
fi
|
|
|
|
adb reverse "tcp:$PORT" "tcp:$PORT" >/dev/null
|
|
|
|
if [[ "$START_GATEWAY" -eq 1 ]]; then
|
|
if command -v bws_get_secret >/dev/null 2>&1; then
|
|
OPENCLAW_OPENAI_API_KEY="$(bws_get_secret OPENCLAW_OPENAI_API_KEY)"
|
|
else
|
|
OPENCLAW_OPENAI_API_KEY="$(zsh -ic 'bws_get_secret OPENCLAW_OPENAI_API_KEY')"
|
|
fi
|
|
(
|
|
cd "$ROOT_DIR"
|
|
OPENAI_API_KEY="$OPENCLAW_OPENAI_API_KEY" \
|
|
pnpm openclaw gateway run \
|
|
--port "$PORT" \
|
|
--auth none \
|
|
--bind loopback \
|
|
--force \
|
|
--allow-unconfigured \
|
|
--ws-log compact
|
|
) >"$ARTIFACT_DIR/gateway.log" 2>&1 &
|
|
GATEWAY_PID=$!
|
|
sleep 4
|
|
if ! kill -0 "$GATEWAY_PID" >/dev/null 2>&1; then
|
|
cat "$ARTIFACT_DIR/gateway.log" >&2
|
|
exit 1
|
|
fi
|
|
unset OPENCLAW_OPENAI_API_KEY
|
|
fi
|
|
|
|
if [[ "$INSTALL" -eq 1 ]]; then
|
|
(cd "$ANDROID_DIR" && ./gradlew :app:installPlayDebug)
|
|
fi
|
|
|
|
adb shell pm grant "$PACKAGE_NAME" android.permission.RECORD_AUDIO >/dev/null 2>&1 || true
|
|
adb shell am force-stop "$PACKAGE_NAME" >/dev/null
|
|
adb shell am start -a "$OPEN_ACTION" -n "$PACKAGE_NAME/.MainActivity" >/dev/null
|
|
adb logcat -c
|
|
|
|
run_mode() {
|
|
local test_mode="$1"
|
|
local result_name="$ARTIFACT_DIR/result-$test_mode.json"
|
|
local screenshot_name="$ARTIFACT_DIR/screen-$test_mode.png"
|
|
local transcript_base64
|
|
local realtime_assistant_base64
|
|
transcript_base64="$(printf '%s' "$TRANSCRIPT" | base64 | tr -d '\n')"
|
|
realtime_assistant_base64="$(printf '%s' "$REALTIME_ASSISTANT" | base64 | tr -d '\n')"
|
|
|
|
adb shell run-as "$PACKAGE_NAME" rm -f cache/voice_e2e_result.json >/dev/null 2>&1 || true
|
|
local no_connect_flag=true
|
|
if [[ "$CONNECT" -eq 1 ]]; then
|
|
no_connect_flag=false
|
|
fi
|
|
|
|
adb shell am broadcast \
|
|
-a "$RUN_ACTION" \
|
|
-n "$RECEIVER" \
|
|
--es mode "$test_mode" \
|
|
--ez noConnect "$no_connect_flag" \
|
|
--es host "$HOST" \
|
|
--ei port "$PORT" \
|
|
--ez tls false \
|
|
--el timeoutMs "$TIMEOUT_MS" \
|
|
--el connectTimeoutMs "$TIMEOUT_MS" \
|
|
--es transcriptBase64 "$transcript_base64" \
|
|
--es realtimeAssistantBase64 "$realtime_assistant_base64" >/dev/null
|
|
|
|
local deadline=$((SECONDS + TIMEOUT_MS / 1000 + 20))
|
|
local result=""
|
|
while [[ "$SECONDS" -lt "$deadline" ]]; do
|
|
result="$(adb shell run-as "$PACKAGE_NAME" cat cache/voice_e2e_result.json 2>/dev/null | tr -d '\r' || true)"
|
|
if [[ -n "$result" ]]; then
|
|
break
|
|
fi
|
|
sleep 1
|
|
done
|
|
|
|
if [[ -z "$result" ]]; then
|
|
echo "voice e2e $test_mode timed out waiting for result" >&2
|
|
exit 1
|
|
fi
|
|
printf '%s\n' "$result" >"$result_name"
|
|
adb exec-out screencap -p >"$screenshot_name"
|
|
if ! grep -q '"ok":true' "$result_name"; then
|
|
echo "voice e2e $test_mode failed: $result" >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
case "$MODE" in
|
|
both)
|
|
run_mode normal
|
|
run_mode realtime
|
|
;;
|
|
normal|dictation)
|
|
run_mode normal
|
|
;;
|
|
realtime|talk)
|
|
run_mode realtime
|
|
;;
|
|
connect)
|
|
run_mode connect
|
|
;;
|
|
*)
|
|
echo "unknown mode: $MODE" >&2
|
|
exit 2
|
|
;;
|
|
esac
|
|
|
|
adb logcat -d -v time |
|
|
rg -i 'OpenClaw|TalkMode|MicCapture|AudioRecord|SpeechRecognizer|realtime|talk.session|appendAudio|transcript|Talk failed|Transcription failed|Speech network|VoiceE2E' |
|
|
tail -250 >"$ARTIFACT_DIR/logcat.txt" || true
|
|
|
|
if [[ "$CLEANUP" -eq 1 ]]; then
|
|
adb shell am broadcast -a "$RUN_ACTION" -n "$RECEIVER" --es mode stop >/dev/null
|
|
fi
|
|
|
|
echo "$ARTIFACT_DIR"
|