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.wifi.WifiBaseTest import WifiBaseTest
30
31WifiEnums = wutils.WifiEnums
32# Default timeout used for reboot, toggle WiFi and Airplane mode,
33# for the system to settle down after the operation.
34DEFAULT_TIMEOUT = 10
35BAND_2GHZ = 0
36BAND_5GHZ = 1
37
38
39class WifiManagerTest(WifiBaseTest):
40    """Tests for APIs in Android's WifiManager class.
41
42    Test Bed Requirement:
43    * One Android device
44    * Several Wi-Fi networks visible to the device, including an open Wi-Fi
45      network.
46    """
47
48    def __init__(self, controllers):
49        WifiBaseTest.__init__(self, controllers)
50
51    def setup_class(self):
52        self.dut = self.android_devices[0]
53        wutils.wifi_test_device_init(self.dut)
54        req_params = []
55        opt_param = [
56            "open_network", "reference_networks", "iperf_server_address"
57        ]
58        self.unpack_userparams(
59            req_param_names=req_params, opt_param_names=opt_param)
60
61        if "AccessPoint" in self.user_params:
62            self.legacy_configure_ap_and_start()
63
64        asserts.assert_true(
65            len(self.reference_networks) > 0,
66            "Need at least one reference network with psk.")
67        wutils.wifi_toggle_state(self.dut, True)
68        if "iperf_server_address" in self.user_params:
69            self.iperf_server = self.iperf_servers[0]
70        self.wpapsk_2g = self.reference_networks[0]["2g"]
71        self.wpapsk_5g = self.reference_networks[0]["5g"]
72        self.open_network = self.open_network[0]["2g"]
73        if hasattr(self, 'iperf_server'):
74            self.iperf_server.start()
75
76    def setup_test(self):
77        self.dut.droid.wakeLockAcquireBright()
78        self.dut.droid.wakeUpNow()
79        wutils.wifi_toggle_state(self.dut, True)
80
81    def teardown_test(self):
82        self.dut.droid.wakeLockRelease()
83        self.dut.droid.goToSleepNow()
84        self.turn_location_off_and_scan_toggle_off()
85        wutils.reset_wifi(self.dut)
86
87    def teardown_class(self):
88        if hasattr(self, 'iperf_server'):
89            self.iperf_server.stop()
90
91    def on_fail(self, test_name, begin_time):
92        self.dut.take_bug_report(test_name, begin_time)
93        self.dut.cat_adb_log(test_name, begin_time)
94
95    def teardown_class(self):
96        if "AccessPoint" in self.user_params:
97            del self.user_params["reference_networks"]
98            del self.user_params["open_network"]
99
100    """Helper Functions"""
101
102    def connect_to_wifi_network(self, params):
103        """Connection logic for open and psk wifi networks.
104
105        Args:
106            params: A tuple of network info and AndroidDevice object.
107        """
108        network, ad = params
109        droid = ad.droid
110        ed = ad.ed
111        SSID = network[WifiEnums.SSID_KEY]
112        wutils.start_wifi_connection_scan_and_ensure_network_found(
113            ad, SSID);
114        wutils.wifi_connect(ad, network, num_of_tries=3)
115
116    def get_connection_data(self, dut, network):
117        """Get network id and ssid info from connection data.
118
119        Args:
120            dut: The Android device object under test.
121            network: dict representing the network to connect to.
122
123        Returns:
124            A convenience dict with the connected network's ID and SSID.
125
126        """
127        params = (network, dut)
128        self.connect_to_wifi_network(params)
129        connect_data = dut.droid.wifiGetConnectionInfo()
130        ssid_id_dict = dict()
131        ssid_id_dict[WifiEnums.NETID_KEY] = connect_data[WifiEnums.NETID_KEY]
132        ssid_id_dict[WifiEnums.SSID_KEY] = connect_data[WifiEnums.SSID_KEY]
133        return ssid_id_dict
134
135    def connect_multiple_networks(self, dut):
136        """Connect to one 2.4GHz and one 5Ghz network.
137
138        Args:
139            dut: The Android device object under test.
140
141        Returns:
142            A list with the connection details for the 2GHz and 5GHz networks.
143
144        """
145        network_list = list()
146        connect_2g_data = self.get_connection_data(dut, self.wpapsk_2g)
147        network_list.append(connect_2g_data)
148        connect_5g_data = self.get_connection_data(dut, self.wpapsk_5g)
149        network_list.append(connect_5g_data)
150        return network_list
151
152    def get_enabled_network(self, network1, network2):
153        """Check network status and return currently unconnected network.
154
155        Args:
156            network1: dict representing a network.
157            network2: dict representing a network.
158
159        Return:
160            Network dict of the unconnected network.
161
162        """
163        wifi_info = self.dut.droid.wifiGetConnectionInfo()
164        enabled = network1
165        if wifi_info[WifiEnums.SSID_KEY] == network1[WifiEnums.SSID_KEY]:
166            enabled = network2
167        return enabled
168
169    def check_configstore_networks(self, networks):
170        """Verify that all previously configured networks are presistent after
171           reboot.
172
173        Args:
174            networks: List of network dicts.
175
176        Return:
177            None. Raises TestFailure.
178
179        """
180        network_info = self.dut.droid.wifiGetConfiguredNetworks()
181        if len(network_info) != len(networks):
182            msg = (
183                "Length of configured networks before and after reboot don't"
184                " match. \nBefore reboot = %s \n After reboot = %s" %
185                (networks, network_info))
186            raise signals.TestFailure(msg)
187        current_count = 0
188        # For each network, check if it exists in configured list after reboot
189        for network in networks:
190            exists = wutils.match_networks({
191                WifiEnums.SSID_KEY: network[WifiEnums.SSID_KEY]
192            }, network_info)
193            if not len(exists):
194                raise signals.TestFailure("%s network is not present in the"
195                                          " configured list after reboot" %
196                                          network[WifiEnums.SSID_KEY])
197            # Get the new network id for each network after reboot.
198            network[WifiEnums.NETID_KEY] = exists[0]['networkId']
199            if exists[0]['status'] == 'CURRENT':
200                current_count += 1
201                # At any given point, there can only be one currently active
202                # network, defined with 'status':'CURRENT'
203                if current_count > 1:
204                    raise signals.TestFailure("More than one network showing"
205                                              "as 'CURRENT' after reboot")
206
207    def connect_to_wifi_network_with_id(self, network_id, network_ssid):
208        """Connect to the given network using network id and verify SSID.
209
210        Args:
211            network_id: int Network Id of the network.
212            network_ssid: string SSID of the network.
213
214        Returns: True if connect using network id was successful;
215                 False otherwise.
216
217        """
218        wutils.start_wifi_connection_scan_and_ensure_network_found(
219            self.dut, network_ssid);
220        wutils.wifi_connect_by_id(self.dut, network_id)
221        connect_data = self.dut.droid.wifiGetConnectionInfo()
222        connect_ssid = connect_data[WifiEnums.SSID_KEY]
223        self.log.debug("Expected SSID = %s Connected SSID = %s" %
224                       (network_ssid, connect_ssid))
225        if connect_ssid != network_ssid:
226            return False
227        return True
228
229    def run_iperf_client(self, params):
230        """Run iperf traffic after connection.
231
232        Args:
233            params: A tuple of network info and AndroidDevice object.
234        """
235        if "iperf_server_address" in self.user_params:
236            wait_time = 5
237            network, ad = params
238            SSID = network[WifiEnums.SSID_KEY]
239            self.log.info("Starting iperf traffic through {}".format(SSID))
240            time.sleep(wait_time)
241            port_arg = "-p {}".format(self.iperf_server.port)
242            success, data = ad.run_iperf_client(self.iperf_server_address,
243                                                port_arg)
244            self.log.debug(pprint.pformat(data))
245            asserts.assert_true(success, "Error occurred in iPerf traffic.")
246
247    def connect_to_wifi_network_toggle_wifi_and_run_iperf(self, params):
248        """ Connect to the provided network and then toggle wifi mode and wait
249        for reconnection to the provided network.
250
251        Logic steps are
252        1. Connect to the network.
253        2. Turn wifi off.
254        3. Turn wifi on.
255        4. Wait for connection to the network.
256        5. Run iperf traffic.
257
258        Args:
259            params: A tuple of network info and AndroidDevice object.
260       """
261        network, ad = params
262        self.connect_to_wifi_network(params)
263        wutils.toggle_wifi_and_wait_for_reconnection(
264            ad, network, num_of_tries=5)
265        self.run_iperf_client(params)
266
267    def run_iperf(self, iperf_args):
268        if "iperf_server_address" not in self.user_params:
269            self.log.error(("Missing iperf_server_address. "
270                            "Provide one in config."))
271        else:
272            iperf_addr = self.user_params["iperf_server_address"]
273            self.log.info("Running iperf client.")
274            result, data = self.dut.run_iperf_client(iperf_addr, iperf_args)
275            self.log.debug(data)
276
277    def run_iperf_rx_tx(self, time, omit=10):
278        args = "-p {} -t {} -O 10".format(self.iperf_server.port, time, omit)
279        self.log.info("Running iperf client {}".format(args))
280        self.run_iperf(args)
281        args = "-p {} -t {} -O 10 -R".format(self.iperf_server.port, time,
282                                             omit)
283        self.log.info("Running iperf client {}".format(args))
284        self.run_iperf(args)
285
286    def get_energy_info(self):
287        """ Steps:
288            1. Check that the WiFi energy info reporting support on this device
289               is as expected (support or not).
290            2. If the device does not support energy info reporting as
291               expected, skip the test.
292            3. Call API to get WiFi energy info.
293            4. Verify the values of "ControllerEnergyUsed" and
294               "ControllerIdleTimeMillis" in energy info don't decrease.
295            5. Repeat from Step 3 for 10 times.
296        """
297        # Check if dut supports energy info reporting.
298        actual_support = self.dut.droid.wifiIsEnhancedPowerReportingSupported()
299        model = self.dut.model
300        if not actual_support:
301            asserts.skip(
302                ("Device %s does not support energy info reporting as "
303                 "expected.") % model)
304        # Verify reported values don't decrease.
305        self.log.info(("Device %s supports energy info reporting, verify that "
306                       "the reported values don't decrease.") % model)
307        energy = 0
308        idle_time = 0
309        for i in range(10):
310            info = self.dut.droid.wifiGetControllerActivityEnergyInfo()
311            self.log.debug("Iteration %d, got energy info: %s" % (i, info))
312            new_energy = info["ControllerEnergyUsed"]
313            new_idle_time = info["ControllerIdleTimeMillis"]
314            asserts.assert_true(new_energy >= energy,
315                                "Energy value decreased: previous %d, now %d" %
316                                (energy, new_energy))
317            energy = new_energy
318            asserts.assert_true(new_idle_time >= idle_time,
319                                "Idle time decreased: previous %d, now %d" % (
320                                    idle_time, new_idle_time))
321            idle_time = new_idle_time
322            wutils.start_wifi_connection_scan(self.dut)
323
324    def turn_location_on_and_scan_toggle_on(self):
325        """ Turns on wifi location scans.
326        """
327        acts.utils.set_location_service(self.dut, True)
328        self.dut.droid.wifiScannerToggleAlwaysAvailable(True)
329        msg = "Failed to turn on location service's scan."
330        asserts.assert_true(self.dut.droid.wifiScannerIsAlwaysAvailable(), msg)
331
332    def turn_location_off_and_scan_toggle_off(self):
333        """ Turns off wifi location scans.
334        """
335        acts.utils.set_location_service(self.dut, False)
336        self.dut.droid.wifiScannerToggleAlwaysAvailable(False)
337        msg = "Failed to turn off location service's scan."
338        asserts.assert_true(not self.dut.droid.wifiScannerIsAlwaysAvailable(), msg)
339
340    def turn_location_on_and_scan_toggle_off(self):
341        """ Turns off wifi location scans, but keeps location on.
342        """
343        acts.utils.set_location_service(self.dut, True)
344        self.dut.droid.wifiScannerToggleAlwaysAvailable(False)
345        msg = "Failed to turn off location service's scan."
346        asserts.assert_true(not self.dut.droid.wifiScannerIsAlwaysAvailable(), msg)
347
348    def helper_reconnect_toggle_wifi(self):
349        """Connect to multiple networks, turn off/on wifi, then reconnect to
350           a previously connected network.
351
352        Steps:
353        1. Connect to a 2GHz network.
354        2. Connect to a 5GHz network.
355        3. Turn WiFi OFF/ON.
356        4. Reconnect to the non-current network.
357
358        """
359        connect_2g_data = self.get_connection_data(self.dut, self.wpapsk_2g)
360        connect_5g_data = self.get_connection_data(self.dut, self.wpapsk_5g)
361        wutils.toggle_wifi_off_and_on(self.dut)
362        reconnect_to = self.get_enabled_network(connect_2g_data,
363                                                connect_5g_data)
364        reconnect = self.connect_to_wifi_network_with_id(
365            reconnect_to[WifiEnums.NETID_KEY],
366            reconnect_to[WifiEnums.SSID_KEY])
367        if not reconnect:
368            raise signals.TestFailure("Device did not connect to the correct"
369                                      " network after toggling WiFi.")
370
371    def helper_reconnect_toggle_airplane(self):
372        """Connect to multiple networks, turn on/off Airplane moce, then
373           reconnect a previously connected network.
374
375        Steps:
376        1. Connect to a 2GHz network.
377        2. Connect to a 5GHz network.
378        3. Turn ON/OFF Airplane mode.
379        4. Reconnect to the non-current network.
380
381        """
382        connect_2g_data = self.get_connection_data(self.dut, self.wpapsk_2g)
383        connect_5g_data = self.get_connection_data(self.dut, self.wpapsk_5g)
384        wutils.toggle_airplane_mode_on_and_off(self.dut)
385        reconnect_to = self.get_enabled_network(connect_2g_data,
386                                                connect_5g_data)
387        reconnect = self.connect_to_wifi_network_with_id(
388            reconnect_to[WifiEnums.NETID_KEY],
389            reconnect_to[WifiEnums.SSID_KEY])
390        if not reconnect:
391            raise signals.TestFailure("Device did not connect to the correct"
392                                      " network after toggling Airplane mode.")
393
394    def helper_reboot_configstore_reconnect(self):
395        """Connect to multiple networks, reboot then reconnect to previously
396           connected network.
397
398        Steps:
399        1. Connect to a 2GHz network.
400        2. Connect to a 5GHz network.
401        3. Reboot device.
402        4. Verify all networks are persistent after reboot.
403        5. Reconnect to the non-current network.
404
405        """
406        network_list = self.connect_multiple_networks(self.dut)
407        self.dut.reboot()
408        time.sleep(DEFAULT_TIMEOUT)
409        self.check_configstore_networks(network_list)
410
411        reconnect_to = self.get_enabled_network(network_list[BAND_2GHZ],
412                                                network_list[BAND_5GHZ])
413
414        reconnect = self.connect_to_wifi_network_with_id(
415            reconnect_to[WifiEnums.NETID_KEY],
416            reconnect_to[WifiEnums.SSID_KEY])
417        if not reconnect:
418            raise signals.TestFailure(
419                "Device failed to reconnect to the correct"
420                " network after reboot.")
421
422    def helper_toggle_wifi_reboot_configstore_reconnect(self):
423        """Connect to multiple networks, disable WiFi, reboot, then
424           reconnect to previously connected network.
425
426        Steps:
427        1. Connect to a 2GHz network.
428        2. Connect to a 5GHz network.
429        3. Turn WiFi OFF.
430        4. Reboot device.
431        5. Turn WiFi ON.
432        4. Verify all networks are persistent after reboot.
433        5. Reconnect to the non-current network.
434
435        """
436        network_list = self.connect_multiple_networks(self.dut)
437        self.log.debug("Toggling wifi OFF")
438        wutils.wifi_toggle_state(self.dut, False)
439        time.sleep(DEFAULT_TIMEOUT)
440        self.dut.reboot()
441        time.sleep(DEFAULT_TIMEOUT)
442        self.log.debug("Toggling wifi ON")
443        wutils.wifi_toggle_state(self.dut, True)
444        time.sleep(DEFAULT_TIMEOUT)
445        self.check_configstore_networks(network_list)
446        reconnect_to = self.get_enabled_network(network_list[BAND_2GHZ],
447                                                network_list[BAND_5GHZ])
448        reconnect = self.connect_to_wifi_network_with_id(
449            reconnect_to[WifiEnums.NETID_KEY],
450            reconnect_to[WifiEnums.SSID_KEY])
451        if not reconnect:
452            msg = ("Device failed to reconnect to the correct network after"
453                   " toggling WiFi and rebooting.")
454            raise signals.TestFailure(msg)
455
456    def helper_toggle_airplane_reboot_configstore_reconnect(self):
457        """Connect to multiple networks, enable Airplane mode, reboot, then
458           reconnect to previously connected network.
459
460        Steps:
461        1. Connect to a 2GHz network.
462        2. Connect to a 5GHz network.
463        3. Toggle Airplane mode ON.
464        4. Reboot device.
465        5. Toggle Airplane mode OFF.
466        4. Verify all networks are persistent after reboot.
467        5. Reconnect to the non-current network.
468
469        """
470        network_list = self.connect_multiple_networks(self.dut)
471        self.log.debug("Toggling Airplane mode ON")
472        asserts.assert_true(
473            acts.utils.force_airplane_mode(self.dut, True),
474            "Can not turn on airplane mode on: %s" % self.dut.serial)
475        time.sleep(DEFAULT_TIMEOUT)
476        self.dut.reboot()
477        time.sleep(DEFAULT_TIMEOUT)
478        self.log.debug("Toggling Airplane mode OFF")
479        asserts.assert_true(
480            acts.utils.force_airplane_mode(self.dut, False),
481            "Can not turn on airplane mode on: %s" % self.dut.serial)
482        time.sleep(DEFAULT_TIMEOUT)
483        self.check_configstore_networks(network_list)
484        reconnect_to = self.get_enabled_network(network_list[BAND_2GHZ],
485                                                network_list[BAND_5GHZ])
486        reconnect = self.connect_to_wifi_network_with_id(
487            reconnect_to[WifiEnums.NETID_KEY],
488            reconnect_to[WifiEnums.SSID_KEY])
489        if not reconnect:
490            msg = ("Device failed to reconnect to the correct network after"
491                   " toggling Airplane mode and rebooting.")
492            raise signals.TestFailure(msg)
493
494    """Tests"""
495
496    @test_tracker_info(uuid="525fc5e3-afba-4bfd-9a02-5834119e3c66")
497    def test_toggle_wifi_state_and_get_startupTime(self):
498        """Test toggling wifi"""
499        self.log.debug("Going from on to off.")
500        wutils.wifi_toggle_state(self.dut, False)
501        self.log.debug("Going from off to on.")
502        startTime = time.time()
503        wutils.wifi_toggle_state(self.dut, True)
504        startup_time = time.time() - startTime
505        self.log.debug("WiFi was enabled on the device in %s s." % startup_time)
506
507    @test_tracker_info(uuid="e9d11563-2bbe-4c96-87eb-ec919b51435b")
508    def test_toggle_with_screen(self):
509        """Test toggling wifi with screen on/off"""
510        wait_time = 5
511        self.log.debug("Screen from off to on.")
512        self.dut.droid.wakeLockAcquireBright()
513        self.dut.droid.wakeUpNow()
514        time.sleep(wait_time)
515        self.log.debug("Going from on to off.")
516        try:
517            wutils.wifi_toggle_state(self.dut, False)
518            time.sleep(wait_time)
519            self.log.debug("Going from off to on.")
520            wutils.wifi_toggle_state(self.dut, True)
521        finally:
522            self.dut.droid.wakeLockRelease()
523            time.sleep(wait_time)
524            self.dut.droid.goToSleepNow()
525
526    @test_tracker_info(uuid="71556e06-7fb1-4e2b-9338-b01f1f8e286e")
527    def test_scan(self):
528        """Test wifi connection scan can start and find expected networks."""
529        ssid = self.open_network[WifiEnums.SSID_KEY]
530        wutils.start_wifi_connection_scan_and_ensure_network_found(
531            self.dut, ssid);
532
533    @test_tracker_info(uuid="3ea09efb-6921-429e-afb1-705ef5a09afa")
534    def test_scan_with_wifi_off_and_location_scan_on(self):
535        """Put wifi in scan only mode"""
536        self.turn_location_on_and_scan_toggle_on()
537        wutils.wifi_toggle_state(self.dut, False)
538
539        """Test wifi connection scan can start and find expected networks."""
540        ssid = self.open_network[WifiEnums.SSID_KEY]
541        wutils.start_wifi_connection_scan_and_ensure_network_found(
542            self.dut, ssid);
543
544    @test_tracker_info(uuid="770caebe-bcb1-43ac-95b6-5dd52dd90e80")
545    def test_scan_with_wifi_off_and_location_scan_off(self):
546        """Turn off wifi and location scan"""
547        self.turn_location_on_and_scan_toggle_off()
548        wutils.wifi_toggle_state(self.dut, False)
549
550        """Test wifi connection scan should fail."""
551        self.dut.droid.wifiStartScan()
552        try:
553            self.dut.ed.pop_event("WifiManagerScanResultsAvailable", 60)
554        except queue.Empty:
555            self.log.debug("Wifi scan results not received.")
556        else:
557            asserts.fail("Wi-Fi scan results received")
558
559    @test_tracker_info(uuid="a4ad9930-a8fa-4868-81ed-a79c7483e502")
560    def test_add_network(self):
561        """Test wifi connection scan."""
562        ssid = self.open_network[WifiEnums.SSID_KEY]
563        nId = self.dut.droid.wifiAddNetwork(self.open_network)
564        asserts.assert_true(nId > -1, "Failed to add network.")
565        configured_networks = self.dut.droid.wifiGetConfiguredNetworks()
566        self.log.debug(
567            ("Configured networks after adding: %s" % configured_networks))
568        wutils.assert_network_in_list({
569            WifiEnums.SSID_KEY: ssid
570        }, configured_networks)
571
572    @test_tracker_info(uuid="aca85551-10ba-4007-90d9-08bcdeb16a60")
573    def test_forget_network(self):
574        ssid = self.open_network[WifiEnums.SSID_KEY]
575        nId = self.dut.droid.wifiAddNetwork(self.open_network)
576        asserts.assert_true(nId > -1, "Failed to add network.")
577        configured_networks = self.dut.droid.wifiGetConfiguredNetworks()
578        self.log.debug(
579            ("Configured networks after adding: %s" % configured_networks))
580        wutils.assert_network_in_list({
581            WifiEnums.SSID_KEY: ssid
582        }, configured_networks)
583        wutils.wifi_forget_network(self.dut, ssid)
584        configured_networks = self.dut.droid.wifiGetConfiguredNetworks()
585        for nw in configured_networks:
586            asserts.assert_true(
587                nw[WifiEnums.BSSID_KEY] != ssid,
588                "Found forgotten network %s in configured networks." % ssid)
589
590    @test_tracker_info(uuid="b306d65c-6df3-4eb5-a178-6278bdc76c3e")
591    def test_reconnect_to_connected_network(self):
592        """Connect to a network and immediately issue reconnect.
593
594        Steps:
595        1. Connect to a 2GHz network.
596        2. Reconnect to the network using its network id.
597        3. Connect to a 5GHz network.
598        4. Reconnect to the network using its network id.
599
600        """
601        connect_2g_data = self.get_connection_data(self.dut, self.wpapsk_2g)
602        reconnect_2g = self.connect_to_wifi_network_with_id(
603            connect_2g_data[WifiEnums.NETID_KEY],
604            connect_2g_data[WifiEnums.SSID_KEY])
605        if not reconnect_2g:
606            raise signals.TestFailure("Device did not connect to the correct"
607                                      " 2GHz network.")
608        connect_5g_data = self.get_connection_data(self.dut, self.wpapsk_5g)
609        reconnect_5g = self.connect_to_wifi_network_with_id(
610            connect_5g_data[WifiEnums.NETID_KEY],
611            connect_5g_data[WifiEnums.SSID_KEY])
612        if not reconnect_5g:
613            raise signals.TestFailure("Device did not connect to the correct"
614                                      " 5GHz network.")
615
616    @test_tracker_info(uuid="3cff17f6-b684-4a95-a438-8272c2ad441d")
617    def test_reconnect_to_previously_connected(self):
618        """Connect to multiple networks and reconnect to the previous network.
619
620        Steps:
621        1. Connect to a 2GHz network.
622        2. Connect to a 5GHz network.
623        3. Reconnect to the 2GHz network using its network id.
624        4. Reconnect to the 5GHz network using its network id.
625
626        """
627        connect_2g_data = self.get_connection_data(self.dut, self.wpapsk_2g)
628        connect_5g_data = self.get_connection_data(self.dut, self.wpapsk_5g)
629        reconnect_2g = self.connect_to_wifi_network_with_id(
630            connect_2g_data[WifiEnums.NETID_KEY],
631            connect_2g_data[WifiEnums.SSID_KEY])
632        if not reconnect_2g:
633            raise signals.TestFailure("Device did not connect to the correct"
634                                      " 2GHz network.")
635        reconnect_5g = self.connect_to_wifi_network_with_id(
636            connect_5g_data[WifiEnums.NETID_KEY],
637            connect_5g_data[WifiEnums.SSID_KEY])
638        if not reconnect_5g:
639            raise signals.TestFailure("Device did not connect to the correct"
640                                      " 5GHz network.")
641
642    @test_tracker_info(uuid="334175c3-d26a-4c87-a8ab-8eb220b2d80f")
643    def test_reconnect_toggle_wifi(self):
644        """Connect to multiple networks, turn off/on wifi, then reconnect to
645           a previously connected network.
646
647        Steps:
648        1. Connect to a 2GHz network.
649        2. Connect to a 5GHz network.
650        3. Turn WiFi OFF/ON.
651        4. Reconnect to the non-current network.
652
653        """
654        self.helper_reconnect_toggle_wifi()
655
656    @test_tracker_info(uuid="bd2cec9e-7f17-44ef-8a0c-4da92a9b55ae")
657    def test_reconnect_toggle_wifi_with_location_scan_on(self):
658        """Connect to multiple networks, turn off/on wifi, then reconnect to
659           a previously connected network.
660
661        Steps:
662        1. Turn on location scans.
663        2. Connect to a 2GHz network.
664        3. Connect to a 5GHz network.
665        4. Turn WiFi OFF/ON.
666        5. Reconnect to the non-current network.
667
668        """
669        self.turn_location_on_and_scan_toggle_on()
670        self.helper_reconnect_toggle_wifi()
671
672    @test_tracker_info(uuid="8e6e6c21-fefb-4fe8-9fb1-f09b1182b76d")
673    def test_reconnect_toggle_airplane(self):
674        """Connect to multiple networks, turn on/off Airplane moce, then
675           reconnect a previously connected network.
676
677        Steps:
678        1. Connect to a 2GHz network.
679        2. Connect to a 5GHz network.
680        3. Turn ON/OFF Airplane mode.
681        4. Reconnect to the non-current network.
682
683        """
684        self.helper_reconnect_toggle_airplane()
685
686    @test_tracker_info(uuid="28562f13-8a0a-492e-932c-e587560db5f2")
687    def test_reconnect_toggle_airplane_with_location_scan_on(self):
688        """Connect to multiple networks, turn on/off Airplane moce, then
689           reconnect a previously connected network.
690
691        Steps:
692        1. Turn on location scans.
693        2. Connect to a 2GHz network.
694        3. Connect to a 5GHz network.
695        4. Turn ON/OFF Airplane mode.
696        5. Reconnect to the non-current network.
697
698        """
699        self.turn_location_on_and_scan_toggle_on()
700        self.helper_reconnect_toggle_airplane()
701
702    @test_tracker_info(uuid="3d041c12-05e2-46a7-ab9b-e3f60cc735db")
703    def test_reboot_configstore_reconnect(self):
704        """Connect to multiple networks, reboot then reconnect to previously
705           connected network.
706
707        Steps:
708        1. Connect to a 2GHz network.
709        2. Connect to a 5GHz network.
710        3. Reboot device.
711        4. Verify all networks are persistent after reboot.
712        5. Reconnect to the non-current network.
713
714        """
715        self.helper_reboot_configstore_reconnect()
716
717    @test_tracker_info(uuid="a70d5853-67b5-4d48-bdf7-08ee51fafd21")
718    def test_reboot_configstore_reconnect_with_location_scan_on(self):
719        """Connect to multiple networks, reboot then reconnect to previously
720           connected network.
721
722        Steps:
723        1. Turn on location scans.
724        2. Connect to a 2GHz network.
725        3. Connect to a 5GHz network.
726        4. Reboot device.
727        5. Verify all networks are persistent after reboot.
728        6. Reconnect to the non-current network.
729
730        """
731        self.turn_location_on_and_scan_toggle_on()
732        self.helper_reboot_configstore_reconnect()
733
734    @test_tracker_info(uuid="26d94dfa-1349-4c8b-aea0-475eb73bb521")
735    def test_toggle_wifi_reboot_configstore_reconnect(self):
736        """Connect to multiple networks, disable WiFi, reboot, then
737           reconnect to previously connected network.
738
739        Steps:
740        1. Connect to a 2GHz network.
741        2. Connect to a 5GHz network.
742        3. Turn WiFi OFF.
743        4. Reboot device.
744        5. Turn WiFi ON.
745        4. Verify all networks are persistent after reboot.
746        5. Reconnect to the non-current network.
747
748        """
749        self.helper_toggle_wifi_reboot_configstore_reconnect()
750
751    @test_tracker_info(uuid="7c004a3b-c1c6-4371-9124-0f34650be915")
752    def test_toggle_wifi_reboot_configstore_reconnect_with_location_scan_on(self):
753        """Connect to multiple networks, disable WiFi, reboot, then
754           reconnect to previously connected network.
755
756        Steps:
757        1. Turn on location scans.
758        2. Connect to a 2GHz network.
759        3. Connect to a 5GHz network.
760        4. Turn WiFi OFF.
761        5. Reboot device.
762        6. Turn WiFi ON.
763        7. Verify all networks are persistent after reboot.
764        8. Reconnect to the non-current network.
765
766        """
767        self.turn_location_on_and_scan_toggle_on()
768        self.helper_toggle_wifi_reboot_configstore_reconnect()
769
770    @test_tracker_info(uuid="4fce017b-b443-40dc-a598-51d59d3bb38f")
771    def test_toggle_airplane_reboot_configstore_reconnect(self):
772        """Connect to multiple networks, enable Airplane mode, reboot, then
773           reconnect to previously connected network.
774
775        Steps:
776        1. Connect to a 2GHz network.
777        2. Connect to a 5GHz network.
778        3. Toggle Airplane mode ON.
779        4. Reboot device.
780        5. Toggle Airplane mode OFF.
781        4. Verify all networks are persistent after reboot.
782        5. Reconnect to the non-current network.
783
784        """
785        self.helper_toggle_airplane_reboot_configstore_reconnect()
786
787    @test_tracker_info(uuid="7f0810f9-2338-4158-95f5-057f5a1905b6")
788    def test_toggle_airplane_reboot_configstore_reconnect_with_location_scan_on(self):
789        """Connect to multiple networks, enable Airplane mode, reboot, then
790           reconnect to previously connected network.
791
792        Steps:
793        1. Turn on location scans.
794        2. Connect to a 2GHz network.
795        3. Connect to a 5GHz network.
796        4. Toggle Airplane mode ON.
797        5. Reboot device.
798        6. Toggle Airplane mode OFF.
799        7. Verify all networks are persistent after reboot.
800        8. Reconnect to the non-current network.
801
802        """
803        self.turn_location_on_and_scan_toggle_on()
804        self.helper_toggle_airplane_reboot_configstore_reconnect()
805
806    @test_tracker_info(uuid="81eb7527-4c92-4422-897a-6b5f6445e84a")
807    def test_config_store_with_wpapsk_2g(self):
808        self.connect_to_wifi_network_toggle_wifi_and_run_iperf(
809            (self.wpapsk_2g, self.dut))
810
811    @test_tracker_info(uuid="8457903d-cb7e-4c89-bcea-7f59585ea6e0")
812    def test_config_store_with_wpapsk_5g(self):
813        self.connect_to_wifi_network_toggle_wifi_and_run_iperf(
814            (self.wpapsk_5g, self.dut))
815
816    @test_tracker_info(uuid="b9fbc13a-47b4-4f64-bd2c-e5a3cb24ab2f")
817    def test_tdls_supported(self):
818        model = self.dut.model
819        self.log.debug("Model is %s" % model)
820        if not model.startswith("volantis"):
821            asserts.assert_true(self.dut.droid.wifiIsTdlsSupported(), (
822                "TDLS should be supported on %s, but device is "
823                "reporting not supported.") % model)
824        else:
825            asserts.assert_false(self.dut.droid.wifiIsTdlsSupported(), (
826                "TDLS should not be supported on %s, but device "
827                "is reporting supported.") % model)
828
829    @test_tracker_info(uuid="50637d40-ea59-4f4b-9fc1-e6641d64074c")
830    def test_energy_info(self):
831        """Verify the WiFi energy info reporting feature """
832        self.get_energy_info()
833
834    @test_tracker_info(uuid="1f1cf549-53eb-4f36-9f33-ce06c9158efc")
835    def test_energy_info_connected(self):
836        """Verify the WiFi energy info reporting feature when connected.
837
838        Connect to a wifi network, then the same as test_energy_info.
839        """
840        wutils.wifi_connect(self.dut, self.open_network)
841        self.get_energy_info()
842