• 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 pprint
18import time
19import re
20
21from acts import asserts
22from acts import base_test
23from acts.controllers.ap_lib import hostapd_constants
24import acts.signals as signals
25from acts.test_decorators import test_tracker_info
26from acts_contrib.test_utils.tel.tel_wifi_utils import WIFI_CONFIG_APBAND_2G
27from acts_contrib.test_utils.tel.tel_wifi_utils import WIFI_CONFIG_APBAND_5G
28import acts_contrib.test_utils.wifi.wifi_test_utils as wutils
29from acts_contrib.test_utils.wifi.WifiBaseTest import WifiBaseTest
30import acts.utils as utils
31import acts_contrib.test_utils.tel.tel_test_utils as tel_utils
32
33
34WifiEnums = wutils.WifiEnums
35WLAN = "wlan0"
36# Channels to configure the AP for various test scenarios.
37WIFI_NETWORK_AP_CHANNEL_2G = 1
38WIFI_NETWORK_AP_CHANNEL_5G = 36
39WIFI_NETWORK_AP_CHANNEL_5G_DFS = 132
40
41
42class WifiStaApConcurrencyTest(WifiBaseTest):
43    """Tests for STA + AP concurrency scenarios.
44
45    Test Bed Requirement:
46    * Two Android devices (For AP)
47    * One Wi-Fi network visible to the device (for STA).
48    """
49
50    def setup_class(self):
51        super().setup_class()
52
53        self.dut = self.android_devices[0]
54        self.dut_client = self.android_devices[1]
55
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.android_devices)
62
63        for ad in self.android_devices:
64            wutils.wifi_test_device_init(ad)
65            utils.sync_device_time(ad)
66            # Set country code explicitly to "US".
67            wutils.set_wifi_country_code(ad, WifiEnums.CountryCode.US)
68            # Enable verbose logging on the duts.
69            ad.droid.wifiEnableVerboseLogging(1)
70
71        req_params = ["dbs_supported_models",
72                      "wifi6_models",
73                      "iperf_server_address",
74                      "iperf_server_port"]
75        self.unpack_userparams(req_param_names=req_params,)
76        asserts.abort_class_if(
77            self.dut.model not in self.dbs_supported_models,
78            "Device %s does not support dual interfaces." % self.dut.model)
79
80    def setup_test(self):
81        super().setup_test()
82        for ad in self.android_devices:
83            ad.droid.wakeLockAcquireBright()
84            ad.droid.wakeUpNow()
85        self.turn_location_off_and_scan_toggle_off()
86
87    def teardown_test(self):
88        super().teardown_test()
89        # Prevent the stop wifi tethering failure to block ap close
90        try:
91            wutils.stop_wifi_tethering(self.dut)
92        except signals.TestFailure:
93            pass
94        for ad in self.android_devices:
95            ad.droid.wakeLockRelease()
96            ad.droid.goToSleepNow()
97            wutils.reset_wifi(ad)
98        self.turn_location_on_and_scan_toggle_on()
99        wutils.wifi_toggle_state(self.dut, True)
100        self.access_points[0].close()
101        if "AccessPoint" in self.user_params:
102            try:
103                del self.user_params["reference_networks"]
104                del self.user_params["open_network"]
105            except KeyError as e:
106                self.log.warn("There is no 'reference_network' or "
107                              "'open_network' to delete")
108
109    ### Helper Functions ###
110
111    def configure_ap(self, hidden=False, channel_2g=None, channel_5g=None):
112        """Configure and bring up AP on required channel.
113
114        Args:
115            channel_2g: The channel number to use for 2GHz network.
116            channel_5g: The channel number to use for 5GHz network.
117
118        """
119        if not channel_2g:
120            channel_2g = hostapd_constants.AP_DEFAULT_CHANNEL_2G
121        if not channel_5g:
122            channel_5g = hostapd_constants.AP_DEFAULT_CHANNEL_5G
123        if "AccessPoint" in self.user_params:
124            self.legacy_configure_ap_and_start(channel_2g=channel_2g,
125                                               channel_5g=channel_5g,
126                                               hidden=hidden)
127        elif "OpenWrtAP" in self.user_params:
128            self.configure_openwrt_ap_and_start(open_network=True,
129                                                channel_2g=channel_2g,
130                                                channel_5g=channel_5g,
131                                                hidden=hidden)
132        self.open_2g = self.open_network[0]["2g"]
133        self.open_5g = self.open_network[0]["5g"]
134
135    def turn_location_on_and_scan_toggle_on(self):
136        """Turns on wifi location scans."""
137        utils.set_location_service(self.dut, True)
138        self.dut.droid.wifiScannerToggleAlwaysAvailable(True)
139        msg = "Failed to turn on location service's scan."
140        asserts.assert_true(self.dut.droid.wifiScannerIsAlwaysAvailable(), msg)
141
142    def turn_location_off_and_scan_toggle_off(self):
143        """Turns off wifi location scans."""
144        utils.set_location_service(self.dut, False)
145        self.dut.droid.wifiScannerToggleAlwaysAvailable(False)
146        msg = "Failed to turn off location service's scan."
147        asserts.assert_false(self.dut.droid.wifiScannerIsAlwaysAvailable(), msg)
148
149    def run_iperf_client(self, params):
150        """Run iperf traffic after connection.
151
152        Args:
153            params: A tuple of network info and AndroidDevice object.
154        """
155        if "iperf_server_address" in self.user_params:
156            wait_time = 5
157            network, ad = params
158            ssid = network[WifiEnums.SSID_KEY]
159            self.log.info("Starting iperf traffic through {}".format(ssid))
160            time.sleep(wait_time)
161            port_arg = "-p {}".format(self.iperf_server_port)
162            success, data = ad.run_iperf_client(self.iperf_server_address,
163                                                port_arg)
164            self.log.debug(pprint.pformat(data))
165            asserts.assert_true(success, "Error occurred in iPerf traffic.")
166
167    def create_softap_config(self):
168        """Create a softap config with ssid and password."""
169        ap_ssid = "softap_" + utils.rand_ascii_str(8)
170        ap_password = utils.rand_ascii_str(8)
171        self.dut.log.info("softap setup: %s %s", ap_ssid, ap_password)
172        config = {wutils.WifiEnums.SSID_KEY: ap_ssid}
173        config[wutils.WifiEnums.PWD_KEY] = ap_password
174        return config
175
176    def start_softap_and_verify(self, band, check_connectivity=True):
177        """Test startup of softap.
178
179        1. Bring up AP mode.
180        2. Verify SoftAP active using the client device.
181
182        Args:
183            band: wifi band to start soft ap on
184            check_connectivity: If set, verify internet connectivity
185
186        Returns:
187            Softap config
188        """
189        config = self.create_softap_config()
190        wutils.start_wifi_tethering(self.dut,
191                                    config[WifiEnums.SSID_KEY],
192                                    config[WifiEnums.PWD_KEY],
193                                    band)
194        for ad in self.android_devices[1:]:
195            wutils.connect_to_wifi_network(
196                ad, config, check_connectivity=check_connectivity)
197            wutils.verify_11ax_softap(self.dut, ad, self.wifi6_models)
198        return config
199
200    def connect_to_wifi_network_and_start_softap(self, nw_params,
201                                                 softap_band,
202                                                 hidden=False):
203        """Test concurrent wifi connection and softap.
204
205        This helper method first makes a wifi connection and then starts SoftAp.
206        1. Bring up wifi.
207        2. Establish connection to a network.
208        3. Bring up softap and verify AP can be connected by a client device.
209        4. Run iperf on the wifi/softap connection to the network.
210
211        Args:
212            nw_params: Params for network STA connection.
213            softap_band: Band for the AP.
214        """
215        wutils.connect_to_wifi_network(self.dut, nw_params, hidden=hidden)
216        wutils.verify_11ax_wifi_connection(
217            self.dut, self.wifi6_models, "wifi6_ap" in self.user_params)
218        softap_config = self.start_softap_and_verify(softap_band)
219        self.run_iperf_client((nw_params, self.dut))
220        self.run_iperf_client((softap_config, self.dut_client))
221
222        if len(self.android_devices) > 2:
223            self.log.info("Testbed has extra devices, do more validation")
224            self.verify_traffic_between_dut_clients(
225                self.dut_client, self.android_devices[2])
226
227        asserts.assert_true(self.dut.droid.wifiCheckState(),
228                            "Wifi is not reported as running")
229        asserts.assert_true(self.dut.droid.wifiIsApEnabled(),
230                            "SoftAp is not reported as running")
231
232    def start_softap_and_connect_to_wifi_network(
233            self, nw_params, softap_band,
234            num_of_scan_tries=wutils.DEFAULT_SCAN_TRIES):
235        """Test concurrent wifi connection and softap.
236
237        This helper method first starts SoftAp and then makes a wifi connection.
238        1. Bring up softap and verify AP can be connected by a client device.
239        2. Bring up wifi.
240        3. Establish connection to a network.
241        4. Run iperf on the wifi/softap connection to the network.
242        5. Verify wifi state and softap state.
243
244        Args:
245            nw_params: Params for network STA connection.
246            softap_band: Band for the AP.
247            num_of_scan_tries: Number of tries to connect to wifi network
248        """
249        softap_config = self.start_softap_and_verify(softap_band, False)
250        wutils.connect_to_wifi_network(
251            self.dut, nw_params, num_of_scan_tries=num_of_scan_tries)
252        wutils.verify_11ax_wifi_connection(
253            self.dut, self.wifi6_models, "wifi6_ap" in self.user_params)
254        self.run_iperf_client((nw_params, self.dut))
255        self.run_iperf_client((softap_config, self.dut_client))
256
257        if len(self.android_devices) > 2:
258            self.log.info("Testbed has extra devices, do more validation")
259            self.verify_traffic_between_dut_clients(
260                self.dut, self.android_devices[2])
261
262        asserts.assert_true(self.dut.droid.wifiCheckState(),
263                            "Wifi is not reported as running")
264        asserts.assert_true(self.dut.droid.wifiIsApEnabled(),
265                            "SoftAp is not reported as running")
266
267    def verify_traffic_between_dut_clients(self, ad1, ad2, num_of_tries=2):
268        """Test the clients that connect to DUT's softap can ping each other.
269
270        Args:
271            ad1: DUT 1
272            ad2: DUT 2
273            num_of_tries: the retry times of ping test.
274        """
275        ad1_ip = ad1.droid.connectivityGetIPv4Addresses(WLAN)[0]
276        ad2_ip = ad2.droid.connectivityGetIPv4Addresses(WLAN)[0]
277        # Ping each other
278        for _ in range(num_of_tries):
279            if utils.adb_shell_ping(ad1, count=10, dest_ip=ad2_ip, timeout=20):
280                break
281        else:
282            asserts.fail("%s ping %s failed" % (ad1.serial, ad2_ip))
283        for _ in range(num_of_tries):
284            if utils.adb_shell_ping(ad2, count=10, dest_ip=ad1_ip, timeout=20):
285                break
286        else:
287            asserts.fail("%s ping %s failed" % (ad2.serial, ad1_ip))
288
289    def softap_change_band(self, ad):
290        """
291        Switch DUT SoftAp to 5G band if currently in 2G.
292        Switch DUT SoftAp to 2G band if currently in 5G.
293        """
294        wlan1_freq = int(self.get_wlan1_status(self.dut)['freq'])
295        if wlan1_freq in wutils.WifiEnums.ALL_5G_FREQUENCIES:
296            band = WIFI_CONFIG_APBAND_2G
297        elif wlan1_freq in wutils.WifiEnums.ALL_2G_FREQUENCIES:
298            band = WIFI_CONFIG_APBAND_5G
299        wutils.stop_wifi_tethering(ad)
300        self.start_softap_and_verify(band)
301
302    def get_wlan1_status(self, ad):
303        """ get wlan1 interface status"""
304        get_wlan1 = 'hostapd_cli status'
305        out_wlan1 = ad.adb.shell(get_wlan1)
306        out_wlan1 = dict(re.findall(r'(\S+)=(".*?"|\S+)', out_wlan1))
307        return out_wlan1
308
309    def enable_mobile_data(self, ad):
310        """Make sure that cell data is enabled if there is a sim present."""
311        init_sim_state = tel_utils.is_sim_ready(self.log, ad)
312        if init_sim_state:
313            if not ad.droid.telephonyIsDataEnabled():
314                ad.droid.telephonyToggleDataConnection(True)
315            asserts.assert_true(ad.droid.telephonyIsDataEnabled(),
316                                "Failed to enable Mobile Data")
317        else:
318            raise signals.TestSkip("Please insert sim card with "
319                                   "Mobile Data enabled before test")
320
321    ### Tests ###
322
323    @test_tracker_info(uuid="c396e7ac-cf22-4736-a623-aa6d3c50193a")
324    def test_wifi_connection_2G_softap_2G(self):
325        """Test connection to 2G network followed by SoftAp on 2G."""
326        self.configure_ap(channel_2g=WIFI_NETWORK_AP_CHANNEL_2G)
327        self.connect_to_wifi_network_and_start_softap(
328            self.open_2g, WIFI_CONFIG_APBAND_2G)
329
330    @test_tracker_info(uuid="1cd6120d-3db4-4624-9bae-55c976533a48")
331    def test_wifi_connection_5G_softap_5G(self):
332        """Test connection to 5G network followed by SoftAp on 5G."""
333        self.configure_ap(channel_5g=WIFI_NETWORK_AP_CHANNEL_5G)
334        self.connect_to_wifi_network_and_start_softap(
335            self.open_5g, WIFI_CONFIG_APBAND_5G)
336
337    @test_tracker_info(uuid="5f980007-3490-413e-b94e-7700ffab8534")
338    def test_wifi_connection_5G_DFS_softap_5G(self):
339        """Test connection to 5G DFS network followed by SoftAp on 5G."""
340        self.configure_ap(channel_5g=WIFI_NETWORK_AP_CHANNEL_5G_DFS)
341        self.connect_to_wifi_network_and_start_softap(
342            self.open_5g, WIFI_CONFIG_APBAND_5G)
343
344    @test_tracker_info(uuid="d05d5d44-c738-4372-9f01-ce2a640a2f25")
345    def test_wifi_connection_5G_softap_2G(self):
346        """Test connection to 5G network followed by SoftAp on 2G."""
347        self.configure_ap(channel_5g=WIFI_NETWORK_AP_CHANNEL_5G)
348        self.connect_to_wifi_network_and_start_softap(
349            self.open_5g, WIFI_CONFIG_APBAND_2G)
350
351    @test_tracker_info(uuid="909ac713-1ad3-4dad-9be3-ad60f00ed25e")
352    def test_wifi_connection_5G_DFS_softap_2G(self):
353        """Test connection to 5G DFS network followed by SoftAp on 2G."""
354        self.configure_ap(channel_5g=WIFI_NETWORK_AP_CHANNEL_5G_DFS)
355        self.connect_to_wifi_network_and_start_softap(
356            self.open_5g, WIFI_CONFIG_APBAND_2G)
357
358    @test_tracker_info(uuid="e8de724a-25d3-4801-94cc-22e9e0ecc8d1")
359    def test_wifi_connection_2G_softap_5G(self):
360        """Test connection to 2G network followed by SoftAp on 5G."""
361        self.configure_ap(channel_2g=WIFI_NETWORK_AP_CHANNEL_2G)
362        self.connect_to_wifi_network_and_start_softap(
363            self.open_2g, WIFI_CONFIG_APBAND_5G)
364
365    @test_tracker_info(uuid="647f4e17-5c7a-4249-98af-f791d163a39f")
366    def test_wifi_connection_5G_softap_2G_with_location_scan_on(self):
367        """Test connection to 5G network, SoftAp on 2G with location scan on."""
368        self.configure_ap(channel_5g=WIFI_NETWORK_AP_CHANNEL_5G)
369        self.turn_location_on_and_scan_toggle_on()
370        self.connect_to_wifi_network_and_start_softap(
371            self.open_5g, WIFI_CONFIG_APBAND_2G)
372        # Now toggle wifi off & ensure we can still scan.
373        wutils.wifi_toggle_state(self.dut, False)
374        wutils.start_wifi_connection_scan_and_ensure_network_found(
375            self.dut, self.open_5g[WifiEnums.SSID_KEY])
376
377    @test_tracker_info(uuid="4aa56c11-e5bc-480b-bd61-4b4ee577a5da")
378    def test_softap_2G_wifi_connection_2G(self):
379        """Test SoftAp on 2G followed by connection to 2G network."""
380        self.configure_ap(channel_2g=WIFI_NETWORK_AP_CHANNEL_2G)
381        self.start_softap_and_connect_to_wifi_network(
382            self.open_2g, WIFI_CONFIG_APBAND_2G)
383
384    @test_tracker_info(uuid="5f954957-ad20-4de1-b20c-6c97d0463bdd")
385    def test_softap_5G_wifi_connection_5G(self):
386        """Test SoftAp on 5G followed by connection to 5G network."""
387        self.configure_ap(channel_5g=WIFI_NETWORK_AP_CHANNEL_5G)
388        self.start_softap_and_connect_to_wifi_network(
389            self.open_5g, WIFI_CONFIG_APBAND_5G)
390
391    @test_tracker_info(uuid="1306aafc-a07e-4654-ba78-674f90cf748e")
392    def test_softap_5G_wifi_connection_5G_DFS(self):
393        """Test SoftAp on 5G followed by connection to 5G DFS network."""
394        self.configure_ap(channel_5g=WIFI_NETWORK_AP_CHANNEL_5G_DFS)
395        # Set scan tries to 10 to fit the 32ms limitation.
396        # SoftAp uses CTS2SELF frame to go offchannel for scan, and max duration
397        # we can set in CTS2SELF frame is 32ms.
398        # Since DUT SAP is enabled and clients are connect to the SAP, firmware
399        # is allocating only 28ms for passive scan in DFS channel for offchannel
400        # scan operation. We need to increase scan tries to get beacons from AP.
401        self.start_softap_and_connect_to_wifi_network(
402            self.open_5g, WIFI_CONFIG_APBAND_5G, num_of_scan_tries=10)
403
404    @test_tracker_info(uuid="5e28e8b5-3faa-4cff-a782-13a796d7f572")
405    def test_softap_5G_wifi_connection_2G(self):
406        """Test SoftAp on 5G followed by connection to 2G network."""
407        self.configure_ap(channel_2g=WIFI_NETWORK_AP_CHANNEL_2G)
408        self.start_softap_and_connect_to_wifi_network(
409            self.open_2g, WIFI_CONFIG_APBAND_5G)
410
411    @test_tracker_info(uuid="a2c62bc6-9ccd-4bc4-8a23-9a1b5d0b4b5c")
412    def test_softap_2G_wifi_connection_5G(self):
413        """Test SoftAp on 2G followed by connection to 5G network."""
414        self.configure_ap(channel_5g=WIFI_NETWORK_AP_CHANNEL_5G)
415        self.start_softap_and_connect_to_wifi_network(
416            self.open_5g, WIFI_CONFIG_APBAND_2G)
417
418    @test_tracker_info(uuid="75400685-a9d9-4091-8af3-97bd539c246a")
419    def test_softap_2G_wifi_connection_5G_DFS(self):
420        """Test SoftAp on 2G followed by connection to 5G DFS network."""
421        self.configure_ap(channel_5g=WIFI_NETWORK_AP_CHANNEL_5G_DFS)
422        self.start_softap_and_connect_to_wifi_network(
423            self.open_5g, WIFI_CONFIG_APBAND_2G)
424
425    @test_tracker_info(uuid="aa23a3fc-31a1-4d5c-8cf5-2eb9fdf9e7ce")
426    def test_softap_5G_wifi_connection_2G_with_location_scan_on(self):
427        """Test SoftAp on 5G, connection to 2G network with location scan on."""
428        self.configure_ap(channel_2g=WIFI_NETWORK_AP_CHANNEL_2G)
429        self.turn_location_on_and_scan_toggle_on()
430        self.start_softap_and_connect_to_wifi_network(
431            self.open_2g, WIFI_CONFIG_APBAND_5G)
432        # Now toggle wifi off & ensure we can still scan.
433        wutils.wifi_toggle_state(self.dut, False)
434        wutils.start_wifi_connection_scan_and_ensure_network_found(
435            self.dut, self.open_2g[WifiEnums.SSID_KEY])
436
437    @test_tracker_info(uuid="9decb951-4500-4476-8161-f4054760f709")
438    def test_wifi_connection_2G_softap_2G_to_softap_5g(self):
439        """Test connection to 2G network followed by SoftAp on 2G,
440        and switch SoftAp to 5G."""
441        self.configure_ap(channel_2g=WIFI_NETWORK_AP_CHANNEL_2G)
442        self.connect_to_wifi_network_and_start_softap(
443            self.open_2g, WIFI_CONFIG_APBAND_2G)
444        self.softap_change_band(self.dut)
445
446    @test_tracker_info(uuid="e17e0fb8-2c1d-4f3c-af2a-7374485f210c")
447    def test_wifi_connection_5G_softap_2G_to_softap_5g(self):
448        """Test connection to 5G network followed by SoftAp on 2G,
449        and switch SoftAp to 5G."""
450        self.configure_ap(channel_5g=WIFI_NETWORK_AP_CHANNEL_5G)
451        self.connect_to_wifi_network_and_start_softap(
452            self.open_2g, WIFI_CONFIG_APBAND_2G)
453        self.softap_change_band(self.dut)
454
455    @test_tracker_info(uuid="d549a18e-73d9-45e7-b4df-b59446c4b833")
456    def test_wifi_connection_hidden_2g_softap_2G_to_softap_5g(self):
457        """Test connection to a hidden 2G network on Channel 1 and
458        followed by SoftAp on 2G, and switch SoftAp to 5G.
459        1. Connect to a hidden 2.4G Wi-Fi AP(channel 1)
460        2. DUT turn on 2.4G hotspot and client connect to DUT
461        3. Change AP Band of DUT Hotspot from 2.4GHz to 5GHz
462        Expected results: Both DUT and Hotspot client can access the Internet
463        """
464        self.configure_ap(channel_2g=WIFI_NETWORK_AP_CHANNEL_2G, hidden=True)
465        self.connect_to_wifi_network_and_start_softap(
466            self.open_2g,
467            WIFI_CONFIG_APBAND_2G,
468            hidden=True)
469        self.softap_change_band(self.dut)
470