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 logging
18import queue
19import random
20import time
21
22from acts import asserts
23from acts import utils
24from acts.test_decorators import test_tracker_info
25from acts.test_utils.net import arduino_test_utils as dutils
26from acts.test_utils.net import socket_test_utils as sutils
27from acts.test_utils.tel import tel_defines
28from acts.test_utils.tel import tel_test_utils as tel_utils
29from acts.test_utils.tel.tel_test_utils import WIFI_CONFIG_APBAND_2G
30from acts.test_utils.tel.tel_test_utils import WIFI_CONFIG_APBAND_5G
31from acts.test_utils.tel.tel_test_utils import WIFI_CONFIG_APBAND_AUTO
32from acts.test_utils.wifi import wifi_constants
33from acts.test_utils.wifi import wifi_test_utils as wutils
34from acts.test_utils.wifi.WifiBaseTest import WifiBaseTest
35
36class WifiSoftApTest(WifiBaseTest):
37
38    def setup_class(self):
39        """It will setup the required dependencies from config file and configure
40           the devices for softap mode testing.
41
42        Returns:
43            True if successfully configured the requirements for testing.
44        """
45        self.dut = self.android_devices[0]
46        self.dut_client = self.android_devices[1]
47        req_params = ["dbs_supported_models"]
48        opt_param = ["open_network"]
49        self.unpack_userparams(
50            req_param_names=req_params, opt_param_names=opt_param)
51        if "AccessPoint" in self.user_params:
52            self.legacy_configure_ap_and_start()
53        self.open_network = self.open_network[0]["2g"]
54        # Do a simple version of init - mainly just sync the time and enable
55        # verbose logging.  This test will fail if the DUT has a sim and cell
56        # data is disabled.  We would also like to test with phones in less
57        # constrained states (or add variations where we specifically
58        # constrain).
59        utils.require_sl4a((self.dut, self.dut_client))
60        utils.sync_device_time(self.dut)
61        utils.sync_device_time(self.dut_client)
62        # Set country code explicitly to "US".
63        wutils.set_wifi_country_code(self.dut, wutils.WifiEnums.CountryCode.US)
64        wutils.set_wifi_country_code(self.dut_client, wutils.WifiEnums.CountryCode.US)
65        # Enable verbose logging on the duts
66        self.dut.droid.wifiEnableVerboseLogging(1)
67        asserts.assert_equal(self.dut.droid.wifiGetVerboseLoggingLevel(), 1,
68            "Failed to enable WiFi verbose logging on the softap dut.")
69        self.dut_client.droid.wifiEnableVerboseLogging(1)
70        asserts.assert_equal(self.dut_client.droid.wifiGetVerboseLoggingLevel(), 1,
71            "Failed to enable WiFi verbose logging on the client dut.")
72        wutils.wifi_toggle_state(self.dut, True)
73        wutils.wifi_toggle_state(self.dut_client, True)
74        self.AP_IFACE = 'wlan0'
75        if self.dut.model in self.dbs_supported_models:
76            self.AP_IFACE = 'wlan1'
77        if len(self.android_devices) > 2:
78            utils.sync_device_time(self.android_devices[2])
79            wutils.set_wifi_country_code(self.android_devices[2], wutils.WifiEnums.CountryCode.US)
80            self.android_devices[2].droid.wifiEnableVerboseLogging(1)
81            asserts.assert_equal(self.android_devices[2].droid.wifiGetVerboseLoggingLevel(), 1,
82                "Failed to enable WiFi verbose logging on the client dut.")
83
84    def teardown_class(self):
85        wutils.stop_wifi_tethering(self.dut)
86        wutils.reset_wifi(self.dut)
87        wutils.reset_wifi(self.dut_client)
88        if "AccessPoint" in self.user_params:
89            del self.user_params["reference_networks"]
90            del self.user_params["open_network"]
91
92    def setup_test(self):
93        for ad in self.android_devices:
94            wutils.wifi_toggle_state(ad, True)
95
96    def teardown_test(self):
97        self.dut.log.debug("Toggling Airplane mode OFF.")
98        asserts.assert_true(utils.force_airplane_mode(self.dut, False),
99                            "Can not turn off airplane mode: %s" % self.dut.serial)
100        if self.dut.droid.wifiIsApEnabled():
101            wutils.stop_wifi_tethering(self.dut)
102
103    def on_fail(self, test_name, begin_time):
104        self.dut.take_bug_report(test_name, begin_time)
105        self.dut_client.take_bug_report(test_name, begin_time)
106
107    """ Helper Functions """
108    def create_softap_config(self):
109        """Create a softap config with ssid and password."""
110        ap_ssid = "softap_" + utils.rand_ascii_str(8)
111        ap_password = utils.rand_ascii_str(8)
112        self.dut.log.info("softap setup: %s %s", ap_ssid, ap_password)
113        config = {wutils.WifiEnums.SSID_KEY: ap_ssid}
114        config[wutils.WifiEnums.PWD_KEY] = ap_password
115        return config
116
117    def confirm_softap_in_scan_results(self, ap_ssid):
118        """Confirm the ap started by wifi tethering is seen in scan results.
119
120        Args:
121            ap_ssid: SSID of the ap we are looking for.
122        """
123        wutils.start_wifi_connection_scan_and_ensure_network_found(
124            self.dut_client, ap_ssid);
125
126    def confirm_softap_not_in_scan_results(self, ap_ssid):
127        """Confirm the ap started by wifi tethering is not seen in scan results.
128
129        Args:
130            ap_ssid: SSID of the ap we are looking for.
131        """
132        wutils.start_wifi_connection_scan_and_ensure_network_not_found(
133            self.dut_client, ap_ssid);
134
135    def validate_traffic_between_softap_clients(self, config):
136        """Send traffic between softAp clients.
137
138        Connect SoftAp clients to the wifi hotspot; one android
139        device and the other arduino wifi controller. Send UDP traffic
140        between the clients and verify that expected messages are received.
141
142        Args:
143            config: wifi network config with SSID, password
144        """
145        ad = self.dut_client
146        wd = self.arduino_wifi_dongles[0]
147        wutils.wifi_connect(ad, config, check_connectivity=False)
148        dutils.connect_wifi(wd, config)
149        local_ip = ad.droid.connectivityGetIPv4Addresses('wlan0')[0]
150        remote_ip = wd.ip_address()
151        port = random.randint(8000, 9000)
152        self.log.info("IP addr on android device: %s" % local_ip)
153        self.log.info("IP addr on arduino device: %s" % remote_ip)
154
155        socket = sutils.open_datagram_socket(ad, local_ip, port)
156        sutils.send_recv_data_datagram_sockets(
157            ad, ad, socket, socket, remote_ip, port)
158        sutils.close_datagram_socket(ad, socket)
159
160    def check_cell_data_and_enable(self):
161        """Make sure that cell data is enabled if there is a sim present.
162
163        If a sim is active, cell data needs to be enabled to allow provisioning
164        checks through (when applicable).  This is done to relax hardware
165        requirements on DUTs - without this check, running this set of tests
166        after other wifi tests may cause failures.
167        """
168        # We do have a sim.  Make sure data is enabled so we can tether.
169        if not self.dut.droid.telephonyIsDataEnabled():
170            self.dut.log.info("need to enable data")
171            self.dut.droid.telephonyToggleDataConnection(True)
172            asserts.assert_true(self.dut.droid.telephonyIsDataEnabled(),
173                                "Failed to enable cell data for softap dut.")
174
175    def validate_full_tether_startup(self, band=None, hidden=None,
176                                     test_ping=False, test_clients=None):
177        """Test full startup of wifi tethering
178
179        1. Report current state.
180        2. Switch to AP mode.
181        3. verify SoftAP active.
182        4. Shutdown wifi tethering.
183        5. verify back to previous mode.
184        """
185        initial_wifi_state = self.dut.droid.wifiCheckState()
186        initial_cell_state = tel_utils.is_sim_ready(self.log, self.dut)
187        self.dut.log.info("current state: %s", initial_wifi_state)
188        self.dut.log.info("is sim ready? %s", initial_cell_state)
189        if initial_cell_state:
190            self.check_cell_data_and_enable()
191        config = self.create_softap_config()
192        wutils.start_wifi_tethering(self.dut,
193                                    config[wutils.WifiEnums.SSID_KEY],
194                                    config[wutils.WifiEnums.PWD_KEY], band, hidden)
195        if hidden:
196            # First ensure it's not seen in scan results.
197            self.confirm_softap_not_in_scan_results(
198                config[wutils.WifiEnums.SSID_KEY])
199            # If the network is hidden, it should be saved on the client to be
200            # seen in scan results.
201            config[wutils.WifiEnums.HIDDEN_KEY] = True
202            ret = self.dut_client.droid.wifiAddNetwork(config)
203            asserts.assert_true(ret != -1, "Add network %r failed" % config)
204            self.dut_client.droid.wifiEnableNetwork(ret, 0)
205        self.confirm_softap_in_scan_results(config[wutils.WifiEnums.SSID_KEY])
206        if test_ping:
207            self.validate_ping_between_softap_and_client(config)
208        if test_clients:
209            if hasattr(self, 'arduino_wifi_dongles'):
210                self.validate_traffic_between_softap_clients(config)
211            if len(self.android_devices) > 2:
212                self.validate_ping_between_two_clients(config)
213        wutils.stop_wifi_tethering(self.dut)
214        asserts.assert_false(self.dut.droid.wifiIsApEnabled(),
215                             "SoftAp is still reported as running")
216        if initial_wifi_state:
217            wutils.wait_for_wifi_state(self.dut, True)
218        elif self.dut.droid.wifiCheckState():
219            asserts.fail("Wifi was disabled before softap and now it is enabled")
220
221    def validate_ping_between_softap_and_client(self, config):
222        """Test ping between softap and its client.
223
224        Connect one android device to the wifi hotspot.
225        Verify they can ping each other.
226
227        Args:
228            config: wifi network config with SSID, password
229        """
230        wutils.wifi_connect(self.dut_client, config, check_connectivity=False)
231
232        dut_ip = self.dut.droid.connectivityGetIPv4Addresses(self.AP_IFACE)[0]
233        dut_client_ip = self.dut_client.droid.connectivityGetIPv4Addresses('wlan0')[0]
234
235        self.dut.log.info("Try to ping %s" % dut_client_ip)
236        asserts.assert_true(
237            utils.adb_shell_ping(self.dut, count=10, dest_ip=dut_client_ip, timeout=20),
238            "%s ping %s failed" % (self.dut.serial, dut_client_ip))
239
240        self.dut_client.log.info("Try to ping %s" % dut_ip)
241        asserts.assert_true(
242            utils.adb_shell_ping(self.dut_client, count=10, dest_ip=dut_ip, timeout=20),
243            "%s ping %s failed" % (self.dut_client.serial, dut_ip))
244
245        wutils.stop_wifi_tethering(self.dut)
246
247    def validate_ping_between_two_clients(self, config):
248        """Test ping between softap's clients.
249
250        Connect two android device to the wifi hotspot.
251        Verify the clients can ping each other.
252
253        Args:
254            config: wifi network config with SSID, password
255        """
256        # Connect DUT to Network
257        ad1 = self.dut_client
258        ad2 = self.android_devices[2]
259
260        wutils.wifi_connect(ad1, config, check_connectivity=False)
261        wutils.wifi_connect(ad2, config, check_connectivity=False)
262        ad1_ip = ad1.droid.connectivityGetIPv4Addresses('wlan0')[0]
263        ad2_ip = ad2.droid.connectivityGetIPv4Addresses('wlan0')[0]
264
265        # Ping each other
266        ad1.log.info("Try to ping %s" % ad2_ip)
267        asserts.assert_true(
268            utils.adb_shell_ping(ad1, count=10, dest_ip=ad2_ip, timeout=20),
269            "%s ping %s failed" % (ad1.serial, ad2_ip))
270
271        ad2.log.info("Try to ping %s" % ad1_ip)
272        asserts.assert_true(
273            utils.adb_shell_ping(ad2, count=10, dest_ip=ad1_ip, timeout=20),
274            "%s ping %s failed" % (ad2.serial, ad1_ip))
275
276    """ Tests Begin """
277
278    @test_tracker_info(uuid="495f1252-e440-461c-87a7-2c45f369e129")
279    def test_check_wifi_tethering_supported(self):
280        """Test check for wifi tethering support.
281
282         1. Call method to check if wifi hotspot is supported
283        """
284        # TODO(silberst): wifiIsPortableHotspotSupported() is currently failing.
285        # Remove the extra check and logging when b/30800811 is resolved
286        hotspot_supported = self.dut.droid.wifiIsPortableHotspotSupported()
287        tethering_supported = self.dut.droid.connectivityIsTetheringSupported()
288        self.log.info(
289            "IsPortableHotspotSupported: %s, IsTetheringSupported %s." % (
290            hotspot_supported, tethering_supported))
291        asserts.assert_true(hotspot_supported,
292                            "DUT should support wifi tethering but is reporting false.")
293        asserts.assert_true(tethering_supported,
294                            "DUT should also support wifi tethering when called from ConnectivityManager")
295
296    @test_tracker_info(uuid="09c19c35-c708-48a5-939b-ac2bbb403d54")
297    def test_full_tether_startup(self):
298        """Test full startup of wifi tethering in default band.
299
300        1. Report current state.
301        2. Switch to AP mode.
302        3. verify SoftAP active.
303        4. Shutdown wifi tethering.
304        5. verify back to previous mode.
305        """
306        self.validate_full_tether_startup()
307
308    @test_tracker_info(uuid="6437727d-7db1-4f69-963e-f26a7797e47f")
309    def test_full_tether_startup_2G(self):
310        """Test full startup of wifi tethering in 2G band.
311
312        1. Report current state.
313        2. Switch to AP mode.
314        3. verify SoftAP active.
315        4. Shutdown wifi tethering.
316        5. verify back to previous mode.
317        """
318        self.validate_full_tether_startup(WIFI_CONFIG_APBAND_2G)
319
320    @test_tracker_info(uuid="970272fa-1302-429b-b261-51efb4dad779")
321    def test_full_tether_startup_5G(self):
322        """Test full startup of wifi tethering in 5G band.
323
324        1. Report current state.
325        2. Switch to AP mode.
326        3. verify SoftAP active.
327        4. Shutdown wifi tethering.
328        5. verify back to previous mode.
329        """
330        self.validate_full_tether_startup(WIFI_CONFIG_APBAND_5G)
331
332    @test_tracker_info(uuid="f76ed37a-519a-48b4-b260-ee3fc5a9cae0")
333    def test_full_tether_startup_auto(self):
334        """Test full startup of wifi tethering in auto-band.
335
336        1. Report current state.
337        2. Switch to AP mode.
338        3. verify SoftAP active.
339        4. Shutdown wifi tethering.
340        5. verify back to previous mode.
341        """
342        self.validate_full_tether_startup(WIFI_CONFIG_APBAND_AUTO)
343
344    @test_tracker_info(uuid="d26ee4df-5dcb-4191-829f-05a10b1218a7")
345    def test_full_tether_startup_2G_hidden(self):
346        """Test full startup of wifi tethering in 2G band using hidden AP.
347
348        1. Report current state.
349        2. Switch to AP mode.
350        3. verify SoftAP active.
351        4. Shutdown wifi tethering.
352        5. verify back to previous mode.
353        """
354        self.validate_full_tether_startup(WIFI_CONFIG_APBAND_2G, True)
355
356    @test_tracker_info(uuid="229cd585-a789-4c9a-8948-89fa72de9dd5")
357    def test_full_tether_startup_5G_hidden(self):
358        """Test full startup of wifi tethering in 5G band using hidden AP.
359
360        1. Report current state.
361        2. Switch to AP mode.
362        3. verify SoftAP active.
363        4. Shutdown wifi tethering.
364        5. verify back to previous mode.
365        """
366        self.validate_full_tether_startup(WIFI_CONFIG_APBAND_5G, True)
367
368    @test_tracker_info(uuid="d546a143-6047-4ffd-b3c6-5ec81a38001f")
369    def test_full_tether_startup_auto_hidden(self):
370        """Test full startup of wifi tethering in auto-band using hidden AP.
371
372        1. Report current state.
373        2. Switch to AP mode.
374        3. verify SoftAP active.
375        4. Shutdown wifi tethering.
376        5. verify back to previous mode.
377        """
378        self.validate_full_tether_startup(WIFI_CONFIG_APBAND_AUTO, True)
379
380    @test_tracker_info(uuid="b2f75330-bf33-4cdd-851a-de390f891ef7")
381    def test_tether_startup_while_connected_to_a_network(self):
382        """Test full startup of wifi tethering in auto-band while the device
383        is connected to a network.
384
385        1. Connect to an open network.
386        2. Turn on AP mode (in auto band).
387        3. Verify SoftAP active.
388        4. Make a client connect to the AP.
389        5. Shutdown wifi tethering.
390        6. Ensure that the client disconnected.
391        """
392        wutils.wifi_toggle_state(self.dut, True)
393        wutils.wifi_connect(self.dut, self.open_network)
394        config = self.create_softap_config()
395        wutils.start_wifi_tethering(self.dut,
396                                    config[wutils.WifiEnums.SSID_KEY],
397                                    config[wutils.WifiEnums.PWD_KEY],
398                                    WIFI_CONFIG_APBAND_AUTO)
399        asserts.assert_true(self.dut.droid.wifiIsApEnabled(),
400                             "SoftAp is not reported as running")
401        # local hotspot may not have internet connectivity
402        self.confirm_softap_in_scan_results(config[wutils.WifiEnums.SSID_KEY])
403        wutils.wifi_connect(self.dut_client, config, check_connectivity=False)
404        wutils.stop_wifi_tethering(self.dut)
405        wutils.wait_for_disconnect(self.dut_client)
406
407    @test_tracker_info(uuid="f2cf56ad-b8b9-43b6-ab15-a47b1d96b92e")
408    def test_full_tether_startup_2G_with_airplane_mode_on(self):
409        """Test full startup of wifi tethering in 2G band with
410        airplane mode on.
411
412        1. Turn on airplane mode.
413        2. Report current state.
414        3. Switch to AP mode.
415        4. verify SoftAP active.
416        5. Shutdown wifi tethering.
417        6. verify back to previous mode.
418        7. Turn off airplane mode.
419        """
420        self.dut.log.debug("Toggling Airplane mode ON.")
421        asserts.assert_true(utils.force_airplane_mode(self.dut, True),
422                            "Can not turn on airplane mode: %s" % self.dut.serial)
423        wutils.wifi_toggle_state(self.dut, True)
424        self.validate_full_tether_startup(WIFI_CONFIG_APBAND_2G)
425
426    @test_tracker_info(uuid="05c6f929-7754-477f-a9cd-f77e850b818b")
427    def test_full_tether_startup_2G_multiple_clients(self):
428        """Test full startup of wifi tethering in 2G band, connect clients
429        to softAp and send traffic between them.
430
431        1. Report current state.
432        2. Switch to AP mode.
433        3. verify SoftAP active.
434        4. Connect clients to softAp.
435        5. Send and recv UDP traffic between them.
436        6. Shutdown wifi tethering.
437        7. verify back to previous mode.
438        """
439        asserts.skip_if(not hasattr(self, 'arduino_wifi_dongles'),
440                        "No wifi dongles connected. Skipping test")
441        self.validate_full_tether_startup(WIFI_CONFIG_APBAND_2G,
442                                          test_clients=True)
443
444    @test_tracker_info(uuid="883dd5b1-50c6-4958-a50f-bb4bea77ccaf")
445    def test_full_tether_startup_2G_one_client_ping_softap(self):
446        """(AP) 1 Device can connect to 2G hotspot
447
448        Steps:
449        1. Turn on DUT's 2G softap
450        2. Client connects to the softap
451        3. Client and DUT ping each other
452        """
453        self.validate_full_tether_startup(WIFI_CONFIG_APBAND_2G, test_ping=True)
454
455    @test_tracker_info(uuid="6604e848-99d6-422c-9fdc-2882642438b6")
456    def test_full_tether_startup_5G_one_client_ping_softap(self):
457        """(AP) 1 Device can connect to 5G hotspot
458
459        Steps:
460        1. Turn on DUT's 5G softap
461        2. Client connects to the softap
462        3. Client and DUT ping each other
463        """
464        self.validate_full_tether_startup(WIFI_CONFIG_APBAND_5G, test_ping=True)
465
466    @test_tracker_info(uuid="17725ecd-f900-4cf7-8b2d-d7515b0a595c")
467    def test_softap_2G_two_clients_ping_each_other(self):
468        """Test for 2G hotspot with 2 clients
469
470        1. Turn on 2G hotspot
471        2. Two clients connect to the hotspot
472        3. Two clients ping each other
473        """
474        asserts.skip_if(len(self.android_devices) < 3,
475                        "No extra android devices. Skip test")
476        self.validate_full_tether_startup(WIFI_CONFIG_APBAND_2G, test_clients=True)
477
478    @test_tracker_info(uuid="98c09888-1021-4f79-9065-b3cf9b132146")
479    def test_softap_5G_two_clients_ping_each_other(self):
480        """Test for 5G hotspot with 2 clients
481
482        1. Turn on 5G hotspot
483        2. Two clients connect to the hotspot
484        3. Two clients ping each other
485        """
486        asserts.skip_if(len(self.android_devices) < 3,
487                        "No extra android devices. Skip test")
488        self.validate_full_tether_startup(WIFI_CONFIG_APBAND_5G, test_clients=True)
489
490    @test_tracker_info(uuid="b991129e-030a-4998-9b08-0687270bec24")
491    def test_number_of_softap_clients(self):
492        """Test for number of softap clients to be updated correctly
493
494        1. Turn of hotspot
495        2. Register softap callback
496        3. Let client connect to the hotspot
497        4. Register second softap callback
498        5. Force client connect/disconnect to hotspot
499        6. Unregister second softap callback
500        7. Force second client connect to hotspot (if supported)
501        8. Turn off hotspot
502        9. Verify second softap callback doesn't respond after unresister
503        """
504        config = wutils.start_softap_and_verify(self, WIFI_CONFIG_APBAND_AUTO)
505        # Register callback after softap enabled to avoid unnecessary callback
506        # impact the test
507        callbackId = self.dut.droid.registerSoftApCallback()
508        # Verify clients will update immediately after register callback
509        wutils.wait_for_expected_number_of_softap_clients(
510                self.dut, callbackId, 0)
511        wutils.wait_for_expected_softap_state(self.dut, callbackId,
512                wifi_constants.WIFI_AP_ENABLED_STATE)
513
514        # Force DUTs connect to Network
515        wutils.wifi_connect(self.dut_client, config,
516                check_connectivity=False)
517        wutils.wait_for_expected_number_of_softap_clients(
518                self.dut, callbackId, 1)
519
520        # Register another callback to verify multi callback clients case
521        callbackId_2 = self.dut.droid.registerSoftApCallback()
522        # Verify clients will update immediately after register callback
523        wutils.wait_for_expected_number_of_softap_clients(
524                self.dut, callbackId_2, 1)
525        wutils.wait_for_expected_softap_state(self.dut, callbackId_2,
526                wifi_constants.WIFI_AP_ENABLED_STATE)
527
528        # Client Off/On Wifi to verify number of softap clients will be updated
529        wutils.toggle_wifi_and_wait_for_reconnection(self.dut_client, config)
530
531        wutils.wait_for_expected_number_of_softap_clients(self.dut,
532                callbackId, 0)
533        wutils.wait_for_expected_number_of_softap_clients(self.dut,
534                callbackId_2, 0)
535        wutils.wait_for_expected_number_of_softap_clients(self.dut,
536                callbackId, 1)
537        wutils.wait_for_expected_number_of_softap_clients(self.dut,
538                callbackId_2, 1)
539
540        # Unregister callbackId_2 to verify multi callback clients case
541        self.dut.droid.unregisterSoftApCallback(callbackId_2)
542
543        if len(self.android_devices) > 2:
544            wutils.wifi_connect(self.android_devices[2], config,
545                    check_connectivity=False)
546            wutils.wait_for_expected_number_of_softap_clients(
547                    self.dut, callbackId, 2)
548
549        # Turn off softap when clients connected
550        wutils.stop_wifi_tethering(self.dut)
551        wutils.wait_for_disconnect(self.dut_client)
552        if len(self.android_devices) > 2:
553            wutils.wait_for_disconnect(self.android_devices[2])
554
555        # Verify client number change back to 0 after softap stop if client
556        # doesn't disconnect before softap stop
557        wutils.wait_for_expected_softap_state(self.dut, callbackId,
558                wifi_constants.WIFI_AP_DISABLING_STATE)
559        wutils.wait_for_expected_softap_state(self.dut, callbackId,
560                wifi_constants.WIFI_AP_DISABLED_STATE)
561        wutils.wait_for_expected_number_of_softap_clients(
562                self.dut, callbackId, 0)
563        # Unregister callback
564        self.dut.droid.unregisterSoftApCallback(callbackId)
565
566        # Check no any callbackId_2 event after unregister
567        asserts.assert_equal(
568                wutils.get_current_number_of_softap_clients(
569                self.dut, callbackId_2), None)
570
571    @test_tracker_info(uuid="35bc4ba1-bade-42ee-a563-0c73afb2402a")
572    def test_softap_auto_shut_off(self):
573        """Test for softap auto shut off
574
575        1. Turn off hotspot
576        2. Register softap callback
577        3. Let client connect to the hotspot
578        4. Start wait [wifi_constants.DEFAULT_SOFTAP_TIMEOUT_S] seconds
579        5. Check hotspot doesn't shut off
580        6. Let client disconnect to the hotspot
581        7. Start wait [wifi_constants.DEFAULT_SOFTAP_TIMEOUT_S] seconds
582        8. Check hotspot auto shut off
583        """
584        config = wutils.start_softap_and_verify(self, WIFI_CONFIG_APBAND_AUTO)
585        # Register callback after softap enabled to avoid unnecessary callback
586        # impact the test
587        callbackId = self.dut.droid.registerSoftApCallback()
588        # Verify clients will update immediately after register callback
589        wutils.wait_for_expected_number_of_softap_clients(self.dut,
590                callbackId, 0)
591        wutils.wait_for_expected_softap_state(self.dut, callbackId,
592                wifi_constants.WIFI_AP_ENABLED_STATE)
593
594        # Force DUTs connect to Network
595        wutils.wifi_connect(self.dut_client, config, check_connectivity=False)
596        wutils.wait_for_expected_number_of_softap_clients(
597                self.dut, callbackId, 1)
598
599        self.dut.log.info("Start waiting %s seconds with 1 clients ",
600                wifi_constants.DEFAULT_SOFTAP_TIMEOUT_S*1.1)
601        time.sleep(wifi_constants.DEFAULT_SOFTAP_TIMEOUT_S*1.1)
602
603        # When client connected, softap should keep as enabled
604        asserts.assert_true(self.dut.droid.wifiIsApEnabled(),
605                "SoftAp is not reported as running")
606
607        wutils.wifi_toggle_state(self.dut_client, False)
608        wutils.wait_for_expected_number_of_softap_clients(self.dut,
609                callbackId, 0)
610        self.dut.log.info("Start waiting %s seconds with 0 client",
611                wifi_constants.DEFAULT_SOFTAP_TIMEOUT_S*1.1)
612        time.sleep(wifi_constants.DEFAULT_SOFTAP_TIMEOUT_S*1.1)
613        # Softap should stop since no client connected
614        # doesn't disconnect before softap stop
615        wutils.wait_for_expected_softap_state(self.dut, callbackId,
616                wifi_constants.WIFI_AP_DISABLING_STATE)
617        wutils.wait_for_expected_softap_state(self.dut, callbackId,
618                wifi_constants.WIFI_AP_DISABLED_STATE)
619        asserts.assert_false(self.dut.droid.wifiIsApEnabled(),
620                "SoftAp is not reported as running")
621        self.dut.droid.unregisterSoftApCallback(callbackId)
622
623    """ Tests End """
624
625
626if __name__ == "__main__":
627    pass
628