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 time 19 20import acts.base_test 21import acts.signals as signals 22from acts_contrib.test_utils.tel.tel_wifi_utils import WIFI_CONFIG_APBAND_2G 23import acts_contrib.test_utils.wifi.wifi_test_utils as wutils 24import acts.utils as utils 25 26from acts import asserts 27from acts.test_decorators import test_tracker_info 28from acts_contrib.test_utils.wifi.WifiBaseTest import WifiBaseTest 29 30WifiEnums = wutils.WifiEnums 31# Default timeout used for reboot, toggle WiFi and Airplane mode, 32# for the system to settle down after the operation. 33DEFAULT_TIMEOUT = 10 34GET_MAC_ADDRESS = ("ip addr show wlan0" 35 "| grep 'link/ether'" 36 "| cut -d ' ' -f6") 37MAC_SETTING = "wifi_connected_mac_randomization_enabled" 38GET_MAC_RANDOMIZATION_STATUS = "settings get global {}".format(MAC_SETTING) 39TURN_ON_MAC_RANDOMIZATION = "settings put global {} 1".format(MAC_SETTING) 40TURN_OFF_MAC_RANDOMIZATION = "settings put global {} 0".format(MAC_SETTING) 41LOG_CLEAR = "logcat -c" 42LOG_GREP = "logcat -d | grep {}" 43 44 45class WifiConnectedMacRandomizationTest(WifiBaseTest): 46 """Tests for Connected MAC Randomization. 47 48 Test Bed Requirement: 49 * Two Android devices with the first one supporting MAC randomization. 50 * At least two Wi-Fi networks to connect to. 51 """ 52 53 def setup_class(self): 54 super().setup_class() 55 56 self.dut = self.android_devices[0] 57 self.dut_softap = self.android_devices[1] 58 wutils.wifi_test_device_init(self.dut) 59 wutils.wifi_test_device_init(self.dut_softap) 60 61 self.reset_mac_address_to_factory_mac() 62 self.dut.adb.shell(TURN_ON_MAC_RANDOMIZATION) 63 asserts.assert_equal( 64 self.dut.adb.shell(GET_MAC_RANDOMIZATION_STATUS), "1", 65 "Failed to enable Connected MAC Randomization on dut.") 66 67 req_params = ["reference_networks"] 68 opt_param = [] 69 self.unpack_userparams(req_param_names=req_params, 70 opt_param_names=opt_param) 71 72 if "AccessPoint" in self.user_params: 73 self.legacy_configure_ap_and_start() 74 75 asserts.assert_true( 76 self.reference_networks[0]["2g"], 77 "Need at least 1 2.4Ghz reference network with psk.") 78 asserts.assert_true( 79 self.reference_networks[0]["5g"], 80 "Need at least 1 5Ghz reference network with psk.") 81 self.wpapsk_2g = self.reference_networks[0]["2g"] 82 self.wpapsk_5g = self.reference_networks[0]["5g"] 83 84 def setup_test(self): 85 super().setup_test() 86 self.dut.droid.wakeLockAcquireBright() 87 self.dut.droid.wakeUpNow() 88 wutils.wifi_toggle_state(self.dut, True) 89 wutils.wifi_toggle_state(self.dut_softap, False) 90 91 def teardown_test(self): 92 super().teardown_test() 93 self.dut.droid.wakeLockRelease() 94 self.dut.droid.goToSleepNow() 95 wutils.reset_wifi(self.dut) 96 wutils.reset_wifi(self.dut_softap) 97 98 def teardown_class(self): 99 wutils.stop_wifi_tethering(self.dut_softap) 100 self.reset_mac_address_to_factory_mac() 101 if "AccessPoint" in self.user_params: 102 del self.user_params["reference_networks"] 103 del self.user_params["open_network"] 104 105 """Helper Functions""" 106 107 def get_current_mac_address(self, ad): 108 """Get the device's wlan0 MAC address. 109 110 Args: 111 ad: AndroidDevice to get MAC address of. 112 113 Returns: 114 A MAC address string in the format of "12:34:56:78:90:12". 115 """ 116 return ad.adb.shell(GET_MAC_ADDRESS) 117 118 def is_valid_randomized_mac_address(self, mac): 119 """Check if the given MAC address is a valid randomized MAC address. 120 121 Args: 122 mac: MAC address to check in the format of "12:34:56:78:90:12". 123 """ 124 asserts.assert_true( 125 mac != self.dut_factory_mac, 126 "Randomized MAC address is same as factory MAC address.") 127 first_byte = int(mac[:2], 16) 128 asserts.assert_equal(first_byte & 1, 0, "MAC address is not unicast.") 129 asserts.assert_equal(first_byte & 2, 2, "MAC address is not local.") 130 131 def reset_mac_address_to_factory_mac(self): 132 """Reset dut to and store factory MAC address by turning off 133 Connected MAC Randomization and rebooting dut. 134 """ 135 self.dut.adb.shell(TURN_OFF_MAC_RANDOMIZATION) 136 asserts.assert_equal( 137 self.dut.adb.shell(GET_MAC_RANDOMIZATION_STATUS), "0", 138 "Failed to disable Connected MAC Randomization on dut.") 139 self.dut.reboot() 140 time.sleep(DEFAULT_TIMEOUT) 141 self.dut_factory_mac = self.get_current_mac_address(self.dut) 142 143 def get_connection_data(self, ad, network): 144 """Connect and get network id and ssid info from connection data. 145 146 Args: 147 ad: AndroidDevice to use for connection 148 network: network info of the network to connect to 149 150 Returns: 151 A convenience dict with the connected network's ID and SSID. 152 """ 153 wutils.connect_to_wifi_network(ad, network) 154 connect_data = ad.droid.wifiGetConnectionInfo() 155 ssid_id_dict = dict() 156 ssid_id_dict[WifiEnums.NETID_KEY] = connect_data[WifiEnums.NETID_KEY] 157 ssid_id_dict[WifiEnums.SSID_KEY] = connect_data[WifiEnums.SSID_KEY] 158 return ssid_id_dict 159 160 """Tests""" 161 162 @test_tracker_info(uuid="") 163 def test_wifi_connection_2G_with_mac_randomization(self): 164 """Tests connection to 2G network with Connected MAC Randomization. 165 """ 166 wutils.connect_to_wifi_network(self.dut, self.wpapsk_2g) 167 mac = self.get_current_mac_address(self.dut) 168 self.is_valid_randomized_mac_address(mac) 169 170 @test_tracker_info(uuid="") 171 def test_wifi_connection_5G_with_mac_randomization(self): 172 """Tests connection to 5G network with Connected MAC Randomization. 173 """ 174 wutils.connect_to_wifi_network(self.dut, self.wpapsk_5g) 175 mac = self.get_current_mac_address(self.dut) 176 self.is_valid_randomized_mac_address(mac) 177 178 @test_tracker_info(uuid="") 179 def test_randomized_mac_persistent_between_connections(self): 180 """Tests that randomized MAC address assigned to each network is 181 persistent between connections. 182 183 Steps: 184 1. Connect to a 2GHz network. 185 2. Connect to a 5GHz network. 186 3. Reconnect to the 2GHz network using its network id. 187 4. Verify that MAC addresses in Steps 1 and 3 are equal. 188 5. Reconnect to the 5GHz network using its network id. 189 6. Verify that MAC addresses in Steps 2 and 5 are equal. 190 """ 191 connect_data_2g = self.get_connection_data(self.dut, self.wpapsk_2g) 192 old_mac_2g = self.get_current_mac_address(self.dut) 193 self.is_valid_randomized_mac_address(old_mac_2g) 194 195 connect_data_5g = self.get_connection_data(self.dut, self.wpapsk_5g) 196 old_mac_5g = self.get_current_mac_address(self.dut) 197 self.is_valid_randomized_mac_address(old_mac_5g) 198 199 asserts.assert_true( 200 old_mac_2g != old_mac_5g, 201 "Randomized MAC addresses for 2G and 5G networks are equal.") 202 203 reconnect_2g = wutils.connect_to_wifi_network_with_id( 204 self.dut, connect_data_2g[WifiEnums.NETID_KEY], 205 connect_data_2g[WifiEnums.SSID_KEY]) 206 if not reconnect_2g: 207 raise signals.TestFailure("Device did not connect to the correct" 208 " 2GHz network.") 209 new_mac_2g = self.get_current_mac_address(self.dut) 210 asserts.assert_equal( 211 old_mac_2g, new_mac_2g, 212 "Randomized MAC for 2G is not persistent between connections.") 213 214 reconnect_5g = wutils.connect_to_wifi_network_with_id( 215 self.dut, connect_data_5g[WifiEnums.NETID_KEY], 216 connect_data_5g[WifiEnums.SSID_KEY]) 217 if not reconnect_5g: 218 raise signals.TestFailure("Device did not connect to the correct" 219 " 5GHz network.") 220 new_mac_5g = self.get_current_mac_address(self.dut) 221 asserts.assert_equal( 222 old_mac_5g, new_mac_5g, 223 "Randomized MAC for 5G is not persistent between connections.") 224 225 @test_tracker_info(uuid="") 226 def test_randomized_mac_used_during_connection(self): 227 """Verify that the randomized MAC address and not the factory 228 MAC address is used during connection by checking the softap logs. 229 230 Steps: 231 1. Set up softAP on dut_softap. 232 2. Have dut connect to the softAp. 233 3. Verify that only randomized MAC appears in softAp logs. 234 """ 235 self.dut_softap.adb.shell(LOG_CLEAR) 236 config = wutils.create_softap_config() 237 wutils.start_wifi_tethering(self.dut_softap, 238 config[wutils.WifiEnums.SSID_KEY], 239 config[wutils.WifiEnums.PWD_KEY], 240 WIFI_CONFIG_APBAND_2G) 241 242 # Internet validation fails when dut_softap does not have a valid sim 243 # supporting softap. Since this test is not checking for internet 244 # validation, we suppress failure signals. 245 wutils.connect_to_wifi_network(self.dut, config, assert_on_fail=False) 246 mac = self.get_current_mac_address(self.dut) 247 wutils.stop_wifi_tethering(self.dut_softap) 248 249 self.is_valid_randomized_mac_address(mac) 250 log = self.dut_softap.adb.shell(LOG_GREP.format(mac)) 251 asserts.assert_true(len(log) > 0, "Randomized MAC not in log.") 252 log = self.dut_softap.adb.shell(LOG_GREP.format(self.dut_factory_mac)) 253 asserts.assert_true(len(log) == 0, "Factory MAC is in log.") 254