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