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 time
18import acts.signals as signals
19import acts.test_utils.wifi.wifi_test_utils as wutils
20from acts import asserts
21from acts import utils
22from acts.test_decorators import test_tracker_info
23from acts.test_utils.wifi.WifiBaseTest import WifiBaseTest
24from acts.test_utils.tel.tel_test_utils import disable_qxdm_logger
25
26WifiEnums = wutils.WifiEnums
27
28class WifiCrashStressTest(WifiBaseTest):
29    """Crash Tests for wifi stack.
30
31    Test Bed Requirement:
32    * Two Android device
33    * One Wi-Fi network visible to the device.
34    """
35
36    def setup_class(self):
37        super().setup_class()
38
39        self.dut = self.android_devices[0]
40        self.dut_client = self.android_devices[1]
41        wutils.wifi_test_device_init(self.dut)
42        wutils.wifi_test_device_init(self.dut_client)
43        if not self.dut.is_apk_installed("com.google.mdstest"):
44            raise signals.TestAbortClass("mdstest is not installed")
45        req_params = ["dbs_supported_models", "stress_count"]
46        opt_param = ["reference_networks"]
47        self.unpack_userparams(
48            req_param_names=req_params, opt_param_names=opt_param)
49
50        if "AccessPoint" in self.user_params:
51            self.legacy_configure_ap_and_start()
52
53        asserts.assert_true(
54            len(self.reference_networks) > 0,
55            "Need at least one reference network with psk.")
56        self.network = self.reference_networks[0]["2g"]
57        self.ap_iface = 'wlan0'
58        if self.dut.model in self.dbs_supported_models:
59            self.ap_iface = 'wlan1'
60
61    def setup_test(self):
62        self.dut.droid.wakeLockAcquireBright()
63        self.dut.droid.wakeUpNow()
64        wutils.wifi_toggle_state(self.dut, True)
65        self.dut_client.droid.wakeLockAcquireBright()
66        self.dut_client.droid.wakeUpNow()
67        wutils.wifi_toggle_state(self.dut_client, True)
68
69    def teardown_test(self):
70        if self.dut.droid.wifiIsApEnabled():
71            wutils.stop_wifi_tethering(self.dut)
72        self.dut.droid.wakeLockRelease()
73        self.dut.droid.goToSleepNow()
74        wutils.reset_wifi(self.dut)
75        self.dut_client.droid.wakeLockRelease()
76        self.dut_client.droid.goToSleepNow()
77        wutils.reset_wifi(self.dut_client)
78
79    def on_fail(self, test_name, begin_time):
80        self.dut.take_bug_report(test_name, begin_time)
81        self.dut.cat_adb_log(test_name, begin_time)
82        self.dut_client.take_bug_report(test_name, begin_time)
83        self.dut_client.cat_adb_log(test_name, begin_time)
84
85    def teardown_class(self):
86        if "AccessPoint" in self.user_params:
87            del self.user_params["reference_networks"]
88
89    """Helper Functions"""
90    def trigger_wifi_firmware_crash(self, ad, timeout=15):
91        pre_timestamp = ad.adb.getprop("vendor.debug.ssrdump.timestamp")
92        ad.adb.shell(
93            "setprop persist.vendor.sys.modem.diag.mdlog false", ignore_status=True)
94        # Legacy pixels use persist.sys.modem.diag.mdlog.
95        ad.adb.shell(
96            "setprop persist.sys.modem.diag.mdlog false", ignore_status=True)
97        disable_qxdm_logger(ad)
98        cmd = ('am instrument -w -e request "4b 25 03 b0 00" '
99               '"com.google.mdstest/com.google.mdstest.instrument.'
100               'ModemCommandInstrumentation"')
101        ad.log.info("Crash wifi firmware by %s", cmd)
102        ad.adb.shell(cmd, ignore_status=True)
103        time.sleep(timeout)  # sleep time for firmware restart
104        subsystem = ad.adb.getprop("vendor.debug.ssrdump.subsys")
105        timestamp = ad.adb.getprop("vendor.debug.ssrdump.timestamp")
106        asserts.assert_true(timestamp != pre_timestamp,
107            "SSR didn't happened %s %s" % (subsystem, timestamp))
108
109    """Tests"""
110    @test_tracker_info(uuid="b5a982ef-10ef-4f36-a1b5-1e5d1fec06a4")
111    def test_firmware_crash_wifi_reconnect_stress(self):
112        """Firmware crash stress test for station mode
113
114        1. Turn on Wi-Fi and connect to access point
115        2. Trigger firmware crash
116        3. Check ssr happened
117        4. Check dut can connect to access point
118        5. Repeat step 2~4
119        """
120        wutils.wifi_toggle_state(self.dut, True)
121        wutils.connect_to_wifi_network(self.dut, self.network)
122        for count in range(self.stress_count):
123            self.log.info("%s: %d/%d" %
124                (self.current_test_name, count + 1, self.stress_count))
125            wutils.reset_wifi(self.dut)
126            self.trigger_wifi_firmware_crash(self.dut)
127            wutils.connect_to_wifi_network(self.dut, self.network)
128
129    @test_tracker_info(uuid="204a921b-b0de-47f7-9b70-9384317051c8")
130    def test_firmware_crash_softap_reconnect_stress(self):
131        """Firmware crash stress test for softap mode
132
133        1. Turn off dut's Wi-Fi
134        2. Turn on dut's hotspot and connected by dut client
135        3. Trigger firmware crash
136        4. Check ssr happened
137        5. Check the connectivity of hotspot's client
138        6. Repeat step 3~5
139        """
140        wutils.wifi_toggle_state(self.dut, False)
141        # Setup Soft AP
142        sap_config = wutils.create_softap_config()
143        wutils.start_wifi_tethering(
144            self.dut, sap_config[wutils.WifiEnums.SSID_KEY],
145            sap_config[wutils.WifiEnums.PWD_KEY], wutils.WifiEnums.WIFI_CONFIG_APBAND_2G)
146        config = {
147            "SSID": sap_config[wutils.WifiEnums.SSID_KEY],
148            "password": sap_config[wutils.WifiEnums.PWD_KEY]
149        }
150        # DUT client connects to softap
151        wutils.wifi_toggle_state(self.dut_client, True)
152        wutils.connect_to_wifi_network(self.dut_client, config, check_connectivity=False)
153        # Ping the DUT
154        dut_addr = self.dut.droid.connectivityGetIPv4Addresses(
155                self.ap_iface)[0]
156        asserts.assert_true(
157            utils.adb_shell_ping(self.dut_client, count=10, dest_ip=dut_addr, timeout=20),
158            "%s ping %s failed" % (self.dut_client.serial, dut_addr))
159        for count in range(self.stress_count):
160            self.log.info("%s: %d/%d" %
161                (self.current_test_name, count + 1, self.stress_count))
162            wutils.reset_wifi(self.dut_client)
163            # Trigger firmware crash
164            self.trigger_wifi_firmware_crash(self.dut)
165            # Connect DUT to Network
166            wutils.connect_to_wifi_network(self.dut_client, config, check_connectivity=False)
167            # Ping the DUT
168            server_addr = self.dut.droid.connectivityGetIPv4Addresses(
169                    self.ap_iface)[0]
170            asserts.assert_true(
171                utils.adb_shell_ping(
172                        self.dut_client,
173                        count=10,
174                        dest_ip=server_addr,
175                        timeout=20),
176                "%s ping %s failed" % (self.dut_client.serial, server_addr))
177        wutils.stop_wifi_tethering(self.dut)
178
179    @test_tracker_info(uuid="4b7f2d89-82be-41de-9277-e938cc1c318b")
180    def test_firmware_crash_concurrent_reconnect_stress(self):
181        """Firmware crash stress test for concurrent mode
182
183        1. Turn on dut's Wi-Fi and connect to access point
184        2. Turn on dut's hotspot and connected by dut client
185        3. Trigger firmware crash
186        4. Check ssr happened
187        5. Check dut can connect to access point
188        6. Check the connectivity of hotspot's client
189        7. Repeat step 3~6
190        """
191        if self.dut.model not in self.dbs_supported_models:
192            raise signals.TestSkip("%s does not support dual interfaces" % self.dut.model)
193
194        # Connect DUT to Network
195        wutils.wifi_toggle_state(self.dut, True)
196        wutils.connect_to_wifi_network(self.dut, self.network)
197        # Setup Soft AP
198        sap_config = wutils.create_softap_config()
199        wutils.start_wifi_tethering(
200            self.dut, sap_config[wutils.WifiEnums.SSID_KEY],
201            sap_config[wutils.WifiEnums.PWD_KEY], wutils.WifiEnums.WIFI_CONFIG_APBAND_2G)
202        config = {
203            "SSID": sap_config[wutils.WifiEnums.SSID_KEY],
204            "password": sap_config[wutils.WifiEnums.PWD_KEY]
205        }
206        # Client connects to Softap
207        wutils.wifi_toggle_state(self.dut_client, True)
208        wutils.connect_to_wifi_network(self.dut_client, config)
209        for count in range(self.stress_count):
210            self.log.info("%s: %d/%d" %
211                (self.current_test_name, count + 1, self.stress_count))
212            wutils.reset_wifi(self.dut_client)
213            wutils.reset_wifi(self.dut)
214            # Trigger firmware crash
215            self.trigger_wifi_firmware_crash(self.dut)
216            wutils.connect_to_wifi_network(self.dut, self.network)
217            wutils.connect_to_wifi_network(self.dut_client, config)
218        wutils.stop_wifi_tethering(self.dut)
219