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