1#
2#   Copyright 2017 - The Android Open Source Project
3#
4#   Licensed under the Apache License, Version 2.0 (the "License");
5#   you may not use this file except in compliance with the License.
6#   You may obtain a copy of the License at
7#
8#       http://www.apache.org/licenses/LICENSE-2.0
9#
10#   Unless required by applicable law or agreed to in writing, software
11#   distributed under the License is distributed on an "AS IS" BASIS,
12#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13#   See the License for the specific language governing permissions and
14#   limitations under the License.
15
16import logging
17import random
18import socket
19import time
20
21from acts import asserts
22from acts import base_test
23from acts import test_runner
24from acts import utils
25from acts.controllers import adb
26from acts.test_decorators import test_tracker_info
27from acts.test_utils.tel import tel_defines
28from acts.test_utils.tel.tel_data_utils import wait_for_cell_data_connection
29from acts.test_utils.tel.tel_test_utils import get_operator_name
30from acts.test_utils.tel.tel_test_utils import verify_http_connection
31from acts.test_utils.tel.tel_test_utils import WIFI_CONFIG_APBAND_2G
32from acts.test_utils.tel.tel_test_utils import WIFI_CONFIG_APBAND_5G
33from acts.test_utils.net import socket_test_utils as sutils
34from acts.test_utils.net import arduino_test_utils as dutils
35from acts.test_utils.net import net_test_utils as nutils
36from acts.test_utils.wifi import wifi_test_utils as wutils
37
38WAIT_TIME = 5
39
40class WifiTetheringTest(base_test.BaseTestClass):
41    """ Tests for Wifi Tethering """
42
43    def setup_class(self):
44        """ Setup devices for tethering and unpack params """
45
46        self.hotspot_device = self.android_devices[0]
47        self.tethered_devices = self.android_devices[1:]
48        req_params = ("url", "open_network")
49        self.unpack_userparams(req_params)
50        self.network = {"SSID": "hotspot_%s" % utils.rand_ascii_str(6),
51                        "password": "pass_%s" % utils.rand_ascii_str(6)}
52        self.new_ssid = "hs_%s" % utils.rand_ascii_str(6)
53        self.tcpdump_pid=[]
54
55        nutils.verify_lte_data_and_tethering_supported(self.hotspot_device)
56        for ad in self.tethered_devices:
57            wutils.wifi_test_device_init(ad)
58
59    def setup_test(self):
60        for ad in self.android_devices:
61            self.tcpdump_pid.append(nutils.start_tcpdump(ad, self.test_name))
62        self.tethered_devices[0].droid.telephonyToggleDataConnection(False)
63
64    def teardown_test(self):
65        if self.hotspot_device.droid.wifiIsApEnabled():
66            wutils.stop_wifi_tethering(self.hotspot_device)
67        self.tethered_devices[0].droid.telephonyToggleDataConnection(True)
68        for ad, pid in zip(self.android_devices, self.tcpdump_pid):
69            nutils.stop_tcpdump(ad, pid, self.test_name)
70        self.tcpdump_pid = []
71
72
73    def teardown_class(self):
74        """ Reset devices """
75        for ad in self.tethered_devices:
76            wutils.reset_wifi(ad)
77
78    def on_fail(self, test_name, begin_time):
79        """ Collect bug report on failure """
80        for ad in self.android_devices:
81            ad.take_bug_report(test_name, begin_time)
82
83    """ Helper functions """
84
85    def _is_ipaddress_ipv6(self, ip_address):
86        """ Verify if the given string is a valid IPv6 address
87
88        Args:
89            1. string which contains the IP address
90
91        Returns:
92            True: if valid ipv6 address
93            False: if not
94        """
95        try:
96            socket.inet_pton(socket.AF_INET6, ip_address)
97            return True
98        except socket.error:
99            return False
100
101    def _supports_ipv6_tethering(self, dut):
102        """ Check if provider supports IPv6 tethering.
103            Currently, only Verizon supports IPv6 tethering
104
105        Returns:
106            True: if provider supports IPv6 tethering
107            False: if not
108        """
109        # Currently only Verizon support IPv6 tethering
110        carrier_supports_tethering = ["vzw", "tmo", "Far EasTone", "Chunghwa Telecom"]
111        operator = get_operator_name(self.log, dut)
112        return operator in carrier_supports_tethering
113
114    def _carrier_supports_ipv6(self,dut):
115        """ Verify if carrier supports ipv6
116            Currently, only verizon and t-mobile supports IPv6
117
118        Returns:
119            True: if carrier supports ipv6
120            False: if not
121        """
122        carrier_supports_ipv6 = ["vzw", "tmo", "Far EasTone", "Chunghwa Telecom"]
123        operator = get_operator_name(self.log, dut)
124        self.log.info("Carrier is %s" % operator)
125        return operator in carrier_supports_ipv6
126
127    def _verify_ipv6_tethering(self, dut):
128        """ Verify IPv6 tethering """
129        http_response = dut.droid.httpRequestString(self.url)
130        self.log.info("IP address %s " % http_response)
131        active_link_addrs = dut.droid.connectivityGetAllAddressesOfActiveLink()
132        if dut==self.hotspot_device and self._carrier_supports_ipv6(dut)\
133            or self._supports_ipv6_tethering(self.hotspot_device):
134            asserts.assert_true(self._is_ipaddress_ipv6(http_response),
135                                "The http response did not return IPv6 address")
136            asserts.assert_true(
137                active_link_addrs and http_response in str(active_link_addrs),
138                "Could not find IPv6 address in link properties")
139            asserts.assert_true(
140                dut.droid.connectivityHasIPv6DefaultRoute(),
141                "Could not find IPv6 default route in link properties")
142        else:
143            asserts.assert_true(
144                not dut.droid.connectivityHasIPv6DefaultRoute(),
145                "Found IPv6 default route in link properties")
146
147    def _start_wifi_tethering(self, wifi_band=WIFI_CONFIG_APBAND_2G):
148        """ Start wifi tethering on hotspot device
149
150        Args:
151            1. wifi_band: specifies the wifi band to start the hotspot
152               on. The current options are 2G and 5G
153        """
154        wutils.start_wifi_tethering(self.hotspot_device,
155                                    self.network[wutils.WifiEnums.SSID_KEY],
156                                    self.network[wutils.WifiEnums.PWD_KEY],
157                                    wifi_band)
158
159    def _connect_disconnect_devices(self):
160        """ Randomly connect and disconnect devices from the
161            self.tethered_devices list to hotspot device
162        """
163        device_connected = [ False ] * len(self.tethered_devices)
164        for _ in range(50):
165            dut_id = random.randint(0, len(self.tethered_devices)-1)
166            dut = self.tethered_devices[dut_id]
167            # wait for 1 sec between connect & disconnect stress test
168            time.sleep(1)
169            if device_connected[dut_id]:
170                wutils.wifi_forget_network(dut, self.network["SSID"])
171            else:
172                wutils.wifi_connect(dut, self.network)
173            device_connected[dut_id] = not device_connected[dut_id]
174
175    def _connect_disconnect_android_device(self, dut_id, wifi_state):
176        """ Connect or disconnect wifi on android device depending on the
177            current wifi state
178
179        Args:
180            1. dut_id: tethered device to change the wifi state
181            2. wifi_state: current wifi state
182        """
183        ad = self.tethered_devices[dut_id]
184        if wifi_state:
185            self.log.info("Disconnecting wifi on android device")
186            wutils.wifi_forget_network(ad, self.network["SSID"])
187        else:
188            self.log.info("Connecting to wifi on android device")
189            wutils.wifi_connect(ad, self.network)
190
191    def _connect_disconnect_wifi_dongle(self, dut_id, wifi_state):
192        """ Connect or disconnect wifi on wifi dongle depending on the
193            current wifi state
194
195        Args:
196            1. dut_id: wifi dongle to change the wifi state
197            2. wifi_state: current wifi state
198        """
199        wd = self.arduino_wifi_dongles[dut_id]
200        if wifi_state:
201            self.log.info("Disconnecting wifi on dongle")
202            dutils.disconnect_wifi(wd)
203        else:
204            self.log.info("Connecting to wifi on dongle")
205            dutils.connect_wifi(wd, self.network)
206
207    def _connect_disconnect_tethered_devices(self):
208        """ Connect disconnect tethered devices to wifi hotspot """
209        num_android_devices = len(self.tethered_devices)
210        num_wifi_dongles = 0
211        if hasattr(self, 'arduino_wifi_dongles'):
212            num_wifi_dongles = len(self.arduino_wifi_dongles)
213        total_devices = num_android_devices + num_wifi_dongles
214        device_connected = [False] * total_devices
215        for _ in range(50):
216            dut_id = random.randint(0, total_devices-1)
217            wifi_state = device_connected[dut_id]
218            if dut_id < num_android_devices:
219              self._connect_disconnect_android_device(dut_id, wifi_state)
220            else:
221              self._connect_disconnect_wifi_dongle(dut_id-num_android_devices,
222                                                   wifi_state)
223            device_connected[dut_id] = not device_connected[dut_id]
224
225    def _verify_ping(self, dut, ip, isIPv6=False):
226        """ Verify ping works from the dut to IP/hostname
227
228        Args:
229            1. dut - ad object to check ping from
230            2. ip - ip/hostname to ping (IPv4 and IPv6)
231
232        Returns:
233            True - if ping is successful
234            False - if not
235        """
236        self.log.info("Pinging %s from dut %s" % (ip, dut.serial))
237        if isIPv6 or self._is_ipaddress_ipv6(ip):
238            return dut.droid.pingHost(ip, 5, "ping6")
239        return dut.droid.pingHost(ip)
240
241    def _return_ip_for_interface(self, dut, iface_name):
242        """ Return list of IP addresses for an interface
243
244        Args:
245            1. dut - ad object
246            2. iface_name - interface name
247
248        Returns:
249            List of IPv4 and IPv6 addresses
250        """
251        return dut.droid.connectivityGetIPv4Addresses(iface_name) + \
252            dut.droid.connectivityGetIPv6Addresses(iface_name)
253
254    def _test_traffic_between_two_tethered_devices(self, ad, wd):
255        """ Verify pinging interfaces of one DUT from another
256
257        Args:
258            1. ad - android device
259            2. wd - wifi dongle
260        """
261        wutils.wifi_connect(ad, self.network)
262        dutils.connect_wifi(wd, self.network)
263        local_ip = ad.droid.connectivityGetIPv4Addresses('wlan0')[0]
264        remote_ip = wd.ip_address()
265        port = 8888
266
267        time.sleep(6) # wait until UDP packets method is invoked
268        socket = sutils.open_datagram_socket(ad, local_ip, port)
269        sutils.send_recv_data_datagram_sockets(
270            ad, ad, socket, socket, remote_ip, port)
271        sutils.close_datagram_socket(ad, socket)
272
273    def _ping_hotspot_interfaces_from_tethered_device(self, dut):
274        """ Ping hotspot interfaces from tethered device
275
276        Args:
277            1. dut - tethered device
278
279        Returns:
280            True - if all IP addresses are pingable
281            False - if not
282        """
283        ifaces = self.hotspot_device.droid.connectivityGetNetworkInterfaces()
284        return_result = True
285        for interface in ifaces:
286            iface_name = interface.split()[0].split(':')[1]
287            if iface_name == "lo":
288                continue
289            ip_list = self._return_ip_for_interface(
290                self.hotspot_device, iface_name)
291            for ip in ip_list:
292                ping_result = self._verify_ping(dut, ip)
293                self.log.info("Ping result: %s %s %s" %
294                              (iface_name, ip, ping_result))
295                return_result = return_result and ping_result
296
297        return return_result
298
299    def _save_wifi_softap_configuration(self, ad, config):
300        """ Save soft AP configuration
301
302        Args:
303            1. dut - device to save configuration on
304            2. config - soft ap configuration
305        """
306        asserts.assert_true(ad.droid.wifiSetWifiApConfiguration(config),
307                            "Failed to set WifiAp Configuration")
308        wifi_ap = ad.droid.wifiGetApConfiguration()
309        asserts.assert_true(wifi_ap[wutils.WifiEnums.SSID_KEY] == config[wutils.WifiEnums.SSID_KEY],
310                            "Configured wifi hotspot SSID does not match with the expected SSID")
311
312    def _turn_on_wifi_hotspot(self, ad):
313        """ Turn on wifi hotspot with a config that is already saved
314
315        Args:
316            1. dut - device to turn wifi hotspot on
317        """
318        ad.droid.wifiStartTrackingTetherStateChange()
319        ad.droid.connectivityStartTethering(tel_defines.TETHERING_WIFI, False)
320        try:
321            ad.ed.pop_event("ConnectivityManagerOnTetheringStarted")
322            ad.ed.wait_for_event("TetherStateChanged",
323                                  lambda x: x["data"]["ACTIVE_TETHER"], 30)
324        except:
325            asserts.fail("Didn't receive wifi tethering starting confirmation")
326        ad.droid.wifiStopTrackingTetherStateChange()
327
328    """ Test Cases """
329
330    @test_tracker_info(uuid="36d03295-bea3-446e-8342-b9f8f1962a32")
331    def test_ipv6_tethering(self):
332        """ IPv6 tethering test
333
334        Steps:
335            1. Start wifi tethering on hotspot device
336            2. Verify IPv6 address on hotspot device (VZW & TMO only)
337            3. Connect tethered device to hotspot device
338            4. Verify IPv6 address on the client's link properties (VZW only)
339            5. Verify ping on client using ping6 which should pass (VZW only)
340            6. Disable mobile data on provider and verify that link properties
341               does not have IPv6 address and default route (VZW only)
342        """
343        # Start wifi tethering on the hotspot device
344        wutils.toggle_wifi_off_and_on(self.hotspot_device)
345        self._start_wifi_tethering()
346
347        # Verify link properties on hotspot device
348        self.log.info("Check IPv6 properties on the hotspot device. "
349                      "Verizon & T-mobile should have IPv6 in link properties")
350        self._verify_ipv6_tethering(self.hotspot_device)
351
352        # Connect the client to the SSID
353        wutils.wifi_connect(self.tethered_devices[0], self.network)
354
355        # Need to wait atleast 2 seconds for IPv6 address to
356        # show up in the link properties
357        time.sleep(WAIT_TIME)
358
359        # Verify link properties on tethered device
360        self.log.info("Check IPv6 properties on the tethered device. "
361                      "Device should have IPv6 if carrier is Verizon")
362        self._verify_ipv6_tethering(self.tethered_devices[0])
363
364        # Verify ping6 on tethered device
365        ping_result = self._verify_ping(self.tethered_devices[0],
366                                        wutils.DEFAULT_PING_ADDR, True)
367        if self._supports_ipv6_tethering(self.hotspot_device):
368            asserts.assert_true(ping_result, "Ping6 failed on the client")
369        else:
370            asserts.assert_true(not ping_result, "Ping6 failed as expected")
371
372        # Disable mobile data on hotspot device
373        # and verify the link properties on tethered device
374        self.log.info("Disabling mobile data to verify ipv6 default route")
375        self.hotspot_device.droid.telephonyToggleDataConnection(False)
376        asserts.assert_equal(
377            self.hotspot_device.droid.telephonyGetDataConnectionState(),
378            tel_defines.DATA_STATE_CONNECTED,
379            "Could not disable cell data")
380
381        time.sleep(WAIT_TIME) # wait until the IPv6 is removed from link properties
382
383        result = self.tethered_devices[0].droid.connectivityHasIPv6DefaultRoute()
384        self.hotspot_device.droid.telephonyToggleDataConnection(True)
385        if result:
386            asserts.fail("Found IPv6 default route in link properties:Data off")
387        self.log.info("Did not find IPv6 address in link properties")
388
389        # Disable wifi tethering
390        wutils.stop_wifi_tethering(self.hotspot_device)
391
392    @test_tracker_info(uuid="110b61d1-8af2-4589-8413-11beac7a3025")
393    def test_wifi_tethering_2ghz_traffic_between_2tethered_devices(self):
394        """ Steps:
395
396            1. Start wifi hotspot with 2G band
397            2. Connect 2 tethered devices to the hotspot device
398            3. Ping interfaces between the tethered devices
399        """
400        asserts.skip_if(not hasattr(self, 'arduino_wifi_dongles'),
401                        "No wifi dongles connected. Skipping test")
402        wutils.toggle_wifi_off_and_on(self.hotspot_device)
403        self._start_wifi_tethering(WIFI_CONFIG_APBAND_2G)
404        self._test_traffic_between_two_tethered_devices(self.tethered_devices[0],
405                                                        self.arduino_wifi_dongles[0])
406        wutils.stop_wifi_tethering(self.hotspot_device)
407
408    @test_tracker_info(uuid="953f6e2e-27bd-4b73-85a6-d2eaa4e755d5")
409    def wifi_tethering_5ghz_traffic_between_2tethered_devices(self):
410        """ Steps:
411
412            1. Start wifi hotspot with 5ghz band
413            2. Connect 2 tethered devices to the hotspot device
414            3. Send traffic between the tethered devices
415        """
416        wutils.toggle_wifi_off_and_on(self.hotspot_device)
417        self._start_wifi_tethering(WIFI_CONFIG_APBAND_5G)
418        self._test_traffic_between_two_tethered_devices(self.tethered_devices[0],
419                                                        self.arduino_wifi_dongles[0])
420        wutils.stop_wifi_tethering(self.hotspot_device)
421
422    @test_tracker_info(uuid="d7d5aa51-682d-4882-a334-61966d93b68c")
423    def test_wifi_tethering_2ghz_connect_disconnect_devices(self):
424        """ Steps:
425
426            1. Start wifi hotspot with 2ghz band
427            2. Connect and disconnect multiple devices randomly
428            3. Verify the correct functionality
429        """
430        wutils.toggle_wifi_off_and_on(self.hotspot_device)
431        self._start_wifi_tethering(WIFI_CONFIG_APBAND_2G)
432        self._connect_disconnect_tethered_devices()
433        wutils.stop_wifi_tethering(self.hotspot_device)
434
435    @test_tracker_info(uuid="34abd6c9-c7f1-4d89-aa2b-a66aeabed9aa")
436    def test_wifi_tethering_5ghz_connect_disconnect_devices(self):
437        """ Steps:
438
439            1. Start wifi hotspot with 5ghz band
440            2. Connect and disconnect multiple devices randomly
441            3. Verify the correct functionality
442        """
443        wutils.toggle_wifi_off_and_on(self.hotspot_device)
444        self._start_wifi_tethering(WIFI_CONFIG_APBAND_5G)
445        self._connect_disconnect_devices()
446        wutils.stop_wifi_tethering(self.hotspot_device)
447
448    @test_tracker_info(uuid="7edfb220-37f8-42ea-8d7c-39712fbe9be5")
449    def test_wifi_tethering_wpapsk_network_2g(self):
450        """ Steps:
451
452            1. Start wifi tethering with wpapsk network 2G band
453            2. Connect tethered device to the SSID
454            3. Verify internet connectivity
455        """
456        self._start_wifi_tethering()
457        wutils.connect_to_wifi_network(self.tethered_devices[0],
458                                       self.network,
459                                       check_connectivity=True)
460
461    @test_tracker_info(uuid="17e450f4-795f-4e67-adab-984940dffedc")
462    def test_wifi_tethering_wpapsk_network_5g(self):
463        """ Steps:
464
465            1. Start wifi tethering with wpapsk network 5G band
466            2. Connect tethered device to the SSID
467            3. Verify internet connectivity
468        """
469        self._start_wifi_tethering(WIFI_CONFIG_APBAND_5G)
470        wutils.connect_to_wifi_network(self.tethered_devices[0],
471                                       self.network,
472                                       check_connectivity=True)
473
474    @test_tracker_info(uuid="2bc344cb-0277-4f06-b6cc-65b3972086ed")
475    def test_change_wifi_hotspot_ssid_when_hotspot_enabled(self):
476        """ Steps:
477
478            1. Start wifi tethering
479            2. Verify wifi Ap configuration
480            3. Change the SSID of the wifi hotspot while hotspot is on
481            4. Verify the new SSID in wifi ap configuration
482            5. Restart tethering and verify that the tethered device is able
483               to connect to the new SSID
484        """
485        dut = self.hotspot_device
486
487        # start tethering and verify the wifi ap configuration settings
488        self._start_wifi_tethering()
489        wifi_ap = dut.droid.wifiGetApConfiguration()
490        asserts.assert_true(
491            wifi_ap[wutils.WifiEnums.SSID_KEY] == \
492                self.network[wutils.WifiEnums.SSID_KEY],
493            "Configured wifi hotspot SSID did not match with the expected SSID")
494        wutils.connect_to_wifi_network(self.tethered_devices[0], self.network)
495
496        # update the wifi ap configuration with new ssid
497        config = {wutils.WifiEnums.SSID_KEY: self.new_ssid}
498        config[wutils.WifiEnums.PWD_KEY] = self.network[wutils.WifiEnums.PWD_KEY]
499        config[wutils.WifiEnums.AP_BAND_KEY] = WIFI_CONFIG_APBAND_2G
500        self._save_wifi_softap_configuration(dut, config)
501
502        # start wifi tethering with new wifi ap configuration
503        wutils.stop_wifi_tethering(dut)
504        self._turn_on_wifi_hotspot(dut)
505
506        # verify dut can connect to new wifi ap configuration
507        new_network = {wutils.WifiEnums.SSID_KEY: self.new_ssid,
508                       wutils.WifiEnums.PWD_KEY: \
509                       self.network[wutils.WifiEnums.PWD_KEY]}
510        wutils.connect_to_wifi_network(self.tethered_devices[0], new_network)
511
512    @test_tracker_info(uuid="4cf7ab26-ca2d-46f6-9d3f-a935c7e04c97")
513    def test_wifi_tethering_open_network_2g(self):
514        """ Steps:
515
516            1. Start wifi tethering with open network 2G band
517               (Not allowed manually. b/72412729)
518            2. Connect tethered device to the SSID
519            3. Verify internet connectivity
520        """
521        open_network = {
522            wutils.WifiEnums.SSID_KEY: "hs_2g_%s" % utils.rand_ascii_str(6)
523        }
524        wutils.start_wifi_tethering(
525            self.hotspot_device,
526            open_network[wutils.WifiEnums.SSID_KEY],
527            None,
528            WIFI_CONFIG_APBAND_2G)
529        wutils.connect_to_wifi_network(self.tethered_devices[0],
530                                       open_network,
531                                       check_connectivity=True)
532
533    @test_tracker_info(uuid="f407049b-1324-40ea-a8d1-f90587933310")
534    def test_wifi_tethering_open_network_5g(self):
535        """ Steps:
536
537            1. Start wifi tethering with open network 5G band
538               (Not allowed manually. b/72412729)
539            2. Connect tethered device to the SSID
540            3. Verify internet connectivity
541        """
542        open_network = {
543            wutils.WifiEnums.SSID_KEY: "hs_5g_%s" % utils.rand_ascii_str(6)
544        }
545        wutils.start_wifi_tethering(
546            self.hotspot_device,
547            open_network[wutils.WifiEnums.SSID_KEY],
548            None,
549            WIFI_CONFIG_APBAND_5G)
550        wutils.connect_to_wifi_network(self.tethered_devices[0],
551                                       open_network,
552                                       check_connectivity=True)
553
554    @test_tracker_info(uuid="d964f2e6-0acb-417c-ada9-eb9fc5a470e4")
555    def test_wifi_tethering_open_network_2g_stress(self):
556        """ Steps:
557
558            1. Save wifi hotspot configuration with open network 2G band
559               (Not allowed manually. b/72412729)
560            2. Turn on wifi hotspot
561            3. Connect tethered device and verify internet connectivity
562            4. Turn off wifi hotspot
563            5. Repeat steps 2 to 4
564        """
565        # save open network wifi ap configuration with 2G band
566        config = {wutils.WifiEnums.SSID_KEY:
567                  self.open_network[wutils.WifiEnums.SSID_KEY]}
568        config[wutils.WifiEnums.AP_BAND_KEY] = WIFI_CONFIG_APBAND_2G
569        self._save_wifi_softap_configuration(self.hotspot_device, config)
570
571        # turn on/off wifi hotspot, connect device
572        for _ in range(9):
573            self._turn_on_wifi_hotspot(self.hotspot_device)
574            wutils.connect_to_wifi_network(self.tethered_devices[0], self.open_network)
575            wutils.stop_wifi_tethering(self.hotspot_device)
576            time.sleep(1) # wait for some time before turning on hotspot
577
578    @test_tracker_info(uuid="c7ef840c-4003-41fc-80e3-755f9057b542")
579    def test_wifi_tethering_open_network_5g_stress(self):
580        """ Steps:
581
582            1. Save wifi hotspot configuration with open network 5G band
583               (Not allowed manually. b/72412729)
584            2. Turn on wifi hotspot
585            3. Connect tethered device and verify internet connectivity
586            4. Turn off wifi hotspot
587            5. Repeat steps 2 to 4
588        """
589        # save open network wifi ap configuration with 5G band
590        config = {wutils.WifiEnums.SSID_KEY:
591                  self.open_network[wutils.WifiEnums.SSID_KEY]}
592        config[wutils.WifiEnums.AP_BAND_KEY] = WIFI_CONFIG_APBAND_5G
593        self._save_wifi_softap_configuration(self.hotspot_device, config)
594
595        # turn on/off wifi hotspot, connect device
596        for _ in range(9):
597            self._turn_on_wifi_hotspot(self.hotspot_device)
598            wutils.connect_to_wifi_network(self.tethered_devices[0], self.open_network)
599            wutils.stop_wifi_tethering(self.hotspot_device)
600            time.sleep(1) # wait for some time before turning on hotspot
601