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
36WifiEnums = wutils.WifiEnums
37
38class WifiSoftApTest(WifiBaseTest):
39
40    def setup_class(self):
41        """It will setup the required dependencies from config file and configure
42           the devices for softap mode testing.
43
44        Returns:
45            True if successfully configured the requirements for testing.
46        """
47        self.dut = self.android_devices[0]
48        self.dut_client = self.android_devices[1]
49        req_params = ["dbs_supported_models"]
50        opt_param = ["open_network"]
51        self.unpack_userparams(
52            req_param_names=req_params, opt_param_names=opt_param)
53        if "AccessPoint" in self.user_params:
54            self.legacy_configure_ap_and_start()
55        self.open_network = self.open_network[0]["2g"]
56        # Do a simple version of init - mainly just sync the time and enable
57        # verbose logging.  This test will fail if the DUT has a sim and cell
58        # data is disabled.  We would also like to test with phones in less
59        # constrained states (or add variations where we specifically
60        # constrain).
61        utils.require_sl4a((self.dut, self.dut_client))
62        utils.sync_device_time(self.dut)
63        utils.sync_device_time(self.dut_client)
64        # Set country code explicitly to "US".
65        wutils.set_wifi_country_code(self.dut, wutils.WifiEnums.CountryCode.US)
66        wutils.set_wifi_country_code(self.dut_client, wutils.WifiEnums.CountryCode.US)
67        # Enable verbose logging on the duts
68        self.dut.droid.wifiEnableVerboseLogging(1)
69        asserts.assert_equal(self.dut.droid.wifiGetVerboseLoggingLevel(), 1,
70            "Failed to enable WiFi verbose logging on the softap dut.")
71        self.dut_client.droid.wifiEnableVerboseLogging(1)
72        asserts.assert_equal(self.dut_client.droid.wifiGetVerboseLoggingLevel(), 1,
73            "Failed to enable WiFi verbose logging on the client dut.")
74        wutils.wifi_toggle_state(self.dut, True)
75        wutils.wifi_toggle_state(self.dut_client, True)
76        self.AP_IFACE = 'wlan0'
77        if self.dut.model in self.dbs_supported_models:
78            self.AP_IFACE = 'wlan1'
79        if len(self.android_devices) > 2:
80            utils.sync_device_time(self.android_devices[2])
81            wutils.set_wifi_country_code(self.android_devices[2], wutils.WifiEnums.CountryCode.US)
82            self.android_devices[2].droid.wifiEnableVerboseLogging(1)
83            asserts.assert_equal(self.android_devices[2].droid.wifiGetVerboseLoggingLevel(), 1,
84                "Failed to enable WiFi verbose logging on the client dut.")
85            self.dut_client_2 = self.android_devices[2]
86
87    def teardown_class(self):
88        if self.dut.droid.wifiIsApEnabled():
89            wutils.stop_wifi_tethering(self.dut)
90        wutils.reset_wifi(self.dut)
91        wutils.reset_wifi(self.dut_client)
92        if "AccessPoint" in self.user_params:
93            del self.user_params["reference_networks"]
94            del self.user_params["open_network"]
95
96    def setup_test(self):
97        for ad in self.android_devices:
98            wutils.wifi_toggle_state(ad, True)
99
100    def teardown_test(self):
101        self.dut.log.debug("Toggling Airplane mode OFF.")
102        asserts.assert_true(utils.force_airplane_mode(self.dut, False),
103                            "Can not turn off airplane mode: %s" % self.dut.serial)
104        if self.dut.droid.wifiIsApEnabled():
105            wutils.stop_wifi_tethering(self.dut)
106
107    def on_fail(self, test_name, begin_time):
108        self.dut.take_bug_report(test_name, begin_time)
109        self.dut_client.take_bug_report(test_name, begin_time)
110
111    """ Helper Functions """
112    def create_softap_config(self):
113        """Create a softap config with ssid and password."""
114        ap_ssid = "softap_" + utils.rand_ascii_str(8)
115        ap_password = utils.rand_ascii_str(8)
116        self.dut.log.info("softap setup: %s %s", ap_ssid, ap_password)
117        config = {wutils.WifiEnums.SSID_KEY: ap_ssid}
118        config[wutils.WifiEnums.PWD_KEY] = ap_password
119        return config
120
121    def confirm_softap_in_scan_results(self, ap_ssid):
122        """Confirm the ap started by wifi tethering is seen in scan results.
123
124        Args:
125            ap_ssid: SSID of the ap we are looking for.
126        """
127        wutils.start_wifi_connection_scan_and_ensure_network_found(
128            self.dut_client, ap_ssid);
129
130    def confirm_softap_not_in_scan_results(self, ap_ssid):
131        """Confirm the ap started by wifi tethering is not seen in scan results.
132
133        Args:
134            ap_ssid: SSID of the ap we are looking for.
135        """
136        wutils.start_wifi_connection_scan_and_ensure_network_not_found(
137            self.dut_client, ap_ssid);
138
139    def validate_traffic_between_softap_clients(self, config):
140        """Send traffic between softAp clients.
141
142        Connect SoftAp clients to the wifi hotspot; one android
143        device and the other arduino wifi controller. Send UDP traffic
144        between the clients and verify that expected messages are received.
145
146        Args:
147            config: wifi network config with SSID, password
148        """
149        ad = self.dut_client
150        wd = self.arduino_wifi_dongles[0]
151        wutils.wifi_connect(ad, config, check_connectivity=False)
152        dutils.connect_wifi(wd, config)
153        local_ip = ad.droid.connectivityGetIPv4Addresses('wlan0')[0]
154        remote_ip = wd.ip_address()
155        port = random.randint(8000, 9000)
156        self.log.info("IP addr on android device: %s" % local_ip)
157        self.log.info("IP addr on arduino device: %s" % remote_ip)
158
159        socket = sutils.open_datagram_socket(ad, local_ip, port)
160        sutils.send_recv_data_datagram_sockets(
161            ad, ad, socket, socket, remote_ip, port)
162        sutils.close_datagram_socket(ad, socket)
163
164    def check_cell_data_and_enable(self):
165        """Make sure that cell data is enabled if there is a sim present.
166
167        If a sim is active, cell data needs to be enabled to allow provisioning
168        checks through (when applicable).  This is done to relax hardware
169        requirements on DUTs - without this check, running this set of tests
170        after other wifi tests may cause failures.
171        """
172        # We do have a sim.  Make sure data is enabled so we can tether.
173        if not self.dut.droid.telephonyIsDataEnabled():
174            self.dut.log.info("need to enable data")
175            self.dut.droid.telephonyToggleDataConnection(True)
176            asserts.assert_true(self.dut.droid.telephonyIsDataEnabled(),
177                                "Failed to enable cell data for softap dut.")
178
179    def validate_full_tether_startup(self, band=None, hidden=None,
180                                     test_ping=False, test_clients=None):
181        """Test full startup of wifi tethering
182
183        1. Report current state.
184        2. Switch to AP mode.
185        3. verify SoftAP active.
186        4. Shutdown wifi tethering.
187        5. verify back to previous mode.
188        """
189        initial_wifi_state = self.dut.droid.wifiCheckState()
190        initial_cell_state = tel_utils.is_sim_ready(self.log, self.dut)
191        self.dut.log.info("current state: %s", initial_wifi_state)
192        self.dut.log.info("is sim ready? %s", initial_cell_state)
193        if initial_cell_state:
194            self.check_cell_data_and_enable()
195        config = self.create_softap_config()
196        wutils.start_wifi_tethering(self.dut,
197                                    config[wutils.WifiEnums.SSID_KEY],
198                                    config[wutils.WifiEnums.PWD_KEY], band, hidden)
199        if hidden:
200            # First ensure it's not seen in scan results.
201            self.confirm_softap_not_in_scan_results(
202                config[wutils.WifiEnums.SSID_KEY])
203            # If the network is hidden, it should be saved on the client to be
204            # seen in scan results.
205            config[wutils.WifiEnums.HIDDEN_KEY] = True
206            ret = self.dut_client.droid.wifiAddNetwork(config)
207            asserts.assert_true(ret != -1, "Add network %r failed" % config)
208            self.dut_client.droid.wifiEnableNetwork(ret, 0)
209        self.confirm_softap_in_scan_results(config[wutils.WifiEnums.SSID_KEY])
210        if test_ping:
211            self.validate_ping_between_softap_and_client(config)
212        if test_clients:
213            if hasattr(self, 'arduino_wifi_dongles'):
214                self.validate_traffic_between_softap_clients(config)
215            if len(self.android_devices) > 2:
216                self.validate_ping_between_two_clients(config)
217        wutils.stop_wifi_tethering(self.dut)
218        asserts.assert_false(self.dut.droid.wifiIsApEnabled(),
219                             "SoftAp is still reported as running")
220        if initial_wifi_state:
221            wutils.wait_for_wifi_state(self.dut, True)
222        elif self.dut.droid.wifiCheckState():
223            asserts.fail("Wifi was disabled before softap and now it is enabled")
224
225    def validate_ping_between_softap_and_client(self, config):
226        """Test ping between softap and its client.
227
228        Connect one android device to the wifi hotspot.
229        Verify they can ping each other.
230
231        Args:
232            config: wifi network config with SSID, password
233        """
234        wutils.wifi_connect(self.dut_client, config, check_connectivity=False)
235
236        dut_ip = self.dut.droid.connectivityGetIPv4Addresses(self.AP_IFACE)[0]
237        dut_client_ip = self.dut_client.droid.connectivityGetIPv4Addresses('wlan0')[0]
238
239        self.dut.log.info("Try to ping %s" % dut_client_ip)
240        asserts.assert_true(
241            utils.adb_shell_ping(self.dut, count=10, dest_ip=dut_client_ip, timeout=20),
242            "%s ping %s failed" % (self.dut.serial, dut_client_ip))
243
244        self.dut_client.log.info("Try to ping %s" % dut_ip)
245        asserts.assert_true(
246            utils.adb_shell_ping(self.dut_client, count=10, dest_ip=dut_ip, timeout=20),
247            "%s ping %s failed" % (self.dut_client.serial, dut_ip))
248
249        wutils.stop_wifi_tethering(self.dut)
250
251    def validate_ping_between_two_clients(self, config):
252        """Test ping between softap's clients.
253
254        Connect two android device to the wifi hotspot.
255        Verify the clients can ping each other.
256
257        Args:
258            config: wifi network config with SSID, password
259        """
260        # Connect DUT to Network
261        ad1 = self.dut_client
262        ad2 = self.android_devices[2]
263
264        wutils.wifi_connect(ad1, config, check_connectivity=False)
265        wutils.wifi_connect(ad2, config, check_connectivity=False)
266        ad1_ip = ad1.droid.connectivityGetIPv4Addresses('wlan0')[0]
267        ad2_ip = ad2.droid.connectivityGetIPv4Addresses('wlan0')[0]
268
269        # Ping each other
270        ad1.log.info("Try to ping %s" % ad2_ip)
271        asserts.assert_true(
272            utils.adb_shell_ping(ad1, count=10, dest_ip=ad2_ip, timeout=20),
273            "%s ping %s failed" % (ad1.serial, ad2_ip))
274
275        ad2.log.info("Try to ping %s" % ad1_ip)
276        asserts.assert_true(
277            utils.adb_shell_ping(ad2, count=10, dest_ip=ad1_ip, timeout=20),
278            "%s ping %s failed" % (ad2.serial, ad1_ip))
279
280    """ Tests Begin """
281
282    @test_tracker_info(uuid="495f1252-e440-461c-87a7-2c45f369e129")
283    def test_check_wifi_tethering_supported(self):
284        """Test check for wifi tethering support.
285
286         1. Call method to check if wifi hotspot is supported
287        """
288        # TODO(silberst): wifiIsPortableHotspotSupported() is currently failing.
289        # Remove the extra check and logging when b/30800811 is resolved
290        hotspot_supported = self.dut.droid.wifiIsPortableHotspotSupported()
291        tethering_supported = self.dut.droid.connectivityIsTetheringSupported()
292        self.log.info(
293            "IsPortableHotspotSupported: %s, IsTetheringSupported %s." % (
294            hotspot_supported, tethering_supported))
295        asserts.assert_true(hotspot_supported,
296                            "DUT should support wifi tethering but is reporting false.")
297        asserts.assert_true(tethering_supported,
298                            "DUT should also support wifi tethering when called from ConnectivityManager")
299
300    @test_tracker_info(uuid="09c19c35-c708-48a5-939b-ac2bbb403d54")
301    def test_full_tether_startup(self):
302        """Test full startup of wifi tethering in default band.
303
304        1. Report current state.
305        2. Switch to AP mode.
306        3. verify SoftAP active.
307        4. Shutdown wifi tethering.
308        5. verify back to previous mode.
309        """
310        self.validate_full_tether_startup()
311
312    @test_tracker_info(uuid="6437727d-7db1-4f69-963e-f26a7797e47f")
313    def test_full_tether_startup_2G(self):
314        """Test full startup of wifi tethering in 2G band.
315
316        1. Report current state.
317        2. Switch to AP mode.
318        3. verify SoftAP active.
319        4. Shutdown wifi tethering.
320        5. verify back to previous mode.
321        """
322        self.validate_full_tether_startup(WIFI_CONFIG_APBAND_2G)
323
324    @test_tracker_info(uuid="970272fa-1302-429b-b261-51efb4dad779")
325    def test_full_tether_startup_5G(self):
326        """Test full startup of wifi tethering in 5G band.
327
328        1. Report current state.
329        2. Switch to AP mode.
330        3. verify SoftAP active.
331        4. Shutdown wifi tethering.
332        5. verify back to previous mode.
333        """
334        self.validate_full_tether_startup(WIFI_CONFIG_APBAND_5G)
335
336    @test_tracker_info(uuid="f76ed37a-519a-48b4-b260-ee3fc5a9cae0")
337    def test_full_tether_startup_auto(self):
338        """Test full startup of wifi tethering in auto-band.
339
340        1. Report current state.
341        2. Switch to AP mode.
342        3. verify SoftAP active.
343        4. Shutdown wifi tethering.
344        5. verify back to previous mode.
345        """
346        self.validate_full_tether_startup(WIFI_CONFIG_APBAND_AUTO)
347
348    @test_tracker_info(uuid="d26ee4df-5dcb-4191-829f-05a10b1218a7")
349    def test_full_tether_startup_2G_hidden(self):
350        """Test full startup of wifi tethering in 2G band using hidden AP.
351
352        1. Report current state.
353        2. Switch to AP mode.
354        3. verify SoftAP active.
355        4. Shutdown wifi tethering.
356        5. verify back to previous mode.
357        """
358        self.validate_full_tether_startup(WIFI_CONFIG_APBAND_2G, True)
359
360    @test_tracker_info(uuid="229cd585-a789-4c9a-8948-89fa72de9dd5")
361    def test_full_tether_startup_5G_hidden(self):
362        """Test full startup of wifi tethering in 5G band using hidden AP.
363
364        1. Report current state.
365        2. Switch to AP mode.
366        3. verify SoftAP active.
367        4. Shutdown wifi tethering.
368        5. verify back to previous mode.
369        """
370        self.validate_full_tether_startup(WIFI_CONFIG_APBAND_5G, True)
371
372    @test_tracker_info(uuid="d546a143-6047-4ffd-b3c6-5ec81a38001f")
373    def test_full_tether_startup_auto_hidden(self):
374        """Test full startup of wifi tethering in auto-band using hidden AP.
375
376        1. Report current state.
377        2. Switch to AP mode.
378        3. verify SoftAP active.
379        4. Shutdown wifi tethering.
380        5. verify back to previous mode.
381        """
382        self.validate_full_tether_startup(WIFI_CONFIG_APBAND_AUTO, True)
383
384    @test_tracker_info(uuid="b2f75330-bf33-4cdd-851a-de390f891ef7")
385    def test_tether_startup_while_connected_to_a_network(self):
386        """Test full startup of wifi tethering in auto-band while the device
387        is connected to a network.
388
389        1. Connect to an open network.
390        2. Turn on AP mode (in auto band).
391        3. Verify SoftAP active.
392        4. Make a client connect to the AP.
393        5. Shutdown wifi tethering.
394        6. Ensure that the client disconnected.
395        """
396        wutils.wifi_toggle_state(self.dut, True)
397        wutils.wifi_connect(self.dut, self.open_network)
398        config = self.create_softap_config()
399        wutils.start_wifi_tethering(self.dut,
400                                    config[wutils.WifiEnums.SSID_KEY],
401                                    config[wutils.WifiEnums.PWD_KEY],
402                                    WIFI_CONFIG_APBAND_AUTO)
403        asserts.assert_true(self.dut.droid.wifiIsApEnabled(),
404                             "SoftAp is not reported as running")
405        # local hotspot may not have internet connectivity
406        self.confirm_softap_in_scan_results(config[wutils.WifiEnums.SSID_KEY])
407        wutils.wifi_connect(self.dut_client, config, check_connectivity=False)
408        wutils.stop_wifi_tethering(self.dut)
409        wutils.wait_for_disconnect(self.dut_client)
410
411    @test_tracker_info(uuid="f2cf56ad-b8b9-43b6-ab15-a47b1d96b92e")
412    def test_full_tether_startup_2G_with_airplane_mode_on(self):
413        """Test full startup of wifi tethering in 2G band with
414        airplane mode on.
415
416        1. Turn on airplane mode.
417        2. Report current state.
418        3. Switch to AP mode.
419        4. verify SoftAP active.
420        5. Shutdown wifi tethering.
421        6. verify back to previous mode.
422        7. Turn off airplane mode.
423        """
424        self.dut.log.debug("Toggling Airplane mode ON.")
425        asserts.assert_true(utils.force_airplane_mode(self.dut, True),
426                            "Can not turn on airplane mode: %s" % self.dut.serial)
427        wutils.wifi_toggle_state(self.dut, True)
428        self.validate_full_tether_startup(WIFI_CONFIG_APBAND_2G)
429
430    @test_tracker_info(uuid="05c6f929-7754-477f-a9cd-f77e850b818b")
431    def test_full_tether_startup_2G_multiple_clients(self):
432        """Test full startup of wifi tethering in 2G band, connect clients
433        to softAp and send traffic between them.
434
435        1. Report current state.
436        2. Switch to AP mode.
437        3. verify SoftAP active.
438        4. Connect clients to softAp.
439        5. Send and recv UDP traffic between them.
440        6. Shutdown wifi tethering.
441        7. verify back to previous mode.
442        """
443        asserts.skip_if(not hasattr(self, 'arduino_wifi_dongles'),
444                        "No wifi dongles connected. Skipping test")
445        self.validate_full_tether_startup(WIFI_CONFIG_APBAND_2G,
446                                          test_clients=True)
447
448    @test_tracker_info(uuid="883dd5b1-50c6-4958-a50f-bb4bea77ccaf")
449    def test_full_tether_startup_2G_one_client_ping_softap(self):
450        """(AP) 1 Device can connect to 2G hotspot
451
452        Steps:
453        1. Turn on DUT's 2G softap
454        2. Client connects to the softap
455        3. Client and DUT ping each other
456        """
457        self.validate_full_tether_startup(WIFI_CONFIG_APBAND_2G, test_ping=True)
458
459    @test_tracker_info(uuid="6604e848-99d6-422c-9fdc-2882642438b6")
460    def test_full_tether_startup_5G_one_client_ping_softap(self):
461        """(AP) 1 Device can connect to 5G hotspot
462
463        Steps:
464        1. Turn on DUT's 5G softap
465        2. Client connects to the softap
466        3. Client and DUT ping each other
467        """
468        self.validate_full_tether_startup(WIFI_CONFIG_APBAND_5G, test_ping=True)
469
470    @test_tracker_info(uuid="17725ecd-f900-4cf7-8b2d-d7515b0a595c")
471    def test_softap_2G_two_clients_ping_each_other(self):
472        """Test for 2G hotspot with 2 clients
473
474        1. Turn on 2G hotspot
475        2. Two clients connect to the hotspot
476        3. Two clients ping each other
477        """
478        asserts.skip_if(len(self.android_devices) < 3,
479                        "No extra android devices. Skip test")
480        self.validate_full_tether_startup(WIFI_CONFIG_APBAND_2G, test_clients=True)
481
482    @test_tracker_info(uuid="98c09888-1021-4f79-9065-b3cf9b132146")
483    def test_softap_5G_two_clients_ping_each_other(self):
484        """Test for 5G hotspot with 2 clients
485
486        1. Turn on 5G hotspot
487        2. Two clients connect to the hotspot
488        3. Two clients ping each other
489        """
490        asserts.skip_if(len(self.android_devices) < 3,
491                        "No extra android devices. Skip test")
492        self.validate_full_tether_startup(WIFI_CONFIG_APBAND_5G, test_clients=True)
493
494    @test_tracker_info(uuid="b991129e-030a-4998-9b08-0687270bec24")
495    def test_number_of_softap_clients(self):
496        """Test for number of softap clients to be updated correctly
497
498        1. Turn of hotspot
499        2. Register softap callback
500        3. Let client connect to the hotspot
501        4. Register second softap callback
502        5. Force client connect/disconnect to hotspot
503        6. Unregister second softap callback
504        7. Force second client connect to hotspot (if supported)
505        8. Turn off hotspot
506        9. Verify second softap callback doesn't respond after unregister
507        """
508        config = wutils.start_softap_and_verify(self, WIFI_CONFIG_APBAND_AUTO)
509        # Register callback after softap enabled to avoid unnecessary callback
510        # impact the test
511        callbackId = self.dut.droid.registerSoftApCallback()
512        # Verify clients will update immediately after register callback
513        wutils.wait_for_expected_number_of_softap_clients(
514                self.dut, callbackId, 0)
515        wutils.wait_for_expected_softap_state(self.dut, callbackId,
516                wifi_constants.WIFI_AP_ENABLED_STATE)
517
518        # Force DUTs connect to Network
519        wutils.wifi_connect(self.dut_client, config,
520                check_connectivity=False)
521        wutils.wait_for_expected_number_of_softap_clients(
522                self.dut, callbackId, 1)
523
524        # Register another callback to verify multi callback clients case
525        callbackId_2 = self.dut.droid.registerSoftApCallback()
526        # Verify clients will update immediately after register callback
527        wutils.wait_for_expected_number_of_softap_clients(
528                self.dut, callbackId_2, 1)
529        wutils.wait_for_expected_softap_state(self.dut, callbackId_2,
530                wifi_constants.WIFI_AP_ENABLED_STATE)
531
532        # Client Off/On Wifi to verify number of softap clients will be updated
533        wutils.toggle_wifi_and_wait_for_reconnection(self.dut_client, config)
534
535        wutils.wait_for_expected_number_of_softap_clients(self.dut,
536                callbackId, 0)
537        wutils.wait_for_expected_number_of_softap_clients(self.dut,
538                callbackId_2, 0)
539        wutils.wait_for_expected_number_of_softap_clients(self.dut,
540                callbackId, 1)
541        wutils.wait_for_expected_number_of_softap_clients(self.dut,
542                callbackId_2, 1)
543
544        # Unregister callbackId_2 to verify multi callback clients case
545        self.dut.droid.unregisterSoftApCallback(callbackId_2)
546
547        if len(self.android_devices) > 2:
548            wutils.wifi_connect(self.android_devices[2], config,
549                    check_connectivity=False)
550            wutils.wait_for_expected_number_of_softap_clients(
551                    self.dut, callbackId, 2)
552
553        # Turn off softap when clients connected
554        wutils.stop_wifi_tethering(self.dut)
555        wutils.wait_for_disconnect(self.dut_client)
556        if len(self.android_devices) > 2:
557            wutils.wait_for_disconnect(self.android_devices[2])
558
559        # Verify client number change back to 0 after softap stop if client
560        # doesn't disconnect before softap stop
561        wutils.wait_for_expected_softap_state(self.dut, callbackId,
562                wifi_constants.WIFI_AP_DISABLING_STATE)
563        wutils.wait_for_expected_softap_state(self.dut, callbackId,
564                wifi_constants.WIFI_AP_DISABLED_STATE)
565        wutils.wait_for_expected_number_of_softap_clients(
566                self.dut, callbackId, 0)
567        # Unregister callback
568        self.dut.droid.unregisterSoftApCallback(callbackId)
569
570        # Check no any callbackId_2 event after unregister
571        asserts.assert_equal(
572                wutils.get_current_number_of_softap_clients(
573                self.dut, callbackId_2), None)
574
575    @test_tracker_info(uuid="35bc4ba1-bade-42ee-a563-0c73afb2402a")
576    def test_softap_auto_shut_off(self):
577        """Test for softap auto shut off
578
579        1. Turn off hotspot
580        2. Register softap callback
581        3. Let client connect to the hotspot
582        4. Start wait [wifi_constants.DEFAULT_SOFTAP_TIMEOUT_S] seconds
583        5. Check hotspot doesn't shut off
584        6. Let client disconnect to the hotspot
585        7. Start wait [wifi_constants.DEFAULT_SOFTAP_TIMEOUT_S] seconds
586        8. Check hotspot auto shut off
587        """
588        config = wutils.start_softap_and_verify(self, WIFI_CONFIG_APBAND_AUTO)
589        # Register callback after softap enabled to avoid unnecessary callback
590        # impact the test
591        callbackId = self.dut.droid.registerSoftApCallback()
592        # Verify clients will update immediately after register callback
593        wutils.wait_for_expected_number_of_softap_clients(self.dut,
594                callbackId, 0)
595        wutils.wait_for_expected_softap_state(self.dut, callbackId,
596                wifi_constants.WIFI_AP_ENABLED_STATE)
597
598        # Force DUTs connect to Network
599        wutils.wifi_connect(self.dut_client, config, check_connectivity=False)
600        wutils.wait_for_expected_number_of_softap_clients(
601                self.dut, callbackId, 1)
602
603        self.dut.log.info("Start waiting %s seconds with 1 clients ",
604                wifi_constants.DEFAULT_SOFTAP_TIMEOUT_S*1.1)
605        time.sleep(wifi_constants.DEFAULT_SOFTAP_TIMEOUT_S*1.1)
606
607        # When client connected, softap should keep as enabled
608        asserts.assert_true(self.dut.droid.wifiIsApEnabled(),
609                "SoftAp is not reported as running")
610
611        wutils.wifi_toggle_state(self.dut_client, False)
612        wutils.wait_for_expected_number_of_softap_clients(self.dut,
613                callbackId, 0)
614        self.dut.log.info("Start waiting %s seconds with 0 client",
615                wifi_constants.DEFAULT_SOFTAP_TIMEOUT_S*1.1)
616        time.sleep(wifi_constants.DEFAULT_SOFTAP_TIMEOUT_S*1.1)
617        # Softap should stop since no client connected
618        # doesn't disconnect before softap stop
619        wutils.wait_for_expected_softap_state(self.dut, callbackId,
620                wifi_constants.WIFI_AP_DISABLING_STATE)
621        wutils.wait_for_expected_softap_state(self.dut, callbackId,
622                wifi_constants.WIFI_AP_DISABLED_STATE)
623        asserts.assert_false(self.dut.droid.wifiIsApEnabled(),
624                "SoftAp is not reported as running")
625        self.dut.droid.unregisterSoftApCallback(callbackId)
626
627    @test_tracker_info(uuid="3a10c7fd-cd8d-4d46-9d12-88a68640e060")
628    def test_softap_auto_shut_off_with_customized_timeout(self):
629        """Test for softap auto shut off
630        1. Turn on hotspot
631        2. Register softap callback
632        3. Backup original shutdown timeout value
633        4. Set up test_shutdown_timeout_value
634        5. Let client connect to the hotspot
635        6. Start wait test_shutdown_timeout_value * 1.1 seconds
636        7. Check hotspot doesn't shut off
637        8. Let client disconnect to the hotspot
638        9. Start wait test_shutdown_timeout_value seconds
639        10. Check hotspot auto shut off
640        """
641        # Backup config
642        original_softap_config = self.dut.droid.wifiGetApConfiguration()
643        # This config only included SSID and Password which used for connection
644        # only.
645        config = wutils.start_softap_and_verify(self, WIFI_CONFIG_APBAND_AUTO)
646
647        # Get current configuration to use for update configuration
648        current_softap_config = self.dut.droid.wifiGetApConfiguration()
649        # Register callback after softap enabled to avoid unnecessary callback
650        # impact the test
651        callbackId = self.dut.droid.registerSoftApCallback()
652        # Verify clients will update immediately after register callback
653        wutils.wait_for_expected_number_of_softap_clients(self.dut,
654                callbackId, 0)
655        wutils.wait_for_expected_softap_state(self.dut, callbackId,
656                wifi_constants.WIFI_AP_ENABLED_STATE)
657
658        # Setup shutdown timeout value
659        test_shutdown_timeout_value_s = 10
660        wutils.save_wifi_soft_ap_config(self.dut, current_softap_config,
661            shutdown_timeout_millis=test_shutdown_timeout_value_s * 1000)
662        # Force DUTs connect to Network
663        wutils.wifi_connect(self.dut_client, config, check_connectivity=False)
664        wutils.wait_for_expected_number_of_softap_clients(
665                self.dut, callbackId, 1)
666
667        self.dut.log.info("Start waiting %s seconds with 1 clients ",
668                test_shutdown_timeout_value_s * 1.1)
669        time.sleep(test_shutdown_timeout_value_s * 1.1)
670
671        # When client connected, softap should keep as enabled
672        asserts.assert_true(self.dut.droid.wifiIsApEnabled(),
673                "SoftAp is not reported as running")
674
675        wutils.wifi_toggle_state(self.dut_client, False)
676        wutils.wait_for_expected_number_of_softap_clients(self.dut,
677                callbackId, 0)
678        self.dut.log.info("Start waiting %s seconds with 0 client",
679                test_shutdown_timeout_value_s * 1.1)
680        time.sleep(test_shutdown_timeout_value_s * 1.1)
681        # Softap should stop since no client connected
682        # doesn't disconnect before softap stop
683        wutils.wait_for_expected_softap_state(self.dut, callbackId,
684                wifi_constants.WIFI_AP_DISABLING_STATE)
685        wutils.wait_for_expected_softap_state(self.dut, callbackId,
686                wifi_constants.WIFI_AP_DISABLED_STATE)
687        asserts.assert_false(self.dut.droid.wifiIsApEnabled(),
688                "SoftAp is not reported as running")
689        self.dut.droid.unregisterSoftApCallback(callbackId)
690
691        # Restore config
692        wutils.save_wifi_soft_ap_config(self.dut, original_softap_config)
693
694    @test_tracker_info(uuid="a9444699-f0d3-4ac3-922b-05e9d4f67968")
695    def test_softap_configuration_update(self):
696      """Test for softap configuration update
697        1. Get current softap configuration
698        2. Update to Open Security configuration
699        3. Update to WPA2_PSK configuration
700        4. Restore the configuration
701      """
702      # Backup config
703      original_softap_config = self.dut.droid.wifiGetApConfiguration()
704      wutils.save_wifi_soft_ap_config(self.dut, {"SSID":"ACTS_TEST"},
705          band=WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G, hidden=False,
706          security=WifiEnums.SoftApSecurityType.OPEN, password="",
707          channel=11, max_clients=0, shutdown_timeout_enable=False,
708          shutdown_timeout_millis=0, client_control_enable=True,
709          allowedList=[], blockedList=[])
710
711      wutils.save_wifi_soft_ap_config(self.dut, {"SSID":"ACTS_TEST"},
712          band=WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G_5G, hidden=True,
713          security=WifiEnums.SoftApSecurityType.WPA2, password="12345678",
714          channel=0, max_clients=1, shutdown_timeout_enable=True,
715          shutdown_timeout_millis=10000, client_control_enable=False,
716          allowedList=["aa:bb:cc:dd:ee:ff"], blockedList=["11:22:33:44:55:66"])
717
718      # Restore config
719      wutils.save_wifi_soft_ap_config(self.dut, original_softap_config)
720
721    @test_tracker_info(uuid="8a5d81fa-649c-4679-a823-5cef50828a94")
722    def test_softap_client_control(self):
723        """Test Client Control feature
724        1. Check SoftApCapability to make sure feature is supported
725        2. Backup config
726        3. Setup configuration which used to start softap
727        4. Register callback after softap enabled
728        5. Trigger client connect to softap
729        6. Verify blocking event
730        7. Add client into allowed list
731        8. Verify client connected
732        9. Restore Config
733        """
734        # Register callback to check capability first
735        callbackId = self.dut.droid.registerSoftApCallback()
736        # Check capability first to make sure DUT support this test.
737        capabilityEventStr = wifi_constants.SOFTAP_CALLBACK_EVENT + str(
738            callbackId) + wifi_constants.SOFTAP_CAPABILITY_CHANGED
739        capability = self.dut.ed.pop_event(capabilityEventStr, 10)
740        asserts.skip_if(not capability['data'][wifi_constants
741            .SOFTAP_CAPABILITY_FEATURE_CLIENT_CONTROL],
742            "Client control isn't supported, ignore test")
743
744        # Unregister callback before start test to avoid
745        # unnecessary callback impact the test
746        self.dut.droid.unregisterSoftApCallback(callbackId)
747
748        # start the test
749
750        # Backup config
751        original_softap_config = self.dut.droid.wifiGetApConfiguration()
752        # Setup configuration which used to start softap
753        wutils.save_wifi_soft_ap_config(self.dut, {"SSID":"ACTS_TEST"},
754            band=WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G_5G, hidden=False,
755            security=WifiEnums.SoftApSecurityType.WPA2, password="12345678",
756            client_control_enable=True)
757
758        wutils.start_wifi_tethering_saved_config(self.dut)
759        current_softap_config = self.dut.droid.wifiGetApConfiguration()
760        # Register callback after softap enabled to avoid unnecessary callback
761        # impact the test
762        callbackId = self.dut.droid.registerSoftApCallback()
763
764        # Verify clients will update immediately after register callback
765        wutils.wait_for_expected_number_of_softap_clients(self.dut,
766                callbackId, 0)
767        wutils.wait_for_expected_softap_state(self.dut, callbackId,
768                wifi_constants.WIFI_AP_ENABLED_STATE)
769
770        # Trigger client connection
771        self.dut_client.droid.wifiConnectByConfig(current_softap_config)
772
773        eventStr = wifi_constants.SOFTAP_CALLBACK_EVENT + str(
774            callbackId) + wifi_constants.SOFTAP_BLOCKING_CLIENT_CONNECTING
775        blockedClient = self.dut.ed.pop_event(eventStr, 10)
776        asserts.assert_equal(blockedClient['data'][wifi_constants.
777            SOFTAP_BLOCKING_CLIENT_REASON_KEY],
778            wifi_constants.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER,
779            "Blocked reason code doesn't match")
780
781        # Update configuration, add client into allowed list
782        wutils.save_wifi_soft_ap_config(self.dut, current_softap_config,
783            allowedList=[blockedClient['data'][wifi_constants.
784            SOFTAP_BLOCKING_CLIENT_WIFICLIENT_KEY]])
785
786        # Wait configuration updated
787        time.sleep(3)
788        # Trigger connection again
789        self.dut_client.droid.wifiConnectByConfig(current_softap_config)
790
791        # Verify client connected
792        wutils.wait_for_expected_number_of_softap_clients(self.dut,
793                callbackId, 1)
794
795        # Restore config
796        wutils.save_wifi_soft_ap_config(self.dut, original_softap_config)
797
798        # Unregister callback
799        self.dut.droid.unregisterSoftApCallback(callbackId)
800
801    @test_tracker_info(uuid="d0b61b58-fa2b-4ced-bc52-3366cb826e79")
802    def test_softap_max_client_setting(self):
803        """Test Client Control feature
804        1. Check device number and capability to make sure feature is supported
805        2. Backup config
806        3. Setup configuration which used to start softap
807        4. Register callback after softap enabled
808        5. Trigger client connect to softap
809        6. Verify blocking event
810        7. Extend max client setting
811        8. Verify client connected
812        9. Restore Config
813        """
814        asserts.skip_if(len(self.android_devices) < 3,
815                        "Device less than 3, skip the test.")
816        # Register callback to check capability first
817        callbackId = self.dut.droid.registerSoftApCallback()
818        # Check capability first to make sure DUT support this test.
819        capabilityEventStr = wifi_constants.SOFTAP_CALLBACK_EVENT + str(
820            callbackId) + wifi_constants.SOFTAP_CAPABILITY_CHANGED
821        capability = self.dut.ed.pop_event(capabilityEventStr, 10)
822        asserts.skip_if(not capability['data'][wifi_constants
823            .SOFTAP_CAPABILITY_FEATURE_CLIENT_CONTROL],
824            "Client control isn't supported, ignore test")
825
826        # Unregister callback before start test to avoid
827        # unnecessary callback impact the test
828        self.dut.droid.unregisterSoftApCallback(callbackId)
829
830        # Backup config
831        original_softap_config = self.dut.droid.wifiGetApConfiguration()
832        # Setup configuration which used to start softap
833        wutils.save_wifi_soft_ap_config(self.dut, {"SSID":"ACTS_TEST"},
834            band=WifiEnums.WIFI_CONFIG_SOFTAP_BAND_2G_5G, hidden=False,
835            security=WifiEnums.SoftApSecurityType.WPA2, password="12345678",
836            max_clients=1)
837
838        wutils.start_wifi_tethering_saved_config(self.dut)
839        current_softap_config = self.dut.droid.wifiGetApConfiguration()
840        # Register callback again after softap enabled to avoid
841        # unnecessary callback impact the test
842        callbackId = self.dut.droid.registerSoftApCallback()
843
844        # Verify clients will update immediately after register calliback
845        wutils.wait_for_expected_number_of_softap_clients(self.dut,
846                callbackId, 0)
847        wutils.wait_for_expected_softap_state(self.dut, callbackId,
848                wifi_constants.WIFI_AP_ENABLED_STATE)
849
850        # Trigger client connection
851        self.dut_client.droid.wifiConnectByConfig(current_softap_config)
852        self.dut_client_2.droid.wifiConnectByConfig(current_softap_config)
853        # Wait client connect
854        time.sleep(3)
855
856        # Verify one client connected and one blocked due to max client
857        eventStr = wifi_constants.SOFTAP_CALLBACK_EVENT + str(
858            callbackId) + wifi_constants.SOFTAP_BLOCKING_CLIENT_CONNECTING
859        blockedClient = self.dut.ed.pop_event(eventStr, 10)
860        asserts.assert_equal(blockedClient['data'][wifi_constants.
861            SOFTAP_BLOCKING_CLIENT_REASON_KEY],
862            wifi_constants.SAP_CLIENT_BLOCK_REASON_CODE_NO_MORE_STAS,
863            "Blocked reason code doesn't match")
864        wutils.wait_for_expected_number_of_softap_clients(self.dut,
865                callbackId, 1)
866
867        # Update configuration, extend client to 2
868        wutils.save_wifi_soft_ap_config(self.dut, current_softap_config,
869            max_clients=2)
870
871        # Wait configuration updated
872        time.sleep(3)
873        # Trigger connection again
874        self.dut_client_2.droid.wifiConnectByConfig(current_softap_config)
875        # Wait client connect
876        time.sleep(3)
877        # Verify client connected
878        wutils.wait_for_expected_number_of_softap_clients(self.dut,
879                callbackId, 2)
880
881        # Restore config
882        wutils.save_wifi_soft_ap_config(self.dut, original_softap_config)
883
884        # Unregister callback
885        self.dut.droid.unregisterSoftApCallback(callbackId)
886    """ Tests End """
887
888
889if __name__ == "__main__":
890    pass
891