1#!/usr/bin/env python3
2#
3#   Copyright 2020 - 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 time
19import re
20import acts.controllers.packet_capture as packet_capture
21import acts.signals as signals
22
23from acts import asserts
24from acts import utils
25from acts.test_decorators import test_tracker_info
26from acts_contrib.test_utils.net import socket_test_utils as sutils
27from acts_contrib.test_utils.tel import tel_defines
28from acts_contrib.test_utils.tel import tel_test_utils as tel_utils
29from acts_contrib.test_utils.tel.tel_wifi_utils import WIFI_CONFIG_APBAND_2G
30from acts_contrib.test_utils.tel.tel_wifi_utils import WIFI_CONFIG_APBAND_5G
31from acts_contrib.test_utils.tel.tel_wifi_utils import WIFI_CONFIG_APBAND_AUTO
32from acts_contrib.test_utils.wifi import wifi_constants
33from acts_contrib.test_utils.wifi import wifi_test_utils as wutils
34from acts_contrib.test_utils.wifi.WifiBaseTest import WifiBaseTest
35from acts.controllers.ap_lib.hostapd_constants import CHANNEL_MAP
36
37WifiEnums = wutils.WifiEnums
38
39
40class WifiSoftApMultiCountryTest(WifiBaseTest):
41    def __init__(self, configs):
42        super().__init__(configs)
43        self.basetest_name = (
44            "test_full_tether_startup_auto_one_client_ping_softap_multicountry",
45            "test_full_tether_startup_2G_one_client_ping_softap_multicountry",
46            "test_full_tether_startup_5G_one_client_ping_softap_multicountry",
47        )
48        self.generate_tests()
49
50    def generate_testcase(self, basetest_name, country):
51        """Generates a single test case from the given data.
52
53        Args:
54            basetest_name: The name of the base test case.
55            country: The information about the country code under test.
56        """
57        base_test = getattr(self, basetest_name)
58        test_tracker_uuid = ""
59        testcase_name = 'test_%s_%s' % (basetest_name, country)
60        test_case = test_tracker_info(
61            uuid=test_tracker_uuid)(lambda: base_test(country))
62        setattr(self, testcase_name, test_case)
63        self.tests.append(testcase_name)
64
65    def generate_tests(self):
66        for country in self.user_params['wifi_country_code']:
67            for basetest_name in self.basetest_name:
68                self.generate_testcase(basetest_name, country)
69
70    def setup_class(self):
71        """It will setup the required dependencies from config file and configure
72           the devices for softap mode testing.
73
74        Returns:
75            True if successfully configured the requirements for testing.
76        """
77        super().setup_class()
78        self.dut = self.android_devices[0]
79        self.dut_client = self.android_devices[1]
80        if hasattr(self, 'packet_capture'):
81            self.packet_capture = self.packet_capture[0]
82
83        self.channel_list_2g = WifiEnums.ALL_2G_FREQUENCIES
84        self.channel_list_5g = WifiEnums.ALL_5G_FREQUENCIES
85        req_params = ["dbs_supported_models"]
86        opt_param = ["open_network"]
87        self.unpack_userparams(req_param_names=req_params,
88                               opt_param_names=opt_param)
89        if "AccessPoint" in self.user_params:
90            self.legacy_configure_ap_and_start()
91        elif "OpenWrtAP" in self.user_params:
92            self.configure_openwrt_ap_and_start(open_network=True)
93        self.open_network = self.open_network[0]["2g"]
94        # Do a simple version of init - mainly just sync the time and enable
95        # verbose logging.  This test will fail if the DUT has a sim and cell
96        # data is disabled.  We would also like to test with phones in less
97        # constrained states (or add variations where we specifically
98        # constrain).
99        utils.require_sl4a((self.dut, self.dut_client))
100        utils.sync_device_time(self.dut)
101        utils.sync_device_time(self.dut_client)
102        # Enable verbose logging on the duts
103        self.dut.droid.wifiEnableVerboseLogging(1)
104        asserts.assert_equal(
105            self.dut.droid.wifiGetVerboseLoggingLevel(), 1,
106            "Failed to enable WiFi verbose logging on the softap dut.")
107        self.dut_client.droid.wifiEnableVerboseLogging(1)
108        asserts.assert_equal(
109            self.dut_client.droid.wifiGetVerboseLoggingLevel(), 1,
110            "Failed to enable WiFi verbose logging on the client dut.")
111        wutils.wifi_toggle_state(self.dut, True)
112        wutils.wifi_toggle_state(self.dut_client, True)
113        self.AP_IFACE = 'wlan0'
114        if self.dut.model in self.dbs_supported_models:
115            self.AP_IFACE = 'wlan1'
116
117    def teardown_class(self):
118        if self.dut.droid.wifiIsApEnabled():
119            wutils.stop_wifi_tethering(self.dut)
120        wutils.reset_wifi(self.dut)
121        wutils.reset_wifi(self.dut_client)
122        if "AccessPoint" in self.user_params:
123            del self.user_params["reference_networks"]
124            del self.user_params["open_network"]
125
126    def teardown_test(self):
127        super().teardown_test()
128        if self.dut.droid.wifiIsApEnabled():
129            wutils.stop_wifi_tethering(self.dut)
130
131    """ Snifferconfig Functions """
132
133    def conf_packet_capture(self, band, channel):
134        """Configure packet capture on necessary channels."""
135        freq_to_chan = wutils.WifiEnums.freq_to_channel[int(channel)]
136        logging.info("Capturing packets from "
137                     "frequency:{}, Channel:{}".format(channel, freq_to_chan))
138        result = self.packet_capture.configure_monitor_mode(band, freq_to_chan)
139        if not result:
140            logging.error("Failed to configure channel "
141                          "for {} band".format(band))
142        self.pcap_procs = wutils.start_pcap(self.packet_capture, band,
143                                            self.test_name)
144        time.sleep(5)
145
146    """ Helper Functions """
147
148    def create_softap_config(self):
149        """Create a softap config with ssid and password."""
150        ap_ssid = "softap_" + utils.rand_ascii_str(8)
151        ap_password = utils.rand_ascii_str(8)
152        self.dut.log.info("softap setup: %s %s", ap_ssid, ap_password)
153        config = {wutils.WifiEnums.SSID_KEY: ap_ssid}
154        config[wutils.WifiEnums.PWD_KEY] = ap_password
155        return config
156
157    def validate_full_tether_startup(self, band=None, test_ping=False):
158        """Test full startup of wifi tethering
159
160        1. Report current state.
161        2. Switch to AP mode.
162        3. verify SoftAP active.
163        4. Shutdown wifi tethering.
164        5. verify back to previous mode.
165        """
166        initial_wifi_state = self.dut.droid.wifiCheckState()
167        self.dut.log.info("current state: %s", initial_wifi_state)
168        config = self.create_softap_config()
169        wutils.start_wifi_tethering(self.dut,
170                                    config[wutils.WifiEnums.SSID_KEY],
171                                    config[wutils.WifiEnums.PWD_KEY],
172                                    band=band)
173
174        if test_ping:
175            self.validate_ping_between_softap_and_client(config)
176
177        wutils.stop_wifi_tethering(self.dut)
178        asserts.assert_false(self.dut.droid.wifiIsApEnabled(),
179                             "SoftAp is still reported as running")
180        if initial_wifi_state:
181            wutils.wait_for_wifi_state(self.dut, True)
182        elif self.dut.droid.wifiCheckState():
183            asserts.fail(
184                "Wifi was disabled before softap and now it is enabled")
185
186    def validate_ping_between_softap_and_client(self, config):
187        """Test ping between softap and its client.
188
189        Connect one android device to the wifi hotspot.
190        Verify they can ping each other.
191
192        Args:
193            config: wifi network config with SSID, password
194        """
195        wutils.wifi_connect(self.dut_client, config, check_connectivity=False)
196        softap_frequency = int(self.get_wlan1_status(self.dut)['freq'])
197        softap_channel = str(CHANNEL_MAP[softap_frequency])
198        n = int(softap_channel)
199        if n in range(len(self.channel_list_2g)):
200            softap_band = '2g'
201        else:
202            softap_band = '5g'
203        self.dut.log.info('softap frequency : {}'.format(softap_frequency))
204        self.dut.log.info('softap channel : {}'.format(softap_channel))
205        self.dut.log.info('softap band : {}'.format(softap_band))
206        if hasattr(self, 'packet_capture'):
207            self.conf_packet_capture(softap_band, softap_frequency)
208        dut_ip = self.dut.droid.connectivityGetIPv4Addresses(self.AP_IFACE)[0]
209        dut_client_ip = self.dut_client.droid.connectivityGetIPv4Addresses(
210            'wlan0')[0]
211
212        self.dut.log.info("Try to ping %s" % dut_client_ip)
213        asserts.assert_true(
214            utils.adb_shell_ping(self.dut,
215                                 count=10,
216                                 dest_ip=dut_client_ip,
217                                 timeout=20),
218            "%s ping %s failed" % (self.dut.serial, dut_client_ip))
219
220        self.dut_client.log.info("Try to ping %s" % dut_ip)
221        asserts.assert_true(
222            utils.adb_shell_ping(self.dut_client,
223                                 count=10,
224                                 dest_ip=dut_ip,
225                                 timeout=20),
226            "%s ping %s failed" % (self.dut_client.serial, dut_ip))
227
228        wutils.stop_wifi_tethering(self.dut)
229
230    def get_wlan1_status(self, dut):
231        """ get wlan1 interface status"""
232        get_wlan1 = 'hostapd_cli status'
233        out_wlan1 = dut.adb.shell(get_wlan1)
234        out_wlan1 = dict(re.findall(r'(\S+)=(".*?"|\S+)', out_wlan1))
235        return out_wlan1
236
237    """ Tests Begin """
238
239    @test_tracker_info(uuid="6ce4fb40-6fa7-452f-ba17-ea3fe47d325d")
240    def test_full_tether_startup_2G_one_client_ping_softap_multicountry(
241            self, country):
242        """(AP) 1 Device can connect to 2G hotspot
243
244        Steps:
245        1. Setting country code for each device
246        2. Turn on DUT's 2G softap
247        3. Client connects to the softap
248        4. Client and DUT ping each other
249        """
250        wutils.set_wifi_country_code(self.dut, country)
251        wutils.set_wifi_country_code(self.dut_client, country)
252        self.validate_full_tether_startup(WIFI_CONFIG_APBAND_2G,
253                                          test_ping=True)
254        if hasattr(self, 'packet_capture'):
255            wutils.stop_pcap(self.packet_capture, self.pcap_procs, False)
256
257    @test_tracker_info(uuid="ae4629e6-08d5-4b51-ac34-6c2485f54df5")
258    def test_full_tether_startup_5G_one_client_ping_softap_multicountry(
259            self, country):
260        """(AP) 1 Device can connect to 2G hotspot
261
262        Steps:
263        1. Setting country code for each device
264        2. Turn on DUT's 5G softap
265        3. Client connects to the softap
266        4. Client and DUT ping each other
267        """
268        wutils.set_wifi_country_code(self.dut, country)
269        wutils.set_wifi_country_code(self.dut_client, country)
270        self.validate_full_tether_startup(WIFI_CONFIG_APBAND_5G,
271                                          test_ping=True)
272        if hasattr(self, 'packet_capture'):
273            wutils.stop_pcap(self.packet_capture, self.pcap_procs, False)
274
275    @test_tracker_info(uuid="84a10203-cb02-433c-92a7-e8aa2348cc02")
276    def test_full_tether_startup_auto_one_client_ping_softap_multicountry(
277            self, country):
278        """(AP) 1 Device can connect to hotspot
279
280        Steps:
281        1.Setting country code for each device
282        2. Turn on DUT's softap
283        3. Client connects to the softap
284        4. Client and DUT ping each other
285        """
286        wutils.set_wifi_country_code(self.dut, country)
287        wutils.set_wifi_country_code(self.dut_client, country)
288        self.validate_full_tether_startup(WIFI_CONFIG_APBAND_AUTO,
289                                          test_ping=True)
290        if hasattr(self, 'packet_capture'):
291            wutils.stop_pcap(self.packet_capture, self.pcap_procs, False)
292
293    """ Tests End """
294
295
296if __name__ == "__main__":
297    pass
298