#!/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.")