Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions Runner/suites/Connectivity/Bluetooth/BT_ON_OFF/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Bluetooth power-cycle validation

`BT_ON_OFF` verifies that a BlueZ controller can transition from powered on to
powered off and back on without changing the selected adapter.

## Usage

Run with automatic adapter discovery:

```sh
./run.sh
```

Select an adapter and tune the retry delays:

```sh
./run.sh \
--adapter hci0 \
--power-cycle-delay 10 \
--power-on-attempts 2 \
--power-on-retry-delay 10 \
--restart-service-on-retry 1
```

The command-line adapter overrides `BT_ADAPTER`. When neither is set, the
shared Bluetooth helper selects a usable runtime controller.

## Validation contract

The test uses the exact BlueZ `Powered: yes|no` property as its power-state
evidence. A transition passes only after two consecutive observations match the
requested state. This avoids accepting a transient or stale response while
BlueZ and the UART controller are settling.

`PowerState` and `hciconfig` state are retained as diagnostics only. For
example, `PowerState: on` or `UP RUNNING` can be present while BlueZ reports
`Powered: no`, so neither is accepted as proof of a successful power-on.

Expected success markers include:

```text
Power OFF completed with consecutive Powered=no confirmations
Power ON completed with consecutive Powered=yes confirmations
```

The test fails when the requested stable state is not observed within the
bounded helper attempts. If a power-on attempt fails, the suite records
diagnostics and can perform the configured controlled recovery before retrying.

## LAVA

The packaged definition exposes these parameters:

- `BT_ADAPTER`
- `BT_POWER_CYCLE_DELAY`
- `BT_POWER_ON_ATTEMPTS`
- `BT_POWER_ON_RETRY_DELAY`
- `BT_RESTART_SERVICE_ON_RETRY`
- `BT_RUNTIME_READY_WAIT`
- `BT_RUNTIME_RECOVERY_WAIT`
- `BT_RUNTIME_RECOVERY_ATTEMPTS`

The result is written to `BT_ON_OFF.res` and sent to LAVA as `BT_ON_OFF`.
30 changes: 7 additions & 23 deletions Runner/suites/Connectivity/Bluetooth/BT_ON_OFF/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
# SPDX-License-Identifier: BSD-3-Clause
# BT_ON_OFF - Basic Bluetooth power toggle validation (non-expect version)
# BT_ON_OFF - Basic Bluetooth power toggle validation

# ---------- Repo env + helpers ----------
SCRIPT_DIR="$(
Expand Down Expand Up @@ -241,18 +241,9 @@ log_info "Initial Powered = $initial_power"
log_info "Powering OFF..."
if ! btpower "$ADAPTER" off; then
btloghcidiag "$ADAPTER" failure "$testpath" || true
test_result_finish "FAIL" "btpower($ADAPTER, off) failed at command level"
fi

after_off="$(btgetpower "$ADAPTER" 2>/dev/null || true)"
[ -z "$after_off" ] && after_off="unknown"

if [ "$after_off" = "no" ]; then
test_result_record "PASS" "Post-OFF verification reported Powered=no"
else
btloghcidiag "$ADAPTER" failure "$testpath" || true
test_result_finish "FAIL" "Post-OFF verification failed with Powered=$after_off"
test_result_finish "FAIL" "btpower($ADAPTER, off) did not confirm stable Powered=no"
fi
test_result_record "PASS" "Power OFF completed with consecutive Powered=no confirmations"

# ---- Power ON test ----
log_info "Waiting ${BT_POWER_CYCLE_DELAY}s before Powering ON..."
Expand All @@ -266,15 +257,8 @@ while [ "$on_attempt" -le "$BT_POWER_ON_ATTEMPTS" ]; do
log_info "Power ON attempt $on_attempt/$BT_POWER_ON_ATTEMPTS"

if btpower "$ADAPTER" on; then
after_on="$(btgetpower "$ADAPTER" 2>/dev/null || true)"
[ -z "$after_on" ] && after_on="unknown"

if [ "$after_on" = "yes" ]; then
on_success=1
break
fi

log_warn "Power ON command returned success, but post-check Powered=$after_on"
on_success=1
break
else
log_warn "btpower($ADAPTER, on) failed on attempt $on_attempt"
fi
Expand Down Expand Up @@ -309,12 +293,12 @@ if [ "$on_success" -eq 1 ]; then

btwarniflistempty "$ADAPTER" || true

test_result_record "PASS" "Post-ON verification reported Powered=yes"
test_result_record "PASS" "Power ON completed with consecutive Powered=yes confirmations"
test_result_finish
fi

after_on="$(btgetpower "$ADAPTER" 2>/dev/null || true)"
[ -z "$after_on" ] && after_on="unknown"

btloghcidiag "$ADAPTER" failure "$testpath" || true
test_result_finish "FAIL" "Post-ON verification failed after $BT_POWER_ON_ATTEMPTS attempts with Powered=$after_on"
test_result_finish "FAIL" "Stable Powered=yes was not confirmed after $BT_POWER_ON_ATTEMPTS attempts, final observation=$after_on"
59 changes: 38 additions & 21 deletions Runner/utils/lib_bluetooth.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3036,17 +3036,23 @@ btgetpower() {

return 2
}
# Usage: btpower hci0 on|off
# Returns:
# 0 = requested state achieved (including when already in that state)
# 1 = requested state not achieved
# 2 = no controller / state unknown
# btpower ADAPTER on|off
# Request a BlueZ controller power transition and require two consecutive exact
# Powered=yes/no observations before reporting success.
# Inputs: adapter identifier and target state. Output: diagnostic logs only.
# Returns: 0 when the requested state is stable, 1 when it is not achieved, and
# 2 when no controller state can be read. Side effects: may issue bounded
# bluetoothctl power requests and wait between verification samples.
btpower() {
dev="${1:-}"
want="${2:-}"

case "$want" in
on|off)
on)
target_state=yes
;;
off)
target_state=no
;;
*)
log_warn "btpower: invalid target state '$want'"
Expand All @@ -3056,22 +3062,24 @@ btpower() {

cur_state="$(btgetpower "$dev" 2>/dev/null || true)"
[ -z "$cur_state" ] && cur_state="unknown"

if [ "$want" = "on" ] && [ "$cur_state" = "yes" ]; then
log_info "btpower: $dev already Powered=yes; skipping 'power on'."
return 0
fi

if [ "$want" = "off" ] && [ "$cur_state" = "no" ]; then
log_info "btpower: $dev already Powered=no; skipping 'power off'."
return 0

if [ "$cur_state" = "$target_state" ]; then
log_info "btpower: $dev already Powered=$target_state, confirming stable state."
sleep 1
confirm_state="$(btgetpower "$dev" 2>/dev/null || true)"
if [ "$confirm_state" = "$target_state" ]; then
log_info "btpower: $dev Powered=$target_state confirmed stable without a new request."
return 0
fi
log_warn "btpower: $dev initial Powered=$target_state observation was not stable, observed=${confirm_state:-unknown} on confirmation"
fi

log_info "btpower: requesting '$want' on $dev (current=$cur_state)"

request_attempts="${BT_POWER_REQUEST_ATTEMPTS:-3}"
verify_attempts="${BT_POWER_VERIFY_ATTEMPTS:-10}"
retry_delay="${BT_POWER_REQUEST_RETRY_DELAY:-2}"
required_confirmations=2

case "$request_attempts" in
""|*[!0-9]*) request_attempts=3 ;;
Expand All @@ -3089,8 +3097,11 @@ btpower() {
if [ "$verify_attempts" -lt 1 ] 2>/dev/null; then
verify_attempts=1
fi
if [ "$verify_attempts" -lt "$required_confirmations" ] 2>/dev/null; then
verify_attempts="$required_confirmations"
fi

log_info "btpower: request attempts=$request_attempts verify attempts=$verify_attempts retry delay=${retry_delay}s"
log_info "btpower: request attempts=$request_attempts verify attempts=$verify_attempts stable confirmations=$required_confirmations retry delay=${retry_delay}s"
if command -v expect >/dev/null 2>&1; then
log_info "btpower: using an expect PTY for interactive bluetoothctl power requests"
else
Expand All @@ -3110,19 +3121,25 @@ btpower() {
fi

verify_attempt=1
stable_confirmations=0
while [ "$verify_attempt" -le "$verify_attempts" ]; do
state="$(btgetpower "$dev" 2>/dev/null || true)"

if [ "$want" = "on" ] && [ "$state" = "yes" ]; then
log_info "btpower: $dev Powered=yes after request attempt $request_attempt."
return 0
if [ "$state" = "$target_state" ]; then
stable_confirmations=$((stable_confirmations + 1))
else
stable_confirmations=0
fi

if [ "$want" = "off" ] && [ "$state" = "no" ]; then
log_info "btpower: $dev Powered=no after request attempt $request_attempt."
if [ "$stable_confirmations" -ge "$required_confirmations" ]; then
log_info "btpower: $dev Powered=$state confirmed stable after request attempt $request_attempt."
return 0
fi

if [ "$stable_confirmations" -gt 0 ]; then
log_info "btpower: $dev Powered=$state confirmation $stable_confirmations/$required_confirmations"
fi

sleep 1
verify_attempt=$((verify_attempt + 1))
done
Expand Down
Loading