• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3.4
2#
3#   Copyright 2018 - The Android Open Source Project
4#
5#   Licensed under the Apache License, Version 2.0 (the "License");
6#   you may not use this file except in compliance with the License.
7#   You may obtain a copy of the License at
8#
9#       http://www.apache.org/licenses/LICENSE-2.0
10#
11#   Unless required by applicable law or agreed to in writing, software
12#   distributed under the License is distributed on an "AS IS" BASIS,
13#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14#   See the License for the specific language governing permissions and
15#   limitations under the License.
16
17import itertools
18import pprint
19import queue
20import time
21
22import acts.base_test
23import acts.signals as signals
24from acts.test_utils.tel.tel_test_utils import WIFI_CONFIG_APBAND_2G
25from acts.test_utils.tel.tel_test_utils import WIFI_CONFIG_APBAND_5G
26import acts.test_utils.wifi.wifi_test_utils as wutils
27import acts.utils as utils
28
29from acts import asserts
30from acts.test_decorators import test_tracker_info
31from acts.test_utils.wifi.WifiBaseTest import WifiBaseTest
32
33WifiEnums = wutils.WifiEnums
34
35# Channels to configure the AP for various test scenarios.
36WIFI_NETWORK_AP_CHANNEL_2G = 1
37WIFI_NETWORK_AP_CHANNEL_5G = 36
38WIFI_NETWORK_AP_CHANNEL_5G_DFS = 132
39
40class WifiStaApConcurrencyTest(WifiBaseTest):
41    """Tests for STA + AP concurrency scenarios.
42
43    Test Bed Requirement:
44    * Two Android devices (For AP)
45    * One Wi-Fi network visible to the device (for STA).
46    """
47
48    def __init__(self, controllers):
49        WifiBaseTest.__init__(self, controllers)
50
51    def setup_class(self):
52        self.dut = self.android_devices[0]
53        self.dut_client = self.android_devices[1]
54        wutils.wifi_test_device_init(self.dut)
55        wutils.wifi_test_device_init(self.dut_client)
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        self.dut.droid.wifiSetCountryCode(wutils.WifiEnums.CountryCode.US)
66        self.dut_client.droid.wifiSetCountryCode(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
75        req_params = ["AccessPoint", "dbs_supported_models"]
76        opt_param = ["iperf_server_address"]
77        self.unpack_userparams(
78            req_param_names=req_params, opt_param_names=opt_param)
79
80        if self.dut.model not in self.dbs_supported_models:
81            asserts.skip(
82                ("Device %s does not support dual interfaces.")
83                % self.dut.model)
84
85        if "iperf_server_address" in self.user_params:
86            self.iperf_server = self.iperf_servers[0]
87        if hasattr(self, 'iperf_server'):
88            self.iperf_server.start()
89
90        # Set the client wifi state to on before the test begins.
91        wutils.wifi_toggle_state(self.dut_client, True)
92
93        if len(self.android_devices) > 2:
94            wutils.wifi_test_device_init(self.android_devices[2])
95            utils.sync_device_time(self.android_devices[2])
96            self.android_devices[2].droid.wifiSetCountryCode(wutils.WifiEnums.CountryCode.US)
97            self.android_devices[2].droid.wifiEnableVerboseLogging(1)
98            asserts.assert_equal(self.android_devices[2].droid.wifiGetVerboseLoggingLevel(), 1,
99                "Failed to enable WiFi verbose logging on the client dut.")
100
101    def setup_test(self):
102        for ad in self.android_devices:
103            ad.droid.wakeLockAcquireBright()
104            ad.droid.wakeUpNow()
105        self.turn_location_off_and_scan_toggle_off()
106        wutils.wifi_toggle_state(self.dut, False)
107
108    def teardown_test(self):
109        # Prevent the stop wifi tethering failure to block ap close
110        try:
111            wutils.stop_wifi_tethering(self.dut)
112        except signals.TestFailure:
113            pass
114        for ad in self.android_devices:
115            ad.droid.wakeLockRelease()
116            ad.droid.goToSleepNow()
117            wutils.reset_wifi(ad)
118        self.access_points[0].close()
119        del self.user_params["reference_networks"]
120        del self.user_params["open_network"]
121
122    def teardown_class(self):
123        if hasattr(self, 'iperf_server'):
124            self.iperf_server.stop()
125
126    def on_fail(self, test_name, begin_time):
127        for ad in self.android_devices:
128            ad.take_bug_report(test_name, begin_time)
129            ad.cat_adb_log(test_name, begin_time)
130
131    """Helper Functions"""
132    def configure_ap(self, channel_2g=None, channel_5g=None):
133        """Configure and bring up AP on required channel.
134
135        Args:
136            channel_2g: The channel number to use for 2GHz network.
137            channel_5g: The channel number to use for 5GHz network.
138
139        """
140        if not channel_2g:
141            self.legacy_configure_ap_and_start(channel_5g=channel_5g)
142        elif not channel_5g:
143            self.legacy_configure_ap_and_start(channel_2g=channel_2g)
144        else:
145            self.legacy_configure_ap_and_start(channel_2g=channel_2g,
146                channel_5g=channel_5g)
147        self.wpapsk_2g = self.reference_networks[0]["2g"]
148        self.wpapsk_5g = self.reference_networks[0]["5g"]
149
150    def turn_location_on_and_scan_toggle_on(self):
151        """ Turns on wifi location scans.
152        """
153        acts.utils.set_location_service(self.dut, True)
154        self.dut.droid.wifiScannerToggleAlwaysAvailable(True)
155        msg = "Failed to turn on location service's scan."
156        asserts.assert_true(self.dut.droid.wifiScannerIsAlwaysAvailable(), msg)
157
158    def turn_location_off_and_scan_toggle_off(self):
159        """ Turns off wifi location scans.
160        """
161        acts.utils.set_location_service(self.dut, False)
162        self.dut.droid.wifiScannerToggleAlwaysAvailable(False)
163        msg = "Failed to turn off location service's scan."
164        asserts.assert_true(not self.dut.droid.wifiScannerIsAlwaysAvailable(), msg)
165
166    def run_iperf_client(self, params):
167        """Run iperf traffic after connection.
168
169        Args:
170            params: A tuple of network info and AndroidDevice object.
171        """
172        if "iperf_server_address" in self.user_params:
173            wait_time = 5
174            network, ad = params
175            SSID = network[WifiEnums.SSID_KEY]
176            self.log.info("Starting iperf traffic through {}".format(SSID))
177            time.sleep(wait_time)
178            port_arg = "-p {}".format(self.iperf_server.port)
179            success, data = ad.run_iperf_client(self.iperf_server_address,
180                                                port_arg)
181            self.log.debug(pprint.pformat(data))
182            asserts.assert_true(success, "Error occurred in iPerf traffic.")
183
184    def connect_to_wifi_network_and_verify(self, params):
185        """Connection logic for open and psk wifi networks.
186
187        Args:
188            params: A tuple of network info and AndroidDevice object.
189        """
190        network, ad = params
191        SSID = network[WifiEnums.SSID_KEY]
192        wutils.start_wifi_connection_scan_and_ensure_network_found(
193            ad, SSID)
194        wutils.wifi_connect(ad, network, num_of_tries=3)
195        if len(self.android_devices) > 2:
196            wutils.reset_wifi(self.android_devices[2])
197            wutils.start_wifi_connection_scan_and_ensure_network_found(
198                    self.android_devices[2], SSID)
199            wutils.wifi_connect(self.android_devices[2], network)
200
201    def confirm_softap_can_be_connected(self, network, check_connectivity=True):
202        """Confirm the ap started by wifi tethering is seen in scan results.
203
204        Args:
205            network: config of the ap we are looking for.
206        """
207        SSID = network[WifiEnums.SSID_KEY]
208        wutils.start_wifi_connection_scan_and_ensure_network_found(
209            self.dut_client, SSID)
210        wutils.wifi_connect(self.dut_client, network, check_connectivity=check_connectivity)
211        if len(self.android_devices) > 2:
212            wutils.reset_wifi(self.android_devices[2])
213            wutils.start_wifi_connection_scan_and_ensure_network_found(
214                    self.android_devices[2], SSID)
215            wutils.wifi_connect(
216                    self.android_devices[2], network, check_connectivity=check_connectivity)
217
218    def create_softap_config(self):
219        """Create a softap config with ssid and password."""
220        ap_ssid = "softap_" + utils.rand_ascii_str(8)
221        ap_password = utils.rand_ascii_str(8)
222        self.dut.log.info("softap setup: %s %s", ap_ssid, ap_password)
223        config = {wutils.WifiEnums.SSID_KEY: ap_ssid}
224        config[wutils.WifiEnums.PWD_KEY] = ap_password
225        return config
226
227    def start_softap_and_verify(self, band, check_connectivity=True):
228        """Test startup of softap
229
230        1. Bring up AP mode.
231        2. Verify SoftAP active using the client device.
232        """
233        config = self.create_softap_config()
234        wutils.start_wifi_tethering(self.dut,
235                                    config[wutils.WifiEnums.SSID_KEY],
236                                    config[wutils.WifiEnums.PWD_KEY], band)
237        self.confirm_softap_can_be_connected(config, check_connectivity)
238        return config
239
240    def connect_to_wifi_network_and_start_softap(self, nw_params, softap_band):
241        """Test concurrent wifi connection and softap.
242        This helper method first makes a wifi connection and then starts SoftAp.
243
244        Args:
245            nw_params: Params for network STA connection.
246            softap_band: Band for the AP.
247
248        1. Bring up wifi.
249        2. Establish connection to a network.
250        3. Bring up softap and verify AP can be connected by a client device.
251        4. Run iperf on the wifi/softap connection to the network.
252        """
253        wutils.wifi_toggle_state(self.dut, True)
254        self.connect_to_wifi_network_and_verify((nw_params, self.dut))
255        softap_config = self.start_softap_and_verify(softap_band)
256        self.run_iperf_client((nw_params, self.dut))
257        self.run_iperf_client((softap_config, self.dut_client))
258        if len(self.android_devices) > 2:
259            self.log.info("Testbed has extra android devices, do more validation")
260            ad1 = self.dut_client
261            ad2 = self.android_devices[2]
262            ad1_ip = ad1.droid.connectivityGetIPv4Addresses('wlan0')[0]
263            ad2_ip = ad2.droid.connectivityGetIPv4Addresses('wlan0')[0]
264            # Ping each other
265            asserts.assert_true(
266                utils.adb_shell_ping(ad1, count=10, dest_ip=ad2_ip, timeout=20),
267                "%s ping %s failed" % (ad1.serial, ad2_ip))
268            asserts.assert_true(
269                utils.adb_shell_ping(ad2, count=10, dest_ip=ad1_ip, timeout=20),
270                "%s ping %s failed" % (ad2.serial, ad1_ip))
271        # Verify that both softap & wifi is enabled concurrently.
272        self.verify_wifi_and_softap_enabled()
273
274    def start_softap_and_connect_to_wifi_network(self, nw_params, softap_band):
275        """Test concurrent wifi connection and softap.
276        This helper method first starts SoftAp and then makes a wifi connection.
277
278        Args:
279            nw_params: Params for network STA connection.
280            softap_band: Band for the AP.
281
282        1. Bring up softap and verify AP can be connected by a client device.
283        2. Bring up wifi.
284        3. Establish connection to a network.
285        4. Run iperf on the wifi/softap connection to the network.
286        """
287        softap_config = self.start_softap_and_verify(softap_band, check_connectivity=False)
288        wutils.wifi_toggle_state(self.dut, True)
289        self.connect_to_wifi_network_and_verify((nw_params, self.dut))
290        self.run_iperf_client((nw_params, self.dut))
291        self.run_iperf_client((softap_config, self.dut_client))
292        if len(self.android_devices) > 2:
293            self.log.info("Testbed has extra android devices, do more validation")
294            self.verify_traffic_between_ap_clients(
295                    self.dut, self.android_devices[2])
296        # Verify that both softap & wifi is enabled concurrently.
297        self.verify_wifi_and_softap_enabled()
298
299    def verify_wifi_and_softap_enabled(self):
300        """Helper to verify both wifi and softap is enabled
301        """
302        asserts.assert_true(self.dut.droid.wifiCheckState(),
303                            "Wifi is not reported as running")
304        asserts.assert_true(self.dut.droid.wifiIsApEnabled(),
305                             "SoftAp is not reported as running")
306
307    def verify_traffic_between_softap_clients(self, ad1, ad2, num_of_tries=2):
308        """Test the clients that connect to DUT's softap can ping each other.
309
310        Args:
311            num_of_tries: the retry times of ping test.
312        """
313        ad1_ip = ad1.droid.connectivityGetIPv4Addresses('wlan0')[0]
314        ad2_ip = ad2.droid.connectivityGetIPv4Addresses('wlan0')[0]
315        # Ping each other
316        for _ in range(num_of_tries):
317            if utils.adb_shell_ping(ad1, count=10, dest_ip=ad2_ip, timeout=20):
318                break
319        else:
320            asserts.fail("%s ping %s failed" % (ad1.serial, ad2_ip))
321        for _ in range(num_of_tries):
322            if utils.adb_shell_ping(ad2, count=10, dest_ip=ad1_ip, timeout=20):
323                break
324        else:
325            asserts.fail("%s ping %s failed" % (ad2.serial, ad1_ip))
326
327    def verify_traffic_between_ap_clients(
328            self, ad1, ad2, num_of_tries=2):
329        """Test the clients that connect to access point can ping each other.
330
331        Args:
332            num_of_tries: the retry times of ping test.
333        """
334        ad1_ip = ad1.droid.connectivityGetIPv4Addresses('wlan0')[0]
335        ad2_ip = ad2.droid.connectivityGetIPv4Addresses('wlan0')[0]
336        # Ping each other
337        for _ in range(num_of_tries):
338            if utils.adb_shell_ping(ad1, count=10, dest_ip=ad2_ip, timeout=20):
339                break
340        else:
341            asserts.fail("%s ping %s failed" % (ad1.serial, ad2_ip))
342        for _ in range(num_of_tries):
343            if utils.adb_shell_ping(ad2, count=10, dest_ip=ad1_ip, timeout=20):
344                break
345        else:
346            asserts.fail("%s ping %s failed" % (ad2.serial, ad1_ip))
347
348    """Tests"""
349    @test_tracker_info(uuid="c396e7ac-cf22-4736-a623-aa6d3c50193a")
350    def test_wifi_connection_2G_softap_2G(self):
351        """Tests connection to 2G network followed by bringing up SoftAp on 2G.
352        """
353        self.configure_ap(channel_2g=WIFI_NETWORK_AP_CHANNEL_2G)
354        self.connect_to_wifi_network_and_start_softap(
355            self.wpapsk_2g, WIFI_CONFIG_APBAND_2G)
356
357    @test_tracker_info(uuid="1cd6120d-3db4-4624-9bae-55c976533a48")
358    def test_wifi_connection_5G_softap_5G(self):
359        """Tests connection to 5G network followed by bringing up SoftAp on 5G.
360        """
361        self.configure_ap(channel_5g=WIFI_NETWORK_AP_CHANNEL_5G)
362        self.connect_to_wifi_network_and_start_softap(
363            self.wpapsk_5g, WIFI_CONFIG_APBAND_5G)
364
365    @test_tracker_info(uuid="5f980007-3490-413e-b94e-7700ffab8534")
366    def test_wifi_connection_5G_DFS_softap_5G(self):
367        """Tests connection to 5G DFS network followed by bringing up SoftAp on 5G.
368        """
369        self.configure_ap(channel_5g=WIFI_NETWORK_AP_CHANNEL_5G_DFS)
370        self.connect_to_wifi_network_and_start_softap(
371            self.wpapsk_5g, WIFI_CONFIG_APBAND_5G)
372
373    @test_tracker_info(uuid="d05d5d44-c738-4372-9f01-ce2a640a2f25")
374    def test_wifi_connection_5G_softap_2G(self):
375        """Tests connection to 5G network followed by bringing up SoftAp on 2G.
376        """
377        self.configure_ap(channel_5g=WIFI_NETWORK_AP_CHANNEL_5G)
378        self.connect_to_wifi_network_and_start_softap(
379            self.wpapsk_5g, WIFI_CONFIG_APBAND_2G)
380
381    @test_tracker_info(uuid="909ac713-1ad3-4dad-9be3-ad60f00ed25e")
382    def test_wifi_connection_5G_DFS_softap_2G(self):
383        """Tests connection to 5G DFS network followed by bringing up SoftAp on 2G.
384        """
385        self.configure_ap(channel_5g=WIFI_NETWORK_AP_CHANNEL_5G_DFS)
386        self.connect_to_wifi_network_and_start_softap(
387            self.wpapsk_5g, WIFI_CONFIG_APBAND_2G)
388
389    @test_tracker_info(uuid="e8de724a-25d3-4801-94cc-22e9e0ecc8d1")
390    def test_wifi_connection_2G_softap_5G(self):
391        """Tests connection to 2G network followed by bringing up SoftAp on 5G.
392        """
393        self.configure_ap(channel_2g=WIFI_NETWORK_AP_CHANNEL_2G)
394        self.connect_to_wifi_network_and_start_softap(
395            self.wpapsk_2g, WIFI_CONFIG_APBAND_5G)
396
397    @test_tracker_info(uuid="647f4e17-5c7a-4249-98af-f791d163a39f")
398    def test_wifi_connection_5G_softap_2G_with_location_scan_on(self):
399        """Tests connection to 5G network followed by bringing up SoftAp on 2G
400        with location scans turned on.
401        """
402        self.configure_ap(channel_5g=WIFI_NETWORK_AP_CHANNEL_5G)
403        self.turn_location_on_and_scan_toggle_on()
404        self.connect_to_wifi_network_and_start_softap(
405            self.wpapsk_5g, WIFI_CONFIG_APBAND_2G)
406        # Now toggle wifi off & ensure we can still scan.
407        wutils.wifi_toggle_state(self.dut, False)
408        wutils.start_wifi_connection_scan_and_ensure_network_found(
409            self.dut, self.wpapsk_5g[WifiEnums.SSID_KEY])
410
411    @test_tracker_info(uuid="4aa56c11-e5bc-480b-bd61-4b4ee577a5da")
412    def test_softap_2G_wifi_connection_2G(self):
413        """Tests bringing up SoftAp on 2G followed by connection to 2G network.
414        """
415        self.configure_ap(channel_2g=WIFI_NETWORK_AP_CHANNEL_2G)
416        self.start_softap_and_connect_to_wifi_network(
417            self.wpapsk_2g, WIFI_CONFIG_APBAND_2G)
418
419    @test_tracker_info(uuid="5f954957-ad20-4de1-b20c-6c97d0463bdd")
420    def test_softap_5G_wifi_connection_5G(self):
421        """Tests bringing up SoftAp on 5G followed by connection to 5G network.
422        """
423        self.configure_ap(channel_5g=WIFI_NETWORK_AP_CHANNEL_5G)
424        self.start_softap_and_connect_to_wifi_network(
425            self.wpapsk_5g, WIFI_CONFIG_APBAND_5G)
426
427    @test_tracker_info(uuid="1306aafc-a07e-4654-ba78-674f90cf748e")
428    def test_softap_5G_wifi_connection_5G_DFS(self):
429        """Tests bringing up SoftAp on 5G followed by connection to 5G DFS network.
430        """
431        self.configure_ap(channel_5g=WIFI_NETWORK_AP_CHANNEL_5G_DFS)
432        self.start_softap_and_connect_to_wifi_network(
433            self.wpapsk_5g, WIFI_CONFIG_APBAND_5G)
434
435    @test_tracker_info(uuid="5e28e8b5-3faa-4cff-a782-13a796d7f572")
436    def test_softap_5G_wifi_connection_2G(self):
437        """Tests bringing up SoftAp on 5G followed by connection to 2G network.
438        """
439        self.configure_ap(channel_2g=WIFI_NETWORK_AP_CHANNEL_2G)
440        self.start_softap_and_connect_to_wifi_network(
441            self.wpapsk_2g, WIFI_CONFIG_APBAND_5G)
442
443    @test_tracker_info(uuid="a2c62bc6-9ccd-4bc4-8a23-9a1b5d0b4b5c")
444    def test_softap_2G_wifi_connection_5G(self):
445        """Tests bringing up SoftAp on 2G followed by connection to 5G network.
446        """
447        self.configure_ap(channel_5g=WIFI_NETWORK_AP_CHANNEL_5G)
448        self.start_softap_and_connect_to_wifi_network(
449            self.wpapsk_5g, WIFI_CONFIG_APBAND_2G)
450
451    @test_tracker_info(uuid="a2c62bc6-9ccd-4bc4-8a23-9a1b5d0b4b5c")
452    def test_softap_2G_wifi_connection_5G_DFS(self):
453        """Tests bringing up SoftAp on 2G followed by connection to 5G DFS network.
454        """
455        self.configure_ap(channel_5g=WIFI_NETWORK_AP_CHANNEL_5G_DFS)
456        self.start_softap_and_connect_to_wifi_network(
457            self.wpapsk_5g, WIFI_CONFIG_APBAND_2G)
458
459    @test_tracker_info(uuid="aa23a3fc-31a1-4d5c-8cf5-2eb9fdf9e7ce")
460    def test_softap_5G_wifi_connection_2G_with_location_scan_on(self):
461        """Tests bringing up SoftAp on 5G followed by connection to 2G network
462        with location scans turned on.
463        """
464        self.configure_ap(channel_2g=WIFI_NETWORK_AP_CHANNEL_2G)
465        self.turn_location_on_and_scan_toggle_on()
466        self.start_softap_and_connect_to_wifi_network(
467            self.wpapsk_2g, WIFI_CONFIG_APBAND_5G)
468        # Now toggle wifi off & ensure we can still scan.
469        wutils.wifi_toggle_state(self.dut, False)
470        wutils.start_wifi_connection_scan_and_ensure_network_found(
471            self.dut, self.wpapsk_2g[WifiEnums.SSID_KEY])
472