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 pprint 19import queue 20import time 21 22import acts.base_test 23import acts.signals as signals 24from acts_contrib.test_utils.tel.tel_test_utils import WIFI_CONFIG_APBAND_2G 25import acts_contrib.test_utils.wifi.wifi_test_utils as wutils 26import acts.utils as utils 27 28from acts import asserts 29from acts.test_decorators import test_tracker_info 30from acts_contrib.test_utils.wifi.WifiBaseTest import WifiBaseTest 31 32WifiEnums = wutils.WifiEnums 33# Default timeout used for reboot, toggle WiFi and Airplane mode, 34# for the system to settle down after the operation. 35DEFAULT_TIMEOUT = 10 36GET_MAC_ADDRESS= ("ip addr show wlan0" 37 "| grep 'link/ether'" 38 "| cut -d ' ' -f6") 39MAC_SETTING = "wifi_connected_mac_randomization_enabled" 40GET_MAC_RANDOMIZATION_STATUS = "settings get global {}".format(MAC_SETTING) 41TURN_ON_MAC_RANDOMIZATION = "settings put global {} 1".format(MAC_SETTING) 42TURN_OFF_MAC_RANDOMIZATION = "settings put global {} 0".format(MAC_SETTING) 43LOG_CLEAR = "logcat -c" 44LOG_GREP = "logcat -d | grep {}" 45 46class WifiConnectedMacRandomizationTest(WifiBaseTest): 47 """Tests for Connected MAC Randomization. 48 49 Test Bed Requirement: 50 * Two Android devices with the first one supporting MAC randomization. 51 * At least two Wi-Fi networks to connect to. 52 """ 53 54 def setup_class(self): 55 super().setup_class() 56 57 self.dut = self.android_devices[0] 58 self.dut_softap = self.android_devices[1] 59 wutils.wifi_test_device_init(self.dut) 60 wutils.wifi_test_device_init(self.dut_softap) 61 62 self.reset_mac_address_to_factory_mac() 63 self.dut.adb.shell(TURN_ON_MAC_RANDOMIZATION) 64 asserts.assert_equal( 65 self.dut.adb.shell(GET_MAC_RANDOMIZATION_STATUS), "1", 66 "Failed to enable Connected MAC Randomization on dut.") 67 68 req_params = ["reference_networks"] 69 opt_param = [] 70 self.unpack_userparams( 71 req_param_names=req_params, opt_param_names=opt_param) 72 73 if "AccessPoint" in self.user_params: 74 self.legacy_configure_ap_and_start() 75 76 asserts.assert_true( 77 self.reference_networks[0]["2g"], 78 "Need at least 1 2.4Ghz reference network with psk.") 79 asserts.assert_true( 80 self.reference_networks[0]["5g"], 81 "Need at least 1 5Ghz reference network with psk.") 82 self.wpapsk_2g = self.reference_networks[0]["2g"] 83 self.wpapsk_5g = self.reference_networks[0]["5g"] 84 85 def setup_test(self): 86 super().setup_test() 87 self.dut.droid.wakeLockAcquireBright() 88 self.dut.droid.wakeUpNow() 89 wutils.wifi_toggle_state(self.dut, True) 90 wutils.wifi_toggle_state(self.dut_softap, False) 91 92 def teardown_test(self): 93 super().teardown_test() 94 self.dut.droid.wakeLockRelease() 95 self.dut.droid.goToSleepNow() 96 wutils.reset_wifi(self.dut) 97 wutils.reset_wifi(self.dut_softap) 98 99 def teardown_class(self): 100 wutils.stop_wifi_tethering(self.dut_softap) 101 self.reset_mac_address_to_factory_mac() 102 if "AccessPoint" in self.user_params: 103 del self.user_params["reference_networks"] 104 del self.user_params["open_network"] 105 106 """Helper Functions""" 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 @test_tracker_info(uuid="") 162 def test_wifi_connection_2G_with_mac_randomization(self): 163 """Tests connection to 2G network with Connected MAC Randomization. 164 """ 165 wutils.connect_to_wifi_network(self.dut, self.wpapsk_2g) 166 mac = self.get_current_mac_address(self.dut) 167 self.is_valid_randomized_mac_address(mac) 168 169 @test_tracker_info(uuid="") 170 def test_wifi_connection_5G_with_mac_randomization(self): 171 """Tests connection to 5G network with Connected MAC Randomization. 172 """ 173 wutils.connect_to_wifi_network(self.dut, self.wpapsk_5g) 174 mac = self.get_current_mac_address(self.dut) 175 self.is_valid_randomized_mac_address(mac) 176 177 @test_tracker_info(uuid="") 178 def test_randomized_mac_persistent_between_connections(self): 179 """Tests that randomized MAC address assigned to each network is 180 persistent between connections. 181 182 Steps: 183 1. Connect to a 2GHz network. 184 2. Connect to a 5GHz network. 185 3. Reconnect to the 2GHz network using its network id. 186 4. Verify that MAC addresses in Steps 1 and 3 are equal. 187 5. Reconnect to the 5GHz network using its network id. 188 6. Verify that MAC addresses in Steps 2 and 5 are equal. 189 """ 190 connect_data_2g = self.get_connection_data(self.dut, self.wpapsk_2g) 191 old_mac_2g = self.get_current_mac_address(self.dut) 192 self.is_valid_randomized_mac_address(old_mac_2g) 193 194 connect_data_5g = self.get_connection_data(self.dut, self.wpapsk_5g) 195 old_mac_5g = self.get_current_mac_address(self.dut) 196 self.is_valid_randomized_mac_address(old_mac_5g) 197 198 asserts.assert_true( 199 old_mac_2g != old_mac_5g, 200 "Randomized MAC addresses for 2G and 5G networks are equal.") 201 202 reconnect_2g = wutils.connect_to_wifi_network_with_id( 203 self.dut, 204 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, 212 new_mac_2g, 213 "Randomized MAC for 2G is not persistent between connections.") 214 215 reconnect_5g = wutils.connect_to_wifi_network_with_id( 216 self.dut, 217 connect_data_5g[WifiEnums.NETID_KEY], 218 connect_data_5g[WifiEnums.SSID_KEY]) 219 if not reconnect_5g: 220 raise signals.TestFailure("Device did not connect to the correct" 221 " 5GHz network.") 222 new_mac_5g = self.get_current_mac_address(self.dut) 223 asserts.assert_equal( 224 old_mac_5g, 225 new_mac_5g, 226 "Randomized MAC for 5G is not persistent between connections.") 227 228 @test_tracker_info(uuid="") 229 def test_randomized_mac_used_during_connection(self): 230 """Verify that the randomized MAC address and not the factory 231 MAC address is used during connection by checking the softap logs. 232 233 Steps: 234 1. Set up softAP on dut_softap. 235 2. Have dut connect to the softAp. 236 3. Verify that only randomized MAC appears in softAp logs. 237 """ 238 self.dut_softap.adb.shell(LOG_CLEAR) 239 config = wutils.create_softap_config() 240 wutils.start_wifi_tethering(self.dut_softap, 241 config[wutils.WifiEnums.SSID_KEY], 242 config[wutils.WifiEnums.PWD_KEY], 243 WIFI_CONFIG_APBAND_2G) 244 245 # Internet validation fails when dut_softap does not have a valid sim 246 # supporting softap. Since this test is not checking for internet 247 # validation, we suppress failure signals. 248 wutils.connect_to_wifi_network(self.dut, config, assert_on_fail=False) 249 mac = self.get_current_mac_address(self.dut) 250 wutils.stop_wifi_tethering(self.dut_softap) 251 252 self.is_valid_randomized_mac_address(mac) 253 log = self.dut_softap.adb.shell(LOG_GREP.format(mac)) 254 asserts.assert_true(len(log) > 0, "Randomized MAC not in log.") 255 log = self.dut_softap.adb.shell(LOG_GREP.format(self.dut_factory_mac)) 256 asserts.assert_true(len(log) == 0, "Factory MAC is in log.") 257