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