1#!/usr/bin/env python3.4 2# 3# Copyright 2021 - 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 acts.asserts as asserts 18from acts.controllers.android_device import SL4A_APK_NAME 19from acts.test_decorators import test_tracker_info 20from acts_contrib.test_utils.wifi.WifiBaseTest import WifiBaseTest 21import acts_contrib.test_utils.net.connectivity_const as cconsts 22import acts_contrib.test_utils.wifi.wifi_test_utils as wutils 23import acts_contrib.test_utils.wifi.aware.aware_test_utils as autils 24 25WifiEnums = wutils.WifiEnums 26 27WIFI_NETWORK_AP_CHANNEL_2G_1 = 1 28WIFI_NETWORK_AP_CHANNEL_5G_1 = 36 29WIFI_NETWORK_AP_CHANNEL_5G_DFS_1 = 132 30 31WIFI_NETWORK_AP_CHANNEL_2G_2 = 2 32WIFI_NETWORK_AP_CHANNEL_5G_2 = 40 33WIFI_NETWORK_AP_CHANNEL_5G_DFS_2 = 136 34 35class WifiStaConcurrencyNetworkRequestTest(WifiBaseTest): 36 """STA + STA Tests for concurrency between intenet connectivity & 37 peer to peer connectivity using NetworkRequest with WifiNetworkSpecifier 38 API surface. 39 40 Test Bed Requirement: 41 * one Android device 42 * Several Wi-Fi networks visible to the device, including an open Wi-Fi 43 network. 44 """ 45 def __init__(self, configs): 46 super().__init__(configs) 47 self.enable_packet_log = True 48 self.p2p_key = None 49 50 def setup_class(self): 51 super().setup_class() 52 53 self.dut = self.android_devices[0] 54 wutils.wifi_test_device_init(self.dut) 55 req_params = ["sta_concurrency_supported_models", "wifi6_models"] 56 opt_param = [ 57 "open_network", "reference_networks" 58 ] 59 self.unpack_userparams( 60 req_param_names=req_params, opt_param_names=opt_param) 61 62 def setup_test(self): 63 asserts.skip_if( 64 self.dut.model not in self.sta_concurrency_supported_models, 65 "Device %s doesn't support STA+STA, skipping tests") 66 asserts.skip_if( 67 "OpenWrtAP" not in self.user_params, 68 "Setup doesn't support OpenWrt AP, skipping tests") 69 70 super().setup_test() 71 self.dut.droid.wakeLockAcquireBright() 72 self.dut.droid.wakeUpNow() 73 self.remove_approvals() 74 self.clear_user_disabled_networks() 75 wutils.wifi_toggle_state(self.dut, True) 76 self.dut.ed.clear_all_events() 77 78 def teardown_test(self): 79 super().teardown_test() 80 self.disconnect_both() 81 self.dut.droid.wakeLockRelease() 82 self.dut.droid.goToSleepNow() 83 self.dut.droid.wifiDisconnect() 84 wutils.reset_wifi(self.dut) 85 # Ensure we disconnected from the current network before the next test. 86 if self.dut.droid.wifiGetConnectionInfo()["supplicant_state"] != "disconnected": 87 wutils.wait_for_disconnect(self.dut) 88 wutils.wifi_toggle_state(self.dut, False) 89 self.dut.ed.clear_all_events() 90 # Reset access point state. 91 for ap in self.access_points: 92 ap.close() 93 94 def teardown_class(self): 95 if "AccessPoint" in self.user_params: 96 del self.user_params["reference_networks"] 97 del self.user_params["open_network"] 98 99 """Helper Functions""" 100 def remove_approvals(self): 101 self.dut.log.debug("Removing all approvals from sl4a app") 102 self.dut.adb.shell( 103 "cmd wifi network-requests-remove-user-approved-access-points" 104 + " " + SL4A_APK_NAME) 105 106 def clear_user_disabled_networks(self): 107 self.dut.log.debug("Clearing user disabled networks") 108 self.dut.adb.shell( 109 "cmd wifi clear-user-disabled-networks") 110 111 def register_network_callback_for_internet(self): 112 self.dut.log.debug("Registering network callback for wifi internet connectivity") 113 network_request = { 114 cconsts.NETWORK_CAP_TRANSPORT_TYPE_KEY : 115 cconsts.NETWORK_CAP_TRANSPORT_WIFI, 116 cconsts.NETWORK_CAP_CAPABILITY_KEY : 117 [cconsts.NETWORK_CAP_CAPABILITY_INTERNET] 118 } 119 key = self.dut.droid.connectivityRegisterNetworkCallback(network_request) 120 return key 121 122 def connect_to_internet_and_wait_for_on_available(self, network): 123 self.dut.log.info("Triggering internet connection after registering " 124 "network callback") 125 self.internet_request_key = ( 126 self.register_network_callback_for_internet()) 127 wutils.connect_to_wifi_network(self.dut, network) 128 # Ensure that the internet connection completed and we got the 129 # ON_AVAILABLE callback. 130 autils.wait_for_event_with_keys( 131 self.dut, 132 cconsts.EVENT_NETWORK_CALLBACK, 133 20, 134 (cconsts.NETWORK_CB_KEY_ID, self.internet_request_key), 135 (cconsts.NETWORK_CB_KEY_EVENT, cconsts.NETWORK_CB_AVAILABLE)) 136 wutils.verify_11ax_wifi_connection( 137 self.dut, self.wifi6_models, "wifi6_ap" in self.user_params) 138 139 def connect_to_p2p_and_wait_for_on_available(self, network): 140 self.p2p_key = wutils.wifi_connect_using_network_request(self.dut, 141 network, 142 network) 143 wutils.verify_11ax_wifi_connection( 144 self.dut, self.wifi6_models, "wifi6_ap" in self.user_params) 145 146 def ensure_both_connections_are_active(self): 147 self.dut.log.info("Ensuring both connections are active") 148 network_caps = ( 149 self.dut.droid.connectivityNetworkGetAllCapabilities()) 150 self.dut.log.info("Active network caps: %s", network_caps) 151 num_wifi_networks = 0 152 for network_cap in network_caps: 153 transport_types = ( 154 network_cap[cconsts.NETWORK_CAP_TRANSPORT_TYPE_KEY]) 155 if cconsts.NETWORK_CAP_TRANSPORT_WIFI in transport_types: 156 num_wifi_networks += 1 157 self.dut.log.info("Wifi connection %s: %s", 158 num_wifi_networks, network_cap) 159 asserts.assert_equal(2, num_wifi_networks, "Expected 2 wifi networks") 160 161 162 def ensure_both_connections_are_active_and_dont_disconnect(self): 163 self.ensure_both_connections_are_active() 164 165 # Don't use the key_id in event to ensure there are no disconnects 166 # from either connection. 167 self.dut.log.info("Ensuring no connection loss") 168 autils.fail_on_event_with_keys( 169 self.dut, 170 cconsts.EVENT_NETWORK_CALLBACK, 171 20, 172 (cconsts.NETWORK_CB_KEY_EVENT, cconsts.NETWORK_CB_LOST)) 173 174 def disconnect_both(self): 175 self.dut.log.info("Disconnecting both connections") 176 if self.p2p_key: 177 asserts.assert_true( 178 self.dut.droid.connectivityUnregisterNetworkCallback( 179 self.p2p_key), 180 "Failed to release the p2p request") 181 self.p2p_key = None 182 self.dut.droid.wifiDisconnect() 183 184 def configure_ap(self, 185 channel_2g=None, 186 channel_5g=None, 187 channel_2g_ap2=None, 188 channel_5g_ap2=None, 189 mirror_ap=False, 190 ap_count=1): 191 """Configure ap based on test requirements.""" 192 if ap_count==1: 193 self.configure_openwrt_ap_and_start( 194 wpa_network=True, 195 channel_2g=WIFI_NETWORK_AP_CHANNEL_2G_1, 196 channel_5g=WIFI_NETWORK_AP_CHANNEL_5G_1, 197 ap_count=1) 198 elif ap_count == 2 and channel_2g_ap2: 199 self.configure_openwrt_ap_and_start( 200 wpa_network=True, 201 channel_2g=WIFI_NETWORK_AP_CHANNEL_2G_1, 202 channel_2g_ap2=WIFI_NETWORK_AP_CHANNEL_2G_2, 203 mirror_ap=mirror_ap, 204 ap_count=2) 205 elif ap_count == 2 and channel_5g_ap2: 206 self.configure_openwrt_ap_and_start( 207 wpa_network=True, 208 channel_5g=WIFI_NETWORK_AP_CHANNEL_5G_1, 209 channel_5g_ap2=WIFI_NETWORK_AP_CHANNEL_5G_2, 210 mirror_ap=mirror_ap, 211 ap_count=2) 212 213 @test_tracker_info(uuid="64a6c35f-d45d-431f-83e8-7fcfaef943e2") 214 def test_connect_to_2g_p2p_while_connected_to_5g_internet(self): 215 """ 216 Initiates a connection to a peer to peer network via network request while 217 already connected to an internet connectivity network. 218 219 Steps: 220 1. Setup 5G & 2G band WPA-PSK networks. 221 2. Connect to WPA-PSK 5G network for internet connectivity. 222 3. Send a network specifier with the specific SSID/credentials of 223 WPA-PSK 2G network. 224 4. Wait for platform to scan and find matching networks. 225 5. Simulate user selecting the network. 226 6. Ensure that the device connects to the network. 227 7. Ensure that the device remains connected to both the networks. 228 8. Disconnect both connections. 229 """ 230 self.configure_ap( 231 channel_2g=WIFI_NETWORK_AP_CHANNEL_2G_1, 232 channel_5g=WIFI_NETWORK_AP_CHANNEL_5G_1, 233 ap_count=1) 234 235 self.connect_to_internet_and_wait_for_on_available( 236 self.wpa_networks[0]["5g"]) 237 self.connect_to_p2p_and_wait_for_on_available( 238 self.wpa_networks[0]["2g"]) 239 240 self.ensure_both_connections_are_active_and_dont_disconnect() 241 242 243 @test_tracker_info(uuid="aa8af713-5d97-4f05-8104-e697f0055d6e") 244 def test_connect_to_2g_internet_while_connected_to_5g_p2p(self): 245 """ 246 Initiates a connection to a peer to peer network via network request while 247 already connected to an internet connectivity network. 248 249 Steps: 250 1. Setup 5G & 2G band WPA-PSK networks. 251 2. Send a network specifier with the specific SSID/credentials of 252 WPA-PSK 5G network. 253 3. Wait for platform to scan and find matching networks. 254 4. Simulate user selecting the network. 255 5. Ensure that the device connects to the network. 256 6. Connect to WPA-PSK 2G network for internet connectivity. 257 7. Ensure that the device remains connected to both the networks. 258 8. Disconnect both connections. 259 """ 260 self.configure_ap( 261 channel_2g=WIFI_NETWORK_AP_CHANNEL_2G_1, 262 channel_5g=WIFI_NETWORK_AP_CHANNEL_5G_1, 263 ap_count=1) 264 265 self.connect_to_p2p_and_wait_for_on_available( 266 self.wpa_networks[0]["5g"]) 267 self.connect_to_internet_and_wait_for_on_available( 268 self.wpa_networks[0]["2g"]) 269 270 self.ensure_both_connections_are_active_and_dont_disconnect() 271 272 273 @test_tracker_info(uuid="64dd09a7-28f6-4000-b1a1-10302922641b") 274 def test_connect_to_2g_internet_while_connected_to_2g_p2p(self): 275 """ 276 Initiates a connection to a peer to peer network via network request while 277 already connected to an internet connectivity network. 278 279 Steps: 280 1. Setup 2 5G & 2G band WPA-PSK networks. 281 2. Send a network specifier with the specific SSID/credentials of 282 WPA-PSK 2G network. 283 3. Wait for platform to scan and find matching networks. 284 4. Simulate user selecting the network. 285 5. Ensure that the device connects to the network. 286 6. Connect to WPA-PSK 2G network for internet connectivity. 287 7. Ensure that the device remains connected to both the networks. 288 8. Disconnect both connections. 289 """ 290 self.configure_ap( 291 channel_2g=WIFI_NETWORK_AP_CHANNEL_2G_1, 292 channel_2g_ap2=WIFI_NETWORK_AP_CHANNEL_2G_2, 293 ap_count=2) 294 295 self.connect_to_p2p_and_wait_for_on_available( 296 self.wpa_networks[0]["2g"]) 297 self.connect_to_internet_and_wait_for_on_available( 298 self.wpa_networks[1]["2g"]) 299 300 self.ensure_both_connections_are_active_and_dont_disconnect() 301 302 303 @test_tracker_info(uuid="0c3df2f1-7311-4dd2-b0dc-1de4bd731495") 304 def test_connect_to_5g_internet_while_connected_to_5g_p2p(self): 305 """ 306 Initiates a connection to a peer to peer network via network request while 307 already connected to an internet connectivity network. 308 309 Steps: 310 1. Setup 2 5G & 2G band WPA-PSK networks. 311 2. Send a network specifier with the specific SSID/credentials of 312 WPA-PSK 5G network. 313 3. Wait for platform to scan and find matching networks. 314 4. Simulate user selecting the network. 315 5. Ensure that the device connects to the network. 316 6. Connect to WPA-PSK 5G network for internet connectivity. 317 7. Ensure that the device remains connected to both the networks. 318 8. Disconnect both connections. 319 """ 320 self.configure_ap( 321 channel_5g=WIFI_NETWORK_AP_CHANNEL_5G_1, 322 channel_5g_ap2=WIFI_NETWORK_AP_CHANNEL_5G_2, 323 ap_count=2) 324 325 self.connect_to_p2p_and_wait_for_on_available( 326 self.wpa_networks[0]["5g"]) 327 self.connect_to_internet_and_wait_for_on_available( 328 self.wpa_networks[1]["5g"]) 329 330 self.ensure_both_connections_are_active_and_dont_disconnect() 331 332 @test_tracker_info(uuid="be22f7f8-b761-4f40-8d10-ff802761cb8b") 333 def test_connect_to_5g_dfs_internet_while_connected_to_5g_dfs_p2p(self): 334 """ 335 Initiates a connection to a peer to peer network via network request while 336 already connected to an internet connectivity network. 337 338 Steps: 339 1. Setup 2 5G-DFS & 2G band WPA-PSK networks. 340 2. Send a network specifier with the specific SSID/credentials of 341 WPA-PSK 5G-DFS network. 342 3. Wait for platform to scan and find matching networks. 343 4. Simulate user selecting the network. 344 5. Ensure that the device connects to the network. 345 6. Connect to WPA-PSK 5G network for internet connectivity. 346 7. Ensure that the device remains connected to both the networks. 347 8. Disconnect both connections. 348 """ 349 self.configure_ap( 350 channel_5g=WIFI_NETWORK_AP_CHANNEL_5G_DFS_1, 351 channel_5g_ap2=WIFI_NETWORK_AP_CHANNEL_5G_DFS_2, 352 ap_count=2) 353 354 self.connect_to_p2p_and_wait_for_on_available( 355 self.wpa_networks[0]["5g"]) 356 self.connect_to_internet_and_wait_for_on_available( 357 self.wpa_networks[1]["5g"]) 358 359 self.ensure_both_connections_are_active_and_dont_disconnect() 360 361 @test_tracker_info(uuid="dc390b3f-2856-4c96-880b-9732e3dc228f") 362 def test_connect_to_2g_internet_while_connected_to_2g_p2p_same_ssid(self): 363 """ 364 Initiates a connection to a peer to peer network via network request while 365 already connected to an internet connectivity network. 366 367 Steps: 368 1. Setup 2 5G & 2G band WPA-PSK networks with the same SSID. 369 2. Send a network specifier with the specific SSID/credentials of 370 WPA-PSK 2G network. 371 3. Wait for platform to scan and find matching networks. 372 4. Simulate user selecting the network. 373 5. Ensure that the device connects to the network. 374 6. Connect to WPA-PSK 2G network for internet connectivity. 375 7. Ensure that the device remains connected to both the networks. 376 8. Disconnect both connections. 377 """ 378 self.configure_ap( 379 channel_2g=WIFI_NETWORK_AP_CHANNEL_2G_1, 380 channel_2g_ap2=WIFI_NETWORK_AP_CHANNEL_2G_2, 381 mirror_ap=True, 382 ap_count=2) 383 384 self.connect_to_p2p_and_wait_for_on_available( 385 self.wpa_networks[0]["2g"]) 386 self.connect_to_internet_and_wait_for_on_available( 387 self.wpa_networks[0]["2g"]) 388 389 self.ensure_both_connections_are_active_and_dont_disconnect() 390 391 @test_tracker_info(uuid="033d324d-94e0-440e-9532-993bc2682269") 392 def test_connect_to_5g_p2p_while_connected_to_5g_internet_same_ssid(self): 393 """ 394 Initiates a connection to a peer to peer network via network request while 395 already connected to an internet connectivity network. 396 397 Steps: 398 1. Setup 2 5G & 2G band WPA-PSK networks with the same SSID. 399 2. Connect to WPA-PSK 5G network for internet connectivity. 400 3. Send a network specifier with the specific SSID/credentials of 401 WPA-PSK 5G network (with the other bssid). 402 4. Wait for platform to scan and find matching networks. 403 5. Simulate user selecting the network. 404 6. Ensure that the device connects to the network. 405 7. Ensure that the device remains connected to both the networks. 406 8. Disconnect both connections. 407 """ 408 self.configure_ap( 409 channel_5g=WIFI_NETWORK_AP_CHANNEL_5G_1, 410 channel_5g_ap2=WIFI_NETWORK_AP_CHANNEL_5G_2, 411 mirror_ap=True, 412 ap_count=2) 413 414 self.connect_to_internet_and_wait_for_on_available( 415 self.wpa_networks[0]["5g"]) 416 417 ssid = self.wpa_networks[0]["5g"][WifiEnums.SSID_KEY] 418 bssids = [self.bssid_map[0]["5g"][ssid], self.bssid_map[1]["5g"][ssid]] 419 # Find the internet connection bssid. 420 wifi_info = self.dut.droid.wifiGetConnectionInfo() 421 connected_bssid = wifi_info[WifiEnums.BSSID_KEY].upper() 422 # Find the bssid of the other access point with same ssid. 423 p2p_bssid = set(bssids) - {connected_bssid} 424 425 # Construct specifier for the other bssid. 426 network_specifier_with_bssid = self.wpa_networks[0]["5g"].copy() 427 network_specifier_with_bssid[WifiEnums.BSSID_KEY] = next(iter(p2p_bssid)) 428 self.connect_to_p2p_and_wait_for_on_available( 429 network_specifier_with_bssid) 430 431 self.ensure_both_connections_are_active_and_dont_disconnect() 432