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