1#!/usr/bin/env python3.4 2# 3# Copyright 2016 - 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 time 18 19import acts.signals as signals 20 21from acts import asserts 22from acts import base_test 23from acts.controllers import android_device 24from acts.controllers import attenuator 25from acts.test_decorators import test_tracker_info 26from acts_contrib.test_utils.wifi import wifi_test_utils as wutils 27from acts_contrib.test_utils.wifi.WifiBaseTest import WifiBaseTest 28 29WifiEnums = wutils.WifiEnums 30 31AP_1 = 0 32AP_2 = 1 33# WifiNetworkSelector imposes a 10 seconds gap between two selections 34NETWORK_SELECTION_TIME_GAP = 12 35LVL1_ATTN = 15 36LVL2_ATTN = 30 37MIN_ATTN = 0 38MAX_ATTN = 95 39ATTN_SLEEP = 12 40 41 42class WifiNetworkSelectorTest(WifiBaseTest): 43 """These tests verify the behavior of the Android Wi-Fi Network Selector 44 feature. 45 """ 46 47 def __init__(self, configs): 48 super().__init__(configs) 49 self.enable_packet_log = True 50 51 def setup_class(self): 52 super().setup_class() 53 54 self.dut = self.android_devices[0] 55 wutils.wifi_test_device_init(self.dut) 56 self.ap1_2g_attn = 0 57 self.ap1_5g_attn = 1 58 self.ap2_2g_attn = 2 59 self.ap2_5g_attn = 3 60 if "AccessPoint" in self.user_params: 61 self.legacy_configure_ap_and_start(mirror_ap=False, ap_count=2) 62 elif "OpenWrtAP" in self.user_params: 63 self.configure_openwrt_ap_and_start(open_network=True, 64 wpa_network=True, 65 ap_count=2) 66 self.ap1_5g_attn, self.ap2_2g_attn, self.ap2_5g_attn, = 0, 1, 1 67 self.configure_packet_capture() 68 69 def setup_test(self): 70 super().setup_test() 71 self.dut.droid.wakeLockAcquireBright() 72 self.dut.droid.wakeUpNow() 73 self.dut.ed.clear_all_events() 74 for a in self.attenuators: 75 a.set_atten(MAX_ATTN) 76 time.sleep(ATTN_SLEEP) 77 78 def teardown_test(self): 79 super().teardown_test() 80 for a in self.attenuators: 81 a.set_atten(MIN_ATTN) 82 wutils.reset_wifi(self.dut) 83 self.dut.droid.wakeLockRelease() 84 self.dut.droid.goToSleepNow() 85 86 def teardown_class(self): 87 if "AccessPoint" in self.user_params: 88 del self.user_params["reference_networks"] 89 del self.user_params["open_network"] 90 91 """ Helper Functions """ 92 93 def add_networks(self, ad, networks): 94 """Add Wi-Fi networks to an Android device and verify the networks were 95 added correctly. 96 97 Args: 98 ad: the AndroidDevice object to add networks to. 99 networks: a list of dicts, each dict represents a Wi-Fi network. 100 """ 101 for network in networks: 102 ret = ad.droid.wifiAddNetwork(network) 103 asserts.assert_true(ret != -1, 104 "Failed to add network %s" % network) 105 ad.droid.wifiEnableNetwork(ret, 0) 106 107 configured_networks = ad.droid.wifiGetConfiguredNetworks() 108 self.log.info("Configured networks: %s", configured_networks) 109 110 def connect_and_verify_connected_bssid(self, network): 111 """Start a scan to get the DUT connected to an AP and verify the DUT 112 is connected to the correct BSSID. 113 114 Args: 115 expected_bssid: Network bssid to which connection. 116 117 Returns: 118 True if connection to given network happen, else return False. 119 """ 120 expected_ssid = network['SSID'] 121 expected_bssid = network['bssid'] 122 wutils.start_wifi_connection_scan_and_ensure_network_found( 123 self.dut, expected_ssid) 124 time.sleep(20) 125 actual_network = self.dut.droid.wifiGetConnectionInfo() 126 self.log.info("Actual network: %s", actual_network) 127 asserts.assert_true( 128 actual_network and WifiEnums.BSSID_KEY in actual_network and \ 129 expected_bssid.lower() == actual_network[ 130 WifiEnums.BSSID_KEY].lower(), 131 "Expected BSSID: %s, Actual BSSID: %s" % 132 (expected_bssid, actual_network[WifiEnums.BSSID_KEY])) 133 self.log.info("DUT connected to valid network: %s" % expected_bssid) 134 135 """ Tests Begin """ 136 137 @test_tracker_info(uuid="ffa5e278-db3f-4e17-af11-6c7a3e7c5cc2") 138 def test_network_selector_automatic_connection(self): 139 """ 140 1. Add one saved network to DUT. 141 2. Move the DUT in range. 142 3. Verify the DUT is connected to the network. 143 """ 144 # add a saved network to DUT 145 networks = [self.reference_networks[AP_1]['5g']] 146 self.add_networks(self.dut, networks) 147 148 # move the DUT in range 149 self.attenuators[self.ap1_5g_attn].set_atten(MIN_ATTN) 150 time.sleep(ATTN_SLEEP) 151 152 # verify DUT is connected to AP_1 5g network 153 network = self.reference_networks[AP_1]['5g'].copy() 154 if "OpenWrtAP" in self.user_params: 155 network['bssid'] = self.bssid_map[AP_1]['5g'][network["SSID"]] 156 self.connect_and_verify_connected_bssid(network) 157 158 @test_tracker_info(uuid="3ea818f2-10d7-4aad-bfab-7d8fb25aae78") 159 def test_network_selector_basic_connection_prefer_5g(self): 160 """ 161 1. Add one saved SSID with 2G and 5G BSSIDs of similar RSSI. 162 2. Move the DUT in range. 163 3. Verify the DUT is connected to the 5G BSSID. 164 """ 165 # add a saved network with both 2G and 5G BSSIDs to DUT 166 networks = [ 167 self.reference_networks[AP_1]['2g'], 168 self.reference_networks[AP_1]['5g'] 169 ] 170 self.add_networks(self.dut, networks) 171 172 # Move DUT in range 173 self.attenuators[self.ap1_2g_attn].set_atten(MIN_ATTN) 174 self.attenuators[self.ap1_5g_attn].set_atten(MIN_ATTN) 175 time.sleep(ATTN_SLEEP) 176 177 # verify DUT is connected to 5G network 178 network = self.reference_networks[AP_1]['5g'].copy() 179 if "OpenWrtAP" in self.user_params: 180 network['bssid'] = self.bssid_map[AP_1]['5g'][network["SSID"]] 181 self.connect_and_verify_connected_bssid(network) 182 183 @test_tracker_info(uuid="bebb29ca-4486-4cde-b390-c5f8f2e1580c") 184 def test_network_selector_prefer_stronger_rssi(self): 185 """ 186 1. Add two saved SSIDs to DUT, same band, one has stronger RSSI 187 than the other. 188 2. Move the DUT in range. 189 3. Verify the DUT is connected to the SSID with stronger RSSI. 190 """ 191 # add a 2G and a 5G saved network to DUT 192 networks = [ 193 self.reference_networks[AP_1]['2g'], 194 self.reference_networks[AP_2]['2g'] 195 ] 196 self.add_networks(self.dut, networks) 197 198 # move the DUT in range 199 self.attenuators[self.ap1_2g_attn].set_atten(LVL1_ATTN) 200 self.attenuators[self.ap2_2g_attn].set_atten(LVL2_ATTN) 201 time.sleep(ATTN_SLEEP) 202 203 # verify DUT is connected AP_1 204 network = self.reference_networks[AP_1]['2g'].copy() 205 if "OpenWrtAP" in self.user_params: 206 network['bssid'] = self.bssid_map[AP_1]['2g'][network["SSID"]] 207 self.connect_and_verify_connected_bssid(network) 208 209 @test_tracker_info(uuid="f9f72dc5-034f-4fe2-a27d-df1b6cae76cd") 210 def test_network_selector_prefer_secure_over_open_network(self): 211 """ 212 1. Add two saved networks to DUT, same band, similar RSSI, one uses 213 WPA2 security, the other is open. 214 2. Move the DUT in range. 215 3. Verify the DUT is connected to the secure network that uses WPA2. 216 """ 217 # add a open network and a secure saved network to DUT 218 networks = [ 219 self.open_network[AP_1]['5g'], self.reference_networks[AP_1]['5g'] 220 ] 221 self.add_networks(self.dut, networks) 222 223 # Move DUT in range 224 self.attenuators[self.ap1_5g_attn].set_atten(MIN_ATTN) 225 time.sleep(ATTN_SLEEP) 226 227 # verify DUT connects to secure network 228 network = self.reference_networks[AP_1]['5g'].copy() 229 if "OpenWrtAP" in self.user_params: 230 network['bssid'] = self.bssid_map[AP_1]['5g'][network["SSID"]] 231 self.connect_and_verify_connected_bssid(network) 232 233 @test_tracker_info(uuid="ab2c527c-0f9c-4f09-a13f-e3f461b7da52") 234 def test_network_selector_blacklist_by_connection_failure(self): 235 """ 236 1. Add two saved secured networks X and Y to DUT. X has stronger 237 RSSI than Y. X has wrong password configured. 238 2. Move the DUT in range. 239 3. Verify the DUT is connected to network Y. 240 """ 241 # add two saved networks to DUT, and one of them is configured with 242 # incorrect password 243 wrong_passwd_network = self.reference_networks[AP_1]['5g'].copy() 244 wrong_passwd_network['password'] += 'haha' 245 networks = [wrong_passwd_network, self.reference_networks[AP_2]['5g']] 246 self.add_networks(self.dut, networks) 247 248 # make AP_1 5G has stronger RSSI than AP_2 5G 249 self.attenuators[self.ap1_5g_attn].set_atten(MIN_ATTN) 250 self.attenuators[self.ap2_5g_attn].set_atten(LVL1_ATTN) 251 time.sleep(ATTN_SLEEP) 252 253 # start 3 scans to get AP_1 5G blacklisted because of the incorrect 254 # password 255 for _ in range(3): 256 wutils.start_wifi_connection_scan_and_return_status(self.dut) 257 time.sleep(NETWORK_SELECTION_TIME_GAP) 258 259 # verify DUT is connect AP_2 5G 260 network = self.reference_networks[AP_2]['5g'].copy() 261 if "OpenWrtAP" in self.user_params: 262 network['bssid'] = self.bssid_map[AP_2]['5g'][network["SSID"]] 263 self.connect_and_verify_connected_bssid(network) 264 265 @test_tracker_info(uuid="71d88fcf-c7b8-4fd2-a7cb-84ac4a130ecf") 266 def network_selector_2g_to_5g_prefer_same_SSID(self): 267 """ 268 1. Add SSID_A and SSID_B to DUT. Both SSIDs have both 2G and 5G 269 BSSIDs. 270 2. Attenuate the networks so that the DUT is connected to SSID_A's 271 2G in the beginning. 272 3. Increase the RSSI of both SSID_A's 5G and SSID_B's 5G. 273 4. Verify the DUT switches to SSID_A's 5G. 274 """ 275 #add two saved networks to DUT 276 networks = [ 277 self.reference_networks[AP_1]['2g'], 278 self.reference_networks[AP_2]['2g'] 279 ] 280 self.add_networks(self.dut, networks) 281 #make AP_1 2G in range 282 self.attenuators[AP_1_2G_ATTENUATOR].set_atten(0) 283 #verify 284 self.connect_and_verify_connected_bssid( 285 self.reference_networks[AP_1]['2g']['bssid']) 286 #make both AP_1 and AP_2 5G in range with similar RSSI 287 self.attenuators[AP_1_5G_ATTENUATOR].set_atten(0) 288 self.attenuators[AP_2_5G_ATTENUATOR].set_atten(0) 289 #ensure the time gap between two network selections 290 time.sleep(NETWORK_SELECTION_TIME_GAP) 291 #verify 292 self.connect_and_verify_connected_bssid( 293 self.reference_networks[AP_1]['5g']['bssid']) 294 295 @test_tracker_info(uuid="c1243cf4-d96e-427e-869e-3d640bee3f28") 296 def network_selector_2g_to_5g_different_ssid(self): 297 """ 298 1. Add SSID_A and SSID_B to DUT. Both SSIDs have both 2G and 5G 299 BSSIDs. 300 2. Attenuate the networks so that the DUT is connected to SSID_A's 301 2G in the beginning. 302 3. Increase the RSSI of SSID_B's 5G while attenuate down SSID_A's 303 2G RSSI. 304 4. Verify the DUT switches to SSID_B's 5G. 305 """ 306 # add two saved networks to DUT 307 networks = [ 308 self.reference_networks[AP_1]['2g'], 309 self.reference_networks[AP_2]['2g'] 310 ] 311 self.add_networks(self.dut, networks) 312 313 # make both AP_1 2G and AP_2 5G in range, and AP_1 2G 314 # has much stronger RSSI than AP_2 5G 315 self.attenuators[AP_1_2G_ATTENUATOR].set_atten(0) 316 self.attenuators[AP_2_5G_ATTENUATOR].set_atten(20) 317 #verify 318 self.connect_and_verify_connected_bssid( 319 self.reference_networks[AP_1]['2g']['bssid']) 320 #bump up AP_2 5G RSSI and reduce AP_1 2G RSSI 321 self.attenuators[AP_1_2G_ATTENUATOR].set_atten(40) 322 self.attenuators[AP_2_5G_ATTENUATOR].set_atten(0) 323 #ensure the time gap between two network selections 324 time.sleep(NETWORK_SELECTION_TIME_GAP) 325 #verify 326 self.connect_and_verify_connected_bssid( 327 self.reference_networks[AP_2]['5g']['bssid']) 328 329 @test_tracker_info(uuid="10da95df-83ed-4447-89f8-735b08dbe2eb") 330 def network_selector_5g_to_2g_same_ssid(self): 331 """ 332 1. Add one SSID that has both 2G and 5G to the DUT. 333 2. Attenuate down the 2G RSSI. 334 3. Connect the DUT to the 5G BSSID. 335 4. Bring up the 2G RSSI and attenuate down the 5G RSSI. 336 5. Verify the DUT switches to the 2G BSSID. 337 """ 338 #add a saved network to DUT 339 networks = [self.reference_networks[AP_1]['2g']] 340 self.add_networks(self.dut, networks) 341 #make both AP_1 2G and AP_2 5G in range, and AP_1 5G 342 #has much stronger RSSI than AP_2 2G 343 self.attenuators[AP_1_5G_ATTENUATOR].set_atten(0) 344 self.attenuators[AP_1_2G_ATTENUATOR].set_atten(50) 345 #verify 346 self.connect_and_verify_connected_bssid( 347 self.reference_networks[AP_1]['5g']['bssid']) 348 #bump up AP_1 2G RSSI and reduce AP_1 5G RSSI 349 self.attenuators[AP_1_2G_ATTENUATOR].set_atten(0) 350 self.attenuators[AP_1_5G_ATTENUATOR].set_atten(30) 351 #ensure the time gap between two network selections 352 time.sleep(NETWORK_SELECTION_TIME_GAP) 353 #verify 354 self.connect_and_verify_connected_bssid( 355 self.reference_networks[AP_1]['2g']['bssid']) 356 357 @test_tracker_info(uuid="ead78ae0-27ab-4bb8-ae77-0b9fe588436a") 358 def test_network_selector_stay_on_sufficient_network(self): 359 """ 360 1. Add two 5G WPA2 BSSIDs X and Y to the DUT. X has higher RSSI 361 than Y. 362 2. Connect the DUT to X. 363 3. Change attenuation so that Y's RSSI goes above X's. 364 4. Verify the DUT stays on X. 365 """ 366 # add two saved networks to DUT 367 networks = [ 368 self.reference_networks[AP_1]['5g'], 369 self.reference_networks[AP_2]['5g'] 370 ] 371 self.add_networks(self.dut, networks) 372 373 # make both AP_1 5G and AP_2 5G in range, and AP_1 5G 374 # has stronger RSSI than AP_2 5G 375 self.attenuators[self.ap1_5g_attn].set_atten(LVL1_ATTN) 376 self.attenuators[self.ap2_5g_attn].set_atten(LVL2_ATTN) 377 time.sleep(ATTN_SLEEP) 378 379 # verify DUT is connected to AP_1 380 network = self.reference_networks[AP_1]['5g'].copy() 381 if "OpenWrtAP" in self.user_params: 382 network['bssid'] = self.bssid_map[AP_1]['5g'][network["SSID"]] 383 self.connect_and_verify_connected_bssid(network) 384 385 # bump up AP_2 5G RSSI over AP_1 5G RSSI 386 self.attenuators[self.ap2_5g_attn].set_atten(MIN_ATTN) 387 388 # ensure the time gap between two network selections 389 time.sleep(NETWORK_SELECTION_TIME_GAP) 390 391 # verify DUT is still connected to AP_1 392 self.connect_and_verify_connected_bssid(network) 393 394 @test_tracker_info(uuid="5470010f-8b62-4b1c-8b83-1f91422eced0") 395 def test_network_selector_stay_on_user_selected_network(self): 396 """ 397 1. Connect the DUT to SSID_A with a very low RSSI via the user select code path. 398 2. Add SSID_B to the DUT as saved network. SSID_B has higher RSSI than SSID_A. 399 3. Start a scan and network selection. 400 4. Verify DUT stays on SSID_A. 401 """ 402 # set max attenuation on AP_2 and make AP_1 5G in range with low RSSI 403 self.attenuators[self.ap2_5g_attn].set_atten(MIN_ATTN) 404 self.attenuators[self.ap1_5g_attn].set_atten(LVL1_ATTN) 405 time.sleep(ATTN_SLEEP) 406 407 # connect to AP_1 via user selection and add, save AP_2 408 wutils.connect_to_wifi_network(self.dut, 409 self.reference_networks[AP_1]['5g']) 410 networks = [self.reference_networks[AP_2]['5g']] 411 self.add_networks(self.dut, networks) 412 413 # ensure the time gap between two network selections 414 time.sleep(NETWORK_SELECTION_TIME_GAP) 415 416 # verify we are still connected to AP_1 5G 417 network = self.reference_networks[AP_1]['5g'].copy() 418 if "OpenWrtAP" in self.user_params: 419 network['bssid'] = self.bssid_map[AP_1]['5g'][network["SSID"]] 420 self.connect_and_verify_connected_bssid(network) 421 422 @test_tracker_info(uuid="f08d8f73-8c94-42af-bba9-4c49bbf16420") 423 def test_network_selector_reselect_after_forget_network(self): 424 """ 425 1. Add two 5G BSSIDs X and Y to the DUT. X has higher RSSI 426 than Y. 427 2. Connect the DUT to X. 428 3. Forget X. 429 5. Verify the DUT reselect and connect to Y. 430 """ 431 # add two networks to DUT 432 networks = [ 433 self.reference_networks[AP_1]['5g'], 434 self.reference_networks[AP_2]['5g'] 435 ] 436 self.add_networks(self.dut, networks) 437 438 # make both AP_1 5G and AP_2 5G in range. AP_1 5G has stronger 439 # RSSI than AP_2 5G 440 self.attenuators[self.ap1_5g_attn].set_atten(MIN_ATTN) 441 self.attenuators[self.ap2_5g_attn].set_atten(LVL1_ATTN) 442 time.sleep(ATTN_SLEEP) 443 444 # verify DUT connected to AP1 445 network = self.reference_networks[AP_1]['5g'].copy() 446 if "OpenWrtAP" in self.user_params: 447 network['bssid'] = self.bssid_map[AP_1]['5g'][network["SSID"]] 448 self.connect_and_verify_connected_bssid(network) 449 450 # forget AP_1 451 wutils.wifi_forget_network(self.dut, 452 self.reference_networks[AP_1]['5g']['SSID']) 453 454 # verify DUT connected to AP2 455 network = self.reference_networks[AP_2]['5g'].copy() 456 if "OpenWrtAP" in self.user_params: 457 network['bssid'] = self.bssid_map[AP_2]['5g'][network["SSID"]] 458 self.connect_and_verify_connected_bssid(network) 459