• 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.MacAddress;
30 import android.net.NetworkInfo;
31 import android.net.wifi.ScanResult;
32 import android.net.wifi.WifiManager;
33 import android.net.wifi.WpsInfo;
34 import android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceInfo;
35 import android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceResponse;
36 import android.net.wifi.p2p.nsd.WifiP2pServiceInfo;
37 import android.net.wifi.p2p.nsd.WifiP2pServiceRequest;
38 import android.net.wifi.p2p.nsd.WifiP2pServiceResponse;
39 import android.net.wifi.p2p.nsd.WifiP2pUpnpServiceInfo;
40 import android.net.wifi.p2p.nsd.WifiP2pUpnpServiceResponse;
41 import android.os.Binder;
42 import android.os.Build;
43 import android.os.Bundle;
44 import android.os.Handler;
45 import android.os.Looper;
46 import android.os.Message;
47 import android.os.Messenger;
48 import android.os.RemoteException;
49 import android.text.TextUtils;
50 import android.util.CloseGuard;
51 import android.util.Log;
52 import android.view.Display;
53 
54 import androidx.annotation.RequiresApi;
55 
56 import com.android.internal.util.AsyncChannel;
57 import com.android.internal.util.Protocol;
58 import com.android.modules.utils.build.SdkLevel;
59 
60 import java.lang.annotation.Retention;
61 import java.lang.annotation.RetentionPolicy;
62 import java.lang.ref.Reference;
63 import java.util.ArrayList;
64 import java.util.HashMap;
65 import java.util.List;
66 import java.util.Map;
67 
68 /**
69  * This class provides the API for managing Wi-Fi peer-to-peer connectivity. This lets an
70  * application discover available peers, setup connection to peers and query for the list of peers.
71  * When a p2p connection is formed over wifi, the device continues to maintain the uplink
72  * connection over mobile or any other available network for internet connectivity on the device.
73  *
74  * <p> The API is asynchronous and responses to requests from an application are on listener
75  * callbacks provided by the application. The application needs to do an initialization with
76  * {@link #initialize} before doing any p2p operation.
77  *
78  * <p> Most application calls need a {@link ActionListener} instance for receiving callbacks
79  * {@link ActionListener#onSuccess} or {@link ActionListener#onFailure}. Action callbacks
80  * indicate whether the initiation of the action was a success or a failure.
81  * Upon failure, the reason of failure can be one of {@link #ERROR}, {@link #P2P_UNSUPPORTED}
82  * or {@link #BUSY}.
83  *
84  * <p> An application can initiate discovery of peers with {@link #discoverPeers}. An initiated
85  * discovery request from an application stays active until the device starts connecting to a peer
86  * ,forms a p2p group or there is an explicit {@link #stopPeerDiscovery}.
87  * Applications can listen to {@link #WIFI_P2P_DISCOVERY_CHANGED_ACTION} to know if a peer-to-peer
88  * discovery is running or stopped. Additionally, {@link #WIFI_P2P_PEERS_CHANGED_ACTION} indicates
89  * if the peer list has changed.
90  *
91  * <p> When an application needs to fetch the current list of peers, it can request the list
92  * of peers with {@link #requestPeers}. When the peer list is available
93  * {@link PeerListListener#onPeersAvailable} is called with the device list.
94  *
95  * <p> An application can initiate a connection request to a peer through {@link #connect}. See
96  * {@link WifiP2pConfig} for details on setting up the configuration. For communication with legacy
97  * Wi-Fi devices that do not support p2p, an app can create a group using {@link #createGroup}
98  * which creates an access point whose details can be fetched with {@link #requestGroupInfo}.
99  *
100  * <p> After a successful group formation through {@link #createGroup} or through {@link #connect},
101  * use {@link #requestConnectionInfo} to fetch the connection details. The connection info
102  * {@link WifiP2pInfo} contains the address of the group owner
103  * {@link WifiP2pInfo#groupOwnerAddress} and a flag {@link WifiP2pInfo#isGroupOwner} to indicate
104  * if the current device is a p2p group owner. A p2p client can thus communicate with
105  * the p2p group owner through a socket connection. If the current device is the p2p group owner,
106  * {@link WifiP2pInfo#groupOwnerAddress} is anonymized unless the caller holds the
107  * {@code android.Manifest.permission#LOCAL_MAC_ADDRESS} permission.
108  *
109  * <p> With peer discovery using {@link  #discoverPeers}, an application discovers the neighboring
110  * peers, but has no good way to figure out which peer to establish a connection with. For example,
111  * if a game application is interested in finding all the neighboring peers that are also running
112  * the same game, it has no way to find out until after the connection is setup. Pre-association
113  * service discovery is meant to address this issue of filtering the peers based on the running
114  * services.
115  *
116  * <p>With pre-association service discovery, an application can advertise a service for a
117  * application on a peer device prior to a connection setup between the devices.
118  * Currently, DNS based service discovery (Bonjour) and Upnp are the higher layer protocols
119  * supported. Get Bonjour resources at dns-sd.org and Upnp resources at upnp.org
120  * As an example, a video application can discover a Upnp capable media renderer
121  * prior to setting up a Wi-fi p2p connection with the device.
122  *
123  * <p> An application can advertise a Upnp or a Bonjour service with a call to
124  * {@link #addLocalService}. After a local service is added,
125  * the framework automatically responds to a peer application discovering the service prior
126  * to establishing a p2p connection. A call to {@link #removeLocalService} removes a local
127  * service and {@link #clearLocalServices} can be used to clear all local services.
128  *
129  * <p> An application that is looking for peer devices that support certain services
130  * can do so with a call to  {@link #discoverServices}. Prior to initiating the discovery,
131  * application can add service discovery request with a call to {@link #addServiceRequest},
132  * remove a service discovery request with a call to {@link #removeServiceRequest} or clear
133  * all requests with a call to {@link #clearServiceRequests}. When no service requests remain,
134  * a previously running service discovery will stop.
135  *
136  * The application is notified of a result of service discovery request through listener callbacks
137  * set through {@link #setDnsSdResponseListeners} for Bonjour or
138  * {@link #setUpnpServiceResponseListener} for Upnp.
139  *
140  * <p class="note"><strong>Note:</strong>
141  * Registering an application handler with {@link #initialize} requires the permissions
142  * {@link android.Manifest.permission#ACCESS_WIFI_STATE} and
143  * {@link android.Manifest.permission#CHANGE_WIFI_STATE} to perform any further peer-to-peer
144  * operations.
145  *
146  * {@see WifiP2pConfig}
147  * {@see WifiP2pInfo}
148  * {@see WifiP2pGroup}
149  * {@see WifiP2pDevice}
150  * {@see WifiP2pDeviceList}
151  * {@see android.net.wifi.WpsInfo}
152  */
153 @SystemService(Context.WIFI_P2P_SERVICE)
154 public class WifiP2pManager {
155     private static final String TAG = "WifiP2pManager";
156 
157     /** @hide */
158     public static final long FEATURE_SET_VENDOR_ELEMENTS        = 1L << 0;
159     /** @hide */
160     public static final long FEATURE_FLEXIBLE_DISCOVERY         = 1L << 1;
161     /** @hide */
162     public static final long FEATURE_GROUP_CLIENT_REMOVAL       = 1L << 2;
163 
164     /**
165      * Extra for transporting a WifiP2pConfig
166      * @hide
167      */
168     public static final String EXTRA_PARAM_KEY_CONFIG =
169             "android.net.wifi.p2p.EXTRA_PARAM_KEY_CONFIG";
170     /**
171      * Extra for transporting a WifiP2pServiceInfo
172      * @hide
173      */
174     public static final String EXTRA_PARAM_KEY_SERVICE_INFO =
175             "android.net.wifi.p2p.EXTRA_PARAM_KEY_SERVICE_INFO";
176     /**
177      * Extra for transporting a peer discovery frequency.
178      * @hide
179      */
180     public static final String EXTRA_PARAM_KEY_PEER_DISCOVERY_FREQ =
181             "android.net.wifi.p2p.EXTRA_PARAM_KEY_PEER_DISCOVERY_FREQ";
182     /**
183      * Extra for transporting a peer MAC address.
184      * @hide
185      */
186     public static final String EXTRA_PARAM_KEY_PEER_ADDRESS =
187             "android.net.wifi.p2p.EXTRA_PARAM_KEY_PEER_ADDRESS";
188     /**
189      * Extra used to indicate that a message is sent from Wifi internally
190      * @hide
191      */
192     public static final String EXTRA_PARAM_KEY_INTERNAL_MESSAGE =
193             "android.net.wifi.p2p.EXTRA_PARAM_KEY_INTERNAL_MESSAGE";
194 
195     /**
196      * Used to communicate the Display ID for multi display devices.
197      * @hide
198      **/
199     public static final String EXTRA_PARAM_KEY_DISPLAY_ID =
200             "android.net.wifi.p2p.EXTRA_PARAM_KEY_DISPLAY_ID";
201 
202     /**
203      * Extra for transporting a WifiP2pDevice.
204      * @hide
205      */
206     public static final String EXTRA_PARAM_KEY_DEVICE =
207             "android.net.wifi.p2p.EXTRA_PARAM_KEY_DEVICE";
208     /**
209      * Extra for transporting a WPS PIN.
210      * @hide
211      */
212     public static final String EXTRA_PARAM_KEY_WPS_PIN =
213             "android.net.wifi.p2p.EXTRA_PARAM_KEY_WPS_PIN";
214 
215     /**
216      * Extra for transporting vendor-specific information element list
217      * @hide
218      */
219     public static final String EXTRA_PARAM_KEY_INFORMATION_ELEMENT_LIST =
220             "android.net.wifi.p2p.EXTRA_PARAM_KEY_INFORMATION_ELEMENT_LIST";
221 
222     /**
223      * Key for transporting a bundle of extra information.
224      * @hide
225      */
226     public static final String EXTRA_PARAM_KEY_BUNDLE =
227             "android.net.wifi.p2p.EXTRA_PARAM_KEY_BUNDLE";
228 
229     /**
230      * Broadcast intent action to indicate whether Wi-Fi p2p is enabled or disabled. An
231      * extra {@link #EXTRA_WIFI_STATE} provides the state information as int.
232      *
233      * @see #EXTRA_WIFI_STATE
234      */
235     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
236     public static final String WIFI_P2P_STATE_CHANGED_ACTION =
237         "android.net.wifi.p2p.STATE_CHANGED";
238 
239     /**
240      * The lookup key for an int that indicates whether Wi-Fi p2p is enabled or disabled.
241      * Retrieve it with {@link android.content.Intent#getIntExtra(String,int)}.
242      *
243      * @see #WIFI_P2P_STATE_DISABLED
244      * @see #WIFI_P2P_STATE_ENABLED
245      */
246     public static final String EXTRA_WIFI_STATE = "wifi_p2p_state";
247 
248     /** @hide */
249     @IntDef({
250             WIFI_P2P_STATE_DISABLED,
251             WIFI_P2P_STATE_ENABLED})
252     @Retention(RetentionPolicy.SOURCE)
253     public @interface WifiP2pState {
254     }
255 
256     /**
257      * Wi-Fi p2p is disabled.
258      *
259      * @see #WIFI_P2P_STATE_CHANGED_ACTION
260      */
261     public static final int WIFI_P2P_STATE_DISABLED = 1;
262 
263     /**
264      * Wi-Fi p2p is enabled.
265      *
266      * @see #WIFI_P2P_STATE_CHANGED_ACTION
267      */
268     public static final int WIFI_P2P_STATE_ENABLED = 2;
269 
270     /**
271      * Broadcast intent action indicating that the state of Wi-Fi p2p connectivity
272      * has changed. One extra {@link #EXTRA_WIFI_P2P_INFO} provides the p2p connection info in
273      * the form of a {@link WifiP2pInfo} object. Another extra {@link #EXTRA_NETWORK_INFO} provides
274      * the network info in the form of a {@link android.net.NetworkInfo}. A third extra provides
275      * the details of the group and may contain a {@code null}.
276      *
277      * All of these permissions are required to receive this broadcast:
278      * {@link android.Manifest.permission#ACCESS_WIFI_STATE} and either
279      * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} or
280      * {@link android.Manifest.permission#NEARBY_WIFI_DEVICES}
281      *
282      * @see #EXTRA_WIFI_P2P_INFO
283      * @see #EXTRA_NETWORK_INFO
284      * @see #EXTRA_WIFI_P2P_GROUP
285      */
286     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
287     public static final String WIFI_P2P_CONNECTION_CHANGED_ACTION =
288         "android.net.wifi.p2p.CONNECTION_STATE_CHANGE";
289 
290     /**
291      * The lookup key for a {@link android.net.wifi.p2p.WifiP2pInfo} object
292      * Retrieve with {@link android.content.Intent#getParcelableExtra(String)}.
293      */
294     public static final String EXTRA_WIFI_P2P_INFO = "wifiP2pInfo";
295 
296     /**
297      * The lookup key for a {@link android.net.NetworkInfo} object associated with the
298      * p2p network. Retrieve with
299      * {@link android.content.Intent#getParcelableExtra(String)}.
300      */
301     public static final String EXTRA_NETWORK_INFO = "networkInfo";
302 
303     /**
304      * The lookup key for a {@link android.net.wifi.p2p.WifiP2pGroup} object
305      * associated with the p2p network. Retrieve with
306      * {@link android.content.Intent#getParcelableExtra(String)}.
307      */
308     public static final String EXTRA_WIFI_P2P_GROUP = "p2pGroupInfo";
309 
310     /**
311      * Broadcast intent action indicating that the available peer list has changed. This
312      * can be sent as a result of peers being found, lost or updated.
313      *
314      * All of these permissions are required to receive this broadcast:
315      * {@link android.Manifest.permission#ACCESS_WIFI_STATE} and either
316      * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} or
317      * {@link android.Manifest.permission#NEARBY_WIFI_DEVICES}
318      *
319      * <p> An extra {@link #EXTRA_P2P_DEVICE_LIST} provides the full list of
320      * current peers. The full list of peers can also be obtained any time with
321      * {@link #requestPeers}.
322      *
323      * @see #EXTRA_P2P_DEVICE_LIST
324      */
325     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
326     public static final String WIFI_P2P_PEERS_CHANGED_ACTION =
327         "android.net.wifi.p2p.PEERS_CHANGED";
328 
329      /**
330       * The lookup key for a {@link android.net.wifi.p2p.WifiP2pDeviceList} object representing
331       * the new peer list when {@link #WIFI_P2P_PEERS_CHANGED_ACTION} broadcast is sent.
332       *
333       * <p>Retrieve with {@link android.content.Intent#getParcelableExtra(String)}.
334       */
335     public static final String EXTRA_P2P_DEVICE_LIST = "wifiP2pDeviceList";
336 
337     /**
338      * Broadcast intent action indicating that peer discovery has either started or stopped.
339      * One extra {@link #EXTRA_DISCOVERY_STATE} indicates whether discovery has started
340      * or stopped.
341      *
342      * <p>Note that discovery will be stopped during a connection setup. If the application tries
343      * to re-initiate discovery during this time, it can fail.
344      */
345     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
346     public static final String WIFI_P2P_DISCOVERY_CHANGED_ACTION =
347         "android.net.wifi.p2p.DISCOVERY_STATE_CHANGE";
348 
349     /**
350      * The lookup key for an int that indicates whether p2p discovery has started or stopped.
351      * Retrieve it with {@link android.content.Intent#getIntExtra(String,int)}.
352      *
353      * @see #WIFI_P2P_DISCOVERY_STARTED
354      * @see #WIFI_P2P_DISCOVERY_STOPPED
355      */
356     public static final String EXTRA_DISCOVERY_STATE = "discoveryState";
357 
358     /** @hide */
359     @IntDef({
360             WIFI_P2P_DISCOVERY_STOPPED,
361             WIFI_P2P_DISCOVERY_STARTED})
362     @Retention(RetentionPolicy.SOURCE)
363     public @interface WifiP2pDiscoveryState {
364     }
365 
366     /**
367      * p2p discovery has stopped
368      *
369      * @see #WIFI_P2P_DISCOVERY_CHANGED_ACTION
370      */
371     public static final int WIFI_P2P_DISCOVERY_STOPPED = 1;
372 
373     /**
374      * p2p discovery has started
375      *
376      * @see #WIFI_P2P_DISCOVERY_CHANGED_ACTION
377      */
378     public static final int WIFI_P2P_DISCOVERY_STARTED = 2;
379 
380     /**
381      * Broadcast intent action indicating that this device details have changed.
382      *
383      * <p> An extra {@link #EXTRA_WIFI_P2P_DEVICE} provides this device details.
384      * The valid device details can also be obtained with
385      * {@link #requestDeviceInfo(Channel, DeviceInfoListener)} when p2p is enabled.
386      * To get information notifications on P2P getting enabled refers
387      * {@link #WIFI_P2P_STATE_ENABLED}.
388      *
389      * <p> The {@link #EXTRA_WIFI_P2P_DEVICE} extra contains an anonymized version of the device's
390      * MAC address. Callers holding the {@code android.Manifest.permission#LOCAL_MAC_ADDRESS}
391      * permission can use {@link #requestDeviceInfo} to obtain the actual MAC address of this
392      * device.
393      *
394      * All of these permissions are required to receive this broadcast:
395      * {@link android.Manifest.permission#ACCESS_WIFI_STATE} and either
396      * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} or
397      * {@link android.Manifest.permission#NEARBY_WIFI_DEVICES}
398      *
399      * @see #EXTRA_WIFI_P2P_DEVICE
400      */
401     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
402     public static final String WIFI_P2P_THIS_DEVICE_CHANGED_ACTION =
403         "android.net.wifi.p2p.THIS_DEVICE_CHANGED";
404 
405     /**
406      * The lookup key for a {@link android.net.wifi.p2p.WifiP2pDevice} object
407      * Retrieve with {@link android.content.Intent#getParcelableExtra(String)}.
408      */
409     public static final String EXTRA_WIFI_P2P_DEVICE = "wifiP2pDevice";
410 
411     /**
412      * Broadcast intent action indicating that remembered persistent groups have changed.
413      *
414      * You can <em>not</em> receive this through components declared
415      * in manifests, only by explicitly registering for it with
416      * {@link android.content.Context#registerReceiver(android.content.BroadcastReceiver,
417      * android.content.IntentFilter) Context.registerReceiver()}.
418      *
419      * @hide
420      */
421     @SystemApi
422     public static final String ACTION_WIFI_P2P_PERSISTENT_GROUPS_CHANGED =
423             "android.net.wifi.p2p.action.WIFI_P2P_PERSISTENT_GROUPS_CHANGED";
424 
425     /**
426      * Broadcast intent action indicating whether or not current connecting
427      * request is accepted.
428      *
429      * The connecting request is initiated by
430      * {@link #connect(Channel, WifiP2pConfig, ActionListener)}.
431      * <p>The {@link #EXTRA_REQUEST_RESPONSE} extra indicates whether or not current
432      * request is accepted or rejected.
433      * <p>The {@link #EXTRA_REQUEST_CONFIG} extra indicates the responsed configuration.
434      */
435     public static final String ACTION_WIFI_P2P_REQUEST_RESPONSE_CHANGED =
436             "android.net.wifi.p2p.action.WIFI_P2P_REQUEST_RESPONSE_CHANGED";
437 
438     /**
439      * The lookup key for the result of a request, true if accepted, false otherwise.
440      */
441     public static final String EXTRA_REQUEST_RESPONSE =
442             "android.net.wifi.p2p.extra.REQUEST_RESPONSE";
443 
444     /**
445      * The lookup key for the {@link WifiP2pConfig} object of a request.
446      */
447     public static final String EXTRA_REQUEST_CONFIG =
448             "android.net.wifi.p2p.extra.REQUEST_CONFIG";
449 
450     /**
451      * The lookup key for a handover message returned by the WifiP2pService.
452      * @hide
453      */
454     public static final String EXTRA_HANDOVER_MESSAGE =
455             "android.net.wifi.p2p.EXTRA_HANDOVER_MESSAGE";
456 
457     /**
458      * The lookup key for a calling package name from WifiP2pManager
459      * @hide
460      */
461     public static final String CALLING_PACKAGE =
462             "android.net.wifi.p2p.CALLING_PACKAGE";
463 
464     /**
465      * The lookup key for a calling feature id from WifiP2pManager
466      * @hide
467      */
468     public static final String CALLING_FEATURE_ID =
469             "android.net.wifi.p2p.CALLING_FEATURE_ID";
470 
471     /**
472      * The lookup key for a calling package binder from WifiP2pManager
473      * @hide
474      */
475     public static final String CALLING_BINDER =
476             "android.net.wifi.p2p.CALLING_BINDER";
477 
478     /**
479      * Run P2P scan on all channels.
480      * @hide
481      */
482     public static final int WIFI_P2P_SCAN_FULL = 0;
483 
484     /**
485      * Run P2P scan only on social channels.
486      * @hide
487      */
488     public static final int WIFI_P2P_SCAN_SOCIAL = 1;
489 
490     /**
491      * Run P2P scan only on a specific channel.
492      * @hide
493      */
494     public static final int WIFI_P2P_SCAN_SINGLE_FREQ = 2;
495 
496     /** @hide */
497     @IntDef(prefix = {"WIFI_P2P_SCAN_"}, value = {
498             WIFI_P2P_SCAN_FULL,
499             WIFI_P2P_SCAN_SOCIAL,
500             WIFI_P2P_SCAN_SINGLE_FREQ})
501     @Retention(RetentionPolicy.SOURCE)
502     public @interface WifiP2pScanType {
503     }
504 
505     /**
506      * No channel specified for discover Peers APIs. Let lower layer decide the frequencies to scan
507      * based on the WifiP2pScanType.
508      * @hide
509      */
510     public static final int WIFI_P2P_SCAN_FREQ_UNSPECIFIED = 0;
511 
512     /**
513      * Maximum length in bytes of all vendor specific information elements (IEs) allowed to
514      * set during Wi-Fi Direct (P2P) discovery.
515      */
516     private static final int WIFI_P2P_VENDOR_ELEMENTS_MAXIMUM_LENGTH = 512;
517 
518     IWifiP2pManager mService;
519 
520     private static final int BASE = Protocol.BASE_WIFI_P2P_MANAGER;
521 
522     /** @hide */
523     public static final int DISCOVER_PEERS                          = BASE + 1;
524     /** @hide */
525     public static final int DISCOVER_PEERS_FAILED                   = BASE + 2;
526     /** @hide */
527     public static final int DISCOVER_PEERS_SUCCEEDED                = BASE + 3;
528 
529     /** @hide */
530     public static final int STOP_DISCOVERY                          = BASE + 4;
531     /** @hide */
532     public static final int STOP_DISCOVERY_FAILED                   = BASE + 5;
533     /** @hide */
534     public static final int STOP_DISCOVERY_SUCCEEDED                = BASE + 6;
535 
536     /** @hide */
537     public static final int CONNECT                                 = BASE + 7;
538     /** @hide */
539     public static final int CONNECT_FAILED                          = BASE + 8;
540     /** @hide */
541     public static final int CONNECT_SUCCEEDED                       = BASE + 9;
542 
543     /** @hide */
544     public static final int CANCEL_CONNECT                          = BASE + 10;
545     /** @hide */
546     public static final int CANCEL_CONNECT_FAILED                   = BASE + 11;
547     /** @hide */
548     public static final int CANCEL_CONNECT_SUCCEEDED                = BASE + 12;
549 
550     /** @hide */
551     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
552     public static final int CREATE_GROUP                            = BASE + 13;
553     /** @hide */
554     public static final int CREATE_GROUP_FAILED                     = BASE + 14;
555     /** @hide */
556     public static final int CREATE_GROUP_SUCCEEDED                  = BASE + 15;
557 
558     /** @hide */
559     public static final int REMOVE_GROUP                            = BASE + 16;
560     /** @hide */
561     public static final int REMOVE_GROUP_FAILED                     = BASE + 17;
562     /** @hide */
563     public static final int REMOVE_GROUP_SUCCEEDED                  = BASE + 18;
564 
565     /** @hide */
566     public static final int REQUEST_PEERS                           = BASE + 19;
567     /** @hide */
568     public static final int RESPONSE_PEERS                          = BASE + 20;
569 
570     /** @hide */
571     public static final int REQUEST_CONNECTION_INFO                 = BASE + 21;
572     /** @hide */
573     public static final int RESPONSE_CONNECTION_INFO                = BASE + 22;
574 
575     /** @hide */
576     public static final int REQUEST_GROUP_INFO                      = BASE + 23;
577     /** @hide */
578     public static final int RESPONSE_GROUP_INFO                     = BASE + 24;
579 
580     /** @hide */
581     public static final int ADD_LOCAL_SERVICE                       = BASE + 28;
582     /** @hide */
583     public static final int ADD_LOCAL_SERVICE_FAILED                = BASE + 29;
584     /** @hide */
585     public static final int ADD_LOCAL_SERVICE_SUCCEEDED             = BASE + 30;
586 
587     /** @hide */
588     public static final int REMOVE_LOCAL_SERVICE                    = BASE + 31;
589     /** @hide */
590     public static final int REMOVE_LOCAL_SERVICE_FAILED             = BASE + 32;
591     /** @hide */
592     public static final int REMOVE_LOCAL_SERVICE_SUCCEEDED          = BASE + 33;
593 
594     /** @hide */
595     public static final int CLEAR_LOCAL_SERVICES                    = BASE + 34;
596     /** @hide */
597     public static final int CLEAR_LOCAL_SERVICES_FAILED             = BASE + 35;
598     /** @hide */
599     public static final int CLEAR_LOCAL_SERVICES_SUCCEEDED          = BASE + 36;
600 
601     /** @hide */
602     public static final int ADD_SERVICE_REQUEST                     = BASE + 37;
603     /** @hide */
604     public static final int ADD_SERVICE_REQUEST_FAILED              = BASE + 38;
605     /** @hide */
606     public static final int ADD_SERVICE_REQUEST_SUCCEEDED           = BASE + 39;
607 
608     /** @hide */
609     public static final int REMOVE_SERVICE_REQUEST                  = BASE + 40;
610     /** @hide */
611     public static final int REMOVE_SERVICE_REQUEST_FAILED           = BASE + 41;
612     /** @hide */
613     public static final int REMOVE_SERVICE_REQUEST_SUCCEEDED        = BASE + 42;
614 
615     /** @hide */
616     public static final int CLEAR_SERVICE_REQUESTS                  = BASE + 43;
617     /** @hide */
618     public static final int CLEAR_SERVICE_REQUESTS_FAILED           = BASE + 44;
619     /** @hide */
620     public static final int CLEAR_SERVICE_REQUESTS_SUCCEEDED        = BASE + 45;
621 
622     /** @hide */
623     public static final int DISCOVER_SERVICES                       = BASE + 46;
624     /** @hide */
625     public static final int DISCOVER_SERVICES_FAILED                = BASE + 47;
626     /** @hide */
627     public static final int DISCOVER_SERVICES_SUCCEEDED             = BASE + 48;
628 
629     /** @hide */
630     public static final int PING                                    = BASE + 49;
631 
632     /** @hide */
633     public static final int RESPONSE_SERVICE                        = BASE + 50;
634 
635     /** @hide */
636     public static final int SET_DEVICE_NAME                         = BASE + 51;
637     /** @hide */
638     public static final int SET_DEVICE_NAME_FAILED                  = BASE + 52;
639     /** @hide */
640     public static final int SET_DEVICE_NAME_SUCCEEDED               = BASE + 53;
641 
642     /** @hide */
643     public static final int DELETE_PERSISTENT_GROUP                 = BASE + 54;
644     /** @hide */
645     public static final int DELETE_PERSISTENT_GROUP_FAILED          = BASE + 55;
646     /** @hide */
647     public static final int DELETE_PERSISTENT_GROUP_SUCCEEDED       = BASE + 56;
648 
649     /** @hide */
650     public static final int REQUEST_PERSISTENT_GROUP_INFO           = BASE + 57;
651     /** @hide */
652     public static final int RESPONSE_PERSISTENT_GROUP_INFO          = BASE + 58;
653 
654     /** @hide */
655     public static final int SET_WFD_INFO                            = BASE + 59;
656     /** @hide */
657     public static final int SET_WFD_INFO_FAILED                     = BASE + 60;
658     /** @hide */
659     public static final int SET_WFD_INFO_SUCCEEDED                  = BASE + 61;
660 
661     /** @hide */
662     public static final int START_WPS                               = BASE + 62;
663     /** @hide */
664     public static final int START_WPS_FAILED                        = BASE + 63;
665     /** @hide */
666     public static final int START_WPS_SUCCEEDED                     = BASE + 64;
667 
668     /** @hide */
669     public static final int START_LISTEN                            = BASE + 65;
670     /** @hide */
671     public static final int START_LISTEN_FAILED                     = BASE + 66;
672     /** @hide */
673     public static final int START_LISTEN_SUCCEEDED                  = BASE + 67;
674 
675     /** @hide */
676     public static final int STOP_LISTEN                             = BASE + 68;
677     /** @hide */
678     public static final int STOP_LISTEN_FAILED                      = BASE + 69;
679     /** @hide */
680     public static final int STOP_LISTEN_SUCCEEDED                   = BASE + 70;
681 
682     /** @hide */
683     public static final int SET_CHANNEL                             = BASE + 71;
684     /** @hide */
685     public static final int SET_CHANNEL_FAILED                      = BASE + 72;
686     /** @hide */
687     public static final int SET_CHANNEL_SUCCEEDED                   = BASE + 73;
688 
689     /** @hide */
690     public static final int GET_HANDOVER_REQUEST                    = BASE + 75;
691     /** @hide */
692     public static final int GET_HANDOVER_SELECT                     = BASE + 76;
693     /** @hide */
694     public static final int RESPONSE_GET_HANDOVER_MESSAGE           = BASE + 77;
695     /** @hide */
696     public static final int INITIATOR_REPORT_NFC_HANDOVER           = BASE + 78;
697     /** @hide */
698     public static final int RESPONDER_REPORT_NFC_HANDOVER           = BASE + 79;
699     /** @hide */
700     public static final int REPORT_NFC_HANDOVER_SUCCEEDED           = BASE + 80;
701     /** @hide */
702     public static final int REPORT_NFC_HANDOVER_FAILED              = BASE + 81;
703 
704     /** @hide */
705     public static final int FACTORY_RESET                           = BASE + 82;
706     /** @hide */
707     public static final int FACTORY_RESET_FAILED                    = BASE + 83;
708     /** @hide */
709     public static final int FACTORY_RESET_SUCCEEDED                 = BASE + 84;
710 
711     /** @hide */
712     public static final int REQUEST_ONGOING_PEER_CONFIG             = BASE + 85;
713     /** @hide */
714     public static final int RESPONSE_ONGOING_PEER_CONFIG            = BASE + 86;
715     /** @hide */
716     public static final int SET_ONGOING_PEER_CONFIG                 = BASE + 87;
717     /** @hide */
718     public static final int SET_ONGOING_PEER_CONFIG_FAILED          = BASE + 88;
719     /** @hide */
720     public static final int SET_ONGOING_PEER_CONFIG_SUCCEEDED       = BASE + 89;
721 
722     /** @hide */
723     public static final int REQUEST_P2P_STATE                       = BASE + 90;
724     /** @hide */
725     public static final int RESPONSE_P2P_STATE                      = BASE + 91;
726 
727     /** @hide */
728     public static final int REQUEST_DISCOVERY_STATE                 = BASE + 92;
729     /** @hide */
730     public static final int RESPONSE_DISCOVERY_STATE                = BASE + 93;
731 
732     /** @hide */
733     public static final int REQUEST_NETWORK_INFO                    = BASE + 94;
734     /** @hide */
735     public static final int RESPONSE_NETWORK_INFO                   = BASE + 95;
736 
737     /** @hide */
738     public static final int UPDATE_CHANNEL_INFO                     = BASE + 96;
739 
740     /** @hide */
741     public static final int REQUEST_DEVICE_INFO                     = BASE + 97;
742     /** @hide */
743     public static final int RESPONSE_DEVICE_INFO                    = BASE + 98;
744 
745     /** @hide */
746     public static final int REMOVE_CLIENT                           = BASE + 99;
747     /** @hide */
748     public static final int REMOVE_CLIENT_FAILED                    = BASE + 100;
749     /** @hide */
750     public static final int REMOVE_CLIENT_SUCCEEDED                 = BASE + 101;
751 
752     /** @hide */
753     public static final int ADD_EXTERNAL_APPROVER                   = BASE + 102;
754     /** @hide */
755     public static final int EXTERNAL_APPROVER_ATTACH                = BASE + 103;
756     /** @hide */
757     public static final int EXTERNAL_APPROVER_DETACH                = BASE + 104;
758     /** @hide */
759     public static final int EXTERNAL_APPROVER_CONNECTION_REQUESTED  = BASE + 105;
760     /** @hide */
761     public static final int EXTERNAL_APPROVER_PIN_GENERATED         = BASE + 106;
762 
763     /** @hide */
764     public static final int REMOVE_EXTERNAL_APPROVER                = BASE + 107;
765     /** @hide */
766     public static final int REMOVE_EXTERNAL_APPROVER_FAILED         = BASE + 108;
767     /** @hide */
768     public static final int REMOVE_EXTERNAL_APPROVER_SUCCEEDED      = BASE + 109;
769 
770     /** @hide */
771     public static final int SET_CONNECTION_REQUEST_RESULT           = BASE + 110;
772     /** @hide */
773     public static final int SET_CONNECTION_REQUEST_RESULT_FAILED    = BASE + 111;
774     /** @hide */
775     public static final int SET_CONNECTION_REQUEST_RESULT_SUCCEEDED = BASE + 112;
776 
777     /** @hide */
778     public static final int SET_VENDOR_ELEMENTS                       = BASE + 113;
779     /** @hide */
780     public static final int SET_VENDOR_ELEMENTS_FAILED                = BASE + 114;
781     /** @hide */
782     public static final int SET_VENDOR_ELEMENTS_SUCCEEDED             = BASE + 115;
783 
784     /**
785      * Create a new WifiP2pManager instance. Applications use
786      * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
787      * the standard {@link android.content.Context#WIFI_P2P_SERVICE Context.WIFI_P2P_SERVICE}.
788      * @param service the Binder interface
789      * @hide - hide this because it takes in a parameter of type IWifiP2pManager, which
790      * is a system private class.
791      */
792     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
WifiP2pManager(IWifiP2pManager service)793     public WifiP2pManager(IWifiP2pManager service) {
794         mService = service;
795     }
796 
797     /**
798      * Passed with {@link ActionListener#onFailure}.
799      * Indicates that the operation failed due to an internal error.
800      */
801     public static final int ERROR               = 0;
802 
803     /**
804      * Passed with {@link ActionListener#onFailure}.
805      * Indicates that the operation failed because p2p is unsupported on the device.
806      */
807     public static final int P2P_UNSUPPORTED     = 1;
808 
809     /**
810      * Passed with {@link ActionListener#onFailure}.
811      * Indicates that the operation failed because the framework is busy and
812      * unable to service the request
813      */
814     public static final int BUSY                = 2;
815 
816     /**
817      * Passed with {@link ActionListener#onFailure}.
818      * Indicates that the {@link #discoverServices} failed because no service
819      * requests are added. Use {@link #addServiceRequest} to add a service
820      * request.
821      */
822     public static final int NO_SERVICE_REQUESTS = 3;
823 
824     /** Interface for callback invocation when framework channel is lost */
825     public interface ChannelListener {
826         /**
827          * The channel to the framework has been disconnected.
828          * Application could try re-initializing using {@link #initialize}
829          */
onChannelDisconnected()830         public void onChannelDisconnected();
831     }
832 
833     /** Interface for callback invocation on an application action */
834     public interface ActionListener {
835         /** The operation succeeded */
onSuccess()836         public void onSuccess();
837         /**
838          * The operation failed
839          * @param reason The reason for failure could be one of {@link #P2P_UNSUPPORTED},
840          * {@link #ERROR} or {@link #BUSY}
841          */
onFailure(int reason)842         public void onFailure(int reason);
843     }
844 
845     /** Interface for callback invocation when peer list is available */
846     public interface PeerListListener {
847         /**
848          * The requested peer list is available
849          * @param peers List of available peers
850          */
onPeersAvailable(WifiP2pDeviceList peers)851         public void onPeersAvailable(WifiP2pDeviceList peers);
852     }
853 
854     /** Interface for callback invocation when connection info is available */
855     public interface ConnectionInfoListener {
856         /**
857          * The requested connection info is available
858          * @param info Wi-Fi p2p connection info
859          */
onConnectionInfoAvailable(WifiP2pInfo info)860         public void onConnectionInfoAvailable(WifiP2pInfo info);
861     }
862 
863     /** Interface for callback invocation when group info is available */
864     public interface GroupInfoListener {
865         /**
866          * The requested p2p group info is available
867          * @param group Wi-Fi p2p group info
868          */
onGroupInfoAvailable(WifiP2pGroup group)869         public void onGroupInfoAvailable(WifiP2pGroup group);
870     }
871 
872    /**
873     * Interface for callback invocation when service discovery response other than
874     * Upnp or Bonjour is received
875     */
876     public interface ServiceResponseListener {
877 
878         /**
879          * The requested service response is available.
880          *
881          * @param protocolType protocol type. currently only
882          * {@link WifiP2pServiceInfo#SERVICE_TYPE_VENDOR_SPECIFIC}.
883          * @param responseData service discovery response data based on the requested
884          *  service protocol type. The format depends on the service type.
885          * @param srcDevice source device.
886          */
onServiceAvailable(int protocolType, byte[] responseData, WifiP2pDevice srcDevice)887         public void onServiceAvailable(int protocolType,
888                 byte[] responseData, WifiP2pDevice srcDevice);
889     }
890 
891     /**
892      * Interface for callback invocation when Bonjour service discovery response
893      * is received
894      */
895     public interface DnsSdServiceResponseListener {
896 
897         /**
898          * The requested Bonjour service response is available.
899          *
900          * <p>This function is invoked when the device with the specified Bonjour
901          * registration type returned the instance name.
902          * @param instanceName instance name.<br>
903          *  e.g) "MyPrinter".
904          * @param registrationType <br>
905          * e.g) "_ipp._tcp.local."
906          * @param srcDevice source device.
907          */
onDnsSdServiceAvailable(String instanceName, String registrationType, WifiP2pDevice srcDevice)908         public void onDnsSdServiceAvailable(String instanceName,
909                 String registrationType, WifiP2pDevice srcDevice);
910 
911    }
912 
913     /**
914      * Interface for callback invocation when Bonjour TXT record is available
915      * for a service
916      */
917    public interface DnsSdTxtRecordListener {
918         /**
919          * The requested Bonjour service response is available.
920          *
921          * <p>This function is invoked when the device with the specified full
922          * service domain service returned TXT record.
923          *
924          * @param fullDomainName full domain name. <br>
925          * e.g) "MyPrinter._ipp._tcp.local.".
926          * @param txtRecordMap TXT record data as a map of key/value pairs
927          * @param srcDevice source device.
928          */
onDnsSdTxtRecordAvailable(String fullDomainName, Map<String, String> txtRecordMap, WifiP2pDevice srcDevice)929         public void onDnsSdTxtRecordAvailable(String fullDomainName,
930                 Map<String, String> txtRecordMap,
931                 WifiP2pDevice srcDevice);
932    }
933 
934     /**
935      * Interface for callback invocation when upnp service discovery response
936      * is received
937      * */
938     public interface UpnpServiceResponseListener {
939 
940         /**
941          * The requested upnp service response is available.
942          *
943          * <p>This function is invoked when the specified device or service is found.
944          *
945          * @param uniqueServiceNames The list of unique service names.<br>
946          * e.g) uuid:6859dede-8574-59ab-9332-123456789012::urn:schemas-upnp-org:device:
947          * MediaServer:1
948          * @param srcDevice source device.
949          */
onUpnpServiceAvailable(List<String> uniqueServiceNames, WifiP2pDevice srcDevice)950         public void onUpnpServiceAvailable(List<String> uniqueServiceNames,
951                 WifiP2pDevice srcDevice);
952     }
953 
954 
955     /**
956      * Interface for callback invocation when stored group info list is available
957      *
958      * @hide
959      */
960     @SystemApi
961     public interface PersistentGroupInfoListener {
962         /**
963          * The requested stored p2p group info list is available
964          * @param groups Wi-Fi p2p group info list
965          */
onPersistentGroupInfoAvailable(@onNull WifiP2pGroupList groups)966         void onPersistentGroupInfoAvailable(@NonNull WifiP2pGroupList groups);
967     }
968 
969     /**
970      * Interface for callback invocation when Handover Request or Select Message is available
971      * @hide
972      */
973     public interface HandoverMessageListener {
onHandoverMessageAvailable(String handoverMessage)974         public void onHandoverMessageAvailable(String handoverMessage);
975     }
976 
977     /** Interface for callback invocation when p2p state is available
978      *  in response to {@link #requestP2pState}.
979      */
980     public interface P2pStateListener {
981         /**
982          * The requested p2p state is available.
983          * @param state Wi-Fi p2p state
984          *        @see #WIFI_P2P_STATE_DISABLED
985          *        @see #WIFI_P2P_STATE_ENABLED
986          */
onP2pStateAvailable(@ifiP2pState int state)987         void onP2pStateAvailable(@WifiP2pState int state);
988     }
989 
990     /** Interface for callback invocation when p2p state is available
991      *  in response to {@link #requestDiscoveryState}.
992      */
993     public interface DiscoveryStateListener {
994         /**
995          * The requested p2p discovery state is available.
996          * @param state Wi-Fi p2p discovery state
997          *        @see #WIFI_P2P_DISCOVERY_STARTED
998          *        @see #WIFI_P2P_DISCOVERY_STOPPED
999          */
onDiscoveryStateAvailable(@ifiP2pDiscoveryState int state)1000         void onDiscoveryStateAvailable(@WifiP2pDiscoveryState int state);
1001     }
1002 
1003     /** Interface for callback invocation when {@link android.net.NetworkInfo} is available
1004      *  in response to {@link #requestNetworkInfo}.
1005      */
1006     public interface NetworkInfoListener {
1007         /**
1008          * The requested {@link android.net.NetworkInfo} is available
1009          * @param networkInfo Wi-Fi p2p {@link android.net.NetworkInfo}
1010          */
onNetworkInfoAvailable(@onNull NetworkInfo networkInfo)1011         void onNetworkInfoAvailable(@NonNull NetworkInfo networkInfo);
1012     }
1013 
1014     /**
1015      * Interface for callback invocation when ongoing peer info is available
1016      * @hide
1017      */
1018     public interface OngoingPeerInfoListener {
1019         /**
1020          * The requested ongoing WifiP2pConfig is available
1021          * @param peerConfig WifiP2pConfig for current connecting session
1022          */
onOngoingPeerAvailable(WifiP2pConfig peerConfig)1023         void onOngoingPeerAvailable(WifiP2pConfig peerConfig);
1024     }
1025 
1026     /** Interface for callback invocation when {@link android.net.wifi.p2p.WifiP2pDevice}
1027      *  is available in response to {@link #requestDeviceInfo(Channel, DeviceInfoListener)}.
1028      */
1029     public interface DeviceInfoListener {
1030         /**
1031          * The requested {@link android.net.wifi.p2p.WifiP2pDevice} is available.
1032          * @param wifiP2pDevice Wi-Fi p2p {@link android.net.wifi.p2p.WifiP2pDevice}
1033          */
onDeviceInfoAvailable(@ullable WifiP2pDevice wifiP2pDevice)1034         void onDeviceInfoAvailable(@Nullable WifiP2pDevice wifiP2pDevice);
1035     }
1036 
1037     /**
1038      * Interface for callback invocation when an incoming request is received.
1039      *
1040      * This callback is registered by
1041      * {@link #addExternalApprover(Channel, MacAddress, ExternalApproverRequestListener)}.
1042      */
1043     public interface ExternalApproverRequestListener {
1044         /**
1045          * This device received a negotiation request from another peer.
1046          *
1047          * Used in {@link #onConnectionRequested(int, WifiP2pConfig, WifiP2pDevice)}.
1048          */
1049         int REQUEST_TYPE_NEGOTIATION = 0;
1050         /**
1051          * This device received an invitation request from GO to join the group.
1052          *
1053          * Used in {@link #onConnectionRequested(int, WifiP2pConfig, WifiP2pDevice)}.
1054          */
1055         int REQUEST_TYPE_INVITATION = 1;
1056         /**
1057          * This GO device received a request from a peer to join the group.
1058          *
1059          * Used in {@link #onConnectionRequested(int, WifiP2pConfig, WifiP2pDevice)}.
1060          */
1061         int REQUEST_TYPE_JOIN = 2;
1062         /** @hide */
1063         @IntDef(prefix = {"REQUEST_TYPE__"}, value = {
1064             REQUEST_TYPE_NEGOTIATION,
1065             REQUEST_TYPE_INVITATION,
1066             REQUEST_TYPE_JOIN})
1067         @Retention(RetentionPolicy.SOURCE)
1068         public @interface RequestType {
1069         }
1070 
1071         /**
1072          * Detached by a call to
1073          * {@link #removeExternalApprover(Channel, MacAddress, ActionListener)}.
1074          *
1075          * Used in {@link #onDetached(MacAddress, int)}.
1076          */
1077         int APPROVER_DETACH_REASON_REMOVE = 0;
1078         /**
1079          * Detached due to a framework failure.
1080          *
1081          * Used in {@link #onDetached(MacAddress, int)}.
1082          */
1083         int APPROVER_DETACH_REASON_FAILURE = 1;
1084         /**
1085          * Detached when a new approver replaces an old one.
1086          *
1087          * Used in {@link #onDetached(MacAddress, int)}.
1088          */
1089         int APPROVER_DETACH_REASON_REPLACE = 2;
1090         /**
1091          * Detached since the {@link WifiP2pManager} channel was closed, e.g.
1092          * by using {@link Channel#close()} method.
1093          *
1094          * Used in {@link #onDetached(MacAddress, int)}.
1095          */
1096         int APPROVER_DETACH_REASON_CLOSE = 3;
1097         /** @hide */
1098         @IntDef(prefix = {"APPROVER_DETACH_REASON_"}, value = {
1099             APPROVER_DETACH_REASON_REMOVE,
1100             APPROVER_DETACH_REASON_FAILURE,
1101             APPROVER_DETACH_REASON_REPLACE,
1102             APPROVER_DETACH_REASON_CLOSE})
1103         @Retention(RetentionPolicy.SOURCE)
1104         public @interface ApproverDetachReason {
1105         }
1106 
1107         /**
1108          * Called when an approver registration via
1109          * {@link #addExternalApprover(Channel, MacAddress, ExternalApproverRequestListener)}
1110          * is successful.
1111          *
1112          * @param deviceAddress is the peer MAC address used in the registration.
1113          */
onAttached(@onNull MacAddress deviceAddress)1114         void onAttached(@NonNull MacAddress deviceAddress);
1115         /**
1116          * Called when an approver registration via
1117          * {@link #addExternalApprover(Channel, MacAddress, ExternalApproverRequestListener)}
1118          * has failed.
1119          *
1120          * @param deviceAddress is the peer MAC address used in the registration.
1121          * @param reason is the failure reason.
1122          */
onDetached(@onNull MacAddress deviceAddress, @ApproverDetachReason int reason)1123         void onDetached(@NonNull MacAddress deviceAddress, @ApproverDetachReason int reason);
1124         /**
1125          * Called when there is an incoming connection request
1126          * which matches a peer (identified by its {@link MacAddress}) registered by the external
1127          * approver through
1128          * {@link #addExternalApprover(Channel, MacAddress, ExternalApproverRequestListener)}.
1129          * The external approver is expected to follow up with a connection decision using the
1130          * {@link #setConnectionRequestResult(Channel, MacAddress, int, ActionListener)} with
1131          * {@link #CONNECTION_REQUEST_ACCEPT}, {@link #CONNECTION_REQUEST_REJECT}, or
1132          * {@link #CONNECTION_REQUEST_DEFER_TO_SERVICE}.
1133          *
1134          * @param requestType is one of {@link #REQUEST_TYPE_NEGOTIATION},
1135          *        {@link #REQUEST_TYPE_INVITATION}, and {@link #REQUEST_TYPE_JOIN}.
1136          * @param config is the peer configuration.
1137          * @param device is the peer information.
1138          */
onConnectionRequested( @equestType int requestType, @NonNull WifiP2pConfig config, @NonNull WifiP2pDevice device)1139         void onConnectionRequested(
1140                 @RequestType int requestType, @NonNull WifiP2pConfig config,
1141                 @NonNull WifiP2pDevice device);
1142         /**
1143          * Called when a PIN is generated by the WiFi service.
1144          *
1145          * The external approver can display the PIN, exchange the PIN via Out-Of-Band way
1146          * or ask the wifi service to show the PIN as usual using the
1147          * {@link #setConnectionRequestResult(Channel, MacAddress, int, ActionListener)}
1148          * with {@link #CONNECTION_REQUEST_DEFER_SHOW_PIN_TO_SERVICE}.
1149          *
1150          * @param deviceAddress is the peer MAC address used in the registration.
1151          * @param pin is the WPS PIN.
1152          */
onPinGenerated(@onNull MacAddress deviceAddress, @NonNull String pin)1153         void onPinGenerated(@NonNull MacAddress deviceAddress, @NonNull String pin);
1154     }
1155 
1156 
1157     /**
1158      * A channel that connects the application to the Wifi p2p framework.
1159      * Most p2p operations require a Channel as an argument. An instance of Channel is obtained
1160      * by doing a call on {@link #initialize}
1161      */
1162     public static class Channel implements AutoCloseable {
1163         /** @hide */
Channel(Context context, Looper looper, ChannelListener l, Binder binder, WifiP2pManager p2pManager)1164         public Channel(Context context, Looper looper, ChannelListener l, Binder binder,
1165                 WifiP2pManager p2pManager) {
1166             mAsyncChannel = new AsyncChannel();
1167             mHandler = new P2pHandler(looper);
1168             mChannelListener = l;
1169             mContext = context;
1170             mBinder = binder;
1171             mP2pManager = p2pManager;
1172 
1173             mCloseGuard.open("close");
1174         }
1175         private final static int INVALID_LISTENER_KEY = 0;
1176         private final WifiP2pManager mP2pManager;
1177         private ChannelListener mChannelListener;
1178         private ServiceResponseListener mServRspListener;
1179         private DnsSdServiceResponseListener mDnsSdServRspListener;
1180         private DnsSdTxtRecordListener mDnsSdTxtListener;
1181         private UpnpServiceResponseListener mUpnpServRspListener;
1182         private HashMap<Integer, Object> mListenerMap = new HashMap<Integer, Object>();
1183         private final Object mListenerMapLock = new Object();
1184         private int mListenerKey = 0;
1185 
1186         private final CloseGuard mCloseGuard = new CloseGuard();
1187 
1188         /**
1189          * Return the binder object.
1190          * @hide
1191          */
getBinder()1192         public @NonNull Binder getBinder() {
1193             return mBinder;
1194         }
1195 
1196         /**
1197          * Close the current P2P connection and indicate to the P2P service that connections
1198          * created by the app can be removed.
1199          */
close()1200         public void close() {
1201             if (mP2pManager == null) {
1202                 Log.w(TAG, "Channel.close(): Null mP2pManager!?");
1203             } else {
1204                 try {
1205                     mP2pManager.mService.close(mBinder);
1206                 } catch (RemoteException e) {
1207                     throw e.rethrowFromSystemServer();
1208                 }
1209             }
1210 
1211             mAsyncChannel.disconnect();
1212             mCloseGuard.close();
1213             Reference.reachabilityFence(this);
1214         }
1215 
1216         /** @hide */
1217         @Override
finalize()1218         protected void finalize() throws Throwable {
1219             try {
1220                 if (mCloseGuard != null) {
1221                     mCloseGuard.warnIfOpen();
1222                 }
1223 
1224                 close();
1225             } finally {
1226                 super.finalize();
1227             }
1228         }
1229 
1230         /* package */ final Binder mBinder;
1231 
1232         @UnsupportedAppUsage
1233         private AsyncChannel mAsyncChannel;
1234         private P2pHandler mHandler;
1235         Context mContext;
1236         class P2pHandler extends Handler {
P2pHandler(Looper looper)1237             P2pHandler(Looper looper) {
1238                 super(looper);
1239             }
1240 
1241             @Override
handleMessage(Message message)1242             public void handleMessage(Message message) {
1243                 Object listener = null;
1244                 // The listener for an external approver should be
1245                 // removed after detaching from the service.
1246                 switch (message.what) {
1247                     case EXTERNAL_APPROVER_ATTACH:
1248                     case EXTERNAL_APPROVER_CONNECTION_REQUESTED:
1249                     case EXTERNAL_APPROVER_PIN_GENERATED:
1250                         listener = getListener(message.arg2);
1251                         break;
1252                     default:
1253                         listener = removeListener(message.arg2);
1254                         break;
1255                 }
1256                 switch (message.what) {
1257                     case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
1258                         if (mChannelListener != null) {
1259                             mChannelListener.onChannelDisconnected();
1260                             mChannelListener = null;
1261                         }
1262                         break;
1263                     /* ActionListeners grouped together */
1264                     case DISCOVER_PEERS_FAILED:
1265                     case STOP_DISCOVERY_FAILED:
1266                     case DISCOVER_SERVICES_FAILED:
1267                     case CONNECT_FAILED:
1268                     case CANCEL_CONNECT_FAILED:
1269                     case CREATE_GROUP_FAILED:
1270                     case REMOVE_GROUP_FAILED:
1271                     case ADD_LOCAL_SERVICE_FAILED:
1272                     case REMOVE_LOCAL_SERVICE_FAILED:
1273                     case CLEAR_LOCAL_SERVICES_FAILED:
1274                     case ADD_SERVICE_REQUEST_FAILED:
1275                     case REMOVE_SERVICE_REQUEST_FAILED:
1276                     case CLEAR_SERVICE_REQUESTS_FAILED:
1277                     case SET_DEVICE_NAME_FAILED:
1278                     case DELETE_PERSISTENT_GROUP_FAILED:
1279                     case SET_WFD_INFO_FAILED:
1280                     case START_WPS_FAILED:
1281                     case START_LISTEN_FAILED:
1282                     case STOP_LISTEN_FAILED:
1283                     case SET_CHANNEL_FAILED:
1284                     case REPORT_NFC_HANDOVER_FAILED:
1285                     case FACTORY_RESET_FAILED:
1286                     case SET_ONGOING_PEER_CONFIG_FAILED:
1287                     case REMOVE_CLIENT_FAILED:
1288                     case REMOVE_EXTERNAL_APPROVER_FAILED:
1289                     case SET_CONNECTION_REQUEST_RESULT_FAILED:
1290                     case SET_VENDOR_ELEMENTS_FAILED:
1291                         if (listener != null) {
1292                             ((ActionListener) listener).onFailure(message.arg1);
1293                         }
1294                         break;
1295                     /* ActionListeners grouped together */
1296                     case DISCOVER_PEERS_SUCCEEDED:
1297                     case STOP_DISCOVERY_SUCCEEDED:
1298                     case DISCOVER_SERVICES_SUCCEEDED:
1299                     case CONNECT_SUCCEEDED:
1300                     case CANCEL_CONNECT_SUCCEEDED:
1301                     case CREATE_GROUP_SUCCEEDED:
1302                     case REMOVE_GROUP_SUCCEEDED:
1303                     case ADD_LOCAL_SERVICE_SUCCEEDED:
1304                     case REMOVE_LOCAL_SERVICE_SUCCEEDED:
1305                     case CLEAR_LOCAL_SERVICES_SUCCEEDED:
1306                     case ADD_SERVICE_REQUEST_SUCCEEDED:
1307                     case REMOVE_SERVICE_REQUEST_SUCCEEDED:
1308                     case CLEAR_SERVICE_REQUESTS_SUCCEEDED:
1309                     case SET_DEVICE_NAME_SUCCEEDED:
1310                     case DELETE_PERSISTENT_GROUP_SUCCEEDED:
1311                     case SET_WFD_INFO_SUCCEEDED:
1312                     case START_WPS_SUCCEEDED:
1313                     case START_LISTEN_SUCCEEDED:
1314                     case STOP_LISTEN_SUCCEEDED:
1315                     case SET_CHANNEL_SUCCEEDED:
1316                     case REPORT_NFC_HANDOVER_SUCCEEDED:
1317                     case FACTORY_RESET_SUCCEEDED:
1318                     case SET_ONGOING_PEER_CONFIG_SUCCEEDED:
1319                     case REMOVE_CLIENT_SUCCEEDED:
1320                     case REMOVE_EXTERNAL_APPROVER_SUCCEEDED:
1321                     case SET_CONNECTION_REQUEST_RESULT_SUCCEEDED:
1322                     case SET_VENDOR_ELEMENTS_SUCCEEDED:
1323                         if (listener != null) {
1324                             ((ActionListener) listener).onSuccess();
1325                         }
1326                         break;
1327                     case RESPONSE_PEERS:
1328                         WifiP2pDeviceList peers = (WifiP2pDeviceList) message.obj;
1329                         if (listener != null) {
1330                             ((PeerListListener) listener).onPeersAvailable(peers);
1331                         }
1332                         break;
1333                     case RESPONSE_CONNECTION_INFO:
1334                         WifiP2pInfo wifiP2pInfo = (WifiP2pInfo) message.obj;
1335                         if (listener != null) {
1336                             ((ConnectionInfoListener) listener).onConnectionInfoAvailable(wifiP2pInfo);
1337                         }
1338                         break;
1339                     case RESPONSE_GROUP_INFO:
1340                         WifiP2pGroup group = (WifiP2pGroup) message.obj;
1341                         if (listener != null) {
1342                             ((GroupInfoListener) listener).onGroupInfoAvailable(group);
1343                         }
1344                         break;
1345                     case RESPONSE_SERVICE:
1346                         WifiP2pServiceResponse resp = (WifiP2pServiceResponse) message.obj;
1347                         handleServiceResponse(resp);
1348                         break;
1349                     case RESPONSE_PERSISTENT_GROUP_INFO:
1350                         WifiP2pGroupList groups = (WifiP2pGroupList) message.obj;
1351                         if (listener != null) {
1352                             ((PersistentGroupInfoListener) listener).
1353                                 onPersistentGroupInfoAvailable(groups);
1354                         }
1355                         break;
1356                     case RESPONSE_GET_HANDOVER_MESSAGE:
1357                         Bundle handoverBundle = (Bundle) message.obj;
1358                         if (listener != null) {
1359                             String handoverMessage = handoverBundle != null
1360                                     ? handoverBundle.getString(EXTRA_HANDOVER_MESSAGE)
1361                                     : null;
1362                             ((HandoverMessageListener) listener)
1363                                     .onHandoverMessageAvailable(handoverMessage);
1364                         }
1365                         break;
1366                     case RESPONSE_ONGOING_PEER_CONFIG:
1367                         WifiP2pConfig peerConfig = (WifiP2pConfig) message.obj;
1368                         if (listener != null) {
1369                             ((OngoingPeerInfoListener) listener)
1370                                     .onOngoingPeerAvailable(peerConfig);
1371                         }
1372                         break;
1373                     case RESPONSE_P2P_STATE:
1374                         if (listener != null) {
1375                             ((P2pStateListener) listener)
1376                                     .onP2pStateAvailable(message.arg1);
1377                         }
1378                         break;
1379                     case RESPONSE_DISCOVERY_STATE:
1380                         if (listener != null) {
1381                             ((DiscoveryStateListener) listener)
1382                                     .onDiscoveryStateAvailable(message.arg1);
1383                         }
1384                         break;
1385                     case RESPONSE_NETWORK_INFO:
1386                         if (listener != null) {
1387                             ((NetworkInfoListener) listener)
1388                                     .onNetworkInfoAvailable((NetworkInfo) message.obj);
1389                         }
1390                         break;
1391                     case RESPONSE_DEVICE_INFO:
1392                         if (listener != null) {
1393                             ((DeviceInfoListener) listener)
1394                                     .onDeviceInfoAvailable((WifiP2pDevice) message.obj);
1395                         }
1396                         break;
1397                     case EXTERNAL_APPROVER_ATTACH:
1398                         if (listener != null) {
1399                             ((ExternalApproverRequestListener) listener)
1400                                     .onAttached((MacAddress) message.obj);
1401                         }
1402                         break;
1403                     case EXTERNAL_APPROVER_DETACH:
1404                         if (listener != null) {
1405                             ((ExternalApproverRequestListener) listener)
1406                                     .onDetached((MacAddress) message.obj, message.arg1);
1407                         }
1408                         break;
1409                     case EXTERNAL_APPROVER_CONNECTION_REQUESTED:
1410                         if (listener != null) {
1411                             int requestType = message.arg1;
1412                             Bundle bundle = (Bundle) message.obj;
1413                             WifiP2pDevice device = bundle.getParcelable(EXTRA_PARAM_KEY_DEVICE);
1414                             WifiP2pConfig config = bundle.getParcelable(EXTRA_PARAM_KEY_CONFIG);
1415                             ((ExternalApproverRequestListener) listener)
1416                                     .onConnectionRequested(requestType, config, device);
1417                         }
1418                         break;
1419                     case EXTERNAL_APPROVER_PIN_GENERATED:
1420                         if (listener != null) {
1421                             Bundle bundle = (Bundle) message.obj;
1422                             MacAddress deviceAddress = bundle.getParcelable(
1423                                     EXTRA_PARAM_KEY_PEER_ADDRESS);
1424                             String pin = bundle.getString(EXTRA_PARAM_KEY_WPS_PIN);
1425                             ((ExternalApproverRequestListener) listener)
1426                                     .onPinGenerated(deviceAddress, pin);
1427                         }
1428                         break;
1429                     default:
1430                         Log.d(TAG, "Ignored " + message);
1431                         break;
1432                 }
1433             }
1434         }
1435 
handleServiceResponse(WifiP2pServiceResponse resp)1436         private void handleServiceResponse(WifiP2pServiceResponse resp) {
1437             if (resp instanceof WifiP2pDnsSdServiceResponse) {
1438                 handleDnsSdServiceResponse((WifiP2pDnsSdServiceResponse)resp);
1439             } else if (resp instanceof WifiP2pUpnpServiceResponse) {
1440                 if (mUpnpServRspListener != null) {
1441                     handleUpnpServiceResponse((WifiP2pUpnpServiceResponse)resp);
1442                 }
1443             } else {
1444                 if (mServRspListener != null) {
1445                     mServRspListener.onServiceAvailable(resp.getServiceType(),
1446                             resp.getRawData(), resp.getSrcDevice());
1447                 }
1448             }
1449         }
1450 
handleUpnpServiceResponse(WifiP2pUpnpServiceResponse resp)1451         private void handleUpnpServiceResponse(WifiP2pUpnpServiceResponse resp) {
1452             mUpnpServRspListener.onUpnpServiceAvailable(resp.getUniqueServiceNames(),
1453                     resp.getSrcDevice());
1454         }
1455 
handleDnsSdServiceResponse(WifiP2pDnsSdServiceResponse resp)1456         private void handleDnsSdServiceResponse(WifiP2pDnsSdServiceResponse resp) {
1457             if (resp.getDnsType() == WifiP2pDnsSdServiceInfo.DNS_TYPE_PTR) {
1458                 if (mDnsSdServRspListener != null) {
1459                     mDnsSdServRspListener.onDnsSdServiceAvailable(
1460                             resp.getInstanceName(),
1461                             resp.getDnsQueryName(),
1462                             resp.getSrcDevice());
1463                 }
1464             } else if (resp.getDnsType() == WifiP2pDnsSdServiceInfo.DNS_TYPE_TXT) {
1465                 if (mDnsSdTxtListener != null) {
1466                     mDnsSdTxtListener.onDnsSdTxtRecordAvailable(
1467                             resp.getDnsQueryName(),
1468                             resp.getTxtRecord(),
1469                             resp.getSrcDevice());
1470                 }
1471             } else {
1472                 Log.e(TAG, "Unhandled resp " + resp);
1473             }
1474         }
1475 
1476         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
putListener(Object listener)1477         private int putListener(Object listener) {
1478             if (listener == null) return INVALID_LISTENER_KEY;
1479             int key;
1480             synchronized (mListenerMapLock) {
1481                 do {
1482                     key = mListenerKey++;
1483                 } while (key == INVALID_LISTENER_KEY);
1484                 mListenerMap.put(key, listener);
1485             }
1486             return key;
1487         }
1488 
getListener(int key)1489         private Object getListener(int key) {
1490             if (key == INVALID_LISTENER_KEY) return null;
1491             synchronized (mListenerMapLock) {
1492                 return mListenerMap.get(key);
1493             }
1494         }
1495 
removeListener(int key)1496         private Object removeListener(int key) {
1497             if (key == INVALID_LISTENER_KEY) return null;
1498             synchronized (mListenerMapLock) {
1499                 return mListenerMap.remove(key);
1500             }
1501         }
1502     }
1503 
checkChannel(Channel c)1504     private static void checkChannel(Channel c) {
1505         if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
1506     }
1507 
checkServiceInfo(WifiP2pServiceInfo info)1508     private static void checkServiceInfo(WifiP2pServiceInfo info) {
1509         if (info == null) throw new IllegalArgumentException("service info is null");
1510     }
1511 
checkServiceRequest(WifiP2pServiceRequest req)1512     private static void checkServiceRequest(WifiP2pServiceRequest req) {
1513         if (req == null) throw new IllegalArgumentException("service request is null");
1514     }
1515 
checkP2pConfig(WifiP2pConfig c)1516     private static void checkP2pConfig(WifiP2pConfig c) {
1517         if (c == null) throw new IllegalArgumentException("config cannot be null");
1518         if (TextUtils.isEmpty(c.deviceAddress)) {
1519             throw new IllegalArgumentException("deviceAddress cannot be empty");
1520         }
1521     }
1522 
1523     /**
1524      * Registers the application with the Wi-Fi framework. This function
1525      * must be the first to be called before any p2p operations are performed.
1526      *
1527      * @param srcContext is the context of the source
1528      * @param srcLooper is the Looper on which the callbacks are receivied
1529      * @param listener for callback at loss of framework communication. Can be null.
1530      * @return Channel instance that is necessary for performing any further p2p operations
1531      */
initialize(Context srcContext, Looper srcLooper, ChannelListener listener)1532     public Channel initialize(Context srcContext, Looper srcLooper, ChannelListener listener) {
1533         Binder binder = new Binder();
1534         Bundle extras = prepareExtrasBundleWithAttributionSource(srcContext);
1535         int displayId = Display.DEFAULT_DISPLAY;
1536         try {
1537             Display display = srcContext.getDisplay();
1538             if (display != null) {
1539                 displayId = display.getDisplayId();
1540             }
1541         } catch (UnsupportedOperationException e) {
1542             // an acceptable (per API definition) result of getDisplay - implying there's no display
1543             // associated with the context
1544         }
1545         extras.putInt(EXTRA_PARAM_KEY_DISPLAY_ID, displayId);
1546         Channel channel = initializeChannel(srcContext, srcLooper, listener,
1547                 getMessenger(binder, srcContext.getOpPackageName(), extras), binder);
1548         return channel;
1549     }
1550 
1551     /**
1552      * Registers the application with the Wi-Fi framework. Enables system-only functionality.
1553      * @hide
1554      */
initializeInternal(Context srcContext, Looper srcLooper, ChannelListener listener)1555     public Channel initializeInternal(Context srcContext, Looper srcLooper,
1556                                       ChannelListener listener) {
1557         return initializeChannel(srcContext, srcLooper, listener, getP2pStateMachineMessenger(),
1558                 null);
1559     }
1560 
prepareMessage(int what, int arg1, int arg2, Bundle extras, Context context)1561     private Message prepareMessage(int what, int arg1, int arg2, Bundle extras, Context context) {
1562         Message msg = Message.obtain();
1563         msg.what = what;
1564         msg.arg1 = arg1;
1565         msg.arg2 = arg2;
1566         msg.obj = maybeGetAttributionSource(context);
1567         msg.getData().putBundle(EXTRA_PARAM_KEY_BUNDLE, extras);
1568         return msg;
1569     }
1570 
prepareExtrasBundle(Channel c)1571     private Bundle prepareExtrasBundle(Channel c) {
1572         Bundle b = new Bundle();
1573         b.putBinder(CALLING_BINDER, c.getBinder());
1574         return b;
1575     }
1576 
1577     /**
1578      * Note, this should only be used for Binder calls.
1579      * Unparcelling an AttributionSource will throw an exception when done outside of a Binder
1580      * transaction. So don't use this with AsyncChannel since it will throw exception when
1581      * unparcelling.
1582      */
prepareExtrasBundleWithAttributionSource(Context context)1583     private Bundle prepareExtrasBundleWithAttributionSource(Context context) {
1584         Bundle bundle = new Bundle();
1585         if (SdkLevel.isAtLeastS()) {
1586             bundle.putParcelable(WifiManager.EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE,
1587                     context.getAttributionSource());
1588         }
1589         return bundle;
1590     }
1591 
maybeGetAttributionSource(Context context)1592     private Object maybeGetAttributionSource(Context context) {
1593         return SdkLevel.isAtLeastS() ? context.getAttributionSource() : null;
1594     }
1595 
initializeChannel(Context srcContext, Looper srcLooper, ChannelListener listener, Messenger messenger, Binder binder)1596     private Channel initializeChannel(Context srcContext, Looper srcLooper,
1597             ChannelListener listener, Messenger messenger, Binder binder) {
1598         if (messenger == null) return null;
1599 
1600         Channel c = new Channel(srcContext, srcLooper, listener, binder, this);
1601         if (c.mAsyncChannel.connectSync(srcContext, c.mHandler, messenger)
1602                 == AsyncChannel.STATUS_SUCCESSFUL) {
1603             Bundle bundle = new Bundle();
1604             bundle.putString(CALLING_PACKAGE, c.mContext.getOpPackageName());
1605             bundle.putString(CALLING_FEATURE_ID, c.mContext.getAttributionTag());
1606             bundle.putBinder(CALLING_BINDER, binder);
1607             Message msg = prepareMessage(UPDATE_CHANNEL_INFO, 0, c.putListener(null),
1608                     bundle, c.mContext);
1609             c.mAsyncChannel.sendMessage(msg);
1610             return c;
1611         } else {
1612             c.close();
1613             return null;
1614         }
1615     }
1616 
1617     /**
1618      * Initiate peer discovery. A discovery process involves scanning for available Wi-Fi peers
1619      * for the purpose of establishing a connection.
1620      *
1621      * <p> The function call immediately returns after sending a discovery request
1622      * to the framework. The application is notified of a success or failure to initiate
1623      * discovery through listener callbacks {@link ActionListener#onSuccess} or
1624      * {@link ActionListener#onFailure}.
1625      *
1626      * <p> The discovery remains active until a connection is initiated or
1627      * a p2p group is formed. Register for {@link #WIFI_P2P_PEERS_CHANGED_ACTION} intent to
1628      * determine when the framework notifies of a change as peers are discovered.
1629      *
1630      * <p> Upon receiving a {@link #WIFI_P2P_PEERS_CHANGED_ACTION} intent, an application
1631      * can request the list of peers using {@link #requestPeers}.
1632      * <p>
1633      * If targeting {@link android.os.Build.VERSION_CODES#TIRAMISU} or later, the application must
1634      * have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
1635      * android:usesPermissionFlags="neverForLocation". If the application does not declare
1636      * android:usesPermissionFlags="neverForLocation", then it must also have
1637      * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
1638      *
1639      * If targeting an earlier release than {@link android.os.Build.VERSION_CODES#TIRAMISU}, the
1640      * application must have {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
1641      *
1642      * @param channel is the channel created at {@link #initialize}
1643      * @param listener for callbacks on success or failure. Can be null.
1644      */
1645     @RequiresPermission(allOf = {
1646             android.Manifest.permission.NEARBY_WIFI_DEVICES,
1647             android.Manifest.permission.ACCESS_FINE_LOCATION
1648             }, conditional = true)
discoverPeers(Channel channel, ActionListener listener)1649     public void discoverPeers(Channel channel, ActionListener listener) {
1650         checkChannel(channel);
1651         Bundle extras = prepareExtrasBundle(channel);
1652         channel.mAsyncChannel.sendMessage(prepareMessage(DISCOVER_PEERS, WIFI_P2P_SCAN_FULL,
1653                 channel.putListener(listener), extras, channel.mContext));
1654     }
1655 
1656     /**
1657      * Scan only the social channels.
1658      *
1659      * A discovery process involves scanning for available Wi-Fi peers
1660      * for the purpose of establishing a connection.
1661      *
1662      * <p> The function call immediately returns after sending a discovery request
1663      * to the framework. The application is notified of a success or failure to initiate
1664      * discovery through listener callbacks {@link ActionListener#onSuccess} or
1665      * {@link ActionListener#onFailure}.
1666      *
1667      * <p> The discovery remains active until a connection is initiated or
1668      * a p2p group is formed. Register for {@link #WIFI_P2P_PEERS_CHANGED_ACTION} intent to
1669      * determine when the framework notifies of a change as peers are discovered.
1670      *
1671      * <p> Upon receiving a {@link #WIFI_P2P_PEERS_CHANGED_ACTION} intent, an application
1672      * can request the list of peers using {@link #requestPeers}.
1673      * <p>
1674      * The application must have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
1675      * android:usesPermissionFlags="neverForLocation". If the application does not declare
1676      * android:usesPermissionFlags="neverForLocation", then it must also have
1677      * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
1678      * <p>
1679      * Use {@link #isChannelConstrainedDiscoverySupported()} to determine whether the device
1680      * supports this feature. If {@link #isChannelConstrainedDiscoverySupported()} return
1681      * {@code false} then this method will throw {@link UnsupportedOperationException}.
1682      *
1683      * @param channel is the channel created at {@link #initialize}
1684      * @param listener for callbacks on success or failure.
1685      */
1686     @RequiresPermission(allOf = {
1687             android.Manifest.permission.NEARBY_WIFI_DEVICES,
1688             android.Manifest.permission.ACCESS_FINE_LOCATION
1689             }, conditional = true)
discoverPeersOnSocialChannels(@onNull Channel channel, @Nullable ActionListener listener)1690     public void discoverPeersOnSocialChannels(@NonNull Channel channel,
1691             @Nullable ActionListener listener) {
1692         if (!isChannelConstrainedDiscoverySupported()) {
1693             throw new UnsupportedOperationException();
1694         }
1695         checkChannel(channel);
1696         Bundle extras = prepareExtrasBundle(channel);
1697         channel.mAsyncChannel.sendMessage(prepareMessage(DISCOVER_PEERS, WIFI_P2P_SCAN_SOCIAL,
1698                 channel.putListener(listener), extras, channel.mContext));
1699     }
1700 
1701     /**
1702      * Scan only a single channel specified by frequency.
1703      *
1704      * A discovery process involves scanning for available Wi-Fi peers
1705      * for the purpose of establishing a connection.
1706      *
1707      * <p> The function call immediately returns after sending a discovery request
1708      * to the framework. The application is notified of a success or failure to initiate
1709      * discovery through listener callbacks {@link ActionListener#onSuccess} or
1710      * {@link ActionListener#onFailure}.
1711      *
1712      * <p> The discovery remains active until a connection is initiated or
1713      * a p2p group is formed. Register for {@link #WIFI_P2P_PEERS_CHANGED_ACTION} intent to
1714      * determine when the framework notifies of a change as peers are discovered.
1715      *
1716      * <p> Upon receiving a {@link #WIFI_P2P_PEERS_CHANGED_ACTION} intent, an application
1717      * can request the list of peers using {@link #requestPeers}.
1718      * <p>
1719      * The application must have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
1720      * android:usesPermissionFlags="neverForLocation". If the application does not declare
1721      * android:usesPermissionFlags="neverForLocation", then it must also have
1722      * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
1723      * <p>
1724      * Use {@link #isChannelConstrainedDiscoverySupported()} to determine whether the device
1725      * supports this feature. If {@link #isChannelConstrainedDiscoverySupported()} return
1726      * {@code false} then this method will throw {@link UnsupportedOperationException}.
1727      *
1728      * @param channel is the channel created at {@link #initialize}
1729      * @param frequencyMhz is the frequency of the channel to use for peer discovery.
1730      * @param listener for callbacks on success or failure.
1731      */
1732     @RequiresPermission(allOf = {
1733             android.Manifest.permission.NEARBY_WIFI_DEVICES,
1734             android.Manifest.permission.ACCESS_FINE_LOCATION
1735             }, conditional = true)
discoverPeersOnSpecificFrequency( @onNull Channel channel, int frequencyMhz, @Nullable ActionListener listener)1736     public void discoverPeersOnSpecificFrequency(
1737             @NonNull Channel channel, int frequencyMhz, @Nullable ActionListener listener) {
1738         if (!isChannelConstrainedDiscoverySupported()) {
1739             throw new UnsupportedOperationException();
1740         }
1741         checkChannel(channel);
1742         if (frequencyMhz <= 0) {
1743             throw new IllegalArgumentException("This frequency must be a positive value.");
1744         }
1745         Bundle extras = prepareExtrasBundle(channel);
1746         extras.putInt(EXTRA_PARAM_KEY_PEER_DISCOVERY_FREQ, frequencyMhz);
1747         channel.mAsyncChannel.sendMessage(prepareMessage(DISCOVER_PEERS, WIFI_P2P_SCAN_SINGLE_FREQ,
1748                 channel.putListener(listener), extras, channel.mContext));
1749     }
1750 
1751     /**
1752      * Stop an ongoing peer discovery
1753      *
1754      * <p> The function call immediately returns after sending a stop request
1755      * to the framework. The application is notified of a success or failure to initiate
1756      * stop through listener callbacks {@link ActionListener#onSuccess} or
1757      * {@link ActionListener#onFailure}.
1758      *
1759      * @param channel is the channel created at {@link #initialize}
1760      * @param listener for callbacks on success or failure. Can be null.
1761      */
stopPeerDiscovery(Channel channel, ActionListener listener)1762     public void stopPeerDiscovery(Channel channel, ActionListener listener) {
1763         checkChannel(channel);
1764         channel.mAsyncChannel.sendMessage(STOP_DISCOVERY, 0, channel.putListener(listener));
1765     }
1766 
1767     /**
1768      * Start a p2p connection to a device with the specified configuration.
1769      *
1770      * <p> The function call immediately returns after sending a connection request
1771      * to the framework. The application is notified of a success or failure to initiate
1772      * connect through listener callbacks {@link ActionListener#onSuccess} or
1773      * {@link ActionListener#onFailure}.
1774      *
1775      * <p> An app should use {@link WifiP2pConfig.Builder} to build the configuration
1776      * for this API, ex. call {@link WifiP2pConfig.Builder#setDeviceAddress(MacAddress)}
1777      * to set the peer MAC address and {@link WifiP2pConfig.Builder#enablePersistentMode(boolean)}
1778      * to configure the persistent mode.
1779      *
1780      * <p> Register for {@link #WIFI_P2P_CONNECTION_CHANGED_ACTION} intent to
1781      * determine when the framework notifies of a change in connectivity.
1782      *
1783      * <p> If the current device is not part of a p2p group, a connect request initiates
1784      * a group negotiation with the peer.
1785      *
1786      * <p> If the current device is part of an existing p2p group or has created
1787      * a p2p group with {@link #createGroup}, an invitation to join the group is sent to
1788      * the peer device.
1789      * <p>
1790      * If targeting {@link android.os.Build.VERSION_CODES#TIRAMISU} or later, the application must
1791      * have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
1792      * android:usesPermissionFlags="neverForLocation". If the application does not declare
1793      * android:usesPermissionFlags="neverForLocation", then it must also have
1794      * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
1795      *
1796      * If targeting an earlier release than {@link android.os.Build.VERSION_CODES#TIRAMISU}, the
1797      * application must have {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
1798      *
1799      * @param channel is the channel created at {@link #initialize}
1800      * @param config options as described in {@link WifiP2pConfig} class
1801      * @param listener for callbacks on success or failure. Can be null.
1802      */
1803     @RequiresPermission(allOf = {
1804             android.Manifest.permission.NEARBY_WIFI_DEVICES,
1805             android.Manifest.permission.ACCESS_FINE_LOCATION
1806             }, conditional = true)
connect(Channel channel, WifiP2pConfig config, ActionListener listener)1807     public void connect(Channel channel, WifiP2pConfig config, ActionListener listener) {
1808         checkChannel(channel);
1809         checkP2pConfig(config);
1810         Bundle extras = prepareExtrasBundle(channel);
1811         extras.putParcelable(EXTRA_PARAM_KEY_CONFIG, config);
1812         channel.mAsyncChannel.sendMessage(prepareMessage(CONNECT, 0, channel.putListener(listener),
1813                 extras, channel.mContext));
1814     }
1815 
1816     /**
1817      * Cancel any ongoing p2p group negotiation
1818      *
1819      * <p> The function call immediately returns after sending a connection cancellation request
1820      * to the framework. The application is notified of a success or failure to initiate
1821      * cancellation through listener callbacks {@link ActionListener#onSuccess} or
1822      * {@link ActionListener#onFailure}.
1823      *
1824      * @param channel is the channel created at {@link #initialize}
1825      * @param listener for callbacks on success or failure. Can be null.
1826      */
cancelConnect(Channel channel, ActionListener listener)1827     public void cancelConnect(Channel channel, ActionListener listener) {
1828         checkChannel(channel);
1829         channel.mAsyncChannel.sendMessage(CANCEL_CONNECT, 0, channel.putListener(listener));
1830     }
1831 
1832     /**
1833      * Create a p2p group with the current device as the group owner. This essentially creates
1834      * an access point that can accept connections from legacy clients as well as other p2p
1835      * devices.
1836      *
1837      * <p class="note"><strong>Note:</strong>
1838      * This function would normally not be used unless the current device needs
1839      * to form a p2p connection with a legacy client
1840      *
1841      * <p> The function call immediately returns after sending a group creation request
1842      * to the framework. The application is notified of a success or failure to initiate
1843      * group creation through listener callbacks {@link ActionListener#onSuccess} or
1844      * {@link ActionListener#onFailure}.
1845      *
1846      * <p> Application can request for the group details with {@link #requestGroupInfo}.
1847      * <p>
1848      * If targeting {@link android.os.Build.VERSION_CODES#TIRAMISU} or later, the application must
1849      * have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
1850      * android:usesPermissionFlags="neverForLocation". If the application does not declare
1851      * android:usesPermissionFlags="neverForLocation", then it must also have
1852      * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
1853      *
1854      * If targeting an earlier release than {@link android.os.Build.VERSION_CODES#TIRAMISU}, the
1855      * application must have {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
1856      *
1857      * @param channel is the channel created at {@link #initialize}
1858      * @param listener for callbacks on success or failure. Can be null.
1859      */
1860     @RequiresPermission(allOf = {
1861             android.Manifest.permission.NEARBY_WIFI_DEVICES,
1862             android.Manifest.permission.ACCESS_FINE_LOCATION
1863             }, conditional = true)
createGroup(Channel channel, ActionListener listener)1864     public void createGroup(Channel channel, ActionListener listener) {
1865         checkChannel(channel);
1866         Bundle extras = prepareExtrasBundle(channel);
1867         channel.mAsyncChannel.sendMessage(prepareMessage(CREATE_GROUP,
1868                 WifiP2pGroup.NETWORK_ID_PERSISTENT, channel.putListener(listener), extras,
1869                 channel.mContext));
1870     }
1871 
1872     /**
1873      * Create a p2p group with the current device as the group owner. This essentially creates
1874      * an access point that can accept connections from legacy clients as well as other p2p
1875      * devices.
1876      *
1877      * <p> An app should use {@link WifiP2pConfig.Builder} to build the configuration
1878      * for a group.
1879      *
1880      * <p class="note"><strong>Note:</strong>
1881      * This function would normally not be used unless the current device needs
1882      * to form a p2p group as a Group Owner and allow peers to join it as either
1883      * Group Clients or legacy Wi-Fi STAs.
1884      *
1885      * <p> The function call immediately returns after sending a group creation request
1886      * to the framework. The application is notified of a success or failure to initiate
1887      * group creation through listener callbacks {@link ActionListener#onSuccess} or
1888      * {@link ActionListener#onFailure}.
1889      *
1890      * <p> Application can request for the group details with {@link #requestGroupInfo}.
1891      * <p>
1892      * If targeting {@link android.os.Build.VERSION_CODES#TIRAMISU} or later, the application must
1893      * have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
1894      * android:usesPermissionFlags="neverForLocation". If the application does not declare
1895      * android:usesPermissionFlags="neverForLocation", then it must also have
1896      * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
1897      *
1898      * If targeting an earlier release than {@link android.os.Build.VERSION_CODES#TIRAMISU}, the
1899      * application must have {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
1900      *
1901      * @param channel is the channel created at {@link #initialize}.
1902      * @param config the configuration of a p2p group.
1903      * @param listener for callbacks on success or failure. Can be null.
1904      */
1905     @RequiresPermission(allOf = {
1906             android.Manifest.permission.NEARBY_WIFI_DEVICES,
1907             android.Manifest.permission.ACCESS_FINE_LOCATION
1908             }, conditional = true)
createGroup(@onNull Channel channel, @Nullable WifiP2pConfig config, @Nullable ActionListener listener)1909     public void createGroup(@NonNull Channel channel,
1910             @Nullable WifiP2pConfig config,
1911             @Nullable ActionListener listener) {
1912         checkChannel(channel);
1913         Bundle extras = prepareExtrasBundle(channel);
1914         extras.putParcelable(EXTRA_PARAM_KEY_CONFIG, config);
1915         channel.mAsyncChannel.sendMessage(prepareMessage(CREATE_GROUP, 0,
1916                 channel.putListener(listener), extras, channel.mContext));
1917     }
1918 
1919     /**
1920      * Remove the current p2p group.
1921      *
1922      * <p> The function call immediately returns after sending a group removal request
1923      * to the framework. The application is notified of a success or failure to initiate
1924      * group removal through listener callbacks {@link ActionListener#onSuccess} or
1925      * {@link ActionListener#onFailure}.
1926      *
1927      * @param channel is the channel created at {@link #initialize}
1928      * @param listener for callbacks on success or failure. Can be null.
1929      */
removeGroup(Channel channel, ActionListener listener)1930     public void removeGroup(Channel channel, ActionListener listener) {
1931         checkChannel(channel);
1932         channel.mAsyncChannel.sendMessage(REMOVE_GROUP, 0, channel.putListener(listener));
1933     }
1934 
1935     /**
1936      * Force p2p to enter listen state.
1937      *
1938      * When this API is called, this device will periodically enter LISTENING state until
1939      * {@link #stopListening(Channel, ActionListener)} or
1940      * {@link #stopPeerDiscovery(Channel, ActionListener)} are called.
1941      * While in LISTENING state, this device will dwell at its social channel and respond
1942      * to probe requests from other Wi-Fi Direct peers.
1943      * <p>
1944      * If targeting {@link android.os.Build.VERSION_CODES#TIRAMISU} or later, the application must
1945      * have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
1946      * android:usesPermissionFlags="neverForLocation". If the application does not declare
1947      * android:usesPermissionFlags="neverForLocation", then it must also have
1948      * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
1949      *
1950      * If targeting an earlier release than {@link android.os.Build.VERSION_CODES#TIRAMISU}, the
1951      * application must have {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
1952      * @param channel is the channel created at
1953      *    {@link #initialize(Context, Looper, ChannelListener)}
1954      * @param listener for callbacks on success or failure.
1955      */
1956     @RequiresPermission(allOf = {
1957             android.Manifest.permission.NEARBY_WIFI_DEVICES,
1958             android.Manifest.permission.ACCESS_FINE_LOCATION
1959             }, conditional = true)
startListening(@onNull Channel channel, @Nullable ActionListener listener)1960     public void startListening(@NonNull Channel channel, @Nullable ActionListener listener) {
1961         checkChannel(channel);
1962         Bundle extras = prepareExtrasBundle(channel);
1963         channel.mAsyncChannel.sendMessage(prepareMessage(START_LISTEN, 0,
1964                 channel.putListener(listener), extras, channel.mContext));
1965     }
1966 
1967     /**
1968      * Force p2p to exit listen state.
1969      *
1970      * When this API is called, this device will stop entering LISTENING state periodically
1971      * which is triggered by {@link #startListening(Channel, ActionListener)}.
1972      * If there are running peer discovery which is triggered by
1973      * {@link #discoverPeers(Channel, ActionListener)} or running service discovery which is
1974      * triggered by {@link #discoverServices(Channel, ActionListener)}, they will be stopped
1975      * as well.
1976      *
1977      * @param channel is the channel created at
1978      *    {@link #initialize(Context, Looper, ChannelListener)}
1979      * @param listener for callbacks on success or failure.
1980      */
stopListening(@onNull Channel channel, @Nullable ActionListener listener)1981     public void stopListening(@NonNull Channel channel, @Nullable ActionListener listener) {
1982         checkChannel(channel);
1983         channel.mAsyncChannel.sendMessage(STOP_LISTEN, 0, channel.putListener(listener));
1984     }
1985 
1986     /**
1987      * Set P2P listening and operating channel.
1988      *
1989      * @param channel is the channel created at {@link #initialize}
1990      * @param listeningChannel the listening channel's Wifi channel number. e.g. 1, 6, 11.
1991      * @param operatingChannel the operating channel's Wifi channel number. e.g. 1, 6, 11.
1992      * @param listener for callbacks on success or failure. Can be null.
1993      *
1994      * @hide
1995      */
1996     @SystemApi
1997     @RequiresPermission(anyOf = {
1998             android.Manifest.permission.NETWORK_SETTINGS,
1999             android.Manifest.permission.NETWORK_STACK,
2000             android.Manifest.permission.OVERRIDE_WIFI_CONFIG
2001     })
setWifiP2pChannels(@onNull Channel channel, int listeningChannel, int operatingChannel, @Nullable ActionListener listener)2002     public void setWifiP2pChannels(@NonNull Channel channel, int listeningChannel,
2003             int operatingChannel, @Nullable ActionListener listener) {
2004         checkChannel(channel);
2005         Bundle p2pChannels = new Bundle();
2006         p2pChannels.putInt("lc", listeningChannel);
2007         p2pChannels.putInt("oc", operatingChannel);
2008         channel.mAsyncChannel.sendMessage(
2009                 SET_CHANNEL, 0, channel.putListener(listener), p2pChannels);
2010     }
2011 
2012     /**
2013      * Start a Wi-Fi Protected Setup (WPS) session.
2014      *
2015      * <p> The function call immediately returns after sending a request to start a
2016      * WPS session. Currently, this is only valid if the current device is running
2017      * as a group owner to allow any new clients to join the group. The application
2018      * is notified of a success or failure to initiate WPS through listener callbacks
2019      * {@link ActionListener#onSuccess} or {@link ActionListener#onFailure}.
2020      * @hide
2021      */
2022     @UnsupportedAppUsage(trackingBug = 185141982)
startWps(Channel channel, WpsInfo wps, ActionListener listener)2023     public void startWps(Channel channel, WpsInfo wps, ActionListener listener) {
2024         checkChannel(channel);
2025         channel.mAsyncChannel.sendMessage(START_WPS, 0, channel.putListener(listener), wps);
2026     }
2027 
2028     /**
2029      * Register a local service for service discovery. If a local service is registered,
2030      * the framework automatically responds to a service discovery request from a peer.
2031      *
2032      * <p> The function call immediately returns after sending a request to add a local
2033      * service to the framework. The application is notified of a success or failure to
2034      * add service through listener callbacks {@link ActionListener#onSuccess} or
2035      * {@link ActionListener#onFailure}.
2036      *
2037      * <p>The service information is set through {@link WifiP2pServiceInfo}.<br>
2038      * or its subclass calls  {@link WifiP2pUpnpServiceInfo#newInstance} or
2039      *  {@link WifiP2pDnsSdServiceInfo#newInstance} for a Upnp or Bonjour service
2040      * respectively
2041      *
2042      * <p>The service information can be cleared with calls to
2043      *  {@link #removeLocalService} or {@link #clearLocalServices}.
2044      * <p>
2045      * If targeting {@link android.os.Build.VERSION_CODES#TIRAMISU} or later, the application must
2046      * have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
2047      * android:usesPermissionFlags="neverForLocation". If the application does not declare
2048      * android:usesPermissionFlags="neverForLocation", then it must also have
2049      * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
2050      *
2051      * If targeting an earlier release than {@link android.os.Build.VERSION_CODES#TIRAMISU}, the
2052      * application must have {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
2053      *
2054      * @param channel is the channel created at {@link #initialize}
2055      * @param servInfo is a local service information.
2056      * @param listener for callbacks on success or failure. Can be null.
2057      */
2058     @RequiresPermission(allOf = {
2059             android.Manifest.permission.NEARBY_WIFI_DEVICES,
2060             android.Manifest.permission.ACCESS_FINE_LOCATION
2061             }, conditional = true)
addLocalService(Channel channel, WifiP2pServiceInfo servInfo, ActionListener listener)2062     public void addLocalService(Channel channel, WifiP2pServiceInfo servInfo,
2063             ActionListener listener) {
2064         checkChannel(channel);
2065         checkServiceInfo(servInfo);
2066         Bundle extras = prepareExtrasBundle(channel);
2067         extras.putParcelable(EXTRA_PARAM_KEY_SERVICE_INFO, servInfo);
2068         channel.mAsyncChannel.sendMessage(prepareMessage(ADD_LOCAL_SERVICE, 0,
2069                 channel.putListener(listener), extras, channel.mContext));
2070     }
2071 
2072     /**
2073      * Remove a registered local service added with {@link #addLocalService}
2074      *
2075      * <p> The function call immediately returns after sending a request to remove a
2076      * local service to the framework. The application is notified of a success or failure to
2077      * add service through listener callbacks {@link ActionListener#onSuccess} or
2078      * {@link ActionListener#onFailure}.
2079      *
2080      * @param channel is the channel created at {@link #initialize}
2081      * @param servInfo is the local service information.
2082      * @param listener for callbacks on success or failure. Can be null.
2083      */
removeLocalService(Channel channel, WifiP2pServiceInfo servInfo, ActionListener listener)2084     public void removeLocalService(Channel channel, WifiP2pServiceInfo servInfo,
2085             ActionListener listener) {
2086         checkChannel(channel);
2087         checkServiceInfo(servInfo);
2088         channel.mAsyncChannel.sendMessage(
2089                 REMOVE_LOCAL_SERVICE, 0, channel.putListener(listener), servInfo);
2090     }
2091 
2092     /**
2093      * Clear all registered local services of service discovery.
2094      *
2095      * <p> The function call immediately returns after sending a request to clear all
2096      * local services to the framework. The application is notified of a success or failure to
2097      * add service through listener callbacks {@link ActionListener#onSuccess} or
2098      * {@link ActionListener#onFailure}.
2099      *
2100      * @param channel is the channel created at {@link #initialize}
2101      * @param listener for callbacks on success or failure. Can be null.
2102      */
clearLocalServices(Channel channel, ActionListener listener)2103     public void clearLocalServices(Channel channel, ActionListener listener) {
2104         checkChannel(channel);
2105         channel.mAsyncChannel.sendMessage(CLEAR_LOCAL_SERVICES, 0, channel.putListener(listener));
2106     }
2107 
2108     /**
2109      * Register a callback to be invoked on receiving service discovery response.
2110      * Used only for vendor specific protocol right now. For Bonjour or Upnp, use
2111      * {@link #setDnsSdResponseListeners} or {@link #setUpnpServiceResponseListener}
2112      * respectively.
2113      *
2114      * <p> see {@link #discoverServices} for the detail.
2115      *
2116      * @param channel is the channel created at {@link #initialize}
2117      * @param listener for callbacks on receiving service discovery response.
2118      */
setServiceResponseListener(Channel channel, ServiceResponseListener listener)2119     public void setServiceResponseListener(Channel channel,
2120             ServiceResponseListener listener) {
2121         checkChannel(channel);
2122         channel.mServRspListener = listener;
2123     }
2124 
2125     /**
2126      * Register a callback to be invoked on receiving Bonjour service discovery
2127      * response.
2128      *
2129      * <p> see {@link #discoverServices} for the detail.
2130      *
2131      * @param channel
2132      * @param servListener is for listening to a Bonjour service response
2133      * @param txtListener is for listening to a Bonjour TXT record response
2134      */
setDnsSdResponseListeners(Channel channel, DnsSdServiceResponseListener servListener, DnsSdTxtRecordListener txtListener)2135     public void setDnsSdResponseListeners(Channel channel,
2136             DnsSdServiceResponseListener servListener, DnsSdTxtRecordListener txtListener) {
2137         checkChannel(channel);
2138         channel.mDnsSdServRspListener = servListener;
2139         channel.mDnsSdTxtListener = txtListener;
2140     }
2141 
2142     /**
2143      * Register a callback to be invoked on receiving upnp service discovery
2144      * response.
2145      *
2146      * <p> see {@link #discoverServices} for the detail.
2147      *
2148      * @param channel is the channel created at {@link #initialize}
2149      * @param listener for callbacks on receiving service discovery response.
2150      */
setUpnpServiceResponseListener(Channel channel, UpnpServiceResponseListener listener)2151     public void setUpnpServiceResponseListener(Channel channel,
2152             UpnpServiceResponseListener listener) {
2153         checkChannel(channel);
2154         channel.mUpnpServRspListener = listener;
2155     }
2156 
2157     /**
2158      * Initiate service discovery. A discovery process involves scanning for
2159      * requested services for the purpose of establishing a connection to a peer
2160      * that supports an available service.
2161      *
2162      * <p> The function call immediately returns after sending a request to start service
2163      * discovery to the framework. The application is notified of a success or failure to initiate
2164      * discovery through listener callbacks {@link ActionListener#onSuccess} or
2165      * {@link ActionListener#onFailure}.
2166      *
2167      * <p> The services to be discovered are specified with calls to {@link #addServiceRequest}.
2168      *
2169      * <p>The application is notified of the response against the service discovery request
2170      * through listener callbacks registered by {@link #setServiceResponseListener} or
2171      * {@link #setDnsSdResponseListeners}, or {@link #setUpnpServiceResponseListener}.
2172      * <p>
2173      * If targeting {@link android.os.Build.VERSION_CODES#TIRAMISU} or later, the application must
2174      * have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
2175      * android:usesPermissionFlags="neverForLocation". If the application does not declare
2176      * android:usesPermissionFlags="neverForLocation", then it must also have
2177      * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
2178      *
2179      * If targeting an earlier release than {@link android.os.Build.VERSION_CODES#TIRAMISU}, the
2180      * application must have {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
2181      *
2182      * @param channel is the channel created at {@link #initialize}
2183      * @param listener for callbacks on success or failure. Can be null.
2184      */
2185     @RequiresPermission(allOf = {
2186             android.Manifest.permission.NEARBY_WIFI_DEVICES,
2187             android.Manifest.permission.ACCESS_FINE_LOCATION
2188             }, conditional = true)
discoverServices(Channel channel, ActionListener listener)2189     public void discoverServices(Channel channel, ActionListener listener) {
2190         checkChannel(channel);
2191         Bundle extras = prepareExtrasBundle(channel);
2192         channel.mAsyncChannel.sendMessage(prepareMessage(DISCOVER_SERVICES, 0,
2193                 channel.putListener(listener), extras, channel.mContext));
2194     }
2195 
2196     /**
2197      * Add a service discovery request.
2198      *
2199      * <p> The function call immediately returns after sending a request to add service
2200      * discovery request to the framework. The application is notified of a success or failure to
2201      * add service through listener callbacks {@link ActionListener#onSuccess} or
2202      * {@link ActionListener#onFailure}.
2203      *
2204      * <p>After service discovery request is added, you can initiate service discovery by
2205      * {@link #discoverServices}.
2206      *
2207      * <p>The added service requests can be cleared with calls to
2208      * {@link #removeServiceRequest(Channel, WifiP2pServiceRequest, ActionListener)} or
2209      * {@link #clearServiceRequests(Channel, ActionListener)}.
2210      *
2211      * @param channel is the channel created at {@link #initialize}
2212      * @param req is the service discovery request.
2213      * @param listener for callbacks on success or failure. Can be null.
2214      */
addServiceRequest(Channel channel, WifiP2pServiceRequest req, ActionListener listener)2215     public void addServiceRequest(Channel channel,
2216             WifiP2pServiceRequest req, ActionListener listener) {
2217         checkChannel(channel);
2218         checkServiceRequest(req);
2219         channel.mAsyncChannel.sendMessage(ADD_SERVICE_REQUEST, 0,
2220                 channel.putListener(listener), req);
2221     }
2222 
2223     /**
2224      * Remove a specified service discovery request added with {@link #addServiceRequest}
2225      *
2226      * <p> The function call immediately returns after sending a request to remove service
2227      * discovery request to the framework. The application is notified of a success or failure to
2228      * add service through listener callbacks {@link ActionListener#onSuccess} or
2229      * {@link ActionListener#onFailure}.
2230      *
2231      * @param channel is the channel created at {@link #initialize}
2232      * @param req is the service discovery request.
2233      * @param listener for callbacks on success or failure. Can be null.
2234      */
removeServiceRequest(Channel channel, WifiP2pServiceRequest req, ActionListener listener)2235     public void removeServiceRequest(Channel channel, WifiP2pServiceRequest req,
2236             ActionListener listener) {
2237         checkChannel(channel);
2238         checkServiceRequest(req);
2239         channel.mAsyncChannel.sendMessage(REMOVE_SERVICE_REQUEST, 0,
2240                 channel.putListener(listener), req);
2241     }
2242 
2243     /**
2244      * Clear all registered service discovery requests.
2245      *
2246      * <p> The function call immediately returns after sending a request to clear all
2247      * service discovery requests to the framework. The application is notified of a success
2248      * or failure to add service through listener callbacks {@link ActionListener#onSuccess} or
2249      * {@link ActionListener#onFailure}.
2250      *
2251      * @param channel is the channel created at {@link #initialize}
2252      * @param listener for callbacks on success or failure. Can be null.
2253      */
clearServiceRequests(Channel channel, ActionListener listener)2254     public void clearServiceRequests(Channel channel, ActionListener listener) {
2255         checkChannel(channel);
2256         channel.mAsyncChannel.sendMessage(CLEAR_SERVICE_REQUESTS,
2257                 0, channel.putListener(listener));
2258     }
2259 
2260     /**
2261      * Request the current list of peers.
2262      * <p>
2263      * If targeting {@link android.os.Build.VERSION_CODES#TIRAMISU} or later, the application must
2264      * have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
2265      * android:usesPermissionFlags="neverForLocation". If the application does not declare
2266      * android:usesPermissionFlags="neverForLocation", then it must also have
2267      * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
2268      *
2269      * If targeting an earlier release than {@link android.os.Build.VERSION_CODES#TIRAMISU}, the
2270      * application must have {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
2271      *
2272      * @param channel is the channel created at {@link #initialize}
2273      * @param listener for callback when peer list is available. Can be null.
2274      */
2275     @RequiresPermission(allOf = {
2276             android.Manifest.permission.NEARBY_WIFI_DEVICES,
2277             android.Manifest.permission.ACCESS_FINE_LOCATION
2278             }, conditional = true)
requestPeers(Channel channel, PeerListListener listener)2279     public void requestPeers(Channel channel, PeerListListener listener) {
2280         checkChannel(channel);
2281         Bundle extras = prepareExtrasBundle(channel);
2282         channel.mAsyncChannel.sendMessage(prepareMessage(REQUEST_PEERS, 0,
2283                 channel.putListener(listener), extras, channel.mContext));
2284     }
2285 
2286     /**
2287      * Request device connection info.
2288      *
2289      * @param channel is the channel created at {@link #initialize}
2290      * @param listener for callback when connection info is available. Can be null.
2291      */
requestConnectionInfo(Channel channel, ConnectionInfoListener listener)2292     public void requestConnectionInfo(Channel channel, ConnectionInfoListener listener) {
2293         checkChannel(channel);
2294         channel.mAsyncChannel.sendMessage(
2295                 REQUEST_CONNECTION_INFO, 0, channel.putListener(listener));
2296     }
2297 
2298     /**
2299      * Request p2p group info.
2300      * <p>
2301      * If targeting {@link android.os.Build.VERSION_CODES#TIRAMISU} or later, the application must
2302      * have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
2303      * android:usesPermissionFlags="neverForLocation". If the application does not declare
2304      * android:usesPermissionFlags="neverForLocation", then it must also have
2305      * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
2306      *
2307      * If targeting an earlier release than {@link android.os.Build.VERSION_CODES#TIRAMISU}, the
2308      * application must have {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
2309      *
2310      * @param channel is the channel created at {@link #initialize}
2311      * @param listener for callback when group info is available. Can be null.
2312      */
2313     @RequiresPermission(allOf = {
2314             android.Manifest.permission.NEARBY_WIFI_DEVICES,
2315             android.Manifest.permission.ACCESS_FINE_LOCATION
2316             }, conditional = true)
requestGroupInfo(Channel channel, GroupInfoListener listener)2317     public void requestGroupInfo(Channel channel, GroupInfoListener listener) {
2318         checkChannel(channel);
2319         Bundle extras = prepareExtrasBundle(channel);
2320         channel.mAsyncChannel.sendMessage(prepareMessage(REQUEST_GROUP_INFO, 0,
2321                 channel.putListener(listener), extras, channel.mContext));
2322     }
2323 
2324     /**
2325      * Set p2p device name.
2326      *
2327      * @param channel is the channel created at {@link #initialize}
2328      * @param listener for callback when group info is available. Can be null.
2329      *
2330      * @hide
2331      */
2332     @SystemApi
2333     @RequiresPermission(anyOf = {
2334             android.Manifest.permission.NETWORK_SETTINGS,
2335             android.Manifest.permission.NETWORK_STACK,
2336             android.Manifest.permission.OVERRIDE_WIFI_CONFIG
2337     })
setDeviceName(@onNull Channel channel, @NonNull String devName, @Nullable ActionListener listener)2338     public void setDeviceName(@NonNull Channel channel, @NonNull String devName,
2339             @Nullable ActionListener listener) {
2340         checkChannel(channel);
2341         WifiP2pDevice d = new WifiP2pDevice();
2342         d.deviceName = devName;
2343         channel.mAsyncChannel.sendMessage(SET_DEVICE_NAME, 0, channel.putListener(listener), d);
2344     }
2345 
2346     /**
2347      * Set Wifi Display information.
2348      *
2349      * @param channel is the channel created at {@link #initialize}
2350      * @param wfdInfo the Wifi Display information to set
2351      * @param listener for callbacks on success or failure. Can be null.
2352      *
2353      * @hide
2354      */
2355     @SystemApi
2356     @RequiresPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
setWfdInfo(@onNull Channel channel, @NonNull WifiP2pWfdInfo wfdInfo, @Nullable ActionListener listener)2357     public void setWfdInfo(@NonNull Channel channel, @NonNull WifiP2pWfdInfo wfdInfo,
2358             @Nullable ActionListener listener) {
2359         setWFDInfo(channel, wfdInfo, listener);
2360     }
2361 
2362     /** @hide */
2363     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
2364     @RequiresPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
setWFDInfo(@onNull Channel channel, @NonNull WifiP2pWfdInfo wfdInfo, @Nullable ActionListener listener)2365     public void setWFDInfo(@NonNull Channel channel, @NonNull WifiP2pWfdInfo wfdInfo,
2366             @Nullable ActionListener listener) {
2367         checkChannel(channel);
2368         try {
2369             mService.checkConfigureWifiDisplayPermission();
2370         } catch (RemoteException e) {
2371             e.rethrowFromSystemServer();
2372         }
2373         channel.mAsyncChannel.sendMessage(SET_WFD_INFO, 0, channel.putListener(listener), wfdInfo);
2374     }
2375 
2376     /**
2377      * Remove the client with the MAC address from the group.
2378      *
2379      * <p> The function call immediately returns after sending a client removal request
2380      * to the framework. The application is notified of a success or failure to initiate
2381      * client removal through listener callbacks {@link ActionListener#onSuccess} or
2382      * {@link ActionListener#onFailure}.
2383      *
2384      * <p> The callbacks are triggered on the thread specified when initializing the
2385      * {@code channel}, see {@link #initialize}.
2386      * <p>
2387      * Use {@link #isGroupClientRemovalSupported()} to determine whether the device supports
2388      * this feature. If {@link #isGroupClientRemovalSupported()} return {@code false} then this
2389      * method will throw {@link UnsupportedOperationException}.
2390      *
2391      * @param channel is the channel created at {@link #initialize}
2392      * @param peerAddress MAC address of the client.
2393      * @param listener for callbacks on success or failure. Can be null.
2394      */
2395     @RequiresApi(Build.VERSION_CODES.TIRAMISU)
removeClient(@onNull Channel channel, @NonNull MacAddress peerAddress, @Nullable ActionListener listener)2396     public void removeClient(@NonNull Channel channel, @NonNull MacAddress peerAddress,
2397             @Nullable ActionListener listener) {
2398         if (!isGroupClientRemovalSupported()) {
2399             throw new UnsupportedOperationException();
2400         }
2401         checkChannel(channel);
2402         channel.mAsyncChannel.sendMessage(
2403                 REMOVE_CLIENT, 0, channel.putListener(listener), peerAddress);
2404     }
2405 
2406 
2407     /**
2408      * Delete a stored persistent group from the system settings.
2409      *
2410      * <p> The function call immediately returns after sending a persistent group removal request
2411      * to the framework. The application is notified of a success or failure to initiate
2412      * group removal through listener callbacks {@link ActionListener#onSuccess} or
2413      * {@link ActionListener#onFailure}.
2414      *
2415      * <p>The persistent p2p group list stored in the system can be obtained by
2416      * {@link #requestPersistentGroupInfo(Channel, PersistentGroupInfoListener)} and
2417      *  a network id can be obtained by {@link WifiP2pGroup#getNetworkId()}.
2418      *
2419      * @param channel is the channel created at {@link #initialize}
2420      * @param netId the network id of the p2p group.
2421      * @param listener for callbacks on success or failure. Can be null.
2422      *
2423      * @hide
2424      */
2425     @SystemApi
2426     @RequiresPermission(anyOf = {
2427             android.Manifest.permission.NETWORK_SETTINGS,
2428             android.Manifest.permission.NETWORK_STACK,
2429             android.Manifest.permission.OVERRIDE_WIFI_CONFIG
2430     })
deletePersistentGroup(@onNull Channel channel, int netId, @Nullable ActionListener listener)2431     public void deletePersistentGroup(@NonNull Channel channel, int netId,
2432             @Nullable ActionListener listener) {
2433         checkChannel(channel);
2434         channel.mAsyncChannel.sendMessage(
2435                 DELETE_PERSISTENT_GROUP, netId, channel.putListener(listener));
2436     }
2437 
2438     /**
2439      * Request a list of all the persistent p2p groups stored in system.
2440      *
2441      * <p>The caller must have one of {@link android.Manifest.permission.NETWORK_SETTINGS},
2442      * {@link android.Manifest.permission.NETWORK_STACK}, and
2443      * {@link android.Manifest.permission.READ_WIFI_CREDENTIAL}.
2444      *
2445      * <p>If targeting {@link android.os.Build.VERSION_CODES#TIRAMISU} or later,
2446      * the application must have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
2447      * android:usesPermissionFlags="neverForLocation". If the application does not declare
2448      * android:usesPermissionFlags="neverForLocation", then it must also have
2449      * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
2450      *
2451      * @param channel is the channel created at {@link #initialize}
2452      * @param listener for callback when persistent group info list is available. Can be null.
2453      *
2454      * @hide
2455      */
2456     @SystemApi
2457     @RequiresPermission(allOf = {
2458             android.Manifest.permission.NETWORK_SETTINGS,
2459             android.Manifest.permission.NETWORK_STACK,
2460             android.Manifest.permission.READ_WIFI_CREDENTIAL,
2461             android.Manifest.permission.NEARBY_WIFI_DEVICES,
2462             android.Manifest.permission.ACCESS_FINE_LOCATION}, conditional = true)
requestPersistentGroupInfo(@onNull Channel channel, @Nullable PersistentGroupInfoListener listener)2463     public void requestPersistentGroupInfo(@NonNull Channel channel,
2464             @Nullable PersistentGroupInfoListener listener) {
2465         checkChannel(channel);
2466         Bundle extras = prepareExtrasBundle(channel);
2467         channel.mAsyncChannel.sendMessage(prepareMessage(REQUEST_PERSISTENT_GROUP_INFO, 0,
2468                 channel.putListener(listener), extras, channel.mContext));
2469     }
2470 
2471     /** @hide */
2472     @Retention(RetentionPolicy.SOURCE)
2473     @IntDef(prefix = {"MIRACAST_"}, value = {
2474             MIRACAST_DISABLED,
2475             MIRACAST_SOURCE,
2476             MIRACAST_SINK})
2477     public @interface MiracastMode {}
2478 
2479     /**
2480      * Miracast is disabled.
2481      * @hide
2482      */
2483     @SystemApi
2484     public static final int MIRACAST_DISABLED = 0;
2485     /**
2486      * Device acts as a Miracast source.
2487      * @hide
2488      */
2489     @SystemApi
2490     public static final int MIRACAST_SOURCE   = 1;
2491     /**
2492      * Device acts as a Miracast sink.
2493      * @hide
2494      */
2495     @SystemApi
2496     public static final int MIRACAST_SINK     = 2;
2497 
2498     /**
2499      * Accept the incoming request.
2500      *
2501      * Used in {@link #setConnectionRequestResult(Channel, MacAddress, int, ActionListener)}.
2502      */
2503     public static final int CONNECTION_REQUEST_ACCEPT = 0;
2504     /**
2505      * Reject the incoming request.
2506      *
2507      * Used in {@link #setConnectionRequestResult(Channel, MacAddress, int, ActionListener)}.
2508      */
2509     public static final int CONNECTION_REQUEST_REJECT = 1;
2510     /**
2511      * Defer the decision back to the Wi-Fi service (which will display a dialog to the user).
2512      *
2513      * Used in {@link #setConnectionRequestResult(Channel, MacAddress, int, ActionListener)}.
2514      */
2515     public static final int CONNECTION_REQUEST_DEFER_TO_SERVICE = 2;
2516     /**
2517      * Defer the PIN display to the Wi-Fi service (which will display a dialog to the user).
2518      *
2519      * Used in {@link #setConnectionRequestResult(Channel, MacAddress, int, ActionListener)}.
2520      */
2521     public static final int CONNECTION_REQUEST_DEFER_SHOW_PIN_TO_SERVICE = 3;
2522     /** @hide */
2523     @IntDef(prefix = {"CONNECTION_REQUEST_"}, value = {
2524         CONNECTION_REQUEST_ACCEPT,
2525         CONNECTION_REQUEST_REJECT,
2526         CONNECTION_REQUEST_DEFER_TO_SERVICE,
2527         CONNECTION_REQUEST_DEFER_SHOW_PIN_TO_SERVICE})
2528     @Retention(RetentionPolicy.SOURCE)
2529     public @interface ConnectionRequestResponse {
2530     }
2531 
2532     /**
2533      * This is used to provide information to drivers to optimize performance depending
2534      * on the current mode of operation.
2535      * {@link #MIRACAST_DISABLED} - disabled
2536      * {@link #MIRACAST_SOURCE} - source operation
2537      * {@link #MIRACAST_SINK} - sink operation
2538      *
2539      * As an example, the driver could reduce the channel dwell time during scanning
2540      * when acting as a source or sink to minimize impact on Miracast.
2541      *
2542      * @param mode mode of operation. One of {@link #MIRACAST_DISABLED}, {@link #MIRACAST_SOURCE},
2543      * or {@link #MIRACAST_SINK}
2544      *
2545      * @hide
2546      */
2547     @SystemApi
2548     @RequiresPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
setMiracastMode(@iracastMode int mode)2549     public void setMiracastMode(@MiracastMode int mode) {
2550         try {
2551             mService.setMiracastMode(mode);
2552         } catch (RemoteException e) {
2553             throw e.rethrowFromSystemServer();
2554         }
2555     }
2556 
getMessenger(@onNull Binder binder, @Nullable String packageName, @NonNull Bundle extras)2557     private Messenger getMessenger(@NonNull Binder binder, @Nullable String packageName,
2558             @NonNull Bundle extras) {
2559         try {
2560             return mService.getMessenger(binder, packageName, extras);
2561         } catch (RemoteException e) {
2562             throw e.rethrowFromSystemServer();
2563         }
2564     }
2565 
2566     /**
2567      * Get a reference to P2pStateMachine handler. This is used to establish
2568      * a priveleged AsyncChannel communication with WifiP2pService.
2569      *
2570      * @return Messenger pointing to the WifiP2pService handler
2571      * @hide
2572      */
getP2pStateMachineMessenger()2573     public Messenger getP2pStateMachineMessenger() {
2574         try {
2575             return mService.getP2pStateMachineMessenger();
2576         } catch (RemoteException e) {
2577             throw e.rethrowFromSystemServer();
2578         }
2579     }
2580 
getSupportedFeatures()2581     private long getSupportedFeatures() {
2582         try {
2583             return mService.getSupportedFeatures();
2584         } catch (RemoteException e) {
2585             throw e.rethrowFromSystemServer();
2586         }
2587     }
2588 
isFeatureSupported(long feature)2589     private boolean isFeatureSupported(long feature) {
2590         return (getSupportedFeatures() & feature) == feature;
2591     }
2592 
2593     /**
2594      * Check if this device supports setting vendor elements.
2595      *
2596      * Gates whether the
2597      * {@link #setVendorElements(Channel, List, ActionListener)}
2598      * method is functional on this device.
2599      *
2600      * @return {@code true} if supported, {@code false} otherwise.
2601      */
isSetVendorElementsSupported()2602     public boolean isSetVendorElementsSupported() {
2603         return isFeatureSupported(FEATURE_SET_VENDOR_ELEMENTS);
2604     }
2605 
2606     /**
2607      * Check if this device supports discovery limited to a specific frequency or
2608      * the social channels.
2609      *
2610      * Gates whether
2611      * {@link #discoverPeersOnSpecificFrequency(Channel, int, ActionListener)} and
2612      * {@link #discoverPeersOnSocialChannels(Channel, ActionListener)}
2613      * methods are functional on this device.
2614      *
2615      * @return {@code true} if supported, {@code false} otherwise.
2616      */
isChannelConstrainedDiscoverySupported()2617     public boolean isChannelConstrainedDiscoverySupported() {
2618         return isFeatureSupported(FEATURE_FLEXIBLE_DISCOVERY);
2619     }
2620 
2621     /**
2622      * Check if this device supports removing clients from a group.
2623      *
2624      * Gates whether the
2625      * {@link #removeClient(Channel, MacAddress, ActionListener)}
2626      * method is functional on this device.
2627      * @return {@code true} if supported, {@code false} otherwise.
2628      */
isGroupClientRemovalSupported()2629     public boolean isGroupClientRemovalSupported() {
2630         return isFeatureSupported(FEATURE_GROUP_CLIENT_REMOVAL);
2631     }
2632 
2633 
2634     /**
2635      * Get a handover request message for use in WFA NFC Handover transfer.
2636      * @hide
2637      */
getNfcHandoverRequest(Channel c, HandoverMessageListener listener)2638     public void getNfcHandoverRequest(Channel c, HandoverMessageListener listener) {
2639         checkChannel(c);
2640         c.mAsyncChannel.sendMessage(GET_HANDOVER_REQUEST, 0, c.putListener(listener));
2641     }
2642 
2643 
2644     /**
2645      * Get a handover select message for use in WFA NFC Handover transfer.
2646      * @hide
2647      */
getNfcHandoverSelect(Channel c, HandoverMessageListener listener)2648     public void getNfcHandoverSelect(Channel c, HandoverMessageListener listener) {
2649         checkChannel(c);
2650         c.mAsyncChannel.sendMessage(GET_HANDOVER_SELECT, 0, c.putListener(listener));
2651     }
2652 
2653     /**
2654      * @hide
2655      */
initiatorReportNfcHandover(Channel c, String handoverSelect, ActionListener listener)2656     public void initiatorReportNfcHandover(Channel c, String handoverSelect,
2657                                               ActionListener listener) {
2658         checkChannel(c);
2659         Bundle bundle = new Bundle();
2660         bundle.putString(EXTRA_HANDOVER_MESSAGE, handoverSelect);
2661         c.mAsyncChannel.sendMessage(INITIATOR_REPORT_NFC_HANDOVER, 0,
2662                 c.putListener(listener), bundle);
2663     }
2664 
2665 
2666     /**
2667      * @hide
2668      */
responderReportNfcHandover(Channel c, String handoverRequest, ActionListener listener)2669     public void responderReportNfcHandover(Channel c, String handoverRequest,
2670                                               ActionListener listener) {
2671         checkChannel(c);
2672         Bundle bundle = new Bundle();
2673         bundle.putString(EXTRA_HANDOVER_MESSAGE, handoverRequest);
2674         c.mAsyncChannel.sendMessage(RESPONDER_REPORT_NFC_HANDOVER, 0,
2675                 c.putListener(listener), bundle);
2676     }
2677 
2678     /**
2679      * Removes all saved p2p groups.
2680      *
2681      * @param c is the channel created at {@link #initialize}.
2682      * @param listener for callback on success or failure. Can be null.
2683      *
2684      * @hide
2685      */
2686     @SystemApi
2687     @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
factoryReset(@onNull Channel c, @Nullable ActionListener listener)2688     public void factoryReset(@NonNull Channel c, @Nullable ActionListener listener) {
2689         checkChannel(c);
2690         c.mAsyncChannel.sendMessage(FACTORY_RESET, 0, c.putListener(listener));
2691     }
2692 
2693     /**
2694      * Request saved WifiP2pConfig which used for an ongoing peer connection
2695      *
2696      * @param c is the channel created at {@link #initialize}
2697      * @param listener for callback when ongoing peer config updated. Can't be null.
2698      *
2699      * @hide
2700      */
2701     @RequiresPermission(android.Manifest.permission.NETWORK_STACK)
requestOngoingPeerConfig(@onNull Channel c, @NonNull OngoingPeerInfoListener listener)2702     public void requestOngoingPeerConfig(@NonNull Channel c,
2703             @NonNull OngoingPeerInfoListener listener) {
2704         checkChannel(c);
2705         c.mAsyncChannel.sendMessage(REQUEST_ONGOING_PEER_CONFIG,
2706                 Binder.getCallingUid(), c.putListener(listener));
2707     }
2708 
2709      /**
2710      * Set saved WifiP2pConfig which used for an ongoing peer connection
2711      *
2712      * @param c is the channel created at {@link #initialize}
2713      * @param config used for change an ongoing peer connection
2714      * @param listener for callback when ongoing peer config updated. Can be null.
2715      *
2716      * @hide
2717      */
2718     @RequiresPermission(android.Manifest.permission.NETWORK_STACK)
setOngoingPeerConfig(@onNull Channel c, @NonNull WifiP2pConfig config, @Nullable ActionListener listener)2719     public void setOngoingPeerConfig(@NonNull Channel c, @NonNull WifiP2pConfig config,
2720             @Nullable ActionListener listener) {
2721         checkChannel(c);
2722         checkP2pConfig(config);
2723         c.mAsyncChannel.sendMessage(SET_ONGOING_PEER_CONFIG, 0,
2724                 c.putListener(listener), config);
2725     }
2726 
2727     /**
2728      * Request p2p enabled state.
2729      *
2730      * <p> This state indicates whether Wi-Fi p2p is enabled or disabled.
2731      * The valid value is one of {@link #WIFI_P2P_STATE_DISABLED} or
2732      * {@link #WIFI_P2P_STATE_ENABLED}. The state is returned using the
2733      * {@link P2pStateListener} listener.
2734      *
2735      * <p> This state is also included in the {@link #WIFI_P2P_STATE_CHANGED_ACTION}
2736      * broadcast event with extra {@link #EXTRA_WIFI_STATE}.
2737      *
2738      * @param c is the channel created at {@link #initialize}.
2739      * @param listener for callback when p2p state is available.
2740      */
requestP2pState(@onNull Channel c, @NonNull P2pStateListener listener)2741     public void requestP2pState(@NonNull Channel c,
2742             @NonNull P2pStateListener listener) {
2743         checkChannel(c);
2744         if (listener == null) throw new IllegalArgumentException("This listener cannot be null.");
2745         c.mAsyncChannel.sendMessage(REQUEST_P2P_STATE, 0, c.putListener(listener));
2746     }
2747 
2748     /**
2749      * Request p2p discovery state.
2750      *
2751      * <p> This state indicates whether p2p discovery has started or stopped.
2752      * The valid value is one of {@link #WIFI_P2P_DISCOVERY_STARTED} or
2753      * {@link #WIFI_P2P_DISCOVERY_STOPPED}. The state is returned using the
2754      * {@link DiscoveryStateListener} listener.
2755      *
2756      * <p> This state is also included in the {@link #WIFI_P2P_DISCOVERY_CHANGED_ACTION}
2757      * broadcast event with extra {@link #EXTRA_DISCOVERY_STATE}.
2758      *
2759      * @param c is the channel created at {@link #initialize}.
2760      * @param listener for callback when discovery state is available.
2761      */
requestDiscoveryState(@onNull Channel c, @NonNull DiscoveryStateListener listener)2762     public void requestDiscoveryState(@NonNull Channel c,
2763             @NonNull DiscoveryStateListener listener) {
2764         checkChannel(c);
2765         if (listener == null) throw new IllegalArgumentException("This listener cannot be null.");
2766         c.mAsyncChannel.sendMessage(REQUEST_DISCOVERY_STATE, 0, c.putListener(listener));
2767     }
2768 
2769     /**
2770      * Request network info.
2771      *
2772      * <p> This method provides the network info in the form of a {@link android.net.NetworkInfo}.
2773      * {@link android.net.NetworkInfo#isAvailable()} indicates the p2p availability and
2774      * {@link android.net.NetworkInfo#getDetailedState()} reports the current fine-grained state
2775      * of the network. This {@link android.net.NetworkInfo} is returned using the
2776      * {@link NetworkInfoListener} listener.
2777      *
2778      * <p> This information is also included in the {@link #WIFI_P2P_CONNECTION_CHANGED_ACTION}
2779      * broadcast event with extra {@link #EXTRA_NETWORK_INFO}.
2780      *
2781      * @param c is the channel created at {@link #initialize}.
2782      * @param listener for callback when network info is available.
2783      */
requestNetworkInfo(@onNull Channel c, @NonNull NetworkInfoListener listener)2784     public void requestNetworkInfo(@NonNull Channel c,
2785             @NonNull NetworkInfoListener listener) {
2786         checkChannel(c);
2787         if (listener == null) throw new IllegalArgumentException("This listener cannot be null.");
2788         c.mAsyncChannel.sendMessage(REQUEST_NETWORK_INFO, 0, c.putListener(listener));
2789     }
2790 
2791     /**
2792      * Request Device Info
2793      *
2794      * <p> This method provides the device info
2795      * in the form of a {@link android.net.wifi.p2p.WifiP2pDevice}.
2796      * Valid {@link android.net.wifi.p2p.WifiP2pDevice} is returned when p2p is enabled.
2797      * To get information notifications on P2P getting enabled refers
2798      * {@link #WIFI_P2P_STATE_ENABLED}.
2799      *
2800      * <p> This {@link android.net.wifi.p2p.WifiP2pDevice} is returned using the
2801      * {@link DeviceInfoListener} listener.
2802      *
2803      * <p> {@link android.net.wifi.p2p.WifiP2pDevice#deviceAddress} is only available if the caller
2804      * holds the {@code android.Manifest.permission#LOCAL_MAC_ADDRESS} permission, and holds the
2805      * anonymized MAC address (02:00:00:00:00:00) otherwise.
2806      *
2807      * <p> This information is also included in the {@link #WIFI_P2P_THIS_DEVICE_CHANGED_ACTION}
2808      * broadcast event with extra {@link #EXTRA_WIFI_P2P_DEVICE}.
2809      * <p>
2810      * If targeting {@link android.os.Build.VERSION_CODES#TIRAMISU} or later, the application must
2811      * have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
2812      * android:usesPermissionFlags="neverForLocation". If the application does not declare
2813      * android:usesPermissionFlags="neverForLocation", then it must also have
2814      * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
2815      *
2816      * If targeting an earlier release than {@link android.os.Build.VERSION_CODES#TIRAMISU}, the
2817      * application must have {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
2818      *
2819      * @param c is the channel created at {@link #initialize(Context, Looper, ChannelListener)}.
2820      * @param listener for callback when network info is available.
2821      */
2822     @RequiresPermission(allOf = {
2823             android.Manifest.permission.NEARBY_WIFI_DEVICES,
2824             android.Manifest.permission.ACCESS_FINE_LOCATION
2825             }, conditional = true)
requestDeviceInfo(@onNull Channel c, @NonNull DeviceInfoListener listener)2826     public void requestDeviceInfo(@NonNull Channel c, @NonNull DeviceInfoListener listener) {
2827         checkChannel(c);
2828         if (listener == null) throw new IllegalArgumentException("This listener cannot be null.");
2829 
2830         Bundle extras = prepareExtrasBundle(c);
2831         c.mAsyncChannel.sendMessage(prepareMessage(REQUEST_DEVICE_INFO, 0,
2832                 c.putListener(listener), extras, c.mContext));
2833     }
2834 
2835     /**
2836      * Set the external approver for a specific peer.
2837      *
2838      * This API associates a specific peer with an approver. When an incoming request is received
2839      * from a peer, an authorization request is routed to the attached approver. The approver then
2840      * calls {@link #setConnectionRequestResult(Channel, MacAddress, int, ActionListener)} to send
2841      * the result to the WiFi service. A specific peer (identified by its {@code MacAddress}) can
2842      * only be attached to a single approver. The previous approver will be detached once a new
2843      * approver is attached. The approver will also be detached automatically when the channel is
2844      * closed.
2845      * <p>
2846      * When an approver is attached, {@link ExternalApproverRequestListener#onAttached(MacAddress)}
2847      * is called. When an approver is detached,
2848      * {@link ExternalApproverRequestListener#onDetached(MacAddress, int)} is called.
2849      * When an incoming request is received,
2850      * {@link ExternalApproverRequestListener#onConnectionRequested(int, WifiP2pConfig, WifiP2pDevice)}
2851      * is called. When a WPS PIN is generated,
2852      * {@link ExternalApproverRequestListener#onPinGenerated(MacAddress, String)} is called.
2853      * <p>
2854      * The application must have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
2855      * android:usesPermissionFlags="neverForLocation". If the application does not declare
2856      * android:usesPermissionFlags="neverForLocation", then it must also have
2857      * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
2858      *
2859      * @param c is the channel created at {@link #initialize(Context, Looper, ChannelListener)}.
2860      * @param deviceAddress the peer which is bound to the external approver.
2861      * @param listener for callback when the framework needs to notify the external approver.
2862      */
2863     @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION)
addExternalApprover(@onNull Channel c, @NonNull MacAddress deviceAddress, @NonNull ExternalApproverRequestListener listener)2864     public void addExternalApprover(@NonNull Channel c, @NonNull MacAddress deviceAddress,
2865             @NonNull ExternalApproverRequestListener listener) {
2866         checkChannel(c);
2867         if (listener == null) throw new IllegalArgumentException("This listener cannot be null.");
2868         if (null == deviceAddress) {
2869             throw new IllegalArgumentException("deviceAddress cannot be empty");
2870         }
2871 
2872         Bundle extras = prepareExtrasBundle(c);
2873         extras.putParcelable(EXTRA_PARAM_KEY_PEER_ADDRESS, deviceAddress);
2874         c.mAsyncChannel.sendMessage(prepareMessage(ADD_EXTERNAL_APPROVER, 0,
2875                 c.putListener(listener), extras, c.mContext));
2876     }
2877 
2878     /**
2879      * Remove the external approver for a specific peer.
2880      *
2881      * The application must have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
2882      * android:usesPermissionFlags="neverForLocation". If the application does not declare
2883      * android:usesPermissionFlags="neverForLocation", then it must also have
2884      * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
2885      *
2886      * @param c is the channel created at {@link #initialize(Context, Looper, ChannelListener)}.
2887      * @param deviceAddress the peer which is bound to the external approver.
2888      * @param listener for callback on success or failure.
2889      */
2890     @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION)
removeExternalApprover(@onNull Channel c, @NonNull MacAddress deviceAddress, @Nullable ActionListener listener)2891     public void removeExternalApprover(@NonNull Channel c, @NonNull MacAddress deviceAddress,
2892             @Nullable ActionListener listener) {
2893         checkChannel(c);
2894         if (null == deviceAddress) {
2895             throw new IllegalArgumentException("deviceAddress cannot be empty");
2896         }
2897 
2898         Bundle extras = prepareExtrasBundle(c);
2899         extras.putParcelable(EXTRA_PARAM_KEY_PEER_ADDRESS, deviceAddress);
2900         c.mAsyncChannel.sendMessage(prepareMessage(REMOVE_EXTERNAL_APPROVER, 0,
2901                 c.putListener(listener), extras, c.mContext));
2902     }
2903 
2904     /**
2905      * Set the result for the incoming request from a specific peer.
2906      *
2907      * The application must have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
2908      * android:usesPermissionFlags="neverForLocation". If the application does not declare
2909      * android:usesPermissionFlags="neverForLocation", then it must also have
2910      * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
2911      *
2912      * @param c is the channel created at {@link #initialize(Context, Looper, ChannelListener)}.
2913      * @param deviceAddress the peer which is bound to the external approver.
2914      * @param result the response for the incoming request.
2915      * @param listener for callback on success or failure.
2916      */
2917     @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION)
setConnectionRequestResult(@onNull Channel c, @NonNull MacAddress deviceAddress, @ConnectionRequestResponse int result, @Nullable ActionListener listener)2918     public void setConnectionRequestResult(@NonNull Channel c, @NonNull MacAddress deviceAddress,
2919             @ConnectionRequestResponse int result, @Nullable ActionListener listener) {
2920         checkChannel(c);
2921         if (null == deviceAddress) {
2922             throw new IllegalArgumentException("deviceAddress cannot be empty");
2923         }
2924 
2925         Bundle extras = prepareExtrasBundle(c);
2926         extras.putParcelable(EXTRA_PARAM_KEY_PEER_ADDRESS, deviceAddress);
2927         c.mAsyncChannel.sendMessage(prepareMessage(SET_CONNECTION_REQUEST_RESULT,
2928                 result, c.putListener(listener), extras, c.mContext));
2929     }
2930 
2931     /**
2932      * Set the result with PIN for the incoming request from a specific peer.
2933      *
2934      * The application must have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
2935      * android:usesPermissionFlags="neverForLocation". If the application does not declare
2936      * android:usesPermissionFlags="neverForLocation", then it must also have
2937      * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
2938      *
2939      * @param c is the channel created at {@link #initialize(Context, Looper, ChannelListener)}.
2940      * @param deviceAddress the peer which is bound to the external approver.
2941      * @param result the response for the incoming request.
2942      * @param pin the PIN for the incoming request.
2943      * @param listener for callback on success or failure.
2944      */
2945     @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION)
setConnectionRequestResult(@onNull Channel c, @NonNull MacAddress deviceAddress, @ConnectionRequestResponse int result, @Nullable String pin, @Nullable ActionListener listener)2946     public void setConnectionRequestResult(@NonNull Channel c, @NonNull MacAddress deviceAddress,
2947             @ConnectionRequestResponse int result, @Nullable String pin,
2948             @Nullable ActionListener listener) {
2949         checkChannel(c);
2950         if (null == deviceAddress) {
2951             throw new IllegalArgumentException("deviceAddress cannot be empty");
2952         }
2953         if (result == CONNECTION_REQUEST_ACCEPT && TextUtils.isEmpty(pin)) {
2954             throw new IllegalArgumentException("PIN cannot be empty for accepting a request");
2955         }
2956 
2957         Bundle extras = prepareExtrasBundle(c);
2958         extras.putParcelable(EXTRA_PARAM_KEY_PEER_ADDRESS, deviceAddress);
2959         extras.putString(EXTRA_PARAM_KEY_WPS_PIN, pin);
2960         c.mAsyncChannel.sendMessage(prepareMessage(SET_CONNECTION_REQUEST_RESULT,
2961                 result, c.putListener(listener), extras, c.mContext));
2962     }
2963 
2964     /**
2965      * Set/Clear vendor specific information elements (VSIEs) to be published during
2966      * Wi-Fi Direct (P2P) discovery.
2967      *
2968      * Once {@link Channel#close()} is called, the vendor information elements will be cleared from
2969      * framework. The information element format is defined in the IEEE 802.11-2016 spec
2970      * Table 9-77.
2971      * <p>
2972      * To clear the previously set vendor elements, call this API with an empty List.
2973      * <p>
2974      * The maximum accumulated length of all VSIEs must be before the limit specified by
2975      * {@link #getP2pMaxAllowedVendorElementsLengthBytes()}.
2976      * <p>
2977      * To publish vendor elements, this API should be called before peer discovery API, ex.
2978      * {@link #discoverPeers(Channel, ActionListener)}.
2979      * <p>
2980      * Use {@link #isSetVendorElementsSupported()} to determine whether the device supports
2981      * this feature. If {@link #isSetVendorElementsSupported()} return {@code false} then
2982      * this method will throw {@link UnsupportedOperationException}.
2983      *
2984      * @param c is the channel created at {@link #initialize(Context, Looper, ChannelListener)}.
2985      * @param vendorElements application information as vendor-specific information elements.
2986      * @param listener for callback when network info is available.
2987      */
2988     @RequiresPermission(allOf = {
2989             android.Manifest.permission.NEARBY_WIFI_DEVICES,
2990             android.Manifest.permission.OVERRIDE_WIFI_CONFIG
2991             })
setVendorElements(@onNull Channel c, @NonNull List<ScanResult.InformationElement> vendorElements, @Nullable ActionListener listener)2992     public void setVendorElements(@NonNull Channel c,
2993             @NonNull List<ScanResult.InformationElement> vendorElements,
2994             @Nullable ActionListener listener) {
2995         if (!isSetVendorElementsSupported()) {
2996             throw new UnsupportedOperationException();
2997         }
2998         checkChannel(c);
2999         int totalBytes = 0;
3000         for (ScanResult.InformationElement e : vendorElements) {
3001             if (e.id != ScanResult.InformationElement.EID_VSA) {
3002                 throw new IllegalArgumentException("received InformationElement which is not "
3003                         + "a Vendor Specific IE (VSIE). VSIEs have an ID = 221.");
3004             }
3005             // Length field is 1 byte.
3006             if (e.bytes == null || e.bytes.length > 0xff) {
3007                 throw new IllegalArgumentException("received InformationElement whose payload "
3008                         + "size is 0 or greater than 255.");
3009             }
3010             // The total bytes of an IE is EID (1 byte) + length (1 byte) + payload length.
3011             totalBytes += 2 + e.bytes.length;
3012             if (totalBytes > WIFI_P2P_VENDOR_ELEMENTS_MAXIMUM_LENGTH) {
3013                 throw new IllegalArgumentException("received InformationElement whose total "
3014                         + "size is greater than " + WIFI_P2P_VENDOR_ELEMENTS_MAXIMUM_LENGTH + ".");
3015             }
3016         }
3017         Bundle extras = prepareExtrasBundle(c);
3018         extras.putParcelableArrayList(EXTRA_PARAM_KEY_INFORMATION_ELEMENT_LIST,
3019                 new ArrayList<>(vendorElements));
3020         c.mAsyncChannel.sendMessage(prepareMessage(SET_VENDOR_ELEMENTS, 0,
3021                 c.putListener(listener), extras, c.mContext));
3022     }
3023 
3024     /**
3025      * Return the maximum total length (in bytes) of all Vendor specific information
3026      * elements (VSIEs) which can be set using the
3027      * {@link #setVendorElements(Channel, List, ActionListener)}.
3028      *
3029      * The length is calculated adding the payload length + 2 bytes for each VSIE
3030      * (2 bytes: 1 byte for type and 1 byte for length).
3031      */
getP2pMaxAllowedVendorElementsLengthBytes()3032     public static int getP2pMaxAllowedVendorElementsLengthBytes() {
3033         return WIFI_P2P_VENDOR_ELEMENTS_MAXIMUM_LENGTH;
3034     }
3035 }
3036