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