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