1#!/usr/bin/env python3.4
2#
3#   Copyright 2016 - The Android Open Source Project
4#
5#   Licensed under the Apache License, Version 2.0 (the "License");
6#   you may not use this file except in compliance with the License.
7#   You may obtain a copy of the License at
8#
9#       http://www.apache.org/licenses/LICENSE-2.0
10#
11#   Unless required by applicable law or agreed to in writing, software
12#   distributed under the License is distributed on an "AS IS" BASIS,
13#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14#   See the License for the specific language governing permissions and
15#   limitations under the License.
16
17import itertools
18import json
19import logging
20import pprint
21import queue
22import time
23
24import acts.base_test
25import acts.signals as signals
26import acts_contrib.test_utils.wifi.wifi_test_utils as wutils
27
28import acts.utils
29
30from acts import asserts
31from acts.test_decorators import test_tracker_info
32from acts.controllers.iperf_server import IPerfServer
33from acts_contrib.test_utils.bt.bt_test_utils import enable_bluetooth
34from acts_contrib.test_utils.bt.bt_test_utils import disable_bluetooth
35from acts_contrib.test_utils.wifi.WifiBaseTest import WifiBaseTest
36from acts_contrib.test_utils.wifi.wifi_constants import\
37    COEX_BAND, COEX_CHANNEL, COEX_POWER_CAP_DBM, KEY_COEX_UNSAFE_CHANNELS, KEY_COEX_RESTRICTIONS
38
39WifiEnums = wutils.WifiEnums
40# Default timeout used for reboot, toggle WiFi and Airplane mode,
41# for the system to settle down after the operation.
42DEFAULT_TIMEOUT = 10
43BAND_2GHZ = 0
44BAND_5GHZ = 1
45
46
47class WifiManagerTest(WifiBaseTest):
48    """Tests for APIs in Android's WifiManager class.
49
50    Test Bed Requirement:
51    * Two Android device
52    * Several Wi-Fi networks visible to the device, including an open Wi-Fi
53      network.
54    """
55
56    def __init__(self, configs):
57        super().__init__(configs)
58        self.enable_packet_log = True
59
60    def setup_class(self):
61        super().setup_class()
62
63        self.dut = self.android_devices[0]
64        wutils.wifi_test_device_init(self.dut)
65        wutils.wifi_toggle_state(self.dut, True)
66
67        self.dut_client = None
68        if len(self.android_devices) > 1:
69            self.dut_client = self.android_devices[1]
70            wutils.wifi_test_device_init(self.dut_client)
71            wutils.wifi_toggle_state(self.dut_client, True)
72
73        req_params = []
74        opt_param = [
75            "open_network", "reference_networks", "iperf_server_address",
76            "wpa_networks", "wep_networks", "coex_unsafe_channels",
77            "coex_restrictions", "wifi6_models"
78        ]
79        self.unpack_userparams(
80            req_param_names=req_params, opt_param_names=opt_param)
81
82        if "AccessPoint" in self.user_params:
83            self.legacy_configure_ap_and_start(wpa_network=True, wep_network=True)
84        elif "OpenWrtAP" in self.user_params:
85            self.openwrt = self.access_points[0]
86            self.configure_openwrt_ap_and_start(open_network=True,
87                                                wpa_network=True,
88                                                wep_network=self.openwrt.is_version_under_20())
89
90        asserts.assert_true(
91            len(self.reference_networks) > 0,
92            "Need at least one reference network with psk.")
93        self.wpapsk_2g = self.reference_networks[0]["2g"]
94        self.wpapsk_5g = self.reference_networks[0]["5g"]
95        self.open_network_2g = self.open_network[0]["2g"]
96        self.open_network_5g = self.open_network[0]["5g"]
97
98        # Use local host as iperf server.
99        asserts.assert_true(
100          wutils.get_host_public_ipv4_address(),
101          "The host has no public ip address")
102        self.iperf_server_address = wutils.get_host_public_ipv4_address()
103        self.iperf_server_port = wutils.get_iperf_server_port()
104        try:
105          self.iperf_server = IPerfServer(self.iperf_server_port)
106          self.iperf_server.start()
107          logging.info(f"IPerf server started on {self.iperf_server_port}")
108        except Exception as e:
109          raise signals.TestFailure("Failed to start iperf3 server: %s" % e)
110
111    def setup_test(self):
112        super().setup_test()
113        for ad in self.android_devices:
114            ad.droid.wakeLockAcquireBright()
115            ad.droid.wakeUpNow()
116        wutils.wifi_toggle_state(self.dut, True)
117
118    def teardown_test(self):
119        super().teardown_test()
120        for ad in self.android_devices:
121            ad.droid.wakeLockRelease()
122            ad.droid.goToSleepNow()
123        self.turn_location_off_and_scan_toggle_off()
124        if self.dut.droid.wifiIsApEnabled():
125            wutils.stop_wifi_tethering(self.dut)
126        for ad in self.android_devices:
127            wutils.reset_wifi(ad)
128        self.log.debug("Toggling Airplane mode OFF")
129        asserts.assert_true(
130            acts.utils.force_airplane_mode(self.dut, False),
131            "Can not turn airplane mode off: %s" % self.dut.serial)
132
133        if self.dut.model in self.user_params["google_pixel_watch_models"]:
134            if wutils.get_wear_wifimediator_disable_status(self.dut):
135                wutils.disable_wear_wifimediator(self.dut, False)
136
137    def teardown_class(self):
138        self.iperf_server.stop()
139        if "AccessPoint" in self.user_params:
140            del self.user_params["reference_networks"]
141            del self.user_params["open_network"]
142
143
144    """Helper Functions"""
145
146    def connect_to_wifi_network(self, params):
147        """Connection logic for open and psk wifi networks.
148
149        Args:
150            params: A tuple of network info and AndroidDevice object.
151        """
152        network, ad = params
153        droid = ad.droid
154        ed = ad.ed
155        SSID = network[WifiEnums.SSID_KEY]
156        wutils.start_wifi_connection_scan_and_ensure_network_found(
157            ad, SSID);
158        wutils.wifi_connect(ad, network, num_of_tries=3)
159
160    def get_connection_data(self, dut, network):
161        """Get network id and ssid info from connection data.
162
163        Args:
164            dut: The Android device object under test.
165            network: dict representing the network to connect to.
166
167        Returns:
168            A convenience dict with the connected network's ID and SSID.
169
170        """
171        params = (network, dut)
172        self.connect_to_wifi_network(params)
173        connect_data = dut.droid.wifiGetConnectionInfo()
174        ssid_id_dict = dict()
175        ssid_id_dict[WifiEnums.NETID_KEY] = connect_data[WifiEnums.NETID_KEY]
176        ssid_id_dict[WifiEnums.SSID_KEY] = connect_data[WifiEnums.SSID_KEY]
177        return ssid_id_dict
178
179    def connect_multiple_networks(self, dut):
180        """Connect to one 2.4GHz and one 5Ghz network.
181
182        Args:
183            dut: The Android device object under test.
184
185        Returns:
186            A list with the connection details for the 2GHz and 5GHz networks.
187
188        """
189        network_list = list()
190        connect_2g_data = self.get_connection_data(dut, self.wpapsk_2g)
191        network_list.append(connect_2g_data)
192        connect_5g_data = self.get_connection_data(dut, self.wpapsk_5g)
193        network_list.append(connect_5g_data)
194        return network_list
195
196    def get_enabled_network(self, network1, network2):
197        """Check network status and return currently unconnected network.
198
199        Args:
200            network1: dict representing a network.
201            network2: dict representing a network.
202
203        Return:
204            Network dict of the unconnected network.
205
206        """
207        wifi_info = self.dut.droid.wifiGetConnectionInfo()
208        enabled = network1
209        if wifi_info[WifiEnums.SSID_KEY] == network1[WifiEnums.SSID_KEY]:
210            enabled = network2
211        return enabled
212
213    def check_configstore_networks(self, networks):
214        """Verify that all previously configured networks are presistent after
215           reboot.
216
217        Args:
218            networks: List of network dicts.
219
220        Return:
221            None. Raises TestFailure.
222
223        """
224        network_info = self.dut.droid.wifiGetConfiguredNetworks()
225        if len(network_info) != len(networks):
226            msg = (
227                "Length of configured networks before and after reboot don't"
228                " match. \nBefore reboot = %s \n After reboot = %s" %
229                (networks, network_info))
230            raise signals.TestFailure(msg)
231        # For each network, check if it exists in configured list after reboot
232        current_ssids = set()
233        for network in networks:
234            exists = wutils.match_networks({
235                WifiEnums.SSID_KEY: network[WifiEnums.SSID_KEY]
236            }, network_info)
237            if not len(exists):
238                raise signals.TestFailure("%s network is not present in the"
239                                          " configured list after reboot" %
240                                          network[WifiEnums.SSID_KEY])
241            # Get the new network id for each network after reboot.
242            network[WifiEnums.NETID_KEY] = exists[0]['networkId']
243            if exists[0]['status'] == 'CURRENT':
244                current_ssids.add(network[WifiEnums.SSID_KEY])
245                # At any given point, there can only be one currently active
246                # network, defined with 'status':'CURRENT'
247                if len(current_ssids) > 1:
248                    raise signals.TestFailure("More than one network showing"
249                                              "as 'CURRENT' after reboot")
250
251    def connect_to_wifi_network_with_id(self, network_id, network_ssid):
252        """Connect to the given network using network id and verify SSID.
253
254        Args:
255            network_id: int Network Id of the network.
256            network_ssid: string SSID of the network.
257
258        Returns: True if connect using network id was successful;
259                 False otherwise.
260
261        """
262        wutils.start_wifi_connection_scan_and_ensure_network_found(
263            self.dut, network_ssid);
264        wutils.wifi_connect_by_id(self.dut, network_id)
265        connect_data = self.dut.droid.wifiGetConnectionInfo()
266        connect_ssid = connect_data[WifiEnums.SSID_KEY]
267        self.log.debug("Expected SSID = %s Connected SSID = %s" %
268                       (network_ssid, connect_ssid))
269        if connect_ssid != network_ssid:
270            return False
271        wutils.verify_11ax_wifi_connection(
272            self.dut, self.wifi6_models, "wifi6_ap" in self.user_params)
273        return True
274
275    def run_iperf_client(self, params):
276        """Run iperf traffic after connection.
277
278        Args:
279            params: A tuple of network info and AndroidDevice object.
280        """
281        wait_time = 5
282        network, ad = params
283        SSID = network[WifiEnums.SSID_KEY]
284        self.log.info("Starting iperf traffic through {}".format(SSID))
285        time.sleep(wait_time)
286        port_arg = "-p {}".format(self.iperf_server_port)
287        success, data = ad.run_iperf_client(self.iperf_server_address,
288                                            port_arg)
289        self.log.debug(pprint.pformat(data))
290        asserts.assert_true(success, "Error occurred in iPerf traffic.")
291
292    def connect_to_wifi_network_toggle_wifi_and_run_iperf(self, params):
293        """ Connect to the provided network and then toggle wifi mode and wait
294        for reconnection to the provided network.
295
296        Logic steps are
297        1. Connect to the network.
298        2. Turn wifi off.
299        3. Turn wifi on.
300        4. Wait for connection to the network.
301        5. Run iperf traffic.
302
303        Args:
304            params: A tuple of network info and AndroidDevice object.
305       """
306        network, ad = params
307        self.connect_to_wifi_network(params)
308        wutils.toggle_wifi_and_wait_for_reconnection(
309            ad, network, num_of_tries=5)
310        self.run_iperf_client(params)
311
312    def run_iperf(self, iperf_args):
313        iperf_addr = self.iperf_server_address
314        self.log.info("Running iperf client.")
315        _, data = self.dut.run_iperf_client(iperf_addr, iperf_args)
316        self.log.debug(data)
317
318    def run_iperf_rx_tx(self, time, omit=10):
319        args = "-p {} -t {} -O 10".format(self.iperf_server_port, time, omit)
320        self.log.info("Running iperf client {}".format(args))
321        self.run_iperf(args)
322        args = "-p {} -t {} -O 10 -R".format(self.iperf_server_port, time,
323                                             omit)
324        self.log.info("Running iperf client {}".format(args))
325        self.run_iperf(args)
326
327    def get_energy_info(self):
328        """ Steps:
329            1. Check that the WiFi energy info reporting support on this device
330               is as expected (support or not).
331            2. If the device does not support energy info reporting as
332               expected, skip the test.
333            3. Call API to get WiFi energy info.
334            4. Verify the values of "ControllerEnergyUsed" and
335               "ControllerIdleTimeMillis" in energy info don't decrease.
336            5. Repeat from Step 3 for 10 times.
337        """
338        # Check if dut supports energy info reporting.
339        actual_support = self.dut.droid.wifiIsEnhancedPowerReportingSupported()
340        model = self.dut.model
341        if not actual_support:
342            asserts.skip(
343                ("Device %s does not support energy info reporting as "
344                 "expected.") % model)
345        # Verify reported values don't decrease.
346        self.log.info(("Device %s supports energy info reporting, verify that "
347                       "the reported values don't decrease.") % model)
348        energy = 0
349        idle_time = 0
350        for i in range(10):
351            info = self.dut.droid.wifiGetControllerActivityEnergyInfo()
352            self.log.debug("Iteration %d, got energy info: %s" % (i, info))
353            new_energy = info["ControllerEnergyUsed"]
354            new_idle_time = info["ControllerIdleTimeMillis"]
355            asserts.assert_true(new_energy >= energy,
356                                "Energy value decreased: previous %d, now %d" %
357                                (energy, new_energy))
358            energy = new_energy
359            asserts.assert_true(new_idle_time >= idle_time,
360                                "Idle time decreased: previous %d, now %d" % (
361                                    idle_time, new_idle_time))
362            idle_time = new_idle_time
363            wutils.start_wifi_connection_scan(self.dut)
364
365    def turn_location_on_and_scan_toggle_on(self):
366        """ Turns on wifi location scans.
367        """
368        acts.utils.set_location_service(self.dut, True)
369        self.dut.droid.wifiScannerToggleAlwaysAvailable(True)
370        msg = "Failed to turn on location service's scan."
371        asserts.assert_true(self.dut.droid.wifiScannerIsAlwaysAvailable(), msg)
372
373    def turn_location_off_and_scan_toggle_off(self):
374        """ Turns off wifi location scans.
375        """
376        acts.utils.set_location_service(self.dut, False)
377        self.dut.droid.wifiScannerToggleAlwaysAvailable(False)
378        msg = "Failed to turn off location service's scan."
379        asserts.assert_true(not self.dut.droid.wifiScannerIsAlwaysAvailable(), msg)
380
381    def turn_location_on_and_scan_toggle_off(self):
382        """ Turns off wifi location scans, but keeps location on.
383        """
384        acts.utils.set_location_service(self.dut, True)
385        self.dut.droid.wifiScannerToggleAlwaysAvailable(False)
386        msg = "Failed to turn off location service's scan."
387        asserts.assert_true(not self.dut.droid.wifiScannerIsAlwaysAvailable(), msg)
388
389    def helper_reconnect_toggle_wifi(self):
390        """Connect to multiple networks, turn off/on wifi, then reconnect to
391           a previously connected network.
392
393        Steps:
394        1. Connect to a 2GHz network.
395        2. Connect to a 5GHz network.
396        3. Turn WiFi OFF/ON.
397        4. Reconnect to the non-current network.
398
399        """
400        connect_2g_data = self.get_connection_data(self.dut, self.wpapsk_2g)
401        connect_5g_data = self.get_connection_data(self.dut, self.wpapsk_5g)
402        wutils.toggle_wifi_off_and_on(self.dut)
403        reconnect_to = self.get_enabled_network(connect_2g_data,
404                                                connect_5g_data)
405        reconnect = self.connect_to_wifi_network_with_id(
406            reconnect_to[WifiEnums.NETID_KEY],
407            reconnect_to[WifiEnums.SSID_KEY])
408        if not reconnect:
409            raise signals.TestFailure("Device did not connect to the correct"
410                                      " network after toggling WiFi.")
411        wutils.verify_11ax_wifi_connection(
412            self.dut, self.wifi6_models, "wifi6_ap" in self.user_params)
413
414    def helper_reconnect_toggle_airplane(self):
415        """Connect to multiple networks, turn on/off Airplane moce, then
416           reconnect a previously connected network.
417
418        Steps:
419        1. Connect to a 2GHz network.
420        2. Connect to a 5GHz network.
421        3. Turn ON/OFF Airplane mode.
422        4. Reconnect to the non-current network.
423
424        """
425        connect_2g_data = self.get_connection_data(self.dut, self.wpapsk_2g)
426        connect_5g_data = self.get_connection_data(self.dut, self.wpapsk_5g)
427        wutils.toggle_airplane_mode_on_and_off(self.dut)
428        reconnect_to = self.get_enabled_network(connect_2g_data,
429                                                connect_5g_data)
430        reconnect = self.connect_to_wifi_network_with_id(
431            reconnect_to[WifiEnums.NETID_KEY],
432            reconnect_to[WifiEnums.SSID_KEY])
433        if not reconnect:
434            raise signals.TestFailure("Device did not connect to the correct"
435                                      " network after toggling Airplane mode.")
436        wutils.verify_11ax_wifi_connection(
437            self.dut, self.wifi6_models, "wifi6_ap" in self.user_params)
438
439    def helper_reboot_configstore_reconnect(self, lock_screen=False):
440        """Connect to multiple networks, reboot then reconnect to previously
441           connected network.
442
443        Steps:
444        1. Connect to a 2GHz network.
445        2. Connect to a 5GHz network.
446        3. Reboot device.
447        4. Verify all networks are persistent after reboot.
448        5. Reconnect to the non-current network.
449
450        """
451        network_list = self.connect_multiple_networks(self.dut)
452        network_list = self.dut.droid.wifiGetConfiguredNetworks()
453        self.dut.reboot()
454        time.sleep(DEFAULT_TIMEOUT)
455        self.check_configstore_networks(network_list)
456
457        reconnect_to = self.get_enabled_network(network_list[BAND_2GHZ],
458                                                network_list[BAND_5GHZ])
459
460        if lock_screen:
461            self.dut.droid.wakeLockRelease()
462            self.dut.droid.goToSleepNow()
463        reconnect = self.connect_to_wifi_network_with_id(
464            reconnect_to[WifiEnums.NETID_KEY],
465            reconnect_to[WifiEnums.SSID_KEY])
466        if not reconnect:
467            raise signals.TestFailure(
468                "Device failed to reconnect to the correct"
469                " network after reboot.")
470        wutils.verify_11ax_wifi_connection(
471            self.dut, self.wifi6_models, "wifi6_ap" in self.user_params)
472
473    def helper_toggle_wifi_reboot_configstore_reconnect(self):
474        """Connect to multiple networks, disable WiFi, reboot, then
475           reconnect to previously connected network.
476
477        Steps:
478        1. Connect to a 2GHz network.
479        2. Connect to a 5GHz network.
480        3. Turn WiFi OFF.
481        4. Reboot device.
482        5. Turn WiFi ON.
483        4. Verify all networks are persistent after reboot.
484        5. Reconnect to the non-current network.
485
486        """
487        network_list = self.connect_multiple_networks(self.dut)
488        self.log.debug("Toggling wifi OFF")
489        wutils.wifi_toggle_state(self.dut, False)
490        time.sleep(DEFAULT_TIMEOUT)
491        network_list = self.dut.droid.wifiGetConfiguredNetworks()
492        self.dut.reboot()
493        time.sleep(DEFAULT_TIMEOUT)
494        self.log.debug("Toggling wifi ON")
495        wutils.wifi_toggle_state(self.dut, True)
496        time.sleep(DEFAULT_TIMEOUT)
497        self.check_configstore_networks(network_list)
498        reconnect_to = self.get_enabled_network(network_list[BAND_2GHZ],
499                                                network_list[BAND_5GHZ])
500        reconnect = self.connect_to_wifi_network_with_id(
501            reconnect_to[WifiEnums.NETID_KEY],
502            reconnect_to[WifiEnums.SSID_KEY])
503        if not reconnect:
504            msg = ("Device failed to reconnect to the correct network after"
505                   " toggling WiFi and rebooting.")
506            raise signals.TestFailure(msg)
507        wutils.verify_11ax_wifi_connection(
508            self.dut, self.wifi6_models, "wifi6_ap" in self.user_params)
509
510    def helper_toggle_airplane_reboot_configstore_reconnect(self):
511        """Connect to multiple networks, enable Airplane mode, reboot, then
512           reconnect to previously connected network.
513
514        Steps:
515        1. Connect to a 2GHz network.
516        2. Connect to a 5GHz network.
517        3. Toggle Airplane mode ON.
518        4. Reboot device.
519        5. Toggle Airplane mode OFF.
520        4. Verify all networks are persistent after reboot.
521        5. Reconnect to the non-current network.
522
523        """
524        network_list = self.connect_multiple_networks(self.dut)
525        self.log.debug("Toggling Airplane mode ON")
526        asserts.assert_true(
527            acts.utils.force_airplane_mode(self.dut, True),
528            "Can not turn on airplane mode on: %s" % self.dut.serial)
529        time.sleep(DEFAULT_TIMEOUT)
530        network_list = self.dut.droid.wifiGetConfiguredNetworks()
531        self.dut.reboot()
532        time.sleep(DEFAULT_TIMEOUT)
533        self.log.debug("Toggling Airplane mode OFF")
534        asserts.assert_true(
535            acts.utils.force_airplane_mode(self.dut, False),
536            "Can not turn on airplane mode on: %s" % self.dut.serial)
537        time.sleep(DEFAULT_TIMEOUT)
538        self.check_configstore_networks(network_list)
539        reconnect_to = self.get_enabled_network(network_list[BAND_2GHZ],
540                                                network_list[BAND_5GHZ])
541        reconnect = self.connect_to_wifi_network_with_id(
542            reconnect_to[WifiEnums.NETID_KEY],
543            reconnect_to[WifiEnums.SSID_KEY])
544        if not reconnect:
545            msg = ("Device failed to reconnect to the correct network after"
546                   " toggling Airplane mode and rebooting.")
547            raise signals.TestFailure(msg)
548        wutils.verify_11ax_wifi_connection(
549            self.dut, self.wifi6_models, "wifi6_ap" in self.user_params)
550
551    def verify_traffic_between_devices(self,dest_device,src_device,num_of_tries=2):
552        """Test the clients and DUT can ping each other.
553
554        Args:
555            num_of_tries: the retry times of ping test.
556            dest_device:Test device.
557            src_device:Second DUT access same AP
558        """
559        dest_device = dest_device.droid.connectivityGetIPv4Addresses('wlan0')[0]
560        for _ in range(num_of_tries):
561            if acts.utils.adb_shell_ping(src_device, count=10, dest_ip=dest_device, timeout=20):
562                break
563        else:
564            asserts.fail("Ping to %s from %s failed" % (src_device.serial, dest_device))
565
566    def ping_public_gateway_ip(self):
567        """Ping 8.8.8.8"""
568        try:
569            ping_result = self.dut.adb.shell('ping -w 5 8.8.8.8')
570            if '0%' in ping_result:
571                self.dut.log.info('Ping success')
572            return True
573        except:
574            self.dut.log.error('Faild to ping public gateway 8.8.8.8')
575            return False
576
577    """Tests"""
578
579    @test_tracker_info(uuid="525fc5e3-afba-4bfd-9a02-5834119e3c66")
580    def test_toggle_wifi_state_and_get_startupTime(self):
581        """Test toggling wifi"""
582        self.log.debug("Going from on to off.")
583        wutils.wifi_toggle_state(self.dut, False)
584        self.log.debug("Going from off to on.")
585        startTime = time.time()
586        wutils.wifi_toggle_state(self.dut, True)
587        startup_time = time.time() - startTime
588        self.log.debug("WiFi was enabled on the device in %s s." % startup_time)
589
590    @test_tracker_info(uuid="e9d11563-2bbe-4c96-87eb-ec919b51435b")
591    def test_toggle_with_screen(self):
592        """Test toggling wifi with screen on/off"""
593        wait_time = 5
594        self.log.debug("Screen from off to on.")
595        self.dut.droid.wakeLockAcquireBright()
596        self.dut.droid.wakeUpNow()
597        time.sleep(wait_time)
598        self.log.debug("Going from on to off.")
599        try:
600            wutils.wifi_toggle_state(self.dut, False)
601            time.sleep(wait_time)
602            self.log.debug("Going from off to on.")
603            wutils.wifi_toggle_state(self.dut, True)
604        finally:
605            self.dut.droid.wakeLockRelease()
606            time.sleep(wait_time)
607            self.dut.droid.goToSleepNow()
608
609    @test_tracker_info(uuid="71556e06-7fb1-4e2b-9338-b01f1f8e286e")
610    def test_scan(self):
611        """Test wifi connection scan can start and find expected networks."""
612        ssid = self.open_network_2g[WifiEnums.SSID_KEY]
613        wutils.start_wifi_connection_scan_and_ensure_network_found(
614            self.dut, ssid)
615        ssid = self.open_network_5g[WifiEnums.SSID_KEY]
616        wutils.start_wifi_connection_scan_and_ensure_network_found(
617            self.dut, ssid)
618
619    @test_tracker_info(uuid="3ea09efb-6921-429e-afb1-705ef5a09afa")
620    def test_scan_with_wifi_off_and_location_scan_on(self):
621        """Put wifi in scan only mode"""
622        self.turn_location_on_and_scan_toggle_on()
623        wutils.wifi_toggle_state(self.dut, False)
624
625        """Test wifi connection scan can start and find expected networks."""
626        ssid = self.open_network_2g[WifiEnums.SSID_KEY]
627        wutils.start_wifi_connection_scan_and_ensure_network_found(
628            self.dut, ssid)
629        ssid = self.open_network_5g[WifiEnums.SSID_KEY]
630        wutils.start_wifi_connection_scan_and_ensure_network_found(
631            self.dut, ssid)
632
633    @test_tracker_info(uuid="558652de-c802-405f-b9dc-b7fcc9237673")
634    def test_scan_after_reboot_with_wifi_off_and_location_scan_on(self):
635        """Put wifi in scan only mode"""
636        self.turn_location_on_and_scan_toggle_on()
637        wutils.wifi_toggle_state(self.dut, False)
638
639        # Reboot the device.
640        self.dut.reboot()
641        time.sleep(DEFAULT_TIMEOUT)
642
643        """Test wifi connection scan can start and find expected networks."""
644        ssid = self.open_network_2g[WifiEnums.SSID_KEY]
645        wutils.start_wifi_connection_scan_and_ensure_network_found(
646            self.dut, ssid)
647        ssid = self.open_network_5g[WifiEnums.SSID_KEY]
648        wutils.start_wifi_connection_scan_and_ensure_network_found(
649            self.dut, ssid)
650
651    @test_tracker_info(uuid="770caebe-bcb1-43ac-95b6-5dd52dd90e80")
652    def test_scan_with_wifi_off_and_location_scan_off(self):
653        """Turn off wifi and location scan"""
654        self.turn_location_on_and_scan_toggle_off()
655
656        if self.dut.model in self.user_params["google_pixel_watch_models"]:
657            wutils.disable_wear_wifimediator(self.dut, True)
658
659        wutils.wifi_toggle_state(self.dut, False)
660
661        """Test wifi connection scan should fail."""
662        self.dut.droid.wifiStartScan()
663        try:
664            self.dut.ed.pop_event("WifiManagerScanResultsAvailable", 60)
665        except queue.Empty:
666            self.log.debug("Wifi scan results not received.")
667        else:
668            asserts.fail("Wi-Fi scan results received")
669
670    @test_tracker_info(uuid="a4ad9930-a8fa-4868-81ed-a79c7483e502")
671    def test_add_network(self):
672        """Test wifi connection scan."""
673        ssid = self.open_network_2g[WifiEnums.SSID_KEY]
674        nId = self.dut.droid.wifiAddNetwork(self.open_network_2g)
675        asserts.assert_true(nId > -1, "Failed to add network.")
676        configured_networks = self.dut.droid.wifiGetConfiguredNetworks()
677        self.log.debug(
678            ("Configured networks after adding: %s" % configured_networks))
679        wutils.assert_network_in_list({
680            WifiEnums.SSID_KEY: ssid
681        }, configured_networks)
682
683    @test_tracker_info(uuid="aca85551-10ba-4007-90d9-08bcdeb16a60")
684    def test_forget_network(self):
685        ssid = self.open_network_2g[WifiEnums.SSID_KEY]
686        nId = self.dut.droid.wifiAddNetwork(self.open_network_2g)
687        asserts.assert_true(nId > -1, "Failed to add network.")
688        configured_networks = self.dut.droid.wifiGetConfiguredNetworks()
689        self.log.debug(
690            ("Configured networks after adding: %s" % configured_networks))
691        wutils.assert_network_in_list({
692            WifiEnums.SSID_KEY: ssid
693        }, configured_networks)
694        wutils.wifi_forget_network(self.dut, ssid)
695        configured_networks = self.dut.droid.wifiGetConfiguredNetworks()
696        for nw in configured_networks:
697            asserts.assert_true(
698                nw[WifiEnums.BSSID_KEY] != ssid,
699                "Found forgotten network %s in configured networks." % ssid)
700
701    @test_tracker_info(uuid="3cff17f6-b684-4a95-a438-8272c2ad441d")
702    def test_reconnect_to_previously_connected(self):
703        """Connect to multiple networks and reconnect to the previous network.
704
705        Steps:
706        1. Connect to a 2GHz network.
707        2. Connect to a 5GHz network.
708        3. Reconnect to the 2GHz network using its network id.
709        4. Reconnect to the 5GHz network using its network id.
710
711        """
712        connect_2g_data = self.get_connection_data(self.dut, self.wpapsk_2g)
713        connect_5g_data = self.get_connection_data(self.dut, self.wpapsk_5g)
714        reconnect_2g = self.connect_to_wifi_network_with_id(
715            connect_2g_data[WifiEnums.NETID_KEY],
716            connect_2g_data[WifiEnums.SSID_KEY])
717        if not reconnect_2g:
718            raise signals.TestFailure("Device did not connect to the correct"
719                                      " 2GHz network.")
720        reconnect_5g = self.connect_to_wifi_network_with_id(
721            connect_5g_data[WifiEnums.NETID_KEY],
722            connect_5g_data[WifiEnums.SSID_KEY])
723        if not reconnect_5g:
724            raise signals.TestFailure("Device did not connect to the correct"
725                                      " 5GHz network.")
726
727    @test_tracker_info(uuid="334175c3-d26a-4c87-a8ab-8eb220b2d80f")
728    def test_reconnect_toggle_wifi(self):
729        """Connect to multiple networks, turn off/on wifi, then reconnect to
730           a previously connected network.
731
732        Steps:
733        1. Connect to a 2GHz network.
734        2. Connect to a 5GHz network.
735        3. Turn WiFi OFF/ON.
736        4. Reconnect to the non-current network.
737
738        """
739        self.helper_reconnect_toggle_wifi()
740
741    @test_tracker_info(uuid="bd2cec9e-7f17-44ef-8a0c-4da92a9b55ae")
742    def test_reconnect_toggle_wifi_with_location_scan_on(self):
743        """Connect to multiple networks, turn off/on wifi, then reconnect to
744           a previously connected network.
745
746        Steps:
747        1. Turn on location scans.
748        2. Connect to a 2GHz network.
749        3. Connect to a 5GHz network.
750        4. Turn WiFi OFF/ON.
751        5. Reconnect to the non-current network.
752
753        """
754        self.turn_location_on_and_scan_toggle_on()
755        self.helper_reconnect_toggle_wifi()
756
757    @test_tracker_info(uuid="8e6e6c21-fefb-4fe8-9fb1-f09b1182b76d")
758    def test_reconnect_toggle_airplane(self):
759        """Connect to multiple networks, turn on/off Airplane moce, then
760           reconnect a previously connected network.
761
762        Steps:
763        1. Connect to a 2GHz network.
764        2. Connect to a 5GHz network.
765        3. Turn ON/OFF Airplane mode.
766        4. Reconnect to the non-current network.
767
768        """
769        self.helper_reconnect_toggle_airplane()
770
771    @test_tracker_info(uuid="28562f13-8a0a-492e-932c-e587560db5f2")
772    def test_reconnect_toggle_airplane_with_location_scan_on(self):
773        """Connect to multiple networks, turn on/off Airplane moce, then
774           reconnect a previously connected network.
775
776        Steps:
777        1. Turn on location scans.
778        2. Connect to a 2GHz network.
779        3. Connect to a 5GHz network.
780        4. Turn ON/OFF Airplane mode.
781        5. Reconnect to the non-current network.
782
783        """
784        self.turn_location_on_and_scan_toggle_on()
785        self.helper_reconnect_toggle_airplane()
786
787    @test_tracker_info(uuid="52b89a47-f260-4343-922d-fbeb4d8d2b63")
788    def test_reconnect_toggle_wifi_on_with_airplane_on(self):
789        """Connect to multiple networks, turn on airplane mode, turn on wifi,
790        then reconnect a previously connected network.
791
792        Steps:
793        1. Connect to a 2GHz network.
794        2. Connect to a 5GHz network.
795        3. Turn ON Airplane mode.
796        4. Turn ON WiFi.
797        5. Reconnect to the a previously connected network.
798        """
799        connect_2g_data = self.get_connection_data(self.dut, self.wpapsk_2g)
800        connect_5g_data = self.get_connection_data(self.dut, self.wpapsk_5g)
801        self.log.debug("Toggling Airplane mode ON")
802        asserts.assert_true(
803            acts.utils.force_airplane_mode(self.dut, True),
804            "Can not turn on airplane mode on: %s" % self.dut.serial)
805        self.log.debug("Toggling wifi ON")
806        wutils.wifi_toggle_state(self.dut, True)
807        time.sleep(DEFAULT_TIMEOUT)
808        reconnect_to = self.get_enabled_network(connect_2g_data,
809                                                connect_5g_data)
810        reconnect = self.connect_to_wifi_network_with_id(
811            reconnect_to[WifiEnums.NETID_KEY],
812            reconnect_to[WifiEnums.SSID_KEY])
813        if not reconnect:
814            raise signals.TestFailure("Device did not connect to the correct"
815                                      " network after toggling WiFi.")
816
817    @test_tracker_info(uuid="2dddc734-e9f6-4d30-9c2d-4368e721a350")
818    def test_verify_airplane_mode_on_with_wifi_disabled(self):
819        """Connect to multiple networks, turn on airplane mode, turn off Wi-Fi,
820        then make sure there is no internet.
821
822        Steps:
823        1. Connect to a 2GHz network.
824        2. Connect to a 5GHz network.
825        3. Turn ON Airplane mode.
826        4. Turn OFF WiFi.
827        5. Ping to make sure there is no internet
828        """
829        connect_2g_data = self.get_connection_data(self.dut, self.wpapsk_2g)
830        connect_5g_data = self.get_connection_data(self.dut, self.wpapsk_5g)
831        self.log.debug("Toggling Airplane mode ON")
832        asserts.assert_true(
833            acts.utils.force_airplane_mode(self.dut, True),
834            "Can not turn on airplane mode on: %s" % self.dut.serial)
835        self.log.debug("Toggling Wi-Fi OFF")
836        wutils.wifi_toggle_state(self.dut, False)
837        time.sleep(DEFAULT_TIMEOUT)
838        if self.ping_public_gateway_ip():
839            raise signals.TestFailure("Device has internet after"
840                                             " toggling WiFi off.")
841
842    @test_tracker_info(uuid="3d041c12-05e2-46a7-ab9b-e3f60cc735db")
843    def test_reboot_configstore_reconnect(self):
844        """Connect to multiple networks, reboot then reconnect to previously
845           connected network.
846
847        Steps:
848        1. Connect to a 2GHz network.
849        2. Connect to a 5GHz network.
850        3. Reboot device.
851        4. Verify all networks are persistent after reboot.
852        5. Reconnect to the non-current network.
853
854        """
855        self.helper_reboot_configstore_reconnect()
856
857    @test_tracker_info(uuid="a70d5853-67b5-4d48-bdf7-08ee51fafd21")
858    def test_reboot_configstore_reconnect_with_location_scan_on(self):
859        """Connect to multiple networks, reboot then reconnect to previously
860           connected network.
861
862        Steps:
863        1. Turn on location scans.
864        2. Connect to a 2GHz network.
865        3. Connect to a 5GHz network.
866        4. Reboot device.
867        5. Verify all networks are persistent after reboot.
868        6. Reconnect to the non-current network.
869
870        """
871        self.turn_location_on_and_scan_toggle_on()
872        self.helper_reboot_configstore_reconnect()
873
874    @test_tracker_info(uuid="26d94dfa-1349-4c8b-aea0-475eb73bb521")
875    def test_toggle_wifi_reboot_configstore_reconnect(self):
876        """Connect to multiple networks, disable WiFi, reboot, then
877           reconnect to previously connected network.
878
879        Steps:
880        1. Connect to a 2GHz network.
881        2. Connect to a 5GHz network.
882        3. Turn WiFi OFF.
883        4. Reboot device.
884        5. Turn WiFi ON.
885        4. Verify all networks are persistent after reboot.
886        5. Reconnect to the non-current network.
887
888        """
889        self.helper_toggle_wifi_reboot_configstore_reconnect()
890
891    @test_tracker_info(uuid="7c004a3b-c1c6-4371-9124-0f34650be915")
892    def test_toggle_wifi_reboot_configstore_reconnect_with_location_scan_on(self):
893        """Connect to multiple networks, disable WiFi, reboot, then
894           reconnect to previously connected network.
895
896        Steps:
897        1. Turn on location scans.
898        2. Connect to a 2GHz network.
899        3. Connect to a 5GHz network.
900        4. Turn WiFi OFF.
901        5. Reboot device.
902        6. Turn WiFi ON.
903        7. Verify all networks are persistent after reboot.
904        8. Reconnect to the non-current network.
905
906        """
907        self.turn_location_on_and_scan_toggle_on()
908        self.helper_toggle_wifi_reboot_configstore_reconnect()
909
910    @test_tracker_info(uuid="4fce017b-b443-40dc-a598-51d59d3bb38f")
911    def test_toggle_airplane_reboot_configstore_reconnect(self):
912        """Connect to multiple networks, enable Airplane mode, reboot, then
913           reconnect to previously connected network.
914
915        Steps:
916        1. Connect to a 2GHz network.
917        2. Connect to a 5GHz network.
918        3. Toggle Airplane mode ON.
919        4. Reboot device.
920        5. Toggle Airplane mode OFF.
921        4. Verify all networks are persistent after reboot.
922        5. Reconnect to the non-current network.
923
924        """
925        self.helper_toggle_airplane_reboot_configstore_reconnect()
926
927    @test_tracker_info(uuid="7f0810f9-2338-4158-95f5-057f5a1905b6")
928    def test_toggle_airplane_reboot_configstore_reconnect_with_location_scan_on(self):
929        """Connect to multiple networks, enable Airplane mode, reboot, then
930           reconnect to previously connected network.
931
932        Steps:
933        1. Turn on location scans.
934        2. Connect to a 2GHz network.
935        3. Connect to a 5GHz network.
936        4. Toggle Airplane mode ON.
937        5. Reboot device.
938        6. Toggle Airplane mode OFF.
939        7. Verify all networks are persistent after reboot.
940        8. Reconnect to the non-current network.
941
942        """
943        self.turn_location_on_and_scan_toggle_on()
944        self.helper_toggle_airplane_reboot_configstore_reconnect()
945
946    @test_tracker_info(uuid="342c13cb-6508-4942-bee3-07c5d20d92a5")
947    def test_reboot_configstore_reconnect_with_screen_lock(self):
948        """Verify device can re-connect to configured networks after reboot.
949
950        Steps:
951        1. Connect to 2G and 5G networks.
952        2. Reboot device
953        3. Verify device connects to 1 network automatically.
954        4. Lock screen and verify device can connect to the other network.
955        """
956        self.helper_reboot_configstore_reconnect(lock_screen=True)
957
958    @test_tracker_info(uuid="7e6050d9-79b1-4726-80cf-686bb99b8945")
959    def test_connect_to_5g_after_reboot_without_unlock(self):
960        """Connect to 5g network afer reboot without unlock.
961
962        Steps:
963        1. Reboot device and lock screen
964        2. Connect to 5G network and verify it works.
965        """
966        self.dut.reboot()
967        time.sleep(DEFAULT_TIMEOUT)
968        self.dut.droid.wakeLockRelease()
969        self.dut.droid.goToSleepNow()
970        wutils.connect_to_wifi_network(self.dut, self.wpapsk_5g)
971        wutils.verify_11ax_wifi_connection(
972            self.dut, self.wifi6_models, "wifi6_ap" in self.user_params)
973
974    @test_tracker_info(uuid="81eb7527-4c92-4422-897a-6b5f6445e84a")
975    def test_config_store_with_wpapsk_2g(self):
976        self.connect_to_wifi_network_toggle_wifi_and_run_iperf(
977            (self.wpapsk_2g, self.dut))
978        wutils.verify_11ax_wifi_connection(
979            self.dut, self.wifi6_models, "wifi6_ap" in self.user_params)
980
981    @test_tracker_info(uuid="8457903d-cb7e-4c89-bcea-7f59585ea6e0")
982    def test_config_store_with_wpapsk_5g(self):
983        self.connect_to_wifi_network_toggle_wifi_and_run_iperf(
984            (self.wpapsk_5g, self.dut))
985        wutils.verify_11ax_wifi_connection(
986            self.dut, self.wifi6_models, "wifi6_ap" in self.user_params)
987
988    @test_tracker_info(uuid="b9fbc13a-47b4-4f64-bd2c-e5a3cb24ab2f")
989    def test_tdls_supported(self):
990        model = self.dut.model
991        self.log.debug("Model is %s" % model)
992        if not model.startswith("volantis"):
993            asserts.assert_true(self.dut.droid.wifiIsTdlsSupported(), (
994                "TDLS should be supported on %s, but device is "
995                "reporting not supported.") % model)
996        else:
997            asserts.assert_false(self.dut.droid.wifiIsTdlsSupported(), (
998                "TDLS should not be supported on %s, but device "
999                "is reporting supported.") % model)
1000
1001    @test_tracker_info(uuid="50637d40-ea59-4f4b-9fc1-e6641d64074c")
1002    def test_energy_info(self):
1003        """Verify the WiFi energy info reporting feature """
1004        self.get_energy_info()
1005
1006    @test_tracker_info(uuid="1f1cf549-53eb-4f36-9f33-ce06c9158efc")
1007    def test_energy_info_connected(self):
1008        """Verify the WiFi energy info reporting feature when connected.
1009
1010        Connect to a wifi network, then the same as test_energy_info.
1011        """
1012        wutils.wifi_connect(self.dut, self.open_network_2g)
1013        self.get_energy_info()
1014        wutils.verify_11ax_wifi_connection(
1015            self.dut, self.wifi6_models, "wifi6_ap" in self.user_params)
1016
1017    @test_tracker_info(uuid="2622c253-defc-4a35-93a6-ca9d29a8238c")
1018    def test_connect_to_wep_2g(self):
1019        """Verify DUT can connect to 2GHz WEP network
1020
1021        Steps:
1022        1. Ensure the 2GHz WEP network is visible in scan result.
1023        2. Connect to the network and validate internet connection.
1024        """
1025        asserts.skip_if(
1026            hasattr(self, "openwrt") and not self.access_points[0].is_version_under_20(),
1027            "OpenWrt no longer support wep network."
1028        )
1029        wutils.connect_to_wifi_network(self.dut, self.wep_networks[0]["2g"])
1030
1031    @test_tracker_info(uuid="1f2d17a2-e92d-43af-966b-3421c0db8620")
1032    def test_connect_to_wep_5g(self):
1033        """Verify DUT can connect to 5GHz WEP network
1034
1035        Steps:
1036        1. Ensure the 5GHz WEP network is visible in scan result.
1037        2. Connect to the network and validate internet connection.
1038        """
1039        asserts.skip_if(
1040            hasattr(self, "openwrt") and not self.access_points[0].is_version_under_20(),
1041            "OpenWrt no longer support wep network."
1042        )
1043        wutils.connect_to_wifi_network(self.dut, self.wep_networks[0]["5g"])
1044
1045    @test_tracker_info(uuid="4a957952-289d-4657-9882-e1475274a7ff")
1046    def test_connect_to_wpa_2g(self):
1047        """Verify DUT can connect to 2GHz WPA-PSK network
1048
1049        Steps:
1050        1. Ensure the 2GHz WPA-PSK network is visible in scan result.
1051        2. Connect to the network and validate internet connection.
1052        """
1053        wutils.connect_to_wifi_network(self.dut, self.wpa_networks[0]["2g"])
1054        wutils.verify_11ax_wifi_connection(
1055            self.dut, self.wifi6_models, "wifi6_ap" in self.user_params)
1056
1057    @test_tracker_info(uuid="612c3c31-a4c5-4014-9a2d-3f4bcc20c0d7")
1058    def test_connect_to_wpa_5g(self):
1059        """Verify DUT can connect to 5GHz WPA-PSK network
1060
1061        Steps:
1062        1. Ensure the 5GHz WPA-PSK network is visible in scan result.
1063        2. Connect to the network and validate internet connection.
1064        """
1065        wutils.connect_to_wifi_network(self.dut, self.wpa_networks[0]["5g"])
1066        wutils.verify_11ax_wifi_connection(
1067            self.dut, self.wifi6_models, "wifi6_ap" in self.user_params)
1068
1069    @test_tracker_info(uuid="2a617fb4-1d8e-44e9-a500-a5456e1df83f")
1070    def test_connect_to_2g_can_be_pinged(self):
1071        """Verify DUT can be pinged by another device when it connects to 2GHz AP
1072
1073        Steps:
1074        1. Ensure the 2GHz WPA-PSK network is visible in scan result.
1075        2. Connect to the network and validate internet connection.
1076        3. Check DUT can be pinged by another device
1077        """
1078        wutils.connect_to_wifi_network(self.dut, self.wpa_networks[0]["2g"])
1079        wutils.verify_11ax_wifi_connection(
1080            self.dut, self.wifi6_models, "wifi6_ap" in self.user_params)
1081        wutils.connect_to_wifi_network(self.dut_client, self.wpa_networks[0]["2g"])
1082        wutils.verify_11ax_wifi_connection(
1083            self.dut_client, self.wifi6_models, "wifi6_ap" in self.user_params)
1084        self.verify_traffic_between_devices(self.dut,self.dut_client)
1085
1086    @test_tracker_info(uuid="94bdd657-649b-4a2c-89c3-3ec6ba18e08e")
1087    def test_connect_to_5g_can_be_pinged(self):
1088        """Verify DUT can be pinged by another device when it connects to 5GHz AP
1089
1090        Steps:
1091        1. Ensure the 5GHz WPA-PSK network is visible in scan result.
1092        2. Connect to the network and validate internet connection.
1093        3. Check DUT can be pinged by another device
1094        """
1095        wutils.connect_to_wifi_network(self.dut, self.wpa_networks[0]["5g"])
1096        wutils.verify_11ax_wifi_connection(
1097            self.dut, self.wifi6_models, "wifi6_ap" in self.user_params)
1098        wutils.connect_to_wifi_network(self.dut_client, self.wpa_networks[0]["5g"])
1099        wutils.verify_11ax_wifi_connection(
1100            self.dut_client, self.wifi6_models, "wifi6_ap" in self.user_params)
1101        self.verify_traffic_between_devices(self.dut,self.dut_client)
1102
1103    @test_tracker_info(uuid="d87359aa-c4da-4554-b5de-8e3fa852a6b0")
1104    def test_sta_turn_off_screen_can_be_pinged(self):
1105        """Verify DUT can be pinged by another device after idle for a while
1106
1107        Steps:
1108        1. Ensure the 2GHz WPA-PSK network is visible in scan result.
1109        2. DUT and DUT_Client connect to the network and validate internet connection.
1110        3. Let DUT sleep for 5 minutes
1111        4. Check DUT can be pinged by DUT_Client
1112        """
1113        asserts.skip_if(len(self.android_devices) < 3, "Need 3 devices")
1114        self.dut_client_a = self.android_devices[1]
1115        self.dut_client_b = self.android_devices[2]
1116
1117        # enable hotspot on dut and connect client devices to it
1118        ap_ssid = "softap_" + acts.utils.rand_ascii_str(8)
1119        ap_password = acts.utils.rand_ascii_str(8)
1120        self.dut.log.info("softap setup: %s %s", ap_ssid, ap_password)
1121        config = {wutils.WifiEnums.SSID_KEY: ap_ssid}
1122        config[wutils.WifiEnums.PWD_KEY] = ap_password
1123        wutils.start_wifi_tethering(
1124            self.dut,
1125            config[wutils.WifiEnums.SSID_KEY],
1126            config[wutils.WifiEnums.PWD_KEY],
1127            wutils.WifiEnums.WIFI_CONFIG_APBAND_AUTO)
1128
1129        # DUT connect to AP
1130        wutils.connect_to_wifi_network(
1131            self.dut_client_a, config, check_connectivity=False)
1132        wutils.connect_to_wifi_network(
1133            self.dut_client_b, config, check_connectivity=False)
1134        # Check DUT and DUT_Client can ping each other successfully
1135        self.verify_traffic_between_devices(self.dut_client_a,
1136                                            self.dut_client_b)
1137        self.verify_traffic_between_devices(self.dut_client_a,
1138                                            self.dut_client_b)
1139
1140        # DUT turn off screen and go sleep for 5 mins
1141        self.dut.droid.wakeLockRelease()
1142        self.dut.droid.goToSleepNow()
1143        # TODO(hsiuchangchen): find a way to check system already suspended
1144        #                      instead of waiting 5 mins
1145        self.log.info("Sleep for 5 minutes")
1146        time.sleep(300)
1147        # Verify DUT_Client can ping DUT when DUT sleeps
1148        self.verify_traffic_between_devices(self.dut_client_a,
1149                                            self.dut_client_b)
1150        self.dut.droid.wakeLockAcquireBright()
1151        self.dut.droid.wakeUpNow()
1152
1153    @test_tracker_info(uuid="25e8dd62-ae9f-46f7-96aa-030fee95dfda")
1154    def test_wifi_saved_network_reset(self):
1155        """Verify DUT can reset Wi-Fi saved network list after add a network.
1156
1157        Steps:
1158        1. Connect to a 2GHz network
1159        2. Reset the Wi-Fi saved network
1160        3. Verify the saved network has been clear
1161        """
1162        ssid = self.open_network_2g[WifiEnums.SSID_KEY]
1163        nId = self.dut.droid.wifiAddNetwork(self.open_network_2g)
1164        asserts.assert_true(nId > -1, "Failed to add network.")
1165        configured_networks = self.dut.droid.wifiGetConfiguredNetworks()
1166        self.log.debug(
1167            ("Configured networks after adding: %s" % configured_networks))
1168        wutils.assert_network_in_list({
1169            WifiEnums.SSID_KEY: ssid
1170        }, configured_networks)
1171        self.dut.droid.wifiFactoryReset()
1172        configured_networks = self.dut.droid.wifiGetConfiguredNetworks()
1173        for nw in configured_networks:
1174            asserts.assert_true(
1175                nw[WifiEnums.BSSID_KEY] != ssid,
1176                "Found saved network %s in configured networks." % ssid)
1177
1178    @test_tracker_info(uuid="402cfaa8-297f-4865-9e27-6bab6adca756")
1179    def test_reboot_wifi_and_bluetooth_on(self):
1180        """Toggle WiFi and bluetooth ON then reboot """
1181        wutils.wifi_toggle_state(self.dut, True)
1182        enable_bluetooth(self.dut.droid, self.dut.ed)
1183
1184        self.dut.reboot()
1185        time.sleep(DEFAULT_TIMEOUT)
1186
1187        asserts.assert_true(self.dut.droid.bluetoothCheckState(),
1188                "bluetooth state changed after reboot")
1189        asserts.assert_true(self.dut.droid.wifiCheckState(),
1190                "wifi state changed after reboot")
1191
1192        disable_bluetooth(self.dut.droid)
1193
1194    @test_tracker_info(uuid="d0e14a2d-a28f-4551-8988-1e15d9d8bb1a")
1195    def test_scan_result_api(self):
1196        """Register scan result callback, start scan and wait for event"""
1197        self.dut.ed.clear_all_events()
1198        self.dut.droid.wifiStartScanWithListener()
1199        try:
1200            events = self.dut.ed.pop_events(
1201                "WifiManagerScanResultsCallbackOnSuccess", 60)
1202        except queue.Empty:
1203            asserts.fail(
1204                "Wi-Fi scan results did not become available within 60s.")
1205
1206    @test_tracker_info(uuid="03cfbc86-7fcc-48d8-ab0f-1f6f3523e596")
1207    def test_enable_disable_auto_join_saved_network(self):
1208        """
1209        Add a saved network, simulate user change the auto join to false, ensure the device doesn't
1210        auto connect to this network
1211
1212        Steps:
1213        1. Create a saved network.
1214        2. Add this saved network, and ensure we connect to this network
1215        3. Simulate user change the auto join to false.
1216        4. Toggle the Wifi off and on
1217        4. Ensure device doesn't connect to his network
1218        """
1219        network = self.open_network_5g
1220        wutils.connect_to_wifi_network(self.dut, network)
1221        wutils.verify_11ax_wifi_connection(
1222            self.dut, self.wifi6_models, "wifi6_ap" in self.user_params)
1223        info = self.dut.droid.wifiGetConnectionInfo()
1224        network_id = info[WifiEnums.NETID_KEY]
1225        self.dut.log.info("Disable auto join on network")
1226        self.dut.droid.wifiEnableAutojoin(network_id, False)
1227        wutils.wifi_toggle_state(self.dut, False)
1228        wutils.wifi_toggle_state(self.dut, True)
1229        asserts.assert_false(
1230            wutils.wait_for_connect(self.dut, network[WifiEnums.SSID_KEY],
1231                                    assert_on_fail=False), "Device should not connect.")
1232        self.dut.droid.wifiEnableAutojoin(network_id, True)
1233        wutils.wait_for_connect(self.dut, network[WifiEnums.SSID_KEY], assert_on_fail=False)
1234        wutils.verify_11ax_wifi_connection(
1235            self.dut, self.wifi6_models, "wifi6_ap" in self.user_params)
1236
1237    def coex_unsafe_channel_key(self, unsafe_channel):
1238        if COEX_POWER_CAP_DBM in unsafe_channel:
1239            return (unsafe_channel[COEX_BAND], unsafe_channel[COEX_CHANNEL],
1240                    unsafe_channel[COEX_POWER_CAP_DBM])
1241        return (unsafe_channel[COEX_BAND], unsafe_channel[COEX_CHANNEL])
1242
1243    @test_tracker_info(uuid="78558b30-3792-4a1f-bb56-34bbbbce6ac8")
1244    def test_set_get_coex_unsafe_channels(self):
1245        """
1246        Set the unsafe channels to avoid for coex, then retrieve the active values and compare to
1247        values set. If the default algorithm is enabled, then ensure that the active values are
1248        unchanged.
1249
1250        Steps:
1251        1. Register a coex callback and listen for the update event to get the current coex values.
1252        2. Create list of coex unsafe channels and restrictions
1253
1254            coex_unsafe_channels format:
1255                [
1256                    {
1257                        "band": <"24_GHZ" or "5_GHZ">
1258                        "channel" : <Channel number>
1259                        (Optional) "powerCapDbm" : <Power Cap in Dbm>
1260                    }
1261                    ...
1262                ]
1263
1264            coex_restrictions format:
1265                [
1266                    (Optional) "WIFI_DIRECT",
1267                    (Optional) "SOFTAP",
1268                    (Optional) "WIFI_AWARE"
1269                ]
1270        3. Set these values as the active values and listen for the update event.
1271        4. If the default algorithm is enabled, expect to not get the update event. If it is
1272           disabled, compare the updated values and see if they are the same as the provided values.
1273        5. Restore the previous values if the test values were set.
1274        """
1275        asserts.skip_if(not self.dut.droid.isSdkAtLeastS(),
1276                        "Require SDK at least S to use wifi coex apis.")
1277        self.dut.ed.clear_all_events()
1278
1279        # Register a coex callback to start receiving coex events
1280        self.dut.droid.wifiRegisterCoexCallback()
1281        try:
1282            # Wait for the immediate callback from registering and store the current values
1283            event = self.dut.ed.pop_event("WifiManagerCoexCallback#onCoexUnsafeChannelsChanged", 5)
1284        except queue.Empty:
1285            asserts.fail("Coex callback event not received after registering.")
1286        prev_unsafe_channels = sorted(json.loads(event["data"][KEY_COEX_UNSAFE_CHANNELS]),
1287                                      key=self.coex_unsafe_channel_key)
1288        prev_restrictions = sorted(json.loads(event["data"][KEY_COEX_RESTRICTIONS]))
1289
1290        # Set new values for coex unsafe channels
1291        test_unsafe_channels = sorted(self.coex_unsafe_channels,
1292                                      key=self.coex_unsafe_channel_key)
1293        test_restrictions = sorted(self.coex_restrictions)
1294        self.dut.droid.wifiSetCoexUnsafeChannels(test_unsafe_channels, test_restrictions)
1295        try:
1296            # Wait for the callback from setting the coex unsafe channels
1297            event = self.dut.ed.pop_event("WifiManagerCoexCallback#onCoexUnsafeChannelsChanged", 5)
1298            # Callback received. This should be expected only if default algo is disabled.
1299            asserts.assert_false(self.dut.droid.wifiIsDefaultCoexAlgorithmEnabled(),
1300                                "Default algo was enabled but Coex callback received after"
1301                                " setCoexUnsafeChannels")
1302            curr_unsafe_channels = sorted(json.loads(event["data"][KEY_COEX_UNSAFE_CHANNELS]),
1303                                          key=self.coex_unsafe_channel_key)
1304            curr_restrictions = sorted(json.loads(event["data"][KEY_COEX_RESTRICTIONS]))
1305            # Compare the current values with the set values
1306            asserts.assert_true(curr_unsafe_channels == test_unsafe_channels,
1307                                "default coex algorithm disabled but current unsafe channels "
1308                                + str(curr_unsafe_channels)
1309                                + " do not match the set values " + str(test_unsafe_channels))
1310            asserts.assert_true(curr_restrictions == test_restrictions,
1311                                "default coex algorithm disabled but current restrictions "
1312                                + str(curr_restrictions)
1313                                + " do not match the set values " + str(test_restrictions))
1314            # Restore the previous values
1315            self.dut.droid.wifiSetCoexUnsafeChannels(prev_unsafe_channels, prev_restrictions)
1316        except queue.Empty:
1317            # Callback not received. This should be expected only if the default algo is enabled.
1318            asserts.assert_true(self.dut.droid.wifiIsDefaultCoexAlgorithmEnabled(),
1319                                "Default algo was disabled but Coex callback not received after"
1320                                " setCoexUnsafeChannels")
1321
1322        self.dut.droid.wifiUnregisterCoexCallback()
1323