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