diff --git a/Runner/suites/Multimedia/Audio/AudioPlayback/AudioPlayback.yaml b/Runner/suites/Multimedia/Audio/AudioPlayback/AudioPlayback.yaml index 62e440a4..a8dbf238 100644 --- a/Runner/suites/Multimedia/Audio/AudioPlayback/AudioPlayback.yaml +++ b/Runner/suites/Multimedia/Audio/AudioPlayback/AudioPlayback.yaml @@ -18,6 +18,8 @@ params: DMESG_SCAN: 1 # Scan dmesg for errors after playback, default: 1 VERBOSE: 0 # Enable verbose logging, default: 0 EXTRACT_AUDIO_ASSETS: true # Download/extract audio assets if missing, default: true + ENABLE_NETWORK_DOWNLOAD: false # Enable network download of missing audio files, default: false + AUDIO_CLIPS_BASE_DIR: "" # Custom path to pre-staged audio clips (for CI), default: unset SSID: "" # Wi-Fi SSID for network connection, default: unset PASSWORD: "" # Wi-Fi password for network connection, default: unset NET_PROBE_ROUTE_IP: "1.1.1.1" # IP used for route probing, default: 1.1.1.1 @@ -27,5 +29,5 @@ run: steps: - REPO_PATH=$PWD - cd Runner/suites/Multimedia/Audio/AudioPlayback/ - - ./run.sh --backend "${AUDIO_BACKEND}" --sink "${SINK_CHOICE}" --format "${FORMAT}" --durations "${DURATIONS}" --loops "${LOOPS}" --timeout "${TIMEOUT}" --strict "${STRICT}" --ssid "${SSID}" --password "${PASSWORD}" || true - - $REPO_PATH/Runner/utils/send-to-lava.sh AudioPlayback.res || true + - ./run.sh --backend "${AUDIO_BACKEND}" --sink "${SINK_CHOICE}" --formats "${FORMATS}" --durations "${DURATIONS}" --loops "${LOOPS}" --timeout "${TIMEOUT}" --strict "${STRICT}" --audio-clips-path "${AUDIO_CLIPS_BASE_DIR}" --ssid "${SSID}" --password "${PASSWORD}" || true + - $REPO_PATH/Runner/utils/send-to-lava.sh AudioPlayback.res || true \ No newline at end of file diff --git a/Runner/suites/Multimedia/Audio/AudioPlayback/Read_me.md b/Runner/suites/Multimedia/Audio/AudioPlayback/Read_me.md index b965512e..a7c0dcf8 100644 --- a/Runner/suites/Multimedia/Audio/AudioPlayback/Read_me.md +++ b/Runner/suites/Multimedia/Audio/AudioPlayback/Read_me.md @@ -9,6 +9,7 @@ This suite automates the validation of audio playback capabilities on Qualcomm L - Supports **PipeWire** and **PulseAudio** backends - Plays audio clips with configurable format, duration, and loop count +- **Network operations are optional**: By default, no network connection is attempted. Use `--enable-network-download` to enable downloading missing audio files - Automatically downloads and extracts audio assets if missing - Validates playback using multiple evidence sources: - PipeWire/PulseAudio streaming state @@ -91,6 +92,23 @@ SSID="MyNetwork" PASSWORD="MyPassword" ./run-test.sh AudioPlayback # Override network probe targets (useful in restricted networks) NET_PROBE_ROUTE_IP=192.168.1.1 NET_PING_HOST=192.168.1.254 ./run-test.sh AudioPlayback +# Run without network (requires local clips) +./run.sh + +# Enable network download for missing clips +./run.sh --enable-network-download + +# Provide WiFi credentials (auto-enables download) +./run.sh --ssid "MyNetwork" --password "MyPassword" + +# Offline mode with local clips only +./run.sh --no-extract-assets + +# CI workflow: Use pre-staged clips at custom location +./run.sh --audio-clips-path /tmp/ci-audio-staging/AudioClips + +# CI workflow: Via environment variable +AUDIO_CLIPS_BASE_DIR="/tmp/ci-audio-staging/AudioClips" ./run-test.sh AudioPlayback **Directly from Test Directory** cd Runner/suites/Multimedia/Audio/AudioPlayback @@ -112,38 +130,42 @@ cd Runner/suites/Multimedia/Audio/AudioPlayback Environment Variables: -Variable Description Default -AUDIO_BACKEND Selects backend: pipewire or pulseaudio auto-detect -SINK_CHOICE Playback sink: speakers or null speakers -FORMATS Audio formats: e.g. wav wav -DURATIONS Playback durations: short, medium, long short -LOOPS Number of playback loops 1 -TIMEOUT Playback timeout per loop (e.g., 15s, 0=none) 0 -STRICT Enable strict mode (fail on any error) 0 -DMESG_SCAN Scan dmesg for errors after playback 1 -VERBOSE Enable verbose logging 0 -EXTRACT_AUDIO_ASSETS Download/extract audio assets if missing true -JUNIT_OUT Path to write JUnit XML output unset -SSID Wi-Fi SSID for network connection unset -PASSWORD Wi-Fi password for network connection unset -NET_PROBE_ROUTE_IP IP used for route probing (default: 1.1.1.1) 1.1.1.1 -NET_PING_HOST Host used for ping reachability check 8.8.8.8 +Variable Description Default +AUDIO_BACKEND Selects backend: pipewire or pulseaudio auto-detect +SINK_CHOICE Playback sink: speakers or null speakers +FORMATS Audio formats: e.g. wav wav +DURATIONS Playback durations: short, medium, long short +LOOPS Number of playback loops 1 +TIMEOUT Playback timeout per loop (e.g., 15s, 0=none) 0 +STRICT Enable strict mode (fail on any error) 0 +DMESG_SCAN Scan dmesg for errors after playback 1 +VERBOSE Enable verbose logging 0 +EXTRACT_AUDIO_ASSETS Download/extract audio assets if missing true +ENABLE_NETWORK_DOWNLOAD Enable network download of missing audio files false +AUDIO_CLIPS_BASE_DIR Custom path to pre-staged audio clips (CI use) unset +JUNIT_OUT Path to write JUnit XML output unset +SSID Wi-Fi SSID for network connection unset +PASSWORD Wi-Fi password for network connection unset +NET_PROBE_ROUTE_IP IP used for route probing (default: 1.1.1.1) 1.1.1.1 +NET_PING_HOST Host used for ping reachability check 8.8.8.8 CLI Options -Option Description ---backend Select backend: pipewire or pulseaudio ---sink Playback sink: speakers or null ---formats Audio formats (space/comma separated): e.g. wav ---durations Playback durations: short, medium, long ---loops Number of playback loops ---timeout Playback timeout per loop (e.g., 15s) ---strict Enable strict mode ---no-dmesg Disable dmesg scan ---no-extract-assets Disable asset extraction ---junit Write JUnit XML output ---verbose Enable verbose logging ---help Show usage instructions +Option Description +--backend Select backend: pipewire or pulseaudio +--sink Playback sink: speakers or null +--formats Audio formats (space/comma separated): e.g. wav +--durations Playback durations: short, medium, long +--loops Number of playback loops +--timeout Playback timeout per loop (e.g., 15s) +--strict Enable strict mode +--no-dmesg Disable dmesg scan +--no-extract-assets Disable asset extraction entirely (skips all asset operations) +--enable-network-download Enable network operations to download missing audio files (default: disabled) +--audio-clips-path Custom location for audio clips (for CI with pre-staged clips) +--junit Write JUnit XML output +--verbose Enable verbose logging +--help Show usage instructions ``` @@ -178,8 +200,10 @@ Diagnostic logs: dmesg snapshots, mixer dumps, playback logs per test case - The script validates the presence of required tools before executing tests; missing tools result in SKIP. - If any critical tool is missing, the script exits with an error message. - Logs include dmesg snapshots, mixer dumps, and playback logs. -- Asset download requires network connectivity. -- Pass Wi-Fi credentials via SSID and PASSWORD environment variables to enable network access for asset downloads and playback validation. +- **Network operations are disabled by default**. Use `--enable-network-download` to download missing audio files. +- Pass Wi-Fi credentials via `--ssid` and `--password` CLI flags (or SSID/PASSWORD environment variables) to auto-enable network download. +- If audio clips are present locally, the test runs without any network operations (offline-capable). +- If clips are missing and network download is disabled, the test will SKIP with a helpful message. - You can override default network probe targets using NET_PROBE_ROUTE_IP and NET_PING_HOST to avoid connectivity-related failures in restricted environments. - Evidence-based PASS/FAIL logic ensures reliability even if backend quirks occur. @@ -188,3 +212,4 @@ Diagnostic logs: dmesg snapshots, mixer dumps, playback logs per test case SPDX-License-Identifier: BSD-3-Clause-Clear (C) Qualcomm Technologies, Inc. and/or its subsidiaries. + diff --git a/Runner/suites/Multimedia/Audio/AudioPlayback/run.sh b/Runner/suites/Multimedia/Audio/AudioPlayback/run.sh index 19a9f9b4..af5d4d72 100755 --- a/Runner/suites/Multimedia/Audio/AudioPlayback/run.sh +++ b/Runner/suites/Multimedia/Audio/AudioPlayback/run.sh @@ -67,6 +67,8 @@ STRICT="${STRICT:-0}" DMESG_SCAN="${DMESG_SCAN:-1}" VERBOSE=0 EXTRACT_AUDIO_ASSETS="${EXTRACT_AUDIO_ASSETS:-true}" +ENABLE_NETWORK_DOWNLOAD="${ENABLE_NETWORK_DOWNLOAD:-false}" # Default: no network operations +AUDIO_CLIPS_BASE_DIR="${AUDIO_CLIPS_BASE_DIR:-}" # Custom path for audio clips (CI use) # Network bring-up knobs (match video behavior) if [ -z "${NET_STABILIZE_SLEEP:-}" ]; then @@ -88,6 +90,8 @@ Usage: $0 [options] --durations "short|short medium|short medium long" --loops N --timeout SECS # set 0 to disable watchdog + --enable-network-download + --audio-clips-path PATH # Custom location for audio clips (CI use) --strict --no-dmesg --no-extract-assets @@ -136,6 +140,14 @@ while [ $# -gt 0 ]; do EXTRACT_AUDIO_ASSETS=false shift ;; + --enable-network-download) + ENABLE_NETWORK_DOWNLOAD=true + shift + ;; + --audio-clips-path) + AUDIO_CLIPS_BASE_DIR="$2" + shift 2 + ;; --ssid) # shellcheck disable=SC2034 SSID="$2" @@ -161,6 +173,12 @@ while [ $# -gt 0 ]; do esac done +# Auto-enable network download if WiFi credentials provided +if [ -n "$SSID" ] && [ -n "$PASSWORD" ]; then + log_info "WiFi credentials provided, auto-enabling network download" + ENABLE_NETWORK_DOWNLOAD=true +fi + # Ensure we run from the testcase dir test_path="$(find_test_case_by_name "$TESTNAME" 2>/dev/null || echo "$SCRIPT_DIR")" if ! cd "$test_path"; then @@ -178,7 +196,13 @@ else log_info "Platform Details: unknown" fi -log_info "Args: backend=${AUDIO_BACKEND:-auto} sink=$SINK_CHOICE loops=$LOOPS timeout=$TIMEOUT formats='$FORMATS' durations='$DURATIONS' strict=$STRICT dmesg=$DMESG_SCAN extract=$EXTRACT_AUDIO_ASSETS" +# Export AUDIO_CLIPS_BASE_DIR for use by resolve_clip() in audio_common.sh +if [ -n "$AUDIO_CLIPS_BASE_DIR" ]; then + export AUDIO_CLIPS_BASE_DIR + log_info "Using custom audio clips path: $AUDIO_CLIPS_BASE_DIR" +fi + +log_info "Args: backend=${AUDIO_BACKEND:-auto} sink=$SINK_CHOICE loops=$LOOPS timeout=$TIMEOUT formats='$FORMATS' durations='$DURATIONS' strict=$STRICT dmesg=$DMESG_SCAN extract=$EXTRACT_AUDIO_ASSETS network_download=$ENABLE_NETWORK_DOWNLOAD clips_path=${AUDIO_CLIPS_BASE_DIR:-default}" # --- Rootfs minimum size check (mirror video policy) --- if [ "$TOP_LEVEL_RUN" -eq 1 ]; then @@ -187,25 +211,51 @@ else log_info "Sub-run: skipping rootfs size check (already performed)." fi -# --- Network preflight identical to video gating --- +# --- Smart network gating: only connect if needed --- if [ "$TOP_LEVEL_RUN" -eq 1 ]; then if [ "${EXTRACT_AUDIO_ASSETS}" = "true" ]; then - NET_RC="1" - - if command -v check_network_status_rc >/dev/null 2>&1; then - check_network_status_rc - NET_RC="$?" - elif command -v check_network_status >/dev/null 2>&1; then - check_network_status >/dev/null 2>&1 - NET_RC="$?" - fi - - if [ "$NET_RC" -ne 0 ]; then - video_step "" "Bring network online (Wi-Fi credentials if provided)" - ensure_network_online || true - sleep "${NET_STABILIZE_SLEEP}" + # First check: Do we have all files we need? + if audio_check_clips_available "$FORMATS" "$DURATIONS"; then + log_info "All required audio clips present locally, skipping all network operations" else - sleep "${NET_STABILIZE_SLEEP}" + # Files missing - check if network download is enabled + if [ "${ENABLE_NETWORK_DOWNLOAD}" = "true" ]; then + log_info "Audio clips missing, network download enabled - bringing network online" + # Now check network status and bring up if needed + NET_RC="1" + if command -v check_network_status_rc >/dev/null 2>&1; then + check_network_status_rc + NET_RC="$?" + elif command -v check_network_status >/dev/null 2>&1; then + check_network_status >/dev/null 2>&1 + NET_RC="$?" + fi + + if [ "$NET_RC" -ne 0 ]; then + video_step "" "Bring network online (Wi-Fi credentials if provided)" + ensure_network_online || true + sleep "${NET_STABILIZE_SLEEP}" + else + sleep "${NET_STABILIZE_SLEEP}" + fi + + # Download and extract audio clips tarball + log_info "Downloading audio clips from: $AUDIO_TAR_URL" + if audio_fetch_assets_from_url "$AUDIO_TAR_URL"; then + log_info "Audio clips downloaded and extracted successfully" + else + log_error "Failed to download or extract audio clips from: $AUDIO_TAR_URL" + log_skip "$TESTNAME SKIP - Audio clips download failed" + echo "$TESTNAME SKIP" >"$RES_FILE" + exit 0 + fi + else + log_skip "$TESTNAME SKIP - Required audio clips not found locally and network download disabled" + log_info "To download audio clips, run with: --enable-network-download" + log_info "Or manually download from: $AUDIO_TAR_URL" + echo "$TESTNAME SKIP" >"$RES_FILE" + exit 0 + fi fi fi else @@ -323,28 +373,22 @@ for fmt in $FORMATS; do continue fi + # Check if clip is available (should have been downloaded at top level if needed) if [ "${EXTRACT_AUDIO_ASSETS}" = "true" ]; then - if [ -f "$clip" ] && [ -s "$clip" ]; then + if [ -s "$clip" ]; then CLIP_BYTES="$(wc -c < "$clip" 2>/dev/null || echo 0)" - log_info "[$case_name] Clip already present: $clip (${CLIP_BYTES} bytes) — skipping fetch/extract." + log_info "[$case_name] Using clip: $clip (${CLIP_BYTES} bytes)" else - log_info "[$case_name] Preparing assets for clip: $clip (not found locally)" - log_info "[$case_name] Attempting fetch/extract from: $AUDIO_TAR_URL" - - audio_ensure_clip_ready "$clip" "$AUDIO_TAR_URL" - rc=$? - - if [ "$rc" -eq 0 ] && [ -f "$clip" ]; then - CLIP_BYTES="$(wc -c < "$clip" 2>/dev/null || echo 0)" - log_info "[$case_name] Clip ready: $clip (${CLIP_BYTES} bytes)" - fi - - if [ "$rc" -eq 2 ] || [ "$rc" -eq 1 ]; then - log_skip "[$case_name] SKIP: Required clip missing and network unavailable or fetch failed." - echo "$case_name SKIP (clip missing)" >> "$LOGDIR/summary.txt" - skip=$((skip + 1)) - continue + # Clip missing or empty - this shouldn't happen if top-level download succeeded + log_skip "[$case_name] SKIP: Clip not available: $clip" + if [ "${ENABLE_NETWORK_DOWNLOAD}" = "true" ]; then + log_info "[$case_name] Hint: Clip should have been downloaded at test startup" + else + log_info "[$case_name] Hint: Run with --enable-network-download to download clips" fi + echo "$case_name SKIP (clip unavailable)" >> "$LOGDIR/summary.txt" + skip=$((skip + 1)) + continue fi fi diff --git a/Runner/utils/audio_common.sh b/Runner/utils/audio_common.sh index 0f9e6c7f..d7e77c5f 100755 --- a/Runner/utils/audio_common.sh +++ b/Runner/utils/audio_common.sh @@ -30,7 +30,8 @@ check_audio_daemon() { # ---------- Assets / clips ---------- resolve_clip() { - fmt="$1"; dur="$2"; base="AudioClips" + fmt="$1"; dur="$2" + base="${AUDIO_CLIPS_BASE_DIR:-AudioClips}" case "$fmt:$dur" in wav:short|wav:medium|wav:long) printf '%s\n' "$base/yesterday_48KHz.wav" ;; *) printf '%s\n' "" ;; @@ -735,3 +736,22 @@ alsa_pick_virtual_pcm() { done return 1 } + + +# Check if all required audio clips are available locally +# Usage: audio_check_clips_available "$FORMATS" "$DURATIONS" +# Returns: 0 if all clips present and non-empty, 1 if any clip missing or empty +audio_check_clips_available() { + formats="$1" + durations="$2" + + for fmt in $formats; do + for dur in $durations; do + clip="$(resolve_clip "$fmt" "$dur")" + if [ -n "$clip" ] && [ ! -s "$clip" ]; then + return 1 # At least one clip missing or empty + fi + done + done + return 0 # All clips present and non-empty +} \ No newline at end of file