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