| #!/usr/bin/env python3.4 |
| # |
| # Copyright 2018 - The Android Open Source Project |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| import itertools |
| import time |
| |
| import acts.base_test |
| import acts.signals as signals |
| from acts_contrib.test_utils.tel.tel_wifi_utils import WIFI_CONFIG_APBAND_2G |
| import acts_contrib.test_utils.wifi.wifi_test_utils as wutils |
| import acts.utils as utils |
| |
| from acts import asserts |
| from acts.test_decorators import test_tracker_info |
| from acts_contrib.test_utils.wifi.WifiBaseTest import WifiBaseTest |
| |
| WifiEnums = wutils.WifiEnums |
| # Default timeout used for reboot, toggle WiFi and Airplane mode, |
| # for the system to settle down after the operation. |
| DEFAULT_TIMEOUT = 10 |
| GET_MAC_ADDRESS = ("ip addr show wlan0" |
| "| grep 'link/ether'" |
| "| cut -d ' ' -f6") |
| MAC_SETTING = "wifi_connected_mac_randomization_enabled" |
| GET_MAC_RANDOMIZATION_STATUS = "settings get global {}".format(MAC_SETTING) |
| TURN_ON_MAC_RANDOMIZATION = "settings put global {} 1".format(MAC_SETTING) |
| TURN_OFF_MAC_RANDOMIZATION = "settings put global {} 0".format(MAC_SETTING) |
| LOG_CLEAR = "logcat -c" |
| LOG_GREP = "logcat -d | grep {}" |
| |
| |
| class WifiConnectedMacRandomizationTest(WifiBaseTest): |
| """Tests for Connected MAC Randomization. |
| |
| Test Bed Requirement: |
| * Two Android devices with the first one supporting MAC randomization. |
| * At least two Wi-Fi networks to connect to. |
| """ |
| |
| def setup_class(self): |
| super().setup_class() |
| |
| self.dut = self.android_devices[0] |
| self.dut_softap = self.android_devices[1] |
| wutils.wifi_test_device_init(self.dut) |
| wutils.wifi_test_device_init(self.dut_softap) |
| |
| self.reset_mac_address_to_factory_mac() |
| self.dut.adb.shell(TURN_ON_MAC_RANDOMIZATION) |
| asserts.assert_equal( |
| self.dut.adb.shell(GET_MAC_RANDOMIZATION_STATUS), "1", |
| "Failed to enable Connected MAC Randomization on dut.") |
| |
| req_params = ["reference_networks"] |
| opt_param = [] |
| self.unpack_userparams(req_param_names=req_params, |
| opt_param_names=opt_param) |
| |
| if "AccessPoint" in self.user_params: |
| self.legacy_configure_ap_and_start() |
| |
| asserts.assert_true( |
| self.reference_networks[0]["2g"], |
| "Need at least 1 2.4Ghz reference network with psk.") |
| asserts.assert_true( |
| self.reference_networks[0]["5g"], |
| "Need at least 1 5Ghz reference network with psk.") |
| self.wpapsk_2g = self.reference_networks[0]["2g"] |
| self.wpapsk_5g = self.reference_networks[0]["5g"] |
| |
| def setup_test(self): |
| super().setup_test() |
| self.dut.droid.wakeLockAcquireBright() |
| self.dut.droid.wakeUpNow() |
| wutils.wifi_toggle_state(self.dut, True) |
| wutils.wifi_toggle_state(self.dut_softap, False) |
| |
| def teardown_test(self): |
| super().teardown_test() |
| self.dut.droid.wakeLockRelease() |
| self.dut.droid.goToSleepNow() |
| wutils.reset_wifi(self.dut) |
| wutils.reset_wifi(self.dut_softap) |
| |
| def teardown_class(self): |
| wutils.stop_wifi_tethering(self.dut_softap) |
| self.reset_mac_address_to_factory_mac() |
| if "AccessPoint" in self.user_params: |
| del self.user_params["reference_networks"] |
| del self.user_params["open_network"] |
| |
| """Helper Functions""" |
| |
| def get_current_mac_address(self, ad): |
| """Get the device's wlan0 MAC address. |
| |
| Args: |
| ad: AndroidDevice to get MAC address of. |
| |
| Returns: |
| A MAC address string in the format of "12:34:56:78:90:12". |
| """ |
| return ad.adb.shell(GET_MAC_ADDRESS) |
| |
| def is_valid_randomized_mac_address(self, mac): |
| """Check if the given MAC address is a valid randomized MAC address. |
| |
| Args: |
| mac: MAC address to check in the format of "12:34:56:78:90:12". |
| """ |
| asserts.assert_true( |
| mac != self.dut_factory_mac, |
| "Randomized MAC address is same as factory MAC address.") |
| first_byte = int(mac[:2], 16) |
| asserts.assert_equal(first_byte & 1, 0, "MAC address is not unicast.") |
| asserts.assert_equal(first_byte & 2, 2, "MAC address is not local.") |
| |
| def reset_mac_address_to_factory_mac(self): |
| """Reset dut to and store factory MAC address by turning off |
| Connected MAC Randomization and rebooting dut. |
| """ |
| self.dut.adb.shell(TURN_OFF_MAC_RANDOMIZATION) |
| asserts.assert_equal( |
| self.dut.adb.shell(GET_MAC_RANDOMIZATION_STATUS), "0", |
| "Failed to disable Connected MAC Randomization on dut.") |
| self.dut.reboot() |
| time.sleep(DEFAULT_TIMEOUT) |
| self.dut_factory_mac = self.get_current_mac_address(self.dut) |
| |
| def get_connection_data(self, ad, network): |
| """Connect and get network id and ssid info from connection data. |
| |
| Args: |
| ad: AndroidDevice to use for connection |
| network: network info of the network to connect to |
| |
| Returns: |
| A convenience dict with the connected network's ID and SSID. |
| """ |
| wutils.connect_to_wifi_network(ad, network) |
| connect_data = ad.droid.wifiGetConnectionInfo() |
| ssid_id_dict = dict() |
| ssid_id_dict[WifiEnums.NETID_KEY] = connect_data[WifiEnums.NETID_KEY] |
| ssid_id_dict[WifiEnums.SSID_KEY] = connect_data[WifiEnums.SSID_KEY] |
| return ssid_id_dict |
| |
| """Tests""" |
| |
| @test_tracker_info(uuid="") |
| def test_wifi_connection_2G_with_mac_randomization(self): |
| """Tests connection to 2G network with Connected MAC Randomization. |
| """ |
| wutils.connect_to_wifi_network(self.dut, self.wpapsk_2g) |
| mac = self.get_current_mac_address(self.dut) |
| self.is_valid_randomized_mac_address(mac) |
| |
| @test_tracker_info(uuid="") |
| def test_wifi_connection_5G_with_mac_randomization(self): |
| """Tests connection to 5G network with Connected MAC Randomization. |
| """ |
| wutils.connect_to_wifi_network(self.dut, self.wpapsk_5g) |
| mac = self.get_current_mac_address(self.dut) |
| self.is_valid_randomized_mac_address(mac) |
| |
| @test_tracker_info(uuid="") |
| def test_randomized_mac_persistent_between_connections(self): |
| """Tests that randomized MAC address assigned to each network is |
| persistent between connections. |
| |
| Steps: |
| 1. Connect to a 2GHz network. |
| 2. Connect to a 5GHz network. |
| 3. Reconnect to the 2GHz network using its network id. |
| 4. Verify that MAC addresses in Steps 1 and 3 are equal. |
| 5. Reconnect to the 5GHz network using its network id. |
| 6. Verify that MAC addresses in Steps 2 and 5 are equal. |
| """ |
| connect_data_2g = self.get_connection_data(self.dut, self.wpapsk_2g) |
| old_mac_2g = self.get_current_mac_address(self.dut) |
| self.is_valid_randomized_mac_address(old_mac_2g) |
| |
| connect_data_5g = self.get_connection_data(self.dut, self.wpapsk_5g) |
| old_mac_5g = self.get_current_mac_address(self.dut) |
| self.is_valid_randomized_mac_address(old_mac_5g) |
| |
| asserts.assert_true( |
| old_mac_2g != old_mac_5g, |
| "Randomized MAC addresses for 2G and 5G networks are equal.") |
| |
| reconnect_2g = wutils.connect_to_wifi_network_with_id( |
| self.dut, connect_data_2g[WifiEnums.NETID_KEY], |
| connect_data_2g[WifiEnums.SSID_KEY]) |
| if not reconnect_2g: |
| raise signals.TestFailure("Device did not connect to the correct" |
| " 2GHz network.") |
| new_mac_2g = self.get_current_mac_address(self.dut) |
| asserts.assert_equal( |
| old_mac_2g, new_mac_2g, |
| "Randomized MAC for 2G is not persistent between connections.") |
| |
| reconnect_5g = wutils.connect_to_wifi_network_with_id( |
| self.dut, connect_data_5g[WifiEnums.NETID_KEY], |
| connect_data_5g[WifiEnums.SSID_KEY]) |
| if not reconnect_5g: |
| raise signals.TestFailure("Device did not connect to the correct" |
| " 5GHz network.") |
| new_mac_5g = self.get_current_mac_address(self.dut) |
| asserts.assert_equal( |
| old_mac_5g, new_mac_5g, |
| "Randomized MAC for 5G is not persistent between connections.") |
| |
| @test_tracker_info(uuid="") |
| def test_randomized_mac_used_during_connection(self): |
| """Verify that the randomized MAC address and not the factory |
| MAC address is used during connection by checking the softap logs. |
| |
| Steps: |
| 1. Set up softAP on dut_softap. |
| 2. Have dut connect to the softAp. |
| 3. Verify that only randomized MAC appears in softAp logs. |
| """ |
| self.dut_softap.adb.shell(LOG_CLEAR) |
| config = wutils.create_softap_config() |
| wutils.start_wifi_tethering(self.dut_softap, |
| config[wutils.WifiEnums.SSID_KEY], |
| config[wutils.WifiEnums.PWD_KEY], |
| WIFI_CONFIG_APBAND_2G) |
| |
| # Internet validation fails when dut_softap does not have a valid sim |
| # supporting softap. Since this test is not checking for internet |
| # validation, we suppress failure signals. |
| wutils.connect_to_wifi_network(self.dut, config, assert_on_fail=False) |
| mac = self.get_current_mac_address(self.dut) |
| wutils.stop_wifi_tethering(self.dut_softap) |
| |
| self.is_valid_randomized_mac_address(mac) |
| log = self.dut_softap.adb.shell(LOG_GREP.format(mac)) |
| asserts.assert_true(len(log) > 0, "Randomized MAC not in log.") |
| log = self.dut_softap.adb.shell(LOG_GREP.format(self.dut_factory_mac)) |
| asserts.assert_true(len(log) == 0, "Factory MAC is in log.") |