1#!/usr/bin/env python3.4 2# 3# Copyright 2018 - The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17import itertools 18import pprint 19import queue 20import time 21 22import acts.base_test 23import acts.signals as signals 24from acts.test_utils.tel.tel_test_utils import WIFI_CONFIG_APBAND_2G 25from acts.test_utils.tel.tel_test_utils import WIFI_CONFIG_APBAND_5G 26import acts.test_utils.wifi.wifi_test_utils as wutils 27import acts.utils as utils 28 29from acts import asserts 30from acts.test_decorators import test_tracker_info 31from acts.test_utils.wifi.WifiBaseTest import WifiBaseTest 32 33WifiEnums = wutils.WifiEnums 34 35# Channels to configure the AP for various test scenarios. 36WIFI_NETWORK_AP_CHANNEL_2G = 1 37WIFI_NETWORK_AP_CHANNEL_5G = 36 38WIFI_NETWORK_AP_CHANNEL_5G_DFS = 132 39 40class WifiStaApConcurrencyTest(WifiBaseTest): 41 """Tests for STA + AP concurrency scenarios. 42 43 Test Bed Requirement: 44 * Two Android devices (For AP) 45 * One Wi-Fi network visible to the device (for STA). 46 """ 47 48 def __init__(self, controllers): 49 WifiBaseTest.__init__(self, controllers) 50 51 def setup_class(self): 52 self.dut = self.android_devices[0] 53 self.dut_client = self.android_devices[1] 54 wutils.wifi_test_device_init(self.dut) 55 wutils.wifi_test_device_init(self.dut_client) 56 # Do a simple version of init - mainly just sync the time and enable 57 # verbose logging. This test will fail if the DUT has a sim and cell 58 # data is disabled. We would also like to test with phones in less 59 # constrained states (or add variations where we specifically 60 # constrain). 61 utils.require_sl4a((self.dut, self.dut_client)) 62 utils.sync_device_time(self.dut) 63 utils.sync_device_time(self.dut_client) 64 # Set country code explicitly to "US". 65 self.dut.droid.wifiSetCountryCode(wutils.WifiEnums.CountryCode.US) 66 self.dut_client.droid.wifiSetCountryCode(wutils.WifiEnums.CountryCode.US) 67 # Enable verbose logging on the duts 68 self.dut.droid.wifiEnableVerboseLogging(1) 69 asserts.assert_equal(self.dut.droid.wifiGetVerboseLoggingLevel(), 1, 70 "Failed to enable WiFi verbose logging on the softap dut.") 71 self.dut_client.droid.wifiEnableVerboseLogging(1) 72 asserts.assert_equal(self.dut_client.droid.wifiGetVerboseLoggingLevel(), 1, 73 "Failed to enable WiFi verbose logging on the client dut.") 74 75 req_params = ["AccessPoint", "dbs_supported_models"] 76 opt_param = ["iperf_server_address"] 77 self.unpack_userparams( 78 req_param_names=req_params, opt_param_names=opt_param) 79 80 if self.dut.model not in self.dbs_supported_models: 81 asserts.skip( 82 ("Device %s does not support dual interfaces.") 83 % self.dut.model) 84 85 if "iperf_server_address" in self.user_params: 86 self.iperf_server = self.iperf_servers[0] 87 if hasattr(self, 'iperf_server'): 88 self.iperf_server.start() 89 90 # Set the client wifi state to on before the test begins. 91 wutils.wifi_toggle_state(self.dut_client, True) 92 93 if len(self.android_devices) > 2: 94 wutils.wifi_test_device_init(self.android_devices[2]) 95 utils.sync_device_time(self.android_devices[2]) 96 self.android_devices[2].droid.wifiSetCountryCode(wutils.WifiEnums.CountryCode.US) 97 self.android_devices[2].droid.wifiEnableVerboseLogging(1) 98 asserts.assert_equal(self.android_devices[2].droid.wifiGetVerboseLoggingLevel(), 1, 99 "Failed to enable WiFi verbose logging on the client dut.") 100 101 def setup_test(self): 102 for ad in self.android_devices: 103 ad.droid.wakeLockAcquireBright() 104 ad.droid.wakeUpNow() 105 self.turn_location_off_and_scan_toggle_off() 106 wutils.wifi_toggle_state(self.dut, False) 107 108 def teardown_test(self): 109 # Prevent the stop wifi tethering failure to block ap close 110 try: 111 wutils.stop_wifi_tethering(self.dut) 112 except signals.TestFailure: 113 pass 114 for ad in self.android_devices: 115 ad.droid.wakeLockRelease() 116 ad.droid.goToSleepNow() 117 wutils.reset_wifi(ad) 118 self.access_points[0].close() 119 del self.user_params["reference_networks"] 120 del self.user_params["open_network"] 121 122 def teardown_class(self): 123 if hasattr(self, 'iperf_server'): 124 self.iperf_server.stop() 125 126 def on_fail(self, test_name, begin_time): 127 for ad in self.android_devices: 128 ad.take_bug_report(test_name, begin_time) 129 ad.cat_adb_log(test_name, begin_time) 130 131 """Helper Functions""" 132 def configure_ap(self, channel_2g=None, channel_5g=None): 133 """Configure and bring up AP on required channel. 134 135 Args: 136 channel_2g: The channel number to use for 2GHz network. 137 channel_5g: The channel number to use for 5GHz network. 138 139 """ 140 if not channel_2g: 141 self.legacy_configure_ap_and_start(channel_5g=channel_5g) 142 elif not channel_5g: 143 self.legacy_configure_ap_and_start(channel_2g=channel_2g) 144 else: 145 self.legacy_configure_ap_and_start(channel_2g=channel_2g, 146 channel_5g=channel_5g) 147 self.wpapsk_2g = self.reference_networks[0]["2g"] 148 self.wpapsk_5g = self.reference_networks[0]["5g"] 149 150 def turn_location_on_and_scan_toggle_on(self): 151 """ Turns on wifi location scans. 152 """ 153 acts.utils.set_location_service(self.dut, True) 154 self.dut.droid.wifiScannerToggleAlwaysAvailable(True) 155 msg = "Failed to turn on location service's scan." 156 asserts.assert_true(self.dut.droid.wifiScannerIsAlwaysAvailable(), msg) 157 158 def turn_location_off_and_scan_toggle_off(self): 159 """ Turns off wifi location scans. 160 """ 161 acts.utils.set_location_service(self.dut, False) 162 self.dut.droid.wifiScannerToggleAlwaysAvailable(False) 163 msg = "Failed to turn off location service's scan." 164 asserts.assert_true(not self.dut.droid.wifiScannerIsAlwaysAvailable(), msg) 165 166 def run_iperf_client(self, params): 167 """Run iperf traffic after connection. 168 169 Args: 170 params: A tuple of network info and AndroidDevice object. 171 """ 172 if "iperf_server_address" in self.user_params: 173 wait_time = 5 174 network, ad = params 175 SSID = network[WifiEnums.SSID_KEY] 176 self.log.info("Starting iperf traffic through {}".format(SSID)) 177 time.sleep(wait_time) 178 port_arg = "-p {}".format(self.iperf_server.port) 179 success, data = ad.run_iperf_client(self.iperf_server_address, 180 port_arg) 181 self.log.debug(pprint.pformat(data)) 182 asserts.assert_true(success, "Error occurred in iPerf traffic.") 183 184 def connect_to_wifi_network_and_verify(self, params): 185 """Connection logic for open and psk wifi networks. 186 187 Args: 188 params: A tuple of network info and AndroidDevice object. 189 """ 190 network, ad = params 191 SSID = network[WifiEnums.SSID_KEY] 192 wutils.start_wifi_connection_scan_and_ensure_network_found( 193 ad, SSID) 194 wutils.wifi_connect(ad, network, num_of_tries=3) 195 if len(self.android_devices) > 2: 196 wutils.reset_wifi(self.android_devices[2]) 197 wutils.start_wifi_connection_scan_and_ensure_network_found( 198 self.android_devices[2], SSID) 199 wutils.wifi_connect(self.android_devices[2], network) 200 201 def confirm_softap_can_be_connected(self, network, check_connectivity=True): 202 """Confirm the ap started by wifi tethering is seen in scan results. 203 204 Args: 205 network: config of the ap we are looking for. 206 """ 207 SSID = network[WifiEnums.SSID_KEY] 208 wutils.start_wifi_connection_scan_and_ensure_network_found( 209 self.dut_client, SSID) 210 wutils.wifi_connect(self.dut_client, network, check_connectivity=check_connectivity) 211 if len(self.android_devices) > 2: 212 wutils.reset_wifi(self.android_devices[2]) 213 wutils.start_wifi_connection_scan_and_ensure_network_found( 214 self.android_devices[2], SSID) 215 wutils.wifi_connect( 216 self.android_devices[2], network, check_connectivity=check_connectivity) 217 218 def create_softap_config(self): 219 """Create a softap config with ssid and password.""" 220 ap_ssid = "softap_" + utils.rand_ascii_str(8) 221 ap_password = utils.rand_ascii_str(8) 222 self.dut.log.info("softap setup: %s %s", ap_ssid, ap_password) 223 config = {wutils.WifiEnums.SSID_KEY: ap_ssid} 224 config[wutils.WifiEnums.PWD_KEY] = ap_password 225 return config 226 227 def start_softap_and_verify(self, band, check_connectivity=True): 228 """Test startup of softap 229 230 1. Bring up AP mode. 231 2. Verify SoftAP active using the client device. 232 """ 233 config = self.create_softap_config() 234 wutils.start_wifi_tethering(self.dut, 235 config[wutils.WifiEnums.SSID_KEY], 236 config[wutils.WifiEnums.PWD_KEY], band) 237 self.confirm_softap_can_be_connected(config, check_connectivity) 238 return config 239 240 def connect_to_wifi_network_and_start_softap(self, nw_params, softap_band): 241 """Test concurrent wifi connection and softap. 242 This helper method first makes a wifi connection and then starts SoftAp. 243 244 Args: 245 nw_params: Params for network STA connection. 246 softap_band: Band for the AP. 247 248 1. Bring up wifi. 249 2. Establish connection to a network. 250 3. Bring up softap and verify AP can be connected by a client device. 251 4. Run iperf on the wifi/softap connection to the network. 252 """ 253 wutils.wifi_toggle_state(self.dut, True) 254 self.connect_to_wifi_network_and_verify((nw_params, self.dut)) 255 softap_config = self.start_softap_and_verify(softap_band) 256 self.run_iperf_client((nw_params, self.dut)) 257 self.run_iperf_client((softap_config, self.dut_client)) 258 if len(self.android_devices) > 2: 259 self.log.info("Testbed has extra android devices, do more validation") 260 ad1 = self.dut_client 261 ad2 = self.android_devices[2] 262 ad1_ip = ad1.droid.connectivityGetIPv4Addresses('wlan0')[0] 263 ad2_ip = ad2.droid.connectivityGetIPv4Addresses('wlan0')[0] 264 # Ping each other 265 asserts.assert_true( 266 utils.adb_shell_ping(ad1, count=10, dest_ip=ad2_ip, timeout=20), 267 "%s ping %s failed" % (ad1.serial, ad2_ip)) 268 asserts.assert_true( 269 utils.adb_shell_ping(ad2, count=10, dest_ip=ad1_ip, timeout=20), 270 "%s ping %s failed" % (ad2.serial, ad1_ip)) 271 # Verify that both softap & wifi is enabled concurrently. 272 self.verify_wifi_and_softap_enabled() 273 274 def start_softap_and_connect_to_wifi_network(self, nw_params, softap_band): 275 """Test concurrent wifi connection and softap. 276 This helper method first starts SoftAp and then makes a wifi connection. 277 278 Args: 279 nw_params: Params for network STA connection. 280 softap_band: Band for the AP. 281 282 1. Bring up softap and verify AP can be connected by a client device. 283 2. Bring up wifi. 284 3. Establish connection to a network. 285 4. Run iperf on the wifi/softap connection to the network. 286 """ 287 softap_config = self.start_softap_and_verify(softap_band, check_connectivity=False) 288 wutils.wifi_toggle_state(self.dut, True) 289 self.connect_to_wifi_network_and_verify((nw_params, self.dut)) 290 self.run_iperf_client((nw_params, self.dut)) 291 self.run_iperf_client((softap_config, self.dut_client)) 292 if len(self.android_devices) > 2: 293 self.log.info("Testbed has extra android devices, do more validation") 294 self.verify_traffic_between_ap_clients( 295 self.dut, self.android_devices[2]) 296 # Verify that both softap & wifi is enabled concurrently. 297 self.verify_wifi_and_softap_enabled() 298 299 def verify_wifi_and_softap_enabled(self): 300 """Helper to verify both wifi and softap is enabled 301 """ 302 asserts.assert_true(self.dut.droid.wifiCheckState(), 303 "Wifi is not reported as running") 304 asserts.assert_true(self.dut.droid.wifiIsApEnabled(), 305 "SoftAp is not reported as running") 306 307 def verify_traffic_between_softap_clients(self, ad1, ad2, num_of_tries=2): 308 """Test the clients that connect to DUT's softap can ping each other. 309 310 Args: 311 num_of_tries: the retry times of ping test. 312 """ 313 ad1_ip = ad1.droid.connectivityGetIPv4Addresses('wlan0')[0] 314 ad2_ip = ad2.droid.connectivityGetIPv4Addresses('wlan0')[0] 315 # Ping each other 316 for _ in range(num_of_tries): 317 if utils.adb_shell_ping(ad1, count=10, dest_ip=ad2_ip, timeout=20): 318 break 319 else: 320 asserts.fail("%s ping %s failed" % (ad1.serial, ad2_ip)) 321 for _ in range(num_of_tries): 322 if utils.adb_shell_ping(ad2, count=10, dest_ip=ad1_ip, timeout=20): 323 break 324 else: 325 asserts.fail("%s ping %s failed" % (ad2.serial, ad1_ip)) 326 327 def verify_traffic_between_ap_clients( 328 self, ad1, ad2, num_of_tries=2): 329 """Test the clients that connect to access point can ping each other. 330 331 Args: 332 num_of_tries: the retry times of ping test. 333 """ 334 ad1_ip = ad1.droid.connectivityGetIPv4Addresses('wlan0')[0] 335 ad2_ip = ad2.droid.connectivityGetIPv4Addresses('wlan0')[0] 336 # Ping each other 337 for _ in range(num_of_tries): 338 if utils.adb_shell_ping(ad1, count=10, dest_ip=ad2_ip, timeout=20): 339 break 340 else: 341 asserts.fail("%s ping %s failed" % (ad1.serial, ad2_ip)) 342 for _ in range(num_of_tries): 343 if utils.adb_shell_ping(ad2, count=10, dest_ip=ad1_ip, timeout=20): 344 break 345 else: 346 asserts.fail("%s ping %s failed" % (ad2.serial, ad1_ip)) 347 348 """Tests""" 349 @test_tracker_info(uuid="c396e7ac-cf22-4736-a623-aa6d3c50193a") 350 def test_wifi_connection_2G_softap_2G(self): 351 """Tests connection to 2G network followed by bringing up SoftAp on 2G. 352 """ 353 self.configure_ap(channel_2g=WIFI_NETWORK_AP_CHANNEL_2G) 354 self.connect_to_wifi_network_and_start_softap( 355 self.wpapsk_2g, WIFI_CONFIG_APBAND_2G) 356 357 @test_tracker_info(uuid="1cd6120d-3db4-4624-9bae-55c976533a48") 358 def test_wifi_connection_5G_softap_5G(self): 359 """Tests connection to 5G network followed by bringing up SoftAp on 5G. 360 """ 361 self.configure_ap(channel_5g=WIFI_NETWORK_AP_CHANNEL_5G) 362 self.connect_to_wifi_network_and_start_softap( 363 self.wpapsk_5g, WIFI_CONFIG_APBAND_5G) 364 365 @test_tracker_info(uuid="5f980007-3490-413e-b94e-7700ffab8534") 366 def test_wifi_connection_5G_DFS_softap_5G(self): 367 """Tests connection to 5G DFS network followed by bringing up SoftAp on 5G. 368 """ 369 self.configure_ap(channel_5g=WIFI_NETWORK_AP_CHANNEL_5G_DFS) 370 self.connect_to_wifi_network_and_start_softap( 371 self.wpapsk_5g, WIFI_CONFIG_APBAND_5G) 372 373 @test_tracker_info(uuid="d05d5d44-c738-4372-9f01-ce2a640a2f25") 374 def test_wifi_connection_5G_softap_2G(self): 375 """Tests connection to 5G network followed by bringing up SoftAp on 2G. 376 """ 377 self.configure_ap(channel_5g=WIFI_NETWORK_AP_CHANNEL_5G) 378 self.connect_to_wifi_network_and_start_softap( 379 self.wpapsk_5g, WIFI_CONFIG_APBAND_2G) 380 381 @test_tracker_info(uuid="909ac713-1ad3-4dad-9be3-ad60f00ed25e") 382 def test_wifi_connection_5G_DFS_softap_2G(self): 383 """Tests connection to 5G DFS network followed by bringing up SoftAp on 2G. 384 """ 385 self.configure_ap(channel_5g=WIFI_NETWORK_AP_CHANNEL_5G_DFS) 386 self.connect_to_wifi_network_and_start_softap( 387 self.wpapsk_5g, WIFI_CONFIG_APBAND_2G) 388 389 @test_tracker_info(uuid="e8de724a-25d3-4801-94cc-22e9e0ecc8d1") 390 def test_wifi_connection_2G_softap_5G(self): 391 """Tests connection to 2G network followed by bringing up SoftAp on 5G. 392 """ 393 self.configure_ap(channel_2g=WIFI_NETWORK_AP_CHANNEL_2G) 394 self.connect_to_wifi_network_and_start_softap( 395 self.wpapsk_2g, WIFI_CONFIG_APBAND_5G) 396 397 @test_tracker_info(uuid="647f4e17-5c7a-4249-98af-f791d163a39f") 398 def test_wifi_connection_5G_softap_2G_with_location_scan_on(self): 399 """Tests connection to 5G network followed by bringing up SoftAp on 2G 400 with location scans turned on. 401 """ 402 self.configure_ap(channel_5g=WIFI_NETWORK_AP_CHANNEL_5G) 403 self.turn_location_on_and_scan_toggle_on() 404 self.connect_to_wifi_network_and_start_softap( 405 self.wpapsk_5g, WIFI_CONFIG_APBAND_2G) 406 # Now toggle wifi off & ensure we can still scan. 407 wutils.wifi_toggle_state(self.dut, False) 408 wutils.start_wifi_connection_scan_and_ensure_network_found( 409 self.dut, self.wpapsk_5g[WifiEnums.SSID_KEY]) 410 411 @test_tracker_info(uuid="4aa56c11-e5bc-480b-bd61-4b4ee577a5da") 412 def test_softap_2G_wifi_connection_2G(self): 413 """Tests bringing up SoftAp on 2G followed by connection to 2G network. 414 """ 415 self.configure_ap(channel_2g=WIFI_NETWORK_AP_CHANNEL_2G) 416 self.start_softap_and_connect_to_wifi_network( 417 self.wpapsk_2g, WIFI_CONFIG_APBAND_2G) 418 419 @test_tracker_info(uuid="5f954957-ad20-4de1-b20c-6c97d0463bdd") 420 def test_softap_5G_wifi_connection_5G(self): 421 """Tests bringing up SoftAp on 5G followed by connection to 5G network. 422 """ 423 self.configure_ap(channel_5g=WIFI_NETWORK_AP_CHANNEL_5G) 424 self.start_softap_and_connect_to_wifi_network( 425 self.wpapsk_5g, WIFI_CONFIG_APBAND_5G) 426 427 @test_tracker_info(uuid="1306aafc-a07e-4654-ba78-674f90cf748e") 428 def test_softap_5G_wifi_connection_5G_DFS(self): 429 """Tests bringing up SoftAp on 5G followed by connection to 5G DFS network. 430 """ 431 self.configure_ap(channel_5g=WIFI_NETWORK_AP_CHANNEL_5G_DFS) 432 self.start_softap_and_connect_to_wifi_network( 433 self.wpapsk_5g, WIFI_CONFIG_APBAND_5G) 434 435 @test_tracker_info(uuid="5e28e8b5-3faa-4cff-a782-13a796d7f572") 436 def test_softap_5G_wifi_connection_2G(self): 437 """Tests bringing up SoftAp on 5G followed by connection to 2G network. 438 """ 439 self.configure_ap(channel_2g=WIFI_NETWORK_AP_CHANNEL_2G) 440 self.start_softap_and_connect_to_wifi_network( 441 self.wpapsk_2g, WIFI_CONFIG_APBAND_5G) 442 443 @test_tracker_info(uuid="a2c62bc6-9ccd-4bc4-8a23-9a1b5d0b4b5c") 444 def test_softap_2G_wifi_connection_5G(self): 445 """Tests bringing up SoftAp on 2G followed by connection to 5G network. 446 """ 447 self.configure_ap(channel_5g=WIFI_NETWORK_AP_CHANNEL_5G) 448 self.start_softap_and_connect_to_wifi_network( 449 self.wpapsk_5g, WIFI_CONFIG_APBAND_2G) 450 451 @test_tracker_info(uuid="a2c62bc6-9ccd-4bc4-8a23-9a1b5d0b4b5c") 452 def test_softap_2G_wifi_connection_5G_DFS(self): 453 """Tests bringing up SoftAp on 2G followed by connection to 5G DFS network. 454 """ 455 self.configure_ap(channel_5g=WIFI_NETWORK_AP_CHANNEL_5G_DFS) 456 self.start_softap_and_connect_to_wifi_network( 457 self.wpapsk_5g, WIFI_CONFIG_APBAND_2G) 458 459 @test_tracker_info(uuid="aa23a3fc-31a1-4d5c-8cf5-2eb9fdf9e7ce") 460 def test_softap_5G_wifi_connection_2G_with_location_scan_on(self): 461 """Tests bringing up SoftAp on 5G followed by connection to 2G network 462 with location scans turned on. 463 """ 464 self.configure_ap(channel_2g=WIFI_NETWORK_AP_CHANNEL_2G) 465 self.turn_location_on_and_scan_toggle_on() 466 self.start_softap_and_connect_to_wifi_network( 467 self.wpapsk_2g, WIFI_CONFIG_APBAND_5G) 468 # Now toggle wifi off & ensure we can still scan. 469 wutils.wifi_toggle_state(self.dut, False) 470 wutils.start_wifi_connection_scan_and_ensure_network_found( 471 self.dut, self.wpapsk_2g[WifiEnums.SSID_KEY]) 472