1# !/usr/bin/env python3.4 2# 3# Copyright 2017 - 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 re 18from acts import asserts 19from acts.controllers.android_device import SL4A_APK_NAME 20from acts.libs.ota import ota_updater 21import acts.signals as signals 22from acts.test_decorators import test_tracker_info 23from acts_contrib.test_utils.tel.tel_wifi_utils import WIFI_CONFIG_APBAND_5G 24import acts_contrib.test_utils.wifi.wifi_test_utils as wutils 25from acts_contrib.test_utils.wifi.WifiBaseTest import WifiBaseTest 26import acts.utils as utils 27 28WifiEnums = wutils.WifiEnums 29SSID = WifiEnums.SSID_KEY 30PWD = WifiEnums.PWD_KEY 31NETID = WifiEnums.NETID_KEY 32# Default timeout used for reboot, toggle WiFi and Airplane mode, 33# for the system to settle down after the operation. 34DEFAULT_TIMEOUT = 10 35BAND_2GHZ = 0 36BAND_5GHZ = 1 37 38 39class WifiAutoUpdateTest(WifiBaseTest): 40 """Tests for APIs in Android's WifiManager class. 41 42 Test Bed Requirement: 43 * One Android device 44 * Several Wi-Fi networks visible to the device, including an open Wi-Fi 45 network. 46 """ 47 48 def __init__(self, controllers): 49 WifiBaseTest.__init__(self, controllers) 50 self.tests = ( 51 "test_check_wifi_state_after_au", 52 "test_verify_networks_after_au", 53 "test_configstore_after_au", 54 "test_mac_randomization_after_au", 55 "test_wifi_hotspot_5g_psk_after_au", 56 "test_all_networks_connectable_after_au", 57 "test_connect_to_network_suggestion_after_au", 58 "test_check_wifi_toggling_after_au", 59 "test_connection_to_new_networks", 60 "test_reset_wifi_after_au") 61 62 def setup_class(self): 63 super(WifiAutoUpdateTest, self).setup_class() 64 ota_updater.initialize(self.user_params, self.android_devices) 65 self.dut = self.android_devices[0] 66 self.dut_client = self.android_devices[1] 67 wutils.wifi_test_device_init(self.dut) 68 wutils.wifi_toggle_state(self.dut, True) 69 70 # configure APs 71 opt_param = ["reference_networks"] 72 self.unpack_userparams(opt_param_names=opt_param) 73 if "AccessPoint" in self.user_params: 74 self.legacy_configure_ap_and_start(wpa_network=True, 75 wep_network=True) 76 elif "OpenWrtAP" in self.user_params: 77 self.configure_openwrt_ap_and_start(wpa_network=True, 78 wep_network=True, 79 ap_count=2) 80 self.wpapsk_2g = self.reference_networks[0]["2g"] 81 self.wpapsk_5g = self.reference_networks[0]["5g"] 82 self.wep_2g = self.wep_networks[0]["2g"] 83 self.wep_5g = self.wep_networks[0]["5g"] 84 85 # saved & connected networks, network suggestions 86 # and new networks 87 self.saved_networks = [self.wep_2g] 88 self.network_suggestions = [self.wpapsk_5g] 89 self.connected_networks = [self.wpapsk_2g, self.wep_5g] 90 self.new_networks = [self.reference_networks[1]["2g"], 91 self.wep_networks[1]["5g"]] 92 93 # add pre ota upgrade configuration 94 self.wifi_config_list = [] 95 self.pre_default_mac = {} 96 self.pre_random_mac = {} 97 self.pst_default_mac = {} 98 self.pst_random_mac = {} 99 self.add_pre_update_configuration() 100 101 # Run OTA below, if ota fails then abort all tests. 102 try: 103 ota_updater.update(self.dut) 104 except Exception as e: 105 raise signals.TestAbortClass( 106 "Failed up apply OTA update. Aborting tests: %s" % e) 107 108 def setup_test(self): 109 super().setup_test() 110 self.dut.droid.wakeLockAcquireBright() 111 self.dut.droid.wakeUpNow() 112 113 def teardown_test(self): 114 super().teardown_test() 115 self.dut.droid.wakeLockRelease() 116 self.dut.droid.goToSleepNow() 117 118 def teardown_class(self): 119 if "AccessPoint" in self.user_params: 120 del self.user_params["reference_networks"] 121 122 ### Helper Methods 123 124 def add_pre_update_configuration(self): 125 self.add_network_suggestions(self.network_suggestions) 126 self.add_network_and_enable(self.saved_networks[0]) 127 self.add_wifi_hotspot() 128 self.connect_to_multiple_networks(self.connected_networks) 129 130 def add_wifi_hotspot(self): 131 self.wifi_hotspot = {"SSID": "hotspot_%s" % utils.rand_ascii_str(6), 132 "password": "pass_%s" % utils.rand_ascii_str(6)} 133 band = WIFI_CONFIG_APBAND_5G 134 if self.dut.build_info["build_id"].startswith("R"): 135 band = WifiEnums.WIFI_CONFIG_SOFTAP_BAND_5G 136 self.wifi_hotspot[WifiEnums.AP_BAND_KEY] = band 137 asserts.assert_true( 138 self.dut.droid.wifiSetWifiApConfiguration(self.wifi_hotspot), 139 "Failed to set WifiAp Configuration") 140 wifi_ap = self.dut.droid.wifiGetApConfiguration() 141 asserts.assert_true( 142 wifi_ap[WifiEnums.SSID_KEY] == self.wifi_hotspot[WifiEnums.SSID_KEY], 143 "Hotspot SSID doesn't match with expected SSID") 144 return 145 if self.dut.build_info["build_id"].startswith("Q"): 146 band = WifiEnums.WIFI_CONFIG_APBAND_5G_OLD 147 self.wifi_hotspot[WifiEnums.AP_BAND_KEY] = band 148 asserts.assert_true( 149 self.dut.droid.wifiSetWifiApConfiguration(self.wifi_hotspot), 150 "Failed to set WifiAp Configuration") 151 wifi_ap = self.dut.droid.wifiGetApConfiguration() 152 asserts.assert_true( 153 wifi_ap[WifiEnums.SSID_KEY] == self.wifi_hotspot[WifiEnums.SSID_KEY], 154 "Hotspot SSID doesn't match with expected SSID") 155 return 156 wutils.save_wifi_soft_ap_config(self.dut, self.wifi_hotspot, band) 157 158 def verify_wifi_hotspot(self): 159 """Verify wifi tethering.""" 160 wutils.start_wifi_tethering_saved_config(self.dut) 161 wutils.connect_to_wifi_network(self.dut_client, 162 self.wifi_hotspot, 163 check_connectivity=False) 164 wutils.stop_wifi_tethering(self.dut) 165 166 def connect_to_multiple_networks(self, networks): 167 """Connect to a list of wifi networks. 168 169 Args: 170 networks : list of wifi networks. 171 """ 172 self.log.info("Connect to multiple wifi networks") 173 for network in networks: 174 ssid = network[SSID] 175 wutils.start_wifi_connection_scan_and_ensure_network_found( 176 self.dut, ssid) 177 wutils.wifi_connect(self.dut, network, num_of_tries=6) 178 self.wifi_config_list.append(network) 179 self.pre_default_mac[network[SSID]] = self.get_sta_mac_address() 180 self.pre_random_mac[network[SSID]] = \ 181 self.dut.droid.wifigetRandomizedMacAddress(network) 182 183 def get_sta_mac_address(self): 184 """Gets the current MAC address being used for client mode.""" 185 out = self.dut.adb.shell("ifconfig wlan0") 186 res = re.match(".* HWaddr (\S+).*", out, re.S) 187 return res.group(1) 188 189 def add_network_suggestions(self, network_suggestions): 190 """Add wifi network suggestions to DUT. 191 192 Args: 193 network_suggestions : suggestions to add. 194 """ 195 self.dut.log.info("Adding network suggestions") 196 asserts.assert_true( 197 self.dut.droid.wifiAddNetworkSuggestions(network_suggestions), 198 "Failed to add suggestions") 199 200 # Enable suggestions by the app. 201 self.dut.log.debug("Enabling suggestions from test") 202 self.dut.adb.shell( 203 "cmd wifi network-suggestions-set-user-approved %s yes" % \ 204 SL4A_APK_NAME) 205 206 def remove_suggestions_and_ensure_no_connection(self, 207 network_suggestions, 208 expected_ssid): 209 """Remove network suggestions. 210 211 Args: 212 network_suggestions : suggestions to remove. 213 expected_ssid : SSID to verify that DUT is not connected. 214 """ 215 # remove network suggestion and verify disconnect 216 self.dut.log.info("Removing network suggestions") 217 asserts.assert_true( 218 self.dut.droid.wifiRemoveNetworkSuggestions(network_suggestions), 219 "Failed to remove suggestions") 220 221 wutils.wait_for_disconnect(self.dut) 222 self.dut.ed.clear_all_events() 223 224 # Now ensure that we didn't connect back. 225 asserts.assert_false( 226 wutils.wait_for_connect(self.dut, 227 expected_ssid, 228 assert_on_fail=False), 229 "Device should not connect back") 230 231 def add_network_and_enable(self, network): 232 """Add a network and enable it. 233 234 Args: 235 network : Network details for the network to be added. 236 """ 237 self.log.info("Add a wifi network and enable it") 238 ret = self.dut.droid.wifiAddNetwork(network) 239 asserts.assert_true(ret != -1, "Add network %r failed" % network) 240 self.wifi_config_list.append({SSID: network[SSID], NETID: ret}) 241 self.dut.droid.wifiEnableNetwork(ret, 0) 242 243 def check_networks_after_autoupdate(self, networks): 244 """Verify that all previously configured networks are persistent. 245 246 Args: 247 networks: List of network dicts. 248 """ 249 network_info = self.dut.droid.wifiGetConfiguredNetworks() 250 """ 251 b/189285598, the network id of a network might be changed after \ 252 reboot because the network sequence is not stable on \ 253 backup/restore. This test should find the correct network against 254 the desired SSID before connecting to the network after reboot. 255 Start from Android S. 256 """ 257 network_info_ssid = list() 258 for i in network_info: 259 network_info_ssid.append(i['SSID']) 260 network_info_ssid_list = set(network_info_ssid) 261 networks_ssid= list() 262 for i in networks: 263 networks_ssid.append(i['SSID']) 264 networks_ssid_list = set(networks_ssid) 265 if len(network_info_ssid_list) != len(networks_ssid_list): 266 msg = ( 267 "Number of configured networks before and after Auto-update " 268 "don't match. \nBefore reboot = %s \n After reboot = %s" % 269 (networks, network_info)) 270 raise signals.TestFailure(msg) 271 272 # For each network, check if it exists in configured list after Auto- 273 # update. 274 for network in networks: 275 exists = wutils.match_networks({SSID: network[SSID]}, network_info) 276 if not exists: 277 raise signals.TestFailure("%s network is not present in the" 278 " configured list after Auto-update" % 279 network[SSID]) 280 281 # Get the new network id for each network after reboot. 282 network[NETID] = exists[0]["networkId"] 283 284 def get_enabled_network(self, network1, network2): 285 """Check network status and return currently unconnected network. 286 287 Args: 288 network1: dict representing a network. 289 network2: dict representing a network. 290 291 Returns: 292 Network dict of the unconnected network. 293 """ 294 wifi_info = self.dut.droid.wifiGetConnectionInfo() 295 enabled = network1 296 if wifi_info[SSID] == network1[SSID]: 297 enabled = network2 298 return enabled 299 300 ### Tests 301 302 @test_tracker_info(uuid="9ff1f01e-e5ff-408b-9a95-29e87a2df2d8") 303 @WifiBaseTest.wifi_test_wrap 304 def test_check_wifi_state_after_au(self): 305 """Check if the state of WiFi is enabled after Auto-update.""" 306 if not self.dut.droid.wifiCheckState(): 307 raise signals.TestFailure("WiFi is disabled after Auto-update!!!") 308 309 @test_tracker_info(uuid="e3ebdbba-71dd-4281-aef8-5b3d42b88770") 310 @WifiBaseTest.wifi_test_wrap 311 def test_verify_networks_after_au(self): 312 """Check if the previously added networks are intact. 313 314 Steps: 315 Number of networs should be the same and match each network. 316 317 """ 318 self.check_networks_after_autoupdate(self.wifi_config_list) 319 320 @test_tracker_info(uuid="799e83c2-305d-4510-921e-dac3c0dbb6c5") 321 @WifiBaseTest.wifi_test_wrap 322 def test_configstore_after_au(self): 323 """Verify DUT automatically connects to wifi networks after ota. 324 325 Steps: 326 1. Connect to two wifi networks pre ota. 327 2. Verify DUT automatically connects to 1 after ota. 328 3. Re-connect to the other wifi network. 329 """ 330 wifi_info = self.dut.droid.wifiGetConnectionInfo() 331 self.pst_default_mac[wifi_info[SSID]] = self.get_sta_mac_address() 332 self.pst_random_mac[wifi_info[SSID]] = \ 333 self.dut.droid.wifigetRandomizedMacAddress(wifi_info) 334 reconnect_to = self.get_enabled_network(self.wifi_config_list[1], 335 self.wifi_config_list[2]) 336 wutils.start_wifi_connection_scan_and_ensure_network_found( 337 self.dut, reconnect_to[SSID]) 338 wutils.wifi_connect_by_id(self.dut, reconnect_to[NETID]) 339 connect_data = self.dut.droid.wifiGetConnectionInfo() 340 connect_ssid = connect_data[SSID] 341 self.log.info("Expected SSID = %s" % reconnect_to[SSID]) 342 self.log.info("Connected SSID = %s" % connect_ssid) 343 if connect_ssid != reconnect_to[SSID]: 344 raise signals.TestFailure( 345 "Device failed to reconnect to the correct" 346 " network after reboot.") 347 self.pst_default_mac[wifi_info[SSID]] = self.get_sta_mac_address() 348 self.pst_random_mac[wifi_info[SSID]] = \ 349 self.dut.droid.wifigetRandomizedMacAddress(wifi_info) 350 351 for network in self.connected_networks: 352 wutils.wifi_forget_network(self.dut, network[SSID]) 353 354 @test_tracker_info(uuid="e26d0ed9-9457-4a95-a962-4d43b0032bac") 355 @WifiBaseTest.wifi_test_wrap 356 def test_mac_randomization_after_au(self): 357 """Verify randomized MAC addrs are persistent after ota. 358 359 Steps: 360 1. Reconnect to the wifi networks configured pre ota. 361 2. Get the randomized MAC addrs. 362 """ 363 for ssid, mac in self.pst_random_mac.items(): 364 asserts.assert_true( 365 self.pre_random_mac[ssid] == mac, 366 "MAC addr of %s is %s after ota. Expected %s" % 367 (ssid, mac, self.pre_random_mac[ssid])) 368 369 @test_tracker_info(uuid="f68a65e6-97b7-4746-bad8-4c206551d87e") 370 @WifiBaseTest.wifi_test_wrap 371 def test_wifi_hotspot_5g_psk_after_au(self): 372 """Verify hotspot after ota upgrade. 373 374 Steps: 375 1. Start wifi hotspot on the saved config. 376 2. Verify DUT client connects to it. 377 """ 378 self.verify_wifi_hotspot() 379 380 @test_tracker_info(uuid="21f91372-88a6-44b9-a4e8-d4664823dffb") 381 @WifiBaseTest.wifi_test_wrap 382 def test_connect_to_network_suggestion_after_au(self): 383 """Verify connection to network suggestion after ota. 384 385 Steps: 386 1. DUT has network suggestion added before OTA. 387 2. Wait for the device to connect to it. 388 3. Remove the suggestions and ensure the device does not 389 connect back. 390 """ 391 wutils.reset_wifi(self.dut) 392 wutils.start_wifi_connection_scan_and_return_status(self.dut) 393 wutils.wait_for_connect(self.dut, self.network_suggestions[0][SSID]) 394 self.remove_suggestions_and_ensure_no_connection( 395 self.network_suggestions, self.network_suggestions[0][SSID]) 396 397 @test_tracker_info(uuid="b8e47a4f-62fe-4a0e-b999-27ae1ebf4d19") 398 @WifiBaseTest.wifi_test_wrap 399 def test_connection_to_new_networks(self): 400 """Check if we can connect to new networks after Auto-update. 401 402 Steps: 403 1. Connect to a PSK network. 404 2. Connect to an open network. 405 3. Forget ntworks added in 1 & 2. 406 TODO: (@bmahadev) Add WEP network once it's ready. 407 """ 408 for network in self.new_networks: 409 wutils.connect_to_wifi_network(self.dut, network) 410 for network in self.new_networks: 411 wutils.wifi_forget_network(self.dut, network[SSID]) 412 413 @test_tracker_info(uuid="1d8309e4-d5a2-4f48-ba3b-895a58c9bf3a") 414 @WifiBaseTest.wifi_test_wrap 415 def test_all_networks_connectable_after_au(self): 416 """Check if previously added networks are connectable. 417 418 Steps: 419 1. Connect to previously added PSK network using network id. 420 2. Connect to previously added open network using network id. 421 TODO: (@bmahadev) Add WEP network once it's ready. 422 """ 423 network = self.wifi_config_list[0] 424 if not wutils.connect_to_wifi_network_with_id(self.dut, 425 network[NETID], 426 network[SSID]): 427 raise signals.TestFailure("Failed to connect to %s after OTA" % 428 network[SSID]) 429 wutils.wifi_forget_network(self.dut, network[SSID]) 430 431 @test_tracker_info(uuid="05671859-38b1-4dbf-930c-18048971d075") 432 @WifiBaseTest.wifi_test_wrap 433 def test_check_wifi_toggling_after_au(self): 434 """Check if WiFi can be toggled ON/OFF after auto-update.""" 435 self.log.debug("Going from on to off.") 436 wutils.wifi_toggle_state(self.dut, False) 437 self.log.debug("Going from off to on.") 438 wutils.wifi_toggle_state(self.dut, True) 439 440 @test_tracker_info(uuid="440edf32-4b00-42b0-9811-9f2bc4a83efb") 441 @WifiBaseTest.wifi_test_wrap 442 def test_reset_wifi_after_au(self): 443 """"Check if WiFi can be reset after auto-update.""" 444 wutils.reset_wifi(self.dut) 445