1# 2# Copyright 2017 - The Android Open Source Project 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15 16import pprint 17import random 18import time 19from acts import context 20from scapy.all import * 21 22from acts import asserts 23from acts import base_test 24from acts import signals 25from acts.test_decorators import test_tracker_info 26from acts.test_utils.wifi import wifi_test_utils as wutils 27from acts.test_utils.wifi.WifiBaseTest import WifiBaseTest 28 29WifiEnums = wutils.WifiEnums 30DEF_ATTN = 60 31MAX_ATTN = 95 32ROAM_DBM = -75 33WAIT_AFTER_ATTN = 12 34ATTN_STEP = 5 35 36class WifiRoamingTest(WifiBaseTest): 37 38 def setup_class(self): 39 """Setup required dependencies from config file and configure 40 the required networks for testing roaming. 41 42 Returns: 43 True if successfully configured the requirements for testing. 44 """ 45 super().setup_class() 46 47 self.dut = self.android_devices[0] 48 wutils.wifi_test_device_init(self.dut) 49 req_params = ["roaming_attn", "roam_interval", "ping_addr", 50 "max_bugreports"] 51 opt_param = ["open_network", "reference_networks",] 52 self.unpack_userparams( 53 req_param_names=req_params, opt_param_names=opt_param) 54 55 if "AccessPoint" in self.user_params: 56 self.legacy_configure_ap_and_start(ap_count=2) 57 58 asserts.assert_true( 59 len(self.reference_networks) > 1, 60 "Need at least two psk networks for roaming.") 61 asserts.assert_true( 62 len(self.open_network) > 1, 63 "Need at least two open networks for roaming") 64 65 66 self.configure_packet_capture() 67 68 def teardown_class(self): 69 self.dut.ed.clear_all_events() 70 if "AccessPoint" in self.user_params: 71 del self.user_params["reference_networks"] 72 del self.user_params["open_network"] 73 74 def setup_test(self): 75 self.dut.ed.clear_all_events() 76 self.dut.droid.wakeLockAcquireBright() 77 self.dut.droid.wakeUpNow() 78 79 def teardown_test(self): 80 self.dut.droid.wakeLockRelease() 81 self.dut.droid.goToSleepNow() 82 wutils.reset_wifi(self.dut) 83 for a in self.attenuators: 84 a.set_atten(0) 85 86 def on_fail(self, test_name, begin_time): 87 self.dut.cat_adb_log(test_name, begin_time) 88 self.dut.take_bug_report(test_name, begin_time) 89 90 def roaming_from_AP1_and_AP2(self, AP1_network, AP2_network): 91 """Test roaming between two APs. 92 93 Args: 94 AP1_network: AP-1's network information. 95 AP2_network: AP-2's network information. 96 97 Steps: 98 1. Make AP1 visible, AP2 not visible. 99 2. Connect to AP1's ssid. 100 3. Make AP1 not visible, AP2 visible. 101 4. Expect DUT to roam to AP2. 102 5. Validate connection information and ping. 103 """ 104 wutils.set_attns(self.attenuators, "AP1_on_AP2_off") 105 wifi_config = AP1_network.copy() 106 wifi_config.pop("bssid") 107 wutils.connect_to_wifi_network(self.dut, wifi_config) 108 self.log.info("Roaming from %s to %s", AP1_network, AP2_network) 109 wutils.trigger_roaming_and_validate( 110 self.dut, self.attenuators, "AP1_off_AP2_on", AP2_network) 111 112 def get_rssi(self, pcap_file, expected_bssid): 113 """Get signal strength of the wifi network attenuated. 114 115 Args: 116 pcap_file: PCAP file path. 117 expected_bssid: BSSID of the wifi network attenuated. 118 """ 119 packets = [] 120 try: 121 packets = rdpcap(pcap_file) 122 except Scapy_Exception: 123 self.log.error("Failed to read pcap file") 124 if not packets: 125 return 0 126 127 dbm = -100 128 for pkt in packets: 129 if pkt and hasattr(pkt, 'type') and pkt.type == 0 and \ 130 pkt.subtype == 8 and hasattr(pkt, 'info'): 131 bssid = pkt.addr3 132 if expected_bssid == bssid: 133 dbm = int(pkt.dBm_AntSignal) 134 self.log.info("RSSI: %s" % dbm) 135 return dbm 136 137 def trigger_roaming_and_verify_attenuation(self, network): 138 """Trigger roaming and verify signal strength is below roaming limit. 139 140 Args: 141 network: Wifi network that is being attenuated. 142 """ 143 wutils.set_attns_steps(self.attenuators, "AP1_off_AP2_on") 144 band = '5G' if network['SSID'].startswith('5g_') else '2G' 145 attn = DEF_ATTN + ATTN_STEP 146 while attn <= MAX_ATTN: 147 self.pcap_procs = wutils.start_pcap( 148 self.packet_capture, 'dual', self.test_name) 149 time.sleep(WAIT_AFTER_ATTN/3) 150 wutils.stop_pcap(self.packet_capture, self.pcap_procs, False) 151 pcap_file = os.path.join( 152 context.get_current_context().get_full_output_path(), 153 'PacketCapture', 154 '%s_%s.pcap' % (self.test_name, band)) 155 156 rssi = self.get_rssi(pcap_file, network["bssid"]) 157 if rssi == 0: 158 self.log.error("Failed to verify signal strength") 159 break 160 if self.get_rssi(pcap_file, network["bssid"]) < ROAM_DBM: 161 break 162 163 self.attenuators[0].set_atten(attn) 164 self.attenuators[1].set_atten(attn) 165 time.sleep(WAIT_AFTER_ATTN) # allow some time for attenuation 166 attn += 5 167 168 def validate_roaming(self, expected_con): 169 """Validate roaming. 170 171 Args: 172 expected_con: Expected wifi network after roaming. 173 """ 174 expected_con = { 175 WifiEnums.SSID_KEY: expected_con[WifiEnums.SSID_KEY], 176 WifiEnums.BSSID_KEY: expected_con["bssid"], 177 } 178 curr_con = self.dut.droid.wifiGetConnectionInfo() 179 for key in expected_con: 180 if expected_con[key] != curr_con[key]: 181 asserts.fail("Expected '%s' to be %s, actual is %s." % 182 (key, expected_con[key], curr_con[key])) 183 self.log.info("Roamed to %s successfully", 184 expected_con[WifiEnums.BSSID_KEY]) 185 if not wutils.validate_connection(self.dut): 186 raise signals.TestFailure("Fail to connect to internet on %s" % 187 expected_con[WifiEnums.BSSID_KEY]) 188 189 """ Tests Begin. 190 191 The following tests are designed to test inter-SSID Roaming only. 192 193 """ 194 @test_tracker_info(uuid="db8a46f9-713f-4b98-8d9f-d36319905b0a") 195 def test_roaming_between_AP1_to_AP2_open_2g(self): 196 AP1_network = self.open_network[0]["2g"] 197 AP2_network = self.open_network[1]["2g"] 198 self.roaming_from_AP1_and_AP2(AP1_network, AP2_network) 199 200 @test_tracker_info(uuid="0db67d9b-6ea9-4f40-acf2-155c4ecf9dc5") 201 def test_roaming_between_AP1_to_AP2_open_5g(self): 202 AP1_network = self.open_network[0]["5g"] 203 AP2_network = self.open_network[1]["5g"] 204 self.roaming_from_AP1_and_AP2(AP1_network, AP2_network) 205 206 @test_tracker_info(uuid="eabc7319-d962-4bef-b679-725e9ff00420") 207 def test_roaming_between_AP1_to_AP2_psk_2g(self): 208 AP1_network = self.reference_networks[0]["2g"] 209 AP2_network = self.reference_networks[1]["2g"] 210 self.roaming_from_AP1_and_AP2(AP1_network, AP2_network) 211 212 @test_tracker_info(uuid="1cf9c681-4ff0-45c1-9719-f01629f6a7f7") 213 def test_roaming_between_AP1_to_AP2_psk_5g(self): 214 AP1_network = self.reference_networks[0]["5g"] 215 AP2_network = self.reference_networks[1]["5g"] 216 self.roaming_from_AP1_and_AP2(AP1_network, AP2_network) 217 218 @test_tracker_info(uuid="3114d625-5cdd-4205-bb46-5a9d057dc80d") 219 def test_roaming_fail_psk_2g(self): 220 network = {'SSID':'test_roaming_fail', 'password':'roam123456@'} 221 # AP2 network with incorrect password. 222 network_fail = {'SSID':'test_roaming_fail', 'password':'roam123456@#$%^'} 223 # Setup AP1 with the correct password. 224 wutils.ap_setup(self, 0, self.access_points[0], network) 225 network_bssid = self.access_points[0].get_bssid_from_ssid( 226 network["SSID"], '2g') 227 # Setup AP2 with the incorrect password. 228 wutils.ap_setup(self, 1, self.access_points[1], network_fail) 229 network_fail_bssid = self.access_points[1].get_bssid_from_ssid( 230 network_fail["SSID"], '2g') 231 network['bssid'] = network_bssid 232 network_fail['bssid'] = network_fail_bssid 233 try: 234 # Initiate roaming with AP2 configured with incorrect password. 235 self.roaming_from_AP1_and_AP2(network, network_fail) 236 except: 237 self.log.info("Roaming failed to AP2 with incorrect password.") 238 # Re-configure AP2 after roaming failed, with correct password. 239 self.log.info("Re-configuring AP2 with correct password.") 240 wutils.ap_setup(self, 1, self.access_points[1], network) 241 self.roaming_from_AP1_and_AP2(network, network_fail) 242 243 """ Tests End """ 244