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 pprint 18import time 19import re 20 21from acts import asserts 22from acts import base_test 23from acts.controllers.ap_lib import hostapd_constants 24import acts.signals as signals 25from acts.test_decorators import test_tracker_info 26from acts_contrib.test_utils.tel.tel_test_utils import WIFI_CONFIG_APBAND_2G 27from acts_contrib.test_utils.tel.tel_test_utils import WIFI_CONFIG_APBAND_5G 28import acts_contrib.test_utils.wifi.wifi_test_utils as wutils 29from acts_contrib.test_utils.wifi.WifiBaseTest import WifiBaseTest 30import acts.utils as utils 31import acts_contrib.test_utils.tel.tel_test_utils as tel_utils 32 33 34WifiEnums = wutils.WifiEnums 35WLAN = "wlan0" 36# Channels to configure the AP for various test scenarios. 37WIFI_NETWORK_AP_CHANNEL_2G = 1 38WIFI_NETWORK_AP_CHANNEL_5G = 36 39WIFI_NETWORK_AP_CHANNEL_5G_DFS = 132 40 41 42class WifiStaApConcurrencyTest(WifiBaseTest): 43 """Tests for STA + AP concurrency scenarios. 44 45 Test Bed Requirement: 46 * Two Android devices (For AP) 47 * One Wi-Fi network visible to the device (for STA). 48 """ 49 50 def setup_class(self): 51 super().setup_class() 52 53 self.dut = self.android_devices[0] 54 self.dut_client = self.android_devices[1] 55 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.android_devices) 62 63 for ad in self.android_devices: 64 wutils.wifi_test_device_init(ad) 65 utils.sync_device_time(ad) 66 # Set country code explicitly to "US". 67 wutils.set_wifi_country_code(ad, WifiEnums.CountryCode.US) 68 # Enable verbose logging on the duts. 69 ad.droid.wifiEnableVerboseLogging(1) 70 71 req_params = ["dbs_supported_models", 72 "wifi6_models", 73 "iperf_server_address", 74 "iperf_server_port"] 75 self.unpack_userparams(req_param_names=req_params,) 76 asserts.abort_class_if( 77 self.dut.model not in self.dbs_supported_models, 78 "Device %s does not support dual interfaces." % self.dut.model) 79 80 def setup_test(self): 81 super().setup_test() 82 for ad in self.android_devices: 83 ad.droid.wakeLockAcquireBright() 84 ad.droid.wakeUpNow() 85 self.turn_location_off_and_scan_toggle_off() 86 87 def teardown_test(self): 88 super().teardown_test() 89 # Prevent the stop wifi tethering failure to block ap close 90 try: 91 wutils.stop_wifi_tethering(self.dut) 92 except signals.TestFailure: 93 pass 94 for ad in self.android_devices: 95 ad.droid.wakeLockRelease() 96 ad.droid.goToSleepNow() 97 wutils.reset_wifi(ad) 98 self.turn_location_on_and_scan_toggle_on() 99 wutils.wifi_toggle_state(self.dut, True) 100 self.access_points[0].close() 101 if "AccessPoint" in self.user_params: 102 try: 103 del self.user_params["reference_networks"] 104 del self.user_params["open_network"] 105 except KeyError as e: 106 self.log.warn("There is no 'reference_network' or " 107 "'open_network' to delete") 108 109 ### Helper Functions ### 110 111 def configure_ap(self, hidden=False, channel_2g=None, channel_5g=None): 112 """Configure and bring up AP on required channel. 113 114 Args: 115 channel_2g: The channel number to use for 2GHz network. 116 channel_5g: The channel number to use for 5GHz network. 117 118 """ 119 if not channel_2g: 120 channel_2g = hostapd_constants.AP_DEFAULT_CHANNEL_2G 121 if not channel_5g: 122 channel_5g = hostapd_constants.AP_DEFAULT_CHANNEL_5G 123 if "AccessPoint" in self.user_params: 124 self.legacy_configure_ap_and_start(channel_2g=channel_2g, 125 channel_5g=channel_5g, 126 hidden=hidden) 127 elif "OpenWrtAP" in self.user_params: 128 self.configure_openwrt_ap_and_start(open_network=True, 129 channel_2g=channel_2g, 130 channel_5g=channel_5g, 131 hidden=hidden) 132 self.open_2g = self.open_network[0]["2g"] 133 self.open_5g = self.open_network[0]["5g"] 134 135 def turn_location_on_and_scan_toggle_on(self): 136 """Turns on wifi location scans.""" 137 utils.set_location_service(self.dut, True) 138 self.dut.droid.wifiScannerToggleAlwaysAvailable(True) 139 msg = "Failed to turn on location service's scan." 140 asserts.assert_true(self.dut.droid.wifiScannerIsAlwaysAvailable(), msg) 141 142 def turn_location_off_and_scan_toggle_off(self): 143 """Turns off wifi location scans.""" 144 utils.set_location_service(self.dut, False) 145 self.dut.droid.wifiScannerToggleAlwaysAvailable(False) 146 msg = "Failed to turn off location service's scan." 147 asserts.assert_false(self.dut.droid.wifiScannerIsAlwaysAvailable(), msg) 148 149 def run_iperf_client(self, params): 150 """Run iperf traffic after connection. 151 152 Args: 153 params: A tuple of network info and AndroidDevice object. 154 """ 155 if "iperf_server_address" in self.user_params: 156 wait_time = 5 157 network, ad = params 158 ssid = network[WifiEnums.SSID_KEY] 159 self.log.info("Starting iperf traffic through {}".format(ssid)) 160 time.sleep(wait_time) 161 port_arg = "-p {}".format(self.iperf_server_port) 162 success, data = ad.run_iperf_client(self.iperf_server_address, 163 port_arg) 164 self.log.debug(pprint.pformat(data)) 165 asserts.assert_true(success, "Error occurred in iPerf traffic.") 166 167 def create_softap_config(self): 168 """Create a softap config with ssid and password.""" 169 ap_ssid = "softap_" + utils.rand_ascii_str(8) 170 ap_password = utils.rand_ascii_str(8) 171 self.dut.log.info("softap setup: %s %s", ap_ssid, ap_password) 172 config = {wutils.WifiEnums.SSID_KEY: ap_ssid} 173 config[wutils.WifiEnums.PWD_KEY] = ap_password 174 return config 175 176 def start_softap_and_verify(self, band, check_connectivity=True): 177 """Test startup of softap. 178 179 1. Bring up AP mode. 180 2. Verify SoftAP active using the client device. 181 182 Args: 183 band: wifi band to start soft ap on 184 check_connectivity: If set, verify internet connectivity 185 186 Returns: 187 Softap config 188 """ 189 config = self.create_softap_config() 190 wutils.start_wifi_tethering(self.dut, 191 config[WifiEnums.SSID_KEY], 192 config[WifiEnums.PWD_KEY], 193 band) 194 for ad in self.android_devices[1:]: 195 wutils.connect_to_wifi_network( 196 ad, config, check_connectivity=check_connectivity) 197 wutils.verify_11ax_softap(self.dut, ad, self.wifi6_models) 198 return config 199 200 def connect_to_wifi_network_and_start_softap(self, nw_params, 201 softap_band, 202 hidden=False): 203 """Test concurrent wifi connection and softap. 204 205 This helper method first makes a wifi connection and then starts SoftAp. 206 1. Bring up wifi. 207 2. Establish connection to a network. 208 3. Bring up softap and verify AP can be connected by a client device. 209 4. Run iperf on the wifi/softap connection to the network. 210 211 Args: 212 nw_params: Params for network STA connection. 213 softap_band: Band for the AP. 214 """ 215 wutils.connect_to_wifi_network(self.dut, nw_params, hidden=hidden) 216 wutils.verify_11ax_wifi_connection( 217 self.dut, self.wifi6_models, "wifi6_ap" in self.user_params) 218 softap_config = self.start_softap_and_verify(softap_band) 219 self.run_iperf_client((nw_params, self.dut)) 220 self.run_iperf_client((softap_config, self.dut_client)) 221 222 if len(self.android_devices) > 2: 223 self.log.info("Testbed has extra devices, do more validation") 224 self.verify_traffic_between_dut_clients( 225 self.dut_client, self.android_devices[2]) 226 227 asserts.assert_true(self.dut.droid.wifiCheckState(), 228 "Wifi is not reported as running") 229 asserts.assert_true(self.dut.droid.wifiIsApEnabled(), 230 "SoftAp is not reported as running") 231 232 def start_softap_and_connect_to_wifi_network(self, nw_params, softap_band): 233 """Test concurrent wifi connection and softap. 234 235 This helper method first starts SoftAp and then makes a wifi connection. 236 1. Bring up softap and verify AP can be connected by a client device. 237 2. Bring up wifi. 238 3. Establish connection to a network. 239 4. Run iperf on the wifi/softap connection to the network. 240 5. Verify wifi state and softap state. 241 242 Args: 243 nw_params: Params for network STA connection. 244 softap_band: Band for the AP. 245 """ 246 softap_config = self.start_softap_and_verify(softap_band, False) 247 wutils.connect_to_wifi_network(self.dut, nw_params) 248 wutils.verify_11ax_wifi_connection( 249 self.dut, self.wifi6_models, "wifi6_ap" in self.user_params) 250 self.run_iperf_client((nw_params, self.dut)) 251 self.run_iperf_client((softap_config, self.dut_client)) 252 253 if len(self.android_devices) > 2: 254 self.log.info("Testbed has extra devices, do more validation") 255 self.verify_traffic_between_dut_clients( 256 self.dut, self.android_devices[2]) 257 258 asserts.assert_true(self.dut.droid.wifiCheckState(), 259 "Wifi is not reported as running") 260 asserts.assert_true(self.dut.droid.wifiIsApEnabled(), 261 "SoftAp is not reported as running") 262 263 def verify_traffic_between_dut_clients(self, ad1, ad2, num_of_tries=2): 264 """Test the clients that connect to DUT's softap can ping each other. 265 266 Args: 267 ad1: DUT 1 268 ad2: DUT 2 269 num_of_tries: the retry times of ping test. 270 """ 271 ad1_ip = ad1.droid.connectivityGetIPv4Addresses(WLAN)[0] 272 ad2_ip = ad2.droid.connectivityGetIPv4Addresses(WLAN)[0] 273 # Ping each other 274 for _ in range(num_of_tries): 275 if utils.adb_shell_ping(ad1, count=10, dest_ip=ad2_ip, timeout=20): 276 break 277 else: 278 asserts.fail("%s ping %s failed" % (ad1.serial, ad2_ip)) 279 for _ in range(num_of_tries): 280 if utils.adb_shell_ping(ad2, count=10, dest_ip=ad1_ip, timeout=20): 281 break 282 else: 283 asserts.fail("%s ping %s failed" % (ad2.serial, ad1_ip)) 284 285 def softap_change_band(self, ad): 286 """ 287 Switch DUT SoftAp to 5G band if currently in 2G. 288 Switch DUT SoftAp to 2G band if currently in 5G. 289 """ 290 wlan1_freq = int(self.get_wlan1_status(self.dut)['freq']) 291 if wlan1_freq in wutils.WifiEnums.ALL_5G_FREQUENCIES: 292 band = WIFI_CONFIG_APBAND_2G 293 elif wlan1_freq in wutils.WifiEnums.ALL_2G_FREQUENCIES: 294 band = WIFI_CONFIG_APBAND_5G 295 wutils.stop_wifi_tethering(ad) 296 self.start_softap_and_verify(band) 297 298 def get_wlan1_status(self, ad): 299 """ get wlan1 interface status""" 300 get_wlan1 = 'hostapd_cli status' 301 out_wlan1 = ad.adb.shell(get_wlan1) 302 out_wlan1 = dict(re.findall(r'(\S+)=(".*?"|\S+)', out_wlan1)) 303 return out_wlan1 304 305 def enable_mobile_data(self, ad): 306 """Make sure that cell data is enabled if there is a sim present.""" 307 init_sim_state = tel_utils.is_sim_ready(self.log, ad) 308 if init_sim_state: 309 if not ad.droid.telephonyIsDataEnabled(): 310 ad.droid.telephonyToggleDataConnection(True) 311 asserts.assert_true(ad.droid.telephonyIsDataEnabled(), 312 "Failed to enable Mobile Data") 313 else: 314 raise signals.TestSkip("Please insert sim card with " 315 "Mobile Data enabled before test") 316 317 ### Tests ### 318 319 @test_tracker_info(uuid="c396e7ac-cf22-4736-a623-aa6d3c50193a") 320 def test_wifi_connection_2G_softap_2G(self): 321 """Test connection to 2G network followed by SoftAp on 2G.""" 322 self.configure_ap(channel_2g=WIFI_NETWORK_AP_CHANNEL_2G) 323 self.connect_to_wifi_network_and_start_softap( 324 self.open_2g, WIFI_CONFIG_APBAND_2G) 325 326 @test_tracker_info(uuid="1cd6120d-3db4-4624-9bae-55c976533a48") 327 def test_wifi_connection_5G_softap_5G(self): 328 """Test connection to 5G network followed by SoftAp on 5G.""" 329 self.configure_ap(channel_5g=WIFI_NETWORK_AP_CHANNEL_5G) 330 self.connect_to_wifi_network_and_start_softap( 331 self.open_5g, WIFI_CONFIG_APBAND_5G) 332 333 @test_tracker_info(uuid="5f980007-3490-413e-b94e-7700ffab8534") 334 def test_wifi_connection_5G_DFS_softap_5G(self): 335 """Test connection to 5G DFS network followed by SoftAp on 5G.""" 336 self.configure_ap(channel_5g=WIFI_NETWORK_AP_CHANNEL_5G_DFS) 337 self.connect_to_wifi_network_and_start_softap( 338 self.open_5g, WIFI_CONFIG_APBAND_5G) 339 340 @test_tracker_info(uuid="d05d5d44-c738-4372-9f01-ce2a640a2f25") 341 def test_wifi_connection_5G_softap_2G(self): 342 """Test connection to 5G network followed by SoftAp on 2G.""" 343 self.configure_ap(channel_5g=WIFI_NETWORK_AP_CHANNEL_5G) 344 self.connect_to_wifi_network_and_start_softap( 345 self.open_5g, WIFI_CONFIG_APBAND_2G) 346 347 @test_tracker_info(uuid="909ac713-1ad3-4dad-9be3-ad60f00ed25e") 348 def test_wifi_connection_5G_DFS_softap_2G(self): 349 """Test connection to 5G DFS network followed by SoftAp on 2G.""" 350 self.configure_ap(channel_5g=WIFI_NETWORK_AP_CHANNEL_5G_DFS) 351 self.connect_to_wifi_network_and_start_softap( 352 self.open_5g, WIFI_CONFIG_APBAND_2G) 353 354 @test_tracker_info(uuid="e8de724a-25d3-4801-94cc-22e9e0ecc8d1") 355 def test_wifi_connection_2G_softap_5G(self): 356 """Test connection to 2G network followed by SoftAp on 5G.""" 357 self.configure_ap(channel_2g=WIFI_NETWORK_AP_CHANNEL_2G) 358 self.connect_to_wifi_network_and_start_softap( 359 self.open_2g, WIFI_CONFIG_APBAND_5G) 360 361 @test_tracker_info(uuid="647f4e17-5c7a-4249-98af-f791d163a39f") 362 def test_wifi_connection_5G_softap_2G_with_location_scan_on(self): 363 """Test connection to 5G network, SoftAp on 2G with location scan on.""" 364 self.configure_ap(channel_5g=WIFI_NETWORK_AP_CHANNEL_5G) 365 self.turn_location_on_and_scan_toggle_on() 366 self.connect_to_wifi_network_and_start_softap( 367 self.open_5g, WIFI_CONFIG_APBAND_2G) 368 # Now toggle wifi off & ensure we can still scan. 369 wutils.wifi_toggle_state(self.dut, False) 370 wutils.start_wifi_connection_scan_and_ensure_network_found( 371 self.dut, self.open_5g[WifiEnums.SSID_KEY]) 372 373 @test_tracker_info(uuid="4aa56c11-e5bc-480b-bd61-4b4ee577a5da") 374 def test_softap_2G_wifi_connection_2G(self): 375 """Test SoftAp on 2G followed by connection to 2G network.""" 376 self.configure_ap(channel_2g=WIFI_NETWORK_AP_CHANNEL_2G) 377 self.start_softap_and_connect_to_wifi_network( 378 self.open_2g, WIFI_CONFIG_APBAND_2G) 379 380 @test_tracker_info(uuid="5f954957-ad20-4de1-b20c-6c97d0463bdd") 381 def test_softap_5G_wifi_connection_5G(self): 382 """Test SoftAp on 5G followed by connection to 5G network.""" 383 self.configure_ap(channel_5g=WIFI_NETWORK_AP_CHANNEL_5G) 384 self.start_softap_and_connect_to_wifi_network( 385 self.open_5g, WIFI_CONFIG_APBAND_5G) 386 387 @test_tracker_info(uuid="1306aafc-a07e-4654-ba78-674f90cf748e") 388 def test_softap_5G_wifi_connection_5G_DFS(self): 389 """Test SoftAp on 5G followed by connection to 5G DFS network.""" 390 self.configure_ap(channel_5g=WIFI_NETWORK_AP_CHANNEL_5G_DFS) 391 self.start_softap_and_connect_to_wifi_network( 392 self.open_5g, WIFI_CONFIG_APBAND_5G) 393 394 @test_tracker_info(uuid="5e28e8b5-3faa-4cff-a782-13a796d7f572") 395 def test_softap_5G_wifi_connection_2G(self): 396 """Test SoftAp on 5G followed by connection to 2G network.""" 397 self.configure_ap(channel_2g=WIFI_NETWORK_AP_CHANNEL_2G) 398 self.start_softap_and_connect_to_wifi_network( 399 self.open_2g, WIFI_CONFIG_APBAND_5G) 400 401 @test_tracker_info(uuid="a2c62bc6-9ccd-4bc4-8a23-9a1b5d0b4b5c") 402 def test_softap_2G_wifi_connection_5G(self): 403 """Test SoftAp on 2G followed by connection to 5G network.""" 404 self.configure_ap(channel_5g=WIFI_NETWORK_AP_CHANNEL_5G) 405 self.start_softap_and_connect_to_wifi_network( 406 self.open_5g, WIFI_CONFIG_APBAND_2G) 407 408 @test_tracker_info(uuid="75400685-a9d9-4091-8af3-97bd539c246a") 409 def test_softap_2G_wifi_connection_5G_DFS(self): 410 """Test SoftAp on 2G followed by connection to 5G DFS network.""" 411 self.configure_ap(channel_5g=WIFI_NETWORK_AP_CHANNEL_5G_DFS) 412 self.start_softap_and_connect_to_wifi_network( 413 self.open_5g, WIFI_CONFIG_APBAND_2G) 414 415 @test_tracker_info(uuid="aa23a3fc-31a1-4d5c-8cf5-2eb9fdf9e7ce") 416 def test_softap_5G_wifi_connection_2G_with_location_scan_on(self): 417 """Test SoftAp on 5G, connection to 2G network with location scan on.""" 418 self.configure_ap(channel_2g=WIFI_NETWORK_AP_CHANNEL_2G) 419 self.turn_location_on_and_scan_toggle_on() 420 self.start_softap_and_connect_to_wifi_network( 421 self.open_2g, WIFI_CONFIG_APBAND_5G) 422 # Now toggle wifi off & ensure we can still scan. 423 wutils.wifi_toggle_state(self.dut, False) 424 wutils.start_wifi_connection_scan_and_ensure_network_found( 425 self.dut, self.open_2g[WifiEnums.SSID_KEY]) 426 427 @test_tracker_info(uuid="9decb951-4500-4476-8161-f4054760f709") 428 def test_wifi_connection_2G_softap_2G_to_softap_5g(self): 429 """Test connection to 2G network followed by SoftAp on 2G, 430 and switch SoftAp to 5G.""" 431 self.configure_ap(channel_2g=WIFI_NETWORK_AP_CHANNEL_2G) 432 self.connect_to_wifi_network_and_start_softap( 433 self.open_2g, WIFI_CONFIG_APBAND_2G) 434 self.softap_change_band(self.dut) 435 436 @test_tracker_info(uuid="e17e0fb8-2c1d-4f3c-af2a-7374485f210c") 437 def test_wifi_connection_5G_softap_2G_to_softap_5g(self): 438 """Test connection to 5G network followed by SoftAp on 2G, 439 and switch SoftAp to 5G.""" 440 self.configure_ap(channel_5g=WIFI_NETWORK_AP_CHANNEL_5G) 441 self.connect_to_wifi_network_and_start_softap( 442 self.open_2g, WIFI_CONFIG_APBAND_2G) 443 self.softap_change_band(self.dut) 444 445 @test_tracker_info(uuid="d549a18e-73d9-45e7-b4df-b59446c4b833") 446 def test_wifi_connection_hidden_2g_softap_2G_to_softap_5g(self): 447 """Test connection to a hidden 2G network on Channel 1 and 448 followed by SoftAp on 2G, and switch SoftAp to 5G. 449 1. Connect to a hidden 2.4G Wi-Fi AP(channel 1) 450 2. DUT turn on 2.4G hotspot and client connect to DUT 451 3. Change AP Band of DUT Hotspot from 2.4GHz to 5GHz 452 Expected results: Both DUT and Hotspot client can access the Internet 453 """ 454 self.configure_ap(channel_2g=WIFI_NETWORK_AP_CHANNEL_2G, hidden=True) 455 self.connect_to_wifi_network_and_start_softap( 456 self.open_2g, 457 WIFI_CONFIG_APBAND_2G, 458 hidden=True) 459 self.softap_change_band(self.dut) 460