blob: eaafb958d5cd67adeaa87bef23de54f4c4f6ce97 [file] [log] [blame]
Bindu Mahadev36725332019-01-29 12:23:21 -08001#!/usr/bin/env python3.4
2#
3# Copyright 2019 - 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.tel.tel_test_utils import WIFI_CONFIG_APBAND_2G
30from acts.test_utils.tel.tel_test_utils import WIFI_CONFIG_APBAND_5G
31from acts.test_utils.wifi.WifiBaseTest import WifiBaseTest
32
33WifiEnums = wutils.WifiEnums
34
35# Default timeout used for reboot, toggle WiFi and Airplane mode,
36# for the system to settle down after the operation.
37DEFAULT_TIMEOUT = 10
38
39# Constants for WiFi state change operations.
40FORGET = 1
41TOGGLE = 2
42REBOOT_DUT = 3
43REBOOT_AP = 4
44
45# MAC Randomization setting constants.
46RANDOMIZATION_NONE = 0
47RANDOMIZATION_PERSISTENT = 1
48
49
50class WifiMacRandomizationTest(WifiBaseTest):
51 """Tests for APIs in Android's WifiManager class.
52
53 Test Bed Requirement:
54 * Atleast one Android device and atleast two Access Points.
55 * Several Wi-Fi networks visible to the device.
56 """
57
58 def __init__(self, controllers):
59 WifiBaseTest.__init__(self, controllers)
60
61 def setup_class(self):
62 self.dut = self.android_devices[0]
63 self.dut_client = self.android_devices[1]
64 wutils.wifi_test_device_init(self.dut)
65 wutils.wifi_test_device_init(self.dut_client)
66 req_params = []
67 opt_param = [
68 "open_network", "reference_networks", "wep_networks"
69 ]
70 self.unpack_userparams(
71 req_param_names=req_params, opt_param_names=opt_param)
72
73 if "AccessPoint" in self.user_params:
74 if "AccessPoint" in self.user_params:
75 self.legacy_configure_ap_and_start(wep_network=True, ap_count=2)
76
77 asserts.assert_true(
78 len(self.reference_networks) > 0,
79 "Need at least one reference network with psk.")
80
81 wutils.wifi_toggle_state(self.dut, True)
82 wutils.wifi_toggle_state(self.dut_client, True)
83 self.wpapsk_2g = self.reference_networks[0]["2g"]
84 self.wpapsk_5g = self.reference_networks[0]["5g"]
85 self.wep_2g = self.wep_networks[0]["2g"]
86 self.wep_5g = self.wep_networks[0]["5g"]
87 self.open_2g = self.open_network[0]["2g"]
88 self.open_5g = self.open_network[0]["5g"]
89
90 def setup_test(self):
91 for ad in self.android_devices:
92 ad.droid.wakeLockAcquireBright()
93 ad.droid.wakeUpNow()
94 wutils.wifi_toggle_state(ad, True)
95
96 def teardown_test(self):
97 for ad in self.android_devices:
98 ad.droid.wakeLockRelease()
99 ad.droid.goToSleepNow()
100 wutils.reset_wifi(self.dut)
101 wutils.reset_wifi(self.dut_client)
102
103 def on_fail(self, test_name, begin_time):
104 pass
105 #self.dut.cat_adb_log(test_name, begin_time)
106 #self.dut.take_bug_report(test_name, begin_time)
107
108 def teardown_class(self):
109 if "AccessPoint" in self.user_params:
110 del self.user_params["reference_networks"]
111 del self.user_params["open_network"]
112 del self.user_params["wep_networks"]
113
114
115 """Helper Functions"""
116
117
118 def get_randomized_mac(self, network):
119 """Get the randomized MAC address.
120
121 Args:
122 network: dict, network information.
123
124 Returns:
125 The randomized MAC address string for the network.
126
127 """
128 return self.dut.droid.wifigetRandomizedMacAddress(network)
129
130 def connect_to_network_and_verify_mac_randomization(self, network,
131 status=RANDOMIZATION_PERSISTENT):
132 """Connect to the given network and verify MAC.
133
134 Args:
135 network: dict, the network information.
136 status: int, MAC randomization level.
137
138 Returns:
139 The randomized MAC addresss string.
140
141 """
142 wutils.connect_to_wifi_network(self.dut, network)
143 return self.verify_mac_randomization(network, status=status)
144
145 def verify_mac_randomization_and_add_to_list(self, network, mac_list):
146 """Connect to a network and populate it's MAC in a reference list,
147 that will be used to verify any repeated MAC addresses.
148
149 Args:
150 network: dict, the network information.
151 mac_list: list of MAC addresss strings.
152
153 """
154 rand_mac = self.connect_to_network_and_verify_mac_randomization(
155 network)
156 if rand_mac in mac_list:
157 raise signals.TestFailure('A new Randomized MAC was not generated '
158 ' for this network %s.' % network)
159 mac_list.append(rand_mac)
160
161 def verify_mac_randomization(self, network, status=RANDOMIZATION_PERSISTENT):
162 """Get the various types of MAC addresses for the device and verify.
163
164 Args:
165 network: dict, the network information.
166 status: int, MAC randomization level.
167
168 Returns:
169 The randomized MAC address string for the network.
170
171 """
172 network_info = self.dut.droid.wifiGetConnectionInfo()
173 factory_mac = self.dut.droid.wifigetFactorymacAddresses()[0]
174 randomized_mac = self.get_randomized_mac(network)
175 default_mac = network_info['mac_address']
176 self.log.info("Factory MAC = %s\nRandomized MAC = %s\nDefault MAC = %s" %
177 (factory_mac, randomized_mac, default_mac))
178
179 if status == RANDOMIZATION_NONE:
180 asserts.assert_true(default_mac == factory_mac, "Connection is not "
181 "using Factory MAC as the default MAC.")
182 message = ('Randomized MAC and Factory MAC are the same. '
183 'Randomized MAC = %s, Factory MAC = %s' % (randomized_mac, factory_mac))
184 asserts.assert_true(randomized_mac != factory_mac, message)
185
186 message = ('Connection is not using randomized MAC as the default MAC. '
187 'Randomized MAC = %s, Deafult MAC = %s' % (randomized_mac, default_mac))
188 # Uncomment after b/123355618 is resolved.
189 #asserts.assert_true(randomized_mac == default_mac, message)
190
191 return randomized_mac
192
193 def check_mac_persistence(self, network, condition):
194 """Check if the MAC is persistent after carrying out specific operations
195 like forget WiFi, toggle WiFi, reboot device and AP.
196
197 Args:
198 network: dict, The network information.
199 condition: int, value to trigger certain operation on the device.
200
201 Raises:
202 TestFaikure is the MAC is not persistent.
203
204 """
205 rand_mac1 = self.connect_to_network_and_verify_mac_randomization(network)
206
207 if condition == FORGET:
208 wutils.wifi_forget_network(self.dut, network['SSID'])
209
210 elif condition == TOGGLE:
211 wutils.wifi_toggle_state(self.dut, False)
212 wutils.wifi_toggle_state(self.dut, True)
213
214 elif condition == REBOOT_DUT:
215 self.dut.reboot()
216 time.sleep(DEFAULT_TIMEOUT)
217
218 elif condition == REBOOT_AP:
219 wutils.turn_ap_off(self, 1)
220 time.sleep(DEFAULT_TIMEOUT)
221 wutils.turn_ap_on(self, 1)
222 time.sleep(DEFAULT_TIMEOUT)
223
224 rand_mac2 = self.connect_to_network_and_verify_mac_randomization(network)
225
226 if rand_mac1 != rand_mac2:
227 raise signals.TestFailure('Randomized MAC is not persistent after '
228 'forgetting networ. Old MAC = %s New MAC'
229 ' = %s' % (rand_mac1, rand_mac2))
230
231 """Tests"""
232
233
234 @test_tracker_info(uuid="2dd0a05e-a318-45a6-81cd-962e098fa242")
235 def test_set_mac_randomization_to_none(self):
236 network = self.wpapsk_2g
237 # Set macRandomizationSetting to RANDOMIZATION_NONE.
238 network["macRand"] = RANDOMIZATION_NONE
239 self.connect_to_network_and_verify_mac_randomization(network,
240 status=RANDOMIZATION_NONE)
241
242 @test_tracker_info(uuid="d9e64202-02d5-421a-967c-42e45f1f7f91")
243 def test_mac_randomization_wpapsk(self):
244 """Verify MAC randomization for a WPA network.
245
246 Steps:
247 1. Connect to WPA network.
248 2. Get the Factory, Randomized and Default MACs.
249 3. Verify randomized MAC is the default MAC for the device.
250
251 """
252 self.connect_to_network_and_verify_mac_randomization(self.wpapsk_2g)
253
254 @test_tracker_info(uuid="b5be7c53-2edf-449e-ba70-a1fb7acf735e")
255 def test_mac_randomization_wep(self):
256 """Verify MAC randomization for a WEP network.
257
258 Steps:
259 1. Connect to WEP network.
260 2. Get the Factory, Randomized and Default MACs.
261 3. Verify randomized MAC is the default MAC for the device.
262
263 """
264 self.connect_to_network_and_verify_mac_randomization(self.wep_2g)
265
266 @test_tracker_info(uuid="f5347ac0-68d5-4882-a58d-1bd0d575503c")
267 def test_mac_randomization_open(self):
268 """Verify MAC randomization for a open network.
269
270 Steps:
271 1. Connect to open network.
272 2. Get the Factory, Randomized and Default MACs.
273 3. Verify randomized MAC is the default MAC for the device.
274
275 """
276 self.connect_to_network_and_verify_mac_randomization(self.open_2g)
277
278 @test_tracker_info(uuid="5d260421-2adf-4ace-b281-3d15aec39b2a")
279 def test_persistent_mac_after_forget(self):
280 """Check if MAC is persistent after forgetting/adding a network.
281
282 Steps:
283 1. Connect to WPA network and get the randomized MAC.
284 2. Forget the network.
285 3. Connect to the same network again.
286 4. Verify randomized MAC has not changed.
287
288 """
289 self.check_mac_persistence(self.wpapsk_2g, FORGET)
290
291 @test_tracker_info(uuid="09d40a93-ead2-45ca-9905-14b05fd79f34")
292 def test_persistent_mac_after_toggle(self):
293 """Check if MAC is persistent after toggling WiFi network.
294
295 Steps:
296 1. Connect to WPA network and get the randomized MAC.
297 2. Turn WiFi ON/OFF.
298 3. Connect to the same network again.
299 4. Verify randomized MAC has not changed.
300
301 """
302 self.check_mac_persistence(self.wpapsk_2g, TOGGLE)
303
304 @test_tracker_info(uuid="a514f-8562-44e8-bfe0-4ecab9af165b")
305 def test_persistent_mac_after_device_reboot(self):
306 """Check if MAC is persistent after a device reboot.
307
308 Steps:
309 1. Connect to WPA network and get the randomized MAC.
310 2. Reboot DUT.
311 3. Connect to the same network again.
312 4. Verify randomized MAC has not changed.
313
314 """
315 self.check_mac_persistence(self.wpapsk_2g, REBOOT_DUT)
316
317 @test_tracker_info(uuid="82d691a0-22e4-4a3d-9596-e150531fcd34")
318 def test_persistent_mac_after_ap_reboot(self):
319 """Check if MAC is persistent after AP reboots itself.
320
321 Steps:
322 1. Connect to WPA network and get the randomized MAC.
323 2. Reboot AP(basically restart hostapd in our case).
324 3. Connect to the same network again.
325 4. Verify randomized MAC has not changed.
326
327 """
328 self.check_mac_persistence(self.wpapsk_2g, REBOOT_AP)
329
330 @test_tracker_info(uuid="e1f33dbc-808c-4e61-8a4a-3a72c1f63c7e")
331 def test_mac_randomization_multiple_networks(self):
332 """Connect to multiple networks and verify same MAC.
333
334 Steps:
335 1. Connect to network A, get randomizd MAC.
336 2. Conenct to network B, get randomized MAC.
337 3. Connect back to network A and verify same MAC.
338 4. Connect back to network B and verify same MAC.
339
340 """
341 mac_list = list()
342
343 # Connect to two different networks and get randomized MAC addresses.
344 self.verify_mac_randomization_and_add_to_list(self.wpapsk_2g, mac_list)
345 self.verify_mac_randomization_and_add_to_list(self.open_2g, mac_list)
346
347 # Connect to the previous network and check MAC is persistent.
348 mac_wpapsk = self.connect_to_network_and_verify_mac_randomization(
349 self.wpapsk_2g)
350 msg = ('Randomized MAC is not persistent for this network %s. Old MAC = '
351 '%s \nNew MAC = %s')
352 if mac_wpapsk != mac_list[0]:
353 raise signals.TestFailure(msg % (self.wpapsk_5g, mac_list[0], mac_wpapsk))
354 mac_open = self.connect_to_network_and_verify_mac_randomization(
355 self.open_2g)
356 if mac_open != mac_list[1]:
357 raise signals.TestFailure(msg %(self.open_5g, mac_list[1], mac_open))
358
359 @test_tracker_info(uuid="edb5a0e5-7f3b-4147-b1d3-48ad7ad9799e")
360 def test_mac_randomization_differnet_APs(self):
361 """Verify randomization using two different APs.
362
363 Steps:
364 1. Connect to network A on AP1, get the randomized MAC.
365 2. Connect to network B on AP2, get the randomized MAC.
366 3. Veirfy the two MACs are different.
367
368 """
369 ap1 = self.wpapsk_2g
370 ap2 = self.reference_networks[1]["5g"]
371 mac_ap1 = self.connect_to_network_and_verify_mac_randomization(ap1)
372 mac_ap2 = self.connect_to_network_and_verify_mac_randomization(ap2)
373 if ap1 == ap2:
374 raise signals.TestFailure("Same MAC address was generated for both "
375 "APs: %s" % mac_ap1)
376
377 @test_tracker_info(uuid="b815e9ce-bccd-4fc3-9774-1e1bc123a2a8")
378 def test_mac_randomization_ap_sta(self):
379 """Bring up STA and softAP and verify MAC randomization.
380
381 Steps:
382 1. Connect to a network and get randomized MAC.
383 2. Bring up softAP on the DUT.
384 3. Connect to softAP network on the client and get MAC.
385 4. Verify AP and STA use different randomized MACs.
386
387 """
388 self.dut.droid.wifiSetCountryCode(wutils.WifiEnums.CountryCode.US)
389 self.dut_client.droid.wifiSetCountryCode(wutils.WifiEnums.CountryCode.US)
390 mac_sta = self.connect_to_network_and_verify_mac_randomization(
391 self.wpapsk_2g)
392 softap = wutils.start_softap_and_verify(self, WIFI_CONFIG_APBAND_2G)
393 wutils.connect_to_wifi_network(self.dut_client, softap)
394 softap_info = self.dut_client.droid.wifiGetConnectionInfo()
395 mac_ap = softap_info['mac_address']
396 if mac_sta == mac_ap:
397 raise signals.TestFailure("Same MAC address was used for both "
398 "AP and STA: %s" % mac_sta)
399
400 @test_tracker_info(uuid="3ca3f911-29f1-41fb-b836-4d25eac1669f")
401 def test_roaming_mac_randomization(self):
402 """test MAC randomization in the roaming scenario.
403
404 Steps:
405 1. Connect to network A on AP1, get randomized MAC.
406 2. Set AP1 to MAX attenuation so that we roam to AP2.
407 3. Wait for device to roam to AP2 and get randomized MAC.
408 4. Veirfy that the device uses same AMC for both APs.
409
410 """
411 AP1_network = self.reference_networks[0]["5g"]
412 AP2_network = self.reference_networks[1]["5g"]
413 wutils.set_attns(self.attenuators, "AP1_on_AP2_off")
414 mac_before_roam = self.connect_to_network_and_verify_mac_randomization(
415 AP1_network)
416 wutils.trigger_roaming_and_validate(self.dut, self.attenuators,
417 "AP1_off_AP2_on", AP2_network)
418 mac_after_roam = self.get_randomized_mac(AP2_network)
419 if mac_after_roam != mac_before_roam:
420 raise signals.TestFailure("Randomized MAC address changed after "
421 "roaming from AP1 to AP2.\nMAC before roam = %s\nMAC after "
422 "roam = %s" %(mac_before_roam, mac_after_roam))
423 wutils.trigger_roaming_and_validate(self.dut, self.attenuators,
424 "AP1_on_AP2_off", AP1_network)
425 mac_after_roam = self.get_randomized_mac(AP1_network)
426 if mac_after_roam != mac_before_roam:
427 raise signals.TestFailure("Randomized MAC address changed after "
428 "roaming from AP1 to AP2.\nMAC before roam = %s\nMAC after "
429 "roam = %s" %(mac_before_roam, mac_after_roam))