OSDN Git Service

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