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