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