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.IntDef;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.annotation.RequiresPermission;
23 import android.annotation.SdkConstant;
24 import android.annotation.SdkConstant.SdkConstantType;
25 import android.annotation.SystemService;
26 import android.compat.annotation.UnsupportedAppUsage;
27 import android.content.Context;
28 import android.net.NetworkInfo;
29 import android.net.wifi.WpsInfo;
30 import android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceInfo;
31 import android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceResponse;
32 import android.net.wifi.p2p.nsd.WifiP2pServiceInfo;
33 import android.net.wifi.p2p.nsd.WifiP2pServiceRequest;
34 import android.net.wifi.p2p.nsd.WifiP2pServiceResponse;
35 import android.net.wifi.p2p.nsd.WifiP2pUpnpServiceInfo;
36 import android.net.wifi.p2p.nsd.WifiP2pUpnpServiceResponse;
37 import android.os.Binder;
38 import android.os.Build;
39 import android.os.Bundle;
40 import android.os.Handler;
41 import android.os.Looper;
42 import android.os.Message;
43 import android.os.Messenger;
44 import android.os.RemoteException;
45 import android.text.TextUtils;
46 import android.util.Log;
47 
48 import com.android.internal.util.AsyncChannel;
49 import com.android.internal.util.Protocol;
50 
51 import dalvik.system.CloseGuard;
52 
53 import java.lang.annotation.Retention;
54 import java.lang.annotation.RetentionPolicy;
55 import java.util.HashMap;
56 import java.util.List;
57 import java.util.Map;
58 
59 /**
60  * This class provides the API for managing Wi-Fi peer-to-peer connectivity. This lets an
61  * application discover available peers, setup connection to peers and query for the list of peers.
62  * When a p2p connection is formed over wifi, the device continues to maintain the uplink
63  * connection over mobile or any other available network for internet connectivity on the device.
64  *
65  * <p> The API is asynchronous and responses to requests from an application are on listener
66  * callbacks provided by the application. The application needs to do an initialization with
67  * {@link #initialize} before doing any p2p operation.
68  *
69  * <p> Most application calls need a {@link ActionListener} instance for receiving callbacks
70  * {@link ActionListener#onSuccess} or {@link ActionListener#onFailure}. Action callbacks
71  * indicate whether the initiation of the action was a success or a failure.
72  * Upon failure, the reason of failure can be one of {@link #ERROR}, {@link #P2P_UNSUPPORTED}
73  * or {@link #BUSY}.
74  *
75  * <p> An application can initiate discovery of peers with {@link #discoverPeers}. An initiated
76  * discovery request from an application stays active until the device starts connecting to a peer
77  * ,forms a p2p group or there is an explicit {@link #stopPeerDiscovery}.
78  * Applications can listen to {@link #WIFI_P2P_DISCOVERY_CHANGED_ACTION} to know if a peer-to-peer
79  * discovery is running or stopped. Additionally, {@link #WIFI_P2P_PEERS_CHANGED_ACTION} indicates
80  * if the peer list has changed.
81  *
82  * <p> When an application needs to fetch the current list of peers, it can request the list
83  * of peers with {@link #requestPeers}. When the peer list is available
84  * {@link PeerListListener#onPeersAvailable} is called with the device list.
85  *
86  * <p> An application can initiate a connection request to a peer through {@link #connect}. See
87  * {@link WifiP2pConfig} for details on setting up the configuration. For communication with legacy
88  * Wi-Fi devices that do not support p2p, an app can create a group using {@link #createGroup}
89  * which creates an access point whose details can be fetched with {@link #requestGroupInfo}.
90  *
91  * <p> After a successful group formation through {@link #createGroup} or through {@link #connect},
92  * use {@link #requestConnectionInfo} to fetch the connection details. The connection info
93  * {@link WifiP2pInfo} contains the address of the group owner
94  * {@link WifiP2pInfo#groupOwnerAddress} and a flag {@link WifiP2pInfo#isGroupOwner} to indicate
95  * if the current device is a p2p group owner. A p2p client can thus communicate with
96  * the p2p group owner through a socket connection. If the current device is the p2p group owner,
97  * {@link WifiP2pInfo#groupOwnerAddress} is anonymized unless the caller holds the
98  * {@code android.Manifest.permission#LOCAL_MAC_ADDRESS} permission.
99  *
100  * <p> With peer discovery using {@link  #discoverPeers}, an application discovers the neighboring
101  * peers, but has no good way to figure out which peer to establish a connection with. For example,
102  * if a game application is interested in finding all the neighboring peers that are also running
103  * the same game, it has no way to find out until after the connection is setup. Pre-association
104  * service discovery is meant to address this issue of filtering the peers based on the running
105  * services.
106  *
107  * <p>With pre-association service discovery, an application can advertise a service for a
108  * application on a peer device prior to a connection setup between the devices.
109  * Currently, DNS based service discovery (Bonjour) and Upnp are the higher layer protocols
110  * supported. Get Bonjour resources at dns-sd.org and Upnp resources at upnp.org
111  * As an example, a video application can discover a Upnp capable media renderer
112  * prior to setting up a Wi-fi p2p connection with the device.
113  *
114  * <p> An application can advertise a Upnp or a Bonjour service with a call to
115  * {@link #addLocalService}. After a local service is added,
116  * the framework automatically responds to a peer application discovering the service prior
117  * to establishing a p2p connection. A call to {@link #removeLocalService} removes a local
118  * service and {@link #clearLocalServices} can be used to clear all local services.
119  *
120  * <p> An application that is looking for peer devices that support certain services
121  * can do so with a call to  {@link #discoverServices}. Prior to initiating the discovery,
122  * application can add service discovery request with a call to {@link #addServiceRequest},
123  * remove a service discovery request with a call to {@link #removeServiceRequest} or clear
124  * all requests with a call to {@link #clearServiceRequests}. When no service requests remain,
125  * a previously running service discovery will stop.
126  *
127  * The application is notified of a result of service discovery request through listener callbacks
128  * set through {@link #setDnsSdResponseListeners} for Bonjour or
129  * {@link #setUpnpServiceResponseListener} for Upnp.
130  *
131  * <p class="note"><strong>Note:</strong>
132  * Registering an application handler with {@link #initialize} requires the permissions
133  * {@link android.Manifest.permission#ACCESS_WIFI_STATE} and
134  * {@link android.Manifest.permission#CHANGE_WIFI_STATE} to perform any further peer-to-peer
135  * operations.
136  *
137  * {@see WifiP2pConfig}
138  * {@see WifiP2pInfo}
139  * {@see WifiP2pGroup}
140  * {@see WifiP2pDevice}
141  * {@see WifiP2pDeviceList}
142  * {@see android.net.wifi.WpsInfo}
143  */
144 @SystemService(Context.WIFI_P2P_SERVICE)
145 public class WifiP2pManager {
146     private static final String TAG = "WifiP2pManager";
147     /**
148      * Broadcast intent action to indicate whether Wi-Fi p2p is enabled or disabled. An
149      * extra {@link #EXTRA_WIFI_STATE} provides the state information as int.
150      *
151      * @see #EXTRA_WIFI_STATE
152      */
153     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
154     public static final String WIFI_P2P_STATE_CHANGED_ACTION =
155         "android.net.wifi.p2p.STATE_CHANGED";
156 
157     /**
158      * The lookup key for an int that indicates whether Wi-Fi p2p is enabled or disabled.
159      * Retrieve it with {@link android.content.Intent#getIntExtra(String,int)}.
160      *
161      * @see #WIFI_P2P_STATE_DISABLED
162      * @see #WIFI_P2P_STATE_ENABLED
163      */
164     public static final String EXTRA_WIFI_STATE = "wifi_p2p_state";
165 
166     /** @hide */
167     @IntDef({
168             WIFI_P2P_STATE_DISABLED,
169             WIFI_P2P_STATE_ENABLED})
170     @Retention(RetentionPolicy.SOURCE)
171     public @interface WifiP2pState {
172     }
173 
174     /**
175      * Wi-Fi p2p is disabled.
176      *
177      * @see #WIFI_P2P_STATE_CHANGED_ACTION
178      */
179     public static final int WIFI_P2P_STATE_DISABLED = 1;
180 
181     /**
182      * Wi-Fi p2p is enabled.
183      *
184      * @see #WIFI_P2P_STATE_CHANGED_ACTION
185      */
186     public static final int WIFI_P2P_STATE_ENABLED = 2;
187 
188     /**
189      * Broadcast intent action indicating that the state of Wi-Fi p2p connectivity
190      * has changed. One extra {@link #EXTRA_WIFI_P2P_INFO} provides the p2p connection info in
191      * the form of a {@link WifiP2pInfo} object. Another extra {@link #EXTRA_NETWORK_INFO} provides
192      * the network info in the form of a {@link android.net.NetworkInfo}. A third extra provides
193      * the details of the group and may contain a {@code null}.
194      *
195      * All of these permissions are required to receive this broadcast:
196      * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} and
197      * {@link android.Manifest.permission#ACCESS_WIFI_STATE}
198      *
199      * @see #EXTRA_WIFI_P2P_INFO
200      * @see #EXTRA_NETWORK_INFO
201      * @see #EXTRA_WIFI_P2P_GROUP
202      */
203     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
204     public static final String WIFI_P2P_CONNECTION_CHANGED_ACTION =
205         "android.net.wifi.p2p.CONNECTION_STATE_CHANGE";
206 
207     /**
208      * The lookup key for a {@link android.net.wifi.p2p.WifiP2pInfo} object
209      * Retrieve with {@link android.content.Intent#getParcelableExtra(String)}.
210      */
211     public static final String EXTRA_WIFI_P2P_INFO = "wifiP2pInfo";
212 
213     /**
214      * The lookup key for a {@link android.net.NetworkInfo} object associated with the
215      * p2p network. Retrieve with
216      * {@link android.content.Intent#getParcelableExtra(String)}.
217      */
218     public static final String EXTRA_NETWORK_INFO = "networkInfo";
219 
220     /**
221      * The lookup key for a {@link android.net.wifi.p2p.WifiP2pGroup} object
222      * associated with the p2p network. Retrieve with
223      * {@link android.content.Intent#getParcelableExtra(String)}.
224      */
225     public static final String EXTRA_WIFI_P2P_GROUP = "p2pGroupInfo";
226 
227     /**
228      * Broadcast intent action indicating that the available peer list has changed. This
229      * can be sent as a result of peers being found, lost or updated.
230      *
231      * All of these permissions are required to receive this broadcast:
232      * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} and
233      * {@link android.Manifest.permission#ACCESS_WIFI_STATE}
234      *
235      * <p> An extra {@link #EXTRA_P2P_DEVICE_LIST} provides the full list of
236      * current peers. The full list of peers can also be obtained any time with
237      * {@link #requestPeers}.
238      *
239      * @see #EXTRA_P2P_DEVICE_LIST
240      */
241     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
242     public static final String WIFI_P2P_PEERS_CHANGED_ACTION =
243         "android.net.wifi.p2p.PEERS_CHANGED";
244 
245      /**
246       * The lookup key for a {@link android.net.wifi.p2p.WifiP2pDeviceList} object representing
247       * the new peer list when {@link #WIFI_P2P_PEERS_CHANGED_ACTION} broadcast is sent.
248       *
249       * <p>Retrieve with {@link android.content.Intent#getParcelableExtra(String)}.
250       */
251     public static final String EXTRA_P2P_DEVICE_LIST = "wifiP2pDeviceList";
252 
253     /**
254      * Broadcast intent action indicating that peer discovery has either started or stopped.
255      * One extra {@link #EXTRA_DISCOVERY_STATE} indicates whether discovery has started
256      * or stopped.
257      *
258      * <p>Note that discovery will be stopped during a connection setup. If the application tries
259      * to re-initiate discovery during this time, it can fail.
260      */
261     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
262     public static final String WIFI_P2P_DISCOVERY_CHANGED_ACTION =
263         "android.net.wifi.p2p.DISCOVERY_STATE_CHANGE";
264 
265     /**
266      * The lookup key for an int that indicates whether p2p discovery has started or stopped.
267      * Retrieve it with {@link android.content.Intent#getIntExtra(String,int)}.
268      *
269      * @see #WIFI_P2P_DISCOVERY_STARTED
270      * @see #WIFI_P2P_DISCOVERY_STOPPED
271      */
272     public static final String EXTRA_DISCOVERY_STATE = "discoveryState";
273 
274     /** @hide */
275     @IntDef({
276             WIFI_P2P_DISCOVERY_STOPPED,
277             WIFI_P2P_DISCOVERY_STARTED})
278     @Retention(RetentionPolicy.SOURCE)
279     public @interface WifiP2pDiscoveryState {
280     }
281 
282     /**
283      * p2p discovery has stopped
284      *
285      * @see #WIFI_P2P_DISCOVERY_CHANGED_ACTION
286      */
287     public static final int WIFI_P2P_DISCOVERY_STOPPED = 1;
288 
289     /**
290      * p2p discovery has started
291      *
292      * @see #WIFI_P2P_DISCOVERY_CHANGED_ACTION
293      */
294     public static final int WIFI_P2P_DISCOVERY_STARTED = 2;
295 
296     /**
297      * Broadcast intent action indicating that this device details have changed.
298      *
299      * <p> An extra {@link #EXTRA_WIFI_P2P_DEVICE} provides this device details.
300      * The valid device details can also be obtained with
301      * {@link #requestDeviceInfo(Channel, DeviceInfoListener)} when p2p is enabled.
302      * To get information notifications on P2P getting enabled refers
303      * {@link #WIFI_P2P_STATE_ENABLED}.
304      *
305      * <p> The {@link #EXTRA_WIFI_P2P_DEVICE} extra contains an anonymized version of the device's
306      * MAC address. Callers holding the {@code android.Manifest.permission#LOCAL_MAC_ADDRESS}
307      * permission can use {@link #requestDeviceInfo} to obtain the actual MAC address of this
308      * device.
309      *
310      * All of these permissions are required to receive this broadcast:
311      * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} and
312      * {@link android.Manifest.permission#ACCESS_WIFI_STATE}
313      *
314      * @see #EXTRA_WIFI_P2P_DEVICE
315      */
316     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
317     public static final String WIFI_P2P_THIS_DEVICE_CHANGED_ACTION =
318         "android.net.wifi.p2p.THIS_DEVICE_CHANGED";
319 
320     /**
321      * The lookup key for a {@link android.net.wifi.p2p.WifiP2pDevice} object
322      * Retrieve with {@link android.content.Intent#getParcelableExtra(String)}.
323      */
324     public static final String EXTRA_WIFI_P2P_DEVICE = "wifiP2pDevice";
325 
326     /**
327      * Broadcast intent action indicating that remembered persistent groups have changed.
328      * @hide
329      */
330     public static final String WIFI_P2P_PERSISTENT_GROUPS_CHANGED_ACTION =
331         "android.net.wifi.p2p.PERSISTENT_GROUPS_CHANGED";
332 
333     /**
334      * The lookup key for a handover message returned by the WifiP2pService.
335      * @hide
336      */
337     public static final String EXTRA_HANDOVER_MESSAGE =
338             "android.net.wifi.p2p.EXTRA_HANDOVER_MESSAGE";
339 
340     /**
341      * The lookup key for a calling package name from WifiP2pManager
342      * @hide
343      */
344     public static final String CALLING_PACKAGE =
345             "android.net.wifi.p2p.CALLING_PACKAGE";
346 
347     /**
348      * The lookup key for a calling package binder from WifiP2pManager
349      * @hide
350      */
351     public static final String CALLING_BINDER =
352             "android.net.wifi.p2p.CALLING_BINDER";
353 
354     IWifiP2pManager mService;
355 
356     private static final int BASE = Protocol.BASE_WIFI_P2P_MANAGER;
357 
358     /** @hide */
359     public static final int DISCOVER_PEERS                          = BASE + 1;
360     /** @hide */
361     public static final int DISCOVER_PEERS_FAILED                   = BASE + 2;
362     /** @hide */
363     public static final int DISCOVER_PEERS_SUCCEEDED                = BASE + 3;
364 
365     /** @hide */
366     public static final int STOP_DISCOVERY                          = BASE + 4;
367     /** @hide */
368     public static final int STOP_DISCOVERY_FAILED                   = BASE + 5;
369     /** @hide */
370     public static final int STOP_DISCOVERY_SUCCEEDED                = BASE + 6;
371 
372     /** @hide */
373     public static final int CONNECT                                 = BASE + 7;
374     /** @hide */
375     public static final int CONNECT_FAILED                          = BASE + 8;
376     /** @hide */
377     public static final int CONNECT_SUCCEEDED                       = BASE + 9;
378 
379     /** @hide */
380     public static final int CANCEL_CONNECT                          = BASE + 10;
381     /** @hide */
382     public static final int CANCEL_CONNECT_FAILED                   = BASE + 11;
383     /** @hide */
384     public static final int CANCEL_CONNECT_SUCCEEDED                = BASE + 12;
385 
386     /** @hide */
387     @UnsupportedAppUsage
388     public static final int CREATE_GROUP                            = BASE + 13;
389     /** @hide */
390     public static final int CREATE_GROUP_FAILED                     = BASE + 14;
391     /** @hide */
392     public static final int CREATE_GROUP_SUCCEEDED                  = BASE + 15;
393 
394     /** @hide */
395     public static final int REMOVE_GROUP                            = BASE + 16;
396     /** @hide */
397     public static final int REMOVE_GROUP_FAILED                     = BASE + 17;
398     /** @hide */
399     public static final int REMOVE_GROUP_SUCCEEDED                  = BASE + 18;
400 
401     /** @hide */
402     public static final int REQUEST_PEERS                           = BASE + 19;
403     /** @hide */
404     public static final int RESPONSE_PEERS                          = BASE + 20;
405 
406     /** @hide */
407     public static final int REQUEST_CONNECTION_INFO                 = BASE + 21;
408     /** @hide */
409     public static final int RESPONSE_CONNECTION_INFO                = BASE + 22;
410 
411     /** @hide */
412     public static final int REQUEST_GROUP_INFO                      = BASE + 23;
413     /** @hide */
414     public static final int RESPONSE_GROUP_INFO                     = BASE + 24;
415 
416     /** @hide */
417     public static final int ADD_LOCAL_SERVICE                       = BASE + 28;
418     /** @hide */
419     public static final int ADD_LOCAL_SERVICE_FAILED                = BASE + 29;
420     /** @hide */
421     public static final int ADD_LOCAL_SERVICE_SUCCEEDED             = BASE + 30;
422 
423     /** @hide */
424     public static final int REMOVE_LOCAL_SERVICE                    = BASE + 31;
425     /** @hide */
426     public static final int REMOVE_LOCAL_SERVICE_FAILED             = BASE + 32;
427     /** @hide */
428     public static final int REMOVE_LOCAL_SERVICE_SUCCEEDED          = BASE + 33;
429 
430     /** @hide */
431     public static final int CLEAR_LOCAL_SERVICES                    = BASE + 34;
432     /** @hide */
433     public static final int CLEAR_LOCAL_SERVICES_FAILED             = BASE + 35;
434     /** @hide */
435     public static final int CLEAR_LOCAL_SERVICES_SUCCEEDED          = BASE + 36;
436 
437     /** @hide */
438     public static final int ADD_SERVICE_REQUEST                     = BASE + 37;
439     /** @hide */
440     public static final int ADD_SERVICE_REQUEST_FAILED              = BASE + 38;
441     /** @hide */
442     public static final int ADD_SERVICE_REQUEST_SUCCEEDED           = BASE + 39;
443 
444     /** @hide */
445     public static final int REMOVE_SERVICE_REQUEST                  = BASE + 40;
446     /** @hide */
447     public static final int REMOVE_SERVICE_REQUEST_FAILED           = BASE + 41;
448     /** @hide */
449     public static final int REMOVE_SERVICE_REQUEST_SUCCEEDED        = BASE + 42;
450 
451     /** @hide */
452     public static final int CLEAR_SERVICE_REQUESTS                  = BASE + 43;
453     /** @hide */
454     public static final int CLEAR_SERVICE_REQUESTS_FAILED           = BASE + 44;
455     /** @hide */
456     public static final int CLEAR_SERVICE_REQUESTS_SUCCEEDED        = BASE + 45;
457 
458     /** @hide */
459     public static final int DISCOVER_SERVICES                       = BASE + 46;
460     /** @hide */
461     public static final int DISCOVER_SERVICES_FAILED                = BASE + 47;
462     /** @hide */
463     public static final int DISCOVER_SERVICES_SUCCEEDED             = BASE + 48;
464 
465     /** @hide */
466     public static final int PING                                    = BASE + 49;
467 
468     /** @hide */
469     public static final int RESPONSE_SERVICE                        = BASE + 50;
470 
471     /** @hide */
472     public static final int SET_DEVICE_NAME                         = BASE + 51;
473     /** @hide */
474     public static final int SET_DEVICE_NAME_FAILED                  = BASE + 52;
475     /** @hide */
476     public static final int SET_DEVICE_NAME_SUCCEEDED               = BASE + 53;
477 
478     /** @hide */
479     public static final int DELETE_PERSISTENT_GROUP                 = BASE + 54;
480     /** @hide */
481     public static final int DELETE_PERSISTENT_GROUP_FAILED          = BASE + 55;
482     /** @hide */
483     public static final int DELETE_PERSISTENT_GROUP_SUCCEEDED       = BASE + 56;
484 
485     /** @hide */
486     public static final int REQUEST_PERSISTENT_GROUP_INFO           = BASE + 57;
487     /** @hide */
488     public static final int RESPONSE_PERSISTENT_GROUP_INFO          = BASE + 58;
489 
490     /** @hide */
491     public static final int SET_WFD_INFO                            = BASE + 59;
492     /** @hide */
493     public static final int SET_WFD_INFO_FAILED                     = BASE + 60;
494     /** @hide */
495     public static final int SET_WFD_INFO_SUCCEEDED                  = BASE + 61;
496 
497     /** @hide */
498     public static final int START_WPS                               = BASE + 62;
499     /** @hide */
500     public static final int START_WPS_FAILED                        = BASE + 63;
501     /** @hide */
502     public static final int START_WPS_SUCCEEDED                     = BASE + 64;
503 
504     /** @hide */
505     public static final int START_LISTEN                            = BASE + 65;
506     /** @hide */
507     public static final int START_LISTEN_FAILED                     = BASE + 66;
508     /** @hide */
509     public static final int START_LISTEN_SUCCEEDED                  = BASE + 67;
510 
511     /** @hide */
512     public static final int STOP_LISTEN                             = BASE + 68;
513     /** @hide */
514     public static final int STOP_LISTEN_FAILED                      = BASE + 69;
515     /** @hide */
516     public static final int STOP_LISTEN_SUCCEEDED                   = BASE + 70;
517 
518     /** @hide */
519     public static final int SET_CHANNEL                             = BASE + 71;
520     /** @hide */
521     public static final int SET_CHANNEL_FAILED                      = BASE + 72;
522     /** @hide */
523     public static final int SET_CHANNEL_SUCCEEDED                   = BASE + 73;
524 
525     /** @hide */
526     public static final int GET_HANDOVER_REQUEST                    = BASE + 75;
527     /** @hide */
528     public static final int GET_HANDOVER_SELECT                     = BASE + 76;
529     /** @hide */
530     public static final int RESPONSE_GET_HANDOVER_MESSAGE           = BASE + 77;
531     /** @hide */
532     public static final int INITIATOR_REPORT_NFC_HANDOVER           = BASE + 78;
533     /** @hide */
534     public static final int RESPONDER_REPORT_NFC_HANDOVER           = BASE + 79;
535     /** @hide */
536     public static final int REPORT_NFC_HANDOVER_SUCCEEDED           = BASE + 80;
537     /** @hide */
538     public static final int REPORT_NFC_HANDOVER_FAILED              = BASE + 81;
539 
540     /** @hide */
541     public static final int FACTORY_RESET                           = BASE + 82;
542     /** @hide */
543     public static final int FACTORY_RESET_FAILED                    = BASE + 83;
544     /** @hide */
545     public static final int FACTORY_RESET_SUCCEEDED                 = BASE + 84;
546 
547     /** @hide */
548     public static final int REQUEST_ONGOING_PEER_CONFIG             = BASE + 85;
549     /** @hide */
550     public static final int RESPONSE_ONGOING_PEER_CONFIG            = BASE + 86;
551     /** @hide */
552     public static final int SET_ONGOING_PEER_CONFIG                 = BASE + 87;
553     /** @hide */
554     public static final int SET_ONGOING_PEER_CONFIG_FAILED          = BASE + 88;
555     /** @hide */
556     public static final int SET_ONGOING_PEER_CONFIG_SUCCEEDED       = BASE + 89;
557 
558     /** @hide */
559     public static final int REQUEST_P2P_STATE                       = BASE + 90;
560     /** @hide */
561     public static final int RESPONSE_P2P_STATE                      = BASE + 91;
562 
563     /** @hide */
564     public static final int REQUEST_DISCOVERY_STATE                 = BASE + 92;
565     /** @hide */
566     public static final int RESPONSE_DISCOVERY_STATE                = BASE + 93;
567 
568     /** @hide */
569     public static final int REQUEST_NETWORK_INFO                    = BASE + 94;
570     /** @hide */
571     public static final int RESPONSE_NETWORK_INFO                   = BASE + 95;
572 
573     /** @hide */
574     public static final int UPDATE_CHANNEL_INFO                     = BASE + 96;
575 
576     /** @hide */
577     public static final int REQUEST_DEVICE_INFO                     = BASE + 97;
578     /** @hide */
579     public static final int RESPONSE_DEVICE_INFO                    = BASE + 98;
580 
581     /**
582      * Create a new WifiP2pManager instance. Applications use
583      * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
584      * the standard {@link android.content.Context#WIFI_P2P_SERVICE Context.WIFI_P2P_SERVICE}.
585      * @param service the Binder interface
586      * @hide - hide this because it takes in a parameter of type IWifiP2pManager, which
587      * is a system private class.
588      */
589     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
WifiP2pManager(IWifiP2pManager service)590     public WifiP2pManager(IWifiP2pManager service) {
591         mService = service;
592     }
593 
594     /**
595      * Passed with {@link ActionListener#onFailure}.
596      * Indicates that the operation failed due to an internal error.
597      */
598     public static final int ERROR               = 0;
599 
600     /**
601      * Passed with {@link ActionListener#onFailure}.
602      * Indicates that the operation failed because p2p is unsupported on the device.
603      */
604     public static final int P2P_UNSUPPORTED     = 1;
605 
606     /**
607      * Passed with {@link ActionListener#onFailure}.
608      * Indicates that the operation failed because the framework is busy and
609      * unable to service the request
610      */
611     public static final int BUSY                = 2;
612 
613     /**
614      * Passed with {@link ActionListener#onFailure}.
615      * Indicates that the {@link #discoverServices} failed because no service
616      * requests are added. Use {@link #addServiceRequest} to add a service
617      * request.
618      */
619     public static final int NO_SERVICE_REQUESTS = 3;
620 
621     /** Interface for callback invocation when framework channel is lost */
622     public interface ChannelListener {
623         /**
624          * The channel to the framework has been disconnected.
625          * Application could try re-initializing using {@link #initialize}
626          */
onChannelDisconnected()627         public void onChannelDisconnected();
628     }
629 
630     /** Interface for callback invocation on an application action */
631     public interface ActionListener {
632         /** The operation succeeded */
onSuccess()633         public void onSuccess();
634         /**
635          * The operation failed
636          * @param reason The reason for failure could be one of {@link #P2P_UNSUPPORTED},
637          * {@link #ERROR} or {@link #BUSY}
638          */
onFailure(int reason)639         public void onFailure(int reason);
640     }
641 
642     /** Interface for callback invocation when peer list is available */
643     public interface PeerListListener {
644         /**
645          * The requested peer list is available
646          * @param peers List of available peers
647          */
onPeersAvailable(WifiP2pDeviceList peers)648         public void onPeersAvailable(WifiP2pDeviceList peers);
649     }
650 
651     /** Interface for callback invocation when connection info is available */
652     public interface ConnectionInfoListener {
653         /**
654          * The requested connection info is available
655          * @param info Wi-Fi p2p connection info
656          */
onConnectionInfoAvailable(WifiP2pInfo info)657         public void onConnectionInfoAvailable(WifiP2pInfo info);
658     }
659 
660     /** Interface for callback invocation when group info is available */
661     public interface GroupInfoListener {
662         /**
663          * The requested p2p group info is available
664          * @param group Wi-Fi p2p group info
665          */
onGroupInfoAvailable(WifiP2pGroup group)666         public void onGroupInfoAvailable(WifiP2pGroup group);
667     }
668 
669    /**
670     * Interface for callback invocation when service discovery response other than
671     * Upnp or Bonjour is received
672     */
673     public interface ServiceResponseListener {
674 
675         /**
676          * The requested service response is available.
677          *
678          * @param protocolType protocol type. currently only
679          * {@link WifiP2pServiceInfo#SERVICE_TYPE_VENDOR_SPECIFIC}.
680          * @param responseData service discovery response data based on the requested
681          *  service protocol type. The format depends on the service type.
682          * @param srcDevice source device.
683          */
onServiceAvailable(int protocolType, byte[] responseData, WifiP2pDevice srcDevice)684         public void onServiceAvailable(int protocolType,
685                 byte[] responseData, WifiP2pDevice srcDevice);
686     }
687 
688     /**
689      * Interface for callback invocation when Bonjour service discovery response
690      * is received
691      */
692     public interface DnsSdServiceResponseListener {
693 
694         /**
695          * The requested Bonjour service response is available.
696          *
697          * <p>This function is invoked when the device with the specified Bonjour
698          * registration type returned the instance name.
699          * @param instanceName instance name.<br>
700          *  e.g) "MyPrinter".
701          * @param registrationType <br>
702          * e.g) "_ipp._tcp.local."
703          * @param srcDevice source device.
704          */
onDnsSdServiceAvailable(String instanceName, String registrationType, WifiP2pDevice srcDevice)705         public void onDnsSdServiceAvailable(String instanceName,
706                 String registrationType, WifiP2pDevice srcDevice);
707 
708    }
709 
710     /**
711      * Interface for callback invocation when Bonjour TXT record is available
712      * for a service
713      */
714    public interface DnsSdTxtRecordListener {
715         /**
716          * The requested Bonjour service response is available.
717          *
718          * <p>This function is invoked when the device with the specified full
719          * service domain service returned TXT record.
720          *
721          * @param fullDomainName full domain name. <br>
722          * e.g) "MyPrinter._ipp._tcp.local.".
723          * @param txtRecordMap TXT record data as a map of key/value pairs
724          * @param srcDevice source device.
725          */
onDnsSdTxtRecordAvailable(String fullDomainName, Map<String, String> txtRecordMap, WifiP2pDevice srcDevice)726         public void onDnsSdTxtRecordAvailable(String fullDomainName,
727                 Map<String, String> txtRecordMap,
728                 WifiP2pDevice srcDevice);
729    }
730 
731     /**
732      * Interface for callback invocation when upnp service discovery response
733      * is received
734      * */
735     public interface UpnpServiceResponseListener {
736 
737         /**
738          * The requested upnp service response is available.
739          *
740          * <p>This function is invoked when the specified device or service is found.
741          *
742          * @param uniqueServiceNames The list of unique service names.<br>
743          * e.g) uuid:6859dede-8574-59ab-9332-123456789012::urn:schemas-upnp-org:device:
744          * MediaServer:1
745          * @param srcDevice source device.
746          */
onUpnpServiceAvailable(List<String> uniqueServiceNames, WifiP2pDevice srcDevice)747         public void onUpnpServiceAvailable(List<String> uniqueServiceNames,
748                 WifiP2pDevice srcDevice);
749     }
750 
751 
752     /** Interface for callback invocation when stored group info list is available {@hide}*/
753     public interface PersistentGroupInfoListener {
754         /**
755          * The requested stored p2p group info list is available
756          * @param groups Wi-Fi p2p group info list
757          */
onPersistentGroupInfoAvailable(WifiP2pGroupList groups)758         public void onPersistentGroupInfoAvailable(WifiP2pGroupList groups);
759     }
760 
761     /**
762      * Interface for callback invocation when Handover Request or Select Message is available
763      * @hide
764      */
765     public interface HandoverMessageListener {
onHandoverMessageAvailable(String handoverMessage)766         public void onHandoverMessageAvailable(String handoverMessage);
767     }
768 
769     /** Interface for callback invocation when p2p state is available
770      *  in response to {@link #requestP2pState}.
771      */
772     public interface P2pStateListener {
773         /**
774          * The requested p2p state is available.
775          * @param state Wi-Fi p2p state
776          *        @see #WIFI_P2P_STATE_DISABLED
777          *        @see #WIFI_P2P_STATE_ENABLED
778          */
onP2pStateAvailable(@ifiP2pState int state)779         void onP2pStateAvailable(@WifiP2pState int state);
780     }
781 
782     /** Interface for callback invocation when p2p state is available
783      *  in response to {@link #requestDiscoveryState}.
784      */
785     public interface DiscoveryStateListener {
786         /**
787          * The requested p2p discovery state is available.
788          * @param state Wi-Fi p2p discovery state
789          *        @see #WIFI_P2P_DISCOVERY_STARTED
790          *        @see #WIFI_P2P_DISCOVERY_STOPPED
791          */
onDiscoveryStateAvailable(@ifiP2pDiscoveryState int state)792         void onDiscoveryStateAvailable(@WifiP2pDiscoveryState int state);
793     }
794 
795     /** Interface for callback invocation when {@link android.net.NetworkInfo} is available
796      *  in response to {@link #requestNetworkInfo}.
797      */
798     public interface NetworkInfoListener {
799         /**
800          * The requested {@link android.net.NetworkInfo} is available
801          * @param networkInfo Wi-Fi p2p {@link android.net.NetworkInfo}
802          */
onNetworkInfoAvailable(@onNull NetworkInfo networkInfo)803         void onNetworkInfoAvailable(@NonNull NetworkInfo networkInfo);
804     }
805 
806     /**
807      * Interface for callback invocation when ongoing peer info is available
808      * @hide
809      */
810     public interface OngoingPeerInfoListener {
811         /**
812          * The requested ongoing WifiP2pConfig is available
813          * @param peerConfig WifiP2pConfig for current connecting session
814          */
onOngoingPeerAvailable(WifiP2pConfig peerConfig)815         void onOngoingPeerAvailable(WifiP2pConfig peerConfig);
816     }
817 
818     /** Interface for callback invocation when {@link android.net.wifi.p2p.WifiP2pDevice}
819      *  is available in response to {@link #requestDeviceInfo(Channel, DeviceInfoListener)}.
820      */
821     public interface DeviceInfoListener {
822         /**
823          * The requested {@link android.net.wifi.p2p.WifiP2pDevice} is available.
824          * @param wifiP2pDevice Wi-Fi p2p {@link android.net.wifi.p2p.WifiP2pDevice}
825          */
onDeviceInfoAvailable(@ullable WifiP2pDevice wifiP2pDevice)826         void onDeviceInfoAvailable(@Nullable WifiP2pDevice wifiP2pDevice);
827     }
828 
829     /**
830      * A channel that connects the application to the Wifi p2p framework.
831      * Most p2p operations require a Channel as an argument. An instance of Channel is obtained
832      * by doing a call on {@link #initialize}
833      */
834     public static class Channel implements AutoCloseable {
835         /** @hide */
Channel(Context context, Looper looper, ChannelListener l, Binder binder, WifiP2pManager p2pManager)836         public Channel(Context context, Looper looper, ChannelListener l, Binder binder,
837                 WifiP2pManager p2pManager) {
838             mAsyncChannel = new AsyncChannel();
839             mHandler = new P2pHandler(looper);
840             mChannelListener = l;
841             mContext = context;
842             mBinder = binder;
843             mP2pManager = p2pManager;
844 
845             mCloseGuard.open("close");
846         }
847         private final static int INVALID_LISTENER_KEY = 0;
848         private final WifiP2pManager mP2pManager;
849         private ChannelListener mChannelListener;
850         private ServiceResponseListener mServRspListener;
851         private DnsSdServiceResponseListener mDnsSdServRspListener;
852         private DnsSdTxtRecordListener mDnsSdTxtListener;
853         private UpnpServiceResponseListener mUpnpServRspListener;
854         private HashMap<Integer, Object> mListenerMap = new HashMap<Integer, Object>();
855         private final Object mListenerMapLock = new Object();
856         private int mListenerKey = 0;
857 
858         private final CloseGuard mCloseGuard = CloseGuard.get();
859 
860         /**
861          * Close the current P2P connection and indicate to the P2P service that connections
862          * created by the app can be removed.
863          */
close()864         public void close() {
865             if (mP2pManager == null) {
866                 Log.w(TAG, "Channel.close(): Null mP2pManager!?");
867             } else {
868                 try {
869                     mP2pManager.mService.close(mBinder);
870                 } catch (RemoteException e) {
871                     throw e.rethrowFromSystemServer();
872                 }
873             }
874 
875             mAsyncChannel.disconnect();
876             mCloseGuard.close();
877         }
878 
879         /** @hide */
880         @Override
finalize()881         protected void finalize() throws Throwable {
882             try {
883                 if (mCloseGuard != null) {
884                     mCloseGuard.warnIfOpen();
885                 }
886 
887                 close();
888             } finally {
889                 super.finalize();
890             }
891         }
892 
893         /* package */ final Binder mBinder;
894 
895         @UnsupportedAppUsage
896         private AsyncChannel mAsyncChannel;
897         private P2pHandler mHandler;
898         Context mContext;
899         class P2pHandler extends Handler {
P2pHandler(Looper looper)900             P2pHandler(Looper looper) {
901                 super(looper);
902             }
903 
904             @Override
handleMessage(Message message)905             public void handleMessage(Message message) {
906                 Object listener = getListener(message.arg2);
907                 switch (message.what) {
908                     case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
909                         if (mChannelListener != null) {
910                             mChannelListener.onChannelDisconnected();
911                             mChannelListener = null;
912                         }
913                         break;
914                     /* ActionListeners grouped together */
915                     case DISCOVER_PEERS_FAILED:
916                     case STOP_DISCOVERY_FAILED:
917                     case DISCOVER_SERVICES_FAILED:
918                     case CONNECT_FAILED:
919                     case CANCEL_CONNECT_FAILED:
920                     case CREATE_GROUP_FAILED:
921                     case REMOVE_GROUP_FAILED:
922                     case ADD_LOCAL_SERVICE_FAILED:
923                     case REMOVE_LOCAL_SERVICE_FAILED:
924                     case CLEAR_LOCAL_SERVICES_FAILED:
925                     case ADD_SERVICE_REQUEST_FAILED:
926                     case REMOVE_SERVICE_REQUEST_FAILED:
927                     case CLEAR_SERVICE_REQUESTS_FAILED:
928                     case SET_DEVICE_NAME_FAILED:
929                     case DELETE_PERSISTENT_GROUP_FAILED:
930                     case SET_WFD_INFO_FAILED:
931                     case START_WPS_FAILED:
932                     case START_LISTEN_FAILED:
933                     case STOP_LISTEN_FAILED:
934                     case SET_CHANNEL_FAILED:
935                     case REPORT_NFC_HANDOVER_FAILED:
936                     case FACTORY_RESET_FAILED:
937                     case SET_ONGOING_PEER_CONFIG_FAILED:
938                         if (listener != null) {
939                             ((ActionListener) listener).onFailure(message.arg1);
940                         }
941                         break;
942                     /* ActionListeners grouped together */
943                     case DISCOVER_PEERS_SUCCEEDED:
944                     case STOP_DISCOVERY_SUCCEEDED:
945                     case DISCOVER_SERVICES_SUCCEEDED:
946                     case CONNECT_SUCCEEDED:
947                     case CANCEL_CONNECT_SUCCEEDED:
948                     case CREATE_GROUP_SUCCEEDED:
949                     case REMOVE_GROUP_SUCCEEDED:
950                     case ADD_LOCAL_SERVICE_SUCCEEDED:
951                     case REMOVE_LOCAL_SERVICE_SUCCEEDED:
952                     case CLEAR_LOCAL_SERVICES_SUCCEEDED:
953                     case ADD_SERVICE_REQUEST_SUCCEEDED:
954                     case REMOVE_SERVICE_REQUEST_SUCCEEDED:
955                     case CLEAR_SERVICE_REQUESTS_SUCCEEDED:
956                     case SET_DEVICE_NAME_SUCCEEDED:
957                     case DELETE_PERSISTENT_GROUP_SUCCEEDED:
958                     case SET_WFD_INFO_SUCCEEDED:
959                     case START_WPS_SUCCEEDED:
960                     case START_LISTEN_SUCCEEDED:
961                     case STOP_LISTEN_SUCCEEDED:
962                     case SET_CHANNEL_SUCCEEDED:
963                     case REPORT_NFC_HANDOVER_SUCCEEDED:
964                     case FACTORY_RESET_SUCCEEDED:
965                     case SET_ONGOING_PEER_CONFIG_SUCCEEDED:
966                         if (listener != null) {
967                             ((ActionListener) listener).onSuccess();
968                         }
969                         break;
970                     case RESPONSE_PEERS:
971                         WifiP2pDeviceList peers = (WifiP2pDeviceList) message.obj;
972                         if (listener != null) {
973                             ((PeerListListener) listener).onPeersAvailable(peers);
974                         }
975                         break;
976                     case RESPONSE_CONNECTION_INFO:
977                         WifiP2pInfo wifiP2pInfo = (WifiP2pInfo) message.obj;
978                         if (listener != null) {
979                             ((ConnectionInfoListener) listener).onConnectionInfoAvailable(wifiP2pInfo);
980                         }
981                         break;
982                     case RESPONSE_GROUP_INFO:
983                         WifiP2pGroup group = (WifiP2pGroup) message.obj;
984                         if (listener != null) {
985                             ((GroupInfoListener) listener).onGroupInfoAvailable(group);
986                         }
987                         break;
988                     case RESPONSE_SERVICE:
989                         WifiP2pServiceResponse resp = (WifiP2pServiceResponse) message.obj;
990                         handleServiceResponse(resp);
991                         break;
992                     case RESPONSE_PERSISTENT_GROUP_INFO:
993                         WifiP2pGroupList groups = (WifiP2pGroupList) message.obj;
994                         if (listener != null) {
995                             ((PersistentGroupInfoListener) listener).
996                                 onPersistentGroupInfoAvailable(groups);
997                         }
998                         break;
999                     case RESPONSE_GET_HANDOVER_MESSAGE:
1000                         Bundle handoverBundle = (Bundle) message.obj;
1001                         if (listener != null) {
1002                             String handoverMessage = handoverBundle != null
1003                                     ? handoverBundle.getString(EXTRA_HANDOVER_MESSAGE)
1004                                     : null;
1005                             ((HandoverMessageListener) listener)
1006                                     .onHandoverMessageAvailable(handoverMessage);
1007                         }
1008                         break;
1009                     case RESPONSE_ONGOING_PEER_CONFIG:
1010                         WifiP2pConfig peerConfig = (WifiP2pConfig) message.obj;
1011                         if (listener != null) {
1012                             ((OngoingPeerInfoListener) listener)
1013                                     .onOngoingPeerAvailable(peerConfig);
1014                         }
1015                         break;
1016                     case RESPONSE_P2P_STATE:
1017                         if (listener != null) {
1018                             ((P2pStateListener) listener)
1019                                     .onP2pStateAvailable(message.arg1);
1020                         }
1021                         break;
1022                     case RESPONSE_DISCOVERY_STATE:
1023                         if (listener != null) {
1024                             ((DiscoveryStateListener) listener)
1025                                     .onDiscoveryStateAvailable(message.arg1);
1026                         }
1027                         break;
1028                     case RESPONSE_NETWORK_INFO:
1029                         if (listener != null) {
1030                             ((NetworkInfoListener) listener)
1031                                     .onNetworkInfoAvailable((NetworkInfo) message.obj);
1032                         }
1033                         break;
1034                     case RESPONSE_DEVICE_INFO:
1035                         if (listener != null) {
1036                             ((DeviceInfoListener) listener)
1037                                     .onDeviceInfoAvailable((WifiP2pDevice) message.obj);
1038                         }
1039                         break;
1040                     default:
1041                         Log.d(TAG, "Ignored " + message);
1042                         break;
1043                 }
1044             }
1045         }
1046 
handleServiceResponse(WifiP2pServiceResponse resp)1047         private void handleServiceResponse(WifiP2pServiceResponse resp) {
1048             if (resp instanceof WifiP2pDnsSdServiceResponse) {
1049                 handleDnsSdServiceResponse((WifiP2pDnsSdServiceResponse)resp);
1050             } else if (resp instanceof WifiP2pUpnpServiceResponse) {
1051                 if (mUpnpServRspListener != null) {
1052                     handleUpnpServiceResponse((WifiP2pUpnpServiceResponse)resp);
1053                 }
1054             } else {
1055                 if (mServRspListener != null) {
1056                     mServRspListener.onServiceAvailable(resp.getServiceType(),
1057                             resp.getRawData(), resp.getSrcDevice());
1058                 }
1059             }
1060         }
1061 
handleUpnpServiceResponse(WifiP2pUpnpServiceResponse resp)1062         private void handleUpnpServiceResponse(WifiP2pUpnpServiceResponse resp) {
1063             mUpnpServRspListener.onUpnpServiceAvailable(resp.getUniqueServiceNames(),
1064                     resp.getSrcDevice());
1065         }
1066 
handleDnsSdServiceResponse(WifiP2pDnsSdServiceResponse resp)1067         private void handleDnsSdServiceResponse(WifiP2pDnsSdServiceResponse resp) {
1068             if (resp.getDnsType() == WifiP2pDnsSdServiceInfo.DNS_TYPE_PTR) {
1069                 if (mDnsSdServRspListener != null) {
1070                     mDnsSdServRspListener.onDnsSdServiceAvailable(
1071                             resp.getInstanceName(),
1072                             resp.getDnsQueryName(),
1073                             resp.getSrcDevice());
1074                 }
1075             } else if (resp.getDnsType() == WifiP2pDnsSdServiceInfo.DNS_TYPE_TXT) {
1076                 if (mDnsSdTxtListener != null) {
1077                     mDnsSdTxtListener.onDnsSdTxtRecordAvailable(
1078                             resp.getDnsQueryName(),
1079                             resp.getTxtRecord(),
1080                             resp.getSrcDevice());
1081                 }
1082             } else {
1083                 Log.e(TAG, "Unhandled resp " + resp);
1084             }
1085         }
1086 
1087         @UnsupportedAppUsage
putListener(Object listener)1088         private int putListener(Object listener) {
1089             if (listener == null) return INVALID_LISTENER_KEY;
1090             int key;
1091             synchronized (mListenerMapLock) {
1092                 do {
1093                     key = mListenerKey++;
1094                 } while (key == INVALID_LISTENER_KEY);
1095                 mListenerMap.put(key, listener);
1096             }
1097             return key;
1098         }
1099 
getListener(int key)1100         private Object getListener(int key) {
1101             if (key == INVALID_LISTENER_KEY) return null;
1102             synchronized (mListenerMapLock) {
1103                 return mListenerMap.remove(key);
1104             }
1105         }
1106     }
1107 
checkChannel(Channel c)1108     private static void checkChannel(Channel c) {
1109         if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
1110     }
1111 
checkServiceInfo(WifiP2pServiceInfo info)1112     private static void checkServiceInfo(WifiP2pServiceInfo info) {
1113         if (info == null) throw new IllegalArgumentException("service info is null");
1114     }
1115 
checkServiceRequest(WifiP2pServiceRequest req)1116     private static void checkServiceRequest(WifiP2pServiceRequest req) {
1117         if (req == null) throw new IllegalArgumentException("service request is null");
1118     }
1119 
checkP2pConfig(WifiP2pConfig c)1120     private static void checkP2pConfig(WifiP2pConfig c) {
1121         if (c == null) throw new IllegalArgumentException("config cannot be null");
1122         if (TextUtils.isEmpty(c.deviceAddress)) {
1123             throw new IllegalArgumentException("deviceAddress cannot be empty");
1124         }
1125     }
1126 
1127     /**
1128      * Registers the application with the Wi-Fi framework. This function
1129      * must be the first to be called before any p2p operations are performed.
1130      *
1131      * @param srcContext is the context of the source
1132      * @param srcLooper is the Looper on which the callbacks are receivied
1133      * @param listener for callback at loss of framework communication. Can be null.
1134      * @return Channel instance that is necessary for performing any further p2p operations
1135      */
initialize(Context srcContext, Looper srcLooper, ChannelListener listener)1136     public Channel initialize(Context srcContext, Looper srcLooper, ChannelListener listener) {
1137         Binder binder = new Binder();
1138         Channel channel = initalizeChannel(srcContext, srcLooper, listener, getMessenger(binder),
1139                 binder);
1140         return channel;
1141     }
1142 
1143     /**
1144      * Registers the application with the Wi-Fi framework. Enables system-only functionality.
1145      * @hide
1146      */
initializeInternal(Context srcContext, Looper srcLooper, ChannelListener listener)1147     public Channel initializeInternal(Context srcContext, Looper srcLooper,
1148                                       ChannelListener listener) {
1149         return initalizeChannel(srcContext, srcLooper, listener, getP2pStateMachineMessenger(),
1150                 null);
1151     }
1152 
initalizeChannel(Context srcContext, Looper srcLooper, ChannelListener listener, Messenger messenger, Binder binder)1153     private Channel initalizeChannel(Context srcContext, Looper srcLooper, ChannelListener listener,
1154                                      Messenger messenger, Binder binder) {
1155         if (messenger == null) return null;
1156 
1157         Channel c = new Channel(srcContext, srcLooper, listener, binder, this);
1158         if (c.mAsyncChannel.connectSync(srcContext, c.mHandler, messenger)
1159                 == AsyncChannel.STATUS_SUCCESSFUL) {
1160             Bundle bundle = new Bundle();
1161             bundle.putString(CALLING_PACKAGE, c.mContext.getOpPackageName());
1162             bundle.putBinder(CALLING_BINDER, binder);
1163             c.mAsyncChannel.sendMessage(UPDATE_CHANNEL_INFO, 0,
1164                     c.putListener(null), bundle);
1165             return c;
1166         } else {
1167             c.close();
1168             return null;
1169         }
1170     }
1171 
1172     /**
1173      * Initiate peer discovery. A discovery process involves scanning for available Wi-Fi peers
1174      * for the purpose of establishing a connection.
1175      *
1176      * <p> The function call immediately returns after sending a discovery request
1177      * to the framework. The application is notified of a success or failure to initiate
1178      * discovery through listener callbacks {@link ActionListener#onSuccess} or
1179      * {@link ActionListener#onFailure}.
1180      *
1181      * <p> The discovery remains active until a connection is initiated or
1182      * a p2p group is formed. Register for {@link #WIFI_P2P_PEERS_CHANGED_ACTION} intent to
1183      * determine when the framework notifies of a change as peers are discovered.
1184      *
1185      * <p> Upon receiving a {@link #WIFI_P2P_PEERS_CHANGED_ACTION} intent, an application
1186      * can request for the list of peers using {@link #requestPeers}.
1187      *
1188      * @param c is the channel created at {@link #initialize}
1189      * @param listener for callbacks on success or failure. Can be null.
1190      */
1191     @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
discoverPeers(Channel c, ActionListener listener)1192     public void discoverPeers(Channel c, ActionListener listener) {
1193         checkChannel(c);
1194         c.mAsyncChannel.sendMessage(DISCOVER_PEERS, 0, c.putListener(listener));
1195     }
1196 
1197    /**
1198      * Stop an ongoing peer discovery
1199      *
1200      * <p> The function call immediately returns after sending a stop request
1201      * to the framework. The application is notified of a success or failure to initiate
1202      * stop through listener callbacks {@link ActionListener#onSuccess} or
1203      * {@link ActionListener#onFailure}.
1204      *
1205      * @param c is the channel created at {@link #initialize}
1206      * @param listener for callbacks on success or failure. Can be null.
1207      */
stopPeerDiscovery(Channel c, ActionListener listener)1208     public void stopPeerDiscovery(Channel c, ActionListener listener) {
1209         checkChannel(c);
1210         c.mAsyncChannel.sendMessage(STOP_DISCOVERY, 0, c.putListener(listener));
1211     }
1212 
1213     /**
1214      * Start a p2p connection to a device with the specified configuration.
1215      *
1216      * <p> The function call immediately returns after sending a connection request
1217      * to the framework. The application is notified of a success or failure to initiate
1218      * connect through listener callbacks {@link ActionListener#onSuccess} or
1219      * {@link ActionListener#onFailure}.
1220      *
1221      * <p> Register for {@link #WIFI_P2P_CONNECTION_CHANGED_ACTION} intent to
1222      * determine when the framework notifies of a change in connectivity.
1223      *
1224      * <p> If the current device is not part of a p2p group, a connect request initiates
1225      * a group negotiation with the peer.
1226      *
1227      * <p> If the current device is part of an existing p2p group or has created
1228      * a p2p group with {@link #createGroup}, an invitation to join the group is sent to
1229      * the peer device.
1230      *
1231      * @param c is the channel created at {@link #initialize}
1232      * @param config options as described in {@link WifiP2pConfig} class
1233      * @param listener for callbacks on success or failure. Can be null.
1234      */
1235     @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
connect(Channel c, WifiP2pConfig config, ActionListener listener)1236     public void connect(Channel c, WifiP2pConfig config, ActionListener listener) {
1237         checkChannel(c);
1238         checkP2pConfig(config);
1239         c.mAsyncChannel.sendMessage(CONNECT, 0, c.putListener(listener), config);
1240     }
1241 
1242     /**
1243      * Cancel any ongoing p2p group negotiation
1244      *
1245      * <p> The function call immediately returns after sending a connection cancellation request
1246      * to the framework. The application is notified of a success or failure to initiate
1247      * cancellation through listener callbacks {@link ActionListener#onSuccess} or
1248      * {@link ActionListener#onFailure}.
1249      *
1250      * @param c is the channel created at {@link #initialize}
1251      * @param listener for callbacks on success or failure. Can be null.
1252      */
cancelConnect(Channel c, ActionListener listener)1253     public void cancelConnect(Channel c, ActionListener listener) {
1254         checkChannel(c);
1255         c.mAsyncChannel.sendMessage(CANCEL_CONNECT, 0, c.putListener(listener));
1256     }
1257 
1258     /**
1259      * Create a p2p group with the current device as the group owner. This essentially creates
1260      * an access point that can accept connections from legacy clients as well as other p2p
1261      * devices.
1262      *
1263      * <p class="note"><strong>Note:</strong>
1264      * This function would normally not be used unless the current device needs
1265      * to form a p2p connection with a legacy client
1266      *
1267      * <p> The function call immediately returns after sending a group creation request
1268      * to the framework. The application is notified of a success or failure to initiate
1269      * group creation through listener callbacks {@link ActionListener#onSuccess} or
1270      * {@link ActionListener#onFailure}.
1271      *
1272      * <p> Application can request for the group details with {@link #requestGroupInfo}.
1273      *
1274      * @param c is the channel created at {@link #initialize}
1275      * @param listener for callbacks on success or failure. Can be null.
1276      */
1277     @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
createGroup(Channel c, ActionListener listener)1278     public void createGroup(Channel c, ActionListener listener) {
1279         checkChannel(c);
1280         c.mAsyncChannel.sendMessage(CREATE_GROUP, WifiP2pGroup.PERSISTENT_NET_ID,
1281                 c.putListener(listener));
1282     }
1283 
1284     /**
1285      * Create a p2p group with the current device as the group owner. This essentially creates
1286      * an access point that can accept connections from legacy clients as well as other p2p
1287      * devices.
1288      *
1289      * <p> An app should use {@link WifiP2pConfig.Builder} to build the configuration
1290      * for a group.
1291      *
1292      * <p class="note"><strong>Note:</strong>
1293      * This function would normally not be used unless the current device needs
1294      * to form a p2p group as a Group Owner and allow peers to join it as either
1295      * Group Clients or legacy Wi-Fi STAs.
1296      *
1297      * <p> The function call immediately returns after sending a group creation request
1298      * to the framework. The application is notified of a success or failure to initiate
1299      * group creation through listener callbacks {@link ActionListener#onSuccess} or
1300      * {@link ActionListener#onFailure}.
1301      *
1302      * <p> Application can request for the group details with {@link #requestGroupInfo}.
1303      *
1304      * @param c is the channel created at {@link #initialize}.
1305      * @param config the configuration of a p2p group.
1306      * @param listener for callbacks on success or failure. Can be null.
1307      */
1308     @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
createGroup(@onNull Channel c, @Nullable WifiP2pConfig config, @Nullable ActionListener listener)1309     public void createGroup(@NonNull Channel c,
1310             @Nullable WifiP2pConfig config,
1311             @Nullable ActionListener listener) {
1312         checkChannel(c);
1313         c.mAsyncChannel.sendMessage(CREATE_GROUP, 0,
1314                 c.putListener(listener), config);
1315     }
1316 
1317     /**
1318      * Remove the current p2p group.
1319      *
1320      * <p> The function call immediately returns after sending a group removal request
1321      * to the framework. The application is notified of a success or failure to initiate
1322      * group removal through listener callbacks {@link ActionListener#onSuccess} or
1323      * {@link ActionListener#onFailure}.
1324      *
1325      * @param c is the channel created at {@link #initialize}
1326      * @param listener for callbacks on success or failure. Can be null.
1327      */
removeGroup(Channel c, ActionListener listener)1328     public void removeGroup(Channel c, ActionListener listener) {
1329         checkChannel(c);
1330         c.mAsyncChannel.sendMessage(REMOVE_GROUP, 0, c.putListener(listener));
1331     }
1332 
1333     /**
1334      * Force p2p to enter or exit listen state
1335      *
1336      * @param c is the channel created at {@link #initialize(Context, Looper, ChannelListener)}
1337      * @param enable enables or disables listening
1338      * @param listener for callbacks on success or failure. Can be null.
1339      *
1340      * @hide
1341      */
1342     @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
listen(Channel c, boolean enable, ActionListener listener)1343     public void listen(Channel c, boolean enable, ActionListener listener) {
1344         checkChannel(c);
1345         c.mAsyncChannel.sendMessage(enable ? START_LISTEN : STOP_LISTEN,
1346                 0, c.putListener(listener));
1347     }
1348 
1349     /** @hide */
1350     @UnsupportedAppUsage
setWifiP2pChannels(Channel c, int lc, int oc, ActionListener listener)1351     public void setWifiP2pChannels(Channel c, int lc, int oc, ActionListener listener) {
1352         checkChannel(c);
1353         Bundle p2pChannels = new Bundle();
1354         p2pChannels.putInt("lc", lc);
1355         p2pChannels.putInt("oc", oc);
1356         c.mAsyncChannel.sendMessage(SET_CHANNEL, 0, c.putListener(listener), p2pChannels);
1357     }
1358 
1359     /**
1360      * Start a Wi-Fi Protected Setup (WPS) session.
1361      *
1362      * <p> The function call immediately returns after sending a request to start a
1363      * WPS session. Currently, this is only valid if the current device is running
1364      * as a group owner to allow any new clients to join the group. The application
1365      * is notified of a success or failure to initiate WPS through listener callbacks
1366      * {@link ActionListener#onSuccess} or {@link ActionListener#onFailure}.
1367      * @hide
1368      */
1369     @UnsupportedAppUsage
startWps(Channel c, WpsInfo wps, ActionListener listener)1370     public void startWps(Channel c, WpsInfo wps, ActionListener listener) {
1371         checkChannel(c);
1372         c.mAsyncChannel.sendMessage(START_WPS, 0, c.putListener(listener), wps);
1373     }
1374 
1375     /**
1376      * Register a local service for service discovery. If a local service is registered,
1377      * the framework automatically responds to a service discovery request from a peer.
1378      *
1379      * <p> The function call immediately returns after sending a request to add a local
1380      * service to the framework. The application is notified of a success or failure to
1381      * add service through listener callbacks {@link ActionListener#onSuccess} or
1382      * {@link ActionListener#onFailure}.
1383      *
1384      * <p>The service information is set through {@link WifiP2pServiceInfo}.<br>
1385      * or its subclass calls  {@link WifiP2pUpnpServiceInfo#newInstance} or
1386      *  {@link WifiP2pDnsSdServiceInfo#newInstance} for a Upnp or Bonjour service
1387      * respectively
1388      *
1389      * <p>The service information can be cleared with calls to
1390      *  {@link #removeLocalService} or {@link #clearLocalServices}.
1391      *
1392      * @param c is the channel created at {@link #initialize}
1393      * @param servInfo is a local service information.
1394      * @param listener for callbacks on success or failure. Can be null.
1395      */
1396     @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
addLocalService(Channel c, WifiP2pServiceInfo servInfo, ActionListener listener)1397     public void addLocalService(Channel c, WifiP2pServiceInfo servInfo, ActionListener listener) {
1398         checkChannel(c);
1399         checkServiceInfo(servInfo);
1400         c.mAsyncChannel.sendMessage(ADD_LOCAL_SERVICE, 0, c.putListener(listener), servInfo);
1401     }
1402 
1403     /**
1404      * Remove a registered local service added with {@link #addLocalService}
1405      *
1406      * <p> The function call immediately returns after sending a request to remove a
1407      * local service to the framework. The application is notified of a success or failure to
1408      * add service through listener callbacks {@link ActionListener#onSuccess} or
1409      * {@link ActionListener#onFailure}.
1410      *
1411      * @param c is the channel created at {@link #initialize}
1412      * @param servInfo is the local service information.
1413      * @param listener for callbacks on success or failure. Can be null.
1414      */
removeLocalService(Channel c, WifiP2pServiceInfo servInfo, ActionListener listener)1415     public void removeLocalService(Channel c, WifiP2pServiceInfo servInfo,
1416             ActionListener listener) {
1417         checkChannel(c);
1418         checkServiceInfo(servInfo);
1419         c.mAsyncChannel.sendMessage(REMOVE_LOCAL_SERVICE, 0, c.putListener(listener), servInfo);
1420     }
1421 
1422     /**
1423      * Clear all registered local services of service discovery.
1424      *
1425      * <p> The function call immediately returns after sending a request to clear all
1426      * local services to the framework. The application is notified of a success or failure to
1427      * add service through listener callbacks {@link ActionListener#onSuccess} or
1428      * {@link ActionListener#onFailure}.
1429      *
1430      * @param c is the channel created at {@link #initialize}
1431      * @param listener for callbacks on success or failure. Can be null.
1432      */
clearLocalServices(Channel c, ActionListener listener)1433     public void clearLocalServices(Channel c, ActionListener listener) {
1434         checkChannel(c);
1435         c.mAsyncChannel.sendMessage(CLEAR_LOCAL_SERVICES, 0, c.putListener(listener));
1436     }
1437 
1438     /**
1439      * Register a callback to be invoked on receiving service discovery response.
1440      * Used only for vendor specific protocol right now. For Bonjour or Upnp, use
1441      * {@link #setDnsSdResponseListeners} or {@link #setUpnpServiceResponseListener}
1442      * respectively.
1443      *
1444      * <p> see {@link #discoverServices} for the detail.
1445      *
1446      * @param c is the channel created at {@link #initialize}
1447      * @param listener for callbacks on receiving service discovery response.
1448      */
setServiceResponseListener(Channel c, ServiceResponseListener listener)1449     public void setServiceResponseListener(Channel c,
1450             ServiceResponseListener listener) {
1451         checkChannel(c);
1452         c.mServRspListener = listener;
1453     }
1454 
1455     /**
1456      * Register a callback to be invoked on receiving Bonjour service discovery
1457      * response.
1458      *
1459      * <p> see {@link #discoverServices} for the detail.
1460      *
1461      * @param c
1462      * @param servListener is for listening to a Bonjour service response
1463      * @param txtListener is for listening to a Bonjour TXT record response
1464      */
setDnsSdResponseListeners(Channel c, DnsSdServiceResponseListener servListener, DnsSdTxtRecordListener txtListener)1465     public void setDnsSdResponseListeners(Channel c,
1466             DnsSdServiceResponseListener servListener, DnsSdTxtRecordListener txtListener) {
1467         checkChannel(c);
1468         c.mDnsSdServRspListener = servListener;
1469         c.mDnsSdTxtListener = txtListener;
1470     }
1471 
1472     /**
1473      * Register a callback to be invoked on receiving upnp service discovery
1474      * response.
1475      *
1476      * <p> see {@link #discoverServices} for the detail.
1477      *
1478      * @param c is the channel created at {@link #initialize}
1479      * @param listener for callbacks on receiving service discovery response.
1480      */
setUpnpServiceResponseListener(Channel c, UpnpServiceResponseListener listener)1481     public void setUpnpServiceResponseListener(Channel c,
1482             UpnpServiceResponseListener listener) {
1483         checkChannel(c);
1484         c.mUpnpServRspListener = listener;
1485     }
1486 
1487     /**
1488      * Initiate service discovery. A discovery process involves scanning for
1489      * requested services for the purpose of establishing a connection to a peer
1490      * that supports an available service.
1491      *
1492      * <p> The function call immediately returns after sending a request to start service
1493      * discovery to the framework. The application is notified of a success or failure to initiate
1494      * discovery through listener callbacks {@link ActionListener#onSuccess} or
1495      * {@link ActionListener#onFailure}.
1496      *
1497      * <p> The services to be discovered are specified with calls to {@link #addServiceRequest}.
1498      *
1499      * <p>The application is notified of the response against the service discovery request
1500      * through listener callbacks registered by {@link #setServiceResponseListener} or
1501      * {@link #setDnsSdResponseListeners}, or {@link #setUpnpServiceResponseListener}.
1502      *
1503      * @param c is the channel created at {@link #initialize}
1504      * @param listener for callbacks on success or failure. Can be null.
1505      */
1506     @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
discoverServices(Channel c, ActionListener listener)1507     public void discoverServices(Channel c, ActionListener listener) {
1508         checkChannel(c);
1509         c.mAsyncChannel.sendMessage(DISCOVER_SERVICES, 0, c.putListener(listener));
1510     }
1511 
1512     /**
1513      * Add a service discovery request.
1514      *
1515      * <p> The function call immediately returns after sending a request to add service
1516      * discovery request to the framework. The application is notified of a success or failure to
1517      * add service through listener callbacks {@link ActionListener#onSuccess} or
1518      * {@link ActionListener#onFailure}.
1519      *
1520      * <p>After service discovery request is added, you can initiate service discovery by
1521      * {@link #discoverServices}.
1522      *
1523      * <p>The added service requests can be cleared with calls to
1524      * {@link #removeServiceRequest(Channel, WifiP2pServiceRequest, ActionListener)} or
1525      * {@link #clearServiceRequests(Channel, ActionListener)}.
1526      *
1527      * @param c is the channel created at {@link #initialize}
1528      * @param req is the service discovery request.
1529      * @param listener for callbacks on success or failure. Can be null.
1530      */
addServiceRequest(Channel c, WifiP2pServiceRequest req, ActionListener listener)1531     public void addServiceRequest(Channel c,
1532             WifiP2pServiceRequest req, ActionListener listener) {
1533         checkChannel(c);
1534         checkServiceRequest(req);
1535         c.mAsyncChannel.sendMessage(ADD_SERVICE_REQUEST, 0,
1536                 c.putListener(listener), req);
1537     }
1538 
1539     /**
1540      * Remove a specified service discovery request added with {@link #addServiceRequest}
1541      *
1542      * <p> The function call immediately returns after sending a request to remove service
1543      * discovery request to the framework. The application is notified of a success or failure to
1544      * add service through listener callbacks {@link ActionListener#onSuccess} or
1545      * {@link ActionListener#onFailure}.
1546      *
1547      * @param c is the channel created at {@link #initialize}
1548      * @param req is the service discovery request.
1549      * @param listener for callbacks on success or failure. Can be null.
1550      */
removeServiceRequest(Channel c, WifiP2pServiceRequest req, ActionListener listener)1551     public void removeServiceRequest(Channel c, WifiP2pServiceRequest req,
1552             ActionListener listener) {
1553         checkChannel(c);
1554         checkServiceRequest(req);
1555         c.mAsyncChannel.sendMessage(REMOVE_SERVICE_REQUEST, 0,
1556                 c.putListener(listener), req);
1557     }
1558 
1559     /**
1560      * Clear all registered service discovery requests.
1561      *
1562      * <p> The function call immediately returns after sending a request to clear all
1563      * service discovery requests to the framework. The application is notified of a success
1564      * or failure to add service through listener callbacks {@link ActionListener#onSuccess} or
1565      * {@link ActionListener#onFailure}.
1566      *
1567      * @param c is the channel created at {@link #initialize}
1568      * @param listener for callbacks on success or failure. Can be null.
1569      */
clearServiceRequests(Channel c, ActionListener listener)1570     public void clearServiceRequests(Channel c, ActionListener listener) {
1571         checkChannel(c);
1572         c.mAsyncChannel.sendMessage(CLEAR_SERVICE_REQUESTS,
1573                 0, c.putListener(listener));
1574     }
1575 
1576     /**
1577      * Request the current list of peers.
1578      *
1579      * @param c is the channel created at {@link #initialize}
1580      * @param listener for callback when peer list is available. Can be null.
1581      */
1582     @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
requestPeers(Channel c, PeerListListener listener)1583     public void requestPeers(Channel c, PeerListListener listener) {
1584         checkChannel(c);
1585         c.mAsyncChannel.sendMessage(REQUEST_PEERS, 0, c.putListener(listener));
1586     }
1587 
1588     /**
1589      * Request device connection info.
1590      *
1591      * @param c is the channel created at {@link #initialize}
1592      * @param listener for callback when connection info is available. Can be null.
1593      */
requestConnectionInfo(Channel c, ConnectionInfoListener listener)1594     public void requestConnectionInfo(Channel c, ConnectionInfoListener listener) {
1595         checkChannel(c);
1596         c.mAsyncChannel.sendMessage(REQUEST_CONNECTION_INFO, 0, c.putListener(listener));
1597     }
1598 
1599     /**
1600      * Request p2p group info.
1601      *
1602      * @param c is the channel created at {@link #initialize}
1603      * @param listener for callback when group info is available. Can be null.
1604      */
1605     @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
requestGroupInfo(Channel c, GroupInfoListener listener)1606     public void requestGroupInfo(Channel c, GroupInfoListener listener) {
1607         checkChannel(c);
1608         c.mAsyncChannel.sendMessage(REQUEST_GROUP_INFO, 0, c.putListener(listener));
1609     }
1610 
1611     /**
1612      * Set p2p device name.
1613      * @hide
1614      * @param c is the channel created at {@link #initialize}
1615      * @param listener for callback when group info is available. Can be null.
1616      */
1617     @UnsupportedAppUsage
setDeviceName(Channel c, String devName, ActionListener listener)1618     public void setDeviceName(Channel c, String devName, ActionListener listener) {
1619         checkChannel(c);
1620         WifiP2pDevice d = new WifiP2pDevice();
1621         d.deviceName = devName;
1622         c.mAsyncChannel.sendMessage(SET_DEVICE_NAME, 0, c.putListener(listener), d);
1623     }
1624 
1625     /** @hide */
1626     @UnsupportedAppUsage
setWFDInfo( Channel c, WifiP2pWfdInfo wfdInfo, ActionListener listener)1627     public void setWFDInfo(
1628             Channel c, WifiP2pWfdInfo wfdInfo,
1629             ActionListener listener) {
1630         checkChannel(c);
1631         try {
1632             mService.checkConfigureWifiDisplayPermission();
1633         } catch (RemoteException e) {
1634             e.rethrowFromSystemServer();
1635         }
1636         c.mAsyncChannel.sendMessage(SET_WFD_INFO, 0, c.putListener(listener), wfdInfo);
1637     }
1638 
1639 
1640     /**
1641      * Delete a stored persistent group from the system settings.
1642      *
1643      * <p> The function call immediately returns after sending a persistent group removal request
1644      * to the framework. The application is notified of a success or failure to initiate
1645      * group removal through listener callbacks {@link ActionListener#onSuccess} or
1646      * {@link ActionListener#onFailure}.
1647      *
1648      * <p>The persistent p2p group list stored in the system can be obtained by
1649      * {@link #requestPersistentGroupInfo(Channel, PersistentGroupInfoListener)} and
1650      *  a network id can be obtained by {@link WifiP2pGroup#getNetworkId()}.
1651      *
1652      * @param c is the channel created at {@link #initialize}
1653      * @param netId he network id of the p2p group.
1654      * @param listener for callbacks on success or failure. Can be null.
1655      * @hide
1656      */
1657     @UnsupportedAppUsage
deletePersistentGroup(Channel c, int netId, ActionListener listener)1658     public void deletePersistentGroup(Channel c, int netId, ActionListener listener) {
1659         checkChannel(c);
1660         c.mAsyncChannel.sendMessage(DELETE_PERSISTENT_GROUP, netId, c.putListener(listener));
1661     }
1662 
1663     /**
1664      * Request a list of all the persistent p2p groups stored in system.
1665      *
1666      * @param c is the channel created at {@link #initialize}
1667      * @param listener for callback when persistent group info list is available. Can be null.
1668      * @hide
1669      */
1670     @UnsupportedAppUsage
requestPersistentGroupInfo(Channel c, PersistentGroupInfoListener listener)1671     public void requestPersistentGroupInfo(Channel c, PersistentGroupInfoListener listener) {
1672         checkChannel(c);
1673         c.mAsyncChannel.sendMessage(REQUEST_PERSISTENT_GROUP_INFO, 0, c.putListener(listener));
1674     }
1675 
1676     /** @hide */
1677     public static final int MIRACAST_DISABLED = 0;
1678     /** @hide */
1679     public static final int MIRACAST_SOURCE   = 1;
1680     /** @hide */
1681     public static final int MIRACAST_SINK     = 2;
1682     /** Internal use only @hide */
1683     @UnsupportedAppUsage
setMiracastMode(int mode)1684     public void setMiracastMode(int mode) {
1685         try {
1686             mService.setMiracastMode(mode);
1687         } catch (RemoteException e) {
1688             throw e.rethrowFromSystemServer();
1689         }
1690     }
1691 
1692     /**
1693      * Get a reference to WifiP2pService handler. This is used to establish
1694      * an AsyncChannel communication with WifiService
1695      *
1696      * @param binder A binder for the service to associate with this client.
1697      *
1698      * @return Messenger pointing to the WifiP2pService handler
1699      * @hide
1700      */
getMessenger(Binder binder)1701     public Messenger getMessenger(Binder binder) {
1702         try {
1703             return mService.getMessenger(binder);
1704         } catch (RemoteException e) {
1705             throw e.rethrowFromSystemServer();
1706         }
1707     }
1708 
1709     /**
1710      * Get a reference to P2pStateMachine handler. This is used to establish
1711      * a priveleged AsyncChannel communication with WifiP2pService.
1712      *
1713      * @return Messenger pointing to the WifiP2pService handler
1714      * @hide
1715      */
getP2pStateMachineMessenger()1716     public Messenger getP2pStateMachineMessenger() {
1717         try {
1718             return mService.getP2pStateMachineMessenger();
1719         } catch (RemoteException e) {
1720             throw e.rethrowFromSystemServer();
1721         }
1722     }
1723 
1724     /**
1725      * Get a handover request message for use in WFA NFC Handover transfer.
1726      * @hide
1727      */
getNfcHandoverRequest(Channel c, HandoverMessageListener listener)1728     public void getNfcHandoverRequest(Channel c, HandoverMessageListener listener) {
1729         checkChannel(c);
1730         c.mAsyncChannel.sendMessage(GET_HANDOVER_REQUEST, 0, c.putListener(listener));
1731     }
1732 
1733 
1734     /**
1735      * Get a handover select message for use in WFA NFC Handover transfer.
1736      * @hide
1737      */
getNfcHandoverSelect(Channel c, HandoverMessageListener listener)1738     public void getNfcHandoverSelect(Channel c, HandoverMessageListener listener) {
1739         checkChannel(c);
1740         c.mAsyncChannel.sendMessage(GET_HANDOVER_SELECT, 0, c.putListener(listener));
1741     }
1742 
1743     /**
1744      * @hide
1745      */
initiatorReportNfcHandover(Channel c, String handoverSelect, ActionListener listener)1746     public void initiatorReportNfcHandover(Channel c, String handoverSelect,
1747                                               ActionListener listener) {
1748         checkChannel(c);
1749         Bundle bundle = new Bundle();
1750         bundle.putString(EXTRA_HANDOVER_MESSAGE, handoverSelect);
1751         c.mAsyncChannel.sendMessage(INITIATOR_REPORT_NFC_HANDOVER, 0,
1752                 c.putListener(listener), bundle);
1753     }
1754 
1755 
1756     /**
1757      * @hide
1758      */
responderReportNfcHandover(Channel c, String handoverRequest, ActionListener listener)1759     public void responderReportNfcHandover(Channel c, String handoverRequest,
1760                                               ActionListener listener) {
1761         checkChannel(c);
1762         Bundle bundle = new Bundle();
1763         bundle.putString(EXTRA_HANDOVER_MESSAGE, handoverRequest);
1764         c.mAsyncChannel.sendMessage(RESPONDER_REPORT_NFC_HANDOVER, 0,
1765                 c.putListener(listener), bundle);
1766     }
1767 
1768     /**
1769      * Removes all saved p2p groups.
1770      *
1771      * @param c is the channel created at {@link #initialize}.
1772      * @param listener for callback on success or failure. Can be null.
1773      * @hide
1774      */
1775     @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
factoryReset(@onNull Channel c, @Nullable ActionListener listener)1776     public void factoryReset(@NonNull Channel c, @Nullable ActionListener listener) {
1777         checkChannel(c);
1778         c.mAsyncChannel.sendMessage(FACTORY_RESET, 0, c.putListener(listener));
1779     }
1780 
1781     /**
1782      * Request saved WifiP2pConfig which used for an ongoing peer connection
1783      *
1784      * @param c is the channel created at {@link #initialize}
1785      * @param listener for callback when ongoing peer config updated. Can't be null.
1786      *
1787      * @hide
1788      */
1789     @RequiresPermission(android.Manifest.permission.NETWORK_STACK)
requestOngoingPeerConfig(@onNull Channel c, @NonNull OngoingPeerInfoListener listener)1790     public void requestOngoingPeerConfig(@NonNull Channel c,
1791             @NonNull OngoingPeerInfoListener listener) {
1792         checkChannel(c);
1793         c.mAsyncChannel.sendMessage(REQUEST_ONGOING_PEER_CONFIG,
1794                 Binder.getCallingUid(), c.putListener(listener));
1795     }
1796 
1797      /**
1798      * Set saved WifiP2pConfig which used for an ongoing peer connection
1799      *
1800      * @param c is the channel created at {@link #initialize}
1801      * @param config used for change an ongoing peer connection
1802      * @param listener for callback when ongoing peer config updated. Can be null.
1803      *
1804      * @hide
1805      */
1806     @RequiresPermission(android.Manifest.permission.NETWORK_STACK)
setOngoingPeerConfig(@onNull Channel c, @NonNull WifiP2pConfig config, @Nullable ActionListener listener)1807     public void setOngoingPeerConfig(@NonNull Channel c, @NonNull WifiP2pConfig config,
1808             @Nullable ActionListener listener) {
1809         checkChannel(c);
1810         checkP2pConfig(config);
1811         c.mAsyncChannel.sendMessage(SET_ONGOING_PEER_CONFIG, 0,
1812                 c.putListener(listener), config);
1813     }
1814 
1815     /**
1816      * Request p2p enabled state.
1817      *
1818      * <p> This state indicates whether Wi-Fi p2p is enabled or disabled.
1819      * The valid value is one of {@link #WIFI_P2P_STATE_DISABLED} or
1820      * {@link #WIFI_P2P_STATE_ENABLED}. The state is returned using the
1821      * {@link P2pStateListener} listener.
1822      *
1823      * <p> This state is also included in the {@link #WIFI_P2P_STATE_CHANGED_ACTION}
1824      * broadcast event with extra {@link #EXTRA_WIFI_STATE}.
1825      *
1826      * @param c is the channel created at {@link #initialize}.
1827      * @param listener for callback when p2p state is available..
1828      */
requestP2pState(@onNull Channel c, @NonNull P2pStateListener listener)1829     public void requestP2pState(@NonNull Channel c,
1830             @NonNull P2pStateListener listener) {
1831         checkChannel(c);
1832         if (listener == null) throw new IllegalArgumentException("This listener cannot be null.");
1833         c.mAsyncChannel.sendMessage(REQUEST_P2P_STATE, 0, c.putListener(listener));
1834     }
1835 
1836     /**
1837      * Request p2p discovery state.
1838      *
1839      * <p> This state indicates whether p2p discovery has started or stopped.
1840      * The valid value is one of {@link #WIFI_P2P_DISCOVERY_STARTED} or
1841      * {@link #WIFI_P2P_DISCOVERY_STOPPED}. The state is returned using the
1842      * {@link DiscoveryStateListener} listener.
1843      *
1844      * <p> This state is also included in the {@link #WIFI_P2P_DISCOVERY_CHANGED_ACTION}
1845      * broadcast event with extra {@link #EXTRA_DISCOVERY_STATE}.
1846      *
1847      * @param c is the channel created at {@link #initialize}.
1848      * @param listener for callback when discovery state is available..
1849      */
requestDiscoveryState(@onNull Channel c, @NonNull DiscoveryStateListener listener)1850     public void requestDiscoveryState(@NonNull Channel c,
1851             @NonNull DiscoveryStateListener listener) {
1852         checkChannel(c);
1853         if (listener == null) throw new IllegalArgumentException("This listener cannot be null.");
1854         c.mAsyncChannel.sendMessage(REQUEST_DISCOVERY_STATE, 0, c.putListener(listener));
1855     }
1856 
1857     /**
1858      * Request network info.
1859      *
1860      * <p> This method provides the network info in the form of a {@link android.net.NetworkInfo}.
1861      * {@link android.net.NetworkInfo#isAvailable()} indicates the p2p availability and
1862      * {@link android.net.NetworkInfo#getDetailedState()} reports the current fine-grained state
1863      * of the network. This {@link android.net.NetworkInfo} is returned using the
1864      * {@link NetworkInfoListener} listener.
1865      *
1866      * <p> This information is also included in the {@link #WIFI_P2P_CONNECTION_CHANGED_ACTION}
1867      * broadcast event with extra {@link #EXTRA_NETWORK_INFO}.
1868      *
1869      * @param c is the channel created at {@link #initialize}.
1870      * @param listener for callback when network info is available..
1871      */
requestNetworkInfo(@onNull Channel c, @NonNull NetworkInfoListener listener)1872     public void requestNetworkInfo(@NonNull Channel c,
1873             @NonNull NetworkInfoListener listener) {
1874         checkChannel(c);
1875         if (listener == null) throw new IllegalArgumentException("This listener cannot be null.");
1876         c.mAsyncChannel.sendMessage(REQUEST_NETWORK_INFO, 0, c.putListener(listener));
1877     }
1878 
1879      /**
1880      * Request Device Info
1881      *
1882      * <p> This method provides the device info
1883      * in the form of a {@link android.net.wifi.p2p.WifiP2pDevice}.
1884      * Valid {@link android.net.wifi.p2p.WifiP2pDevice} is returned when p2p is enabled.
1885      * To get information notifications on P2P getting enabled refers
1886      * {@link #WIFI_P2P_STATE_ENABLED}.
1887      *
1888      * <p> This {@link android.net.wifi.p2p.WifiP2pDevice} is returned using the
1889      * {@link DeviceInfoListener} listener.
1890      *
1891      * <p> {@link android.net.wifi.p2p.WifiP2pDevice#deviceAddress} is only available if the caller
1892      * holds the {@code android.Manifest.permission#LOCAL_MAC_ADDRESS} permission, and holds the
1893      * anonymized MAC address (02:00:00:00:00:00) otherwise.
1894      *
1895      * <p> This information is also included in the {@link #WIFI_P2P_THIS_DEVICE_CHANGED_ACTION}
1896      * broadcast event with extra {@link #EXTRA_WIFI_P2P_DEVICE}.
1897      *
1898      * @param c is the channel created at {@link #initialize(Context, Looper, ChannelListener)}.
1899      * @param listener for callback when network info is available.
1900      */
1901     @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
requestDeviceInfo(@onNull Channel c, @NonNull DeviceInfoListener listener)1902     public void requestDeviceInfo(@NonNull Channel c, @NonNull DeviceInfoListener listener) {
1903         checkChannel(c);
1904         if (listener == null) throw new IllegalArgumentException("This listener cannot be null.");
1905         c.mAsyncChannel.sendMessage(REQUEST_DEVICE_INFO, 0, c.putListener(listener));
1906     }
1907 }
1908