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