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