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