1#!/usr/bin/env python3 2# 3# Copyright 2019 - 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 inspect 18import logging 19 20import acts.test_utils.wifi.wifi_test_utils as awutils 21import acts.test_utils.abstract_devices.utils_lib.wlan_utils as fwutils 22from acts.utils import get_interface_ip_addresses 23from acts.utils import adb_shell_ping 24 25from acts import asserts 26from acts.controllers.fuchsia_device import FuchsiaDevice 27from acts.controllers.android_device import AndroidDevice 28 29 30def create_wlan_device(hardware_device): 31 """Creates a generic WLAN device based on type of device that is sent to 32 the functions. 33 34 Args: 35 hardware_device: A WLAN hardware device that is supported by ACTS. 36 """ 37 if isinstance(hardware_device, FuchsiaDevice): 38 return FuchsiaWlanDevice(hardware_device) 39 elif isinstance(hardware_device, AndroidDevice): 40 return AndroidWlanDevice(hardware_device) 41 else: 42 raise ValueError('Unable to create WlanDevice for type %s' % 43 type(hardware_device)) 44 45 46class WlanDevice(object): 47 """Class representing a generic WLAN device. 48 49 Each object of this class represents a generic WLAN device. 50 Android device and Fuchsia devices are the currently supported devices/ 51 52 Attributes: 53 device: A generic WLAN device. 54 """ 55 def __init__(self, device): 56 self.device = device 57 self.log = logging 58 59 def wifi_toggle_state(self, state): 60 """Base generic WLAN interface. Only called if not overridden by 61 another supported device. 62 """ 63 raise NotImplementedError("{} must be defined.".format( 64 inspect.currentframe().f_code.co_name)) 65 66 def reset_wifi(self): 67 """Base generic WLAN interface. Only called if not overridden by 68 another supported device. 69 """ 70 raise NotImplementedError("{} must be defined.".format( 71 inspect.currentframe().f_code.co_name)) 72 73 def take_bug_report(self, test_name, begin_time): 74 """Base generic WLAN interface. Only called if not overridden by 75 another supported device. 76 """ 77 raise NotImplementedError("{} must be defined.".format( 78 inspect.currentframe().f_code.co_name)) 79 80 def get_log(self, test_name, begin_time): 81 """Base generic WLAN interface. Only called if not overridden by 82 another supported device. 83 """ 84 raise NotImplementedError("{} must be defined.".format( 85 inspect.currentframe().f_code.co_name)) 86 87 def turn_location_off_and_scan_toggle_off(self): 88 """Base generic WLAN interface. Only called if not overridden by 89 another supported device. 90 """ 91 raise NotImplementedError("{} must be defined.".format( 92 inspect.currentframe().f_code.co_name)) 93 94 def associate(self, 95 target_ssid, 96 target_pwd=None, 97 check_connectivity=True, 98 hidden=False): 99 """Base generic WLAN interface. Only called if not overriden by 100 another supported device. 101 """ 102 raise NotImplementedError("{} must be defined.".format( 103 inspect.currentframe().f_code.co_name)) 104 105 def disconnect(self): 106 """Base generic WLAN interface. Only called if not overridden by 107 another supported device. 108 """ 109 raise NotImplementedError("{} must be defined.".format( 110 inspect.currentframe().f_code.co_name)) 111 112 def get_wlan_interface_id_list(self): 113 """Base generic WLAN interface. Only called if not overridden by 114 another supported device. 115 """ 116 raise NotImplementedError("{} must be defined.".format( 117 inspect.currentframe().f_code.co_name)) 118 119 def destroy_wlan_interface(self, iface_id): 120 """Base generic WLAN interface. Only called if not overridden by 121 another supported device. 122 """ 123 raise NotImplementedError("{} must be defined.".format( 124 inspect.currentframe().f_code.co_name)) 125 126 def send_command(self, command): 127 raise NotImplementedError("{} must be defined.".format( 128 inspect.currentframe().f_code.co_name)) 129 130 def get_interface_ip_addresses(self, interface): 131 raise NotImplementedError("{} must be defined.".format( 132 inspect.currentframe().f_code.co_name)) 133 134 def is_connected(self): 135 raise NotImplementedError("{} must be defined.".format( 136 inspect.currentframe().f_code.co_name)) 137 138 def ping(self, dest_ip, count=3, interval=1000, timeout=1000, size=25): 139 raise NotImplementedError("{} must be defined.".format( 140 inspect.currentframe().f_code.co_name)) 141 142 143class AndroidWlanDevice(WlanDevice): 144 """Class wrapper for an Android WLAN device. 145 146 Each object of this class represents a generic WLAN device. 147 Android device and Fuchsia devices are the currently supported devices/ 148 149 Attributes: 150 android_device: An Android WLAN device. 151 """ 152 def __init__(self, android_device): 153 super().__init__(android_device) 154 155 def wifi_toggle_state(self, state): 156 awutils.wifi_toggle_state(self.device, state) 157 158 def reset_wifi(self): 159 awutils.reset_wifi(self.device) 160 161 def take_bug_report(self, test_name, begin_time): 162 self.device.take_bug_report(test_name, begin_time) 163 164 def get_log(self, test_name, begin_time): 165 self.device.cat_adb_log(test_name, begin_time) 166 167 def turn_location_off_and_scan_toggle_off(self): 168 awutils.turn_location_off_and_scan_toggle_off(self.device) 169 170 def associate(self, 171 target_ssid, 172 target_pwd=None, 173 key_mgmt=None, 174 check_connectivity=True, 175 hidden=False): 176 """Function to associate an Android WLAN device. 177 178 Args: 179 target_ssid: SSID to associate to. 180 target_pwd: Password for the SSID, if necessary. 181 key_mgmt: The hostapd wpa_key_mgmt value, distinguishes wpa3 from 182 wpa2 for android tests. 183 check_connectivity: Whether to check for internet connectivity. 184 hidden: Whether the network is hidden. 185 Returns: 186 True if successfully connected to WLAN, False if not. 187 """ 188 network = {'SSID': target_ssid, 'hiddenSSID': hidden} 189 if target_pwd: 190 network['password'] = target_pwd 191 if key_mgmt: 192 network['security'] = key_mgmt 193 try: 194 awutils.connect_to_wifi_network( 195 self.device, 196 network, 197 check_connectivity=check_connectivity, 198 hidden=hidden) 199 return True 200 except Exception as e: 201 self.device.log.info('Failed to associated (%s)' % e) 202 return False 203 204 def disconnect(self): 205 awutils.turn_location_off_and_scan_toggle_off(self.device) 206 207 def get_wlan_interface_id_list(self): 208 pass 209 210 def destroy_wlan_interface(self, iface_id): 211 pass 212 213 def send_command(self, command): 214 return self.device.adb.shell(str(command)) 215 216 def get_interface_ip_addresses(self, interface): 217 return get_interface_ip_addresses(self.device, interface) 218 219 def is_connected(self): 220 return 'BSSID' in self.device.droid.wifiGetConnectionInfo() 221 222 def ping(self, dest_ip, count=3, interval=1000, timeout=1000, size=25): 223 return adb_shell_ping(self.device, 224 dest_ip=dest_ip, 225 count=count, 226 timeout=timeout) 227 228 229class FuchsiaWlanDevice(WlanDevice): 230 """Class wrapper for an Fuchsia WLAN device. 231 232 Each object of this class represents a generic WLAN device. 233 Android device and Fuchsia devices are the currently supported devices/ 234 235 Attributes: 236 fuchsia_device: A Fuchsia WLAN device. 237 """ 238 def __init__(self, fuchsia_device): 239 super().__init__(fuchsia_device) 240 241 def wifi_toggle_state(self, state): 242 """Stub for Fuchsia implementation.""" 243 pass 244 245 def reset_wifi(self): 246 """Stub for Fuchsia implementation.""" 247 pass 248 249 def take_bug_report(self, test_name, begin_time): 250 """Stub for Fuchsia implementation.""" 251 pass 252 253 def get_log(self, test_name, begin_time): 254 """Stub for Fuchsia implementation.""" 255 pass 256 257 def turn_location_off_and_scan_toggle_off(self): 258 """Stub for Fuchsia implementation.""" 259 pass 260 261 def associate(self, 262 target_ssid, 263 target_pwd=None, 264 key_mgmt=None, 265 check_connectivity=True, 266 hidden=False): 267 """Function to associate a Fuchsia WLAN device. 268 269 Args: 270 target_ssid: SSID to associate to. 271 target_pwd: Password for the SSID, if necessary. 272 key_mgmt: the hostapd wpa_key_mgmt, if specified. 273 check_connectivity: Whether to check for internet connectivity. 274 hidden: Whether the network is hidden. 275 Returns: 276 True if successfully connected to WLAN, False if not. 277 """ 278 connection_response = self.device.wlan_lib.wlanConnectToNetwork( 279 target_ssid, target_pwd=target_pwd) 280 281 return self.device.check_connect_response(connection_response) 282 283 def disconnect(self): 284 """Function to disconnect from a Fuchsia WLAN device. 285 Asserts if disconnect was not successful. 286 """ 287 disconnect_response = self.device.wlan_lib.wlanDisconnect() 288 asserts.assert_true( 289 self.device.check_disconnect_response(disconnect_response), 290 'Failed to disconnect.') 291 292 def status(self): 293 return self.device.wlan_lib.wlanStatus() 294 295 def ping(self, dest_ip, count=3, interval=1000, timeout=1000, size=25): 296 ping_result = self.device.ping(dest_ip, 297 count=count, 298 interval=interval, 299 timeout=timeout, 300 size=size) 301 return ping_result['status'] 302 303 def get_wlan_interface_id_list(self): 304 """Function to list available WLAN interfaces. 305 306 Returns: 307 A list of wlan interface IDs. 308 """ 309 return self.device.wlan_lib.wlanGetIfaceIdList().get('result') 310 311 def destroy_wlan_interface(self, iface_id): 312 """Function to associate a Fuchsia WLAN device. 313 314 Args: 315 target_ssid: SSID to associate to. 316 target_pwd: Password for the SSID, if necessary. 317 check_connectivity: Whether to check for internet connectivity. 318 hidden: Whether the network is hidden. 319 Returns: 320 True if successfully destroyed wlan interface, False if not. 321 """ 322 result = self.device.wlan_lib.wlanDestroyIface(iface_id) 323 if result.get('error') is None: 324 return True 325 else: 326 self.log.error("Failed to destroy interface with: {}".format( 327 result.get('error'))) 328 return False 329 330 def send_command(self, command): 331 return self.device.send_command_ssh(str(command)).stdout 332 333 def get_interface_ip_addresses(self, interface): 334 return get_interface_ip_addresses(self.device, interface) 335 336 def is_connected(self): 337 return fwutils.is_connected(self) 338