• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 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 android.net.wifi.p2p;
18 
19 import android.annotation.SdkConstant;
20 import android.annotation.SdkConstant.SdkConstantType;
21 import android.content.Context;
22 import android.net.ConnectivityManager;
23 import android.net.IConnectivityManager;
24 import android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceInfo;
25 import android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceResponse;
26 import android.net.wifi.p2p.nsd.WifiP2pServiceInfo;
27 import android.net.wifi.p2p.nsd.WifiP2pServiceRequest;
28 import android.net.wifi.p2p.nsd.WifiP2pServiceResponse;
29 import android.net.wifi.p2p.nsd.WifiP2pUpnpServiceInfo;
30 import android.net.wifi.p2p.nsd.WifiP2pUpnpServiceResponse;
31 import android.os.Binder;
32 import android.os.Bundle;
33 import android.os.IBinder;
34 import android.os.Handler;
35 import android.os.Looper;
36 import android.os.Message;
37 import android.os.Messenger;
38 import android.os.RemoteException;
39 import android.os.ServiceManager;
40 import android.os.WorkSource;
41 import android.util.Log;
42 
43 import com.android.internal.util.AsyncChannel;
44 import com.android.internal.util.Protocol;
45 
46 import java.util.HashMap;
47 import java.util.List;
48 import java.util.Map;
49 
50 /**
51  * This class provides the API for managing Wi-Fi peer-to-peer connectivity. This lets an
52  * application discover available peers, setup connection to peers and query for the list of peers.
53  * When a p2p connection is formed over wifi, the device continues to maintain the uplink
54  * connection over mobile or any other available network for internet connectivity on the device.
55  *
56  * <p> The API is asynchronous and responses to requests from an application are on listener
57  * callbacks provided by the application. The application needs to do an initialization with
58  * {@link #initialize} before doing any p2p operation.
59  *
60  * <p> Most application calls need a {@link ActionListener} instance for receiving callbacks
61  * {@link ActionListener#onSuccess} or {@link ActionListener#onFailure}. Action callbacks
62  * indicate whether the initiation of the action was a success or a failure.
63  * Upon failure, the reason of failure can be one of {@link #ERROR}, {@link #P2P_UNSUPPORTED}
64  * or {@link #BUSY}.
65  *
66  * <p> An application can initiate discovery of peers with {@link #discoverPeers}. An initiated
67  * discovery request from an application stays active until the device starts connecting to a peer
68  * ,forms a p2p group or there is an explicit {@link #stopPeerDiscovery}.
69  * Applications can listen to {@link #WIFI_P2P_DISCOVERY_CHANGED_ACTION} to know if a peer-to-peer
70  * discovery is running or stopped. Additionally, {@link #WIFI_P2P_PEERS_CHANGED_ACTION} indicates
71  * if the peer list has changed.
72  *
73  * <p> When an application needs to fetch the current list of peers, it can request the list
74  * of peers with {@link #requestPeers}. When the peer list is available
75  * {@link PeerListListener#onPeersAvailable} is called with the device list.
76  *
77  * <p> An application can initiate a connection request to a peer through {@link #connect}. See
78  * {@link WifiP2pConfig} for details on setting up the configuration. For communication with legacy
79  * Wi-Fi devices that do not support p2p, an app can create a group using {@link #createGroup}
80  * which creates an access point whose details can be fetched with {@link #requestGroupInfo}.
81  *
82  * <p> After a successful group formation through {@link #createGroup} or through {@link #connect},
83  * use {@link #requestConnectionInfo} to fetch the connection details. The connection info
84  * {@link WifiP2pInfo} contains the address of the group owner
85  * {@link WifiP2pInfo#groupOwnerAddress} and a flag {@link WifiP2pInfo#isGroupOwner} to indicate
86  * if the current device is a p2p group owner. A p2p client can thus communicate with
87  * the p2p group owner through a socket connection.
88  *
89  * <p> With peer discovery using {@link  #discoverPeers}, an application discovers the neighboring
90  * peers, but has no good way to figure out which peer to establish a connection with. For example,
91  * if a game application is interested in finding all the neighboring peers that are also running
92  * the same game, it has no way to find out until after the connection is setup. Pre-association
93  * service discovery is meant to address this issue of filtering the peers based on the running
94  * services.
95  *
96  * <p>With pre-association service discovery, an application can advertise a service for a
97  * application on a peer device prior to a connection setup between the devices.
98  * Currently, DNS based service discovery (Bonjour) and Upnp are the higher layer protocols
99  * supported. Get Bonjour resources at dns-sd.org and Upnp resources at upnp.org
100  * As an example, a video application can discover a Upnp capable media renderer
101  * prior to setting up a Wi-fi p2p connection with the device.
102  *
103  * <p> An application can advertise a Upnp or a Bonjour service with a call to
104  * {@link #addLocalService}. After a local service is added,
105  * the framework automatically responds to a peer application discovering the service prior
106  * to establishing a p2p connection. A call to {@link #removeLocalService} removes a local
107  * service and {@link #clearLocalServices} can be used to clear all local services.
108  *
109  * <p> An application that is looking for peer devices that support certain services
110  * can do so with a call to  {@link #discoverServices}. Prior to initiating the discovery,
111  * application can add service discovery request with a call to {@link #addServiceRequest},
112  * remove a service discovery request with a call to {@link #removeServiceRequest} or clear
113  * all requests with a call to {@link #clearServiceRequests}. When no service requests remain,
114  * a previously running service discovery will stop.
115  *
116  * The application is notified of a result of service discovery request through listener callbacks
117  * set through {@link #setDnsSdResponseListeners} for Bonjour or
118  * {@link #setUpnpServiceResponseListener} for Upnp.
119  *
120  * <p class="note"><strong>Note:</strong>
121  * Registering an application handler with {@link #initialize} requires the permissions
122  * {@link android.Manifest.permission#ACCESS_WIFI_STATE} and
123  * {@link android.Manifest.permission#CHANGE_WIFI_STATE} to perform any further peer-to-peer
124  * operations.
125  *
126  * Get an instance of this class by calling {@link android.content.Context#getSystemService(String)
127  * Context.getSystemService(Context.WIFI_P2P_SERVICE)}.
128  *
129  * {@see WifiP2pConfig}
130  * {@see WifiP2pInfo}
131  * {@see WifiP2pGroup}
132  * {@see WifiP2pDevice}
133  * {@see WifiP2pDeviceList}
134  * {@see android.net.wifi.WpsInfo}
135  */
136 public class WifiP2pManager {
137     private static final String TAG = "WifiP2pManager";
138     /**
139      * Broadcast intent action to indicate whether Wi-Fi p2p is enabled or disabled. An
140      * extra {@link #EXTRA_WIFI_STATE} provides the state information as int.
141      *
142      * @see #EXTRA_WIFI_STATE
143      */
144     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
145     public static final String WIFI_P2P_STATE_CHANGED_ACTION =
146         "android.net.wifi.p2p.STATE_CHANGED";
147 
148     /**
149      * The lookup key for an int that indicates whether Wi-Fi p2p is enabled or disabled.
150      * Retrieve it with {@link android.content.Intent#getIntExtra(String,int)}.
151      *
152      * @see #WIFI_P2P_STATE_DISABLED
153      * @see #WIFI_P2P_STATE_ENABLED
154      */
155     public static final String EXTRA_WIFI_STATE = "wifi_p2p_state";
156 
157     /**
158      * Wi-Fi p2p is disabled.
159      *
160      * @see #WIFI_P2P_STATE_CHANGED_ACTION
161      */
162     public static final int WIFI_P2P_STATE_DISABLED = 1;
163 
164     /**
165      * Wi-Fi p2p is enabled.
166      *
167      * @see #WIFI_P2P_STATE_CHANGED_ACTION
168      */
169     public static final int WIFI_P2P_STATE_ENABLED = 2;
170 
171     /**
172      * Broadcast intent action indicating that the state of Wi-Fi p2p connectivity
173      * has changed. One extra {@link #EXTRA_WIFI_P2P_INFO} provides the p2p connection info in
174      * the form of a {@link WifiP2pInfo} object. Another extra {@link #EXTRA_NETWORK_INFO} provides
175      * the network info in the form of a {@link android.net.NetworkInfo}.
176      *
177      * @see #EXTRA_WIFI_P2P_INFO
178      * @see #EXTRA_NETWORK_INFO
179      */
180     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
181     public static final String WIFI_P2P_CONNECTION_CHANGED_ACTION =
182         "android.net.wifi.p2p.CONNECTION_STATE_CHANGE";
183 
184     /**
185      * The lookup key for a {@link android.net.wifi.p2p.WifiP2pInfo} object
186      * Retrieve with {@link android.content.Intent#getParcelableExtra(String)}.
187      */
188     public static final String EXTRA_WIFI_P2P_INFO = "wifiP2pInfo";
189 
190     /**
191      * The lookup key for a {@link android.net.NetworkInfo} object associated with the
192      * Wi-Fi network. Retrieve with
193      * {@link android.content.Intent#getParcelableExtra(String)}.
194      */
195     public static final String EXTRA_NETWORK_INFO = "networkInfo";
196 
197     /**
198      * The lookup key for a {@link android.net.LinkProperties} object associated with the
199      * network. Retrieve with
200      * {@link android.content.Intent#getParcelableExtra(String)}.
201      * @hide
202      */
203     public static final String EXTRA_LINK_PROPERTIES = "linkProperties";
204 
205     /**
206      * The lookup key for a {@link android.net.LinkCapabilities} object associated with the
207      * network. Retrieve with
208      * {@link android.content.Intent#getParcelableExtra(String)}.
209      * @hide
210      */
211     public static final String EXTRA_LINK_CAPABILITIES = "linkCapabilities";
212 
213     /**
214      * Broadcast intent action indicating that the available peer list has changed. Fetch
215      * the changed list of peers with {@link #requestPeers}
216      */
217     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
218     public static final String WIFI_P2P_PEERS_CHANGED_ACTION =
219         "android.net.wifi.p2p.PEERS_CHANGED";
220 
221     /**
222      * Broadcast intent action indicating that peer discovery has either started or stopped.
223      * One extra {@link #EXTRA_DISCOVERY_STATE} indicates whether discovery has started
224      * or stopped.
225      *
226      * Note that discovery will be stopped during a connection setup. If the application tries
227      * to re-initiate discovery during this time, it can fail.
228      */
229     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
230     public static final String WIFI_P2P_DISCOVERY_CHANGED_ACTION =
231         "android.net.wifi.p2p.DISCOVERY_STATE_CHANGE";
232 
233     /**
234      * The lookup key for an int that indicates whether p2p discovery has started or stopped.
235      * Retrieve it with {@link android.content.Intent#getIntExtra(String,int)}.
236      *
237      * @see #WIFI_P2P_DISCOVERY_STARTED
238      * @see #WIFI_P2P_DISCOVERY_STOPPED
239      */
240     public static final String EXTRA_DISCOVERY_STATE = "discoveryState";
241 
242     /**
243      * p2p discovery has stopped
244      *
245      * @see #WIFI_P2P_DISCOVERY_CHANGED_ACTION
246      */
247     public static final int WIFI_P2P_DISCOVERY_STOPPED = 1;
248 
249     /**
250      * p2p discovery has started
251      *
252      * @see #WIFI_P2P_DISCOVERY_CHANGED_ACTION
253      */
254     public static final int WIFI_P2P_DISCOVERY_STARTED = 2;
255 
256     /**
257      * Broadcast intent action indicating that this device details have changed.
258      */
259     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
260     public static final String WIFI_P2P_THIS_DEVICE_CHANGED_ACTION =
261         "android.net.wifi.p2p.THIS_DEVICE_CHANGED";
262 
263     /**
264      * The lookup key for a {@link android.net.wifi.p2p.WifiP2pDevice} object
265      * Retrieve with {@link android.content.Intent#getParcelableExtra(String)}.
266      */
267     public static final String EXTRA_WIFI_P2P_DEVICE = "wifiP2pDevice";
268 
269     /**
270      * Broadcast intent action indicating that remembered persistent groups have changed.
271      * @hide
272      */
273     public static final String WIFI_P2P_PERSISTENT_GROUPS_CHANGED_ACTION =
274         "android.net.wifi.p2p.PERSISTENT_GROUPS_CHANGED";
275 
276     /**
277      * The lookup key for a {@link #String} object.
278      * Retrieve with {@link android.os.Bundle#getString(String)}.
279      * @hide
280      */
281     public static final String APP_PKG_BUNDLE_KEY = "appPkgName";
282 
283     /**
284      * The lookup key for a {@link #Boolean} object.
285      * Retrieve with {@link android.os.Bundle#getBoolean(String)}.
286      * @hide
287      */
288     public static final String RESET_DIALOG_LISTENER_BUNDLE_KEY = "dialogResetFlag";
289 
290     /**
291      * The lookup key for a {@link #String} object.
292      * Retrieve with {@link android.os.Bundle#getString(String)}.
293      * @hide
294      */
295     public static final String WPS_PIN_BUNDLE_KEY = "wpsPin";
296 
297     /**
298      * The lookup key for a {@link android.net.wifi.p2p.WifiP2pDevice} object
299      * Retrieve with {@link android.os.Bundle#getParcelable(String)}.
300      * @hide
301      */
302     public static final String P2P_DEV_BUNDLE_KEY = "wifiP2pDevice";
303 
304     /**
305      * The lookup key for a {@link android.net.wifi.p2p.WifiP2pConfig} object
306      * Retrieve with {@link android.os.Bundle#getParcelable(String)}.
307      * @hide
308      */
309     public static final String P2P_CONFIG_BUNDLE_KEY = "wifiP2pConfig";
310 
311     IWifiP2pManager mService;
312 
313     private static final int BASE = Protocol.BASE_WIFI_P2P_MANAGER;
314 
315     /** @hide */
316     public static final int DISCOVER_PEERS                          = BASE + 1;
317     /** @hide */
318     public static final int DISCOVER_PEERS_FAILED                   = BASE + 2;
319     /** @hide */
320     public static final int DISCOVER_PEERS_SUCCEEDED                = BASE + 3;
321 
322     /** @hide */
323     public static final int STOP_DISCOVERY                          = BASE + 4;
324     /** @hide */
325     public static final int STOP_DISCOVERY_FAILED                   = BASE + 5;
326     /** @hide */
327     public static final int STOP_DISCOVERY_SUCCEEDED                = BASE + 6;
328 
329     /** @hide */
330     public static final int CONNECT                                 = BASE + 7;
331     /** @hide */
332     public static final int CONNECT_FAILED                          = BASE + 8;
333     /** @hide */
334     public static final int CONNECT_SUCCEEDED                       = BASE + 9;
335 
336     /** @hide */
337     public static final int CANCEL_CONNECT                          = BASE + 10;
338     /** @hide */
339     public static final int CANCEL_CONNECT_FAILED                   = BASE + 11;
340     /** @hide */
341     public static final int CANCEL_CONNECT_SUCCEEDED                = BASE + 12;
342 
343     /** @hide */
344     public static final int CREATE_GROUP                            = BASE + 13;
345     /** @hide */
346     public static final int CREATE_GROUP_FAILED                     = BASE + 14;
347     /** @hide */
348     public static final int CREATE_GROUP_SUCCEEDED                  = BASE + 15;
349 
350     /** @hide */
351     public static final int REMOVE_GROUP                            = BASE + 16;
352     /** @hide */
353     public static final int REMOVE_GROUP_FAILED                     = BASE + 17;
354     /** @hide */
355     public static final int REMOVE_GROUP_SUCCEEDED                  = BASE + 18;
356 
357     /** @hide */
358     public static final int REQUEST_PEERS                           = BASE + 19;
359     /** @hide */
360     public static final int RESPONSE_PEERS                          = BASE + 20;
361 
362     /** @hide */
363     public static final int REQUEST_CONNECTION_INFO                 = BASE + 21;
364     /** @hide */
365     public static final int RESPONSE_CONNECTION_INFO                = BASE + 22;
366 
367     /** @hide */
368     public static final int REQUEST_GROUP_INFO                      = BASE + 23;
369     /** @hide */
370     public static final int RESPONSE_GROUP_INFO                     = BASE + 24;
371 
372     /** @hide */
373     public static final int ADD_LOCAL_SERVICE                       = BASE + 28;
374     /** @hide */
375     public static final int ADD_LOCAL_SERVICE_FAILED                = BASE + 29;
376     /** @hide */
377     public static final int ADD_LOCAL_SERVICE_SUCCEEDED             = BASE + 30;
378 
379     /** @hide */
380     public static final int REMOVE_LOCAL_SERVICE                    = BASE + 31;
381     /** @hide */
382     public static final int REMOVE_LOCAL_SERVICE_FAILED             = BASE + 32;
383     /** @hide */
384     public static final int REMOVE_LOCAL_SERVICE_SUCCEEDED          = BASE + 33;
385 
386     /** @hide */
387     public static final int CLEAR_LOCAL_SERVICES                    = BASE + 34;
388     /** @hide */
389     public static final int CLEAR_LOCAL_SERVICES_FAILED             = BASE + 35;
390     /** @hide */
391     public static final int CLEAR_LOCAL_SERVICES_SUCCEEDED          = BASE + 36;
392 
393     /** @hide */
394     public static final int ADD_SERVICE_REQUEST                     = BASE + 37;
395     /** @hide */
396     public static final int ADD_SERVICE_REQUEST_FAILED              = BASE + 38;
397     /** @hide */
398     public static final int ADD_SERVICE_REQUEST_SUCCEEDED           = BASE + 39;
399 
400     /** @hide */
401     public static final int REMOVE_SERVICE_REQUEST                  = BASE + 40;
402     /** @hide */
403     public static final int REMOVE_SERVICE_REQUEST_FAILED           = BASE + 41;
404     /** @hide */
405     public static final int REMOVE_SERVICE_REQUEST_SUCCEEDED        = BASE + 42;
406 
407     /** @hide */
408     public static final int CLEAR_SERVICE_REQUESTS                  = BASE + 43;
409     /** @hide */
410     public static final int CLEAR_SERVICE_REQUESTS_FAILED           = BASE + 44;
411     /** @hide */
412     public static final int CLEAR_SERVICE_REQUESTS_SUCCEEDED        = BASE + 45;
413 
414     /** @hide */
415     public static final int DISCOVER_SERVICES                       = BASE + 46;
416     /** @hide */
417     public static final int DISCOVER_SERVICES_FAILED                = BASE + 47;
418     /** @hide */
419     public static final int DISCOVER_SERVICES_SUCCEEDED             = BASE + 48;
420 
421     /** @hide */
422     public static final int PING                                    = BASE + 49;
423 
424     /** @hide */
425     public static final int RESPONSE_SERVICE                        = BASE + 50;
426 
427     /** @hide */
428     public static final int SET_DEVICE_NAME                         = BASE + 51;
429     /** @hide */
430     public static final int SET_DEVICE_NAME_FAILED                  = BASE + 52;
431     /** @hide */
432     public static final int SET_DEVICE_NAME_SUCCEEDED               = BASE + 53;
433 
434     /** @hide */
435     public static final int SET_DIALOG_LISTENER                     = BASE + 54;
436     /** @hide */
437     public static final int DIALOG_LISTENER_DETACHED                = BASE + 55;
438     /** @hide */
439     public static final int DIALOG_LISTENER_ATTACHED                = BASE + 56;
440 
441     /** @hide */
442     public static final int CONNECTION_REQUESTED                    = BASE + 57;
443     /** @hide */
444     public static final int SHOW_PIN_REQUESTED                      = BASE + 58;
445 
446     /** @hide */
447     public static final int DELETE_PERSISTENT_GROUP                 = BASE + 59;
448     /** @hide */
449     public static final int DELETE_PERSISTENT_GROUP_FAILED          = BASE + 60;
450     /** @hide */
451     public static final int DELETE_PERSISTENT_GROUP_SUCCEEDED       = BASE + 61;
452 
453     /** @hide */
454     public static final int REQUEST_PERSISTENT_GROUP_INFO           = BASE + 62;
455     /** @hide */
456     public static final int RESPONSE_PERSISTENT_GROUP_INFO          = BASE + 63;
457 
458     /** @hide */
459     public static final int SET_WFD_INFO                            = BASE + 64;
460     /** @hide */
461     public static final int SET_WFD_INFO_FAILED                     = BASE + 65;
462     /** @hide */
463     public static final int SET_WFD_INFO_SUCCEEDED                  = BASE + 66;
464 
465     /**
466      * Create a new WifiP2pManager instance. Applications use
467      * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
468      * the standard {@link android.content.Context#WIFI_P2P_SERVICE Context.WIFI_P2P_SERVICE}.
469      * @param service the Binder interface
470      * @hide - hide this because it takes in a parameter of type IWifiP2pManager, which
471      * is a system private class.
472      */
WifiP2pManager(IWifiP2pManager service)473     public WifiP2pManager(IWifiP2pManager service) {
474         mService = service;
475     }
476 
477     /**
478      * Passed with {@link ActionListener#onFailure}.
479      * Indicates that the operation failed due to an internal error.
480      */
481     public static final int ERROR               = 0;
482 
483     /**
484      * Passed with {@link ActionListener#onFailure}.
485      * Indicates that the operation failed because p2p is unsupported on the device.
486      */
487     public static final int P2P_UNSUPPORTED     = 1;
488 
489     /**
490      * Passed with {@link ActionListener#onFailure}.
491      * Indicates that the operation failed because the framework is busy and
492      * unable to service the request
493      */
494     public static final int BUSY                = 2;
495 
496     /**
497      * Passed with {@link ActionListener#onFailure}.
498      * Indicates that the {@link #discoverServices} failed because no service
499      * requests are added. Use {@link #addServiceRequest} to add a service
500      * request.
501      */
502     public static final int NO_SERVICE_REQUESTS = 3;
503 
504     /**
505      * Passed with {@link DialogListener#onDetached}.
506      * Indicates that the registered listener was detached from the system because
507      * the application went into background.
508      * @hide
509      */
510     public static final int NOT_IN_FOREGROUND   = 4;
511 
512     /** Interface for callback invocation when framework channel is lost */
513     public interface ChannelListener {
514         /**
515          * The channel to the framework has been disconnected.
516          * Application could try re-initializing using {@link #initialize}
517          */
onChannelDisconnected()518         public void onChannelDisconnected();
519     }
520 
521     /** Interface for callback invocation on an application action */
522     public interface ActionListener {
523         /** The operation succeeded */
onSuccess()524         public void onSuccess();
525         /**
526          * The operation failed
527          * @param reason The reason for failure could be one of {@link #P2P_UNSUPPORTED},
528          * {@link #ERROR} or {@link #BUSY}
529          */
onFailure(int reason)530         public void onFailure(int reason);
531     }
532 
533     /** Interface for callback invocation when peer list is available */
534     public interface PeerListListener {
535         /**
536          * The requested peer list is available
537          * @param peers List of available peers
538          */
onPeersAvailable(WifiP2pDeviceList peers)539         public void onPeersAvailable(WifiP2pDeviceList peers);
540     }
541 
542     /** Interface for callback invocation when connection info is available */
543     public interface ConnectionInfoListener {
544         /**
545          * The requested connection info is available
546          * @param info Wi-Fi p2p connection info
547          */
onConnectionInfoAvailable(WifiP2pInfo info)548         public void onConnectionInfoAvailable(WifiP2pInfo info);
549     }
550 
551     /** Interface for callback invocation when group info is available */
552     public interface GroupInfoListener {
553         /**
554          * The requested p2p group info is available
555          * @param group Wi-Fi p2p group info
556          */
onGroupInfoAvailable(WifiP2pGroup group)557         public void onGroupInfoAvailable(WifiP2pGroup group);
558     }
559 
560    /**
561     * Interface for callback invocation when service discovery response other than
562     * Upnp or Bonjour is received
563     */
564     public interface ServiceResponseListener {
565 
566         /**
567          * The requested service response is available.
568          *
569          * @param protocolType protocol type. currently only
570          * {@link WifiP2pServiceInfo#SERVICE_TYPE_VENDOR_SPECIFIC}.
571          * @param responseData service discovery response data based on the requested
572          *  service protocol type. The format depends on the service type.
573          * @param srcDevice source device.
574          */
onServiceAvailable(int protocolType, byte[] responseData, WifiP2pDevice srcDevice)575         public void onServiceAvailable(int protocolType,
576                 byte[] responseData, WifiP2pDevice srcDevice);
577     }
578 
579     /**
580      * Interface for callback invocation when Bonjour service discovery response
581      * is received
582      */
583     public interface DnsSdServiceResponseListener {
584 
585         /**
586          * The requested Bonjour service response is available.
587          *
588          * <p>This function is invoked when the device with the specified Bonjour
589          * registration type returned the instance name.
590          * @param instanceName instance name.<br>
591          *  e.g) "MyPrinter".
592          * @param registrationType <br>
593          * e.g) "_ipp._tcp.local."
594          * @param srcDevice source device.
595          */
onDnsSdServiceAvailable(String instanceName, String registrationType, WifiP2pDevice srcDevice)596         public void onDnsSdServiceAvailable(String instanceName,
597                 String registrationType, WifiP2pDevice srcDevice);
598 
599    }
600 
601     /**
602      * Interface for callback invocation when Bonjour TXT record is available
603      * for a service
604      */
605    public interface DnsSdTxtRecordListener {
606         /**
607          * The requested Bonjour service response is available.
608          *
609          * <p>This function is invoked when the device with the specified full
610          * service domain service returned TXT record.
611          *
612          * @param fullDomainName full domain name. <br>
613          * e.g) "MyPrinter._ipp._tcp.local.".
614          * @param txtRecordMap TXT record data as a map of key/value pairs
615          * @param srcDevice source device.
616          */
onDnsSdTxtRecordAvailable(String fullDomainName, Map<String, String> txtRecordMap, WifiP2pDevice srcDevice)617         public void onDnsSdTxtRecordAvailable(String fullDomainName,
618                 Map<String, String> txtRecordMap,
619                 WifiP2pDevice srcDevice);
620    }
621 
622     /**
623      * Interface for callback invocation when upnp service discovery response
624      * is received
625      * */
626     public interface UpnpServiceResponseListener {
627 
628         /**
629          * The requested upnp service response is available.
630          *
631          * <p>This function is invoked when the specified device or service is found.
632          *
633          * @param uniqueServiceNames The list of unique service names.<br>
634          * e.g) uuid:6859dede-8574-59ab-9332-123456789012::urn:schemas-upnp-org:device:
635          * MediaServer:1
636          * @param srcDevice source device.
637          */
onUpnpServiceAvailable(List<String> uniqueServiceNames, WifiP2pDevice srcDevice)638         public void onUpnpServiceAvailable(List<String> uniqueServiceNames,
639                 WifiP2pDevice srcDevice);
640     }
641 
642 
643     /**
644      * Interface for callback invocation when dialog events are received.
645      * see {@link #setDialogListener}.
646      * @hide
647      */
648     public interface DialogListener {
649 
650         /**
651          * Called by the system when a request to show WPS pin is received.
652          *
653          * @param pin WPS pin.
654          */
onShowPinRequested(String pin)655         public void onShowPinRequested(String pin);
656 
657         /**
658          * Called by the system when a request to establish the connection is received.
659          *
660          * Application can then call {@link #connect} with the given config if the request
661          * is acceptable.
662          *
663          * @param device the source device.
664          * @param config p2p configuration.
665          */
onConnectionRequested(WifiP2pDevice device, WifiP2pConfig config)666         public void onConnectionRequested(WifiP2pDevice device, WifiP2pConfig config);
667 
668         /**
669          * Called by the system when this listener was attached to the system.
670          */
onAttached()671         public void onAttached();
672 
673         /**
674          * Called by the system when this listener was detached from the system or
675          * failed to attach.
676          *
677          * Application can request again using {@link #setDialogListener} when it is
678          * in the foreground.
679          *
680          * @param reason The reason for failure could be one of {@link #ERROR},
681          * {@link #BUSY}, {@link #P2P_UNSUPPORTED} or {@link #NOT_IN_FOREGROUND}
682          */
onDetached(int reason)683         public void onDetached(int reason);
684     }
685 
686     /** Interface for callback invocation when stored group info list is available {@hide}*/
687     public interface PersistentGroupInfoListener {
688         /**
689          * The requested stored p2p group info list is available
690          * @param groups Wi-Fi p2p group info list
691          */
onPersistentGroupInfoAvailable(WifiP2pGroupList groups)692         public void onPersistentGroupInfoAvailable(WifiP2pGroupList groups);
693     }
694 
695     /**
696      * A channel that connects the application to the Wifi p2p framework.
697      * Most p2p operations require a Channel as an argument. An instance of Channel is obtained
698      * by doing a call on {@link #initialize}
699      */
700     public static class Channel {
Channel(Context context, Looper looper, ChannelListener l)701         Channel(Context context, Looper looper, ChannelListener l) {
702             mAsyncChannel = new AsyncChannel();
703             mHandler = new P2pHandler(looper);
704             mChannelListener = l;
705             mContext = context;
706         }
707         private final static int INVALID_LISTENER_KEY = 0;
708         private ChannelListener mChannelListener;
709         private ServiceResponseListener mServRspListener;
710         private DnsSdServiceResponseListener mDnsSdServRspListener;
711         private DnsSdTxtRecordListener mDnsSdTxtListener;
712         private UpnpServiceResponseListener mUpnpServRspListener;
713         private HashMap<Integer, Object> mListenerMap = new HashMap<Integer, Object>();
714         private Object mListenerMapLock = new Object();
715         private int mListenerKey = 0;
716         private DialogListener mDialogListener;
717 
718         private AsyncChannel mAsyncChannel;
719         private P2pHandler mHandler;
720         Context mContext;
721         class P2pHandler extends Handler {
P2pHandler(Looper looper)722             P2pHandler(Looper looper) {
723                 super(looper);
724             }
725 
726             @Override
handleMessage(Message message)727             public void handleMessage(Message message) {
728                 Object listener = getListener(message.arg2);
729                 switch (message.what) {
730                     case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
731                         if (mChannelListener != null) {
732                             mChannelListener.onChannelDisconnected();
733                             mChannelListener = null;
734                         }
735                         break;
736                     /* ActionListeners grouped together */
737                     case WifiP2pManager.DISCOVER_PEERS_FAILED:
738                     case WifiP2pManager.STOP_DISCOVERY_FAILED:
739                     case WifiP2pManager.DISCOVER_SERVICES_FAILED:
740                     case WifiP2pManager.CONNECT_FAILED:
741                     case WifiP2pManager.CANCEL_CONNECT_FAILED:
742                     case WifiP2pManager.CREATE_GROUP_FAILED:
743                     case WifiP2pManager.REMOVE_GROUP_FAILED:
744                     case WifiP2pManager.ADD_LOCAL_SERVICE_FAILED:
745                     case WifiP2pManager.REMOVE_LOCAL_SERVICE_FAILED:
746                     case WifiP2pManager.CLEAR_LOCAL_SERVICES_FAILED:
747                     case WifiP2pManager.ADD_SERVICE_REQUEST_FAILED:
748                     case WifiP2pManager.REMOVE_SERVICE_REQUEST_FAILED:
749                     case WifiP2pManager.CLEAR_SERVICE_REQUESTS_FAILED:
750                     case WifiP2pManager.SET_DEVICE_NAME_FAILED:
751                     case WifiP2pManager.DELETE_PERSISTENT_GROUP_FAILED:
752                     case WifiP2pManager.SET_WFD_INFO_FAILED:
753                         if (listener != null) {
754                             ((ActionListener) listener).onFailure(message.arg1);
755                         }
756                         break;
757                     /* ActionListeners grouped together */
758                     case WifiP2pManager.DISCOVER_PEERS_SUCCEEDED:
759                     case WifiP2pManager.STOP_DISCOVERY_SUCCEEDED:
760                     case WifiP2pManager.DISCOVER_SERVICES_SUCCEEDED:
761                     case WifiP2pManager.CONNECT_SUCCEEDED:
762                     case WifiP2pManager.CANCEL_CONNECT_SUCCEEDED:
763                     case WifiP2pManager.CREATE_GROUP_SUCCEEDED:
764                     case WifiP2pManager.REMOVE_GROUP_SUCCEEDED:
765                     case WifiP2pManager.ADD_LOCAL_SERVICE_SUCCEEDED:
766                     case WifiP2pManager.REMOVE_LOCAL_SERVICE_SUCCEEDED:
767                     case WifiP2pManager.CLEAR_LOCAL_SERVICES_SUCCEEDED:
768                     case WifiP2pManager.ADD_SERVICE_REQUEST_SUCCEEDED:
769                     case WifiP2pManager.REMOVE_SERVICE_REQUEST_SUCCEEDED:
770                     case WifiP2pManager.CLEAR_SERVICE_REQUESTS_SUCCEEDED:
771                     case WifiP2pManager.SET_DEVICE_NAME_SUCCEEDED:
772                     case WifiP2pManager.DELETE_PERSISTENT_GROUP_SUCCEEDED:
773                     case WifiP2pManager.SET_WFD_INFO_SUCCEEDED:
774                         if (listener != null) {
775                             ((ActionListener) listener).onSuccess();
776                         }
777                         break;
778                     case WifiP2pManager.RESPONSE_PEERS:
779                         WifiP2pDeviceList peers = (WifiP2pDeviceList) message.obj;
780                         if (listener != null) {
781                             ((PeerListListener) listener).onPeersAvailable(peers);
782                         }
783                         break;
784                     case WifiP2pManager.RESPONSE_CONNECTION_INFO:
785                         WifiP2pInfo wifiP2pInfo = (WifiP2pInfo) message.obj;
786                         if (listener != null) {
787                             ((ConnectionInfoListener) listener).onConnectionInfoAvailable(wifiP2pInfo);
788                         }
789                         break;
790                     case WifiP2pManager.RESPONSE_GROUP_INFO:
791                         WifiP2pGroup group = (WifiP2pGroup) message.obj;
792                         if (listener != null) {
793                             ((GroupInfoListener) listener).onGroupInfoAvailable(group);
794                         }
795                         break;
796                     case WifiP2pManager.RESPONSE_SERVICE:
797                         WifiP2pServiceResponse resp = (WifiP2pServiceResponse) message.obj;
798                         handleServiceResponse(resp);
799                         break;
800                     case WifiP2pManager.CONNECTION_REQUESTED:
801                         if (mDialogListener != null) {
802                             Bundle bundle = message.getData();
803                             mDialogListener.onConnectionRequested(
804                                     (WifiP2pDevice)bundle.getParcelable(
805                                             P2P_DEV_BUNDLE_KEY),
806                                     (WifiP2pConfig)bundle.getParcelable(
807                                             P2P_CONFIG_BUNDLE_KEY));
808                         }
809                         break;
810                     case WifiP2pManager.SHOW_PIN_REQUESTED:
811                         if (mDialogListener != null) {
812                             Bundle bundle = message.getData();
813                             mDialogListener.onShowPinRequested(
814                                     bundle.getString(WPS_PIN_BUNDLE_KEY));
815                         }
816                         break;
817                     case WifiP2pManager.DIALOG_LISTENER_ATTACHED:
818                         if (mDialogListener != null) {
819                             mDialogListener.onAttached();
820                         }
821                         break;
822                     case WifiP2pManager.DIALOG_LISTENER_DETACHED:
823                         if (mDialogListener != null) {
824                             mDialogListener.onDetached(message.arg1);
825                             mDialogListener = null;
826                         }
827                         break;
828                     case WifiP2pManager.RESPONSE_PERSISTENT_GROUP_INFO:
829                         WifiP2pGroupList groups = (WifiP2pGroupList) message.obj;
830                         if (listener != null) {
831                             ((PersistentGroupInfoListener) listener).
832                                 onPersistentGroupInfoAvailable(groups);
833                         }
834                         break;
835                    default:
836                         Log.d(TAG, "Ignored " + message);
837                         break;
838                 }
839             }
840         }
841 
handleServiceResponse(WifiP2pServiceResponse resp)842         private void handleServiceResponse(WifiP2pServiceResponse resp) {
843             if (resp instanceof WifiP2pDnsSdServiceResponse) {
844                 handleDnsSdServiceResponse((WifiP2pDnsSdServiceResponse)resp);
845             } else if (resp instanceof WifiP2pUpnpServiceResponse) {
846                 if (mUpnpServRspListener != null) {
847                     handleUpnpServiceResponse((WifiP2pUpnpServiceResponse)resp);
848                 }
849             } else {
850                 if (mServRspListener != null) {
851                     mServRspListener.onServiceAvailable(resp.getServiceType(),
852                             resp.getRawData(), resp.getSrcDevice());
853                 }
854             }
855         }
856 
handleUpnpServiceResponse(WifiP2pUpnpServiceResponse resp)857         private void handleUpnpServiceResponse(WifiP2pUpnpServiceResponse resp) {
858             mUpnpServRspListener.onUpnpServiceAvailable(resp.getUniqueServiceNames(),
859                     resp.getSrcDevice());
860         }
861 
handleDnsSdServiceResponse(WifiP2pDnsSdServiceResponse resp)862         private void handleDnsSdServiceResponse(WifiP2pDnsSdServiceResponse resp) {
863             if (resp.getDnsType() == WifiP2pDnsSdServiceInfo.DNS_TYPE_PTR) {
864                 if (mDnsSdServRspListener != null) {
865                     mDnsSdServRspListener.onDnsSdServiceAvailable(
866                             resp.getInstanceName(),
867                             resp.getDnsQueryName(),
868                             resp.getSrcDevice());
869                 }
870             } else if (resp.getDnsType() == WifiP2pDnsSdServiceInfo.DNS_TYPE_TXT) {
871                 if (mDnsSdTxtListener != null) {
872                     mDnsSdTxtListener.onDnsSdTxtRecordAvailable(
873                             resp.getDnsQueryName(),
874                             resp.getTxtRecord(),
875                             resp.getSrcDevice());
876                 }
877             } else {
878                 Log.e(TAG, "Unhandled resp " + resp);
879             }
880         }
881 
putListener(Object listener)882         private int putListener(Object listener) {
883             if (listener == null) return INVALID_LISTENER_KEY;
884             int key;
885             synchronized (mListenerMapLock) {
886                 do {
887                     key = mListenerKey++;
888                 } while (key == INVALID_LISTENER_KEY);
889                 mListenerMap.put(key, listener);
890             }
891             return key;
892         }
893 
getListener(int key)894         private Object getListener(int key) {
895             if (key == INVALID_LISTENER_KEY) return null;
896             synchronized (mListenerMapLock) {
897                 return mListenerMap.remove(key);
898             }
899         }
900 
setDialogListener(DialogListener listener)901         private void setDialogListener(DialogListener listener) {
902             mDialogListener = listener;
903         }
904     }
905 
checkChannel(Channel c)906     private static void checkChannel(Channel c) {
907         if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
908     }
909 
checkServiceInfo(WifiP2pServiceInfo info)910     private static void checkServiceInfo(WifiP2pServiceInfo info) {
911         if (info == null) throw new IllegalArgumentException("service info is null");
912     }
913 
checkServiceRequest(WifiP2pServiceRequest req)914     private static void checkServiceRequest(WifiP2pServiceRequest req) {
915         if (req == null) throw new IllegalArgumentException("service request is null");
916     }
917 
918     /**
919      * Registers the application with the Wi-Fi framework. This function
920      * must be the first to be called before any p2p operations are performed.
921      *
922      * @param srcContext is the context of the source
923      * @param srcLooper is the Looper on which the callbacks are receivied
924      * @param listener for callback at loss of framework communication. Can be null.
925      * @return Channel instance that is necessary for performing any further p2p operations
926      */
initialize(Context srcContext, Looper srcLooper, ChannelListener listener)927     public Channel initialize(Context srcContext, Looper srcLooper, ChannelListener listener) {
928         Messenger messenger = getMessenger();
929         if (messenger == null) return null;
930 
931         Channel c = new Channel(srcContext, srcLooper, listener);
932         if (c.mAsyncChannel.connectSync(srcContext, c.mHandler, messenger)
933                 == AsyncChannel.STATUS_SUCCESSFUL) {
934             return c;
935         } else {
936             return null;
937         }
938     }
939 
940     /**
941      * Initiate peer discovery. A discovery process involves scanning for available Wi-Fi peers
942      * for the purpose of establishing a connection.
943      *
944      * <p> The function call immediately returns after sending a discovery request
945      * to the framework. The application is notified of a success or failure to initiate
946      * discovery through listener callbacks {@link ActionListener#onSuccess} or
947      * {@link ActionListener#onFailure}.
948      *
949      * <p> The discovery remains active until a connection is initiated or
950      * a p2p group is formed. Register for {@link #WIFI_P2P_PEERS_CHANGED_ACTION} intent to
951      * determine when the framework notifies of a change as peers are discovered.
952      *
953      * <p> Upon receiving a {@link #WIFI_P2P_PEERS_CHANGED_ACTION} intent, an application
954      * can request for the list of peers using {@link #requestPeers}.
955      *
956      * @param c is the channel created at {@link #initialize}
957      * @param listener for callbacks on success or failure. Can be null.
958      */
discoverPeers(Channel c, ActionListener listener)959     public void discoverPeers(Channel c, ActionListener listener) {
960         checkChannel(c);
961         c.mAsyncChannel.sendMessage(DISCOVER_PEERS, 0, c.putListener(listener));
962     }
963 
964    /**
965      * Stop an ongoing peer discovery
966      *
967      * <p> The function call immediately returns after sending a stop request
968      * to the framework. The application is notified of a success or failure to initiate
969      * stop through listener callbacks {@link ActionListener#onSuccess} or
970      * {@link ActionListener#onFailure}.
971      *
972      * @param c is the channel created at {@link #initialize}
973      * @param listener for callbacks on success or failure. Can be null.
974      */
stopPeerDiscovery(Channel c, ActionListener listener)975     public void stopPeerDiscovery(Channel c, ActionListener listener) {
976         checkChannel(c);
977         c.mAsyncChannel.sendMessage(STOP_DISCOVERY, 0, c.putListener(listener));
978     }
979 
980     /**
981      * Start a p2p connection to a device with the specified configuration.
982      *
983      * <p> The function call immediately returns after sending a connection request
984      * to the framework. The application is notified of a success or failure to initiate
985      * connect through listener callbacks {@link ActionListener#onSuccess} or
986      * {@link ActionListener#onFailure}.
987      *
988      * <p> Register for {@link #WIFI_P2P_CONNECTION_CHANGED_ACTION} intent to
989      * determine when the framework notifies of a change in connectivity.
990      *
991      * <p> If the current device is not part of a p2p group, a connect request initiates
992      * a group negotiation with the peer.
993      *
994      * <p> If the current device is part of an existing p2p group or has created
995      * a p2p group with {@link #createGroup}, an invitation to join the group is sent to
996      * the peer device.
997      *
998      * @param c is the channel created at {@link #initialize}
999      * @param config options as described in {@link WifiP2pConfig} class
1000      * @param listener for callbacks on success or failure. Can be null.
1001      */
connect(Channel c, WifiP2pConfig config, ActionListener listener)1002     public void connect(Channel c, WifiP2pConfig config, ActionListener listener) {
1003         checkChannel(c);
1004         c.mAsyncChannel.sendMessage(CONNECT, 0, c.putListener(listener), config);
1005     }
1006 
1007     /**
1008      * Cancel any ongoing p2p group negotiation
1009      *
1010      * <p> The function call immediately returns after sending a connection cancellation request
1011      * to the framework. The application is notified of a success or failure to initiate
1012      * cancellation through listener callbacks {@link ActionListener#onSuccess} or
1013      * {@link ActionListener#onFailure}.
1014      *
1015      * @param c is the channel created at {@link #initialize}
1016      * @param listener for callbacks on success or failure. Can be null.
1017      */
cancelConnect(Channel c, ActionListener listener)1018     public void cancelConnect(Channel c, ActionListener listener) {
1019         checkChannel(c);
1020         c.mAsyncChannel.sendMessage(CANCEL_CONNECT, 0, c.putListener(listener));
1021     }
1022 
1023     /**
1024      * Create a p2p group with the current device as the group owner. This essentially creates
1025      * an access point that can accept connections from legacy clients as well as other p2p
1026      * devices.
1027      *
1028      * <p class="note"><strong>Note:</strong>
1029      * This function would normally not be used unless the current device needs
1030      * to form a p2p connection with a legacy client
1031      *
1032      * <p> The function call immediately returns after sending a group creation request
1033      * to the framework. The application is notified of a success or failure to initiate
1034      * group creation through listener callbacks {@link ActionListener#onSuccess} or
1035      * {@link ActionListener#onFailure}.
1036      *
1037      * <p> Application can request for the group details with {@link #requestGroupInfo}.
1038      *
1039      * @param c is the channel created at {@link #initialize}
1040      * @param listener for callbacks on success or failure. Can be null.
1041      */
createGroup(Channel c, ActionListener listener)1042     public void createGroup(Channel c, ActionListener listener) {
1043         checkChannel(c);
1044         c.mAsyncChannel.sendMessage(CREATE_GROUP, WifiP2pGroup.PERSISTENT_NET_ID,
1045                 c.putListener(listener));
1046     }
1047 
1048     /**
1049      * Remove the current p2p group.
1050      *
1051      * <p> The function call immediately returns after sending a group removal request
1052      * to the framework. The application is notified of a success or failure to initiate
1053      * group removal through listener callbacks {@link ActionListener#onSuccess} or
1054      * {@link ActionListener#onFailure}.
1055      *
1056      * @param c is the channel created at {@link #initialize}
1057      * @param listener for callbacks on success or failure. Can be null.
1058      */
removeGroup(Channel c, ActionListener listener)1059     public void removeGroup(Channel c, ActionListener listener) {
1060         checkChannel(c);
1061         c.mAsyncChannel.sendMessage(REMOVE_GROUP, 0, c.putListener(listener));
1062     }
1063 
1064     /**
1065      * Register a local service for service discovery. If a local service is registered,
1066      * the framework automatically responds to a service discovery request from a peer.
1067      *
1068      * <p> The function call immediately returns after sending a request to add a local
1069      * service to the framework. The application is notified of a success or failure to
1070      * add service through listener callbacks {@link ActionListener#onSuccess} or
1071      * {@link ActionListener#onFailure}.
1072      *
1073      * <p>The service information is set through {@link WifiP2pServiceInfo}.<br>
1074      * or its subclass calls  {@link WifiP2pUpnpServiceInfo#newInstance} or
1075      *  {@link WifiP2pDnsSdServiceInfo#newInstance} for a Upnp or Bonjour service
1076      * respectively
1077      *
1078      * <p>The service information can be cleared with calls to
1079      *  {@link #removeLocalService} or {@link #clearLocalServices}.
1080      *
1081      * @param c is the channel created at {@link #initialize}
1082      * @param servInfo is a local service information.
1083      * @param listener for callbacks on success or failure. Can be null.
1084      */
addLocalService(Channel c, WifiP2pServiceInfo servInfo, ActionListener listener)1085     public void addLocalService(Channel c, WifiP2pServiceInfo servInfo, ActionListener listener) {
1086         checkChannel(c);
1087         checkServiceInfo(servInfo);
1088         c.mAsyncChannel.sendMessage(ADD_LOCAL_SERVICE, 0, c.putListener(listener), servInfo);
1089     }
1090 
1091     /**
1092      * Remove a registered local service added with {@link #addLocalService}
1093      *
1094      * <p> The function call immediately returns after sending a request to remove a
1095      * local service to the framework. The application is notified of a success or failure to
1096      * add service through listener callbacks {@link ActionListener#onSuccess} or
1097      * {@link ActionListener#onFailure}.
1098      *
1099      * @param c is the channel created at {@link #initialize}
1100      * @param servInfo is the local service information.
1101      * @param listener for callbacks on success or failure. Can be null.
1102      */
removeLocalService(Channel c, WifiP2pServiceInfo servInfo, ActionListener listener)1103     public void removeLocalService(Channel c, WifiP2pServiceInfo servInfo,
1104             ActionListener listener) {
1105         checkChannel(c);
1106         checkServiceInfo(servInfo);
1107         c.mAsyncChannel.sendMessage(REMOVE_LOCAL_SERVICE, 0, c.putListener(listener), servInfo);
1108     }
1109 
1110     /**
1111      * Clear all registered local services of service discovery.
1112      *
1113      * <p> The function call immediately returns after sending a request to clear all
1114      * local services to the framework. The application is notified of a success or failure to
1115      * add service through listener callbacks {@link ActionListener#onSuccess} or
1116      * {@link ActionListener#onFailure}.
1117      *
1118      * @param c is the channel created at {@link #initialize}
1119      * @param listener for callbacks on success or failure. Can be null.
1120      */
clearLocalServices(Channel c, ActionListener listener)1121     public void clearLocalServices(Channel c, ActionListener listener) {
1122         checkChannel(c);
1123         c.mAsyncChannel.sendMessage(CLEAR_LOCAL_SERVICES, 0, c.putListener(listener));
1124     }
1125 
1126     /**
1127      * Register a callback to be invoked on receiving service discovery response.
1128      * Used only for vendor specific protocol right now. For Bonjour or Upnp, use
1129      * {@link #setDnsSdResponseListeners} or {@link #setUpnpServiceResponseListener}
1130      * respectively.
1131      *
1132      * <p> see {@link #discoverServices} for the detail.
1133      *
1134      * @param c is the channel created at {@link #initialize}
1135      * @param listener for callbacks on receiving service discovery response.
1136      */
setServiceResponseListener(Channel c, ServiceResponseListener listener)1137     public void setServiceResponseListener(Channel c,
1138             ServiceResponseListener listener) {
1139         checkChannel(c);
1140         c.mServRspListener = listener;
1141     }
1142 
1143     /**
1144      * Register a callback to be invoked on receiving Bonjour service discovery
1145      * response.
1146      *
1147      * <p> see {@link #discoverServices} for the detail.
1148      *
1149      * @param c
1150      * @param servListener is for listening to a Bonjour service response
1151      * @param txtListener is for listening to a Bonjour TXT record response
1152      */
setDnsSdResponseListeners(Channel c, DnsSdServiceResponseListener servListener, DnsSdTxtRecordListener txtListener)1153     public void setDnsSdResponseListeners(Channel c,
1154             DnsSdServiceResponseListener servListener, DnsSdTxtRecordListener txtListener) {
1155         checkChannel(c);
1156         c.mDnsSdServRspListener = servListener;
1157         c.mDnsSdTxtListener = txtListener;
1158     }
1159 
1160     /**
1161      * Register a callback to be invoked on receiving upnp service discovery
1162      * response.
1163      *
1164      * <p> see {@link #discoverServices} for the detail.
1165      *
1166      * @param c is the channel created at {@link #initialize}
1167      * @param listener for callbacks on receiving service discovery response.
1168      */
setUpnpServiceResponseListener(Channel c, UpnpServiceResponseListener listener)1169     public void setUpnpServiceResponseListener(Channel c,
1170             UpnpServiceResponseListener listener) {
1171         checkChannel(c);
1172         c.mUpnpServRspListener = listener;
1173     }
1174 
1175     /**
1176      * Initiate service discovery. A discovery process involves scanning for
1177      * requested services for the purpose of establishing a connection to a peer
1178      * that supports an available service.
1179      *
1180      * <p> The function call immediately returns after sending a request to start service
1181      * discovery to the framework. The application is notified of a success or failure to initiate
1182      * discovery through listener callbacks {@link ActionListener#onSuccess} or
1183      * {@link ActionListener#onFailure}.
1184      *
1185      * <p> The services to be discovered are specified with calls to {@link #addServiceRequest}.
1186      *
1187      * <p>The application is notified of the response against the service discovery request
1188      * through listener callbacks registered by {@link #setServiceResponseListener} or
1189      * {@link #setDnsSdResponseListeners}, or {@link #setUpnpServiceResponseListener}.
1190      *
1191      * @param c is the channel created at {@link #initialize}
1192      * @param listener for callbacks on success or failure. Can be null.
1193      */
discoverServices(Channel c, ActionListener listener)1194     public void discoverServices(Channel c, ActionListener listener) {
1195         checkChannel(c);
1196         c.mAsyncChannel.sendMessage(DISCOVER_SERVICES, 0, c.putListener(listener));
1197     }
1198 
1199     /**
1200      * Add a service discovery request.
1201      *
1202      * <p> The function call immediately returns after sending a request to add service
1203      * discovery request to the framework. The application is notified of a success or failure to
1204      * add service through listener callbacks {@link ActionListener#onSuccess} or
1205      * {@link ActionListener#onFailure}.
1206      *
1207      * <p>After service discovery request is added, you can initiate service discovery by
1208      * {@link #discoverServices}.
1209      *
1210      * <p>The added service requests can be cleared with calls to
1211      * {@link #removeServiceRequest(Channel, WifiP2pServiceRequest, ActionListener)} or
1212      * {@link #clearServiceRequests(Channel, ActionListener)}.
1213      *
1214      * @param c is the channel created at {@link #initialize}
1215      * @param req is the service discovery request.
1216      * @param listener for callbacks on success or failure. Can be null.
1217      */
addServiceRequest(Channel c, WifiP2pServiceRequest req, ActionListener listener)1218     public void addServiceRequest(Channel c,
1219             WifiP2pServiceRequest req, ActionListener listener) {
1220         checkChannel(c);
1221         checkServiceRequest(req);
1222         c.mAsyncChannel.sendMessage(ADD_SERVICE_REQUEST, 0,
1223                 c.putListener(listener), req);
1224     }
1225 
1226     /**
1227      * Remove a specified service discovery request added with {@link #addServiceRequest}
1228      *
1229      * <p> The function call immediately returns after sending a request to remove service
1230      * discovery request to the framework. The application is notified of a success or failure to
1231      * add service through listener callbacks {@link ActionListener#onSuccess} or
1232      * {@link ActionListener#onFailure}.
1233      *
1234      * @param c is the channel created at {@link #initialize}
1235      * @param req is the service discovery request.
1236      * @param listener for callbacks on success or failure. Can be null.
1237      */
removeServiceRequest(Channel c, WifiP2pServiceRequest req, ActionListener listener)1238     public void removeServiceRequest(Channel c, WifiP2pServiceRequest req,
1239             ActionListener listener) {
1240         checkChannel(c);
1241         checkServiceRequest(req);
1242         c.mAsyncChannel.sendMessage(REMOVE_SERVICE_REQUEST, 0,
1243                 c.putListener(listener), req);
1244     }
1245 
1246     /**
1247      * Clear all registered service discovery requests.
1248      *
1249      * <p> The function call immediately returns after sending a request to clear all
1250      * service discovery requests to the framework. The application is notified of a success
1251      * or failure to add service through listener callbacks {@link ActionListener#onSuccess} or
1252      * {@link ActionListener#onFailure}.
1253      *
1254      * @param c is the channel created at {@link #initialize}
1255      * @param listener for callbacks on success or failure. Can be null.
1256      */
clearServiceRequests(Channel c, ActionListener listener)1257     public void clearServiceRequests(Channel c, ActionListener listener) {
1258         checkChannel(c);
1259         c.mAsyncChannel.sendMessage(CLEAR_SERVICE_REQUESTS,
1260                 0, c.putListener(listener));
1261     }
1262 
1263     /**
1264      * Request the current list of peers.
1265      *
1266      * @param c is the channel created at {@link #initialize}
1267      * @param listener for callback when peer list is available. Can be null.
1268      */
requestPeers(Channel c, PeerListListener listener)1269     public void requestPeers(Channel c, PeerListListener listener) {
1270         checkChannel(c);
1271         c.mAsyncChannel.sendMessage(REQUEST_PEERS, 0, c.putListener(listener));
1272     }
1273 
1274     /**
1275      * Request device connection info.
1276      *
1277      * @param c is the channel created at {@link #initialize}
1278      * @param listener for callback when connection info is available. Can be null.
1279      */
requestConnectionInfo(Channel c, ConnectionInfoListener listener)1280     public void requestConnectionInfo(Channel c, ConnectionInfoListener listener) {
1281         checkChannel(c);
1282         c.mAsyncChannel.sendMessage(REQUEST_CONNECTION_INFO, 0, c.putListener(listener));
1283     }
1284 
1285     /**
1286      * Request p2p group info.
1287      *
1288      * @param c is the channel created at {@link #initialize}
1289      * @param listener for callback when group info is available. Can be null.
1290      */
requestGroupInfo(Channel c, GroupInfoListener listener)1291     public void requestGroupInfo(Channel c, GroupInfoListener listener) {
1292         checkChannel(c);
1293         c.mAsyncChannel.sendMessage(REQUEST_GROUP_INFO, 0, c.putListener(listener));
1294     }
1295 
1296     /**
1297      * Set p2p device name.
1298      * @hide
1299      * @param c is the channel created at {@link #initialize}
1300      * @param listener for callback when group info is available. Can be null.
1301      */
setDeviceName(Channel c, String devName, ActionListener listener)1302     public void setDeviceName(Channel c, String devName, ActionListener listener) {
1303         checkChannel(c);
1304         WifiP2pDevice d = new WifiP2pDevice();
1305         d.deviceName = devName;
1306         c.mAsyncChannel.sendMessage(SET_DEVICE_NAME, 0, c.putListener(listener), d);
1307     }
1308 
1309     /** @hide */
setWFDInfo( Channel c, WifiP2pWfdInfo wfdInfo, ActionListener listener)1310     public void setWFDInfo(
1311             Channel c, WifiP2pWfdInfo wfdInfo,
1312             ActionListener listener) {
1313         checkChannel(c);
1314         c.mAsyncChannel.sendMessage(SET_WFD_INFO, 0, c.putListener(listener), wfdInfo);
1315     }
1316 
1317     /**
1318      * Set dialog listener to over-ride system dialogs on p2p events. This function
1319      * allows an application to receive notifications on connection requests from
1320      * peers so that it can customize the user experience for connection with
1321      * peers.
1322      *
1323      * <p> The function call immediately returns after sending a request
1324      * to the framework. The application is notified of a success or failure to attach
1325      * to the system through listener callbacks {@link DialogListener#onAttached} or
1326      * {@link DialogListener#onDetached}.
1327      *
1328      * <p> Note that only foreground application will be successful in overriding the
1329      * system dialogs.
1330      * @hide
1331      *
1332      * @param c is the channel created at {@link #initialize}
1333      * @param listener for callback on a dialog event.
1334      */
setDialogListener(Channel c, DialogListener listener)1335     public void setDialogListener(Channel c, DialogListener listener) {
1336         checkChannel(c);
1337         c.setDialogListener(listener);
1338 
1339         /**
1340          * mAsyncChannel should always stay private and inaccessible from the app
1341          * to prevent an app from sending a message with a fake app name to gain
1342          * control over the dialogs
1343          */
1344         Message msg = Message.obtain();
1345         Bundle bundle = new Bundle();
1346         bundle.putString(APP_PKG_BUNDLE_KEY, c.mContext.getPackageName());
1347         bundle.putBoolean(RESET_DIALOG_LISTENER_BUNDLE_KEY, listener == null);
1348         msg.what = SET_DIALOG_LISTENER;
1349         msg.setData(bundle);
1350         c.mAsyncChannel.sendMessage(msg);
1351     }
1352 
1353     /**
1354      * Delete a stored persistent group from the system settings.
1355      *
1356      * <p> The function call immediately returns after sending a persistent group removal request
1357      * to the framework. The application is notified of a success or failure to initiate
1358      * group removal through listener callbacks {@link ActionListener#onSuccess} or
1359      * {@link ActionListener#onFailure}.
1360      *
1361      * <p>The persistent p2p group list stored in the system can be obtained by
1362      * {@link #requestPersistentGroupInfo(Channel, PersistentGroupInfoListener)} and
1363      *  a network id can be obtained by {@link WifiP2pGroup#getNetworkId()}.
1364      *
1365      * @param c is the channel created at {@link #initialize}
1366      * @param netId he network id of the p2p group.
1367      * @param listener for callbacks on success or failure. Can be null.
1368      * @hide
1369      */
deletePersistentGroup(Channel c, int netId, ActionListener listener)1370     public void deletePersistentGroup(Channel c, int netId, ActionListener listener) {
1371         checkChannel(c);
1372         c.mAsyncChannel.sendMessage(DELETE_PERSISTENT_GROUP, netId, c.putListener(listener));
1373     }
1374 
1375     /**
1376      * Request a list of all the persistent p2p groups stored in system.
1377      *
1378      * @param c is the channel created at {@link #initialize}
1379      * @param listener for callback when persistent group info list is available. Can be null.
1380      * @hide
1381      */
requestPersistentGroupInfo(Channel c, PersistentGroupInfoListener listener)1382     public void requestPersistentGroupInfo(Channel c, PersistentGroupInfoListener listener) {
1383         checkChannel(c);
1384         c.mAsyncChannel.sendMessage(REQUEST_PERSISTENT_GROUP_INFO, 0, c.putListener(listener));
1385     }
1386 
1387     /**
1388      * Get a reference to WifiP2pService handler. This is used to establish
1389      * an AsyncChannel communication with WifiService
1390      *
1391      * @return Messenger pointing to the WifiP2pService handler
1392      * @hide
1393      */
getMessenger()1394     public Messenger getMessenger() {
1395         try {
1396             return mService.getMessenger();
1397         } catch (RemoteException e) {
1398             return null;
1399         }
1400     }
1401 
1402 }
1403