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