1# Copyright (C) 2023 The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14# 15# Licensed under the Apache License, Version 2.0 (the "License"); 16# you may not use this file except in compliance with the License. 17# You may obtain a copy of the License at 18# 19# http://www.apache.org/licenses/LICENSE-2.0 20# 21# Unless required by applicable law or agreed to in writing, software 22# distributed under the License is distributed on an "AS IS" BASIS, 23# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 24# See the License for the specific language governing permissions and 25# limitations under the License. 26 27# Lint as: python3 28 29from __future__ import annotations 30 31from collections.abc import Sequence 32import dataclasses 33import enum 34import logging 35from typing import Any, Optional, Union 36 37WIFI_SNIPPET_PACKAGE_NAME = "com.google.snippet.wifi" 38WIFI_DIRECT_SNIPPET_PACKAGE_NAME = 'com.google.snippet.wifi.direct' 39 40ACTION_LISTENER_CALLBACK_EVENT = "WifiP2pManagerActionListenerCallback" 41ACTION_LISTENER_ON_SUCCESS = 'onSuccess' 42ACTION_LISTENER_ON_FAILURE = 'onFailure' 43ACTION_LISTENER_FAILURE_REASON = 'reason' 44 45EVENT_KEY_CALLBACK_NAME = 'callbackName' 46EVENT_KEY_REASON = 'reason' 47EVENT_KEY_P2P_DEVICE = 'p2pDevice' 48EVENT_KEY_P2P_INFO = 'p2pInfo' 49EVENT_KEY_P2P_GROUP = 'p2pGroup' 50EVENT_KEY_PEER_LIST = 'peerList' 51 52EXTRA_WIFI_P2P_GROUP = 'p2pGroupInfo' 53EXTRA_WIFI_STATE = 'wifi_p2p_state' 54 55ON_CONNECTION_INFO_AVAILABLE = 'WifiP2pOnConnectionInfoAvailable' 56ON_DEVICE_INFO_AVAILABLE = 'WifiP2pOnDeviceInfoAvailable' 57ON_PERSISTENT_GROUP_INFO_AVAILABLE = 'onPersistentGroupInfoAvailable' 58ON_UPNP_SERVICE_AVAILABLE = 'onUpnpServiceAvailable' 59ON_DNS_SD_SERVICE_AVAILABLE = 'onDnsSdServiceAvailable' 60ON_DNS_SD_TXT_RECORD_AVAILABLE = 'onDnsSdTxtRecordAvailable' 61WIFI_P2P_CREATING_GROUP = 'CREATING_GROUP' 62WIFI_P2P_CONNECTION_CHANGED_ACTION = ( 63 'android.net.wifi.p2p.CONNECTION_STATE_CHANGE' 64) 65WIFI_P2P_DISCOVERY_CHANGED_ACTION = ( 66 'android.net.wifi.p2p.DISCOVERY_STATE_CHANGE' 67) 68WIFI_P2P_PEERS_CHANGED_ACTION = 'android.net.wifi.p2p.PEERS_CHANGED' 69WIFI_P2P_STATE_CHANGED_ACTION = 'android.net.wifi.p2p.STATE_CHANGED' 70WIFI_P2P_THIS_DEVICE_CHANGED_ACTION = 'android.net.wifi.p2p.THIS_DEVICE_CHANGED' 71 72ANONYMIZED_MAC_ADDRESS = '02:00:00:00:00:00' 73 74 75@enum.unique 76class ActionListenerOnFailure(enum.IntEnum): 77 """Indicates the failure reason of the initiation of the action. 78 79 https://developer.android.com/reference/android/net/wifi/p2p/WifiP2pManager.ActionListener#onFailure(int) 80 """ 81 82 ERROR = 0 83 P2P_UNSUPPORTED = 1 84 BUSY = 2 85 NO_SERVICE_REQUESTS = 3 86 87 88@enum.unique 89class Band(enum.IntEnum): 90 """Indicates the band of the operating frequency. 91 92 https://developer.android.com/reference/android/net/wifi/p2p/WifiP2pConfig#getGroupOwnerBand() 93 """ 94 95 GROUP_OWNER_BAND_AUTO = 0 96 GROUP_OWNER_BAND_2GHZ = 1 97 GROUP_OWNER_BAND_5GHZ = 2 98 99 100@enum.unique 101class IpProvisioningMode(enum.IntEnum): 102 """Indicates the IP provisioning mode. 103 104 https://developer.android.com/reference/android/net/wifi/p2p/WifiP2pConfig#getGroupClientIpProvisioningMode() 105 """ 106 107 GROUP_CLIENT_IP_PROVISIONING_MODE_IPV4_DHCP = 0 108 GROUP_CLIENT_IP_PROVISIONING_MODE_IPV6_LINK_LOCAL = 1 109 110 111@enum.unique 112class ExtraWifiState(enum.IntEnum): 113 """Indicates whether Wi-Fi p2p is enabled or disabled. 114 115 https://developer.android.com/reference/android/net/wifi/p2p/WifiP2pManager#EXTRA_WIFI_STATE 116 """ 117 118 WIFI_P2P_STATE_UNKNOWN = 0 119 WIFI_P2P_STATE_DISABLED = 1 120 WIFI_P2P_STATE_ENABLED = 2 121 122 123@enum.unique 124class WifiP2pDeviceStatus(enum.IntEnum): 125 """Represents status code for WifiP2pDevice.and 126 127 https://developer.android.com/reference/android/net/wifi/p2p/WifiP2pDevice#constants_1 128 """ 129 130 CONNECTED = 0 131 INVITED = 1 132 FAILED = 2 133 AVAILABLE = 3 134 UNAVAILABLE = 4 135 136 137@enum.unique 138class WpsInfo(enum.IntEnum): 139 """Represents Wi-Fi Protected Setup. 140 141 https://developer.android.com/reference/android/net/wifi/WpsInfo 142 """ 143 144 PBC = 0 145 DISPLAY = 1 146 KEYPAD = 2 147 LABEL = 3 148 INVALID = 4 149 150 151@dataclasses.dataclass(frozen=True) 152class WifiP2pConfig: 153 """Represents a Wi-Fi P2p configuration for setting up a connection. 154 155 https://developer.android.com/reference/android/net/wifi/p2p/WifiP2pConfig 156 """ 157 158 persistent_mode: Optional[bool] = None 159 device_address: Optional[str] = None 160 group_client_ip_provisioning_mode: Optional[IpProvisioningMode] = None 161 group_operating_band: Optional[Band] = None 162 group_operating_frequency: Optional[int] = None 163 network_name: Optional[str] = None 164 passphrase: Optional[str] = None 165 wps_setup: WpsInfo | None = None 166 167 def to_dict(self) -> dict[str, Union[bool, int, str]]: 168 """Converts this WifiP2pConfig to a dictionary.""" 169 return { 170 k: v.value if isinstance(v, enum.Enum) else v 171 for k, v in self.__dict__.items() 172 if v is not None 173 } 174 175 176@dataclasses.dataclass 177class WifiP2pDevice: 178 """Represents a Wi-Fi p2p device. 179 180 https://developer.android.com/reference/android/net/wifi/p2p/WifiP2pDevice 181 """ 182 183 device_name: str 184 device_address: str 185 is_group_owner: bool 186 status: int 187 primary_device_type: str 188 secondary_device_type: str 189 190 @classmethod 191 def from_dict(cls, device: dict[str, Any]) -> WifiP2pDevice: 192 """Generates a WifiP2pDevice object from a dictionary.""" 193 logging.debug( 194 "Converting following snippet event data to WifiP2pDevice: %s", 195 device, 196 ) 197 return WifiP2pDevice( 198 device_name=device["deviceName"], 199 device_address=device["deviceAddress"], 200 is_group_owner=device["isGroupOwner"], 201 status=device["status"], 202 primary_device_type=device["primaryDeviceType"], 203 secondary_device_type=device["secondaryDeviceType"], 204 ) 205 206 @classmethod 207 def from_dict_list( 208 cls, devices: list[dict[str, Any]] 209 ) -> Sequence[WifiP2pDevice]: 210 """Generates WifiP2pDevice objects from a list of dictionary.""" 211 return [cls.from_dict(device) for device in devices] 212 213 214@dataclasses.dataclass(frozen=True) 215class WifiP2pInfo: 216 """Represents a connection information about a Wi-Fi p2p group. 217 218 https://developer.android.com/reference/android/net/wifi/p2p/WifiP2pInfo 219 """ 220 221 group_formed: bool 222 group_owner_address: str 223 is_group_owner: bool 224 225 @classmethod 226 def from_dict(cls, info: dict[str, Any]) -> WifiP2pInfo: 227 """Generates a WifiP2pInfo object from a dictionary.""" 228 return WifiP2pInfo( 229 group_formed=info["groupFormed"], 230 group_owner_address=info["groupOwnerAddress"], 231 is_group_owner=info["isGroupOwner"], 232 ) 233 234 235@dataclasses.dataclass(frozen=True) 236class WifiP2pGroup: 237 """Represents a Wi-Fi p2p group. 238 239 https://developer.android.com/reference/android/net/wifi/p2p/WifiP2pGroup 240 """ 241 242 frequency: int 243 interface: str 244 network_id: int 245 network_name: str 246 owner: WifiP2pDevice 247 passphrase: str 248 is_group_owner: bool 249 250 @classmethod 251 def from_dict(cls, group: dict[str, Any]) -> WifiP2pGroup: 252 """Generates a WifiP2pGroup object from a dictionary.""" 253 return WifiP2pGroup( 254 frequency=group['frequency'], 255 interface=group['interface'], 256 network_id=group['networkId'], 257 network_name=group['networkName'], 258 owner=WifiP2pDevice.from_dict(group['owner']), 259 passphrase=group['passphrase'], 260 is_group_owner=group['isGroupOwner'], 261 ) 262 263 @classmethod 264 def from_dict_list( 265 cls, groups: list[dict[str, Any]] 266 ) -> Sequence[WifiP2pGroup]: 267 """Generates WifiP2pGroup objects from a list of dictionary.""" 268 return [cls.from_dict(group) for group in groups] 269 270 271@enum.unique 272class ServiceType(enum.IntEnum): 273 """Indicates the type of Wi-Fi p2p services. 274 275 https://developer.android.com/reference/android/net/wifi/p2p/nsd/WifiP2pServiceInfo#summary 276 """ 277 278 ALL = 0 279 BONJOUR = 1 280 UPNP = 2 281 WS_DISCOVERY = 3 282 283 284class ServiceData: 285 """Constants for Wi-Fi p2p services.""" 286 287 # Service configurations. 288 # Configuration for Bonjour IPP local service. 289 IPP_DNS_SD = (('MyPrinter', '_ipp._tcp.local.'),) 290 AFP_DNS_SD = (('Example', '_afpovertcp._tcp.local.'),) 291 ALL_DNS_SD = ( 292 ('MyPrinter', '_ipp._tcp.local.'), 293 ('Example', '_afpovertcp._tcp.local.'), 294 ) 295 296 IPP_DNS_TXT = ( 297 ('myprinter._ipp._tcp.local.', { 298 'txtvers': '1', 299 'pdl': 'application/postscript' 300 }), 301 ) 302 AFP_DNS_TXT = (('example._afpovertcp._tcp.local.', {}),) 303 ALL_DNS_TXT = (('myprinter._ipp._tcp.local.', 304 { 305 'txtvers': '1', 306 'pdl': 'application/postscript' 307 } 308 ), ('example._afpovertcp._tcp.local.', {}),) 309 310 # Configuration for IPP local service. 311 DEFAULT_IPP_SERVICE_CONF = { 312 'instance_name': 'MyPrinter', 313 'service_type': '_ipp._tcp', 314 'txt_map': { 315 'txtvers': '1', 316 'pdl': 'application/postscript' 317 }, 318 } 319 # Configuration for AFP local service. 320 DEFAULT_AFP_SERVICE_CONF = { 321 'instance_name': 'Example', 322 'service_type': '_afpovertcp._tcp', 323 'txt_map': {}, 324 } 325 # Configuration for UPnP MediaRenderer local service. 326 DEFAULT_UPNP_SERVICE_CONF = { 327 'uuid': '6859dede-8574-59ab-9332-123456789011', 328 'device': 'urn:schemas-upnp-org:device:MediaRenderer:1', 329 'services': [ 330 'urn:schemas-upnp-org:service:AVTransport:1', 331 'urn:schemas-upnp-org:service:ConnectionManager:1', 332 ], 333 } 334 335 # Expected services to be discovered. 336 ALL_UPNP_SERVICES = ( 337 'uuid:6859dede-8574-59ab-9332-123456789011', 338 'uuid:6859dede-8574-59ab-9332-123456789011::upnp:rootdevice', 339 ( 340 'uuid:6859dede-8574-59ab-9332-123456789011::urn:schemas-upnp-org:' 341 'device:MediaRenderer:1' 342 ), 343 ( 344 'uuid:6859dede-8574-59ab-9332-123456789011::urn:schemas-upnp-org:' 345 'service:AVTransport:1' 346 ), 347 ( 348 'uuid:6859dede-8574-59ab-9332-123456789011::urn:schemas-upnp-org:' 349 'service:ConnectionManager:1' 350 ), 351 ) 352 353 UPNP_ROOT_DEVICE = ('uuid:6859dede-8574-59ab-9332-123456789011::upnp:rootdevice',) 354 355 356class WifiP2pManagerConstants: 357 """Constants for Wi-Fi p2p manager. 358 359 https://developer.android.com/reference/android/net/wifi/p2p/WifiP2pManager#NO_SERVICE_REQUESTS 360 """ 361 NO_SERVICE_REQUESTS = 3 362