• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/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 re
19import time
20
21import acts.base_test
22import acts.signals as signals
23import acts_contrib.test_utils.wifi.wifi_test_utils as wutils
24import acts.utils
25
26from acts import asserts
27from acts.test_decorators import test_tracker_info
28from acts_contrib.test_utils.tel.tel_wifi_utils import WIFI_CONFIG_APBAND_2G
29from acts_contrib.test_utils.tel.tel_wifi_utils import WIFI_CONFIG_APBAND_5G
30from acts_contrib.test_utils.wifi.WifiBaseTest import WifiBaseTest
31from scapy.all import *
32from acts.controllers.ap_lib import hostapd_constants
33
34WifiEnums = wutils.WifiEnums
35
36# Default timeout used for reboot, toggle WiFi and Airplane mode,
37# for the system to settle down after the operation.
38DEFAULT_TIMEOUT = 10
39SHORT_TIMEOUT = 5
40
41# Constants for WiFi state change operations.
42FORGET = 1
43TOGGLE = 2
44REBOOT_DUT = 3
45REBOOT_AP = 4
46
47# MAC Randomization setting constants.
48RANDOMIZATION_NONE = 0
49RANDOMIZATION_PERSISTENT = 1
50
51
52class WifiMacRandomizationTest(WifiBaseTest):
53    """Tests for APIs in Android's WifiManager class.
54
55    Test Bed Requirement:
56    * Atleast one Android device and atleast two Access Points.
57    * Several Wi-Fi networks visible to the device.
58    """
59
60    def setup_class(self):
61        super().setup_class()
62
63        self.dut = self.android_devices[0]
64        self.dut_client = self.android_devices[1]
65        wutils.wifi_test_device_init(self.dut)
66        wutils.wifi_test_device_init(self.dut_client)
67        req_params = [
68            "sta_sta_supported_models", "dbs_supported_models",
69            "support_one_factory_mac_address", "roaming_attn"
70        ]
71        opt_param = ["open_network", "reference_networks", "wep_networks"]
72        self.unpack_userparams(req_param_names=req_params,
73                               opt_param_names=opt_param)
74
75        if not hasattr(self, 'packet_capture'):
76            raise signals.TestFailure("Needs packet_capture attribute to "
77                                      "support sniffing.")
78        self.configure_packet_capture()
79
80        if "AccessPoint" in self.user_params:
81            self.legacy_configure_ap_and_start(wep_network=True, ap_count=2)
82        elif "OpenWrtAP" in self.user_params:
83            self.configure_openwrt_ap_and_start(open_network=True,
84                                                wpa_network=True,
85                                                wep_network=True,
86                                                mirror_ap=True,
87                                                ap_count=2)
88
89        asserts.assert_true(
90            len(self.reference_networks) > 0,
91            "Need at least one reference network with psk.")
92
93        # Reboot device to reset factory MAC of wlan1
94        self.dut.reboot()
95        self.dut_client.reboot()
96        time.sleep(DEFAULT_TIMEOUT)
97        wutils.wifi_toggle_state(self.dut, True)
98        wutils.wifi_toggle_state(self.dut_client, True)
99        if self.dut.model in self.support_one_factory_mac_address:
100            self.soft_ap_factory_mac = (
101                self.dut.droid.wifigetFactorymacAddresses()[0])
102        else:
103            self.soft_ap_factory_mac = self.get_soft_ap_mac_address()
104        self.sta_factory_mac = self.dut.droid.wifigetFactorymacAddresses()[0]
105
106        self.wpapsk_2g = self.reference_networks[0]["2g"]
107        self.wpapsk_5g = self.reference_networks[0]["5g"]
108        self.wep_2g = self.wep_networks[0]["2g"]
109        self.wep_5g = self.wep_networks[0]["5g"]
110        self.open_2g = self.open_network[0]["2g"]
111        self.open_5g = self.open_network[0]["5g"]
112
113    def setup_test(self):
114        super().setup_test()
115        for ad in self.android_devices:
116            ad.droid.wakeLockAcquireBright()
117            ad.droid.wakeUpNow()
118            wutils.wifi_toggle_state(ad, True)
119
120    def teardown_test(self):
121        super().teardown_test()
122        for ad in self.android_devices:
123            ad.droid.wakeLockRelease()
124            ad.droid.goToSleepNow()
125        self.dut.droid.wifiRemoveNetworkSuggestions([])
126        wutils.reset_wifi(self.dut)
127        wutils.reset_wifi(self.dut_client)
128
129    def teardown_class(self):
130        if "AccessPoint" in self.user_params:
131            del self.user_params["reference_networks"]
132            del self.user_params["open_network"]
133            del self.user_params["wep_networks"]
134
135    """Helper Functions"""
136
137    def get_randomized_mac(self, network):
138        """Get the randomized MAC address.
139
140        Args:
141            network: dict, network information.
142
143        Returns:
144            The randomized MAC address string for the network.
145
146        """
147        return self.dut.droid.wifigetRandomizedMacAddress(network)
148
149    def connect_to_network_and_verify_mac_randomization(
150            self, network, status=RANDOMIZATION_PERSISTENT):
151        """Connect to the given network and verify MAC.
152
153          Args:
154              network: dict, the network information.
155              status: int, MAC randomization level.
156
157          Returns:
158              The randomized MAC addresss string.
159
160        """
161        wutils.connect_to_wifi_network(self.dut, network)
162        return self.verify_mac_randomization(network, status=status)
163
164    def verify_mac_randomization_and_add_to_list(self, network, mac_list):
165        """Connect to a network and populate it's MAC in a reference list,
166        that will be used to verify any repeated MAC addresses.
167
168        Args:
169            network: dict, the network information.
170            mac_list: list of MAC addresss strings.
171
172        """
173        rand_mac = self.connect_to_network_and_verify_mac_randomization(
174            network)
175        if rand_mac in mac_list:
176            raise signals.TestFailure('A new Randomized MAC was not generated '
177                                      ' for this network %s.' % network)
178        mac_list.append(rand_mac)
179
180    def verify_mac_randomization(self,
181                                 network,
182                                 status=RANDOMIZATION_PERSISTENT):
183        """Get the various types of MAC addresses for the device and verify.
184
185        Args:
186            network: dict, the network information.
187            status: int, MAC randomization level.
188
189        Returns:
190            The randomized MAC address string for the network.
191
192        """
193        randomized_mac = self.get_randomized_mac(network)
194        default_mac = self.get_sta_mac_address()
195        self.log.info(
196            "Factory MAC = %s\nRandomized MAC = %s\nDefault MAC = %s" %
197            (self.sta_factory_mac, randomized_mac, default_mac))
198        message = ('Randomized MAC and Factory MAC are the same. '
199                   'Randomized MAC = %s, Factory MAC = %s' %
200                   (randomized_mac, self.sta_factory_mac))
201        asserts.assert_true(randomized_mac != self.sta_factory_mac, message)
202        if status == RANDOMIZATION_NONE:
203            asserts.assert_true(
204                default_mac == self.sta_factory_mac, "Connection is not "
205                "using Factory MAC as the default MAC.")
206        else:
207            message = (
208                'Connection is not using randomized MAC as the default MAC. '
209                'Randomized MAC = %s, Default MAC = %s' %
210                (randomized_mac, default_mac))
211            asserts.assert_true(default_mac == randomized_mac, message)
212        return randomized_mac
213
214    def check_mac_persistence(self, network, condition):
215        """Check if the MAC is persistent after carrying out specific operations
216        like forget WiFi, toggle WiFi, reboot device and AP.
217
218        Args:
219            network: dict, The network information.
220            condition: int, value to trigger certain  operation on the device.
221
222        Raises:
223            TestFaikure is the MAC is not persistent.
224
225        """
226        rand_mac1 = self.connect_to_network_and_verify_mac_randomization(
227            network)
228
229        if condition == FORGET:
230            wutils.wifi_forget_network(self.dut, network['SSID'])
231
232        elif condition == TOGGLE:
233            wutils.wifi_toggle_state(self.dut, False)
234            wutils.wifi_toggle_state(self.dut, True)
235
236        elif condition == REBOOT_DUT:
237            self.dut.reboot()
238            time.sleep(DEFAULT_TIMEOUT)
239
240        elif condition == REBOOT_AP:
241            wutils.turn_ap_off(self, 1)
242            time.sleep(DEFAULT_TIMEOUT)
243            wutils.turn_ap_on(self, 1)
244            time.sleep(DEFAULT_TIMEOUT)
245
246        rand_mac2 = self.connect_to_network_and_verify_mac_randomization(
247            network)
248
249        if rand_mac1 != rand_mac2:
250            raise signals.TestFailure('Randomized MAC is not persistent after '
251                                      'forgetting networ. Old MAC = %s New MAC'
252                                      ' = %s' % (rand_mac1, rand_mac2))
253
254    def verify_mac_not_found_in_pcap(self, mac, packets):
255        for pkt in packets:
256            self.log.debug("Packet Summary = %s" % pkt.summary())
257            if mac in pkt.summary():
258                raise signals.TestFailure(
259                    "Caught Factory MAC in packet sniffer"
260                    "Packet = %s Device = %s" % (pkt.show(), self.dut))
261
262    def verify_mac_is_found_in_pcap(self, mac, packets):
263        for pkt in packets:
264            self.log.debug("Packet Summary = %s" % pkt.summary())
265            if mac in pkt.summary():
266                return
267        raise signals.TestFailure("Did not find MAC = %s in packet sniffer."
268                                  "for device %s" % (mac, self.dut))
269
270    def get_sta_mac_address(self):
271        """Gets the current MAC address being used for client mode."""
272        out = self.dut.adb.shell("ifconfig wlan0")
273        res = re.match(".* HWaddr (\S+).*", out, re.S)
274        return res.group(1)
275
276    def get_soft_ap_mac_address(self):
277        """Gets the current MAC address being used for SoftAp."""
278        if self.dut.model in self.sta_sta_supported_models:
279            out = self.dut.adb.shell("ifconfig wlan2")
280            return re.match(".* HWaddr (\S+).*", out, re.S).group(1)
281        if self.dut.model in self.dbs_supported_models:
282            out = self.dut.adb.shell("ifconfig wlan1")
283            return re.match(".* HWaddr (\S+).*", out, re.S).group(1)
284        else:
285            return self.get_sta_mac_address()
286
287    def _add_suggestion_and_verify_mac_randomization(self, network_suggestion):
288        """Add wifi network suggestion and verify MAC randomization.
289
290        Args:
291            network_suggestion: network suggestion to add.
292
293        Returns:
294            Randomized MAC address.
295        """
296        self.log.info("Adding network suggestion")
297        asserts.assert_true(
298            self.dut.droid.wifiAddNetworkSuggestions([network_suggestion]),
299            "Failed to add suggestions")
300        wutils.start_wifi_connection_scan_and_ensure_network_found(
301            self.dut, network_suggestion[WifiEnums.SSID_KEY])
302        wutils.wait_for_connect(self.dut,
303                                network_suggestion[WifiEnums.SSID_KEY])
304        default_mac = self.get_sta_mac_address()
305        randomized_mac = self.dut.droid.wifiGetConnectionInfo()["mac_address"]
306        self.log.info(
307            "Factory MAC = %s\nRandomized MAC = %s\nDefault MAC = %s" %
308            (self.sta_factory_mac, randomized_mac, default_mac))
309        asserts.assert_true(
310            default_mac == randomized_mac,
311            "Connection is not using randomized MAC as the default MAC.")
312        return randomized_mac
313
314    def _remove_suggestion_and_verify_disconnect(self, network_suggestion):
315        """Remove wifi network suggestion and verify device disconnects.
316
317        Args:
318            network_suggestion: network suggestion to remove.
319        """
320        self.dut.log.info("Removing network suggestions")
321        asserts.assert_true(
322            self.dut.droid.wifiRemoveNetworkSuggestions([network_suggestion]),
323            "Failed to remove suggestions")
324        wutils.wait_for_disconnect(self.dut)
325        self.dut.ed.clear_all_events()
326        asserts.assert_false(
327            wutils.wait_for_connect(self.dut,
328                                    network_suggestion[WifiEnums.SSID_KEY],
329                                    assert_on_fail=False),
330            "Device should not connect back")
331
332    """Tests"""
333
334    @test_tracker_info(uuid="2dd0a05e-a318-45a6-81cd-962e098fa242")
335    def test_set_mac_randomization_to_none(self):
336        self.pcap_procs = wutils.start_pcap(self.packet_capture, 'dual',
337                                            self.test_name)
338        network = self.wpapsk_2g
339        # Set macRandomizationSetting to RANDOMIZATION_NONE.
340        network["macRand"] = RANDOMIZATION_NONE
341        self.connect_to_network_and_verify_mac_randomization(
342            network, status=RANDOMIZATION_NONE)
343        pcap_fname = '%s_%s.pcap' % \
344            (self.pcap_procs[hostapd_constants.BAND_2G][1],
345             hostapd_constants.BAND_2G.upper())
346        time.sleep(SHORT_TIMEOUT)
347        wutils.stop_pcap(self.packet_capture, self.pcap_procs, False)
348        packets = rdpcap(pcap_fname)
349        self.verify_mac_is_found_in_pcap(self.sta_factory_mac, packets)
350
351    @test_tracker_info(uuid="d9e64202-02d5-421a-967c-42e45f1f7f91")
352    def test_mac_randomization_wpapsk(self):
353        """Verify MAC randomization for a WPA network.
354
355        Steps:
356            1. Connect to WPA network.
357            2. Get the Factory, Randomized and Default MACs.
358            3. Verify randomized MAC is the default MAC for the device.
359
360        """
361        self.connect_to_network_and_verify_mac_randomization(self.wpapsk_2g)
362
363    @test_tracker_info(uuid="b5be7c53-2edf-449e-ba70-a1fb7acf735e")
364    def test_mac_randomization_wep(self):
365        """Verify MAC randomization for a WEP network.
366
367        Steps:
368            1. Connect to WEP network.
369            2. Get the Factory, Randomized and Default MACs.
370            3. Verify randomized MAC is the default MAC for the device.
371
372        """
373        self.connect_to_network_and_verify_mac_randomization(self.wep_2g)
374
375    @test_tracker_info(uuid="f5347ac0-68d5-4882-a58d-1bd0d575503c")
376    def test_mac_randomization_open(self):
377        """Verify MAC randomization for a open network.
378
379        Steps:
380            1. Connect to open network.
381            2. Get the Factory, Randomized and Default MACs.
382            3. Verify randomized MAC is the default MAC for the device.
383
384        """
385        self.connect_to_network_and_verify_mac_randomization(self.open_2g)
386
387    @test_tracker_info(uuid="5d260421-2adf-4ace-b281-3d15aec39b2a")
388    def test_persistent_mac_after_forget(self):
389        """Check if MAC is persistent after forgetting/adding a network.
390
391        Steps:
392            1. Connect to WPA network and get the randomized MAC.
393            2. Forget the network.
394            3. Connect to the same network again.
395            4. Verify randomized MAC has not changed.
396
397        """
398        self.check_mac_persistence(self.wpapsk_2g, FORGET)
399
400    @test_tracker_info(uuid="09d40a93-ead2-45ca-9905-14b05fd79f34")
401    def test_persistent_mac_after_toggle(self):
402        """Check if MAC is persistent after toggling WiFi network.
403
404        Steps:
405            1. Connect to WPA network and get the randomized MAC.
406            2. Turn WiFi ON/OFF.
407            3. Connect to the same network again.
408            4. Verify randomized MAC has not changed.
409
410        """
411        self.check_mac_persistence(self.wpapsk_2g, TOGGLE)
412
413    @test_tracker_info(uuid="b3aa514f-8562-44e8-bfe0-4ecab9af165b")
414    def test_persistent_mac_after_device_reboot(self):
415        """Check if MAC is persistent after a device reboot.
416
417        Steps:
418            1. Connect to WPA network and get the randomized MAC.
419            2. Reboot DUT.
420            3. Connect to the same network again.
421            4. Verify randomized MAC has not changed.
422
423        """
424        self.check_mac_persistence(self.wpapsk_2g, REBOOT_DUT)
425
426    # Disable reboot test for debugging purpose.
427    #@test_tracker_info(uuid="82d691a0-22e4-4a3d-9596-e150531fcd34")
428    def persistent_mac_after_ap_reboot(self):
429        """Check if MAC is persistent after AP reboots itself.
430
431        Steps:
432            1. Connect to WPA network and get the randomized MAC.
433            2. Reboot AP(basically restart hostapd in our case).
434            3. Connect to the same network again.
435            4. Verify randomized MAC has not changed.
436
437        """
438        self.check_mac_persistence(self.wpapsk_2g, REBOOT_AP)
439
440    @test_tracker_info(uuid="e1f33dbc-808c-4e61-8a4a-3a72c1f63c7e")
441    def test_mac_randomization_multiple_networks(self):
442        """Connect to multiple networks and verify same MAC.
443
444        Steps:
445            1. Connect to network A, get randomizd MAC.
446            2. Conenct to network B, get randomized MAC.
447            3. Connect back to network A and verify same MAC.
448            4. Connect back to network B and verify same MAC.
449
450        """
451        mac_list = list()
452
453        # Connect to two different networks and get randomized MAC addresses.
454        self.verify_mac_randomization_and_add_to_list(self.wpapsk_2g, mac_list)
455        self.verify_mac_randomization_and_add_to_list(self.open_2g, mac_list)
456
457        # Connect to the previous network and check MAC is persistent.
458        mac_wpapsk = self.connect_to_network_and_verify_mac_randomization(
459            self.wpapsk_2g)
460        msg = (
461            'Randomized MAC is not persistent for this network %s. Old MAC = '
462            '%s \nNew MAC = %s')
463        if mac_wpapsk != mac_list[0]:
464            raise signals.TestFailure(
465                msg % (self.wpapsk_5g, mac_list[0], mac_wpapsk))
466        mac_open = self.connect_to_network_and_verify_mac_randomization(
467            self.open_2g)
468        if mac_open != mac_list[1]:
469            raise signals.TestFailure(msg %
470                                      (self.open_5g, mac_list[1], mac_open))
471
472    @test_tracker_info(uuid="edb5a0e5-7f3b-4147-b1d3-48ad7ad9799e")
473    def test_mac_randomization_different_APs(self):
474        """Verify randomization using two different APs.
475
476        Steps:
477            1. Connect to network A on AP1, get the randomized MAC.
478            2. Connect to network B on AP2, get the randomized MAC.
479            3. Veirfy the two MACs are different.
480
481        """
482        ap1 = self.wpapsk_2g
483        ap2 = self.reference_networks[1]["5g"]
484        mac_ap1 = self.connect_to_network_and_verify_mac_randomization(ap1)
485        mac_ap2 = self.connect_to_network_and_verify_mac_randomization(ap2)
486        if mac_ap1 == mac_ap2:
487            raise signals.TestFailure(
488                "Same MAC address was generated for both "
489                "APs: %s" % mac_ap1)
490
491    @test_tracker_info(uuid="b815e9ce-bccd-4fc3-9774-1e1bc123a2a8")
492    def test_mac_randomization_ap_sta(self):
493        """Bring up STA and softAP and verify MAC randomization.
494
495        Steps:
496            1. Connect to a network and get randomized MAC.
497            2. Bring up softAP on the DUT.
498            3. Connect to softAP network on the client and get MAC.
499            4. Verify AP and STA use different randomized MACs.
500            5. Find the channel of the SoftAp network.
501            6. Configure sniffer on that channel.
502            7. Verify the factory MAC is not leaked.
503
504        """
505        wutils.set_wifi_country_code(self.dut, wutils.WifiEnums.CountryCode.US)
506        wutils.set_wifi_country_code(self.dut_client,
507                                     wutils.WifiEnums.CountryCode.US)
508        mac_sta = self.connect_to_network_and_verify_mac_randomization(
509            self.wpapsk_2g)
510        softap = wutils.start_softap_and_verify(self, WIFI_CONFIG_APBAND_2G)
511        wutils.connect_to_wifi_network(self.dut_client, softap)
512        softap_info = self.dut_client.droid.wifiGetConnectionInfo()
513        mac_ap = softap_info['mac_address']
514        if mac_sta == mac_ap:
515            raise signals.TestFailure("Same MAC address was used for both "
516                                      "AP and STA: %s" % mac_sta)
517
518        # Verify SoftAp MAC is randomized
519        softap_mac = self.get_soft_ap_mac_address()
520        message = (
521            'Randomized SoftAp MAC and Factory SoftAp MAC are the same. '
522            'Randomized SoftAp MAC = %s, Factory SoftAp MAC = %s' %
523            (softap_mac, self.soft_ap_factory_mac))
524        asserts.assert_true(softap_mac != self.soft_ap_factory_mac, message)
525
526        softap_channel = hostapd_constants.CHANNEL_MAP[
527            softap_info['frequency']]
528        self.log.info("softap_channel = %s\n" % (softap_channel))
529        result = self.packet_capture.configure_monitor_mode(
530            hostapd_constants.BAND_2G, softap_channel)
531        if not result:
532            raise ValueError("Failed to configure channel for 2G band")
533        self.pcap_procs = wutils.start_pcap(self.packet_capture, 'dual',
534                                            self.test_name)
535        # re-connect to the softAp network after sniffer is started
536        wutils.connect_to_wifi_network(self.dut_client, self.wpapsk_2g)
537        wutils.connect_to_wifi_network(self.dut_client, softap)
538        time.sleep(SHORT_TIMEOUT)
539        wutils.stop_pcap(self.packet_capture, self.pcap_procs, False)
540        pcap_fname = '%s_%s.pcap' % \
541            (self.pcap_procs[hostapd_constants.BAND_2G][1],
542             hostapd_constants.BAND_2G.upper())
543        packets = rdpcap(pcap_fname)
544        self.verify_mac_not_found_in_pcap(self.soft_ap_factory_mac, packets)
545        self.verify_mac_not_found_in_pcap(self.sta_factory_mac, packets)
546        self.verify_mac_is_found_in_pcap(softap_mac, packets)
547        self.verify_mac_is_found_in_pcap(self.get_sta_mac_address(), packets)
548
549    @test_tracker_info(uuid="3ca3f911-29f1-41fb-b836-4d25eac1669f")
550    def test_roaming_mac_randomization(self):
551        """test MAC randomization in the roaming scenario.
552
553        Steps:
554            1. Connect to network A on AP1, get randomized MAC.
555            2. Set AP1 to MAX attenuation so that we roam to AP2.
556            3. Wait for device to roam to AP2 and get randomized MAC.
557            4. Veirfy that the device uses same AMC for both APs.
558
559        """
560        AP1_network = self.reference_networks[0]["5g"]
561        AP2_network = self.reference_networks[1]["5g"]
562        if "OpenWrtAP" in self.user_params:
563            AP1_network["bssid"] = self.bssid_map[0]["5g"][AP1_network["SSID"]]
564            AP2_network["bssid"] = self.bssid_map[1]["5g"][AP2_network["SSID"]]
565        wutils.set_attns(self.attenuators, "AP1_on_AP2_off", self.roaming_attn)
566        mac_before_roam = self.connect_to_network_and_verify_mac_randomization(
567            AP1_network)
568        wutils.trigger_roaming_and_validate(self.dut, self.attenuators,
569                                            "AP1_off_AP2_on", AP2_network,
570                                            self.roaming_attn)
571        mac_after_roam = self.get_randomized_mac(AP2_network)
572        if mac_after_roam != mac_before_roam:
573            raise signals.TestFailure(
574                "Randomized MAC address changed after "
575                "roaming from AP1 to AP2.\nMAC before roam = %s\nMAC after "
576                "roam = %s" % (mac_before_roam, mac_after_roam))
577        wutils.trigger_roaming_and_validate(self.dut, self.attenuators,
578                                            "AP1_on_AP2_off", AP1_network,
579                                            self.roaming_attn)
580        mac_after_roam = self.get_randomized_mac(AP1_network)
581        if mac_after_roam != mac_before_roam:
582            raise signals.TestFailure(
583                "Randomized MAC address changed after "
584                "roaming from AP1 to AP2.\nMAC before roam = %s\nMAC after "
585                "roam = %s" % (mac_before_roam, mac_after_roam))
586
587    @test_tracker_info(uuid="17b12f1a-7c62-4188-b5a5-52d7a0bb7849")
588    def test_check_mac_sta_with_link_probe(self):
589        """Test to ensure Factory MAC is not exposed, using sniffer data.
590
591        Steps:
592            1. Configure and start the sniffer on 5GHz band.
593            2. Connect to 5GHz network.
594            3. Send link probes.
595            4. Stop the sniffer.
596            5. Invoke scapy to read the .pcap file.
597            6. Read each packet summary and make sure Factory MAC is not used.
598
599        """
600        self.pcap_procs = wutils.start_pcap(self.packet_capture, 'dual',
601                                            self.test_name)
602        time.sleep(SHORT_TIMEOUT)
603        network = self.wpapsk_5g
604        rand_mac = self.connect_to_network_and_verify_mac_randomization(
605            network)
606        pcap_fname_bflink = '%s_%s.pcap' % \
607            (self.pcap_procs[hostapd_constants.BAND_5G][1],
608             hostapd_constants.BAND_5G.upper())
609        wutils.stop_pcap(self.packet_capture, self.pcap_procs, False)
610        time.sleep(SHORT_TIMEOUT)
611        packets_bflink = rdpcap(pcap_fname_bflink)
612        self.verify_mac_not_found_in_pcap(self.sta_factory_mac, packets_bflink)
613        self.verify_mac_is_found_in_pcap(rand_mac, packets_bflink)
614        self.pcap_procs = wutils.start_pcap(self.packet_capture, 'dual',
615                                            self.test_name)
616        time.sleep(SHORT_TIMEOUT)
617        wutils.send_link_probes(self.dut, 3, 3)
618        pcap_fname = '%s_%s.pcap' % \
619            (self.pcap_procs[hostapd_constants.BAND_5G][1],
620             hostapd_constants.BAND_5G.upper())
621        wutils.stop_pcap(self.packet_capture, self.pcap_procs, False)
622        time.sleep(SHORT_TIMEOUT)
623        packets = rdpcap(pcap_fname)
624        self.verify_mac_not_found_in_pcap(self.sta_factory_mac, packets)
625        self.verify_mac_is_found_in_pcap(rand_mac, packets)
626
627    @test_tracker_info(uuid="1c2cc0fd-a340-40c4-b679-6acc5f526451")
628    def test_check_mac_in_wifi_scan(self):
629        """Test to ensure Factory MAC is not exposed, in Wi-Fi scans
630
631        Steps:
632          1. Configure and start the sniffer on both bands.
633          2. Perform a full scan.
634          3. Stop the sniffer.
635          4. Invoke scapy to read the .pcap file.
636          5. Read each packet summary and make sure Factory MAC is not used.
637
638        """
639        self.pcap_procs = wutils.start_pcap(self.packet_capture, 'dual',
640                                            self.test_name)
641        wutils.start_wifi_connection_scan(self.dut)
642        time.sleep(SHORT_TIMEOUT)
643        wutils.stop_pcap(self.packet_capture, self.pcap_procs, False)
644        pcap_fname = '%s_%s.pcap' % \
645            (self.pcap_procs[hostapd_constants.BAND_2G][1],
646             hostapd_constants.BAND_2G.upper())
647        packets = rdpcap(pcap_fname)
648        self.verify_mac_not_found_in_pcap(self.sta_factory_mac, packets)
649
650    @test_tracker_info(uuid="7714d31f-bb08-4f29-b246-0ce1398a3c03")
651    def test_mac_randomization_for_network_suggestion(self):
652        """Add network suggestion and verify MAC randomization.
653
654        Steps:
655            1. Add a network suggestion and verify device connects to it.
656            2. Verify the device uses randomized MAC address for this network.
657        """
658        network_suggestion = self.reference_networks[0]["2g"]
659        self._add_suggestion_and_verify_mac_randomization(network_suggestion)
660
661    @test_tracker_info(uuid="144ad0b4-b79d-4b1d-a8a9-3c612a76c32c")
662    def test_enhanced_mac_randomization_for_network_suggestion(self):
663        """Test enhanced MAC randomization.
664
665        Steps:
666            1. Add a network suggestion with enhanced mac randomization enabled.
667            2. Connect to the network and verify the MAC address is random.
668            3. Remove the suggestion network and add it back.
669            4. Connect to the network. Verify the MAC address is random and
670               different from the randomized MAC observed in step 2.
671        """
672        asserts.skip_if(not self.dut.droid.isSdkAtLeastS(),
673                        "This feature is only supported on S and later.")
674
675        network_suggestion = self.reference_networks[0]["5g"]
676        network_suggestion["enhancedMacRandomizationEnabled"] = True
677
678        # add network suggestion with enhanced mac randomization
679        randomized_mac1 = self._add_suggestion_and_verify_mac_randomization(
680            network_suggestion)
681
682        # remove network suggestion and verify no connection
683        self._remove_suggestion_and_verify_disconnect(network_suggestion)
684
685        # add network suggestion and verify device connects back
686        randomized_mac2 = self._add_suggestion_and_verify_mac_randomization(
687            network_suggestion)
688
689        # verify both randomized mac addrs are different
690        asserts.assert_true(randomized_mac1 != randomized_mac2,
691                            "Randomized MAC addresses are same.")
692