blob: 419f09f3a557fd2a028c3c61976a2203f33b1b9a [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
Xianyuan Jia63751fb2020-11-17 00:07:40 +000036from acts_contrib.test_utils.wifi import wifi_constants
37from acts_contrib.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 Moturuddc0d382020-08-24 12:08:41 -070053CNSS_DIAG_CONFIG_PATH = "/data/vendor/wifi/cnss_diag/"
54CNSS_DIAG_CONFIG_FILE = "cnss_diag.conf"
55
Girish Moturu36348a32019-12-10 08:41:54 -080056ROAMING_ATTN = {
Bindu Mahadev7060a9f2018-05-04 13:48:12 -070057 "AP1_on_AP2_off": [
58 0,
59 0,
Xianyuan Jia97a865e2020-11-10 02:09:40 +000060 95,
61 95
Bindu Mahadev7060a9f2018-05-04 13:48:12 -070062 ],
63 "AP1_off_AP2_on": [
Xianyuan Jia97a865e2020-11-10 02:09:40 +000064 95,
65 95,
Bindu Mahadev7060a9f2018-05-04 13:48:12 -070066 0,
67 0
68 ],
69 "default": [
70 0,
71 0,
72 0,
73 0
74 ]
75 }
Ang Li82522812016-06-02 13:57:21 -070076
Xianyuan Jia0e39e552019-01-24 17:17:47 -080077
Ang Li73697b32015-12-03 00:41:53 +000078class WifiEnums():
79
leslce9cf6d2020-02-19 16:37:07 +080080 SSID_KEY = "SSID" # Used for Wifi & SoftAp
Roshan Piusc999e5e2018-11-09 10:59:52 -080081 SSID_PATTERN_KEY = "ssidPattern"
Bindu Mahadev4c94b532019-01-09 12:20:10 -080082 NETID_KEY = "network_id"
leslce9cf6d2020-02-19 16:37:07 +080083 BSSID_KEY = "BSSID" # Used for Wifi & SoftAp
Roshan Piusc999e5e2018-11-09 10:59:52 -080084 BSSID_PATTERN_KEY = "bssidPattern"
leslce9cf6d2020-02-19 16:37:07 +080085 PWD_KEY = "password" # Used for Wifi & SoftAp
Ang Li73697b32015-12-03 00:41:53 +000086 frequency_key = "frequency"
lesl6d30a172020-03-05 15:05:22 +080087 HIDDEN_KEY = "hiddenSSID" # Used for Wifi & SoftAp
Roshan Piusd1204442018-11-12 12:20:39 -080088 IS_APP_INTERACTION_REQUIRED = "isAppInteractionRequired"
89 IS_USER_INTERACTION_REQUIRED = "isUserInteractionRequired"
Roshan Pius55fb7c42020-04-03 14:47:18 -070090 IS_SUGGESTION_METERED = "isMetered"
Roshan Piusd1204442018-11-12 12:20:39 -080091 PRIORITY = "priority"
leslce9cf6d2020-02-19 16:37:07 +080092 SECURITY = "security" # Used for Wifi & SoftAp
Ang Li73697b32015-12-03 00:41:53 +000093
leslce9cf6d2020-02-19 16:37:07 +080094 # Used for SoftAp
lesl6d30a172020-03-05 15:05:22 +080095 AP_BAND_KEY = "apBand"
96 AP_CHANNEL_KEY = "apChannel"
97 AP_MAXCLIENTS_KEY = "MaxNumberOfClients"
98 AP_SHUTDOWNTIMEOUT_KEY = "ShutdownTimeoutMillis"
99 AP_SHUTDOWNTIMEOUTENABLE_KEY = "AutoShutdownEnabled"
100 AP_CLIENTCONTROL_KEY = "ClientControlByUserEnabled"
101 AP_ALLOWEDLIST_KEY = "AllowedClientList"
102 AP_BLOCKEDLIST_KEY = "BlockedClientList"
103
leslce9cf6d2020-02-19 16:37:07 +0800104 WIFI_CONFIG_SOFTAP_BAND_2G = 1
105 WIFI_CONFIG_SOFTAP_BAND_5G = 2
106 WIFI_CONFIG_SOFTAP_BAND_2G_5G = 3
107 WIFI_CONFIG_SOFTAP_BAND_6G = 4
108 WIFI_CONFIG_SOFTAP_BAND_2G_6G = 5
109 WIFI_CONFIG_SOFTAP_BAND_5G_6G = 6
110 WIFI_CONFIG_SOFTAP_BAND_ANY = 7
111
112 # DO NOT USE IT for new test case! Replaced by WIFI_CONFIG_SOFTAP_BAND_
113 WIFI_CONFIG_APBAND_2G = WIFI_CONFIG_SOFTAP_BAND_2G
114 WIFI_CONFIG_APBAND_5G = WIFI_CONFIG_SOFTAP_BAND_5G
115 WIFI_CONFIG_APBAND_AUTO = WIFI_CONFIG_SOFTAP_BAND_2G_5G
116
117 WIFI_CONFIG_APBAND_2G_OLD = 0
118 WIFI_CONFIG_APBAND_5G_OLD = 1
119 WIFI_CONFIG_APBAND_AUTO_OLD = -1
Ang Li73697b32015-12-03 00:41:53 +0000120
Ang Li82522812016-06-02 13:57:21 -0700121 WIFI_WPS_INFO_PBC = 0
122 WIFI_WPS_INFO_DISPLAY = 1
123 WIFI_WPS_INFO_KEYPAD = 2
124 WIFI_WPS_INFO_LABEL = 3
125 WIFI_WPS_INFO_INVALID = 4
Ang Li73697b32015-12-03 00:41:53 +0000126
lesl6d30a172020-03-05 15:05:22 +0800127 class SoftApSecurityType():
128 OPEN = "NONE"
129 WPA2 = "WPA2_PSK"
130 WPA3_SAE_TRANSITION = "WPA3_SAE_TRANSITION"
131 WPA3_SAE = "WPA3_SAE"
132
Ang Li73697b32015-12-03 00:41:53 +0000133 class CountryCode():
134 CHINA = "CN"
Girish Moturua5ef35d2020-10-19 14:58:01 -0700135 GERMANY = "DE"
Ang Li73697b32015-12-03 00:41:53 +0000136 JAPAN = "JP"
137 UK = "GB"
138 US = "US"
139 UNKNOWN = "UNKNOWN"
140
141 # Start of Macros for EAP
142 # EAP types
143 class Eap(IntEnum):
144 NONE = -1
145 PEAP = 0
Ang Li82522812016-06-02 13:57:21 -0700146 TLS = 1
Ang Li73697b32015-12-03 00:41:53 +0000147 TTLS = 2
Ang Li82522812016-06-02 13:57:21 -0700148 PWD = 3
149 SIM = 4
150 AKA = 5
151 AKA_PRIME = 6
152 UNAUTH_TLS = 7
Ang Li73697b32015-12-03 00:41:53 +0000153
154 # EAP Phase2 types
155 class EapPhase2(IntEnum):
Ang Li82522812016-06-02 13:57:21 -0700156 NONE = 0
157 PAP = 1
158 MSCHAP = 2
159 MSCHAPV2 = 3
160 GTC = 4
Ang Li73697b32015-12-03 00:41:53 +0000161
162 class Enterprise:
Ang Li82522812016-06-02 13:57:21 -0700163 # Enterprise Config Macros
164 EMPTY_VALUE = "NULL"
165 EAP = "eap"
166 PHASE2 = "phase2"
167 IDENTITY = "identity"
168 ANON_IDENTITY = "anonymous_identity"
169 PASSWORD = "password"
170 SUBJECT_MATCH = "subject_match"
Ang Li73697b32015-12-03 00:41:53 +0000171 ALTSUBJECT_MATCH = "altsubject_match"
172 DOM_SUFFIX_MATCH = "domain_suffix_match"
Ang Li82522812016-06-02 13:57:21 -0700173 CLIENT_CERT = "client_cert"
174 CA_CERT = "ca_cert"
175 ENGINE = "engine"
176 ENGINE_ID = "engine_id"
177 PRIVATE_KEY_ID = "key_id"
178 REALM = "realm"
179 PLMN = "plmn"
180 FQDN = "FQDN"
181 FRIENDLY_NAME = "providerFriendlyName"
182 ROAMING_IDS = "roamingConsortiumIds"
Jimmy Chen7baec622020-06-23 19:00:33 +0800183 OCSP = "ocsp"
Ang Li73697b32015-12-03 00:41:53 +0000184 # End of Macros for EAP
185
186 # Macros for wifi p2p.
187 WIFI_P2P_SERVICE_TYPE_ALL = 0
188 WIFI_P2P_SERVICE_TYPE_BONJOUR = 1
189 WIFI_P2P_SERVICE_TYPE_UPNP = 2
190 WIFI_P2P_SERVICE_TYPE_VENDOR_SPECIFIC = 255
191
192 class ScanResult:
193 CHANNEL_WIDTH_20MHZ = 0
194 CHANNEL_WIDTH_40MHZ = 1
195 CHANNEL_WIDTH_80MHZ = 2
196 CHANNEL_WIDTH_160MHZ = 3
197 CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 4
198
199 # Macros for wifi rtt.
200 class RttType(IntEnum):
Ang Li82522812016-06-02 13:57:21 -0700201 TYPE_ONE_SIDED = 1
202 TYPE_TWO_SIDED = 2
Ang Li73697b32015-12-03 00:41:53 +0000203
204 class RttPeerType(IntEnum):
Ang Li82522812016-06-02 13:57:21 -0700205 PEER_TYPE_AP = 1
206 PEER_TYPE_STA = 2 # Requires NAN.
207 PEER_P2P_GO = 3
208 PEER_P2P_CLIENT = 4
209 PEER_NAN = 5
Ang Li73697b32015-12-03 00:41:53 +0000210
211 class RttPreamble(IntEnum):
Ang Li82522812016-06-02 13:57:21 -0700212 PREAMBLE_LEGACY = 0x01
213 PREAMBLE_HT = 0x02
214 PREAMBLE_VHT = 0x04
Ang Li73697b32015-12-03 00:41:53 +0000215
216 class RttBW(IntEnum):
Ang Li82522812016-06-02 13:57:21 -0700217 BW_5_SUPPORT = 0x01
218 BW_10_SUPPORT = 0x02
219 BW_20_SUPPORT = 0x04
220 BW_40_SUPPORT = 0x08
221 BW_80_SUPPORT = 0x10
Ang Li73697b32015-12-03 00:41:53 +0000222 BW_160_SUPPORT = 0x20
223
224 class Rtt(IntEnum):
Ang Li82522812016-06-02 13:57:21 -0700225 STATUS_SUCCESS = 0
226 STATUS_FAILURE = 1
227 STATUS_FAIL_NO_RSP = 2
228 STATUS_FAIL_REJECTED = 3
229 STATUS_FAIL_NOT_SCHEDULED_YET = 4
230 STATUS_FAIL_TM_TIMEOUT = 5
231 STATUS_FAIL_AP_ON_DIFF_CHANNEL = 6
232 STATUS_FAIL_NO_CAPABILITY = 7
233 STATUS_ABORTED = 8
234 STATUS_FAIL_INVALID_TS = 9
235 STATUS_FAIL_PROTOCOL = 10
236 STATUS_FAIL_SCHEDULE = 11
237 STATUS_FAIL_BUSY_TRY_LATER = 12
238 STATUS_INVALID_REQ = 13
239 STATUS_NO_WIFI = 14
240 STATUS_FAIL_FTM_PARAM_OVERRIDE = 15
Ang Li73697b32015-12-03 00:41:53 +0000241
Ang Li82522812016-06-02 13:57:21 -0700242 REASON_UNSPECIFIED = -1
243 REASON_NOT_AVAILABLE = -2
244 REASON_INVALID_LISTENER = -3
245 REASON_INVALID_REQUEST = -4
Ang Li73697b32015-12-03 00:41:53 +0000246
247 class RttParam:
248 device_type = "deviceType"
249 request_type = "requestType"
250 BSSID = "bssid"
251 channel_width = "channelWidth"
252 frequency = "frequency"
253 center_freq0 = "centerFreq0"
254 center_freq1 = "centerFreq1"
255 number_burst = "numberBurst"
256 interval = "interval"
257 num_samples_per_burst = "numSamplesPerBurst"
258 num_retries_per_measurement_frame = "numRetriesPerMeasurementFrame"
259 num_retries_per_FTMR = "numRetriesPerFTMR"
260 lci_request = "LCIRequest"
261 lcr_request = "LCRRequest"
262 burst_timeout = "burstTimeout"
263 preamble = "preamble"
264 bandwidth = "bandwidth"
265 margin = "margin"
266
267 RTT_MARGIN_OF_ERROR = {
268 RttBW.BW_80_SUPPORT: 2,
269 RttBW.BW_40_SUPPORT: 5,
270 RttBW.BW_20_SUPPORT: 5
271 }
272
273 # Macros as specified in the WifiScanner code.
Ang Li82522812016-06-02 13:57:21 -0700274 WIFI_BAND_UNSPECIFIED = 0 # not specified
275 WIFI_BAND_24_GHZ = 1 # 2.4 GHz band
276 WIFI_BAND_5_GHZ = 2 # 5 GHz band without DFS channels
277 WIFI_BAND_5_GHZ_DFS_ONLY = 4 # 5 GHz band with DFS channels
278 WIFI_BAND_5_GHZ_WITH_DFS = 6 # 5 GHz band with DFS channels
279 WIFI_BAND_BOTH = 3 # both bands without DFS channels
280 WIFI_BAND_BOTH_WITH_DFS = 7 # both bands with DFS channels
Ang Li73697b32015-12-03 00:41:53 +0000281
282 REPORT_EVENT_AFTER_BUFFER_FULL = 0
283 REPORT_EVENT_AFTER_EACH_SCAN = 1
284 REPORT_EVENT_FULL_SCAN_RESULT = 2
285
xshuaabcfeb2018-02-14 11:43:24 -0800286 SCAN_TYPE_LOW_LATENCY = 0
287 SCAN_TYPE_LOW_POWER = 1
288 SCAN_TYPE_HIGH_ACCURACY = 2
289
Ang Li73697b32015-12-03 00:41:53 +0000290 # US Wifi frequencies
291 ALL_2G_FREQUENCIES = [2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452,
292 2457, 2462]
293 DFS_5G_FREQUENCIES = [5260, 5280, 5300, 5320, 5500, 5520, 5540, 5560, 5580,
294 5600, 5620, 5640, 5660, 5680, 5700, 5720]
295 NONE_DFS_5G_FREQUENCIES = [5180, 5200, 5220, 5240, 5745, 5765, 5785, 5805,
296 5825]
297 ALL_5G_FREQUENCIES = DFS_5G_FREQUENCIES + NONE_DFS_5G_FREQUENCIES
298
299 band_to_frequencies = {
Ang Li82522812016-06-02 13:57:21 -0700300 WIFI_BAND_24_GHZ: ALL_2G_FREQUENCIES,
301 WIFI_BAND_5_GHZ: NONE_DFS_5G_FREQUENCIES,
302 WIFI_BAND_5_GHZ_DFS_ONLY: DFS_5G_FREQUENCIES,
303 WIFI_BAND_5_GHZ_WITH_DFS: ALL_5G_FREQUENCIES,
304 WIFI_BAND_BOTH: ALL_2G_FREQUENCIES + NONE_DFS_5G_FREQUENCIES,
305 WIFI_BAND_BOTH_WITH_DFS: ALL_5G_FREQUENCIES + ALL_2G_FREQUENCIES
Ang Li73697b32015-12-03 00:41:53 +0000306 }
307
308 # All Wifi frequencies to channels lookup.
309 freq_to_channel = {
310 2412: 1,
311 2417: 2,
312 2422: 3,
313 2427: 4,
314 2432: 5,
315 2437: 6,
316 2442: 7,
317 2447: 8,
318 2452: 9,
319 2457: 10,
320 2462: 11,
321 2467: 12,
322 2472: 13,
323 2484: 14,
324 4915: 183,
325 4920: 184,
326 4925: 185,
327 4935: 187,
328 4940: 188,
329 4945: 189,
330 4960: 192,
331 4980: 196,
332 5035: 7,
333 5040: 8,
334 5045: 9,
335 5055: 11,
336 5060: 12,
337 5080: 16,
338 5170: 34,
339 5180: 36,
340 5190: 38,
341 5200: 40,
342 5210: 42,
343 5220: 44,
344 5230: 46,
345 5240: 48,
346 5260: 52,
347 5280: 56,
348 5300: 60,
349 5320: 64,
350 5500: 100,
351 5520: 104,
352 5540: 108,
353 5560: 112,
354 5580: 116,
355 5600: 120,
356 5620: 124,
357 5640: 128,
358 5660: 132,
359 5680: 136,
360 5700: 140,
361 5745: 149,
362 5765: 153,
363 5785: 157,
Omar El Ayachdb8463b2020-05-15 18:08:23 -0700364 5795: 159,
Ang Li73697b32015-12-03 00:41:53 +0000365 5805: 161,
366 5825: 165,
367 }
368
369 # All Wifi channels to frequencies lookup.
370 channel_2G_to_freq = {
371 1: 2412,
372 2: 2417,
373 3: 2422,
374 4: 2427,
375 5: 2432,
376 6: 2437,
377 7: 2442,
378 8: 2447,
379 9: 2452,
380 10: 2457,
381 11: 2462,
382 12: 2467,
383 13: 2472,
384 14: 2484
385 }
386
387 channel_5G_to_freq = {
388 183: 4915,
389 184: 4920,
390 185: 4925,
391 187: 4935,
392 188: 4940,
393 189: 4945,
394 192: 4960,
395 196: 4980,
396 7: 5035,
397 8: 5040,
398 9: 5045,
399 11: 5055,
400 12: 5060,
401 16: 5080,
402 34: 5170,
403 36: 5180,
404 38: 5190,
405 40: 5200,
406 42: 5210,
407 44: 5220,
408 46: 5230,
409 48: 5240,
410 52: 5260,
411 56: 5280,
412 60: 5300,
413 64: 5320,
414 100: 5500,
415 104: 5520,
416 108: 5540,
417 112: 5560,
418 116: 5580,
419 120: 5600,
420 124: 5620,
421 128: 5640,
422 132: 5660,
423 136: 5680,
424 140: 5700,
425 149: 5745,
Omar El Ayachdb8463b2020-05-15 18:08:23 -0700426 151: 5755,
Ang Li73697b32015-12-03 00:41:53 +0000427 153: 5765,
Omar El Ayachdb8463b2020-05-15 18:08:23 -0700428 155: 5775,
Ang Li73697b32015-12-03 00:41:53 +0000429 157: 5785,
Omar El Ayachdb8463b2020-05-15 18:08:23 -0700430 159: 5795,
Ang Li73697b32015-12-03 00:41:53 +0000431 161: 5805,
432 165: 5825
433 }
434
Ang Li82522812016-06-02 13:57:21 -0700435
Ang Li73697b32015-12-03 00:41:53 +0000436class WifiChannelBase:
437 ALL_2G_FREQUENCIES = []
438 DFS_5G_FREQUENCIES = []
439 NONE_DFS_5G_FREQUENCIES = []
440 ALL_5G_FREQUENCIES = DFS_5G_FREQUENCIES + NONE_DFS_5G_FREQUENCIES
441 MIX_CHANNEL_SCAN = []
442
443 def band_to_freq(self, band):
444 _band_to_frequencies = {
445 WifiEnums.WIFI_BAND_24_GHZ: self.ALL_2G_FREQUENCIES,
446 WifiEnums.WIFI_BAND_5_GHZ: self.NONE_DFS_5G_FREQUENCIES,
447 WifiEnums.WIFI_BAND_5_GHZ_DFS_ONLY: self.DFS_5G_FREQUENCIES,
448 WifiEnums.WIFI_BAND_5_GHZ_WITH_DFS: self.ALL_5G_FREQUENCIES,
Ang Li82522812016-06-02 13:57:21 -0700449 WifiEnums.WIFI_BAND_BOTH:
450 self.ALL_2G_FREQUENCIES + self.NONE_DFS_5G_FREQUENCIES,
451 WifiEnums.WIFI_BAND_BOTH_WITH_DFS:
452 self.ALL_5G_FREQUENCIES + self.ALL_2G_FREQUENCIES
Ang Li73697b32015-12-03 00:41:53 +0000453 }
454 return _band_to_frequencies[band]
455
Ang Li82522812016-06-02 13:57:21 -0700456
Ang Li73697b32015-12-03 00:41:53 +0000457class WifiChannelUS(WifiChannelBase):
458 # US Wifi frequencies
459 ALL_2G_FREQUENCIES = [2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452,
460 2457, 2462]
461 NONE_DFS_5G_FREQUENCIES = [5180, 5200, 5220, 5240, 5745, 5765, 5785, 5805,
462 5825]
Ang Li82522812016-06-02 13:57:21 -0700463 MIX_CHANNEL_SCAN = [2412, 2437, 2462, 5180, 5200, 5280, 5260, 5300, 5500,
464 5320, 5520, 5560, 5700, 5745, 5805]
Ang Li73697b32015-12-03 00:41:53 +0000465
466 def __init__(self, model=None):
Girish Moturu0c567b02017-08-11 16:20:01 -0700467 self.DFS_5G_FREQUENCIES = [5260, 5280, 5300, 5320, 5500, 5520,
468 5540, 5560, 5580, 5600, 5620, 5640,
469 5660, 5680, 5700, 5720]
470 self.ALL_5G_FREQUENCIES = self.DFS_5G_FREQUENCIES + self.NONE_DFS_5G_FREQUENCIES
Ang Li73697b32015-12-03 00:41:53 +0000471
Bindu Mahadevff295782019-02-08 16:17:48 -0800472
Girish Moturuf02fa1d2017-05-21 09:51:23 +0530473class WifiReferenceNetworks:
474 """ Class to parse and return networks of different band and
475 auth type from reference_networks
476 """
477 def __init__(self, obj):
478 self.reference_networks = obj
479 self.WIFI_2G = "2g"
480 self.WIFI_5G = "5g"
481
482 self.secure_networks_2g = []
483 self.secure_networks_5g = []
484 self.open_networks_2g = []
485 self.open_networks_5g = []
486 self._parse_networks()
487
488 def _parse_networks(self):
489 for network in self.reference_networks:
490 for key in network:
491 if key == self.WIFI_2G:
492 if "password" in network[key]:
493 self.secure_networks_2g.append(network[key])
494 else:
495 self.open_networks_2g.append(network[key])
496 else:
497 if "password" in network[key]:
498 self.secure_networks_5g.append(network[key])
499 else:
500 self.open_networks_5g.append(network[key])
501
502 def return_2g_secure_networks(self):
503 return self.secure_networks_2g
504
505 def return_5g_secure_networks(self):
506 return self.secure_networks_5g
507
508 def return_2g_open_networks(self):
509 return self.open_networks_2g
510
511 def return_5g_open_networks(self):
512 return self.open_networks_5g
513
514 def return_secure_networks(self):
515 return self.secure_networks_2g + self.secure_networks_5g
516
517 def return_open_networks(self):
518 return self.open_networks_2g + self.open_networks_5g
519
Ang Li82522812016-06-02 13:57:21 -0700520
521def _assert_on_fail_handler(func, assert_on_fail, *args, **kwargs):
522 """Wrapper function that handles the bahevior of assert_on_fail.
523
524 When assert_on_fail is True, let all test signals through, which can
525 terminate test cases directly. When assert_on_fail is False, the wrapper
526 raises no test signals and reports operation status by returning True or
527 False.
528
529 Args:
530 func: The function to wrap. This function reports operation status by
531 raising test signals.
532 assert_on_fail: A boolean that specifies if the output of the wrapper
533 is test signal based or return value based.
534 args: Positional args for func.
535 kwargs: Name args for func.
536
537 Returns:
538 If assert_on_fail is True, returns True/False to signal operation
539 status, otherwise return nothing.
540 """
541 try:
542 func(*args, **kwargs)
543 if not assert_on_fail:
544 return True
545 except signals.TestSignal:
546 if assert_on_fail:
547 raise
548 return False
549
550
551def assert_network_in_list(target, network_list):
552 """Makes sure a specified target Wi-Fi network exists in a list of Wi-Fi
553 networks.
554
555 Args:
556 target: A dict representing a Wi-Fi network.
557 E.g. {WifiEnums.SSID_KEY: "SomeNetwork"}
558 network_list: A list of dicts, each representing a Wi-Fi network.
559 """
560 match_results = match_networks(target, network_list)
561 asserts.assert_true(
562 match_results, "Target network %s, does not exist in network list %s" %
563 (target, network_list))
564
565
Ang Li73697b32015-12-03 00:41:53 +0000566def match_networks(target_params, networks):
567 """Finds the WiFi networks that match a given set of parameters in a list
568 of WiFi networks.
569
Girish Moturubc48d9f2016-11-01 13:24:14 -0700570 To be considered a match, the network should contain every key-value pair
571 of target_params
Ang Li73697b32015-12-03 00:41:53 +0000572
573 Args:
Girish Moturubc48d9f2016-11-01 13:24:14 -0700574 target_params: A dict with 1 or more key-value pairs representing a Wi-Fi network.
575 E.g { 'SSID': 'wh_ap1_5g', 'BSSID': '30:b5:c2:33:e4:47' }
Ang Li73697b32015-12-03 00:41:53 +0000576 networks: A list of dict objects representing WiFi networks.
577
578 Returns:
579 The networks that match the target parameters.
580 """
581 results = []
Betty Zhou3caa0982017-02-22 19:26:20 -0800582 asserts.assert_true(target_params,
583 "Expected networks object 'target_params' is empty")
Ang Li73697b32015-12-03 00:41:53 +0000584 for n in networks:
Girish Moturubc48d9f2016-11-01 13:24:14 -0700585 add_network = 1
Ang Li9a66de72016-02-08 15:26:38 -0800586 for k, v in target_params.items():
587 if k not in n:
Girish Moturubc48d9f2016-11-01 13:24:14 -0700588 add_network = 0
589 break
Ang Li9a66de72016-02-08 15:26:38 -0800590 if n[k] != v:
Girish Moturubc48d9f2016-11-01 13:24:14 -0700591 add_network = 0
592 break
593 if add_network:
Ang Li73697b32015-12-03 00:41:53 +0000594 results.append(n)
595 return results
596
Bindu Mahadevff295782019-02-08 16:17:48 -0800597
Roshan Pius93b519c2018-05-09 12:07:11 -0700598def wait_for_wifi_state(ad, state, assert_on_fail=True):
599 """Waits for the device to transition to the specified wifi state
600
601 Args:
602 ad: An AndroidDevice object.
603 state: Wifi state to wait for.
604 assert_on_fail: If True, error checks in this function will raise test
605 failure signals.
606
607 Returns:
608 If assert_on_fail is False, function returns True if the device transitions
609 to the specified state, False otherwise. If assert_on_fail is True, no return value.
610 """
611 return _assert_on_fail_handler(
612 _wait_for_wifi_state, assert_on_fail, ad, state=state)
613
614
615def _wait_for_wifi_state(ad, state):
616 """Toggles the state of wifi.
617
618 TestFailure signals are raised when something goes wrong.
619
620 Args:
621 ad: An AndroidDevice object.
622 state: Wifi state to wait for.
623 """
624 if state == ad.droid.wifiCheckState():
625 # Check if the state is already achieved, so we don't wait for the
626 # state change event by mistake.
627 return
628 ad.droid.wifiStartTrackingStateChange()
629 fail_msg = "Device did not transition to Wi-Fi state to %s on %s." % (state,
630 ad.serial)
631 try:
632 ad.ed.wait_for_event(wifi_constants.WIFI_STATE_CHANGED,
633 lambda x: x["data"]["enabled"] == state,
634 SHORT_TIMEOUT)
635 except Empty:
636 asserts.assert_equal(state, ad.droid.wifiCheckState(), fail_msg)
637 finally:
638 ad.droid.wifiStopTrackingStateChange()
Ang Li82522812016-06-02 13:57:21 -0700639
Bindu Mahadevff295782019-02-08 16:17:48 -0800640
Ang Li82522812016-06-02 13:57:21 -0700641def wifi_toggle_state(ad, new_state=None, assert_on_fail=True):
Ang Li6b557182015-11-11 17:19:17 -0800642 """Toggles the state of wifi.
Ang Li73697b32015-12-03 00:41:53 +0000643
Ang Li6b557182015-11-11 17:19:17 -0800644 Args:
645 ad: An AndroidDevice object.
646 new_state: Wifi state to set to. If None, opposite of the current state.
Ang Li82522812016-06-02 13:57:21 -0700647 assert_on_fail: If True, error checks in this function will raise test
648 failure signals.
Ang Li73697b32015-12-03 00:41:53 +0000649
Ang Li6b557182015-11-11 17:19:17 -0800650 Returns:
Ang Li82522812016-06-02 13:57:21 -0700651 If assert_on_fail is False, function returns True if the toggle was
652 successful, False otherwise. If assert_on_fail is True, no return value.
653 """
Betty Zhou3caa0982017-02-22 19:26:20 -0800654 return _assert_on_fail_handler(
655 _wifi_toggle_state, assert_on_fail, ad, new_state=new_state)
Ang Li82522812016-06-02 13:57:21 -0700656
657
658def _wifi_toggle_state(ad, new_state=None):
659 """Toggles the state of wifi.
660
661 TestFailure signals are raised when something goes wrong.
662
663 Args:
664 ad: An AndroidDevice object.
665 new_state: The state to set Wi-Fi to. If None, opposite of the current
666 state will be set.
Ang Li6b557182015-11-11 17:19:17 -0800667 """
Ang Li31b00782016-06-21 13:04:23 -0700668 if new_state is None:
669 new_state = not ad.droid.wifiCheckState()
Ang Lie5c85c92016-07-27 15:38:09 -0700670 elif new_state == ad.droid.wifiCheckState():
671 # Check if the new_state is already achieved, so we don't wait for the
672 # state change event by mistake.
673 return
674 ad.droid.wifiStartTrackingStateChange()
Ang Li31b00782016-06-21 13:04:23 -0700675 ad.log.info("Setting Wi-Fi state to %s.", new_state)
Roshan Pius5a027fa2018-05-04 13:59:38 -0700676 ad.ed.clear_all_events()
Ang Li31b00782016-06-21 13:04:23 -0700677 # Setting wifi state.
Ang Li6b557182015-11-11 17:19:17 -0800678 ad.droid.wifiToggleState(new_state)
Jaineel3bd9bea2019-12-13 12:44:17 -0800679 time.sleep(2)
Ang Lie2e93a22016-06-22 16:43:28 -0700680 fail_msg = "Failed to set Wi-Fi state to %s on %s." % (new_state,
681 ad.serial)
Ang Li73697b32015-12-03 00:41:53 +0000682 try:
Roshan Pius5a027fa2018-05-04 13:59:38 -0700683 ad.ed.wait_for_event(wifi_constants.WIFI_STATE_CHANGED,
684 lambda x: x["data"]["enabled"] == new_state,
685 SHORT_TIMEOUT)
Ang Li73697b32015-12-03 00:41:53 +0000686 except Empty:
Ang Li82522812016-06-02 13:57:21 -0700687 asserts.assert_equal(new_state, ad.droid.wifiCheckState(), fail_msg)
Ang Li6b557182015-11-11 17:19:17 -0800688 finally:
689 ad.droid.wifiStopTrackingStateChange()
690
Ang Li82522812016-06-02 13:57:21 -0700691
Ang Li6b557182015-11-11 17:19:17 -0800692def reset_wifi(ad):
Ang Li1179fa72016-06-16 09:44:06 -0700693 """Clears all saved Wi-Fi networks on a device.
694
695 This will turn Wi-Fi on.
Ang Li6b557182015-11-11 17:19:17 -0800696
697 Args:
698 ad: An AndroidDevice object.
699
Ang Li6b557182015-11-11 17:19:17 -0800700 """
Ang Li6b557182015-11-11 17:19:17 -0800701 networks = ad.droid.wifiGetConfiguredNetworks()
702 if not networks:
703 return
704 for n in networks:
705 ad.droid.wifiForgetNetwork(n['networkId'])
706 try:
Bindu Mahadev4e710362016-11-17 16:17:11 -0800707 event = ad.ed.pop_event(wifi_constants.WIFI_FORGET_NW_SUCCESS,
Ang Li82522812016-06-02 13:57:21 -0700708 SHORT_TIMEOUT)
Ang Li6b557182015-11-11 17:19:17 -0800709 except Empty:
Ang Li1179fa72016-06-16 09:44:06 -0700710 logging.warning("Could not confirm the removal of network %s.", n)
711 # Check again to see if there's any network left.
Betty Zhou3caa0982017-02-22 19:26:20 -0800712 asserts.assert_true(
713 not ad.droid.wifiGetConfiguredNetworks(),
714 "Failed to remove these configured Wi-Fi networks: %s" % networks)
Ang Li82522812016-06-02 13:57:21 -0700715
Ang Li73697b32015-12-03 00:41:53 +0000716
Bindu Mahadev1d3991e2017-03-20 18:06:54 -0700717def toggle_airplane_mode_on_and_off(ad):
718 """Turn ON and OFF Airplane mode.
Bindu Mahadev3c54c492017-02-15 16:00:08 -0800719
Bindu Mahadev1d3991e2017-03-20 18:06:54 -0700720 ad: An AndroidDevice object.
721 Returns: Assert if turning on/off Airplane mode fails.
Bindu Mahadev3c54c492017-02-15 16:00:08 -0800722
Bindu Mahadev1d3991e2017-03-20 18:06:54 -0700723 """
724 ad.log.debug("Toggling Airplane mode ON.")
725 asserts.assert_true(
726 utils.force_airplane_mode(ad, True),
727 "Can not turn on airplane mode on: %s" % ad.serial)
728 time.sleep(DEFAULT_TIMEOUT)
729 ad.log.debug("Toggling Airplane mode OFF.")
730 asserts.assert_true(
731 utils.force_airplane_mode(ad, False),
732 "Can not turn on airplane mode on: %s" % ad.serial)
733 time.sleep(DEFAULT_TIMEOUT)
Bindu Mahadev3c54c492017-02-15 16:00:08 -0800734
735
Bindu Mahadev1d3991e2017-03-20 18:06:54 -0700736def toggle_wifi_off_and_on(ad):
737 """Turn OFF and ON WiFi.
Bindu Mahadev3c54c492017-02-15 16:00:08 -0800738
Bindu Mahadev1d3991e2017-03-20 18:06:54 -0700739 ad: An AndroidDevice object.
740 Returns: Assert if turning off/on WiFi fails.
Bindu Mahadev3c54c492017-02-15 16:00:08 -0800741
Bindu Mahadev1d3991e2017-03-20 18:06:54 -0700742 """
743 ad.log.debug("Toggling wifi OFF.")
744 wifi_toggle_state(ad, False)
745 time.sleep(DEFAULT_TIMEOUT)
746 ad.log.debug("Toggling wifi ON.")
747 wifi_toggle_state(ad, True)
748 time.sleep(DEFAULT_TIMEOUT)
Bindu Mahadev3c54c492017-02-15 16:00:08 -0800749
750
Ang Li73697b32015-12-03 00:41:53 +0000751def wifi_forget_network(ad, net_ssid):
Ang Li8e767182015-12-09 17:29:24 -0800752 """Remove configured Wifi network on an android device.
Ang Li73697b32015-12-03 00:41:53 +0000753
Ang Li8e767182015-12-09 17:29:24 -0800754 Args:
755 ad: android_device object for forget network.
756 net_ssid: ssid of network to be forget
Ang Li73697b32015-12-03 00:41:53 +0000757
Ang Li8e767182015-12-09 17:29:24 -0800758 """
Girish Moturu40d7dc22016-11-02 12:14:56 -0700759 networks = ad.droid.wifiGetConfiguredNetworks()
Ang Li8e767182015-12-09 17:29:24 -0800760 if not networks:
761 return
762 for n in networks:
763 if net_ssid in n[WifiEnums.SSID_KEY]:
Girish Moturu40d7dc22016-11-02 12:14:56 -0700764 ad.droid.wifiForgetNetwork(n['networkId'])
Ang Li8e767182015-12-09 17:29:24 -0800765 try:
Bindu Mahadev4e710362016-11-17 16:17:11 -0800766 event = ad.ed.pop_event(wifi_constants.WIFI_FORGET_NW_SUCCESS,
Betty Zhou3caa0982017-02-22 19:26:20 -0800767 SHORT_TIMEOUT)
Ang Li8e767182015-12-09 17:29:24 -0800768 except Empty:
Girish Moturu1bf82302016-11-01 13:27:00 -0700769 asserts.fail("Failed to remove network %s." % n)
Ang Li73697b32015-12-03 00:41:53 +0000770
Ang Li82522812016-06-02 13:57:21 -0700771
Ang Li73697b32015-12-03 00:41:53 +0000772def wifi_test_device_init(ad):
773 """Initializes an android device for wifi testing.
774
775 0. Make sure SL4A connection is established on the android device.
776 1. Disable location service's WiFi scan.
777 2. Turn WiFi on.
778 3. Clear all saved networks.
779 4. Set country code to US.
780 5. Enable WiFi verbose logging.
781 6. Sync device time with computer time.
782 7. Turn off cellular data.
Ang Lifee28402016-07-13 13:43:29 -0700783 8. Turn off ambient display.
Ang Li73697b32015-12-03 00:41:53 +0000784 """
Ang Lifee28402016-07-13 13:43:29 -0700785 utils.require_sl4a((ad, ))
Ang Li73697b32015-12-03 00:41:53 +0000786 ad.droid.wifiScannerToggleAlwaysAvailable(False)
787 msg = "Failed to turn off location service's scan."
Ang Li82522812016-06-02 13:57:21 -0700788 asserts.assert_true(not ad.droid.wifiScannerIsAlwaysAvailable(), msg)
789 wifi_toggle_state(ad, True)
Ang Li6b557182015-11-11 17:19:17 -0800790 reset_wifi(ad)
Ang Li73697b32015-12-03 00:41:53 +0000791 ad.droid.wifiEnableVerboseLogging(1)
Ang Li8e767182015-12-09 17:29:24 -0800792 msg = "Failed to enable WiFi verbose logging."
Ang Li82522812016-06-02 13:57:21 -0700793 asserts.assert_equal(ad.droid.wifiGetVerboseLoggingLevel(), 1, msg)
Ang Li73697b32015-12-03 00:41:53 +0000794 # We don't verify the following settings since they are not critical.
Ang Lie2e93a22016-06-22 16:43:28 -0700795 # Set wpa_supplicant log level to EXCESSIVE.
796 output = ad.adb.shell("wpa_cli -i wlan0 -p -g@android:wpa_wlan0 IFNAME="
Jaineel Mehta8dbe1ce2020-11-17 00:16:16 +0000797 "wlan0 log_level EXCESSIVE", ignore_status=True)
Ang Lie2e93a22016-06-22 16:43:28 -0700798 ad.log.info("wpa_supplicant log change status: %s", output)
Ang Lifee28402016-07-13 13:43:29 -0700799 utils.sync_device_time(ad)
Ang Li0bf8e022016-01-04 17:34:48 -0800800 ad.droid.telephonyToggleDataConnection(False)
Roshan Pius48df08c2019-09-13 08:07:30 -0700801 set_wifi_country_code(ad, WifiEnums.CountryCode.US)
Ang Lifee28402016-07-13 13:43:29 -0700802 utils.set_ambient_display(ad, False)
Ang Li73697b32015-12-03 00:41:53 +0000803
Roshan Pius48df08c2019-09-13 08:07:30 -0700804def set_wifi_country_code(ad, country_code):
805 """Sets the wifi country code on the device.
806
807 Args:
808 ad: An AndroidDevice object.
809 country_code: 2 letter ISO country code
codycaldwell35b87182020-01-16 14:08:01 -0800810
811 Raises:
812 An RpcException if unable to set the country code.
Roshan Pius48df08c2019-09-13 08:07:30 -0700813 """
Jaineelc5b56a62019-10-10 17:12:02 -0700814 try:
codycaldwell35b87182020-01-16 14:08:01 -0800815 ad.adb.shell("cmd wifi force-country-code enabled %s" % country_code)
816 except ad.adb.AdbError as e:
Jaineelc5b56a62019-10-10 17:12:02 -0700817 ad.droid.wifiSetCountryCode(WifiEnums.CountryCode.US)
Roshan Pius48df08c2019-09-13 08:07:30 -0700818
Ang Li82522812016-06-02 13:57:21 -0700819
Ang Li6b557182015-11-11 17:19:17 -0800820def start_wifi_connection_scan(ad):
Ang Li73697b32015-12-03 00:41:53 +0000821 """Starts a wifi connection scan and wait for results to become available.
822
823 Args:
Ang Li6b557182015-11-11 17:19:17 -0800824 ad: An AndroidDevice object.
Ang Li73697b32015-12-03 00:41:53 +0000825 """
Roshan Pius7f61f1c2018-01-24 18:36:49 -0800826 ad.ed.clear_all_events()
Ang Li6b557182015-11-11 17:19:17 -0800827 ad.droid.wifiStartScan()
Ang Li82522812016-06-02 13:57:21 -0700828 try:
829 ad.ed.pop_event("WifiManagerScanResultsAvailable", 60)
830 except Empty:
831 asserts.fail("Wi-Fi results did not become available within 60s.")
832
Ang Li73697b32015-12-03 00:41:53 +0000833
Roshan Piuscb9bc482018-02-01 14:27:09 -0800834def start_wifi_connection_scan_and_return_status(ad):
835 """
836 Starts a wifi connection scan and wait for results to become available
837 or a scan failure to be reported.
838
839 Args:
840 ad: An AndroidDevice object.
841 Returns:
842 True: if scan succeeded & results are available
843 False: if scan failed
844 """
845 ad.ed.clear_all_events()
846 ad.droid.wifiStartScan()
847 try:
848 events = ad.ed.pop_events(
849 "WifiManagerScan(ResultsAvailable|Failure)", 60)
850 except Empty:
851 asserts.fail(
852 "Wi-Fi scan results/failure did not become available within 60s.")
853 # If there are multiple matches, we check for atleast one success.
854 for event in events:
855 if event["name"] == "WifiManagerScanResultsAvailable":
856 return True
857 elif event["name"] == "WifiManagerScanFailure":
858 ad.log.debug("Scan failure received")
859 return False
860
861
Roshan Pius7f61f1c2018-01-24 18:36:49 -0800862def start_wifi_connection_scan_and_check_for_network(ad, network_ssid,
Roshan Piuscb9bc482018-02-01 14:27:09 -0800863 max_tries=3):
Roshan Pius7f61f1c2018-01-24 18:36:49 -0800864 """
865 Start connectivity scans & checks if the |network_ssid| is seen in
866 scan results. The method performs a max of |max_tries| connectivity scans
867 to find the network.
868
869 Args:
870 ad: An AndroidDevice object.
871 network_ssid: SSID of the network we are looking for.
872 max_tries: Number of scans to try.
873 Returns:
874 True: if network_ssid is found in scan results.
875 False: if network_ssid is not found in scan results.
876 """
877 for num_tries in range(max_tries):
Roshan Piuscb9bc482018-02-01 14:27:09 -0800878 if start_wifi_connection_scan_and_return_status(ad):
879 scan_results = ad.droid.wifiGetScanResults()
880 match_results = match_networks(
881 {WifiEnums.SSID_KEY: network_ssid}, scan_results)
882 if len(match_results) > 0:
883 return True
Roshan Pius7f61f1c2018-01-24 18:36:49 -0800884 return False
885
886
887def start_wifi_connection_scan_and_ensure_network_found(ad, network_ssid,
Roshan Piuscb9bc482018-02-01 14:27:09 -0800888 max_tries=3):
Roshan Pius7f61f1c2018-01-24 18:36:49 -0800889 """
890 Start connectivity scans & ensure the |network_ssid| is seen in
891 scan results. The method performs a max of |max_tries| connectivity scans
892 to find the network.
893 This method asserts on failure!
894
895 Args:
896 ad: An AndroidDevice object.
897 network_ssid: SSID of the network we are looking for.
898 max_tries: Number of scans to try.
899 """
900 ad.log.info("Starting scans to ensure %s is present", network_ssid)
901 assert_msg = "Failed to find " + network_ssid + " in scan results" \
902 " after " + str(max_tries) + " tries"
903 asserts.assert_true(start_wifi_connection_scan_and_check_for_network(
904 ad, network_ssid, max_tries), assert_msg)
905
906
907def start_wifi_connection_scan_and_ensure_network_not_found(ad, network_ssid,
Roshan Piuscb9bc482018-02-01 14:27:09 -0800908 max_tries=3):
Roshan Pius7f61f1c2018-01-24 18:36:49 -0800909 """
910 Start connectivity scans & ensure the |network_ssid| is not seen in
911 scan results. The method performs a max of |max_tries| connectivity scans
912 to find the network.
913 This method asserts on failure!
914
915 Args:
916 ad: An AndroidDevice object.
917 network_ssid: SSID of the network we are looking for.
918 max_tries: Number of scans to try.
919 """
920 ad.log.info("Starting scans to ensure %s is not present", network_ssid)
921 assert_msg = "Found " + network_ssid + " in scan results" \
922 " after " + str(max_tries) + " tries"
923 asserts.assert_false(start_wifi_connection_scan_and_check_for_network(
924 ad, network_ssid, max_tries), assert_msg)
925
926
Ang Li73697b32015-12-03 00:41:53 +0000927def start_wifi_background_scan(ad, scan_setting):
928 """Starts wifi background scan.
929
930 Args:
931 ad: android_device object to initiate connection on.
932 scan_setting: A dict representing the settings of the scan.
933
934 Returns:
935 If scan was started successfully, event data of success event is returned.
936 """
Girish Moturu40d7dc22016-11-02 12:14:56 -0700937 idx = ad.droid.wifiScannerStartBackgroundScan(scan_setting)
938 event = ad.ed.pop_event("WifiScannerScan{}onSuccess".format(idx),
Betty Zhou3caa0982017-02-22 19:26:20 -0800939 SHORT_TIMEOUT)
Ang Li73697b32015-12-03 00:41:53 +0000940 return event['data']
941
Ang Li82522812016-06-02 13:57:21 -0700942
Roshan Piusce821342018-01-10 11:03:04 -0800943def start_wifi_tethering(ad, ssid, password, band=None, hidden=None):
Ang Li73697b32015-12-03 00:41:53 +0000944 """Starts wifi tethering on an android_device.
945
946 Args:
947 ad: android_device to start wifi tethering on.
948 ssid: The SSID the soft AP should broadcast.
949 password: The password the soft AP should use.
950 band: The band the soft AP should be set on. It should be either
951 WifiEnums.WIFI_CONFIG_APBAND_2G or WifiEnums.WIFI_CONFIG_APBAND_5G.
Roshan Piusce821342018-01-10 11:03:04 -0800952 hidden: boolean to indicate if the AP needs to be hidden or not.
Ang Li73697b32015-12-03 00:41:53 +0000953
954 Returns:
Girish Moturu3581d612016-11-02 15:08:51 -0700955 No return value. Error checks in this function will raise test failure signals
Ang Li73697b32015-12-03 00:41:53 +0000956 """
Ang Li82522812016-06-02 13:57:21 -0700957 config = {WifiEnums.SSID_KEY: ssid}
Ang Li73697b32015-12-03 00:41:53 +0000958 if password:
959 config[WifiEnums.PWD_KEY] = password
960 if band:
lesl6d30a172020-03-05 15:05:22 +0800961 config[WifiEnums.AP_BAND_KEY] = band
Roshan Piusce821342018-01-10 11:03:04 -0800962 if hidden:
963 config[WifiEnums.HIDDEN_KEY] = hidden
Betty Zhou3caa0982017-02-22 19:26:20 -0800964 asserts.assert_true(
965 ad.droid.wifiSetWifiApConfiguration(config),
966 "Failed to update WifiAp Configuration")
Girish Moturu40d7dc22016-11-02 12:14:56 -0700967 ad.droid.wifiStartTrackingTetherStateChange()
968 ad.droid.connectivityStartTethering(tel_defines.TETHERING_WIFI, False)
Rebecca Silbersteina2889852016-08-11 00:48:53 -0700969 try:
Girish Moturu40d7dc22016-11-02 12:14:56 -0700970 ad.ed.pop_event("ConnectivityManagerOnTetheringStarted")
971 ad.ed.wait_for_event("TetherStateChanged",
Betty Zhou3caa0982017-02-22 19:26:20 -0800972 lambda x: x["data"]["ACTIVE_TETHER"], 30)
Ang Li76216d12016-09-20 14:51:57 -0700973 ad.log.debug("Tethering started successfully.")
Rebecca Silbersteina2889852016-08-11 00:48:53 -0700974 except Empty:
975 msg = "Failed to receive confirmation of wifi tethering starting"
976 asserts.fail(msg)
977 finally:
Girish Moturu40d7dc22016-11-02 12:14:56 -0700978 ad.droid.wifiStopTrackingTetherStateChange()
Ang Li73697b32015-12-03 00:41:53 +0000979
Bindu Mahadevff295782019-02-08 16:17:48 -0800980
lesl6d30a172020-03-05 15:05:22 +0800981def save_wifi_soft_ap_config(ad, wifi_config, band=None, hidden=None,
982 security=None, password=None,
983 channel=None, max_clients=None,
984 shutdown_timeout_enable=None,
985 shutdown_timeout_millis=None,
986 client_control_enable=None,
987 allowedList=None, blockedList=None):
988 """ Save a soft ap configuration and verified
989 Args:
990 ad: android_device to set soft ap configuration.
991 wifi_config: a soft ap configuration object, at least include SSID.
992 band: specifies the band for the soft ap.
993 hidden: specifies the soft ap need to broadcast its SSID or not.
994 security: specifies the security type for the soft ap.
995 password: specifies the password for the soft ap.
996 channel: specifies the channel for the soft ap.
997 max_clients: specifies the maximum connected client number.
998 shutdown_timeout_enable: specifies the auto shut down enable or not.
999 shutdown_timeout_millis: specifies the shut down timeout value.
1000 client_control_enable: specifies the client control enable or not.
1001 allowedList: specifies allowed clients list.
1002 blockedList: specifies blocked clients list.
1003 """
1004 if security and password:
1005 wifi_config[WifiEnums.SECURITY] = security
1006 wifi_config[WifiEnums.PWD_KEY] = password
Girish Moturu528b5442018-06-07 10:48:14 -07001007 if band:
lesl6d30a172020-03-05 15:05:22 +08001008 wifi_config[WifiEnums.AP_BAND_KEY] = band
Girish Moturu528b5442018-06-07 10:48:14 -07001009 if hidden:
1010 wifi_config[WifiEnums.HIDDEN_KEY] = hidden
lesl6d30a172020-03-05 15:05:22 +08001011 if channel and band:
1012 wifi_config[WifiEnums.AP_BAND_KEY] = band
1013 wifi_config[WifiEnums.AP_CHANNEL_KEY] = channel
1014 if max_clients:
1015 wifi_config[WifiEnums.AP_MAXCLIENTS_KEY] = max_clients
1016 if shutdown_timeout_enable:
1017 wifi_config[
1018 WifiEnums.AP_SHUTDOWNTIMEOUTENABLE_KEY] = shutdown_timeout_enable
1019 if shutdown_timeout_millis:
1020 wifi_config[
1021 WifiEnums.AP_SHUTDOWNTIMEOUT_KEY] = shutdown_timeout_millis
1022 if client_control_enable:
1023 wifi_config[WifiEnums.AP_CLIENTCONTROL_KEY] = client_control_enable
1024 if allowedList:
1025 wifi_config[WifiEnums.AP_ALLOWEDLIST_KEY] = allowedList
1026 if blockedList:
1027 wifi_config[WifiEnums.AP_BLOCKEDLIST_KEY] = blockedList
1028
1029 if WifiEnums.AP_CHANNEL_KEY in wifi_config and wifi_config[
1030 WifiEnums.AP_CHANNEL_KEY] == 0:
1031 del wifi_config[WifiEnums.AP_CHANNEL_KEY]
1032
1033 if WifiEnums.SECURITY in wifi_config and wifi_config[
1034 WifiEnums.SECURITY] == WifiEnums.SoftApSecurityType.OPEN:
1035 del wifi_config[WifiEnums.SECURITY]
1036 del wifi_config[WifiEnums.PWD_KEY]
1037
Girish Moturu528b5442018-06-07 10:48:14 -07001038 asserts.assert_true(ad.droid.wifiSetWifiApConfiguration(wifi_config),
1039 "Failed to set WifiAp Configuration")
1040
1041 wifi_ap = ad.droid.wifiGetApConfiguration()
1042 asserts.assert_true(
1043 wifi_ap[WifiEnums.SSID_KEY] == wifi_config[WifiEnums.SSID_KEY],
lesl6d30a172020-03-05 15:05:22 +08001044 "Hotspot SSID doesn't match")
1045 if WifiEnums.SECURITY in wifi_config:
1046 asserts.assert_true(
1047 wifi_ap[WifiEnums.SECURITY] == wifi_config[WifiEnums.SECURITY],
1048 "Hotspot Security doesn't match")
1049 if WifiEnums.PWD_KEY in wifi_config:
1050 asserts.assert_true(
1051 wifi_ap[WifiEnums.PWD_KEY] == wifi_config[WifiEnums.PWD_KEY],
1052 "Hotspot Password doesn't match")
Girish Moturu528b5442018-06-07 10:48:14 -07001053
lesl6d30a172020-03-05 15:05:22 +08001054 if WifiEnums.HIDDEN_KEY in wifi_config:
1055 asserts.assert_true(
1056 wifi_ap[WifiEnums.HIDDEN_KEY] == wifi_config[WifiEnums.HIDDEN_KEY],
1057 "Hotspot hidden setting doesn't match")
1058
1059 if WifiEnums.AP_BAND_KEY in wifi_config:
1060 asserts.assert_true(
1061 wifi_ap[WifiEnums.AP_BAND_KEY] == wifi_config[WifiEnums.AP_BAND_KEY],
1062 "Hotspot Band doesn't match")
1063 if WifiEnums.AP_CHANNEL_KEY in wifi_config:
1064 asserts.assert_true(
1065 wifi_ap[WifiEnums.AP_CHANNEL_KEY] == wifi_config[
1066 WifiEnums.AP_CHANNEL_KEY], "Hotspot Channel doesn't match")
1067 if WifiEnums.AP_MAXCLIENTS_KEY in wifi_config:
1068 asserts.assert_true(
1069 wifi_ap[WifiEnums.AP_MAXCLIENTS_KEY] == wifi_config[
1070 WifiEnums.AP_MAXCLIENTS_KEY], "Hotspot Max Clients doesn't match")
1071 if WifiEnums.AP_SHUTDOWNTIMEOUTENABLE_KEY in wifi_config:
1072 asserts.assert_true(
1073 wifi_ap[WifiEnums.AP_SHUTDOWNTIMEOUTENABLE_KEY] == wifi_config[
1074 WifiEnums.AP_SHUTDOWNTIMEOUTENABLE_KEY],
1075 "Hotspot ShutDown feature flag doesn't match")
1076 if WifiEnums.AP_SHUTDOWNTIMEOUT_KEY in wifi_config:
1077 asserts.assert_true(
1078 wifi_ap[WifiEnums.AP_SHUTDOWNTIMEOUT_KEY] == wifi_config[
1079 WifiEnums.AP_SHUTDOWNTIMEOUT_KEY],
1080 "Hotspot ShutDown timeout setting doesn't match")
1081 if WifiEnums.AP_CLIENTCONTROL_KEY in wifi_config:
1082 asserts.assert_true(
1083 wifi_ap[WifiEnums.AP_CLIENTCONTROL_KEY] == wifi_config[
1084 WifiEnums.AP_CLIENTCONTROL_KEY],
1085 "Hotspot Client control flag doesn't match")
1086 if WifiEnums.AP_ALLOWEDLIST_KEY in wifi_config:
1087 asserts.assert_true(
1088 wifi_ap[WifiEnums.AP_ALLOWEDLIST_KEY] == wifi_config[
1089 WifiEnums.AP_ALLOWEDLIST_KEY],
1090 "Hotspot Allowed List doesn't match")
1091 if WifiEnums.AP_BLOCKEDLIST_KEY in wifi_config:
1092 asserts.assert_true(
1093 wifi_ap[WifiEnums.AP_BLOCKEDLIST_KEY] == wifi_config[
1094 WifiEnums.AP_BLOCKEDLIST_KEY],
1095 "Hotspot Blocked List doesn't match")
Bindu Mahadevff295782019-02-08 16:17:48 -08001096
Girish Moturu528b5442018-06-07 10:48:14 -07001097def start_wifi_tethering_saved_config(ad):
1098 """ Turn on wifi hotspot with a config that is already saved """
1099 ad.droid.wifiStartTrackingTetherStateChange()
1100 ad.droid.connectivityStartTethering(tel_defines.TETHERING_WIFI, False)
1101 try:
1102 ad.ed.pop_event("ConnectivityManagerOnTetheringStarted")
1103 ad.ed.wait_for_event("TetherStateChanged",
1104 lambda x: x["data"]["ACTIVE_TETHER"], 30)
1105 except:
1106 asserts.fail("Didn't receive wifi tethering starting confirmation")
1107 finally:
1108 ad.droid.wifiStopTrackingTetherStateChange()
Betty Zhou3caa0982017-02-22 19:26:20 -08001109
Bindu Mahadevff295782019-02-08 16:17:48 -08001110
Ang Li73697b32015-12-03 00:41:53 +00001111def stop_wifi_tethering(ad):
1112 """Stops wifi tethering on an android_device.
Ang Li73697b32015-12-03 00:41:53 +00001113 Args:
1114 ad: android_device to stop wifi tethering on.
1115 """
Girish Moturu40d7dc22016-11-02 12:14:56 -07001116 ad.droid.wifiStartTrackingTetherStateChange()
1117 ad.droid.connectivityStopTethering(tel_defines.TETHERING_WIFI)
Rebecca Silbersteina2889852016-08-11 00:48:53 -07001118 try:
Girish Moturu40d7dc22016-11-02 12:14:56 -07001119 ad.ed.pop_event("WifiManagerApDisabled", 30)
1120 ad.ed.wait_for_event("TetherStateChanged",
Betty Zhou3caa0982017-02-22 19:26:20 -08001121 lambda x: not x["data"]["ACTIVE_TETHER"], 30)
Rebecca Silbersteina2889852016-08-11 00:48:53 -07001122 except Empty:
1123 msg = "Failed to receive confirmation of wifi tethering stopping"
1124 asserts.fail(msg)
1125 finally:
Girish Moturu40d7dc22016-11-02 12:14:56 -07001126 ad.droid.wifiStopTrackingTetherStateChange()
Ang Li82522812016-06-02 13:57:21 -07001127
Ang Li76216d12016-09-20 14:51:57 -07001128
Roshan Pius58916a32016-06-16 16:26:44 -07001129def toggle_wifi_and_wait_for_reconnection(ad,
1130 network,
1131 num_of_tries=1,
1132 assert_on_fail=True):
1133 """Toggle wifi state and then wait for Android device to reconnect to
1134 the provided wifi network.
1135
1136 This expects the device to be already connected to the provided network.
1137
1138 Logic steps are
1139 1. Ensure that we're connected to the network.
1140 2. Turn wifi off.
1141 3. Wait for 10 seconds.
1142 4. Turn wifi on.
1143 5. Wait for the "connected" event, then confirm the connected ssid is the
1144 one requested.
1145
1146 Args:
1147 ad: android_device object to initiate connection on.
1148 network: A dictionary representing the network to await connection. The
1149 dictionary must have the key "SSID".
1150 num_of_tries: An integer that is the number of times to try before
1151 delaring failure. Default is 1.
1152 assert_on_fail: If True, error checks in this function will raise test
1153 failure signals.
1154
1155 Returns:
1156 If assert_on_fail is False, function returns True if the toggle was
1157 successful, False otherwise. If assert_on_fail is True, no return value.
1158 """
Betty Zhou3caa0982017-02-22 19:26:20 -08001159 return _assert_on_fail_handler(
1160 _toggle_wifi_and_wait_for_reconnection,
1161 assert_on_fail,
1162 ad,
1163 network,
1164 num_of_tries=num_of_tries)
Roshan Pius58916a32016-06-16 16:26:44 -07001165
1166
Girish Moturu5d9f4202019-12-03 15:29:21 -08001167def _toggle_wifi_and_wait_for_reconnection(ad, network, num_of_tries=3):
Roshan Pius58916a32016-06-16 16:26:44 -07001168 """Toggle wifi state and then wait for Android device to reconnect to
1169 the provided wifi network.
1170
1171 This expects the device to be already connected to the provided network.
1172
1173 Logic steps are
1174 1. Ensure that we're connected to the network.
1175 2. Turn wifi off.
1176 3. Wait for 10 seconds.
1177 4. Turn wifi on.
1178 5. Wait for the "connected" event, then confirm the connected ssid is the
1179 one requested.
1180
1181 This will directly fail a test if anything goes wrong.
1182
1183 Args:
1184 ad: android_device object to initiate connection on.
1185 network: A dictionary representing the network to await connection. The
1186 dictionary must have the key "SSID".
1187 num_of_tries: An integer that is the number of times to try before
1188 delaring failure. Default is 1.
1189 """
Roshan Pius58916a32016-06-16 16:26:44 -07001190 expected_ssid = network[WifiEnums.SSID_KEY]
1191 # First ensure that we're already connected to the provided network.
1192 verify_con = {WifiEnums.SSID_KEY: expected_ssid}
1193 verify_wifi_connection_info(ad, verify_con)
1194 # Now toggle wifi state and wait for the connection event.
1195 wifi_toggle_state(ad, False)
1196 time.sleep(10)
1197 wifi_toggle_state(ad, True)
1198 ad.droid.wifiStartTrackingStateChange()
1199 try:
1200 connect_result = None
1201 for i in range(num_of_tries):
1202 try:
Bindu Mahadev4e710362016-11-17 16:17:11 -08001203 connect_result = ad.ed.pop_event(wifi_constants.WIFI_CONNECTED,
Roshan Pius58916a32016-06-16 16:26:44 -07001204 30)
1205 break
1206 except Empty:
1207 pass
1208 asserts.assert_true(connect_result,
1209 "Failed to connect to Wi-Fi network %s on %s" %
Girish Moturu40d7dc22016-11-02 12:14:56 -07001210 (network, ad.serial))
Betty Zhou3caa0982017-02-22 19:26:20 -08001211 logging.debug("Connection result on %s: %s.", ad.serial,
1212 connect_result)
Roshan Pius58916a32016-06-16 16:26:44 -07001213 actual_ssid = connect_result['data'][WifiEnums.SSID_KEY]
1214 asserts.assert_equal(actual_ssid, expected_ssid,
1215 "Connected to the wrong network on %s."
1216 "Expected %s, but got %s." %
Girish Moturu40d7dc22016-11-02 12:14:56 -07001217 (ad.serial, expected_ssid, actual_ssid))
Betty Zhou3caa0982017-02-22 19:26:20 -08001218 logging.info("Connected to Wi-Fi network %s on %s", actual_ssid,
1219 ad.serial)
Roshan Pius58916a32016-06-16 16:26:44 -07001220 finally:
1221 ad.droid.wifiStopTrackingStateChange()
1222
1223
Roshan Piusd1204442018-11-12 12:20:39 -08001224def wait_for_connect(ad, expected_ssid=None, expected_id=None, tries=2,
Oscar Shucb9af9b2019-05-02 20:01:49 +00001225 assert_on_fail=True):
Roshan Piusd1204442018-11-12 12:20:39 -08001226 """Wait for a connect event.
1227
1228 This will directly fail a test if anything goes wrong.
1229
1230 Args:
1231 ad: An Android device object.
1232 expected_ssid: SSID of the network to connect to.
1233 expected_id: Network Id of the network to connect to.
1234 tries: An integer that is the number of times to try before failing.
1235 assert_on_fail: If True, error checks in this function will raise test
1236 failure signals.
1237
1238 Returns:
1239 Returns a value only if assert_on_fail is false.
1240 Returns True if the connection was successful, False otherwise.
1241 """
1242 return _assert_on_fail_handler(
1243 _wait_for_connect, assert_on_fail, ad, expected_ssid, expected_id,
Oscar Shucb9af9b2019-05-02 20:01:49 +00001244 tries)
Roshan Piusd1204442018-11-12 12:20:39 -08001245
1246
Oscar Shucb9af9b2019-05-02 20:01:49 +00001247def _wait_for_connect(ad, expected_ssid=None, expected_id=None, tries=2):
Roshan Piusd1204442018-11-12 12:20:39 -08001248 """Wait for a connect event.
1249
1250 Args:
1251 ad: An Android device object.
1252 expected_ssid: SSID of the network to connect to.
1253 expected_id: Network Id of the network to connect to.
1254 tries: An integer that is the number of times to try before failing.
1255 """
1256 ad.droid.wifiStartTrackingStateChange()
1257 try:
1258 connect_result = _wait_for_connect_event(
Oscar Shucb9af9b2019-05-02 20:01:49 +00001259 ad, ssid=expected_ssid, id=expected_id, tries=tries)
Roshan Piusd1204442018-11-12 12:20:39 -08001260 asserts.assert_true(connect_result,
1261 "Failed to connect to Wi-Fi network %s" %
1262 expected_ssid)
1263 ad.log.debug("Wi-Fi connection result: %s.", connect_result)
1264 actual_ssid = connect_result['data'][WifiEnums.SSID_KEY]
1265 if expected_ssid:
1266 asserts.assert_equal(actual_ssid, expected_ssid,
1267 "Connected to the wrong network")
1268 actual_id = connect_result['data'][WifiEnums.NETID_KEY]
1269 if expected_id:
1270 asserts.assert_equal(actual_id, expected_id,
1271 "Connected to the wrong network")
1272 ad.log.info("Connected to Wi-Fi network %s.", actual_ssid)
1273 except Empty:
1274 asserts.fail("Failed to start connection process to %s" %
1275 expected_ssid)
1276 except Exception as error:
1277 ad.log.error("Failed to connect to %s with error %s", expected_ssid,
1278 error)
1279 raise signals.TestFailure("Failed to connect to %s network" %
1280 expected_ssid)
1281 finally:
1282 ad.droid.wifiStopTrackingStateChange()
1283
1284
Oscar Shucb9af9b2019-05-02 20:01:49 +00001285def _wait_for_connect_event(ad, ssid=None, id=None, tries=1):
Bindu Mahadev3c54c492017-02-15 16:00:08 -08001286 """Wait for a connect event on queue and pop when available.
1287
1288 Args:
1289 ad: An Android device object.
Bindu Mahadevaf983c92017-03-27 12:00:37 -07001290 ssid: SSID of the network to connect to.
1291 id: Network Id of the network to connect to.
Bindu Mahadev3c54c492017-02-15 16:00:08 -08001292 tries: An integer that is the number of times to try before failing.
1293
1294 Returns:
1295 A dict with details of the connection data, which looks like this:
1296 {
1297 'time': 1485460337798,
1298 'name': 'WifiNetworkConnected',
1299 'data': {
1300 'rssi': -27,
1301 'is_24ghz': True,
1302 'mac_address': '02:00:00:00:00:00',
1303 'network_id': 1,
1304 'BSSID': '30:b5:c2:33:d3:fc',
1305 'ip_address': 117483712,
1306 'link_speed': 54,
1307 'supplicant_state': 'completed',
1308 'hidden_ssid': False,
1309 'SSID': 'wh_ap1_2g',
1310 'is_5ghz': False}
1311 }
1312
1313 """
Bindu Mahadevd4542a82017-04-05 09:50:17 -07001314 conn_result = None
Bindu Mahadevaf983c92017-03-27 12:00:37 -07001315
Bindu Mahadevd4542a82017-04-05 09:50:17 -07001316 # If ssid and network id is None, just wait for any connect event.
Bindu Mahadevaf983c92017-03-27 12:00:37 -07001317 if id is None and ssid is None:
Bindu Mahadevd4542a82017-04-05 09:50:17 -07001318 for i in range(tries):
1319 try:
1320 conn_result = ad.ed.pop_event(wifi_constants.WIFI_CONNECTED, 30)
Bindu Mahadevaf983c92017-03-27 12:00:37 -07001321 break
Bindu Mahadevd4542a82017-04-05 09:50:17 -07001322 except Empty:
1323 pass
1324 else:
1325 # If ssid or network id is specified, wait for specific connect event.
1326 for i in range(tries):
1327 try:
1328 conn_result = ad.ed.pop_event(wifi_constants.WIFI_CONNECTED, 30)
1329 if id and conn_result['data'][WifiEnums.NETID_KEY] == id:
1330 break
1331 elif ssid and conn_result['data'][WifiEnums.SSID_KEY] == ssid:
1332 break
1333 except Empty:
1334 pass
Bindu Mahadevaf983c92017-03-27 12:00:37 -07001335
Bindu Mahadevd4542a82017-04-05 09:50:17 -07001336 return conn_result
1337
Bindu Mahadevff295782019-02-08 16:17:48 -08001338
Roshan Piusffc29912019-01-18 13:39:49 -08001339def wait_for_disconnect(ad, timeout=10):
1340 """Wait for a disconnect event within the specified timeout.
Bindu Mahadevd4542a82017-04-05 09:50:17 -07001341
1342 Args:
1343 ad: Android device object.
Roshan Piusffc29912019-01-18 13:39:49 -08001344 timeout: Timeout in seconds.
Bindu Mahadevd4542a82017-04-05 09:50:17 -07001345
1346 """
1347 try:
1348 ad.droid.wifiStartTrackingStateChange()
Roshan Piusffc29912019-01-18 13:39:49 -08001349 event = ad.ed.pop_event("WifiNetworkDisconnected", timeout)
Roshan Piusbf7e3982018-02-15 12:37:41 -08001350 except Empty:
Bindu Mahadevd4542a82017-04-05 09:50:17 -07001351 raise signals.TestFailure("Device did not disconnect from the network")
Roshan Piusffc29912019-01-18 13:39:49 -08001352 finally:
1353 ad.droid.wifiStopTrackingStateChange()
1354
1355
1356def ensure_no_disconnect(ad, duration=10):
1357 """Ensure that there is no disconnect for the specified duration.
1358
1359 Args:
1360 ad: Android device object.
1361 duration: Duration in seconds.
1362
1363 """
1364 try:
1365 ad.droid.wifiStartTrackingStateChange()
1366 event = ad.ed.pop_event("WifiNetworkDisconnected", duration)
1367 raise signals.TestFailure("Device disconnected from the network")
1368 except Empty:
1369 pass
1370 finally:
1371 ad.droid.wifiStopTrackingStateChange()
Bindu Mahadev3c54c492017-02-15 16:00:08 -08001372
1373
Bindu Mahadev27c2d292018-03-19 16:13:08 -07001374def connect_to_wifi_network(ad, network, assert_on_fail=True,
Joe Brennan48c3f692019-04-11 08:30:16 -07001375 check_connectivity=True, hidden=False):
Bindu Mahadev3876ae52017-12-19 14:22:19 -08001376 """Connection logic for open and psk wifi networks.
1377
1378 Args:
Jong Wook Kim92356922018-02-06 18:32:49 -08001379 ad: AndroidDevice to use for connection
1380 network: network info of the network to connect to
1381 assert_on_fail: If true, errors from wifi_connect will raise
1382 test failure signals.
Joe Brennan48c3f692019-04-11 08:30:16 -07001383 hidden: Is the Wifi network hidden.
Bindu Mahadev3876ae52017-12-19 14:22:19 -08001384 """
Joe Brennan48c3f692019-04-11 08:30:16 -07001385 if hidden:
1386 start_wifi_connection_scan_and_ensure_network_not_found(
1387 ad, network[WifiEnums.SSID_KEY])
1388 else:
1389 start_wifi_connection_scan_and_ensure_network_found(
1390 ad, network[WifiEnums.SSID_KEY])
Jong Wook Kim92356922018-02-06 18:32:49 -08001391 wifi_connect(ad,
1392 network,
1393 num_of_tries=3,
Bindu Mahadev27c2d292018-03-19 16:13:08 -07001394 assert_on_fail=assert_on_fail,
1395 check_connectivity=check_connectivity)
Bindu Mahadev3876ae52017-12-19 14:22:19 -08001396
1397
1398def connect_to_wifi_network_with_id(ad, network_id, network_ssid):
1399 """Connect to the given network using network id and verify SSID.
1400
1401 Args:
1402 network_id: int Network Id of the network.
1403 network_ssid: string SSID of the network.
1404
1405 Returns: True if connect using network id was successful;
1406 False otherwise.
1407
1408 """
Jong Wook Kim92356922018-02-06 18:32:49 -08001409 start_wifi_connection_scan_and_ensure_network_found(ad, network_ssid)
Bindu Mahadev3876ae52017-12-19 14:22:19 -08001410 wifi_connect_by_id(ad, network_id)
1411 connect_data = ad.droid.wifiGetConnectionInfo()
1412 connect_ssid = connect_data[WifiEnums.SSID_KEY]
1413 ad.log.debug("Expected SSID = %s Connected SSID = %s" %
1414 (network_ssid, connect_ssid))
1415 if connect_ssid != network_ssid:
1416 return False
1417 return True
1418
1419
Bindu Mahadev27c2d292018-03-19 16:13:08 -07001420def wifi_connect(ad, network, num_of_tries=1, assert_on_fail=True,
Oscar Shucb9af9b2019-05-02 20:01:49 +00001421 check_connectivity=True):
Ang Li99d8c6d2015-12-09 15:56:13 -08001422 """Connect an Android device to a wifi network.
Ang Li73697b32015-12-03 00:41:53 +00001423
1424 Initiate connection to a wifi network, wait for the "connected" event, then
Ang Li99d8c6d2015-12-09 15:56:13 -08001425 confirm the connected ssid is the one requested.
Ang Li73697b32015-12-03 00:41:53 +00001426
Ang Li82522812016-06-02 13:57:21 -07001427 This will directly fail a test if anything goes wrong.
1428
Ang Li73697b32015-12-03 00:41:53 +00001429 Args:
1430 ad: android_device object to initiate connection on.
Ang Li99d8c6d2015-12-09 15:56:13 -08001431 network: A dictionary representing the network to connect to. The
Ang Li82522812016-06-02 13:57:21 -07001432 dictionary must have the key "SSID".
1433 num_of_tries: An integer that is the number of times to try before
1434 delaring failure. Default is 1.
1435 assert_on_fail: If True, error checks in this function will raise test
1436 failure signals.
1437
1438 Returns:
Bindu Mahadev3c54c492017-02-15 16:00:08 -08001439 Returns a value only if assert_on_fail is false.
1440 Returns True if the connection was successful, False otherwise.
Ang Li73697b32015-12-03 00:41:53 +00001441 """
Betty Zhou3caa0982017-02-22 19:26:20 -08001442 return _assert_on_fail_handler(
Bindu Mahadev27c2d292018-03-19 16:13:08 -07001443 _wifi_connect, assert_on_fail, ad, network, num_of_tries=num_of_tries,
Oscar Shucb9af9b2019-05-02 20:01:49 +00001444 check_connectivity=check_connectivity)
Ang Li82522812016-06-02 13:57:21 -07001445
1446
Oscar Shucb9af9b2019-05-02 20:01:49 +00001447def _wifi_connect(ad, network, num_of_tries=1, check_connectivity=True):
Ang Li82522812016-06-02 13:57:21 -07001448 """Connect an Android device to a wifi network.
1449
1450 Initiate connection to a wifi network, wait for the "connected" event, then
1451 confirm the connected ssid is the one requested.
1452
1453 This will directly fail a test if anything goes wrong.
1454
1455 Args:
1456 ad: android_device object to initiate connection on.
1457 network: A dictionary representing the network to connect to. The
1458 dictionary must have the key "SSID".
1459 num_of_tries: An integer that is the number of times to try before
1460 delaring failure. Default is 1.
1461 """
Ang Li82522812016-06-02 13:57:21 -07001462 asserts.assert_true(WifiEnums.SSID_KEY in network,
1463 "Key '%s' must be present in network definition." %
1464 WifiEnums.SSID_KEY)
Ang Li99d8c6d2015-12-09 15:56:13 -08001465 ad.droid.wifiStartTrackingStateChange()
Betty Zhoud35dab82016-12-06 15:24:23 -08001466 expected_ssid = network[WifiEnums.SSID_KEY]
Bindu Mahadev50374df2017-01-04 11:03:32 -08001467 ad.droid.wifiConnectByConfig(network)
1468 ad.log.info("Starting connection process to %s", expected_ssid)
Ang Li73697b32015-12-03 00:41:53 +00001469 try:
Bindu Mahadev50374df2017-01-04 11:03:32 -08001470 event = ad.ed.pop_event(wifi_constants.CONNECT_BY_CONFIG_SUCCESS, 30)
Roshan Piusd1204442018-11-12 12:20:39 -08001471 connect_result = _wait_for_connect_event(
Oscar Shucb9af9b2019-05-02 20:01:49 +00001472 ad, ssid=expected_ssid, tries=num_of_tries)
Ang Li82522812016-06-02 13:57:21 -07001473 asserts.assert_true(connect_result,
1474 "Failed to connect to Wi-Fi network %s on %s" %
Girish Moturubc48d9f2016-11-01 13:24:14 -07001475 (network, ad.serial))
Ang Li31b00782016-06-21 13:04:23 -07001476 ad.log.debug("Wi-Fi connection result: %s.", connect_result)
Ang Li99d8c6d2015-12-09 15:56:13 -08001477 actual_ssid = connect_result['data'][WifiEnums.SSID_KEY]
Ang Li82522812016-06-02 13:57:21 -07001478 asserts.assert_equal(actual_ssid, expected_ssid,
Betty Zhou3caa0982017-02-22 19:26:20 -08001479 "Connected to the wrong network on %s." %
1480 ad.serial)
Ang Li31b00782016-06-21 13:04:23 -07001481 ad.log.info("Connected to Wi-Fi network %s.", actual_ssid)
Bindu Mahadev50374df2017-01-04 11:03:32 -08001482
Bindu Mahadev27c2d292018-03-19 16:13:08 -07001483 if check_connectivity:
Hsiu-Chang Chend7b3c572020-06-12 12:19:30 +08001484 internet = validate_connection(ad, DEFAULT_PING_ADDR)
Bindu Mahadev27c2d292018-03-19 16:13:08 -07001485 if not internet:
1486 raise signals.TestFailure("Failed to connect to internet on %s" %
1487 expected_ssid)
Bindu Mahadev50374df2017-01-04 11:03:32 -08001488 except Empty:
1489 asserts.fail("Failed to start connection process to %s on %s" %
1490 (network, ad.serial))
Bindu Mahadev4e710362016-11-17 16:17:11 -08001491 except Exception as error:
Bindu Mahadev50374df2017-01-04 11:03:32 -08001492 ad.log.error("Failed to connect to %s with error %s", expected_ssid,
1493 error)
1494 raise signals.TestFailure("Failed to connect to %s network" % network)
1495
Ang Li73697b32015-12-03 00:41:53 +00001496 finally:
Ang Li99d8c6d2015-12-09 15:56:13 -08001497 ad.droid.wifiStopTrackingStateChange()
Ang Li73697b32015-12-03 00:41:53 +00001498
Bindu Mahadev50374df2017-01-04 11:03:32 -08001499
Oscar Shucb9af9b2019-05-02 20:01:49 +00001500def wifi_connect_by_id(ad, network_id, num_of_tries=3, assert_on_fail=True):
Bindu Mahadev3c54c492017-02-15 16:00:08 -08001501 """Connect an Android device to a wifi network using network Id.
1502
1503 Start connection to the wifi network, with the given network Id, wait for
1504 the "connected" event, then verify the connected network is the one requested.
1505
1506 This will directly fail a test if anything goes wrong.
1507
1508 Args:
1509 ad: android_device object to initiate connection on.
1510 network_id: Integer specifying the network id of the network.
1511 num_of_tries: An integer that is the number of times to try before
1512 delaring failure. Default is 1.
1513 assert_on_fail: If True, error checks in this function will raise test
1514 failure signals.
1515
1516 Returns:
1517 Returns a value only if assert_on_fail is false.
1518 Returns True if the connection was successful, False otherwise.
1519 """
1520 _assert_on_fail_handler(_wifi_connect_by_id, assert_on_fail, ad,
Oscar Shucb9af9b2019-05-02 20:01:49 +00001521 network_id, num_of_tries)
Bindu Mahadev3c54c492017-02-15 16:00:08 -08001522
1523
Oscar Shucb9af9b2019-05-02 20:01:49 +00001524def _wifi_connect_by_id(ad, network_id, num_of_tries=1):
Bindu Mahadev3c54c492017-02-15 16:00:08 -08001525 """Connect an Android device to a wifi network using it's network id.
1526
1527 Start connection to the wifi network, with the given network id, wait for
1528 the "connected" event, then verify the connected network is the one requested.
1529
1530 Args:
1531 ad: android_device object to initiate connection on.
1532 network_id: Integer specifying the network id of the network.
1533 num_of_tries: An integer that is the number of times to try before
1534 delaring failure. Default is 1.
1535 """
Bindu Mahadev3c54c492017-02-15 16:00:08 -08001536 ad.droid.wifiStartTrackingStateChange()
Bindu Mahadevaf983c92017-03-27 12:00:37 -07001537 # Clear all previous events.
1538 ad.ed.clear_all_events()
Bindu Mahadev3c54c492017-02-15 16:00:08 -08001539 ad.droid.wifiConnectByNetworkId(network_id)
1540 ad.log.info("Starting connection to network with id %d", network_id)
1541 try:
1542 event = ad.ed.pop_event(wifi_constants.CONNECT_BY_NETID_SUCCESS, 60)
Roshan Piusd1204442018-11-12 12:20:39 -08001543 connect_result = _wait_for_connect_event(
Oscar Shucb9af9b2019-05-02 20:01:49 +00001544 ad, id=network_id, tries=num_of_tries)
Bindu Mahadev3c54c492017-02-15 16:00:08 -08001545 asserts.assert_true(connect_result,
1546 "Failed to connect to Wi-Fi network using network id")
1547 ad.log.debug("Wi-Fi connection result: %s", connect_result)
1548 actual_id = connect_result['data'][WifiEnums.NETID_KEY]
1549 asserts.assert_equal(actual_id, network_id,
1550 "Connected to the wrong network on %s."
1551 "Expected network id = %d, but got %d." %
1552 (ad.serial, network_id, actual_id))
1553 expected_ssid = connect_result['data'][WifiEnums.SSID_KEY]
1554 ad.log.info("Connected to Wi-Fi network %s with %d network id.",
1555 expected_ssid, network_id)
1556
Bindu Mahadev3c54c492017-02-15 16:00:08 -08001557 internet = validate_connection(ad, DEFAULT_PING_ADDR)
1558 if not internet:
1559 raise signals.TestFailure("Failed to connect to internet on %s" %
1560 expected_ssid)
1561 except Empty:
1562 asserts.fail("Failed to connect to network with id %d on %s" %
1563 (network_id, ad.serial))
1564 except Exception as error:
1565 ad.log.error("Failed to connect to network with id %d with error %s",
1566 network_id, error)
1567 raise signals.TestFailure("Failed to connect to network with network"
1568 " id %d" % network_id)
1569 finally:
1570 ad.droid.wifiStopTrackingStateChange()
1571
Oscar Shu0b5ff4d2019-08-07 18:11:56 +00001572
Roshan Piusc999e5e2018-11-09 10:59:52 -08001573def wifi_connect_using_network_request(ad, network, network_specifier,
1574 num_of_tries=3, assert_on_fail=True):
1575 """Connect an Android device to a wifi network using network request.
1576
1577 Trigger a network request with the provided network specifier,
1578 wait for the "onMatch" event, ensure that the scan results in "onMatch"
1579 event contain the specified network, then simulate the user granting the
1580 request with the specified network selected. Then wait for the "onAvailable"
1581 network callback indicating successful connection to network.
1582
1583 This will directly fail a test if anything goes wrong.
1584
1585 Args:
1586 ad: android_device object to initiate connection on.
1587 network_specifier: A dictionary representing the network specifier to
1588 use.
1589 network: A dictionary representing the network to connect to. The
1590 dictionary must have the key "SSID".
1591 num_of_tries: An integer that is the number of times to try before
1592 delaring failure.
1593 assert_on_fail: If True, error checks in this function will raise test
1594 failure signals.
1595
1596 Returns:
1597 Returns a value only if assert_on_fail is false.
1598 Returns True if the connection was successful, False otherwise.
1599 """
1600 _assert_on_fail_handler(_wifi_connect_using_network_request, assert_on_fail,
1601 ad, network, network_specifier, num_of_tries)
1602
1603
1604def _wifi_connect_using_network_request(ad, network, network_specifier,
1605 num_of_tries=3):
1606 """Connect an Android device to a wifi network using network request.
1607
1608 Trigger a network request with the provided network specifier,
1609 wait for the "onMatch" event, ensure that the scan results in "onMatch"
1610 event contain the specified network, then simulate the user granting the
1611 request with the specified network selected. Then wait for the "onAvailable"
1612 network callback indicating successful connection to network.
1613
1614 Args:
1615 ad: android_device object to initiate connection on.
1616 network_specifier: A dictionary representing the network specifier to
1617 use.
1618 network: A dictionary representing the network to connect to. The
1619 dictionary must have the key "SSID".
1620 num_of_tries: An integer that is the number of times to try before
1621 delaring failure.
1622 """
1623 ad.droid.wifiRequestNetworkWithSpecifier(network_specifier)
1624 ad.log.info("Sent network request with %s", network_specifier)
1625 # Need a delay here because UI interaction should only start once wifi
1626 # starts processing the request.
1627 time.sleep(wifi_constants.NETWORK_REQUEST_CB_REGISTER_DELAY_SEC)
1628 _wait_for_wifi_connect_after_network_request(ad, network, num_of_tries)
1629
1630
1631def wait_for_wifi_connect_after_network_request(ad, network, num_of_tries=3,
1632 assert_on_fail=True):
1633 """
1634 Simulate and verify the connection flow after initiating the network
1635 request.
1636
1637 Wait for the "onMatch" event, ensure that the scan results in "onMatch"
1638 event contain the specified network, then simulate the user granting the
1639 request with the specified network selected. Then wait for the "onAvailable"
1640 network callback indicating successful connection to network.
1641
1642 Args:
1643 ad: android_device object to initiate connection on.
1644 network: A dictionary representing the network to connect to. The
1645 dictionary must have the key "SSID".
1646 num_of_tries: An integer that is the number of times to try before
1647 delaring failure.
1648 assert_on_fail: If True, error checks in this function will raise test
1649 failure signals.
1650
1651 Returns:
1652 Returns a value only if assert_on_fail is false.
1653 Returns True if the connection was successful, False otherwise.
1654 """
1655 _assert_on_fail_handler(_wait_for_wifi_connect_after_network_request,
1656 assert_on_fail, ad, network, num_of_tries)
1657
1658
1659def _wait_for_wifi_connect_after_network_request(ad, network, num_of_tries=3):
1660 """
1661 Simulate and verify the connection flow after initiating the network
1662 request.
1663
1664 Wait for the "onMatch" event, ensure that the scan results in "onMatch"
1665 event contain the specified network, then simulate the user granting the
1666 request with the specified network selected. Then wait for the "onAvailable"
1667 network callback indicating successful connection to network.
1668
1669 Args:
1670 ad: android_device object to initiate connection on.
1671 network: A dictionary representing the network to connect to. The
1672 dictionary must have the key "SSID".
1673 num_of_tries: An integer that is the number of times to try before
1674 delaring failure.
1675 """
1676 asserts.assert_true(WifiEnums.SSID_KEY in network,
1677 "Key '%s' must be present in network definition." %
1678 WifiEnums.SSID_KEY)
1679 ad.droid.wifiStartTrackingStateChange()
1680 expected_ssid = network[WifiEnums.SSID_KEY]
1681 ad.droid.wifiRegisterNetworkRequestMatchCallback()
1682 # Wait for the platform to scan and return a list of networks
1683 # matching the request
1684 try:
1685 matched_network = None
1686 for _ in [0, num_of_tries]:
1687 on_match_event = ad.ed.pop_event(
1688 wifi_constants.WIFI_NETWORK_REQUEST_MATCH_CB_ON_MATCH, 60)
1689 asserts.assert_true(on_match_event,
1690 "Network request on match not received.")
1691 matched_scan_results = on_match_event["data"]
1692 ad.log.debug("Network request on match results %s",
1693 matched_scan_results)
1694 matched_network = match_networks(
1695 {WifiEnums.SSID_KEY: network[WifiEnums.SSID_KEY]},
1696 matched_scan_results)
1697 if matched_network:
1698 break;
1699
1700 asserts.assert_true(
1701 matched_network, "Target network %s not found" % network)
1702
1703 ad.droid.wifiSendUserSelectionForNetworkRequestMatch(network)
1704 ad.log.info("Sent user selection for network request %s",
1705 expected_ssid)
1706
1707 # Wait for the platform to connect to the network.
1708 on_available_event = ad.ed.pop_event(
1709 wifi_constants.WIFI_NETWORK_CB_ON_AVAILABLE, 60)
1710 asserts.assert_true(on_available_event,
1711 "Network request on available not received.")
1712 connected_network = on_available_event["data"]
1713 ad.log.info("Connected to network %s", connected_network)
1714 asserts.assert_equal(connected_network[WifiEnums.SSID_KEY],
1715 expected_ssid,
1716 "Connected to the wrong network."
1717 "Expected %s, but got %s." %
1718 (network, connected_network))
1719 except Empty:
1720 asserts.fail("Failed to connect to %s" % expected_ssid)
1721 except Exception as error:
1722 ad.log.error("Failed to connect to %s with error %s",
1723 (expected_ssid, error))
1724 raise signals.TestFailure("Failed to connect to %s network" % network)
1725 finally:
1726 ad.droid.wifiStopTrackingStateChange()
1727
1728
Bindu Mahadevd4542a82017-04-05 09:50:17 -07001729def wifi_passpoint_connect(ad, passpoint_network, num_of_tries=1,
Oscar Shucb9af9b2019-05-02 20:01:49 +00001730 assert_on_fail=True):
Bindu Mahadev9dd48172017-03-06 17:04:34 -08001731 """Connect an Android device to a wifi network.
1732
1733 Initiate connection to a wifi network, wait for the "connected" event, then
1734 confirm the connected ssid is the one requested.
1735
1736 This will directly fail a test if anything goes wrong.
1737
1738 Args:
1739 ad: android_device object to initiate connection on.
Bindu Mahadevd4542a82017-04-05 09:50:17 -07001740 passpoint_network: SSID of the Passpoint network to connect to.
Bindu Mahadev9dd48172017-03-06 17:04:34 -08001741 num_of_tries: An integer that is the number of times to try before
1742 delaring failure. Default is 1.
1743 assert_on_fail: If True, error checks in this function will raise test
1744 failure signals.
1745
1746 Returns:
1747 If assert_on_fail is False, function returns network id, if the connect was
1748 successful, False otherwise. If assert_on_fail is True, no return value.
1749 """
Bindu Mahadevd4542a82017-04-05 09:50:17 -07001750 _assert_on_fail_handler(_wifi_passpoint_connect, assert_on_fail, ad,
Oscar Shucb9af9b2019-05-02 20:01:49 +00001751 passpoint_network, num_of_tries = num_of_tries)
Bindu Mahadev9dd48172017-03-06 17:04:34 -08001752
1753
Oscar Shucb9af9b2019-05-02 20:01:49 +00001754def _wifi_passpoint_connect(ad, passpoint_network, num_of_tries=1):
Bindu Mahadev9dd48172017-03-06 17:04:34 -08001755 """Connect an Android device to a wifi network.
1756
1757 Initiate connection to a wifi network, wait for the "connected" event, then
1758 confirm the connected ssid is the one requested.
1759
1760 This will directly fail a test if anything goes wrong.
1761
1762 Args:
1763 ad: android_device object to initiate connection on.
Bindu Mahadevd4542a82017-04-05 09:50:17 -07001764 passpoint_network: SSID of the Passpoint network to connect to.
Bindu Mahadev9dd48172017-03-06 17:04:34 -08001765 num_of_tries: An integer that is the number of times to try before
1766 delaring failure. Default is 1.
1767 """
Bindu Mahadev9dd48172017-03-06 17:04:34 -08001768 ad.droid.wifiStartTrackingStateChange()
Bindu Mahadevd4542a82017-04-05 09:50:17 -07001769 expected_ssid = passpoint_network
Bindu Mahadev9dd48172017-03-06 17:04:34 -08001770 ad.log.info("Starting connection process to passpoint %s", expected_ssid)
1771
1772 try:
Roshan Piusd1204442018-11-12 12:20:39 -08001773 connect_result = _wait_for_connect_event(
Oscar Shucb9af9b2019-05-02 20:01:49 +00001774 ad, expected_ssid, num_of_tries)
Bindu Mahadev9dd48172017-03-06 17:04:34 -08001775 asserts.assert_true(connect_result,
1776 "Failed to connect to WiFi passpoint network %s on"
1777 " %s" % (expected_ssid, ad.serial))
1778 ad.log.info("Wi-Fi connection result: %s.", connect_result)
1779 actual_ssid = connect_result['data'][WifiEnums.SSID_KEY]
1780 asserts.assert_equal(actual_ssid, expected_ssid,
1781 "Connected to the wrong network on %s." % ad.serial)
1782 ad.log.info("Connected to Wi-Fi passpoint network %s.", actual_ssid)
1783
Bindu Mahadev9dd48172017-03-06 17:04:34 -08001784 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
Hsiu-Chang Chend7b3c572020-06-12 12:19:30 +08001911def validate_connection(ad, ping_addr=DEFAULT_PING_ADDR, wait_time=15,
Girish Moturu804a3492020-02-17 14:32:02 -08001912 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.
Hsiu-Chang Chend7b3c572020-06-12 12:19:30 +08001924 for i in range(wait_time):
Girish Moturuacf35002020-11-09 23:37:35 -08001925 if ad.droid.connectivityNetworkIsConnected(
1926 ) and ad.droid.connectivityGetIPv4DefaultGateway():
Hsiu-Chang Chend7b3c572020-06-12 12:19:30 +08001927 break
1928 time.sleep(1)
Girish Moturu804a3492020-02-17 14:32:02 -08001929 ping = False
1930 try:
1931 ping = ad.droid.httpPing(ping_addr)
1932 ad.log.info("Http ping result: %s.", ping)
1933 except:
1934 pass
1935 if not ping and ping_gateway:
1936 ad.log.info("Http ping failed. Pinging default gateway")
1937 gw = ad.droid.connectivityGetIPv4DefaultGateway()
1938 result = ad.adb.shell("ping -c 6 {}".format(gw))
1939 ad.log.info("Default gateway ping result: %s" % result)
1940 ping = False if "100% packet loss" in result else True
Ang Li73697b32015-12-03 00:41:53 +00001941 return ping
1942
Ang Li82522812016-06-02 13:57:21 -07001943
Ang Li73697b32015-12-03 00:41:53 +00001944#TODO(angli): This can only verify if an actual value is exactly the same.
1945# Would be nice to be able to verify an actual value is one of serveral.
1946def verify_wifi_connection_info(ad, expected_con):
1947 """Verifies that the information of the currently connected wifi network is
1948 as expected.
1949
1950 Args:
1951 expected_con: A dict representing expected key-value pairs for wifi
1952 connection. e.g. {"SSID": "test_wifi"}
1953 """
1954 current_con = ad.droid.wifiGetConnectionInfo()
Ang Li374d7602016-02-08 17:27:27 -08001955 case_insensitive = ["BSSID", "supplicant_state"]
Ang Li31b00782016-06-21 13:04:23 -07001956 ad.log.debug("Current connection: %s", current_con)
Ang Li73697b32015-12-03 00:41:53 +00001957 for k, expected_v in expected_con.items():
Ang Li9a66de72016-02-08 15:26:38 -08001958 # Do not verify authentication related fields.
1959 if k == "password":
1960 continue
Ang Li82522812016-06-02 13:57:21 -07001961 msg = "Field %s does not exist in wifi connection info %s." % (
1962 k, current_con)
Ang Li374d7602016-02-08 17:27:27 -08001963 if k not in current_con:
1964 raise signals.TestFailure(msg)
1965 actual_v = current_con[k]
1966 if k in case_insensitive:
1967 actual_v = actual_v.lower()
1968 expected_v = expected_v.lower()
Ang Li73697b32015-12-03 00:41:53 +00001969 msg = "Expected %s to be %s, actual %s is %s." % (k, expected_v, k,
Ang Li82522812016-06-02 13:57:21 -07001970 actual_v)
Ang Li374d7602016-02-08 17:27:27 -08001971 if actual_v != expected_v:
1972 raise signals.TestFailure(msg)
Ang Li73697b32015-12-03 00:41:53 +00001973
Ang Li82522812016-06-02 13:57:21 -07001974
Preetesh Barrettoe8c428b2019-02-14 09:15:44 -08001975def check_autoconnect_to_open_network(ad, conn_timeout=WIFI_CONNECTION_TIMEOUT_DEFAULT):
1976 """Connects to any open WiFI AP
1977 Args:
1978 timeout value in sec to wait for UE to connect to a WiFi AP
1979 Returns:
1980 True if UE connects to WiFi AP (supplicant_state = completed)
1981 False if UE fails to complete connection within WIFI_CONNECTION_TIMEOUT time.
1982 """
1983 if ad.droid.wifiCheckState():
1984 return True
1985 ad.droid.wifiToggleState()
1986 wifi_connection_state = None
1987 timeout = time.time() + conn_timeout
1988 while wifi_connection_state != "completed":
1989 wifi_connection_state = ad.droid.wifiGetConnectionInfo()[
1990 'supplicant_state']
1991 if time.time() > timeout:
1992 ad.log.warning("Failed to connect to WiFi AP")
1993 return False
1994 return True
1995
1996
Ang Li73697b32015-12-03 00:41:53 +00001997def expand_enterprise_config_by_phase2(config):
1998 """Take an enterprise config and generate a list of configs, each with
1999 a different phase2 auth type.
2000
2001 Args:
2002 config: A dict representing enterprise config.
2003
2004 Returns
2005 A list of enterprise configs.
2006 """
2007 results = []
Ang Li0e7e58f2016-02-22 12:15:02 -08002008 phase2_types = WifiEnums.EapPhase2
2009 if config[WifiEnums.Enterprise.EAP] == WifiEnums.Eap.PEAP:
2010 # Skip unsupported phase2 types for PEAP.
2011 phase2_types = [WifiEnums.EapPhase2.GTC, WifiEnums.EapPhase2.MSCHAPV2]
2012 for phase2_type in phase2_types:
Ang Li73697b32015-12-03 00:41:53 +00002013 # Skip a special case for passpoint TTLS.
2014 if (WifiEnums.Enterprise.FQDN in config and
Ang Li82522812016-06-02 13:57:21 -07002015 phase2_type == WifiEnums.EapPhase2.GTC):
Ang Li73697b32015-12-03 00:41:53 +00002016 continue
2017 c = dict(config)
Girish Moturu150d32f2017-02-14 12:27:07 -08002018 c[WifiEnums.Enterprise.PHASE2] = phase2_type.value
Ang Li73697b32015-12-03 00:41:53 +00002019 results.append(c)
2020 return results
Ang Li2d3fe982016-06-08 10:00:43 -07002021
2022
Girish Moturub48a13c2017-02-27 11:36:42 -08002023def generate_eap_test_name(config, ad=None):
Girish Moturu150d32f2017-02-14 12:27:07 -08002024 """ Generates a test case name based on an EAP configuration.
2025
2026 Args:
2027 config: A dict representing an EAP credential.
Girish Moturub48a13c2017-02-27 11:36:42 -08002028 ad object: Redundant but required as the same param is passed
2029 to test_func in run_generated_tests
Girish Moturu150d32f2017-02-14 12:27:07 -08002030
2031 Returns:
2032 A string representing the name of a generated EAP test case.
2033 """
2034 eap = WifiEnums.Eap
2035 eap_phase2 = WifiEnums.EapPhase2
Girish Moturub48a13c2017-02-27 11:36:42 -08002036 Ent = WifiEnums.Enterprise
Girish Moturu150d32f2017-02-14 12:27:07 -08002037 name = "test_connect-"
2038 eap_name = ""
2039 for e in eap:
2040 if e.value == config[Ent.EAP]:
2041 eap_name = e.name
2042 break
2043 if "peap0" in config[WifiEnums.SSID_KEY].lower():
2044 eap_name = "PEAP0"
2045 if "peap1" in config[WifiEnums.SSID_KEY].lower():
2046 eap_name = "PEAP1"
2047 name += eap_name
2048 if Ent.PHASE2 in config:
2049 for e in eap_phase2:
2050 if e.value == config[Ent.PHASE2]:
2051 name += "-{}".format(e.name)
2052 break
2053 return name
2054
2055
Ang Li2d3fe982016-06-08 10:00:43 -07002056def group_attenuators(attenuators):
2057 """Groups a list of attenuators into attenuator groups for backward
2058 compatibility reasons.
2059
2060 Most legacy Wi-Fi setups have two attenuators each connected to a separate
2061 AP. The new Wi-Fi setup has four attenuators, each connected to one channel
2062 on an AP, so two of them are connected to one AP.
2063
2064 To make the existing scripts work in the new setup, when the script needs
2065 to attenuate one AP, it needs to set attenuation on both attenuators
2066 connected to the same AP.
2067
2068 This function groups attenuators properly so the scripts work in both
2069 legacy and new Wi-Fi setups.
2070
2071 Args:
2072 attenuators: A list of attenuator objects, either two or four in length.
2073
2074 Raises:
2075 signals.TestFailure is raised if the attenuator list does not have two
2076 or four objects.
2077 """
2078 attn0 = attenuator.AttenuatorGroup("AP0")
2079 attn1 = attenuator.AttenuatorGroup("AP1")
2080 # Legacy testbed setup has two attenuation channels.
2081 num_of_attns = len(attenuators)
2082 if num_of_attns == 2:
2083 attn0.add(attenuators[0])
2084 attn1.add(attenuators[1])
2085 elif num_of_attns == 4:
2086 attn0.add(attenuators[0])
2087 attn0.add(attenuators[1])
2088 attn1.add(attenuators[2])
2089 attn1.add(attenuators[3])
2090 else:
2091 asserts.fail(("Either two or four attenuators are required for this "
2092 "test, but found %s") % num_of_attns)
2093 return [attn0, attn1]
Jong Wook Kim92356922018-02-06 18:32:49 -08002094
Bindu Mahadevff295782019-02-08 16:17:48 -08002095
Girish Moturu36348a32019-12-10 08:41:54 -08002096def set_attns(attenuator, attn_val_name, roaming_attn=ROAMING_ATTN):
Bindu Mahadev7060a9f2018-05-04 13:48:12 -07002097 """Sets attenuation values on attenuators used in this test.
2098
2099 Args:
2100 attenuator: The attenuator object.
2101 attn_val_name: Name of the attenuation value pair to use.
Girish Moturu36348a32019-12-10 08:41:54 -08002102 roaming_attn: Dictionary specifying the attenuation params.
Bindu Mahadev7060a9f2018-05-04 13:48:12 -07002103 """
2104 logging.info("Set attenuation values to %s", roaming_attn[attn_val_name])
2105 try:
2106 attenuator[0].set_atten(roaming_attn[attn_val_name][0])
2107 attenuator[1].set_atten(roaming_attn[attn_val_name][1])
2108 attenuator[2].set_atten(roaming_attn[attn_val_name][2])
2109 attenuator[3].set_atten(roaming_attn[attn_val_name][3])
2110 except:
2111 logging.exception("Failed to set attenuation values %s.",
2112 attn_val_name)
2113 raise
2114
Girish Moturu36348a32019-12-10 08:41:54 -08002115def set_attns_steps(attenuators,
2116 atten_val_name,
2117 roaming_attn=ROAMING_ATTN,
2118 steps=10,
2119 wait_time=12):
Hsiu-Chang Chen73ea3342019-05-22 11:20:08 +08002120 """Set attenuation values on attenuators used in this test. It will change
2121 the attenuation values linearly from current value to target value step by
2122 step.
2123
2124 Args:
2125 attenuators: The list of attenuator objects that you want to change
2126 their attenuation value.
2127 atten_val_name: Name of the attenuation value pair to use.
Girish Moturu36348a32019-12-10 08:41:54 -08002128 roaming_attn: Dictionary specifying the attenuation params.
Hsiu-Chang Chen73ea3342019-05-22 11:20:08 +08002129 steps: Number of attenuator changes to reach the target value.
2130 wait_time: Sleep time for each change of attenuator.
2131 """
2132 logging.info("Set attenuation values to %s in %d step(s)",
2133 roaming_attn[atten_val_name], steps)
2134 start_atten = [attenuator.get_atten() for attenuator in attenuators]
2135 target_atten = roaming_attn[atten_val_name]
2136 for current_step in range(steps):
2137 progress = (current_step + 1) / steps
2138 for i, attenuator in enumerate(attenuators):
2139 amount_since_start = (target_atten[i] - start_atten[i]) * progress
2140 attenuator.set_atten(round(start_atten[i] + amount_since_start))
2141 time.sleep(wait_time)
2142
Bindu Mahadev7060a9f2018-05-04 13:48:12 -07002143
Girish Moturu36348a32019-12-10 08:41:54 -08002144def trigger_roaming_and_validate(dut,
2145 attenuator,
2146 attn_val_name,
2147 expected_con,
2148 roaming_attn=ROAMING_ATTN):
Bindu Mahadev7060a9f2018-05-04 13:48:12 -07002149 """Sets attenuators to trigger roaming and validate the DUT connected
2150 to the BSSID expected.
2151
2152 Args:
2153 attenuator: The attenuator object.
2154 attn_val_name: Name of the attenuation value pair to use.
2155 expected_con: The network information of the expected network.
Girish Moturu36348a32019-12-10 08:41:54 -08002156 roaming_attn: Dictionary specifying the attenaution params.
Bindu Mahadev7060a9f2018-05-04 13:48:12 -07002157 """
2158 expected_con = {
2159 WifiEnums.SSID_KEY: expected_con[WifiEnums.SSID_KEY],
2160 WifiEnums.BSSID_KEY: expected_con["bssid"],
2161 }
Girish Moturu36348a32019-12-10 08:41:54 -08002162 set_attns_steps(attenuator, attn_val_name, roaming_attn)
Bindu Mahadev7060a9f2018-05-04 13:48:12 -07002163
Hsiu-Chang Chenef856402018-09-18 12:32:49 +08002164 verify_wifi_connection_info(dut, expected_con)
2165 expected_bssid = expected_con[WifiEnums.BSSID_KEY]
2166 logging.info("Roamed to %s successfully", expected_bssid)
2167 if not validate_connection(dut):
2168 raise signals.TestFailure("Fail to connect to internet on %s" %
2169 expected_bssid)
Jong Wook Kim92356922018-02-06 18:32:49 -08002170
2171def create_softap_config():
2172 """Create a softap config with random ssid and password."""
2173 ap_ssid = "softap_" + utils.rand_ascii_str(8)
2174 ap_password = utils.rand_ascii_str(8)
2175 logging.info("softap setup: %s %s", ap_ssid, ap_password)
2176 config = {
2177 WifiEnums.SSID_KEY: ap_ssid,
2178 WifiEnums.PWD_KEY: ap_password,
2179 }
2180 return config
Girish Moturucf4dccd2018-08-27 12:22:00 -07002181
Bindu Mahadevff295782019-02-08 16:17:48 -08002182def start_softap_and_verify(ad, band):
2183 """Bring-up softap and verify AP mode and in scan results.
2184
2185 Args:
2186 band: The band to use for softAP.
2187
2188 Returns: dict, the softAP config.
2189
2190 """
lesl2f0fb232019-11-05 16:35:28 +08002191 # Register before start the test.
2192 callbackId = ad.dut.droid.registerSoftApCallback()
2193 # Check softap info value is default
2194 frequency, bandwdith = get_current_softap_info(ad.dut, callbackId, True)
2195 asserts.assert_true(frequency == 0, "Softap frequency is not reset")
2196 asserts.assert_true(bandwdith == 0, "Softap bandwdith is not reset")
2197
Bindu Mahadevff295782019-02-08 16:17:48 -08002198 config = create_softap_config()
2199 start_wifi_tethering(ad.dut,
2200 config[WifiEnums.SSID_KEY],
2201 config[WifiEnums.PWD_KEY], band=band)
2202 asserts.assert_true(ad.dut.droid.wifiIsApEnabled(),
2203 "SoftAp is not reported as running")
2204 start_wifi_connection_scan_and_ensure_network_found(ad.dut_client,
2205 config[WifiEnums.SSID_KEY])
lesl2f0fb232019-11-05 16:35:28 +08002206
2207 # Check softap info can get from callback succeed and assert value should be
2208 # valid.
2209 frequency, bandwdith = get_current_softap_info(ad.dut, callbackId, True)
2210 asserts.assert_true(frequency > 0, "Softap frequency is not valid")
2211 asserts.assert_true(bandwdith > 0, "Softap bandwdith is not valid")
2212 # Unregister callback
2213 ad.dut.droid.unregisterSoftApCallback(callbackId)
2214
Bindu Mahadevff295782019-02-08 16:17:48 -08002215 return config
2216
lesle8e3c0a2019-02-22 17:06:04 +08002217def wait_for_expected_number_of_softap_clients(ad, callbackId,
2218 expected_num_of_softap_clients):
2219 """Wait for the number of softap clients to be updated as expected.
2220 Args:
2221 callbackId: Id of the callback associated with registering.
2222 expected_num_of_softap_clients: expected number of softap clients.
2223 """
2224 eventStr = wifi_constants.SOFTAP_CALLBACK_EVENT + str(
2225 callbackId) + wifi_constants.SOFTAP_NUMBER_CLIENTS_CHANGED
James Mattis5a5dd492020-05-14 13:09:43 -07002226 clientData = ad.ed.pop_event(eventStr, SHORT_TIMEOUT)['data']
2227 clientCount = clientData[wifi_constants.SOFTAP_NUMBER_CLIENTS_CALLBACK_KEY]
2228 clientMacAddresses = clientData[wifi_constants.SOFTAP_CLIENTS_MACS_CALLBACK_KEY]
2229 asserts.assert_equal(clientCount, expected_num_of_softap_clients,
2230 "The number of softap clients doesn't match the expected number")
2231 asserts.assert_equal(len(clientMacAddresses), expected_num_of_softap_clients,
2232 "The number of mac addresses doesn't match the expected number")
2233 for macAddress in clientMacAddresses:
2234 asserts.assert_true(checkMacAddress(macAddress), "An invalid mac address was returned")
2235
2236def checkMacAddress(input):
2237 """Validate whether a string is a valid mac address or not.
2238
2239 Args:
2240 input: The string to validate.
2241
2242 Returns: True/False, returns true for a valid mac address and false otherwise.
2243 """
2244 macValidationRegex = "[0-9a-f]{2}([-:]?)[0-9a-f]{2}(\\1[0-9a-f]{2}){4}$"
2245 if re.match(macValidationRegex, input.lower()):
2246 return True
2247 return False
lesle8e3c0a2019-02-22 17:06:04 +08002248
2249def wait_for_expected_softap_state(ad, callbackId, expected_softap_state):
2250 """Wait for the expected softap state change.
2251 Args:
2252 callbackId: Id of the callback associated with registering.
2253 expected_softap_state: The expected softap state.
2254 """
2255 eventStr = wifi_constants.SOFTAP_CALLBACK_EVENT + str(
2256 callbackId) + wifi_constants.SOFTAP_STATE_CHANGED
2257 asserts.assert_equal(ad.ed.pop_event(eventStr,
2258 SHORT_TIMEOUT)['data'][wifi_constants.
2259 SOFTAP_STATE_CHANGE_CALLBACK_KEY],
2260 expected_softap_state,
2261 "Softap state doesn't match with expected state")
2262
2263def get_current_number_of_softap_clients(ad, callbackId):
2264 """pop up all of softap client updated event from queue.
2265 Args:
2266 callbackId: Id of the callback associated with registering.
2267
2268 Returns:
2269 If exist aleast callback, returns last updated number_of_softap_clients.
2270 Returns None when no any match callback event in queue.
2271 """
2272 eventStr = wifi_constants.SOFTAP_CALLBACK_EVENT + str(
2273 callbackId) + wifi_constants.SOFTAP_NUMBER_CLIENTS_CHANGED
2274 events = ad.ed.pop_all(eventStr)
2275 for event in events:
2276 num_of_clients = event['data'][wifi_constants.
2277 SOFTAP_NUMBER_CLIENTS_CALLBACK_KEY]
2278 if len(events) == 0:
2279 return None
2280 return num_of_clients
Bindu Mahadevff295782019-02-08 16:17:48 -08002281
lesl2f0fb232019-11-05 16:35:28 +08002282def get_current_softap_info(ad, callbackId, least_one):
2283 """pop up all of softap info changed event from queue.
2284 Args:
2285 callbackId: Id of the callback associated with registering.
2286 least_one: Wait for the info callback event before pop all.
2287 Returns:
2288 Returns last updated information of softap.
2289 """
2290 eventStr = wifi_constants.SOFTAP_CALLBACK_EVENT + str(
2291 callbackId) + wifi_constants.SOFTAP_INFO_CHANGED
2292 ad.log.info("softap info dump from eventStr %s",
2293 eventStr)
2294 frequency = 0
2295 bandwidth = 0
2296 if (least_one):
2297 event = ad.ed.pop_event(eventStr, SHORT_TIMEOUT)
2298 frequency = event['data'][wifi_constants.
2299 SOFTAP_INFO_FREQUENCY_CALLBACK_KEY]
2300 bandwidth = event['data'][wifi_constants.
2301 SOFTAP_INFO_BANDWIDTH_CALLBACK_KEY]
2302 ad.log.info("softap info updated, frequency is %s, bandwidth is %s",
2303 frequency, bandwidth)
2304
2305 events = ad.ed.pop_all(eventStr)
2306 for event in events:
2307 frequency = event['data'][wifi_constants.
2308 SOFTAP_INFO_FREQUENCY_CALLBACK_KEY]
2309 bandwidth = event['data'][wifi_constants.
2310 SOFTAP_INFO_BANDWIDTH_CALLBACK_KEY]
2311 ad.log.info("softap info, frequency is %s, bandwidth is %s",
2312 frequency, bandwidth)
2313 return frequency, bandwidth
2314
2315
2316
Hsiu-Chang Chenebb239d2020-09-16 15:12:34 +08002317def get_ssrdumps(ad):
Hsiu-Chang Chen6aac0d32019-05-15 14:21:08 +08002318 """Pulls dumps in the ssrdump dir
2319 Args:
2320 ad: android device object.
Hsiu-Chang Chen6aac0d32019-05-15 14:21:08 +08002321 """
2322 logs = ad.get_file_names("/data/vendor/ssrdump/")
2323 if logs:
2324 ad.log.info("Pulling ssrdumps %s", logs)
Hsiu-Chang Chenebb239d2020-09-16 15:12:34 +08002325 log_path = os.path.join(ad.device_log_path, "SSRDUMPS_%s" % ad.serial)
Mark De Ruyter72f8df92020-02-12 13:44:49 -08002326 os.makedirs(log_path, exist_ok=True)
Hsiu-Chang Chen6aac0d32019-05-15 14:21:08 +08002327 ad.pull_files(logs, log_path)
Hsiu-Chang Chen769bef12020-10-10 06:07:52 +00002328 ad.adb.shell("find /data/vendor/ssrdump/ -type f -delete",
2329 ignore_status=True)
Hsiu-Chang Chen6aac0d32019-05-15 14:21:08 +08002330
Xianyuan Jia0e39e552019-01-24 17:17:47 -08002331def start_pcap(pcap, wifi_band, test_name):
Girish Moturucf4dccd2018-08-27 12:22:00 -07002332 """Start packet capture in monitor mode.
2333
2334 Args:
2335 pcap: packet capture object
2336 wifi_band: '2g' or '5g' or 'dual'
Bindu Mahadev76551c12018-12-13 19:42:14 +00002337 test_name: test name to be used for pcap file name
2338
2339 Returns:
xianyuanjia0431ba32018-12-14 09:56:42 -08002340 Dictionary with wifi band as key and the tuple
2341 (pcap Process object, log directory) as the value
Girish Moturucf4dccd2018-08-27 12:22:00 -07002342 """
Xianyuan Jia0e39e552019-01-24 17:17:47 -08002343 log_dir = os.path.join(
Xianyuan Jia5cd06bb2019-06-10 16:29:57 -07002344 context.get_current_context().get_full_output_path(), 'PacketCapture')
Mark De Ruyter72f8df92020-02-12 13:44:49 -08002345 os.makedirs(log_dir, exist_ok=True)
Girish Moturucf4dccd2018-08-27 12:22:00 -07002346 if wifi_band == 'dual':
2347 bands = [BAND_2G, BAND_5G]
2348 else:
2349 bands = [wifi_band]
xianyuanjia0431ba32018-12-14 09:56:42 -08002350 procs = {}
Girish Moturucf4dccd2018-08-27 12:22:00 -07002351 for band in bands:
xianyuanjia0431ba32018-12-14 09:56:42 -08002352 proc = pcap.start_packet_capture(band, log_dir, test_name)
2353 procs[band] = (proc, os.path.join(log_dir, test_name))
2354 return procs
Girish Moturucf4dccd2018-08-27 12:22:00 -07002355
Bindu Mahadevff295782019-02-08 16:17:48 -08002356
xianyuanjia0431ba32018-12-14 09:56:42 -08002357def stop_pcap(pcap, procs, test_status=None):
Bindu Mahadev76551c12018-12-13 19:42:14 +00002358 """Stop packet capture in monitor mode.
2359
2360 Since, the pcap logs in monitor mode can be very large, we will
2361 delete them if they are not required. 'test_status' if True, will delete
2362 the pcap files. If False, we will keep them.
Girish Moturucf4dccd2018-08-27 12:22:00 -07002363
2364 Args:
2365 pcap: packet capture object
xianyuanjia0431ba32018-12-14 09:56:42 -08002366 procs: dictionary returned by start_pcap
Bindu Mahadev76551c12018-12-13 19:42:14 +00002367 test_status: status of the test case
Girish Moturucf4dccd2018-08-27 12:22:00 -07002368 """
xianyuanjia0431ba32018-12-14 09:56:42 -08002369 for proc, fname in procs.values():
2370 pcap.stop_packet_capture(proc)
Bindu Mahadev76551c12018-12-13 19:42:14 +00002371
2372 if test_status:
xianyuanjia0431ba32018-12-14 09:56:42 -08002373 shutil.rmtree(os.path.dirname(fname))
Hsiu-Chang Chenf8578472018-09-18 12:23:42 +08002374
Jaineel95887fd2019-10-16 16:19:01 -07002375def verify_mac_not_found_in_pcap(ad, mac, packets):
xshuf7267682019-06-03 14:41:56 -07002376 """Verify that a mac address is not found in the captured packets.
2377
2378 Args:
Jaineel95887fd2019-10-16 16:19:01 -07002379 ad: android device object
xshuf7267682019-06-03 14:41:56 -07002380 mac: string representation of the mac address
2381 packets: packets obtained by rdpcap(pcap_fname)
2382 """
2383 for pkt in packets:
2384 logging.debug("Packet Summary = %s", pkt.summary())
2385 if mac in pkt.summary():
Jaineel95887fd2019-10-16 16:19:01 -07002386 asserts.fail("Device %s caught Factory MAC: %s in packet sniffer."
2387 "Packet = %s" % (ad.serial, mac, pkt.show()))
Bindu Mahadevff295782019-02-08 16:17:48 -08002388
Jaineel95887fd2019-10-16 16:19:01 -07002389def verify_mac_is_found_in_pcap(ad, mac, packets):
Nate Jiangc2c09c62019-06-05 17:26:08 -07002390 """Verify that a mac address is found in the captured packets.
2391
2392 Args:
Jaineel95887fd2019-10-16 16:19:01 -07002393 ad: android device object
Nate Jiangc2c09c62019-06-05 17:26:08 -07002394 mac: string representation of the mac address
2395 packets: packets obtained by rdpcap(pcap_fname)
2396 """
2397 for pkt in packets:
2398 if mac in pkt.summary():
2399 return
Jaineel95887fd2019-10-16 16:19:01 -07002400 asserts.fail("Did not find MAC = %s in packet sniffer."
2401 "for device %s" % (mac, ad.serial))
Nate Jiangc2c09c62019-06-05 17:26:08 -07002402
Girish Moturuddc0d382020-08-24 12:08:41 -07002403def start_cnss_diags(ads, cnss_diag_file, pixel_models):
Hsiu-Chang Chenf8578472018-09-18 12:23:42 +08002404 for ad in ads:
Girish Moturuddc0d382020-08-24 12:08:41 -07002405 start_cnss_diag(ad, cnss_diag_file, pixel_models)
Hsiu-Chang Chenf8578472018-09-18 12:23:42 +08002406
Bindu Mahadevff295782019-02-08 16:17:48 -08002407
Girish Moturuddc0d382020-08-24 12:08:41 -07002408def start_cnss_diag(ad, cnss_diag_file, pixel_models):
Hsiu-Chang Chenf8578472018-09-18 12:23:42 +08002409 """Start cnss_diag to record extra wifi logs
2410
2411 Args:
2412 ad: android device object.
Girish Moturuddc0d382020-08-24 12:08:41 -07002413 cnss_diag_file: cnss diag config file to push to device.
2414 pixel_models: pixel devices.
Hsiu-Chang Chenf8578472018-09-18 12:23:42 +08002415 """
Girish Moturuddc0d382020-08-24 12:08:41 -07002416 if ad.model not in pixel_models:
2417 ad.log.info("Device not supported to collect pixel logger")
2418 return
Hsiu-Chang Chenf8578472018-09-18 12:23:42 +08002419 if ad.model in wifi_constants.DEVICES_USING_LEGACY_PROP:
2420 prop = wifi_constants.LEGACY_CNSS_DIAG_PROP
2421 else:
2422 prop = wifi_constants.CNSS_DIAG_PROP
2423 if ad.adb.getprop(prop) != 'true':
Girish Moturuddc0d382020-08-24 12:08:41 -07002424 if not int(ad.adb.shell("ls -l %s%s | wc -l" %
2425 (CNSS_DIAG_CONFIG_PATH,
2426 CNSS_DIAG_CONFIG_FILE))):
2427 ad.adb.push("%s %s" % (cnss_diag_file, CNSS_DIAG_CONFIG_PATH))
Hsiu-Chang Chen769bef12020-10-10 06:07:52 +00002428 ad.adb.shell("find /data/vendor/wifi/cnss_diag/wlan_logs/ -type f -delete",
2429 ignore_status=True)
Hsiu-Chang Chenf8578472018-09-18 12:23:42 +08002430 ad.adb.shell("setprop %s true" % prop, ignore_status=True)
2431
Bindu Mahadevff295782019-02-08 16:17:48 -08002432
Girish Moturuddc0d382020-08-24 12:08:41 -07002433def stop_cnss_diags(ads, pixel_models):
Hsiu-Chang Chenf8578472018-09-18 12:23:42 +08002434 for ad in ads:
Girish Moturuddc0d382020-08-24 12:08:41 -07002435 stop_cnss_diag(ad, pixel_models)
Hsiu-Chang Chenf8578472018-09-18 12:23:42 +08002436
Bindu Mahadevff295782019-02-08 16:17:48 -08002437
Girish Moturuddc0d382020-08-24 12:08:41 -07002438def stop_cnss_diag(ad, pixel_models):
Hsiu-Chang Chenf8578472018-09-18 12:23:42 +08002439 """Stops cnss_diag
2440
2441 Args:
2442 ad: android device object.
Girish Moturuddc0d382020-08-24 12:08:41 -07002443 pixel_models: pixel devices.
Hsiu-Chang Chenf8578472018-09-18 12:23:42 +08002444 """
Girish Moturuddc0d382020-08-24 12:08:41 -07002445 if ad.model not in pixel_models:
2446 ad.log.info("Device not supported to collect pixel logger")
2447 return
Hsiu-Chang Chenf8578472018-09-18 12:23:42 +08002448 if ad.model in wifi_constants.DEVICES_USING_LEGACY_PROP:
2449 prop = wifi_constants.LEGACY_CNSS_DIAG_PROP
2450 else:
2451 prop = wifi_constants.CNSS_DIAG_PROP
2452 ad.adb.shell("setprop %s false" % prop, ignore_status=True)
2453
Bindu Mahadevff295782019-02-08 16:17:48 -08002454
Hsiu-Chang Chenebb239d2020-09-16 15:12:34 +08002455def get_cnss_diag_log(ad):
Hsiu-Chang Chenf8578472018-09-18 12:23:42 +08002456 """Pulls the cnss_diag logs in the wlan_logs dir
2457 Args:
2458 ad: android device object.
Hsiu-Chang Chenf8578472018-09-18 12:23:42 +08002459 """
2460 logs = ad.get_file_names("/data/vendor/wifi/cnss_diag/wlan_logs/")
2461 if logs:
2462 ad.log.info("Pulling cnss_diag logs %s", logs)
Xianyuan Jia0e39e552019-01-24 17:17:47 -08002463 log_path = os.path.join(ad.device_log_path, "CNSS_DIAG_%s" % ad.serial)
Mark De Ruyter72f8df92020-02-12 13:44:49 -08002464 os.makedirs(log_path, exist_ok=True)
Hsiu-Chang Chenf8578472018-09-18 12:23:42 +08002465 ad.pull_files(logs, log_path)
Bindu Mahadev7e5dc682019-02-01 16:53:34 -08002466
Bindu Mahadevff295782019-02-08 16:17:48 -08002467
David Sue4cd9c22019-03-26 18:07:26 -07002468LinkProbeResult = namedtuple('LinkProbeResult', (
2469 'is_success', 'stdout', 'elapsed_time', 'failure_reason'))
2470
2471
2472def send_link_probe(ad):
2473 """Sends a link probe to the currently connected AP, and returns whether the
2474 probe succeeded or not.
2475
2476 Args:
2477 ad: android device object
2478 Returns:
2479 LinkProbeResult namedtuple
2480 """
2481 stdout = ad.adb.shell('cmd wifi send-link-probe')
2482 asserts.assert_false('Error' in stdout or 'Exception' in stdout,
2483 'Exception while sending link probe: ' + stdout)
2484
2485 is_success = False
2486 elapsed_time = None
2487 failure_reason = None
2488 if 'succeeded' in stdout:
2489 is_success = True
2490 elapsed_time = next(
2491 (int(token) for token in stdout.split() if token.isdigit()), None)
2492 elif 'failed with reason' in stdout:
2493 failure_reason = next(
2494 (int(token) for token in stdout.split() if token.isdigit()), None)
2495 else:
2496 asserts.fail('Unexpected link probe result: ' + stdout)
2497
2498 return LinkProbeResult(
2499 is_success=is_success, stdout=stdout,
2500 elapsed_time=elapsed_time, failure_reason=failure_reason)
2501
2502
2503def send_link_probes(ad, num_probes, delay_sec):
2504 """Sends a sequence of link probes to the currently connected AP, and
2505 returns whether the probes succeeded or not.
2506
2507 Args:
2508 ad: android device object
2509 num_probes: number of probes to perform
2510 delay_sec: delay time between probes, in seconds
2511 Returns:
2512 List[LinkProbeResult] one LinkProbeResults for each probe
2513 """
2514 logging.info('Sending link probes')
2515 results = []
2516 for _ in range(num_probes):
2517 # send_link_probe() will also fail the test if it sees an exception
2518 # in the stdout of the adb shell command
2519 result = send_link_probe(ad)
2520 logging.info('link probe results: ' + str(result))
2521 results.append(result)
2522 time.sleep(delay_sec)
2523
2524 return results
2525
2526
Bindu Mahadev7e5dc682019-02-01 16:53:34 -08002527def ap_setup(test, index, ap, network, bandwidth=80, channel=6):
2528 """Set up the AP with provided network info.
2529
2530 Args:
2531 test: the calling test class object.
2532 index: int, index of the AP.
2533 ap: access_point object of the AP.
2534 network: dict with information of the network, including ssid,
2535 password and bssid.
2536 bandwidth: the operation bandwidth for the AP, default 80MHz.
2537 channel: the channel number for the AP.
2538 Returns:
2539 brconfigs: the bridge interface configs
2540 """
2541 bss_settings = []
2542 ssid = network[WifiEnums.SSID_KEY]
2543 test.access_points[index].close()
2544 time.sleep(5)
2545
2546 # Configure AP as required.
2547 if "password" in network.keys():
2548 password = network["password"]
2549 security = hostapd_security.Security(
2550 security_mode="wpa", password=password)
2551 else:
2552 security = hostapd_security.Security(security_mode=None, password=None)
2553 config = hostapd_ap_preset.create_ap_preset(
2554 channel=channel,
2555 ssid=ssid,
2556 security=security,
2557 bss_settings=bss_settings,
2558 vht_bandwidth=bandwidth,
2559 profile_name='whirlwind',
2560 iface_wlan_2g=ap.wlan_2g,
2561 iface_wlan_5g=ap.wlan_5g)
2562 ap.start_ap(config)
2563 logging.info("AP started on channel {} with SSID {}".format(channel, ssid))
Bindu Mahadevff295782019-02-08 16:17:48 -08002564
2565
2566def turn_ap_off(test, AP):
2567 """Bring down hostapd on the Access Point.
2568 Args:
2569 test: The test class object.
2570 AP: int, indicating which AP to turn OFF.
2571 """
2572 hostapd_2g = test.access_points[AP-1]._aps['wlan0'].hostapd
2573 if hostapd_2g.is_alive():
2574 hostapd_2g.stop()
2575 logging.debug('Turned WLAN0 AP%d off' % AP)
2576 hostapd_5g = test.access_points[AP-1]._aps['wlan1'].hostapd
2577 if hostapd_5g.is_alive():
2578 hostapd_5g.stop()
2579 logging.debug('Turned WLAN1 AP%d off' % AP)
2580
2581
2582def turn_ap_on(test, AP):
2583 """Bring up hostapd on the Access Point.
2584 Args:
2585 test: The test class object.
2586 AP: int, indicating which AP to turn ON.
2587 """
2588 hostapd_2g = test.access_points[AP-1]._aps['wlan0'].hostapd
2589 if not hostapd_2g.is_alive():
2590 hostapd_2g.start(hostapd_2g.config)
2591 logging.debug('Turned WLAN0 AP%d on' % AP)
2592 hostapd_5g = test.access_points[AP-1]._aps['wlan1'].hostapd
2593 if not hostapd_5g.is_alive():
2594 hostapd_5g.start(hostapd_5g.config)
2595 logging.debug('Turned WLAN1 AP%d on' % AP)
Joe Brennan48c3f692019-04-11 08:30:16 -07002596
2597
2598def turn_location_off_and_scan_toggle_off(ad):
2599 """Turns off wifi location scans."""
2600 utils.set_location_service(ad, False)
2601 ad.droid.wifiScannerToggleAlwaysAvailable(False)
2602 msg = "Failed to turn off location service's scan."
2603 asserts.assert_true(not ad.droid.wifiScannerIsAlwaysAvailable(), msg)
Alfie Chen675be872020-06-04 10:48:14 +08002604
2605
2606def set_softap_channel(dut, ap_iface='wlan1', cs_count=10, channel=2462):
2607 """ Set SoftAP mode channel
2608
2609 Args:
2610 dut: android device object
2611 ap_iface: interface of SoftAP mode.
2612 cs_count: how many beacon frames before switch channel, default = 10
2613 channel: a wifi channel.
2614 """
2615 chan_switch_cmd = 'hostapd_cli -i {} chan_switch {} {}'
2616 chan_switch_cmd_show = chan_switch_cmd.format(ap_iface,cs_count,channel)
2617 dut.log.info('adb shell {}'.format(chan_switch_cmd_show))
2618 chan_switch_result = dut.adb.shell(chan_switch_cmd.format(ap_iface,
2619 cs_count,
2620 channel))
2621 if chan_switch_result == 'OK':
2622 dut.log.info('switch hotspot channel to {}'.format(channel))
2623 return chan_switch_result
2624
2625 asserts.fail("Failed to switch hotspot channel")
2626