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.SdkConstant; 20 import android.annotation.SystemService; 21 import android.annotation.SdkConstant.SdkConstantType; 22 import android.content.Context; 23 import android.net.wifi.WpsInfo; 24 import android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceInfo; 25 import android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceResponse; 26 import android.net.wifi.p2p.nsd.WifiP2pServiceInfo; 27 import android.net.wifi.p2p.nsd.WifiP2pServiceRequest; 28 import android.net.wifi.p2p.nsd.WifiP2pServiceResponse; 29 import android.net.wifi.p2p.nsd.WifiP2pUpnpServiceInfo; 30 import android.net.wifi.p2p.nsd.WifiP2pUpnpServiceResponse; 31 import android.os.Binder; 32 import android.os.Bundle; 33 import android.os.Handler; 34 import android.os.Looper; 35 import android.os.Message; 36 import android.os.Messenger; 37 import android.os.RemoteException; 38 import android.text.TextUtils; 39 import android.util.Log; 40 41 import com.android.internal.util.AsyncChannel; 42 import com.android.internal.util.Protocol; 43 44 import dalvik.system.CloseGuard; 45 46 import java.util.HashMap; 47 import java.util.List; 48 import java.util.Map; 49 50 /** 51 * This class provides the API for managing Wi-Fi peer-to-peer connectivity. This lets an 52 * application discover available peers, setup connection to peers and query for the list of peers. 53 * When a p2p connection is formed over wifi, the device continues to maintain the uplink 54 * connection over mobile or any other available network for internet connectivity on the device. 55 * 56 * <p> The API is asynchronous and responses to requests from an application are on listener 57 * callbacks provided by the application. The application needs to do an initialization with 58 * {@link #initialize} before doing any p2p operation. 59 * 60 * <p> Most application calls need a {@link ActionListener} instance for receiving callbacks 61 * {@link ActionListener#onSuccess} or {@link ActionListener#onFailure}. Action callbacks 62 * indicate whether the initiation of the action was a success or a failure. 63 * Upon failure, the reason of failure can be one of {@link #ERROR}, {@link #P2P_UNSUPPORTED} 64 * or {@link #BUSY}. 65 * 66 * <p> An application can initiate discovery of peers with {@link #discoverPeers}. An initiated 67 * discovery request from an application stays active until the device starts connecting to a peer 68 * ,forms a p2p group or there is an explicit {@link #stopPeerDiscovery}. 69 * Applications can listen to {@link #WIFI_P2P_DISCOVERY_CHANGED_ACTION} to know if a peer-to-peer 70 * discovery is running or stopped. Additionally, {@link #WIFI_P2P_PEERS_CHANGED_ACTION} indicates 71 * if the peer list has changed. 72 * 73 * <p> When an application needs to fetch the current list of peers, it can request the list 74 * of peers with {@link #requestPeers}. When the peer list is available 75 * {@link PeerListListener#onPeersAvailable} is called with the device list. 76 * 77 * <p> An application can initiate a connection request to a peer through {@link #connect}. See 78 * {@link WifiP2pConfig} for details on setting up the configuration. For communication with legacy 79 * Wi-Fi devices that do not support p2p, an app can create a group using {@link #createGroup} 80 * which creates an access point whose details can be fetched with {@link #requestGroupInfo}. 81 * 82 * <p> After a successful group formation through {@link #createGroup} or through {@link #connect}, 83 * use {@link #requestConnectionInfo} to fetch the connection details. The connection info 84 * {@link WifiP2pInfo} contains the address of the group owner 85 * {@link WifiP2pInfo#groupOwnerAddress} and a flag {@link WifiP2pInfo#isGroupOwner} to indicate 86 * if the current device is a p2p group owner. A p2p client can thus communicate with 87 * the p2p group owner through a socket connection. 88 * 89 * <p> With peer discovery using {@link #discoverPeers}, an application discovers the neighboring 90 * peers, but has no good way to figure out which peer to establish a connection with. For example, 91 * if a game application is interested in finding all the neighboring peers that are also running 92 * the same game, it has no way to find out until after the connection is setup. Pre-association 93 * service discovery is meant to address this issue of filtering the peers based on the running 94 * services. 95 * 96 * <p>With pre-association service discovery, an application can advertise a service for a 97 * application on a peer device prior to a connection setup between the devices. 98 * Currently, DNS based service discovery (Bonjour) and Upnp are the higher layer protocols 99 * supported. Get Bonjour resources at dns-sd.org and Upnp resources at upnp.org 100 * As an example, a video application can discover a Upnp capable media renderer 101 * prior to setting up a Wi-fi p2p connection with the device. 102 * 103 * <p> An application can advertise a Upnp or a Bonjour service with a call to 104 * {@link #addLocalService}. After a local service is added, 105 * the framework automatically responds to a peer application discovering the service prior 106 * to establishing a p2p connection. A call to {@link #removeLocalService} removes a local 107 * service and {@link #clearLocalServices} can be used to clear all local services. 108 * 109 * <p> An application that is looking for peer devices that support certain services 110 * can do so with a call to {@link #discoverServices}. Prior to initiating the discovery, 111 * application can add service discovery request with a call to {@link #addServiceRequest}, 112 * remove a service discovery request with a call to {@link #removeServiceRequest} or clear 113 * all requests with a call to {@link #clearServiceRequests}. When no service requests remain, 114 * a previously running service discovery will stop. 115 * 116 * The application is notified of a result of service discovery request through listener callbacks 117 * set through {@link #setDnsSdResponseListeners} for Bonjour or 118 * {@link #setUpnpServiceResponseListener} for Upnp. 119 * 120 * <p class="note"><strong>Note:</strong> 121 * Registering an application handler with {@link #initialize} requires the permissions 122 * {@link android.Manifest.permission#ACCESS_WIFI_STATE} and 123 * {@link android.Manifest.permission#CHANGE_WIFI_STATE} to perform any further peer-to-peer 124 * operations. 125 * 126 * {@see WifiP2pConfig} 127 * {@see WifiP2pInfo} 128 * {@see WifiP2pGroup} 129 * {@see WifiP2pDevice} 130 * {@see WifiP2pDeviceList} 131 * {@see android.net.wifi.WpsInfo} 132 */ 133 @SystemService(Context.WIFI_P2P_SERVICE) 134 public class WifiP2pManager { 135 private static final String TAG = "WifiP2pManager"; 136 /** 137 * Broadcast intent action to indicate whether Wi-Fi p2p is enabled or disabled. An 138 * extra {@link #EXTRA_WIFI_STATE} provides the state information as int. 139 * 140 * @see #EXTRA_WIFI_STATE 141 */ 142 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 143 public static final String WIFI_P2P_STATE_CHANGED_ACTION = 144 "android.net.wifi.p2p.STATE_CHANGED"; 145 146 /** 147 * The lookup key for an int that indicates whether Wi-Fi p2p is enabled or disabled. 148 * Retrieve it with {@link android.content.Intent#getIntExtra(String,int)}. 149 * 150 * @see #WIFI_P2P_STATE_DISABLED 151 * @see #WIFI_P2P_STATE_ENABLED 152 */ 153 public static final String EXTRA_WIFI_STATE = "wifi_p2p_state"; 154 155 /** 156 * Wi-Fi p2p is disabled. 157 * 158 * @see #WIFI_P2P_STATE_CHANGED_ACTION 159 */ 160 public static final int WIFI_P2P_STATE_DISABLED = 1; 161 162 /** 163 * Wi-Fi p2p is enabled. 164 * 165 * @see #WIFI_P2P_STATE_CHANGED_ACTION 166 */ 167 public static final int WIFI_P2P_STATE_ENABLED = 2; 168 169 /** 170 * Broadcast intent action indicating that the state of Wi-Fi p2p connectivity 171 * has changed. One extra {@link #EXTRA_WIFI_P2P_INFO} provides the p2p connection info in 172 * the form of a {@link WifiP2pInfo} object. Another extra {@link #EXTRA_NETWORK_INFO} provides 173 * the network info in the form of a {@link android.net.NetworkInfo}. A third extra provides 174 * the details of the group. 175 * 176 * @see #EXTRA_WIFI_P2P_INFO 177 * @see #EXTRA_NETWORK_INFO 178 * @see #EXTRA_WIFI_P2P_GROUP 179 */ 180 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 181 public static final String WIFI_P2P_CONNECTION_CHANGED_ACTION = 182 "android.net.wifi.p2p.CONNECTION_STATE_CHANGE"; 183 184 /** 185 * The lookup key for a {@link android.net.wifi.p2p.WifiP2pInfo} object 186 * Retrieve with {@link android.content.Intent#getParcelableExtra(String)}. 187 */ 188 public static final String EXTRA_WIFI_P2P_INFO = "wifiP2pInfo"; 189 190 /** 191 * The lookup key for a {@link android.net.NetworkInfo} object associated with the 192 * p2p network. Retrieve with 193 * {@link android.content.Intent#getParcelableExtra(String)}. 194 */ 195 public static final String EXTRA_NETWORK_INFO = "networkInfo"; 196 197 /** 198 * The lookup key for a {@link android.net.wifi.p2p.WifiP2pGroup} object 199 * associated with the p2p network. Retrieve with 200 * {@link android.content.Intent#getParcelableExtra(String)}. 201 */ 202 public static final String EXTRA_WIFI_P2P_GROUP = "p2pGroupInfo"; 203 204 /** 205 * Broadcast intent action indicating that the available peer list has changed. This 206 * can be sent as a result of peers being found, lost or updated. 207 * 208 * <p> An extra {@link #EXTRA_P2P_DEVICE_LIST} provides the full list of 209 * current peers. The full list of peers can also be obtained any time with 210 * {@link #requestPeers}. 211 * 212 * @see #EXTRA_P2P_DEVICE_LIST 213 */ 214 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 215 public static final String WIFI_P2P_PEERS_CHANGED_ACTION = 216 "android.net.wifi.p2p.PEERS_CHANGED"; 217 218 /** 219 * The lookup key for a {@link android.net.wifi.p2p.WifiP2pDeviceList} object representing 220 * the new peer list when {@link #WIFI_P2P_PEERS_CHANGED_ACTION} broadcast is sent. 221 * 222 * <p>Retrieve with {@link android.content.Intent#getParcelableExtra(String)}. 223 */ 224 public static final String EXTRA_P2P_DEVICE_LIST = "wifiP2pDeviceList"; 225 226 /** 227 * Broadcast intent action indicating that peer discovery has either started or stopped. 228 * One extra {@link #EXTRA_DISCOVERY_STATE} indicates whether discovery has started 229 * or stopped. 230 * 231 * <p>Note that discovery will be stopped during a connection setup. If the application tries 232 * to re-initiate discovery during this time, it can fail. 233 */ 234 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 235 public static final String WIFI_P2P_DISCOVERY_CHANGED_ACTION = 236 "android.net.wifi.p2p.DISCOVERY_STATE_CHANGE"; 237 238 /** 239 * The lookup key for an int that indicates whether p2p discovery has started or stopped. 240 * Retrieve it with {@link android.content.Intent#getIntExtra(String,int)}. 241 * 242 * @see #WIFI_P2P_DISCOVERY_STARTED 243 * @see #WIFI_P2P_DISCOVERY_STOPPED 244 */ 245 public static final String EXTRA_DISCOVERY_STATE = "discoveryState"; 246 247 /** 248 * p2p discovery has stopped 249 * 250 * @see #WIFI_P2P_DISCOVERY_CHANGED_ACTION 251 */ 252 public static final int WIFI_P2P_DISCOVERY_STOPPED = 1; 253 254 /** 255 * p2p discovery has started 256 * 257 * @see #WIFI_P2P_DISCOVERY_CHANGED_ACTION 258 */ 259 public static final int WIFI_P2P_DISCOVERY_STARTED = 2; 260 261 /** 262 * Broadcast intent action indicating that this device details have changed. 263 */ 264 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 265 public static final String WIFI_P2P_THIS_DEVICE_CHANGED_ACTION = 266 "android.net.wifi.p2p.THIS_DEVICE_CHANGED"; 267 268 /** 269 * The lookup key for a {@link android.net.wifi.p2p.WifiP2pDevice} object 270 * Retrieve with {@link android.content.Intent#getParcelableExtra(String)}. 271 */ 272 public static final String EXTRA_WIFI_P2P_DEVICE = "wifiP2pDevice"; 273 274 /** 275 * Broadcast intent action indicating that remembered persistent groups have changed. 276 * @hide 277 */ 278 public static final String WIFI_P2P_PERSISTENT_GROUPS_CHANGED_ACTION = 279 "android.net.wifi.p2p.PERSISTENT_GROUPS_CHANGED"; 280 281 /** 282 * The lookup key for a handover message returned by the WifiP2pService. 283 * @hide 284 */ 285 public static final String EXTRA_HANDOVER_MESSAGE = 286 "android.net.wifi.p2p.EXTRA_HANDOVER_MESSAGE"; 287 288 /** 289 * The lookup key for a calling package returned by the WifiP2pService. 290 * @hide 291 */ 292 public static final String CALLING_PACKAGE = 293 "android.net.wifi.p2p.CALLING_PACKAGE"; 294 295 IWifiP2pManager mService; 296 297 private static final int BASE = Protocol.BASE_WIFI_P2P_MANAGER; 298 299 /** @hide */ 300 public static final int DISCOVER_PEERS = BASE + 1; 301 /** @hide */ 302 public static final int DISCOVER_PEERS_FAILED = BASE + 2; 303 /** @hide */ 304 public static final int DISCOVER_PEERS_SUCCEEDED = BASE + 3; 305 306 /** @hide */ 307 public static final int STOP_DISCOVERY = BASE + 4; 308 /** @hide */ 309 public static final int STOP_DISCOVERY_FAILED = BASE + 5; 310 /** @hide */ 311 public static final int STOP_DISCOVERY_SUCCEEDED = BASE + 6; 312 313 /** @hide */ 314 public static final int CONNECT = BASE + 7; 315 /** @hide */ 316 public static final int CONNECT_FAILED = BASE + 8; 317 /** @hide */ 318 public static final int CONNECT_SUCCEEDED = BASE + 9; 319 320 /** @hide */ 321 public static final int CANCEL_CONNECT = BASE + 10; 322 /** @hide */ 323 public static final int CANCEL_CONNECT_FAILED = BASE + 11; 324 /** @hide */ 325 public static final int CANCEL_CONNECT_SUCCEEDED = BASE + 12; 326 327 /** @hide */ 328 public static final int CREATE_GROUP = BASE + 13; 329 /** @hide */ 330 public static final int CREATE_GROUP_FAILED = BASE + 14; 331 /** @hide */ 332 public static final int CREATE_GROUP_SUCCEEDED = BASE + 15; 333 334 /** @hide */ 335 public static final int REMOVE_GROUP = BASE + 16; 336 /** @hide */ 337 public static final int REMOVE_GROUP_FAILED = BASE + 17; 338 /** @hide */ 339 public static final int REMOVE_GROUP_SUCCEEDED = BASE + 18; 340 341 /** @hide */ 342 public static final int REQUEST_PEERS = BASE + 19; 343 /** @hide */ 344 public static final int RESPONSE_PEERS = BASE + 20; 345 346 /** @hide */ 347 public static final int REQUEST_CONNECTION_INFO = BASE + 21; 348 /** @hide */ 349 public static final int RESPONSE_CONNECTION_INFO = BASE + 22; 350 351 /** @hide */ 352 public static final int REQUEST_GROUP_INFO = BASE + 23; 353 /** @hide */ 354 public static final int RESPONSE_GROUP_INFO = BASE + 24; 355 356 /** @hide */ 357 public static final int ADD_LOCAL_SERVICE = BASE + 28; 358 /** @hide */ 359 public static final int ADD_LOCAL_SERVICE_FAILED = BASE + 29; 360 /** @hide */ 361 public static final int ADD_LOCAL_SERVICE_SUCCEEDED = BASE + 30; 362 363 /** @hide */ 364 public static final int REMOVE_LOCAL_SERVICE = BASE + 31; 365 /** @hide */ 366 public static final int REMOVE_LOCAL_SERVICE_FAILED = BASE + 32; 367 /** @hide */ 368 public static final int REMOVE_LOCAL_SERVICE_SUCCEEDED = BASE + 33; 369 370 /** @hide */ 371 public static final int CLEAR_LOCAL_SERVICES = BASE + 34; 372 /** @hide */ 373 public static final int CLEAR_LOCAL_SERVICES_FAILED = BASE + 35; 374 /** @hide */ 375 public static final int CLEAR_LOCAL_SERVICES_SUCCEEDED = BASE + 36; 376 377 /** @hide */ 378 public static final int ADD_SERVICE_REQUEST = BASE + 37; 379 /** @hide */ 380 public static final int ADD_SERVICE_REQUEST_FAILED = BASE + 38; 381 /** @hide */ 382 public static final int ADD_SERVICE_REQUEST_SUCCEEDED = BASE + 39; 383 384 /** @hide */ 385 public static final int REMOVE_SERVICE_REQUEST = BASE + 40; 386 /** @hide */ 387 public static final int REMOVE_SERVICE_REQUEST_FAILED = BASE + 41; 388 /** @hide */ 389 public static final int REMOVE_SERVICE_REQUEST_SUCCEEDED = BASE + 42; 390 391 /** @hide */ 392 public static final int CLEAR_SERVICE_REQUESTS = BASE + 43; 393 /** @hide */ 394 public static final int CLEAR_SERVICE_REQUESTS_FAILED = BASE + 44; 395 /** @hide */ 396 public static final int CLEAR_SERVICE_REQUESTS_SUCCEEDED = BASE + 45; 397 398 /** @hide */ 399 public static final int DISCOVER_SERVICES = BASE + 46; 400 /** @hide */ 401 public static final int DISCOVER_SERVICES_FAILED = BASE + 47; 402 /** @hide */ 403 public static final int DISCOVER_SERVICES_SUCCEEDED = BASE + 48; 404 405 /** @hide */ 406 public static final int PING = BASE + 49; 407 408 /** @hide */ 409 public static final int RESPONSE_SERVICE = BASE + 50; 410 411 /** @hide */ 412 public static final int SET_DEVICE_NAME = BASE + 51; 413 /** @hide */ 414 public static final int SET_DEVICE_NAME_FAILED = BASE + 52; 415 /** @hide */ 416 public static final int SET_DEVICE_NAME_SUCCEEDED = BASE + 53; 417 418 /** @hide */ 419 public static final int DELETE_PERSISTENT_GROUP = BASE + 54; 420 /** @hide */ 421 public static final int DELETE_PERSISTENT_GROUP_FAILED = BASE + 55; 422 /** @hide */ 423 public static final int DELETE_PERSISTENT_GROUP_SUCCEEDED = BASE + 56; 424 425 /** @hide */ 426 public static final int REQUEST_PERSISTENT_GROUP_INFO = BASE + 57; 427 /** @hide */ 428 public static final int RESPONSE_PERSISTENT_GROUP_INFO = BASE + 58; 429 430 /** @hide */ 431 public static final int SET_WFD_INFO = BASE + 59; 432 /** @hide */ 433 public static final int SET_WFD_INFO_FAILED = BASE + 60; 434 /** @hide */ 435 public static final int SET_WFD_INFO_SUCCEEDED = BASE + 61; 436 437 /** @hide */ 438 public static final int START_WPS = BASE + 62; 439 /** @hide */ 440 public static final int START_WPS_FAILED = BASE + 63; 441 /** @hide */ 442 public static final int START_WPS_SUCCEEDED = BASE + 64; 443 444 /** @hide */ 445 public static final int START_LISTEN = BASE + 65; 446 /** @hide */ 447 public static final int START_LISTEN_FAILED = BASE + 66; 448 /** @hide */ 449 public static final int START_LISTEN_SUCCEEDED = BASE + 67; 450 451 /** @hide */ 452 public static final int STOP_LISTEN = BASE + 68; 453 /** @hide */ 454 public static final int STOP_LISTEN_FAILED = BASE + 69; 455 /** @hide */ 456 public static final int STOP_LISTEN_SUCCEEDED = BASE + 70; 457 458 /** @hide */ 459 public static final int SET_CHANNEL = BASE + 71; 460 /** @hide */ 461 public static final int SET_CHANNEL_FAILED = BASE + 72; 462 /** @hide */ 463 public static final int SET_CHANNEL_SUCCEEDED = BASE + 73; 464 465 /** @hide */ 466 public static final int GET_HANDOVER_REQUEST = BASE + 75; 467 /** @hide */ 468 public static final int GET_HANDOVER_SELECT = BASE + 76; 469 /** @hide */ 470 public static final int RESPONSE_GET_HANDOVER_MESSAGE = BASE + 77; 471 /** @hide */ 472 public static final int INITIATOR_REPORT_NFC_HANDOVER = BASE + 78; 473 /** @hide */ 474 public static final int RESPONDER_REPORT_NFC_HANDOVER = BASE + 79; 475 /** @hide */ 476 public static final int REPORT_NFC_HANDOVER_SUCCEEDED = BASE + 80; 477 /** @hide */ 478 public static final int REPORT_NFC_HANDOVER_FAILED = BASE + 81; 479 480 481 /** 482 * Create a new WifiP2pManager instance. Applications use 483 * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve 484 * the standard {@link android.content.Context#WIFI_P2P_SERVICE Context.WIFI_P2P_SERVICE}. 485 * @param service the Binder interface 486 * @hide - hide this because it takes in a parameter of type IWifiP2pManager, which 487 * is a system private class. 488 */ WifiP2pManager(IWifiP2pManager service)489 public WifiP2pManager(IWifiP2pManager service) { 490 mService = service; 491 } 492 493 /** 494 * Passed with {@link ActionListener#onFailure}. 495 * Indicates that the operation failed due to an internal error. 496 */ 497 public static final int ERROR = 0; 498 499 /** 500 * Passed with {@link ActionListener#onFailure}. 501 * Indicates that the operation failed because p2p is unsupported on the device. 502 */ 503 public static final int P2P_UNSUPPORTED = 1; 504 505 /** 506 * Passed with {@link ActionListener#onFailure}. 507 * Indicates that the operation failed because the framework is busy and 508 * unable to service the request 509 */ 510 public static final int BUSY = 2; 511 512 /** 513 * Passed with {@link ActionListener#onFailure}. 514 * Indicates that the {@link #discoverServices} failed because no service 515 * requests are added. Use {@link #addServiceRequest} to add a service 516 * request. 517 */ 518 public static final int NO_SERVICE_REQUESTS = 3; 519 520 /** Interface for callback invocation when framework channel is lost */ 521 public interface ChannelListener { 522 /** 523 * The channel to the framework has been disconnected. 524 * Application could try re-initializing using {@link #initialize} 525 */ onChannelDisconnected()526 public void onChannelDisconnected(); 527 } 528 529 /** Interface for callback invocation on an application action */ 530 public interface ActionListener { 531 /** The operation succeeded */ onSuccess()532 public void onSuccess(); 533 /** 534 * The operation failed 535 * @param reason The reason for failure could be one of {@link #P2P_UNSUPPORTED}, 536 * {@link #ERROR} or {@link #BUSY} 537 */ onFailure(int reason)538 public void onFailure(int reason); 539 } 540 541 /** Interface for callback invocation when peer list is available */ 542 public interface PeerListListener { 543 /** 544 * The requested peer list is available 545 * @param peers List of available peers 546 */ onPeersAvailable(WifiP2pDeviceList peers)547 public void onPeersAvailable(WifiP2pDeviceList peers); 548 } 549 550 /** Interface for callback invocation when connection info is available */ 551 public interface ConnectionInfoListener { 552 /** 553 * The requested connection info is available 554 * @param info Wi-Fi p2p connection info 555 */ onConnectionInfoAvailable(WifiP2pInfo info)556 public void onConnectionInfoAvailable(WifiP2pInfo info); 557 } 558 559 /** Interface for callback invocation when group info is available */ 560 public interface GroupInfoListener { 561 /** 562 * The requested p2p group info is available 563 * @param group Wi-Fi p2p group info 564 */ onGroupInfoAvailable(WifiP2pGroup group)565 public void onGroupInfoAvailable(WifiP2pGroup group); 566 } 567 568 /** 569 * Interface for callback invocation when service discovery response other than 570 * Upnp or Bonjour is received 571 */ 572 public interface ServiceResponseListener { 573 574 /** 575 * The requested service response is available. 576 * 577 * @param protocolType protocol type. currently only 578 * {@link WifiP2pServiceInfo#SERVICE_TYPE_VENDOR_SPECIFIC}. 579 * @param responseData service discovery response data based on the requested 580 * service protocol type. The format depends on the service type. 581 * @param srcDevice source device. 582 */ onServiceAvailable(int protocolType, byte[] responseData, WifiP2pDevice srcDevice)583 public void onServiceAvailable(int protocolType, 584 byte[] responseData, WifiP2pDevice srcDevice); 585 } 586 587 /** 588 * Interface for callback invocation when Bonjour service discovery response 589 * is received 590 */ 591 public interface DnsSdServiceResponseListener { 592 593 /** 594 * The requested Bonjour service response is available. 595 * 596 * <p>This function is invoked when the device with the specified Bonjour 597 * registration type returned the instance name. 598 * @param instanceName instance name.<br> 599 * e.g) "MyPrinter". 600 * @param registrationType <br> 601 * e.g) "_ipp._tcp.local." 602 * @param srcDevice source device. 603 */ onDnsSdServiceAvailable(String instanceName, String registrationType, WifiP2pDevice srcDevice)604 public void onDnsSdServiceAvailable(String instanceName, 605 String registrationType, WifiP2pDevice srcDevice); 606 607 } 608 609 /** 610 * Interface for callback invocation when Bonjour TXT record is available 611 * for a service 612 */ 613 public interface DnsSdTxtRecordListener { 614 /** 615 * The requested Bonjour service response is available. 616 * 617 * <p>This function is invoked when the device with the specified full 618 * service domain service returned TXT record. 619 * 620 * @param fullDomainName full domain name. <br> 621 * e.g) "MyPrinter._ipp._tcp.local.". 622 * @param txtRecordMap TXT record data as a map of key/value pairs 623 * @param srcDevice source device. 624 */ onDnsSdTxtRecordAvailable(String fullDomainName, Map<String, String> txtRecordMap, WifiP2pDevice srcDevice)625 public void onDnsSdTxtRecordAvailable(String fullDomainName, 626 Map<String, String> txtRecordMap, 627 WifiP2pDevice srcDevice); 628 } 629 630 /** 631 * Interface for callback invocation when upnp service discovery response 632 * is received 633 * */ 634 public interface UpnpServiceResponseListener { 635 636 /** 637 * The requested upnp service response is available. 638 * 639 * <p>This function is invoked when the specified device or service is found. 640 * 641 * @param uniqueServiceNames The list of unique service names.<br> 642 * e.g) uuid:6859dede-8574-59ab-9332-123456789012::urn:schemas-upnp-org:device: 643 * MediaServer:1 644 * @param srcDevice source device. 645 */ onUpnpServiceAvailable(List<String> uniqueServiceNames, WifiP2pDevice srcDevice)646 public void onUpnpServiceAvailable(List<String> uniqueServiceNames, 647 WifiP2pDevice srcDevice); 648 } 649 650 651 /** Interface for callback invocation when stored group info list is available {@hide}*/ 652 public interface PersistentGroupInfoListener { 653 /** 654 * The requested stored p2p group info list is available 655 * @param groups Wi-Fi p2p group info list 656 */ onPersistentGroupInfoAvailable(WifiP2pGroupList groups)657 public void onPersistentGroupInfoAvailable(WifiP2pGroupList groups); 658 } 659 660 /** 661 * Interface for callback invocation when Handover Request or Select Message is available 662 * @hide 663 */ 664 public interface HandoverMessageListener { onHandoverMessageAvailable(String handoverMessage)665 public void onHandoverMessageAvailable(String handoverMessage); 666 } 667 668 /** 669 * A channel that connects the application to the Wifi p2p framework. 670 * Most p2p operations require a Channel as an argument. An instance of Channel is obtained 671 * by doing a call on {@link #initialize} 672 */ 673 public static class Channel implements AutoCloseable { 674 /** @hide */ Channel(Context context, Looper looper, ChannelListener l, Binder binder, WifiP2pManager p2pManager)675 public Channel(Context context, Looper looper, ChannelListener l, Binder binder, 676 WifiP2pManager p2pManager) { 677 mAsyncChannel = new AsyncChannel(); 678 mHandler = new P2pHandler(looper); 679 mChannelListener = l; 680 mContext = context; 681 mBinder = binder; 682 mP2pManager = p2pManager; 683 684 mCloseGuard.open("close"); 685 } 686 private final static int INVALID_LISTENER_KEY = 0; 687 private final WifiP2pManager mP2pManager; 688 private ChannelListener mChannelListener; 689 private ServiceResponseListener mServRspListener; 690 private DnsSdServiceResponseListener mDnsSdServRspListener; 691 private DnsSdTxtRecordListener mDnsSdTxtListener; 692 private UpnpServiceResponseListener mUpnpServRspListener; 693 private HashMap<Integer, Object> mListenerMap = new HashMap<Integer, Object>(); 694 private final Object mListenerMapLock = new Object(); 695 private int mListenerKey = 0; 696 697 private final CloseGuard mCloseGuard = CloseGuard.get(); 698 699 /** 700 * Close the current P2P connection and indicate to the P2P service that connections 701 * created by the app can be removed. 702 */ close()703 public void close() { 704 if (mP2pManager == null) { 705 Log.w(TAG, "Channel.close(): Null mP2pManager!?"); 706 } else { 707 try { 708 mP2pManager.mService.close(mBinder); 709 } catch (RemoteException e) { 710 throw e.rethrowFromSystemServer(); 711 } 712 } 713 714 mAsyncChannel.disconnect(); 715 mCloseGuard.close(); 716 } 717 718 /** @hide */ 719 @Override finalize()720 protected void finalize() throws Throwable { 721 try { 722 if (mCloseGuard != null) { 723 mCloseGuard.warnIfOpen(); 724 } 725 726 close(); 727 } finally { 728 super.finalize(); 729 } 730 } 731 732 /* package */ final Binder mBinder; 733 734 private AsyncChannel mAsyncChannel; 735 private P2pHandler mHandler; 736 Context mContext; 737 class P2pHandler extends Handler { P2pHandler(Looper looper)738 P2pHandler(Looper looper) { 739 super(looper); 740 } 741 742 @Override handleMessage(Message message)743 public void handleMessage(Message message) { 744 Object listener = getListener(message.arg2); 745 switch (message.what) { 746 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: 747 if (mChannelListener != null) { 748 mChannelListener.onChannelDisconnected(); 749 mChannelListener = null; 750 } 751 break; 752 /* ActionListeners grouped together */ 753 case DISCOVER_PEERS_FAILED: 754 case STOP_DISCOVERY_FAILED: 755 case DISCOVER_SERVICES_FAILED: 756 case CONNECT_FAILED: 757 case CANCEL_CONNECT_FAILED: 758 case CREATE_GROUP_FAILED: 759 case REMOVE_GROUP_FAILED: 760 case ADD_LOCAL_SERVICE_FAILED: 761 case REMOVE_LOCAL_SERVICE_FAILED: 762 case CLEAR_LOCAL_SERVICES_FAILED: 763 case ADD_SERVICE_REQUEST_FAILED: 764 case REMOVE_SERVICE_REQUEST_FAILED: 765 case CLEAR_SERVICE_REQUESTS_FAILED: 766 case SET_DEVICE_NAME_FAILED: 767 case DELETE_PERSISTENT_GROUP_FAILED: 768 case SET_WFD_INFO_FAILED: 769 case START_WPS_FAILED: 770 case START_LISTEN_FAILED: 771 case STOP_LISTEN_FAILED: 772 case SET_CHANNEL_FAILED: 773 case REPORT_NFC_HANDOVER_FAILED: 774 if (listener != null) { 775 ((ActionListener) listener).onFailure(message.arg1); 776 } 777 break; 778 /* ActionListeners grouped together */ 779 case DISCOVER_PEERS_SUCCEEDED: 780 case STOP_DISCOVERY_SUCCEEDED: 781 case DISCOVER_SERVICES_SUCCEEDED: 782 case CONNECT_SUCCEEDED: 783 case CANCEL_CONNECT_SUCCEEDED: 784 case CREATE_GROUP_SUCCEEDED: 785 case REMOVE_GROUP_SUCCEEDED: 786 case ADD_LOCAL_SERVICE_SUCCEEDED: 787 case REMOVE_LOCAL_SERVICE_SUCCEEDED: 788 case CLEAR_LOCAL_SERVICES_SUCCEEDED: 789 case ADD_SERVICE_REQUEST_SUCCEEDED: 790 case REMOVE_SERVICE_REQUEST_SUCCEEDED: 791 case CLEAR_SERVICE_REQUESTS_SUCCEEDED: 792 case SET_DEVICE_NAME_SUCCEEDED: 793 case DELETE_PERSISTENT_GROUP_SUCCEEDED: 794 case SET_WFD_INFO_SUCCEEDED: 795 case START_WPS_SUCCEEDED: 796 case START_LISTEN_SUCCEEDED: 797 case STOP_LISTEN_SUCCEEDED: 798 case SET_CHANNEL_SUCCEEDED: 799 case REPORT_NFC_HANDOVER_SUCCEEDED: 800 if (listener != null) { 801 ((ActionListener) listener).onSuccess(); 802 } 803 break; 804 case RESPONSE_PEERS: 805 WifiP2pDeviceList peers = (WifiP2pDeviceList) message.obj; 806 if (listener != null) { 807 ((PeerListListener) listener).onPeersAvailable(peers); 808 } 809 break; 810 case RESPONSE_CONNECTION_INFO: 811 WifiP2pInfo wifiP2pInfo = (WifiP2pInfo) message.obj; 812 if (listener != null) { 813 ((ConnectionInfoListener) listener).onConnectionInfoAvailable(wifiP2pInfo); 814 } 815 break; 816 case RESPONSE_GROUP_INFO: 817 WifiP2pGroup group = (WifiP2pGroup) message.obj; 818 if (listener != null) { 819 ((GroupInfoListener) listener).onGroupInfoAvailable(group); 820 } 821 break; 822 case RESPONSE_SERVICE: 823 WifiP2pServiceResponse resp = (WifiP2pServiceResponse) message.obj; 824 handleServiceResponse(resp); 825 break; 826 case RESPONSE_PERSISTENT_GROUP_INFO: 827 WifiP2pGroupList groups = (WifiP2pGroupList) message.obj; 828 if (listener != null) { 829 ((PersistentGroupInfoListener) listener). 830 onPersistentGroupInfoAvailable(groups); 831 } 832 break; 833 case RESPONSE_GET_HANDOVER_MESSAGE: 834 Bundle handoverBundle = (Bundle) message.obj; 835 if (listener != null) { 836 String handoverMessage = handoverBundle != null 837 ? handoverBundle.getString(EXTRA_HANDOVER_MESSAGE) 838 : null; 839 ((HandoverMessageListener) listener) 840 .onHandoverMessageAvailable(handoverMessage); 841 } 842 break; 843 default: 844 Log.d(TAG, "Ignored " + message); 845 break; 846 } 847 } 848 } 849 handleServiceResponse(WifiP2pServiceResponse resp)850 private void handleServiceResponse(WifiP2pServiceResponse resp) { 851 if (resp instanceof WifiP2pDnsSdServiceResponse) { 852 handleDnsSdServiceResponse((WifiP2pDnsSdServiceResponse)resp); 853 } else if (resp instanceof WifiP2pUpnpServiceResponse) { 854 if (mUpnpServRspListener != null) { 855 handleUpnpServiceResponse((WifiP2pUpnpServiceResponse)resp); 856 } 857 } else { 858 if (mServRspListener != null) { 859 mServRspListener.onServiceAvailable(resp.getServiceType(), 860 resp.getRawData(), resp.getSrcDevice()); 861 } 862 } 863 } 864 handleUpnpServiceResponse(WifiP2pUpnpServiceResponse resp)865 private void handleUpnpServiceResponse(WifiP2pUpnpServiceResponse resp) { 866 mUpnpServRspListener.onUpnpServiceAvailable(resp.getUniqueServiceNames(), 867 resp.getSrcDevice()); 868 } 869 handleDnsSdServiceResponse(WifiP2pDnsSdServiceResponse resp)870 private void handleDnsSdServiceResponse(WifiP2pDnsSdServiceResponse resp) { 871 if (resp.getDnsType() == WifiP2pDnsSdServiceInfo.DNS_TYPE_PTR) { 872 if (mDnsSdServRspListener != null) { 873 mDnsSdServRspListener.onDnsSdServiceAvailable( 874 resp.getInstanceName(), 875 resp.getDnsQueryName(), 876 resp.getSrcDevice()); 877 } 878 } else if (resp.getDnsType() == WifiP2pDnsSdServiceInfo.DNS_TYPE_TXT) { 879 if (mDnsSdTxtListener != null) { 880 mDnsSdTxtListener.onDnsSdTxtRecordAvailable( 881 resp.getDnsQueryName(), 882 resp.getTxtRecord(), 883 resp.getSrcDevice()); 884 } 885 } else { 886 Log.e(TAG, "Unhandled resp " + resp); 887 } 888 } 889 putListener(Object listener)890 private int putListener(Object listener) { 891 if (listener == null) return INVALID_LISTENER_KEY; 892 int key; 893 synchronized (mListenerMapLock) { 894 do { 895 key = mListenerKey++; 896 } while (key == INVALID_LISTENER_KEY); 897 mListenerMap.put(key, listener); 898 } 899 return key; 900 } 901 getListener(int key)902 private Object getListener(int key) { 903 if (key == INVALID_LISTENER_KEY) return null; 904 synchronized (mListenerMapLock) { 905 return mListenerMap.remove(key); 906 } 907 } 908 } 909 checkChannel(Channel c)910 private static void checkChannel(Channel c) { 911 if (c == null) throw new IllegalArgumentException("Channel needs to be initialized"); 912 } 913 checkServiceInfo(WifiP2pServiceInfo info)914 private static void checkServiceInfo(WifiP2pServiceInfo info) { 915 if (info == null) throw new IllegalArgumentException("service info is null"); 916 } 917 checkServiceRequest(WifiP2pServiceRequest req)918 private static void checkServiceRequest(WifiP2pServiceRequest req) { 919 if (req == null) throw new IllegalArgumentException("service request is null"); 920 } 921 checkP2pConfig(WifiP2pConfig c)922 private static void checkP2pConfig(WifiP2pConfig c) { 923 if (c == null) throw new IllegalArgumentException("config cannot be null"); 924 if (TextUtils.isEmpty(c.deviceAddress)) { 925 throw new IllegalArgumentException("deviceAddress cannot be empty"); 926 } 927 } 928 929 /** 930 * Registers the application with the Wi-Fi framework. This function 931 * must be the first to be called before any p2p operations are performed. 932 * 933 * @param srcContext is the context of the source 934 * @param srcLooper is the Looper on which the callbacks are receivied 935 * @param listener for callback at loss of framework communication. Can be null. 936 * @return Channel instance that is necessary for performing any further p2p operations 937 */ initialize(Context srcContext, Looper srcLooper, ChannelListener listener)938 public Channel initialize(Context srcContext, Looper srcLooper, ChannelListener listener) { 939 Binder binder = new Binder(); 940 Channel channel = initalizeChannel(srcContext, srcLooper, listener, getMessenger(binder), 941 binder); 942 return channel; 943 } 944 945 /** 946 * Registers the application with the Wi-Fi framework. Enables system-only functionality. 947 * @hide 948 */ initializeInternal(Context srcContext, Looper srcLooper, ChannelListener listener)949 public Channel initializeInternal(Context srcContext, Looper srcLooper, 950 ChannelListener listener) { 951 return initalizeChannel(srcContext, srcLooper, listener, getP2pStateMachineMessenger(), 952 null); 953 } 954 initalizeChannel(Context srcContext, Looper srcLooper, ChannelListener listener, Messenger messenger, Binder binder)955 private Channel initalizeChannel(Context srcContext, Looper srcLooper, ChannelListener listener, 956 Messenger messenger, Binder binder) { 957 if (messenger == null) return null; 958 959 Channel c = new Channel(srcContext, srcLooper, listener, binder, this); 960 if (c.mAsyncChannel.connectSync(srcContext, c.mHandler, messenger) 961 == AsyncChannel.STATUS_SUCCESSFUL) { 962 return c; 963 } else { 964 c.close(); 965 return null; 966 } 967 } 968 969 /** 970 * Initiate peer discovery. A discovery process involves scanning for available Wi-Fi peers 971 * for the purpose of establishing a connection. 972 * 973 * <p> The function call immediately returns after sending a discovery request 974 * to the framework. The application is notified of a success or failure to initiate 975 * discovery through listener callbacks {@link ActionListener#onSuccess} or 976 * {@link ActionListener#onFailure}. 977 * 978 * <p> The discovery remains active until a connection is initiated or 979 * a p2p group is formed. Register for {@link #WIFI_P2P_PEERS_CHANGED_ACTION} intent to 980 * determine when the framework notifies of a change as peers are discovered. 981 * 982 * <p> Upon receiving a {@link #WIFI_P2P_PEERS_CHANGED_ACTION} intent, an application 983 * can request for the list of peers using {@link #requestPeers}. 984 * 985 * @param c is the channel created at {@link #initialize} 986 * @param listener for callbacks on success or failure. Can be null. 987 */ discoverPeers(Channel c, ActionListener listener)988 public void discoverPeers(Channel c, ActionListener listener) { 989 checkChannel(c); 990 c.mAsyncChannel.sendMessage(DISCOVER_PEERS, 0, c.putListener(listener)); 991 } 992 993 /** 994 * Stop an ongoing peer discovery 995 * 996 * <p> The function call immediately returns after sending a stop request 997 * to the framework. The application is notified of a success or failure to initiate 998 * stop through listener callbacks {@link ActionListener#onSuccess} or 999 * {@link ActionListener#onFailure}. 1000 * 1001 * @param c is the channel created at {@link #initialize} 1002 * @param listener for callbacks on success or failure. Can be null. 1003 */ stopPeerDiscovery(Channel c, ActionListener listener)1004 public void stopPeerDiscovery(Channel c, ActionListener listener) { 1005 checkChannel(c); 1006 c.mAsyncChannel.sendMessage(STOP_DISCOVERY, 0, c.putListener(listener)); 1007 } 1008 1009 /** 1010 * Start a p2p connection to a device with the specified configuration. 1011 * 1012 * <p> The function call immediately returns after sending a connection request 1013 * to the framework. The application is notified of a success or failure to initiate 1014 * connect through listener callbacks {@link ActionListener#onSuccess} or 1015 * {@link ActionListener#onFailure}. 1016 * 1017 * <p> Register for {@link #WIFI_P2P_CONNECTION_CHANGED_ACTION} intent to 1018 * determine when the framework notifies of a change in connectivity. 1019 * 1020 * <p> If the current device is not part of a p2p group, a connect request initiates 1021 * a group negotiation with the peer. 1022 * 1023 * <p> If the current device is part of an existing p2p group or has created 1024 * a p2p group with {@link #createGroup}, an invitation to join the group is sent to 1025 * the peer device. 1026 * 1027 * @param c is the channel created at {@link #initialize} 1028 * @param config options as described in {@link WifiP2pConfig} class 1029 * @param listener for callbacks on success or failure. Can be null. 1030 */ connect(Channel c, WifiP2pConfig config, ActionListener listener)1031 public void connect(Channel c, WifiP2pConfig config, ActionListener listener) { 1032 checkChannel(c); 1033 checkP2pConfig(config); 1034 c.mAsyncChannel.sendMessage(CONNECT, 0, c.putListener(listener), config); 1035 } 1036 1037 /** 1038 * Cancel any ongoing p2p group negotiation 1039 * 1040 * <p> The function call immediately returns after sending a connection cancellation request 1041 * to the framework. The application is notified of a success or failure to initiate 1042 * cancellation through listener callbacks {@link ActionListener#onSuccess} or 1043 * {@link ActionListener#onFailure}. 1044 * 1045 * @param c is the channel created at {@link #initialize} 1046 * @param listener for callbacks on success or failure. Can be null. 1047 */ cancelConnect(Channel c, ActionListener listener)1048 public void cancelConnect(Channel c, ActionListener listener) { 1049 checkChannel(c); 1050 c.mAsyncChannel.sendMessage(CANCEL_CONNECT, 0, c.putListener(listener)); 1051 } 1052 1053 /** 1054 * Create a p2p group with the current device as the group owner. This essentially creates 1055 * an access point that can accept connections from legacy clients as well as other p2p 1056 * devices. 1057 * 1058 * <p class="note"><strong>Note:</strong> 1059 * This function would normally not be used unless the current device needs 1060 * to form a p2p connection with a legacy client 1061 * 1062 * <p> The function call immediately returns after sending a group creation request 1063 * to the framework. The application is notified of a success or failure to initiate 1064 * group creation through listener callbacks {@link ActionListener#onSuccess} or 1065 * {@link ActionListener#onFailure}. 1066 * 1067 * <p> Application can request for the group details with {@link #requestGroupInfo}. 1068 * 1069 * @param c is the channel created at {@link #initialize} 1070 * @param listener for callbacks on success or failure. Can be null. 1071 */ createGroup(Channel c, ActionListener listener)1072 public void createGroup(Channel c, ActionListener listener) { 1073 checkChannel(c); 1074 c.mAsyncChannel.sendMessage(CREATE_GROUP, WifiP2pGroup.PERSISTENT_NET_ID, 1075 c.putListener(listener)); 1076 } 1077 1078 /** 1079 * Remove the current p2p group. 1080 * 1081 * <p> The function call immediately returns after sending a group removal request 1082 * to the framework. The application is notified of a success or failure to initiate 1083 * group removal through listener callbacks {@link ActionListener#onSuccess} or 1084 * {@link ActionListener#onFailure}. 1085 * 1086 * @param c is the channel created at {@link #initialize} 1087 * @param listener for callbacks on success or failure. Can be null. 1088 */ removeGroup(Channel c, ActionListener listener)1089 public void removeGroup(Channel c, ActionListener listener) { 1090 checkChannel(c); 1091 c.mAsyncChannel.sendMessage(REMOVE_GROUP, 0, c.putListener(listener)); 1092 } 1093 1094 /** @hide */ listen(Channel c, boolean enable, ActionListener listener)1095 public void listen(Channel c, boolean enable, ActionListener listener) { 1096 checkChannel(c); 1097 c.mAsyncChannel.sendMessage(enable ? START_LISTEN : STOP_LISTEN, 1098 0, c.putListener(listener)); 1099 } 1100 1101 /** @hide */ setWifiP2pChannels(Channel c, int lc, int oc, ActionListener listener)1102 public void setWifiP2pChannels(Channel c, int lc, int oc, ActionListener listener) { 1103 checkChannel(c); 1104 Bundle p2pChannels = new Bundle(); 1105 p2pChannels.putInt("lc", lc); 1106 p2pChannels.putInt("oc", oc); 1107 c.mAsyncChannel.sendMessage(SET_CHANNEL, 0, c.putListener(listener), p2pChannels); 1108 } 1109 1110 /** 1111 * Start a Wi-Fi Protected Setup (WPS) session. 1112 * 1113 * <p> The function call immediately returns after sending a request to start a 1114 * WPS session. Currently, this is only valid if the current device is running 1115 * as a group owner to allow any new clients to join the group. The application 1116 * is notified of a success or failure to initiate WPS through listener callbacks 1117 * {@link ActionListener#onSuccess} or {@link ActionListener#onFailure}. 1118 * @hide 1119 */ startWps(Channel c, WpsInfo wps, ActionListener listener)1120 public void startWps(Channel c, WpsInfo wps, ActionListener listener) { 1121 checkChannel(c); 1122 c.mAsyncChannel.sendMessage(START_WPS, 0, c.putListener(listener), wps); 1123 } 1124 1125 /** 1126 * Register a local service for service discovery. If a local service is registered, 1127 * the framework automatically responds to a service discovery request from a peer. 1128 * 1129 * <p> The function call immediately returns after sending a request to add a local 1130 * service to the framework. The application is notified of a success or failure to 1131 * add service through listener callbacks {@link ActionListener#onSuccess} or 1132 * {@link ActionListener#onFailure}. 1133 * 1134 * <p>The service information is set through {@link WifiP2pServiceInfo}.<br> 1135 * or its subclass calls {@link WifiP2pUpnpServiceInfo#newInstance} or 1136 * {@link WifiP2pDnsSdServiceInfo#newInstance} for a Upnp or Bonjour service 1137 * respectively 1138 * 1139 * <p>The service information can be cleared with calls to 1140 * {@link #removeLocalService} or {@link #clearLocalServices}. 1141 * 1142 * @param c is the channel created at {@link #initialize} 1143 * @param servInfo is a local service information. 1144 * @param listener for callbacks on success or failure. Can be null. 1145 */ addLocalService(Channel c, WifiP2pServiceInfo servInfo, ActionListener listener)1146 public void addLocalService(Channel c, WifiP2pServiceInfo servInfo, ActionListener listener) { 1147 checkChannel(c); 1148 checkServiceInfo(servInfo); 1149 c.mAsyncChannel.sendMessage(ADD_LOCAL_SERVICE, 0, c.putListener(listener), servInfo); 1150 } 1151 1152 /** 1153 * Remove a registered local service added with {@link #addLocalService} 1154 * 1155 * <p> The function call immediately returns after sending a request to remove a 1156 * local service to the framework. The application is notified of a success or failure to 1157 * add service through listener callbacks {@link ActionListener#onSuccess} or 1158 * {@link ActionListener#onFailure}. 1159 * 1160 * @param c is the channel created at {@link #initialize} 1161 * @param servInfo is the local service information. 1162 * @param listener for callbacks on success or failure. Can be null. 1163 */ removeLocalService(Channel c, WifiP2pServiceInfo servInfo, ActionListener listener)1164 public void removeLocalService(Channel c, WifiP2pServiceInfo servInfo, 1165 ActionListener listener) { 1166 checkChannel(c); 1167 checkServiceInfo(servInfo); 1168 c.mAsyncChannel.sendMessage(REMOVE_LOCAL_SERVICE, 0, c.putListener(listener), servInfo); 1169 } 1170 1171 /** 1172 * Clear all registered local services of service discovery. 1173 * 1174 * <p> The function call immediately returns after sending a request to clear all 1175 * local services to the framework. The application is notified of a success or failure to 1176 * add service through listener callbacks {@link ActionListener#onSuccess} or 1177 * {@link ActionListener#onFailure}. 1178 * 1179 * @param c is the channel created at {@link #initialize} 1180 * @param listener for callbacks on success or failure. Can be null. 1181 */ clearLocalServices(Channel c, ActionListener listener)1182 public void clearLocalServices(Channel c, ActionListener listener) { 1183 checkChannel(c); 1184 c.mAsyncChannel.sendMessage(CLEAR_LOCAL_SERVICES, 0, c.putListener(listener)); 1185 } 1186 1187 /** 1188 * Register a callback to be invoked on receiving service discovery response. 1189 * Used only for vendor specific protocol right now. For Bonjour or Upnp, use 1190 * {@link #setDnsSdResponseListeners} or {@link #setUpnpServiceResponseListener} 1191 * respectively. 1192 * 1193 * <p> see {@link #discoverServices} for the detail. 1194 * 1195 * @param c is the channel created at {@link #initialize} 1196 * @param listener for callbacks on receiving service discovery response. 1197 */ setServiceResponseListener(Channel c, ServiceResponseListener listener)1198 public void setServiceResponseListener(Channel c, 1199 ServiceResponseListener listener) { 1200 checkChannel(c); 1201 c.mServRspListener = listener; 1202 } 1203 1204 /** 1205 * Register a callback to be invoked on receiving Bonjour service discovery 1206 * response. 1207 * 1208 * <p> see {@link #discoverServices} for the detail. 1209 * 1210 * @param c 1211 * @param servListener is for listening to a Bonjour service response 1212 * @param txtListener is for listening to a Bonjour TXT record response 1213 */ setDnsSdResponseListeners(Channel c, DnsSdServiceResponseListener servListener, DnsSdTxtRecordListener txtListener)1214 public void setDnsSdResponseListeners(Channel c, 1215 DnsSdServiceResponseListener servListener, DnsSdTxtRecordListener txtListener) { 1216 checkChannel(c); 1217 c.mDnsSdServRspListener = servListener; 1218 c.mDnsSdTxtListener = txtListener; 1219 } 1220 1221 /** 1222 * Register a callback to be invoked on receiving upnp service discovery 1223 * response. 1224 * 1225 * <p> see {@link #discoverServices} for the detail. 1226 * 1227 * @param c is the channel created at {@link #initialize} 1228 * @param listener for callbacks on receiving service discovery response. 1229 */ setUpnpServiceResponseListener(Channel c, UpnpServiceResponseListener listener)1230 public void setUpnpServiceResponseListener(Channel c, 1231 UpnpServiceResponseListener listener) { 1232 checkChannel(c); 1233 c.mUpnpServRspListener = listener; 1234 } 1235 1236 /** 1237 * Initiate service discovery. A discovery process involves scanning for 1238 * requested services for the purpose of establishing a connection to a peer 1239 * that supports an available service. 1240 * 1241 * <p> The function call immediately returns after sending a request to start service 1242 * discovery to the framework. The application is notified of a success or failure to initiate 1243 * discovery through listener callbacks {@link ActionListener#onSuccess} or 1244 * {@link ActionListener#onFailure}. 1245 * 1246 * <p> The services to be discovered are specified with calls to {@link #addServiceRequest}. 1247 * 1248 * <p>The application is notified of the response against the service discovery request 1249 * through listener callbacks registered by {@link #setServiceResponseListener} or 1250 * {@link #setDnsSdResponseListeners}, or {@link #setUpnpServiceResponseListener}. 1251 * 1252 * @param c is the channel created at {@link #initialize} 1253 * @param listener for callbacks on success or failure. Can be null. 1254 */ discoverServices(Channel c, ActionListener listener)1255 public void discoverServices(Channel c, ActionListener listener) { 1256 checkChannel(c); 1257 c.mAsyncChannel.sendMessage(DISCOVER_SERVICES, 0, c.putListener(listener)); 1258 } 1259 1260 /** 1261 * Add a service discovery request. 1262 * 1263 * <p> The function call immediately returns after sending a request to add service 1264 * discovery request to the framework. The application is notified of a success or failure to 1265 * add service through listener callbacks {@link ActionListener#onSuccess} or 1266 * {@link ActionListener#onFailure}. 1267 * 1268 * <p>After service discovery request is added, you can initiate service discovery by 1269 * {@link #discoverServices}. 1270 * 1271 * <p>The added service requests can be cleared with calls to 1272 * {@link #removeServiceRequest(Channel, WifiP2pServiceRequest, ActionListener)} or 1273 * {@link #clearServiceRequests(Channel, ActionListener)}. 1274 * 1275 * @param c is the channel created at {@link #initialize} 1276 * @param req is the service discovery request. 1277 * @param listener for callbacks on success or failure. Can be null. 1278 */ addServiceRequest(Channel c, WifiP2pServiceRequest req, ActionListener listener)1279 public void addServiceRequest(Channel c, 1280 WifiP2pServiceRequest req, ActionListener listener) { 1281 checkChannel(c); 1282 checkServiceRequest(req); 1283 c.mAsyncChannel.sendMessage(ADD_SERVICE_REQUEST, 0, 1284 c.putListener(listener), req); 1285 } 1286 1287 /** 1288 * Remove a specified service discovery request added with {@link #addServiceRequest} 1289 * 1290 * <p> The function call immediately returns after sending a request to remove service 1291 * discovery request to the framework. The application is notified of a success or failure to 1292 * add service through listener callbacks {@link ActionListener#onSuccess} or 1293 * {@link ActionListener#onFailure}. 1294 * 1295 * @param c is the channel created at {@link #initialize} 1296 * @param req is the service discovery request. 1297 * @param listener for callbacks on success or failure. Can be null. 1298 */ removeServiceRequest(Channel c, WifiP2pServiceRequest req, ActionListener listener)1299 public void removeServiceRequest(Channel c, WifiP2pServiceRequest req, 1300 ActionListener listener) { 1301 checkChannel(c); 1302 checkServiceRequest(req); 1303 c.mAsyncChannel.sendMessage(REMOVE_SERVICE_REQUEST, 0, 1304 c.putListener(listener), req); 1305 } 1306 1307 /** 1308 * Clear all registered service discovery requests. 1309 * 1310 * <p> The function call immediately returns after sending a request to clear all 1311 * service discovery requests to the framework. The application is notified of a success 1312 * or failure to add service through listener callbacks {@link ActionListener#onSuccess} or 1313 * {@link ActionListener#onFailure}. 1314 * 1315 * @param c is the channel created at {@link #initialize} 1316 * @param listener for callbacks on success or failure. Can be null. 1317 */ clearServiceRequests(Channel c, ActionListener listener)1318 public void clearServiceRequests(Channel c, ActionListener listener) { 1319 checkChannel(c); 1320 c.mAsyncChannel.sendMessage(CLEAR_SERVICE_REQUESTS, 1321 0, c.putListener(listener)); 1322 } 1323 1324 /** 1325 * Request the current list of peers. 1326 * 1327 * @param c is the channel created at {@link #initialize} 1328 * @param listener for callback when peer list is available. Can be null. 1329 */ requestPeers(Channel c, PeerListListener listener)1330 public void requestPeers(Channel c, PeerListListener listener) { 1331 checkChannel(c); 1332 Bundle callingPackage = new Bundle(); 1333 callingPackage.putString(CALLING_PACKAGE, c.mContext.getOpPackageName()); 1334 c.mAsyncChannel.sendMessage(REQUEST_PEERS, 0, c.putListener(listener), 1335 callingPackage); 1336 } 1337 1338 /** 1339 * Request device connection info. 1340 * 1341 * @param c is the channel created at {@link #initialize} 1342 * @param listener for callback when connection info is available. Can be null. 1343 */ requestConnectionInfo(Channel c, ConnectionInfoListener listener)1344 public void requestConnectionInfo(Channel c, ConnectionInfoListener listener) { 1345 checkChannel(c); 1346 c.mAsyncChannel.sendMessage(REQUEST_CONNECTION_INFO, 0, c.putListener(listener)); 1347 } 1348 1349 /** 1350 * Request p2p group info. 1351 * 1352 * @param c is the channel created at {@link #initialize} 1353 * @param listener for callback when group info is available. Can be null. 1354 */ requestGroupInfo(Channel c, GroupInfoListener listener)1355 public void requestGroupInfo(Channel c, GroupInfoListener listener) { 1356 checkChannel(c); 1357 c.mAsyncChannel.sendMessage(REQUEST_GROUP_INFO, 0, c.putListener(listener)); 1358 } 1359 1360 /** 1361 * Set p2p device name. 1362 * @hide 1363 * @param c is the channel created at {@link #initialize} 1364 * @param listener for callback when group info is available. Can be null. 1365 */ setDeviceName(Channel c, String devName, ActionListener listener)1366 public void setDeviceName(Channel c, String devName, ActionListener listener) { 1367 checkChannel(c); 1368 WifiP2pDevice d = new WifiP2pDevice(); 1369 d.deviceName = devName; 1370 c.mAsyncChannel.sendMessage(SET_DEVICE_NAME, 0, c.putListener(listener), d); 1371 } 1372 1373 /** @hide */ setWFDInfo( Channel c, WifiP2pWfdInfo wfdInfo, ActionListener listener)1374 public void setWFDInfo( 1375 Channel c, WifiP2pWfdInfo wfdInfo, 1376 ActionListener listener) { 1377 checkChannel(c); 1378 try { 1379 mService.checkConfigureWifiDisplayPermission(); 1380 } catch (RemoteException e) { 1381 e.rethrowFromSystemServer(); 1382 } 1383 c.mAsyncChannel.sendMessage(SET_WFD_INFO, 0, c.putListener(listener), wfdInfo); 1384 } 1385 1386 1387 /** 1388 * Delete a stored persistent group from the system settings. 1389 * 1390 * <p> The function call immediately returns after sending a persistent group removal request 1391 * to the framework. The application is notified of a success or failure to initiate 1392 * group removal through listener callbacks {@link ActionListener#onSuccess} or 1393 * {@link ActionListener#onFailure}. 1394 * 1395 * <p>The persistent p2p group list stored in the system can be obtained by 1396 * {@link #requestPersistentGroupInfo(Channel, PersistentGroupInfoListener)} and 1397 * a network id can be obtained by {@link WifiP2pGroup#getNetworkId()}. 1398 * 1399 * @param c is the channel created at {@link #initialize} 1400 * @param netId he network id of the p2p group. 1401 * @param listener for callbacks on success or failure. Can be null. 1402 * @hide 1403 */ deletePersistentGroup(Channel c, int netId, ActionListener listener)1404 public void deletePersistentGroup(Channel c, int netId, ActionListener listener) { 1405 checkChannel(c); 1406 c.mAsyncChannel.sendMessage(DELETE_PERSISTENT_GROUP, netId, c.putListener(listener)); 1407 } 1408 1409 /** 1410 * Request a list of all the persistent p2p groups stored in system. 1411 * 1412 * @param c is the channel created at {@link #initialize} 1413 * @param listener for callback when persistent group info list is available. Can be null. 1414 * @hide 1415 */ requestPersistentGroupInfo(Channel c, PersistentGroupInfoListener listener)1416 public void requestPersistentGroupInfo(Channel c, PersistentGroupInfoListener listener) { 1417 checkChannel(c); 1418 c.mAsyncChannel.sendMessage(REQUEST_PERSISTENT_GROUP_INFO, 0, c.putListener(listener)); 1419 } 1420 1421 /** @hide */ 1422 public static final int MIRACAST_DISABLED = 0; 1423 /** @hide */ 1424 public static final int MIRACAST_SOURCE = 1; 1425 /** @hide */ 1426 public static final int MIRACAST_SINK = 2; 1427 /** Internal use only @hide */ setMiracastMode(int mode)1428 public void setMiracastMode(int mode) { 1429 try { 1430 mService.setMiracastMode(mode); 1431 } catch (RemoteException e) { 1432 throw e.rethrowFromSystemServer(); 1433 } 1434 } 1435 1436 /** 1437 * Get a reference to WifiP2pService handler. This is used to establish 1438 * an AsyncChannel communication with WifiService 1439 * 1440 * @param binder A binder for the service to associate with this client. 1441 * 1442 * @return Messenger pointing to the WifiP2pService handler 1443 * @hide 1444 */ getMessenger(Binder binder)1445 public Messenger getMessenger(Binder binder) { 1446 try { 1447 return mService.getMessenger(binder); 1448 } catch (RemoteException e) { 1449 throw e.rethrowFromSystemServer(); 1450 } 1451 } 1452 1453 /** 1454 * Get a reference to P2pStateMachine handler. This is used to establish 1455 * a priveleged AsyncChannel communication with WifiP2pService. 1456 * 1457 * @return Messenger pointing to the WifiP2pService handler 1458 * @hide 1459 */ getP2pStateMachineMessenger()1460 public Messenger getP2pStateMachineMessenger() { 1461 try { 1462 return mService.getP2pStateMachineMessenger(); 1463 } catch (RemoteException e) { 1464 throw e.rethrowFromSystemServer(); 1465 } 1466 } 1467 1468 /** 1469 * Get a handover request message for use in WFA NFC Handover transfer. 1470 * @hide 1471 */ getNfcHandoverRequest(Channel c, HandoverMessageListener listener)1472 public void getNfcHandoverRequest(Channel c, HandoverMessageListener listener) { 1473 checkChannel(c); 1474 c.mAsyncChannel.sendMessage(GET_HANDOVER_REQUEST, 0, c.putListener(listener)); 1475 } 1476 1477 1478 /** 1479 * Get a handover select message for use in WFA NFC Handover transfer. 1480 * @hide 1481 */ getNfcHandoverSelect(Channel c, HandoverMessageListener listener)1482 public void getNfcHandoverSelect(Channel c, HandoverMessageListener listener) { 1483 checkChannel(c); 1484 c.mAsyncChannel.sendMessage(GET_HANDOVER_SELECT, 0, c.putListener(listener)); 1485 } 1486 1487 /** 1488 * @hide 1489 */ initiatorReportNfcHandover(Channel c, String handoverSelect, ActionListener listener)1490 public void initiatorReportNfcHandover(Channel c, String handoverSelect, 1491 ActionListener listener) { 1492 checkChannel(c); 1493 Bundle bundle = new Bundle(); 1494 bundle.putString(EXTRA_HANDOVER_MESSAGE, handoverSelect); 1495 c.mAsyncChannel.sendMessage(INITIATOR_REPORT_NFC_HANDOVER, 0, 1496 c.putListener(listener), bundle); 1497 } 1498 1499 1500 /** 1501 * @hide 1502 */ responderReportNfcHandover(Channel c, String handoverRequest, ActionListener listener)1503 public void responderReportNfcHandover(Channel c, String handoverRequest, 1504 ActionListener listener) { 1505 checkChannel(c); 1506 Bundle bundle = new Bundle(); 1507 bundle.putString(EXTRA_HANDOVER_MESSAGE, handoverRequest); 1508 c.mAsyncChannel.sendMessage(RESPONDER_REPORT_NFC_HANDOVER, 0, 1509 c.putListener(listener), bundle); 1510 } 1511 } 1512