Home | History | Annotate | Download | only in wifi
      1 /*
      2  * Copyright (C) 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  */
     16 
     17 package com.googlecode.android_scripting.facade.wifi;
     18 
     19 import android.app.Service;
     20 import android.content.BroadcastReceiver;
     21 import android.content.Context;
     22 import android.content.Intent;
     23 import android.content.IntentFilter;
     24 import android.net.NetworkInfo;
     25 import android.net.wifi.WpsInfo;
     26 import android.net.wifi.p2p.WifiP2pConfig;
     27 import android.net.wifi.p2p.WifiP2pDevice;
     28 import android.net.wifi.p2p.WifiP2pDeviceList;
     29 import android.net.wifi.p2p.WifiP2pGroup;
     30 import android.net.wifi.p2p.WifiP2pGroupList;
     31 import android.net.wifi.p2p.WifiP2pInfo;
     32 import android.net.wifi.p2p.WifiP2pManager;
     33 import android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceInfo;
     34 import android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceRequest;
     35 import android.net.wifi.p2p.nsd.WifiP2pServiceInfo;
     36 import android.net.wifi.p2p.nsd.WifiP2pServiceRequest;
     37 import android.net.wifi.p2p.nsd.WifiP2pUpnpServiceInfo;
     38 import android.net.wifi.p2p.nsd.WifiP2pUpnpServiceRequest;
     39 import android.os.Bundle;
     40 import android.os.Message;
     41 import android.os.Messenger;
     42 import android.os.RemoteException;
     43 
     44 import com.android.internal.util.Protocol;
     45 
     46 import com.googlecode.android_scripting.Log;
     47 import com.googlecode.android_scripting.facade.EventFacade;
     48 import com.googlecode.android_scripting.facade.FacadeManager;
     49 import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
     50 import com.googlecode.android_scripting.rpc.Rpc;
     51 import com.googlecode.android_scripting.rpc.RpcParameter;
     52 
     53 import org.json.JSONArray;
     54 import org.json.JSONException;
     55 import org.json.JSONObject;
     56 
     57 import java.net.InetAddress;
     58 import java.util.ArrayList;
     59 import java.util.Collection;
     60 import java.util.HashMap;
     61 import java.util.Iterator;
     62 import java.util.List;
     63 import java.util.Map;
     64 
     65 /**
     66  * WifiP2pManager functions.
     67  */
     68 public class WifiP2pManagerFacade extends RpcReceiver {
     69 
     70     class WifiP2pActionListener implements WifiP2pManager.ActionListener {
     71         private final EventFacade mEventFacade;
     72         private final String mEventType;
     73         private final String TAG;
     74 
     75         public WifiP2pActionListener(EventFacade eventFacade, String tag) {
     76             mEventType = "WifiP2p";
     77             mEventFacade = eventFacade;
     78             TAG = tag;
     79         }
     80 
     81         @Override
     82         public void onSuccess() {
     83             mEventFacade.postEvent(mEventType + TAG + "OnSuccess", null);
     84         }
     85 
     86         @Override
     87         public void onFailure(int reason) {
     88             Log.d("WifiActionListener  " + mEventType);
     89             Bundle msg = new Bundle();
     90             if (reason == WifiP2pManager.P2P_UNSUPPORTED) {
     91                 msg.putString("reason", "P2P_UNSUPPORTED");
     92             } else if (reason == WifiP2pManager.ERROR) {
     93                 msg.putString("reason", "ERROR");
     94             } else if (reason == WifiP2pManager.BUSY) {
     95                 msg.putString("reason", "BUSY");
     96             } else if (reason == WifiP2pManager.NO_SERVICE_REQUESTS) {
     97                 msg.putString("reason", "NO_SERVICE_REQUESTS");
     98             } else {
     99                 msg.putInt("reason", reason);
    100             }
    101             mEventFacade.postEvent(mEventType + TAG + "OnFailure", msg);
    102         }
    103     }
    104 
    105     class WifiP2pConnectionInfoListener implements WifiP2pManager.ConnectionInfoListener {
    106         private final EventFacade mEventFacade;
    107         private final String mEventType;
    108 
    109         public WifiP2pConnectionInfoListener(EventFacade eventFacade) {
    110             mEventType = "WifiP2p";
    111             mEventFacade = eventFacade;
    112         }
    113 
    114         @Override
    115         public void onConnectionInfoAvailable(WifiP2pInfo info) {
    116             Bundle msg = new Bundle();
    117             msg.putBoolean("groupFormed", info.groupFormed);
    118             msg.putBoolean("isGroupOwner", info.isGroupOwner);
    119             InetAddress addr = info.groupOwnerAddress;
    120             String hostName = null;
    121             String hostAddress = null;
    122             if (addr != null) {
    123                 hostName = addr.getHostName();
    124                 hostAddress = addr.getHostAddress();
    125             }
    126             msg.putString("groupOwnerHostName", hostName);
    127             msg.putString("groupOwnerHostAddress", hostAddress);
    128             mEventFacade.postEvent(mEventType + "OnConnectionInfoAvailable", msg);
    129         }
    130     }
    131 
    132     class WifiP2pDnsSdServiceResponseListener implements
    133             WifiP2pManager.DnsSdServiceResponseListener {
    134         private final EventFacade mEventFacade;
    135         private final String mEventType;
    136 
    137         public WifiP2pDnsSdServiceResponseListener(EventFacade eventFacade) {
    138             mEventType = "WifiP2p";
    139             mEventFacade = eventFacade;
    140         }
    141 
    142         @Override
    143         public void onDnsSdServiceAvailable(String instanceName, String registrationType,
    144                 WifiP2pDevice srcDevice) {
    145             Bundle msg = new Bundle();
    146             msg.putString("InstanceName", instanceName);
    147             msg.putString("RegistrationType", registrationType);
    148             msg.putString("SourceDeviceName", srcDevice.deviceName);
    149             msg.putString("SourceDeviceAddress", srcDevice.deviceAddress);
    150             mEventFacade.postEvent(mEventType + "OnDnsSdServiceAvailable", msg);
    151         }
    152     }
    153 
    154     class WifiP2pDnsSdTxtRecordListener implements WifiP2pManager.DnsSdTxtRecordListener {
    155         private final EventFacade mEventFacade;
    156         private final String mEventType;
    157 
    158         public WifiP2pDnsSdTxtRecordListener(EventFacade eventFacade) {
    159             mEventType = "WifiP2p";
    160             mEventFacade = eventFacade;
    161         }
    162 
    163         @Override
    164         public void onDnsSdTxtRecordAvailable(String fullDomainName,
    165                 Map<String, String> txtRecordMap, WifiP2pDevice srcDevice) {
    166             Bundle msg = new Bundle();
    167             msg.putString("FullDomainName", fullDomainName);
    168             Bundle txtMap = new Bundle();
    169             for (String key : txtRecordMap.keySet()) {
    170                 txtMap.putString(key, txtRecordMap.get(key));
    171             }
    172             msg.putBundle("TxtRecordMap", txtMap);
    173             msg.putString("SourceDeviceName", srcDevice.deviceName);
    174             msg.putString("SourceDeviceAddress", srcDevice.deviceAddress);
    175             mEventFacade.postEvent(mEventType + "OnDnsSdTxtRecordAvailable", msg);
    176         }
    177     }
    178 
    179     class WifiP2pGroupInfoListener implements WifiP2pManager.GroupInfoListener {
    180         private final EventFacade mEventFacade;
    181         private final String mEventType;
    182 
    183         public WifiP2pGroupInfoListener(EventFacade eventFacade) {
    184             mEventType = "WifiP2p";
    185             mEventFacade = eventFacade;
    186         }
    187 
    188         @Override
    189         public void onGroupInfoAvailable(WifiP2pGroup group) {
    190             mEventFacade.postEvent(mEventType + "OnGroupInfoAvailable", parseGroupInfo(group));
    191         }
    192     }
    193 
    194     class WifiP2pPeerListListener implements WifiP2pManager.PeerListListener {
    195         private final EventFacade mEventFacade;
    196 
    197         public WifiP2pPeerListListener(EventFacade eventFacade) {
    198             mEventFacade = eventFacade;
    199         }
    200 
    201         @Override
    202         public void onPeersAvailable(WifiP2pDeviceList newPeers) {
    203             Collection<WifiP2pDevice> devices = newPeers.getDeviceList();
    204             Log.d(devices.toString());
    205             if (devices.size() > 0) {
    206                 mP2pPeers.clear();
    207                 mP2pPeers.addAll(devices);
    208                 Bundle msg = new Bundle();
    209                 msg.putParcelableList("Peers", mP2pPeers);
    210                 mEventFacade.postEvent(mEventType + "OnPeersAvailable", msg);
    211             }
    212         }
    213     }
    214 
    215     class WifiP2pPersistentGroupInfoListener implements WifiP2pManager.PersistentGroupInfoListener {
    216         private final EventFacade mEventFacade;
    217         private final String mEventType;
    218 
    219         public WifiP2pPersistentGroupInfoListener(EventFacade eventFacade) {
    220             mEventType = "WifiP2p";
    221             mEventFacade = eventFacade;
    222         }
    223 
    224         @Override
    225         public void onPersistentGroupInfoAvailable(WifiP2pGroupList groups) {
    226             ArrayList<Bundle> gs = new ArrayList<Bundle>();
    227             for (WifiP2pGroup g : groups.getGroupList()) {
    228                 gs.add(parseGroupInfo(g));
    229             }
    230             mEventFacade.postEvent(mEventType + "OnPersistentGroupInfoAvailable", gs);
    231         }
    232     }
    233 
    234     class WifiP2pOngoingPeerConfigListener implements WifiP2pManager.OngoingPeerInfoListener {
    235         private final EventFacade mEventFacade;
    236         private final String mEventType;
    237 
    238         WifiP2pOngoingPeerConfigListener(EventFacade eventFacade) {
    239             mEventType = "WifiP2p";
    240             mEventFacade = eventFacade;
    241         }
    242 
    243         @Override
    244         public void onOngoingPeerAvailable(WifiP2pConfig config) {
    245             Bundle msg = new Bundle();
    246             mEventFacade.postEvent(mEventType + "OnOngoingPeerAvailable", config);
    247         }
    248     }
    249 
    250     class WifiP2pUpnpServiceResponseListener implements WifiP2pManager.UpnpServiceResponseListener {
    251         private final EventFacade mEventFacade;
    252         private final String mEventType;
    253 
    254         WifiP2pUpnpServiceResponseListener(EventFacade eventFacade) {
    255             mEventType = "WifiP2p";
    256             mEventFacade = eventFacade;
    257         }
    258 
    259         @Override
    260         public void onUpnpServiceAvailable(List<String> uniqueServiceNames,
    261                 WifiP2pDevice srcDevice) {
    262             Bundle msg = new Bundle();
    263             msg.putParcelable("Device", srcDevice);
    264             msg.putStringArrayList("ServiceList", new ArrayList(uniqueServiceNames));
    265             mEventFacade.postEvent(mEventType + "OnUpnpServiceAvailable", msg);
    266         }
    267     }
    268 
    269     class WifiP2pStateChangedReceiver extends BroadcastReceiver {
    270         private final EventFacade mEventFacade;
    271 
    272         WifiP2pStateChangedReceiver(EventFacade eventFacade) {
    273             mEventFacade = eventFacade;
    274         }
    275 
    276         @Override
    277         public void onReceive(Context c, Intent intent) {
    278             Bundle mResults = new Bundle();
    279             String action = intent.getAction();
    280             if (action.equals(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION)) {
    281                 Log.d("Wifi P2p State Changed.");
    282                 int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, 0);
    283                 if (state == WifiP2pManager.WIFI_P2P_STATE_DISABLED) {
    284                     Log.d("Disabled");
    285                     isP2pEnabled = false;
    286                 } else if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {
    287                     Log.d("Enabled");
    288                     isP2pEnabled = true;
    289                 }
    290             } else if (action.equals(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION)) {
    291                 Log.d("Wifi P2p Peers Changed. Requesting peers.");
    292                 WifiP2pDeviceList peers = intent
    293                         .getParcelableExtra(WifiP2pManager.EXTRA_P2P_DEVICE_LIST);
    294                 Log.d(peers.toString());
    295                 wifiP2pRequestPeers();
    296             } else if (action.equals(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION)) {
    297                 Log.d("Wifi P2p Connection Changed.");
    298                 WifiP2pInfo p2pInfo = intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO);
    299                 NetworkInfo networkInfo = intent
    300                         .getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);
    301                 WifiP2pGroup group = intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP);
    302                 if (networkInfo.isConnected()) {
    303                     Log.d("Wifi P2p Connected.");
    304                     mResults.putParcelable("P2pInfo", p2pInfo);
    305                     mResults.putParcelable("Group", group);
    306                     mEventFacade.postEvent(mEventType + "Connected", mResults);
    307                 } else {
    308                     mEventFacade.postEvent(mEventType + "Disconnected", null);
    309                 }
    310             } else if (action.equals(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION)) {
    311                 Log.d("Wifi P2p This Device Changed.");
    312                 WifiP2pDevice device = intent
    313                         .getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE);
    314                 mResults.putParcelable("Device", device);
    315                 mEventFacade.postEvent(mEventType + "ThisDeviceChanged", mResults);
    316             } else if (action.equals(WifiP2pManager.WIFI_P2P_DISCOVERY_CHANGED_ACTION)) {
    317                 Log.d("Wifi P2p Discovery Changed.");
    318                 int state = intent.getIntExtra(WifiP2pManager.EXTRA_DISCOVERY_STATE, 0);
    319                 if (state == WifiP2pManager.WIFI_P2P_DISCOVERY_STARTED) {
    320                     Log.d("discovery started.");
    321                 } else if (state == WifiP2pManager.WIFI_P2P_DISCOVERY_STOPPED) {
    322                     Log.d("discovery stoped.");
    323                 }
    324             }
    325         }
    326     }
    327 
    328     private final static String mEventType = "WifiP2p";
    329 
    330     private WifiP2pManager.Channel mChannel;
    331     private final EventFacade mEventFacade;
    332     private final WifiP2pManager mP2p;
    333     private final WifiP2pStateChangedReceiver mP2pStateChangedReceiver;
    334     private final Service mService;
    335     private final IntentFilter mStateChangeFilter;
    336     private final Map<Integer, WifiP2pServiceRequest> mServiceRequests;
    337 
    338     private boolean isP2pEnabled;
    339     private int mServiceRequestCnt = 0;
    340     private WifiP2pServiceInfo mServiceInfo = null;
    341     private List<WifiP2pDevice> mP2pPeers = new ArrayList<WifiP2pDevice>();
    342 
    343     public WifiP2pManagerFacade(FacadeManager manager) {
    344         super(manager);
    345         mService = manager.getService();
    346         mP2p = (WifiP2pManager) mService.getSystemService(Context.WIFI_P2P_SERVICE);
    347         mEventFacade = manager.getReceiver(EventFacade.class);
    348 
    349         mStateChangeFilter = new IntentFilter(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
    350         mStateChangeFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
    351         mStateChangeFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
    352         mStateChangeFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
    353         mStateChangeFilter.setPriority(999);
    354 
    355         mP2pStateChangedReceiver = new WifiP2pStateChangedReceiver(mEventFacade);
    356         mServiceRequests = new HashMap<Integer, WifiP2pServiceRequest>();
    357     }
    358 
    359     public Bundle parseGroupInfo(WifiP2pGroup group) {
    360         Bundle msg = new Bundle();
    361         msg.putString("Interface", group.getInterface());
    362         msg.putString("NetworkName", group.getNetworkName());
    363         msg.putString("Passphrase", group.getPassphrase());
    364         msg.putInt("NetworkId", group.getNetworkId());
    365         msg.putString("OwnerName", group.getOwner().deviceName);
    366         msg.putString("OwnerAddress", group.getOwner().deviceAddress);
    367         return msg;
    368     }
    369 
    370     @Override
    371     public void shutdown() {
    372         mService.unregisterReceiver(mP2pStateChangedReceiver);
    373     }
    374 
    375     @Rpc(description = "Accept p2p connection invitation.")
    376     public void wifiP2pAcceptConnection() throws RemoteException {
    377         Log.d("Accepting p2p connection.");
    378         Messenger m = mP2p.getP2pStateMachineMessenger();
    379         int user_accept = Protocol.BASE_WIFI_P2P_SERVICE + 2;
    380         Message msg = Message.obtain();
    381         msg.what = user_accept;
    382         m.send(msg);
    383     }
    384 
    385     @Rpc(description = "Reject p2p connection invitation.")
    386     public void wifiP2pRejectConnection() throws RemoteException {
    387         Log.d("Rejecting p2p connection.");
    388         Messenger m = mP2p.getP2pStateMachineMessenger();
    389         int user_accept = Protocol.BASE_WIFI_P2P_SERVICE + 3;
    390         Message msg = Message.obtain();
    391         msg.what = user_accept;
    392         m.send(msg);
    393     }
    394 
    395     /**
    396      * Confirm p2p keypad connection invitation.
    397      */
    398     @Rpc(description = "Confirm p2p keypad connection invitation.")
    399     public void wifiP2pConfirmConnection() throws RemoteException {
    400         Log.d("Confirm p2p connection.");
    401         Messenger m = mP2p.getP2pStateMachineMessenger();
    402         int user_confirm = Protocol.BASE_WIFI_P2P_SERVICE + 7;
    403         Message msg = Message.obtain();
    404         msg.what = user_confirm;
    405         m.send(msg);
    406     }
    407 
    408     @Rpc(description = "Register a local service for service discovery. One of the \"CreateXxxServiceInfo functions needs to be called first.\"")
    409     public void wifiP2pAddLocalService() {
    410         mP2p.addLocalService(mChannel, mServiceInfo,
    411                 new WifiP2pActionListener(mEventFacade, "AddLocalService"));
    412     }
    413 
    414     @Rpc(description = "Add a service discovery request.")
    415     public Integer wifiP2pAddServiceRequest(
    416             @RpcParameter(name = "protocolType") Integer protocolType) {
    417         WifiP2pServiceRequest request = WifiP2pServiceRequest.newInstance(protocolType);
    418         mServiceRequestCnt += 1;
    419         mServiceRequests.put(mServiceRequestCnt, request);
    420         mP2p.addServiceRequest(mChannel, request, new WifiP2pActionListener(mEventFacade,
    421                 "AddServiceRequest"));
    422         return mServiceRequestCnt;
    423     }
    424 
    425     /**
    426      * Add a service upnp discovery request.
    427      * @param query The part of service specific query
    428      */
    429     @Rpc(description = "Add a service upnp discovery request.")
    430     public Integer wifiP2pAddUpnpServiceRequest(
    431             @RpcParameter(name = "query") String query) {
    432         WifiP2pUpnpServiceRequest request = WifiP2pUpnpServiceRequest.newInstance(query);
    433         mServiceRequestCnt += 1;
    434         mServiceRequests.put(mServiceRequestCnt, request);
    435         mP2p.addServiceRequest(mChannel, request, new WifiP2pActionListener(mEventFacade,
    436                 "AddUpnpServiceRequest"));
    437         return mServiceRequestCnt;
    438     }
    439 
    440     /**
    441      * Create a service discovery request to get the TXT data from the specified
    442      * Bonjour service.
    443      *
    444      * @param instanceName instance name. Can be null.
    445      * e.g)
    446      *  "MyPrinter"
    447      * @param serviceType service type. Cannot be null.
    448      * e.g)
    449      *  "_afpovertcp._tcp."(Apple File Sharing over TCP)
    450      *  "_ipp._tcp" (IP Printing over TCP)
    451      *  "_http._tcp" (http service)
    452      */
    453     @Rpc(description = "Add a service dns discovery request.")
    454     public Integer wifiP2pAddDnssdServiceRequest(
    455             @RpcParameter(name = "serviceType") String serviceType,
    456             @RpcParameter(name = "instanceName") String instanceName) {
    457         WifiP2pDnsSdServiceRequest request;
    458         if (instanceName != null) {
    459             request = WifiP2pDnsSdServiceRequest.newInstance(instanceName, serviceType);
    460         } else {
    461             request = WifiP2pDnsSdServiceRequest.newInstance(serviceType);
    462         }
    463         mServiceRequestCnt += 1;
    464         mServiceRequests.put(mServiceRequestCnt, request);
    465         mP2p.addServiceRequest(mChannel, request, new WifiP2pActionListener(mEventFacade,
    466                 "AddDnssdServiceRequest"));
    467         return mServiceRequestCnt;
    468     }
    469 
    470     @Rpc(description = "Cancel any ongoing connect negotiation.")
    471     public void wifiP2pCancelConnect() {
    472         mP2p.cancelConnect(mChannel, new WifiP2pActionListener(mEventFacade, "CancelConnect"));
    473     }
    474 
    475     @Rpc(description = "Clear all registered local services of service discovery.")
    476     public void wifiP2pClearLocalServices() {
    477         mP2p.clearLocalServices(mChannel,
    478                 new WifiP2pActionListener(mEventFacade, "ClearLocalServices"));
    479     }
    480 
    481     @Rpc(description = "Clear all registered service discovery requests.")
    482     public void wifiP2pClearServiceRequests() {
    483         mP2p.clearServiceRequests(mChannel,
    484                 new WifiP2pActionListener(mEventFacade, "ClearServiceRequests"));
    485     }
    486 
    487     /**
    488      * Connects to a discovered wifi p2p device
    489      * @param config JSONObject Dictionary of p2p connection parameters
    490      * @throws JSONException
    491      */
    492     @Rpc(description = "Connects to a discovered wifi p2p device.")
    493     public void wifiP2pConnect(@RpcParameter(name = "config") JSONObject config)
    494             throws JSONException {
    495         WifiP2pConfig wifiP2pConfig = genWifiP2pConfig(config);
    496         mP2p.connect(mChannel, wifiP2pConfig,
    497                 new WifiP2pActionListener(mEventFacade, "Connect"));
    498     }
    499 
    500     @Rpc(description = "Create a Bonjour service info object to be used for wifiP2pAddLocalService.")
    501     public void wifiP2pCreateBonjourServiceInfo(
    502             @RpcParameter(name = "instanceName") String instanceName,
    503             @RpcParameter(name = "serviceType") String serviceType,
    504             @RpcParameter(name = "txtMap") JSONObject txtMap) throws JSONException {
    505         Map<String, String> map = new HashMap<String, String>();
    506         Iterator<String> keyIterator = txtMap.keys();
    507         while (keyIterator.hasNext()) {
    508             String key = keyIterator.next();
    509             map.put(key, txtMap.getString(key));
    510         }
    511         mServiceInfo = WifiP2pDnsSdServiceInfo.newInstance(instanceName, serviceType, map);
    512     }
    513 
    514     @Rpc(description = "Create a wifi p2p group.")
    515     public void wifiP2pCreateGroup() {
    516         mP2p.createGroup(mChannel, new WifiP2pActionListener(mEventFacade, "CreateGroup"));
    517     }
    518 
    519     /**
    520      * Create a group with config.
    521      *
    522      * @param config JSONObject Dictionary of p2p connection parameters
    523      * @throws JSONException
    524      */
    525     @Rpc(description = "Create a wifi p2p group with config.")
    526     public void wifiP2pCreateGroupWithConfig(@RpcParameter(name = "config") JSONObject config)
    527             throws JSONException {
    528         WifiP2pConfig wifiP2pConfig = genWifiP2pConfig(config);
    529         mP2p.createGroup(mChannel, wifiP2pConfig,
    530                 new WifiP2pActionListener(mEventFacade, "CreateGroup"));
    531     }
    532 
    533     @Rpc(description = "Create a Upnp service info object to be used for wifiP2pAddLocalService.")
    534     public void wifiP2pCreateUpnpServiceInfo(
    535             @RpcParameter(name = "uuid") String uuid,
    536             @RpcParameter(name = "device") String device,
    537             @RpcParameter(name = "services") JSONArray services) throws JSONException {
    538         List<String> serviceList = new ArrayList<String>();
    539         for (int i = 0; i < services.length(); i++) {
    540             serviceList.add(services.getString(i));
    541             Log.d("wifiP2pCreateUpnpServiceInfo, services: " + services.getString(i));
    542         }
    543         mServiceInfo = WifiP2pUpnpServiceInfo.newInstance(uuid, device, serviceList);
    544     }
    545 
    546     @Rpc(description = "Delete a stored persistent group from the system settings.")
    547     public void wifiP2pDeletePersistentGroup(@RpcParameter(name = "netId") Integer netId) {
    548         mP2p.deletePersistentGroup(mChannel, netId,
    549                 new WifiP2pActionListener(mEventFacade, "DeletePersistentGroup"));
    550     }
    551 
    552     private boolean wifiP2pDeviceMatches(WifiP2pDevice d, String deviceId) {
    553         return d.deviceName.equals(deviceId) || d.deviceAddress.equals(deviceId);
    554     }
    555 
    556     @Rpc(description = "Start peers discovery for wifi p2p.")
    557     public void wifiP2pDiscoverPeers() {
    558         mP2p.discoverPeers(mChannel, new WifiP2pActionListener(mEventFacade, "DiscoverPeers"));
    559     }
    560 
    561     @Rpc(description = "Initiate service discovery.")
    562     public void wifiP2pDiscoverServices() {
    563         mP2p.discoverServices(mChannel,
    564                 new WifiP2pActionListener(mEventFacade, "DiscoverServices"));
    565     }
    566 
    567     @Rpc(description = "Initialize wifi p2p. Must be called before any other p2p functions.")
    568     public void wifiP2pInitialize() {
    569         mService.registerReceiver(mP2pStateChangedReceiver, mStateChangeFilter);
    570         mChannel = mP2p.initialize(mService, mService.getMainLooper(), null);
    571     }
    572 
    573     @Rpc(description = "Sets the listening channel and operating channel of the current group created with initialize")
    574     public void wifiP2pSetChannelsForCurrentGroup(
    575             @RpcParameter(name = "listeningChannel") Integer listeningChannel,
    576             @RpcParameter(name = "operatingChannel") Integer operatingChannel) {
    577         mP2p.setWifiP2pChannels(mChannel, listeningChannel, operatingChannel,
    578                 new WifiP2pActionListener(mEventFacade, "SetChannels"));
    579     }
    580 
    581     @Rpc(description = "Close the current wifi p2p connection created with initialize.")
    582     public void wifiP2pClose() {
    583         if (mChannel != null) {
    584             mChannel.close();
    585         }
    586     }
    587 
    588     @Rpc(description = "Returns true if wifi p2p is enabled, false otherwise.")
    589     public Boolean wifiP2pIsEnabled() {
    590         return isP2pEnabled;
    591     }
    592 
    593     @Rpc(description = "Remove the current p2p group.")
    594     public void wifiP2pRemoveGroup() {
    595         mP2p.removeGroup(mChannel, new WifiP2pActionListener(mEventFacade, "RemoveGroup"));
    596     }
    597 
    598     @Rpc(description = "Remove a registered local service added with wifiP2pAddLocalService.")
    599     public void wifiP2pRemoveLocalService() {
    600         mP2p.removeLocalService(mChannel, mServiceInfo,
    601                 new WifiP2pActionListener(mEventFacade, "RemoveLocalService"));
    602     }
    603 
    604     @Rpc(description = "Remove a service discovery request.")
    605     public void wifiP2pRemoveServiceRequest(@RpcParameter(name = "index") Integer index) {
    606         mP2p.removeServiceRequest(mChannel, mServiceRequests.remove(index),
    607                 new WifiP2pActionListener(mEventFacade, "RemoveServiceRequest"));
    608     }
    609 
    610     @Rpc(description = "Request device connection info.")
    611     public void wifiP2pRequestConnectionInfo() {
    612         mP2p.requestConnectionInfo(mChannel, new WifiP2pConnectionInfoListener(mEventFacade));
    613     }
    614 
    615     @Rpc(description = "Create a wifi p2p group.")
    616     public void wifiP2pRequestGroupInfo() {
    617         mP2p.requestGroupInfo(mChannel, new WifiP2pGroupInfoListener(mEventFacade));
    618     }
    619 
    620     @Rpc(description = "Request peers that are discovered for wifi p2p.")
    621     public void wifiP2pRequestPeers() {
    622         mP2p.requestPeers(mChannel, new WifiP2pPeerListListener(mEventFacade));
    623     }
    624 
    625     @Rpc(description = "Request a list of all the persistent p2p groups stored in system.")
    626     public void wifiP2pRequestPersistentGroupInfo() {
    627         mP2p.requestPersistentGroupInfo(mChannel,
    628                 new WifiP2pPersistentGroupInfoListener(mEventFacade));
    629     }
    630 
    631     @Rpc(description = "Set p2p device name.")
    632     public void wifiP2pSetDeviceName(@RpcParameter(name = "devName") String devName) {
    633         mP2p.setDeviceName(mChannel, devName,
    634                 new WifiP2pActionListener(mEventFacade, "SetDeviceName"));
    635     }
    636 
    637     @Rpc(description = "Register a callback to be invoked on receiving Bonjour service discovery response.")
    638     public void wifiP2pSetDnsSdResponseListeners() {
    639         mP2p.setDnsSdResponseListeners(mChannel,
    640                 new WifiP2pDnsSdServiceResponseListener(mEventFacade),
    641                 new WifiP2pDnsSdTxtRecordListener(mEventFacade));
    642     }
    643 
    644     /**
    645      * Register a callback to be invoked on receiving
    646      * Upnp service discovery response.
    647      */
    648     @Rpc(description = "Register a callback to be invoked on receiving "
    649             + "Upnp service discovery response.")
    650     public void wifiP2pSetUpnpResponseListeners() {
    651         mP2p.setUpnpServiceResponseListener(mChannel,
    652                 new WifiP2pUpnpServiceResponseListener(mEventFacade));
    653     }
    654 
    655     @Rpc(description = "Stop an ongoing peer discovery.")
    656     public void wifiP2pStopPeerDiscovery() {
    657         mP2p.stopPeerDiscovery(mChannel,
    658                 new WifiP2pActionListener(mEventFacade, "StopPeerDiscovery"));
    659     }
    660 
    661     private WpsInfo genWpsInfo(JSONObject j) throws JSONException {
    662         if (j == null) {
    663             return null;
    664         }
    665         WpsInfo wpsInfo = new WpsInfo();
    666         if (j.has("setup")) {
    667             wpsInfo.setup = j.getInt("setup");
    668         }
    669         if (j.has("BSSID")) {
    670             wpsInfo.BSSID = j.getString("BSSID");
    671         }
    672         if (j.has("pin")) {
    673             wpsInfo.pin = j.getString("pin");
    674         }
    675         return wpsInfo;
    676     }
    677 
    678     private WifiP2pConfig genWifiP2pConfig(JSONObject j) throws JSONException,
    679             NumberFormatException {
    680         if (j == null) {
    681             return null;
    682         }
    683         WifiP2pConfig config = new WifiP2pConfig();
    684         if (j.has("networkName") && j.has("passphrase")) {
    685             WifiP2pConfig.Builder b = new WifiP2pConfig.Builder();
    686             b.setNetworkName(j.getString("networkName"));
    687             b.setPassphrase(j.getString("passphrase"));
    688             if (j.has("groupOwnerBand")) {
    689                 b.setGroupOperatingBand(Integer.parseInt(j.getString("groupOwnerBand")));
    690             }
    691             config = b.build();
    692         }
    693         if (j.has("deviceAddress")) {
    694             config.deviceAddress = j.getString("deviceAddress");
    695         }
    696         if (j.has("wpsInfo")) {
    697             config.wps = genWpsInfo(j.getJSONObject("wpsInfo"));
    698         }
    699         if (j.has("groupOwnerIntent")) {
    700             config.groupOwnerIntent = j.getInt("groupOwnerIntent");
    701         }
    702         if (j.has("netId")) {
    703             config.netId = j.getInt("netId");
    704         }
    705         return config;
    706     }
    707 
    708     /**
    709      * Set saved WifiP2pConfig for an ongoing peer connection
    710      * @param wifiP2pConfig JSONObject Dictionary of p2p connection parameters
    711      * @throws JSONException
    712      */
    713     @Rpc(description = "Set saved WifiP2pConfig for an ongoing peer connection")
    714     public void setP2pPeerConfigure(@RpcParameter(name = "config") JSONObject wifiP2pConfig)
    715             throws JSONException {
    716         mP2p.setOngoingPeerConfig(mChannel, genWifiP2pConfig(wifiP2pConfig),
    717                 new WifiP2pActionListener(mEventFacade, "setP2pPeerConfigure"));
    718     }
    719 
    720     /**
    721      * Request saved WifiP2pConfig which used for an ongoing peer connection
    722      */
    723     @Rpc(description = "Request saved WifiP2pConfig which used for an ongoing peer connection")
    724     public void requestP2pPeerConfigure() {
    725         mP2p.requestOngoingPeerConfig(mChannel, new WifiP2pOngoingPeerConfigListener(mEventFacade));
    726     }
    727 }
    728