1 2package com.googlecode.android_scripting.facade.wifi; 3 4import android.app.Service; 5import android.content.BroadcastReceiver; 6import android.content.Context; 7import android.content.Intent; 8import android.content.IntentFilter; 9import android.net.NetworkInfo; 10import android.net.wifi.WpsInfo; 11import android.net.wifi.p2p.WifiP2pConfig; 12import android.net.wifi.p2p.WifiP2pDevice; 13import android.net.wifi.p2p.WifiP2pDeviceList; 14import android.net.wifi.p2p.WifiP2pGroup; 15import android.net.wifi.p2p.WifiP2pGroupList; 16import android.net.wifi.p2p.WifiP2pInfo; 17import android.net.wifi.p2p.WifiP2pManager; 18import android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceInfo; 19import android.net.wifi.p2p.nsd.WifiP2pServiceInfo; 20import android.net.wifi.p2p.nsd.WifiP2pServiceRequest; 21import android.net.wifi.p2p.nsd.WifiP2pUpnpServiceInfo; 22import android.os.Bundle; 23import android.os.Message; 24import android.os.Messenger; 25import android.os.RemoteException; 26 27import com.android.internal.util.Protocol; 28import com.googlecode.android_scripting.Log; 29import com.googlecode.android_scripting.facade.EventFacade; 30import com.googlecode.android_scripting.facade.FacadeManager; 31import com.googlecode.android_scripting.jsonrpc.RpcReceiver; 32import com.googlecode.android_scripting.rpc.Rpc; 33import com.googlecode.android_scripting.rpc.RpcParameter; 34 35import java.net.InetAddress; 36import java.util.ArrayList; 37import java.util.Collection; 38import java.util.HashMap; 39import java.util.List; 40import java.util.Map; 41 42import org.json.JSONException; 43import org.json.JSONObject; 44 45/** 46 * WifiP2pManager functions. 47 */ 48public class WifiP2pManagerFacade extends RpcReceiver { 49 50 class WifiP2pActionListener implements WifiP2pManager.ActionListener { 51 private final EventFacade mEventFacade; 52 private final String mEventType; 53 private final String TAG; 54 55 public WifiP2pActionListener(EventFacade eventFacade, String tag) { 56 mEventType = "WifiP2p"; 57 mEventFacade = eventFacade; 58 TAG = tag; 59 } 60 61 @Override 62 public void onSuccess() { 63 mEventFacade.postEvent(mEventType + TAG + "OnSuccess", null); 64 } 65 66 @Override 67 public void onFailure(int reason) { 68 Log.d("WifiActionListener " + mEventType); 69 Bundle msg = new Bundle(); 70 if (reason == WifiP2pManager.P2P_UNSUPPORTED) { 71 msg.putString("reason", "P2P_UNSUPPORTED"); 72 } else if (reason == WifiP2pManager.ERROR) { 73 msg.putString("reason", "ERROR"); 74 } else if (reason == WifiP2pManager.BUSY) { 75 msg.putString("reason", "BUSY"); 76 } else if (reason == WifiP2pManager.NO_SERVICE_REQUESTS) { 77 msg.putString("reason", "NO_SERVICE_REQUESTS"); 78 } else { 79 msg.putInt("reason", reason); 80 } 81 mEventFacade.postEvent(mEventType + TAG + "OnFailure", msg); 82 } 83 } 84 85 class WifiP2pConnectionInfoListener implements WifiP2pManager.ConnectionInfoListener { 86 private final EventFacade mEventFacade; 87 private final String mEventType; 88 89 public WifiP2pConnectionInfoListener(EventFacade eventFacade) { 90 mEventType = "WifiP2p"; 91 mEventFacade = eventFacade; 92 } 93 94 @Override 95 public void onConnectionInfoAvailable(WifiP2pInfo info) { 96 Bundle msg = new Bundle(); 97 msg.putBoolean("groupFormed", info.groupFormed); 98 msg.putBoolean("isGroupOwner", info.isGroupOwner); 99 InetAddress addr = info.groupOwnerAddress; 100 String hostName = null; 101 String hostAddress = null; 102 if (addr != null) { 103 hostName = addr.getHostName(); 104 hostAddress = addr.getHostAddress(); 105 } 106 msg.putString("groupOwnerHostName", hostName); 107 msg.putString("groupOwnerHostAddress", hostAddress); 108 mEventFacade.postEvent(mEventType + "OnConnectionInfoAvailable", msg); 109 } 110 } 111 112 class WifiP2pDnsSdServiceResponseListener implements 113 WifiP2pManager.DnsSdServiceResponseListener { 114 private final EventFacade mEventFacade; 115 private final String mEventType; 116 117 public WifiP2pDnsSdServiceResponseListener(EventFacade eventFacade) { 118 mEventType = "WifiP2p"; 119 mEventFacade = eventFacade; 120 } 121 122 @Override 123 public void onDnsSdServiceAvailable(String instanceName, String registrationType, 124 WifiP2pDevice srcDevice) { 125 Bundle msg = new Bundle(); 126 msg.putString("InstanceName", instanceName); 127 msg.putString("RegistrationType", registrationType); 128 msg.putString("SourceDeviceName", srcDevice.deviceName); 129 msg.putString("SourceDeviceAddress", srcDevice.deviceAddress); 130 mEventFacade.postEvent(mEventType + "OnDnsSdServiceAvailable", msg); 131 } 132 } 133 134 class WifiP2pDnsSdTxtRecordListener implements WifiP2pManager.DnsSdTxtRecordListener { 135 private final EventFacade mEventFacade; 136 private final String mEventType; 137 138 public WifiP2pDnsSdTxtRecordListener(EventFacade eventFacade) { 139 mEventType = "WifiP2p"; 140 mEventFacade = eventFacade; 141 } 142 143 @Override 144 public void onDnsSdTxtRecordAvailable(String fullDomainName, 145 Map<String, String> txtRecordMap, WifiP2pDevice srcDevice) { 146 Bundle msg = new Bundle(); 147 msg.putString("FullDomainName", fullDomainName); 148 Bundle txtMap = new Bundle(); 149 for (String key : txtRecordMap.keySet()) { 150 txtMap.putString(key, txtRecordMap.get(key)); 151 } 152 msg.putBundle("TxtRecordMap", txtMap); 153 msg.putString("SourceDeviceName", srcDevice.deviceName); 154 msg.putString("SourceDeviceAddress", srcDevice.deviceAddress); 155 mEventFacade.postEvent(mEventType + "OnDnsSdTxtRecordAvailable", msg); 156 } 157 158 } 159 160 class WifiP2pGroupInfoListener implements WifiP2pManager.GroupInfoListener { 161 private final EventFacade mEventFacade; 162 private final String mEventType; 163 164 public WifiP2pGroupInfoListener(EventFacade eventFacade) { 165 mEventType = "WifiP2p"; 166 mEventFacade = eventFacade; 167 } 168 169 @Override 170 public void onGroupInfoAvailable(WifiP2pGroup group) { 171 mEventFacade.postEvent(mEventType + "OnGroupInfoAvailable", parseGroupInfo(group)); 172 } 173 } 174 175 class WifiP2pPeerListListener implements WifiP2pManager.PeerListListener { 176 private final EventFacade mEventFacade; 177 178 public WifiP2pPeerListListener(EventFacade eventFacade) { 179 mEventFacade = eventFacade; 180 } 181 182 @Override 183 public void onPeersAvailable(WifiP2pDeviceList newPeers) { 184 Collection<WifiP2pDevice> devices = newPeers.getDeviceList(); 185 Log.d(devices.toString()); 186 if (devices.size() > 0) { 187 mP2pPeers.clear(); 188 mP2pPeers.addAll(devices); 189 Bundle msg = new Bundle(); 190 msg.putParcelableList("Peers", mP2pPeers); 191 mEventFacade.postEvent(mEventType + "OnPeersAvailable", msg); 192 } 193 } 194 } 195 196 class WifiP2pPersistentGroupInfoListener implements WifiP2pManager.PersistentGroupInfoListener { 197 private final EventFacade mEventFacade; 198 private final String mEventType; 199 200 public WifiP2pPersistentGroupInfoListener(EventFacade eventFacade) { 201 mEventType = "WifiP2p"; 202 mEventFacade = eventFacade; 203 } 204 205 @Override 206 public void onPersistentGroupInfoAvailable(WifiP2pGroupList groups) { 207 ArrayList<Bundle> gs = new ArrayList<Bundle>(); 208 for (WifiP2pGroup g : groups.getGroupList()) { 209 gs.add(parseGroupInfo(g)); 210 } 211 mEventFacade.postEvent(mEventType + "OnPersistentGroupInfoAvailable", gs); 212 } 213 214 } 215 216 class WifiP2pStateChangedReceiver extends BroadcastReceiver { 217 private final EventFacade mEventFacade; 218 private final Bundle mResults; 219 220 WifiP2pStateChangedReceiver(EventFacade eventFacade) { 221 mEventFacade = eventFacade; 222 mResults = new Bundle(); 223 } 224 225 @Override 226 public void onReceive(Context c, Intent intent) { 227 String action = intent.getAction(); 228 if (action.equals(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION)) { 229 Log.d("Wifi P2p State Changed."); 230 int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, 0); 231 if (state == WifiP2pManager.WIFI_P2P_STATE_DISABLED) { 232 Log.d("Disabled"); 233 isP2pEnabled = false; 234 } else if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) { 235 Log.d("Enabled"); 236 isP2pEnabled = true; 237 } 238 } else if (action.equals(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION)) { 239 Log.d("Wifi P2p Peers Changed. Requesting peers."); 240 WifiP2pDeviceList peers = intent 241 .getParcelableExtra(WifiP2pManager.EXTRA_P2P_DEVICE_LIST); 242 Log.d(peers.toString()); 243 wifiP2pRequestPeers(); 244 } else if (action.equals(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION)) { 245 Log.d("Wifi P2p Connection Changed."); 246 WifiP2pInfo p2pInfo = intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO); 247 NetworkInfo networkInfo = intent 248 .getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO); 249 WifiP2pGroup group = intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP); 250 if (networkInfo.isConnected()) { 251 Log.d("Wifi P2p Connected."); 252 mResults.putParcelable("P2pInfo", p2pInfo); 253 mResults.putParcelable("Group", group); 254 mEventFacade.postEvent(mEventType + "Connected", mResults); 255 mResults.clear(); 256 } else { 257 mEventFacade.postEvent(mEventType + "Disconnected", null); 258 } 259 } else if (action.equals(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION)) { 260 Log.d("Wifi P2p This Device Changed."); 261 WifiP2pDevice device = intent 262 .getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE); 263 mResults.putParcelable("Device", device); 264 mEventFacade.postEvent(mEventType + "ThisDeviceChanged", mResults); 265 mResults.clear(); 266 } else if (action.equals(WifiP2pManager.WIFI_P2P_DISCOVERY_CHANGED_ACTION)) { 267 Log.d("Wifi P2p Discovery Changed."); 268 int state = intent.getIntExtra(WifiP2pManager.EXTRA_DISCOVERY_STATE, 0); 269 if (state == WifiP2pManager.WIFI_P2P_DISCOVERY_STARTED) { 270 Log.d("discovery started."); 271 } else if (state == WifiP2pManager.WIFI_P2P_DISCOVERY_STOPPED) { 272 Log.d("discovery stoped."); 273 } 274 } 275 } 276 } 277 278 private final static String mEventType = "WifiP2p"; 279 280 private WifiP2pManager.Channel mChannel; 281 private final EventFacade mEventFacade; 282 private final WifiP2pManager mP2p; 283 private final WifiP2pStateChangedReceiver mP2pStateChangedReceiver; 284 private final Service mService; 285 private final IntentFilter mStateChangeFilter; 286 private final Map<Integer, WifiP2pServiceRequest> mServiceRequests; 287 288 private boolean isP2pEnabled; 289 private int mServiceRequestCnt = 0; 290 private WifiP2pServiceInfo mServiceInfo = null; 291 private List<WifiP2pDevice> mP2pPeers = new ArrayList<WifiP2pDevice>(); 292 293 public WifiP2pManagerFacade(FacadeManager manager) { 294 super(manager); 295 mService = manager.getService(); 296 mP2p = (WifiP2pManager) mService.getSystemService(Context.WIFI_P2P_SERVICE); 297 mEventFacade = manager.getReceiver(EventFacade.class); 298 299 mStateChangeFilter = new IntentFilter(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION); 300 mStateChangeFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION); 301 mStateChangeFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION); 302 mStateChangeFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION); 303 mStateChangeFilter.setPriority(999); 304 305 mP2pStateChangedReceiver = new WifiP2pStateChangedReceiver(mEventFacade); 306 mServiceRequests = new HashMap<Integer, WifiP2pServiceRequest>(); 307 } 308 309 public Bundle parseGroupInfo(WifiP2pGroup group) { 310 Bundle msg = new Bundle(); 311 msg.putString("Interface", group.getInterface()); 312 msg.putString("NetworkName", group.getNetworkName()); 313 msg.putString("Passphrase", group.getPassphrase()); 314 msg.putInt("NetworkId", group.getNetworkId()); 315 msg.putString("OwnerName", group.getOwner().deviceName); 316 msg.putString("OwnerAddress", group.getOwner().deviceAddress); 317 return msg; 318 } 319 320 @Override 321 public void shutdown() { 322 mService.unregisterReceiver(mP2pStateChangedReceiver); 323 } 324 325 @Rpc(description = "Accept p2p connection invitation.") 326 public void wifiP2pAcceptConnection() throws RemoteException { 327 Log.d("Accepting p2p connection."); 328 Messenger m = mP2p.getP2pStateMachineMessenger(); 329 int user_accept = Protocol.BASE_WIFI_P2P_SERVICE + 2; 330 Message msg = Message.obtain(); 331 msg.what = user_accept; 332 m.send(msg); 333 } 334 335 @Rpc(description = "Reject p2p connection invitation.") 336 public void wifiP2pRejectConnection() throws RemoteException { 337 Log.d("Rejecting p2p connection."); 338 Messenger m = mP2p.getP2pStateMachineMessenger(); 339 int user_accept = Protocol.BASE_WIFI_P2P_SERVICE + 3; 340 Message msg = Message.obtain(); 341 msg.what = user_accept; 342 m.send(msg); 343 } 344 345 @Rpc(description = "Register a local service for service discovery. One of the \"CreateXxxServiceInfo functions needs to be called first.\"") 346 public void wifiP2pAddLocalService() { 347 mP2p.addLocalService(mChannel, mServiceInfo, 348 new WifiP2pActionListener(mEventFacade, "AddLocalService")); 349 } 350 351 @Rpc(description = "Add a service discovery request.") 352 public Integer wifiP2pAddServiceRequest( 353 @RpcParameter(name = "protocolType") Integer protocolType) { 354 WifiP2pServiceRequest request = WifiP2pServiceRequest.newInstance(protocolType); 355 mServiceRequestCnt += 1; 356 mServiceRequests.put(mServiceRequestCnt, request); 357 mP2p.addServiceRequest(mChannel, request, new WifiP2pActionListener(mEventFacade, 358 "AddServiceRequest")); 359 return mServiceRequestCnt; 360 } 361 362 @Rpc(description = "Cancel any ongoing connect negotiation.") 363 public void wifiP2pCancelConnect() { 364 mP2p.cancelConnect(mChannel, new WifiP2pActionListener(mEventFacade, "CancelConnect")); 365 } 366 367 @Rpc(description = "Clear all registered local services of service discovery.") 368 public void wifiP2pClearLocalServices() { 369 mP2p.clearLocalServices(mChannel, 370 new WifiP2pActionListener(mEventFacade, "ClearLocalServices")); 371 } 372 373 @Rpc(description = "Clear all registered service discovery requests.") 374 public void wifiP2pClearServiceRequests() { 375 mP2p.clearServiceRequests(mChannel, 376 new WifiP2pActionListener(mEventFacade, "ClearServiceRequests")); 377 } 378 379 @Rpc(description = "Connects to a discovered wifi p2p device.") 380 public void wifiP2pConnect(@RpcParameter(name = "deviceId") String deviceId) { 381 for (WifiP2pDevice d : mP2pPeers) { 382 if (wifiP2pDeviceMatches(d, deviceId)) { 383 WifiP2pConfig config = new WifiP2pConfig(); 384 config.deviceAddress = d.deviceAddress; 385 config.wps.setup = WpsInfo.PBC; 386 mP2p.connect(mChannel, config, 387 new WifiP2pActionListener(mEventFacade, "Connect")); 388 } 389 } 390 } 391 392 @Rpc(description = "Create a Bonjour service info object to be used for wifiP2pAddLocalService.") 393 public void wifiP2pCreateBonjourServiceInfo( 394 @RpcParameter(name = "instanceName") String instanceName, 395 @RpcParameter(name = "serviceType") String serviceType, 396 @RpcParameter(name = "txtMap") JSONObject txtMap) throws JSONException { 397 Map<String, String> map = new HashMap<String, String>(); 398 for (String key : txtMap.keySet()) { 399 map.put(key, txtMap.getString(key)); 400 } 401 mServiceInfo = WifiP2pDnsSdServiceInfo.newInstance(instanceName, serviceType, map); 402 } 403 404 @Rpc(description = "Create a wifi p2p group.") 405 public void wifiP2pCreateGroup() { 406 mP2p.createGroup(mChannel, new WifiP2pActionListener(mEventFacade, "CreatGroup")); 407 } 408 409 @Rpc(description = "Create a Upnp service info object to be used for wifiP2pAddLocalService.") 410 public void wifiP2pCreateUpnpServiceInfo( 411 @RpcParameter(name = "uuid") String uuid, 412 @RpcParameter(name = "device") String device, 413 @RpcParameter(name = "services") List<String> services) { 414 mServiceInfo = WifiP2pUpnpServiceInfo.newInstance(uuid, device, services); 415 } 416 417 @Rpc(description = "Delete a stored persistent group from the system settings.") 418 public void wifiP2pDeletePersistentGroup(@RpcParameter(name = "netId") Integer netId) { 419 mP2p.deletePersistentGroup(mChannel, netId, 420 new WifiP2pActionListener(mEventFacade, "DeletePersistentGroup")); 421 } 422 423 private boolean wifiP2pDeviceMatches(WifiP2pDevice d, String deviceId) { 424 return d.deviceName.equals(deviceId) || d.deviceAddress.equals(deviceId); 425 } 426 427 @Rpc(description = "Start peers discovery for wifi p2p.") 428 public void wifiP2pDiscoverPeers() { 429 mP2p.discoverPeers(mChannel, new WifiP2pActionListener(mEventFacade, "DiscoverPeers")); 430 } 431 432 @Rpc(description = "Initiate service discovery.") 433 public void wifiP2pDiscoverServices() { 434 mP2p.discoverServices(mChannel, 435 new WifiP2pActionListener(mEventFacade, "DiscoverServices")); 436 } 437 438 @Rpc(description = "Initialize wifi p2p. Must be called before any other p2p functions.") 439 public void wifiP2pInitialize() { 440 mService.registerReceiver(mP2pStateChangedReceiver, mStateChangeFilter); 441 mChannel = mP2p.initialize(mService, mService.getMainLooper(), null); 442 } 443 444 @Rpc(description = "Returns true if wifi p2p is enabled, false otherwise.") 445 public Boolean wifiP2pIsEnabled() { 446 return isP2pEnabled; 447 } 448 449 @Rpc(description = "Remove the current p2p group.") 450 public void wifiP2pRemoveGroup() { 451 mP2p.removeGroup(mChannel, new WifiP2pActionListener(mEventFacade, "RemoveGroup")); 452 } 453 454 @Rpc(description = "Remove a registered local service added with wifiP2pAddLocalService.") 455 public void wifiP2pRemoveLocalService() { 456 mP2p.removeLocalService(mChannel, mServiceInfo, 457 new WifiP2pActionListener(mEventFacade, "RemoveLocalService")); 458 } 459 460 @Rpc(description = "Remove a service discovery request.") 461 public void wifiP2pRemoveServiceRequest(@RpcParameter(name = "index") Integer index) { 462 mP2p.removeServiceRequest(mChannel, mServiceRequests.remove(index), 463 new WifiP2pActionListener(mEventFacade, "RemoveServiceRequest")); 464 } 465 466 @Rpc(description = "Request device connection info.") 467 public void wifiP2pRequestConnectionInfo() { 468 mP2p.requestConnectionInfo(mChannel, new WifiP2pConnectionInfoListener(mEventFacade)); 469 } 470 471 @Rpc(description = "Create a wifi p2p group.") 472 public void wifiP2pRequestGroupInfo() { 473 mP2p.requestGroupInfo(mChannel, new WifiP2pGroupInfoListener(mEventFacade)); 474 } 475 476 @Rpc(description = "Request peers that are discovered for wifi p2p.") 477 public void wifiP2pRequestPeers() { 478 mP2p.requestPeers(mChannel, new WifiP2pPeerListListener(mEventFacade)); 479 } 480 481 @Rpc(description = "Request a list of all the persistent p2p groups stored in system.") 482 public void wifiP2pRequestPersistentGroupInfo() { 483 mP2p.requestPersistentGroupInfo(mChannel, 484 new WifiP2pPersistentGroupInfoListener(mEventFacade)); 485 } 486 487 @Rpc(description = "Set p2p device name.") 488 public void wifiP2pSetDeviceName(@RpcParameter(name = "devName") String devName) { 489 mP2p.setDeviceName(mChannel, devName, 490 new WifiP2pActionListener(mEventFacade, "SetDeviceName")); 491 } 492 493 @Rpc(description = "Register a callback to be invoked on receiving Bonjour service discovery response.") 494 public void wifiP2pSetDnsSdResponseListeners() { 495 mP2p.setDnsSdResponseListeners(mChannel, 496 new WifiP2pDnsSdServiceResponseListener(mEventFacade), 497 new WifiP2pDnsSdTxtRecordListener(mEventFacade)); 498 } 499 500 @Rpc(description = "Stop an ongoing peer discovery.") 501 public void wifiP2pStopPeerDiscovery() { 502 mP2p.stopPeerDiscovery(mChannel, 503 new WifiP2pActionListener(mEventFacade, "StopPeerDiscovery")); 504 } 505 506} 507