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