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