1# 2# Copyright 2017 - The Android Open Source Project 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15 16import time 17from acts import asserts 18from acts import utils 19from acts import signals 20from acts.keys import Config 21from acts.test_decorators import test_tracker_info 22from acts_contrib.test_utils.net import connectivity_const as cconsts 23from acts_contrib.test_utils.wifi import wifi_test_utils as wutils 24from acts_contrib.test_utils.wifi.WifiBaseTest import WifiBaseTest 25from acts_contrib.test_utils.wifi.aware import aware_test_utils as autils 26import os 27 28WifiEnums = wutils.WifiEnums 29 30 31class WifiRoamingTest(WifiBaseTest): 32 33 def setup_class(self): 34 """Configure the required networks for testing roaming.""" 35 super().setup_class() 36 37 self.dut = self.android_devices[0] 38 self.dut_client = self.android_devices[1] 39 req_params = ["roaming_attn"] 40 self.unpack_userparams(req_param_names=req_params,) 41 self.country_code = wutils.WifiEnums.CountryCode.US 42 if hasattr(self, "country_code_file"): 43 if isinstance(self.country_code_file, list): 44 self.country_code_file = self.country_code_file[0] 45 if not os.path.isfile(self.country_code_file): 46 self.country_code_file = os.path.join( 47 self.user_params[Config.key_config_path.value], 48 self.country_code_file) 49 self.country_code = utils.load_config( 50 self.country_code_file)["country"] 51 52 if "AccessPoint" in self.user_params: 53 self.legacy_configure_ap_and_start(ap_count=2) 54 55 def teardown_class(self): 56 self.dut.ed.clear_all_events() 57 if "AccessPoint" in self.user_params: 58 del self.user_params["reference_networks"] 59 del self.user_params["open_network"] 60 61 def setup_test(self): 62 super().setup_test() 63 self.dut.ed.clear_all_events() 64 self.dut.droid.wakeLockAcquireBright() 65 self.dut.droid.wakeUpNow() 66 67 def teardown_test(self): 68 super().teardown_test() 69 self.dut.droid.wakeLockRelease() 70 self.dut.droid.goToSleepNow() 71 wutils.reset_wifi(self.dut) 72 wutils.set_attns(self.attenuators, "default") 73 for ad in self.android_devices: 74 wutils.set_wifi_country_code(ad, self.country_code) 75 if "OpenWrtAP" in self.user_params: 76 for ap in self.access_points: 77 ap.close() 78 79 ### Helper Methods ### 80 81 def register_network_callback_for_internet(self): 82 self.dut.log.debug("Registering network callback for wifi internet" 83 "connectivity") 84 network_request = { 85 cconsts.NETWORK_CAP_TRANSPORT_TYPE_KEY : 86 cconsts.NETWORK_CAP_TRANSPORT_WIFI, 87 cconsts.NETWORK_CAP_CAPABILITY_KEY : 88 [cconsts.NETWORK_CAP_CAPABILITY_INTERNET] 89 } 90 key = self.dut.droid.connectivityRegisterNetworkCallback(network_request) 91 return key 92 93 def generate_wifi_info(self, network): 94 return { 95 WifiEnums.SSID_KEY : network[WifiEnums.SSID_KEY], 96 # We need to use "BSSID" in WifiInfo map, also need to use lower 97 # chars for bssid. 98 WifiEnums.BSSID_KEY : network["bssid"].lower() 99 } 100 101 def roaming_from_AP1_and_AP2(self, AP1_network, AP2_network): 102 """Test roaming between two APs. 103 104 Args: 105 AP1_network: AP-1's network information. 106 AP2_network: AP-2's network information. 107 108 Steps: 109 1. Make AP1 visible, AP2 not visible. 110 2. Connect to AP1's ssid. 111 3. Make AP1 not visible, AP2 visible. 112 4. Expect DUT to roam to AP2. 113 5. Validate connection information and ping. 114 """ 115 network_cb_key = None 116 if self.dut.droid.isSdkAtLeastS(): 117 network_cb_key = self.register_network_callback_for_internet() 118 wutils.set_attns(self.attenuators, "AP1_on_AP2_off", self.roaming_attn) 119 wifi_config = AP1_network.copy() 120 wifi_config.pop("bssid") 121 wutils.connect_to_wifi_network(self.dut, wifi_config) 122 if network_cb_key is not None: 123 self.dut.log.info("Waiting for onAvailable and " 124 "onCapabilitiesChanged after connection") 125 # Ensure that the connection completed and we got the ON_AVAILABLE 126 # callback. 127 autils.wait_for_event_with_keys( 128 self.dut, 129 cconsts.EVENT_NETWORK_CALLBACK, 130 20, 131 (cconsts.NETWORK_CB_KEY_ID, network_cb_key), 132 (cconsts.NETWORK_CB_KEY_EVENT, cconsts.NETWORK_CB_AVAILABLE)) 133 autils.wait_for_event_with_keys( 134 self.dut, cconsts.EVENT_NETWORK_CALLBACK, 10, 135 (cconsts.NETWORK_CB_KEY_ID, network_cb_key), 136 (cconsts.NETWORK_CB_KEY_EVENT, 137 cconsts.NETWORK_CB_CAPABILITIES_CHANGED), 138 (cconsts.NETWORK_CB_KEY_TRANSPORT_INFO, 139 self.generate_wifi_info(AP1_network))) 140 self.log.info("Roaming from %s to %s", AP1_network, AP2_network) 141 wutils.trigger_roaming_and_validate( 142 self.dut, self.attenuators, "AP1_off_AP2_on", AP2_network, 143 self.roaming_attn) 144 if network_cb_key is not None: 145 self.dut.log.info("Waiting for onCapabilitiesChanged after" 146 " roaming") 147 # Ensure that the roaming complete triggered a capabilities change 148 # with the new bssid. 149 autils.wait_for_event_with_keys( 150 self.dut, cconsts.EVENT_NETWORK_CALLBACK, 10, 151 (cconsts.NETWORK_CB_KEY_ID, network_cb_key), 152 (cconsts.NETWORK_CB_KEY_EVENT, 153 cconsts.NETWORK_CB_CAPABILITIES_CHANGED), 154 (cconsts.NETWORK_CB_KEY_TRANSPORT_INFO, 155 self.generate_wifi_info(AP2_network))) 156 157 ### Test Cases ### 158 159 @test_tracker_info(uuid="db8a46f9-713f-4b98-8d9f-d36319905b0a") 160 def test_roaming_between_AP1_to_AP2_open_2g(self): 161 if "OpenWrtAP" in self.user_params: 162 self.configure_openwrt_ap_and_start(open_network=True, 163 ap_count=2, 164 mirror_ap=True) 165 self.log.info("BSSID map: %s" % self.bssid_map) 166 ap1_network = self.open_network[0]["2g"] 167 ap2_network = self.open_network[1]["2g"] 168 if "OpenWrtAP" in self.user_params: 169 ap1_network["bssid"] = self.bssid_map[0]["2g"][ap1_network["SSID"]] 170 ap2_network["bssid"] = self.bssid_map[1]["2g"][ap2_network["SSID"]] 171 self.roaming_from_AP1_and_AP2(ap1_network, ap2_network) 172 173 @test_tracker_info(uuid="0db67d9b-6ea9-4f40-acf2-155c4ecf9dc5") 174 def test_roaming_between_AP1_to_AP2_open_5g(self): 175 if "OpenWrtAP" in self.user_params: 176 self.configure_openwrt_ap_and_start(open_network=True, 177 ap_count=2, 178 mirror_ap=True) 179 ap1_network = self.open_network[0]["5g"] 180 ap2_network = self.open_network[1]["5g"] 181 if "OpenWrtAP" in self.user_params: 182 ap1_network["bssid"] = self.bssid_map[0]["5g"][ap1_network["SSID"]] 183 ap2_network["bssid"] = self.bssid_map[1]["5g"][ap2_network["SSID"]] 184 self.roaming_from_AP1_and_AP2(ap1_network, ap2_network) 185 186 @test_tracker_info(uuid="eabc7319-d962-4bef-b679-725e9ff00420") 187 def test_roaming_between_AP1_to_AP2_psk_2g(self): 188 if "OpenWrtAP" in self.user_params: 189 self.configure_openwrt_ap_and_start(wpa_network=True, 190 ap_count=2, 191 mirror_ap=True) 192 ap1_network = self.reference_networks[0]["2g"] 193 ap2_network = self.reference_networks[1]["2g"] 194 if "OpenWrtAP" in self.user_params: 195 ap1_network["bssid"] = self.bssid_map[0]["2g"][ap1_network["SSID"]] 196 ap2_network["bssid"] = self.bssid_map[1]["2g"][ap2_network["SSID"]] 197 self.roaming_from_AP1_and_AP2(ap1_network, ap2_network) 198 199 @test_tracker_info(uuid="1cf9c681-4ff0-45c1-9719-f01629f6a7f7") 200 def test_roaming_between_AP1_to_AP2_psk_5g(self): 201 if "OpenWrtAP" in self.user_params: 202 self.configure_openwrt_ap_and_start(wpa_network=True, 203 ap_count=2, 204 mirror_ap=True) 205 ap1_network = self.reference_networks[0]["5g"] 206 ap2_network = self.reference_networks[1]["5g"] 207 if "OpenWrtAP" in self.user_params: 208 ap1_network["bssid"] = self.bssid_map[0]["5g"][ap1_network["SSID"]] 209 ap2_network["bssid"] = self.bssid_map[1]["5g"][ap2_network["SSID"]] 210 self.roaming_from_AP1_and_AP2(ap1_network, ap2_network) 211 212 @test_tracker_info(uuid="a28f7d2e-fae4-4e66-b633-7ee59f8b46e0") 213 def test_roaming_between_AP1_to_AP2_owe_2g(self): 214 if "OpenWrtAP" in self.user_params: 215 self.configure_openwrt_ap_and_start(owe_network=True, 216 ap_count=2, 217 mirror_ap=True) 218 ap1_network = self.owe_networks[0]["2g"] 219 ap2_network = self.owe_networks[1]["2g"] 220 if "OpenWrtAP" in self.user_params: 221 ap1_network["bssid"] = self.bssid_map[0]["2g"][ap1_network["SSID"]] 222 ap2_network["bssid"] = self.bssid_map[1]["2g"][ap2_network["SSID"]] 223 self.roaming_from_AP1_and_AP2(ap1_network, ap2_network) 224 225 @test_tracker_info(uuid="3c39110a-9336-4abd-b885-acbba85dc10d") 226 def test_roaming_between_AP1_to_AP2_owe_5g(self): 227 if "OpenWrtAP" in self.user_params: 228 self.configure_openwrt_ap_and_start(owe_network=True, 229 ap_count=2, 230 mirror_ap=True) 231 ap1_network = self.owe_networks[0]["5g"] 232 ap2_network = self.owe_networks[1]["5g"] 233 if "OpenWrtAP" in self.user_params: 234 ap1_network["bssid"] = self.bssid_map[0]["5g"][ap1_network["SSID"]] 235 ap2_network["bssid"] = self.bssid_map[1]["5g"][ap2_network["SSID"]] 236 self.roaming_from_AP1_and_AP2(ap1_network, ap2_network) 237 238 @test_tracker_info(uuid="68b2baf6-162a-44f2-a00d-4973e5ac9471") 239 def test_roaming_between_AP1_to_AP2_sae_2g(self): 240 if "OpenWrtAP" in self.user_params: 241 self.configure_openwrt_ap_and_start(sae_network=True, 242 ap_count=2, 243 mirror_ap=True) 244 ap1_network = self.sae_networks[0]["2g"] 245 ap2_network = self.sae_networks[1]["2g"] 246 if "OpenWrtAP" in self.user_params: 247 ap1_network["bssid"] = self.bssid_map[0]["2g"][ap1_network["SSID"]] 248 ap2_network["bssid"] = self.bssid_map[1]["2g"][ap2_network["SSID"]] 249 self.roaming_from_AP1_and_AP2(ap1_network, ap2_network) 250 251 @test_tracker_info(uuid="20e24ed3-0cd1-46dd-bd26-2183ffb443e6") 252 def test_roaming_between_AP1_to_AP2_sae_5g(self): 253 if "OpenWrtAP" in self.user_params: 254 self.configure_openwrt_ap_and_start(sae_network=True, 255 ap_count=2, 256 mirror_ap=True) 257 ap1_network = self.sae_networks[0]["5g"] 258 ap2_network = self.sae_networks[1]["5g"] 259 if "OpenWrtAP" in self.user_params: 260 ap1_network["bssid"] = self.bssid_map[0]["5g"][ap1_network["SSID"]] 261 ap2_network["bssid"] = self.bssid_map[1]["5g"][ap2_network["SSID"]] 262 self.roaming_from_AP1_and_AP2(ap1_network, ap2_network) 263 264 @test_tracker_info(uuid="521269cb-5d2c-46e6-bc01-a03bd148ce28") 265 def test_soft_2g_ap_channel_when_roam_to_chan_13(self): 266 """Verify softAp 2G channel when after roaming to network on channel 13. 267 268 Steps: 269 1. Configure 2 APs - 1 on channel 6, the other on channel 13. 270 2. Connect DUT to AP on channel 6. 271 3. Start softAp on DUT on 2G band. 272 4. Verify softAp is started on channel 6. 273 5. Roam to AP2 with channel 13. 274 6. Verify SoftAp on DUT changed to channel 13. 275 """ 276 for ad in self.android_devices: 277 wutils.set_wifi_country_code( 278 ad, wutils.WifiEnums.CountryCode.AUSTRALIA) 279 if "OpenWrtAP" in self.user_params: 280 self.configure_openwrt_ap_and_start(open_network=True, 281 ap_count=2, 282 channel_2g_ap2=13, 283 mirror_ap=True) 284 ap1_network = self.open_network[0]["2g"] 285 ap2_network = self.open_network[1]["2g"] 286 if "OpenWrtAP" in self.user_params: 287 ap1_network["bssid"] = self.bssid_map[0]["2g"][ap1_network["SSID"]] 288 ap2_network["bssid"] = self.bssid_map[1]["2g"][ap2_network["SSID"]] 289 wutils.set_attns(self.attenuators, "AP1_on_AP2_off", self.roaming_attn) 290 wutils.connect_to_wifi_network(self.dut, ap1_network) 291 292 # start softap on 2G and verify the channel is 6. 293 sap_config = { 294 WifiEnums.SSID_KEY: "hotspot_%s" % utils.rand_ascii_str(6), 295 WifiEnums.PWD_KEY: "pass_%s" % utils.rand_ascii_str(6), 296 WifiEnums.AP_BAND_KEY: WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G} 297 asserts.assert_true( 298 self.dut.droid.wifiSetWifiApConfiguration(sap_config), 299 "Failed to set WifiAp Configuration") 300 wutils.start_wifi_tethering_saved_config(self.dut) 301 softap_conf = self.dut.droid.wifiGetApConfiguration() 302 self.log.info("softap conf: %s" % softap_conf) 303 wutils.connect_to_wifi_network(self.dut_client, sap_config) 304 conn_info = self.dut_client.droid.wifiGetConnectionInfo() 305 self.log.info("Wifi connection info on dut_client: %s" % conn_info) 306 softap_channel = wutils.WifiEnums.freq_to_channel[conn_info["frequency"]] 307 asserts.assert_true(softap_channel == 6, 308 "Dut client did not connect to softAp on channel 6") 309 310 # trigger roaming to AP2 with channel 13 311 self.log.info("Roaming from %s to %s", ap1_network, ap2_network) 312 wutils.trigger_roaming_and_validate( 313 self.dut, self.attenuators, "AP1_off_AP2_on", ap2_network, 314 self.roaming_attn) 315 316 # verify softap is now moved to channel 13 317 conn_info = self.dut_client.droid.wifiGetConnectionInfo() 318 self.log.info("Wifi connection info on dut_client: %s" % conn_info) 319 softap_channel = wutils.WifiEnums.freq_to_channel[conn_info["frequency"]] 320 asserts.assert_true(softap_channel == 13, 321 "Dut client did not connect to softAp on channel 13") 322 323 @test_tracker_info(uuid="3114d625-5cdd-4205-bb46-5a9d057dc80d") 324 def test_roaming_fail_psk_2g(self): 325 """Verify roaming fail with mismatch passwords. 326 327 Steps: 328 DUT connect to AP1. 329 Change AP2's password. 330 DUT try roaming from AP1 to AP2 with mismatched password. 331 Change AP2's password back to original one. 332 DUT try roaming from AP1 to AP2 with matched passwords. 333 """ 334 # Use OpenWrt as Wi-Fi AP when it's available in testbed. 335 if "OpenWrtAP" in self.user_params: 336 self.configure_openwrt_ap_and_start(wpa_network=True, 337 ap_count=2, 338 mirror_ap=True) 339 self.openwrt1 = self.access_points[0] 340 self.openwrt2 = self.access_points[1] 341 ap1_network = self.reference_networks[0]["2g"] 342 ap2_network = self.reference_networks[1]["2g"] 343 # Get APs' BSSIDs. 344 ap1_bssid = self.bssid_map[0]["2g"][ap1_network["SSID"]] 345 ap2_bssid = self.bssid_map[1]["2g"][ap2_network["SSID"]] 346 # Make AP's configs. 347 ap1_network["bssid"] = ap1_bssid 348 ap2_network["bssid"] = ap2_bssid 349 350 # Change AP2 2G to password. 351 self.openwrt2.set_password(pwd_2g=utils.rand_ascii_str(8)) 352 353 try: 354 # DUT roaming from AP1 to AP2 with mismatched passwords. 355 self.dut.log.info("Roaming via mismatched passwords to AP2 [{}]" 356 .format(ap2_bssid)) 357 self.roaming_from_AP1_and_AP2(ap1_network, ap2_network) 358 except: 359 self.dut.log.info("Failed roaming to AP2") 360 self.dut.log.info("Roaming via matched passwords to AP2 [{}]" 361 .format(ap1_bssid)) 362 wutils.set_attns_steps(self.attenuators, "AP1_on_AP2_off", 363 self.roaming_attn) 364 self.openwrt2.set_password(pwd_2g=ap2_network["password"]) 365 self.dut.log.info("Toggling wifi OFF.") 366 wutils.wifi_toggle_state(self.dut, False) 367 self.dut.log.info("Toggling wifi ON.") 368 wutils.wifi_toggle_state(self.dut, True) 369 self.roaming_from_AP1_and_AP2(ap1_network, ap2_network) 370 else: 371 raise signals.TestFailure("DUT unexpectedly connect to Wi-Fi.") 372 373 # Use Google OnHub as Wi-Fi AP to test when OpenWrt is no available. 374 elif "AccessPoint" in self.user_params: 375 network = {'SSID':'test_roaming_fail', 'password':'roam123456@'} 376 # AP2 network with incorrect password. 377 network_fail = {'SSID':'test_roaming_fail', 'password':'roam123456@#$%^'} 378 # Setup AP1 with the correct password. 379 wutils.ap_setup(self, 0, self.access_points[0], network) 380 network_bssid = self.access_points[0].get_bssid_from_ssid( 381 network["SSID"], '2g') 382 # Setup AP2 with the incorrect password. 383 wutils.ap_setup(self, 1, self.access_points[1], network_fail) 384 network_fail_bssid = self.access_points[1].get_bssid_from_ssid( 385 network_fail["SSID"], '2g') 386 network['bssid'] = network_bssid 387 network_fail['bssid'] = network_fail_bssid 388 try: 389 # Initiate roaming with AP2 configured with incorrect password. 390 self.roaming_from_AP1_and_AP2(network, network_fail) 391 except: 392 self.log.info("Roaming failed to AP2 with incorrect password.") 393 # Re-configure AP2 after roaming failed, with correct password. 394 self.log.info("Re-configuring AP2 with correct password.") 395 wutils.ap_setup(self, 1, self.access_points[1], network) 396 self.roaming_from_AP1_and_AP2(network, network_fail) 397 398 @test_tracker_info(uuid="b6d73094-22bc-4460-9d55-ce34a0a6a8c9") 399 def test_roaming_fail_different_bssid(self): 400 """Verify devices is disconnect with difference bssid after roaming 401 402 Steps: 403 1. Configure 2 APs 404 2. Connect DUT to AP 1 405 3. Roam to AP2 406 4. Verify the bssid is difference and the device can't connect 407 5. Verify device is disconnect after roaming. 408 """ 409 if "OpenWrtAP" in self.user_params: 410 self.configure_openwrt_ap_and_start(wpa_network=True, 411 ap_count=2, 412 mirror_ap=True) 413 ap1_network = self.reference_networks[0]["2g"] 414 ap2_network = self.reference_networks[1]["2g"] 415 if "OpenWrtAP" in self.user_params: 416 ap1_network["bssid"] = self.bssid_map[0]["2g"][ap1_network["SSID"]] 417 ap2_network["bssid"] = self.bssid_map[1]["2g"][ap2_network["SSID"]] 418 wutils.set_attns(self.attenuators, "AP1_on_AP2_off") 419 wutils.connect_to_wifi_network(self.dut, ap1_network) 420 421 # Initiate roaming with AP2 422 wutils.set_attns(self.attenuators, "AP1_off_AP2_on") 423 time.sleep(10) 424 try: 425 wutils.verify_wifi_connection_info(self.dut, ap2_network) 426 except: 427 self.log.info("Roaming failed to AP2 with incorrect BSSID") 428 wutils.wait_for_disconnect(self.dut) 429 self.log.info("Device is disconnect") 430