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