resolve merge conflicts of 9bce15d9087a80c2bf565717e9b61c1a2fcd02e3 to stage-aosp-master
BUG: None
Test: I solemnly swear I tested this conflict resolution.
Change-Id: I41cfea9d74d5f044866ade338d187b469acb4c4d
diff --git a/Android.mk b/Android.mk
index 4040a1c..11b923b 100644
--- a/Android.mk
+++ b/Android.mk
@@ -23,11 +23,11 @@
# general Android Conntectivity Test Suite
ACTS_DISTRO := $(HOST_OUT)/acts-dist/acts.zip
-$(ACTS_DISTRO): $(sort $(shell find $(LOCAL_PATH)/acts/framework))
+$(ACTS_DISTRO): $(sort $(shell find $(LOCAL_PATH)/acts))
@echo "Packaging ACTS into $(ACTS_DISTRO)"
@mkdir -p $(HOST_OUT)/acts-dist/
@rm -f $(HOST_OUT)/acts-dist/acts.zip
- $(hide) zip -r $(HOST_OUT)/acts-dist/acts.zip tools/test/connectivity/acts/*
+ $(hide) zip $(HOST_OUT)/acts-dist/acts.zip $(shell find tools/test/connectivity/acts/* ! -wholename "*__pycache__*")
acts: $(ACTS_DISTRO)
$(call dist-for-goals,tests,$(ACTS_DISTRO))
diff --git a/acts/framework/acts/controllers/attenuator_lib/_tnhelper.py b/acts/framework/acts/controllers/attenuator_lib/_tnhelper.py
index 6dbfd49..d03cf19 100644
--- a/acts/framework/acts/controllers/attenuator_lib/_tnhelper.py
+++ b/acts/framework/acts/controllers/attenuator_lib/_tnhelper.py
@@ -19,6 +19,7 @@
User code shouldn't need to directly access this class.
"""
+import logging
import telnetlib
from acts.controllers import attenuator
@@ -44,7 +45,7 @@
def open(self, host, port=23):
if self._tn:
self._tn.close()
-
+ logging.debug("Attenuator IP = %s" % host)
self._tn = telnetlib.Telnet()
self._tn.open(host, port, 10)
diff --git a/acts/framework/acts/test_utils/bt/bt_contacts_utils.py b/acts/framework/acts/test_utils/bt/bt_contacts_utils.py
index 1024c80..9d6b2c7 100644
--- a/acts/framework/acts/test_utils/bt/bt_contacts_utils.py
+++ b/acts/framework/acts/test_utils/bt/bt_contacts_utils.py
@@ -425,3 +425,4 @@
log.info(pce_call_log)
return call_logs_match
+
diff --git a/acts/framework/acts/test_utils/bt/bt_test_utils.py b/acts/framework/acts/test_utils/bt/bt_test_utils.py
index d7e44f1..e35e2f1 100644
--- a/acts/framework/acts/test_utils/bt/bt_test_utils.py
+++ b/acts/framework/acts/test_utils/bt/bt_test_utils.py
@@ -1,4 +1,4 @@
-#/usr/bin/env python3.4
+# /usr/bin/env python3.4
#
# Copyright (C) 2016 The Android Open Source Project
#
@@ -421,7 +421,7 @@
regex = "(" + adv_succ.format(
advertise_callback) + "|" + adv_fail.format(
- advertise_callback) + ")"
+ advertise_callback) + ")"
# wait for either success or failure event
evt = android_device.ed.pop_events(regex, bt_default_timeout,
small_timeout)
@@ -474,7 +474,7 @@
else:
max_advertisements = determine_max_advertisements(a)
max_tries = 3
- #Retry to calculate max advertisements
+ # Retry to calculate max advertisements
while max_advertisements == -1 and max_tries > 0:
a.log.info(
"Attempts left to determine max advertisements: {}".format(
@@ -497,7 +497,7 @@
def generate_id_by_size(
size,
chars=(
- string.ascii_lowercase + string.ascii_uppercase + string.digits)):
+ string.ascii_lowercase + string.ascii_uppercase + string.digits)):
"""Generate random ascii characters of input size and input char types
Args:
@@ -537,7 +537,7 @@
except Exception as err:
adv_android_device.log.debug(
"Failed to stop LE advertisement... reseting Bluetooth. Error {}".
- format(err))
+ format(err))
reset_bluetooth([adv_android_device])
@@ -902,7 +902,7 @@
paired = False
for paired_device in pri_ad.droid.bluetoothGetBondedDevices():
if paired_device['address'] == \
- sec_ad.droid.bluetoothGetLocalAddress():
+ sec_ad.droid.bluetoothGetLocalAddress():
paired = True
break
@@ -960,7 +960,7 @@
device_addr = profile_event['data']['addr']
if state == bt_profile_states['connected'] and \
- device_addr == sec_ad.droid.bluetoothGetLocalAddress():
+ device_addr == sec_ad.droid.bluetoothGetLocalAddress():
profile_connected.add(profile)
pri_ad.log.info(
"Profiles connected until now {}".format(profile_connected))
@@ -1020,7 +1020,7 @@
device_addr = profile_event['data']['addr']
if state == bt_profile_states['disconnected'] and \
- device_addr == sec_ad.droid.bluetoothGetLocalAddress():
+ device_addr == sec_ad.droid.bluetoothGetLocalAddress():
profile_disconnected.add(profile)
pri_ad.log.info(
"Profiles disconnected so far {}".format(profile_disconnected))
@@ -1252,6 +1252,11 @@
if not toggle_airplane_mode_by_adb(log, panu_dut, True):
panu_dut.log.error("Failed to toggle airplane mode on")
return False
+ if not toggle_airplane_mode_by_adb(log, panu_dut, False):
+ pan_dut.log.error("Failed to toggle airplane mode off")
+ return False
+ pan_dut.droid.bluetoothStartConnectionStateChangeMonitor("")
+ panu_dut.droid.bluetoothStartConnectionStateChangeMonitor("")
if not bluetooth_enabled_check(panu_dut):
return False
if not bluetooth_enabled_check(pan_dut):
@@ -1387,6 +1392,26 @@
hid_keyboard_report("00"))
+def is_a2dp_connected(sink, source):
+ """
+ Convenience Function to see if the 2 devices are connected on
+ A2dp.
+ Args:
+ sink: Audio Sink
+ source: Audio Source
+ Returns:
+ True if Connected
+ False if Not connected
+ """
+
+ devices = sink.droid.bluetoothA2dpSinkGetConnectedDevices()
+ for device in devices:
+ sink.log.info("A2dp Connected device {}".format(device["name"]))
+ if (device["address"] == source.droid.bluetoothGetLocalAddress()):
+ return True
+ return False
+
+
def get_device_selector_dictionary(android_device_list):
"""Create a dictionary of Bluetooth features vs Android devices.
diff --git a/acts/framework/acts/test_utils/car/car_media_utils.py b/acts/framework/acts/test_utils/car/car_media_utils.py
index 6c7bc3d..3fb1e6c 100644
--- a/acts/framework/acts/test_utils/car/car_media_utils.py
+++ b/acts/framework/acts/test_utils/car/car_media_utils.py
@@ -84,26 +84,6 @@
return verifyEventReceived(log, toDevice, expctEvent, timeout)
-def is_a2dp_connected(log, sink, source):
- """
- Convenience Function to see if the 2 devices are connected on
- A2dp.
- ToDo: Move to bt_test_utils if used in more places.
- Args:
- sink: Audio Sink
- source: Audio Source
- Returns:
- True if Connected
- False if Not connected
- """
- devices = sink.droid.bluetoothA2dpSinkGetConnectedDevices()
- for device in devices:
- log.info("A2dp Connected device {}".format(device["name"]))
- if (device["address"] == source.droid.bluetoothGetLocalAddress()):
- return True
- return False
-
-
def log_metadata(log, metadata):
"""
Log the Metadata to the console.
@@ -154,7 +134,7 @@
return False
if not (metadata1[MEDIA_KEY_NUM_TRACKS] == metadata2[MEDIA_KEY_NUM_TRACKS]
- ):
+ ):
log.info("Song Num Tracks do not match")
return False
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 d6896c7..e7a7609 100644
--- a/acts/framework/acts/test_utils/tel/tel_test_utils.py
+++ b/acts/framework/acts/test_utils/tel/tel_test_utils.py
@@ -2837,6 +2837,9 @@
def trigger_modem_crash_by_modem(ad, timeout=120):
begin_time = get_device_epoch_time(ad)
ad.adb.shell(
+ "setprop persist.vendor.sys.modem.diag.mdlog false", ignore_status=True)
+ # Legacy pixels use persist.sys.modem.diag.mdlog.
+ ad.adb.shell(
"setprop persist.sys.modem.diag.mdlog false", ignore_status=True)
disable_qxdm_logger(ad)
cmd = ('am instrument -w -e request "4b 25 03 00" '
diff --git a/acts/framework/acts/test_utils/wifi/aware/AwareBaseTest.py b/acts/framework/acts/test_utils/wifi/aware/AwareBaseTest.py
index dec26a2..9ca84d3 100644
--- a/acts/framework/acts/test_utils/wifi/aware/AwareBaseTest.py
+++ b/acts/framework/acts/test_utils/wifi/aware/AwareBaseTest.py
@@ -15,6 +15,7 @@
# limitations under the License.
from acts import asserts
+from acts import utils
from acts.base_test import BaseTestClass
from acts.test_utils.wifi import wifi_test_utils as wutils
from acts.test_utils.wifi.aware import aware_const as aconsts
@@ -23,7 +24,7 @@
class AwareBaseTest(BaseTestClass):
def __init__(self, controllers):
- BaseTestClass.__init__(self, controllers)
+ super(AwareBaseTest, self).__init__(controllers)
# message ID counter to make sure all uses are unique
msg_id = 0
@@ -43,6 +44,7 @@
"Device under test does not support Wi-Fi Aware - skipping test")
wutils.wifi_toggle_state(ad, True)
ad.droid.wifiP2pClose()
+ utils.set_location_service(ad, True)
aware_avail = ad.droid.wifiIsAwareAvailable()
if not aware_avail:
self.log.info('Aware not available. Waiting ...')
@@ -52,7 +54,11 @@
self.reset_device_parameters(ad)
self.reset_device_statistics(ad)
self.set_power_mode_parameters(ad)
-
+ ad.droid.wifiSetCountryCode(wutils.WifiEnums.CountryCode.US)
+ autils.configure_ndp_allow_any_override(ad, True)
+ # set randomization interval to 0 (disable) to reduce likelihood of
+ # interference in tests
+ autils.configure_mac_random_interval(ad, 0)
def teardown_test(self):
for ad in self.android_devices:
@@ -85,9 +91,9 @@
"""Set the power configuration DW parameters for the device based on any
configuration overrides (if provided)"""
if self.aware_default_power_mode == "INTERACTIVE":
- autils.config_dw_high_power(ad)
+ autils.config_settings_high_power(ad)
elif self.aware_default_power_mode == "NON_INTERACTIVE":
- autils.config_dw_low_power(ad)
+ autils.config_settings_low_power(ad)
else:
asserts.assert_false(
"The 'aware_default_power_mode' configuration must be INTERACTIVE or "
@@ -102,3 +108,8 @@
"""
self.msg_id = self.msg_id + 1
return self.msg_id
+
+ def on_fail(self, test_name, begin_time):
+ for ad in self.android_devices:
+ ad.take_bug_report(test_name, begin_time)
+ ad.cat_adb_log(test_name, begin_time)
diff --git a/acts/framework/acts/test_utils/wifi/aware/aware_const.py b/acts/framework/acts/test_utils/wifi/aware/aware_const.py
index 608c5c7..36c469e 100644
--- a/acts/framework/acts/test_utils/wifi/aware/aware_const.py
+++ b/acts/framework/acts/test_utils/wifi/aware/aware_const.py
@@ -15,14 +15,21 @@
# limitations under the License.
######################################################
-# Aware DW (Discovery Window) power mode values
+# Aware power settings values for interactive (high power) and
+# non-interactive (low power) modes
######################################################
-DW_24_INTERACTIVE = 1
-DW_5_INTERACTIVE = 1
+POWER_DW_24_INTERACTIVE = 1
+POWER_DW_5_INTERACTIVE = 1
+POWER_DISC_BEACON_INTERVAL_INTERACTIVE = 0
+POWER_NUM_SS_IN_DISC_INTERACTIVE = 0
+POWER_ENABLE_DW_EARLY_TERM_INTERACTIVE = 0
-DW_24_NON_INTERACTIVE = 4
-DW_5_NON_INTERACTIVE = 0
+POWER_DW_24_NON_INTERACTIVE = 4
+POWER_DW_5_NON_INTERACTIVE = 0
+POWER_DISC_BEACON_INTERVAL_NON_INTERACTIVE = 0
+POWER_NUM_SS_IN_DISC_NON_INTERACTIVE = 0
+POWER_ENABLE_DW_EARLY_TERM_NON_INTERACTIVE = 0
######################################################
# Broadcast events
@@ -51,6 +58,9 @@
DISCOVERY_KEY_DISCOVERY_TYPE = "DiscoveryType"
DISCOVERY_KEY_TTL = "TtlSec"
DISCOVERY_KEY_TERM_CB_ENABLED = "TerminateNotificationEnabled"
+DISCOVERY_KEY_RANGING_ENABLED = "RangingEnabled"
+DISCOVERY_KEY_MIN_DISTANCE_MM = "MinDistanceMm"
+DISCOVERY_KEY_MAX_DISTANCE_MM = "MaxDistanceMm"
PUBLISH_TYPE_UNSOLICITED = 0
PUBLISH_TYPE_SOLICITED = 1
@@ -101,6 +111,7 @@
SESSION_CB_KEY_MESSAGE_AS_STRING = "messageAsString"
SESSION_CB_KEY_LATENCY_MS = "latencyMs"
SESSION_CB_KEY_TIMESTAMP_MS = "timestampMs"
+SESSION_CB_KEY_DISTANCE_MM = "distanceMm"
######################################################
# WifiAwareRangingListener events (RttManager.RttListener)
diff --git a/acts/framework/acts/test_utils/wifi/aware/aware_test_utils.py b/acts/framework/acts/test_utils/wifi/aware/aware_test_utils.py
index 092df2b..ca15db5 100644
--- a/acts/framework/acts/test_utils/wifi/aware/aware_test_utils.py
+++ b/acts/framework/acts/test_utils/wifi/aware/aware_test_utils.py
@@ -310,21 +310,78 @@
data_min = min(data)
data_max = max(data)
data_mean = statistics.mean(data)
+ data_cdf = extract_cdf(data)
+ data_cdf_decile = extract_cdf_decile(data_cdf)
results['%smin' % key_prefix] = data_min
results['%smax' % key_prefix] = data_max
results['%smean' % key_prefix] = data_mean
+ results['%scdf' % key_prefix] = data_cdf
+ results['%scdf_decile' % key_prefix] = data_cdf_decile
results['%sraw_data' % key_prefix] = data
if num_samples > 1:
data_stdev = statistics.stdev(data)
results['%sstdev' % key_prefix] = data_stdev
- ad.log.info('%s: num_samples=%d, min=%.2f, max=%.2f, mean=%.2f, stdev=%.2f',
- log_prefix, num_samples, data_min, data_max, data_mean,
- data_stdev)
+ ad.log.info(
+ '%s: num_samples=%d, min=%.2f, max=%.2f, mean=%.2f, stdev=%.2f, cdf_decile=%s',
+ log_prefix, num_samples, data_min, data_max, data_mean, data_stdev,
+ data_cdf_decile)
else:
- ad.log.info('%s: num_samples=%d, min=%.2f, max=%.2f, mean=%.2f', log_prefix,
- num_samples, data_min, data_max, data_mean)
+ ad.log.info(
+ '%s: num_samples=%d, min=%.2f, max=%.2f, mean=%.2f, cdf_decile=%s',
+ log_prefix, num_samples, data_min, data_max, data_mean, data_cdf_decile)
+
+def extract_cdf_decile(cdf):
+ """Extracts the 10%, 20%, ..., 90% points from the CDF and returns their
+ value (a list of 9 values).
+
+ Since CDF may not (will not) have exact x% value picks the value >= x%.
+
+ Args:
+ cdf: a list of 2 lists, the X and Y of the CDF.
+ """
+ decades = []
+ next_decade = 10
+ for x, y in zip(cdf[0], cdf[1]):
+ while 100*y >= next_decade:
+ decades.append(x)
+ next_decade = next_decade + 10
+ if next_decade == 100:
+ break
+ return decades
+
+def extract_cdf(data):
+ """Calculates the Cumulative Distribution Function (CDF) of the data.
+
+ Args:
+ data: A list containing data (does not have to be sorted).
+
+ Returns: a list of 2 lists: the X and Y axis of the CDF.
+ """
+ x = []
+ cdf = []
+ if not data:
+ return (x, cdf)
+
+ all_values = sorted(data)
+ for val in all_values:
+ if not x:
+ x.append(val)
+ cdf.append(1)
+ else:
+ if x[-1] == val:
+ cdf[-1] += 1
+ else:
+ x.append(val)
+ cdf.append(cdf[-1] + 1)
+
+ scale = 1.0 / len(all_values)
+ for i in range(len(cdf)):
+ cdf[i] = cdf[i] * scale
+
+ return (x, cdf)
+
def get_mac_addr(device, interface):
"""Get the MAC address of the specified interface. Uses ifconfig and parses
@@ -392,74 +449,134 @@
return dut.droid.wifiAwareCreateNetworkSpecifierOob(
id, dev_type, peer_mac, None, sec)
-def configure_dw(device, is_default, is_24_band, value):
- """Use the command-line API to configure the DW (discovery window) setting
+def configure_power_setting(device, mode, name, value):
+ """Use the command-line API to configure the power setting
Args:
device: Device on which to perform configuration
- is_default: True for the default setting, False for the non-interactive
- setting
- is_24_band: True for 2.4GHz band, False for 5GHz band
- value: An integer 0 to 5
+ mode: The power mode being set, should be "default", "inactive", or "idle"
+ name: One of the power settings from 'wifiaware set-power'.
+ value: An integer.
"""
- variable = 'dw_%s_%sghz' % ('default' if is_default else 'on_inactive', '24'
- if is_24_band else '5')
- device.adb.shell("cmd wifiaware native_api set %s %d" % (variable, value))
+ device.adb.shell(
+ "cmd wifiaware native_api set-power %s %s %d" % (mode, name, value))
-def config_dw_high_power(device):
- """Configure device's discovery window (DW) values to high power mode -
+def configure_mac_random_interval(device, interval_sec):
+ """Use the command-line API to configure the MAC address randomization
+ interval.
+
+ Args:
+ device: Device on which to perform configuration
+ interval_sec: The MAC randomization interval in seconds. A value of 0
+ disables all randomization.
+ """
+ device.adb.shell(
+ "cmd wifiaware native_api set mac_random_interval_sec %d" % interval_sec)
+
+def configure_ndp_allow_any_override(device, override_api_check):
+ """Use the command-line API to configure whether an NDP Responder may be
+ configured to accept an NDP request from ANY peer.
+
+ By default the target API level of the requesting app determines whether such
+ configuration is permitted. This allows overriding the API check and allowing
+ it.
+
+ Args:
+ device: Device on which to perform configuration.
+ override_api_check: True to allow a Responder to ANY configuration, False to
+ perform the API level check.
+ """
+ device.adb.shell("cmd wifiaware state_mgr allow_ndp_any %s" % (
+ "true" if override_api_check else "false"))
+
+def config_settings_high_power(device):
+ """Configure device's power settings values to high power mode -
whether device is in interactive or non-interactive modes"""
- configure_dw(
- device, is_default=True, is_24_band=True, value=aconsts.DW_24_INTERACTIVE)
- configure_dw(
- device, is_default=True, is_24_band=False, value=aconsts.DW_5_INTERACTIVE)
- configure_dw(
- device,
- is_default=False,
- is_24_band=True,
- value=aconsts.DW_24_INTERACTIVE)
- configure_dw(
- device,
- is_default=False,
- is_24_band=False,
- value=aconsts.DW_5_INTERACTIVE)
+ configure_power_setting(device, "default", "dw_24ghz",
+ aconsts.POWER_DW_24_INTERACTIVE)
+ configure_power_setting(device, "default", "dw_5ghz",
+ aconsts.POWER_DW_5_INTERACTIVE)
+ configure_power_setting(device, "default", "disc_beacon_interval_ms",
+ aconsts.POWER_DISC_BEACON_INTERVAL_INTERACTIVE)
+ configure_power_setting(device, "default", "num_ss_in_discovery",
+ aconsts.POWER_NUM_SS_IN_DISC_INTERACTIVE)
+ configure_power_setting(device, "default", "enable_dw_early_term",
+ aconsts.POWER_ENABLE_DW_EARLY_TERM_INTERACTIVE)
-def config_dw_low_power(device):
- """Configure device's discovery window (DW) values to low power mode - whether
+ configure_power_setting(device, "inactive", "dw_24ghz",
+ aconsts.POWER_DW_24_INTERACTIVE)
+ configure_power_setting(device, "inactive", "dw_5ghz",
+ aconsts.POWER_DW_5_INTERACTIVE)
+ configure_power_setting(device, "inactive", "disc_beacon_interval_ms",
+ aconsts.POWER_DISC_BEACON_INTERVAL_INTERACTIVE)
+ configure_power_setting(device, "inactive", "num_ss_in_discovery",
+ aconsts.POWER_NUM_SS_IN_DISC_INTERACTIVE)
+ configure_power_setting(device, "inactive", "enable_dw_early_term",
+ aconsts.POWER_ENABLE_DW_EARLY_TERM_INTERACTIVE)
+
+def config_settings_low_power(device):
+ """Configure device's power settings values to low power mode - whether
device is in interactive or non-interactive modes"""
- configure_dw(
- device,
- is_default=True,
- is_24_band=True,
- value=aconsts.DW_24_NON_INTERACTIVE)
- configure_dw(
- device,
- is_default=True,
- is_24_band=False,
- value=aconsts.DW_5_NON_INTERACTIVE)
- configure_dw(
- device,
- is_default=False,
- is_24_band=True,
- value=aconsts.DW_24_NON_INTERACTIVE)
- configure_dw(
- device,
- is_default=False,
- is_24_band=False,
- value=aconsts.DW_5_NON_INTERACTIVE)
+ configure_power_setting(device, "default", "dw_24ghz",
+ aconsts.POWER_DW_24_NON_INTERACTIVE)
+ configure_power_setting(device, "default", "dw_5ghz",
+ aconsts.POWER_DW_5_NON_INTERACTIVE)
+ configure_power_setting(device, "default", "disc_beacon_interval_ms",
+ aconsts.POWER_DISC_BEACON_INTERVAL_NON_INTERACTIVE)
+ configure_power_setting(device, "default", "num_ss_in_discovery",
+ aconsts.POWER_NUM_SS_IN_DISC_NON_INTERACTIVE)
+ configure_power_setting(device, "default", "enable_dw_early_term",
+ aconsts.POWER_ENABLE_DW_EARLY_TERM_NON_INTERACTIVE)
-def config_dw_all_modes(device, dw_24ghz, dw_5ghz):
+ configure_power_setting(device, "inactive", "dw_24ghz",
+ aconsts.POWER_DW_24_NON_INTERACTIVE)
+ configure_power_setting(device, "inactive", "dw_5ghz",
+ aconsts.POWER_DW_5_NON_INTERACTIVE)
+ configure_power_setting(device, "inactive", "disc_beacon_interval_ms",
+ aconsts.POWER_DISC_BEACON_INTERVAL_NON_INTERACTIVE)
+ configure_power_setting(device, "inactive", "num_ss_in_discovery",
+ aconsts.POWER_NUM_SS_IN_DISC_NON_INTERACTIVE)
+ configure_power_setting(device, "inactive", "enable_dw_early_term",
+ aconsts.POWER_ENABLE_DW_EARLY_TERM_NON_INTERACTIVE)
+
+
+def config_power_settings(device, dw_24ghz, dw_5ghz, disc_beacon_interval=None,
+ num_ss_in_disc=None, enable_dw_early_term=None):
"""Configure device's discovery window (DW) values to the specified values -
whether the device is in interactive or non-interactive mode.
Args:
dw_24ghz: DW interval in the 2.4GHz band.
dw_5ghz: DW interval in the 5GHz band.
+ disc_beacon_interval: The discovery beacon interval (in ms). If None then
+ not set.
+ num_ss_in_disc: Number of spatial streams to use for discovery. If None then
+ not set.
+ enable_dw_early_term: If True then enable early termination of the DW. If
+ None then not set.
"""
- configure_dw(device, is_default=True, is_24_band=True, value=dw_24ghz)
- configure_dw(device, is_default=True, is_24_band=False, value=dw_5ghz)
- configure_dw(device, is_default=False, is_24_band=True, value=dw_24ghz)
- configure_dw(device, is_default=False, is_24_band=False, value=dw_5ghz)
+ configure_power_setting(device, "default", "dw_24ghz", dw_24ghz)
+ configure_power_setting(device, "default", "dw_5ghz", dw_5ghz)
+ configure_power_setting(device, "inactive", "dw_24ghz", dw_24ghz)
+ configure_power_setting(device, "inactive", "dw_5ghz", dw_5ghz)
+
+ if disc_beacon_interval is not None:
+ configure_power_setting(device, "default", "disc_beacon_interval_ms",
+ disc_beacon_interval)
+ configure_power_setting(device, "inactive", "disc_beacon_interval_ms",
+ disc_beacon_interval)
+
+ if num_ss_in_disc is not None:
+ configure_power_setting(device, "default", "num_ss_in_discovery",
+ num_ss_in_disc)
+ configure_power_setting(device, "inactive", "num_ss_in_discovery",
+ num_ss_in_disc)
+
+ if enable_dw_early_term is not None:
+ configure_power_setting(device, "default", "enable_dw_early_term",
+ enable_dw_early_term)
+ configure_power_setting(device, "inactive", "enable_dw_early_term",
+ enable_dw_early_term)
def create_discovery_config(service_name,
d_type,
@@ -495,6 +612,36 @@
config[aconsts.DISCOVERY_KEY_TERM_CB_ENABLED] = term_cb_enable
return config
+def add_ranging_to_pub(p_config, enable_ranging):
+ """Add ranging enabled configuration to a publish configuration (only relevant
+ for publish configuration).
+
+ Args:
+ p_config: The Publish discovery configuration.
+ enable_ranging: True to enable ranging, False to disable.
+ Returns:
+ The modified publish configuration.
+ """
+ p_config[aconsts.DISCOVERY_KEY_RANGING_ENABLED] = enable_ranging
+ return p_config
+
+def add_ranging_to_sub(s_config, min_distance_mm, max_distance_mm):
+ """Add ranging distance configuration to a subscribe configuration (only
+ relevant to a subscribe configuration).
+
+ Args:
+ s_config: The Subscribe discovery configuration.
+ min_distance_mm, max_distance_mm: The min and max distance specification.
+ Used if not None.
+ Returns:
+ The modified subscribe configuration.
+ """
+ if min_distance_mm is not None:
+ s_config[aconsts.DISCOVERY_KEY_MIN_DISTANCE_MM] = min_distance_mm
+ if max_distance_mm is not None:
+ s_config[aconsts.DISCOVERY_KEY_MAX_DISTANCE_MM] = max_distance_mm
+ return s_config
+
def attach_with_identity(dut):
"""Start an Aware session (attach) and wait for confirmation and identity
information (mac address).
diff --git a/acts/framework/acts/test_utils/wifi/rtt/RttBaseTest.py b/acts/framework/acts/test_utils/wifi/rtt/RttBaseTest.py
new file mode 100644
index 0000000..2182780
--- /dev/null
+++ b/acts/framework/acts/test_utils/wifi/rtt/RttBaseTest.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python3.4
+#
+# Copyright 2017 - Google
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from acts import asserts
+from acts import utils
+from acts.base_test import BaseTestClass
+from acts.test_utils.wifi import wifi_test_utils as wutils
+from acts.test_utils.wifi.rtt import rtt_const as rconsts
+from acts.test_utils.wifi.rtt import rtt_test_utils as rutils
+
+
+class RttBaseTest(BaseTestClass):
+
+ def __init__(self, controllers):
+ super(RttBaseTest, self).__init__(controllers)
+
+ def setup_test(self):
+ required_params = ("lci_reference", "lcr_reference",
+ "rtt_reference_distance_mm",
+ "stress_test_min_iteration_count",
+ "stress_test_target_run_time_sec")
+ self.unpack_userparams(required_params)
+
+ # can be moved to JSON config file
+ self.rtt_reference_distance_margin_mm = 1000
+ self.rtt_max_failure_rate_two_sided_rtt_percentage = 10
+ self.rtt_max_failure_rate_one_sided_rtt_percentage = 50
+ self.rtt_max_margin_exceeded_rate_two_sided_rtt_percentage = 10
+ self.rtt_max_margin_exceeded_rate_one_sided_rtt_percentage = 50
+ self.rtt_min_expected_rssi_dbm = -100
+
+ for ad in self.android_devices:
+ utils.set_location_service(ad, True)
+ asserts.skip_if(
+ not ad.droid.doesDeviceSupportWifiRttFeature(),
+ "Device under test does not support Wi-Fi RTT - skipping test")
+ wutils.wifi_toggle_state(ad, True)
+ rtt_avail = ad.droid.wifiIsRttAvailable()
+ if not rtt_avail:
+ self.log.info('RTT not available. Waiting ...')
+ rutils.wait_for_event(ad, rconsts.BROADCAST_WIFI_RTT_AVAILABLE)
+ ad.ed.clear_all_events()
+ rutils.config_privilege_override(ad, False)
+ ad.droid.wifiSetCountryCode(wutils.WifiEnums.CountryCode.US)
+
+ def teardown_test(self):
+ for ad in self.android_devices:
+ if not ad.droid.doesDeviceSupportWifiRttFeature():
+ return
+
+ # clean-up queue from the System Service UID
+ ad.droid.wifiRttCancelRanging([1000])
+
+ def on_fail(self, test_name, begin_time):
+ for ad in self.android_devices:
+ ad.take_bug_report(test_name, begin_time)
+ ad.cat_adb_log(test_name, begin_time)
diff --git a/acts/framework/acts/test_utils/wifi/rtt/__init__.py b/acts/framework/acts/test_utils/wifi/rtt/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/acts/framework/acts/test_utils/wifi/rtt/__init__.py
diff --git a/acts/framework/acts/test_utils/wifi/rtt/rtt_const.py b/acts/framework/acts/test_utils/wifi/rtt/rtt_const.py
new file mode 100644
index 0000000..ddf29e5
--- /dev/null
+++ b/acts/framework/acts/test_utils/wifi/rtt/rtt_const.py
@@ -0,0 +1,59 @@
+#!/usr/bin/env python3.4
+#
+# Copyright 2017 - Google
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+######################################################
+# Broadcast events
+######################################################
+BROADCAST_WIFI_RTT_AVAILABLE = "WifiRttAvailable"
+BROADCAST_WIFI_RTT_NOT_AVAILABLE = "WifiRttNotAvailable"
+
+######################################################
+# RangingResultCallback events
+######################################################
+EVENT_CB_RANGING_ON_FAIL = "WifiRttRangingFailure"
+EVENT_CB_RANGING_ON_RESULT = "WifiRttRangingResults"
+
+EVENT_CB_RANGING_KEY_RESULTS = "Results"
+
+EVENT_CB_RANGING_KEY_STATUS = "status"
+EVENT_CB_RANGING_KEY_DISTANCE_MM = "distanceMm"
+EVENT_CB_RANGING_KEY_DISTANCE_STD_DEV_MM = "distanceStdDevMm"
+EVENT_CB_RANGING_KEY_RSSI = "rssi"
+EVENT_CB_RANGING_KEY_NUM_ATTEMPTED_MEASUREMENTS = "numAttemptedMeasurements"
+EVENT_CB_RANGING_KEY_NUM_SUCCESSFUL_MEASUREMENTS = "numSuccessfulMeasurements"
+EVENT_CB_RANGING_KEY_LCI = "lci"
+EVENT_CB_RANGING_KEY_LCR = "lcr"
+EVENT_CB_RANGING_KEY_TIMESTAMP = "timestamp"
+EVENT_CB_RANGING_KEY_MAC = "mac"
+EVENT_CB_RANGING_KEY_PEER_ID = "peerId"
+EVENT_CB_RANGING_KEY_MAC_AS_STRING = "macAsString"
+
+EVENT_CB_RANGING_STATUS_SUCCESS = 0
+EVENT_CB_RANGING_STATUS_FAIL = 1
+EVENT_CB_RANGING_STATUS_RESPONDER_DOES_NOT_SUPPORT_IEEE80211MC = 2
+
+######################################################
+# status codes
+######################################################
+
+RANGING_FAIL_CODE_GENERIC = 1
+RANGING_FAIL_CODE_RTT_NOT_AVAILABLE = 2
+
+######################################################
+# ScanResults keys
+######################################################
+
+SCAN_RESULT_KEY_RTT_RESPONDER = "is80211McRTTResponder"
\ No newline at end of file
diff --git a/acts/framework/acts/test_utils/wifi/rtt/rtt_test_utils.py b/acts/framework/acts/test_utils/wifi/rtt/rtt_test_utils.py
new file mode 100644
index 0000000..c24b406
--- /dev/null
+++ b/acts/framework/acts/test_utils/wifi/rtt/rtt_test_utils.py
@@ -0,0 +1,463 @@
+#!/usr/bin/env python3.4
+#
+# Copyright 2017 - Google
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import queue
+import statistics
+import time
+
+from acts import asserts
+from acts.test_utils.wifi import wifi_test_utils as wutils
+from acts.test_utils.wifi.rtt import rtt_const as rconsts
+
+# arbitrary timeout for events
+EVENT_TIMEOUT = 10
+
+
+def decorate_event(event_name, id):
+ return '%s_%d' % (event_name, id)
+
+
+def wait_for_event(ad, event_name, timeout=EVENT_TIMEOUT):
+ """Wait for the specified event or timeout.
+
+ Args:
+ ad: The android device
+ event_name: The event to wait on
+ timeout: Number of seconds to wait
+ Returns:
+ The event (if available)
+ """
+ prefix = ''
+ if hasattr(ad, 'pretty_name'):
+ prefix = '[%s] ' % ad.pretty_name
+ try:
+ event = ad.ed.pop_event(event_name, timeout)
+ ad.log.info('%s%s: %s', prefix, event_name, event['data'])
+ return event
+ except queue.Empty:
+ ad.log.info('%sTimed out while waiting for %s', prefix, event_name)
+ asserts.fail(event_name)
+
+def fail_on_event(ad, event_name, timeout=EVENT_TIMEOUT):
+ """Wait for a timeout period and looks for the specified event - fails if it
+ is observed.
+
+ Args:
+ ad: The android device
+ event_name: The event to wait for (and fail on its appearance)
+ """
+ prefix = ''
+ if hasattr(ad, 'pretty_name'):
+ prefix = '[%s] ' % ad.pretty_name
+ try:
+ event = ad.ed.pop_event(event_name, timeout)
+ ad.log.info('%sReceived unwanted %s: %s', prefix, event_name, event['data'])
+ asserts.fail(event_name, extras=event)
+ except queue.Empty:
+ ad.log.info('%s%s not seen (as expected)', prefix, event_name)
+ return
+
+
+def config_privilege_override(dut, override_to_no_privilege):
+ """Configure the device to override the permission check and to disallow any
+ privileged RTT operations, e.g. disallow one-sided RTT to Responders (APs)
+ which do not support IEEE 802.11mc.
+
+ Args:
+ dut: Device to configure.
+ override_to_no_privilege: True to indicate no privileged ops, False for
+ default (which will allow privileged ops).
+ """
+ dut.adb.shell("cmd wifirtt set override_assume_no_privilege %d" % (
+ 1 if override_to_no_privilege else 0))
+
+
+def get_rtt_constrained_results(scanned_networks, support_rtt):
+ """Filter the input list and only return those networks which either support
+ or do not support RTT (IEEE 802.11mc.)
+
+ Args:
+ scanned_networks: A list of networks from scan results.
+ support_rtt: True - only return those APs which support RTT, False - only
+ return those APs which do not support RTT.
+
+ Returns: a sub-set of the scanned_networks per support_rtt constraint.
+ """
+ matching_networks = []
+ for network in scanned_networks:
+ if support_rtt:
+ if (rconsts.SCAN_RESULT_KEY_RTT_RESPONDER in network and
+ network[rconsts.SCAN_RESULT_KEY_RTT_RESPONDER]):
+ matching_networks.append(network)
+ else:
+ if (rconsts.SCAN_RESULT_KEY_RTT_RESPONDER not in network or
+ not network[rconsts.SCAN_RESULT_KEY_RTT_RESPONDER]):
+ matching_networks.append(network)
+
+ return matching_networks
+
+
+def scan_networks(dut):
+ """Perform a scan and return scan results.
+
+ Args:
+ dut: Device under test.
+
+ Returns: an array of scan results.
+ """
+ wutils.start_wifi_connection_scan(dut)
+ return dut.droid.wifiGetScanResults()
+
+
+def scan_with_rtt_support_constraint(dut, support_rtt, repeat=0):
+ """Perform a scan and return scan results of APs: only those that support or
+ do not support RTT (IEEE 802.11mc) - per the support_rtt parameter.
+
+ Args:
+ dut: Device under test.
+ support_rtt: True - only return those APs which support RTT, False - only
+ return those APs which do not support RTT.
+ repeat: Re-scan this many times to find an RTT supporting network.
+
+ Returns: an array of scan results.
+ """
+ for i in range(repeat + 1):
+ scan_results = scan_networks(dut)
+ aps = get_rtt_constrained_results(scan_results, support_rtt)
+ if len(aps) != 0:
+ return aps
+
+ return []
+
+
+def select_best_scan_results(scans, select_count, lowest_rssi=-80):
+ """Select the strongest 'select_count' scans in the input list based on
+ highest RSSI. Exclude all very weak signals, even if results in a shorter
+ list.
+
+ Args:
+ scans: List of scan results.
+ select_count: An integer specifying how many scans to return at most.
+ lowest_rssi: The lowest RSSI to accept into the output.
+ Returns: a list of the strongest 'select_count' scan results from the scans
+ list.
+ """
+ def takeRssi(element):
+ return element['level']
+
+ result = []
+ scans.sort(key=takeRssi, reverse=True)
+ for scan in scans:
+ if len(result) == select_count:
+ break
+ if scan['level'] < lowest_rssi:
+ break # rest are lower since we're sorted
+ result.append(scan)
+
+ return result
+
+
+def validate_ap_result(scan_result, range_result):
+ """Validate the range results:
+ - Successful if AP (per scan result) support 802.11mc (allowed to fail
+ otherwise)
+ - MAC of result matches the BSSID
+
+ Args:
+ scan_result: Scan result for the AP
+ range_result: Range result returned by the RTT API
+ """
+ asserts.assert_equal(scan_result[wutils.WifiEnums.BSSID_KEY], range_result[
+ rconsts.EVENT_CB_RANGING_KEY_MAC_AS_STRING_BSSID], 'MAC/BSSID mismatch')
+ if (rconsts.SCAN_RESULT_KEY_RTT_RESPONDER in scan_result and
+ scan_result[rconsts.SCAN_RESULT_KEY_RTT_RESPONDER]):
+ asserts.assert_true(range_result[rconsts.EVENT_CB_RANGING_KEY_STATUS] ==
+ rconsts.EVENT_CB_RANGING_STATUS_SUCCESS,
+ 'Ranging failed for an AP which supports 802.11mc!')
+
+
+def validate_ap_results(scan_results, range_results):
+ """Validate an array of ranging results against the scan results used to
+ trigger the range. The assumption is that the results are returned in the
+ same order as the request (which were the scan results).
+
+ Args:
+ scan_results: Scans results used to trigger the range request
+ range_results: Range results returned by the RTT API
+ """
+ asserts.assert_equal(
+ len(scan_results),
+ len(range_results),
+ 'Mismatch in length of scan results and range results')
+
+ # sort first based on BSSID/MAC
+ scan_results.sort(key=lambda x: x[wutils.WifiEnums.BSSID_KEY])
+ range_results.sort(
+ key=lambda x: x[rconsts.EVENT_CB_RANGING_KEY_MAC_AS_STRING_BSSID])
+
+ for i in range(len(scan_results)):
+ validate_ap_result(scan_results[i], range_results[i])
+
+
+def validate_aware_mac_result(range_result, mac, description):
+ """Validate the range result for an Aware peer specified with a MAC address:
+ - Correct MAC address.
+
+ The MAC addresses may contain ":" (which are ignored for the comparison) and
+ may be in any case (which is ignored for the comparison).
+
+ Args:
+ range_result: Range result returned by the RTT API
+ mac: MAC address of the peer
+ description: Additional content to print on failure
+ """
+ mac1 = mac.replace(':', '').lower()
+ mac2 = range_result[rconsts.EVENT_CB_RANGING_KEY_MAC_AS_STRING].replace(':',
+ '').lower()
+ asserts.assert_equal(mac1, mac2,
+ '%s: MAC mismatch' % description)
+
+def validate_aware_peer_id_result(range_result, peer_id, description):
+ """Validate the range result for An Aware peer specified with a Peer ID:
+ - Correct Peer ID
+ - MAC address information not available
+
+ Args:
+ range_result: Range result returned by the RTT API
+ peer_id: Peer ID of the peer
+ description: Additional content to print on failure
+ """
+ asserts.assert_equal(peer_id,
+ range_result[rconsts.EVENT_CB_RANGING_KEY_PEER_ID],
+ '%s: Peer Id mismatch' % description)
+ asserts.assert_false(rconsts.EVENT_CB_RANGING_KEY_MAC in range_result,
+ '%s: MAC Address not empty!' % description)
+
+
+def extract_stats(results, range_reference_mm, range_margin_mm, min_rssi,
+ reference_lci=[], reference_lcr=[], summary_only=False):
+ """Extract statistics from a list of RTT results. Returns a dictionary
+ with results:
+ - num_results (success or fails)
+ - num_success_results
+ - num_no_results (e.g. timeout)
+ - num_failures
+ - num_range_out_of_margin (only for successes)
+ - num_invalid_rssi (only for successes)
+ - distances: extracted list of distances
+ - distance_std_devs: extracted list of distance standard-deviations
+ - rssis: extracted list of RSSI
+ - distance_mean
+ - distance_std_dev (based on distance - ignoring the individual std-devs)
+ - rssi_mean
+ - rssi_std_dev
+ - status_codes
+ - lcis: extracted list of all of the individual LCI
+ - lcrs: extracted list of all of the individual LCR
+ - any_lci_mismatch: True/False - checks if all LCI results are identical to
+ the reference LCI.
+ - any_lcr_mismatch: True/False - checks if all LCR results are identical to
+ the reference LCR.
+ - num_attempted_measurements: extracted list of all of the individual
+ number of attempted measurements.
+ - num_successful_measurements: extracted list of all of the individual
+ number of successful measurements.
+ - invalid_num_attempted: True/False - checks if number of attempted
+ measurements is non-zero for successful results.
+ - invalid_num_successful: True/False - checks if number of successful
+ measurements is non-zero for successful results.
+
+ Args:
+ results: List of RTT results.
+ range_reference_mm: Reference value for the distance (in mm)
+ range_margin_mm: Acceptable absolute margin for distance (in mm)
+ min_rssi: Acceptable minimum RSSI value.
+ reference_lci, reference_lcr: Reference values for LCI and LCR.
+ summary_only: Only include summary keys (reduce size).
+
+ Returns: A dictionary of stats.
+ """
+ stats = {}
+ stats['num_results'] = 0
+ stats['num_success_results'] = 0
+ stats['num_no_results'] = 0
+ stats['num_failures'] = 0
+ stats['num_range_out_of_margin'] = 0
+ stats['num_invalid_rssi'] = 0
+ stats['any_lci_mismatch'] = False
+ stats['any_lcr_mismatch'] = False
+ stats['invalid_num_attempted'] = False
+ stats['invalid_num_successful'] = False
+
+ range_max_mm = range_reference_mm + range_margin_mm
+ range_min_mm = range_reference_mm - range_margin_mm
+
+ distances = []
+ distance_std_devs = []
+ rssis = []
+ num_attempted_measurements = []
+ num_successful_measurements = []
+ status_codes = []
+ lcis = []
+ lcrs = []
+
+ for i in range(len(results)):
+ result = results[i]
+
+ if result is None: # None -> timeout waiting for RTT result
+ stats['num_no_results'] = stats['num_no_results'] + 1
+ continue
+ stats['num_results'] = stats['num_results'] + 1
+
+ status_codes.append(result[rconsts.EVENT_CB_RANGING_KEY_STATUS])
+ if status_codes[-1] != rconsts.EVENT_CB_RANGING_STATUS_SUCCESS:
+ stats['num_failures'] = stats['num_failures'] + 1
+ continue
+ stats['num_success_results'] = stats['num_success_results'] + 1
+
+ distance_mm = result[rconsts.EVENT_CB_RANGING_KEY_DISTANCE_MM]
+ distances.append(distance_mm)
+ if not range_min_mm <= distance_mm <= range_max_mm:
+ stats['num_range_out_of_margin'] = stats['num_range_out_of_margin'] + 1
+ distance_std_devs.append(
+ result[rconsts.EVENT_CB_RANGING_KEY_DISTANCE_STD_DEV_MM])
+
+ rssi = result[rconsts.EVENT_CB_RANGING_KEY_RSSI]
+ rssis.append(rssi)
+ if not min_rssi <= rssi <= 0:
+ stats['num_invalid_rssi'] = stats['num_invalid_rssi'] + 1
+
+ num_attempted = result[
+ rconsts.EVENT_CB_RANGING_KEY_NUM_ATTEMPTED_MEASUREMENTS]
+ num_attempted_measurements.append(num_attempted)
+ if num_attempted == 0:
+ stats['invalid_num_attempted'] = True
+
+ num_successful = result[
+ rconsts.EVENT_CB_RANGING_KEY_NUM_SUCCESSFUL_MEASUREMENTS]
+ num_successful_measurements.append(num_successful)
+ if num_successful == 0:
+ stats['invalid_num_successful'] = True
+
+ lcis.append(result[rconsts.EVENT_CB_RANGING_KEY_LCI])
+ if (result[rconsts.EVENT_CB_RANGING_KEY_LCI] != reference_lci):
+ stats['any_lci_mismatch'] = True
+ lcrs.append(result[rconsts.EVENT_CB_RANGING_KEY_LCR])
+ if (result[rconsts.EVENT_CB_RANGING_KEY_LCR] != reference_lcr):
+ stats['any_lcr_mismatch'] = True
+
+ if len(distances) > 0:
+ stats['distance_mean'] = statistics.mean(distances)
+ if len(distances) > 1:
+ stats['distance_std_dev'] = statistics.stdev(distances)
+ if len(rssis) > 0:
+ stats['rssi_mean'] = statistics.mean(rssis)
+ if len(rssis) > 1:
+ stats['rssi_std_dev'] = statistics.stdev(rssis)
+ if not summary_only:
+ stats['distances'] = distances
+ stats['distance_std_devs'] = distance_std_devs
+ stats['rssis'] = rssis
+ stats['num_attempted_measurements'] = num_attempted_measurements
+ stats['num_successful_measurements'] = num_successful_measurements
+ stats['status_codes'] = status_codes
+ stats['lcis'] = lcis
+ stats['lcrs'] = lcrs
+
+ return stats
+
+
+def run_ranging(dut, aps, iter_count, time_between_iterations,
+ target_run_time_sec=0):
+ """Executing ranging to the set of APs.
+
+ Will execute a minimum of 'iter_count' iterations. Will continue to run
+ until execution time (just) exceeds 'target_run_time_sec'.
+
+ Args:
+ dut: Device under test
+ aps: A list of APs (Access Points) to range to.
+ iter_count: (Minimum) Number of measurements to perform.
+ time_between_iterations: Number of seconds to wait between iterations.
+ target_run_time_sec: The target run time in seconds.
+
+ Returns: a list of the events containing the RTT results (or None for a
+ failed measurement).
+ """
+ max_peers = dut.droid.wifiRttMaxPeersInRequest()
+
+ asserts.assert_true(len(aps) > 0, "Need at least one AP!")
+ if len(aps) > max_peers:
+ aps = aps[0:max_peers]
+
+ events = {} # need to keep track per BSSID!
+ for ap in aps:
+ events[ap["BSSID"]] = []
+
+ start_clock = time.time()
+ iterations_done = 0
+ run_time = 0
+ while iterations_done < iter_count or (
+ target_run_time_sec != 0 and run_time < target_run_time_sec):
+ if iterations_done != 0 and time_between_iterations != 0:
+ time.sleep(time_between_iterations)
+
+ id = dut.droid.wifiRttStartRangingToAccessPoints(aps)
+ try:
+ event = dut.ed.pop_event(
+ decorate_event(rconsts.EVENT_CB_RANGING_ON_RESULT, id), EVENT_TIMEOUT)
+ range_results = event["data"][rconsts.EVENT_CB_RANGING_KEY_RESULTS]
+ asserts.assert_equal(
+ len(aps),
+ len(range_results),
+ 'Mismatch in length of scan results and range results')
+ for result in range_results:
+ bssid = result[rconsts.EVENT_CB_RANGING_KEY_MAC_AS_STRING]
+ asserts.assert_true(bssid in events,
+ "Result BSSID %s not in requested AP!?" % bssid)
+ asserts.assert_equal(len(events[bssid]), iterations_done,
+ "Duplicate results for BSSID %s!?" % bssid)
+ events[bssid].append(result)
+ except queue.Empty:
+ for ap in aps:
+ events[ap["BSSID"]].append(None)
+
+ iterations_done = iterations_done + 1
+ run_time = time.time() - start_clock
+
+ return events
+
+
+def analyze_results(all_aps_events, rtt_reference_distance_mm,
+ distance_margin_mm, min_expected_rssi, lci_reference, lcr_reference,
+ summary_only=False):
+ """Verifies the results of the RTT experiment.
+
+ Args:
+ all_aps_events: Dictionary of APs, each a list of RTT result events.
+ rtt_reference_distance_mm: Expected distance to the AP (source of truth).
+ distance_margin_mm: Accepted error marging in distance measurement.
+ min_expected_rssi: Minimum acceptable RSSI value
+ lci_reference, lcr_reference: Expected LCI/LCR values (arrays of bytes).
+ summary_only: Only include summary keys (reduce size).
+ """
+ all_stats = {}
+ for bssid, events in all_aps_events.items():
+ stats = extract_stats(events, rtt_reference_distance_mm,
+ distance_margin_mm, min_expected_rssi,
+ lci_reference, lcr_reference, summary_only)
+ all_stats[bssid] = stats
+ return all_stats
diff --git a/acts/framework/acts/test_utils/wifi/wifi_test_utils.py b/acts/framework/acts/test_utils/wifi/wifi_test_utils.py
index b6510ae..9b17383 100755
--- a/acts/framework/acts/test_utils/wifi/wifi_test_utils.py
+++ b/acts/framework/acts/test_utils/wifi/wifi_test_utils.py
@@ -234,6 +234,10 @@
REPORT_EVENT_AFTER_EACH_SCAN = 1
REPORT_EVENT_FULL_SCAN_RESULT = 2
+ SCAN_TYPE_LOW_LATENCY = 0
+ SCAN_TYPE_LOW_POWER = 1
+ SCAN_TYPE_HIGH_ACCURACY = 2
+
# US Wifi frequencies
ALL_2G_FREQUENCIES = [2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452,
2457, 2462]
diff --git a/acts/framework/acts/utils.py b/acts/framework/acts/utils.py
index d89e1d5..7181921 100755
--- a/acts/framework/acts/utils.py
+++ b/acts/framework/acts/utils.py
@@ -738,6 +738,12 @@
If new_state is False, turn off location service.
If new_state if True, set location service to "High accuracy".
"""
+ ad.adb.shell("content insert --uri "
+ " content://com.google.settings/partner --bind "
+ "name:s:network_location_opt_in --bind value:s:1")
+ ad.adb.shell("content insert --uri "
+ " content://com.google.settings/partner --bind "
+ "name:s:use_location_for_services --bind value:s:1")
if new_state:
ad.adb.shell("settings put secure location_providers_allowed +gps")
ad.adb.shell("settings put secure location_providers_allowed +network")
@@ -759,16 +765,6 @@
1 if new_state else 0))
-def set_regulatory_domain(ad, domain):
- """Set the Wi-Fi regulatory domain
-
- Args:
- ad: android device object.
- domain: regulatory domain
- """
- ad.adb.shell("iw reg set %s" % domain)
-
-
def bypass_setup_wizard(ad, bypass_wait_time=3):
"""Bypass the setup wizard on an input Android device
diff --git a/acts/framework/tests/acts_android_device_test.py b/acts/framework/tests/acts_android_device_test.py
index 2052281..08332ab 100755
--- a/acts/framework/tests/acts_android_device_test.py
+++ b/acts/framework/tests/acts_android_device_test.py
@@ -286,6 +286,26 @@
@mock.patch(
'acts.controllers.fastboot.FastbootProxy',
return_value=MockFastbootProxy(MOCK_SERIAL))
+ def test_AndroidDevice_build_info_release(self, MockFastboot,
+ MockAdbProxy):
+ """Verifies the AndroidDevice object's basic attributes are correctly
+ set after instantiation.
+ """
+ global MOCK_BUILD_ID
+ ad = android_device.AndroidDevice(serial=1)
+ old_mock_build_id = MOCK_BUILD_ID
+ MOCK_BUILD_ID = "ABC-MR1"
+ build_info = ad.build_info
+ self.assertEqual(build_info["build_id"], "123456789")
+ self.assertEqual(build_info["build_type"], "userdebug")
+ MOCK_BUILD_ID = old_mock_build_id
+
+ @mock.patch(
+ 'acts.controllers.adb.AdbProxy',
+ return_value=MockAdbProxy(MOCK_SERIAL))
+ @mock.patch(
+ 'acts.controllers.fastboot.FastbootProxy',
+ return_value=MockFastbootProxy(MOCK_SERIAL))
def test_AndroidDevice_build_info_dev(self, MockFastboot, MockAdbProxy):
"""Verifies the AndroidDevice object's basic attributes are correctly
set after instantiation.
@@ -315,6 +335,7 @@
@mock.patch(
'acts.controllers.fastboot.FastbootProxy',
return_value=MockFastbootProxy(MOCK_SERIAL))
+
@mock.patch('acts.utils.create_dir')
@mock.patch('acts.utils.exe_cmd')
def test_AndroidDevice_take_bug_report(self, exe_mock, create_dir_mock,
diff --git a/acts/tests/google/bt/car_bt/BtCarMediaConnectionTest.py b/acts/tests/google/bt/car_bt/BtCarMediaConnectionTest.py
index 3841883..4611c0d 100644
--- a/acts/tests/google/bt/car_bt/BtCarMediaConnectionTest.py
+++ b/acts/tests/google/bt/car_bt/BtCarMediaConnectionTest.py
@@ -1,4 +1,4 @@
-#/usr/bin/env python3.4
+# /usr/bin/env python3.4
#
# Copyright (C) 2016 The Android Open Source Project
#
@@ -23,8 +23,8 @@
from acts.test_utils.bt.BluetoothBaseTest import BluetoothBaseTest
from acts.test_utils.bt import bt_test_utils
from acts.test_utils.car import car_bt_utils
-from acts.test_utils.car import car_media_utils
from acts.test_utils.bt import BtEnum
+from acts.test_utils.bt.bt_test_utils import is_a2dp_connected
class BtCarMediaConnectionTest(BluetoothBaseTest):
@@ -58,26 +58,6 @@
self.SNK, self.SRC, [BtEnum.BluetoothProfile.A2DP_SINK],
BtEnum.BluetoothPriorityLevel.PRIORITY_ON)
- def is_a2dp_connected(self, device1, device2):
- """
- Convenience Function to see if the 2 devices are connected on
- A2dp.
- ToDo: Move to bt_test_utils if used in more places.
- Args:
- device1: Device 1
- device2: Device 2
- Returns:
- True if Connected
- False if Not connected
- """
- devices = device1.droid.bluetoothA2dpSinkGetConnectedDevices()
- for device in devices:
- self.device1.log.info("A2dp Connected device {}".format(device[
- "name"]))
- if (device["address"] == device2.droid.bluetoothGetLocalAddress()):
- return True
- return False
-
@test_tracker_info(uuid='1934c0d5-3fa3-43e5-a91f-2c8a4424f5cd')
@BluetoothBaseTest.bt_test_wrap
def test_a2dp_connect_disconnect_from_src(self):
@@ -99,7 +79,7 @@
Priority: 0
"""
- if (car_media_utils.is_a2dp_connected(self.log, self.SNK, self.SRC)):
+ if (is_a2dp_connected(self.SNK, self.SRC)):
self.log.info("Already Connected")
else:
if (not bt_test_utils.connect_pri_to_sec(
@@ -120,7 +100,7 @@
return False
# Logging if we connected right back, since that happens sometimes
# Not failing the test if it did though
- if (car_media_utils.is_a2dp_connected(self.log, self.SNK, self.SRC)):
+ if (is_a2dp_connected(self.SNK, self.SRC)):
self.SNK.log.error("Still connected after a disconnect")
return True
@@ -147,7 +127,7 @@
Priority: 0
"""
# Connect
- if car_media_utils.is_a2dp_connected(self.log, self.SNK, self.SRC):
+ if is_a2dp_connected(self.SNK, self.SRC):
self.log.info("Already Connected")
else:
if (not bt_test_utils.connect_pri_to_sec(
@@ -169,6 +149,6 @@
return False
# Logging if we connected right back, since that happens sometimes
# Not failing the test if it did though
- if car_media_utils.is_a2dp_connected(self.log, self.SNK, self.SRC):
+ if is_a2dp_connected(self.SNK, self.SRC):
self.SNK.log.error("Still connected after a disconnect")
return True
diff --git a/acts/tests/google/bt/car_bt/BtCarMediaPassthroughTest.py b/acts/tests/google/bt/car_bt/BtCarMediaPassthroughTest.py
index 05d1737..3e5b28f 100644
--- a/acts/tests/google/bt/car_bt/BtCarMediaPassthroughTest.py
+++ b/acts/tests/google/bt/car_bt/BtCarMediaPassthroughTest.py
@@ -25,8 +25,9 @@
from acts.test_utils.bt import bt_test_utils
from acts.test_utils.bt import BtEnum
from acts.test_utils.car import car_media_utils
-from acts.utils import exe_cmd
-from acts.controllers import adb
+from acts.test_utils.bt.bt_test_utils import is_a2dp_connected
+from acts.keys import Config
+
DEFAULT_WAIT_TIME = 1.0
DEFAULT_EVENT_TIMEOUT = 1.0
@@ -126,8 +127,7 @@
if not super(BtCarMediaPassthroughTest, self).teardown_test():
return False
# If A2dp connection was disconnected as part of the test, connect it back
- if not (car_media_utils.is_a2dp_connected(self.log, self.SNK,
- self.SRC)):
+ if not (is_a2dp_connected(self.SNK,self.SRC)):
result = bt_test_utils.connect_pri_to_sec(
self.SRC, self.SNK, set([BtEnum.BluetoothProfile.A2DP.value]))
if not result:
@@ -235,8 +235,7 @@
Priority: 0
"""
- if not (car_media_utils.is_a2dp_connected(self.log, self.SNK,
- self.SRC)):
+ if not (is_a2dp_connected(self.SNK,self.SRC)):
self.SNK.log.error('No A2dp Connection')
return False
diff --git a/acts/tests/google/bt/car_bt/BtCarPbapTest.py b/acts/tests/google/bt/car_bt/BtCarPbapTest.py
index 1a1bba3..c77c859 100644
--- a/acts/tests/google/bt/car_bt/BtCarPbapTest.py
+++ b/acts/tests/google/bt/car_bt/BtCarPbapTest.py
@@ -485,3 +485,4 @@
bt_contacts_utils.erase_contacts(self.pse)
bt_contacts_utils.erase_contacts(self.pse2)
return pse1_matches and pse2_matches and pse1andpse2_matches
+
diff --git a/acts/tests/google/wifi/WifiAutoUpdateTest.py b/acts/tests/google/wifi/WifiAutoUpdateTest.py
new file mode 100755
index 0000000..4a8ab7b
--- /dev/null
+++ b/acts/tests/google/wifi/WifiAutoUpdateTest.py
@@ -0,0 +1,242 @@
+#!/usr/bin/env python3.4
+#
+# Copyright 2017 - The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import itertools
+import pprint
+import queue
+import time
+
+import acts.base_test
+import acts.signals as signals
+import acts.test_utils.wifi.wifi_test_utils as wutils
+import acts.utils
+
+from acts import asserts
+from acts.libs.ota import ota_updater
+from acts.test_decorators import test_tracker_info
+from acts.test_utils.wifi.WifiBaseTest import WifiBaseTest
+
+WifiEnums = wutils.WifiEnums
+# Default timeout used for reboot, toggle WiFi and Airplane mode,
+# for the system to settle down after the operation.
+DEFAULT_TIMEOUT = 10
+BAND_2GHZ = 0
+BAND_5GHZ = 1
+
+
+class WifiAutoUpdateTest(WifiBaseTest):
+ """Tests for APIs in Android's WifiManager class.
+
+ Test Bed Requirement:
+ * One Android device
+ * Several Wi-Fi networks visible to the device, including an open Wi-Fi
+ network.
+ """
+
+ def __init__(self, controllers):
+ WifiBaseTest.__init__(self, controllers)
+ self.tests = (
+ "test_check_wifi_state_after_au",
+ "test_verify_networks_after_au",
+ "test_all_networks_connectable_after_au",
+ "test_connection_to_new_networks",
+ "test_check_wifi_toggling_after_au",
+ "test_reset_wifi_after_au")
+
+ def setup_class(self):
+ super(WifiAutoUpdateTest, self).setup_class()
+ ota_updater.initialize(self.user_params, self.android_devices)
+ self.dut = self.android_devices[0]
+ wutils.wifi_test_device_init(self.dut)
+ req_params = []
+ opt_param = [
+ "open_network", "reference_networks", "iperf_server_address"
+ ]
+ self.unpack_userparams(
+ req_param_names=req_params, opt_param_names=opt_param)
+
+ if "AccessPoint" in self.user_params:
+ self.legacy_configure_ap_and_start()
+
+ asserts.assert_true(
+ len(self.reference_networks) > 0,
+ "Need at least two reference network with psk.")
+ asserts.assert_true(
+ len(self.open_network) > 0,
+ "Need at least two open network with psk.")
+ wutils.wifi_toggle_state(self.dut, True)
+
+ self.wifi_config_list = []
+
+ # Setup WiFi and add few open and wpa networks before OTA.
+ self.add_network_and_enable(self.open_network[0]['2g'])
+ self.add_network_and_enable(self.reference_networks[0]['5g'])
+
+ # Add few dummy networks to the list.
+ self.add_and_enable_dummy_networks()
+
+ # Run OTA below, if ota fails then abort all tests.
+ try:
+ ota_updater.update(self.dut)
+ except Exception as err:
+ raise signals.TestSkipClass(
+ "Failed up apply OTA update. Aborting tests")
+
+ def setup_test(self):
+ self.dut.droid.wakeLockAcquireBright()
+ self.dut.droid.wakeUpNow()
+
+ def teardown_test(self):
+ self.dut.droid.wakeLockRelease()
+ self.dut.droid.goToSleepNow()
+
+ def on_fail(self, test_name, begin_time):
+ self.dut.take_bug_report(test_name, begin_time)
+ self.dut.cat_adb_log(test_name, begin_time)
+
+ def teardown_class(self):
+ if "AccessPoint" in self.user_params:
+ del self.user_params["reference_networks"]
+ del self.user_params["open_network"]
+
+ """Helper Functions"""
+
+ def add_network_and_enable(self, network):
+ """Add a network and enable it.
+
+ Args:
+ network : Network details for the network to be added.
+
+ """
+ ret = self.dut.droid.wifiAddNetwork(network)
+ asserts.assert_true(ret != -1, "Add network %r failed" % network)
+ self.wifi_config_list.append({
+ WifiEnums.SSID_KEY: network[WifiEnums.SSID_KEY],
+ WifiEnums.NETID_KEY: ret})
+ self.dut.droid.wifiEnableNetwork(ret, 0)
+
+ def add_and_enable_dummy_networks(self, num_networks=5):
+ """Add some dummy networks to the device and enable them.
+
+ Args:
+ num_networks: Number of networks to add.
+ """
+ ssid_name_base = "dummy_network_"
+ for i in range(0, num_networks):
+ network = {}
+ network[WifiEnums.SSID_KEY] = ssid_name_base + str(i)
+ network[WifiEnums.PWD_KEY] = "dummynet_password"
+ self.add_network_and_enable(network)
+
+ def check_networks_after_autoupdate(self, networks):
+ """Verify that all previously configured networks are presistent after
+ reboot.
+
+ Args:
+ networks: List of network dicts.
+
+ Return:
+ None. Raises TestFailure.
+
+ """
+ network_info = self.dut.droid.wifiGetConfiguredNetworks()
+ if len(network_info) != len(networks):
+ msg = (
+ "Number of configured networks before and after Auto-update "
+ "don't match. \nBefore reboot = %s \n After reboot = %s" %
+ (networks, network_info))
+ raise signals.TestFailure(msg)
+ current_count = 0
+ # For each network, check if it exists in configured list after Auto-
+ # update.
+ for network in networks:
+ exists = wutils.match_networks({
+ WifiEnums.SSID_KEY: network[WifiEnums.SSID_KEY]
+ }, network_info)
+ if not len(exists):
+ raise signals.TestFailure("%s network is not present in the"
+ " configured list after Auto-update" %
+ network[WifiEnums.SSID_KEY])
+ # Get the new network id for each network after reboot.
+ network[WifiEnums.NETID_KEY] = exists[0]['networkId']
+
+ """Tests"""
+
+ @test_tracker_info(uuid="9ff1f01e-e5ff-408b-9a95-29e87a2df2d8")
+ def test_check_wifi_state_after_au(self):
+ """Check if the state of WiFi is enabled after Auto-update."""
+ if not self.dut.droid.wifiCheckState():
+ raise signals.TestFailure("WiFi is disabled after Auto-update!!!")
+
+ @test_tracker_info(uuid="e3ebdbba-71dd-4281-aef8-5b3d42b88770")
+ def test_verify_networks_after_au(self):
+ """Check if the previously added networks are intact.
+
+ Steps:
+ Number of networs should be the same and match each network.
+
+ """
+ self.check_networks_after_autoupdate(self.wifi_config_list)
+
+ @test_tracker_info(uuid="b8e47a4f-62fe-4a0e-b999-27ae1ebf4d19")
+ def test_connection_to_new_networks(self):
+ """Check if we can connect to new networks after Auto-update.
+
+ Steps:
+ 1. Connect to a PSK network.
+ 2. Connect to an open network.
+ 3. Forget ntworks added in 1 & 2.
+ TODO: (@bmahadev) Add WEP network once it's ready.
+
+ """
+ wutils.connect_to_wifi_network((self.open_network[0]['5g'], self.dut))
+ wutils.connect_to_wifi_network((self.reference_networks[0]['2g'],
+ self.dut))
+ wutils.wifi_forget_network(self.dut,
+ self.reference_networks[0]['2g'][WifiEnums.SSID_KEY])
+ wutils.wifi_forget_network(self.dut,
+ self.open_network[0]['5g'][WifiEnums.SSID_KEY])
+
+ @test_tracker_info(uuid="1d8309e4-d5a2-4f48-ba3b-895a58c9bf3a")
+ def test_all_networks_connectable_after_au(self):
+ """Check if previously added networks are connectable.
+
+ Steps:
+ 1. Connect to previously added PSK network using network id.
+ 2. Connect to previously added open network using network id.
+ TODO: (@bmahadev) Add WEP network once it's ready.
+
+ """
+ for network in self.wifi_config_list:
+ if 'dummy' not in network[WifiEnums.SSID_KEY]:
+ if not wutils.connect_to_wifi_network_with_id(self.dut,
+ network[WifiEnums.NETID_KEY],
+ network[WifiEnums.SSID_KEY]):
+ raise signals.TestFailure("Failed to connect to %s after \
+ Auto-update" % network[WifiEnums.SSID_KEY])
+
+ @test_tracker_info(uuid="05671859-38b1-4dbf-930c-18048971d075")
+ def test_check_wifi_toggling_after_au(self):
+ """Check if WiFi can be toggled ON/OFF after auto-update."""
+ self.log.debug("Going from on to off.")
+ wutils.wifi_toggle_state(self.dut, False)
+ self.log.debug("Going from off to on.")
+ wutils.wifi_toggle_state(self.dut, True)
+
+ @test_tracker_info(uuid="440edf32-4b00-42b0-9811-9f2bc4a83efb")
+ def test_reset_wifi_after_au(self):
+ """"Check if WiFi can be reset after auto-update."""
+ wutils.reset_wifi(self.dut)
diff --git a/acts/tests/google/wifi/WifiDiagnosticsTest.py b/acts/tests/google/wifi/WifiDiagnosticsTest.py
new file mode 100644
index 0000000..79fb082
--- /dev/null
+++ b/acts/tests/google/wifi/WifiDiagnosticsTest.py
@@ -0,0 +1,102 @@
+#!/usr/bin/env python3.4
+#
+# Copyright 2018 - The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import itertools
+import pprint
+import queue
+import time
+
+import acts.base_test
+import acts.signals as signals
+import acts.test_utils.wifi.wifi_test_utils as wutils
+import acts.utils
+
+from acts import asserts
+from acts.test_decorators import test_tracker_info
+from acts.test_utils.wifi.WifiBaseTest import WifiBaseTest
+
+WifiEnums = wutils.WifiEnums
+
+DEFAULT_WAIT_TIME = 2
+
+
+class WifiDiagnosticsTest(WifiBaseTest):
+ """
+ Test Bed Requirement:
+ * One Android device
+ * An open Wi-Fi network.
+ * Verbose logging is on.
+ """
+
+ def __init__(self, controllers):
+ WifiBaseTest.__init__(self, controllers)
+
+ def setup_class(self):
+ self.dut = self.android_devices[0]
+ wutils.wifi_test_device_init(self.dut)
+ req_params = []
+ opt_param = ["open_network"]
+ self.unpack_userparams(
+ req_param_names=req_params, opt_param_names=opt_param)
+
+ if "AccessPoint" in self.user_params:
+ self.legacy_configure_ap_and_start()
+ wutils.wifi_toggle_state(self.dut, True)
+ asserts.assert_true(
+ len(self.open_network) > 0,
+ "Need at least one open network.")
+ self.open_network = self.open_network[0]["2g"]
+
+ def setup_test(self):
+ self.dut.droid.wakeLockAcquireBright()
+ self.dut.droid.wakeUpNow()
+
+ def teardown_test(self):
+ self.dut.droid.wakeLockRelease()
+ self.dut.droid.goToSleepNow()
+ wutils.reset_wifi(self.dut)
+
+
+ def on_fail(self, test_name, begin_time):
+ self.dut.take_bug_report(test_name, begin_time)
+ self.dut.cat_adb_log(test_name, begin_time)
+
+ def teardown_class(self):
+ if "AccessPoint" in self.user_params:
+ del self.user_params["open_network"]
+
+ """Tests"""
+
+ @test_tracker_info(uuid="d6f1661b-6732-4939-8c28-f20917774ec0")
+ def test_ringbuffers_are_dumped_during_lsdebug(self):
+ """Steps:
+ 1. Connect to a open network.
+ 2. Delete old files under data/vendor/tombstones/wifi
+ 3. Call lshal debug on wifi hal component
+ 4. Verify that files are created under data/vender/tombstones/wifi
+ """
+ wutils.connect_to_wifi_network(self.dut, self.open_network)
+ time.sleep(DEFAULT_WAIT_TIME)
+ self.dut.adb.shell("rm data/vendor/tombstones/wifi/*")
+ try:
+ self.dut.adb.shell("lshal debug android.hardware.wifi@1.2::IWifi")
+ except UnicodeDecodeError:
+ """ Gets this error because adb.shell trys to parse the output to a string
+ but ringbuffer dumps should already be generated """
+ self.log.info("Unicode decode error occurred, but this is ok")
+ file_count_plus_one = self.dut.adb.shell("ls -l data/vendor/tombstones/wifi | wc -l")
+ if int(file_count_plus_one) <= 1:
+ raise signals.TestFailure("Failed to create ringbuffer debug files.")
\ No newline at end of file
diff --git a/acts/tests/google/wifi/WifiIOTTest.py b/acts/tests/google/wifi/WifiIOTTest.py
index 6e68d70..ec0a314 100755
--- a/acts/tests/google/wifi/WifiIOTTest.py
+++ b/acts/tests/google/wifi/WifiIOTTest.py
@@ -37,7 +37,6 @@
"""
def __init__(self, controllers):
- self.attenuators = None
WifiBaseTest.__init__(self, controllers)
def setup_class(self):
diff --git a/acts/tests/google/wifi/WifiManagerTest.py b/acts/tests/google/wifi/WifiManagerTest.py
index 41f65c4..5a5dfeb 100755
--- a/acts/tests/google/wifi/WifiManagerTest.py
+++ b/acts/tests/google/wifi/WifiManagerTest.py
@@ -494,12 +494,15 @@
"""Tests"""
@test_tracker_info(uuid="525fc5e3-afba-4bfd-9a02-5834119e3c66")
- def test_toggle_state(self):
+ def test_toggle_wifi_state_and_get_startupTime(self):
"""Test toggling wifi"""
self.log.debug("Going from on to off.")
wutils.wifi_toggle_state(self.dut, False)
self.log.debug("Going from off to on.")
+ startTime = time.time()
wutils.wifi_toggle_state(self.dut, True)
+ startup_time = time.time() - startTime
+ self.log.debug("WiFi was enabled on the device in %s s." % startup_time)
@test_tracker_info(uuid="e9d11563-2bbe-4c96-87eb-ec919b51435b")
def test_toggle_with_screen(self):
diff --git a/acts/tests/google/wifi/WifiPnoTest.py b/acts/tests/google/wifi/WifiPnoTest.py
index b8f85c0..1282929 100644
--- a/acts/tests/google/wifi/WifiPnoTest.py
+++ b/acts/tests/google/wifi/WifiPnoTest.py
@@ -144,7 +144,7 @@
""" Tests Begin """
@test_tracker_info(uuid="33d3cae4-5fa7-4e90-b9e2-5d3747bba64c")
- def test_simple_pno_connection_2g_to_5g(self):
+ def test_simple_pno_connection_to_2g(self):
"""Test PNO triggered autoconnect to a network.
Steps:
@@ -152,16 +152,13 @@
2. Save 2 valid network configurations (a & b) in the device.
3. Attenuate 5Ghz network and wait for a few seconds to trigger PNO.
4. Check the device connected to 2Ghz network automatically.
- 5. Attenuate 2Ghz network and wait for a few seconds to trigger PNO.
- 6. Check the device connected to 5Ghz network automatically.
"""
self.add_network_and_enable(self.pno_network_a)
self.add_network_and_enable(self.pno_network_b)
self.trigger_pno_and_assert_connect("a_on_b_off", self.pno_network_a)
- self.trigger_pno_and_assert_connect("b_on_a_off", self.pno_network_b)
@test_tracker_info(uuid="39b945a1-830f-4f11-9e6a-9e9641066a96")
- def test_simple_pno_connection_5g_to_2g(self):
+ def test_simple_pno_connection_to_5g(self):
"""Test PNO triggered autoconnect to a network.
Steps:
@@ -169,15 +166,11 @@
2. Save 2 valid network configurations (a & b) in the device.
3. Attenuate 2Ghz network and wait for a few seconds to trigger PNO.
4. Check the device connected to 5Ghz network automatically.
- 5. Attenuate 5Ghz network and wait for a few seconds to trigger PNO.
- 6. Check the device connected to 2Ghz network automatically.
"""
self.add_network_and_enable(self.pno_network_a)
self.add_network_and_enable(self.pno_network_b)
self.trigger_pno_and_assert_connect("b_on_a_off", self.pno_network_b)
- self.trigger_pno_and_assert_connect("a_on_b_off", self.pno_network_a)
-
@test_tracker_info(uuid="844b15be-ff45-4b09-a11b-0b2b4bb13b22")
def test_pno_connection_with_multiple_saved_networks(self):
@@ -195,7 +188,8 @@
self.add_and_enable_dummy_networks(16)
self.add_network_and_enable(self.pno_network_a)
self.add_network_and_enable(self.pno_network_b)
+ # Force single scan so that both networks become preferred before PNO.
+ wutils.start_wifi_connection_scan(self.dut)
self.trigger_pno_and_assert_connect("a_on_b_off", self.pno_network_a)
- self.trigger_pno_and_assert_connect("b_on_a_off", self.pno_network_b)
""" Tests End """
diff --git a/acts/tests/google/wifi/WifiScannerMultiScanTest.py b/acts/tests/google/wifi/WifiScannerMultiScanTest.py
index 0ff3574..1b33e57 100755
--- a/acts/tests/google/wifi/WifiScannerMultiScanTest.py
+++ b/acts/tests/google/wifi/WifiScannerMultiScanTest.py
@@ -149,15 +149,12 @@
'numUsage': 0,
'SSID': '"wh_ap1_2g"',
'timestamp': 4280078660,
- 'numConnection': 0,
'BSSID': '30:b5:c2:33:f9:05',
'frequency': 2412,
- 'numIpConfigFailures': 0,
'distanceSdCm': 0,
'distanceCm': 0,
'centerFreq1': 0,
'centerFreq0': 0,
- 'blackListTimestamp': 0,
'venueName': '',
'seen': 0,
'operatorFriendlyName': '',
diff --git a/acts/tests/google/wifi/WifiScannerScanTest.py b/acts/tests/google/wifi/WifiScannerScanTest.py
index 9eb6d38..b0d73de 100755
--- a/acts/tests/google/wifi/WifiScannerScanTest.py
+++ b/acts/tests/google/wifi/WifiScannerScanTest.py
@@ -75,12 +75,15 @@
"test_single_scan_while_pno",
"test_wifi_connection_and_pno_while_batch_scan",
"test_wifi_scanner_single_scan_in_isolated",
- "test_wifi_scanner_with_invalid_numBssidsPerScan")
+ "test_wifi_scanner_with_invalid_numBssidsPerScan",
+ "test_wifi_scanner_dual_radio_low_latency",
+ "test_wifi_scanner_dual_radio_low_power",
+ "test_wifi_scanner_dual_radio_high_accuracy")
def setup_class(self):
self.dut = self.android_devices[0]
wutils.wifi_test_device_init(self.dut)
- req_params = ("run_extended_test", "ping_addr", "max_bugreports")
+ req_params = ("run_extended_test", "ping_addr", "max_bugreports", "dbs_supported_models")
opt_param = ["reference_networks"]
self.unpack_userparams(
req_param_names=req_params, opt_param_names=opt_param)
@@ -108,6 +111,7 @@
self.attenuators = wutils.group_attenuators(self.attenuators)
self.attenuators[0].set_atten(0)
self.attenuators[1].set_atten(0)
+ self.dut.droid.wifiEnableWifiConnectivityManager(False)
def teardown_test(self):
base_test.BaseTestClass.teardown_test(self)
@@ -121,6 +125,7 @@
self.dut.cat_adb_log(test_name, begin_time)
def teardown_class(self):
+ self.dut.droid.wifiEnableWifiConnectivityManager(True)
if "AccessPoint" in self.user_params:
del self.user_params["reference_networks"]
del self.user_params["open_network"]
@@ -317,6 +322,8 @@
parameter.
3. Pop all full scan result events occurred earlier.
4. Verify that full scan results match with normal scan results.
+ 5. If the scan type is included in scan_setting, verify that the
+ radioChainInfos length.
Args:
scan_setting: The parameters for the single scan.
@@ -348,12 +355,27 @@
asserts.assert_true(
len(results) >= bssids,
"Full single shot result don't match {}".format(len(results)))
+ if 'type' in scan_setting.keys():
+ for item in results:
+ self.verify_radio_chain_length(scan_setting['type'], item)
except queue.Empty as error:
raise AssertionError(
"Event did not triggered for single shot {}".format(error))
finally:
self.dut.droid.wifiScannerStopScan(idx)
+ def verify_radio_chain_length(self, scan_setting_type, scan_result):
+ llen = len(scan_result[0]["radioChainInfos"])
+ if scan_setting_type == wutils.WifiEnums.SCAN_TYPE_LOW_LATENCY \
+ or scan_setting_type == wutils.WifiEnums.SCAN_TYPE_LOW_POWER:
+ asserts.assert_true(llen == 1,
+ "radioChainInfos len expected:{} "
+ "actual:{}".format(1, llen))
+ else:
+ asserts.assert_true(llen == 2,
+ "radioChainInfos len expected:{} "
+ "actual:{}".format(2, llen))
+
def wifi_scanner_batch_scan_full(self, scan_setting):
"""Common logic for batch scan test case for full scan result.
@@ -953,6 +975,63 @@
wutils.WifiEnums.REPORT_EVENT_AFTER_EACH_SCAN}
self.wifi_scanner_single_scan(scan_setting)
+ @test_tracker_info(uuid="7c8da0c4-dec7-4d04-abd4-f8ea467a5c6d")
+ def test_wifi_scanner_dual_radio_low_latency(self):
+ """Test WiFi scanner single scan for mix channel with default setting
+ parameters.
+
+ 1. Start WifiScanner single scan for type = SCAN_TYPE_LOW_LATENCY.
+ 2. Verify that scan results match with respective scan settings.
+ """
+ if self.dut.model not in self.dbs_supported_models:
+ asserts.skip(
+ ("Device %s does not support dual radio scanning.")
+ % self.dut.model)
+ scan_setting = {"channels": self.wifi_chs.MIX_CHANNEL_SCAN,
+ "periodInMs": SCANTIME,
+ "reportEvents":
+ wutils.WifiEnums.REPORT_EVENT_FULL_SCAN_RESULT,
+ "type": wutils.WifiEnums.SCAN_TYPE_LOW_LATENCY}
+ self.wifi_scanner_single_scan_full(scan_setting)
+
+ @test_tracker_info(uuid="58b49b01-851b-4e45-b218-9fd27c0be921")
+ def test_wifi_scanner_dual_radio_low_power(self):
+ """Test WiFi scanner single scan for mix channel with default setting
+ parameters.
+
+ 1. Start WifiScanner single scan for type = SCAN_TYPE_LOW_POWER.
+ 2. Verify that scan results match with respective scan settings.
+ """
+ if self.dut.model not in self.dbs_supported_models:
+ asserts.skip(
+ ("Device %s does not support dual radio scanning.")
+ % self.dut.model)
+ scan_setting = {"channels": self.wifi_chs.MIX_CHANNEL_SCAN,
+ "periodInMs": SCANTIME,
+ "reportEvents":
+ wutils.WifiEnums.REPORT_EVENT_FULL_SCAN_RESULT,
+ "type": wutils.WifiEnums.SCAN_TYPE_LOW_POWER}
+ self.wifi_scanner_single_scan_full(scan_setting)
+
+ @test_tracker_info(uuid="3e7288bc-45e4-497c-bf3a-977eec4e896e")
+ def test_wifi_scanner_dual_radio_high_accuracy(self):
+ """Test WiFi scanner single scan for mix channel with default setting
+ parameters.
+
+ 1. Start WifiScanner single scan for type = SCAN_TYPE_HIGH_ACCURACY.
+ 2. Verify that scan results match with respective scan settings.
+ """
+ if self.dut.model not in self.dbs_supported_models:
+ asserts.skip(
+ ("Device %s does not support dual radio scanning.")
+ % self.dut.model)
+ scan_setting = {"channels": self.wifi_chs.MIX_CHANNEL_SCAN,
+ "periodInMs": SCANTIME,
+ "reportEvents":
+ wutils.WifiEnums.REPORT_EVENT_FULL_SCAN_RESULT,
+ "type": wutils.WifiEnums.SCAN_TYPE_HIGH_ACCURACY}
+ self.wifi_scanner_single_scan_full(scan_setting)
+
@test_tracker_info(uuid="e9f3aaad-4af3-4c54-9829-65dc1d6d4987")
def test_wifi_scanner_batch_scan_channel_sanity(self):
"""Test WiFi scanner batch scan for mix channel with default setting
diff --git a/acts/tests/google/wifi/WifiSoftApTest.py b/acts/tests/google/wifi/WifiSoftApTest.py
index 987b14d..0d722e3 100644
--- a/acts/tests/google/wifi/WifiSoftApTest.py
+++ b/acts/tests/google/wifi/WifiSoftApTest.py
@@ -55,7 +55,6 @@
utils.require_sl4a((self.dut, self.dut_client))
utils.sync_device_time(self.dut)
utils.sync_device_time(self.dut_client)
-
# Set country code explicitly to "US".
self.dut.droid.wifiSetCountryCode(wutils.WifiEnums.CountryCode.US)
self.dut_client.droid.wifiSetCountryCode(wutils.WifiEnums.CountryCode.US)
diff --git a/acts/tests/google/wifi/WifiStressTest.py b/acts/tests/google/wifi/WifiStressTest.py
index 01d9a6f..aee3d3b 100755
--- a/acts/tests/google/wifi/WifiStressTest.py
+++ b/acts/tests/google/wifi/WifiStressTest.py
@@ -32,7 +32,7 @@
WAIT_BEFORE_CONNECTION = 30
TIMEOUT = 1
-
+PING_ADDR = 'www.google.com'
class WifiStressTest(WifiBaseTest):
"""WiFi Stress test class.
@@ -80,11 +80,11 @@
def teardown_test(self):
self.dut.droid.wakeLockRelease()
self.dut.droid.goToSleepNow()
+ wutils.reset_wifi(self.dut)
def on_fail(self, test_name, begin_time):
self.dut.take_bug_report(test_name, begin_time)
self.dut.cat_adb_log(test_name, begin_time)
- pass
def teardown_class(self):
wutils.reset_wifi(self.dut)
@@ -120,6 +120,19 @@
ssid)
wutils.wifi_connect_by_id(self.dut, net_id)
+ def run_ping(self, sec):
+ """Run ping for given number of seconds.
+
+ Args:
+ sec: Time in seconds to run teh ping traffic.
+
+ """
+ self.log.info("Running ping for %d seconds" % sec)
+ result = self.dut.adb.shell("ping -w %d %s" %(sec, PING_ADDR),
+ timeout=sec+1)
+ self.log.debug("Ping Result = %s" % result)
+ if "100% packet loss" in result:
+ raise signals.TestFailure("100% packet loss during ping")
"""Tests"""
@@ -128,13 +141,20 @@
"""Toggle WiFi state ON and OFF for N times."""
for count in range(self.stress_count):
"""Test toggling wifi"""
- self.log.debug("Going from on to off.")
- wutils.wifi_toggle_state(self.dut, False)
- self.log.debug("Going from off to on.")
- startTime = time.time()
- wutils.wifi_toggle_state(self.dut, True)
- startup_time = time.time() - startTime
- self.log.debug("WiFi was enabled on the device in %s s." % startup_time)
+ try:
+ self.log.debug("Going from on to off.")
+ wutils.wifi_toggle_state(self.dut, False)
+ self.log.debug("Going from off to on.")
+ startTime = time.time()
+ wutils.wifi_toggle_state(self.dut, True)
+ startup_time = time.time() - startTime
+ self.log.debug("WiFi was enabled on the device in %s s." %
+ startup_time)
+ except:
+ signals.TestFailure(details="", extras={"Iterations":"%d" %
+ self.stress_count, "Pass":"%d" %count})
+ raise signals.TestPass(details="", extras={"Iterations":"%d" %
+ self.stress_count, "Pass":"%d" %(count+1)})
@test_tracker_info(uuid="49e3916a-9580-4bf7-a60d-a0f2545dcdde")
def test_stress_connect_traffic_disconnect_5g(self):
@@ -148,21 +168,26 @@
"""
for count in range(self.stress_count):
- net_id = self.dut.droid.wifiAddNetwork(self.wpa_5g)
- asserts.assert_true(net_id != -1, "Add network %r failed" % self.wpa_5g)
- self.dut.droid.wifiEnableNetwork(net_id, 0)
- self.scan_and_connect_by_id(self.wpa_5g, net_id)
- # Start IPerf traffic from phone to server.
- # Upload data for 10s.
- args = "-p {} -t {}".format(self.iperf_server.port, 10)
- self.log.info("Running iperf client {}".format(args))
- result, data = self.dut.run_iperf_client(self.iperf_server_address, args)
- if not result:
- self.log.debug("Error occurred in iPerf traffic.")
- raise signals.TestFailure("Error occurred in iPerf traffic. Current"
- " WiFi state = %d" % self.dut.droid.wifiCheckState())
- wutils.wifi_forget_network(self.dut,self.wpa_5g[WifiEnums.SSID_KEY])
- time.sleep(WAIT_BEFORE_CONNECTION)
+ try:
+ net_id = self.dut.droid.wifiAddNetwork(self.wpa_5g)
+ asserts.assert_true(net_id != -1, "Add network %r failed" % self.wpa_5g)
+ self.scan_and_connect_by_id(self.wpa_5g, net_id)
+ # Start IPerf traffic from phone to server.
+ # Upload data for 10s.
+ args = "-p {} -t {}".format(self.iperf_server.port, 10)
+ self.log.info("Running iperf client {}".format(args))
+ result, data = self.dut.run_iperf_client(self.iperf_server_address, args)
+ if not result:
+ self.log.debug("Error occurred in iPerf traffic.")
+ self.run_ping(10)
+ wutils.wifi_forget_network(self.dut,self.wpa_5g[WifiEnums.SSID_KEY])
+ time.sleep(WAIT_BEFORE_CONNECTION)
+ except:
+ raise signals.TestFailure("Network connect-disconnect failed."
+ "Look at logs", extras={"Iterations":"%d" %
+ self.stress_count, "Pass":"%d" %count})
+ raise signals.TestPass(details="", extras={"Iterations":"%d" %
+ self.stress_count, "Pass":"%d" %(count+1)})
@test_tracker_info(uuid="e9827dff-0755-43ec-8b50-1f9756958460")
def test_stress_connect_long_traffic_5g(self):
@@ -174,19 +199,24 @@
3. Verify no WiFi disconnects/data interruption.
"""
- self.scan_and_connect_by_ssid(self.wpa_5g)
- # Start IPerf traffic from server to phone.
- # Download data for 5 hours.
- sec = self.stress_hours * 60 * 60
- args = "-p {} -t {} -R".format(self.iperf_server.port, sec)
- self.log.info("Running iperf client {}".format(args))
- result, data = self.dut.run_iperf_client(self.iperf_server_address,
- args, timeout=sec+1)
- self.dut.droid.wifiDisconnect()
- if not result:
- self.log.debug("Error occurred in iPerf traffic.")
- raise signals.TestFailure("Error occurred in iPerf traffic. Current"
- " WiFi state = %d" % self.dut.droid.wifiCheckState())
+ try:
+ self.scan_and_connect_by_ssid(self.wpa_5g)
+ # Start IPerf traffic from server to phone.
+ # Download data for 5 hours.
+ sec = self.stress_hours * 60 * 60
+ args = "-p {} -t {} -R".format(self.iperf_server.port, sec)
+ self.log.info("Running iperf client {}".format(args))
+ result, data = self.dut.run_iperf_client(self.iperf_server_address,
+ args, timeout=sec+1)
+ if not result:
+ self.log.debug("Error occurred in iPerf traffic.")
+ self.run_ping(sec)
+ except:
+ raise signals.TestFailure("Network long-connect failed."
+ "Look at logs", extras={"Total Hours":"%d" %self.stress_hours,
+ "Seconds Run":"UNKNOWN"})
+ raise signals.TestPass(details="", extras={"Total Hours":"%d" %
+ self.stress_hours, "Seconds":"%d" %sec})
@test_tracker_info(uuid="d367c83e-5b00-4028-9ed8-f7b875997d13")
def test_stress_wifi_failover(self):
@@ -211,24 +241,28 @@
time.sleep(WAIT_FOR_AUTO_CONNECT)
cur_network = self.dut.droid.wifiGetConnectionInfo()
cur_ssid = cur_network[WifiEnums.SSID_KEY]
- self.log.debug("Cur_ssid = %s" % cur_ssid)
- for count in range(0,len(self.networks)):
+ self.log.info("Cur_ssid = %s" % cur_ssid)
+ for i in range(0,len(self.networks)):
self.log.debug("Forget network %s" % cur_ssid)
wutils.wifi_forget_network(self.dut, cur_ssid)
time.sleep(WAIT_FOR_AUTO_CONNECT)
cur_network = self.dut.droid.wifiGetConnectionInfo()
cur_ssid = cur_network[WifiEnums.SSID_KEY]
- self.log.debug("Cur_ssid = %s" % cur_ssid)
- if count == len(self.networks) - 1:
+ self.log.info("Cur_ssid = %s" % cur_ssid)
+ if i == len(self.networks) - 1:
break
if cur_ssid not in ssids:
raise signals.TestFailure("Device did not failover to the "
"expected network. SSID = %s" % cur_ssid)
network_config = self.dut.droid.wifiGetConfiguredNetworks()
- self.log.debug("Network Config = %s" % network_config)
+ self.log.info("Network Config = %s" % network_config)
if len(network_config):
raise signals.TestFailure("All the network configurations were not "
- "removed. Configured networks = %s" % network_config)
+ "removed. Configured networks = %s" % network_config,
+ extras={"Iterations":"%d" % self.stress_count,
+ "Pass":"%d" %(count*4)})
+ raise signals.TestPass(details="", extras={"Iterations":"%d" %
+ self.stress_count, "Pass":"%d" %((count+1)*4)})
@test_tracker_info(uuid="2c19e8d1-ac16-4d7e-b309-795144e6b956")
def test_stress_softAP_startup_and_stop_5g(self):
@@ -241,14 +275,14 @@
4. Verify softAP is turned down and WiFi is up.
"""
+ # Set country code explicitly to "US".
+ self.dut.droid.wifiSetCountryCode(wutils.WifiEnums.CountryCode.US)
+ self.dut_client.droid.wifiSetCountryCode(wutils.WifiEnums.CountryCode.US)
ap_ssid = "softap_" + utils.rand_ascii_str(8)
ap_password = utils.rand_ascii_str(8)
self.dut.log.info("softap setup: %s %s", ap_ssid, ap_password)
config = {wutils.WifiEnums.SSID_KEY: ap_ssid}
config[wutils.WifiEnums.PWD_KEY] = ap_password
- # Set country code explicitly to "US".
- self.dut.droid.wifiSetCountryCode(wutils.WifiEnums.CountryCode.US)
- self.dut_client.droid.wifiSetCountryCode(wutils.WifiEnums.CountryCode.US)
for count in range(self.stress_count):
initial_wifi_state = self.dut.droid.wifiCheckState()
wutils.start_wifi_tethering(self.dut,
@@ -257,31 +291,40 @@
WifiEnums.WIFI_CONFIG_APBAND_5G)
wutils.start_wifi_connection_scan_and_ensure_network_found(
self.dut_client, ap_ssid)
- # Toggle WiFi ON, which inturn calls softAP teardown.
- wutils.wifi_toggle_state(self.dut, True)
- time.sleep(TIMEOUT)
+ wutils.stop_wifi_tethering(self.dut)
asserts.assert_false(self.dut.droid.wifiIsApEnabled(),
"SoftAp failed to shutdown!")
time.sleep(TIMEOUT)
cur_wifi_state = self.dut.droid.wifiCheckState()
if initial_wifi_state != cur_wifi_state:
- raise signals.TestFailure("Wifi state was %d before softAP and %d now!" %
- (initial_wifi_state, cur_wifi_state))
+ raise signals.TestFailure("Wifi state was %d before softAP and %d now!" %
+ (initial_wifi_state, cur_wifi_state),
+ extras={"Iterations":"%d" % self.stres_count,
+ "Pass":"%d" %count})
+ raise signals.TestPass(details="", extras={"Iterations":"%d" %
+ self.stress_count, "Pass":"%d" %(count+1)})
@test_tracker_info(uuid="eb22e26b-95d1-4580-8c76-85dfe6a42a0f")
def test_stress_wifi_roaming(self):
AP1_network = self.reference_networks[0]["5g"]
AP2_network = self.reference_networks[1]["5g"]
wutils.set_attns(self.attenuators, "AP1_on_AP2_off")
- wutils.wifi_connect(self.dut, AP1_network)
+ self.scan_and_connect_by_ssid(AP1_network)
# Reduce iteration to half because each iteration does two roams.
- for count in range(self.stress_count/2):
+ for count in range(int(self.stress_count/2)):
self.log.info("Roaming iteration %d, from %s to %s", count,
AP1_network, AP2_network)
- wutils.trigger_roaming_and_validate(self.dut, self.attenuators,
- "AP1_off_AP2_on", AP2_network)
- self.log.info("Roaming iteration %d, from %s to %s", count,
- AP2_network, AP1_network)
- wutils.trigger_roaming_and_validate(self.dut, self.attenuators,
- "AP1_on_AP2_off", AP1_network)
+ try:
+ wutils.trigger_roaming_and_validate(self.dut, self.attenuators,
+ "AP1_off_AP2_on", AP2_network)
+ self.log.info("Roaming iteration %d, from %s to %s", count,
+ AP2_network, AP1_network)
+ wutils.trigger_roaming_and_validate(self.dut, self.attenuators,
+ "AP1_on_AP2_off", AP1_network)
+ except:
+ raise signals.TestFailure("Roaming failed. Look at logs",
+ extras={"Iterations":"%d" %self.stress_count, "Pass":"%d" %
+ (count*2)})
+ raise signals.TestPass(details="", extras={"Iterations":"%d" %
+ self.stress_count, "Pass":"%d" %((count+1)*2)})
diff --git a/acts/tests/google/wifi/WifiTeleCoexTest.py b/acts/tests/google/wifi/WifiTeleCoexTest.py
index f5d4c7f..3d30640 100644
--- a/acts/tests/google/wifi/WifiTeleCoexTest.py
+++ b/acts/tests/google/wifi/WifiTeleCoexTest.py
@@ -127,9 +127,11 @@
self.log.debug("Toggling wifi ON")
wifi_utils.wifi_toggle_state(self.dut, True)
+ # Sleep for 1s before getting new WiFi state.
+ time.sleep(1)
if not self.dut.droid.wifiGetisWifiEnabled():
raise signals.TestFailure("WiFi did not turn on after turning ON"
- "Airplane mode")
+ " Airplane mode")
asserts.assert_true(
acts.utils.force_airplane_mode(self.dut, False),
"Can not turn on airplane mode on: %s" % self.dut.serial)
@@ -159,6 +161,8 @@
3. Make a short sequence voice call between Phone A and B.
"""
+ # Sleep for 5s before getting new WiFi state.
+ time.sleep(5)
wifi_info = self.dut.droid.wifiGetConnectionInfo()
if wifi_info[WifiEnums.SSID_KEY] != self.wifi_network_ssid:
raise signals.TestFailure("Phone failed to connect to %s network on"
diff --git a/acts/tests/google/wifi/aware/functional/AttachTest.py b/acts/tests/google/wifi/aware/functional/AttachTest.py
index 598cca6..37f07e0 100644
--- a/acts/tests/google/wifi/aware/functional/AttachTest.py
+++ b/acts/tests/google/wifi/aware/functional/AttachTest.py
@@ -16,12 +16,13 @@
import time
+from acts import asserts
+from acts import utils
from acts.test_decorators import test_tracker_info
from acts.test_utils.wifi import wifi_test_utils as wutils
from acts.test_utils.wifi.aware import aware_const as aconsts
from acts.test_utils.wifi.aware import aware_test_utils as autils
from acts.test_utils.wifi.aware.AwareBaseTest import AwareBaseTest
-from acts.utils import force_airplane_mode
class AttachTest(AwareBaseTest):
@@ -99,8 +100,8 @@
"""Function test case / Attach test cases / attempt to attach with wifi off
Validates that if trying to attach with Wi-Fi disabled will receive the
- expected failure callback. As a side-effect also validates that the broadcast
- for Aware unavailable is received.
+ expected failure callback. As a side-effect also validates that the
+ broadcast for Aware unavailable is received.
"""
dut = self.android_devices[0]
wutils.wifi_toggle_state(dut, False)
@@ -108,6 +109,39 @@
dut.droid.wifiAwareAttach()
autils.wait_for_event(dut, aconsts.EVENT_CB_ON_ATTACH_FAILED)
+ @test_tracker_info(uuid="7dcc4530-c936-4447-9d22-a7c5b315e2ce")
+ def test_attach_with_doze(self):
+ """Function test case / Attach test cases / attempt to attach with doze on
+
+ Validates that if trying to attach with device in doze mode will receive the
+ expected failure callback. As a side-effect also validates that the
+ broadcast for Aware unavailable is received.
+ """
+ dut = self.android_devices[0]
+ asserts.assert_true(utils.enable_doze(dut), "Can't enable doze")
+ autils.wait_for_event(dut, aconsts.BROADCAST_WIFI_AWARE_NOT_AVAILABLE)
+ dut.droid.wifiAwareAttach()
+ autils.wait_for_event(dut, aconsts.EVENT_CB_ON_ATTACH_FAILED)
+ asserts.assert_true(utils.disable_doze(dut), "Can't disable doze")
+ autils.wait_for_event(dut, aconsts.BROADCAST_WIFI_AWARE_AVAILABLE)
+
+ @test_tracker_info(uuid="2574fd01-8974-4dd0-aeb8-a7194461140e")
+ def test_attach_with_location_off(self):
+ """Function test case / Attach test cases / attempt to attach with location
+ mode off.
+
+ Validates that if trying to attach with device location mode off will
+ receive the expected failure callback. As a side-effect also validates that
+ the broadcast for Aware unavailable is received.
+ """
+ dut = self.android_devices[0]
+ utils.set_location_service(dut, False)
+ autils.wait_for_event(dut, aconsts.BROADCAST_WIFI_AWARE_NOT_AVAILABLE)
+ dut.droid.wifiAwareAttach()
+ autils.wait_for_event(dut, aconsts.EVENT_CB_ON_ATTACH_FAILED)
+ utils.set_location_service(dut, True)
+ autils.wait_for_event(dut, aconsts.BROADCAST_WIFI_AWARE_AVAILABLE)
+
@test_tracker_info(uuid="7ffde8e7-a010-4b77-97f5-959f263b5249")
def test_attach_apm_toggle_attach_again(self):
"""Validates that enabling Airplane mode while Aware is on resets it
@@ -120,12 +154,12 @@
autils.wait_for_event(dut, aconsts.EVENT_CB_ON_ATTACHED)
# enable airplane mode
- force_airplane_mode(dut, True)
+ utils.force_airplane_mode(dut, True)
autils.wait_for_event(dut, aconsts.BROADCAST_WIFI_AWARE_NOT_AVAILABLE)
# wait a few seconds and disable airplane mode
time.sleep(10)
- force_airplane_mode(dut, False)
+ utils.force_airplane_mode(dut, False)
autils.wait_for_event(dut, aconsts.BROADCAST_WIFI_AWARE_AVAILABLE)
# try enabling Aware again (attach)
diff --git a/acts/tests/google/wifi/aware/functional/DataPathTest.py b/acts/tests/google/wifi/aware/functional/DataPathTest.py
index 66ec715..8afb2a4 100644
--- a/acts/tests/google/wifi/aware/functional/DataPathTest.py
+++ b/acts/tests/google/wifi/aware/functional/DataPathTest.py
@@ -19,6 +19,7 @@
from acts import asserts
from acts.test_decorators import test_tracker_info
from acts.test_utils.net import connectivity_const as cconsts
+from acts.test_utils.wifi import wifi_test_utils as wutils
from acts.test_utils.wifi.aware import aware_const as aconsts
from acts.test_utils.wifi.aware import aware_test_utils as autils
from acts.test_utils.wifi.aware.AwareBaseTest import AwareBaseTest
@@ -148,7 +149,8 @@
use_peer_id,
passphrase_to_use=None,
pub_on_both=False,
- pub_on_both_same=True):
+ pub_on_both_same=True,
+ expect_failure=False):
"""Runs the in-band data-path tests.
Args:
@@ -163,6 +165,8 @@
publisher isn't used (existing to test use-case).
pub_on_both_same: If True then the second publish uses an identical
service name, otherwise a different service name.
+ expect_failure: If True then don't expect NDP formation, otherwise expect
+ NDP setup to succeed.
"""
(p_dut, s_dut, p_id, s_id, p_disc_id, s_disc_id, peer_id_on_sub,
peer_id_on_pub) = self.set_up_discovery(ptype, stype, use_peer_id,
@@ -189,51 +193,59 @@
s_dut.droid.wifiAwareCreateNetworkSpecifier(s_disc_id, peer_id_on_sub,
passphrase, pmk))
- # Publisher & Subscriber: wait for network formation
- p_net_event = autils.wait_for_event_with_keys(
- p_dut, cconsts.EVENT_NETWORK_CALLBACK,
- autils.EVENT_NDP_TIMEOUT,
- (cconsts.NETWORK_CB_KEY_EVENT,
- cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
- (cconsts.NETWORK_CB_KEY_ID, p_req_key))
- s_net_event = autils.wait_for_event_with_keys(
- s_dut, cconsts.EVENT_NETWORK_CALLBACK,
- autils.EVENT_NDP_TIMEOUT,
- (cconsts.NETWORK_CB_KEY_EVENT,
- cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
- (cconsts.NETWORK_CB_KEY_ID, s_req_key))
+ if expect_failure:
+ # Publisher & Subscriber: fail on network formation
+ time.sleep(autils.EVENT_NDP_TIMEOUT)
+ autils.fail_on_event_with_keys(p_dut, cconsts.EVENT_NETWORK_CALLBACK, 0,
+ (cconsts.NETWORK_CB_KEY_ID, p_req_key))
+ autils.fail_on_event_with_keys(s_dut, cconsts.EVENT_NETWORK_CALLBACK, 0,
+ (cconsts.NETWORK_CB_KEY_ID, s_req_key))
+ else:
+ # Publisher & Subscriber: wait for network formation
+ p_net_event = autils.wait_for_event_with_keys(
+ p_dut, cconsts.EVENT_NETWORK_CALLBACK,
+ autils.EVENT_NDP_TIMEOUT,
+ (cconsts.NETWORK_CB_KEY_EVENT,
+ cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
+ (cconsts.NETWORK_CB_KEY_ID, p_req_key))
+ s_net_event = autils.wait_for_event_with_keys(
+ s_dut, cconsts.EVENT_NETWORK_CALLBACK,
+ autils.EVENT_NDP_TIMEOUT,
+ (cconsts.NETWORK_CB_KEY_EVENT,
+ cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
+ (cconsts.NETWORK_CB_KEY_ID, s_req_key))
- p_aware_if = p_net_event["data"][cconsts.NETWORK_CB_KEY_INTERFACE_NAME]
- s_aware_if = s_net_event["data"][cconsts.NETWORK_CB_KEY_INTERFACE_NAME]
- self.log.info("Interface names: p=%s, s=%s", p_aware_if, s_aware_if)
+ p_aware_if = p_net_event["data"][cconsts.NETWORK_CB_KEY_INTERFACE_NAME]
+ s_aware_if = s_net_event["data"][cconsts.NETWORK_CB_KEY_INTERFACE_NAME]
+ self.log.info("Interface names: p=%s, s=%s", p_aware_if, s_aware_if)
- p_ipv6 = p_dut.droid.connectivityGetLinkLocalIpv6Address(p_aware_if).split(
- "%")[0]
- s_ipv6 = s_dut.droid.connectivityGetLinkLocalIpv6Address(s_aware_if).split(
- "%")[0]
- self.log.info("Interface addresses (IPv6): p=%s, s=%s", p_ipv6, s_ipv6)
+ p_ipv6 = \
+ p_dut.droid.connectivityGetLinkLocalIpv6Address(p_aware_if).split("%")[0]
+ s_ipv6 = \
+ s_dut.droid.connectivityGetLinkLocalIpv6Address(s_aware_if).split("%")[0]
+ self.log.info("Interface addresses (IPv6): p=%s, s=%s", p_ipv6, s_ipv6)
- # TODO: possibly send messages back and forth, prefer to use netcat/nc
+ # TODO: possibly send messages back and forth, prefer to use netcat/nc
- # terminate sessions and wait for ON_LOST callbacks
- p_dut.droid.wifiAwareDestroy(p_id)
- s_dut.droid.wifiAwareDestroy(s_id)
+ # terminate sessions and wait for ON_LOST callbacks
+ p_dut.droid.wifiAwareDestroy(p_id)
+ s_dut.droid.wifiAwareDestroy(s_id)
- autils.wait_for_event_with_keys(
- p_dut, cconsts.EVENT_NETWORK_CALLBACK, autils.EVENT_NDP_TIMEOUT,
- (cconsts.NETWORK_CB_KEY_EVENT,
- cconsts.NETWORK_CB_LOST), (cconsts.NETWORK_CB_KEY_ID, p_req_key))
- autils.wait_for_event_with_keys(
- s_dut, cconsts.EVENT_NETWORK_CALLBACK, autils.EVENT_NDP_TIMEOUT,
- (cconsts.NETWORK_CB_KEY_EVENT,
- cconsts.NETWORK_CB_LOST), (cconsts.NETWORK_CB_KEY_ID, s_req_key))
+ autils.wait_for_event_with_keys(
+ p_dut, cconsts.EVENT_NETWORK_CALLBACK, autils.EVENT_NDP_TIMEOUT,
+ (cconsts.NETWORK_CB_KEY_EVENT,
+ cconsts.NETWORK_CB_LOST), (cconsts.NETWORK_CB_KEY_ID, p_req_key))
+ autils.wait_for_event_with_keys(
+ s_dut, cconsts.EVENT_NETWORK_CALLBACK, autils.EVENT_NDP_TIMEOUT,
+ (cconsts.NETWORK_CB_KEY_EVENT,
+ cconsts.NETWORK_CB_LOST), (cconsts.NETWORK_CB_KEY_ID, s_req_key))
# clean-up
p_dut.droid.connectivityUnregisterNetworkCallback(p_req_key)
s_dut.droid.connectivityUnregisterNetworkCallback(s_req_key)
def run_oob_data_path_test(self, encr_type, use_peer_id,
- setup_discovery_sessions=False):
+ setup_discovery_sessions=False, expect_failure=False):
"""Runs the out-of-band data-path tests.
Args:
@@ -243,6 +255,8 @@
setup_discovery_sessions: If True also set up a (spurious) discovery
session (pub on both sides, sub on Responder side). Validates a corner
case.
+ expect_failure: If True then don't expect NDP formation, otherwise expect
+ NDP setup to succeed.
"""
init_dut = self.android_devices[0]
init_dut.pretty_name = "Initiator"
@@ -299,47 +313,57 @@
init_dut.droid.wifiAwareCreateNetworkSpecifierOob(
init_id, aconsts.DATA_PATH_INITIATOR, resp_mac, passphrase, pmk))
- # Initiator & Responder: wait for network formation
- init_net_event = autils.wait_for_event_with_keys(
- init_dut, cconsts.EVENT_NETWORK_CALLBACK,
- autils.EVENT_NDP_TIMEOUT,
- (cconsts.NETWORK_CB_KEY_EVENT,
- cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
- (cconsts.NETWORK_CB_KEY_ID, init_req_key))
- resp_net_event = autils.wait_for_event_with_keys(
- resp_dut, cconsts.EVENT_NETWORK_CALLBACK,
- autils.EVENT_NDP_TIMEOUT,
- (cconsts.NETWORK_CB_KEY_EVENT,
- cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
- (cconsts.NETWORK_CB_KEY_ID, resp_req_key))
+ if expect_failure:
+ # Initiator & Responder: fail on network formation
+ time.sleep(autils.EVENT_NDP_TIMEOUT)
+ autils.fail_on_event_with_keys(resp_dut, cconsts.EVENT_NETWORK_CALLBACK,
+ 0,
+ (cconsts.NETWORK_CB_KEY_ID, resp_req_key))
+ autils.fail_on_event_with_keys(init_dut, cconsts.EVENT_NETWORK_CALLBACK,
+ 0,
+ (cconsts.NETWORK_CB_KEY_ID, init_req_key))
+ else:
+ # Initiator & Responder: wait for network formation
+ init_net_event = autils.wait_for_event_with_keys(
+ init_dut, cconsts.EVENT_NETWORK_CALLBACK,
+ autils.EVENT_NDP_TIMEOUT,
+ (cconsts.NETWORK_CB_KEY_EVENT,
+ cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
+ (cconsts.NETWORK_CB_KEY_ID, init_req_key))
+ resp_net_event = autils.wait_for_event_with_keys(
+ resp_dut, cconsts.EVENT_NETWORK_CALLBACK,
+ autils.EVENT_NDP_TIMEOUT,
+ (cconsts.NETWORK_CB_KEY_EVENT,
+ cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
+ (cconsts.NETWORK_CB_KEY_ID, resp_req_key))
- init_aware_if = init_net_event["data"][
- cconsts.NETWORK_CB_KEY_INTERFACE_NAME]
- resp_aware_if = resp_net_event["data"][
- cconsts.NETWORK_CB_KEY_INTERFACE_NAME]
- self.log.info("Interface names: I=%s, R=%s", init_aware_if, resp_aware_if)
+ init_aware_if = init_net_event["data"][
+ cconsts.NETWORK_CB_KEY_INTERFACE_NAME]
+ resp_aware_if = resp_net_event["data"][
+ cconsts.NETWORK_CB_KEY_INTERFACE_NAME]
+ self.log.info("Interface names: I=%s, R=%s", init_aware_if, resp_aware_if)
- init_ipv6 = init_dut.droid.connectivityGetLinkLocalIpv6Address(
- init_aware_if).split("%")[0]
- resp_ipv6 = resp_dut.droid.connectivityGetLinkLocalIpv6Address(
- resp_aware_if).split("%")[0]
- self.log.info("Interface addresses (IPv6): I=%s, R=%s", init_ipv6,
- resp_ipv6)
+ init_ipv6 = init_dut.droid.connectivityGetLinkLocalIpv6Address(
+ init_aware_if).split("%")[0]
+ resp_ipv6 = resp_dut.droid.connectivityGetLinkLocalIpv6Address(
+ resp_aware_if).split("%")[0]
+ self.log.info("Interface addresses (IPv6): I=%s, R=%s", init_ipv6,
+ resp_ipv6)
- # TODO: possibly send messages back and forth, prefer to use netcat/nc
+ # TODO: possibly send messages back and forth, prefer to use netcat/nc
- # terminate sessions and wait for ON_LOST callbacks
- init_dut.droid.wifiAwareDestroy(init_id)
- resp_dut.droid.wifiAwareDestroy(resp_id)
+ # terminate sessions and wait for ON_LOST callbacks
+ init_dut.droid.wifiAwareDestroy(init_id)
+ resp_dut.droid.wifiAwareDestroy(resp_id)
- autils.wait_for_event_with_keys(
- init_dut, cconsts.EVENT_NETWORK_CALLBACK, autils.EVENT_NDP_TIMEOUT,
- (cconsts.NETWORK_CB_KEY_EVENT,
- cconsts.NETWORK_CB_LOST), (cconsts.NETWORK_CB_KEY_ID, init_req_key))
- autils.wait_for_event_with_keys(
- resp_dut, cconsts.EVENT_NETWORK_CALLBACK, autils.EVENT_NDP_TIMEOUT,
- (cconsts.NETWORK_CB_KEY_EVENT,
- cconsts.NETWORK_CB_LOST), (cconsts.NETWORK_CB_KEY_ID, resp_req_key))
+ autils.wait_for_event_with_keys(
+ init_dut, cconsts.EVENT_NETWORK_CALLBACK, autils.EVENT_NDP_TIMEOUT,
+ (cconsts.NETWORK_CB_KEY_EVENT,
+ cconsts.NETWORK_CB_LOST), (cconsts.NETWORK_CB_KEY_ID, init_req_key))
+ autils.wait_for_event_with_keys(
+ resp_dut, cconsts.EVENT_NETWORK_CALLBACK, autils.EVENT_NDP_TIMEOUT,
+ (cconsts.NETWORK_CB_KEY_EVENT,
+ cconsts.NETWORK_CB_LOST), (cconsts.NETWORK_CB_KEY_ID, resp_req_key))
# clean-up
resp_dut.droid.connectivityUnregisterNetworkCallback(resp_req_key)
@@ -638,13 +662,14 @@
# or different from the primary session.
# pub_type: Type of publish discovery session: unsolicited or solicited.
# sub_type: Type of subscribe discovery session: passive or active.
- # encr_type: Encription type: open, passphrase
+ # encr_type: Encryption type: open, passphrase
# peer_spec: Peer specification method: any or specific
#
# Note: In-Band means using Wi-Fi Aware for discovery and referring to the
# peer using the Aware-provided peer handle (as opposed to a MAC address).
#######################################
+ @test_tracker_info(uuid="e855dd81-45c8-4bb2-a204-7687c48ff843")
def test_ib_extra_pub_same_unsolicited_passive_open_specific(self):
"""Data-path: in-band, unsolicited/passive, open encryption, specific peer.
@@ -661,6 +686,7 @@
pub_on_both=True,
pub_on_both_same=True)
+ @test_tracker_info(uuid="57fc9d53-32ae-470f-a8b1-2fe37893687d")
def test_ib_extra_pub_same_unsolicited_passive_open_any(self):
"""Data-path: in-band, unsolicited/passive, open encryption, any peer.
@@ -677,6 +703,7 @@
pub_on_both=True,
pub_on_both_same=True)
+ @test_tracker_info(uuid="7a32f439-d745-4716-a75e-b54109aaaf82")
def test_ib_extra_pub_diff_unsolicited_passive_open_specific(self):
"""Data-path: in-band, unsolicited/passive, open encryption, specific peer.
@@ -693,6 +720,7 @@
pub_on_both=True,
pub_on_both_same=False)
+ @test_tracker_info(uuid="a14ddc66-88fd-4b49-ab37-225533867c63")
def test_ib_extra_pub_diff_unsolicited_passive_open_any(self):
"""Data-path: in-band, unsolicited/passive, open encryption, any peer.
@@ -715,7 +743,7 @@
# names is: test_oob_<encr_type>_<peer_spec>
# where:
#
- # encr_type: Encription type: open, passphrase
+ # encr_type: Encryption type: open, passphrase
# peer_spec: Peer specification method: any or specific
#
# Optionally set up an extra discovery session to test coexistence. If so
@@ -785,6 +813,7 @@
encr_type=self.ENCR_TYPE_PMK,
use_peer_id=False)
+ @test_tracker_info(uuid="dd464f24-b404-4eea-955c-d10c9e8adefc")
def test_oob_ib_coex_open_specific(self):
"""Data-path: out-of-band, open encryption, specific peer - in-band coex:
set up a concurrent discovery session to verify no impact. The session
@@ -797,6 +826,7 @@
use_peer_id=True,
setup_discovery_sessions=True)
+ @test_tracker_info(uuid="088fcd3a-b015-4179-a9a5-91f782b03e3b")
def test_oob_ib_coex_open_any(self):
"""Data-path: out-of-band, open encryption, any peer - in-band coex:
set up a concurrent discovery session to verify no impact. The session
@@ -928,7 +958,8 @@
"""
num_events = 0
while num_events != len(req_keys):
- event = autils.wait_for_event(dut, cconsts.EVENT_NETWORK_CALLBACK)
+ event = autils.wait_for_event(dut, cconsts.EVENT_NETWORK_CALLBACK,
+ timeout=autils.EVENT_NDP_TIMEOUT)
if (event["data"][cconsts.NETWORK_CB_KEY_EVENT] ==
cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED):
if event["data"][cconsts.NETWORK_CB_KEY_ID] in req_keys:
@@ -1204,6 +1235,8 @@
dut1_req_keys = []
dut2_aware_ifs = []
dut1_aware_ifs = []
+ dut2_aware_ipv6 = []
+ dut1_aware_ipv6 = []
dut2_type = aconsts.DATA_PATH_RESPONDER
dut1_type = aconsts.DATA_PATH_INITIATOR
@@ -1244,20 +1277,24 @@
# Wait for network
dut1_net_event = autils.wait_for_event_with_keys(
- dut1, cconsts.EVENT_NETWORK_CALLBACK, autils.EVENT_TIMEOUT,
+ dut1, cconsts.EVENT_NETWORK_CALLBACK, autils.EVENT_NDP_TIMEOUT,
(cconsts.NETWORK_CB_KEY_EVENT,
cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
(cconsts.NETWORK_CB_KEY_ID, dut1_req_key))
dut2_net_event = autils.wait_for_event_with_keys(
- dut2, cconsts.EVENT_NETWORK_CALLBACK, autils.EVENT_TIMEOUT,
+ dut2, cconsts.EVENT_NETWORK_CALLBACK, autils.EVENT_NDP_TIMEOUT,
(cconsts.NETWORK_CB_KEY_EVENT,
cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
(cconsts.NETWORK_CB_KEY_ID, dut2_req_key))
- dut2_aware_ifs.append(
- dut2_net_event["data"][cconsts.NETWORK_CB_KEY_INTERFACE_NAME])
- dut1_aware_ifs.append(
- dut1_net_event["data"][cconsts.NETWORK_CB_KEY_INTERFACE_NAME])
+ dut2_aware_if = dut2_net_event["data"][
+ cconsts.NETWORK_CB_KEY_INTERFACE_NAME]
+ dut1_aware_if = dut1_net_event["data"][
+ cconsts.NETWORK_CB_KEY_INTERFACE_NAME]
+ dut2_aware_ifs.append(dut2_aware_if)
+ dut1_aware_ifs.append(dut1_aware_if)
+ dut2_aware_ipv6.append(autils.get_ipv6_addr(dut2, dut2_aware_if))
+ dut1_aware_ipv6.append(autils.get_ipv6_addr(dut1, dut1_aware_if))
if flip_init_resp:
if dut2_is_responder:
@@ -1268,12 +1305,16 @@
dut1_type = aconsts.DATA_PATH_INITIATOR
dut2_is_responder = not dut2_is_responder
- # check that we are using 2 NDIs
+ # check that we are using 2 NDIs & that they have unique IPv6 addresses
dut1_aware_ifs = list(set(dut1_aware_ifs))
dut2_aware_ifs = list(set(dut2_aware_ifs))
+ dut1_aware_ipv6 = list(set(dut1_aware_ipv6))
+ dut2_aware_ipv6 = list(set(dut2_aware_ipv6))
self.log.info("Interface names: DUT1=%s, DUT2=%s", dut1_aware_ifs,
dut2_aware_ifs)
+ self.log.info("IPv6 addresses: DUT1=%s, DUT2=%s", dut1_aware_ipv6,
+ dut2_aware_ipv6)
self.log.info("DUT1 requests: %s", dut1_req_keys)
self.log.info("DUT2 requests: %s", dut2_req_keys)
@@ -1281,6 +1322,10 @@
len(dut1_aware_ifs), len(sec_configs), "Multiple DUT1 interfaces")
asserts.assert_equal(
len(dut2_aware_ifs), len(sec_configs), "Multiple DUT2 interfaces")
+ asserts.assert_equal(
+ len(dut1_aware_ipv6), len(sec_configs), "Multiple DUT1 IPv6 addresses")
+ asserts.assert_equal(
+ len(dut2_aware_ipv6), len(sec_configs), "Multiple DUT2 IPv6 addresses")
for i in range(len(sec_configs)):
if_name = "%s%d" % (aconsts.AWARE_NDI_PREFIX, i)
@@ -1302,41 +1347,42 @@
@test_tracker_info(uuid="2d728163-11cc-46ba-a973-c8e1e71397fc")
def test_multiple_ndi_open_passphrase(self):
- """Verify that can between 2 DUTs can create 2 NDPs with different security
+ """Verify that between 2 DUTs can create 2 NDPs with different security
configuration (one open, one using passphrase). The result should use two
different NDIs"""
self.run_multiple_ndi([None, self.PASSPHRASE])
@test_tracker_info(uuid="5f2c32aa-20b2-41f0-8b1e-d0b68df73ada")
def test_multiple_ndi_open_pmk(self):
- """Verify that can between 2 DUTs can create 2 NDPs with different security
+ """Verify that between 2 DUTs can create 2 NDPs with different security
configuration (one open, one using pmk). The result should use two
different NDIs"""
self.run_multiple_ndi([None, self.PMK])
@test_tracker_info(uuid="34467659-bcfb-40cd-ba25-7e50560fca63")
def test_multiple_ndi_passphrase_pmk(self):
- """Verify that can between 2 DUTs can create 2 NDPs with different security
+ """Verify that between 2 DUTs can create 2 NDPs with different security
configuration (one using passphrase, one using pmk). The result should use
two different NDIs"""
self.run_multiple_ndi([self.PASSPHRASE, self.PMK])
@test_tracker_info(uuid="d9194ce6-45b6-41b1-9cc8-ada79968966d")
def test_multiple_ndi_passphrases(self):
- """Verify that can between 2 DUTs can create 2 NDPs with different security
+ """Verify that between 2 DUTs can create 2 NDPs with different security
configuration (using different passphrases). The result should use two
different NDIs"""
self.run_multiple_ndi([self.PASSPHRASE, self.PASSPHRASE2])
@test_tracker_info(uuid="879df795-62d2-40d4-a862-bd46d8f7e67f")
def test_multiple_ndi_pmks(self):
- """Verify that can between 2 DUTs can create 2 NDPs with different security
+ """Verify that between 2 DUTs can create 2 NDPs with different security
configuration (using different PMKS). The result should use two different
NDIs"""
self.run_multiple_ndi([self.PMK, self.PMK2])
+ @test_tracker_info(uuid="397d380a-8e41-466e-9ccb-cf8f413d83ba")
def test_multiple_ndi_open_passphrase_flip(self):
- """Verify that can between 2 DUTs can create 2 NDPs with different security
+ """Verify that between 2 DUTs can create 2 NDPs with different security
configuration (one open, one using passphrase). The result should use two
different NDIs.
@@ -1344,8 +1390,9 @@
"""
self.run_multiple_ndi([None, self.PASSPHRASE], flip_init_resp=True)
+ @test_tracker_info(uuid="b3a4300b-1514-4cb8-a814-9c2baa449700")
def test_multiple_ndi_open_pmk_flip(self):
- """Verify that can between 2 DUTs can create 2 NDPs with different security
+ """Verify that between 2 DUTs can create 2 NDPs with different security
configuration (one open, one using pmk). The result should use two
different NDIs
@@ -1353,8 +1400,9 @@
"""
self.run_multiple_ndi([None, self.PMK], flip_init_resp=True)
+ @test_tracker_info(uuid="0bfea9e4-e57d-417f-8db4-245741e9bbd5")
def test_multiple_ndi_passphrase_pmk_flip(self):
- """Verify that can between 2 DUTs can create 2 NDPs with different security
+ """Verify that between 2 DUTs can create 2 NDPs with different security
configuration (one using passphrase, one using pmk). The result should use
two different NDIs
@@ -1362,8 +1410,9 @@
"""
self.run_multiple_ndi([self.PASSPHRASE, self.PMK], flip_init_resp=True)
+ @test_tracker_info(uuid="74023483-5417-431b-a362-991ad4a03ab8")
def test_multiple_ndi_passphrases_flip(self):
- """Verify that can between 2 DUTs can create 2 NDPs with different security
+ """Verify that between 2 DUTs can create 2 NDPs with different security
configuration (using different passphrases). The result should use two
different NDIs
@@ -1372,11 +1421,505 @@
self.run_multiple_ndi([self.PASSPHRASE, self.PASSPHRASE2],
flip_init_resp=True)
+ @test_tracker_info(uuid="873b2d91-28a1-403f-ae9c-d756bb2f59ee")
def test_multiple_ndi_pmks_flip(self):
- """Verify that can between 2 DUTs can create 2 NDPs with different security
+ """Verify that between 2 DUTs can create 2 NDPs with different security
configuration (using different PMKS). The result should use two different
NDIs
Flip Initiator and Responder roles.
"""
self.run_multiple_ndi([self.PMK, self.PMK2], flip_init_resp=True)
+
+ #######################################
+
+ @test_tracker_info(uuid="2f10a9df-7fbd-490d-a238-3523f47ab54c")
+ def test_ib_responder_any_usage(self):
+ """Verify that configuring an in-band (Aware discovery) Responder to receive
+ an NDP request from any peer is not permitted by current API level. Override
+ API check to validate that possible (i.e. that failure at current API level
+ is due to an API check and not some underlying failure).
+ """
+
+ # configure all devices to override API check and allow a Responder from ANY
+ for ad in self.android_devices:
+ autils.configure_ndp_allow_any_override(ad, True)
+ self.run_ib_data_path_test(
+ ptype=aconsts.PUBLISH_TYPE_UNSOLICITED,
+ stype=aconsts.SUBSCRIBE_TYPE_PASSIVE,
+ encr_type=self.ENCR_TYPE_OPEN,
+ use_peer_id=False)
+
+ # configure all devices to respect API check - i.e. disallow a Responder
+ # from ANY
+ for ad in self.android_devices:
+ autils.configure_ndp_allow_any_override(ad, False)
+ self.run_ib_data_path_test(
+ ptype=aconsts.PUBLISH_TYPE_UNSOLICITED,
+ stype=aconsts.SUBSCRIBE_TYPE_PASSIVE,
+ encr_type=self.ENCR_TYPE_OPEN,
+ use_peer_id=False,
+ expect_failure=True)
+
+ @test_tracker_info(uuid="5889cd41-0a72-4b7b-ab82-5b9168b9b5b8")
+ def test_oob_responder_any_usage(self):
+ """Verify that configuring an out-of-band (Aware discovery) Responder to
+ receive an NDP request from any peer is not permitted by current API level.
+ Override API check to validate that possible (i.e. that failure at current
+ API level is due to an API check and not some underlying failure).
+ """
+
+ # configure all devices to override API check and allow a Responder from ANY
+ for ad in self.android_devices:
+ autils.configure_ndp_allow_any_override(ad, True)
+ self.run_oob_data_path_test(
+ encr_type=self.ENCR_TYPE_OPEN,
+ use_peer_id=False)
+
+ # configure all devices to respect API check - i.e. disallow a Responder
+ # from ANY
+ for ad in self.android_devices:
+ autils.configure_ndp_allow_any_override(ad, False)
+ self.run_oob_data_path_test(
+ encr_type=self.ENCR_TYPE_OPEN,
+ use_peer_id=False,
+ expect_failure=True)
+
+ #######################################
+
+ def run_multiple_regulatory_domains(self, use_ib, init_domain, resp_domain):
+ """Verify that a data-path setup with two conflicting regulatory domains
+ works (the result should be run in Channel 6 - but that is not tested).
+
+ Args:
+ use_ib: True to use in-band discovery, False to use out-of-band discovery.
+ init_domain: The regulatory domain of the Initiator/Subscriber.
+ resp_domain: The regulator domain of the Responder/Publisher.
+ """
+ init_dut = self.android_devices[0]
+ resp_dut = self.android_devices[1]
+
+ init_dut.droid.wifiSetCountryCode(init_domain)
+ resp_dut.droid.wifiSetCountryCode(resp_domain)
+
+ if use_ib:
+ (resp_req_key, init_req_key, resp_aware_if, init_aware_if, resp_ipv6,
+ init_ipv6) = autils.create_ib_ndp(resp_dut, init_dut,
+ autils.create_discovery_config(
+ "GoogleTestXyz",
+ aconsts.PUBLISH_TYPE_UNSOLICITED),
+ autils.create_discovery_config(
+ "GoogleTestXyz",
+ aconsts.SUBSCRIBE_TYPE_PASSIVE),
+ self.device_startup_offset)
+ else:
+ (init_req_key, resp_req_key, init_aware_if, resp_aware_if, init_ipv6,
+ resp_ipv6) = autils.create_oob_ndp(init_dut, resp_dut)
+
+ self.log.info("Interface names: I=%s, R=%s", init_aware_if, resp_aware_if)
+ self.log.info("Interface addresses (IPv6): I=%s, R=%s", init_ipv6,
+ resp_ipv6)
+
+ # clean-up
+ resp_dut.droid.connectivityUnregisterNetworkCallback(resp_req_key)
+ init_dut.droid.connectivityUnregisterNetworkCallback(init_req_key)
+
+ @test_tracker_info(uuid="eff53739-35c5-47a6-81f0-d70b51d89c3b")
+ def test_multiple_regulator_domains_ib_us_jp(self):
+ """Verify data-path setup across multiple regulator domains.
+
+ - Uses in-band discovery
+ - Subscriber=US, Publisher=JP
+ """
+ self.run_multiple_regulatory_domains(
+ use_ib=True,
+ init_domain=wutils.WifiEnums.CountryCode.US,
+ resp_domain=wutils.WifiEnums.CountryCode.JAPAN)
+
+ @test_tracker_info(uuid="19af47cc-3204-40ef-b50f-14cf7b89cf4a")
+ def test_multiple_regulator_domains_ib_jp_us(self):
+ """Verify data-path setup across multiple regulator domains.
+
+ - Uses in-band discovery
+ - Subscriber=JP, Publisher=US
+ """
+ self.run_multiple_regulatory_domains(
+ use_ib=True,
+ init_domain=wutils.WifiEnums.CountryCode.JAPAN,
+ resp_domain=wutils.WifiEnums.CountryCode.US)
+
+ @test_tracker_info(uuid="65285ab3-977f-4dbd-b663-d5a02f4fc663")
+ def test_multiple_regulator_domains_oob_us_jp(self):
+ """Verify data-path setup across multiple regulator domains.
+
+ - Uses out-f-band discovery
+ - Initiator=US, Responder=JP
+ """
+ self.run_multiple_regulatory_domains(
+ use_ib=False,
+ init_domain=wutils.WifiEnums.CountryCode.US,
+ resp_domain=wutils.WifiEnums.CountryCode.JAPAN)
+
+ @test_tracker_info(uuid="8a417e24-aaf6-44b9-a089-a07c3ba8d954")
+ def test_multiple_regulator_domains_oob_jp_us(self):
+ """Verify data-path setup across multiple regulator domains.
+
+ - Uses out-of-band discovery
+ - Initiator=JP, Responder=US
+ """
+ self.run_multiple_regulatory_domains(
+ use_ib=False,
+ init_domain=wutils.WifiEnums.CountryCode.JAPAN,
+ resp_domain=wutils.WifiEnums.CountryCode.US)
+
+ ########################################################################
+
+ def run_mix_ib_oob(self, same_request, ib_first, inits_on_same_dut):
+ """Validate that multiple network requests issued using both in-band and
+ out-of-band discovery behave as expected.
+
+ The same_request parameter controls whether identical single NDP is
+ expected, if True, or whether multiple NDPs on different NDIs are expected,
+ if False.
+
+ Args:
+ same_request: Issue canonically identical requests (same NMI peer, same
+ passphrase) if True, if False use different passphrases.
+ ib_first: If True then the in-band network is requested first, otherwise
+ (if False) then the out-of-band network is requested first.
+ inits_on_same_dut: If True then the Initiators are run on the same device,
+ otherwise (if False) then the Initiators are run on
+ different devices. Note that Subscribe == Initiator.
+ """
+ if not same_request:
+ asserts.skip_if(self.android_devices[0].aware_capabilities[
+ aconsts.CAP_MAX_NDI_INTERFACES] < 2 or
+ self.android_devices[1].aware_capabilities[
+ aconsts.CAP_MAX_NDI_INTERFACES] < 2,
+ "DUTs do not support enough NDIs")
+
+ (p_dut, s_dut, p_id, s_id, p_disc_id, s_disc_id, peer_id_on_sub,
+ peer_id_on_pub_null) = self.set_up_discovery(
+ aconsts.PUBLISH_TYPE_UNSOLICITED, aconsts.SUBSCRIBE_TYPE_PASSIVE, False)
+
+ p_id2, p_mac = autils.attach_with_identity(p_dut)
+ s_id2, s_mac = autils.attach_with_identity(s_dut)
+
+ if inits_on_same_dut:
+ resp_dut = p_dut
+ resp_id = p_id2
+ resp_mac = p_mac
+
+ init_dut = s_dut
+ init_id = s_id2
+ init_mac = s_mac
+ else:
+ resp_dut = s_dut
+ resp_id = s_id2
+ resp_mac = s_mac
+
+ init_dut = p_dut
+ init_id = p_id2
+ init_mac = p_mac
+
+ passphrase = None if same_request else self.PASSPHRASE
+
+ if ib_first:
+ # request in-band network (to completion)
+ p_req_key = self.request_network(
+ p_dut,
+ p_dut.droid.wifiAwareCreateNetworkSpecifier(p_disc_id, None))
+ s_req_key = self.request_network(
+ s_dut,
+ s_dut.droid.wifiAwareCreateNetworkSpecifier(s_disc_id,
+ peer_id_on_sub))
+
+ # Publisher & Subscriber: wait for network formation
+ p_net_event = autils.wait_for_event_with_keys(
+ p_dut, cconsts.EVENT_NETWORK_CALLBACK,
+ autils.EVENT_NDP_TIMEOUT,
+ (cconsts.NETWORK_CB_KEY_EVENT,
+ cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
+ (cconsts.NETWORK_CB_KEY_ID, p_req_key))
+ s_net_event = autils.wait_for_event_with_keys(
+ s_dut, cconsts.EVENT_NETWORK_CALLBACK,
+ autils.EVENT_NDP_TIMEOUT,
+ (cconsts.NETWORK_CB_KEY_EVENT,
+ cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
+ (cconsts.NETWORK_CB_KEY_ID, s_req_key))
+
+ # request out-of-band network
+ resp_req_key = autils.request_network(resp_dut,
+ resp_dut.droid.wifiAwareCreateNetworkSpecifierOob(
+ resp_id, aconsts.DATA_PATH_RESPONDER, init_mac, passphrase))
+ init_req_key = autils.request_network(init_dut,
+ init_dut.droid.wifiAwareCreateNetworkSpecifierOob(
+ init_id, aconsts.DATA_PATH_INITIATOR, resp_mac, passphrase))
+
+ resp_net_event = autils.wait_for_event_with_keys(
+ resp_dut, cconsts.EVENT_NETWORK_CALLBACK,
+ autils.EVENT_NDP_TIMEOUT,
+ (cconsts.NETWORK_CB_KEY_EVENT,
+ cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
+ (cconsts.NETWORK_CB_KEY_ID, resp_req_key))
+ init_net_event = autils.wait_for_event_with_keys(
+ init_dut, cconsts.EVENT_NETWORK_CALLBACK,
+ autils.EVENT_NDP_TIMEOUT,
+ (cconsts.NETWORK_CB_KEY_EVENT,
+ cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
+ (cconsts.NETWORK_CB_KEY_ID, init_req_key))
+
+ if not ib_first:
+ # request in-band network (to completion)
+ p_req_key = self.request_network(
+ p_dut,
+ p_dut.droid.wifiAwareCreateNetworkSpecifier(p_disc_id, None))
+ s_req_key = self.request_network(
+ s_dut,
+ s_dut.droid.wifiAwareCreateNetworkSpecifier(s_disc_id,
+ peer_id_on_sub))
+
+ # Publisher & Subscriber: wait for network formation
+ p_net_event = autils.wait_for_event_with_keys(
+ p_dut, cconsts.EVENT_NETWORK_CALLBACK,
+ autils.EVENT_NDP_TIMEOUT,
+ (cconsts.NETWORK_CB_KEY_EVENT,
+ cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
+ (cconsts.NETWORK_CB_KEY_ID, p_req_key))
+ s_net_event = autils.wait_for_event_with_keys(
+ s_dut, cconsts.EVENT_NETWORK_CALLBACK,
+ autils.EVENT_NDP_TIMEOUT,
+ (cconsts.NETWORK_CB_KEY_EVENT,
+ cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
+ (cconsts.NETWORK_CB_KEY_ID, s_req_key))
+
+ # extract net info
+ pub_interface = p_net_event["data"][cconsts.NETWORK_CB_KEY_INTERFACE_NAME]
+ sub_interface = s_net_event["data"][cconsts.NETWORK_CB_KEY_INTERFACE_NAME]
+ resp_interface = resp_net_event["data"][
+ cconsts.NETWORK_CB_KEY_INTERFACE_NAME]
+ init_interface = init_net_event["data"][
+ cconsts.NETWORK_CB_KEY_INTERFACE_NAME]
+
+ self.log.info(
+ "Interface names: Pub=%s, Sub=%s, Resp=%s, Init=%s", pub_interface,
+ sub_interface, resp_interface, init_interface)
+
+ pub_ipv6 = \
+ p_dut.droid.connectivityGetLinkLocalIpv6Address(pub_interface).split("%")[0]
+ sub_ipv6 = \
+ s_dut.droid.connectivityGetLinkLocalIpv6Address(sub_interface).split("%")[0]
+ resp_ipv6 = \
+ resp_dut.droid.connectivityGetLinkLocalIpv6Address(resp_interface).split(
+ "%")[0]
+ init_ipv6 = \
+ init_dut.droid.connectivityGetLinkLocalIpv6Address(init_interface).split(
+ "%")[0]
+
+ self.log.info(
+ "Interface addresses (IPv6): Pub=%s, Sub=%s, Resp=%s, Init=%s", pub_ipv6,
+ sub_ipv6, resp_ipv6, init_ipv6)
+
+ # validate NDP/NDI conditions (using interface names & ipv6)
+ if same_request:
+ asserts.assert_equal(pub_interface,
+ resp_interface if inits_on_same_dut else init_interface,
+ "NDP interfaces don't match on Pub/other")
+ asserts.assert_equal(sub_interface,
+ init_interface if inits_on_same_dut else resp_interface,
+ "NDP interfaces don't match on Sub/other")
+
+ asserts.assert_equal(pub_ipv6,
+ resp_ipv6 if inits_on_same_dut else init_ipv6,
+ "NDP IPv6 don't match on Pub/other")
+ asserts.assert_equal(sub_ipv6,
+ init_ipv6 if inits_on_same_dut else resp_ipv6,
+ "NDP IPv6 don't match on Sub/other")
+ else:
+ asserts.assert_false(pub_interface == (
+ resp_interface if inits_on_same_dut else init_interface),
+ "NDP interfaces match on Pub/other")
+ asserts.assert_false(sub_interface == (
+ init_interface if inits_on_same_dut else resp_interface),
+ "NDP interfaces match on Sub/other")
+
+ asserts.assert_false(pub_ipv6 ==
+ (resp_ipv6 if inits_on_same_dut else init_ipv6),
+ "NDP IPv6 match on Pub/other")
+ asserts.assert_false(sub_ipv6 ==
+ (init_ipv6 if inits_on_same_dut else resp_ipv6),
+ "NDP IPv6 match on Sub/other")
+
+ # release requests
+ p_dut.droid.connectivityUnregisterNetworkCallback(p_req_key)
+ s_dut.droid.connectivityUnregisterNetworkCallback(s_req_key)
+ resp_dut.droid.connectivityUnregisterNetworkCallback(resp_req_key)
+ init_dut.droid.connectivityUnregisterNetworkCallback(init_req_key)
+
+ @test_tracker_info(uuid="d8a0839d-4ba0-43f2-af93-3cf1382f9f16")
+ def test_identical_ndps_mix_ib_oob_ib_first_same_polarity(self):
+ """Validate that a single NDP is created for multiple identical requests
+ which are issued through either in-band (ib) or out-of-band (oob) APIs.
+
+ The in-band request is issued first. Both Initiators (Sub == Initiator) are
+ run on the same device.
+ """
+ self.run_mix_ib_oob(same_request=True,
+ ib_first=True,
+ inits_on_same_dut=True)
+
+ @test_tracker_info(uuid="70bbb811-0bed-4a19-96b3-f2446e777c8a")
+ def test_identical_ndps_mix_ib_oob_oob_first_same_polarity(self):
+ """Validate that a single NDP is created for multiple identical requests
+ which are issued through either in-band (ib) or out-of-band (oob) APIs.
+
+ The out-of-band request is issued first. Both Initiators (Sub == Initiator)
+ are run on the same device.
+ """
+ self.run_mix_ib_oob(same_request=True,
+ ib_first=False,
+ inits_on_same_dut=True)
+
+ @test_tracker_info(uuid="d9796da5-f96a-4a51-be0f-89d6f5bfe3ad")
+ def test_identical_ndps_mix_ib_oob_ib_first_diff_polarity(self):
+ """Validate that a single NDP is created for multiple identical requests
+ which are issued through either in-band (ib) or out-of-band (oob) APIs.
+
+ The in-band request is issued first. Initiators (Sub == Initiator) are
+ run on different devices.
+ """
+ self.run_mix_ib_oob(same_request=True,
+ ib_first=True,
+ inits_on_same_dut=False)
+
+ @test_tracker_info(uuid="72b16cbf-53ad-4f98-8dcf-a8cc5fa812e3")
+ def test_identical_ndps_mix_ib_oob_oob_first_diff_polarity(self):
+ """Validate that a single NDP is created for multiple identical requests
+ which are issued through either in-band (ib) or out-of-band (oob) APIs.
+
+ The out-of-band request is issued first. Initiators (Sub == Initiator) are
+ run on different devices.
+ """
+ self.run_mix_ib_oob(same_request=True,
+ ib_first=False,
+ inits_on_same_dut=False)
+
+ @test_tracker_info(uuid="51f9581e-c5ee-48a7-84d2-adff4876c3d7")
+ def test_multiple_ndis_mix_ib_oob_ib_first_same_polarity(self):
+ """Validate that multiple NDIs are created for NDPs which are requested with
+ different security configurations. Use a mix of in-band and out-of-band APIs
+ to request the different NDPs.
+
+ The in-band request is issued first. Initiators (Sub == Initiator) are
+ run on the same device.
+ """
+ self.run_mix_ib_oob(same_request=False,
+ ib_first=True,
+ inits_on_same_dut=True)
+
+ @test_tracker_info(uuid="b1e3070e-4d38-4b31-862d-39b82e0f2853")
+ def test_multiple_ndis_mix_ib_oob_oob_first_same_polarity(self):
+ """Validate that multiple NDIs are created for NDPs which are requested with
+ different security configurations. Use a mix of in-band and out-of-band APIs
+ to request the different NDPs.
+
+ The out-of-band request is issued first. Initiators (Sub == Initiator) are
+ run on the same device.
+ """
+ self.run_mix_ib_oob(same_request=False,
+ ib_first=False,
+ inits_on_same_dut=True)
+
+ @test_tracker_info(uuid="b1e3070e-4d38-4b31-862d-39b82e0f2853")
+ def test_multiple_ndis_mix_ib_oob_ib_first_diff_polarity(self):
+ """Validate that multiple NDIs are created for NDPs which are requested with
+ different security configurations. Use a mix of in-band and out-of-band APIs
+ to request the different NDPs.
+
+ The in-band request is issued first. Initiators (Sub == Initiator) are
+ run on different devices.
+ """
+ self.run_mix_ib_oob(same_request=False,
+ ib_first=True,
+ inits_on_same_dut=False)
+
+ @test_tracker_info(uuid="596caadf-028e-494b-bbce-8304ccec2cbb")
+ def test_multiple_ndis_mix_ib_oob_oob_first_diff_polarity(self):
+ """Validate that multiple NDIs are created for NDPs which are requested with
+ different security configurations. Use a mix of in-band and out-of-band APIs
+ to request the different NDPs.
+
+ The out-of-band request is issued first. Initiators (Sub == Initiator) are
+ run on different devices.
+ """
+ self.run_mix_ib_oob(same_request=False,
+ ib_first=False,
+ inits_on_same_dut=False)
+
+ ########################################################################
+
+ def test_ndp_loop(self):
+ """Validate that can create a loop (chain) of N NDPs between N devices,
+ where N >= 3, e.g.
+
+ A - B
+ B - C
+ C - A
+
+ The NDPs are all OPEN (no encryption).
+ """
+ asserts.assert_true(len(self.android_devices) >= 3,
+ 'A minimum of 3 devices is needed to run the test, have %d' %
+ len(self.android_devices))
+
+ duts = self.android_devices
+ loop_len = len(duts)
+ ids = []
+ macs = []
+ reqs = [[], [], []]
+ ifs = [[], [], []]
+ ipv6s = [[], [], []]
+
+ for i in range(loop_len):
+ duts[i].pretty_name = chr(ord("A") + i)
+
+ # start-up 3 devices (attach w/ identity)
+ for i in range(loop_len):
+ ids.append(duts[i].droid.wifiAwareAttach(True))
+ autils.wait_for_event(duts[i], aconsts.EVENT_CB_ON_ATTACHED)
+ ident_event = autils.wait_for_event(duts[i],
+ aconsts.EVENT_CB_ON_IDENTITY_CHANGED)
+ macs.append(ident_event['data']['mac'])
+
+ # wait for for devices to synchronize with each other - there are no other
+ # mechanisms to make sure this happens for OOB discovery (except retrying
+ # to execute the data-path request)
+ time.sleep(autils.WAIT_FOR_CLUSTER)
+
+ # create the N NDPs: i to (i+1) % N
+ for i in range(loop_len):
+ peer_device = (i + 1) % loop_len
+
+ (init_req_key, resp_req_key, init_aware_if,
+ resp_aware_if, init_ipv6, resp_ipv6) = autils.create_oob_ndp_on_sessions(
+ duts[i], duts[peer_device],
+ ids[i], macs[i], ids[peer_device], macs[peer_device])
+
+ reqs[i].append(init_req_key)
+ reqs[peer_device].append(resp_req_key)
+ ifs[i].append(init_aware_if)
+ ifs[peer_device].append(resp_aware_if)
+ ipv6s[i].append(init_ipv6)
+ ipv6s[peer_device].append(resp_ipv6)
+
+ # clean-up
+ for i in range(loop_len):
+ for req in reqs[i]:
+ duts[i].droid.connectivityUnregisterNetworkCallback(req)
+
+ # info
+ self.log.info("MACs: %s", macs)
+ self.log.info("Interface names: %s", ifs)
+ self.log.info("IPv6 addresses: %s", ipv6s)
+ asserts.explicit_pass("NDP loop test",
+ extras={"macs": macs, "ifs": ifs, "ipv6s": ipv6s})
diff --git a/acts/tests/google/wifi/aware/functional/DiscoveryTest.py b/acts/tests/google/wifi/aware/functional/DiscoveryTest.py
index 1784d12..c6f75b0 100644
--- a/acts/tests/google/wifi/aware/functional/DiscoveryTest.py
+++ b/acts/tests/google/wifi/aware/functional/DiscoveryTest.py
@@ -831,7 +831,7 @@
s_mf_1="goodbye there string")
#######################################
- # Multiple concurrent services key
+ # Multiple concurrent services
#######################################
def run_multiple_concurrent_services(self, type_x, type_y):
@@ -957,6 +957,7 @@
event["data"][aconsts.SESSION_CB_KEY_MESSAGE_AS_STRING], y_msg,
"Message on service Y from DUT2 to DUT1 not received correctly")
+ @test_tracker_info(uuid="eef80cf3-1fd2-4526-969b-6af2dce785d7")
def test_multiple_concurrent_services_both_unsolicited_passive(self):
"""Validate multiple concurrent discovery sessions running on both devices.
- DUT1 & DUT2 running Publish for X
@@ -974,6 +975,7 @@
type_x=[aconsts.PUBLISH_TYPE_UNSOLICITED, aconsts.SUBSCRIBE_TYPE_PASSIVE],
type_y=[aconsts.PUBLISH_TYPE_UNSOLICITED, aconsts.SUBSCRIBE_TYPE_PASSIVE])
+ @test_tracker_info(uuid="46739f04-ab2b-4556-b1a4-9aa2774869b5")
def test_multiple_concurrent_services_both_solicited_active(self):
"""Validate multiple concurrent discovery sessions running on both devices.
- DUT1 & DUT2 running Publish for X
@@ -991,6 +993,7 @@
type_x=[aconsts.PUBLISH_TYPE_SOLICITED, aconsts.SUBSCRIBE_TYPE_ACTIVE],
type_y=[aconsts.PUBLISH_TYPE_SOLICITED, aconsts.SUBSCRIBE_TYPE_ACTIVE])
+ @test_tracker_info(uuid="5f8f7fd2-4a0e-4cca-8cbb-6d54353f2baa")
def test_multiple_concurrent_services_mix_unsolicited_solicited(self):
"""Validate multiple concurrent discovery sessions running on both devices.
- DUT1 & DUT2 running Publish for X
@@ -1008,3 +1011,25 @@
self.run_multiple_concurrent_services(
type_x=[aconsts.PUBLISH_TYPE_UNSOLICITED, aconsts.SUBSCRIBE_TYPE_PASSIVE],
type_y=[aconsts.PUBLISH_TYPE_SOLICITED, aconsts.SUBSCRIBE_TYPE_ACTIVE])
+
+ #########################################################
+
+ @test_tracker_info(uuid="908ec896-fc7a-4ee4-b633-a2f042b74448")
+ def test_upper_lower_service_name_equivalence(self):
+ """Validate that Service Name is case-insensitive. Publish a service name
+ with mixed case, subscribe to the same service name with alternative case
+ and verify that discovery happens."""
+ p_dut = self.android_devices[0]
+ s_dut = self.android_devices[1]
+
+ pub_service_name = "GoogleAbCdEf"
+ sub_service_name = "GoogleaBcDeF"
+
+ autils.create_discovery_pair(p_dut, s_dut,
+ p_config=autils.create_discovery_config(
+ pub_service_name,
+ aconsts.PUBLISH_TYPE_UNSOLICITED),
+ s_config=autils.create_discovery_config(
+ sub_service_name,
+ aconsts.SUBSCRIBE_TYPE_PASSIVE),
+ device_startup_offset=self.device_startup_offset)
diff --git a/acts/tests/google/wifi/aware/functional/MacRandomTest.py b/acts/tests/google/wifi/aware/functional/MacRandomTest.py
index 329ead4..af1503b 100644
--- a/acts/tests/google/wifi/aware/functional/MacRandomTest.py
+++ b/acts/tests/google/wifi/aware/functional/MacRandomTest.py
@@ -57,6 +57,10 @@
(NAN data-interface) on each enable/disable cycle"""
dut = self.android_devices[0]
+ # re-enable randomization interval (since if disabled it may also disable
+ # the 'randomize on enable' feature).
+ autils.configure_mac_random_interval(dut, 1800)
+
# DUT: attach and wait for confirmation & identity 10 times
mac_addresses = {}
for i in range(self.NUM_ITERATIONS):
@@ -108,9 +112,8 @@
dut = self.android_devices[0]
- # set randomization interval to 5 seconds
- dut.adb.shell("cmd wifiaware native_api set mac_random_interval_sec %d" %
- RANDOM_INTERVAL)
+ # set randomization interval to 120 seconds
+ autils.configure_mac_random_interval(dut, RANDOM_INTERVAL)
# attach and wait for first identity
id = dut.droid.wifiAwareAttach(True)
diff --git a/acts/tests/google/wifi/aware/performance/LatencyTest.py b/acts/tests/google/wifi/aware/performance/LatencyTest.py
index bde9ff4..bfadebc 100644
--- a/acts/tests/google/wifi/aware/performance/LatencyTest.py
+++ b/acts/tests/google/wifi/aware/performance/LatencyTest.py
@@ -92,8 +92,8 @@
s_dut.pretty_name = "Subscriber"
# override the default DW configuration
- autils.config_dw_all_modes(p_dut, dw_24ghz, dw_5ghz)
- autils.config_dw_all_modes(s_dut, dw_24ghz, dw_5ghz)
+ autils.config_power_settings(p_dut, dw_24ghz, dw_5ghz)
+ autils.config_power_settings(s_dut, dw_24ghz, dw_5ghz)
latencies = []
failed_discoveries = 0
@@ -174,8 +174,8 @@
s_dut.pretty_name = "Subscriber"
# override the default DW configuration
- autils.config_dw_all_modes(p_dut, dw_24ghz, dw_5ghz)
- autils.config_dw_all_modes(s_dut, dw_24ghz, dw_5ghz)
+ autils.config_power_settings(p_dut, dw_24ghz, dw_5ghz)
+ autils.config_power_settings(s_dut, dw_24ghz, dw_5ghz)
# Publisher+Subscriber: attach and wait for confirmation
p_id = p_dut.droid.wifiAwareAttach(False)
@@ -253,8 +253,8 @@
s_dut = self.android_devices[1]
# override the default DW configuration
- autils.config_dw_all_modes(p_dut, dw_24ghz, dw_5ghz)
- autils.config_dw_all_modes(s_dut, dw_24ghz, dw_5ghz)
+ autils.config_power_settings(p_dut, dw_24ghz, dw_5ghz)
+ autils.config_power_settings(s_dut, dw_24ghz, dw_5ghz)
# Start up a discovery session
(p_id, s_id, p_disc_id, s_disc_id,
@@ -341,8 +341,8 @@
resp_dut.pretty_name = 'Responder'
# override the default DW configuration
- autils.config_dw_all_modes(init_dut, dw_24ghz, dw_5ghz)
- autils.config_dw_all_modes(resp_dut, dw_24ghz, dw_5ghz)
+ autils.config_power_settings(init_dut, dw_24ghz, dw_5ghz)
+ autils.config_power_settings(resp_dut, dw_24ghz, dw_5ghz)
# Initiator+Responder: attach and wait for confirmation & identity
init_id = init_dut.droid.wifiAwareAttach(True)
@@ -427,6 +427,209 @@
dw_5ghz))
results[key_avail]["ndp_setup_failures"] = ndp_setup_failures
+ def run_end_to_end_latency(self, results, dw_24ghz, dw_5ghz, num_iterations,
+ startup_offset, include_setup):
+ """Measure the latency for end-to-end communication link setup:
+ - Start Aware
+ - Discovery
+ - Message from Sub -> Pub
+ - Message from Pub -> Sub
+ - NDP setup
+
+ Args:
+ results: Result array to be populated - will add results (not erase it)
+ dw_24ghz: DW interval in the 2.4GHz band.
+ dw_5ghz: DW interval in the 5GHz band.
+ startup_offset: The start-up gap (in seconds) between the two devices
+ include_setup: True to include the cluster setup in the latency
+ measurements.
+ """
+ key = "dw24_%d_dw5_%d" % (dw_24ghz, dw_5ghz)
+ results[key] = {}
+ results[key]["num_iterations"] = num_iterations
+
+ p_dut = self.android_devices[0]
+ p_dut.pretty_name = "Publisher"
+ s_dut = self.android_devices[1]
+ s_dut.pretty_name = "Subscriber"
+
+ # override the default DW configuration
+ autils.config_power_settings(p_dut, dw_24ghz, dw_5ghz)
+ autils.config_power_settings(s_dut, dw_24ghz, dw_5ghz)
+
+ latencies = []
+
+ # allow for failures here since running lots of samples and would like to
+ # get the partial data even in the presence of errors
+ failures = 0
+
+ if not include_setup:
+ # Publisher+Subscriber: attach and wait for confirmation
+ p_id = p_dut.droid.wifiAwareAttach(False)
+ autils.wait_for_event(p_dut, aconsts.EVENT_CB_ON_ATTACHED)
+ time.sleep(startup_offset)
+ s_id = s_dut.droid.wifiAwareAttach(False)
+ autils.wait_for_event(s_dut, aconsts.EVENT_CB_ON_ATTACHED)
+
+ for i in range(num_iterations):
+ while (True): # for pseudo-goto/finalize
+ timestamp_start = time.perf_counter()
+
+ if include_setup:
+ # Publisher+Subscriber: attach and wait for confirmation
+ p_id = p_dut.droid.wifiAwareAttach(False)
+ autils.wait_for_event(p_dut, aconsts.EVENT_CB_ON_ATTACHED)
+ time.sleep(startup_offset)
+ s_id = s_dut.droid.wifiAwareAttach(False)
+ autils.wait_for_event(s_dut, aconsts.EVENT_CB_ON_ATTACHED)
+
+ # start publish
+ p_disc_id, p_disc_event = self.start_discovery_session(
+ p_dut, p_id, True, aconsts.PUBLISH_TYPE_UNSOLICITED)
+
+ # start subscribe
+ s_disc_id, s_session_event = self.start_discovery_session(
+ s_dut, s_id, False, aconsts.SUBSCRIBE_TYPE_PASSIVE)
+
+ # wait for discovery (allow for failures here since running lots of
+ # samples and would like to get the partial data even in the presence of
+ # errors)
+ try:
+ event = s_dut.ed.pop_event(aconsts.SESSION_CB_ON_SERVICE_DISCOVERED,
+ autils.EVENT_TIMEOUT)
+ s_dut.log.info("[Subscriber] SESSION_CB_ON_SERVICE_DISCOVERED: %s",
+ event["data"])
+ peer_id_on_sub = event['data'][aconsts.SESSION_CB_KEY_PEER_ID]
+ except queue.Empty:
+ s_dut.log.info("[Subscriber] Timed out while waiting for "
+ "SESSION_CB_ON_SERVICE_DISCOVERED")
+ failures = failures + 1
+ break
+
+ # message from Sub -> Pub
+ msg_s2p = "Message Subscriber -> Publisher #%d" % i
+ next_msg_id = self.get_next_msg_id()
+ s_dut.droid.wifiAwareSendMessage(s_disc_id, peer_id_on_sub, next_msg_id,
+ msg_s2p, 0)
+
+ # wait for Tx confirmation
+ try:
+ s_dut.ed.pop_event(aconsts.SESSION_CB_ON_MESSAGE_SENT,
+ autils.EVENT_TIMEOUT)
+ except queue.Empty:
+ s_dut.log.info("[Subscriber] Timed out while waiting for "
+ "SESSION_CB_ON_MESSAGE_SENT")
+ failures = failures + 1
+ break
+
+ # wait for Rx confirmation (and validate contents)
+ try:
+ event = p_dut.ed.pop_event(aconsts.SESSION_CB_ON_MESSAGE_RECEIVED,
+ autils.EVENT_TIMEOUT)
+ peer_id_on_pub = event['data'][aconsts.SESSION_CB_KEY_PEER_ID]
+ if (event["data"][
+ aconsts.SESSION_CB_KEY_MESSAGE_AS_STRING] != msg_s2p):
+ p_dut.log.info("[Publisher] Corrupted input message - %s", event)
+ failures = failures + 1
+ break
+ except queue.Empty:
+ p_dut.log.info("[Publisher] Timed out while waiting for "
+ "SESSION_CB_ON_MESSAGE_RECEIVED")
+ failures = failures + 1
+ break
+
+ # message from Pub -> Sub
+ msg_p2s = "Message Publisher -> Subscriber #%d" % i
+ next_msg_id = self.get_next_msg_id()
+ p_dut.droid.wifiAwareSendMessage(p_disc_id, peer_id_on_pub, next_msg_id,
+ msg_p2s, 0)
+
+ # wait for Tx confirmation
+ try:
+ p_dut.ed.pop_event(aconsts.SESSION_CB_ON_MESSAGE_SENT,
+ autils.EVENT_TIMEOUT)
+ except queue.Empty:
+ p_dut.log.info("[Publisher] Timed out while waiting for "
+ "SESSION_CB_ON_MESSAGE_SENT")
+ failures = failures + 1
+ break
+
+ # wait for Rx confirmation (and validate contents)
+ try:
+ event = s_dut.ed.pop_event(aconsts.SESSION_CB_ON_MESSAGE_RECEIVED,
+ autils.EVENT_TIMEOUT)
+ if (event["data"][
+ aconsts.SESSION_CB_KEY_MESSAGE_AS_STRING] != msg_p2s):
+ s_dut.log.info("[Subscriber] Corrupted input message - %s", event)
+ failures = failures + 1
+ break
+ except queue.Empty:
+ s_dut.log.info("[Subscriber] Timed out while waiting for "
+ "SESSION_CB_ON_MESSAGE_RECEIVED")
+ failures = failures + 1
+ break
+
+ # create NDP
+
+ # Publisher: request network
+ p_req_key = autils.request_network(
+ p_dut,
+ p_dut.droid.wifiAwareCreateNetworkSpecifier(p_disc_id,
+ peer_id_on_pub, None))
+
+ # Subscriber: request network
+ s_req_key = autils.request_network(
+ s_dut,
+ s_dut.droid.wifiAwareCreateNetworkSpecifier(s_disc_id,
+ peer_id_on_sub, None))
+
+ # Publisher & Subscriber: wait for network formation
+ try:
+ p_net_event = autils.wait_for_event_with_keys(
+ p_dut, cconsts.EVENT_NETWORK_CALLBACK, autils.EVENT_TIMEOUT, (
+ cconsts.NETWORK_CB_KEY_EVENT,
+ cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
+ (cconsts.NETWORK_CB_KEY_ID, p_req_key))
+ s_net_event = autils.wait_for_event_with_keys(
+ s_dut, cconsts.EVENT_NETWORK_CALLBACK, autils.EVENT_TIMEOUT, (
+ cconsts.NETWORK_CB_KEY_EVENT,
+ cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
+ (cconsts.NETWORK_CB_KEY_ID, s_req_key))
+ except:
+ failures = failures + 1
+ break
+
+ p_aware_if = p_net_event["data"][cconsts.NETWORK_CB_KEY_INTERFACE_NAME]
+ s_aware_if = s_net_event["data"][cconsts.NETWORK_CB_KEY_INTERFACE_NAME]
+
+ p_ipv6 = \
+ p_dut.droid.connectivityGetLinkLocalIpv6Address(p_aware_if).split("%")[
+ 0]
+ s_ipv6 = \
+ s_dut.droid.connectivityGetLinkLocalIpv6Address(s_aware_if).split("%")[
+ 0]
+
+ p_dut.log.info("[Publisher] IF=%s, IPv6=%s", p_aware_if, p_ipv6)
+ s_dut.log.info("[Subscriber] IF=%s, IPv6=%s", s_aware_if, s_ipv6)
+
+ latencies.append(time.perf_counter() - timestamp_start)
+ break
+
+ # destroy sessions
+ p_dut.droid.wifiAwareDestroyDiscoverySession(p_disc_id)
+ s_dut.droid.wifiAwareDestroyDiscoverySession(s_disc_id)
+ if include_setup:
+ p_dut.droid.wifiAwareDestroy(p_id)
+ s_dut.droid.wifiAwareDestroy(s_id)
+
+ autils.extract_stats(
+ p_dut,
+ data=latencies,
+ results=results[key],
+ key_prefix="",
+ log_prefix="End-to-End(dw24=%d, dw5=%d)" % (dw_24ghz, dw_5ghz))
+ results[key]["failures"] = failures
+
########################################################################
@@ -438,8 +641,8 @@
self.run_synchronization_latency(
results=results,
do_unsolicited_passive=True,
- dw_24ghz=aconsts.DW_24_INTERACTIVE,
- dw_5ghz=aconsts.DW_5_INTERACTIVE,
+ dw_24ghz=aconsts.POWER_DW_24_INTERACTIVE,
+ dw_5ghz=aconsts.POWER_DW_5_INTERACTIVE,
num_iterations=10,
startup_offset=startup_offset,
timeout_period=20)
@@ -454,8 +657,8 @@
self.run_synchronization_latency(
results=results,
do_unsolicited_passive=True,
- dw_24ghz=aconsts.DW_24_NON_INTERACTIVE,
- dw_5ghz=aconsts.DW_5_NON_INTERACTIVE,
+ dw_24ghz=aconsts.POWER_DW_24_NON_INTERACTIVE,
+ dw_5ghz=aconsts.POWER_DW_5_NON_INTERACTIVE,
num_iterations=10,
startup_offset=startup_offset,
timeout_period=20)
@@ -469,8 +672,8 @@
self.run_discovery_latency(
results=results,
do_unsolicited_passive=True,
- dw_24ghz=aconsts.DW_24_INTERACTIVE,
- dw_5ghz=aconsts.DW_5_INTERACTIVE,
+ dw_24ghz=aconsts.POWER_DW_24_INTERACTIVE,
+ dw_5ghz=aconsts.POWER_DW_5_INTERACTIVE,
num_iterations=100)
asserts.explicit_pass(
"test_discovery_latency_default_parameters finished", extras=results)
@@ -482,8 +685,8 @@
self.run_discovery_latency(
results=results,
do_unsolicited_passive=True,
- dw_24ghz=aconsts.DW_24_NON_INTERACTIVE,
- dw_5ghz=aconsts.DW_5_NON_INTERACTIVE,
+ dw_24ghz=aconsts.POWER_DW_24_NON_INTERACTIVE,
+ dw_5ghz=aconsts.POWER_DW_5_NON_INTERACTIVE,
num_iterations=100)
asserts.explicit_pass(
"test_discovery_latency_non_interactive_dws finished", extras=results)
@@ -510,8 +713,8 @@
results = {}
self.run_message_latency(
results=results,
- dw_24ghz=aconsts.DW_24_INTERACTIVE,
- dw_5ghz=aconsts.DW_5_INTERACTIVE,
+ dw_24ghz=aconsts.POWER_DW_24_INTERACTIVE,
+ dw_5ghz=aconsts.POWER_DW_5_INTERACTIVE,
num_iterations=100)
asserts.explicit_pass(
"test_message_latency_default_dws finished", extras=results)
@@ -524,8 +727,8 @@
results = {}
self.run_message_latency(
results=results,
- dw_24ghz=aconsts.DW_24_NON_INTERACTIVE,
- dw_5ghz=aconsts.DW_5_NON_INTERACTIVE,
+ dw_24ghz=aconsts.POWER_DW_24_NON_INTERACTIVE,
+ dw_5ghz=aconsts.POWER_DW_5_NON_INTERACTIVE,
num_iterations=100)
asserts.explicit_pass(
"test_message_latency_non_interactive_dws finished", extras=results)
@@ -536,8 +739,8 @@
results = {}
self.run_ndp_oob_latency(
results=results,
- dw_24ghz=aconsts.DW_24_INTERACTIVE,
- dw_5ghz=aconsts.DW_5_INTERACTIVE,
+ dw_24ghz=aconsts.POWER_DW_24_INTERACTIVE,
+ dw_5ghz=aconsts.POWER_DW_5_INTERACTIVE,
num_iterations=100)
asserts.explicit_pass(
"test_ndp_setup_latency_default_dws finished", extras=results)
@@ -549,8 +752,49 @@
results = {}
self.run_ndp_oob_latency(
results=results,
- dw_24ghz=aconsts.DW_24_NON_INTERACTIVE,
- dw_5ghz=aconsts.DW_5_NON_INTERACTIVE,
+ dw_24ghz=aconsts.POWER_DW_24_NON_INTERACTIVE,
+ dw_5ghz=aconsts.POWER_DW_5_NON_INTERACTIVE,
num_iterations=100)
asserts.explicit_pass(
"test_ndp_setup_latency_non_interactive_dws finished", extras=results)
+
+ def test_end_to_end_latency_default_dws(self):
+ """Measure the latency for end-to-end communication link setup:
+ - Start Aware
+ - Discovery
+ - Message from Sub -> Pub
+ - Message from Pub -> Sub
+ - NDP setup
+ """
+ results = {}
+ self.run_end_to_end_latency(
+ results,
+ dw_24ghz=aconsts.POWER_DW_24_INTERACTIVE,
+ dw_5ghz=aconsts.POWER_DW_5_INTERACTIVE,
+ num_iterations=10,
+ startup_offset=0,
+ include_setup=True)
+ asserts.explicit_pass(
+ "test_end_to_end_latency_default_dws finished", extras=results)
+
+ def test_end_to_end_latency_post_attach_default_dws(self):
+ """Measure the latency for end-to-end communication link setup without
+ the initial synchronization:
+ - Start Aware & synchronize initially
+ - Loop:
+ - Discovery
+ - Message from Sub -> Pub
+ - Message from Pub -> Sub
+ - NDP setup
+ """
+ results = {}
+ self.run_end_to_end_latency(
+ results,
+ dw_24ghz=aconsts.POWER_DW_24_INTERACTIVE,
+ dw_5ghz=aconsts.POWER_DW_5_INTERACTIVE,
+ num_iterations=10,
+ startup_offset=0,
+ include_setup=False)
+ asserts.explicit_pass(
+ "test_end_to_end_latency_post_attach_default_dws finished",
+ extras=results)
diff --git a/acts/tests/google/wifi/aware/performance/ThroughputTest.py b/acts/tests/google/wifi/aware/performance/ThroughputTest.py
index 6cf1046..ddb6d15 100644
--- a/acts/tests/google/wifi/aware/performance/ThroughputTest.py
+++ b/acts/tests/google/wifi/aware/performance/ThroughputTest.py
@@ -36,7 +36,7 @@
PASSPHRASE2 = "This is some random passphrase - very very secure - but diff!!"
def __init__(self, controllers):
- AwareBaseTest.__init__(self, controllers)
+ super(ThroughputTest, self).__init__(controllers)
def request_network(self, dut, ns):
"""Request a Wi-Fi Aware network.
@@ -302,12 +302,12 @@
# Wait for network
init_net_event = autils.wait_for_event_with_keys(
- init_dut, cconsts.EVENT_NETWORK_CALLBACK, autils.EVENT_TIMEOUT,
+ init_dut, cconsts.EVENT_NETWORK_CALLBACK, autils.EVENT_NDP_TIMEOUT,
(cconsts.NETWORK_CB_KEY_EVENT,
cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
(cconsts.NETWORK_CB_KEY_ID, init_req_key))
resp_net_event = autils.wait_for_event_with_keys(
- resp_dut, cconsts.EVENT_NETWORK_CALLBACK, autils.EVENT_TIMEOUT,
+ resp_dut, cconsts.EVENT_NETWORK_CALLBACK, autils.EVENT_NDP_TIMEOUT,
(cconsts.NETWORK_CB_KEY_EVENT,
cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
(cconsts.NETWORK_CB_KEY_ID, resp_req_key))
diff --git a/acts/tests/google/wifi/aware/stress/DataPathStressTest.py b/acts/tests/google/wifi/aware/stress/DataPathStressTest.py
index 9a862cb..f718007 100644
--- a/acts/tests/google/wifi/aware/stress/DataPathStressTest.py
+++ b/acts/tests/google/wifi/aware/stress/DataPathStressTest.py
@@ -18,6 +18,7 @@
import time
from acts import asserts
+from acts.test_decorators import test_tracker_info
from acts.test_utils.net import connectivity_const as cconsts
from acts.test_utils.wifi.aware import aware_const as aconsts
from acts.test_utils.wifi.aware import aware_test_utils as autils
@@ -30,16 +31,29 @@
ATTACH_ITERATIONS = 2
# Number of iterations on create/destroy NDP in each discovery session.
- NDP_ITERATIONS = 20
+ NDP_ITERATIONS = 50
+
+ # Maximum percentage of NDP setup failures over all iterations
+ MAX_FAILURE_PERCENTAGE = 1
def __init__(self, controllers):
AwareBaseTest.__init__(self, controllers)
################################################################
- def test_oob_ndp_stress(self):
+ def run_oob_ndp_stress(self, attach_iterations, ndp_iterations,
+ trigger_failure_on_index=None):
"""Run NDP (NAN data-path) stress test creating and destroying Aware
- attach sessions, discovery sessions, and NDPs."""
+ attach sessions, discovery sessions, and NDPs.
+
+ Args:
+ attach_iterations: Number of attach sessions.
+ ndp_iterations: Number of NDP to be attempted per attach session.
+ trigger_failure_on_index: Trigger a failure on this NDP iteration (the
+ mechanism is to request NDP on Initiator
+ before issuing the requeest on the Responder).
+ If None then no artificial failure triggered.
+ """
init_dut = self.android_devices[0]
init_dut.pretty_name = 'Initiator'
resp_dut = self.android_devices[1]
@@ -50,7 +64,7 @@
ndp_resp_setup_success = 0
ndp_resp_setup_failures = 0
- for attach_iter in range(self.ATTACH_ITERATIONS):
+ for attach_iter in range(attach_iterations):
init_id = init_dut.droid.wifiAwareAttach(True)
autils.wait_for_event(init_dut, aconsts.EVENT_CB_ON_ATTACHED)
init_ident_event = autils.wait_for_event(
@@ -68,18 +82,41 @@
# to execute the data-path request)
time.sleep(autils.WAIT_FOR_CLUSTER)
- for ndp_iteration in range(self.NDP_ITERATIONS):
- # Responder: request network
- resp_req_key = autils.request_network(
- resp_dut,
- resp_dut.droid.wifiAwareCreateNetworkSpecifierOob(
- resp_id, aconsts.DATA_PATH_RESPONDER, init_mac, None))
+ for ndp_iteration in range(ndp_iterations):
+ if trigger_failure_on_index != ndp_iteration:
+ # Responder: request network
+ resp_req_key = autils.request_network(
+ resp_dut,
+ resp_dut.droid.wifiAwareCreateNetworkSpecifierOob(
+ resp_id, aconsts.DATA_PATH_RESPONDER, init_mac, None))
- # Initiator: request network
- init_req_key = autils.request_network(
- init_dut,
- init_dut.droid.wifiAwareCreateNetworkSpecifierOob(
- init_id, aconsts.DATA_PATH_INITIATOR, resp_mac, None))
+ # Wait a minimal amount of time to let the Responder configure itself
+ # and be ready for the request. While calling it first may be
+ # sufficient there are no guarantees that a glitch may slow the
+ # Responder slightly enough to invert the setup order.
+ time.sleep(1)
+
+ # Initiator: request network
+ init_req_key = autils.request_network(
+ init_dut,
+ init_dut.droid.wifiAwareCreateNetworkSpecifierOob(
+ init_id, aconsts.DATA_PATH_INITIATOR, resp_mac, None))
+ else:
+ # Initiator: request network
+ init_req_key = autils.request_network(
+ init_dut,
+ init_dut.droid.wifiAwareCreateNetworkSpecifierOob(
+ init_id, aconsts.DATA_PATH_INITIATOR, resp_mac, None))
+
+ # Wait a minimal amount of time to let the Initiator configure itself
+ # to guarantee failure!
+ time.sleep(2)
+
+ # Responder: request network
+ resp_req_key = autils.request_network(
+ resp_dut,
+ resp_dut.droid.wifiAwareCreateNetworkSpecifierOob(
+ resp_id, aconsts.DATA_PATH_RESPONDER, init_mac, None))
# Initiator: wait for network formation
got_on_available = False
@@ -138,9 +175,31 @@
results['ndp_init_setup_failures'] = ndp_init_setup_failures
results['ndp_resp_setup_success'] = ndp_resp_setup_success
results['ndp_resp_setup_failures'] = ndp_resp_setup_failures
- asserts.assert_equal(
- ndp_init_setup_failures + ndp_resp_setup_failures,
- 0,
- 'test_oob_ndp_stress finished',
- extras=results)
- asserts.explicit_pass("test_oob_ndp_stress done", extras=results)
+ max_failures = (
+ self.MAX_FAILURE_PERCENTAGE * attach_iterations * ndp_iterations / 100)
+ if max_failures == 0:
+ max_failures = 1
+ if trigger_failure_on_index is not None:
+ max_failures = max_failures + 1 # for the triggered failure
+ asserts.assert_true(
+ (ndp_init_setup_failures + ndp_resp_setup_failures) < (2 * max_failures),
+ 'NDP setup failure rate exceeds threshold', extras=results)
+ asserts.explicit_pass("test_oob_ndp_stress* done", extras=results)
+
+ @test_tracker_info(uuid="a20a96ba-e71f-4d31-b850-b88a75381981")
+ def test_oob_ndp_stress(self):
+ """Run NDP (NAN data-path) stress test creating and destroying Aware
+ attach sessions, discovery sessions, and NDPs."""
+ self.run_oob_ndp_stress(self.ATTACH_ITERATIONS, self.NDP_ITERATIONS)
+
+ @test_tracker_info(uuid="1fb4a383-bf1a-411a-a904-489dd9e29c6a")
+ def test_oob_ndp_stress_failure_case(self):
+ """Run NDP (NAN data-path) stress test creating and destroying Aware
+ attach sessions, discovery sessions, and NDPs.
+
+ Verify recovery from failure by triggering an artifical failure and
+ verifying that all subsequent iterations succeed.
+ """
+ self.run_oob_ndp_stress(attach_iterations=1,
+ ndp_iterations=10,
+ trigger_failure_on_index=3)
diff --git a/acts/tests/google/wifi/aware/stress/DiscoveryStressTest.py b/acts/tests/google/wifi/aware/stress/DiscoveryStressTest.py
index 8b3d925..eaa5d19 100644
--- a/acts/tests/google/wifi/aware/stress/DiscoveryStressTest.py
+++ b/acts/tests/google/wifi/aware/stress/DiscoveryStressTest.py
@@ -15,9 +15,9 @@
# limitations under the License.
import queue
-import time
from acts import asserts
+from acts.test_decorators import test_tracker_info
from acts.test_utils.wifi.aware import aware_const as aconsts
from acts.test_utils.wifi.aware import aware_test_utils as autils
from acts.test_utils.wifi.aware.AwareBaseTest import AwareBaseTest
@@ -37,6 +37,7 @@
####################################################################
+ @test_tracker_info(uuid="783791e5-7726-44e0-ac5b-98c1dbf493cb")
def test_discovery_stress(self):
"""Create and destroy a random array of discovery sessions, up to the
limit of capabilities."""
@@ -101,9 +102,6 @@
results = {}
results['discovery_setup_success'] = discovery_setup_success
results['discovery_setup_fail'] = discovery_setup_fail
- asserts.assert_equal(
- discovery_setup_fail,
- 0,
- 'test_discovery_stress finished',
- extras=results)
+ asserts.assert_equal(discovery_setup_fail, 0,
+ 'Discovery setup failures', extras=results)
asserts.explicit_pass('test_discovery_stress done', extras=results)
diff --git a/acts/tests/google/wifi/aware/stress/MessagesStressTest.py b/acts/tests/google/wifi/aware/stress/MessagesStressTest.py
index 5871d61..34827f1 100644
--- a/acts/tests/google/wifi/aware/stress/MessagesStressTest.py
+++ b/acts/tests/google/wifi/aware/stress/MessagesStressTest.py
@@ -17,6 +17,7 @@
import queue
from acts import asserts
+from acts.test_decorators import test_tracker_info
from acts.test_utils.wifi.aware import aware_const as aconsts
from acts.test_utils.wifi.aware import aware_test_utils as autils
from acts.test_utils.wifi.aware.AwareBaseTest import AwareBaseTest
@@ -29,7 +30,19 @@
class MessagesStressTest(AwareBaseTest):
"""Set of stress tests for Wi-Fi Aware L2 (layer 2) message exchanges."""
+
+ # Number of iterations in the stress test (number of messages)
NUM_ITERATIONS = 100
+
+ # Maximum permitted percentage of messages which fail to be transmitted
+ # correctly
+ MAX_TX_FAILURE_PERCENTAGE = 2
+
+ # Maximum permitted percentage of messages which are received more than once
+ # (indicating, most likely, that the ACK wasn't received and the message was
+ # retransmitted)
+ MAX_DUPLICATE_RX_PERCENTAGE = 2
+
SERVICE_NAME = "GoogleTestServiceXY"
def __init__(self, controllers):
@@ -184,6 +197,7 @@
#######################################################################
+ @test_tracker_info(uuid="e88c060f-4ca7-41c1-935a-d3d62878ec0b")
def test_stress_message(self):
"""Stress test for bi-directional message transmission and reception."""
p_dut = self.android_devices[0]
@@ -250,6 +264,9 @@
# clear errors
asserts.assert_equal(results["tx_unknown_ids"], 0, "Message ID corruption",
results)
+ asserts.assert_equal(results["tx_count_neither"], 0,
+ "Tx message with no success or fail indication",
+ results)
asserts.assert_equal(results["tx_count_duplicate_fail"], 0,
"Duplicate Tx fail messages", results)
asserts.assert_equal(results["tx_count_duplicate_success"], 0,
@@ -266,4 +283,14 @@
asserts.assert_equal(results["rx_count_fail_tx_indication"], 0,
"Message received but Tx didn't get ACK", results)
- asserts.explicit_pass("test_stress_message done", extras=results)
+ # permissible failures based on thresholds
+ asserts.assert_true(results["tx_count_fail"] <= (
+ self.MAX_TX_FAILURE_PERCENTAGE * self.NUM_ITERATIONS / 100),
+ "Number of Tx failures exceeds threshold",
+ extras=results)
+ asserts.assert_true(results["rx_count_duplicate"] <= (
+ self.MAX_DUPLICATE_RX_PERCENTAGE * self.NUM_ITERATIONS / 100),
+ "Number of duplicate Rx exceeds threshold",
+ extras=results)
+
+ asserts.explicit_pass("test_stress_message done", extras=results)
\ No newline at end of file
diff --git a/acts/tests/google/wifi/example_config.json b/acts/tests/google/wifi/example_config.json
new file mode 100644
index 0000000..42b0be7
--- /dev/null
+++ b/acts/tests/google/wifi/example_config.json
@@ -0,0 +1,38 @@
+{
+ "_description": "This and example IOT WiFi testbed.",
+ "testbed": [
+ {
+ "_description": "WiFi testbed with 1 devices",
+ "name": "<test station name>",
+ "AndroidDevice": [
+ "<device serial>"
+ ],
+ "IPerfServer": [
+ 5005
+ ]
+ }
+ ],
+ "logpath": "/tmp/ACTS_logs",
+ "testpaths": [
+ "<path to acts root>/tools/test/connectivity/acts/tests/google/wifi"
+ ],
+ "iot_networks": [
+ {
+ "SSID": "<your SSID 2G>",
+ "password": "<your password>"
+ },
+ {
+ "SSID": "<your SSID 5G>",
+ "password": "<your password>"
+ },
+ {
+ "SSID": "<your SSID 2G 2>",
+ "password": "<your password>"
+ },
+ {
+ "SSID": "<your SSID 5G 2>",
+ "password": "<your password>"
+ }
+ ],
+ "iperf_server_address": "<your IP address>"
+}
\ No newline at end of file
diff --git a/acts/tests/google/wifi/rtt/README.md b/acts/tests/google/wifi/rtt/README.md
new file mode 100644
index 0000000..639c3d8
--- /dev/null
+++ b/acts/tests/google/wifi/rtt/README.md
@@ -0,0 +1,56 @@
+# Wi-Fi RTT (IEEE 802.11mc) Integrated (ACTS/sl4a) Test Suite
+
+This directory contains ACTS/sl4a test scripts to verify and characterize
+the Wi-Fi RTT (IEEE 802.11mc) implementation in Android.
+
+There are 2 groups of tests (in 2 sub-directories):
+
+* functional: Functional tests that each implementation must pass. These
+are pass/fail tests.
+* stress: Tests which run through a large number of iterations to stress
+test the implementation. Considering that some failures are expected,
+especially in an over-the-air situation, pass/fail criteria are either
+not provided or may not apply to all implementations or test environments.
+
+The tests can be executed using:
+
+`act.py -c <config> -tc {<test_class>|<test_class>:<test_name>}`
+
+Where a test file is any of the `.py` files in any of the test sub-directories.
+If a test class is specified, then all tests within that test class are executed.
+
+## Test Beds
+The Wi-Fi RTT tests support several different test scenarios which require different test bed
+configuration. The test beds and their corresponding test files are:
+
+* Device Under Test + AP which supports IEEE 802.11mc
+ * functional/RangeApSupporting11McTest.py
+ * functional/RttRequestManagementTest.py
+ * functional/RttDisableTest.py
+ * stress/StressRangeApTest.py
+* Device Under Test + AP which does **not** support IEEE 802.11mc
+ * functional/RangeApNonSupporting11McTest.py
+* 2 Devices Under Test
+ * functional/RangeAwareTest.py
+ * functional/AwareDiscoveryWithRangingTest.py
+ * functional/RangeSoftApTest.py
+ * stress/StressRangeAwareTest.py
+
+## Test Configurations
+The test configuration, the `<config>` in the commands above, is stored in
+the *config* sub-directory. The configuration simply uses all connected
+devices without listing specific serial numbers. Note that some tests use a
+single device while others use 2 devices.
+
+The only provided configuration is *wifi_rtt.json*.
+
+The configuration defines the following keys to configure the test:
+
+* **lci_reference**, **lcr_reference**: Arrays of bytes used to validate that the *correct* LCI and
+LCR were received from the AP. These are empty by default and should be configured to match the
+configuration of the AP used in the test.
+* **rtt_reference_distance_mm**: The reference distance, in mm, between the test device and the test
+AP or between the two test devices (for Aware ranging tests).
+* **stress_test_min_iteration_count**, **stress_test_target_run_time_sec**: Parameters used to
+control the length and duration of the stress tests. The stress test runs for the specified number
+of iterations or for the specified duration - whichever is longer.
diff --git a/acts/tests/google/wifi/rtt/config/wifi_rtt.json b/acts/tests/google/wifi/rtt/config/wifi_rtt.json
new file mode 100644
index 0000000..41f77dc
--- /dev/null
+++ b/acts/tests/google/wifi/rtt/config/wifi_rtt.json
@@ -0,0 +1,20 @@
+{
+ "_description": "This is a test configuration file for Wi-Fi RTT tests.",
+ "testbed":
+ [
+ {
+ "_description": "Wi-Fi RTT testbed: auto-detect all attached devices",
+ "name": "WifiRttAllAttached",
+ "AndroidDevice": "*"
+ }
+ ],
+ "logpath": "~/logs",
+ "testpaths": ["./tools/test/connectivity/acts/tests/google/wifi"],
+ "adb_logcat_param": "-b all",
+ "aware_default_power_mode": "INTERACTIVE",
+ "lci_reference": [],
+ "lcr_reference": [],
+ "rtt_reference_distance_mm": 100,
+ "stress_test_min_iteration_count": 100,
+ "stress_test_target_run_time_sec" : 30
+}
diff --git a/acts/tests/google/wifi/rtt/functional/AwareDiscoveryWithRangingTest.py b/acts/tests/google/wifi/rtt/functional/AwareDiscoveryWithRangingTest.py
new file mode 100644
index 0000000..f6d7c8d
--- /dev/null
+++ b/acts/tests/google/wifi/rtt/functional/AwareDiscoveryWithRangingTest.py
@@ -0,0 +1,1567 @@
+#!/usr/bin/python3.4
+#
+# Copyright 2017 - The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import sys
+import time
+
+from acts import asserts
+from acts.test_decorators import test_tracker_info
+from acts.test_utils.net import connectivity_const as cconsts
+from acts.test_utils.wifi.aware import aware_const as aconsts
+from acts.test_utils.wifi.aware import aware_test_utils as autils
+from acts.test_utils.wifi.aware.AwareBaseTest import AwareBaseTest
+from acts.test_utils.wifi.rtt import rtt_const as rconsts
+from acts.test_utils.wifi.rtt import rtt_test_utils as rutils
+from acts.test_utils.wifi.rtt.RttBaseTest import RttBaseTest
+
+
+class AwareDiscoveryWithRangingTest(AwareBaseTest, RttBaseTest):
+ """Set of tests for Wi-Fi Aware discovery configured with ranging (RTT)."""
+
+ SERVICE_NAME = "GoogleTestServiceRRRRR"
+
+ # Flag indicating whether the device has a limitation that does not allow it
+ # to execute Aware-based Ranging (whether direct or as part of discovery)
+ # whenever NDP is enabled.
+ RANGING_NDP_CONCURRENCY_LIMITATION = True
+
+ # Flag indicating whether the device has a limitation that does not allow it
+ # to execute Aware-based Ranging (whether direct or as part of discovery)
+ # for both Initiators and Responders. Only the first mode works.
+ RANGING_INITIATOR_RESPONDER_CONCURRENCY_LIMITATION = True
+
+ def __init__(self, controllers):
+ AwareBaseTest.__init__(self, controllers)
+ RttBaseTest.__init__(self, controllers)
+
+ def setup_test(self):
+ """Manual setup here due to multiple inheritance: explicitly execute the
+ setup method from both parents."""
+ AwareBaseTest.setup_test(self)
+ RttBaseTest.setup_test(self)
+
+ def teardown_test(self):
+ """Manual teardown here due to multiple inheritance: explicitly execute the
+ teardown method from both parents."""
+ AwareBaseTest.teardown_test(self)
+ RttBaseTest.teardown_test(self)
+
+ #########################################################################
+
+ def run_discovery(self, p_config, s_config, expect_discovery,
+ expect_range=False):
+ """Run discovery on the 2 input devices with the specified configurations.
+
+ Args:
+ p_config, s_config: Publisher and Subscriber discovery configuration.
+ expect_discovery: True or False indicating whether discovery is expected
+ with the specified configurations.
+ expect_range: True if we expect distance results (i.e. ranging to happen).
+ Only relevant if expect_discovery is True.
+ Returns:
+ p_dut, s_dut: Publisher/Subscribe DUT
+ p_disc_id, s_disc_id: Publisher/Subscribe discovery session ID
+ """
+ p_dut = self.android_devices[0]
+ p_dut.pretty_name = "Publisher"
+ s_dut = self.android_devices[1]
+ s_dut.pretty_name = "Subscriber"
+
+ # Publisher+Subscriber: attach and wait for confirmation
+ p_id = p_dut.droid.wifiAwareAttach(False)
+ autils.wait_for_event(p_dut, aconsts.EVENT_CB_ON_ATTACHED)
+ time.sleep(self.device_startup_offset)
+ s_id = s_dut.droid.wifiAwareAttach(False)
+ autils.wait_for_event(s_dut, aconsts.EVENT_CB_ON_ATTACHED)
+
+ # Publisher: start publish and wait for confirmation
+ p_disc_id = p_dut.droid.wifiAwarePublish(p_id, p_config)
+ autils.wait_for_event(p_dut, aconsts.SESSION_CB_ON_PUBLISH_STARTED)
+
+ # Subscriber: start subscribe and wait for confirmation
+ s_disc_id = s_dut.droid.wifiAwareSubscribe(s_id, s_config)
+ autils.wait_for_event(s_dut, aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED)
+
+ # Subscriber: wait or fail on service discovery
+ if expect_discovery:
+ event = autils.wait_for_event(s_dut,
+ aconsts.SESSION_CB_ON_SERVICE_DISCOVERED)
+ if expect_range:
+ asserts.assert_true(aconsts.SESSION_CB_KEY_DISTANCE_MM in event["data"],
+ "Discovery with ranging expected!")
+ else:
+ asserts.assert_false(
+ aconsts.SESSION_CB_KEY_DISTANCE_MM in event["data"],
+ "Discovery with ranging NOT expected!")
+ else:
+ autils.fail_on_event(s_dut, aconsts.SESSION_CB_ON_SERVICE_DISCOVERED)
+
+ # (single) sleep for timeout period and then verify that no further events
+ time.sleep(autils.EVENT_TIMEOUT)
+ autils.verify_no_more_events(p_dut, timeout=0)
+ autils.verify_no_more_events(s_dut, timeout=0)
+
+ return p_dut, s_dut, p_disc_id, s_disc_id
+
+ def run_discovery_update(self, p_dut, s_dut, p_disc_id, s_disc_id, p_config,
+ s_config, expect_discovery, expect_range=False):
+ """Run discovery on the 2 input devices with the specified update
+ configurations. I.e. update the existing discovery sessions with the
+ configurations.
+
+ Args:
+ p_dut, s_dut: Publisher/Subscriber DUTs.
+ p_disc_id, s_disc_id: Publisher/Subscriber discovery session IDs.
+ p_config, s_config: Publisher and Subscriber discovery configuration.
+ expect_discovery: True or False indicating whether discovery is expected
+ with the specified configurations.
+ expect_range: True if we expect distance results (i.e. ranging to happen).
+ Only relevant if expect_discovery is True.
+ """
+
+ # try to perform reconfiguration at same time (and wait once for all
+ # confirmations)
+ if p_config is not None:
+ p_dut.droid.wifiAwareUpdatePublish(p_disc_id, p_config)
+ if s_config is not None:
+ s_dut.droid.wifiAwareUpdateSubscribe(s_disc_id, s_config)
+
+ if p_config is not None:
+ autils.wait_for_event(p_dut, aconsts.SESSION_CB_ON_SESSION_CONFIG_UPDATED)
+ if s_config is not None:
+ autils.wait_for_event(s_dut, aconsts.SESSION_CB_ON_SESSION_CONFIG_UPDATED)
+
+ # Subscriber: wait or fail on service discovery
+ if expect_discovery:
+ event = autils.wait_for_event(s_dut,
+ aconsts.SESSION_CB_ON_SERVICE_DISCOVERED)
+ if expect_range:
+ asserts.assert_true(aconsts.SESSION_CB_KEY_DISTANCE_MM in event["data"],
+ "Discovery with ranging expected!")
+ else:
+ asserts.assert_false(
+ aconsts.SESSION_CB_KEY_DISTANCE_MM in event["data"],
+ "Discovery with ranging NOT expected!")
+ else:
+ autils.fail_on_event(s_dut, aconsts.SESSION_CB_ON_SERVICE_DISCOVERED)
+
+ # (single) sleep for timeout period and then verify that no further events
+ time.sleep(autils.EVENT_TIMEOUT)
+ autils.verify_no_more_events(p_dut, timeout=0)
+ autils.verify_no_more_events(s_dut, timeout=0)
+
+ def run_discovery_prange_sminmax_outofrange(self, is_unsolicited_passive):
+ """Run discovery with ranging:
+ - Publisher enables ranging
+ - Subscriber enables ranging with min/max such that out of range (min=large,
+ max=large+1)
+
+ Expected: no discovery
+
+ This is a baseline test for the update-configuration tests.
+
+ Args:
+ is_unsolicited_passive: True for Unsolicited/Passive, False for
+ Solicited/Active.
+ Returns: the return arguments of the run_discovery.
+ """
+ pub_type = (aconsts.PUBLISH_TYPE_UNSOLICITED if is_unsolicited_passive
+ else aconsts.PUBLISH_TYPE_SOLICITED)
+ sub_type = (aconsts.SUBSCRIBE_TYPE_PASSIVE if is_unsolicited_passive
+ else aconsts.SUBSCRIBE_TYPE_ACTIVE)
+ return self.run_discovery(
+ p_config=autils.add_ranging_to_pub(
+ autils.create_discovery_config(self.SERVICE_NAME, pub_type,
+ ssi=self.getname(2)),
+ enable_ranging=True),
+ s_config=autils.add_ranging_to_sub(
+ autils.create_discovery_config(self.SERVICE_NAME, sub_type,
+ ssi=self.getname(2)),
+ min_distance_mm=1000000,
+ max_distance_mm=1000001),
+ expect_discovery=False)
+
+ def getname(self, level=1):
+ """Python magic to return the name of the *calling* function.
+
+ Args:
+ level: How many levels up to go for the method name. Default = calling
+ method.
+ """
+ return sys._getframe(level).f_code.co_name
+
+ #########################################################################
+ # Run discovery with ranging configuration.
+ #
+ # Names: test_ranged_discovery_<ptype>_<stype>_<p_range>_<s_range>_<ref_dist>
+ #
+ # where:
+ # <ptype>_<stype>: unsolicited_passive or solicited_active
+ # <p_range>: prange or pnorange
+ # <s_range>: smin or smax or sminmax or snorange
+ # <ref_distance>: inrange or outoforange
+ #########################################################################
+
+ @test_tracker_info(uuid="3a216e9a-7a57-4741-89c0-84456975e1ac")
+ def test_ranged_discovery_unsolicited_passive_prange_snorange(self):
+ """Verify discovery with ranging:
+ - Unsolicited Publish/Passive Subscribe
+ - Publisher enables ranging
+ - Subscriber disables ranging
+
+ Expect: normal discovery (as if no ranging performed) - no distance
+ """
+ self.run_discovery(
+ p_config=autils.add_ranging_to_pub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.PUBLISH_TYPE_UNSOLICITED,
+ ssi=self.getname()),
+ enable_ranging=True),
+ s_config=autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.SUBSCRIBE_TYPE_PASSIVE,
+ ssi=self.getname()),
+ expect_discovery=True,
+ expect_range=False)
+
+ @test_tracker_info(uuid="859a321e-18e2-437b-aa7a-2a45a42ee737")
+ def test_ranged_discovery_solicited_active_prange_snorange(self):
+ """Verify discovery with ranging:
+ - Solicited Publish/Active Subscribe
+ - Publisher enables ranging
+ - Subscriber disables ranging
+
+ Expect: normal discovery (as if no ranging performed) - no distance
+ """
+ self.run_discovery(
+ p_config=autils.add_ranging_to_pub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.PUBLISH_TYPE_SOLICITED,
+ ssi=self.getname()),
+ enable_ranging=True),
+ s_config=autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.SUBSCRIBE_TYPE_ACTIVE,
+ ssi=self.getname()),
+ expect_discovery=True,
+ expect_range=False)
+
+ @test_tracker_info(uuid="12a4f899-4f70-4641-8f3c-351004669b71")
+ def test_ranged_discovery_unsolicited_passive_pnorange_smax_inrange(self):
+ """Verify discovery with ranging:
+ - Unsolicited Publish/Passive Subscribe
+ - Publisher disables ranging
+ - Subscriber enables ranging with max such that always within range (large
+ max)
+
+ Expect: normal discovery (as if no ranging performed) - no distance
+ """
+ self.run_discovery(
+ p_config=autils.add_ranging_to_pub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.PUBLISH_TYPE_UNSOLICITED,
+ ssi=self.getname()),
+ enable_ranging=False),
+ s_config=autils.add_ranging_to_sub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.SUBSCRIBE_TYPE_PASSIVE,
+ ssi=self.getname()),
+ min_distance_mm=None,
+ max_distance_mm=1000000),
+ expect_discovery=True,
+ expect_range=False)
+
+ @test_tracker_info(uuid="b7f90793-113d-4355-be20-856d92ac939f")
+ def test_ranged_discovery_solicited_active_pnorange_smax_inrange(self):
+ """Verify discovery with ranging:
+ - Solicited Publish/Active Subscribe
+ - Publisher disables ranging
+ - Subscriber enables ranging with max such that always within range (large
+ max)
+
+ Expect: normal discovery (as if no ranging performed) - no distance
+ """
+ self.run_discovery(
+ p_config=autils.add_ranging_to_pub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.PUBLISH_TYPE_SOLICITED,
+ ssi=self.getname()),
+ enable_ranging=False),
+ s_config=autils.add_ranging_to_sub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.SUBSCRIBE_TYPE_ACTIVE,
+ ssi=self.getname()),
+ min_distance_mm=None,
+ max_distance_mm=1000000),
+ expect_discovery=True,
+ expect_range=False)
+
+ @test_tracker_info(uuid="da3ab6df-58f9-44ae-b7be-8200d9e1bb76")
+ def test_ranged_discovery_unsolicited_passive_pnorange_smin_outofrange(self):
+ """Verify discovery with ranging:
+ - Unsolicited Publish/Passive Subscribe
+ - Publisher disables ranging
+ - Subscriber enables ranging with min such that always out of range (large
+ min)
+
+ Expect: normal discovery (as if no ranging performed) - no distance
+ """
+ self.run_discovery(
+ p_config=autils.add_ranging_to_pub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.PUBLISH_TYPE_UNSOLICITED,
+ ssi=self.getname()),
+ enable_ranging=False),
+ s_config=autils.add_ranging_to_sub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.SUBSCRIBE_TYPE_PASSIVE,
+ ssi=self.getname()),
+ min_distance_mm=1000000,
+ max_distance_mm=None),
+ expect_discovery=True,
+ expect_range=False)
+
+ @test_tracker_info(uuid="275e0806-f266-4fa6-9ca0-1cfd7b65a6ca")
+ def test_ranged_discovery_solicited_active_pnorange_smin_outofrange(self):
+ """Verify discovery with ranging:
+ - Solicited Publish/Active Subscribe
+ - Publisher disables ranging
+ - Subscriber enables ranging with min such that always out of range (large
+ min)
+
+ Expect: normal discovery (as if no ranging performed) - no distance
+ """
+ self.run_discovery(
+ p_config=autils.add_ranging_to_pub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.PUBLISH_TYPE_SOLICITED,
+ ssi=self.getname()),
+ enable_ranging=False),
+ s_config=autils.add_ranging_to_sub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.SUBSCRIBE_TYPE_ACTIVE,
+ ssi=self.getname()),
+ min_distance_mm=1000000,
+ max_distance_mm=None),
+ expect_discovery=True,
+ expect_range=False)
+
+ @test_tracker_info(uuid="8cd0aa1e-6866-4a5d-a550-f25483eebea1")
+ def test_ranged_discovery_unsolicited_passive_prange_smin_inrange(self):
+ """Verify discovery with ranging:
+ - Unsolicited Publish/Passive Subscribe
+ - Publisher enables ranging
+ - Subscriber enables ranging with min such that in range (min=0)
+
+ Expect: discovery with distance
+ """
+ self.run_discovery(
+ p_config=autils.add_ranging_to_pub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.PUBLISH_TYPE_UNSOLICITED,
+ ssi=self.getname()),
+ enable_ranging=True),
+ s_config=autils.add_ranging_to_sub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.SUBSCRIBE_TYPE_PASSIVE,
+ ssi=self.getname()),
+ min_distance_mm=0,
+ max_distance_mm=None),
+ expect_discovery=True,
+ expect_range=True)
+
+ @test_tracker_info(uuid="97c22c54-669b-4f7a-bf51-2f484e5f3e74")
+ def test_ranged_discovery_unsolicited_passive_prange_smax_inrange(self):
+ """Verify discovery with ranging:
+ - Unsolicited Publish/Passive Subscribe
+ - Publisher enables ranging
+ - Subscriber enables ranging with max such that in range (max=large)
+
+ Expect: discovery with distance
+ """
+ self.run_discovery(
+ p_config=autils.add_ranging_to_pub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.PUBLISH_TYPE_UNSOLICITED,
+ ssi=self.getname()),
+ enable_ranging=True),
+ s_config=autils.add_ranging_to_sub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.SUBSCRIBE_TYPE_PASSIVE,
+ ssi=self.getname()),
+ min_distance_mm=None,
+ max_distance_mm=1000000),
+ expect_discovery=True,
+ expect_range=True)
+
+ @test_tracker_info(uuid="616673d7-9d0b-43de-a378-e5e949b51b32")
+ def test_ranged_discovery_unsolicited_passive_prange_sminmax_inrange(self):
+ """Verify discovery with ranging:
+ - Unsolicited Publish/Passive Subscribe
+ - Publisher enables ranging
+ - Subscriber enables ranging with min/max such that in range (min=0,
+ max=large)
+
+ Expect: discovery with distance
+ """
+ self.run_discovery(
+ p_config=autils.add_ranging_to_pub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.PUBLISH_TYPE_UNSOLICITED,
+ ssi=self.getname()),
+ enable_ranging=True),
+ s_config=autils.add_ranging_to_sub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.SUBSCRIBE_TYPE_PASSIVE,
+ ssi=self.getname()),
+ min_distance_mm=0,
+ max_distance_mm=1000000),
+ expect_discovery=True,
+ expect_range=True)
+
+ @test_tracker_info(uuid="2bf84912-dcad-4a8f-971f-e445a07f05ce")
+ def test_ranged_discovery_solicited_active_prange_smin_inrange(self):
+ """Verify discovery with ranging:
+ - Solicited Publish/Active Subscribe
+ - Publisher enables ranging
+ - Subscriber enables ranging with min such that in range (min=0)
+
+ Expect: discovery with distance
+ """
+ self.run_discovery(
+ p_config=autils.add_ranging_to_pub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.PUBLISH_TYPE_SOLICITED,
+ ssi=self.getname()),
+ enable_ranging=True),
+ s_config=autils.add_ranging_to_sub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.SUBSCRIBE_TYPE_ACTIVE,
+ ssi=self.getname()),
+ min_distance_mm=0,
+ max_distance_mm=None),
+ expect_discovery=True,
+ expect_range=True)
+
+ @test_tracker_info(uuid="5cfd7961-9665-4742-a1b5-2d1fc97f9795")
+ def test_ranged_discovery_solicited_active_prange_smax_inrange(self):
+ """Verify discovery with ranging:
+ - Solicited Publish/Active Subscribe
+ - Publisher enables ranging
+ - Subscriber enables ranging with max such that in range (max=large)
+
+ Expect: discovery with distance
+ """
+ self.run_discovery(
+ p_config=autils.add_ranging_to_pub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.PUBLISH_TYPE_SOLICITED,
+ ssi=self.getname()),
+ enable_ranging=True),
+ s_config=autils.add_ranging_to_sub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.SUBSCRIBE_TYPE_ACTIVE,
+ ssi=self.getname()),
+ min_distance_mm=None,
+ max_distance_mm=1000000),
+ expect_discovery=True,
+ expect_range=True)
+
+ @test_tracker_info(uuid="5cf650ad-0b42-4b7d-9e05-d5f45fe0554d")
+ def test_ranged_discovery_solicited_active_prange_sminmax_inrange(self):
+ """Verify discovery with ranging:
+ - Solicited Publish/Active Subscribe
+ - Publisher enables ranging
+ - Subscriber enables ranging with min/max such that in range (min=0,
+ max=large)
+
+ Expect: discovery with distance
+ """
+ self.run_discovery(
+ p_config=autils.add_ranging_to_pub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.PUBLISH_TYPE_SOLICITED,
+ ssi=self.getname()),
+ enable_ranging=True),
+ s_config=autils.add_ranging_to_sub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.SUBSCRIBE_TYPE_ACTIVE,
+ ssi=self.getname()),
+ min_distance_mm=0,
+ max_distance_mm=1000000),
+ expect_discovery=True,
+ expect_range=True)
+
+ @test_tracker_info(uuid="5277f418-ac35-43ce-9b30-3c895272898e")
+ def test_ranged_discovery_unsolicited_passive_prange_smin_outofrange(self):
+ """Verify discovery with ranging:
+ - Unsolicited Publish/Passive Subscribe
+ - Publisher enables ranging
+ - Subscriber enables ranging with min such that out of range (min=large)
+
+ Expect: no discovery
+ """
+ self.run_discovery(
+ p_config=autils.add_ranging_to_pub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.PUBLISH_TYPE_UNSOLICITED,
+ ssi=self.getname()),
+ enable_ranging=True),
+ s_config=autils.add_ranging_to_sub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.SUBSCRIBE_TYPE_PASSIVE,
+ ssi=self.getname()),
+ min_distance_mm=1000000,
+ max_distance_mm=None),
+ expect_discovery=False)
+
+ @test_tracker_info(uuid="8a7e6ab1-acf4-41a7-a5fb-8c164d593b5f")
+ def test_ranged_discovery_unsolicited_passive_prange_smax_outofrange(self):
+ """Verify discovery with ranging:
+ - Unsolicited Publish/Passive Subscribe
+ - Publisher enables ranging
+ - Subscriber enables ranging with max such that in range (max=0)
+
+ Expect: no discovery
+ """
+ self.run_discovery(
+ p_config=autils.add_ranging_to_pub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.PUBLISH_TYPE_UNSOLICITED,
+ ssi=self.getname()),
+ enable_ranging=True),
+ s_config=autils.add_ranging_to_sub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.SUBSCRIBE_TYPE_PASSIVE,
+ ssi=self.getname()),
+ min_distance_mm=None,
+ max_distance_mm=0),
+ expect_discovery=False)
+
+ @test_tracker_info(uuid="b744f5f9-2641-4373-bf86-3752e2f9aace")
+ def test_ranged_discovery_unsolicited_passive_prange_sminmax_outofrange(self):
+ """Verify discovery with ranging:
+ - Unsolicited Publish/Passive Subscribe
+ - Publisher enables ranging
+ - Subscriber enables ranging with min/max such that out of range (min=large,
+ max=large+1)
+
+ Expect: no discovery
+ """
+ self.run_discovery(
+ p_config=autils.add_ranging_to_pub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.PUBLISH_TYPE_UNSOLICITED,
+ ssi=self.getname()),
+ enable_ranging=True),
+ s_config=autils.add_ranging_to_sub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.SUBSCRIBE_TYPE_PASSIVE,
+ ssi=self.getname()),
+ min_distance_mm=1000000,
+ max_distance_mm=1000001),
+ expect_discovery=False)
+
+ @test_tracker_info(uuid="d2e94199-b2e6-4fa5-a347-24594883c801")
+ def test_ranged_discovery_solicited_active_prange_smin_outofrange(self):
+ """Verify discovery with ranging:
+ - Solicited Publish/Active Subscribe
+ - Publisher enables ranging
+ - Subscriber enables ranging with min such that out of range (min=large)
+
+ Expect: no discovery
+ """
+ self.run_discovery(
+ p_config=autils.add_ranging_to_pub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.PUBLISH_TYPE_SOLICITED,
+ ssi=self.getname()),
+ enable_ranging=True),
+ s_config=autils.add_ranging_to_sub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.SUBSCRIBE_TYPE_ACTIVE,
+ ssi=self.getname()),
+ min_distance_mm=1000000,
+ max_distance_mm=None),
+ expect_discovery=False)
+
+ @test_tracker_info(uuid="a5619835-496a-4244-a428-f85cba3d4115")
+ def test_ranged_discovery_solicited_active_prange_smax_outofrange(self):
+ """Verify discovery with ranging:
+ - Solicited Publish/Active Subscribe
+ - Publisher enables ranging
+ - Subscriber enables ranging with max such that out of range (max=0)
+
+ Expect: no discovery
+ """
+ self.run_discovery(
+ p_config=autils.add_ranging_to_pub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.PUBLISH_TYPE_SOLICITED,
+ ssi=self.getname()),
+ enable_ranging=True),
+ s_config=autils.add_ranging_to_sub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.SUBSCRIBE_TYPE_ACTIVE,
+ ssi=self.getname()),
+ min_distance_mm=None,
+ max_distance_mm=0),
+ expect_discovery=False)
+
+ @test_tracker_info(uuid="12ebd91f-a973-410b-8ee1-0bd86024b921")
+ def test_ranged_discovery_solicited_active_prange_sminmax_outofrange(self):
+ """Verify discovery with ranging:
+ - Solicited Publish/Active Subscribe
+ - Publisher enables ranging
+ - Subscriber enables ranging with min/max such that out of range (min=large,
+ max=large+1)
+
+ Expect: no discovery
+ """
+ self.run_discovery(
+ p_config=autils.add_ranging_to_pub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.PUBLISH_TYPE_SOLICITED,
+ ssi=self.getname()),
+ enable_ranging=True),
+ s_config=autils.add_ranging_to_sub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.SUBSCRIBE_TYPE_ACTIVE,
+ ssi=self.getname()),
+ min_distance_mm=1000000,
+ max_distance_mm=1000001),
+ expect_discovery=False)
+
+ #########################################################################
+ # Run discovery with ranging configuration & update configurations after
+ # first run.
+ #
+ # Names: test_ranged_updated_discovery_<ptype>_<stype>_<scenario>
+ #
+ # where:
+ # <ptype>_<stype>: unsolicited_passive or solicited_active
+ # <scenario>: test scenario (details in name)
+ #########################################################################
+
+ @test_tracker_info(uuid="59442180-4a6c-428f-b926-86000e8339b4")
+ def test_ranged_updated_discovery_unsolicited_passive_oor_to_ir(self):
+ """Verify discovery with ranging operation with updated configuration:
+ - Unsolicited Publish/Passive Subscribe
+ - Publisher enables ranging
+ - Subscriber:
+ - Starts: Ranging enabled, min/max such that out of range (min=large,
+ max=large+1)
+ - Reconfigured to: Ranging enabled, min/max such that in range (min=0,
+ max=large)
+
+ Expect: discovery + ranging after update
+ """
+ (p_dut, s_dut, p_disc_id,
+ s_disc_id) = self.run_discovery_prange_sminmax_outofrange(True)
+ self.run_discovery_update(p_dut, s_dut, p_disc_id, s_disc_id,
+ p_config=None, # no updates
+ s_config=autils.add_ranging_to_sub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.SUBSCRIBE_TYPE_PASSIVE,
+ ssi=self.getname()),
+ min_distance_mm=0,
+ max_distance_mm=1000000),
+ expect_discovery=True,
+ expect_range=True)
+
+ @test_tracker_info(uuid="60188508-104d-42d5-ac3a-3605093c45d7")
+ def test_ranged_updated_discovery_unsolicited_passive_pub_unrange(self):
+ """Verify discovery with ranging operation with updated configuration:
+ - Unsolicited Publish/Passive Subscribe
+ - Publisher enables ranging
+ - Subscriber: Ranging enabled, min/max such that out of range (min=large,
+ max=large+1)
+ - Reconfigured to: Publisher disables ranging
+
+ Expect: discovery w/o ranging after update
+ """
+ (p_dut, s_dut, p_disc_id,
+ s_disc_id) = self.run_discovery_prange_sminmax_outofrange(True)
+ self.run_discovery_update(p_dut, s_dut, p_disc_id, s_disc_id,
+ p_config=autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.PUBLISH_TYPE_UNSOLICITED,
+ ssi=self.getname()),
+ s_config=None, # no updates
+ expect_discovery=True,
+ expect_range=False)
+
+ @test_tracker_info(uuid="f96b434e-751d-4eb5-ae01-0c5c3a6fb4a2")
+ def test_ranged_updated_discovery_unsolicited_passive_sub_unrange(self):
+ """Verify discovery with ranging operation with updated configuration:
+ - Unsolicited Publish/Passive Subscribe
+ - Publisher enables ranging
+ - Subscriber:
+ - Starts: Ranging enabled, min/max such that out of range (min=large,
+ max=large+1)
+ - Reconfigured to: Ranging disabled
+
+ Expect: discovery w/o ranging after update
+ """
+ (p_dut, s_dut, p_disc_id,
+ s_disc_id) = self.run_discovery_prange_sminmax_outofrange(True)
+ self.run_discovery_update(p_dut, s_dut, p_disc_id, s_disc_id,
+ p_config=None, # no updates
+ s_config=autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.SUBSCRIBE_TYPE_PASSIVE,
+ ssi=self.getname()),
+ expect_discovery=True,
+ expect_range=False)
+
+ @test_tracker_info(uuid="78970de8-9362-4647-931a-3513bcf58e80")
+ def test_ranged_updated_discovery_unsolicited_passive_sub_oor(self):
+ """Verify discovery with ranging operation with updated configuration:
+ - Unsolicited Publish/Passive Subscribe
+ - Publisher enables ranging
+ - Subscriber:
+ - Starts: Ranging enabled, min/max such that out of range (min=large,
+ max=large+1)
+ - Reconfigured to: different out-of-range setting
+
+ Expect: no discovery after update
+ """
+ (p_dut, s_dut, p_disc_id,
+ s_disc_id) = self.run_discovery_prange_sminmax_outofrange(True)
+ self.run_discovery_update(p_dut, s_dut, p_disc_id, s_disc_id,
+ p_config=None, # no updates
+ s_config=autils.add_ranging_to_sub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.SUBSCRIBE_TYPE_PASSIVE,
+ ssi=self.getname()),
+ min_distance_mm=100000,
+ max_distance_mm=100001),
+ expect_discovery=False)
+
+ @test_tracker_info(uuid="0841ad05-4899-4521-bd24-04a8e2e345ac")
+ def test_ranged_updated_discovery_unsolicited_passive_pub_same(self):
+ """Verify discovery with ranging operation with updated configuration:
+ - Unsolicited Publish/Passive Subscribe
+ - Publisher enables ranging
+ - Subscriber: Ranging enabled, min/max such that out of range (min=large,
+ max=large+1)
+ - Reconfigured to: Publisher with same settings (ranging enabled)
+
+ Expect: no discovery after update
+ """
+ (p_dut, s_dut, p_disc_id,
+ s_disc_id) = self.run_discovery_prange_sminmax_outofrange(True)
+ self.run_discovery_update(p_dut, s_dut, p_disc_id, s_disc_id,
+ p_config=autils.add_ranging_to_pub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.PUBLISH_TYPE_UNSOLICITED,
+ ssi=self.getname()),
+ enable_ranging=True),
+ s_config=None, # no updates
+ expect_discovery=False)
+
+ @test_tracker_info(uuid="ec6ca57b-f115-4516-813a-4572b930c8d3")
+ def test_ranged_updated_discovery_unsolicited_passive_multi_step(self):
+ """Verify discovery with ranging operation with updated configuration:
+ - Unsolicited Publish/Passive Subscribe
+ - Publisher enables ranging
+ - Subscriber: Ranging enabled, min/max such that out of range (min=large,
+ max=large+1)
+ - Expect: no discovery
+ - Reconfigured to: Ranging enabled, min/max such that in-range (min=0)
+ - Expect: discovery with ranging
+ - Reconfigured to: Ranging enabled, min/max such that out-of-range
+ (min=large)
+ - Expect: no discovery
+ - Reconfigured to: Ranging disabled
+ - Expect: discovery without ranging
+ """
+ (p_dut, s_dut, p_disc_id,
+ s_disc_id) = self.run_discovery_prange_sminmax_outofrange(True)
+ self.run_discovery_update(p_dut, s_dut, p_disc_id, s_disc_id,
+ p_config=None, # no updates
+ s_config=autils.add_ranging_to_sub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.SUBSCRIBE_TYPE_PASSIVE,
+ ssi=self.getname()),
+ min_distance_mm=0,
+ max_distance_mm=None),
+ expect_discovery=True,
+ expect_range=True)
+ self.run_discovery_update(p_dut, s_dut, p_disc_id, s_disc_id,
+ p_config=None, # no updates
+ s_config=autils.add_ranging_to_sub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.SUBSCRIBE_TYPE_PASSIVE,
+ ssi=self.getname()),
+ min_distance_mm=1000000,
+ max_distance_mm=None),
+ expect_discovery=False)
+ self.run_discovery_update(p_dut, s_dut, p_disc_id, s_disc_id,
+ p_config=None, # no updates
+ s_config=autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.SUBSCRIBE_TYPE_PASSIVE,
+ ssi=self.getname()),
+ expect_discovery=True,
+ expect_range=False)
+
+ @test_tracker_info(uuid="bbaac63b-000c-415f-bf19-0906f04031cd")
+ def test_ranged_updated_discovery_solicited_active_oor_to_ir(self):
+ """Verify discovery with ranging operation with updated configuration:
+ - Solicited Publish/Active Subscribe
+ - Publisher enables ranging
+ - Subscriber:
+ - Starts: Ranging enabled, min/max such that out of range (min=large,
+ max=large+1)
+ - Reconfigured to: Ranging enabled, min/max such that in range (min=0,
+ max=large)
+
+ Expect: discovery + ranging after update
+ """
+ (p_dut, s_dut, p_disc_id,
+ s_disc_id) = self.run_discovery_prange_sminmax_outofrange(False)
+ self.run_discovery_update(p_dut, s_dut, p_disc_id, s_disc_id,
+ p_config=None, # no updates
+ s_config=autils.add_ranging_to_sub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.SUBSCRIBE_TYPE_ACTIVE,
+ ssi=self.getname()),
+ min_distance_mm=0,
+ max_distance_mm=1000000),
+ expect_discovery=True,
+ expect_range=True)
+
+ @test_tracker_info(uuid="c385b361-7955-4f34-9109-8d8ca81cb4cc")
+ def test_ranged_updated_discovery_solicited_active_pub_unrange(self):
+ """Verify discovery with ranging operation with updated configuration:
+ - Solicited Publish/Active Subscribe
+ - Publisher enables ranging
+ - Subscriber: Ranging enabled, min/max such that out of range (min=large,
+ max=large+1)
+ - Reconfigured to: Publisher disables ranging
+
+ Expect: discovery w/o ranging after update
+ """
+ (p_dut, s_dut, p_disc_id,
+ s_disc_id) = self.run_discovery_prange_sminmax_outofrange(False)
+ self.run_discovery_update(p_dut, s_dut, p_disc_id, s_disc_id,
+ p_config=autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.PUBLISH_TYPE_SOLICITED,
+ ssi=self.getname()),
+ s_config=None, # no updates
+ expect_discovery=True,
+ expect_range=False)
+
+ @test_tracker_info(uuid="ec5120ea-77ec-48c6-8820-48b82ad3dfd4")
+ def test_ranged_updated_discovery_solicited_active_sub_unrange(self):
+ """Verify discovery with ranging operation with updated configuration:
+ - Solicited Publish/Active Subscribe
+ - Publisher enables ranging
+ - Subscriber:
+ - Starts: Ranging enabled, min/max such that out of range (min=large,
+ max=large+1)
+ - Reconfigured to: Ranging disabled
+
+ Expect: discovery w/o ranging after update
+ """
+ (p_dut, s_dut, p_disc_id,
+ s_disc_id) = self.run_discovery_prange_sminmax_outofrange(False)
+ self.run_discovery_update(p_dut, s_dut, p_disc_id, s_disc_id,
+ p_config=None, # no updates
+ s_config=autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.SUBSCRIBE_TYPE_ACTIVE,
+ ssi=self.getname()),
+ expect_discovery=True,
+ expect_range=False)
+
+ @test_tracker_info(uuid="6231cb42-91e4-48d3-b9db-b37efbe8537c")
+ def test_ranged_updated_discovery_solicited_active_sub_oor(self):
+ """Verify discovery with ranging operation with updated configuration:
+ - Solicited Publish/Active Subscribe
+ - Publisher enables ranging
+ - Subscriber:
+ - Starts: Ranging enabled, min/max such that out of range (min=large,
+ max=large+1)
+ - Reconfigured to: different out-of-range setting
+
+ Expect: no discovery after update
+ """
+ (p_dut, s_dut, p_disc_id,
+ s_disc_id) = self.run_discovery_prange_sminmax_outofrange(False)
+ self.run_discovery_update(p_dut, s_dut, p_disc_id, s_disc_id,
+ p_config=None, # no updates
+ s_config=autils.add_ranging_to_sub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.SUBSCRIBE_TYPE_ACTIVE,
+ ssi=self.getname()),
+ min_distance_mm=100000,
+ max_distance_mm=100001),
+ expect_discovery=False)
+
+ @test_tracker_info(uuid="ec999420-6a50-455e-b624-f4c9b4cb7ea5")
+ def test_ranged_updated_discovery_solicited_active_pub_same(self):
+ """Verify discovery with ranging operation with updated configuration:
+ - Solicited Publish/Active Subscribe
+ - Publisher enables ranging
+ - Subscriber: Ranging enabled, min/max such that out of range (min=large,
+ max=large+1)
+ - Reconfigured to: Publisher with same settings (ranging enabled)
+
+ Expect: no discovery after update
+ """
+ (p_dut, s_dut, p_disc_id,
+ s_disc_id) = self.run_discovery_prange_sminmax_outofrange(False)
+ self.run_discovery_update(p_dut, s_dut, p_disc_id, s_disc_id,
+ p_config=autils.add_ranging_to_pub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.PUBLISH_TYPE_SOLICITED,
+ ssi=self.getname()),
+ enable_ranging=True),
+ s_config=None, # no updates
+ expect_discovery=False)
+
+ @test_tracker_info(uuid="ec6ca57b-f115-4516-813a-4572b930c8d3")
+ def test_ranged_updated_discovery_solicited_active_multi_step(self):
+ """Verify discovery with ranging operation with updated configuration:
+ - Unsolicited Publish/Passive Subscribe
+ - Publisher enables ranging
+ - Subscriber: Ranging enabled, min/max such that out of range (min=large,
+ max=large+1)
+ - Expect: no discovery
+ - Reconfigured to: Ranging enabled, min/max such that in-range (min=0)
+ - Expect: discovery with ranging
+ - Reconfigured to: Ranging enabled, min/max such that out-of-range
+ (min=large)
+ - Expect: no discovery
+ - Reconfigured to: Ranging disabled
+ - Expect: discovery without ranging
+ """
+ (p_dut, s_dut, p_disc_id,
+ s_disc_id) = self.run_discovery_prange_sminmax_outofrange(True)
+ self.run_discovery_update(p_dut, s_dut, p_disc_id, s_disc_id,
+ p_config=None, # no updates
+ s_config=autils.add_ranging_to_sub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.SUBSCRIBE_TYPE_ACTIVE,
+ ssi=self.getname()),
+ min_distance_mm=0,
+ max_distance_mm=None),
+ expect_discovery=True,
+ expect_range=True)
+ self.run_discovery_update(p_dut, s_dut, p_disc_id, s_disc_id,
+ p_config=None, # no updates
+ s_config=autils.add_ranging_to_sub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.SUBSCRIBE_TYPE_ACTIVE,
+ ssi=self.getname()),
+ min_distance_mm=1000000,
+ max_distance_mm=None),
+ expect_discovery=False)
+ self.run_discovery_update(p_dut, s_dut, p_disc_id, s_disc_id,
+ p_config=None, # no updates
+ s_config=autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.SUBSCRIBE_TYPE_ACTIVE,
+ ssi=self.getname()),
+ expect_discovery=True,
+ expect_range=False)
+
+ #########################################################################
+
+ @test_tracker_info(uuid="6edc47ab-7300-4bff-b7dd-5de83f58928a")
+ def test_ranged_discovery_multi_session(self):
+ """Verify behavior with multiple concurrent discovery session with different
+ configurations:
+
+ Device A (Publisher):
+ Publisher AA: ranging enabled
+ Publisher BB: ranging enabled
+ Publisher CC: ranging enabled
+ Publisher DD: ranging disabled
+ Device B (Subscriber):
+ Subscriber AA: ranging out-of-range -> no match
+ Subscriber BB: ranging in-range -> match w/range
+ Subscriber CC: ranging disabled -> match w/o range
+ Subscriber DD: ranging out-of-range -> match w/o range
+ """
+ p_dut = self.android_devices[0]
+ p_dut.pretty_name = "Publisher"
+ s_dut = self.android_devices[1]
+ s_dut.pretty_name = "Subscriber"
+
+ # Publisher+Subscriber: attach and wait for confirmation
+ p_id = p_dut.droid.wifiAwareAttach(False)
+ autils.wait_for_event(p_dut, aconsts.EVENT_CB_ON_ATTACHED)
+ time.sleep(self.device_startup_offset)
+ s_id = s_dut.droid.wifiAwareAttach(False)
+ autils.wait_for_event(s_dut, aconsts.EVENT_CB_ON_ATTACHED)
+
+ # Subscriber: start sessions
+ aa_s_disc_id = s_dut.droid.wifiAwareSubscribe(
+ s_id,
+ autils.add_ranging_to_sub(
+ autils.create_discovery_config("AA",
+ aconsts.SUBSCRIBE_TYPE_PASSIVE),
+ min_distance_mm=1000000, max_distance_mm=1000001),
+ True)
+ bb_s_disc_id = s_dut.droid.wifiAwareSubscribe(
+ s_id,
+ autils.add_ranging_to_sub(
+ autils.create_discovery_config("BB",
+ aconsts.SUBSCRIBE_TYPE_PASSIVE),
+ min_distance_mm=0, max_distance_mm=1000000),
+ True)
+ cc_s_disc_id = s_dut.droid.wifiAwareSubscribe(
+ s_id,
+ autils.create_discovery_config("CC", aconsts.SUBSCRIBE_TYPE_PASSIVE),
+ True)
+ dd_s_disc_id = s_dut.droid.wifiAwareSubscribe(
+ s_id,
+ autils.add_ranging_to_sub(
+ autils.create_discovery_config("DD",
+ aconsts.SUBSCRIBE_TYPE_PASSIVE),
+ min_distance_mm=1000000, max_distance_mm=1000001),
+ True)
+
+ autils.wait_for_event(s_dut, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED, aa_s_disc_id))
+ autils.wait_for_event(s_dut, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED, bb_s_disc_id))
+ autils.wait_for_event(s_dut, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED, cc_s_disc_id))
+ autils.wait_for_event(s_dut, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED, dd_s_disc_id))
+
+ # Publisher: start sessions
+ aa_p_disc_id = p_dut.droid.wifiAwarePublish(
+ p_id,
+ autils.add_ranging_to_pub(
+ autils.create_discovery_config("AA",
+ aconsts.PUBLISH_TYPE_UNSOLICITED),
+ enable_ranging=True),
+ True)
+ bb_p_disc_id = p_dut.droid.wifiAwarePublish(
+ p_id,
+ autils.add_ranging_to_pub(
+ autils.create_discovery_config("BB",
+ aconsts.PUBLISH_TYPE_UNSOLICITED),
+ enable_ranging=True),
+ True)
+ cc_p_disc_id = p_dut.droid.wifiAwarePublish(
+ p_id,
+ autils.add_ranging_to_pub(
+ autils.create_discovery_config("CC",
+ aconsts.PUBLISH_TYPE_UNSOLICITED),
+ enable_ranging=True),
+ True)
+ dd_p_disc_id = p_dut.droid.wifiAwarePublish(
+ p_id,
+ autils.create_discovery_config("DD", aconsts.PUBLISH_TYPE_UNSOLICITED),
+ True)
+
+ autils.wait_for_event(p_dut, autils.decorate_event(
+ aconsts.SESSION_CB_ON_PUBLISH_STARTED, aa_p_disc_id))
+ autils.wait_for_event(p_dut, autils.decorate_event(
+ aconsts.SESSION_CB_ON_PUBLISH_STARTED, bb_p_disc_id))
+ autils.wait_for_event(p_dut, autils.decorate_event(
+ aconsts.SESSION_CB_ON_PUBLISH_STARTED, cc_p_disc_id))
+ autils.wait_for_event(p_dut, autils.decorate_event(
+ aconsts.SESSION_CB_ON_PUBLISH_STARTED, dd_p_disc_id))
+
+ # Expected and unexpected service discovery
+ event = autils.wait_for_event(s_dut, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SERVICE_DISCOVERED, bb_s_disc_id))
+ asserts.assert_true(aconsts.SESSION_CB_KEY_DISTANCE_MM in event["data"],
+ "Discovery with ranging for BB expected!")
+ event = autils.wait_for_event(s_dut, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SERVICE_DISCOVERED, cc_s_disc_id))
+ asserts.assert_false(
+ aconsts.SESSION_CB_KEY_DISTANCE_MM in event["data"],
+ "Discovery with ranging for CC NOT expected!")
+ event = autils.wait_for_event(s_dut, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SERVICE_DISCOVERED, dd_s_disc_id))
+ asserts.assert_false(
+ aconsts.SESSION_CB_KEY_DISTANCE_MM in event["data"],
+ "Discovery with ranging for DD NOT expected!")
+ autils.fail_on_event(s_dut, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SERVICE_DISCOVERED, aa_s_disc_id))
+
+ # (single) sleep for timeout period and then verify that no further events
+ time.sleep(autils.EVENT_TIMEOUT)
+ autils.verify_no_more_events(p_dut, timeout=0)
+ autils.verify_no_more_events(s_dut, timeout=0)
+
+ #########################################################################
+
+ @test_tracker_info(uuid="deede47f-a54c-46d9-88bb-f4482fbd8470")
+ def test_ndp_concurrency(self):
+ """Verify the behavior of Wi-Fi Aware Ranging whenever an NDP is created -
+ for those devices that have a concurrency limitation that does not allow
+ Aware Ranging, whether direct or as part of discovery.
+
+ Publisher: start 3 services
+ AA w/o ranging
+ BB w/ ranging
+ CC w/ ranging
+ DD w/ ranging
+ Subscriber: start 2 services
+ AA w/o ranging
+ BB w/ ranging out-of-range
+ (do not start CC!)
+ DD w/ ranging in-range
+ Expect AA discovery, DD discovery w/range, but no BB
+ Start NDP in context of AA
+ IF NDP_CONCURRENCY_LIMITATION:
+ Verify discovery on BB w/o range
+ Start EE w/ranging out-of-range
+ Start FF w/ranging in-range
+ IF NDP_CONCURRENCY_LIMITATION:
+ Verify discovery on EE w/o range
+ Verify discovery on FF w/o range
+ Else:
+ Verify discovery on FF w/ range
+ Tear down NDP
+ Subscriber
+ Start CC w/ ranging out-of-range
+ Wait to verify that do not get match
+ Update configuration to be in-range
+ Verify that get match with ranging information
+ """
+ p_dut = self.android_devices[0]
+ p_dut.pretty_name = "Publisher"
+ s_dut = self.android_devices[1]
+ s_dut.pretty_name = "Subscriber"
+
+ # Publisher+Subscriber: attach and wait for confirmation
+ p_id = p_dut.droid.wifiAwareAttach(False)
+ autils.wait_for_event(p_dut, aconsts.EVENT_CB_ON_ATTACHED)
+ time.sleep(self.device_startup_offset)
+ s_id = s_dut.droid.wifiAwareAttach(False)
+ autils.wait_for_event(s_dut, aconsts.EVENT_CB_ON_ATTACHED)
+
+ # Publisher: AA w/o ranging, BB w/ ranging, CC w/ ranging, DD w/ ranging
+ aa_p_id = p_dut.droid.wifiAwarePublish(p_id,
+ autils.create_discovery_config("AA", aconsts.PUBLISH_TYPE_SOLICITED),
+ True)
+ autils.wait_for_event(p_dut, autils.decorate_event(
+ aconsts.SESSION_CB_ON_PUBLISH_STARTED, aa_p_id))
+ bb_p_id = p_dut.droid.wifiAwarePublish(p_id, autils.add_ranging_to_pub(
+ autils.create_discovery_config("BB", aconsts.PUBLISH_TYPE_UNSOLICITED),
+ enable_ranging=True), True)
+ autils.wait_for_event(p_dut, autils.decorate_event(
+ aconsts.SESSION_CB_ON_PUBLISH_STARTED, bb_p_id))
+ cc_p_id = p_dut.droid.wifiAwarePublish(p_id, autils.add_ranging_to_pub(
+ autils.create_discovery_config("CC", aconsts.PUBLISH_TYPE_UNSOLICITED),
+ enable_ranging=True), True)
+ autils.wait_for_event(p_dut, autils.decorate_event(
+ aconsts.SESSION_CB_ON_PUBLISH_STARTED, cc_p_id))
+ dd_p_id = p_dut.droid.wifiAwarePublish(p_id, autils.add_ranging_to_pub(
+ autils.create_discovery_config("DD", aconsts.PUBLISH_TYPE_UNSOLICITED),
+ enable_ranging=True), True)
+ autils.wait_for_event(p_dut, autils.decorate_event(
+ aconsts.SESSION_CB_ON_PUBLISH_STARTED, dd_p_id))
+
+ # Subscriber: AA w/o ranging, BB w/ranging out-of-range,
+ # DD w /ranging in-range
+ aa_s_id = s_dut.droid.wifiAwareSubscribe(s_id,
+ autils.create_discovery_config("AA", aconsts.SUBSCRIBE_TYPE_ACTIVE),
+ True)
+ autils.wait_for_event(s_dut, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED, aa_s_id))
+ bb_s_id = s_dut.droid.wifiAwareSubscribe(s_id, autils.add_ranging_to_sub(
+ autils.create_discovery_config("BB", aconsts.SUBSCRIBE_TYPE_PASSIVE),
+ min_distance_mm=1000000, max_distance_mm=1000001), True)
+ autils.wait_for_event(s_dut, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED, bb_s_id))
+ dd_s_id = s_dut.droid.wifiAwareSubscribe(s_id, autils.add_ranging_to_sub(
+ autils.create_discovery_config("DD", aconsts.SUBSCRIBE_TYPE_PASSIVE),
+ min_distance_mm=None, max_distance_mm=1000000), True)
+ autils.wait_for_event(s_dut, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED, dd_s_id))
+
+ # verify: AA discovered, BB not discovered, DD discovery w/range
+ event = autils.wait_for_event(s_dut, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SERVICE_DISCOVERED, aa_s_id))
+ asserts.assert_false(aconsts.SESSION_CB_KEY_DISTANCE_MM in event["data"],
+ "Discovery with ranging for AA NOT expected!")
+ aa_peer_id_on_sub = event['data'][aconsts.SESSION_CB_KEY_PEER_ID]
+ autils.fail_on_event(s_dut, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SERVICE_DISCOVERED, bb_s_id))
+ event = autils.wait_for_event(s_dut, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SERVICE_DISCOVERED, dd_s_id))
+ asserts.assert_true(aconsts.SESSION_CB_KEY_DISTANCE_MM in event["data"],
+ "Discovery with ranging for DD expected!")
+
+ # start NDP in context of AA:
+
+ # Publisher: request network (from ANY)
+ p_req_key = autils.request_network(p_dut,
+ p_dut.droid.wifiAwareCreateNetworkSpecifier(aa_p_id, None))
+
+ # Subscriber: request network
+ s_req_key = autils.request_network(s_dut,
+ s_dut.droid.wifiAwareCreateNetworkSpecifier(aa_s_id, aa_peer_id_on_sub))
+
+ # Publisher & Subscriber: wait for network formation
+ p_net_event = autils.wait_for_event_with_keys(p_dut,
+ cconsts.EVENT_NETWORK_CALLBACK,
+ autils.EVENT_TIMEOUT, (
+ cconsts.NETWORK_CB_KEY_EVENT,
+ cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
+ (cconsts.NETWORK_CB_KEY_ID,
+ p_req_key))
+ s_net_event = autils.wait_for_event_with_keys(s_dut,
+ cconsts.EVENT_NETWORK_CALLBACK,
+ autils.EVENT_TIMEOUT, (
+ cconsts.NETWORK_CB_KEY_EVENT,
+ cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
+ (cconsts.NETWORK_CB_KEY_ID,
+ s_req_key))
+
+ p_aware_if = p_net_event["data"][cconsts.NETWORK_CB_KEY_INTERFACE_NAME]
+ s_aware_if = s_net_event["data"][cconsts.NETWORK_CB_KEY_INTERFACE_NAME]
+
+ p_ipv6 = p_dut.droid.connectivityGetLinkLocalIpv6Address(p_aware_if).split(
+ "%")[0]
+ s_ipv6 = s_dut.droid.connectivityGetLinkLocalIpv6Address(s_aware_if).split(
+ "%")[0]
+
+ self.log.info("AA NDP Interface names: P=%s, S=%s", p_aware_if, s_aware_if)
+ self.log.info("AA NDP Interface addresses (IPv6): P=%s, S=%s", p_ipv6,
+ s_ipv6)
+
+ if self.RANGING_NDP_CONCURRENCY_LIMITATION:
+ # Expect BB to now discover w/o ranging
+ event = autils.wait_for_event(s_dut, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SERVICE_DISCOVERED, bb_s_id))
+ asserts.assert_false(aconsts.SESSION_CB_KEY_DISTANCE_MM in event["data"],
+ "Discovery with ranging for BB NOT expected!")
+
+ # Publishers: EE, FF w/ ranging
+ ee_p_id = p_dut.droid.wifiAwarePublish(p_id, autils.add_ranging_to_pub(
+ autils.create_discovery_config("EE", aconsts.PUBLISH_TYPE_SOLICITED),
+ enable_ranging=True), True)
+ autils.wait_for_event(p_dut, autils.decorate_event(
+ aconsts.SESSION_CB_ON_PUBLISH_STARTED, ee_p_id))
+ ff_p_id = p_dut.droid.wifiAwarePublish(p_id, autils.add_ranging_to_pub(
+ autils.create_discovery_config("FF", aconsts.PUBLISH_TYPE_UNSOLICITED),
+ enable_ranging=True), True)
+ autils.wait_for_event(p_dut, autils.decorate_event(
+ aconsts.SESSION_CB_ON_PUBLISH_STARTED, ff_p_id))
+
+ # Subscribers: EE out-of-range, FF in-range
+ ee_s_id = s_dut.droid.wifiAwareSubscribe(s_id, autils.add_ranging_to_sub(
+ autils.create_discovery_config("EE", aconsts.SUBSCRIBE_TYPE_ACTIVE),
+ min_distance_mm=1000000, max_distance_mm=1000001), True)
+ autils.wait_for_event(s_dut, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED, ee_s_id))
+ ff_s_id = s_dut.droid.wifiAwareSubscribe(s_id, autils.add_ranging_to_sub(
+ autils.create_discovery_config("FF", aconsts.SUBSCRIBE_TYPE_PASSIVE),
+ min_distance_mm=None, max_distance_mm=1000000), True)
+ autils.wait_for_event(s_dut, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED, ff_s_id))
+
+ if self.RANGING_NDP_CONCURRENCY_LIMITATION:
+ # Expect EE & FF discovery w/o range
+ event = autils.wait_for_event(s_dut, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SERVICE_DISCOVERED, ee_s_id))
+ asserts.assert_false(aconsts.SESSION_CB_KEY_DISTANCE_MM in event["data"],
+ "Discovery with ranging for EE NOT expected!")
+ event = autils.wait_for_event(s_dut, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SERVICE_DISCOVERED, ff_s_id))
+ asserts.assert_false(aconsts.SESSION_CB_KEY_DISTANCE_MM in event["data"],
+ "Discovery with ranging for FF NOT expected!")
+ else:
+ event = autils.wait_for_event(s_dut, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SERVICE_DISCOVERED, ff_s_id))
+ asserts.assert_true(aconsts.SESSION_CB_KEY_DISTANCE_MM in event["data"],
+ "Discovery with ranging for FF expected!")
+
+ # tear down NDP
+ p_dut.droid.connectivityUnregisterNetworkCallback(p_req_key)
+ s_dut.droid.connectivityUnregisterNetworkCallback(s_req_key)
+
+ time.sleep(5) # give time for NDP termination to finish
+
+ # Subscriber: start CC out-of-range - no discovery expected!
+ cc_s_id = s_dut.droid.wifiAwareSubscribe(s_id, autils.add_ranging_to_sub(
+ autils.create_discovery_config("CC", aconsts.SUBSCRIBE_TYPE_PASSIVE),
+ min_distance_mm=1000000, max_distance_mm=1000001), True)
+ autils.wait_for_event(s_dut, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED, cc_s_id))
+ autils.fail_on_event(s_dut, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SERVICE_DISCOVERED, cc_s_id))
+
+ # Subscriber: modify CC to in-range - expect discovery w/ range
+ s_dut.droid.wifiAwareUpdateSubscribe(cc_s_id, autils.add_ranging_to_sub(
+ autils.create_discovery_config("CC", aconsts.SUBSCRIBE_TYPE_PASSIVE),
+ min_distance_mm=None, max_distance_mm=1000001))
+ autils.wait_for_event(s_dut, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SESSION_CONFIG_UPDATED, cc_s_id))
+ event = autils.wait_for_event(s_dut, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SERVICE_DISCOVERED, cc_s_id))
+ asserts.assert_true(aconsts.SESSION_CB_KEY_DISTANCE_MM in event["data"],
+ "Discovery with ranging for CC expected!")
+
+ @test_tracker_info(uuid="d94dac91-4090-4c03-a867-6dfac6558ba3")
+ def test_role_concurrency(self):
+ """Verify the behavior of Wi-Fi Aware Ranging (in the context of discovery)
+ when the device has concurrency limitations which do not permit concurrent
+ Initiator and Responder roles on the same device. In such case it is
+ expected that normal discovery without ranging is executed AND that ranging
+ is restored whenever the concurrency constraints are removed.
+
+ Note: all Subscribers are in-range.
+
+ DUT1: start multiple services
+ Publish AA w/ ranging (unsolicited)
+ Subscribe BB w/ ranging (active)
+ Publish CC w/ ranging (unsolicited)
+ Publish DD w/o ranging (solicited)
+ Subscribe EE w/ ranging (passive)
+ Subscribe FF w/ ranging (active)
+ DUT2: start multiple services
+ Subscribe AA w/ ranging (passive)
+ Publish BB w/ ranging (solicited)
+ Subscribe DD w/o ranging (active)
+ Expect
+ DUT2: AA match w/ range information
+ DUT1: BB match w/o range information (concurrency disables ranging)
+ DUT2: DD match w/o range information
+ DUT1: Terminate AA
+ DUT2:
+ Terminate AA
+ Start Publish EE w/ ranging (unsolicited)
+ DUT1: expect EE w/o ranging
+ DUT1: Terminate CC
+ DUT2: Start Publish FF w/ ranging (solicited)
+ DUT1: expect FF w/ ranging information - should finally be back up
+ """
+ dut1 = self.android_devices[0]
+ dut1.pretty_name = "DUT1"
+ dut2 = self.android_devices[1]
+ dut2.pretty_name = "DUT2"
+
+ # Publisher+Subscriber: attach and wait for confirmation
+ dut1_id = dut1.droid.wifiAwareAttach(False)
+ autils.wait_for_event(dut1, aconsts.EVENT_CB_ON_ATTACHED)
+ time.sleep(self.device_startup_offset)
+ dut2_id = dut2.droid.wifiAwareAttach(False)
+ autils.wait_for_event(dut2, aconsts.EVENT_CB_ON_ATTACHED)
+
+ # DUT1: initial service bringup
+ aa_p_id = dut1.droid.wifiAwarePublish(dut1_id, autils.add_ranging_to_pub(
+ autils.create_discovery_config("AA", aconsts.PUBLISH_TYPE_UNSOLICITED),
+ enable_ranging=True), True)
+ autils.wait_for_event(dut1, autils.decorate_event(
+ aconsts.SESSION_CB_ON_PUBLISH_STARTED, aa_p_id))
+ bb_s_id = dut1.droid.wifiAwareSubscribe(dut1_id, autils.add_ranging_to_sub(
+ autils.create_discovery_config("BB", aconsts.SUBSCRIBE_TYPE_ACTIVE),
+ min_distance_mm=None, max_distance_mm=1000000), True)
+ autils.wait_for_event(dut1, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED, bb_s_id))
+ cc_p_id = dut1.droid.wifiAwarePublish(dut1_id, autils.add_ranging_to_pub(
+ autils.create_discovery_config("CC", aconsts.PUBLISH_TYPE_UNSOLICITED),
+ enable_ranging=True), True)
+ autils.wait_for_event(dut1, autils.decorate_event(
+ aconsts.SESSION_CB_ON_PUBLISH_STARTED, cc_p_id))
+ dd_p_id = dut1.droid.wifiAwarePublish(dut1_id,
+ autils.create_discovery_config("DD", aconsts.PUBLISH_TYPE_SOLICITED),
+ True)
+ autils.wait_for_event(dut1, autils.decorate_event(
+ aconsts.SESSION_CB_ON_PUBLISH_STARTED, dd_p_id))
+ ee_s_id = dut1.droid.wifiAwareSubscribe(dut1_id, autils.add_ranging_to_sub(
+ autils.create_discovery_config("EE", aconsts.SUBSCRIBE_TYPE_PASSIVE),
+ min_distance_mm=None, max_distance_mm=1000000), True)
+ autils.wait_for_event(dut1, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED, ee_s_id))
+ ff_s_id = dut1.droid.wifiAwareSubscribe(dut1_id, autils.add_ranging_to_sub(
+ autils.create_discovery_config("FF", aconsts.SUBSCRIBE_TYPE_ACTIVE),
+ min_distance_mm=None, max_distance_mm=1000000), True)
+ autils.wait_for_event(dut1, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED, ff_s_id))
+
+ # DUT2: initial service bringup
+ aa_s_id = dut2.droid.wifiAwareSubscribe(dut2_id, autils.add_ranging_to_sub(
+ autils.create_discovery_config("AA", aconsts.SUBSCRIBE_TYPE_PASSIVE),
+ min_distance_mm=None, max_distance_mm=1000000), True)
+ autils.wait_for_event(dut2, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED, aa_s_id))
+ bb_p_id = dut2.droid.wifiAwarePublish(dut2_id, autils.add_ranging_to_pub(
+ autils.create_discovery_config("BB", aconsts.PUBLISH_TYPE_SOLICITED),
+ enable_ranging=True), True)
+ autils.wait_for_event(dut2, autils.decorate_event(
+ aconsts.SESSION_CB_ON_PUBLISH_STARTED, bb_p_id))
+ dd_s_id = dut2.droid.wifiAwareSubscribe(dut2_id,
+ autils.create_discovery_config("AA", aconsts.SUBSCRIBE_TYPE_ACTIVE),
+ True)
+ autils.wait_for_event(dut2, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED, dd_s_id))
+
+ # Initial set of discovery events for AA, BB, and DD (which are up)
+ event = autils.wait_for_event(dut2, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SERVICE_DISCOVERED, aa_s_id))
+ asserts.assert_true(aconsts.SESSION_CB_KEY_DISTANCE_MM in event["data"],
+ "Discovery with ranging for AA expected!")
+ event = autils.wait_for_event(dut1, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SERVICE_DISCOVERED, bb_s_id))
+ if self.RANGING_INITIATOR_RESPONDER_CONCURRENCY_LIMITATION:
+ asserts.assert_false(aconsts.SESSION_CB_KEY_DISTANCE_MM in event["data"],
+ "Discovery with ranging for BB NOT expected!")
+ else:
+ asserts.assert_true(aconsts.SESSION_CB_KEY_DISTANCE_MM in event["data"],
+ "Discovery with ranging for BB expected!")
+ event = autils.wait_for_event(dut2, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SERVICE_DISCOVERED, dd_s_id))
+ asserts.assert_false(aconsts.SESSION_CB_KEY_DISTANCE_MM in event["data"],
+ "Discovery with ranging for DD NOT expected!")
+
+ # DUT1/DUT2: terminate AA
+ dut1.droid.wifiAwareDestroyDiscoverySession(aa_p_id)
+ dut2.droid.wifiAwareDestroyDiscoverySession(aa_s_id)
+
+ time.sleep(5) # guarantee that session terminated (and host recovered?)
+
+ # DUT2: try EE service - ranging still disabled
+ ee_p_id = dut2.droid.wifiAwarePublish(dut2_id, autils.add_ranging_to_pub(
+ autils.create_discovery_config("EE", aconsts.PUBLISH_TYPE_UNSOLICITED),
+ enable_ranging=True), True)
+ autils.wait_for_event(dut2, autils.decorate_event(
+ aconsts.SESSION_CB_ON_PUBLISH_STARTED, ee_p_id))
+
+ event = autils.wait_for_event(dut1, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SERVICE_DISCOVERED, ee_s_id))
+ if self.RANGING_INITIATOR_RESPONDER_CONCURRENCY_LIMITATION:
+ asserts.assert_false(aconsts.SESSION_CB_KEY_DISTANCE_MM in event["data"],
+ "Discovery with ranging for EE NOT expected!")
+ else:
+ asserts.assert_true(aconsts.SESSION_CB_KEY_DISTANCE_MM in event["data"],
+ "Discovery with ranging for EE expected!")
+
+ # DUT1: terminate CC - last publish w/ ranging on DUT!
+ dut1.droid.wifiAwareDestroyDiscoverySession(cc_p_id)
+
+ time.sleep(5) # guarantee that session terminated (and host recovered?)
+
+ # DUT2: try FF service - ranging should now function
+ ff_p_id = dut2.droid.wifiAwarePublish(dut2_id, autils.add_ranging_to_pub(
+ autils.create_discovery_config("FF", aconsts.PUBLISH_TYPE_SOLICITED),
+ enable_ranging=True), True)
+ autils.wait_for_event(dut2, autils.decorate_event(
+ aconsts.SESSION_CB_ON_PUBLISH_STARTED, ff_p_id))
+
+ event = autils.wait_for_event(dut1, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SERVICE_DISCOVERED, ff_s_id))
+ asserts.assert_true(aconsts.SESSION_CB_KEY_DISTANCE_MM in event["data"],
+ "Discovery with ranging for FF expected!")
+
+
+ @test_tracker_info(uuid="6700eab8-a172-43cd-aed3-e6577ce8fd89")
+ def test_discovery_direct_concurrency(self):
+ """Verify the behavior of Wi-Fi Aware Ranging used as part of discovery and
+ as direct ranging to a peer device.
+
+ Process:
+ - Start YYY service with ranging in-range
+ - Start XXX service with ranging out-of-range
+ - Start performing direct Ranging
+ - While above going on update XXX to be in-range
+ - Keep performing direct Ranging in context of YYY
+ - Stop direct Ranging and look for XXX to discover
+ """
+ dut1 = self.android_devices[0]
+ dut1.pretty_name = "DUT1"
+ dut2 = self.android_devices[1]
+ dut2.pretty_name = "DUT2"
+
+ # DUTs: attach and wait for confirmation
+ dut1_id = dut1.droid.wifiAwareAttach(False)
+ autils.wait_for_event(dut1, aconsts.EVENT_CB_ON_ATTACHED)
+ time.sleep(self.device_startup_offset)
+ dut2_id = dut2.droid.wifiAwareAttach(True)
+ event = autils.wait_for_event(dut2, aconsts.EVENT_CB_ON_IDENTITY_CHANGED)
+ dut2_mac = event['data']['mac']
+
+ # DUT1: publishers bring-up
+ xxx_p_id = dut1.droid.wifiAwarePublish(dut1_id, autils.add_ranging_to_pub(
+ autils.create_discovery_config("XXX", aconsts.PUBLISH_TYPE_UNSOLICITED),
+ enable_ranging=True), True)
+ autils.wait_for_event(dut1, autils.decorate_event(
+ aconsts.SESSION_CB_ON_PUBLISH_STARTED, xxx_p_id))
+ yyy_p_id = dut1.droid.wifiAwarePublish(dut1_id, autils.add_ranging_to_pub(
+ autils.create_discovery_config("YYY", aconsts.PUBLISH_TYPE_UNSOLICITED),
+ enable_ranging=True), True)
+ autils.wait_for_event(dut1, autils.decorate_event(
+ aconsts.SESSION_CB_ON_PUBLISH_STARTED, yyy_p_id))
+
+ # DUT2: subscribers bring-up
+ xxx_s_id = dut2.droid.wifiAwareSubscribe(dut2_id, autils.add_ranging_to_sub(
+ autils.create_discovery_config("XXX", aconsts.SUBSCRIBE_TYPE_PASSIVE),
+ min_distance_mm=1000000, max_distance_mm=1000001), True)
+ autils.wait_for_event(dut2, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED, xxx_s_id))
+ yyy_s_id = dut2.droid.wifiAwareSubscribe(dut2_id, autils.add_ranging_to_sub(
+ autils.create_discovery_config("YYY", aconsts.SUBSCRIBE_TYPE_PASSIVE),
+ min_distance_mm=None, max_distance_mm=1000000), True)
+ autils.wait_for_event(dut2, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED, yyy_s_id))
+
+ # Service discovery: YYY (with range info), but no XXX
+ event = autils.wait_for_event(dut2, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SERVICE_DISCOVERED, yyy_s_id))
+ asserts.assert_true(aconsts.SESSION_CB_KEY_DISTANCE_MM in event["data"],
+ "Discovery with ranging for YYY expected!")
+ yyy_peer_id_on_sub = event['data'][aconsts.SESSION_CB_KEY_PEER_ID]
+
+ autils.fail_on_event(dut2, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SERVICE_DISCOVERED, xxx_s_id))
+
+ # Direct ranging
+ results21 = []
+ for iter in range(10):
+ id = dut2.droid.wifiRttStartRangingToAwarePeerId(yyy_peer_id_on_sub)
+ event = autils.wait_for_event(dut2, rutils.decorate_event(
+ rconsts.EVENT_CB_RANGING_ON_RESULT, id))
+ results21.append(event["data"][rconsts.EVENT_CB_RANGING_KEY_RESULTS][0])
+
+ time.sleep(5) # while switching roles
+
+ results12 = []
+ for iter in range(10):
+ id = dut1.droid.wifiRttStartRangingToAwarePeerMac(dut2_mac)
+ event = autils.wait_for_event(dut1, rutils.decorate_event(
+ rconsts.EVENT_CB_RANGING_ON_RESULT, id))
+ results12.append(event["data"][rconsts.EVENT_CB_RANGING_KEY_RESULTS][0])
+
+ stats = [rutils.extract_stats(results12, 0, 0, 0),
+ rutils.extract_stats(results21, 0, 0, 0)]
+
+ # Update XXX to be within range
+ dut2.droid.wifiAwareUpdateSubscribe(xxx_s_id, autils.add_ranging_to_sub(
+ autils.create_discovery_config("XXX", aconsts.SUBSCRIBE_TYPE_PASSIVE),
+ min_distance_mm=None, max_distance_mm=1000000))
+ autils.wait_for_event(dut2, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SESSION_CONFIG_UPDATED, xxx_s_id))
+
+ # Expect discovery on XXX - wait until discovery with ranging:
+ # - 0 or more: without ranging info (due to concurrency limitations)
+ # - 1 or more: with ranging (once concurrency limitation relieved)
+ num_events = 0
+ while True:
+ event = autils.wait_for_event(dut2, autils.decorate_event(
+ aconsts.SESSION_CB_ON_SERVICE_DISCOVERED, xxx_s_id))
+ if aconsts.SESSION_CB_KEY_DISTANCE_MM in event["data"]:
+ break
+ num_events = num_events + 1
+ asserts.assert_true(num_events < 10, # arbitrary safety valve
+ "Way too many discovery events without ranging!")
+
+ asserts.explicit_pass("Discovery/Direct RTT Concurrency Pass", extras=stats)
\ No newline at end of file
diff --git a/acts/tests/google/wifi/rtt/functional/RangeApMiscTest.py b/acts/tests/google/wifi/rtt/functional/RangeApMiscTest.py
new file mode 100644
index 0000000..dd5560d
--- /dev/null
+++ b/acts/tests/google/wifi/rtt/functional/RangeApMiscTest.py
@@ -0,0 +1,85 @@
+#!/usr/bin/python3.4
+#
+# Copyright 2017 - The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from acts import asserts
+from acts.test_utils.wifi import wifi_test_utils as wutils
+from acts.test_utils.wifi.rtt import rtt_const as rconsts
+from acts.test_utils.wifi.rtt import rtt_test_utils as rutils
+from acts.test_utils.wifi.rtt.RttBaseTest import RttBaseTest
+
+
+class RangeApMiscTest(RttBaseTest):
+ """Test class for RTT ranging to Access Points - miscellaneous tests which
+ do not fit into the strict IEEE 802.11mc supporting or non-supporting test
+ beds - e.g. a mixed test."""
+
+ # Number of RTT iterations
+ NUM_ITER = 10
+
+ # Time gap (in seconds) between iterations
+ TIME_BETWEEN_ITERATIONS = 0
+
+ def __init__(self, controllers):
+ RttBaseTest.__init__(self, controllers)
+
+ #############################################################################
+
+ def test_rtt_mixed_80211mc_supporting_aps_wo_privilege(self):
+ """Scan for APs and perform RTT on one supporting and one non-supporting
+ IEEE 802.11mc APs with the device not having privilege access (expect
+ failures)."""
+ dut = self.android_devices[0]
+ rutils.config_privilege_override(dut, True)
+ rtt_aps = rutils.scan_with_rtt_support_constraint(dut, True)
+ non_rtt_aps = rutils.scan_with_rtt_support_constraint(dut, False)
+ mix_list = [rtt_aps[0], non_rtt_aps[0]]
+ dut.log.debug("Visible non-IEEE 802.11mc APs=%s", mix_list)
+ events = rutils.run_ranging(dut, mix_list, self.NUM_ITER,
+ self.TIME_BETWEEN_ITERATIONS)
+ stats = rutils.analyze_results(events, self.rtt_reference_distance_mm,
+ self.rtt_reference_distance_margin_mm,
+ self.rtt_min_expected_rssi_dbm,
+ self.lci_reference, self.lcr_reference)
+ dut.log.debug("Stats=%s", stats)
+
+ for bssid, stat in stats.items():
+ asserts.assert_true(stat['num_no_results'] == 0,
+ "Missing (timed-out) results", extras=stats)
+ if bssid == rtt_aps[0][wutils.WifiEnums.BSSID_KEY]:
+ asserts.assert_false(stat['any_lci_mismatch'],
+ "LCI mismatch", extras=stats)
+ asserts.assert_false(stat['any_lcr_mismatch'],
+ "LCR mismatch", extras=stats)
+ asserts.assert_equal(stat['num_invalid_rssi'], 0, "Invalid RSSI",
+ extras=stats)
+ asserts.assert_true(stat['num_failures'] <=
+ self.rtt_max_failure_rate_two_sided_rtt_percentage
+ * stat['num_results'] / 100,
+ "Failure rate is too high", extras=stats)
+ asserts.assert_true(stat['num_range_out_of_margin'] <=
+ self.rtt_max_margin_exceeded_rate_two_sided_rtt_percentage
+ * stat['num_success_results'] / 100,
+ "Results exceeding error margin rate is too high",
+ extras=stats)
+ else:
+ asserts.assert_true(stat['num_failures'] == self.NUM_ITER,
+ "All one-sided RTT requests must fail when executed without privilege",
+ extras=stats)
+ for code in stat['status_codes']:
+ asserts.assert_true(code ==
+ rconsts.EVENT_CB_RANGING_STATUS_RESPONDER_DOES_NOT_SUPPORT_IEEE80211MC,
+ "Expected non-support error code", extras=stats)
+ asserts.explicit_pass("RTT test done", extras=stats)
diff --git a/acts/tests/google/wifi/rtt/functional/RangeApNonSupporting11McTest.py b/acts/tests/google/wifi/rtt/functional/RangeApNonSupporting11McTest.py
new file mode 100644
index 0000000..65b67d2
--- /dev/null
+++ b/acts/tests/google/wifi/rtt/functional/RangeApNonSupporting11McTest.py
@@ -0,0 +1,137 @@
+#!/usr/bin/python3.4
+#
+# Copyright 2017 - The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from acts import asserts
+from acts.test_decorators import test_tracker_info
+from acts.test_utils.wifi.WifiBaseTest import WifiBaseTest
+from acts.test_utils.wifi.rtt import rtt_const as rconsts
+from acts.test_utils.wifi.rtt import rtt_test_utils as rutils
+from acts.test_utils.wifi.rtt.RttBaseTest import RttBaseTest
+
+
+class RangeApNonSupporting11McTest(WifiBaseTest, RttBaseTest):
+ """Test class for RTT ranging to Access Points which do not support IEEE
+ 802.11mc"""
+
+ # Number of RTT iterations
+ NUM_ITER = 10
+
+ # Time gap (in seconds) between iterations
+ TIME_BETWEEN_ITERATIONS = 0
+
+ def __init__(self, controllers):
+ WifiBaseTest.__init__(self, controllers)
+ RttBaseTest.__init__(self, controllers)
+ if "AccessPoint" in self.user_params:
+ self.legacy_configure_ap_and_start()
+
+ #############################################################################
+
+ @test_tracker_info(uuid="cde756e9-11f3-43da-b9ae-9edf85764f82")
+ def test_rtt_non_80211mc_supporting_aps(self):
+ """Scan for APs and perform RTT on non-IEEE 802.11mc supporting APs"""
+ dut = self.android_devices[0]
+ non_rtt_aps = rutils.select_best_scan_results(
+ rutils.scan_with_rtt_support_constraint(dut, False), select_count=1)
+ dut.log.debug("Visible non-IEEE 802.11mc APs=%s", non_rtt_aps)
+ asserts.assert_true(len(non_rtt_aps) > 0, "Need at least one AP!")
+ events = rutils.run_ranging(dut, non_rtt_aps, self.NUM_ITER,
+ self.TIME_BETWEEN_ITERATIONS)
+ stats = rutils.analyze_results(events, self.rtt_reference_distance_mm,
+ self.rtt_reference_distance_margin_mm,
+ self.rtt_min_expected_rssi_dbm,
+ self.lci_reference, self.lcr_reference)
+ dut.log.debug("Stats=%s", stats)
+
+ for bssid, stat in stats.items():
+ asserts.assert_true(stat['num_no_results'] == 0,
+ "Missing (timed-out) results", extras=stats)
+ asserts.assert_false(stat['any_lci_mismatch'],
+ "LCI mismatch", extras=stats)
+ asserts.assert_false(stat['any_lcr_mismatch'],
+ "LCR mismatch", extras=stats)
+ asserts.assert_equal(stat['num_invalid_rssi'], 0, "Invalid RSSI",
+ extras=stats)
+ asserts.assert_true(stat['num_failures'] <=
+ self.rtt_max_failure_rate_one_sided_rtt_percentage
+ * stat['num_results'] / 100,
+ "Failure rate is too high", extras=stats)
+ asserts.assert_true(stat['num_range_out_of_margin'] <=
+ self.rtt_max_margin_exceeded_rate_one_sided_rtt_percentage
+ * stat['num_success_results'] / 100,
+ "Results exceeding error margin rate is too high",
+ extras=stats)
+ asserts.explicit_pass("RTT test done", extras=stats)
+
+ @test_tracker_info(uuid="c9e22185-16d4-4fe6-894f-5823587b3288")
+ def test_rtt_non_80211mc_supporting_aps_wo_privilege(self):
+ """Scan for APs and perform RTT on non-IEEE 802.11mc supporting APs with the
+ device not having privilege access (expect failures)."""
+ dut = self.android_devices[0]
+ rutils.config_privilege_override(dut, True)
+ non_rtt_aps = rutils.select_best_scan_results(
+ rutils.scan_with_rtt_support_constraint(dut, False), select_count=1)
+ dut.log.debug("Visible non-IEEE 802.11mc APs=%s", non_rtt_aps)
+ asserts.assert_true(len(non_rtt_aps) > 0, "Need at least one AP!")
+ events = rutils.run_ranging(dut, non_rtt_aps, self.NUM_ITER,
+ self.TIME_BETWEEN_ITERATIONS)
+ stats = rutils.analyze_results(events, self.rtt_reference_distance_mm,
+ self.rtt_reference_distance_margin_mm,
+ self.rtt_min_expected_rssi_dbm,
+ self.lci_reference, self.lcr_reference)
+ dut.log.debug("Stats=%s", stats)
+
+ for bssid, stat in stats.items():
+ asserts.assert_true(stat['num_no_results'] == 0,
+ "Missing (timed-out) results", extras=stats)
+ asserts.assert_true(stat['num_failures'] == self.NUM_ITER,
+ "All one-sided RTT requests must fail when executed without privilege",
+ extras=stats)
+ for code in stat['status_codes']:
+ asserts.assert_true(code ==
+ rconsts.EVENT_CB_RANGING_STATUS_RESPONDER_DOES_NOT_SUPPORT_IEEE80211MC,
+ "Expected non-support error code", extras=stats)
+ asserts.explicit_pass("RTT test done", extras=stats)
+
+ @test_tracker_info(uuid="e117af56-bd3f-40ae-a2fd-4175f0daa7fa")
+ def test_rtt_non_80211mc_supporting_ap_faked_as_supporting(self):
+ """Scan for APs which do not support IEEE 802.11mc, maliciously modify the
+ Responder config to indicate support and pass-through to service. Verify
+ that get an error result.
+ """
+ dut = self.android_devices[0]
+ non_rtt_aps = rutils.select_best_scan_results(
+ rutils.scan_with_rtt_support_constraint(dut, False), select_count=1)
+ dut.log.debug("Visible non-IEEE 802.11mc APs=%s", non_rtt_aps)
+ asserts.assert_true(len(non_rtt_aps) > 0, "Need at least one AP!")
+ non_rtt_aps = non_rtt_aps[0:1] # pick first
+ non_rtt_aps[0][rconsts.SCAN_RESULT_KEY_RTT_RESPONDER] = True # falsify
+ dut.log.debug("Visible non-IEEE 802.11mc APs=%s", non_rtt_aps)
+ events = rutils.run_ranging(dut, non_rtt_aps, self.NUM_ITER,
+ self.TIME_BETWEEN_ITERATIONS)
+ stats = rutils.analyze_results(events, self.rtt_reference_distance_mm,
+ self.rtt_reference_distance_margin_mm,
+ self.rtt_min_expected_rssi_dbm,
+ self.lci_reference, self.lcr_reference)
+ dut.log.debug("Stats=%s", stats)
+
+ for bssid, stat in stats.items():
+ asserts.assert_true(stat['num_no_results'] == 0,
+ "Missing (timed-out) results", extras=stats)
+ asserts.assert_true(stat['num_failures'] == self.NUM_ITER,
+ "Failures expected for falsified responder config",
+ extras=stats)
+ asserts.explicit_pass("RTT test done", extras=stats)
diff --git a/acts/tests/google/wifi/rtt/functional/RangeApSupporting11McTest.py b/acts/tests/google/wifi/rtt/functional/RangeApSupporting11McTest.py
new file mode 100644
index 0000000..d889a22
--- /dev/null
+++ b/acts/tests/google/wifi/rtt/functional/RangeApSupporting11McTest.py
@@ -0,0 +1,187 @@
+#!/usr/bin/python3.4
+#
+# Copyright 2017 - The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import queue
+
+from acts import asserts
+from acts.test_decorators import test_tracker_info
+from acts.test_utils.wifi import wifi_test_utils as wutils
+from acts.test_utils.wifi.rtt import rtt_const as rconsts
+from acts.test_utils.wifi.rtt import rtt_test_utils as rutils
+from acts.test_utils.wifi.rtt.RttBaseTest import RttBaseTest
+
+
+class RangeApSupporting11McTest(RttBaseTest):
+ """Test class for RTT ranging to Access Points which support IEEE 802.11mc"""
+
+ # Number of RTT iterations
+ NUM_ITER = 10
+
+ # Time gap (in seconds) between iterations
+ TIME_BETWEEN_ITERATIONS = 0
+
+ def __init__(self, controllers):
+ RttBaseTest.__init__(self, controllers)
+
+ #############################################################################
+
+ @test_tracker_info(uuid="6705270f-924b-4bef-b50a-0f0a7eb9ce52")
+ def test_rtt_80211mc_supporting_aps(self):
+ """Scan for APs and perform RTT only to those which support 802.11mc"""
+ dut = self.android_devices[0]
+ rtt_supporting_aps = rutils.select_best_scan_results(
+ rutils.scan_with_rtt_support_constraint(dut, True, repeat=10),
+ select_count=2)
+ dut.log.debug("RTT Supporting APs=%s", rtt_supporting_aps)
+ events = rutils.run_ranging(dut, rtt_supporting_aps, self.NUM_ITER,
+ self.TIME_BETWEEN_ITERATIONS)
+ stats = rutils.analyze_results(events, self.rtt_reference_distance_mm,
+ self.rtt_reference_distance_margin_mm,
+ self.rtt_min_expected_rssi_dbm,
+ self.lci_reference, self.lcr_reference)
+ dut.log.debug("Stats=%s", stats)
+
+ for bssid, stat in stats.items():
+ asserts.assert_true(stat['num_no_results'] == 0,
+ "Missing (timed-out) results", extras=stats)
+ asserts.assert_false(stat['any_lci_mismatch'],
+ "LCI mismatch", extras=stats)
+ asserts.assert_false(stat['any_lcr_mismatch'],
+ "LCR mismatch", extras=stats)
+ asserts.assert_false(stat['invalid_num_attempted'],
+ "Invalid (0) number of attempts", extras=stats)
+ asserts.assert_false(stat['invalid_num_successful'],
+ "Invalid (0) number of successes", extras=stats)
+ asserts.assert_equal(stat['num_invalid_rssi'], 0, "Invalid RSSI",
+ extras=stats)
+ asserts.assert_true(stat['num_failures'] <=
+ self.rtt_max_failure_rate_two_sided_rtt_percentage
+ * stat['num_results'] / 100,
+ "Failure rate is too high", extras=stats)
+ asserts.assert_true(stat['num_range_out_of_margin'] <=
+ self.rtt_max_margin_exceeded_rate_two_sided_rtt_percentage
+ * stat['num_success_results'] / 100,
+ "Results exceeding error margin rate is too high", extras=stats)
+ asserts.explicit_pass("RTT test done", extras=stats)
+
+ #########################################################################
+ #
+ # LEGACY API test code
+ #
+ #########################################################################
+
+ @test_tracker_info(uuid="18be9737-2f03-4e35-9a23-f722dea7b82d")
+ def test_legacy_rtt_80211mc_supporting_aps(self):
+ """Scan for APs and perform RTT only to those which support 802.11mc - using
+ the LEGACY API!"""
+ dut = self.android_devices[0]
+ rtt_supporting_aps = rutils.select_best_scan_results(
+ rutils.scan_with_rtt_support_constraint(dut, True, repeat=10),
+ select_count=2)
+ dut.log.debug("RTT Supporting APs=%s", rtt_supporting_aps)
+
+ rtt_configs = []
+ for ap in rtt_supporting_aps:
+ rtt_configs.append(self.rtt_config_from_scan_result(ap))
+ dut.log.debug("RTT configs=%s", rtt_configs)
+
+ results = []
+ num_missing = 0
+ num_failed_aborted = 0
+ for i in range(self.NUM_ITER):
+ idx = dut.droid.wifiRttStartRanging(rtt_configs)
+ event = None
+ try:
+ events = dut.ed.pop_events("WifiRttRanging%d" % idx, 30)
+ dut.log.debug("Event=%s", events)
+ for event in events:
+ if rconsts.EVENT_CB_RANGING_KEY_RESULTS in event["data"]:
+ results.append(
+ event["data"][rconsts.EVENT_CB_RANGING_KEY_RESULTS])
+ else:
+ self.log.info("RTT failed/aborted - %s", event)
+ results.append([])
+ num_failed_aborted = num_failed_aborted + 1
+ except queue.Empty:
+ self.log.debug("Waiting for RTT event timed out.")
+ results.append([])
+ num_missing = num_missing + 1
+
+ # basic error checking:
+ # 1. no missing
+ # 2. no full failed/aborted (i.e. operation not even tried)
+ # 3. overall (all BSSIDs) success rate > threshold
+ asserts.assert_equal(num_missing, 0,
+ "Missing results (timeout waiting for event)",
+ extras={"data":results})
+ asserts.assert_equal(num_failed_aborted, 0,
+ "Failed or aborted operations (not tried)",
+ extras={"data":results})
+
+ num_results = 0
+ num_errors = 0
+ for result_group in results:
+ num_results = num_results + len(result_group)
+ for result in result_group:
+ if result["status"] != 0:
+ num_errors = num_errors + 1
+
+ extras = [results, {"num_results": num_results, "num_errors": num_errors}]
+ asserts.assert_true(
+ num_errors <= self.rtt_max_failure_rate_two_sided_rtt_percentage
+ * num_results / 100,
+ "Failure rate is too high", extras={"data":extras})
+ asserts.explicit_pass("RTT test done", extras={"data": extras})
+
+ def rtt_config_from_scan_result(self, scan_result):
+ """Creates an Rtt configuration based on the scan result of a network.
+ """
+ WifiEnums = wutils.WifiEnums
+ ScanResult = WifiEnums.ScanResult
+ RttParam = WifiEnums.RttParam
+ RttBW = WifiEnums.RttBW
+ RttPreamble = WifiEnums.RttPreamble
+ RttType = WifiEnums.RttType
+
+ scan_result_channel_width_to_rtt = {
+ ScanResult.CHANNEL_WIDTH_20MHZ: RttBW.BW_20_SUPPORT,
+ ScanResult.CHANNEL_WIDTH_40MHZ: RttBW.BW_40_SUPPORT,
+ ScanResult.CHANNEL_WIDTH_80MHZ: RttBW.BW_80_SUPPORT,
+ ScanResult.CHANNEL_WIDTH_160MHZ: RttBW.BW_160_SUPPORT,
+ ScanResult.CHANNEL_WIDTH_80MHZ_PLUS_MHZ: RttBW.BW_160_SUPPORT
+ }
+ p = {}
+ freq = scan_result[RttParam.frequency]
+ p[RttParam.frequency] = freq
+ p[RttParam.BSSID] = scan_result[WifiEnums.BSSID_KEY]
+ if freq > 5000:
+ p[RttParam.preamble] = RttPreamble.PREAMBLE_VHT
+ else:
+ p[RttParam.preamble] = RttPreamble.PREAMBLE_HT
+ cf0 = scan_result[RttParam.center_freq0]
+ if cf0 > 0:
+ p[RttParam.center_freq0] = cf0
+ cf1 = scan_result[RttParam.center_freq1]
+ if cf1 > 0:
+ p[RttParam.center_freq1] = cf1
+ cw = scan_result["channelWidth"]
+ p[RttParam.channel_width] = cw
+ p[RttParam.bandwidth] = scan_result_channel_width_to_rtt[cw]
+ if scan_result["is80211McRTTResponder"]:
+ p[RttParam.request_type] = RttType.TYPE_TWO_SIDED
+ else:
+ p[RttParam.request_type] = RttType.TYPE_ONE_SIDED
+ return p
diff --git a/acts/tests/google/wifi/rtt/functional/RangeAwareTest.py b/acts/tests/google/wifi/rtt/functional/RangeAwareTest.py
new file mode 100644
index 0000000..d4b7d41
--- /dev/null
+++ b/acts/tests/google/wifi/rtt/functional/RangeAwareTest.py
@@ -0,0 +1,409 @@
+#!/usr/bin/python3.4
+#
+# Copyright 2017 - The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import queue
+import time
+
+from acts import asserts
+from acts.test_decorators import test_tracker_info
+from acts.test_utils.wifi.aware import aware_const as aconsts
+from acts.test_utils.wifi.aware import aware_test_utils as autils
+from acts.test_utils.wifi.aware.AwareBaseTest import AwareBaseTest
+from acts.test_utils.wifi.rtt import rtt_const as rconsts
+from acts.test_utils.wifi.rtt import rtt_test_utils as rutils
+from acts.test_utils.wifi.rtt.RttBaseTest import RttBaseTest
+
+
+class RangeAwareTest(AwareBaseTest, RttBaseTest):
+ """Test class for RTT ranging to Wi-Fi Aware peers"""
+ SERVICE_NAME = "GoogleTestServiceXY"
+
+ # Number of RTT iterations
+ NUM_ITER = 10
+
+ # Time gap (in seconds) between iterations
+ TIME_BETWEEN_ITERATIONS = 0
+
+ # Time gap (in seconds) when switching between Initiator and Responder
+ TIME_BETWEEN_ROLES = 4
+
+ def __init__(self, controllers):
+ AwareBaseTest.__init__(self, controllers)
+ RttBaseTest.__init__(self, controllers)
+
+ def setup_test(self):
+ """Manual setup here due to multiple inheritance: explicitly execute the
+ setup method from both parents."""
+ AwareBaseTest.setup_test(self)
+ RttBaseTest.setup_test(self)
+
+ def teardown_test(self):
+ """Manual teardown here due to multiple inheritance: explicitly execute the
+ teardown method from both parents."""
+ AwareBaseTest.teardown_test(self)
+ RttBaseTest.teardown_test(self)
+
+ #############################################################################
+
+ def run_rtt_discovery(self, init_dut, resp_mac=None, resp_peer_id=None):
+ """Perform single RTT measurement, using Aware, from the Initiator DUT to
+ a Responder. The RTT Responder can be specified using its MAC address
+ (obtained using out- of-band discovery) or its Peer ID (using Aware
+ discovery).
+
+ Args:
+ init_dut: RTT Initiator device
+ resp_mac: MAC address of the RTT Responder device
+ resp_peer_id: Peer ID of the RTT Responder device
+ """
+ asserts.assert_true(resp_mac is not None or resp_peer_id is not None,
+ "One of the Responder specifications (MAC or Peer ID)"
+ " must be provided!")
+ if resp_mac is not None:
+ id = init_dut.droid.wifiRttStartRangingToAwarePeerMac(resp_mac)
+ else:
+ id = init_dut.droid.wifiRttStartRangingToAwarePeerId(resp_peer_id)
+ try:
+ event = init_dut.ed.pop_event(rutils.decorate_event(
+ rconsts.EVENT_CB_RANGING_ON_RESULT, id), rutils.EVENT_TIMEOUT)
+ result = event["data"][rconsts.EVENT_CB_RANGING_KEY_RESULTS][0]
+ if resp_mac is not None:
+ rutils.validate_aware_mac_result(result, resp_mac, "DUT")
+ else:
+ rutils.validate_aware_peer_id_result(result, resp_peer_id, "DUT")
+ return result
+ except queue.Empty:
+ return None
+
+ def run_rtt_ib_discovery_set(self, do_both_directions, iter_count,
+ time_between_iterations, time_between_roles):
+ """Perform a set of RTT measurements, using in-band (Aware) discovery.
+
+ Args:
+ do_both_directions: False - perform all measurements in one direction,
+ True - perform 2 measurements one in both directions.
+ iter_count: Number of measurements to perform.
+ time_between_iterations: Number of seconds to wait between iterations.
+ time_between_roles: Number of seconds to wait when switching between
+ Initiator and Responder roles (only matters if
+ do_both_directions=True).
+
+ Returns: a list of the events containing the RTT results (or None for a
+ failed measurement). If both directions are tested then returns a list of
+ 2 elements: one set for each direction.
+ """
+ p_dut = self.android_devices[0]
+ s_dut = self.android_devices[1]
+
+ (p_id, s_id, p_disc_id, s_disc_id,
+ peer_id_on_sub, peer_id_on_pub) = autils.create_discovery_pair(
+ p_dut,
+ s_dut,
+ p_config=autils.add_ranging_to_pub(autils.create_discovery_config(
+ self.SERVICE_NAME, aconsts.PUBLISH_TYPE_UNSOLICITED), True),
+ s_config=autils.add_ranging_to_pub(autils.create_discovery_config(
+ self.SERVICE_NAME, aconsts.SUBSCRIBE_TYPE_PASSIVE), True),
+ device_startup_offset=self.device_startup_offset,
+ msg_id=self.get_next_msg_id())
+
+ resultsPS = []
+ resultsSP = []
+ for i in range(iter_count):
+ if i != 0 and time_between_iterations != 0:
+ time.sleep(time_between_iterations)
+
+ # perform RTT from pub -> sub
+ resultsPS.append(
+ self.run_rtt_discovery(p_dut, resp_peer_id=peer_id_on_pub))
+
+ if do_both_directions:
+ if time_between_roles != 0:
+ time.sleep(time_between_roles)
+
+ # perform RTT from sub -> pub
+ resultsSP.append(
+ self.run_rtt_discovery(s_dut, resp_peer_id=peer_id_on_sub))
+
+ return resultsPS if not do_both_directions else [resultsPS, resultsSP]
+
+ def run_rtt_oob_discovery_set(self, do_both_directions, iter_count,
+ time_between_iterations, time_between_roles):
+ """Perform a set of RTT measurements, using out-of-band discovery.
+
+ Args:
+ do_both_directions: False - perform all measurements in one direction,
+ True - perform 2 measurements one in both directions.
+ iter_count: Number of measurements to perform.
+ time_between_iterations: Number of seconds to wait between iterations.
+ time_between_roles: Number of seconds to wait when switching between
+ Initiator and Responder roles (only matters if
+ do_both_directions=True).
+ enable_ranging: True to enable Ranging, False to disable.
+
+ Returns: a list of the events containing the RTT results (or None for a
+ failed measurement). If both directions are tested then returns a list of
+ 2 elements: one set for each direction.
+ """
+ dut0 = self.android_devices[0]
+ dut1 = self.android_devices[1]
+
+ id0, mac0 = autils.attach_with_identity(dut0)
+ id1, mac1 = autils.attach_with_identity(dut1)
+
+ # wait for for devices to synchronize with each other - there are no other
+ # mechanisms to make sure this happens for OOB discovery (except retrying
+ # to execute the data-path request)
+ time.sleep(autils.WAIT_FOR_CLUSTER)
+
+ # start publisher(s) on the Responder(s) with ranging enabled
+ p_config = autils.add_ranging_to_pub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.PUBLISH_TYPE_UNSOLICITED),
+ enable_ranging=True)
+ dut1.droid.wifiAwarePublish(id1, p_config)
+ autils.wait_for_event(dut1, aconsts.SESSION_CB_ON_PUBLISH_STARTED)
+ if do_both_directions:
+ dut0.droid.wifiAwarePublish(id0, p_config)
+ autils.wait_for_event(dut0, aconsts.SESSION_CB_ON_PUBLISH_STARTED)
+
+ results01 = []
+ results10 = []
+ for i in range(iter_count):
+ if i != 0 and time_between_iterations != 0:
+ time.sleep(time_between_iterations)
+
+ # perform RTT from dut0 -> dut1
+ results01.append(
+ self.run_rtt_discovery(dut0, resp_mac=mac1))
+
+ if do_both_directions:
+ if time_between_roles != 0:
+ time.sleep(time_between_roles)
+
+ # perform RTT from dut1 -> dut0
+ results10.append(
+ self.run_rtt_discovery(dut1, resp_mac=mac0))
+
+ return results01 if not do_both_directions else [results01, results10]
+
+ def verify_results(self, results, results_reverse_direction=None):
+ """Verifies the results of the RTT experiment.
+
+ Args:
+ results: List of RTT results.
+ results_reverse_direction: List of RTT results executed in the
+ reverse direction. Optional.
+ """
+ stats = rutils.extract_stats(results, self.rtt_reference_distance_mm,
+ self.rtt_reference_distance_margin_mm,
+ self.rtt_min_expected_rssi_dbm)
+ stats_reverse_direction = None
+ if results_reverse_direction is not None:
+ stats_reverse_direction = rutils.extract_stats(results_reverse_direction,
+ self.rtt_reference_distance_mm, self.rtt_reference_distance_margin_mm,
+ self.rtt_min_expected_rssi_dbm)
+ self.log.debug("Stats: %s", stats)
+ if stats_reverse_direction is not None:
+ self.log.debug("Stats in reverse direction: %s", stats_reverse_direction)
+
+ extras = stats if stats_reverse_direction is None else {
+ "forward": stats,
+ "reverse": stats_reverse_direction}
+
+ asserts.assert_true(stats['num_no_results'] == 0,
+ "Missing (timed-out) results", extras=extras)
+ asserts.assert_false(stats['any_lci_mismatch'],
+ "LCI mismatch", extras=extras)
+ asserts.assert_false(stats['any_lcr_mismatch'],
+ "LCR mismatch", extras=extras)
+ asserts.assert_false(stats['invalid_num_attempted'],
+ "Invalid (0) number of attempts", extras=stats)
+ asserts.assert_false(stats['invalid_num_successful'],
+ "Invalid (0) number of successes", extras=stats)
+ asserts.assert_equal(stats['num_invalid_rssi'], 0, "Invalid RSSI",
+ extras=extras)
+ asserts.assert_true(
+ stats['num_failures'] <=
+ self.rtt_max_failure_rate_two_sided_rtt_percentage
+ * stats['num_results'] / 100,
+ "Failure rate is too high", extras=extras)
+ asserts.assert_true(
+ stats['num_range_out_of_margin']
+ <= self.rtt_max_margin_exceeded_rate_two_sided_rtt_percentage
+ * stats['num_success_results'] / 100,
+ "Results exceeding error margin rate is too high", extras=extras)
+
+ if stats_reverse_direction is not None:
+ asserts.assert_true(stats_reverse_direction['num_no_results'] == 0,
+ "Missing (timed-out) results",
+ extras=extras)
+ asserts.assert_false(stats['any_lci_mismatch'],
+ "LCI mismatch", extras=extras)
+ asserts.assert_false(stats['any_lcr_mismatch'],
+ "LCR mismatch", extras=extras)
+ asserts.assert_equal(stats['num_invalid_rssi'], 0, "Invalid RSSI",
+ extras=extras)
+ asserts.assert_true(
+ stats_reverse_direction['num_failures']
+ <= self.rtt_max_failure_rate_two_sided_rtt_percentage
+ * stats['num_results'] / 100,
+ "Failure rate is too high", extras=extras)
+ asserts.assert_true(
+ stats_reverse_direction['num_range_out_of_margin']
+ <= self.rtt_max_margin_exceeded_rate_two_sided_rtt_percentage
+ * stats['num_success_results'] / 100,
+ "Results exceeding error margin rate is too high",
+ extras=extras)
+
+ asserts.explicit_pass("RTT Aware test done", extras=extras)
+
+ #############################################################################
+
+ @test_tracker_info(uuid="9e4e7ab4-2254-498c-9788-21e15ed9a370")
+ def test_rtt_oob_discovery_one_way(self):
+ """Perform RTT between 2 Wi-Fi Aware devices. Use out-of-band discovery
+ to communicate the MAC addresses to the peer. Test one-direction RTT only.
+ """
+ rtt_results = self.run_rtt_oob_discovery_set(do_both_directions=False,
+ iter_count=self.NUM_ITER,
+ time_between_iterations=self.TIME_BETWEEN_ITERATIONS,
+ time_between_roles=self.TIME_BETWEEN_ROLES)
+ self.verify_results(rtt_results)
+
+ @test_tracker_info(uuid="22edba77-eeb2-43ee-875a-84437550ad84")
+ def test_rtt_oob_discovery_both_ways(self):
+ """Perform RTT between 2 Wi-Fi Aware devices. Use out-of-band discovery
+ to communicate the MAC addresses to the peer. Test RTT both-ways:
+ switching rapidly between Initiator and Responder.
+ """
+ rtt_results1, rtt_results2 = self.run_rtt_oob_discovery_set(
+ do_both_directions=True, iter_count=self.NUM_ITER,
+ time_between_iterations=self.TIME_BETWEEN_ITERATIONS,
+ time_between_roles=self.TIME_BETWEEN_ROLES)
+ self.verify_results(rtt_results1, rtt_results2)
+
+ @test_tracker_info(uuid="18cef4be-95b4-4f7d-a140-5165874e7d1c")
+ def test_rtt_ib_discovery_one_way(self):
+ """Perform RTT between 2 Wi-Fi Aware devices. Use in-band (Aware) discovery
+ to communicate the MAC addresses to the peer. Test one-direction RTT only.
+ """
+ rtt_results = self.run_rtt_ib_discovery_set(do_both_directions=False,
+ iter_count=self.NUM_ITER,
+ time_between_iterations=self.TIME_BETWEEN_ITERATIONS,
+ time_between_roles=self.TIME_BETWEEN_ROLES)
+ self.verify_results(rtt_results)
+
+ @test_tracker_info(uuid="c67c8e70-c417-42d9-9bca-af3a89f1ddd9")
+ def test_rtt_ib_discovery_both_ways(self):
+ """Perform RTT between 2 Wi-Fi Aware devices. Use in-band (Aware) discovery
+ to communicate the MAC addresses to the peer. Test RTT both-ways:
+ switching rapidly between Initiator and Responder.
+ """
+ rtt_results1, rtt_results2 = self.run_rtt_ib_discovery_set(
+ do_both_directions=True, iter_count=self.NUM_ITER,
+ time_between_iterations=self.TIME_BETWEEN_ITERATIONS,
+ time_between_roles=self.TIME_BETWEEN_ROLES)
+ self.verify_results(rtt_results1, rtt_results2)
+
+ @test_tracker_info(uuid="54f9693d-45e5-4979-adbb-1b875d217c0c")
+ def test_rtt_without_initiator_aware(self):
+ """Try to perform RTT operation when there is no local Aware session (on the
+ Initiator). The Responder is configured normally: Aware on and a Publisher
+ with Ranging enable. Should FAIL."""
+ init_dut = self.android_devices[0]
+ resp_dut = self.android_devices[1]
+
+ # Enable a Responder and start a Publisher
+ resp_id = resp_dut.droid.wifiAwareAttach(True)
+ autils.wait_for_event(resp_dut, aconsts.EVENT_CB_ON_ATTACHED)
+ resp_ident_event = autils.wait_for_event(resp_dut,
+ aconsts.EVENT_CB_ON_IDENTITY_CHANGED)
+ resp_mac = resp_ident_event['data']['mac']
+
+ resp_config = autils.add_ranging_to_pub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.PUBLISH_TYPE_UNSOLICITED),
+ enable_ranging=True)
+ resp_dut.droid.wifiAwarePublish(resp_id, resp_config)
+ autils.wait_for_event(resp_dut, aconsts.SESSION_CB_ON_PUBLISH_STARTED)
+
+ # Initiate an RTT to Responder (no Aware started on Initiator!)
+ results = []
+ num_no_responses = 0
+ num_successes = 0
+ for i in range(self.NUM_ITER):
+ result = self.run_rtt_discovery(init_dut, resp_mac=resp_mac)
+ self.log.debug("result: %s", result)
+ results.append(result)
+ if result is None:
+ num_no_responses = num_no_responses + 1
+ elif (result[rconsts.EVENT_CB_RANGING_KEY_STATUS]
+ == rconsts.EVENT_CB_RANGING_STATUS_SUCCESS):
+ num_successes = num_successes + 1
+
+ asserts.assert_equal(num_no_responses, 0, "No RTT response?",
+ extras={"data":results})
+ asserts.assert_equal(num_successes, 0, "Aware RTT w/o Aware should FAIL!",
+ extras={"data":results})
+ asserts.explicit_pass("RTT Aware test done", extras={"data":results})
+
+ @test_tracker_info(uuid="87a69053-8261-4928-8ec1-c93aac7f3a8d")
+ def test_rtt_without_responder_aware(self):
+ """Try to perform RTT operation when there is no peer Aware session (on the
+ Responder). Should FAIL."""
+ init_dut = self.android_devices[0]
+ resp_dut = self.android_devices[1]
+
+ # Enable a Responder and start a Publisher
+ resp_id = resp_dut.droid.wifiAwareAttach(True)
+ autils.wait_for_event(resp_dut, aconsts.EVENT_CB_ON_ATTACHED)
+ resp_ident_event = autils.wait_for_event(resp_dut,
+ aconsts.EVENT_CB_ON_IDENTITY_CHANGED)
+ resp_mac = resp_ident_event['data']['mac']
+
+ resp_config = autils.add_ranging_to_pub(
+ autils.create_discovery_config(self.SERVICE_NAME,
+ aconsts.PUBLISH_TYPE_UNSOLICITED),
+ enable_ranging=True)
+ resp_dut.droid.wifiAwarePublish(resp_id, resp_config)
+ autils.wait_for_event(resp_dut, aconsts.SESSION_CB_ON_PUBLISH_STARTED)
+
+ # Disable Responder
+ resp_dut.droid.wifiAwareDestroy(resp_id)
+
+ # Enable the Initiator
+ init_id = init_dut.droid.wifiAwareAttach()
+ autils.wait_for_event(init_dut, aconsts.EVENT_CB_ON_ATTACHED)
+
+ # Initiate an RTT to Responder (no Aware started on Initiator!)
+ results = []
+ num_no_responses = 0
+ num_successes = 0
+ for i in range(self.NUM_ITER):
+ result = self.run_rtt_discovery(init_dut, resp_mac=resp_mac)
+ self.log.debug("result: %s", result)
+ results.append(result)
+ if result is None:
+ num_no_responses = num_no_responses + 1
+ elif (result[rconsts.EVENT_CB_RANGING_KEY_STATUS]
+ == rconsts.EVENT_CB_RANGING_STATUS_SUCCESS):
+ num_successes = num_successes + 1
+
+ asserts.assert_equal(num_no_responses, 0, "No RTT response?",
+ extras={"data":results})
+ asserts.assert_equal(num_successes, 0, "Aware RTT w/o Aware should FAIL!",
+ extras={"data":results})
+ asserts.explicit_pass("RTT Aware test done", extras={"data":results})
diff --git a/acts/tests/google/wifi/rtt/functional/RangeSoftApTest.py b/acts/tests/google/wifi/rtt/functional/RangeSoftApTest.py
new file mode 100644
index 0000000..f0c4f4c
--- /dev/null
+++ b/acts/tests/google/wifi/rtt/functional/RangeSoftApTest.py
@@ -0,0 +1,95 @@
+#!/usr/bin/python3.4
+#
+# Copyright 2018 - The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from acts import asserts
+from acts.test_decorators import test_tracker_info
+from acts.test_utils.tel.tel_test_utils import WIFI_CONFIG_APBAND_5G
+from acts.test_utils.wifi import wifi_test_utils as wutils
+from acts.test_utils.wifi.rtt import rtt_const as rconsts
+from acts.test_utils.wifi.rtt import rtt_test_utils as rutils
+from acts.test_utils.wifi.rtt.RttBaseTest import RttBaseTest
+
+
+class RangeSoftApTest(RttBaseTest):
+ """Test class for RTT ranging to an Android Soft AP."""
+
+ # Soft AP SSID
+ SOFT_AP_SSID = "RTT_TEST_SSID"
+
+ # Soft AP Password (irrelevant)
+ SOFT_AP_PASSWORD = "ABCDEFGH"
+
+ # Number of RTT iterations
+ NUM_ITER = 10
+
+ def __init__(self, controllers):
+ RttBaseTest.__init__(self, controllers)
+
+ #########################################################################
+
+ @test_tracker_info(uuid="578f0725-31e3-4e60-ad62-0212d93cf5b8")
+ def test_rtt_to_soft_ap(self):
+ """Set up a Soft AP on one device and try performing an RTT ranging to it
+ from another device. The attempt must fail - RTT on Soft AP must be
+ disabled."""
+ sap = self.android_devices[0]
+ sap.pretty_name = "SoftAP"
+ client = self.android_devices[1]
+ client.pretty_name = "Client"
+
+ # start Soft AP
+ wutils.start_wifi_tethering(sap, self.SOFT_AP_SSID, self.SOFT_AP_PASSWORD,
+ band=WIFI_CONFIG_APBAND_5G, hidden=False)
+
+ try:
+ # start scanning on the client
+ wutils.start_wifi_connection_scan_and_ensure_network_found(client,
+ self.SOFT_AP_SSID)
+ scans = client.droid.wifiGetScanResults()
+ scanned_softap = None
+ for scanned_ap in scans:
+ if scanned_ap[wutils.WifiEnums.SSID_KEY] == self.SOFT_AP_SSID:
+ scanned_softap = scanned_ap
+ break
+
+ asserts.assert_false(scanned_softap == None, "Soft AP not found in scan!",
+ extras=scans)
+
+ # validate that Soft AP does not advertise 802.11mc support
+ asserts.assert_false(
+ rconsts.SCAN_RESULT_KEY_RTT_RESPONDER in scanned_softap and
+ scanned_softap[rconsts.SCAN_RESULT_KEY_RTT_RESPONDER],
+ "Soft AP advertises itself as supporting 802.11mc!",
+ extras=scanned_softap)
+
+ # falsify the SoftAP's support for IEEE 802.11 so we try a 2-sided RTT
+ scanned_softap[rconsts.SCAN_RESULT_KEY_RTT_RESPONDER] = True # falsify
+
+ # actually try ranging to the Soft AP
+ events = rutils.run_ranging(client, [scanned_softap], self.NUM_ITER, 0)
+ stats = rutils.analyze_results(events, self.rtt_reference_distance_mm,
+ self.rtt_reference_distance_margin_mm,
+ self.rtt_min_expected_rssi_dbm,
+ self.lci_reference, self.lcr_reference)
+
+ asserts.assert_equal(
+ stats[scanned_ap[wutils.WifiEnums.BSSID_KEY]]['num_failures'],
+ self.NUM_ITER, "Some RTT operations to Soft AP succeed!?",
+ extras=stats)
+
+ asserts.explicit_pass("SoftAP + RTT validation done", extras=events)
+ finally:
+ wutils.stop_wifi_tethering(sap)
diff --git a/acts/tests/google/wifi/rtt/functional/RttDisableTest.py b/acts/tests/google/wifi/rtt/functional/RttDisableTest.py
new file mode 100644
index 0000000..1816cd5
--- /dev/null
+++ b/acts/tests/google/wifi/rtt/functional/RttDisableTest.py
@@ -0,0 +1,109 @@
+#!/usr/bin/python3.4
+#
+# Copyright 2017 - The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from acts import asserts
+from acts import utils
+from acts.test_decorators import test_tracker_info
+from acts.test_utils.wifi.rtt import rtt_const as rconsts
+from acts.test_utils.wifi.rtt import rtt_test_utils as rutils
+from acts.test_utils.wifi.rtt.RttBaseTest import RttBaseTest
+from acts.test_utils.wifi.WifiBaseTest import WifiBaseTest
+
+
+class RttDisableTest(WifiBaseTest, RttBaseTest):
+ """Test class for RTT ranging enable/disable flows."""
+
+ MODE_DISABLE_WIFI = 0
+ MODE_ENABLE_DOZE = 1
+ MODE_DISABLE_LOCATIONING = 2
+
+ def __init__(self, controllers):
+ WifiBaseTest.__init__(self, controllers)
+ RttBaseTest.__init__(self, controllers)
+ if "AccessPoint" in self.user_params:
+ self.legacy_configure_ap_and_start()
+
+ def run_disable_rtt(self, disable_mode):
+ """Validate the RTT disabled flows: whether by disabling Wi-Fi or entering
+ doze mode.
+
+ Args:
+ disable_mode: The particular mechanism in which RTT is disabled. One of
+ the MODE_* constants.
+ """
+ dut = self.android_devices[0]
+
+ # validate start-up conditions
+ asserts.assert_true(dut.droid.wifiIsRttAvailable(), "RTT is not available")
+
+ # scan to get some APs to be used later
+ all_aps = rutils.select_best_scan_results(rutils.scan_networks(dut),
+ select_count=1)
+ asserts.assert_true(len(all_aps) > 0, "Need at least one visible AP!")
+
+ # disable RTT and validate broadcast & API
+ if disable_mode == self.MODE_DISABLE_WIFI:
+ # disabling Wi-Fi is not sufficient: since scan mode (and hence RTT) will
+ # remain enabled - we need to disable the Wi-Fi chip aka Airplane Mode
+ asserts.assert_true(utils.force_airplane_mode(dut, True),
+ "Can not turn on airplane mode on: %s" % dut.serial)
+ elif disable_mode == self.MODE_ENABLE_DOZE:
+ asserts.assert_true(utils.enable_doze(dut), "Can't enable doze")
+ elif disable_mode == self.MODE_DISABLE_LOCATIONING:
+ utils.set_location_service(dut, False)
+
+ rutils.wait_for_event(dut, rconsts.BROADCAST_WIFI_RTT_NOT_AVAILABLE)
+ asserts.assert_false(dut.droid.wifiIsRttAvailable(), "RTT is available")
+
+ # request a range and validate error
+ id = dut.droid.wifiRttStartRangingToAccessPoints(all_aps[0:1])
+ event = rutils.wait_for_event(dut, rutils.decorate_event(
+ rconsts.EVENT_CB_RANGING_ON_FAIL, id))
+ asserts.assert_equal(event["data"][rconsts.EVENT_CB_RANGING_KEY_STATUS],
+ rconsts.RANGING_FAIL_CODE_RTT_NOT_AVAILABLE,
+ "Invalid error code")
+
+ # enable RTT and validate broadcast & API
+ if disable_mode == self.MODE_DISABLE_WIFI:
+ asserts.assert_true(utils.force_airplane_mode(dut, False),
+ "Can not turn off airplane mode on: %s" % dut.serial)
+ elif disable_mode == self.MODE_ENABLE_DOZE:
+ asserts.assert_true(utils.disable_doze(dut), "Can't disable doze")
+ elif disable_mode == self.MODE_DISABLE_LOCATIONING:
+ utils.set_location_service(dut, True)
+
+ rutils.wait_for_event(dut, rconsts.BROADCAST_WIFI_RTT_AVAILABLE)
+ asserts.assert_true(dut.droid.wifiIsRttAvailable(), "RTT is not available")
+
+ ############################################################################
+
+ @test_tracker_info(uuid="498c49ab-a188-4612-998d-c47b35ff285e")
+ def test_disable_wifi(self):
+ """Validate that getting expected broadcast when Wi-Fi is disabled and that
+ any range requests are rejected."""
+ self.run_disable_rtt(self.MODE_DISABLE_WIFI)
+
+ @test_tracker_info(uuid="f71f731f-4aaf-402b-8595-db94b625b544")
+ def test_enable_doze(self):
+ """Validate that getting expected broadcast when RTT is disabled due to doze
+ mode and that any range requests are rejected."""
+ self.run_disable_rtt(self.MODE_ENABLE_DOZE)
+
+ @test_tracker_info(uuid="6a1c83a8-9eaf-49db-b547-5131cba0eafe")
+ def test_disable_location(self):
+ """Validate that getting expected broadcast when locationing is disabled and
+ that any range requests are rejected."""
+ self.run_disable_rtt(self.MODE_DISABLE_LOCATIONING)
diff --git a/acts/tests/google/wifi/rtt/functional/RttRequestManagementTest.py b/acts/tests/google/wifi/rtt/functional/RttRequestManagementTest.py
new file mode 100644
index 0000000..82c1058
--- /dev/null
+++ b/acts/tests/google/wifi/rtt/functional/RttRequestManagementTest.py
@@ -0,0 +1,140 @@
+#!/usr/bin/python3.4
+#
+# Copyright 2017 - The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import random
+import time
+
+from acts import asserts
+from acts.test_decorators import test_tracker_info
+from acts.test_utils.wifi.rtt import rtt_const as rconsts
+from acts.test_utils.wifi.rtt import rtt_test_utils as rutils
+from acts.test_utils.wifi.rtt.RttBaseTest import RttBaseTest
+
+
+class RttRequestManagementTest(RttBaseTest):
+ """Test class for RTT request management flows."""
+
+ SPAMMING_LIMIT = 20
+
+ def __init__(self, controllers):
+ RttBaseTest.__init__(self, controllers)
+
+ #############################################################################
+
+ @test_tracker_info(uuid="29ff4a02-2952-47df-bf56-64f30c963093")
+ def test_cancel_ranging(self):
+ """Request a 'large' number of range operations with various UIDs (using the
+ work-source API), then cancel some of them.
+
+ We can't guarantee a reaction time - it is possible that a cancelled test
+ was already finished and it's results dispatched back. The test therefore
+ stacks the request queue. The sequence is:
+
+ - Request:
+ - 50 tests @ UIDs = {uid1, uid2, uid3}
+ - 2 tests @ UIDs = {uid2, uid3}
+ - 1 test2 @ UIDs = {uid1, uid2, uid3}
+ - Cancel UIDs = {uid2, uid3}
+
+ Expect to receive only 51 results.
+ """
+ dut = self.android_devices[0]
+ max_peers = dut.droid.wifiRttMaxPeersInRequest()
+
+ all_uids = [1000, 20, 30] # 1000 = System Server (makes requests foreground)
+ some_uids = [20, 30]
+
+ aps = rutils.select_best_scan_results(
+ rutils.scan_with_rtt_support_constraint(dut, True, repeat=10),
+ select_count=1)
+ dut.log.info("RTT Supporting APs=%s", aps)
+
+ asserts.assert_true(
+ len(aps) > 0,
+ "Need at least one AP which supports 802.11mc!")
+ if len(aps) > max_peers:
+ aps = aps[0:max_peers]
+
+ group1_ids = []
+ group2_ids = []
+ group3_ids = []
+
+ # step 1: request <spam_limit> ranging operations on [uid1, uid2, uid3]
+ for i in range(self.SPAMMING_LIMIT):
+ group1_ids.append(
+ dut.droid.wifiRttStartRangingToAccessPoints(aps, all_uids))
+
+ # step 2: request 2 ranging operations on [uid2, uid3]
+ for i in range(2):
+ group2_ids.append(
+ dut.droid.wifiRttStartRangingToAccessPoints(aps, some_uids))
+
+ # step 3: request 1 ranging operation on [uid1, uid2, uid3]
+ for i in range(1):
+ group3_ids.append(
+ dut.droid.wifiRttStartRangingToAccessPoints(aps, all_uids))
+
+ # step 4: cancel ranging requests on [uid2, uid3]
+ dut.droid.wifiRttCancelRanging(some_uids)
+
+ # collect results
+ for i in range(len(group1_ids)):
+ rutils.wait_for_event(dut, rutils.decorate_event(
+ rconsts.EVENT_CB_RANGING_ON_RESULT, group1_ids[i]))
+ time.sleep(rutils.EVENT_TIMEOUT) # optimize time-outs below to single one
+ for i in range(len(group2_ids)):
+ rutils.fail_on_event(dut, rutils.decorate_event(
+ rconsts.EVENT_CB_RANGING_ON_RESULT, group2_ids[i]), 0)
+ for i in range(len(group3_ids)):
+ rutils.wait_for_event(dut, rutils.decorate_event(
+ rconsts.EVENT_CB_RANGING_ON_RESULT, group3_ids[i]))
+
+ @test_tracker_info(uuid="48297480-c026-4780-8c13-476e7bea440c")
+ def test_throttling(self):
+ """Request sequential range operations using a bogus UID (which will
+ translate as a throttled process) and similarly using the ACTS/sl4a as
+ the source (a foreground/unthrottled process)."""
+ dut = self.android_devices[0]
+ max_peers = dut.droid.wifiRttMaxPeersInRequest()
+
+ # Need to use a random number since the system keeps states and so the
+ # background uid will be throttled on the next run of this script
+ fake_uid = [random.randint(10, 9999)]
+
+ aps = rutils.select_best_scan_results(
+ rutils.scan_with_rtt_support_constraint(dut, True, repeat=10),
+ select_count=1)
+ dut.log.info("RTT Supporting APs=%s", aps)
+
+ asserts.assert_true(
+ len(aps) > 0,
+ "Need at least one AP which supports 802.11mc!")
+ if len(aps) > max_peers:
+ aps = aps[0:max_peers]
+
+ id1 = dut.droid.wifiRttStartRangingToAccessPoints(aps) # as ACTS/sl4a
+ id2 = dut.droid.wifiRttStartRangingToAccessPoints(aps, fake_uid)
+ id3 = dut.droid.wifiRttStartRangingToAccessPoints(aps, fake_uid)
+ id4 = dut.droid.wifiRttStartRangingToAccessPoints(aps) # as ACTS/sl4a
+
+ rutils.wait_for_event(dut, rutils.decorate_event(
+ rconsts.EVENT_CB_RANGING_ON_RESULT, id1))
+ rutils.wait_for_event(dut, rutils.decorate_event(
+ rconsts.EVENT_CB_RANGING_ON_RESULT, id2))
+ rutils.wait_for_event(dut, rutils.decorate_event(
+ rconsts.EVENT_CB_RANGING_ON_FAIL, id3))
+ rutils.wait_for_event(dut, rutils.decorate_event(
+ rconsts.EVENT_CB_RANGING_ON_RESULT, id4))
diff --git a/acts/tests/google/wifi/rtt/stress/StressRangeApTest.py b/acts/tests/google/wifi/rtt/stress/StressRangeApTest.py
new file mode 100644
index 0000000..497c125
--- /dev/null
+++ b/acts/tests/google/wifi/rtt/stress/StressRangeApTest.py
@@ -0,0 +1,79 @@
+#!/usr/bin/python3.4
+#
+# Copyright 2017 - The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from acts import asserts
+from acts.base_test import BaseTestClass
+from acts.test_utils.wifi.rtt import rtt_test_utils as rutils
+from acts.test_utils.wifi.rtt.RttBaseTest import RttBaseTest
+
+
+class StressRangeApTest(RttBaseTest):
+ """Test class for stress testing of RTT ranging to Access Points"""
+
+ def __init__(self, controllers):
+ BaseTestClass.__init__(self, controllers)
+
+ #############################################################################
+
+ def test_rtt_supporting_ap_only(self):
+ """Scan for APs and perform RTT only to those which support 802.11mc.
+
+ Stress test: repeat ranging to the same AP. Verify rate of success and
+ stability of results.
+ """
+ dut = self.android_devices[0]
+ rtt_supporting_aps = rutils.scan_with_rtt_support_constraint(dut, True,
+ repeat=10)
+ dut.log.debug("RTT Supporting APs=%s", rtt_supporting_aps)
+
+ num_iter = self.stress_test_min_iteration_count
+
+ max_peers = dut.droid.wifiRttMaxPeersInRequest()
+ asserts.assert_true(
+ len(rtt_supporting_aps) > 0,
+ "Need at least one AP which supports 802.11mc!")
+ if len(rtt_supporting_aps) > max_peers:
+ rtt_supporting_aps = rtt_supporting_aps[0:max_peers]
+
+ events = rutils.run_ranging(dut, rtt_supporting_aps, num_iter, 0,
+ self.stress_test_target_run_time_sec)
+ stats = rutils.analyze_results(events, self.rtt_reference_distance_mm,
+ self.rtt_reference_distance_margin_mm,
+ self.rtt_min_expected_rssi_dbm,
+ self.lci_reference, self.lcr_reference,
+ summary_only=True)
+ dut.log.debug("Stats=%s", stats)
+
+ for bssid, stat in stats.items():
+ asserts.assert_true(stat['num_no_results'] == 0,
+ "Missing (timed-out) results", extras=stats)
+ asserts.assert_false(stat['any_lci_mismatch'],
+ "LCI mismatch", extras=stats)
+ asserts.assert_false(stat['any_lcr_mismatch'],
+ "LCR mismatch", extras=stats)
+ asserts.assert_equal(stat['num_invalid_rssi'], 0, "Invalid RSSI",
+ extras=stats)
+ asserts.assert_true(stat['num_failures'] <=
+ self.rtt_max_failure_rate_two_sided_rtt_percentage
+ * stat['num_results'] / 100,
+ "Failure rate is too high", extras=stats)
+ asserts.assert_true(stat['num_range_out_of_margin'] <=
+ self.rtt_max_margin_exceeded_rate_two_sided_rtt_percentage
+ * stat['num_success_results'] / 100,
+ "Results exceeding error margin rate is too high",
+ extras=stats)
+ asserts.explicit_pass("RTT test done", extras=stats)
+
diff --git a/acts/tests/google/wifi/rtt/stress/StressRangeAwareTest.py b/acts/tests/google/wifi/rtt/stress/StressRangeAwareTest.py
new file mode 100644
index 0000000..3073898
--- /dev/null
+++ b/acts/tests/google/wifi/rtt/stress/StressRangeAwareTest.py
@@ -0,0 +1,137 @@
+#!/usr/bin/python3.4
+#
+# Copyright 2018 - The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import queue
+import time
+
+from acts import asserts
+from acts.test_utils.wifi.aware import aware_const as aconsts
+from acts.test_utils.wifi.aware import aware_test_utils as autils
+from acts.test_utils.wifi.aware.AwareBaseTest import AwareBaseTest
+from acts.test_utils.wifi.rtt import rtt_const as rconsts
+from acts.test_utils.wifi.rtt import rtt_test_utils as rutils
+from acts.test_utils.wifi.rtt.RttBaseTest import RttBaseTest
+
+
+class StressRangeAwareTest(AwareBaseTest, RttBaseTest):
+ """Test class for stress testing of RTT ranging to Wi-Fi Aware peers."""
+ SERVICE_NAME = "GoogleTestServiceXY"
+
+ def __init__(self, controllers):
+ AwareBaseTest.__init__(self, controllers)
+ RttBaseTest.__init__(self, controllers)
+
+ def setup_test(self):
+ """Manual setup here due to multiple inheritance: explicitly execute the
+ setup method from both parents."""
+ AwareBaseTest.setup_test(self)
+ RttBaseTest.setup_test(self)
+
+ def teardown_test(self):
+ """Manual teardown here due to multiple inheritance: explicitly execute the
+ teardown method from both parents."""
+ AwareBaseTest.teardown_test(self)
+ RttBaseTest.teardown_test(self)
+
+ #############################################################################
+
+ def run_rtt_discovery(self, init_dut, resp_mac=None, resp_peer_id=None):
+ """Perform single RTT measurement, using Aware, from the Initiator DUT to
+ a Responder. The RTT Responder can be specified using its MAC address
+ (obtained using out- of-band discovery) or its Peer ID (using Aware
+ discovery).
+
+ Args:
+ init_dut: RTT Initiator device
+ resp_mac: MAC address of the RTT Responder device
+ resp_peer_id: Peer ID of the RTT Responder device
+ """
+ asserts.assert_true(resp_mac is not None or resp_peer_id is not None,
+ "One of the Responder specifications (MAC or Peer ID)"
+ " must be provided!")
+ if resp_mac is not None:
+ id = init_dut.droid.wifiRttStartRangingToAwarePeerMac(resp_mac)
+ else:
+ id = init_dut.droid.wifiRttStartRangingToAwarePeerId(resp_peer_id)
+ try:
+ event = init_dut.ed.pop_event(rutils.decorate_event(
+ rconsts.EVENT_CB_RANGING_ON_RESULT, id), rutils.EVENT_TIMEOUT)
+ result = event["data"][rconsts.EVENT_CB_RANGING_KEY_RESULTS][0]
+ if resp_mac is not None:
+ rutils.validate_aware_mac_result(result, resp_mac, "DUT")
+ else:
+ rutils.validate_aware_peer_id_result(result, resp_peer_id, "DUT")
+ return result
+ except queue.Empty:
+ return None
+
+ def test_stress_rtt_ib_discovery_set(self):
+ """Perform a set of RTT measurements, using in-band (Aware) discovery, and
+ switching Initiator and Responder roles repeatedly.
+
+ Stress test: repeat ranging operations. Verify rate of success and
+ stability of results.
+ """
+ p_dut = self.android_devices[0]
+ s_dut = self.android_devices[1]
+
+ (p_id, s_id, p_disc_id, s_disc_id,
+ peer_id_on_sub, peer_id_on_pub) = autils.create_discovery_pair(
+ p_dut,
+ s_dut,
+ p_config=autils.add_ranging_to_pub(autils.create_discovery_config(
+ self.SERVICE_NAME, aconsts.PUBLISH_TYPE_UNSOLICITED), True),
+ s_config=autils.add_ranging_to_pub(autils.create_discovery_config(
+ self.SERVICE_NAME, aconsts.SUBSCRIBE_TYPE_PASSIVE), True),
+ device_startup_offset=self.device_startup_offset,
+ msg_id=self.get_next_msg_id())
+
+ results = []
+ start_clock = time.time()
+ iterations_done = 0
+ run_time = 0
+ while iterations_done < self.stress_test_min_iteration_count or (
+ self.stress_test_target_run_time_sec != 0
+ and run_time < self.stress_test_target_run_time_sec):
+ results.append(self.run_rtt_discovery(p_dut, resp_peer_id=peer_id_on_pub))
+ results.append(self.run_rtt_discovery(s_dut, resp_peer_id=peer_id_on_sub))
+
+ iterations_done = iterations_done + 1
+ run_time = time.time() - start_clock
+
+ stats = rutils.extract_stats(results, self.rtt_reference_distance_mm,
+ self.rtt_reference_distance_margin_mm,
+ self.rtt_min_expected_rssi_dbm,
+ summary_only=True)
+ self.log.debug("Stats: %s", stats)
+ asserts.assert_true(stats['num_no_results'] == 0,
+ "Missing (timed-out) results", extras=stats)
+ asserts.assert_false(stats['any_lci_mismatch'],
+ "LCI mismatch", extras=stats)
+ asserts.assert_false(stats['any_lcr_mismatch'],
+ "LCR mismatch", extras=stats)
+ asserts.assert_equal(stats['num_invalid_rssi'], 0, "Invalid RSSI",
+ extras=stats)
+ asserts.assert_true(
+ stats['num_failures'] <=
+ self.rtt_max_failure_rate_two_sided_rtt_percentage
+ * stats['num_results'] / 100,
+ "Failure rate is too high", extras=stats)
+ asserts.assert_true(
+ stats['num_range_out_of_margin']
+ <= self.rtt_max_margin_exceeded_rate_two_sided_rtt_percentage
+ * stats['num_success_results'] / 100,
+ "Results exceeding error margin rate is too high", extras=stats)