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