Make Airplane Mode Toggle Wait for All Radios to Change State
The toggle_airplane_mode() function previously only waited for
a connectivity state change, and then it would check that both
wifi and bluetooth radios had changed state. Unfortunately, those
radios sometimes require more time to turn on/off when entering
or leaving airplane mode than is taken by the CONNECTIVITY_CHANGE
broadcast. Thus, we need to wait for connectivity change and then
each of the peripheral radios in turn up to the maximum amount of
time.
Bug: 31473466
Test: none
Change-Id: I397d04f12cbd368ba229cb72306229580d76cb57
diff --git a/acts/framework/acts/test_utils/tel/tel_test_utils.py b/acts/framework/acts/test_utils/tel/tel_test_utils.py
index ed47b70..d930b79 100644
--- a/acts/framework/acts/test_utils/tel/tel_test_utils.py
+++ b/acts/framework/acts/test_utils/tel/tel_test_utils.py
@@ -319,6 +319,40 @@
event_recv_list[i] = value
+def _wait_for_bluetooth_in_state(log, ad, state, max_wait):
+ # FIXME: These event names should be defined in a common location
+ _BLUETOOTH_STATE_ON_EVENT = 'BluetoothStateChangedOn'
+ _BLUETOOTH_STATE_OFF_EVENT = 'BluetoothStateChangedOff'
+ ad.droid.bluetoothStartListeningForAdapterStateChange()
+ try:
+ bt_state = ad.droid.bluetoothCheckState()
+ if bt_state == state:
+ return True
+ if max_wait <= 0:
+ log.error("Time out: bluetooth state still {}, expecting {}".format(
+ bt_state, state))
+ return False
+
+ event = {False: _BLUETOOTH_STATE_OFF_EVENT,
+ True: _BLUETOOTH_STATE_ON_EVENT}[state]
+ ad.ed.pop_event(event, max_wait)
+ return True
+ except Empty:
+ log.error("Time out: bluetooth state still {}, expecting {}".format(
+ bt_state, state))
+ return False
+ finally:
+ ad.droid.bluetoothStopListeningForAdapterStateChange()
+
+
+# TODO: replace this with an event-based function
+def _wait_for_wifi_in_state(log, ad, state, max_wait):
+ return _wait_for_droid_in_state(log, ad, max_wait,
+ lambda log, ad, state: \
+ (True if ad.droid.wifiCheckState() == state else False),
+ state)
+
+
def toggle_airplane_mode_msim(log, ad, new_state=None):
""" Toggle the state of airplane mode.
@@ -367,6 +401,8 @@
for sub_id in sub_id_list:
ad.droid.telephonyStartTrackingServiceStateChangeForSubscription(
sub_id)
+
+ timeout_time = time.time() + MAX_WAIT_TIME_AIRPLANEMODE_EVENT
ad.droid.connectivityToggleAirplaneMode(new_state)
event = None
@@ -390,15 +426,22 @@
ad.droid.telephonyStopTrackingServiceStateChangeForSubscription(
sub_id)
- if new_state:
- if (not ad.droid.connectivityCheckAirplaneMode() or
- ad.droid.wifiCheckState() or ad.droid.bluetoothCheckState()):
- log.error("Airplane mode ON fail on {}".format(ad.serial))
- return False
- else:
- if ad.droid.connectivityCheckAirplaneMode():
- log.error("Airplane mode OFF fail on {}".format(ad.serial))
- return False
+ # APM on (new_state=True) will turn off bluetooth but may not turn it on
+ if new_state and not _wait_for_bluetooth_in_state(
+ log, ad, False, timeout_time - time.time()):
+ log.error("Failed waiting for bluetooth during airplane mode toggle")
+ return False
+
+ # APM on (new_state=True) will turn off wifi but may not turn it on
+ if new_state and not _wait_for_wifi_in_state(
+ log, ad, False, timeout_time - time.time()):
+ log.error("Failed waiting for wifi during airplane mode toggle")
+ return False
+
+ if ad.droid.connectivityCheckAirplaneMode() != new_state:
+ log.error("Airplane mode {} failed on {}".format("ON" if new_state else
+ "OFF", ad.serial))
+ return False
return True