blob: 13c6b2dc0b8e7bad0b3347f0eadc7d1015620723 [file] [log] [blame]
Jaineel7e67a3f2019-08-28 15:58:49 -07001#!/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 queue
19
20from acts import asserts
21from acts.controllers.android_device import SL4A_APK_NAME
22from acts.test_decorators import test_tracker_info
23from acts.test_utils.wifi.WifiBaseTest import WifiBaseTest
24import acts.test_utils.wifi.wifi_test_utils as wutils
25import acts.utils
26
27CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT = 5
28LAST_DISCONNECT_TIMEOUT_MILLIS = 5000
29LAST_DISCONNECT_TIMEOUT_SEC = LAST_DISCONNECT_TIMEOUT_MILLIS / 1000
30PRESCAN_DELAY_SEC = 5
31
32
33class WifiWakeTest(WifiBaseTest):
34 """
35 Tests Wifi Wake.
36
37 Test Bed Requirements:
38 * One Android Device
39 * Two APs that can be turned on and off
40 """
41
Jaineel7e67a3f2019-08-28 15:58:49 -070042 def setup_class(self):
Xianyuan Jia168103b2019-09-06 12:22:52 -070043 super().setup_class()
44
Jaineel7e67a3f2019-08-28 15:58:49 -070045 self.dut = self.android_devices[0]
46 wutils.wifi_test_device_init(self.dut)
47 # turn location back on
48 acts.utils.set_location_service(self.dut, True)
49 self.dut.droid.wifiScannerToggleAlwaysAvailable(True)
50
51 self.unpack_userparams(req_param_names=[],
52 opt_param_names=["reference_networks"])
53
54 if "AccessPoint" in self.user_params:
55 self.legacy_configure_ap_and_start(mirror_ap=False, ap_count=2)
56
57 # use 2G since Wifi Wake does not work if an AP is on a 5G DFS channel
58 self.ap_a = self.reference_networks[0]["2g"]
59 self.ap_b = self.reference_networks[1]["2g"]
60
61 self.ap_a_atten = self.attenuators[0]
62 self.ap_b_atten = self.attenuators[2]
63
64 # TODO(b/119040540): this method of disabling/re-enabling Wifi on APs is
65 # hacky, switch to using public methods when they are implemented
66 def ap_a_off(self):
67 ap_a_hostapd = self.access_points[0]._aps['wlan0'].hostapd
68 if ap_a_hostapd.is_alive():
69 ap_a_hostapd.stop()
70 self.log.info('Turned AP A off')
71
72 def ap_a_on(self):
73 ap_a_hostapd = self.access_points[0]._aps['wlan0'].hostapd
74 if not ap_a_hostapd.is_alive():
75 ap_a_hostapd.start(ap_a_hostapd.config)
76 self.log.info('Turned AP A on')
77
78 def ap_b_off(self):
79 ap_b_hostapd = self.access_points[1]._aps['wlan0'].hostapd
80 if ap_b_hostapd.is_alive():
81 ap_b_hostapd.stop()
82 self.log.info('Turned AP B off')
83
84 def ap_b_on(self):
85 ap_b_hostapd = self.access_points[1]._aps['wlan0'].hostapd
86 if not ap_b_hostapd.is_alive():
87 ap_b_hostapd.start(ap_b_hostapd.config)
88 self.log.info('Turned AP B on')
89
90 def setup_test(self):
91 self.dut.droid.wakeLockAcquireBright()
92 self.dut.droid.wakeUpNow()
93 self.ap_a_on()
94 self.ap_b_on()
95 self.ap_a_atten.set_atten(0)
96 self.ap_b_atten.set_atten(0)
97 wutils.reset_wifi(self.dut)
98 wutils.wifi_toggle_state(self.dut, new_state=True)
99 # clear events from event dispatcher
100 self.dut.droid.wifiStartTrackingStateChange()
101 self.dut.droid.wifiStopTrackingStateChange()
102 self.dut.ed.clear_all_events()
103
104 def teardown_test(self):
105 self.dut.droid.wakeLockRelease()
106 self.dut.droid.goToSleepNow()
107
108 def on_fail(self, test_name, begin_time):
109 self.dut.take_bug_report(test_name, begin_time)
110 self.dut.cat_adb_log(test_name, begin_time)
111
112 def do_location_scan(self, num_times=1):
113 scan_settings = {
114 "band": wutils.WifiEnums.WIFI_BAND_BOTH,
115 "periodInMs": 0,
116 "reportEvents": wutils.WifiEnums.REPORT_EVENT_AFTER_EACH_SCAN
117 }
118
119 wifi_chs = wutils.WifiChannelUS(self.dut.model)
120 stime_channel = 47 # dwell time plus 2ms
121 leeway = 10
122
123 for i in range(num_times):
124 self.log.info("Scan count: {}".format(i))
125 data = wutils.start_wifi_single_scan(self.dut, scan_settings)
126 idx = data["Index"]
127 scan_rt = data["ScanElapsedRealtime"]
128 self.log.debug(
129 "Wifi single shot scan started index: %s at real time: %s", idx,
130 scan_rt)
131 # generating event wait time from scan setting plus leeway
132 scan_time, scan_channels = wutils.get_scan_time_and_channels(
133 wifi_chs, scan_settings, stime_channel)
134 wait_time = int(scan_time / 1000) + leeway
135 # track number of result received
136 result_received = 0
137 try:
138 for _ in range(1, 3):
139 event_name = "{}{}onResults".format("WifiScannerScan", idx)
140 self.log.debug("Waiting for event: %s for time %s",
141 event_name, wait_time)
142 event = self.dut.ed.pop_event(event_name, wait_time)
143 self.log.debug("Event received: %s", event)
144 result_received += 1
145 except queue.Empty as error:
146 asserts.assert_true(
147 result_received >= 1,
148 "Event did not triggered for single shot {}".format(error))
149 finally:
150 self.dut.droid.wifiScannerStopScan(idx)
151 # For single shot number of result received and length of result
152 # should be one
153 asserts.assert_true(
154 result_received == 1,
155 "Test fail because received result {}".format(
156 result_received))
157
158 @test_tracker_info(uuid="372b9b74-4241-46ce-8f18-e6a97d3a3452")
159 def test_no_reconnect_manual_disable_wifi(self):
160 """
161 Tests that Wifi Wake does not reconnect to a network if the user turned
162 off Wifi while connected to that network and the user has not moved
163 (i.e. moved out of range of the AP then came back).
164 """
165 wutils.wifi_connect(self.dut, self.ap_a, num_of_tries=5)
166 wutils.wifi_toggle_state(self.dut, new_state=False)
167 time.sleep(PRESCAN_DELAY_SEC)
168 self.do_location_scan(
169 2 * CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT + 2)
170 asserts.assert_false(
171 self.dut.droid.wifiCheckState(),
172 "Expect Wifi Wake to not enable Wifi, but Wifi was enabled.")
173
174 @test_tracker_info(uuid="ec7a54a5-f293-43f5-a1dd-d41679aa1825")
175 def test_reconnect_wifi_saved_network(self):
176 """Tests that Wifi Wake re-enables Wifi for a saved network."""
177 wutils.wifi_connect(self.dut, self.ap_a, num_of_tries=5)
178 wutils.wifi_connect(self.dut, self.ap_b, num_of_tries=5)
179 self.dut.ed.clear_all_events()
180 self.ap_a_off()
181 self.ap_b_off()
182 wutils.wait_for_disconnect(self.dut)
183 self.log.info("Wifi Disconnected")
184 time.sleep(LAST_DISCONNECT_TIMEOUT_SEC * 1.2)
185 wutils.wifi_toggle_state(self.dut, new_state=False)
186 time.sleep(PRESCAN_DELAY_SEC)
187 self.do_location_scan(CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT + 2)
188
189 self.ap_a_on()
190 self.do_location_scan()
191 asserts.assert_true(
192 self.dut.droid.wifiCheckState(),
193 "Expect Wifi Wake to enable Wifi, but Wifi is disabled.")
194
195 @test_tracker_info(uuid="")
196 def test_reconnect_wifi_network_suggestion(self):
197 """Tests that Wifi Wake re-enables Wifi for app provided suggestion."""
198 self.dut.log.info("Adding network suggestions");
199 asserts.assert_true(
200 self.dut.droid.wifiAddNetworkSuggestions([self.ap_a]),
201 "Failed to add suggestions")
202 asserts.assert_true(
203 self.dut.droid.wifiAddNetworkSuggestions([self.ap_b]),
204 "Failed to add suggestions")
205 # Enable suggestions by the app.
206 self.dut.log.debug("Enabling suggestions from test");
207 self.dut.adb.shell("cmd wifi network-suggestions-set-user-approved"
208 + " " + SL4A_APK_NAME + " yes")
209 # Ensure network is seen in scan results & auto-connected to.
210 self.do_location_scan(2)
211 wutils.wait_for_connect(self.dut)
212 self.dut.ed.clear_all_events()
213 self.ap_a_off()
214 self.ap_b_off()
215 wutils.wait_for_disconnect(self.dut)
216 self.log.info("Wifi Disconnected")
217 time.sleep(LAST_DISCONNECT_TIMEOUT_SEC * 1.2)
218 wutils.wifi_toggle_state(self.dut, new_state=False)
219 time.sleep(PRESCAN_DELAY_SEC)
220 self.do_location_scan(CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT + 2)
221
222 self.ap_a_on()
223 self.do_location_scan()
224 asserts.assert_true(
225 self.dut.droid.wifiCheckState(),
226 "Expect Wifi Wake to enable Wifi, but Wifi is disabled.")
227
228 @test_tracker_info(uuid="6c77ca9b-ff34-4bc7-895f-cc7340e0e645")
229 def test_reconnect_wifi_move_back_in_range(self):
230 """
231 Tests that Wifi Wake re-enables Wifi if the device moves out of range of
232 the AP then came back.
233 """
234 wutils.wifi_connect(self.dut, self.ap_a, num_of_tries=5)
235 wutils.wifi_toggle_state(self.dut, new_state=False)
236 time.sleep(PRESCAN_DELAY_SEC)
237 # init Wakeup Lock with AP A
238 self.do_location_scan(CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT + 2)
239 self.ap_a_off()
240 # evict AP A from Wakeup Lock
241 self.do_location_scan(CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT + 2)
242 self.ap_a_on()
243 self.do_location_scan()
244 asserts.assert_true(
245 self.dut.droid.wifiCheckState(),
246 "Expect Wifi Wake to enable Wifi, but Wifi is disabled.")
247
248 @test_tracker_info(uuid="08e8284a-a523-48f3-b9ea-9c6bf27d711e")
249 def test_no_reconnect_to_flaky_ap(self):
250 """
251 Tests that Wifi Wake does not reconnect to flaky networks.
252 If a network sporadically connects and disconnects, and the user turns
253 off Wifi even during the disconnected phase, Wifi Wake should not
254 re-enable Wifi for that network.
255 """
256 wutils.wifi_connect(self.dut, self.ap_a, num_of_tries=5)
257 self.ap_a_off()
258 time.sleep(LAST_DISCONNECT_TIMEOUT_SEC * 0.4)
259 wutils.wifi_toggle_state(self.dut, new_state=False)
260 time.sleep(PRESCAN_DELAY_SEC)
261 self.do_location_scan(CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT + 2)
262 self.ap_a_on()
263 self.do_location_scan(
264 2 * CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT + 2)
265 asserts.assert_false(
266 self.dut.droid.wifiCheckState(),
267 "Expect Wifi Wake to not enable Wifi, but Wifi was enabled.")
268
269 @test_tracker_info(uuid="b990a8f7-e3a0-4774-89cf-2067ccd64903")
270 def test_reconnect_wifi_disabled_after_disconnecting(self):
271 """
272 Tests that Wifi Wake reconnects to a network if Wifi was disabled long
273 after disconnecting from a network.
274 """
275 wutils.wifi_connect(self.dut, self.ap_a, num_of_tries=5)
276 self.dut.ed.clear_all_events()
277 self.ap_a_off()
278 wutils.wait_for_disconnect(self.dut)
279 self.log.info("Wifi Disconnected")
280 time.sleep(LAST_DISCONNECT_TIMEOUT_SEC * 1.2)
281 wutils.wifi_toggle_state(self.dut, new_state=False)
282 time.sleep(PRESCAN_DELAY_SEC)
283 self.do_location_scan(CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT + 2)
284 self.ap_a_on()
285 self.do_location_scan()
286 asserts.assert_true(
287 self.dut.droid.wifiCheckState(),
288 "Expect Wifi Wake to enable Wifi, but Wifi is disabled.")
289
290 @test_tracker_info(uuid="bb217794-d3ee-4fb9-87ff-7a594d0223b0")
291 def test_no_reconnect_if_exists_ap_in_wakeup_lock(self):
292 """
293 2 APs in Wakeup Lock, user moves out of range of one AP but stays in
294 range of the other, should not reconnect when user moves back in range
295 of both.
296 """
297 wutils.wifi_connect(self.dut, self.ap_a, num_of_tries=5)
298 wutils.wifi_connect(self.dut, self.ap_b, num_of_tries=5)
299 wutils.wifi_toggle_state(self.dut, new_state=False)
300 time.sleep(PRESCAN_DELAY_SEC)
301 self.do_location_scan(CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT + 2)
302 self.ap_b_off()
303 self.do_location_scan(CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT + 2)
304 self.ap_b_on()
305 self.do_location_scan(CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT + 2)
306 asserts.assert_false(
307 self.dut.droid.wifiCheckState(),
308 "Expect Wifi Wake to not enable Wifi, but Wifi was enabled.")
309
310 @test_tracker_info(uuid="567a0663-4ce0-488d-8fe2-db79a3ebf068")
311 def test_reconnect_if_both_ap_evicted_from_wakeup_lock(self):
312 """
313 2 APs in Wakeup Lock, user moves out of range of both APs, should
314 reconnect when user moves back in range of either AP.
315 """
316 wutils.wifi_connect(self.dut, self.ap_a, num_of_tries=5)
317 wutils.wifi_connect(self.dut, self.ap_b, num_of_tries=5)
318 wutils.wifi_toggle_state(self.dut, new_state=False)
319 time.sleep(PRESCAN_DELAY_SEC)
320 self.do_location_scan(CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT + 2)
321 self.ap_a_off()
322 self.ap_b_off()
323 self.do_location_scan(CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT + 2)
324 self.ap_a_on()
325 self.do_location_scan()
326 asserts.assert_true(
327 self.dut.droid.wifiCheckState(),
328 "Expect Wifi Wake to enable Wifi, but Wifi is disabled.")
329
330 @test_tracker_info(uuid="d67657c8-3de3-46a6-a103-428cdab89423")
331 def test_reconnect_to_better_saved_network(self):
332 """
333 2 saved APs, one attenuated, one unattenuated, Wifi Wake should connect
334 to the unattenuated AP
335 """
336 wutils.wifi_connect(self.dut, self.ap_a, num_of_tries=5)
337 wutils.wifi_connect(self.dut, self.ap_b, num_of_tries=5)
338 self.dut.ed.clear_all_events()
339 self.ap_a_off()
340 self.ap_b_off()
341 wutils.wait_for_disconnect(self.dut)
342 self.log.info("Wifi Disconnected")
343 time.sleep(LAST_DISCONNECT_TIMEOUT_SEC * 1.2)
344 wutils.wifi_toggle_state(self.dut, new_state=False)
345 time.sleep(PRESCAN_DELAY_SEC)
346 self.do_location_scan(CONSECUTIVE_MISSED_SCANS_REQUIRED_TO_EVICT + 2)
347
348 self.ap_a_on()
349 self.ap_b_on()
350 self.ap_a_atten.set_atten(30)
351 self.ap_b_atten.set_atten(0)
352
353 self.do_location_scan()
354 asserts.assert_true(
355 self.dut.droid.wifiCheckState(),
356 "Expect Wifi Wake to enable Wifi, but Wifi is disabled.")
357 expected_ssid = self.ap_b[wutils.WifiEnums.SSID_KEY]
358 actual_ssid = self.dut.droid.wifiGetConnectionInfo()[
359 wutils.WifiEnums.SSID_KEY]
360 asserts.assert_equal(
361 expected_ssid, actual_ssid,
362 ("Expected to connect to SSID '{}', but actually connected to "
363 "'{}' instead.").format(expected_ssid, actual_ssid))