1 #!/usr/bin/env python3.4 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 17 import logging 18 import time 19 import pprint 20 21 from enum import IntEnum 22 from queue import Empty 23 24 from acts import asserts 25 from acts import signals 26 from acts import utils 27 from acts.controllers import attenuator 28 from acts.test_utils.wifi import wifi_constants 29 from acts.test_utils.tel import tel_defines 30 31 # Default timeout used for reboot, toggle WiFi and Airplane mode, 32 # for the system to settle down after the operation. 33 DEFAULT_TIMEOUT = 10 34 # Number of seconds to wait for events that are supposed to happen quickly. 35 # Like onSuccess for start background scan and confirmation on wifi state 36 # change. 37 SHORT_TIMEOUT = 30 38 39 # The currently supported devices that existed before release 40 #TODO: (navtejsingh) Need to clean up the below lists going forward 41 K_DEVICES = ["hammerhead", "razor", "razorg"] 42 L_DEVICES = ["shamu", "ryu"] 43 L_TAP_DEVICES = ["volantis", "volantisg"] 44 M_DEVICES = ["angler"] 45 46 # Speed of light in m/s. 47 SPEED_OF_LIGHT = 299792458 48 49 DEFAULT_PING_ADDR = "http://www.google.com/robots.txt" 50 51 52 class WifiEnums(): 53 54 SSID_KEY = "SSID" 55 NETID_KEY = "network_id" 56 BSSID_KEY = "BSSID" 57 PWD_KEY = "password" 58 frequency_key = "frequency" 59 APBAND_KEY = "apBand" 60 61 WIFI_CONFIG_APBAND_2G = 0 62 WIFI_CONFIG_APBAND_5G = 1 63 64 WIFI_WPS_INFO_PBC = 0 65 WIFI_WPS_INFO_DISPLAY = 1 66 WIFI_WPS_INFO_KEYPAD = 2 67 WIFI_WPS_INFO_LABEL = 3 68 WIFI_WPS_INFO_INVALID = 4 69 70 class CountryCode(): 71 CHINA = "CN" 72 JAPAN = "JP" 73 UK = "GB" 74 US = "US" 75 UNKNOWN = "UNKNOWN" 76 77 # Start of Macros for EAP 78 # EAP types 79 class Eap(IntEnum): 80 NONE = -1 81 PEAP = 0 82 TLS = 1 83 TTLS = 2 84 PWD = 3 85 SIM = 4 86 AKA = 5 87 AKA_PRIME = 6 88 UNAUTH_TLS = 7 89 90 # EAP Phase2 types 91 class EapPhase2(IntEnum): 92 NONE = 0 93 PAP = 1 94 MSCHAP = 2 95 MSCHAPV2 = 3 96 GTC = 4 97 98 class Enterprise: 99 # Enterprise Config Macros 100 EMPTY_VALUE = "NULL" 101 EAP = "eap" 102 PHASE2 = "phase2" 103 IDENTITY = "identity" 104 ANON_IDENTITY = "anonymous_identity" 105 PASSWORD = "password" 106 SUBJECT_MATCH = "subject_match" 107 ALTSUBJECT_MATCH = "altsubject_match" 108 DOM_SUFFIX_MATCH = "domain_suffix_match" 109 CLIENT_CERT = "client_cert" 110 CA_CERT = "ca_cert" 111 ENGINE = "engine" 112 ENGINE_ID = "engine_id" 113 PRIVATE_KEY_ID = "key_id" 114 REALM = "realm" 115 PLMN = "plmn" 116 FQDN = "FQDN" 117 FRIENDLY_NAME = "providerFriendlyName" 118 ROAMING_IDS = "roamingConsortiumIds" 119 # End of Macros for EAP 120 121 # Macros for wifi p2p. 122 WIFI_P2P_SERVICE_TYPE_ALL = 0 123 WIFI_P2P_SERVICE_TYPE_BONJOUR = 1 124 WIFI_P2P_SERVICE_TYPE_UPNP = 2 125 WIFI_P2P_SERVICE_TYPE_VENDOR_SPECIFIC = 255 126 127 class ScanResult: 128 CHANNEL_WIDTH_20MHZ = 0 129 CHANNEL_WIDTH_40MHZ = 1 130 CHANNEL_WIDTH_80MHZ = 2 131 CHANNEL_WIDTH_160MHZ = 3 132 CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 4 133 134 # Macros for wifi rtt. 135 class RttType(IntEnum): 136 TYPE_ONE_SIDED = 1 137 TYPE_TWO_SIDED = 2 138 139 class RttPeerType(IntEnum): 140 PEER_TYPE_AP = 1 141 PEER_TYPE_STA = 2 # Requires NAN. 142 PEER_P2P_GO = 3 143 PEER_P2P_CLIENT = 4 144 PEER_NAN = 5 145 146 class RttPreamble(IntEnum): 147 PREAMBLE_LEGACY = 0x01 148 PREAMBLE_HT = 0x02 149 PREAMBLE_VHT = 0x04 150 151 class RttBW(IntEnum): 152 BW_5_SUPPORT = 0x01 153 BW_10_SUPPORT = 0x02 154 BW_20_SUPPORT = 0x04 155 BW_40_SUPPORT = 0x08 156 BW_80_SUPPORT = 0x10 157 BW_160_SUPPORT = 0x20 158 159 class Rtt(IntEnum): 160 STATUS_SUCCESS = 0 161 STATUS_FAILURE = 1 162 STATUS_FAIL_NO_RSP = 2 163 STATUS_FAIL_REJECTED = 3 164 STATUS_FAIL_NOT_SCHEDULED_YET = 4 165 STATUS_FAIL_TM_TIMEOUT = 5 166 STATUS_FAIL_AP_ON_DIFF_CHANNEL = 6 167 STATUS_FAIL_NO_CAPABILITY = 7 168 STATUS_ABORTED = 8 169 STATUS_FAIL_INVALID_TS = 9 170 STATUS_FAIL_PROTOCOL = 10 171 STATUS_FAIL_SCHEDULE = 11 172 STATUS_FAIL_BUSY_TRY_LATER = 12 173 STATUS_INVALID_REQ = 13 174 STATUS_NO_WIFI = 14 175 STATUS_FAIL_FTM_PARAM_OVERRIDE = 15 176 177 REASON_UNSPECIFIED = -1 178 REASON_NOT_AVAILABLE = -2 179 REASON_INVALID_LISTENER = -3 180 REASON_INVALID_REQUEST = -4 181 182 class RttParam: 183 device_type = "deviceType" 184 request_type = "requestType" 185 BSSID = "bssid" 186 channel_width = "channelWidth" 187 frequency = "frequency" 188 center_freq0 = "centerFreq0" 189 center_freq1 = "centerFreq1" 190 number_burst = "numberBurst" 191 interval = "interval" 192 num_samples_per_burst = "numSamplesPerBurst" 193 num_retries_per_measurement_frame = "numRetriesPerMeasurementFrame" 194 num_retries_per_FTMR = "numRetriesPerFTMR" 195 lci_request = "LCIRequest" 196 lcr_request = "LCRRequest" 197 burst_timeout = "burstTimeout" 198 preamble = "preamble" 199 bandwidth = "bandwidth" 200 margin = "margin" 201 202 RTT_MARGIN_OF_ERROR = { 203 RttBW.BW_80_SUPPORT: 2, 204 RttBW.BW_40_SUPPORT: 5, 205 RttBW.BW_20_SUPPORT: 5 206 } 207 208 # Macros as specified in the WifiScanner code. 209 WIFI_BAND_UNSPECIFIED = 0 # not specified 210 WIFI_BAND_24_GHZ = 1 # 2.4 GHz band 211 WIFI_BAND_5_GHZ = 2 # 5 GHz band without DFS channels 212 WIFI_BAND_5_GHZ_DFS_ONLY = 4 # 5 GHz band with DFS channels 213 WIFI_BAND_5_GHZ_WITH_DFS = 6 # 5 GHz band with DFS channels 214 WIFI_BAND_BOTH = 3 # both bands without DFS channels 215 WIFI_BAND_BOTH_WITH_DFS = 7 # both bands with DFS channels 216 217 REPORT_EVENT_AFTER_BUFFER_FULL = 0 218 REPORT_EVENT_AFTER_EACH_SCAN = 1 219 REPORT_EVENT_FULL_SCAN_RESULT = 2 220 221 # US Wifi frequencies 222 ALL_2G_FREQUENCIES = [2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 223 2457, 2462] 224 DFS_5G_FREQUENCIES = [5260, 5280, 5300, 5320, 5500, 5520, 5540, 5560, 5580, 225 5600, 5620, 5640, 5660, 5680, 5700, 5720] 226 NONE_DFS_5G_FREQUENCIES = [5180, 5200, 5220, 5240, 5745, 5765, 5785, 5805, 227 5825] 228 ALL_5G_FREQUENCIES = DFS_5G_FREQUENCIES + NONE_DFS_5G_FREQUENCIES 229 230 band_to_frequencies = { 231 WIFI_BAND_24_GHZ: ALL_2G_FREQUENCIES, 232 WIFI_BAND_5_GHZ: NONE_DFS_5G_FREQUENCIES, 233 WIFI_BAND_5_GHZ_DFS_ONLY: DFS_5G_FREQUENCIES, 234 WIFI_BAND_5_GHZ_WITH_DFS: ALL_5G_FREQUENCIES, 235 WIFI_BAND_BOTH: ALL_2G_FREQUENCIES + NONE_DFS_5G_FREQUENCIES, 236 WIFI_BAND_BOTH_WITH_DFS: ALL_5G_FREQUENCIES + ALL_2G_FREQUENCIES 237 } 238 239 # All Wifi frequencies to channels lookup. 240 freq_to_channel = { 241 2412: 1, 242 2417: 2, 243 2422: 3, 244 2427: 4, 245 2432: 5, 246 2437: 6, 247 2442: 7, 248 2447: 8, 249 2452: 9, 250 2457: 10, 251 2462: 11, 252 2467: 12, 253 2472: 13, 254 2484: 14, 255 4915: 183, 256 4920: 184, 257 4925: 185, 258 4935: 187, 259 4940: 188, 260 4945: 189, 261 4960: 192, 262 4980: 196, 263 5035: 7, 264 5040: 8, 265 5045: 9, 266 5055: 11, 267 5060: 12, 268 5080: 16, 269 5170: 34, 270 5180: 36, 271 5190: 38, 272 5200: 40, 273 5210: 42, 274 5220: 44, 275 5230: 46, 276 5240: 48, 277 5260: 52, 278 5280: 56, 279 5300: 60, 280 5320: 64, 281 5500: 100, 282 5520: 104, 283 5540: 108, 284 5560: 112, 285 5580: 116, 286 5600: 120, 287 5620: 124, 288 5640: 128, 289 5660: 132, 290 5680: 136, 291 5700: 140, 292 5745: 149, 293 5765: 153, 294 5785: 157, 295 5805: 161, 296 5825: 165, 297 } 298 299 # All Wifi channels to frequencies lookup. 300 channel_2G_to_freq = { 301 1: 2412, 302 2: 2417, 303 3: 2422, 304 4: 2427, 305 5: 2432, 306 6: 2437, 307 7: 2442, 308 8: 2447, 309 9: 2452, 310 10: 2457, 311 11: 2462, 312 12: 2467, 313 13: 2472, 314 14: 2484 315 } 316 317 channel_5G_to_freq = { 318 183: 4915, 319 184: 4920, 320 185: 4925, 321 187: 4935, 322 188: 4940, 323 189: 4945, 324 192: 4960, 325 196: 4980, 326 7: 5035, 327 8: 5040, 328 9: 5045, 329 11: 5055, 330 12: 5060, 331 16: 5080, 332 34: 5170, 333 36: 5180, 334 38: 5190, 335 40: 5200, 336 42: 5210, 337 44: 5220, 338 46: 5230, 339 48: 5240, 340 52: 5260, 341 56: 5280, 342 60: 5300, 343 64: 5320, 344 100: 5500, 345 104: 5520, 346 108: 5540, 347 112: 5560, 348 116: 5580, 349 120: 5600, 350 124: 5620, 351 128: 5640, 352 132: 5660, 353 136: 5680, 354 140: 5700, 355 149: 5745, 356 153: 5765, 357 157: 5785, 358 161: 5805, 359 165: 5825 360 } 361 362 363 class WifiChannelBase: 364 ALL_2G_FREQUENCIES = [] 365 DFS_5G_FREQUENCIES = [] 366 NONE_DFS_5G_FREQUENCIES = [] 367 ALL_5G_FREQUENCIES = DFS_5G_FREQUENCIES + NONE_DFS_5G_FREQUENCIES 368 MIX_CHANNEL_SCAN = [] 369 370 def band_to_freq(self, band): 371 _band_to_frequencies = { 372 WifiEnums.WIFI_BAND_24_GHZ: self.ALL_2G_FREQUENCIES, 373 WifiEnums.WIFI_BAND_5_GHZ: self.NONE_DFS_5G_FREQUENCIES, 374 WifiEnums.WIFI_BAND_5_GHZ_DFS_ONLY: self.DFS_5G_FREQUENCIES, 375 WifiEnums.WIFI_BAND_5_GHZ_WITH_DFS: self.ALL_5G_FREQUENCIES, 376 WifiEnums.WIFI_BAND_BOTH: 377 self.ALL_2G_FREQUENCIES + self.NONE_DFS_5G_FREQUENCIES, 378 WifiEnums.WIFI_BAND_BOTH_WITH_DFS: 379 self.ALL_5G_FREQUENCIES + self.ALL_2G_FREQUENCIES 380 } 381 return _band_to_frequencies[band] 382 383 384 class WifiChannelUS(WifiChannelBase): 385 # US Wifi frequencies 386 ALL_2G_FREQUENCIES = [2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 387 2457, 2462] 388 NONE_DFS_5G_FREQUENCIES = [5180, 5200, 5220, 5240, 5745, 5765, 5785, 5805, 389 5825] 390 MIX_CHANNEL_SCAN = [2412, 2437, 2462, 5180, 5200, 5280, 5260, 5300, 5500, 391 5320, 5520, 5560, 5700, 5745, 5805] 392 393 def __init__(self, model=None): 394 if model and utils.trim_model_name(model) in K_DEVICES: 395 self.DFS_5G_FREQUENCIES = [] 396 self.ALL_5G_FREQUENCIES = self.NONE_DFS_5G_FREQUENCIES 397 self.MIX_CHANNEL_SCAN = [2412, 2437, 2462, 5180, 5200, 5240, 5745, 398 5765] 399 elif model and utils.trim_model_name(model) in L_DEVICES: 400 self.DFS_5G_FREQUENCIES = [5260, 5280, 5300, 5320, 5500, 5520, 401 5540, 5560, 5580, 5660, 5680, 5700] 402 self.ALL_5G_FREQUENCIES = self.DFS_5G_FREQUENCIES + self.NONE_DFS_5G_FREQUENCIES 403 elif model and utils.trim_model_name(model) in L_TAP_DEVICES: 404 self.DFS_5G_FREQUENCIES = [5260, 5280, 5300, 5320, 5500, 5520, 405 5540, 5560, 5580, 5660, 5680, 5700, 406 5720] 407 self.ALL_5G_FREQUENCIES = self.DFS_5G_FREQUENCIES + self.NONE_DFS_5G_FREQUENCIES 408 elif model and utils.trim_model_name(model) in M_DEVICES: 409 self.DFS_5G_FREQUENCIES = [5260, 5280, 5300, 5320, 5500, 5520, 410 5540, 5560, 5580, 5600, 5620, 5640, 411 5660, 5680, 5700] 412 self.ALL_5G_FREQUENCIES = self.DFS_5G_FREQUENCIES + self.NONE_DFS_5G_FREQUENCIES 413 else: 414 self.DFS_5G_FREQUENCIES = [5260, 5280, 5300, 5320, 5500, 5520, 415 5540, 5560, 5580, 5600, 5620, 5640, 416 5660, 5680, 5700, 5720] 417 self.ALL_5G_FREQUENCIES = self.DFS_5G_FREQUENCIES + self.NONE_DFS_5G_FREQUENCIES 418 419 class WifiReferenceNetworks: 420 """ Class to parse and return networks of different band and 421 auth type from reference_networks 422 """ 423 def __init__(self, obj): 424 self.reference_networks = obj 425 self.WIFI_2G = "2g" 426 self.WIFI_5G = "5g" 427 428 self.secure_networks_2g = [] 429 self.secure_networks_5g = [] 430 self.open_networks_2g = [] 431 self.open_networks_5g = [] 432 self._parse_networks() 433 434 def _parse_networks(self): 435 for network in self.reference_networks: 436 for key in network: 437 if key == self.WIFI_2G: 438 if "password" in network[key]: 439 self.secure_networks_2g.append(network[key]) 440 else: 441 self.open_networks_2g.append(network[key]) 442 else: 443 if "password" in network[key]: 444 self.secure_networks_5g.append(network[key]) 445 else: 446 self.open_networks_5g.append(network[key]) 447 448 def return_2g_secure_networks(self): 449 return self.secure_networks_2g 450 451 def return_5g_secure_networks(self): 452 return self.secure_networks_5g 453 454 def return_2g_open_networks(self): 455 return self.open_networks_2g 456 457 def return_5g_open_networks(self): 458 return self.open_networks_5g 459 460 def return_secure_networks(self): 461 return self.secure_networks_2g + self.secure_networks_5g 462 463 def return_open_networks(self): 464 return self.open_networks_2g + self.open_networks_5g 465 466 467 def _assert_on_fail_handler(func, assert_on_fail, *args, **kwargs): 468 """Wrapper function that handles the bahevior of assert_on_fail. 469 470 When assert_on_fail is True, let all test signals through, which can 471 terminate test cases directly. When assert_on_fail is False, the wrapper 472 raises no test signals and reports operation status by returning True or 473 False. 474 475 Args: 476 func: The function to wrap. This function reports operation status by 477 raising test signals. 478 assert_on_fail: A boolean that specifies if the output of the wrapper 479 is test signal based or return value based. 480 args: Positional args for func. 481 kwargs: Name args for func. 482 483 Returns: 484 If assert_on_fail is True, returns True/False to signal operation 485 status, otherwise return nothing. 486 """ 487 try: 488 func(*args, **kwargs) 489 if not assert_on_fail: 490 return True 491 except signals.TestSignal: 492 if assert_on_fail: 493 raise 494 return False 495 496 497 def assert_network_in_list(target, network_list): 498 """Makes sure a specified target Wi-Fi network exists in a list of Wi-Fi 499 networks. 500 501 Args: 502 target: A dict representing a Wi-Fi network. 503 E.g. {WifiEnums.SSID_KEY: "SomeNetwork"} 504 network_list: A list of dicts, each representing a Wi-Fi network. 505 """ 506 match_results = match_networks(target, network_list) 507 asserts.assert_true( 508 match_results, "Target network %s, does not exist in network list %s" % 509 (target, network_list)) 510 511 512 def match_networks(target_params, networks): 513 """Finds the WiFi networks that match a given set of parameters in a list 514 of WiFi networks. 515 516 To be considered a match, the network should contain every key-value pair 517 of target_params 518 519 Args: 520 target_params: A dict with 1 or more key-value pairs representing a Wi-Fi network. 521 E.g { 'SSID': 'wh_ap1_5g', 'BSSID': '30:b5:c2:33:e4:47' } 522 networks: A list of dict objects representing WiFi networks. 523 524 Returns: 525 The networks that match the target parameters. 526 """ 527 results = [] 528 asserts.assert_true(target_params, 529 "Expected networks object 'target_params' is empty") 530 for n in networks: 531 add_network = 1 532 for k, v in target_params.items(): 533 if k not in n: 534 add_network = 0 535 break 536 if n[k] != v: 537 add_network = 0 538 break 539 if add_network: 540 results.append(n) 541 return results 542 543 544 def wifi_toggle_state(ad, new_state=None, assert_on_fail=True): 545 """Toggles the state of wifi. 546 547 Args: 548 ad: An AndroidDevice object. 549 new_state: Wifi state to set to. If None, opposite of the current state. 550 assert_on_fail: If True, error checks in this function will raise test 551 failure signals. 552 553 Returns: 554 If assert_on_fail is False, function returns True if the toggle was 555 successful, False otherwise. If assert_on_fail is True, no return value. 556 """ 557 return _assert_on_fail_handler( 558 _wifi_toggle_state, assert_on_fail, ad, new_state=new_state) 559 560 561 def _wifi_toggle_state(ad, new_state=None): 562 """Toggles the state of wifi. 563 564 TestFailure signals are raised when something goes wrong. 565 566 Args: 567 ad: An AndroidDevice object. 568 new_state: The state to set Wi-Fi to. If None, opposite of the current 569 state will be set. 570 """ 571 if new_state is None: 572 new_state = not ad.droid.wifiCheckState() 573 elif new_state == ad.droid.wifiCheckState(): 574 # Check if the new_state is already achieved, so we don't wait for the 575 # state change event by mistake. 576 return 577 ad.droid.wifiStartTrackingStateChange() 578 ad.log.info("Setting Wi-Fi state to %s.", new_state) 579 # Setting wifi state. 580 ad.droid.wifiToggleState(new_state) 581 fail_msg = "Failed to set Wi-Fi state to %s on %s." % (new_state, 582 ad.serial) 583 try: 584 event = ad.ed.pop_event(wifi_constants.SUPPLICANT_CON_CHANGED, 585 SHORT_TIMEOUT) 586 asserts.assert_equal(event['data']['Connected'], new_state, fail_msg) 587 except Empty: 588 # Supplicant connection event is not always reliable. We double check 589 # here and call it a success as long as the new state equals the 590 # expected state. 591 time.sleep(5) 592 asserts.assert_equal(new_state, ad.droid.wifiCheckState(), fail_msg) 593 finally: 594 ad.droid.wifiStopTrackingStateChange() 595 596 597 def reset_wifi(ad): 598 """Clears all saved Wi-Fi networks on a device. 599 600 This will turn Wi-Fi on. 601 602 Args: 603 ad: An AndroidDevice object. 604 605 """ 606 # TODO(gmoturu): need to remove wifi_toggle_state() in reset_wifi() when 607 # bug: 32809235 is fixed 608 wifi_toggle_state(ad, True) 609 networks = ad.droid.wifiGetConfiguredNetworks() 610 if not networks: 611 return 612 for n in networks: 613 ad.droid.wifiForgetNetwork(n['networkId']) 614 try: 615 event = ad.ed.pop_event(wifi_constants.WIFI_FORGET_NW_SUCCESS, 616 SHORT_TIMEOUT) 617 except Empty: 618 logging.warning("Could not confirm the removal of network %s.", n) 619 # Check again to see if there's any network left. 620 asserts.assert_true( 621 not ad.droid.wifiGetConfiguredNetworks(), 622 "Failed to remove these configured Wi-Fi networks: %s" % networks) 623 624 625 def toggle_airplane_mode_on_and_off(ad): 626 """Turn ON and OFF Airplane mode. 627 628 ad: An AndroidDevice object. 629 Returns: Assert if turning on/off Airplane mode fails. 630 631 """ 632 ad.log.debug("Toggling Airplane mode ON.") 633 asserts.assert_true( 634 utils.force_airplane_mode(ad, True), 635 "Can not turn on airplane mode on: %s" % ad.serial) 636 time.sleep(DEFAULT_TIMEOUT) 637 ad.log.debug("Toggling Airplane mode OFF.") 638 asserts.assert_true( 639 utils.force_airplane_mode(ad, False), 640 "Can not turn on airplane mode on: %s" % ad.serial) 641 time.sleep(DEFAULT_TIMEOUT) 642 643 644 def toggle_wifi_off_and_on(ad): 645 """Turn OFF and ON WiFi. 646 647 ad: An AndroidDevice object. 648 Returns: Assert if turning off/on WiFi fails. 649 650 """ 651 ad.log.debug("Toggling wifi OFF.") 652 wifi_toggle_state(ad, False) 653 time.sleep(DEFAULT_TIMEOUT) 654 ad.log.debug("Toggling wifi ON.") 655 wifi_toggle_state(ad, True) 656 time.sleep(DEFAULT_TIMEOUT) 657 658 659 def wifi_forget_network(ad, net_ssid): 660 """Remove configured Wifi network on an android device. 661 662 Args: 663 ad: android_device object for forget network. 664 net_ssid: ssid of network to be forget 665 666 """ 667 ad.droid.wifiToggleState(True) 668 networks = ad.droid.wifiGetConfiguredNetworks() 669 if not networks: 670 return 671 for n in networks: 672 if net_ssid in n[WifiEnums.SSID_KEY]: 673 ad.droid.wifiForgetNetwork(n['networkId']) 674 try: 675 event = ad.ed.pop_event(wifi_constants.WIFI_FORGET_NW_SUCCESS, 676 SHORT_TIMEOUT) 677 except Empty: 678 asserts.fail("Failed to remove network %s." % n) 679 680 681 def wifi_test_device_init(ad): 682 """Initializes an android device for wifi testing. 683 684 0. Make sure SL4A connection is established on the android device. 685 1. Disable location service's WiFi scan. 686 2. Turn WiFi on. 687 3. Clear all saved networks. 688 4. Set country code to US. 689 5. Enable WiFi verbose logging. 690 6. Sync device time with computer time. 691 7. Turn off cellular data. 692 8. Turn off ambient display. 693 """ 694 utils.require_sl4a((ad, )) 695 ad.droid.wifiScannerToggleAlwaysAvailable(False) 696 msg = "Failed to turn off location service's scan." 697 asserts.assert_true(not ad.droid.wifiScannerIsAlwaysAvailable(), msg) 698 wifi_toggle_state(ad, True) 699 reset_wifi(ad) 700 ad.droid.wifiEnableVerboseLogging(1) 701 msg = "Failed to enable WiFi verbose logging." 702 asserts.assert_equal(ad.droid.wifiGetVerboseLoggingLevel(), 1, msg) 703 # We don't verify the following settings since they are not critical. 704 # Set wpa_supplicant log level to EXCESSIVE. 705 output = ad.adb.shell("wpa_cli -i wlan0 -p -g@android:wpa_wlan0 IFNAME=" 706 "wlan0 log_level EXCESSIVE") 707 ad.log.info("wpa_supplicant log change status: %s", output) 708 utils.sync_device_time(ad) 709 ad.droid.telephonyToggleDataConnection(False) 710 # TODO(angli): need to verify the country code was actually set. No generic 711 # way to check right now. 712 ad.adb.shell("halutil -country %s" % WifiEnums.CountryCode.US) 713 utils.set_ambient_display(ad, False) 714 715 716 def start_wifi_connection_scan(ad): 717 """Starts a wifi connection scan and wait for results to become available. 718 719 Args: 720 ad: An AndroidDevice object. 721 """ 722 ad.droid.wifiStartScan() 723 try: 724 ad.ed.pop_event("WifiManagerScanResultsAvailable", 60) 725 except Empty: 726 asserts.fail("Wi-Fi results did not become available within 60s.") 727 728 729 def start_wifi_background_scan(ad, scan_setting): 730 """Starts wifi background scan. 731 732 Args: 733 ad: android_device object to initiate connection on. 734 scan_setting: A dict representing the settings of the scan. 735 736 Returns: 737 If scan was started successfully, event data of success event is returned. 738 """ 739 idx = ad.droid.wifiScannerStartBackgroundScan(scan_setting) 740 event = ad.ed.pop_event("WifiScannerScan{}onSuccess".format(idx), 741 SHORT_TIMEOUT) 742 return event['data'] 743 744 745 def start_wifi_tethering(ad, ssid, password, band=None): 746 """Starts wifi tethering on an android_device. 747 748 Args: 749 ad: android_device to start wifi tethering on. 750 ssid: The SSID the soft AP should broadcast. 751 password: The password the soft AP should use. 752 band: The band the soft AP should be set on. It should be either 753 WifiEnums.WIFI_CONFIG_APBAND_2G or WifiEnums.WIFI_CONFIG_APBAND_5G. 754 755 Returns: 756 No return value. Error checks in this function will raise test failure signals 757 """ 758 config = {WifiEnums.SSID_KEY: ssid} 759 if password: 760 config[WifiEnums.PWD_KEY] = password 761 if band: 762 config[WifiEnums.APBAND_KEY] = band 763 asserts.assert_true( 764 ad.droid.wifiSetWifiApConfiguration(config), 765 "Failed to update WifiAp Configuration") 766 ad.droid.wifiStartTrackingTetherStateChange() 767 ad.droid.connectivityStartTethering(tel_defines.TETHERING_WIFI, False) 768 try: 769 ad.ed.pop_event("ConnectivityManagerOnTetheringStarted") 770 ad.ed.wait_for_event("TetherStateChanged", 771 lambda x: x["data"]["ACTIVE_TETHER"], 30) 772 ad.log.debug("Tethering started successfully.") 773 except Empty: 774 msg = "Failed to receive confirmation of wifi tethering starting" 775 asserts.fail(msg) 776 finally: 777 ad.droid.wifiStopTrackingTetherStateChange() 778 779 780 def stop_wifi_tethering(ad): 781 """Stops wifi tethering on an android_device. 782 783 Args: 784 ad: android_device to stop wifi tethering on. 785 """ 786 ad.droid.wifiStartTrackingTetherStateChange() 787 ad.droid.connectivityStopTethering(tel_defines.TETHERING_WIFI) 788 ad.droid.wifiSetApEnabled(False, None) 789 try: 790 ad.ed.pop_event("WifiManagerApDisabled", 30) 791 ad.ed.wait_for_event("TetherStateChanged", 792 lambda x: not x["data"]["ACTIVE_TETHER"], 30) 793 except Empty: 794 msg = "Failed to receive confirmation of wifi tethering stopping" 795 asserts.fail(msg) 796 finally: 797 ad.droid.wifiStopTrackingTetherStateChange() 798 799 800 def toggle_wifi_and_wait_for_reconnection(ad, 801 network, 802 num_of_tries=1, 803 assert_on_fail=True): 804 """Toggle wifi state and then wait for Android device to reconnect to 805 the provided wifi network. 806 807 This expects the device to be already connected to the provided network. 808 809 Logic steps are 810 1. Ensure that we're connected to the network. 811 2. Turn wifi off. 812 3. Wait for 10 seconds. 813 4. Turn wifi on. 814 5. Wait for the "connected" event, then confirm the connected ssid is the 815 one requested. 816 817 Args: 818 ad: android_device object to initiate connection on. 819 network: A dictionary representing the network to await connection. The 820 dictionary must have the key "SSID". 821 num_of_tries: An integer that is the number of times to try before 822 delaring failure. Default is 1. 823 assert_on_fail: If True, error checks in this function will raise test 824 failure signals. 825 826 Returns: 827 If assert_on_fail is False, function returns True if the toggle was 828 successful, False otherwise. If assert_on_fail is True, no return value. 829 """ 830 return _assert_on_fail_handler( 831 _toggle_wifi_and_wait_for_reconnection, 832 assert_on_fail, 833 ad, 834 network, 835 num_of_tries=num_of_tries) 836 837 838 def _toggle_wifi_and_wait_for_reconnection(ad, network, num_of_tries=1): 839 """Toggle wifi state and then wait for Android device to reconnect to 840 the provided wifi network. 841 842 This expects the device to be already connected to the provided network. 843 844 Logic steps are 845 1. Ensure that we're connected to the network. 846 2. Turn wifi off. 847 3. Wait for 10 seconds. 848 4. Turn wifi on. 849 5. Wait for the "connected" event, then confirm the connected ssid is the 850 one requested. 851 852 This will directly fail a test if anything goes wrong. 853 854 Args: 855 ad: android_device object to initiate connection on. 856 network: A dictionary representing the network to await connection. The 857 dictionary must have the key "SSID". 858 num_of_tries: An integer that is the number of times to try before 859 delaring failure. Default is 1. 860 """ 861 expected_ssid = network[WifiEnums.SSID_KEY] 862 # First ensure that we're already connected to the provided network. 863 verify_con = {WifiEnums.SSID_KEY: expected_ssid} 864 verify_wifi_connection_info(ad, verify_con) 865 # Now toggle wifi state and wait for the connection event. 866 wifi_toggle_state(ad, False) 867 time.sleep(10) 868 wifi_toggle_state(ad, True) 869 ad.droid.wifiStartTrackingStateChange() 870 try: 871 connect_result = None 872 for i in range(num_of_tries): 873 try: 874 connect_result = ad.ed.pop_event(wifi_constants.WIFI_CONNECTED, 875 30) 876 break 877 except Empty: 878 pass 879 asserts.assert_true(connect_result, 880 "Failed to connect to Wi-Fi network %s on %s" % 881 (network, ad.serial)) 882 logging.debug("Connection result on %s: %s.", ad.serial, 883 connect_result) 884 actual_ssid = connect_result['data'][WifiEnums.SSID_KEY] 885 asserts.assert_equal(actual_ssid, expected_ssid, 886 "Connected to the wrong network on %s." 887 "Expected %s, but got %s." % 888 (ad.serial, expected_ssid, actual_ssid)) 889 logging.info("Connected to Wi-Fi network %s on %s", actual_ssid, 890 ad.serial) 891 finally: 892 ad.droid.wifiStopTrackingStateChange() 893 894 895 def wait_for_connect(ad, ssid=None, id=None, tries=1): 896 """Wait for a connect event on queue and pop when available. 897 898 Args: 899 ad: An Android device object. 900 ssid: SSID of the network to connect to. 901 id: Network Id of the network to connect to. 902 tries: An integer that is the number of times to try before failing. 903 904 Returns: 905 A dict with details of the connection data, which looks like this: 906 { 907 'time': 1485460337798, 908 'name': 'WifiNetworkConnected', 909 'data': { 910 'rssi': -27, 911 'is_24ghz': True, 912 'mac_address': '02:00:00:00:00:00', 913 'network_id': 1, 914 'BSSID': '30:b5:c2:33:d3:fc', 915 'ip_address': 117483712, 916 'link_speed': 54, 917 'supplicant_state': 'completed', 918 'hidden_ssid': False, 919 'SSID': 'wh_ap1_2g', 920 'is_5ghz': False} 921 } 922 923 """ 924 conn_result = None 925 926 # If ssid and network id is None, just wait for any connect event. 927 if id is None and ssid is None: 928 for i in range(tries): 929 try: 930 conn_result = ad.ed.pop_event(wifi_constants.WIFI_CONNECTED, 30) 931 break 932 except Empty: 933 pass 934 else: 935 # If ssid or network id is specified, wait for specific connect event. 936 for i in range(tries): 937 try: 938 conn_result = ad.ed.pop_event(wifi_constants.WIFI_CONNECTED, 30) 939 if id and conn_result['data'][WifiEnums.NETID_KEY] == id: 940 break 941 elif ssid and conn_result['data'][WifiEnums.SSID_KEY] == ssid: 942 break 943 except Empty: 944 pass 945 946 return conn_result 947 948 949 def wait_for_disconnect(ad): 950 """Wait for a Disconnect event from the supplicant. 951 952 Args: 953 ad: Android device object. 954 955 """ 956 try: 957 ad.droid.wifiStartTrackingStateChange() 958 event = ad.ed.pop_event("WifiNetworkDisconnected", 10) 959 ad.droid.wifiStopTrackingStateChange() 960 except queue.Empty: 961 raise signals.TestFailure("Device did not disconnect from the network") 962 963 964 def wifi_connect(ad, network, num_of_tries=1, assert_on_fail=True): 965 """Connect an Android device to a wifi network. 966 967 Initiate connection to a wifi network, wait for the "connected" event, then 968 confirm the connected ssid is the one requested. 969 970 This will directly fail a test if anything goes wrong. 971 972 Args: 973 ad: android_device object to initiate connection on. 974 network: A dictionary representing the network to connect to. The 975 dictionary must have the key "SSID". 976 num_of_tries: An integer that is the number of times to try before 977 delaring failure. Default is 1. 978 assert_on_fail: If True, error checks in this function will raise test 979 failure signals. 980 981 Returns: 982 Returns a value only if assert_on_fail is false. 983 Returns True if the connection was successful, False otherwise. 984 """ 985 return _assert_on_fail_handler( 986 _wifi_connect, assert_on_fail, ad, network, num_of_tries=num_of_tries) 987 988 989 def _wifi_connect(ad, network, num_of_tries=1): 990 """Connect an Android device to a wifi network. 991 992 Initiate connection to a wifi network, wait for the "connected" event, then 993 confirm the connected ssid is the one requested. 994 995 This will directly fail a test if anything goes wrong. 996 997 Args: 998 ad: android_device object to initiate connection on. 999 network: A dictionary representing the network to connect to. The 1000 dictionary must have the key "SSID". 1001 num_of_tries: An integer that is the number of times to try before 1002 delaring failure. Default is 1. 1003 """ 1004 asserts.assert_true(WifiEnums.SSID_KEY in network, 1005 "Key '%s' must be present in network definition." % 1006 WifiEnums.SSID_KEY) 1007 ad.droid.wifiStartTrackingStateChange() 1008 expected_ssid = network[WifiEnums.SSID_KEY] 1009 ad.droid.wifiConnectByConfig(network) 1010 ad.log.info("Starting connection process to %s", expected_ssid) 1011 try: 1012 event = ad.ed.pop_event(wifi_constants.CONNECT_BY_CONFIG_SUCCESS, 30) 1013 connect_result = wait_for_connect(ad, ssid=expected_ssid, tries=num_of_tries) 1014 asserts.assert_true(connect_result, 1015 "Failed to connect to Wi-Fi network %s on %s" % 1016 (network, ad.serial)) 1017 ad.log.debug("Wi-Fi connection result: %s.", connect_result) 1018 actual_ssid = connect_result['data'][WifiEnums.SSID_KEY] 1019 asserts.assert_equal(actual_ssid, expected_ssid, 1020 "Connected to the wrong network on %s." % 1021 ad.serial) 1022 ad.log.info("Connected to Wi-Fi network %s.", actual_ssid) 1023 1024 # Wait for data connection to stabilize. 1025 time.sleep(5) 1026 1027 internet = validate_connection(ad, DEFAULT_PING_ADDR) 1028 if not internet: 1029 raise signals.TestFailure("Failed to connect to internet on %s" % 1030 expected_ssid) 1031 except Empty: 1032 asserts.fail("Failed to start connection process to %s on %s" % 1033 (network, ad.serial)) 1034 except Exception as error: 1035 ad.log.error("Failed to connect to %s with error %s", expected_ssid, 1036 error) 1037 raise signals.TestFailure("Failed to connect to %s network" % network) 1038 1039 finally: 1040 ad.droid.wifiStopTrackingStateChange() 1041 1042 1043 def wifi_connect_by_id(ad, network_id, num_of_tries=3, assert_on_fail=True): 1044 """Connect an Android device to a wifi network using network Id. 1045 1046 Start connection to the wifi network, with the given network Id, wait for 1047 the "connected" event, then verify the connected network is the one requested. 1048 1049 This will directly fail a test if anything goes wrong. 1050 1051 Args: 1052 ad: android_device object to initiate connection on. 1053 network_id: Integer specifying the network id of the network. 1054 num_of_tries: An integer that is the number of times to try before 1055 delaring failure. Default is 1. 1056 assert_on_fail: If True, error checks in this function will raise test 1057 failure signals. 1058 1059 Returns: 1060 Returns a value only if assert_on_fail is false. 1061 Returns True if the connection was successful, False otherwise. 1062 """ 1063 _assert_on_fail_handler(_wifi_connect_by_id, assert_on_fail, ad, 1064 network_id, num_of_tries) 1065 1066 1067 def _wifi_connect_by_id(ad, network_id, num_of_tries=1): 1068 """Connect an Android device to a wifi network using it's network id. 1069 1070 Start connection to the wifi network, with the given network id, wait for 1071 the "connected" event, then verify the connected network is the one requested. 1072 1073 Args: 1074 ad: android_device object to initiate connection on. 1075 network_id: Integer specifying the network id of the network. 1076 num_of_tries: An integer that is the number of times to try before 1077 delaring failure. Default is 1. 1078 """ 1079 ad.droid.wifiStartTrackingStateChange() 1080 # Clear all previous events. 1081 ad.ed.clear_all_events() 1082 ad.droid.wifiConnectByNetworkId(network_id) 1083 ad.log.info("Starting connection to network with id %d", network_id) 1084 try: 1085 event = ad.ed.pop_event(wifi_constants.CONNECT_BY_NETID_SUCCESS, 60) 1086 connect_result = wait_for_connect(ad, id=network_id, tries=num_of_tries) 1087 asserts.assert_true(connect_result, 1088 "Failed to connect to Wi-Fi network using network id") 1089 ad.log.debug("Wi-Fi connection result: %s", connect_result) 1090 actual_id = connect_result['data'][WifiEnums.NETID_KEY] 1091 asserts.assert_equal(actual_id, network_id, 1092 "Connected to the wrong network on %s." 1093 "Expected network id = %d, but got %d." % 1094 (ad.serial, network_id, actual_id)) 1095 expected_ssid = connect_result['data'][WifiEnums.SSID_KEY] 1096 ad.log.info("Connected to Wi-Fi network %s with %d network id.", 1097 expected_ssid, network_id) 1098 1099 # Wait for data connection to stabilize. 1100 time.sleep(5) 1101 1102 internet = validate_connection(ad, DEFAULT_PING_ADDR) 1103 if not internet: 1104 raise signals.TestFailure("Failed to connect to internet on %s" % 1105 expected_ssid) 1106 except Empty: 1107 asserts.fail("Failed to connect to network with id %d on %s" % 1108 (network_id, ad.serial)) 1109 except Exception as error: 1110 ad.log.error("Failed to connect to network with id %d with error %s", 1111 network_id, error) 1112 raise signals.TestFailure("Failed to connect to network with network" 1113 " id %d" % network_id) 1114 finally: 1115 ad.droid.wifiStopTrackingStateChange() 1116 1117 1118 def wifi_passpoint_connect(ad, passpoint_network, num_of_tries=1, 1119 assert_on_fail=True): 1120 """Connect an Android device to a wifi network. 1121 1122 Initiate connection to a wifi network, wait for the "connected" event, then 1123 confirm the connected ssid is the one requested. 1124 1125 This will directly fail a test if anything goes wrong. 1126 1127 Args: 1128 ad: android_device object to initiate connection on. 1129 passpoint_network: SSID of the Passpoint network to connect to. 1130 num_of_tries: An integer that is the number of times to try before 1131 delaring failure. Default is 1. 1132 assert_on_fail: If True, error checks in this function will raise test 1133 failure signals. 1134 1135 Returns: 1136 If assert_on_fail is False, function returns network id, if the connect was 1137 successful, False otherwise. If assert_on_fail is True, no return value. 1138 """ 1139 _assert_on_fail_handler(_wifi_passpoint_connect, assert_on_fail, ad, 1140 passpoint_network, num_of_tries = num_of_tries) 1141 1142 1143 def _wifi_passpoint_connect(ad, passpoint_network, num_of_tries=1): 1144 """Connect an Android device to a wifi network. 1145 1146 Initiate connection to a wifi network, wait for the "connected" event, then 1147 confirm the connected ssid is the one requested. 1148 1149 This will directly fail a test if anything goes wrong. 1150 1151 Args: 1152 ad: android_device object to initiate connection on. 1153 passpoint_network: SSID of the Passpoint network to connect to. 1154 num_of_tries: An integer that is the number of times to try before 1155 delaring failure. Default is 1. 1156 """ 1157 ad.droid.wifiStartTrackingStateChange() 1158 expected_ssid = passpoint_network 1159 ad.log.info("Starting connection process to passpoint %s", expected_ssid) 1160 1161 try: 1162 connect_result = wait_for_connect(ad, expected_ssid, num_of_tries) 1163 asserts.assert_true(connect_result, 1164 "Failed to connect to WiFi passpoint network %s on" 1165 " %s" % (expected_ssid, ad.serial)) 1166 ad.log.info("Wi-Fi connection result: %s.", connect_result) 1167 actual_ssid = connect_result['data'][WifiEnums.SSID_KEY] 1168 asserts.assert_equal(actual_ssid, expected_ssid, 1169 "Connected to the wrong network on %s." % ad.serial) 1170 ad.log.info("Connected to Wi-Fi passpoint network %s.", actual_ssid) 1171 1172 # Wait for data connection to stabilize. 1173 time.sleep(5) 1174 1175 internet = validate_connection(ad, DEFAULT_PING_ADDR) 1176 if not internet: 1177 raise signals.TestFailure("Failed to connect to internet on %s" % 1178 expected_ssid) 1179 except Exception as error: 1180 ad.log.error("Failed to connect to passpoint network %s with error %s", 1181 expected_ssid, error) 1182 raise signals.TestFailure("Failed to connect to %s passpoint network" % 1183 expected_ssid) 1184 1185 finally: 1186 ad.droid.wifiStopTrackingStateChange() 1187 1188 1189 def delete_passpoint(ad, fqdn): 1190 """Delete a required Passpoint configuration.""" 1191 try: 1192 ad.droid.removePasspointConfig(fqdn) 1193 return True 1194 except Exception as error: 1195 ad.log.error("Failed to remove passpoint configuration with FQDN=%s " 1196 "and error=%s" , fqdn, error) 1197 return False 1198 1199 1200 def start_wifi_single_scan(ad, scan_setting): 1201 """Starts wifi single shot scan. 1202 1203 Args: 1204 ad: android_device object to initiate connection on. 1205 scan_setting: A dict representing the settings of the scan. 1206 1207 Returns: 1208 If scan was started successfully, event data of success event is returned. 1209 """ 1210 idx = ad.droid.wifiScannerStartScan(scan_setting) 1211 event = ad.ed.pop_event("WifiScannerScan%sonSuccess" % idx, SHORT_TIMEOUT) 1212 ad.log.debug("Got event %s", event) 1213 return event['data'] 1214 1215 1216 def track_connection(ad, network_ssid, check_connection_count): 1217 """Track wifi connection to network changes for given number of counts 1218 1219 Args: 1220 ad: android_device object for forget network. 1221 network_ssid: network ssid to which connection would be tracked 1222 check_connection_count: Integer for maximum number network connection 1223 check. 1224 Returns: 1225 True if connection to given network happen, else return False. 1226 """ 1227 ad.droid.wifiStartTrackingStateChange() 1228 while check_connection_count > 0: 1229 connect_network = ad.ed.pop_event("WifiNetworkConnected", 120) 1230 ad.log.info("Connected to network %s", connect_network) 1231 if (WifiEnums.SSID_KEY in connect_network['data'] and 1232 connect_network['data'][WifiEnums.SSID_KEY] == network_ssid): 1233 return True 1234 check_connection_count -= 1 1235 ad.droid.wifiStopTrackingStateChange() 1236 return False 1237 1238 1239 def get_scan_time_and_channels(wifi_chs, scan_setting, stime_channel): 1240 """Calculate the scan time required based on the band or channels in scan 1241 setting 1242 1243 Args: 1244 wifi_chs: Object of channels supported 1245 scan_setting: scan setting used for start scan 1246 stime_channel: scan time per channel 1247 1248 Returns: 1249 scan_time: time required for completing a scan 1250 scan_channels: channel used for scanning 1251 """ 1252 scan_time = 0 1253 scan_channels = [] 1254 if "band" in scan_setting and "channels" not in scan_setting: 1255 scan_channels = wifi_chs.band_to_freq(scan_setting["band"]) 1256 elif "channels" in scan_setting and "band" not in scan_setting: 1257 scan_channels = scan_setting["channels"] 1258 scan_time = len(scan_channels) * stime_channel 1259 for channel in scan_channels: 1260 if channel in WifiEnums.DFS_5G_FREQUENCIES: 1261 scan_time += 132 #passive scan time on DFS 1262 return scan_time, scan_channels 1263 1264 1265 def start_wifi_track_bssid(ad, track_setting): 1266 """Start tracking Bssid for the given settings. 1267 1268 Args: 1269 ad: android_device object. 1270 track_setting: Setting for which the bssid tracking should be started 1271 1272 Returns: 1273 If tracking started successfully, event data of success event is returned. 1274 """ 1275 idx = ad.droid.wifiScannerStartTrackingBssids( 1276 track_setting["bssidInfos"], track_setting["apLostThreshold"]) 1277 event = ad.ed.pop_event("WifiScannerBssid{}onSuccess".format(idx), 1278 SHORT_TIMEOUT) 1279 return event['data'] 1280 1281 1282 def convert_pem_key_to_pkcs8(in_file, out_file): 1283 """Converts the key file generated by us to the format required by 1284 Android using openssl. 1285 1286 The input file must have the extension "pem". The output file must 1287 have the extension "der". 1288 1289 Args: 1290 in_file: The original key file. 1291 out_file: The full path to the converted key file, including 1292 filename. 1293 """ 1294 asserts.assert_true(in_file.endswith(".pem"), "Input file has to be .pem.") 1295 asserts.assert_true( 1296 out_file.endswith(".der"), "Output file has to be .der.") 1297 cmd = ("openssl pkcs8 -inform PEM -in {} -outform DER -out {} -nocrypt" 1298 " -topk8").format(in_file, out_file) 1299 utils.exe_cmd(cmd) 1300 1301 1302 def validate_connection(ad, ping_addr): 1303 """Validate internet connection by pinging the address provided. 1304 1305 Args: 1306 ad: android_device object. 1307 ping_addr: address on internet for pinging. 1308 1309 Returns: 1310 ping output if successful, NULL otherwise. 1311 """ 1312 ping = ad.droid.httpPing(ping_addr) 1313 ad.log.info("Http ping result: %s.", ping) 1314 return ping 1315 1316 1317 #TODO(angli): This can only verify if an actual value is exactly the same. 1318 # Would be nice to be able to verify an actual value is one of serveral. 1319 def verify_wifi_connection_info(ad, expected_con): 1320 """Verifies that the information of the currently connected wifi network is 1321 as expected. 1322 1323 Args: 1324 expected_con: A dict representing expected key-value pairs for wifi 1325 connection. e.g. {"SSID": "test_wifi"} 1326 """ 1327 current_con = ad.droid.wifiGetConnectionInfo() 1328 case_insensitive = ["BSSID", "supplicant_state"] 1329 ad.log.debug("Current connection: %s", current_con) 1330 for k, expected_v in expected_con.items(): 1331 # Do not verify authentication related fields. 1332 if k == "password": 1333 continue 1334 msg = "Field %s does not exist in wifi connection info %s." % ( 1335 k, current_con) 1336 if k not in current_con: 1337 raise signals.TestFailure(msg) 1338 actual_v = current_con[k] 1339 if k in case_insensitive: 1340 actual_v = actual_v.lower() 1341 expected_v = expected_v.lower() 1342 msg = "Expected %s to be %s, actual %s is %s." % (k, expected_v, k, 1343 actual_v) 1344 if actual_v != expected_v: 1345 raise signals.TestFailure(msg) 1346 1347 1348 def expand_enterprise_config_by_phase2(config): 1349 """Take an enterprise config and generate a list of configs, each with 1350 a different phase2 auth type. 1351 1352 Args: 1353 config: A dict representing enterprise config. 1354 1355 Returns 1356 A list of enterprise configs. 1357 """ 1358 results = [] 1359 phase2_types = WifiEnums.EapPhase2 1360 if config[WifiEnums.Enterprise.EAP] == WifiEnums.Eap.PEAP: 1361 # Skip unsupported phase2 types for PEAP. 1362 phase2_types = [WifiEnums.EapPhase2.GTC, WifiEnums.EapPhase2.MSCHAPV2] 1363 for phase2_type in phase2_types: 1364 # Skip a special case for passpoint TTLS. 1365 if (WifiEnums.Enterprise.FQDN in config and 1366 phase2_type == WifiEnums.EapPhase2.GTC): 1367 continue 1368 c = dict(config) 1369 c[WifiEnums.Enterprise.PHASE2] = phase2_type.value 1370 results.append(c) 1371 return results 1372 1373 1374 def generate_eap_test_name(config, ad=None): 1375 """ Generates a test case name based on an EAP configuration. 1376 1377 Args: 1378 config: A dict representing an EAP credential. 1379 ad object: Redundant but required as the same param is passed 1380 to test_func in run_generated_tests 1381 1382 Returns: 1383 A string representing the name of a generated EAP test case. 1384 """ 1385 eap = WifiEnums.Eap 1386 eap_phase2 = WifiEnums.EapPhase2 1387 Ent = WifiEnums.Enterprise 1388 name = "test_connect-" 1389 eap_name = "" 1390 for e in eap: 1391 if e.value == config[Ent.EAP]: 1392 eap_name = e.name 1393 break 1394 if "peap0" in config[WifiEnums.SSID_KEY].lower(): 1395 eap_name = "PEAP0" 1396 if "peap1" in config[WifiEnums.SSID_KEY].lower(): 1397 eap_name = "PEAP1" 1398 name += eap_name 1399 if Ent.PHASE2 in config: 1400 for e in eap_phase2: 1401 if e.value == config[Ent.PHASE2]: 1402 name += "-{}".format(e.name) 1403 break 1404 return name 1405 1406 1407 def group_attenuators(attenuators): 1408 """Groups a list of attenuators into attenuator groups for backward 1409 compatibility reasons. 1410 1411 Most legacy Wi-Fi setups have two attenuators each connected to a separate 1412 AP. The new Wi-Fi setup has four attenuators, each connected to one channel 1413 on an AP, so two of them are connected to one AP. 1414 1415 To make the existing scripts work in the new setup, when the script needs 1416 to attenuate one AP, it needs to set attenuation on both attenuators 1417 connected to the same AP. 1418 1419 This function groups attenuators properly so the scripts work in both 1420 legacy and new Wi-Fi setups. 1421 1422 Args: 1423 attenuators: A list of attenuator objects, either two or four in length. 1424 1425 Raises: 1426 signals.TestFailure is raised if the attenuator list does not have two 1427 or four objects. 1428 """ 1429 attn0 = attenuator.AttenuatorGroup("AP0") 1430 attn1 = attenuator.AttenuatorGroup("AP1") 1431 # Legacy testbed setup has two attenuation channels. 1432 num_of_attns = len(attenuators) 1433 if num_of_attns == 2: 1434 attn0.add(attenuators[0]) 1435 attn1.add(attenuators[1]) 1436 elif num_of_attns == 4: 1437 attn0.add(attenuators[0]) 1438 attn0.add(attenuators[1]) 1439 attn1.add(attenuators[2]) 1440 attn1.add(attenuators[3]) 1441 else: 1442 asserts.fail(("Either two or four attenuators are required for this " 1443 "test, but found %s") % num_of_attns) 1444 return [attn0, attn1] 1445