blob: cf316163125509d3c5c1e86542e453f4f5ef7a81 [file] [log] [blame]
Mark De Ruyter1a7ae572018-03-02 15:35:36 -08001#!/usr/bin/env python3
Ang Li73697b32015-12-03 00:41:53 +00002#
tturney1bdf77d2015-12-28 17:46:13 -08003# Copyright 2016 Google, Inc.
Ang Li73697b32015-12-03 00:41:53 +00004#
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
Ang Li5bd83f32016-05-23 14:39:38 -070017import logging
Girish Moturucf4dccd2018-08-27 12:22:00 -070018import os
James Mattis5a5dd492020-05-14 13:09:43 -070019import re
xianyuanjia0431ba32018-12-14 09:56:42 -080020import shutil
Girish Moturucf4dccd2018-08-27 12:22:00 -070021import time
Ang Li73697b32015-12-03 00:41:53 +000022
David Sue4cd9c22019-03-26 18:07:26 -070023from collections import namedtuple
Ang Li73697b32015-12-03 00:41:53 +000024from enum import IntEnum
25from queue import Empty
26
Ang Li82522812016-06-02 13:57:21 -070027from acts import asserts
Xianyuan Jia0e39e552019-01-24 17:17:47 -080028from acts import context
Ang Li374d7602016-02-08 17:27:27 -080029from acts import signals
Ang Lifee28402016-07-13 13:43:29 -070030from acts import utils
Ang Li2d3fe982016-06-08 10:00:43 -070031from acts.controllers import attenuator
Bindu Mahadev7e5dc682019-02-01 16:53:34 -080032from acts.controllers.ap_lib import hostapd_security
33from acts.controllers.ap_lib import hostapd_ap_preset
Girish Moturucf4dccd2018-08-27 12:22:00 -070034from acts.controllers.ap_lib.hostapd_constants import BAND_2G
35from acts.controllers.ap_lib.hostapd_constants import BAND_5G
Bindu Mahadev4e710362016-11-17 16:17:11 -080036from acts.test_utils.wifi import wifi_constants
Rebecca Silberstein8c422e62016-07-19 15:04:46 -070037from acts.test_utils.tel import tel_defines
Ang Li73697b32015-12-03 00:41:53 +000038
Bindu Mahadev1d3991e2017-03-20 18:06:54 -070039# Default timeout used for reboot, toggle WiFi and Airplane mode,
40# for the system to settle down after the operation.
41DEFAULT_TIMEOUT = 10
Ang Li73697b32015-12-03 00:41:53 +000042# Number of seconds to wait for events that are supposed to happen quickly.
43# Like onSuccess for start background scan and confirmation on wifi state
44# change.
45SHORT_TIMEOUT = 30
Bindu Mahadev7060a9f2018-05-04 13:48:12 -070046ROAMING_TIMEOUT = 30
Preetesh Barrettoe8c428b2019-02-14 09:15:44 -080047WIFI_CONNECTION_TIMEOUT_DEFAULT = 30
Ang Li73697b32015-12-03 00:41:53 +000048# Speed of light in m/s.
49SPEED_OF_LIGHT = 299792458
50
Qi Jiang8b443672018-03-16 14:46:50 -070051DEFAULT_PING_ADDR = "https://www.google.com/robots.txt"
Ang Li73697b32015-12-03 00:41:53 +000052
Girish Moturu36348a32019-12-10 08:41:54 -080053ROAMING_ATTN = {
Bindu Mahadev7060a9f2018-05-04 13:48:12 -070054 "AP1_on_AP2_off": [
55 0,
56 0,
Hsiu-Chang Chen73ea3342019-05-22 11:20:08 +080057 60,
58 60
Bindu Mahadev7060a9f2018-05-04 13:48:12 -070059 ],
60 "AP1_off_AP2_on": [
Hsiu-Chang Chen73ea3342019-05-22 11:20:08 +080061 60,
62 60,
Bindu Mahadev7060a9f2018-05-04 13:48:12 -070063 0,
64 0
65 ],
66 "default": [
67 0,
68 0,
69 0,
70 0
71 ]
72 }
Ang Li82522812016-06-02 13:57:21 -070073
Xianyuan Jia0e39e552019-01-24 17:17:47 -080074
Ang Li73697b32015-12-03 00:41:53 +000075class WifiEnums():
76
leslce9cf6d2020-02-19 16:37:07 +080077 SSID_KEY = "SSID" # Used for Wifi & SoftAp
Roshan Piusc999e5e2018-11-09 10:59:52 -080078 SSID_PATTERN_KEY = "ssidPattern"
Bindu Mahadev4c94b532019-01-09 12:20:10 -080079 NETID_KEY = "network_id"
leslce9cf6d2020-02-19 16:37:07 +080080 BSSID_KEY = "BSSID" # Used for Wifi & SoftAp
Roshan Piusc999e5e2018-11-09 10:59:52 -080081 BSSID_PATTERN_KEY = "bssidPattern"
leslce9cf6d2020-02-19 16:37:07 +080082 PWD_KEY = "password" # Used for Wifi & SoftAp
Ang Li73697b32015-12-03 00:41:53 +000083 frequency_key = "frequency"
lesl6d30a172020-03-05 15:05:22 +080084 HIDDEN_KEY = "hiddenSSID" # Used for Wifi & SoftAp
Roshan Piusd1204442018-11-12 12:20:39 -080085 IS_APP_INTERACTION_REQUIRED = "isAppInteractionRequired"
86 IS_USER_INTERACTION_REQUIRED = "isUserInteractionRequired"
Roshan Pius55fb7c42020-04-03 14:47:18 -070087 IS_SUGGESTION_METERED = "isMetered"
Roshan Piusd1204442018-11-12 12:20:39 -080088 PRIORITY = "priority"
leslce9cf6d2020-02-19 16:37:07 +080089 SECURITY = "security" # Used for Wifi & SoftAp
Ang Li73697b32015-12-03 00:41:53 +000090
leslce9cf6d2020-02-19 16:37:07 +080091 # Used for SoftAp
lesl6d30a172020-03-05 15:05:22 +080092 AP_BAND_KEY = "apBand"
93 AP_CHANNEL_KEY = "apChannel"
94 AP_MAXCLIENTS_KEY = "MaxNumberOfClients"
95 AP_SHUTDOWNTIMEOUT_KEY = "ShutdownTimeoutMillis"
96 AP_SHUTDOWNTIMEOUTENABLE_KEY = "AutoShutdownEnabled"
97 AP_CLIENTCONTROL_KEY = "ClientControlByUserEnabled"
98 AP_ALLOWEDLIST_KEY = "AllowedClientList"
99 AP_BLOCKEDLIST_KEY = "BlockedClientList"
100
leslce9cf6d2020-02-19 16:37:07 +0800101 WIFI_CONFIG_SOFTAP_BAND_2G = 1
102 WIFI_CONFIG_SOFTAP_BAND_5G = 2
103 WIFI_CONFIG_SOFTAP_BAND_2G_5G = 3
104 WIFI_CONFIG_SOFTAP_BAND_6G = 4
105 WIFI_CONFIG_SOFTAP_BAND_2G_6G = 5
106 WIFI_CONFIG_SOFTAP_BAND_5G_6G = 6
107 WIFI_CONFIG_SOFTAP_BAND_ANY = 7
108
109 # DO NOT USE IT for new test case! Replaced by WIFI_CONFIG_SOFTAP_BAND_
110 WIFI_CONFIG_APBAND_2G = WIFI_CONFIG_SOFTAP_BAND_2G
111 WIFI_CONFIG_APBAND_5G = WIFI_CONFIG_SOFTAP_BAND_5G
112 WIFI_CONFIG_APBAND_AUTO = WIFI_CONFIG_SOFTAP_BAND_2G_5G
113
114 WIFI_CONFIG_APBAND_2G_OLD = 0
115 WIFI_CONFIG_APBAND_5G_OLD = 1
116 WIFI_CONFIG_APBAND_AUTO_OLD = -1
Ang Li73697b32015-12-03 00:41:53 +0000117
Ang Li82522812016-06-02 13:57:21 -0700118 WIFI_WPS_INFO_PBC = 0
119 WIFI_WPS_INFO_DISPLAY = 1
120 WIFI_WPS_INFO_KEYPAD = 2
121 WIFI_WPS_INFO_LABEL = 3
122 WIFI_WPS_INFO_INVALID = 4
Ang Li73697b32015-12-03 00:41:53 +0000123
lesl6d30a172020-03-05 15:05:22 +0800124 class SoftApSecurityType():
125 OPEN = "NONE"
126 WPA2 = "WPA2_PSK"
127 WPA3_SAE_TRANSITION = "WPA3_SAE_TRANSITION"
128 WPA3_SAE = "WPA3_SAE"
129
Ang Li73697b32015-12-03 00:41:53 +0000130 class CountryCode():
131 CHINA = "CN"
132 JAPAN = "JP"
133 UK = "GB"
134 US = "US"
135 UNKNOWN = "UNKNOWN"
136
137 # Start of Macros for EAP
138 # EAP types
139 class Eap(IntEnum):
140 NONE = -1
141 PEAP = 0
Ang Li82522812016-06-02 13:57:21 -0700142 TLS = 1
Ang Li73697b32015-12-03 00:41:53 +0000143 TTLS = 2
Ang Li82522812016-06-02 13:57:21 -0700144 PWD = 3
145 SIM = 4
146 AKA = 5
147 AKA_PRIME = 6
148 UNAUTH_TLS = 7
Ang Li73697b32015-12-03 00:41:53 +0000149
150 # EAP Phase2 types
151 class EapPhase2(IntEnum):
Ang Li82522812016-06-02 13:57:21 -0700152 NONE = 0
153 PAP = 1
154 MSCHAP = 2
155 MSCHAPV2 = 3
156 GTC = 4
Ang Li73697b32015-12-03 00:41:53 +0000157
158 class Enterprise:
Ang Li82522812016-06-02 13:57:21 -0700159 # Enterprise Config Macros
160 EMPTY_VALUE = "NULL"
161 EAP = "eap"
162 PHASE2 = "phase2"
163 IDENTITY = "identity"
164 ANON_IDENTITY = "anonymous_identity"
165 PASSWORD = "password"
166 SUBJECT_MATCH = "subject_match"
Ang Li73697b32015-12-03 00:41:53 +0000167 ALTSUBJECT_MATCH = "altsubject_match"
168 DOM_SUFFIX_MATCH = "domain_suffix_match"
Ang Li82522812016-06-02 13:57:21 -0700169 CLIENT_CERT = "client_cert"
170 CA_CERT = "ca_cert"
171 ENGINE = "engine"
172 ENGINE_ID = "engine_id"
173 PRIVATE_KEY_ID = "key_id"
174 REALM = "realm"
175 PLMN = "plmn"
176 FQDN = "FQDN"
177 FRIENDLY_NAME = "providerFriendlyName"
178 ROAMING_IDS = "roamingConsortiumIds"
Ang Li73697b32015-12-03 00:41:53 +0000179 # 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):
Ang Li82522812016-06-02 13:57:21 -0700196 TYPE_ONE_SIDED = 1
197 TYPE_TWO_SIDED = 2
Ang Li73697b32015-12-03 00:41:53 +0000198
199 class RttPeerType(IntEnum):
Ang Li82522812016-06-02 13:57:21 -0700200 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
Ang Li73697b32015-12-03 00:41:53 +0000205
206 class RttPreamble(IntEnum):
Ang Li82522812016-06-02 13:57:21 -0700207 PREAMBLE_LEGACY = 0x01
208 PREAMBLE_HT = 0x02
209 PREAMBLE_VHT = 0x04
Ang Li73697b32015-12-03 00:41:53 +0000210
211 class RttBW(IntEnum):
Ang Li82522812016-06-02 13:57:21 -0700212 BW_5_SUPPORT = 0x01
213 BW_10_SUPPORT = 0x02
214 BW_20_SUPPORT = 0x04
215 BW_40_SUPPORT = 0x08
216 BW_80_SUPPORT = 0x10
Ang Li73697b32015-12-03 00:41:53 +0000217 BW_160_SUPPORT = 0x20
218
219 class Rtt(IntEnum):
Ang Li82522812016-06-02 13:57:21 -0700220 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
Ang Li73697b32015-12-03 00:41:53 +0000236
Ang Li82522812016-06-02 13:57:21 -0700237 REASON_UNSPECIFIED = -1
238 REASON_NOT_AVAILABLE = -2
239 REASON_INVALID_LISTENER = -3
240 REASON_INVALID_REQUEST = -4
Ang Li73697b32015-12-03 00:41:53 +0000241
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.
Ang Li82522812016-06-02 13:57:21 -0700269 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
Ang Li73697b32015-12-03 00:41:53 +0000276
277 REPORT_EVENT_AFTER_BUFFER_FULL = 0
278 REPORT_EVENT_AFTER_EACH_SCAN = 1
279 REPORT_EVENT_FULL_SCAN_RESULT = 2
280
xshuaabcfeb2018-02-14 11:43:24 -0800281 SCAN_TYPE_LOW_LATENCY = 0
282 SCAN_TYPE_LOW_POWER = 1
283 SCAN_TYPE_HIGH_ACCURACY = 2
284
Ang Li73697b32015-12-03 00:41:53 +0000285 # US Wifi frequencies
286 ALL_2G_FREQUENCIES = [2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452,
287 2457, 2462]
288 DFS_5G_FREQUENCIES = [5260, 5280, 5300, 5320, 5500, 5520, 5540, 5560, 5580,
289 5600, 5620, 5640, 5660, 5680, 5700, 5720]
290 NONE_DFS_5G_FREQUENCIES = [5180, 5200, 5220, 5240, 5745, 5765, 5785, 5805,
291 5825]
292 ALL_5G_FREQUENCIES = DFS_5G_FREQUENCIES + NONE_DFS_5G_FREQUENCIES
293
294 band_to_frequencies = {
Ang Li82522812016-06-02 13:57:21 -0700295 WIFI_BAND_24_GHZ: ALL_2G_FREQUENCIES,
296 WIFI_BAND_5_GHZ: NONE_DFS_5G_FREQUENCIES,
297 WIFI_BAND_5_GHZ_DFS_ONLY: DFS_5G_FREQUENCIES,
298 WIFI_BAND_5_GHZ_WITH_DFS: ALL_5G_FREQUENCIES,
299 WIFI_BAND_BOTH: ALL_2G_FREQUENCIES + NONE_DFS_5G_FREQUENCIES,
300 WIFI_BAND_BOTH_WITH_DFS: ALL_5G_FREQUENCIES + ALL_2G_FREQUENCIES
Ang Li73697b32015-12-03 00:41:53 +0000301 }
302
303 # All Wifi frequencies to channels lookup.
304 freq_to_channel = {
305 2412: 1,
306 2417: 2,
307 2422: 3,
308 2427: 4,
309 2432: 5,
310 2437: 6,
311 2442: 7,
312 2447: 8,
313 2452: 9,
314 2457: 10,
315 2462: 11,
316 2467: 12,
317 2472: 13,
318 2484: 14,
319 4915: 183,
320 4920: 184,
321 4925: 185,
322 4935: 187,
323 4940: 188,
324 4945: 189,
325 4960: 192,
326 4980: 196,
327 5035: 7,
328 5040: 8,
329 5045: 9,
330 5055: 11,
331 5060: 12,
332 5080: 16,
333 5170: 34,
334 5180: 36,
335 5190: 38,
336 5200: 40,
337 5210: 42,
338 5220: 44,
339 5230: 46,
340 5240: 48,
341 5260: 52,
342 5280: 56,
343 5300: 60,
344 5320: 64,
345 5500: 100,
346 5520: 104,
347 5540: 108,
348 5560: 112,
349 5580: 116,
350 5600: 120,
351 5620: 124,
352 5640: 128,
353 5660: 132,
354 5680: 136,
355 5700: 140,
356 5745: 149,
357 5765: 153,
358 5785: 157,
359 5805: 161,
360 5825: 165,
361 }
362
363 # All Wifi channels to frequencies lookup.
364 channel_2G_to_freq = {
365 1: 2412,
366 2: 2417,
367 3: 2422,
368 4: 2427,
369 5: 2432,
370 6: 2437,
371 7: 2442,
372 8: 2447,
373 9: 2452,
374 10: 2457,
375 11: 2462,
376 12: 2467,
377 13: 2472,
378 14: 2484
379 }
380
381 channel_5G_to_freq = {
382 183: 4915,
383 184: 4920,
384 185: 4925,
385 187: 4935,
386 188: 4940,
387 189: 4945,
388 192: 4960,
389 196: 4980,
390 7: 5035,
391 8: 5040,
392 9: 5045,
393 11: 5055,
394 12: 5060,
395 16: 5080,
396 34: 5170,
397 36: 5180,
398 38: 5190,
399 40: 5200,
400 42: 5210,
401 44: 5220,
402 46: 5230,
403 48: 5240,
404 52: 5260,
405 56: 5280,
406 60: 5300,
407 64: 5320,
408 100: 5500,
409 104: 5520,
410 108: 5540,
411 112: 5560,
412 116: 5580,
413 120: 5600,
414 124: 5620,
415 128: 5640,
416 132: 5660,
417 136: 5680,
418 140: 5700,
419 149: 5745,
420 153: 5765,
421 157: 5785,
422 161: 5805,
423 165: 5825
424 }
425
Ang Li82522812016-06-02 13:57:21 -0700426
Ang Li73697b32015-12-03 00:41:53 +0000427class WifiChannelBase:
428 ALL_2G_FREQUENCIES = []
429 DFS_5G_FREQUENCIES = []
430 NONE_DFS_5G_FREQUENCIES = []
431 ALL_5G_FREQUENCIES = DFS_5G_FREQUENCIES + NONE_DFS_5G_FREQUENCIES
432 MIX_CHANNEL_SCAN = []
433
434 def band_to_freq(self, band):
435 _band_to_frequencies = {
436 WifiEnums.WIFI_BAND_24_GHZ: self.ALL_2G_FREQUENCIES,
437 WifiEnums.WIFI_BAND_5_GHZ: self.NONE_DFS_5G_FREQUENCIES,
438 WifiEnums.WIFI_BAND_5_GHZ_DFS_ONLY: self.DFS_5G_FREQUENCIES,
439 WifiEnums.WIFI_BAND_5_GHZ_WITH_DFS: self.ALL_5G_FREQUENCIES,
Ang Li82522812016-06-02 13:57:21 -0700440 WifiEnums.WIFI_BAND_BOTH:
441 self.ALL_2G_FREQUENCIES + self.NONE_DFS_5G_FREQUENCIES,
442 WifiEnums.WIFI_BAND_BOTH_WITH_DFS:
443 self.ALL_5G_FREQUENCIES + self.ALL_2G_FREQUENCIES
Ang Li73697b32015-12-03 00:41:53 +0000444 }
445 return _band_to_frequencies[band]
446
Ang Li82522812016-06-02 13:57:21 -0700447
Ang Li73697b32015-12-03 00:41:53 +0000448class WifiChannelUS(WifiChannelBase):
449 # US Wifi frequencies
450 ALL_2G_FREQUENCIES = [2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452,
451 2457, 2462]
452 NONE_DFS_5G_FREQUENCIES = [5180, 5200, 5220, 5240, 5745, 5765, 5785, 5805,
453 5825]
Ang Li82522812016-06-02 13:57:21 -0700454 MIX_CHANNEL_SCAN = [2412, 2437, 2462, 5180, 5200, 5280, 5260, 5300, 5500,
455 5320, 5520, 5560, 5700, 5745, 5805]
Ang Li73697b32015-12-03 00:41:53 +0000456
457 def __init__(self, model=None):
Girish Moturu0c567b02017-08-11 16:20:01 -0700458 self.DFS_5G_FREQUENCIES = [5260, 5280, 5300, 5320, 5500, 5520,
459 5540, 5560, 5580, 5600, 5620, 5640,
460 5660, 5680, 5700, 5720]
461 self.ALL_5G_FREQUENCIES = self.DFS_5G_FREQUENCIES + self.NONE_DFS_5G_FREQUENCIES
Ang Li73697b32015-12-03 00:41:53 +0000462
Bindu Mahadevff295782019-02-08 16:17:48 -0800463
Girish Moturuf02fa1d2017-05-21 09:51:23 +0530464class WifiReferenceNetworks:
465 """ Class to parse and return networks of different band and
466 auth type from reference_networks
467 """
468 def __init__(self, obj):
469 self.reference_networks = obj
470 self.WIFI_2G = "2g"
471 self.WIFI_5G = "5g"
472
473 self.secure_networks_2g = []
474 self.secure_networks_5g = []
475 self.open_networks_2g = []
476 self.open_networks_5g = []
477 self._parse_networks()
478
479 def _parse_networks(self):
480 for network in self.reference_networks:
481 for key in network:
482 if key == self.WIFI_2G:
483 if "password" in network[key]:
484 self.secure_networks_2g.append(network[key])
485 else:
486 self.open_networks_2g.append(network[key])
487 else:
488 if "password" in network[key]:
489 self.secure_networks_5g.append(network[key])
490 else:
491 self.open_networks_5g.append(network[key])
492
493 def return_2g_secure_networks(self):
494 return self.secure_networks_2g
495
496 def return_5g_secure_networks(self):
497 return self.secure_networks_5g
498
499 def return_2g_open_networks(self):
500 return self.open_networks_2g
501
502 def return_5g_open_networks(self):
503 return self.open_networks_5g
504
505 def return_secure_networks(self):
506 return self.secure_networks_2g + self.secure_networks_5g
507
508 def return_open_networks(self):
509 return self.open_networks_2g + self.open_networks_5g
510
Ang Li82522812016-06-02 13:57:21 -0700511
512def _assert_on_fail_handler(func, assert_on_fail, *args, **kwargs):
513 """Wrapper function that handles the bahevior of assert_on_fail.
514
515 When assert_on_fail is True, let all test signals through, which can
516 terminate test cases directly. When assert_on_fail is False, the wrapper
517 raises no test signals and reports operation status by returning True or
518 False.
519
520 Args:
521 func: The function to wrap. This function reports operation status by
522 raising test signals.
523 assert_on_fail: A boolean that specifies if the output of the wrapper
524 is test signal based or return value based.
525 args: Positional args for func.
526 kwargs: Name args for func.
527
528 Returns:
529 If assert_on_fail is True, returns True/False to signal operation
530 status, otherwise return nothing.
531 """
532 try:
533 func(*args, **kwargs)
534 if not assert_on_fail:
535 return True
536 except signals.TestSignal:
537 if assert_on_fail:
538 raise
539 return False
540
541
542def assert_network_in_list(target, network_list):
543 """Makes sure a specified target Wi-Fi network exists in a list of Wi-Fi
544 networks.
545
546 Args:
547 target: A dict representing a Wi-Fi network.
548 E.g. {WifiEnums.SSID_KEY: "SomeNetwork"}
549 network_list: A list of dicts, each representing a Wi-Fi network.
550 """
551 match_results = match_networks(target, network_list)
552 asserts.assert_true(
553 match_results, "Target network %s, does not exist in network list %s" %
554 (target, network_list))
555
556
Ang Li73697b32015-12-03 00:41:53 +0000557def match_networks(target_params, networks):
558 """Finds the WiFi networks that match a given set of parameters in a list
559 of WiFi networks.
560
Girish Moturubc48d9f2016-11-01 13:24:14 -0700561 To be considered a match, the network should contain every key-value pair
562 of target_params
Ang Li73697b32015-12-03 00:41:53 +0000563
564 Args:
Girish Moturubc48d9f2016-11-01 13:24:14 -0700565 target_params: A dict with 1 or more key-value pairs representing a Wi-Fi network.
566 E.g { 'SSID': 'wh_ap1_5g', 'BSSID': '30:b5:c2:33:e4:47' }
Ang Li73697b32015-12-03 00:41:53 +0000567 networks: A list of dict objects representing WiFi networks.
568
569 Returns:
570 The networks that match the target parameters.
571 """
572 results = []
Betty Zhou3caa0982017-02-22 19:26:20 -0800573 asserts.assert_true(target_params,
574 "Expected networks object 'target_params' is empty")
Ang Li73697b32015-12-03 00:41:53 +0000575 for n in networks:
Girish Moturubc48d9f2016-11-01 13:24:14 -0700576 add_network = 1
Ang Li9a66de72016-02-08 15:26:38 -0800577 for k, v in target_params.items():
578 if k not in n:
Girish Moturubc48d9f2016-11-01 13:24:14 -0700579 add_network = 0
580 break
Ang Li9a66de72016-02-08 15:26:38 -0800581 if n[k] != v:
Girish Moturubc48d9f2016-11-01 13:24:14 -0700582 add_network = 0
583 break
584 if add_network:
Ang Li73697b32015-12-03 00:41:53 +0000585 results.append(n)
586 return results
587
Bindu Mahadevff295782019-02-08 16:17:48 -0800588
Roshan Pius93b519c2018-05-09 12:07:11 -0700589def wait_for_wifi_state(ad, state, assert_on_fail=True):
590 """Waits for the device to transition to the specified wifi state
591
592 Args:
593 ad: An AndroidDevice object.
594 state: Wifi state to wait for.
595 assert_on_fail: If True, error checks in this function will raise test
596 failure signals.
597
598 Returns:
599 If assert_on_fail is False, function returns True if the device transitions
600 to the specified state, False otherwise. If assert_on_fail is True, no return value.
601 """
602 return _assert_on_fail_handler(
603 _wait_for_wifi_state, assert_on_fail, ad, state=state)
604
605
606def _wait_for_wifi_state(ad, state):
607 """Toggles the state of wifi.
608
609 TestFailure signals are raised when something goes wrong.
610
611 Args:
612 ad: An AndroidDevice object.
613 state: Wifi state to wait for.
614 """
615 if state == ad.droid.wifiCheckState():
616 # Check if the state is already achieved, so we don't wait for the
617 # state change event by mistake.
618 return
619 ad.droid.wifiStartTrackingStateChange()
620 fail_msg = "Device did not transition to Wi-Fi state to %s on %s." % (state,
621 ad.serial)
622 try:
623 ad.ed.wait_for_event(wifi_constants.WIFI_STATE_CHANGED,
624 lambda x: x["data"]["enabled"] == state,
625 SHORT_TIMEOUT)
626 except Empty:
627 asserts.assert_equal(state, ad.droid.wifiCheckState(), fail_msg)
628 finally:
629 ad.droid.wifiStopTrackingStateChange()
Ang Li82522812016-06-02 13:57:21 -0700630
Bindu Mahadevff295782019-02-08 16:17:48 -0800631
Ang Li82522812016-06-02 13:57:21 -0700632def wifi_toggle_state(ad, new_state=None, assert_on_fail=True):
Ang Li6b557182015-11-11 17:19:17 -0800633 """Toggles the state of wifi.
Ang Li73697b32015-12-03 00:41:53 +0000634
Ang Li6b557182015-11-11 17:19:17 -0800635 Args:
636 ad: An AndroidDevice object.
637 new_state: Wifi state to set to. If None, opposite of the current state.
Ang Li82522812016-06-02 13:57:21 -0700638 assert_on_fail: If True, error checks in this function will raise test
639 failure signals.
Ang Li73697b32015-12-03 00:41:53 +0000640
Ang Li6b557182015-11-11 17:19:17 -0800641 Returns:
Ang Li82522812016-06-02 13:57:21 -0700642 If assert_on_fail is False, function returns True if the toggle was
643 successful, False otherwise. If assert_on_fail is True, no return value.
644 """
Betty Zhou3caa0982017-02-22 19:26:20 -0800645 return _assert_on_fail_handler(
646 _wifi_toggle_state, assert_on_fail, ad, new_state=new_state)
Ang Li82522812016-06-02 13:57:21 -0700647
648
649def _wifi_toggle_state(ad, new_state=None):
650 """Toggles the state of wifi.
651
652 TestFailure signals are raised when something goes wrong.
653
654 Args:
655 ad: An AndroidDevice object.
656 new_state: The state to set Wi-Fi to. If None, opposite of the current
657 state will be set.
Ang Li6b557182015-11-11 17:19:17 -0800658 """
Ang Li31b00782016-06-21 13:04:23 -0700659 if new_state is None:
660 new_state = not ad.droid.wifiCheckState()
Ang Lie5c85c92016-07-27 15:38:09 -0700661 elif new_state == ad.droid.wifiCheckState():
662 # Check if the new_state is already achieved, so we don't wait for the
663 # state change event by mistake.
664 return
665 ad.droid.wifiStartTrackingStateChange()
Ang Li31b00782016-06-21 13:04:23 -0700666 ad.log.info("Setting Wi-Fi state to %s.", new_state)
Roshan Pius5a027fa2018-05-04 13:59:38 -0700667 ad.ed.clear_all_events()
Ang Li31b00782016-06-21 13:04:23 -0700668 # Setting wifi state.
Ang Li6b557182015-11-11 17:19:17 -0800669 ad.droid.wifiToggleState(new_state)
Jaineel3bd9bea2019-12-13 12:44:17 -0800670 time.sleep(2)
Ang Lie2e93a22016-06-22 16:43:28 -0700671 fail_msg = "Failed to set Wi-Fi state to %s on %s." % (new_state,
672 ad.serial)
Ang Li73697b32015-12-03 00:41:53 +0000673 try:
Roshan Pius5a027fa2018-05-04 13:59:38 -0700674 ad.ed.wait_for_event(wifi_constants.WIFI_STATE_CHANGED,
675 lambda x: x["data"]["enabled"] == new_state,
676 SHORT_TIMEOUT)
Ang Li73697b32015-12-03 00:41:53 +0000677 except Empty:
Ang Li82522812016-06-02 13:57:21 -0700678 asserts.assert_equal(new_state, ad.droid.wifiCheckState(), fail_msg)
Ang Li6b557182015-11-11 17:19:17 -0800679 finally:
680 ad.droid.wifiStopTrackingStateChange()
681
Ang Li82522812016-06-02 13:57:21 -0700682
Ang Li6b557182015-11-11 17:19:17 -0800683def reset_wifi(ad):
Ang Li1179fa72016-06-16 09:44:06 -0700684 """Clears all saved Wi-Fi networks on a device.
685
686 This will turn Wi-Fi on.
Ang Li6b557182015-11-11 17:19:17 -0800687
688 Args:
689 ad: An AndroidDevice object.
690
Ang Li6b557182015-11-11 17:19:17 -0800691 """
Ang Li6b557182015-11-11 17:19:17 -0800692 networks = ad.droid.wifiGetConfiguredNetworks()
693 if not networks:
694 return
695 for n in networks:
696 ad.droid.wifiForgetNetwork(n['networkId'])
697 try:
Bindu Mahadev4e710362016-11-17 16:17:11 -0800698 event = ad.ed.pop_event(wifi_constants.WIFI_FORGET_NW_SUCCESS,
Ang Li82522812016-06-02 13:57:21 -0700699 SHORT_TIMEOUT)
Ang Li6b557182015-11-11 17:19:17 -0800700 except Empty:
Ang Li1179fa72016-06-16 09:44:06 -0700701 logging.warning("Could not confirm the removal of network %s.", n)
702 # Check again to see if there's any network left.
Betty Zhou3caa0982017-02-22 19:26:20 -0800703 asserts.assert_true(
704 not ad.droid.wifiGetConfiguredNetworks(),
705 "Failed to remove these configured Wi-Fi networks: %s" % networks)
Ang Li82522812016-06-02 13:57:21 -0700706
Ang Li73697b32015-12-03 00:41:53 +0000707
Bindu Mahadev1d3991e2017-03-20 18:06:54 -0700708def toggle_airplane_mode_on_and_off(ad):
709 """Turn ON and OFF Airplane mode.
Bindu Mahadev3c54c492017-02-15 16:00:08 -0800710
Bindu Mahadev1d3991e2017-03-20 18:06:54 -0700711 ad: An AndroidDevice object.
712 Returns: Assert if turning on/off Airplane mode fails.
Bindu Mahadev3c54c492017-02-15 16:00:08 -0800713
Bindu Mahadev1d3991e2017-03-20 18:06:54 -0700714 """
715 ad.log.debug("Toggling Airplane mode ON.")
716 asserts.assert_true(
717 utils.force_airplane_mode(ad, True),
718 "Can not turn on airplane mode on: %s" % ad.serial)
719 time.sleep(DEFAULT_TIMEOUT)
720 ad.log.debug("Toggling Airplane mode OFF.")
721 asserts.assert_true(
722 utils.force_airplane_mode(ad, False),
723 "Can not turn on airplane mode on: %s" % ad.serial)
724 time.sleep(DEFAULT_TIMEOUT)
Bindu Mahadev3c54c492017-02-15 16:00:08 -0800725
726
Bindu Mahadev1d3991e2017-03-20 18:06:54 -0700727def toggle_wifi_off_and_on(ad):
728 """Turn OFF and ON WiFi.
Bindu Mahadev3c54c492017-02-15 16:00:08 -0800729
Bindu Mahadev1d3991e2017-03-20 18:06:54 -0700730 ad: An AndroidDevice object.
731 Returns: Assert if turning off/on WiFi fails.
Bindu Mahadev3c54c492017-02-15 16:00:08 -0800732
Bindu Mahadev1d3991e2017-03-20 18:06:54 -0700733 """
734 ad.log.debug("Toggling wifi OFF.")
735 wifi_toggle_state(ad, False)
736 time.sleep(DEFAULT_TIMEOUT)
737 ad.log.debug("Toggling wifi ON.")
738 wifi_toggle_state(ad, True)
739 time.sleep(DEFAULT_TIMEOUT)
Bindu Mahadev3c54c492017-02-15 16:00:08 -0800740
741
Ang Li73697b32015-12-03 00:41:53 +0000742def wifi_forget_network(ad, net_ssid):
Ang Li8e767182015-12-09 17:29:24 -0800743 """Remove configured Wifi network on an android device.
Ang Li73697b32015-12-03 00:41:53 +0000744
Ang Li8e767182015-12-09 17:29:24 -0800745 Args:
746 ad: android_device object for forget network.
747 net_ssid: ssid of network to be forget
Ang Li73697b32015-12-03 00:41:53 +0000748
Ang Li8e767182015-12-09 17:29:24 -0800749 """
Girish Moturu40d7dc22016-11-02 12:14:56 -0700750 networks = ad.droid.wifiGetConfiguredNetworks()
Ang Li8e767182015-12-09 17:29:24 -0800751 if not networks:
752 return
753 for n in networks:
754 if net_ssid in n[WifiEnums.SSID_KEY]:
Girish Moturu40d7dc22016-11-02 12:14:56 -0700755 ad.droid.wifiForgetNetwork(n['networkId'])
Ang Li8e767182015-12-09 17:29:24 -0800756 try:
Bindu Mahadev4e710362016-11-17 16:17:11 -0800757 event = ad.ed.pop_event(wifi_constants.WIFI_FORGET_NW_SUCCESS,
Betty Zhou3caa0982017-02-22 19:26:20 -0800758 SHORT_TIMEOUT)
Ang Li8e767182015-12-09 17:29:24 -0800759 except Empty:
Girish Moturu1bf82302016-11-01 13:27:00 -0700760 asserts.fail("Failed to remove network %s." % n)
Ang Li73697b32015-12-03 00:41:53 +0000761
Ang Li82522812016-06-02 13:57:21 -0700762
Ang Li73697b32015-12-03 00:41:53 +0000763def wifi_test_device_init(ad):
764 """Initializes an android device for wifi testing.
765
766 0. Make sure SL4A connection is established on the android device.
767 1. Disable location service's WiFi scan.
768 2. Turn WiFi on.
769 3. Clear all saved networks.
770 4. Set country code to US.
771 5. Enable WiFi verbose logging.
772 6. Sync device time with computer time.
773 7. Turn off cellular data.
Ang Lifee28402016-07-13 13:43:29 -0700774 8. Turn off ambient display.
Ang Li73697b32015-12-03 00:41:53 +0000775 """
Ang Lifee28402016-07-13 13:43:29 -0700776 utils.require_sl4a((ad, ))
Ang Li73697b32015-12-03 00:41:53 +0000777 ad.droid.wifiScannerToggleAlwaysAvailable(False)
778 msg = "Failed to turn off location service's scan."
Ang Li82522812016-06-02 13:57:21 -0700779 asserts.assert_true(not ad.droid.wifiScannerIsAlwaysAvailable(), msg)
780 wifi_toggle_state(ad, True)
Ang Li6b557182015-11-11 17:19:17 -0800781 reset_wifi(ad)
Ang Li73697b32015-12-03 00:41:53 +0000782 ad.droid.wifiEnableVerboseLogging(1)
Ang Li8e767182015-12-09 17:29:24 -0800783 msg = "Failed to enable WiFi verbose logging."
Ang Li82522812016-06-02 13:57:21 -0700784 asserts.assert_equal(ad.droid.wifiGetVerboseLoggingLevel(), 1, msg)
Ang Li73697b32015-12-03 00:41:53 +0000785 # We don't verify the following settings since they are not critical.
Ang Lie2e93a22016-06-22 16:43:28 -0700786 # Set wpa_supplicant log level to EXCESSIVE.
787 output = ad.adb.shell("wpa_cli -i wlan0 -p -g@android:wpa_wlan0 IFNAME="
788 "wlan0 log_level EXCESSIVE")
789 ad.log.info("wpa_supplicant log change status: %s", output)
Ang Lifee28402016-07-13 13:43:29 -0700790 utils.sync_device_time(ad)
Ang Li0bf8e022016-01-04 17:34:48 -0800791 ad.droid.telephonyToggleDataConnection(False)
Roshan Pius48df08c2019-09-13 08:07:30 -0700792 set_wifi_country_code(ad, WifiEnums.CountryCode.US)
Ang Lifee28402016-07-13 13:43:29 -0700793 utils.set_ambient_display(ad, False)
Ang Li73697b32015-12-03 00:41:53 +0000794
Roshan Pius48df08c2019-09-13 08:07:30 -0700795def set_wifi_country_code(ad, country_code):
796 """Sets the wifi country code on the device.
797
798 Args:
799 ad: An AndroidDevice object.
800 country_code: 2 letter ISO country code
codycaldwell35b87182020-01-16 14:08:01 -0800801
802 Raises:
803 An RpcException if unable to set the country code.
Roshan Pius48df08c2019-09-13 08:07:30 -0700804 """
Jaineelc5b56a62019-10-10 17:12:02 -0700805 try:
codycaldwell35b87182020-01-16 14:08:01 -0800806 ad.adb.shell("cmd wifi force-country-code enabled %s" % country_code)
807 except ad.adb.AdbError as e:
Jaineelc5b56a62019-10-10 17:12:02 -0700808 ad.droid.wifiSetCountryCode(WifiEnums.CountryCode.US)
Roshan Pius48df08c2019-09-13 08:07:30 -0700809
Ang Li82522812016-06-02 13:57:21 -0700810
Ang Li6b557182015-11-11 17:19:17 -0800811def start_wifi_connection_scan(ad):
Ang Li73697b32015-12-03 00:41:53 +0000812 """Starts a wifi connection scan and wait for results to become available.
813
814 Args:
Ang Li6b557182015-11-11 17:19:17 -0800815 ad: An AndroidDevice object.
Ang Li73697b32015-12-03 00:41:53 +0000816 """
Roshan Pius7f61f1c2018-01-24 18:36:49 -0800817 ad.ed.clear_all_events()
Ang Li6b557182015-11-11 17:19:17 -0800818 ad.droid.wifiStartScan()
Ang Li82522812016-06-02 13:57:21 -0700819 try:
820 ad.ed.pop_event("WifiManagerScanResultsAvailable", 60)
821 except Empty:
822 asserts.fail("Wi-Fi results did not become available within 60s.")
823
Ang Li73697b32015-12-03 00:41:53 +0000824
Roshan Piuscb9bc482018-02-01 14:27:09 -0800825def start_wifi_connection_scan_and_return_status(ad):
826 """
827 Starts a wifi connection scan and wait for results to become available
828 or a scan failure to be reported.
829
830 Args:
831 ad: An AndroidDevice object.
832 Returns:
833 True: if scan succeeded & results are available
834 False: if scan failed
835 """
836 ad.ed.clear_all_events()
837 ad.droid.wifiStartScan()
838 try:
839 events = ad.ed.pop_events(
840 "WifiManagerScan(ResultsAvailable|Failure)", 60)
841 except Empty:
842 asserts.fail(
843 "Wi-Fi scan results/failure did not become available within 60s.")
844 # If there are multiple matches, we check for atleast one success.
845 for event in events:
846 if event["name"] == "WifiManagerScanResultsAvailable":
847 return True
848 elif event["name"] == "WifiManagerScanFailure":
849 ad.log.debug("Scan failure received")
850 return False
851
852
Roshan Pius7f61f1c2018-01-24 18:36:49 -0800853def start_wifi_connection_scan_and_check_for_network(ad, network_ssid,
Roshan Piuscb9bc482018-02-01 14:27:09 -0800854 max_tries=3):
Roshan Pius7f61f1c2018-01-24 18:36:49 -0800855 """
856 Start connectivity scans & checks if the |network_ssid| is seen in
857 scan results. The method performs a max of |max_tries| connectivity scans
858 to find the network.
859
860 Args:
861 ad: An AndroidDevice object.
862 network_ssid: SSID of the network we are looking for.
863 max_tries: Number of scans to try.
864 Returns:
865 True: if network_ssid is found in scan results.
866 False: if network_ssid is not found in scan results.
867 """
868 for num_tries in range(max_tries):
Roshan Piuscb9bc482018-02-01 14:27:09 -0800869 if start_wifi_connection_scan_and_return_status(ad):
870 scan_results = ad.droid.wifiGetScanResults()
871 match_results = match_networks(
872 {WifiEnums.SSID_KEY: network_ssid}, scan_results)
873 if len(match_results) > 0:
874 return True
Roshan Pius7f61f1c2018-01-24 18:36:49 -0800875 return False
876
877
878def start_wifi_connection_scan_and_ensure_network_found(ad, network_ssid,
Roshan Piuscb9bc482018-02-01 14:27:09 -0800879 max_tries=3):
Roshan Pius7f61f1c2018-01-24 18:36:49 -0800880 """
881 Start connectivity scans & ensure the |network_ssid| is seen in
882 scan results. The method performs a max of |max_tries| connectivity scans
883 to find the network.
884 This method asserts on failure!
885
886 Args:
887 ad: An AndroidDevice object.
888 network_ssid: SSID of the network we are looking for.
889 max_tries: Number of scans to try.
890 """
891 ad.log.info("Starting scans to ensure %s is present", network_ssid)
892 assert_msg = "Failed to find " + network_ssid + " in scan results" \
893 " after " + str(max_tries) + " tries"
894 asserts.assert_true(start_wifi_connection_scan_and_check_for_network(
895 ad, network_ssid, max_tries), assert_msg)
896
897
898def start_wifi_connection_scan_and_ensure_network_not_found(ad, network_ssid,
Roshan Piuscb9bc482018-02-01 14:27:09 -0800899 max_tries=3):
Roshan Pius7f61f1c2018-01-24 18:36:49 -0800900 """
901 Start connectivity scans & ensure the |network_ssid| is not seen in
902 scan results. The method performs a max of |max_tries| connectivity scans
903 to find the network.
904 This method asserts on failure!
905
906 Args:
907 ad: An AndroidDevice object.
908 network_ssid: SSID of the network we are looking for.
909 max_tries: Number of scans to try.
910 """
911 ad.log.info("Starting scans to ensure %s is not present", network_ssid)
912 assert_msg = "Found " + network_ssid + " in scan results" \
913 " after " + str(max_tries) + " tries"
914 asserts.assert_false(start_wifi_connection_scan_and_check_for_network(
915 ad, network_ssid, max_tries), assert_msg)
916
917
Ang Li73697b32015-12-03 00:41:53 +0000918def start_wifi_background_scan(ad, scan_setting):
919 """Starts wifi background scan.
920
921 Args:
922 ad: android_device object to initiate connection on.
923 scan_setting: A dict representing the settings of the scan.
924
925 Returns:
926 If scan was started successfully, event data of success event is returned.
927 """
Girish Moturu40d7dc22016-11-02 12:14:56 -0700928 idx = ad.droid.wifiScannerStartBackgroundScan(scan_setting)
929 event = ad.ed.pop_event("WifiScannerScan{}onSuccess".format(idx),
Betty Zhou3caa0982017-02-22 19:26:20 -0800930 SHORT_TIMEOUT)
Ang Li73697b32015-12-03 00:41:53 +0000931 return event['data']
932
Ang Li82522812016-06-02 13:57:21 -0700933
Roshan Piusce821342018-01-10 11:03:04 -0800934def start_wifi_tethering(ad, ssid, password, band=None, hidden=None):
Ang Li73697b32015-12-03 00:41:53 +0000935 """Starts wifi tethering on an android_device.
936
937 Args:
938 ad: android_device to start wifi tethering on.
939 ssid: The SSID the soft AP should broadcast.
940 password: The password the soft AP should use.
941 band: The band the soft AP should be set on. It should be either
942 WifiEnums.WIFI_CONFIG_APBAND_2G or WifiEnums.WIFI_CONFIG_APBAND_5G.
Roshan Piusce821342018-01-10 11:03:04 -0800943 hidden: boolean to indicate if the AP needs to be hidden or not.
Ang Li73697b32015-12-03 00:41:53 +0000944
945 Returns:
Girish Moturu3581d612016-11-02 15:08:51 -0700946 No return value. Error checks in this function will raise test failure signals
Ang Li73697b32015-12-03 00:41:53 +0000947 """
Ang Li82522812016-06-02 13:57:21 -0700948 config = {WifiEnums.SSID_KEY: ssid}
Ang Li73697b32015-12-03 00:41:53 +0000949 if password:
950 config[WifiEnums.PWD_KEY] = password
951 if band:
lesl6d30a172020-03-05 15:05:22 +0800952 config[WifiEnums.AP_BAND_KEY] = band
Roshan Piusce821342018-01-10 11:03:04 -0800953 if hidden:
954 config[WifiEnums.HIDDEN_KEY] = hidden
Betty Zhou3caa0982017-02-22 19:26:20 -0800955 asserts.assert_true(
956 ad.droid.wifiSetWifiApConfiguration(config),
957 "Failed to update WifiAp Configuration")
Girish Moturu40d7dc22016-11-02 12:14:56 -0700958 ad.droid.wifiStartTrackingTetherStateChange()
959 ad.droid.connectivityStartTethering(tel_defines.TETHERING_WIFI, False)
Rebecca Silbersteina2889852016-08-11 00:48:53 -0700960 try:
Girish Moturu40d7dc22016-11-02 12:14:56 -0700961 ad.ed.pop_event("ConnectivityManagerOnTetheringStarted")
962 ad.ed.wait_for_event("TetherStateChanged",
Betty Zhou3caa0982017-02-22 19:26:20 -0800963 lambda x: x["data"]["ACTIVE_TETHER"], 30)
Ang Li76216d12016-09-20 14:51:57 -0700964 ad.log.debug("Tethering started successfully.")
Rebecca Silbersteina2889852016-08-11 00:48:53 -0700965 except Empty:
966 msg = "Failed to receive confirmation of wifi tethering starting"
967 asserts.fail(msg)
968 finally:
Girish Moturu40d7dc22016-11-02 12:14:56 -0700969 ad.droid.wifiStopTrackingTetherStateChange()
Ang Li73697b32015-12-03 00:41:53 +0000970
Bindu Mahadevff295782019-02-08 16:17:48 -0800971
lesl6d30a172020-03-05 15:05:22 +0800972def save_wifi_soft_ap_config(ad, wifi_config, band=None, hidden=None,
973 security=None, password=None,
974 channel=None, max_clients=None,
975 shutdown_timeout_enable=None,
976 shutdown_timeout_millis=None,
977 client_control_enable=None,
978 allowedList=None, blockedList=None):
979 """ Save a soft ap configuration and verified
980 Args:
981 ad: android_device to set soft ap configuration.
982 wifi_config: a soft ap configuration object, at least include SSID.
983 band: specifies the band for the soft ap.
984 hidden: specifies the soft ap need to broadcast its SSID or not.
985 security: specifies the security type for the soft ap.
986 password: specifies the password for the soft ap.
987 channel: specifies the channel for the soft ap.
988 max_clients: specifies the maximum connected client number.
989 shutdown_timeout_enable: specifies the auto shut down enable or not.
990 shutdown_timeout_millis: specifies the shut down timeout value.
991 client_control_enable: specifies the client control enable or not.
992 allowedList: specifies allowed clients list.
993 blockedList: specifies blocked clients list.
994 """
995 if security and password:
996 wifi_config[WifiEnums.SECURITY] = security
997 wifi_config[WifiEnums.PWD_KEY] = password
Girish Moturu528b5442018-06-07 10:48:14 -0700998 if band:
lesl6d30a172020-03-05 15:05:22 +0800999 wifi_config[WifiEnums.AP_BAND_KEY] = band
Girish Moturu528b5442018-06-07 10:48:14 -07001000 if hidden:
1001 wifi_config[WifiEnums.HIDDEN_KEY] = hidden
lesl6d30a172020-03-05 15:05:22 +08001002 if channel and band:
1003 wifi_config[WifiEnums.AP_BAND_KEY] = band
1004 wifi_config[WifiEnums.AP_CHANNEL_KEY] = channel
1005 if max_clients:
1006 wifi_config[WifiEnums.AP_MAXCLIENTS_KEY] = max_clients
1007 if shutdown_timeout_enable:
1008 wifi_config[
1009 WifiEnums.AP_SHUTDOWNTIMEOUTENABLE_KEY] = shutdown_timeout_enable
1010 if shutdown_timeout_millis:
1011 wifi_config[
1012 WifiEnums.AP_SHUTDOWNTIMEOUT_KEY] = shutdown_timeout_millis
1013 if client_control_enable:
1014 wifi_config[WifiEnums.AP_CLIENTCONTROL_KEY] = client_control_enable
1015 if allowedList:
1016 wifi_config[WifiEnums.AP_ALLOWEDLIST_KEY] = allowedList
1017 if blockedList:
1018 wifi_config[WifiEnums.AP_BLOCKEDLIST_KEY] = blockedList
1019
1020 if WifiEnums.AP_CHANNEL_KEY in wifi_config and wifi_config[
1021 WifiEnums.AP_CHANNEL_KEY] == 0:
1022 del wifi_config[WifiEnums.AP_CHANNEL_KEY]
1023
1024 if WifiEnums.SECURITY in wifi_config and wifi_config[
1025 WifiEnums.SECURITY] == WifiEnums.SoftApSecurityType.OPEN:
1026 del wifi_config[WifiEnums.SECURITY]
1027 del wifi_config[WifiEnums.PWD_KEY]
1028
Girish Moturu528b5442018-06-07 10:48:14 -07001029 asserts.assert_true(ad.droid.wifiSetWifiApConfiguration(wifi_config),
1030 "Failed to set WifiAp Configuration")
1031
1032 wifi_ap = ad.droid.wifiGetApConfiguration()
1033 asserts.assert_true(
1034 wifi_ap[WifiEnums.SSID_KEY] == wifi_config[WifiEnums.SSID_KEY],
lesl6d30a172020-03-05 15:05:22 +08001035 "Hotspot SSID doesn't match")
1036 if WifiEnums.SECURITY in wifi_config:
1037 asserts.assert_true(
1038 wifi_ap[WifiEnums.SECURITY] == wifi_config[WifiEnums.SECURITY],
1039 "Hotspot Security doesn't match")
1040 if WifiEnums.PWD_KEY in wifi_config:
1041 asserts.assert_true(
1042 wifi_ap[WifiEnums.PWD_KEY] == wifi_config[WifiEnums.PWD_KEY],
1043 "Hotspot Password doesn't match")
Girish Moturu528b5442018-06-07 10:48:14 -07001044
lesl6d30a172020-03-05 15:05:22 +08001045 if WifiEnums.HIDDEN_KEY in wifi_config:
1046 asserts.assert_true(
1047 wifi_ap[WifiEnums.HIDDEN_KEY] == wifi_config[WifiEnums.HIDDEN_KEY],
1048 "Hotspot hidden setting doesn't match")
1049
1050 if WifiEnums.AP_BAND_KEY in wifi_config:
1051 asserts.assert_true(
1052 wifi_ap[WifiEnums.AP_BAND_KEY] == wifi_config[WifiEnums.AP_BAND_KEY],
1053 "Hotspot Band doesn't match")
1054 if WifiEnums.AP_CHANNEL_KEY in wifi_config:
1055 asserts.assert_true(
1056 wifi_ap[WifiEnums.AP_CHANNEL_KEY] == wifi_config[
1057 WifiEnums.AP_CHANNEL_KEY], "Hotspot Channel doesn't match")
1058 if WifiEnums.AP_MAXCLIENTS_KEY in wifi_config:
1059 asserts.assert_true(
1060 wifi_ap[WifiEnums.AP_MAXCLIENTS_KEY] == wifi_config[
1061 WifiEnums.AP_MAXCLIENTS_KEY], "Hotspot Max Clients doesn't match")
1062 if WifiEnums.AP_SHUTDOWNTIMEOUTENABLE_KEY in wifi_config:
1063 asserts.assert_true(
1064 wifi_ap[WifiEnums.AP_SHUTDOWNTIMEOUTENABLE_KEY] == wifi_config[
1065 WifiEnums.AP_SHUTDOWNTIMEOUTENABLE_KEY],
1066 "Hotspot ShutDown feature flag doesn't match")
1067 if WifiEnums.AP_SHUTDOWNTIMEOUT_KEY in wifi_config:
1068 asserts.assert_true(
1069 wifi_ap[WifiEnums.AP_SHUTDOWNTIMEOUT_KEY] == wifi_config[
1070 WifiEnums.AP_SHUTDOWNTIMEOUT_KEY],
1071 "Hotspot ShutDown timeout setting doesn't match")
1072 if WifiEnums.AP_CLIENTCONTROL_KEY in wifi_config:
1073 asserts.assert_true(
1074 wifi_ap[WifiEnums.AP_CLIENTCONTROL_KEY] == wifi_config[
1075 WifiEnums.AP_CLIENTCONTROL_KEY],
1076 "Hotspot Client control flag doesn't match")
1077 if WifiEnums.AP_ALLOWEDLIST_KEY in wifi_config:
1078 asserts.assert_true(
1079 wifi_ap[WifiEnums.AP_ALLOWEDLIST_KEY] == wifi_config[
1080 WifiEnums.AP_ALLOWEDLIST_KEY],
1081 "Hotspot Allowed List doesn't match")
1082 if WifiEnums.AP_BLOCKEDLIST_KEY in wifi_config:
1083 asserts.assert_true(
1084 wifi_ap[WifiEnums.AP_BLOCKEDLIST_KEY] == wifi_config[
1085 WifiEnums.AP_BLOCKEDLIST_KEY],
1086 "Hotspot Blocked List doesn't match")
Bindu Mahadevff295782019-02-08 16:17:48 -08001087
Girish Moturu528b5442018-06-07 10:48:14 -07001088def start_wifi_tethering_saved_config(ad):
1089 """ Turn on wifi hotspot with a config that is already saved """
1090 ad.droid.wifiStartTrackingTetherStateChange()
1091 ad.droid.connectivityStartTethering(tel_defines.TETHERING_WIFI, False)
1092 try:
1093 ad.ed.pop_event("ConnectivityManagerOnTetheringStarted")
1094 ad.ed.wait_for_event("TetherStateChanged",
1095 lambda x: x["data"]["ACTIVE_TETHER"], 30)
1096 except:
1097 asserts.fail("Didn't receive wifi tethering starting confirmation")
1098 finally:
1099 ad.droid.wifiStopTrackingTetherStateChange()
Betty Zhou3caa0982017-02-22 19:26:20 -08001100
Bindu Mahadevff295782019-02-08 16:17:48 -08001101
Ang Li73697b32015-12-03 00:41:53 +00001102def stop_wifi_tethering(ad):
1103 """Stops wifi tethering on an android_device.
Ang Li73697b32015-12-03 00:41:53 +00001104 Args:
1105 ad: android_device to stop wifi tethering on.
1106 """
Girish Moturu40d7dc22016-11-02 12:14:56 -07001107 ad.droid.wifiStartTrackingTetherStateChange()
1108 ad.droid.connectivityStopTethering(tel_defines.TETHERING_WIFI)
Rebecca Silbersteina2889852016-08-11 00:48:53 -07001109 try:
Girish Moturu40d7dc22016-11-02 12:14:56 -07001110 ad.ed.pop_event("WifiManagerApDisabled", 30)
1111 ad.ed.wait_for_event("TetherStateChanged",
Betty Zhou3caa0982017-02-22 19:26:20 -08001112 lambda x: not x["data"]["ACTIVE_TETHER"], 30)
Rebecca Silbersteina2889852016-08-11 00:48:53 -07001113 except Empty:
1114 msg = "Failed to receive confirmation of wifi tethering stopping"
1115 asserts.fail(msg)
1116 finally:
Girish Moturu40d7dc22016-11-02 12:14:56 -07001117 ad.droid.wifiStopTrackingTetherStateChange()
Ang Li82522812016-06-02 13:57:21 -07001118
Ang Li76216d12016-09-20 14:51:57 -07001119
Roshan Pius58916a32016-06-16 16:26:44 -07001120def toggle_wifi_and_wait_for_reconnection(ad,
1121 network,
1122 num_of_tries=1,
1123 assert_on_fail=True):
1124 """Toggle wifi state and then wait for Android device to reconnect to
1125 the provided wifi network.
1126
1127 This expects the device to be already connected to the provided network.
1128
1129 Logic steps are
1130 1. Ensure that we're connected to the network.
1131 2. Turn wifi off.
1132 3. Wait for 10 seconds.
1133 4. Turn wifi on.
1134 5. Wait for the "connected" event, then confirm the connected ssid is the
1135 one requested.
1136
1137 Args:
1138 ad: android_device object to initiate connection on.
1139 network: A dictionary representing the network to await connection. The
1140 dictionary must have the key "SSID".
1141 num_of_tries: An integer that is the number of times to try before
1142 delaring failure. Default is 1.
1143 assert_on_fail: If True, error checks in this function will raise test
1144 failure signals.
1145
1146 Returns:
1147 If assert_on_fail is False, function returns True if the toggle was
1148 successful, False otherwise. If assert_on_fail is True, no return value.
1149 """
Betty Zhou3caa0982017-02-22 19:26:20 -08001150 return _assert_on_fail_handler(
1151 _toggle_wifi_and_wait_for_reconnection,
1152 assert_on_fail,
1153 ad,
1154 network,
1155 num_of_tries=num_of_tries)
Roshan Pius58916a32016-06-16 16:26:44 -07001156
1157
Girish Moturu5d9f4202019-12-03 15:29:21 -08001158def _toggle_wifi_and_wait_for_reconnection(ad, network, num_of_tries=3):
Roshan Pius58916a32016-06-16 16:26:44 -07001159 """Toggle wifi state and then wait for Android device to reconnect to
1160 the provided wifi network.
1161
1162 This expects the device to be already connected to the provided network.
1163
1164 Logic steps are
1165 1. Ensure that we're connected to the network.
1166 2. Turn wifi off.
1167 3. Wait for 10 seconds.
1168 4. Turn wifi on.
1169 5. Wait for the "connected" event, then confirm the connected ssid is the
1170 one requested.
1171
1172 This will directly fail a test if anything goes wrong.
1173
1174 Args:
1175 ad: android_device object to initiate connection on.
1176 network: A dictionary representing the network to await connection. The
1177 dictionary must have the key "SSID".
1178 num_of_tries: An integer that is the number of times to try before
1179 delaring failure. Default is 1.
1180 """
Roshan Pius58916a32016-06-16 16:26:44 -07001181 expected_ssid = network[WifiEnums.SSID_KEY]
1182 # First ensure that we're already connected to the provided network.
1183 verify_con = {WifiEnums.SSID_KEY: expected_ssid}
1184 verify_wifi_connection_info(ad, verify_con)
1185 # Now toggle wifi state and wait for the connection event.
1186 wifi_toggle_state(ad, False)
1187 time.sleep(10)
1188 wifi_toggle_state(ad, True)
1189 ad.droid.wifiStartTrackingStateChange()
1190 try:
1191 connect_result = None
1192 for i in range(num_of_tries):
1193 try:
Bindu Mahadev4e710362016-11-17 16:17:11 -08001194 connect_result = ad.ed.pop_event(wifi_constants.WIFI_CONNECTED,
Roshan Pius58916a32016-06-16 16:26:44 -07001195 30)
1196 break
1197 except Empty:
1198 pass
1199 asserts.assert_true(connect_result,
1200 "Failed to connect to Wi-Fi network %s on %s" %
Girish Moturu40d7dc22016-11-02 12:14:56 -07001201 (network, ad.serial))
Betty Zhou3caa0982017-02-22 19:26:20 -08001202 logging.debug("Connection result on %s: %s.", ad.serial,
1203 connect_result)
Roshan Pius58916a32016-06-16 16:26:44 -07001204 actual_ssid = connect_result['data'][WifiEnums.SSID_KEY]
1205 asserts.assert_equal(actual_ssid, expected_ssid,
1206 "Connected to the wrong network on %s."
1207 "Expected %s, but got %s." %
Girish Moturu40d7dc22016-11-02 12:14:56 -07001208 (ad.serial, expected_ssid, actual_ssid))
Betty Zhou3caa0982017-02-22 19:26:20 -08001209 logging.info("Connected to Wi-Fi network %s on %s", actual_ssid,
1210 ad.serial)
Roshan Pius58916a32016-06-16 16:26:44 -07001211 finally:
1212 ad.droid.wifiStopTrackingStateChange()
1213
1214
Roshan Piusd1204442018-11-12 12:20:39 -08001215def wait_for_connect(ad, expected_ssid=None, expected_id=None, tries=2,
Oscar Shucb9af9b2019-05-02 20:01:49 +00001216 assert_on_fail=True):
Roshan Piusd1204442018-11-12 12:20:39 -08001217 """Wait for a connect event.
1218
1219 This will directly fail a test if anything goes wrong.
1220
1221 Args:
1222 ad: An Android device object.
1223 expected_ssid: SSID of the network to connect to.
1224 expected_id: Network Id of the network to connect to.
1225 tries: An integer that is the number of times to try before failing.
1226 assert_on_fail: If True, error checks in this function will raise test
1227 failure signals.
1228
1229 Returns:
1230 Returns a value only if assert_on_fail is false.
1231 Returns True if the connection was successful, False otherwise.
1232 """
1233 return _assert_on_fail_handler(
1234 _wait_for_connect, assert_on_fail, ad, expected_ssid, expected_id,
Oscar Shucb9af9b2019-05-02 20:01:49 +00001235 tries)
Roshan Piusd1204442018-11-12 12:20:39 -08001236
1237
Oscar Shucb9af9b2019-05-02 20:01:49 +00001238def _wait_for_connect(ad, expected_ssid=None, expected_id=None, tries=2):
Roshan Piusd1204442018-11-12 12:20:39 -08001239 """Wait for a connect event.
1240
1241 Args:
1242 ad: An Android device object.
1243 expected_ssid: SSID of the network to connect to.
1244 expected_id: Network Id of the network to connect to.
1245 tries: An integer that is the number of times to try before failing.
1246 """
1247 ad.droid.wifiStartTrackingStateChange()
1248 try:
1249 connect_result = _wait_for_connect_event(
Oscar Shucb9af9b2019-05-02 20:01:49 +00001250 ad, ssid=expected_ssid, id=expected_id, tries=tries)
Roshan Piusd1204442018-11-12 12:20:39 -08001251 asserts.assert_true(connect_result,
1252 "Failed to connect to Wi-Fi network %s" %
1253 expected_ssid)
1254 ad.log.debug("Wi-Fi connection result: %s.", connect_result)
1255 actual_ssid = connect_result['data'][WifiEnums.SSID_KEY]
1256 if expected_ssid:
1257 asserts.assert_equal(actual_ssid, expected_ssid,
1258 "Connected to the wrong network")
1259 actual_id = connect_result['data'][WifiEnums.NETID_KEY]
1260 if expected_id:
1261 asserts.assert_equal(actual_id, expected_id,
1262 "Connected to the wrong network")
1263 ad.log.info("Connected to Wi-Fi network %s.", actual_ssid)
1264 except Empty:
1265 asserts.fail("Failed to start connection process to %s" %
1266 expected_ssid)
1267 except Exception as error:
1268 ad.log.error("Failed to connect to %s with error %s", expected_ssid,
1269 error)
1270 raise signals.TestFailure("Failed to connect to %s network" %
1271 expected_ssid)
1272 finally:
1273 ad.droid.wifiStopTrackingStateChange()
1274
1275
Oscar Shucb9af9b2019-05-02 20:01:49 +00001276def _wait_for_connect_event(ad, ssid=None, id=None, tries=1):
Bindu Mahadev3c54c492017-02-15 16:00:08 -08001277 """Wait for a connect event on queue and pop when available.
1278
1279 Args:
1280 ad: An Android device object.
Bindu Mahadevaf983c92017-03-27 12:00:37 -07001281 ssid: SSID of the network to connect to.
1282 id: Network Id of the network to connect to.
Bindu Mahadev3c54c492017-02-15 16:00:08 -08001283 tries: An integer that is the number of times to try before failing.
1284
1285 Returns:
1286 A dict with details of the connection data, which looks like this:
1287 {
1288 'time': 1485460337798,
1289 'name': 'WifiNetworkConnected',
1290 'data': {
1291 'rssi': -27,
1292 'is_24ghz': True,
1293 'mac_address': '02:00:00:00:00:00',
1294 'network_id': 1,
1295 'BSSID': '30:b5:c2:33:d3:fc',
1296 'ip_address': 117483712,
1297 'link_speed': 54,
1298 'supplicant_state': 'completed',
1299 'hidden_ssid': False,
1300 'SSID': 'wh_ap1_2g',
1301 'is_5ghz': False}
1302 }
1303
1304 """
Bindu Mahadevd4542a82017-04-05 09:50:17 -07001305 conn_result = None
Bindu Mahadevaf983c92017-03-27 12:00:37 -07001306
Bindu Mahadevd4542a82017-04-05 09:50:17 -07001307 # If ssid and network id is None, just wait for any connect event.
Bindu Mahadevaf983c92017-03-27 12:00:37 -07001308 if id is None and ssid is None:
Bindu Mahadevd4542a82017-04-05 09:50:17 -07001309 for i in range(tries):
1310 try:
1311 conn_result = ad.ed.pop_event(wifi_constants.WIFI_CONNECTED, 30)
Bindu Mahadevaf983c92017-03-27 12:00:37 -07001312 break
Bindu Mahadevd4542a82017-04-05 09:50:17 -07001313 except Empty:
1314 pass
1315 else:
1316 # If ssid or network id is specified, wait for specific connect event.
1317 for i in range(tries):
1318 try:
1319 conn_result = ad.ed.pop_event(wifi_constants.WIFI_CONNECTED, 30)
1320 if id and conn_result['data'][WifiEnums.NETID_KEY] == id:
1321 break
1322 elif ssid and conn_result['data'][WifiEnums.SSID_KEY] == ssid:
1323 break
1324 except Empty:
1325 pass
Bindu Mahadevaf983c92017-03-27 12:00:37 -07001326
Bindu Mahadevd4542a82017-04-05 09:50:17 -07001327 return conn_result
1328
Bindu Mahadevff295782019-02-08 16:17:48 -08001329
Roshan Piusffc29912019-01-18 13:39:49 -08001330def wait_for_disconnect(ad, timeout=10):
1331 """Wait for a disconnect event within the specified timeout.
Bindu Mahadevd4542a82017-04-05 09:50:17 -07001332
1333 Args:
1334 ad: Android device object.
Roshan Piusffc29912019-01-18 13:39:49 -08001335 timeout: Timeout in seconds.
Bindu Mahadevd4542a82017-04-05 09:50:17 -07001336
1337 """
1338 try:
1339 ad.droid.wifiStartTrackingStateChange()
Roshan Piusffc29912019-01-18 13:39:49 -08001340 event = ad.ed.pop_event("WifiNetworkDisconnected", timeout)
Roshan Piusbf7e3982018-02-15 12:37:41 -08001341 except Empty:
Bindu Mahadevd4542a82017-04-05 09:50:17 -07001342 raise signals.TestFailure("Device did not disconnect from the network")
Roshan Piusffc29912019-01-18 13:39:49 -08001343 finally:
1344 ad.droid.wifiStopTrackingStateChange()
1345
1346
1347def ensure_no_disconnect(ad, duration=10):
1348 """Ensure that there is no disconnect for the specified duration.
1349
1350 Args:
1351 ad: Android device object.
1352 duration: Duration in seconds.
1353
1354 """
1355 try:
1356 ad.droid.wifiStartTrackingStateChange()
1357 event = ad.ed.pop_event("WifiNetworkDisconnected", duration)
1358 raise signals.TestFailure("Device disconnected from the network")
1359 except Empty:
1360 pass
1361 finally:
1362 ad.droid.wifiStopTrackingStateChange()
Bindu Mahadev3c54c492017-02-15 16:00:08 -08001363
1364
Bindu Mahadev27c2d292018-03-19 16:13:08 -07001365def connect_to_wifi_network(ad, network, assert_on_fail=True,
Joe Brennan48c3f692019-04-11 08:30:16 -07001366 check_connectivity=True, hidden=False):
Bindu Mahadev3876ae52017-12-19 14:22:19 -08001367 """Connection logic for open and psk wifi networks.
1368
1369 Args:
Jong Wook Kim92356922018-02-06 18:32:49 -08001370 ad: AndroidDevice to use for connection
1371 network: network info of the network to connect to
1372 assert_on_fail: If true, errors from wifi_connect will raise
1373 test failure signals.
Joe Brennan48c3f692019-04-11 08:30:16 -07001374 hidden: Is the Wifi network hidden.
Bindu Mahadev3876ae52017-12-19 14:22:19 -08001375 """
Joe Brennan48c3f692019-04-11 08:30:16 -07001376 if hidden:
1377 start_wifi_connection_scan_and_ensure_network_not_found(
1378 ad, network[WifiEnums.SSID_KEY])
1379 else:
1380 start_wifi_connection_scan_and_ensure_network_found(
1381 ad, network[WifiEnums.SSID_KEY])
Jong Wook Kim92356922018-02-06 18:32:49 -08001382 wifi_connect(ad,
1383 network,
1384 num_of_tries=3,
Bindu Mahadev27c2d292018-03-19 16:13:08 -07001385 assert_on_fail=assert_on_fail,
1386 check_connectivity=check_connectivity)
Bindu Mahadev3876ae52017-12-19 14:22:19 -08001387
1388
1389def connect_to_wifi_network_with_id(ad, network_id, network_ssid):
1390 """Connect to the given network using network id and verify SSID.
1391
1392 Args:
1393 network_id: int Network Id of the network.
1394 network_ssid: string SSID of the network.
1395
1396 Returns: True if connect using network id was successful;
1397 False otherwise.
1398
1399 """
Jong Wook Kim92356922018-02-06 18:32:49 -08001400 start_wifi_connection_scan_and_ensure_network_found(ad, network_ssid)
Bindu Mahadev3876ae52017-12-19 14:22:19 -08001401 wifi_connect_by_id(ad, network_id)
1402 connect_data = ad.droid.wifiGetConnectionInfo()
1403 connect_ssid = connect_data[WifiEnums.SSID_KEY]
1404 ad.log.debug("Expected SSID = %s Connected SSID = %s" %
1405 (network_ssid, connect_ssid))
1406 if connect_ssid != network_ssid:
1407 return False
1408 return True
1409
1410
Bindu Mahadev27c2d292018-03-19 16:13:08 -07001411def wifi_connect(ad, network, num_of_tries=1, assert_on_fail=True,
Oscar Shucb9af9b2019-05-02 20:01:49 +00001412 check_connectivity=True):
Ang Li99d8c6d2015-12-09 15:56:13 -08001413 """Connect an Android device to a wifi network.
Ang Li73697b32015-12-03 00:41:53 +00001414
1415 Initiate connection to a wifi network, wait for the "connected" event, then
Ang Li99d8c6d2015-12-09 15:56:13 -08001416 confirm the connected ssid is the one requested.
Ang Li73697b32015-12-03 00:41:53 +00001417
Ang Li82522812016-06-02 13:57:21 -07001418 This will directly fail a test if anything goes wrong.
1419
Ang Li73697b32015-12-03 00:41:53 +00001420 Args:
1421 ad: android_device object to initiate connection on.
Ang Li99d8c6d2015-12-09 15:56:13 -08001422 network: A dictionary representing the network to connect to. The
Ang Li82522812016-06-02 13:57:21 -07001423 dictionary must have the key "SSID".
1424 num_of_tries: An integer that is the number of times to try before
1425 delaring failure. Default is 1.
1426 assert_on_fail: If True, error checks in this function will raise test
1427 failure signals.
1428
1429 Returns:
Bindu Mahadev3c54c492017-02-15 16:00:08 -08001430 Returns a value only if assert_on_fail is false.
1431 Returns True if the connection was successful, False otherwise.
Ang Li73697b32015-12-03 00:41:53 +00001432 """
Betty Zhou3caa0982017-02-22 19:26:20 -08001433 return _assert_on_fail_handler(
Bindu Mahadev27c2d292018-03-19 16:13:08 -07001434 _wifi_connect, assert_on_fail, ad, network, num_of_tries=num_of_tries,
Oscar Shucb9af9b2019-05-02 20:01:49 +00001435 check_connectivity=check_connectivity)
Ang Li82522812016-06-02 13:57:21 -07001436
1437
Oscar Shucb9af9b2019-05-02 20:01:49 +00001438def _wifi_connect(ad, network, num_of_tries=1, check_connectivity=True):
Ang Li82522812016-06-02 13:57:21 -07001439 """Connect an Android device to a wifi network.
1440
1441 Initiate connection to a wifi network, wait for the "connected" event, then
1442 confirm the connected ssid is the one requested.
1443
1444 This will directly fail a test if anything goes wrong.
1445
1446 Args:
1447 ad: android_device object to initiate connection on.
1448 network: A dictionary representing the network to connect to. The
1449 dictionary must have the key "SSID".
1450 num_of_tries: An integer that is the number of times to try before
1451 delaring failure. Default is 1.
1452 """
Ang Li82522812016-06-02 13:57:21 -07001453 asserts.assert_true(WifiEnums.SSID_KEY in network,
1454 "Key '%s' must be present in network definition." %
1455 WifiEnums.SSID_KEY)
Ang Li99d8c6d2015-12-09 15:56:13 -08001456 ad.droid.wifiStartTrackingStateChange()
Betty Zhoud35dab82016-12-06 15:24:23 -08001457 expected_ssid = network[WifiEnums.SSID_KEY]
Bindu Mahadev50374df2017-01-04 11:03:32 -08001458 ad.droid.wifiConnectByConfig(network)
1459 ad.log.info("Starting connection process to %s", expected_ssid)
Ang Li73697b32015-12-03 00:41:53 +00001460 try:
Bindu Mahadev50374df2017-01-04 11:03:32 -08001461 event = ad.ed.pop_event(wifi_constants.CONNECT_BY_CONFIG_SUCCESS, 30)
Roshan Piusd1204442018-11-12 12:20:39 -08001462 connect_result = _wait_for_connect_event(
Oscar Shucb9af9b2019-05-02 20:01:49 +00001463 ad, ssid=expected_ssid, tries=num_of_tries)
Ang Li82522812016-06-02 13:57:21 -07001464 asserts.assert_true(connect_result,
1465 "Failed to connect to Wi-Fi network %s on %s" %
Girish Moturubc48d9f2016-11-01 13:24:14 -07001466 (network, ad.serial))
Ang Li31b00782016-06-21 13:04:23 -07001467 ad.log.debug("Wi-Fi connection result: %s.", connect_result)
Ang Li99d8c6d2015-12-09 15:56:13 -08001468 actual_ssid = connect_result['data'][WifiEnums.SSID_KEY]
Ang Li82522812016-06-02 13:57:21 -07001469 asserts.assert_equal(actual_ssid, expected_ssid,
Betty Zhou3caa0982017-02-22 19:26:20 -08001470 "Connected to the wrong network on %s." %
1471 ad.serial)
Ang Li31b00782016-06-21 13:04:23 -07001472 ad.log.info("Connected to Wi-Fi network %s.", actual_ssid)
Bindu Mahadev50374df2017-01-04 11:03:32 -08001473
1474 # Wait for data connection to stabilize.
1475 time.sleep(5)
1476
Bindu Mahadev27c2d292018-03-19 16:13:08 -07001477 if check_connectivity:
Girish Moturua2a5bf22019-08-16 09:52:29 -07001478 internet = validate_connection(ad, DEFAULT_PING_ADDR, 10)
Bindu Mahadev27c2d292018-03-19 16:13:08 -07001479 if not internet:
1480 raise signals.TestFailure("Failed to connect to internet on %s" %
1481 expected_ssid)
Bindu Mahadev50374df2017-01-04 11:03:32 -08001482 except Empty:
1483 asserts.fail("Failed to start connection process to %s on %s" %
1484 (network, ad.serial))
Bindu Mahadev4e710362016-11-17 16:17:11 -08001485 except Exception as error:
Bindu Mahadev50374df2017-01-04 11:03:32 -08001486 ad.log.error("Failed to connect to %s with error %s", expected_ssid,
1487 error)
1488 raise signals.TestFailure("Failed to connect to %s network" % network)
1489
Ang Li73697b32015-12-03 00:41:53 +00001490 finally:
Ang Li99d8c6d2015-12-09 15:56:13 -08001491 ad.droid.wifiStopTrackingStateChange()
Ang Li73697b32015-12-03 00:41:53 +00001492
Bindu Mahadev50374df2017-01-04 11:03:32 -08001493
Oscar Shucb9af9b2019-05-02 20:01:49 +00001494def wifi_connect_by_id(ad, network_id, num_of_tries=3, assert_on_fail=True):
Bindu Mahadev3c54c492017-02-15 16:00:08 -08001495 """Connect an Android device to a wifi network using network Id.
1496
1497 Start connection to the wifi network, with the given network Id, wait for
1498 the "connected" event, then verify the connected network is the one requested.
1499
1500 This will directly fail a test if anything goes wrong.
1501
1502 Args:
1503 ad: android_device object to initiate connection on.
1504 network_id: Integer specifying the network id of the network.
1505 num_of_tries: An integer that is the number of times to try before
1506 delaring failure. Default is 1.
1507 assert_on_fail: If True, error checks in this function will raise test
1508 failure signals.
1509
1510 Returns:
1511 Returns a value only if assert_on_fail is false.
1512 Returns True if the connection was successful, False otherwise.
1513 """
1514 _assert_on_fail_handler(_wifi_connect_by_id, assert_on_fail, ad,
Oscar Shucb9af9b2019-05-02 20:01:49 +00001515 network_id, num_of_tries)
Bindu Mahadev3c54c492017-02-15 16:00:08 -08001516
1517
Oscar Shucb9af9b2019-05-02 20:01:49 +00001518def _wifi_connect_by_id(ad, network_id, num_of_tries=1):
Bindu Mahadev3c54c492017-02-15 16:00:08 -08001519 """Connect an Android device to a wifi network using it's network id.
1520
1521 Start connection to the wifi network, with the given network id, wait for
1522 the "connected" event, then verify the connected network is the one requested.
1523
1524 Args:
1525 ad: android_device object to initiate connection on.
1526 network_id: Integer specifying the network id of the network.
1527 num_of_tries: An integer that is the number of times to try before
1528 delaring failure. Default is 1.
1529 """
Bindu Mahadev3c54c492017-02-15 16:00:08 -08001530 ad.droid.wifiStartTrackingStateChange()
Bindu Mahadevaf983c92017-03-27 12:00:37 -07001531 # Clear all previous events.
1532 ad.ed.clear_all_events()
Bindu Mahadev3c54c492017-02-15 16:00:08 -08001533 ad.droid.wifiConnectByNetworkId(network_id)
1534 ad.log.info("Starting connection to network with id %d", network_id)
1535 try:
1536 event = ad.ed.pop_event(wifi_constants.CONNECT_BY_NETID_SUCCESS, 60)
Roshan Piusd1204442018-11-12 12:20:39 -08001537 connect_result = _wait_for_connect_event(
Oscar Shucb9af9b2019-05-02 20:01:49 +00001538 ad, id=network_id, tries=num_of_tries)
Bindu Mahadev3c54c492017-02-15 16:00:08 -08001539 asserts.assert_true(connect_result,
1540 "Failed to connect to Wi-Fi network using network id")
1541 ad.log.debug("Wi-Fi connection result: %s", connect_result)
1542 actual_id = connect_result['data'][WifiEnums.NETID_KEY]
1543 asserts.assert_equal(actual_id, network_id,
1544 "Connected to the wrong network on %s."
1545 "Expected network id = %d, but got %d." %
1546 (ad.serial, network_id, actual_id))
1547 expected_ssid = connect_result['data'][WifiEnums.SSID_KEY]
1548 ad.log.info("Connected to Wi-Fi network %s with %d network id.",
1549 expected_ssid, network_id)
1550
1551 # Wait for data connection to stabilize.
1552 time.sleep(5)
1553
1554 internet = validate_connection(ad, DEFAULT_PING_ADDR)
1555 if not internet:
1556 raise signals.TestFailure("Failed to connect to internet on %s" %
1557 expected_ssid)
1558 except Empty:
1559 asserts.fail("Failed to connect to network with id %d on %s" %
1560 (network_id, ad.serial))
1561 except Exception as error:
1562 ad.log.error("Failed to connect to network with id %d with error %s",
1563 network_id, error)
1564 raise signals.TestFailure("Failed to connect to network with network"
1565 " id %d" % network_id)
1566 finally:
1567 ad.droid.wifiStopTrackingStateChange()
1568
Oscar Shu0b5ff4d2019-08-07 18:11:56 +00001569
Roshan Piusc999e5e2018-11-09 10:59:52 -08001570def wifi_connect_using_network_request(ad, network, network_specifier,
1571 num_of_tries=3, assert_on_fail=True):
1572 """Connect an Android device to a wifi network using network request.
1573
1574 Trigger a network request with the provided network specifier,
1575 wait for the "onMatch" event, ensure that the scan results in "onMatch"
1576 event contain the specified network, then simulate the user granting the
1577 request with the specified network selected. Then wait for the "onAvailable"
1578 network callback indicating successful connection to network.
1579
1580 This will directly fail a test if anything goes wrong.
1581
1582 Args:
1583 ad: android_device object to initiate connection on.
1584 network_specifier: A dictionary representing the network specifier to
1585 use.
1586 network: A dictionary representing the network to connect to. The
1587 dictionary must have the key "SSID".
1588 num_of_tries: An integer that is the number of times to try before
1589 delaring failure.
1590 assert_on_fail: If True, error checks in this function will raise test
1591 failure signals.
1592
1593 Returns:
1594 Returns a value only if assert_on_fail is false.
1595 Returns True if the connection was successful, False otherwise.
1596 """
1597 _assert_on_fail_handler(_wifi_connect_using_network_request, assert_on_fail,
1598 ad, network, network_specifier, num_of_tries)
1599
1600
1601def _wifi_connect_using_network_request(ad, network, network_specifier,
1602 num_of_tries=3):
1603 """Connect an Android device to a wifi network using network request.
1604
1605 Trigger a network request with the provided network specifier,
1606 wait for the "onMatch" event, ensure that the scan results in "onMatch"
1607 event contain the specified network, then simulate the user granting the
1608 request with the specified network selected. Then wait for the "onAvailable"
1609 network callback indicating successful connection to network.
1610
1611 Args:
1612 ad: android_device object to initiate connection on.
1613 network_specifier: A dictionary representing the network specifier to
1614 use.
1615 network: A dictionary representing the network to connect to. The
1616 dictionary must have the key "SSID".
1617 num_of_tries: An integer that is the number of times to try before
1618 delaring failure.
1619 """
1620 ad.droid.wifiRequestNetworkWithSpecifier(network_specifier)
1621 ad.log.info("Sent network request with %s", network_specifier)
1622 # Need a delay here because UI interaction should only start once wifi
1623 # starts processing the request.
1624 time.sleep(wifi_constants.NETWORK_REQUEST_CB_REGISTER_DELAY_SEC)
1625 _wait_for_wifi_connect_after_network_request(ad, network, num_of_tries)
1626
1627
1628def wait_for_wifi_connect_after_network_request(ad, network, num_of_tries=3,
1629 assert_on_fail=True):
1630 """
1631 Simulate and verify the connection flow after initiating the network
1632 request.
1633
1634 Wait for the "onMatch" event, ensure that the scan results in "onMatch"
1635 event contain the specified network, then simulate the user granting the
1636 request with the specified network selected. Then wait for the "onAvailable"
1637 network callback indicating successful connection to network.
1638
1639 Args:
1640 ad: android_device object to initiate connection on.
1641 network: A dictionary representing the network to connect to. The
1642 dictionary must have the key "SSID".
1643 num_of_tries: An integer that is the number of times to try before
1644 delaring failure.
1645 assert_on_fail: If True, error checks in this function will raise test
1646 failure signals.
1647
1648 Returns:
1649 Returns a value only if assert_on_fail is false.
1650 Returns True if the connection was successful, False otherwise.
1651 """
1652 _assert_on_fail_handler(_wait_for_wifi_connect_after_network_request,
1653 assert_on_fail, ad, network, num_of_tries)
1654
1655
1656def _wait_for_wifi_connect_after_network_request(ad, network, num_of_tries=3):
1657 """
1658 Simulate and verify the connection flow after initiating the network
1659 request.
1660
1661 Wait for the "onMatch" event, ensure that the scan results in "onMatch"
1662 event contain the specified network, then simulate the user granting the
1663 request with the specified network selected. Then wait for the "onAvailable"
1664 network callback indicating successful connection to network.
1665
1666 Args:
1667 ad: android_device object to initiate connection on.
1668 network: A dictionary representing the network to connect to. The
1669 dictionary must have the key "SSID".
1670 num_of_tries: An integer that is the number of times to try before
1671 delaring failure.
1672 """
1673 asserts.assert_true(WifiEnums.SSID_KEY in network,
1674 "Key '%s' must be present in network definition." %
1675 WifiEnums.SSID_KEY)
1676 ad.droid.wifiStartTrackingStateChange()
1677 expected_ssid = network[WifiEnums.SSID_KEY]
1678 ad.droid.wifiRegisterNetworkRequestMatchCallback()
1679 # Wait for the platform to scan and return a list of networks
1680 # matching the request
1681 try:
1682 matched_network = None
1683 for _ in [0, num_of_tries]:
1684 on_match_event = ad.ed.pop_event(
1685 wifi_constants.WIFI_NETWORK_REQUEST_MATCH_CB_ON_MATCH, 60)
1686 asserts.assert_true(on_match_event,
1687 "Network request on match not received.")
1688 matched_scan_results = on_match_event["data"]
1689 ad.log.debug("Network request on match results %s",
1690 matched_scan_results)
1691 matched_network = match_networks(
1692 {WifiEnums.SSID_KEY: network[WifiEnums.SSID_KEY]},
1693 matched_scan_results)
1694 if matched_network:
1695 break;
1696
1697 asserts.assert_true(
1698 matched_network, "Target network %s not found" % network)
1699
1700 ad.droid.wifiSendUserSelectionForNetworkRequestMatch(network)
1701 ad.log.info("Sent user selection for network request %s",
1702 expected_ssid)
1703
1704 # Wait for the platform to connect to the network.
1705 on_available_event = ad.ed.pop_event(
1706 wifi_constants.WIFI_NETWORK_CB_ON_AVAILABLE, 60)
1707 asserts.assert_true(on_available_event,
1708 "Network request on available not received.")
1709 connected_network = on_available_event["data"]
1710 ad.log.info("Connected to network %s", connected_network)
1711 asserts.assert_equal(connected_network[WifiEnums.SSID_KEY],
1712 expected_ssid,
1713 "Connected to the wrong network."
1714 "Expected %s, but got %s." %
1715 (network, connected_network))
1716 except Empty:
1717 asserts.fail("Failed to connect to %s" % expected_ssid)
1718 except Exception as error:
1719 ad.log.error("Failed to connect to %s with error %s",
1720 (expected_ssid, error))
1721 raise signals.TestFailure("Failed to connect to %s network" % network)
1722 finally:
1723 ad.droid.wifiStopTrackingStateChange()
1724
1725
Bindu Mahadevd4542a82017-04-05 09:50:17 -07001726def wifi_passpoint_connect(ad, passpoint_network, num_of_tries=1,
Oscar Shucb9af9b2019-05-02 20:01:49 +00001727 assert_on_fail=True):
Bindu Mahadev9dd48172017-03-06 17:04:34 -08001728 """Connect an Android device to a wifi network.
1729
1730 Initiate connection to a wifi network, wait for the "connected" event, then
1731 confirm the connected ssid is the one requested.
1732
1733 This will directly fail a test if anything goes wrong.
1734
1735 Args:
1736 ad: android_device object to initiate connection on.
Bindu Mahadevd4542a82017-04-05 09:50:17 -07001737 passpoint_network: SSID of the Passpoint network to connect to.
Bindu Mahadev9dd48172017-03-06 17:04:34 -08001738 num_of_tries: An integer that is the number of times to try before
1739 delaring failure. Default is 1.
1740 assert_on_fail: If True, error checks in this function will raise test
1741 failure signals.
1742
1743 Returns:
1744 If assert_on_fail is False, function returns network id, if the connect was
1745 successful, False otherwise. If assert_on_fail is True, no return value.
1746 """
Bindu Mahadevd4542a82017-04-05 09:50:17 -07001747 _assert_on_fail_handler(_wifi_passpoint_connect, assert_on_fail, ad,
Oscar Shucb9af9b2019-05-02 20:01:49 +00001748 passpoint_network, num_of_tries = num_of_tries)
Bindu Mahadev9dd48172017-03-06 17:04:34 -08001749
1750
Oscar Shucb9af9b2019-05-02 20:01:49 +00001751def _wifi_passpoint_connect(ad, passpoint_network, num_of_tries=1):
Bindu Mahadev9dd48172017-03-06 17:04:34 -08001752 """Connect an Android device to a wifi network.
1753
1754 Initiate connection to a wifi network, wait for the "connected" event, then
1755 confirm the connected ssid is the one requested.
1756
1757 This will directly fail a test if anything goes wrong.
1758
1759 Args:
1760 ad: android_device object to initiate connection on.
Bindu Mahadevd4542a82017-04-05 09:50:17 -07001761 passpoint_network: SSID of the Passpoint network to connect to.
Bindu Mahadev9dd48172017-03-06 17:04:34 -08001762 num_of_tries: An integer that is the number of times to try before
1763 delaring failure. Default is 1.
1764 """
Bindu Mahadev9dd48172017-03-06 17:04:34 -08001765 ad.droid.wifiStartTrackingStateChange()
Bindu Mahadevd4542a82017-04-05 09:50:17 -07001766 expected_ssid = passpoint_network
Bindu Mahadev9dd48172017-03-06 17:04:34 -08001767 ad.log.info("Starting connection process to passpoint %s", expected_ssid)
1768
1769 try:
Roshan Piusd1204442018-11-12 12:20:39 -08001770 connect_result = _wait_for_connect_event(
Oscar Shucb9af9b2019-05-02 20:01:49 +00001771 ad, expected_ssid, num_of_tries)
Bindu Mahadev9dd48172017-03-06 17:04:34 -08001772 asserts.assert_true(connect_result,
1773 "Failed to connect to WiFi passpoint network %s on"
1774 " %s" % (expected_ssid, ad.serial))
1775 ad.log.info("Wi-Fi connection result: %s.", connect_result)
1776 actual_ssid = connect_result['data'][WifiEnums.SSID_KEY]
1777 asserts.assert_equal(actual_ssid, expected_ssid,
1778 "Connected to the wrong network on %s." % ad.serial)
1779 ad.log.info("Connected to Wi-Fi passpoint network %s.", actual_ssid)
1780
1781 # Wait for data connection to stabilize.
1782 time.sleep(5)
1783
1784 internet = validate_connection(ad, DEFAULT_PING_ADDR)
1785 if not internet:
1786 raise signals.TestFailure("Failed to connect to internet on %s" %
1787 expected_ssid)
1788 except Exception as error:
1789 ad.log.error("Failed to connect to passpoint network %s with error %s",
1790 expected_ssid, error)
1791 raise signals.TestFailure("Failed to connect to %s passpoint network" %
1792 expected_ssid)
1793
1794 finally:
1795 ad.droid.wifiStopTrackingStateChange()
1796
1797
Bindu Mahadevd4542a82017-04-05 09:50:17 -07001798def delete_passpoint(ad, fqdn):
1799 """Delete a required Passpoint configuration."""
1800 try:
1801 ad.droid.removePasspointConfig(fqdn)
1802 return True
1803 except Exception as error:
1804 ad.log.error("Failed to remove passpoint configuration with FQDN=%s "
1805 "and error=%s" , fqdn, error)
1806 return False
1807
1808
Ang Li73697b32015-12-03 00:41:53 +00001809def start_wifi_single_scan(ad, scan_setting):
1810 """Starts wifi single shot scan.
1811
1812 Args:
1813 ad: android_device object to initiate connection on.
1814 scan_setting: A dict representing the settings of the scan.
1815
1816 Returns:
1817 If scan was started successfully, event data of success event is returned.
1818 """
Ang Li82522812016-06-02 13:57:21 -07001819 idx = ad.droid.wifiScannerStartScan(scan_setting)
1820 event = ad.ed.pop_event("WifiScannerScan%sonSuccess" % idx, SHORT_TIMEOUT)
Ang Li31b00782016-06-21 13:04:23 -07001821 ad.log.debug("Got event %s", event)
Ang Li73697b32015-12-03 00:41:53 +00001822 return event['data']
1823
Ang Li82522812016-06-02 13:57:21 -07001824
Ang Li73697b32015-12-03 00:41:53 +00001825def track_connection(ad, network_ssid, check_connection_count):
1826 """Track wifi connection to network changes for given number of counts
1827
1828 Args:
1829 ad: android_device object for forget network.
1830 network_ssid: network ssid to which connection would be tracked
1831 check_connection_count: Integer for maximum number network connection
Ang Li82522812016-06-02 13:57:21 -07001832 check.
Ang Li73697b32015-12-03 00:41:53 +00001833 Returns:
Ang Li73697b32015-12-03 00:41:53 +00001834 True if connection to given network happen, else return False.
1835 """
Girish Moturu40d7dc22016-11-02 12:14:56 -07001836 ad.droid.wifiStartTrackingStateChange()
Ang Li73697b32015-12-03 00:41:53 +00001837 while check_connection_count > 0:
Girish Moturu40d7dc22016-11-02 12:14:56 -07001838 connect_network = ad.ed.pop_event("WifiNetworkConnected", 120)
Ang Li31b00782016-06-21 13:04:23 -07001839 ad.log.info("Connected to network %s", connect_network)
Ang Li82522812016-06-02 13:57:21 -07001840 if (WifiEnums.SSID_KEY in connect_network['data'] and
1841 connect_network['data'][WifiEnums.SSID_KEY] == network_ssid):
1842 return True
Ang Li8e767182015-12-09 17:29:24 -08001843 check_connection_count -= 1
Girish Moturu40d7dc22016-11-02 12:14:56 -07001844 ad.droid.wifiStopTrackingStateChange()
Ang Li73697b32015-12-03 00:41:53 +00001845 return False
1846
Ang Li82522812016-06-02 13:57:21 -07001847
Ang Li73697b32015-12-03 00:41:53 +00001848def get_scan_time_and_channels(wifi_chs, scan_setting, stime_channel):
1849 """Calculate the scan time required based on the band or channels in scan
1850 setting
1851
1852 Args:
1853 wifi_chs: Object of channels supported
1854 scan_setting: scan setting used for start scan
1855 stime_channel: scan time per channel
1856
1857 Returns:
1858 scan_time: time required for completing a scan
1859 scan_channels: channel used for scanning
1860 """
1861 scan_time = 0
1862 scan_channels = []
1863 if "band" in scan_setting and "channels" not in scan_setting:
Ang Li8e767182015-12-09 17:29:24 -08001864 scan_channels = wifi_chs.band_to_freq(scan_setting["band"])
Ang Li73697b32015-12-03 00:41:53 +00001865 elif "channels" in scan_setting and "band" not in scan_setting:
Ang Li8e767182015-12-09 17:29:24 -08001866 scan_channels = scan_setting["channels"]
Ang Li73697b32015-12-03 00:41:53 +00001867 scan_time = len(scan_channels) * stime_channel
1868 for channel in scan_channels:
Ang Li8e767182015-12-09 17:29:24 -08001869 if channel in WifiEnums.DFS_5G_FREQUENCIES:
Ang Li82522812016-06-02 13:57:21 -07001870 scan_time += 132 #passive scan time on DFS
Ang Li73697b32015-12-03 00:41:53 +00001871 return scan_time, scan_channels
1872
Ang Li82522812016-06-02 13:57:21 -07001873
Ang Li73697b32015-12-03 00:41:53 +00001874def start_wifi_track_bssid(ad, track_setting):
1875 """Start tracking Bssid for the given settings.
1876
1877 Args:
1878 ad: android_device object.
1879 track_setting: Setting for which the bssid tracking should be started
1880
1881 Returns:
1882 If tracking started successfully, event data of success event is returned.
1883 """
Girish Moturu40d7dc22016-11-02 12:14:56 -07001884 idx = ad.droid.wifiScannerStartTrackingBssids(
Ang Li82522812016-06-02 13:57:21 -07001885 track_setting["bssidInfos"], track_setting["apLostThreshold"])
Girish Moturu40d7dc22016-11-02 12:14:56 -07001886 event = ad.ed.pop_event("WifiScannerBssid{}onSuccess".format(idx),
Betty Zhou3caa0982017-02-22 19:26:20 -08001887 SHORT_TIMEOUT)
Ang Li73697b32015-12-03 00:41:53 +00001888 return event['data']
1889
Ang Li82522812016-06-02 13:57:21 -07001890
Ang Li73697b32015-12-03 00:41:53 +00001891def convert_pem_key_to_pkcs8(in_file, out_file):
1892 """Converts the key file generated by us to the format required by
1893 Android using openssl.
1894
1895 The input file must have the extension "pem". The output file must
1896 have the extension "der".
1897
1898 Args:
1899 in_file: The original key file.
1900 out_file: The full path to the converted key file, including
1901 filename.
1902 """
Ang Li82522812016-06-02 13:57:21 -07001903 asserts.assert_true(in_file.endswith(".pem"), "Input file has to be .pem.")
1904 asserts.assert_true(
1905 out_file.endswith(".der"), "Output file has to be .der.")
Ang Li73697b32015-12-03 00:41:53 +00001906 cmd = ("openssl pkcs8 -inform PEM -in {} -outform DER -out {} -nocrypt"
1907 " -topk8").format(in_file, out_file)
Ang Lifee28402016-07-13 13:43:29 -07001908 utils.exe_cmd(cmd)
Ang Li73697b32015-12-03 00:41:53 +00001909
Ang Li82522812016-06-02 13:57:21 -07001910
Girish Moturu804a3492020-02-17 14:32:02 -08001911def validate_connection(ad, ping_addr=DEFAULT_PING_ADDR, wait_time=2,
1912 ping_gateway=True):
Ang Li73697b32015-12-03 00:41:53 +00001913 """Validate internet connection by pinging the address provided.
1914
1915 Args:
1916 ad: android_device object.
1917 ping_addr: address on internet for pinging.
Girish Moturua2a5bf22019-08-16 09:52:29 -07001918 wait_time: wait for some time before validating connection
Ang Li73697b32015-12-03 00:41:53 +00001919
1920 Returns:
Bindu Mahadev50374df2017-01-04 11:03:32 -08001921 ping output if successful, NULL otherwise.
Ang Li73697b32015-12-03 00:41:53 +00001922 """
Girish Moturua2a5bf22019-08-16 09:52:29 -07001923 # wait_time to allow for DHCP to complete.
1924 time.sleep(wait_time)
Girish Moturu804a3492020-02-17 14:32:02 -08001925 ping = False
1926 try:
1927 ping = ad.droid.httpPing(ping_addr)
1928 ad.log.info("Http ping result: %s.", ping)
1929 except:
1930 pass
1931 if not ping and ping_gateway:
1932 ad.log.info("Http ping failed. Pinging default gateway")
1933 gw = ad.droid.connectivityGetIPv4DefaultGateway()
1934 result = ad.adb.shell("ping -c 6 {}".format(gw))
1935 ad.log.info("Default gateway ping result: %s" % result)
1936 ping = False if "100% packet loss" in result else True
Ang Li73697b32015-12-03 00:41:53 +00001937 return ping
1938
Ang Li82522812016-06-02 13:57:21 -07001939
Ang Li73697b32015-12-03 00:41:53 +00001940#TODO(angli): This can only verify if an actual value is exactly the same.
1941# Would be nice to be able to verify an actual value is one of serveral.
1942def verify_wifi_connection_info(ad, expected_con):
1943 """Verifies that the information of the currently connected wifi network is
1944 as expected.
1945
1946 Args:
1947 expected_con: A dict representing expected key-value pairs for wifi
1948 connection. e.g. {"SSID": "test_wifi"}
1949 """
1950 current_con = ad.droid.wifiGetConnectionInfo()
Ang Li374d7602016-02-08 17:27:27 -08001951 case_insensitive = ["BSSID", "supplicant_state"]
Ang Li31b00782016-06-21 13:04:23 -07001952 ad.log.debug("Current connection: %s", current_con)
Ang Li73697b32015-12-03 00:41:53 +00001953 for k, expected_v in expected_con.items():
Ang Li9a66de72016-02-08 15:26:38 -08001954 # Do not verify authentication related fields.
1955 if k == "password":
1956 continue
Ang Li82522812016-06-02 13:57:21 -07001957 msg = "Field %s does not exist in wifi connection info %s." % (
1958 k, current_con)
Ang Li374d7602016-02-08 17:27:27 -08001959 if k not in current_con:
1960 raise signals.TestFailure(msg)
1961 actual_v = current_con[k]
1962 if k in case_insensitive:
1963 actual_v = actual_v.lower()
1964 expected_v = expected_v.lower()
Ang Li73697b32015-12-03 00:41:53 +00001965 msg = "Expected %s to be %s, actual %s is %s." % (k, expected_v, k,
Ang Li82522812016-06-02 13:57:21 -07001966 actual_v)
Ang Li374d7602016-02-08 17:27:27 -08001967 if actual_v != expected_v:
1968 raise signals.TestFailure(msg)
Ang Li73697b32015-12-03 00:41:53 +00001969
Ang Li82522812016-06-02 13:57:21 -07001970
Preetesh Barrettoe8c428b2019-02-14 09:15:44 -08001971def check_autoconnect_to_open_network(ad, conn_timeout=WIFI_CONNECTION_TIMEOUT_DEFAULT):
1972 """Connects to any open WiFI AP
1973 Args:
1974 timeout value in sec to wait for UE to connect to a WiFi AP
1975 Returns:
1976 True if UE connects to WiFi AP (supplicant_state = completed)
1977 False if UE fails to complete connection within WIFI_CONNECTION_TIMEOUT time.
1978 """
1979 if ad.droid.wifiCheckState():
1980 return True
1981 ad.droid.wifiToggleState()
1982 wifi_connection_state = None
1983 timeout = time.time() + conn_timeout
1984 while wifi_connection_state != "completed":
1985 wifi_connection_state = ad.droid.wifiGetConnectionInfo()[
1986 'supplicant_state']
1987 if time.time() > timeout:
1988 ad.log.warning("Failed to connect to WiFi AP")
1989 return False
1990 return True
1991
1992
Ang Li73697b32015-12-03 00:41:53 +00001993def expand_enterprise_config_by_phase2(config):
1994 """Take an enterprise config and generate a list of configs, each with
1995 a different phase2 auth type.
1996
1997 Args:
1998 config: A dict representing enterprise config.
1999
2000 Returns
2001 A list of enterprise configs.
2002 """
2003 results = []
Ang Li0e7e58f2016-02-22 12:15:02 -08002004 phase2_types = WifiEnums.EapPhase2
2005 if config[WifiEnums.Enterprise.EAP] == WifiEnums.Eap.PEAP:
2006 # Skip unsupported phase2 types for PEAP.
2007 phase2_types = [WifiEnums.EapPhase2.GTC, WifiEnums.EapPhase2.MSCHAPV2]
2008 for phase2_type in phase2_types:
Ang Li73697b32015-12-03 00:41:53 +00002009 # Skip a special case for passpoint TTLS.
2010 if (WifiEnums.Enterprise.FQDN in config and
Ang Li82522812016-06-02 13:57:21 -07002011 phase2_type == WifiEnums.EapPhase2.GTC):
Ang Li73697b32015-12-03 00:41:53 +00002012 continue
2013 c = dict(config)
Girish Moturu150d32f2017-02-14 12:27:07 -08002014 c[WifiEnums.Enterprise.PHASE2] = phase2_type.value
Ang Li73697b32015-12-03 00:41:53 +00002015 results.append(c)
2016 return results
Ang Li2d3fe982016-06-08 10:00:43 -07002017
2018
Girish Moturub48a13c2017-02-27 11:36:42 -08002019def generate_eap_test_name(config, ad=None):
Girish Moturu150d32f2017-02-14 12:27:07 -08002020 """ Generates a test case name based on an EAP configuration.
2021
2022 Args:
2023 config: A dict representing an EAP credential.
Girish Moturub48a13c2017-02-27 11:36:42 -08002024 ad object: Redundant but required as the same param is passed
2025 to test_func in run_generated_tests
Girish Moturu150d32f2017-02-14 12:27:07 -08002026
2027 Returns:
2028 A string representing the name of a generated EAP test case.
2029 """
2030 eap = WifiEnums.Eap
2031 eap_phase2 = WifiEnums.EapPhase2
Girish Moturub48a13c2017-02-27 11:36:42 -08002032 Ent = WifiEnums.Enterprise
Girish Moturu150d32f2017-02-14 12:27:07 -08002033 name = "test_connect-"
2034 eap_name = ""
2035 for e in eap:
2036 if e.value == config[Ent.EAP]:
2037 eap_name = e.name
2038 break
2039 if "peap0" in config[WifiEnums.SSID_KEY].lower():
2040 eap_name = "PEAP0"
2041 if "peap1" in config[WifiEnums.SSID_KEY].lower():
2042 eap_name = "PEAP1"
2043 name += eap_name
2044 if Ent.PHASE2 in config:
2045 for e in eap_phase2:
2046 if e.value == config[Ent.PHASE2]:
2047 name += "-{}".format(e.name)
2048 break
2049 return name
2050
2051
Ang Li2d3fe982016-06-08 10:00:43 -07002052def group_attenuators(attenuators):
2053 """Groups a list of attenuators into attenuator groups for backward
2054 compatibility reasons.
2055
2056 Most legacy Wi-Fi setups have two attenuators each connected to a separate
2057 AP. The new Wi-Fi setup has four attenuators, each connected to one channel
2058 on an AP, so two of them are connected to one AP.
2059
2060 To make the existing scripts work in the new setup, when the script needs
2061 to attenuate one AP, it needs to set attenuation on both attenuators
2062 connected to the same AP.
2063
2064 This function groups attenuators properly so the scripts work in both
2065 legacy and new Wi-Fi setups.
2066
2067 Args:
2068 attenuators: A list of attenuator objects, either two or four in length.
2069
2070 Raises:
2071 signals.TestFailure is raised if the attenuator list does not have two
2072 or four objects.
2073 """
2074 attn0 = attenuator.AttenuatorGroup("AP0")
2075 attn1 = attenuator.AttenuatorGroup("AP1")
2076 # Legacy testbed setup has two attenuation channels.
2077 num_of_attns = len(attenuators)
2078 if num_of_attns == 2:
2079 attn0.add(attenuators[0])
2080 attn1.add(attenuators[1])
2081 elif num_of_attns == 4:
2082 attn0.add(attenuators[0])
2083 attn0.add(attenuators[1])
2084 attn1.add(attenuators[2])
2085 attn1.add(attenuators[3])
2086 else:
2087 asserts.fail(("Either two or four attenuators are required for this "
2088 "test, but found %s") % num_of_attns)
2089 return [attn0, attn1]
Jong Wook Kim92356922018-02-06 18:32:49 -08002090
Bindu Mahadevff295782019-02-08 16:17:48 -08002091
Girish Moturu36348a32019-12-10 08:41:54 -08002092def set_attns(attenuator, attn_val_name, roaming_attn=ROAMING_ATTN):
Bindu Mahadev7060a9f2018-05-04 13:48:12 -07002093 """Sets attenuation values on attenuators used in this test.
2094
2095 Args:
2096 attenuator: The attenuator object.
2097 attn_val_name: Name of the attenuation value pair to use.
Girish Moturu36348a32019-12-10 08:41:54 -08002098 roaming_attn: Dictionary specifying the attenuation params.
Bindu Mahadev7060a9f2018-05-04 13:48:12 -07002099 """
2100 logging.info("Set attenuation values to %s", roaming_attn[attn_val_name])
2101 try:
2102 attenuator[0].set_atten(roaming_attn[attn_val_name][0])
2103 attenuator[1].set_atten(roaming_attn[attn_val_name][1])
2104 attenuator[2].set_atten(roaming_attn[attn_val_name][2])
2105 attenuator[3].set_atten(roaming_attn[attn_val_name][3])
2106 except:
2107 logging.exception("Failed to set attenuation values %s.",
2108 attn_val_name)
2109 raise
2110
Girish Moturu36348a32019-12-10 08:41:54 -08002111def set_attns_steps(attenuators,
2112 atten_val_name,
2113 roaming_attn=ROAMING_ATTN,
2114 steps=10,
2115 wait_time=12):
Hsiu-Chang Chen73ea3342019-05-22 11:20:08 +08002116 """Set attenuation values on attenuators used in this test. It will change
2117 the attenuation values linearly from current value to target value step by
2118 step.
2119
2120 Args:
2121 attenuators: The list of attenuator objects that you want to change
2122 their attenuation value.
2123 atten_val_name: Name of the attenuation value pair to use.
Girish Moturu36348a32019-12-10 08:41:54 -08002124 roaming_attn: Dictionary specifying the attenuation params.
Hsiu-Chang Chen73ea3342019-05-22 11:20:08 +08002125 steps: Number of attenuator changes to reach the target value.
2126 wait_time: Sleep time for each change of attenuator.
2127 """
2128 logging.info("Set attenuation values to %s in %d step(s)",
2129 roaming_attn[atten_val_name], steps)
2130 start_atten = [attenuator.get_atten() for attenuator in attenuators]
2131 target_atten = roaming_attn[atten_val_name]
2132 for current_step in range(steps):
2133 progress = (current_step + 1) / steps
2134 for i, attenuator in enumerate(attenuators):
2135 amount_since_start = (target_atten[i] - start_atten[i]) * progress
2136 attenuator.set_atten(round(start_atten[i] + amount_since_start))
2137 time.sleep(wait_time)
2138
Bindu Mahadev7060a9f2018-05-04 13:48:12 -07002139
Girish Moturu36348a32019-12-10 08:41:54 -08002140def trigger_roaming_and_validate(dut,
2141 attenuator,
2142 attn_val_name,
2143 expected_con,
2144 roaming_attn=ROAMING_ATTN):
Bindu Mahadev7060a9f2018-05-04 13:48:12 -07002145 """Sets attenuators to trigger roaming and validate the DUT connected
2146 to the BSSID expected.
2147
2148 Args:
2149 attenuator: The attenuator object.
2150 attn_val_name: Name of the attenuation value pair to use.
2151 expected_con: The network information of the expected network.
Girish Moturu36348a32019-12-10 08:41:54 -08002152 roaming_attn: Dictionary specifying the attenaution params.
Bindu Mahadev7060a9f2018-05-04 13:48:12 -07002153 """
2154 expected_con = {
2155 WifiEnums.SSID_KEY: expected_con[WifiEnums.SSID_KEY],
2156 WifiEnums.BSSID_KEY: expected_con["bssid"],
2157 }
Girish Moturu36348a32019-12-10 08:41:54 -08002158 set_attns_steps(attenuator, attn_val_name, roaming_attn)
Bindu Mahadev7060a9f2018-05-04 13:48:12 -07002159
Hsiu-Chang Chenef856402018-09-18 12:32:49 +08002160 verify_wifi_connection_info(dut, expected_con)
2161 expected_bssid = expected_con[WifiEnums.BSSID_KEY]
2162 logging.info("Roamed to %s successfully", expected_bssid)
2163 if not validate_connection(dut):
2164 raise signals.TestFailure("Fail to connect to internet on %s" %
2165 expected_bssid)
Jong Wook Kim92356922018-02-06 18:32:49 -08002166
2167def create_softap_config():
2168 """Create a softap config with random ssid and password."""
2169 ap_ssid = "softap_" + utils.rand_ascii_str(8)
2170 ap_password = utils.rand_ascii_str(8)
2171 logging.info("softap setup: %s %s", ap_ssid, ap_password)
2172 config = {
2173 WifiEnums.SSID_KEY: ap_ssid,
2174 WifiEnums.PWD_KEY: ap_password,
2175 }
2176 return config
Girish Moturucf4dccd2018-08-27 12:22:00 -07002177
Bindu Mahadevff295782019-02-08 16:17:48 -08002178def start_softap_and_verify(ad, band):
2179 """Bring-up softap and verify AP mode and in scan results.
2180
2181 Args:
2182 band: The band to use for softAP.
2183
2184 Returns: dict, the softAP config.
2185
2186 """
lesl2f0fb232019-11-05 16:35:28 +08002187 # Register before start the test.
2188 callbackId = ad.dut.droid.registerSoftApCallback()
2189 # Check softap info value is default
2190 frequency, bandwdith = get_current_softap_info(ad.dut, callbackId, True)
2191 asserts.assert_true(frequency == 0, "Softap frequency is not reset")
2192 asserts.assert_true(bandwdith == 0, "Softap bandwdith is not reset")
2193
Bindu Mahadevff295782019-02-08 16:17:48 -08002194 config = create_softap_config()
2195 start_wifi_tethering(ad.dut,
2196 config[WifiEnums.SSID_KEY],
2197 config[WifiEnums.PWD_KEY], band=band)
2198 asserts.assert_true(ad.dut.droid.wifiIsApEnabled(),
2199 "SoftAp is not reported as running")
2200 start_wifi_connection_scan_and_ensure_network_found(ad.dut_client,
2201 config[WifiEnums.SSID_KEY])
lesl2f0fb232019-11-05 16:35:28 +08002202
2203 # Check softap info can get from callback succeed and assert value should be
2204 # valid.
2205 frequency, bandwdith = get_current_softap_info(ad.dut, callbackId, True)
2206 asserts.assert_true(frequency > 0, "Softap frequency is not valid")
2207 asserts.assert_true(bandwdith > 0, "Softap bandwdith is not valid")
2208 # Unregister callback
2209 ad.dut.droid.unregisterSoftApCallback(callbackId)
2210
Bindu Mahadevff295782019-02-08 16:17:48 -08002211 return config
2212
lesle8e3c0a2019-02-22 17:06:04 +08002213def wait_for_expected_number_of_softap_clients(ad, callbackId,
2214 expected_num_of_softap_clients):
2215 """Wait for the number of softap clients to be updated as expected.
2216 Args:
2217 callbackId: Id of the callback associated with registering.
2218 expected_num_of_softap_clients: expected number of softap clients.
2219 """
2220 eventStr = wifi_constants.SOFTAP_CALLBACK_EVENT + str(
2221 callbackId) + wifi_constants.SOFTAP_NUMBER_CLIENTS_CHANGED
James Mattis5a5dd492020-05-14 13:09:43 -07002222 clientData = ad.ed.pop_event(eventStr, SHORT_TIMEOUT)['data']
2223 clientCount = clientData[wifi_constants.SOFTAP_NUMBER_CLIENTS_CALLBACK_KEY]
2224 clientMacAddresses = clientData[wifi_constants.SOFTAP_CLIENTS_MACS_CALLBACK_KEY]
2225 asserts.assert_equal(clientCount, expected_num_of_softap_clients,
2226 "The number of softap clients doesn't match the expected number")
2227 asserts.assert_equal(len(clientMacAddresses), expected_num_of_softap_clients,
2228 "The number of mac addresses doesn't match the expected number")
2229 for macAddress in clientMacAddresses:
2230 asserts.assert_true(checkMacAddress(macAddress), "An invalid mac address was returned")
2231
2232def checkMacAddress(input):
2233 """Validate whether a string is a valid mac address or not.
2234
2235 Args:
2236 input: The string to validate.
2237
2238 Returns: True/False, returns true for a valid mac address and false otherwise.
2239 """
2240 macValidationRegex = "[0-9a-f]{2}([-:]?)[0-9a-f]{2}(\\1[0-9a-f]{2}){4}$"
2241 if re.match(macValidationRegex, input.lower()):
2242 return True
2243 return False
lesle8e3c0a2019-02-22 17:06:04 +08002244
2245def wait_for_expected_softap_state(ad, callbackId, expected_softap_state):
2246 """Wait for the expected softap state change.
2247 Args:
2248 callbackId: Id of the callback associated with registering.
2249 expected_softap_state: The expected softap state.
2250 """
2251 eventStr = wifi_constants.SOFTAP_CALLBACK_EVENT + str(
2252 callbackId) + wifi_constants.SOFTAP_STATE_CHANGED
2253 asserts.assert_equal(ad.ed.pop_event(eventStr,
2254 SHORT_TIMEOUT)['data'][wifi_constants.
2255 SOFTAP_STATE_CHANGE_CALLBACK_KEY],
2256 expected_softap_state,
2257 "Softap state doesn't match with expected state")
2258
2259def get_current_number_of_softap_clients(ad, callbackId):
2260 """pop up all of softap client updated event from queue.
2261 Args:
2262 callbackId: Id of the callback associated with registering.
2263
2264 Returns:
2265 If exist aleast callback, returns last updated number_of_softap_clients.
2266 Returns None when no any match callback event in queue.
2267 """
2268 eventStr = wifi_constants.SOFTAP_CALLBACK_EVENT + str(
2269 callbackId) + wifi_constants.SOFTAP_NUMBER_CLIENTS_CHANGED
2270 events = ad.ed.pop_all(eventStr)
2271 for event in events:
2272 num_of_clients = event['data'][wifi_constants.
2273 SOFTAP_NUMBER_CLIENTS_CALLBACK_KEY]
2274 if len(events) == 0:
2275 return None
2276 return num_of_clients
Bindu Mahadevff295782019-02-08 16:17:48 -08002277
lesl2f0fb232019-11-05 16:35:28 +08002278def get_current_softap_info(ad, callbackId, least_one):
2279 """pop up all of softap info changed event from queue.
2280 Args:
2281 callbackId: Id of the callback associated with registering.
2282 least_one: Wait for the info callback event before pop all.
2283 Returns:
2284 Returns last updated information of softap.
2285 """
2286 eventStr = wifi_constants.SOFTAP_CALLBACK_EVENT + str(
2287 callbackId) + wifi_constants.SOFTAP_INFO_CHANGED
2288 ad.log.info("softap info dump from eventStr %s",
2289 eventStr)
2290 frequency = 0
2291 bandwidth = 0
2292 if (least_one):
2293 event = ad.ed.pop_event(eventStr, SHORT_TIMEOUT)
2294 frequency = event['data'][wifi_constants.
2295 SOFTAP_INFO_FREQUENCY_CALLBACK_KEY]
2296 bandwidth = event['data'][wifi_constants.
2297 SOFTAP_INFO_BANDWIDTH_CALLBACK_KEY]
2298 ad.log.info("softap info updated, frequency is %s, bandwidth is %s",
2299 frequency, bandwidth)
2300
2301 events = ad.ed.pop_all(eventStr)
2302 for event in events:
2303 frequency = event['data'][wifi_constants.
2304 SOFTAP_INFO_FREQUENCY_CALLBACK_KEY]
2305 bandwidth = event['data'][wifi_constants.
2306 SOFTAP_INFO_BANDWIDTH_CALLBACK_KEY]
2307 ad.log.info("softap info, frequency is %s, bandwidth is %s",
2308 frequency, bandwidth)
2309 return frequency, bandwidth
2310
2311
2312
Hsiu-Chang Chen6aac0d32019-05-15 14:21:08 +08002313def get_ssrdumps(ad, test_name=""):
2314 """Pulls dumps in the ssrdump dir
2315 Args:
2316 ad: android device object.
2317 test_name: test case name
2318 """
2319 logs = ad.get_file_names("/data/vendor/ssrdump/")
2320 if logs:
2321 ad.log.info("Pulling ssrdumps %s", logs)
2322 log_path = os.path.join(ad.log_path, test_name,
2323 "SSRDUMP_%s" % ad.serial)
Mark De Ruyter72f8df92020-02-12 13:44:49 -08002324 os.makedirs(log_path, exist_ok=True)
Hsiu-Chang Chen6aac0d32019-05-15 14:21:08 +08002325 ad.pull_files(logs, log_path)
2326 ad.adb.shell("find /data/vendor/ssrdump/ -type f -delete")
2327
Xianyuan Jia0e39e552019-01-24 17:17:47 -08002328def start_pcap(pcap, wifi_band, test_name):
Girish Moturucf4dccd2018-08-27 12:22:00 -07002329 """Start packet capture in monitor mode.
2330
2331 Args:
2332 pcap: packet capture object
2333 wifi_band: '2g' or '5g' or 'dual'
Bindu Mahadev76551c12018-12-13 19:42:14 +00002334 test_name: test name to be used for pcap file name
2335
2336 Returns:
xianyuanjia0431ba32018-12-14 09:56:42 -08002337 Dictionary with wifi band as key and the tuple
2338 (pcap Process object, log directory) as the value
Girish Moturucf4dccd2018-08-27 12:22:00 -07002339 """
Xianyuan Jia0e39e552019-01-24 17:17:47 -08002340 log_dir = os.path.join(
Xianyuan Jia5cd06bb2019-06-10 16:29:57 -07002341 context.get_current_context().get_full_output_path(), 'PacketCapture')
Mark De Ruyter72f8df92020-02-12 13:44:49 -08002342 os.makedirs(log_dir, exist_ok=True)
Girish Moturucf4dccd2018-08-27 12:22:00 -07002343 if wifi_band == 'dual':
2344 bands = [BAND_2G, BAND_5G]
2345 else:
2346 bands = [wifi_band]
xianyuanjia0431ba32018-12-14 09:56:42 -08002347 procs = {}
Girish Moturucf4dccd2018-08-27 12:22:00 -07002348 for band in bands:
xianyuanjia0431ba32018-12-14 09:56:42 -08002349 proc = pcap.start_packet_capture(band, log_dir, test_name)
2350 procs[band] = (proc, os.path.join(log_dir, test_name))
2351 return procs
Girish Moturucf4dccd2018-08-27 12:22:00 -07002352
Bindu Mahadevff295782019-02-08 16:17:48 -08002353
xianyuanjia0431ba32018-12-14 09:56:42 -08002354def stop_pcap(pcap, procs, test_status=None):
Bindu Mahadev76551c12018-12-13 19:42:14 +00002355 """Stop packet capture in monitor mode.
2356
2357 Since, the pcap logs in monitor mode can be very large, we will
2358 delete them if they are not required. 'test_status' if True, will delete
2359 the pcap files. If False, we will keep them.
Girish Moturucf4dccd2018-08-27 12:22:00 -07002360
2361 Args:
2362 pcap: packet capture object
xianyuanjia0431ba32018-12-14 09:56:42 -08002363 procs: dictionary returned by start_pcap
Bindu Mahadev76551c12018-12-13 19:42:14 +00002364 test_status: status of the test case
Girish Moturucf4dccd2018-08-27 12:22:00 -07002365 """
xianyuanjia0431ba32018-12-14 09:56:42 -08002366 for proc, fname in procs.values():
2367 pcap.stop_packet_capture(proc)
Bindu Mahadev76551c12018-12-13 19:42:14 +00002368
2369 if test_status:
xianyuanjia0431ba32018-12-14 09:56:42 -08002370 shutil.rmtree(os.path.dirname(fname))
Hsiu-Chang Chenf8578472018-09-18 12:23:42 +08002371
Jaineel95887fd2019-10-16 16:19:01 -07002372def verify_mac_not_found_in_pcap(ad, mac, packets):
xshuf7267682019-06-03 14:41:56 -07002373 """Verify that a mac address is not found in the captured packets.
2374
2375 Args:
Jaineel95887fd2019-10-16 16:19:01 -07002376 ad: android device object
xshuf7267682019-06-03 14:41:56 -07002377 mac: string representation of the mac address
2378 packets: packets obtained by rdpcap(pcap_fname)
2379 """
2380 for pkt in packets:
2381 logging.debug("Packet Summary = %s", pkt.summary())
2382 if mac in pkt.summary():
Jaineel95887fd2019-10-16 16:19:01 -07002383 asserts.fail("Device %s caught Factory MAC: %s in packet sniffer."
2384 "Packet = %s" % (ad.serial, mac, pkt.show()))
Bindu Mahadevff295782019-02-08 16:17:48 -08002385
Jaineel95887fd2019-10-16 16:19:01 -07002386def verify_mac_is_found_in_pcap(ad, mac, packets):
Nate Jiangc2c09c62019-06-05 17:26:08 -07002387 """Verify that a mac address is found in the captured packets.
2388
2389 Args:
Jaineel95887fd2019-10-16 16:19:01 -07002390 ad: android device object
Nate Jiangc2c09c62019-06-05 17:26:08 -07002391 mac: string representation of the mac address
2392 packets: packets obtained by rdpcap(pcap_fname)
2393 """
2394 for pkt in packets:
2395 if mac in pkt.summary():
2396 return
Jaineel95887fd2019-10-16 16:19:01 -07002397 asserts.fail("Did not find MAC = %s in packet sniffer."
2398 "for device %s" % (mac, ad.serial))
Nate Jiangc2c09c62019-06-05 17:26:08 -07002399
Hsiu-Chang Chenf8578472018-09-18 12:23:42 +08002400def start_cnss_diags(ads):
2401 for ad in ads:
2402 start_cnss_diag(ad)
2403
Bindu Mahadevff295782019-02-08 16:17:48 -08002404
Hsiu-Chang Chenf8578472018-09-18 12:23:42 +08002405def start_cnss_diag(ad):
2406 """Start cnss_diag to record extra wifi logs
2407
2408 Args:
2409 ad: android device object.
2410 """
2411 if ad.model in wifi_constants.DEVICES_USING_LEGACY_PROP:
2412 prop = wifi_constants.LEGACY_CNSS_DIAG_PROP
2413 else:
2414 prop = wifi_constants.CNSS_DIAG_PROP
2415 if ad.adb.getprop(prop) != 'true':
2416 ad.adb.shell("find /data/vendor/wifi/cnss_diag/wlan_logs/ -type f -delete")
2417 ad.adb.shell("setprop %s true" % prop, ignore_status=True)
2418
Bindu Mahadevff295782019-02-08 16:17:48 -08002419
Hsiu-Chang Chenf8578472018-09-18 12:23:42 +08002420def stop_cnss_diags(ads):
2421 for ad in ads:
2422 stop_cnss_diag(ad)
2423
Bindu Mahadevff295782019-02-08 16:17:48 -08002424
Hsiu-Chang Chenf8578472018-09-18 12:23:42 +08002425def stop_cnss_diag(ad):
2426 """Stops cnss_diag
2427
2428 Args:
2429 ad: android device object.
2430 """
2431 if ad.model in wifi_constants.DEVICES_USING_LEGACY_PROP:
2432 prop = wifi_constants.LEGACY_CNSS_DIAG_PROP
2433 else:
2434 prop = wifi_constants.CNSS_DIAG_PROP
2435 ad.adb.shell("setprop %s false" % prop, ignore_status=True)
2436
Bindu Mahadevff295782019-02-08 16:17:48 -08002437
Hsiu-Chang Chenf8578472018-09-18 12:23:42 +08002438def get_cnss_diag_log(ad, test_name=""):
2439 """Pulls the cnss_diag logs in the wlan_logs dir
2440 Args:
2441 ad: android device object.
2442 test_name: test case name
2443 """
2444 logs = ad.get_file_names("/data/vendor/wifi/cnss_diag/wlan_logs/")
2445 if logs:
2446 ad.log.info("Pulling cnss_diag logs %s", logs)
Xianyuan Jia0e39e552019-01-24 17:17:47 -08002447 log_path = os.path.join(ad.device_log_path, "CNSS_DIAG_%s" % ad.serial)
Mark De Ruyter72f8df92020-02-12 13:44:49 -08002448 os.makedirs(log_path, exist_ok=True)
Hsiu-Chang Chenf8578472018-09-18 12:23:42 +08002449 ad.pull_files(logs, log_path)
Bindu Mahadev7e5dc682019-02-01 16:53:34 -08002450
Bindu Mahadevff295782019-02-08 16:17:48 -08002451
David Sue4cd9c22019-03-26 18:07:26 -07002452LinkProbeResult = namedtuple('LinkProbeResult', (
2453 'is_success', 'stdout', 'elapsed_time', 'failure_reason'))
2454
2455
2456def send_link_probe(ad):
2457 """Sends a link probe to the currently connected AP, and returns whether the
2458 probe succeeded or not.
2459
2460 Args:
2461 ad: android device object
2462 Returns:
2463 LinkProbeResult namedtuple
2464 """
2465 stdout = ad.adb.shell('cmd wifi send-link-probe')
2466 asserts.assert_false('Error' in stdout or 'Exception' in stdout,
2467 'Exception while sending link probe: ' + stdout)
2468
2469 is_success = False
2470 elapsed_time = None
2471 failure_reason = None
2472 if 'succeeded' in stdout:
2473 is_success = True
2474 elapsed_time = next(
2475 (int(token) for token in stdout.split() if token.isdigit()), None)
2476 elif 'failed with reason' in stdout:
2477 failure_reason = next(
2478 (int(token) for token in stdout.split() if token.isdigit()), None)
2479 else:
2480 asserts.fail('Unexpected link probe result: ' + stdout)
2481
2482 return LinkProbeResult(
2483 is_success=is_success, stdout=stdout,
2484 elapsed_time=elapsed_time, failure_reason=failure_reason)
2485
2486
2487def send_link_probes(ad, num_probes, delay_sec):
2488 """Sends a sequence of link probes to the currently connected AP, and
2489 returns whether the probes succeeded or not.
2490
2491 Args:
2492 ad: android device object
2493 num_probes: number of probes to perform
2494 delay_sec: delay time between probes, in seconds
2495 Returns:
2496 List[LinkProbeResult] one LinkProbeResults for each probe
2497 """
2498 logging.info('Sending link probes')
2499 results = []
2500 for _ in range(num_probes):
2501 # send_link_probe() will also fail the test if it sees an exception
2502 # in the stdout of the adb shell command
2503 result = send_link_probe(ad)
2504 logging.info('link probe results: ' + str(result))
2505 results.append(result)
2506 time.sleep(delay_sec)
2507
2508 return results
2509
2510
Bindu Mahadev7e5dc682019-02-01 16:53:34 -08002511def ap_setup(test, index, ap, network, bandwidth=80, channel=6):
2512 """Set up the AP with provided network info.
2513
2514 Args:
2515 test: the calling test class object.
2516 index: int, index of the AP.
2517 ap: access_point object of the AP.
2518 network: dict with information of the network, including ssid,
2519 password and bssid.
2520 bandwidth: the operation bandwidth for the AP, default 80MHz.
2521 channel: the channel number for the AP.
2522 Returns:
2523 brconfigs: the bridge interface configs
2524 """
2525 bss_settings = []
2526 ssid = network[WifiEnums.SSID_KEY]
2527 test.access_points[index].close()
2528 time.sleep(5)
2529
2530 # Configure AP as required.
2531 if "password" in network.keys():
2532 password = network["password"]
2533 security = hostapd_security.Security(
2534 security_mode="wpa", password=password)
2535 else:
2536 security = hostapd_security.Security(security_mode=None, password=None)
2537 config = hostapd_ap_preset.create_ap_preset(
2538 channel=channel,
2539 ssid=ssid,
2540 security=security,
2541 bss_settings=bss_settings,
2542 vht_bandwidth=bandwidth,
2543 profile_name='whirlwind',
2544 iface_wlan_2g=ap.wlan_2g,
2545 iface_wlan_5g=ap.wlan_5g)
2546 ap.start_ap(config)
2547 logging.info("AP started on channel {} with SSID {}".format(channel, ssid))
Bindu Mahadevff295782019-02-08 16:17:48 -08002548
2549
2550def turn_ap_off(test, AP):
2551 """Bring down hostapd on the Access Point.
2552 Args:
2553 test: The test class object.
2554 AP: int, indicating which AP to turn OFF.
2555 """
2556 hostapd_2g = test.access_points[AP-1]._aps['wlan0'].hostapd
2557 if hostapd_2g.is_alive():
2558 hostapd_2g.stop()
2559 logging.debug('Turned WLAN0 AP%d off' % AP)
2560 hostapd_5g = test.access_points[AP-1]._aps['wlan1'].hostapd
2561 if hostapd_5g.is_alive():
2562 hostapd_5g.stop()
2563 logging.debug('Turned WLAN1 AP%d off' % AP)
2564
2565
2566def turn_ap_on(test, AP):
2567 """Bring up hostapd on the Access Point.
2568 Args:
2569 test: The test class object.
2570 AP: int, indicating which AP to turn ON.
2571 """
2572 hostapd_2g = test.access_points[AP-1]._aps['wlan0'].hostapd
2573 if not hostapd_2g.is_alive():
2574 hostapd_2g.start(hostapd_2g.config)
2575 logging.debug('Turned WLAN0 AP%d on' % AP)
2576 hostapd_5g = test.access_points[AP-1]._aps['wlan1'].hostapd
2577 if not hostapd_5g.is_alive():
2578 hostapd_5g.start(hostapd_5g.config)
2579 logging.debug('Turned WLAN1 AP%d on' % AP)
Joe Brennan48c3f692019-04-11 08:30:16 -07002580
2581
2582def turn_location_off_and_scan_toggle_off(ad):
2583 """Turns off wifi location scans."""
2584 utils.set_location_service(ad, False)
2585 ad.droid.wifiScannerToggleAlwaysAvailable(False)
2586 msg = "Failed to turn off location service's scan."
2587 asserts.assert_true(not ad.droid.wifiScannerIsAlwaysAvailable(), msg)
Alfie Chen675be872020-06-04 10:48:14 +08002588
2589
2590def set_softap_channel(dut, ap_iface='wlan1', cs_count=10, channel=2462):
2591 """ Set SoftAP mode channel
2592
2593 Args:
2594 dut: android device object
2595 ap_iface: interface of SoftAP mode.
2596 cs_count: how many beacon frames before switch channel, default = 10
2597 channel: a wifi channel.
2598 """
2599 chan_switch_cmd = 'hostapd_cli -i {} chan_switch {} {}'
2600 chan_switch_cmd_show = chan_switch_cmd.format(ap_iface,cs_count,channel)
2601 dut.log.info('adb shell {}'.format(chan_switch_cmd_show))
2602 chan_switch_result = dut.adb.shell(chan_switch_cmd.format(ap_iface,
2603 cs_count,
2604 channel))
2605 if chan_switch_result == 'OK':
2606 dut.log.info('switch hotspot channel to {}'.format(channel))
2607 return chan_switch_result
2608
2609 asserts.fail("Failed to switch hotspot channel")
2610