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
24import acts.test_utils.wifi.wifi_test_utils as wutils
25import acts.utils
26
27from acts import asserts
28from acts.test_decorators import test_tracker_info
29from acts.test_utils.wifi.WifiBaseTest import WifiBaseTest
30
31WifiEnums = wutils.WifiEnums
32# Timeout used for crash recovery.
33RECOVERY_TIMEOUT = 15
34WIFICOND_KILL_SHELL_COMMAND = "killall wificond"
35WIFI_VENDOR_HAL_KILL_SHELL_COMMAND = "killall android.hardware.wifi@1.0-service vendor.google.wifi_ext@1.0-service-vendor"
36SUPPLICANT_KILL_SHELL_COMMAND = "killall wpa_supplicant"
37
38class WifiCrashTest(WifiBaseTest):
39    """Crash Tests for wifi stack.
40
41    Test Bed Requirement:
42    * One Android device
43    * One Wi-Fi network visible to the device.
44    """
45
46    def setup_class(self):
47        super().setup_class()
48
49        self.dut = self.android_devices[0]
50        wutils.wifi_test_device_init(self.dut)
51        req_params = []
52        opt_param = ["reference_networks"]
53        self.unpack_userparams(
54            req_param_names=req_params, opt_param_names=opt_param)
55
56        if "AccessPoint" in self.user_params:
57            self.legacy_configure_ap_and_start()
58
59        asserts.assert_true(
60            len(self.reference_networks) > 0,
61            "Need at least one reference network with psk.")
62        self.network = self.reference_networks[0]["2g"]
63
64    def setup_test(self):
65        self.dut.droid.wakeLockAcquireBright()
66        self.dut.droid.wakeUpNow()
67        wutils.wifi_toggle_state(self.dut, True)
68
69    def teardown_test(self):
70        self.dut.droid.wakeLockRelease()
71        self.dut.droid.goToSleepNow()
72        wutils.reset_wifi(self.dut)
73
74    def on_fail(self, test_name, begin_time):
75        self.dut.take_bug_report(test_name, begin_time)
76        self.dut.cat_adb_log(test_name, begin_time)
77
78    def teardown_class(self):
79        if "AccessPoint" in self.user_params:
80            del self.user_params["reference_networks"]
81
82    """Helper Functions"""
83
84    """Tests"""
85    @test_tracker_info(uuid="b87fd23f-9bfc-406b-a5b2-17ce6be6c780")
86    def test_wifi_framework_crash_reconnect(self):
87        """Connect to a network, crash framework, then ensure
88        we connect back to the previously connected network.
89
90        Steps:
91        1. Connect to a network.
92        2. Restart framework.
93        3. Reconnect to the previous network.
94
95        """
96        wutils.wifi_connect(self.dut, self.network, num_of_tries=3)
97        # Restart framework
98        self.log.info("Crashing framework")
99        self.dut.restart_runtime()
100        # We won't get the disconnect broadcast because framework crashed.
101        # wutils.wait_for_disconnect(self.dut)
102        time.sleep(RECOVERY_TIMEOUT)
103        wifi_info = self.dut.droid.wifiGetConnectionInfo()
104        if wifi_info[WifiEnums.SSID_KEY] != self.network[WifiEnums.SSID_KEY]:
105            raise signals.TestFailure("Device did not connect to the"
106                                      " network after crashing framework.")
107
108    @test_tracker_info(uuid="33f9e4f6-29b8-4116-8f9b-5b13d93b4bcb")
109    def test_wifi_cond_crash_reconnect(self):
110        """Connect to a network, crash wificond, then ensure
111        we connect back to the previously connected network.
112
113        Steps:
114        1. Connect to a network.
115        2. Crash wificond.
116        3. Ensure we get a disconnect.
117        4. Ensure we reconnect to the previous network.
118
119        """
120        wutils.wifi_connect(self.dut, self.network, num_of_tries=3)
121        # Restart wificond
122        self.log.info("Crashing wificond")
123        self.dut.adb.shell(WIFICOND_KILL_SHELL_COMMAND)
124        wutils.wait_for_disconnect(self.dut)
125        time.sleep(RECOVERY_TIMEOUT)
126        wifi_info = self.dut.droid.wifiGetConnectionInfo()
127        if wifi_info[WifiEnums.SSID_KEY] != self.network[WifiEnums.SSID_KEY]:
128            raise signals.TestFailure("Device did not connect to the"
129                                      " network after crashing wificond.")
130
131    @test_tracker_info(uuid="463e3d7b-b0b7-4843-b83b-5613a71ae2ac")
132    def test_wifi_vendorhal_crash_reconnect(self):
133        """Connect to a network, crash wifi HAL, then ensure
134        we connect back to the previously connected network.
135
136        Steps:
137        1. Connect to a network.
138        2. Crash wifi HAL.
139        3. Ensure we get a disconnect.
140        4. Ensure we reconnect to the previous network.
141
142        """
143        wutils.wifi_connect(self.dut, self.network, num_of_tries=3)
144        # Restart wificond
145        self.log.info("Crashing wifi HAL")
146        self.dut.adb.shell(WIFI_VENDOR_HAL_KILL_SHELL_COMMAND)
147        wutils.wait_for_disconnect(self.dut)
148        time.sleep(RECOVERY_TIMEOUT)
149        wifi_info = self.dut.droid.wifiGetConnectionInfo()
150        if wifi_info[WifiEnums.SSID_KEY] != self.network[WifiEnums.SSID_KEY]:
151            raise signals.TestFailure("Device did not connect to the"
152                                      " network after crashing wifi HAL.")
153
154    @test_tracker_info(uuid="7c5cd1fc-8f8d-494c-beaf-4eb61b48917b")
155    def test_wpa_supplicant_crash_reconnect(self):
156        """Connect to a network, crash wpa_supplicant, then ensure
157        we connect back to the previously connected network.
158
159        Steps:
160        1. Connect to a network.
161        2. Crash wpa_supplicant.
162        3. Ensure we get a disconnect.
163        4. Ensure we reconnect to the previous network.
164
165        """
166        wutils.wifi_connect(self.dut, self.network, num_of_tries=3)
167        # Restart wificond
168        self.log.info("Crashing wpa_supplicant")
169        self.dut.adb.shell(SUPPLICANT_KILL_SHELL_COMMAND)
170        wutils.wait_for_disconnect(self.dut)
171        time.sleep(RECOVERY_TIMEOUT)
172        wifi_info = self.dut.droid.wifiGetConnectionInfo()
173        if wifi_info[WifiEnums.SSID_KEY] != self.network[WifiEnums.SSID_KEY]:
174            raise signals.TestFailure("Device did not connect to the"
175                                      " network after crashing wpa_supplicant.")
176