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