1#!/usr/bin/env python3 2# 3# Copyright 2016 Google, Inc. 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 os 19import re 20import shutil 21import time 22 23from collections import namedtuple 24from enum import IntEnum 25from queue import Empty 26 27from acts import asserts 28from acts import context 29from acts import signals 30from acts import utils 31from acts.controllers import attenuator 32from acts.controllers.ap_lib import hostapd_security 33from acts.controllers.ap_lib import hostapd_ap_preset 34from acts.controllers.ap_lib.hostapd_constants import BAND_2G 35from acts.controllers.ap_lib.hostapd_constants import BAND_5G 36from acts.test_utils.wifi import wifi_constants 37from acts.test_utils.tel import tel_defines 38 39# Default timeout used for reboot, toggle WiFi and Airplane mode, 40# for the system to settle down after the operation. 41DEFAULT_TIMEOUT = 10 42# Number of seconds to wait for events that are supposed to happen quickly. 43# Like onSuccess for start background scan and confirmation on wifi state 44# change. 45SHORT_TIMEOUT = 30 46ROAMING_TIMEOUT = 30 47WIFI_CONNECTION_TIMEOUT_DEFAULT = 30 48# Speed of light in m/s. 49SPEED_OF_LIGHT = 299792458 50 51DEFAULT_PING_ADDR = "https://www.google.com/robots.txt" 52 53ROAMING_ATTN = { 54 "AP1_on_AP2_off": [ 55 0, 56 0, 57 95, 58 95 59 ], 60 "AP1_off_AP2_on": [ 61 95, 62 95, 63 0, 64 0 65 ], 66 "default": [ 67 0, 68 0, 69 0, 70 0 71 ] 72 } 73 74 75class WifiEnums(): 76 77 SSID_KEY = "SSID" # Used for Wifi & SoftAp 78 SSID_PATTERN_KEY = "ssidPattern" 79 NETID_KEY = "network_id" 80 BSSID_KEY = "BSSID" # Used for Wifi & SoftAp 81 BSSID_PATTERN_KEY = "bssidPattern" 82 PWD_KEY = "password" # Used for Wifi & SoftAp 83 frequency_key = "frequency" 84 HIDDEN_KEY = "hiddenSSID" # Used for Wifi & SoftAp 85 IS_APP_INTERACTION_REQUIRED = "isAppInteractionRequired" 86 IS_USER_INTERACTION_REQUIRED = "isUserInteractionRequired" 87 IS_SUGGESTION_METERED = "isMetered" 88 PRIORITY = "priority" 89 SECURITY = "security" # Used for Wifi & SoftAp 90 91 # Used for SoftAp 92 AP_BAND_KEY = "apBand" 93 AP_CHANNEL_KEY = "apChannel" 94 AP_MAXCLIENTS_KEY = "MaxNumberOfClients" 95 AP_SHUTDOWNTIMEOUT_KEY = "ShutdownTimeoutMillis" 96 AP_SHUTDOWNTIMEOUTENABLE_KEY = "AutoShutdownEnabled" 97 AP_CLIENTCONTROL_KEY = "ClientControlByUserEnabled" 98 AP_ALLOWEDLIST_KEY = "AllowedClientList" 99 AP_BLOCKEDLIST_KEY = "BlockedClientList" 100 101 WIFI_CONFIG_SOFTAP_BAND_2G = 1 102 WIFI_CONFIG_SOFTAP_BAND_5G = 2 103 WIFI_CONFIG_SOFTAP_BAND_2G_5G = 3 104 WIFI_CONFIG_SOFTAP_BAND_6G = 4 105 WIFI_CONFIG_SOFTAP_BAND_2G_6G = 5 106 WIFI_CONFIG_SOFTAP_BAND_5G_6G = 6 107 WIFI_CONFIG_SOFTAP_BAND_ANY = 7 108 109 # DO NOT USE IT for new test case! Replaced by WIFI_CONFIG_SOFTAP_BAND_ 110 WIFI_CONFIG_APBAND_2G = WIFI_CONFIG_SOFTAP_BAND_2G 111 WIFI_CONFIG_APBAND_5G = WIFI_CONFIG_SOFTAP_BAND_5G 112 WIFI_CONFIG_APBAND_AUTO = WIFI_CONFIG_SOFTAP_BAND_2G_5G 113 114 WIFI_CONFIG_APBAND_2G_OLD = 0 115 WIFI_CONFIG_APBAND_5G_OLD = 1 116 WIFI_CONFIG_APBAND_AUTO_OLD = -1 117 118 WIFI_WPS_INFO_PBC = 0 119 WIFI_WPS_INFO_DISPLAY = 1 120 WIFI_WPS_INFO_KEYPAD = 2 121 WIFI_WPS_INFO_LABEL = 3 122 WIFI_WPS_INFO_INVALID = 4 123 124 class SoftApSecurityType(): 125 OPEN = "NONE" 126 WPA2 = "WPA2_PSK" 127 WPA3_SAE_TRANSITION = "WPA3_SAE_TRANSITION" 128 WPA3_SAE = "WPA3_SAE" 129 130 class CountryCode(): 131 CHINA = "CN" 132 JAPAN = "JP" 133 UK = "GB" 134 US = "US" 135 UNKNOWN = "UNKNOWN" 136 137 # Start of Macros for EAP 138 # EAP types 139 class Eap(IntEnum): 140 NONE = -1 141 PEAP = 0 142 TLS = 1 143 TTLS = 2 144 PWD = 3 145 SIM = 4 146 AKA = 5 147 AKA_PRIME = 6 148 UNAUTH_TLS = 7 149 150 # EAP Phase2 types 151 class EapPhase2(IntEnum): 152 NONE = 0 153 PAP = 1 154 MSCHAP = 2 155 MSCHAPV2 = 3 156 GTC = 4 157 158 class Enterprise: 159 # Enterprise Config Macros 160 EMPTY_VALUE = "NULL" 161 EAP = "eap" 162 PHASE2 = "phase2" 163 IDENTITY = "identity" 164 ANON_IDENTITY = "anonymous_identity" 165 PASSWORD = "password" 166 SUBJECT_MATCH = "subject_match" 167 ALTSUBJECT_MATCH = "altsubject_match" 168 DOM_SUFFIX_MATCH = "domain_suffix_match" 169 CLIENT_CERT = "client_cert" 170 CA_CERT = "ca_cert" 171 ENGINE = "engine" 172 ENGINE_ID = "engine_id" 173 PRIVATE_KEY_ID = "key_id" 174 REALM = "realm" 175 PLMN = "plmn" 176 FQDN = "FQDN" 177 FRIENDLY_NAME = "providerFriendlyName" 178 ROAMING_IDS = "roamingConsortiumIds" 179 OCSP = "ocsp" 180 # End of Macros for EAP 181 182 # Macros for wifi p2p. 183 WIFI_P2P_SERVICE_TYPE_ALL = 0 184 WIFI_P2P_SERVICE_TYPE_BONJOUR = 1 185 WIFI_P2P_SERVICE_TYPE_UPNP = 2 186 WIFI_P2P_SERVICE_TYPE_VENDOR_SPECIFIC = 255 187 188 class ScanResult: 189 CHANNEL_WIDTH_20MHZ = 0 190 CHANNEL_WIDTH_40MHZ = 1 191 CHANNEL_WIDTH_80MHZ = 2 192 CHANNEL_WIDTH_160MHZ = 3 193 CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 4 194 195 # Macros for wifi rtt. 196 class RttType(IntEnum): 197 TYPE_ONE_SIDED = 1 198 TYPE_TWO_SIDED = 2 199 200 class RttPeerType(IntEnum): 201 PEER_TYPE_AP = 1 202 PEER_TYPE_STA = 2 # Requires NAN. 203 PEER_P2P_GO = 3 204 PEER_P2P_CLIENT = 4 205 PEER_NAN = 5 206 207 class RttPreamble(IntEnum): 208 PREAMBLE_LEGACY = 0x01 209 PREAMBLE_HT = 0x02 210 PREAMBLE_VHT = 0x04 211 212 class RttBW(IntEnum): 213 BW_5_SUPPORT = 0x01 214 BW_10_SUPPORT = 0x02 215 BW_20_SUPPORT = 0x04 216 BW_40_SUPPORT = 0x08 217 BW_80_SUPPORT = 0x10 218 BW_160_SUPPORT = 0x20 219 220 class Rtt(IntEnum): 221 STATUS_SUCCESS = 0 222 STATUS_FAILURE = 1 223 STATUS_FAIL_NO_RSP = 2 224 STATUS_FAIL_REJECTED = 3 225 STATUS_FAIL_NOT_SCHEDULED_YET = 4 226 STATUS_FAIL_TM_TIMEOUT = 5 227 STATUS_FAIL_AP_ON_DIFF_CHANNEL = 6 228 STATUS_FAIL_NO_CAPABILITY = 7 229 STATUS_ABORTED = 8 230 STATUS_FAIL_INVALID_TS = 9 231 STATUS_FAIL_PROTOCOL = 10 232 STATUS_FAIL_SCHEDULE = 11 233 STATUS_FAIL_BUSY_TRY_LATER = 12 234 STATUS_INVALID_REQ = 13 235 STATUS_NO_WIFI = 14 236 STATUS_FAIL_FTM_PARAM_OVERRIDE = 15 237 238 REASON_UNSPECIFIED = -1 239 REASON_NOT_AVAILABLE = -2 240 REASON_INVALID_LISTENER = -3 241 REASON_INVALID_REQUEST = -4 242 243 class RttParam: 244 device_type = "deviceType" 245 request_type = "requestType" 246 BSSID = "bssid" 247 channel_width = "channelWidth" 248 frequency = "frequency" 249 center_freq0 = "centerFreq0" 250 center_freq1 = "centerFreq1" 251 number_burst = "numberBurst" 252 interval = "interval" 253 num_samples_per_burst = "numSamplesPerBurst" 254 num_retries_per_measurement_frame = "numRetriesPerMeasurementFrame" 255 num_retries_per_FTMR = "numRetriesPerFTMR" 256 lci_request = "LCIRequest" 257 lcr_request = "LCRRequest" 258 burst_timeout = "burstTimeout" 259 preamble = "preamble" 260 bandwidth = "bandwidth" 261 margin = "margin" 262 263 RTT_MARGIN_OF_ERROR = { 264 RttBW.BW_80_SUPPORT: 2, 265 RttBW.BW_40_SUPPORT: 5, 266 RttBW.BW_20_SUPPORT: 5 267 } 268 269 # Macros as specified in the WifiScanner code. 270 WIFI_BAND_UNSPECIFIED = 0 # not specified 271 WIFI_BAND_24_GHZ = 1 # 2.4 GHz band 272 WIFI_BAND_5_GHZ = 2 # 5 GHz band without DFS channels 273 WIFI_BAND_5_GHZ_DFS_ONLY = 4 # 5 GHz band with DFS channels 274 WIFI_BAND_5_GHZ_WITH_DFS = 6 # 5 GHz band with DFS channels 275 WIFI_BAND_BOTH = 3 # both bands without DFS channels 276 WIFI_BAND_BOTH_WITH_DFS = 7 # both bands with DFS channels 277 278 REPORT_EVENT_AFTER_BUFFER_FULL = 0 279 REPORT_EVENT_AFTER_EACH_SCAN = 1 280 REPORT_EVENT_FULL_SCAN_RESULT = 2 281 282 SCAN_TYPE_LOW_LATENCY = 0 283 SCAN_TYPE_LOW_POWER = 1 284 SCAN_TYPE_HIGH_ACCURACY = 2 285 286 # US Wifi frequencies 287 ALL_2G_FREQUENCIES = [2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 288 2457, 2462] 289 DFS_5G_FREQUENCIES = [5260, 5280, 5300, 5320, 5500, 5520, 5540, 5560, 5580, 290 5600, 5620, 5640, 5660, 5680, 5700, 5720] 291 NONE_DFS_5G_FREQUENCIES = [5180, 5200, 5220, 5240, 5745, 5765, 5785, 5805, 292 5825] 293 ALL_5G_FREQUENCIES = DFS_5G_FREQUENCIES + NONE_DFS_5G_FREQUENCIES 294 295 band_to_frequencies = { 296 WIFI_BAND_24_GHZ: ALL_2G_FREQUENCIES, 297 WIFI_BAND_5_GHZ: NONE_DFS_5G_FREQUENCIES, 298 WIFI_BAND_5_GHZ_DFS_ONLY: DFS_5G_FREQUENCIES, 299 WIFI_BAND_5_GHZ_WITH_DFS: ALL_5G_FREQUENCIES, 300 WIFI_BAND_BOTH: ALL_2G_FREQUENCIES + NONE_DFS_5G_FREQUENCIES, 301 WIFI_BAND_BOTH_WITH_DFS: ALL_5G_FREQUENCIES + ALL_2G_FREQUENCIES 302 } 303 304 # All Wifi frequencies to channels lookup. 305 freq_to_channel = { 306 2412: 1, 307 2417: 2, 308 2422: 3, 309 2427: 4, 310 2432: 5, 311 2437: 6, 312 2442: 7, 313 2447: 8, 314 2452: 9, 315 2457: 10, 316 2462: 11, 317 2467: 12, 318 2472: 13, 319 2484: 14, 320 4915: 183, 321 4920: 184, 322 4925: 185, 323 4935: 187, 324 4940: 188, 325 4945: 189, 326 4960: 192, 327 4980: 196, 328 5035: 7, 329 5040: 8, 330 5045: 9, 331 5055: 11, 332 5060: 12, 333 5080: 16, 334 5170: 34, 335 5180: 36, 336 5190: 38, 337 5200: 40, 338 5210: 42, 339 5220: 44, 340 5230: 46, 341 5240: 48, 342 5260: 52, 343 5280: 56, 344 5300: 60, 345 5320: 64, 346 5500: 100, 347 5520: 104, 348 5540: 108, 349 5560: 112, 350 5580: 116, 351 5600: 120, 352 5620: 124, 353 5640: 128, 354 5660: 132, 355 5680: 136, 356 5700: 140, 357 5745: 149, 358 5765: 153, 359 5785: 157, 360 5805: 161, 361 5825: 165, 362 } 363 364 # All Wifi channels to frequencies lookup. 365 channel_2G_to_freq = { 366 1: 2412, 367 2: 2417, 368 3: 2422, 369 4: 2427, 370 5: 2432, 371 6: 2437, 372 7: 2442, 373 8: 2447, 374 9: 2452, 375 10: 2457, 376 11: 2462, 377 12: 2467, 378 13: 2472, 379 14: 2484 380 } 381 382 channel_5G_to_freq = { 383 183: 4915, 384 184: 4920, 385 185: 4925, 386 187: 4935, 387 188: 4940, 388 189: 4945, 389 192: 4960, 390 196: 4980, 391 7: 5035, 392 8: 5040, 393 9: 5045, 394 11: 5055, 395 12: 5060, 396 16: 5080, 397 34: 5170, 398 36: 5180, 399 38: 5190, 400 40: 5200, 401 42: 5210, 402 44: 5220, 403 46: 5230, 404 48: 5240, 405 52: 5260, 406 56: 5280, 407 60: 5300, 408 64: 5320, 409 100: 5500, 410 104: 5520, 411 108: 5540, 412 112: 5560, 413 116: 5580, 414 120: 5600, 415 124: 5620, 416 128: 5640, 417 132: 5660, 418 136: 5680, 419 140: 5700, 420 149: 5745, 421 153: 5765, 422 157: 5785, 423 161: 5805, 424 165: 5825 425 } 426 427 428class WifiChannelBase: 429 ALL_2G_FREQUENCIES = [] 430 DFS_5G_FREQUENCIES = [] 431 NONE_DFS_5G_FREQUENCIES = [] 432 ALL_5G_FREQUENCIES = DFS_5G_FREQUENCIES + NONE_DFS_5G_FREQUENCIES 433 MIX_CHANNEL_SCAN = [] 434 435 def band_to_freq(self, band): 436 _band_to_frequencies = { 437 WifiEnums.WIFI_BAND_24_GHZ: self.ALL_2G_FREQUENCIES, 438 WifiEnums.WIFI_BAND_5_GHZ: self.NONE_DFS_5G_FREQUENCIES, 439 WifiEnums.WIFI_BAND_5_GHZ_DFS_ONLY: self.DFS_5G_FREQUENCIES, 440 WifiEnums.WIFI_BAND_5_GHZ_WITH_DFS: self.ALL_5G_FREQUENCIES, 441 WifiEnums.WIFI_BAND_BOTH: 442 self.ALL_2G_FREQUENCIES + self.NONE_DFS_5G_FREQUENCIES, 443 WifiEnums.WIFI_BAND_BOTH_WITH_DFS: 444 self.ALL_5G_FREQUENCIES + self.ALL_2G_FREQUENCIES 445 } 446 return _band_to_frequencies[band] 447 448 449class WifiChannelUS(WifiChannelBase): 450 # US Wifi frequencies 451 ALL_2G_FREQUENCIES = [2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 452 2457, 2462] 453 NONE_DFS_5G_FREQUENCIES = [5180, 5200, 5220, 5240, 5745, 5765, 5785, 5805, 454 5825] 455 MIX_CHANNEL_SCAN = [2412, 2437, 2462, 5180, 5200, 5280, 5260, 5300, 5500, 456 5320, 5520, 5560, 5700, 5745, 5805] 457 458 def __init__(self, model=None): 459 self.DFS_5G_FREQUENCIES = [5260, 5280, 5300, 5320, 5500, 5520, 460 5540, 5560, 5580, 5600, 5620, 5640, 461 5660, 5680, 5700, 5720] 462 self.ALL_5G_FREQUENCIES = self.DFS_5G_FREQUENCIES + self.NONE_DFS_5G_FREQUENCIES 463 464 465class WifiReferenceNetworks: 466 """ Class to parse and return networks of different band and 467 auth type from reference_networks 468 """ 469 def __init__(self, obj): 470 self.reference_networks = obj 471 self.WIFI_2G = "2g" 472 self.WIFI_5G = "5g" 473 474 self.secure_networks_2g = [] 475 self.secure_networks_5g = [] 476 self.open_networks_2g = [] 477 self.open_networks_5g = [] 478 self._parse_networks() 479 480 def _parse_networks(self): 481 for network in self.reference_networks: 482 for key in network: 483 if key == self.WIFI_2G: 484 if "password" in network[key]: 485 self.secure_networks_2g.append(network[key]) 486 else: 487 self.open_networks_2g.append(network[key]) 488 else: 489 if "password" in network[key]: 490 self.secure_networks_5g.append(network[key]) 491 else: 492 self.open_networks_5g.append(network[key]) 493 494 def return_2g_secure_networks(self): 495 return self.secure_networks_2g 496 497 def return_5g_secure_networks(self): 498 return self.secure_networks_5g 499 500 def return_2g_open_networks(self): 501 return self.open_networks_2g 502 503 def return_5g_open_networks(self): 504 return self.open_networks_5g 505 506 def return_secure_networks(self): 507 return self.secure_networks_2g + self.secure_networks_5g 508 509 def return_open_networks(self): 510 return self.open_networks_2g + self.open_networks_5g 511 512 513def _assert_on_fail_handler(func, assert_on_fail, *args, **kwargs): 514 """Wrapper function that handles the bahevior of assert_on_fail. 515 516 When assert_on_fail is True, let all test signals through, which can 517 terminate test cases directly. When assert_on_fail is False, the wrapper 518 raises no test signals and reports operation status by returning True or 519 False. 520 521 Args: 522 func: The function to wrap. This function reports operation status by 523 raising test signals. 524 assert_on_fail: A boolean that specifies if the output of the wrapper 525 is test signal based or return value based. 526 args: Positional args for func. 527 kwargs: Name args for func. 528 529 Returns: 530 If assert_on_fail is True, returns True/False to signal operation 531 status, otherwise return nothing. 532 """ 533 try: 534 func(*args, **kwargs) 535 if not assert_on_fail: 536 return True 537 except signals.TestSignal: 538 if assert_on_fail: 539 raise 540 return False 541 542 543def assert_network_in_list(target, network_list): 544 """Makes sure a specified target Wi-Fi network exists in a list of Wi-Fi 545 networks. 546 547 Args: 548 target: A dict representing a Wi-Fi network. 549 E.g. {WifiEnums.SSID_KEY: "SomeNetwork"} 550 network_list: A list of dicts, each representing a Wi-Fi network. 551 """ 552 match_results = match_networks(target, network_list) 553 asserts.assert_true( 554 match_results, "Target network %s, does not exist in network list %s" % 555 (target, network_list)) 556 557 558def match_networks(target_params, networks): 559 """Finds the WiFi networks that match a given set of parameters in a list 560 of WiFi networks. 561 562 To be considered a match, the network should contain every key-value pair 563 of target_params 564 565 Args: 566 target_params: A dict with 1 or more key-value pairs representing a Wi-Fi network. 567 E.g { 'SSID': 'wh_ap1_5g', 'BSSID': '30:b5:c2:33:e4:47' } 568 networks: A list of dict objects representing WiFi networks. 569 570 Returns: 571 The networks that match the target parameters. 572 """ 573 results = [] 574 asserts.assert_true(target_params, 575 "Expected networks object 'target_params' is empty") 576 for n in networks: 577 add_network = 1 578 for k, v in target_params.items(): 579 if k not in n: 580 add_network = 0 581 break 582 if n[k] != v: 583 add_network = 0 584 break 585 if add_network: 586 results.append(n) 587 return results 588 589 590def wait_for_wifi_state(ad, state, assert_on_fail=True): 591 """Waits for the device to transition to the specified wifi state 592 593 Args: 594 ad: An AndroidDevice object. 595 state: Wifi state to wait for. 596 assert_on_fail: If True, error checks in this function will raise test 597 failure signals. 598 599 Returns: 600 If assert_on_fail is False, function returns True if the device transitions 601 to the specified state, False otherwise. If assert_on_fail is True, no return value. 602 """ 603 return _assert_on_fail_handler( 604 _wait_for_wifi_state, assert_on_fail, ad, state=state) 605 606 607def _wait_for_wifi_state(ad, state): 608 """Toggles the state of wifi. 609 610 TestFailure signals are raised when something goes wrong. 611 612 Args: 613 ad: An AndroidDevice object. 614 state: Wifi state to wait for. 615 """ 616 if state == ad.droid.wifiCheckState(): 617 # Check if the state is already achieved, so we don't wait for the 618 # state change event by mistake. 619 return 620 ad.droid.wifiStartTrackingStateChange() 621 fail_msg = "Device did not transition to Wi-Fi state to %s on %s." % (state, 622 ad.serial) 623 try: 624 ad.ed.wait_for_event(wifi_constants.WIFI_STATE_CHANGED, 625 lambda x: x["data"]["enabled"] == state, 626 SHORT_TIMEOUT) 627 except Empty: 628 asserts.assert_equal(state, ad.droid.wifiCheckState(), fail_msg) 629 finally: 630 ad.droid.wifiStopTrackingStateChange() 631 632 633def wifi_toggle_state(ad, new_state=None, assert_on_fail=True): 634 """Toggles the state of wifi. 635 636 Args: 637 ad: An AndroidDevice object. 638 new_state: Wifi state to set to. If None, opposite of the current state. 639 assert_on_fail: If True, error checks in this function will raise test 640 failure signals. 641 642 Returns: 643 If assert_on_fail is False, function returns True if the toggle was 644 successful, False otherwise. If assert_on_fail is True, no return value. 645 """ 646 return _assert_on_fail_handler( 647 _wifi_toggle_state, assert_on_fail, ad, new_state=new_state) 648 649 650def _wifi_toggle_state(ad, new_state=None): 651 """Toggles the state of wifi. 652 653 TestFailure signals are raised when something goes wrong. 654 655 Args: 656 ad: An AndroidDevice object. 657 new_state: The state to set Wi-Fi to. If None, opposite of the current 658 state will be set. 659 """ 660 if new_state is None: 661 new_state = not ad.droid.wifiCheckState() 662 elif new_state == ad.droid.wifiCheckState(): 663 # Check if the new_state is already achieved, so we don't wait for the 664 # state change event by mistake. 665 return 666 ad.droid.wifiStartTrackingStateChange() 667 ad.log.info("Setting Wi-Fi state to %s.", new_state) 668 ad.ed.clear_all_events() 669 # Setting wifi state. 670 ad.droid.wifiToggleState(new_state) 671 time.sleep(2) 672 fail_msg = "Failed to set Wi-Fi state to %s on %s." % (new_state, 673 ad.serial) 674 try: 675 ad.ed.wait_for_event(wifi_constants.WIFI_STATE_CHANGED, 676 lambda x: x["data"]["enabled"] == new_state, 677 SHORT_TIMEOUT) 678 except Empty: 679 asserts.assert_equal(new_state, ad.droid.wifiCheckState(), fail_msg) 680 finally: 681 ad.droid.wifiStopTrackingStateChange() 682 683 684def reset_wifi(ad): 685 """Clears all saved Wi-Fi networks on a device. 686 687 This will turn Wi-Fi on. 688 689 Args: 690 ad: An AndroidDevice object. 691 692 """ 693 networks = ad.droid.wifiGetConfiguredNetworks() 694 if not networks: 695 return 696 for n in networks: 697 ad.droid.wifiForgetNetwork(n['networkId']) 698 try: 699 event = ad.ed.pop_event(wifi_constants.WIFI_FORGET_NW_SUCCESS, 700 SHORT_TIMEOUT) 701 except Empty: 702 logging.warning("Could not confirm the removal of network %s.", n) 703 # Check again to see if there's any network left. 704 asserts.assert_true( 705 not ad.droid.wifiGetConfiguredNetworks(), 706 "Failed to remove these configured Wi-Fi networks: %s" % networks) 707 708 709def toggle_airplane_mode_on_and_off(ad): 710 """Turn ON and OFF Airplane mode. 711 712 ad: An AndroidDevice object. 713 Returns: Assert if turning on/off Airplane mode fails. 714 715 """ 716 ad.log.debug("Toggling Airplane mode ON.") 717 asserts.assert_true( 718 utils.force_airplane_mode(ad, True), 719 "Can not turn on airplane mode on: %s" % ad.serial) 720 time.sleep(DEFAULT_TIMEOUT) 721 ad.log.debug("Toggling Airplane mode OFF.") 722 asserts.assert_true( 723 utils.force_airplane_mode(ad, False), 724 "Can not turn on airplane mode on: %s" % ad.serial) 725 time.sleep(DEFAULT_TIMEOUT) 726 727 728def toggle_wifi_off_and_on(ad): 729 """Turn OFF and ON WiFi. 730 731 ad: An AndroidDevice object. 732 Returns: Assert if turning off/on WiFi fails. 733 734 """ 735 ad.log.debug("Toggling wifi OFF.") 736 wifi_toggle_state(ad, False) 737 time.sleep(DEFAULT_TIMEOUT) 738 ad.log.debug("Toggling wifi ON.") 739 wifi_toggle_state(ad, True) 740 time.sleep(DEFAULT_TIMEOUT) 741 742 743def wifi_forget_network(ad, net_ssid): 744 """Remove configured Wifi network on an android device. 745 746 Args: 747 ad: android_device object for forget network. 748 net_ssid: ssid of network to be forget 749 750 """ 751 networks = ad.droid.wifiGetConfiguredNetworks() 752 if not networks: 753 return 754 for n in networks: 755 if net_ssid in n[WifiEnums.SSID_KEY]: 756 ad.droid.wifiForgetNetwork(n['networkId']) 757 try: 758 event = ad.ed.pop_event(wifi_constants.WIFI_FORGET_NW_SUCCESS, 759 SHORT_TIMEOUT) 760 except Empty: 761 asserts.fail("Failed to remove network %s." % n) 762 763 764def wifi_test_device_init(ad): 765 """Initializes an android device for wifi testing. 766 767 0. Make sure SL4A connection is established on the android device. 768 1. Disable location service's WiFi scan. 769 2. Turn WiFi on. 770 3. Clear all saved networks. 771 4. Set country code to US. 772 5. Enable WiFi verbose logging. 773 6. Sync device time with computer time. 774 7. Turn off cellular data. 775 8. Turn off ambient display. 776 """ 777 utils.require_sl4a((ad, )) 778 ad.droid.wifiScannerToggleAlwaysAvailable(False) 779 msg = "Failed to turn off location service's scan." 780 asserts.assert_true(not ad.droid.wifiScannerIsAlwaysAvailable(), msg) 781 wifi_toggle_state(ad, True) 782 reset_wifi(ad) 783 ad.droid.wifiEnableVerboseLogging(1) 784 msg = "Failed to enable WiFi verbose logging." 785 asserts.assert_equal(ad.droid.wifiGetVerboseLoggingLevel(), 1, msg) 786 # We don't verify the following settings since they are not critical. 787 # Set wpa_supplicant log level to EXCESSIVE. 788 output = ad.adb.shell("wpa_cli -i wlan0 -p -g@android:wpa_wlan0 IFNAME=" 789 "wlan0 log_level EXCESSIVE") 790 ad.log.info("wpa_supplicant log change status: %s", output) 791 utils.sync_device_time(ad) 792 ad.droid.telephonyToggleDataConnection(False) 793 set_wifi_country_code(ad, WifiEnums.CountryCode.US) 794 utils.set_ambient_display(ad, False) 795 796def set_wifi_country_code(ad, country_code): 797 """Sets the wifi country code on the device. 798 799 Args: 800 ad: An AndroidDevice object. 801 country_code: 2 letter ISO country code 802 803 Raises: 804 An RpcException if unable to set the country code. 805 """ 806 try: 807 ad.adb.shell("cmd wifi force-country-code enabled %s" % country_code) 808 except ad.adb.AdbError as e: 809 ad.droid.wifiSetCountryCode(WifiEnums.CountryCode.US) 810 811 812def start_wifi_connection_scan(ad): 813 """Starts a wifi connection scan and wait for results to become available. 814 815 Args: 816 ad: An AndroidDevice object. 817 """ 818 ad.ed.clear_all_events() 819 ad.droid.wifiStartScan() 820 try: 821 ad.ed.pop_event("WifiManagerScanResultsAvailable", 60) 822 except Empty: 823 asserts.fail("Wi-Fi results did not become available within 60s.") 824 825 826def start_wifi_connection_scan_and_return_status(ad): 827 """ 828 Starts a wifi connection scan and wait for results to become available 829 or a scan failure to be reported. 830 831 Args: 832 ad: An AndroidDevice object. 833 Returns: 834 True: if scan succeeded & results are available 835 False: if scan failed 836 """ 837 ad.ed.clear_all_events() 838 ad.droid.wifiStartScan() 839 try: 840 events = ad.ed.pop_events( 841 "WifiManagerScan(ResultsAvailable|Failure)", 60) 842 except Empty: 843 asserts.fail( 844 "Wi-Fi scan results/failure did not become available within 60s.") 845 # If there are multiple matches, we check for atleast one success. 846 for event in events: 847 if event["name"] == "WifiManagerScanResultsAvailable": 848 return True 849 elif event["name"] == "WifiManagerScanFailure": 850 ad.log.debug("Scan failure received") 851 return False 852 853 854def start_wifi_connection_scan_and_check_for_network(ad, network_ssid, 855 max_tries=3): 856 """ 857 Start connectivity scans & checks if the |network_ssid| is seen in 858 scan results. The method performs a max of |max_tries| connectivity scans 859 to find the network. 860 861 Args: 862 ad: An AndroidDevice object. 863 network_ssid: SSID of the network we are looking for. 864 max_tries: Number of scans to try. 865 Returns: 866 True: if network_ssid is found in scan results. 867 False: if network_ssid is not found in scan results. 868 """ 869 for num_tries in range(max_tries): 870 if start_wifi_connection_scan_and_return_status(ad): 871 scan_results = ad.droid.wifiGetScanResults() 872 match_results = match_networks( 873 {WifiEnums.SSID_KEY: network_ssid}, scan_results) 874 if len(match_results) > 0: 875 return True 876 return False 877 878 879def start_wifi_connection_scan_and_ensure_network_found(ad, network_ssid, 880 max_tries=3): 881 """ 882 Start connectivity scans & ensure the |network_ssid| is seen in 883 scan results. The method performs a max of |max_tries| connectivity scans 884 to find the network. 885 This method asserts on failure! 886 887 Args: 888 ad: An AndroidDevice object. 889 network_ssid: SSID of the network we are looking for. 890 max_tries: Number of scans to try. 891 """ 892 ad.log.info("Starting scans to ensure %s is present", network_ssid) 893 assert_msg = "Failed to find " + network_ssid + " in scan results" \ 894 " after " + str(max_tries) + " tries" 895 asserts.assert_true(start_wifi_connection_scan_and_check_for_network( 896 ad, network_ssid, max_tries), assert_msg) 897 898 899def start_wifi_connection_scan_and_ensure_network_not_found(ad, network_ssid, 900 max_tries=3): 901 """ 902 Start connectivity scans & ensure the |network_ssid| is not seen in 903 scan results. The method performs a max of |max_tries| connectivity scans 904 to find the network. 905 This method asserts on failure! 906 907 Args: 908 ad: An AndroidDevice object. 909 network_ssid: SSID of the network we are looking for. 910 max_tries: Number of scans to try. 911 """ 912 ad.log.info("Starting scans to ensure %s is not present", network_ssid) 913 assert_msg = "Found " + network_ssid + " in scan results" \ 914 " after " + str(max_tries) + " tries" 915 asserts.assert_false(start_wifi_connection_scan_and_check_for_network( 916 ad, network_ssid, max_tries), assert_msg) 917 918 919def start_wifi_background_scan(ad, scan_setting): 920 """Starts wifi background scan. 921 922 Args: 923 ad: android_device object to initiate connection on. 924 scan_setting: A dict representing the settings of the scan. 925 926 Returns: 927 If scan was started successfully, event data of success event is returned. 928 """ 929 idx = ad.droid.wifiScannerStartBackgroundScan(scan_setting) 930 event = ad.ed.pop_event("WifiScannerScan{}onSuccess".format(idx), 931 SHORT_TIMEOUT) 932 return event['data'] 933 934 935def start_wifi_tethering(ad, ssid, password, band=None, hidden=None): 936 """Starts wifi tethering on an android_device. 937 938 Args: 939 ad: android_device to start wifi tethering on. 940 ssid: The SSID the soft AP should broadcast. 941 password: The password the soft AP should use. 942 band: The band the soft AP should be set on. It should be either 943 WifiEnums.WIFI_CONFIG_APBAND_2G or WifiEnums.WIFI_CONFIG_APBAND_5G. 944 hidden: boolean to indicate if the AP needs to be hidden or not. 945 946 Returns: 947 No return value. Error checks in this function will raise test failure signals 948 """ 949 config = {WifiEnums.SSID_KEY: ssid} 950 if password: 951 config[WifiEnums.PWD_KEY] = password 952 if band: 953 config[WifiEnums.AP_BAND_KEY] = band 954 if hidden: 955 config[WifiEnums.HIDDEN_KEY] = hidden 956 asserts.assert_true( 957 ad.droid.wifiSetWifiApConfiguration(config), 958 "Failed to update WifiAp Configuration") 959 ad.droid.wifiStartTrackingTetherStateChange() 960 ad.droid.connectivityStartTethering(tel_defines.TETHERING_WIFI, False) 961 try: 962 ad.ed.pop_event("ConnectivityManagerOnTetheringStarted") 963 ad.ed.wait_for_event("TetherStateChanged", 964 lambda x: x["data"]["ACTIVE_TETHER"], 30) 965 ad.log.debug("Tethering started successfully.") 966 except Empty: 967 msg = "Failed to receive confirmation of wifi tethering starting" 968 asserts.fail(msg) 969 finally: 970 ad.droid.wifiStopTrackingTetherStateChange() 971 972 973def save_wifi_soft_ap_config(ad, wifi_config, band=None, hidden=None, 974 security=None, password=None, 975 channel=None, max_clients=None, 976 shutdown_timeout_enable=None, 977 shutdown_timeout_millis=None, 978 client_control_enable=None, 979 allowedList=None, blockedList=None): 980 """ Save a soft ap configuration and verified 981 Args: 982 ad: android_device to set soft ap configuration. 983 wifi_config: a soft ap configuration object, at least include SSID. 984 band: specifies the band for the soft ap. 985 hidden: specifies the soft ap need to broadcast its SSID or not. 986 security: specifies the security type for the soft ap. 987 password: specifies the password for the soft ap. 988 channel: specifies the channel for the soft ap. 989 max_clients: specifies the maximum connected client number. 990 shutdown_timeout_enable: specifies the auto shut down enable or not. 991 shutdown_timeout_millis: specifies the shut down timeout value. 992 client_control_enable: specifies the client control enable or not. 993 allowedList: specifies allowed clients list. 994 blockedList: specifies blocked clients list. 995 """ 996 if security and password: 997 wifi_config[WifiEnums.SECURITY] = security 998 wifi_config[WifiEnums.PWD_KEY] = password 999 if band: 1000 wifi_config[WifiEnums.AP_BAND_KEY] = band 1001 if hidden: 1002 wifi_config[WifiEnums.HIDDEN_KEY] = hidden 1003 if channel and band: 1004 wifi_config[WifiEnums.AP_BAND_KEY] = band 1005 wifi_config[WifiEnums.AP_CHANNEL_KEY] = channel 1006 if max_clients: 1007 wifi_config[WifiEnums.AP_MAXCLIENTS_KEY] = max_clients 1008 if shutdown_timeout_enable: 1009 wifi_config[ 1010 WifiEnums.AP_SHUTDOWNTIMEOUTENABLE_KEY] = shutdown_timeout_enable 1011 if shutdown_timeout_millis: 1012 wifi_config[ 1013 WifiEnums.AP_SHUTDOWNTIMEOUT_KEY] = shutdown_timeout_millis 1014 if client_control_enable: 1015 wifi_config[WifiEnums.AP_CLIENTCONTROL_KEY] = client_control_enable 1016 if allowedList: 1017 wifi_config[WifiEnums.AP_ALLOWEDLIST_KEY] = allowedList 1018 if blockedList: 1019 wifi_config[WifiEnums.AP_BLOCKEDLIST_KEY] = blockedList 1020 1021 if WifiEnums.AP_CHANNEL_KEY in wifi_config and wifi_config[ 1022 WifiEnums.AP_CHANNEL_KEY] == 0: 1023 del wifi_config[WifiEnums.AP_CHANNEL_KEY] 1024 1025 if WifiEnums.SECURITY in wifi_config and wifi_config[ 1026 WifiEnums.SECURITY] == WifiEnums.SoftApSecurityType.OPEN: 1027 del wifi_config[WifiEnums.SECURITY] 1028 del wifi_config[WifiEnums.PWD_KEY] 1029 1030 asserts.assert_true(ad.droid.wifiSetWifiApConfiguration(wifi_config), 1031 "Failed to set WifiAp Configuration") 1032 1033 wifi_ap = ad.droid.wifiGetApConfiguration() 1034 asserts.assert_true( 1035 wifi_ap[WifiEnums.SSID_KEY] == wifi_config[WifiEnums.SSID_KEY], 1036 "Hotspot SSID doesn't match") 1037 if WifiEnums.SECURITY in wifi_config: 1038 asserts.assert_true( 1039 wifi_ap[WifiEnums.SECURITY] == wifi_config[WifiEnums.SECURITY], 1040 "Hotspot Security doesn't match") 1041 if WifiEnums.PWD_KEY in wifi_config: 1042 asserts.assert_true( 1043 wifi_ap[WifiEnums.PWD_KEY] == wifi_config[WifiEnums.PWD_KEY], 1044 "Hotspot Password doesn't match") 1045 1046 if WifiEnums.HIDDEN_KEY in wifi_config: 1047 asserts.assert_true( 1048 wifi_ap[WifiEnums.HIDDEN_KEY] == wifi_config[WifiEnums.HIDDEN_KEY], 1049 "Hotspot hidden setting doesn't match") 1050 1051 if WifiEnums.AP_BAND_KEY in wifi_config: 1052 asserts.assert_true( 1053 wifi_ap[WifiEnums.AP_BAND_KEY] == wifi_config[WifiEnums.AP_BAND_KEY], 1054 "Hotspot Band doesn't match") 1055 if WifiEnums.AP_CHANNEL_KEY in wifi_config: 1056 asserts.assert_true( 1057 wifi_ap[WifiEnums.AP_CHANNEL_KEY] == wifi_config[ 1058 WifiEnums.AP_CHANNEL_KEY], "Hotspot Channel doesn't match") 1059 if WifiEnums.AP_MAXCLIENTS_KEY in wifi_config: 1060 asserts.assert_true( 1061 wifi_ap[WifiEnums.AP_MAXCLIENTS_KEY] == wifi_config[ 1062 WifiEnums.AP_MAXCLIENTS_KEY], "Hotspot Max Clients doesn't match") 1063 if WifiEnums.AP_SHUTDOWNTIMEOUTENABLE_KEY in wifi_config: 1064 asserts.assert_true( 1065 wifi_ap[WifiEnums.AP_SHUTDOWNTIMEOUTENABLE_KEY] == wifi_config[ 1066 WifiEnums.AP_SHUTDOWNTIMEOUTENABLE_KEY], 1067 "Hotspot ShutDown feature flag doesn't match") 1068 if WifiEnums.AP_SHUTDOWNTIMEOUT_KEY in wifi_config: 1069 asserts.assert_true( 1070 wifi_ap[WifiEnums.AP_SHUTDOWNTIMEOUT_KEY] == wifi_config[ 1071 WifiEnums.AP_SHUTDOWNTIMEOUT_KEY], 1072 "Hotspot ShutDown timeout setting doesn't match") 1073 if WifiEnums.AP_CLIENTCONTROL_KEY in wifi_config: 1074 asserts.assert_true( 1075 wifi_ap[WifiEnums.AP_CLIENTCONTROL_KEY] == wifi_config[ 1076 WifiEnums.AP_CLIENTCONTROL_KEY], 1077 "Hotspot Client control flag doesn't match") 1078 if WifiEnums.AP_ALLOWEDLIST_KEY in wifi_config: 1079 asserts.assert_true( 1080 wifi_ap[WifiEnums.AP_ALLOWEDLIST_KEY] == wifi_config[ 1081 WifiEnums.AP_ALLOWEDLIST_KEY], 1082 "Hotspot Allowed List doesn't match") 1083 if WifiEnums.AP_BLOCKEDLIST_KEY in wifi_config: 1084 asserts.assert_true( 1085 wifi_ap[WifiEnums.AP_BLOCKEDLIST_KEY] == wifi_config[ 1086 WifiEnums.AP_BLOCKEDLIST_KEY], 1087 "Hotspot Blocked List doesn't match") 1088 1089def start_wifi_tethering_saved_config(ad): 1090 """ Turn on wifi hotspot with a config that is already saved """ 1091 ad.droid.wifiStartTrackingTetherStateChange() 1092 ad.droid.connectivityStartTethering(tel_defines.TETHERING_WIFI, False) 1093 try: 1094 ad.ed.pop_event("ConnectivityManagerOnTetheringStarted") 1095 ad.ed.wait_for_event("TetherStateChanged", 1096 lambda x: x["data"]["ACTIVE_TETHER"], 30) 1097 except: 1098 asserts.fail("Didn't receive wifi tethering starting confirmation") 1099 finally: 1100 ad.droid.wifiStopTrackingTetherStateChange() 1101 1102 1103def stop_wifi_tethering(ad): 1104 """Stops wifi tethering on an android_device. 1105 Args: 1106 ad: android_device to stop wifi tethering on. 1107 """ 1108 ad.droid.wifiStartTrackingTetherStateChange() 1109 ad.droid.connectivityStopTethering(tel_defines.TETHERING_WIFI) 1110 try: 1111 ad.ed.pop_event("WifiManagerApDisabled", 30) 1112 ad.ed.wait_for_event("TetherStateChanged", 1113 lambda x: not x["data"]["ACTIVE_TETHER"], 30) 1114 except Empty: 1115 msg = "Failed to receive confirmation of wifi tethering stopping" 1116 asserts.fail(msg) 1117 finally: 1118 ad.droid.wifiStopTrackingTetherStateChange() 1119 1120 1121def toggle_wifi_and_wait_for_reconnection(ad, 1122 network, 1123 num_of_tries=1, 1124 assert_on_fail=True): 1125 """Toggle wifi state and then wait for Android device to reconnect to 1126 the provided wifi network. 1127 1128 This expects the device to be already connected to the provided network. 1129 1130 Logic steps are 1131 1. Ensure that we're connected to the network. 1132 2. Turn wifi off. 1133 3. Wait for 10 seconds. 1134 4. Turn wifi on. 1135 5. Wait for the "connected" event, then confirm the connected ssid is the 1136 one requested. 1137 1138 Args: 1139 ad: android_device object to initiate connection on. 1140 network: A dictionary representing the network to await connection. The 1141 dictionary must have the key "SSID". 1142 num_of_tries: An integer that is the number of times to try before 1143 delaring failure. Default is 1. 1144 assert_on_fail: If True, error checks in this function will raise test 1145 failure signals. 1146 1147 Returns: 1148 If assert_on_fail is False, function returns True if the toggle was 1149 successful, False otherwise. If assert_on_fail is True, no return value. 1150 """ 1151 return _assert_on_fail_handler( 1152 _toggle_wifi_and_wait_for_reconnection, 1153 assert_on_fail, 1154 ad, 1155 network, 1156 num_of_tries=num_of_tries) 1157 1158 1159def _toggle_wifi_and_wait_for_reconnection(ad, network, num_of_tries=3): 1160 """Toggle wifi state and then wait for Android device to reconnect to 1161 the provided wifi network. 1162 1163 This expects the device to be already connected to the provided network. 1164 1165 Logic steps are 1166 1. Ensure that we're connected to the network. 1167 2. Turn wifi off. 1168 3. Wait for 10 seconds. 1169 4. Turn wifi on. 1170 5. Wait for the "connected" event, then confirm the connected ssid is the 1171 one requested. 1172 1173 This will directly fail a test if anything goes wrong. 1174 1175 Args: 1176 ad: android_device object to initiate connection on. 1177 network: A dictionary representing the network to await connection. The 1178 dictionary must have the key "SSID". 1179 num_of_tries: An integer that is the number of times to try before 1180 delaring failure. Default is 1. 1181 """ 1182 expected_ssid = network[WifiEnums.SSID_KEY] 1183 # First ensure that we're already connected to the provided network. 1184 verify_con = {WifiEnums.SSID_KEY: expected_ssid} 1185 verify_wifi_connection_info(ad, verify_con) 1186 # Now toggle wifi state and wait for the connection event. 1187 wifi_toggle_state(ad, False) 1188 time.sleep(10) 1189 wifi_toggle_state(ad, True) 1190 ad.droid.wifiStartTrackingStateChange() 1191 try: 1192 connect_result = None 1193 for i in range(num_of_tries): 1194 try: 1195 connect_result = ad.ed.pop_event(wifi_constants.WIFI_CONNECTED, 1196 30) 1197 break 1198 except Empty: 1199 pass 1200 asserts.assert_true(connect_result, 1201 "Failed to connect to Wi-Fi network %s on %s" % 1202 (network, ad.serial)) 1203 logging.debug("Connection result on %s: %s.", ad.serial, 1204 connect_result) 1205 actual_ssid = connect_result['data'][WifiEnums.SSID_KEY] 1206 asserts.assert_equal(actual_ssid, expected_ssid, 1207 "Connected to the wrong network on %s." 1208 "Expected %s, but got %s." % 1209 (ad.serial, expected_ssid, actual_ssid)) 1210 logging.info("Connected to Wi-Fi network %s on %s", actual_ssid, 1211 ad.serial) 1212 finally: 1213 ad.droid.wifiStopTrackingStateChange() 1214 1215 1216def wait_for_connect(ad, expected_ssid=None, expected_id=None, tries=2, 1217 assert_on_fail=True): 1218 """Wait for a connect event. 1219 1220 This will directly fail a test if anything goes wrong. 1221 1222 Args: 1223 ad: An Android device object. 1224 expected_ssid: SSID of the network to connect to. 1225 expected_id: Network Id of the network to connect to. 1226 tries: An integer that is the number of times to try before failing. 1227 assert_on_fail: If True, error checks in this function will raise test 1228 failure signals. 1229 1230 Returns: 1231 Returns a value only if assert_on_fail is false. 1232 Returns True if the connection was successful, False otherwise. 1233 """ 1234 return _assert_on_fail_handler( 1235 _wait_for_connect, assert_on_fail, ad, expected_ssid, expected_id, 1236 tries) 1237 1238 1239def _wait_for_connect(ad, expected_ssid=None, expected_id=None, tries=2): 1240 """Wait for a connect event. 1241 1242 Args: 1243 ad: An Android device object. 1244 expected_ssid: SSID of the network to connect to. 1245 expected_id: Network Id of the network to connect to. 1246 tries: An integer that is the number of times to try before failing. 1247 """ 1248 ad.droid.wifiStartTrackingStateChange() 1249 try: 1250 connect_result = _wait_for_connect_event( 1251 ad, ssid=expected_ssid, id=expected_id, tries=tries) 1252 asserts.assert_true(connect_result, 1253 "Failed to connect to Wi-Fi network %s" % 1254 expected_ssid) 1255 ad.log.debug("Wi-Fi connection result: %s.", connect_result) 1256 actual_ssid = connect_result['data'][WifiEnums.SSID_KEY] 1257 if expected_ssid: 1258 asserts.assert_equal(actual_ssid, expected_ssid, 1259 "Connected to the wrong network") 1260 actual_id = connect_result['data'][WifiEnums.NETID_KEY] 1261 if expected_id: 1262 asserts.assert_equal(actual_id, expected_id, 1263 "Connected to the wrong network") 1264 ad.log.info("Connected to Wi-Fi network %s.", actual_ssid) 1265 except Empty: 1266 asserts.fail("Failed to start connection process to %s" % 1267 expected_ssid) 1268 except Exception as error: 1269 ad.log.error("Failed to connect to %s with error %s", expected_ssid, 1270 error) 1271 raise signals.TestFailure("Failed to connect to %s network" % 1272 expected_ssid) 1273 finally: 1274 ad.droid.wifiStopTrackingStateChange() 1275 1276 1277def _wait_for_connect_event(ad, ssid=None, id=None, tries=1): 1278 """Wait for a connect event on queue and pop when available. 1279 1280 Args: 1281 ad: An Android device object. 1282 ssid: SSID of the network to connect to. 1283 id: Network Id of the network to connect to. 1284 tries: An integer that is the number of times to try before failing. 1285 1286 Returns: 1287 A dict with details of the connection data, which looks like this: 1288 { 1289 'time': 1485460337798, 1290 'name': 'WifiNetworkConnected', 1291 'data': { 1292 'rssi': -27, 1293 'is_24ghz': True, 1294 'mac_address': '02:00:00:00:00:00', 1295 'network_id': 1, 1296 'BSSID': '30:b5:c2:33:d3:fc', 1297 'ip_address': 117483712, 1298 'link_speed': 54, 1299 'supplicant_state': 'completed', 1300 'hidden_ssid': False, 1301 'SSID': 'wh_ap1_2g', 1302 'is_5ghz': False} 1303 } 1304 1305 """ 1306 conn_result = None 1307 1308 # If ssid and network id is None, just wait for any connect event. 1309 if id is None and ssid is None: 1310 for i in range(tries): 1311 try: 1312 conn_result = ad.ed.pop_event(wifi_constants.WIFI_CONNECTED, 30) 1313 break 1314 except Empty: 1315 pass 1316 else: 1317 # If ssid or network id is specified, wait for specific connect event. 1318 for i in range(tries): 1319 try: 1320 conn_result = ad.ed.pop_event(wifi_constants.WIFI_CONNECTED, 30) 1321 if id and conn_result['data'][WifiEnums.NETID_KEY] == id: 1322 break 1323 elif ssid and conn_result['data'][WifiEnums.SSID_KEY] == ssid: 1324 break 1325 except Empty: 1326 pass 1327 1328 return conn_result 1329 1330 1331def wait_for_disconnect(ad, timeout=10): 1332 """Wait for a disconnect event within the specified timeout. 1333 1334 Args: 1335 ad: Android device object. 1336 timeout: Timeout in seconds. 1337 1338 """ 1339 try: 1340 ad.droid.wifiStartTrackingStateChange() 1341 event = ad.ed.pop_event("WifiNetworkDisconnected", timeout) 1342 except Empty: 1343 raise signals.TestFailure("Device did not disconnect from the network") 1344 finally: 1345 ad.droid.wifiStopTrackingStateChange() 1346 1347 1348def ensure_no_disconnect(ad, duration=10): 1349 """Ensure that there is no disconnect for the specified duration. 1350 1351 Args: 1352 ad: Android device object. 1353 duration: Duration in seconds. 1354 1355 """ 1356 try: 1357 ad.droid.wifiStartTrackingStateChange() 1358 event = ad.ed.pop_event("WifiNetworkDisconnected", duration) 1359 raise signals.TestFailure("Device disconnected from the network") 1360 except Empty: 1361 pass 1362 finally: 1363 ad.droid.wifiStopTrackingStateChange() 1364 1365 1366def connect_to_wifi_network(ad, network, assert_on_fail=True, 1367 check_connectivity=True, hidden=False): 1368 """Connection logic for open and psk wifi networks. 1369 1370 Args: 1371 ad: AndroidDevice to use for connection 1372 network: network info of the network to connect to 1373 assert_on_fail: If true, errors from wifi_connect will raise 1374 test failure signals. 1375 hidden: Is the Wifi network hidden. 1376 """ 1377 if hidden: 1378 start_wifi_connection_scan_and_ensure_network_not_found( 1379 ad, network[WifiEnums.SSID_KEY]) 1380 else: 1381 start_wifi_connection_scan_and_ensure_network_found( 1382 ad, network[WifiEnums.SSID_KEY]) 1383 wifi_connect(ad, 1384 network, 1385 num_of_tries=3, 1386 assert_on_fail=assert_on_fail, 1387 check_connectivity=check_connectivity) 1388 1389 1390def connect_to_wifi_network_with_id(ad, network_id, network_ssid): 1391 """Connect to the given network using network id and verify SSID. 1392 1393 Args: 1394 network_id: int Network Id of the network. 1395 network_ssid: string SSID of the network. 1396 1397 Returns: True if connect using network id was successful; 1398 False otherwise. 1399 1400 """ 1401 start_wifi_connection_scan_and_ensure_network_found(ad, network_ssid) 1402 wifi_connect_by_id(ad, network_id) 1403 connect_data = ad.droid.wifiGetConnectionInfo() 1404 connect_ssid = connect_data[WifiEnums.SSID_KEY] 1405 ad.log.debug("Expected SSID = %s Connected SSID = %s" % 1406 (network_ssid, connect_ssid)) 1407 if connect_ssid != network_ssid: 1408 return False 1409 return True 1410 1411 1412def wifi_connect(ad, network, num_of_tries=1, assert_on_fail=True, 1413 check_connectivity=True): 1414 """Connect an Android device to a wifi network. 1415 1416 Initiate connection to a wifi network, wait for the "connected" event, then 1417 confirm the connected ssid is the one requested. 1418 1419 This will directly fail a test if anything goes wrong. 1420 1421 Args: 1422 ad: android_device object to initiate connection on. 1423 network: A dictionary representing the network to connect to. The 1424 dictionary must have the key "SSID". 1425 num_of_tries: An integer that is the number of times to try before 1426 delaring failure. Default is 1. 1427 assert_on_fail: If True, error checks in this function will raise test 1428 failure signals. 1429 1430 Returns: 1431 Returns a value only if assert_on_fail is false. 1432 Returns True if the connection was successful, False otherwise. 1433 """ 1434 return _assert_on_fail_handler( 1435 _wifi_connect, assert_on_fail, ad, network, num_of_tries=num_of_tries, 1436 check_connectivity=check_connectivity) 1437 1438 1439def _wifi_connect(ad, network, num_of_tries=1, check_connectivity=True): 1440 """Connect an Android device to a wifi network. 1441 1442 Initiate connection to a wifi network, wait for the "connected" event, then 1443 confirm the connected ssid is the one requested. 1444 1445 This will directly fail a test if anything goes wrong. 1446 1447 Args: 1448 ad: android_device object to initiate connection on. 1449 network: A dictionary representing the network to connect to. The 1450 dictionary must have the key "SSID". 1451 num_of_tries: An integer that is the number of times to try before 1452 delaring failure. Default is 1. 1453 """ 1454 asserts.assert_true(WifiEnums.SSID_KEY in network, 1455 "Key '%s' must be present in network definition." % 1456 WifiEnums.SSID_KEY) 1457 ad.droid.wifiStartTrackingStateChange() 1458 expected_ssid = network[WifiEnums.SSID_KEY] 1459 ad.droid.wifiConnectByConfig(network) 1460 ad.log.info("Starting connection process to %s", expected_ssid) 1461 try: 1462 event = ad.ed.pop_event(wifi_constants.CONNECT_BY_CONFIG_SUCCESS, 30) 1463 connect_result = _wait_for_connect_event( 1464 ad, ssid=expected_ssid, tries=num_of_tries) 1465 asserts.assert_true(connect_result, 1466 "Failed to connect to Wi-Fi network %s on %s" % 1467 (network, ad.serial)) 1468 ad.log.debug("Wi-Fi connection result: %s.", connect_result) 1469 actual_ssid = connect_result['data'][WifiEnums.SSID_KEY] 1470 asserts.assert_equal(actual_ssid, expected_ssid, 1471 "Connected to the wrong network on %s." % 1472 ad.serial) 1473 ad.log.info("Connected to Wi-Fi network %s.", actual_ssid) 1474 1475 if check_connectivity: 1476 internet = validate_connection(ad, DEFAULT_PING_ADDR) 1477 if not internet: 1478 raise signals.TestFailure("Failed to connect to internet on %s" % 1479 expected_ssid) 1480 except Empty: 1481 asserts.fail("Failed to start connection process to %s on %s" % 1482 (network, ad.serial)) 1483 except Exception as error: 1484 ad.log.error("Failed to connect to %s with error %s", expected_ssid, 1485 error) 1486 raise signals.TestFailure("Failed to connect to %s network" % network) 1487 1488 finally: 1489 ad.droid.wifiStopTrackingStateChange() 1490 1491 1492def wifi_connect_by_id(ad, network_id, num_of_tries=3, assert_on_fail=True): 1493 """Connect an Android device to a wifi network using network Id. 1494 1495 Start connection to the wifi network, with the given network Id, wait for 1496 the "connected" event, then verify the connected network is the one requested. 1497 1498 This will directly fail a test if anything goes wrong. 1499 1500 Args: 1501 ad: android_device object to initiate connection on. 1502 network_id: Integer specifying the network id of the network. 1503 num_of_tries: An integer that is the number of times to try before 1504 delaring failure. Default is 1. 1505 assert_on_fail: If True, error checks in this function will raise test 1506 failure signals. 1507 1508 Returns: 1509 Returns a value only if assert_on_fail is false. 1510 Returns True if the connection was successful, False otherwise. 1511 """ 1512 _assert_on_fail_handler(_wifi_connect_by_id, assert_on_fail, ad, 1513 network_id, num_of_tries) 1514 1515 1516def _wifi_connect_by_id(ad, network_id, num_of_tries=1): 1517 """Connect an Android device to a wifi network using it's network id. 1518 1519 Start connection to the wifi network, with the given network id, wait for 1520 the "connected" event, then verify the connected network is the one requested. 1521 1522 Args: 1523 ad: android_device object to initiate connection on. 1524 network_id: Integer specifying the network id of the network. 1525 num_of_tries: An integer that is the number of times to try before 1526 delaring failure. Default is 1. 1527 """ 1528 ad.droid.wifiStartTrackingStateChange() 1529 # Clear all previous events. 1530 ad.ed.clear_all_events() 1531 ad.droid.wifiConnectByNetworkId(network_id) 1532 ad.log.info("Starting connection to network with id %d", network_id) 1533 try: 1534 event = ad.ed.pop_event(wifi_constants.CONNECT_BY_NETID_SUCCESS, 60) 1535 connect_result = _wait_for_connect_event( 1536 ad, id=network_id, tries=num_of_tries) 1537 asserts.assert_true(connect_result, 1538 "Failed to connect to Wi-Fi network using network id") 1539 ad.log.debug("Wi-Fi connection result: %s", connect_result) 1540 actual_id = connect_result['data'][WifiEnums.NETID_KEY] 1541 asserts.assert_equal(actual_id, network_id, 1542 "Connected to the wrong network on %s." 1543 "Expected network id = %d, but got %d." % 1544 (ad.serial, network_id, actual_id)) 1545 expected_ssid = connect_result['data'][WifiEnums.SSID_KEY] 1546 ad.log.info("Connected to Wi-Fi network %s with %d network id.", 1547 expected_ssid, network_id) 1548 1549 internet = validate_connection(ad, DEFAULT_PING_ADDR) 1550 if not internet: 1551 raise signals.TestFailure("Failed to connect to internet on %s" % 1552 expected_ssid) 1553 except Empty: 1554 asserts.fail("Failed to connect to network with id %d on %s" % 1555 (network_id, ad.serial)) 1556 except Exception as error: 1557 ad.log.error("Failed to connect to network with id %d with error %s", 1558 network_id, error) 1559 raise signals.TestFailure("Failed to connect to network with network" 1560 " id %d" % network_id) 1561 finally: 1562 ad.droid.wifiStopTrackingStateChange() 1563 1564 1565def wifi_connect_using_network_request(ad, network, network_specifier, 1566 num_of_tries=3, assert_on_fail=True): 1567 """Connect an Android device to a wifi network using network request. 1568 1569 Trigger a network request with the provided network specifier, 1570 wait for the "onMatch" event, ensure that the scan results in "onMatch" 1571 event contain the specified network, then simulate the user granting the 1572 request with the specified network selected. Then wait for the "onAvailable" 1573 network callback indicating successful connection to network. 1574 1575 This will directly fail a test if anything goes wrong. 1576 1577 Args: 1578 ad: android_device object to initiate connection on. 1579 network_specifier: A dictionary representing the network specifier to 1580 use. 1581 network: A dictionary representing the network to connect to. The 1582 dictionary must have the key "SSID". 1583 num_of_tries: An integer that is the number of times to try before 1584 delaring failure. 1585 assert_on_fail: If True, error checks in this function will raise test 1586 failure signals. 1587 1588 Returns: 1589 Returns a value only if assert_on_fail is false. 1590 Returns True if the connection was successful, False otherwise. 1591 """ 1592 _assert_on_fail_handler(_wifi_connect_using_network_request, assert_on_fail, 1593 ad, network, network_specifier, num_of_tries) 1594 1595 1596def _wifi_connect_using_network_request(ad, network, network_specifier, 1597 num_of_tries=3): 1598 """Connect an Android device to a wifi network using network request. 1599 1600 Trigger a network request with the provided network specifier, 1601 wait for the "onMatch" event, ensure that the scan results in "onMatch" 1602 event contain the specified network, then simulate the user granting the 1603 request with the specified network selected. Then wait for the "onAvailable" 1604 network callback indicating successful connection to network. 1605 1606 Args: 1607 ad: android_device object to initiate connection on. 1608 network_specifier: A dictionary representing the network specifier to 1609 use. 1610 network: A dictionary representing the network to connect to. The 1611 dictionary must have the key "SSID". 1612 num_of_tries: An integer that is the number of times to try before 1613 delaring failure. 1614 """ 1615 ad.droid.wifiRequestNetworkWithSpecifier(network_specifier) 1616 ad.log.info("Sent network request with %s", network_specifier) 1617 # Need a delay here because UI interaction should only start once wifi 1618 # starts processing the request. 1619 time.sleep(wifi_constants.NETWORK_REQUEST_CB_REGISTER_DELAY_SEC) 1620 _wait_for_wifi_connect_after_network_request(ad, network, num_of_tries) 1621 1622 1623def wait_for_wifi_connect_after_network_request(ad, network, num_of_tries=3, 1624 assert_on_fail=True): 1625 """ 1626 Simulate and verify the connection flow after initiating the network 1627 request. 1628 1629 Wait for the "onMatch" event, ensure that the scan results in "onMatch" 1630 event contain the specified network, then simulate the user granting the 1631 request with the specified network selected. Then wait for the "onAvailable" 1632 network callback indicating successful connection to network. 1633 1634 Args: 1635 ad: android_device object to initiate connection on. 1636 network: A dictionary representing the network to connect to. The 1637 dictionary must have the key "SSID". 1638 num_of_tries: An integer that is the number of times to try before 1639 delaring failure. 1640 assert_on_fail: If True, error checks in this function will raise test 1641 failure signals. 1642 1643 Returns: 1644 Returns a value only if assert_on_fail is false. 1645 Returns True if the connection was successful, False otherwise. 1646 """ 1647 _assert_on_fail_handler(_wait_for_wifi_connect_after_network_request, 1648 assert_on_fail, ad, network, num_of_tries) 1649 1650 1651def _wait_for_wifi_connect_after_network_request(ad, network, num_of_tries=3): 1652 """ 1653 Simulate and verify the connection flow after initiating the network 1654 request. 1655 1656 Wait for the "onMatch" event, ensure that the scan results in "onMatch" 1657 event contain the specified network, then simulate the user granting the 1658 request with the specified network selected. Then wait for the "onAvailable" 1659 network callback indicating successful connection to network. 1660 1661 Args: 1662 ad: android_device object to initiate connection on. 1663 network: A dictionary representing the network to connect to. The 1664 dictionary must have the key "SSID". 1665 num_of_tries: An integer that is the number of times to try before 1666 delaring failure. 1667 """ 1668 asserts.assert_true(WifiEnums.SSID_KEY in network, 1669 "Key '%s' must be present in network definition." % 1670 WifiEnums.SSID_KEY) 1671 ad.droid.wifiStartTrackingStateChange() 1672 expected_ssid = network[WifiEnums.SSID_KEY] 1673 ad.droid.wifiRegisterNetworkRequestMatchCallback() 1674 # Wait for the platform to scan and return a list of networks 1675 # matching the request 1676 try: 1677 matched_network = None 1678 for _ in [0, num_of_tries]: 1679 on_match_event = ad.ed.pop_event( 1680 wifi_constants.WIFI_NETWORK_REQUEST_MATCH_CB_ON_MATCH, 60) 1681 asserts.assert_true(on_match_event, 1682 "Network request on match not received.") 1683 matched_scan_results = on_match_event["data"] 1684 ad.log.debug("Network request on match results %s", 1685 matched_scan_results) 1686 matched_network = match_networks( 1687 {WifiEnums.SSID_KEY: network[WifiEnums.SSID_KEY]}, 1688 matched_scan_results) 1689 if matched_network: 1690 break; 1691 1692 asserts.assert_true( 1693 matched_network, "Target network %s not found" % network) 1694 1695 ad.droid.wifiSendUserSelectionForNetworkRequestMatch(network) 1696 ad.log.info("Sent user selection for network request %s", 1697 expected_ssid) 1698 1699 # Wait for the platform to connect to the network. 1700 on_available_event = ad.ed.pop_event( 1701 wifi_constants.WIFI_NETWORK_CB_ON_AVAILABLE, 60) 1702 asserts.assert_true(on_available_event, 1703 "Network request on available not received.") 1704 connected_network = on_available_event["data"] 1705 ad.log.info("Connected to network %s", connected_network) 1706 asserts.assert_equal(connected_network[WifiEnums.SSID_KEY], 1707 expected_ssid, 1708 "Connected to the wrong network." 1709 "Expected %s, but got %s." % 1710 (network, connected_network)) 1711 except Empty: 1712 asserts.fail("Failed to connect to %s" % expected_ssid) 1713 except Exception as error: 1714 ad.log.error("Failed to connect to %s with error %s", 1715 (expected_ssid, error)) 1716 raise signals.TestFailure("Failed to connect to %s network" % network) 1717 finally: 1718 ad.droid.wifiStopTrackingStateChange() 1719 1720 1721def wifi_passpoint_connect(ad, passpoint_network, num_of_tries=1, 1722 assert_on_fail=True): 1723 """Connect an Android device to a wifi network. 1724 1725 Initiate connection to a wifi network, wait for the "connected" event, then 1726 confirm the connected ssid is the one requested. 1727 1728 This will directly fail a test if anything goes wrong. 1729 1730 Args: 1731 ad: android_device object to initiate connection on. 1732 passpoint_network: SSID of the Passpoint network to connect to. 1733 num_of_tries: An integer that is the number of times to try before 1734 delaring failure. Default is 1. 1735 assert_on_fail: If True, error checks in this function will raise test 1736 failure signals. 1737 1738 Returns: 1739 If assert_on_fail is False, function returns network id, if the connect was 1740 successful, False otherwise. If assert_on_fail is True, no return value. 1741 """ 1742 _assert_on_fail_handler(_wifi_passpoint_connect, assert_on_fail, ad, 1743 passpoint_network, num_of_tries = num_of_tries) 1744 1745 1746def _wifi_passpoint_connect(ad, passpoint_network, num_of_tries=1): 1747 """Connect an Android device to a wifi network. 1748 1749 Initiate connection to a wifi network, wait for the "connected" event, then 1750 confirm the connected ssid is the one requested. 1751 1752 This will directly fail a test if anything goes wrong. 1753 1754 Args: 1755 ad: android_device object to initiate connection on. 1756 passpoint_network: SSID of the Passpoint network to connect to. 1757 num_of_tries: An integer that is the number of times to try before 1758 delaring failure. Default is 1. 1759 """ 1760 ad.droid.wifiStartTrackingStateChange() 1761 expected_ssid = passpoint_network 1762 ad.log.info("Starting connection process to passpoint %s", expected_ssid) 1763 1764 try: 1765 connect_result = _wait_for_connect_event( 1766 ad, expected_ssid, num_of_tries) 1767 asserts.assert_true(connect_result, 1768 "Failed to connect to WiFi passpoint network %s on" 1769 " %s" % (expected_ssid, ad.serial)) 1770 ad.log.info("Wi-Fi connection result: %s.", connect_result) 1771 actual_ssid = connect_result['data'][WifiEnums.SSID_KEY] 1772 asserts.assert_equal(actual_ssid, expected_ssid, 1773 "Connected to the wrong network on %s." % ad.serial) 1774 ad.log.info("Connected to Wi-Fi passpoint network %s.", actual_ssid) 1775 1776 internet = validate_connection(ad, DEFAULT_PING_ADDR) 1777 if not internet: 1778 raise signals.TestFailure("Failed to connect to internet on %s" % 1779 expected_ssid) 1780 except Exception as error: 1781 ad.log.error("Failed to connect to passpoint network %s with error %s", 1782 expected_ssid, error) 1783 raise signals.TestFailure("Failed to connect to %s passpoint network" % 1784 expected_ssid) 1785 1786 finally: 1787 ad.droid.wifiStopTrackingStateChange() 1788 1789 1790def delete_passpoint(ad, fqdn): 1791 """Delete a required Passpoint configuration.""" 1792 try: 1793 ad.droid.removePasspointConfig(fqdn) 1794 return True 1795 except Exception as error: 1796 ad.log.error("Failed to remove passpoint configuration with FQDN=%s " 1797 "and error=%s" , fqdn, error) 1798 return False 1799 1800 1801def start_wifi_single_scan(ad, scan_setting): 1802 """Starts wifi single shot scan. 1803 1804 Args: 1805 ad: android_device object to initiate connection on. 1806 scan_setting: A dict representing the settings of the scan. 1807 1808 Returns: 1809 If scan was started successfully, event data of success event is returned. 1810 """ 1811 idx = ad.droid.wifiScannerStartScan(scan_setting) 1812 event = ad.ed.pop_event("WifiScannerScan%sonSuccess" % idx, SHORT_TIMEOUT) 1813 ad.log.debug("Got event %s", event) 1814 return event['data'] 1815 1816 1817def track_connection(ad, network_ssid, check_connection_count): 1818 """Track wifi connection to network changes for given number of counts 1819 1820 Args: 1821 ad: android_device object for forget network. 1822 network_ssid: network ssid to which connection would be tracked 1823 check_connection_count: Integer for maximum number network connection 1824 check. 1825 Returns: 1826 True if connection to given network happen, else return False. 1827 """ 1828 ad.droid.wifiStartTrackingStateChange() 1829 while check_connection_count > 0: 1830 connect_network = ad.ed.pop_event("WifiNetworkConnected", 120) 1831 ad.log.info("Connected to network %s", connect_network) 1832 if (WifiEnums.SSID_KEY in connect_network['data'] and 1833 connect_network['data'][WifiEnums.SSID_KEY] == network_ssid): 1834 return True 1835 check_connection_count -= 1 1836 ad.droid.wifiStopTrackingStateChange() 1837 return False 1838 1839 1840def get_scan_time_and_channels(wifi_chs, scan_setting, stime_channel): 1841 """Calculate the scan time required based on the band or channels in scan 1842 setting 1843 1844 Args: 1845 wifi_chs: Object of channels supported 1846 scan_setting: scan setting used for start scan 1847 stime_channel: scan time per channel 1848 1849 Returns: 1850 scan_time: time required for completing a scan 1851 scan_channels: channel used for scanning 1852 """ 1853 scan_time = 0 1854 scan_channels = [] 1855 if "band" in scan_setting and "channels" not in scan_setting: 1856 scan_channels = wifi_chs.band_to_freq(scan_setting["band"]) 1857 elif "channels" in scan_setting and "band" not in scan_setting: 1858 scan_channels = scan_setting["channels"] 1859 scan_time = len(scan_channels) * stime_channel 1860 for channel in scan_channels: 1861 if channel in WifiEnums.DFS_5G_FREQUENCIES: 1862 scan_time += 132 #passive scan time on DFS 1863 return scan_time, scan_channels 1864 1865 1866def start_wifi_track_bssid(ad, track_setting): 1867 """Start tracking Bssid for the given settings. 1868 1869 Args: 1870 ad: android_device object. 1871 track_setting: Setting for which the bssid tracking should be started 1872 1873 Returns: 1874 If tracking started successfully, event data of success event is returned. 1875 """ 1876 idx = ad.droid.wifiScannerStartTrackingBssids( 1877 track_setting["bssidInfos"], track_setting["apLostThreshold"]) 1878 event = ad.ed.pop_event("WifiScannerBssid{}onSuccess".format(idx), 1879 SHORT_TIMEOUT) 1880 return event['data'] 1881 1882 1883def convert_pem_key_to_pkcs8(in_file, out_file): 1884 """Converts the key file generated by us to the format required by 1885 Android using openssl. 1886 1887 The input file must have the extension "pem". The output file must 1888 have the extension "der". 1889 1890 Args: 1891 in_file: The original key file. 1892 out_file: The full path to the converted key file, including 1893 filename. 1894 """ 1895 asserts.assert_true(in_file.endswith(".pem"), "Input file has to be .pem.") 1896 asserts.assert_true( 1897 out_file.endswith(".der"), "Output file has to be .der.") 1898 cmd = ("openssl pkcs8 -inform PEM -in {} -outform DER -out {} -nocrypt" 1899 " -topk8").format(in_file, out_file) 1900 utils.exe_cmd(cmd) 1901 1902 1903def validate_connection(ad, ping_addr=DEFAULT_PING_ADDR, wait_time=15, 1904 ping_gateway=True): 1905 """Validate internet connection by pinging the address provided. 1906 1907 Args: 1908 ad: android_device object. 1909 ping_addr: address on internet for pinging. 1910 wait_time: wait for some time before validating connection 1911 1912 Returns: 1913 ping output if successful, NULL otherwise. 1914 """ 1915 # wait_time to allow for DHCP to complete. 1916 for i in range(wait_time): 1917 if ad.droid.connectivityNetworkIsConnected(): 1918 break 1919 time.sleep(1) 1920 ping = False 1921 try: 1922 ping = ad.droid.httpPing(ping_addr) 1923 ad.log.info("Http ping result: %s.", ping) 1924 except: 1925 pass 1926 if not ping and ping_gateway: 1927 ad.log.info("Http ping failed. Pinging default gateway") 1928 gw = ad.droid.connectivityGetIPv4DefaultGateway() 1929 result = ad.adb.shell("ping -c 6 {}".format(gw)) 1930 ad.log.info("Default gateway ping result: %s" % result) 1931 ping = False if "100% packet loss" in result else True 1932 return ping 1933 1934 1935#TODO(angli): This can only verify if an actual value is exactly the same. 1936# Would be nice to be able to verify an actual value is one of serveral. 1937def verify_wifi_connection_info(ad, expected_con): 1938 """Verifies that the information of the currently connected wifi network is 1939 as expected. 1940 1941 Args: 1942 expected_con: A dict representing expected key-value pairs for wifi 1943 connection. e.g. {"SSID": "test_wifi"} 1944 """ 1945 current_con = ad.droid.wifiGetConnectionInfo() 1946 case_insensitive = ["BSSID", "supplicant_state"] 1947 ad.log.debug("Current connection: %s", current_con) 1948 for k, expected_v in expected_con.items(): 1949 # Do not verify authentication related fields. 1950 if k == "password": 1951 continue 1952 msg = "Field %s does not exist in wifi connection info %s." % ( 1953 k, current_con) 1954 if k not in current_con: 1955 raise signals.TestFailure(msg) 1956 actual_v = current_con[k] 1957 if k in case_insensitive: 1958 actual_v = actual_v.lower() 1959 expected_v = expected_v.lower() 1960 msg = "Expected %s to be %s, actual %s is %s." % (k, expected_v, k, 1961 actual_v) 1962 if actual_v != expected_v: 1963 raise signals.TestFailure(msg) 1964 1965 1966def check_autoconnect_to_open_network(ad, conn_timeout=WIFI_CONNECTION_TIMEOUT_DEFAULT): 1967 """Connects to any open WiFI AP 1968 Args: 1969 timeout value in sec to wait for UE to connect to a WiFi AP 1970 Returns: 1971 True if UE connects to WiFi AP (supplicant_state = completed) 1972 False if UE fails to complete connection within WIFI_CONNECTION_TIMEOUT time. 1973 """ 1974 if ad.droid.wifiCheckState(): 1975 return True 1976 ad.droid.wifiToggleState() 1977 wifi_connection_state = None 1978 timeout = time.time() + conn_timeout 1979 while wifi_connection_state != "completed": 1980 wifi_connection_state = ad.droid.wifiGetConnectionInfo()[ 1981 'supplicant_state'] 1982 if time.time() > timeout: 1983 ad.log.warning("Failed to connect to WiFi AP") 1984 return False 1985 return True 1986 1987 1988def expand_enterprise_config_by_phase2(config): 1989 """Take an enterprise config and generate a list of configs, each with 1990 a different phase2 auth type. 1991 1992 Args: 1993 config: A dict representing enterprise config. 1994 1995 Returns 1996 A list of enterprise configs. 1997 """ 1998 results = [] 1999 phase2_types = WifiEnums.EapPhase2 2000 if config[WifiEnums.Enterprise.EAP] == WifiEnums.Eap.PEAP: 2001 # Skip unsupported phase2 types for PEAP. 2002 phase2_types = [WifiEnums.EapPhase2.GTC, WifiEnums.EapPhase2.MSCHAPV2] 2003 for phase2_type in phase2_types: 2004 # Skip a special case for passpoint TTLS. 2005 if (WifiEnums.Enterprise.FQDN in config and 2006 phase2_type == WifiEnums.EapPhase2.GTC): 2007 continue 2008 c = dict(config) 2009 c[WifiEnums.Enterprise.PHASE2] = phase2_type.value 2010 results.append(c) 2011 return results 2012 2013 2014def generate_eap_test_name(config, ad=None): 2015 """ Generates a test case name based on an EAP configuration. 2016 2017 Args: 2018 config: A dict representing an EAP credential. 2019 ad object: Redundant but required as the same param is passed 2020 to test_func in run_generated_tests 2021 2022 Returns: 2023 A string representing the name of a generated EAP test case. 2024 """ 2025 eap = WifiEnums.Eap 2026 eap_phase2 = WifiEnums.EapPhase2 2027 Ent = WifiEnums.Enterprise 2028 name = "test_connect-" 2029 eap_name = "" 2030 for e in eap: 2031 if e.value == config[Ent.EAP]: 2032 eap_name = e.name 2033 break 2034 if "peap0" in config[WifiEnums.SSID_KEY].lower(): 2035 eap_name = "PEAP0" 2036 if "peap1" in config[WifiEnums.SSID_KEY].lower(): 2037 eap_name = "PEAP1" 2038 name += eap_name 2039 if Ent.PHASE2 in config: 2040 for e in eap_phase2: 2041 if e.value == config[Ent.PHASE2]: 2042 name += "-{}".format(e.name) 2043 break 2044 return name 2045 2046 2047def group_attenuators(attenuators): 2048 """Groups a list of attenuators into attenuator groups for backward 2049 compatibility reasons. 2050 2051 Most legacy Wi-Fi setups have two attenuators each connected to a separate 2052 AP. The new Wi-Fi setup has four attenuators, each connected to one channel 2053 on an AP, so two of them are connected to one AP. 2054 2055 To make the existing scripts work in the new setup, when the script needs 2056 to attenuate one AP, it needs to set attenuation on both attenuators 2057 connected to the same AP. 2058 2059 This function groups attenuators properly so the scripts work in both 2060 legacy and new Wi-Fi setups. 2061 2062 Args: 2063 attenuators: A list of attenuator objects, either two or four in length. 2064 2065 Raises: 2066 signals.TestFailure is raised if the attenuator list does not have two 2067 or four objects. 2068 """ 2069 attn0 = attenuator.AttenuatorGroup("AP0") 2070 attn1 = attenuator.AttenuatorGroup("AP1") 2071 # Legacy testbed setup has two attenuation channels. 2072 num_of_attns = len(attenuators) 2073 if num_of_attns == 2: 2074 attn0.add(attenuators[0]) 2075 attn1.add(attenuators[1]) 2076 elif num_of_attns == 4: 2077 attn0.add(attenuators[0]) 2078 attn0.add(attenuators[1]) 2079 attn1.add(attenuators[2]) 2080 attn1.add(attenuators[3]) 2081 else: 2082 asserts.fail(("Either two or four attenuators are required for this " 2083 "test, but found %s") % num_of_attns) 2084 return [attn0, attn1] 2085 2086 2087def set_attns(attenuator, attn_val_name, roaming_attn=ROAMING_ATTN): 2088 """Sets attenuation values on attenuators used in this test. 2089 2090 Args: 2091 attenuator: The attenuator object. 2092 attn_val_name: Name of the attenuation value pair to use. 2093 roaming_attn: Dictionary specifying the attenuation params. 2094 """ 2095 logging.info("Set attenuation values to %s", roaming_attn[attn_val_name]) 2096 try: 2097 attenuator[0].set_atten(roaming_attn[attn_val_name][0]) 2098 attenuator[1].set_atten(roaming_attn[attn_val_name][1]) 2099 attenuator[2].set_atten(roaming_attn[attn_val_name][2]) 2100 attenuator[3].set_atten(roaming_attn[attn_val_name][3]) 2101 except: 2102 logging.exception("Failed to set attenuation values %s.", 2103 attn_val_name) 2104 raise 2105 2106def set_attns_steps(attenuators, 2107 atten_val_name, 2108 roaming_attn=ROAMING_ATTN, 2109 steps=10, 2110 wait_time=12): 2111 """Set attenuation values on attenuators used in this test. It will change 2112 the attenuation values linearly from current value to target value step by 2113 step. 2114 2115 Args: 2116 attenuators: The list of attenuator objects that you want to change 2117 their attenuation value. 2118 atten_val_name: Name of the attenuation value pair to use. 2119 roaming_attn: Dictionary specifying the attenuation params. 2120 steps: Number of attenuator changes to reach the target value. 2121 wait_time: Sleep time for each change of attenuator. 2122 """ 2123 logging.info("Set attenuation values to %s in %d step(s)", 2124 roaming_attn[atten_val_name], steps) 2125 start_atten = [attenuator.get_atten() for attenuator in attenuators] 2126 target_atten = roaming_attn[atten_val_name] 2127 for current_step in range(steps): 2128 progress = (current_step + 1) / steps 2129 for i, attenuator in enumerate(attenuators): 2130 amount_since_start = (target_atten[i] - start_atten[i]) * progress 2131 attenuator.set_atten(round(start_atten[i] + amount_since_start)) 2132 time.sleep(wait_time) 2133 2134 2135def trigger_roaming_and_validate(dut, 2136 attenuator, 2137 attn_val_name, 2138 expected_con, 2139 roaming_attn=ROAMING_ATTN): 2140 """Sets attenuators to trigger roaming and validate the DUT connected 2141 to the BSSID expected. 2142 2143 Args: 2144 attenuator: The attenuator object. 2145 attn_val_name: Name of the attenuation value pair to use. 2146 expected_con: The network information of the expected network. 2147 roaming_attn: Dictionary specifying the attenaution params. 2148 """ 2149 expected_con = { 2150 WifiEnums.SSID_KEY: expected_con[WifiEnums.SSID_KEY], 2151 WifiEnums.BSSID_KEY: expected_con["bssid"], 2152 } 2153 set_attns_steps(attenuator, attn_val_name, roaming_attn) 2154 2155 verify_wifi_connection_info(dut, expected_con) 2156 expected_bssid = expected_con[WifiEnums.BSSID_KEY] 2157 logging.info("Roamed to %s successfully", expected_bssid) 2158 if not validate_connection(dut): 2159 raise signals.TestFailure("Fail to connect to internet on %s" % 2160 expected_bssid) 2161 2162def create_softap_config(): 2163 """Create a softap config with random ssid and password.""" 2164 ap_ssid = "softap_" + utils.rand_ascii_str(8) 2165 ap_password = utils.rand_ascii_str(8) 2166 logging.info("softap setup: %s %s", ap_ssid, ap_password) 2167 config = { 2168 WifiEnums.SSID_KEY: ap_ssid, 2169 WifiEnums.PWD_KEY: ap_password, 2170 } 2171 return config 2172 2173def start_softap_and_verify(ad, band): 2174 """Bring-up softap and verify AP mode and in scan results. 2175 2176 Args: 2177 band: The band to use for softAP. 2178 2179 Returns: dict, the softAP config. 2180 2181 """ 2182 # Register before start the test. 2183 callbackId = ad.dut.droid.registerSoftApCallback() 2184 # Check softap info value is default 2185 frequency, bandwdith = get_current_softap_info(ad.dut, callbackId, True) 2186 asserts.assert_true(frequency == 0, "Softap frequency is not reset") 2187 asserts.assert_true(bandwdith == 0, "Softap bandwdith is not reset") 2188 2189 config = create_softap_config() 2190 start_wifi_tethering(ad.dut, 2191 config[WifiEnums.SSID_KEY], 2192 config[WifiEnums.PWD_KEY], band=band) 2193 asserts.assert_true(ad.dut.droid.wifiIsApEnabled(), 2194 "SoftAp is not reported as running") 2195 start_wifi_connection_scan_and_ensure_network_found(ad.dut_client, 2196 config[WifiEnums.SSID_KEY]) 2197 2198 # Check softap info can get from callback succeed and assert value should be 2199 # valid. 2200 frequency, bandwdith = get_current_softap_info(ad.dut, callbackId, True) 2201 asserts.assert_true(frequency > 0, "Softap frequency is not valid") 2202 asserts.assert_true(bandwdith > 0, "Softap bandwdith is not valid") 2203 # Unregister callback 2204 ad.dut.droid.unregisterSoftApCallback(callbackId) 2205 2206 return config 2207 2208def wait_for_expected_number_of_softap_clients(ad, callbackId, 2209 expected_num_of_softap_clients): 2210 """Wait for the number of softap clients to be updated as expected. 2211 Args: 2212 callbackId: Id of the callback associated with registering. 2213 expected_num_of_softap_clients: expected number of softap clients. 2214 """ 2215 eventStr = wifi_constants.SOFTAP_CALLBACK_EVENT + str( 2216 callbackId) + wifi_constants.SOFTAP_NUMBER_CLIENTS_CHANGED 2217 clientData = ad.ed.pop_event(eventStr, SHORT_TIMEOUT)['data'] 2218 clientCount = clientData[wifi_constants.SOFTAP_NUMBER_CLIENTS_CALLBACK_KEY] 2219 clientMacAddresses = clientData[wifi_constants.SOFTAP_CLIENTS_MACS_CALLBACK_KEY] 2220 asserts.assert_equal(clientCount, expected_num_of_softap_clients, 2221 "The number of softap clients doesn't match the expected number") 2222 asserts.assert_equal(len(clientMacAddresses), expected_num_of_softap_clients, 2223 "The number of mac addresses doesn't match the expected number") 2224 for macAddress in clientMacAddresses: 2225 asserts.assert_true(checkMacAddress(macAddress), "An invalid mac address was returned") 2226 2227def checkMacAddress(input): 2228 """Validate whether a string is a valid mac address or not. 2229 2230 Args: 2231 input: The string to validate. 2232 2233 Returns: True/False, returns true for a valid mac address and false otherwise. 2234 """ 2235 macValidationRegex = "[0-9a-f]{2}([-:]?)[0-9a-f]{2}(\\1[0-9a-f]{2}){4}$" 2236 if re.match(macValidationRegex, input.lower()): 2237 return True 2238 return False 2239 2240def wait_for_expected_softap_state(ad, callbackId, expected_softap_state): 2241 """Wait for the expected softap state change. 2242 Args: 2243 callbackId: Id of the callback associated with registering. 2244 expected_softap_state: The expected softap state. 2245 """ 2246 eventStr = wifi_constants.SOFTAP_CALLBACK_EVENT + str( 2247 callbackId) + wifi_constants.SOFTAP_STATE_CHANGED 2248 asserts.assert_equal(ad.ed.pop_event(eventStr, 2249 SHORT_TIMEOUT)['data'][wifi_constants. 2250 SOFTAP_STATE_CHANGE_CALLBACK_KEY], 2251 expected_softap_state, 2252 "Softap state doesn't match with expected state") 2253 2254def get_current_number_of_softap_clients(ad, callbackId): 2255 """pop up all of softap client updated event from queue. 2256 Args: 2257 callbackId: Id of the callback associated with registering. 2258 2259 Returns: 2260 If exist aleast callback, returns last updated number_of_softap_clients. 2261 Returns None when no any match callback event in queue. 2262 """ 2263 eventStr = wifi_constants.SOFTAP_CALLBACK_EVENT + str( 2264 callbackId) + wifi_constants.SOFTAP_NUMBER_CLIENTS_CHANGED 2265 events = ad.ed.pop_all(eventStr) 2266 for event in events: 2267 num_of_clients = event['data'][wifi_constants. 2268 SOFTAP_NUMBER_CLIENTS_CALLBACK_KEY] 2269 if len(events) == 0: 2270 return None 2271 return num_of_clients 2272 2273def get_current_softap_info(ad, callbackId, least_one): 2274 """pop up all of softap info changed event from queue. 2275 Args: 2276 callbackId: Id of the callback associated with registering. 2277 least_one: Wait for the info callback event before pop all. 2278 Returns: 2279 Returns last updated information of softap. 2280 """ 2281 eventStr = wifi_constants.SOFTAP_CALLBACK_EVENT + str( 2282 callbackId) + wifi_constants.SOFTAP_INFO_CHANGED 2283 ad.log.info("softap info dump from eventStr %s", 2284 eventStr) 2285 frequency = 0 2286 bandwidth = 0 2287 if (least_one): 2288 event = ad.ed.pop_event(eventStr, SHORT_TIMEOUT) 2289 frequency = event['data'][wifi_constants. 2290 SOFTAP_INFO_FREQUENCY_CALLBACK_KEY] 2291 bandwidth = event['data'][wifi_constants. 2292 SOFTAP_INFO_BANDWIDTH_CALLBACK_KEY] 2293 ad.log.info("softap info updated, frequency is %s, bandwidth is %s", 2294 frequency, bandwidth) 2295 2296 events = ad.ed.pop_all(eventStr) 2297 for event in events: 2298 frequency = event['data'][wifi_constants. 2299 SOFTAP_INFO_FREQUENCY_CALLBACK_KEY] 2300 bandwidth = event['data'][wifi_constants. 2301 SOFTAP_INFO_BANDWIDTH_CALLBACK_KEY] 2302 ad.log.info("softap info, frequency is %s, bandwidth is %s", 2303 frequency, bandwidth) 2304 return frequency, bandwidth 2305 2306 2307 2308def get_ssrdumps(ad, test_name=""): 2309 """Pulls dumps in the ssrdump dir 2310 Args: 2311 ad: android device object. 2312 test_name: test case name 2313 """ 2314 logs = ad.get_file_names("/data/vendor/ssrdump/") 2315 if logs: 2316 ad.log.info("Pulling ssrdumps %s", logs) 2317 log_path = os.path.join(ad.log_path, test_name, 2318 "SSRDUMP_%s" % ad.serial) 2319 os.makedirs(log_path, exist_ok=True) 2320 ad.pull_files(logs, log_path) 2321 ad.adb.shell("find /data/vendor/ssrdump/ -type f -delete") 2322 2323def start_pcap(pcap, wifi_band, test_name): 2324 """Start packet capture in monitor mode. 2325 2326 Args: 2327 pcap: packet capture object 2328 wifi_band: '2g' or '5g' or 'dual' 2329 test_name: test name to be used for pcap file name 2330 2331 Returns: 2332 Dictionary with wifi band as key and the tuple 2333 (pcap Process object, log directory) as the value 2334 """ 2335 log_dir = os.path.join( 2336 context.get_current_context().get_full_output_path(), 'PacketCapture') 2337 os.makedirs(log_dir, exist_ok=True) 2338 if wifi_band == 'dual': 2339 bands = [BAND_2G, BAND_5G] 2340 else: 2341 bands = [wifi_band] 2342 procs = {} 2343 for band in bands: 2344 proc = pcap.start_packet_capture(band, log_dir, test_name) 2345 procs[band] = (proc, os.path.join(log_dir, test_name)) 2346 return procs 2347 2348 2349def stop_pcap(pcap, procs, test_status=None): 2350 """Stop packet capture in monitor mode. 2351 2352 Since, the pcap logs in monitor mode can be very large, we will 2353 delete them if they are not required. 'test_status' if True, will delete 2354 the pcap files. If False, we will keep them. 2355 2356 Args: 2357 pcap: packet capture object 2358 procs: dictionary returned by start_pcap 2359 test_status: status of the test case 2360 """ 2361 for proc, fname in procs.values(): 2362 pcap.stop_packet_capture(proc) 2363 2364 if test_status: 2365 shutil.rmtree(os.path.dirname(fname)) 2366 2367def verify_mac_not_found_in_pcap(ad, mac, packets): 2368 """Verify that a mac address is not found in the captured packets. 2369 2370 Args: 2371 ad: android device object 2372 mac: string representation of the mac address 2373 packets: packets obtained by rdpcap(pcap_fname) 2374 """ 2375 for pkt in packets: 2376 logging.debug("Packet Summary = %s", pkt.summary()) 2377 if mac in pkt.summary(): 2378 asserts.fail("Device %s caught Factory MAC: %s in packet sniffer." 2379 "Packet = %s" % (ad.serial, mac, pkt.show())) 2380 2381def verify_mac_is_found_in_pcap(ad, mac, packets): 2382 """Verify that a mac address is found in the captured packets. 2383 2384 Args: 2385 ad: android device object 2386 mac: string representation of the mac address 2387 packets: packets obtained by rdpcap(pcap_fname) 2388 """ 2389 for pkt in packets: 2390 if mac in pkt.summary(): 2391 return 2392 asserts.fail("Did not find MAC = %s in packet sniffer." 2393 "for device %s" % (mac, ad.serial)) 2394 2395def start_cnss_diags(ads): 2396 for ad in ads: 2397 start_cnss_diag(ad) 2398 2399 2400def start_cnss_diag(ad): 2401 """Start cnss_diag to record extra wifi logs 2402 2403 Args: 2404 ad: android device object. 2405 """ 2406 if ad.model in wifi_constants.DEVICES_USING_LEGACY_PROP: 2407 prop = wifi_constants.LEGACY_CNSS_DIAG_PROP 2408 else: 2409 prop = wifi_constants.CNSS_DIAG_PROP 2410 if ad.adb.getprop(prop) != 'true': 2411 ad.adb.shell("find /data/vendor/wifi/cnss_diag/wlan_logs/ -type f -delete") 2412 ad.adb.shell("setprop %s true" % prop, ignore_status=True) 2413 2414 2415def stop_cnss_diags(ads): 2416 for ad in ads: 2417 stop_cnss_diag(ad) 2418 2419 2420def stop_cnss_diag(ad): 2421 """Stops cnss_diag 2422 2423 Args: 2424 ad: android device object. 2425 """ 2426 if ad.model in wifi_constants.DEVICES_USING_LEGACY_PROP: 2427 prop = wifi_constants.LEGACY_CNSS_DIAG_PROP 2428 else: 2429 prop = wifi_constants.CNSS_DIAG_PROP 2430 ad.adb.shell("setprop %s false" % prop, ignore_status=True) 2431 2432 2433def get_cnss_diag_log(ad, test_name=""): 2434 """Pulls the cnss_diag logs in the wlan_logs dir 2435 Args: 2436 ad: android device object. 2437 test_name: test case name 2438 """ 2439 logs = ad.get_file_names("/data/vendor/wifi/cnss_diag/wlan_logs/") 2440 if logs: 2441 ad.log.info("Pulling cnss_diag logs %s", logs) 2442 log_path = os.path.join(ad.device_log_path, "CNSS_DIAG_%s" % ad.serial) 2443 os.makedirs(log_path, exist_ok=True) 2444 ad.pull_files(logs, log_path) 2445 2446 2447LinkProbeResult = namedtuple('LinkProbeResult', ( 2448 'is_success', 'stdout', 'elapsed_time', 'failure_reason')) 2449 2450 2451def send_link_probe(ad): 2452 """Sends a link probe to the currently connected AP, and returns whether the 2453 probe succeeded or not. 2454 2455 Args: 2456 ad: android device object 2457 Returns: 2458 LinkProbeResult namedtuple 2459 """ 2460 stdout = ad.adb.shell('cmd wifi send-link-probe') 2461 asserts.assert_false('Error' in stdout or 'Exception' in stdout, 2462 'Exception while sending link probe: ' + stdout) 2463 2464 is_success = False 2465 elapsed_time = None 2466 failure_reason = None 2467 if 'succeeded' in stdout: 2468 is_success = True 2469 elapsed_time = next( 2470 (int(token) for token in stdout.split() if token.isdigit()), None) 2471 elif 'failed with reason' in stdout: 2472 failure_reason = next( 2473 (int(token) for token in stdout.split() if token.isdigit()), None) 2474 else: 2475 asserts.fail('Unexpected link probe result: ' + stdout) 2476 2477 return LinkProbeResult( 2478 is_success=is_success, stdout=stdout, 2479 elapsed_time=elapsed_time, failure_reason=failure_reason) 2480 2481 2482def send_link_probes(ad, num_probes, delay_sec): 2483 """Sends a sequence of link probes to the currently connected AP, and 2484 returns whether the probes succeeded or not. 2485 2486 Args: 2487 ad: android device object 2488 num_probes: number of probes to perform 2489 delay_sec: delay time between probes, in seconds 2490 Returns: 2491 List[LinkProbeResult] one LinkProbeResults for each probe 2492 """ 2493 logging.info('Sending link probes') 2494 results = [] 2495 for _ in range(num_probes): 2496 # send_link_probe() will also fail the test if it sees an exception 2497 # in the stdout of the adb shell command 2498 result = send_link_probe(ad) 2499 logging.info('link probe results: ' + str(result)) 2500 results.append(result) 2501 time.sleep(delay_sec) 2502 2503 return results 2504 2505 2506def ap_setup(test, index, ap, network, bandwidth=80, channel=6): 2507 """Set up the AP with provided network info. 2508 2509 Args: 2510 test: the calling test class object. 2511 index: int, index of the AP. 2512 ap: access_point object of the AP. 2513 network: dict with information of the network, including ssid, 2514 password and bssid. 2515 bandwidth: the operation bandwidth for the AP, default 80MHz. 2516 channel: the channel number for the AP. 2517 Returns: 2518 brconfigs: the bridge interface configs 2519 """ 2520 bss_settings = [] 2521 ssid = network[WifiEnums.SSID_KEY] 2522 test.access_points[index].close() 2523 time.sleep(5) 2524 2525 # Configure AP as required. 2526 if "password" in network.keys(): 2527 password = network["password"] 2528 security = hostapd_security.Security( 2529 security_mode="wpa", password=password) 2530 else: 2531 security = hostapd_security.Security(security_mode=None, password=None) 2532 config = hostapd_ap_preset.create_ap_preset( 2533 channel=channel, 2534 ssid=ssid, 2535 security=security, 2536 bss_settings=bss_settings, 2537 vht_bandwidth=bandwidth, 2538 profile_name='whirlwind', 2539 iface_wlan_2g=ap.wlan_2g, 2540 iface_wlan_5g=ap.wlan_5g) 2541 ap.start_ap(config) 2542 logging.info("AP started on channel {} with SSID {}".format(channel, ssid)) 2543 2544 2545def turn_ap_off(test, AP): 2546 """Bring down hostapd on the Access Point. 2547 Args: 2548 test: The test class object. 2549 AP: int, indicating which AP to turn OFF. 2550 """ 2551 hostapd_2g = test.access_points[AP-1]._aps['wlan0'].hostapd 2552 if hostapd_2g.is_alive(): 2553 hostapd_2g.stop() 2554 logging.debug('Turned WLAN0 AP%d off' % AP) 2555 hostapd_5g = test.access_points[AP-1]._aps['wlan1'].hostapd 2556 if hostapd_5g.is_alive(): 2557 hostapd_5g.stop() 2558 logging.debug('Turned WLAN1 AP%d off' % AP) 2559 2560 2561def turn_ap_on(test, AP): 2562 """Bring up hostapd on the Access Point. 2563 Args: 2564 test: The test class object. 2565 AP: int, indicating which AP to turn ON. 2566 """ 2567 hostapd_2g = test.access_points[AP-1]._aps['wlan0'].hostapd 2568 if not hostapd_2g.is_alive(): 2569 hostapd_2g.start(hostapd_2g.config) 2570 logging.debug('Turned WLAN0 AP%d on' % AP) 2571 hostapd_5g = test.access_points[AP-1]._aps['wlan1'].hostapd 2572 if not hostapd_5g.is_alive(): 2573 hostapd_5g.start(hostapd_5g.config) 2574 logging.debug('Turned WLAN1 AP%d on' % AP) 2575 2576 2577def turn_location_off_and_scan_toggle_off(ad): 2578 """Turns off wifi location scans.""" 2579 utils.set_location_service(ad, False) 2580 ad.droid.wifiScannerToggleAlwaysAvailable(False) 2581 msg = "Failed to turn off location service's scan." 2582 asserts.assert_true(not ad.droid.wifiScannerIsAlwaysAvailable(), msg) 2583