/* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.net.wifi.p2p; import android.annotation.CallbackExecutor; import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.annotation.SystemService; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.net.MacAddress; import android.net.NetworkInfo; import android.net.wifi.ScanResult; import android.net.wifi.WifiManager; import android.net.wifi.WpsInfo; import android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceInfo; import android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceResponse; import android.net.wifi.p2p.nsd.WifiP2pServiceInfo; import android.net.wifi.p2p.nsd.WifiP2pServiceRequest; import android.net.wifi.p2p.nsd.WifiP2pServiceResponse; import android.net.wifi.p2p.nsd.WifiP2pUpnpServiceInfo; import android.net.wifi.p2p.nsd.WifiP2pUpnpServiceResponse; import android.os.Binder; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.Messenger; import android.os.RemoteException; import android.text.TextUtils; import android.util.CloseGuard; import android.util.Log; import android.util.SparseArray; import android.view.Display; import androidx.annotation.RequiresApi; import com.android.internal.util.AsyncChannel; import com.android.internal.util.Protocol; import com.android.modules.utils.build.SdkLevel; import com.android.wifi.flags.Flags; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.ref.Reference; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.Executor; import java.util.function.Consumer; /** * This class provides the API for managing Wi-Fi peer-to-peer connectivity. This lets an * application discover available peers, setup connection to peers and query for the list of peers. * When a p2p connection is formed over wifi, the device continues to maintain the uplink * connection over mobile or any other available network for internet connectivity on the device. * *
The API is asynchronous and responses to requests from an application are on listener * callbacks provided by the application. The application needs to do an initialization with * {@link #initialize} before doing any p2p operation. * *
Most application calls need a {@link ActionListener} instance for receiving callbacks * {@link ActionListener#onSuccess} or {@link ActionListener#onFailure}. Action callbacks * indicate whether the initiation of the action was a success or a failure. * Upon failure, the reason of failure can be one of {@link #ERROR}, {@link #P2P_UNSUPPORTED} * or {@link #BUSY}. * *
An application can initiate discovery of peers with {@link #discoverPeers}. An initiated * discovery request from an application stays active until the device starts connecting to a peer * ,forms a p2p group or there is an explicit {@link #stopPeerDiscovery}. * Applications can listen to {@link #WIFI_P2P_DISCOVERY_CHANGED_ACTION} to know if a peer-to-peer * discovery is running or stopped. Additionally, {@link #WIFI_P2P_PEERS_CHANGED_ACTION} indicates * if the peer list has changed. * *
When an application needs to fetch the current list of peers, it can request the list * of peers with {@link #requestPeers}. When the peer list is available * {@link PeerListListener#onPeersAvailable} is called with the device list. * *
An application can initiate a connection request to a peer through {@link #connect}. See * {@link WifiP2pConfig} for details on setting up the configuration. For communication with legacy * Wi-Fi devices that do not support p2p, an app can create a group using {@link #createGroup} * which creates an access point whose details can be fetched with {@link #requestGroupInfo}. * *
After a successful group formation through {@link #createGroup} or through {@link #connect}, * use {@link #requestConnectionInfo} to fetch the connection details. The connection info * {@link WifiP2pInfo} contains the address of the group owner * {@link WifiP2pInfo#groupOwnerAddress} and a flag {@link WifiP2pInfo#isGroupOwner} to indicate * if the current device is a p2p group owner. A p2p client can thus communicate with * the p2p group owner through a socket connection. If the current device is the p2p group owner, * {@link WifiP2pInfo#groupOwnerAddress} is anonymized unless the caller holds the * {@code android.Manifest.permission#LOCAL_MAC_ADDRESS} permission. * *
With peer discovery using {@link #discoverPeers}, an application discovers the neighboring * peers, but has no good way to figure out which peer to establish a connection with. For example, * if a game application is interested in finding all the neighboring peers that are also running * the same game, it has no way to find out until after the connection is setup. Pre-association * service discovery is meant to address this issue of filtering the peers based on the running * services. * *
With pre-association service discovery, an application can advertise a service for a * application on a peer device prior to a connection setup between the devices. * Currently, DNS based service discovery (Bonjour) and Upnp are the higher layer protocols * supported. Get Bonjour resources at dns-sd.org and Upnp resources at upnp.org * As an example, a video application can discover a Upnp capable media renderer * prior to setting up a Wi-fi p2p connection with the device. * *
An application can advertise a Upnp or a Bonjour service with a call to * {@link #addLocalService}. After a local service is added, * the framework automatically responds to a peer application discovering the service prior * to establishing a p2p connection. A call to {@link #removeLocalService} removes a local * service and {@link #clearLocalServices} can be used to clear all local services. * *
An application that is looking for peer devices that support certain services * can do so with a call to {@link #discoverServices}. Prior to initiating the discovery, * application can add service discovery request with a call to {@link #addServiceRequest}, * remove a service discovery request with a call to {@link #removeServiceRequest} or clear * all requests with a call to {@link #clearServiceRequests}. When no service requests remain, * a previously running service discovery will stop. * * The application is notified of a result of service discovery request through listener callbacks * set through {@link #setDnsSdResponseListeners} for Bonjour or * {@link #setUpnpServiceResponseListener} for Upnp. * *
Note: * Registering an application handler with {@link #initialize} requires the permissions * {@link android.Manifest.permission#ACCESS_WIFI_STATE} and * {@link android.Manifest.permission#CHANGE_WIFI_STATE} to perform any further peer-to-peer * operations. * * {@see WifiP2pConfig} * {@see WifiP2pInfo} * {@see WifiP2pGroup} * {@see WifiP2pDevice} * {@see WifiP2pDeviceList} * {@see android.net.wifi.WpsInfo} */ @SystemService(Context.WIFI_P2P_SERVICE) public class WifiP2pManager { private static final String TAG = "WifiP2pManager"; /** @hide */ public static final long FEATURE_SET_VENDOR_ELEMENTS = 1L << 0; /** @hide */ public static final long FEATURE_FLEXIBLE_DISCOVERY = 1L << 1; /** @hide */ public static final long FEATURE_GROUP_CLIENT_REMOVAL = 1L << 2; /** @hide */ public static final long FEATURE_GROUP_OWNER_IPV6_LINK_LOCAL_ADDRESS_PROVIDED = 1L << 3; /** * Extra for transporting a WifiP2pConfig * @hide */ public static final String EXTRA_PARAM_KEY_CONFIG = "android.net.wifi.p2p.EXTRA_PARAM_KEY_CONFIG"; /** * Extra for transporting a WifiP2pServiceInfo * @hide */ public static final String EXTRA_PARAM_KEY_SERVICE_INFO = "android.net.wifi.p2p.EXTRA_PARAM_KEY_SERVICE_INFO"; /** * Extra for transporting a peer discovery frequency. * @hide */ public static final String EXTRA_PARAM_KEY_PEER_DISCOVERY_FREQ = "android.net.wifi.p2p.EXTRA_PARAM_KEY_PEER_DISCOVERY_FREQ"; /** * Extra for transporting a peer MAC address. * @hide */ public static final String EXTRA_PARAM_KEY_PEER_ADDRESS = "android.net.wifi.p2p.EXTRA_PARAM_KEY_PEER_ADDRESS"; /** * Extra used to indicate that a message is sent from Wifi internally * @hide */ public static final String EXTRA_PARAM_KEY_INTERNAL_MESSAGE = "android.net.wifi.p2p.EXTRA_PARAM_KEY_INTERNAL_MESSAGE"; /** * Used to communicate the Display ID for multi display devices. * @hide **/ public static final String EXTRA_PARAM_KEY_DISPLAY_ID = "android.net.wifi.p2p.EXTRA_PARAM_KEY_DISPLAY_ID"; /** * Extra for transporting a WifiP2pDevice. * @hide */ public static final String EXTRA_PARAM_KEY_DEVICE = "android.net.wifi.p2p.EXTRA_PARAM_KEY_DEVICE"; /** * Extra for transporting a WPS PIN. * @hide */ public static final String EXTRA_PARAM_KEY_WPS_PIN = "android.net.wifi.p2p.EXTRA_PARAM_KEY_WPS_PIN"; /** * Extra for transporting vendor-specific information element list * @hide */ public static final String EXTRA_PARAM_KEY_INFORMATION_ELEMENT_LIST = "android.net.wifi.p2p.EXTRA_PARAM_KEY_INFORMATION_ELEMENT_LIST"; /** * Extra for transporting discovery config with vendor-specific data * @hide */ public static final String EXTRA_PARAM_KEY_DISCOVERY_CONFIG = "android.net.wifi.p2p.EXTRA_PARAM_KEY_DISCOVERY_CONFIG"; /** * Extra for transporting extended listening parameters * @hide */ public static final String EXTRA_PARAM_KEY_EXT_LISTEN_PARAMS = "android.net.wifi.p2p.EXTRA_PARAM_KEY_EXT_LISTEN_PARAMS"; /** * Key for transporting a bundle of extra information. * @hide */ public static final String EXTRA_PARAM_KEY_BUNDLE = "android.net.wifi.p2p.EXTRA_PARAM_KEY_BUNDLE"; /** * Broadcast intent action to indicate whether Wi-Fi p2p is enabled or disabled. An * extra {@link #EXTRA_WIFI_STATE} provides the state information as int. * * @see #EXTRA_WIFI_STATE */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String WIFI_P2P_STATE_CHANGED_ACTION = "android.net.wifi.p2p.STATE_CHANGED"; /** * The lookup key for an int that indicates whether Wi-Fi p2p is enabled or disabled. * Retrieve it with {@link android.content.Intent#getIntExtra(String,int)}. * * @see #WIFI_P2P_STATE_DISABLED * @see #WIFI_P2P_STATE_ENABLED */ public static final String EXTRA_WIFI_STATE = "wifi_p2p_state"; /** @hide */ @IntDef({ WIFI_P2P_STATE_DISABLED, WIFI_P2P_STATE_ENABLED}) @Retention(RetentionPolicy.SOURCE) public @interface WifiP2pState { } /** * Wi-Fi p2p is disabled. * * @see #WIFI_P2P_STATE_CHANGED_ACTION */ public static final int WIFI_P2P_STATE_DISABLED = 1; /** * Wi-Fi p2p is enabled. * * @see #WIFI_P2P_STATE_CHANGED_ACTION */ public static final int WIFI_P2P_STATE_ENABLED = 2; /** * Broadcast intent action indicating that the state of Wi-Fi p2p connectivity * has changed. One extra {@link #EXTRA_WIFI_P2P_INFO} provides the p2p connection info in * the form of a {@link WifiP2pInfo} object. Another extra {@link #EXTRA_NETWORK_INFO} provides * the network info in the form of a {@link android.net.NetworkInfo}. A third extra provides * the details of the group and may contain a {@code null}. * * All of these permissions are required to receive this broadcast: * {@link android.Manifest.permission#ACCESS_WIFI_STATE} and either * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} or * {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} * * @see #EXTRA_WIFI_P2P_INFO * @see #EXTRA_NETWORK_INFO * @see #EXTRA_WIFI_P2P_GROUP */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String WIFI_P2P_CONNECTION_CHANGED_ACTION = "android.net.wifi.p2p.CONNECTION_STATE_CHANGE"; /** * The lookup key for a {@link android.net.wifi.p2p.WifiP2pInfo} object * Retrieve with {@link android.content.Intent#getParcelableExtra(String)}. */ public static final String EXTRA_WIFI_P2P_INFO = "wifiP2pInfo"; /** * The lookup key for a {@link android.net.NetworkInfo} object associated with the * p2p network. Retrieve with * {@link android.content.Intent#getParcelableExtra(String)}. */ public static final String EXTRA_NETWORK_INFO = "networkInfo"; /** * The lookup key for a {@link android.net.wifi.p2p.WifiP2pGroup} object * associated with the p2p network. Retrieve with * {@link android.content.Intent#getParcelableExtra(String)}. */ public static final String EXTRA_WIFI_P2P_GROUP = "p2pGroupInfo"; /** * Broadcast intent action indicating that the available peer list has changed. This * can be sent as a result of peers being found, lost or updated. * * All of these permissions are required to receive this broadcast: * {@link android.Manifest.permission#ACCESS_WIFI_STATE} and either * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} or * {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} * *
An extra {@link #EXTRA_P2P_DEVICE_LIST} provides the full list of * current peers. The full list of peers can also be obtained any time with * {@link #requestPeers}. * * @see #EXTRA_P2P_DEVICE_LIST */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String WIFI_P2P_PEERS_CHANGED_ACTION = "android.net.wifi.p2p.PEERS_CHANGED"; /** * The lookup key for a {@link android.net.wifi.p2p.WifiP2pDeviceList} object representing * the new peer list when {@link #WIFI_P2P_PEERS_CHANGED_ACTION} broadcast is sent. * *
Retrieve with {@link android.content.Intent#getParcelableExtra(String)}. */ public static final String EXTRA_P2P_DEVICE_LIST = "wifiP2pDeviceList"; /** * Broadcast intent action indicating that peer discovery has either started or stopped. * One extra {@link #EXTRA_DISCOVERY_STATE} indicates whether discovery has started * or stopped. * *
Note that discovery will be stopped during a connection setup. If the application tries * to re-initiate discovery during this time, it can fail. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String WIFI_P2P_DISCOVERY_CHANGED_ACTION = "android.net.wifi.p2p.DISCOVERY_STATE_CHANGE"; /** * The lookup key for an int that indicates whether p2p discovery has started or stopped. * Retrieve it with {@link android.content.Intent#getIntExtra(String,int)}. * * @see #WIFI_P2P_DISCOVERY_STARTED * @see #WIFI_P2P_DISCOVERY_STOPPED */ public static final String EXTRA_DISCOVERY_STATE = "discoveryState"; /** @hide */ @IntDef({ WIFI_P2P_DISCOVERY_STOPPED, WIFI_P2P_DISCOVERY_STARTED}) @Retention(RetentionPolicy.SOURCE) public @interface WifiP2pDiscoveryState { } /** * p2p discovery has stopped * * @see #WIFI_P2P_DISCOVERY_CHANGED_ACTION */ public static final int WIFI_P2P_DISCOVERY_STOPPED = 1; /** * p2p discovery has started * * @see #WIFI_P2P_DISCOVERY_CHANGED_ACTION */ public static final int WIFI_P2P_DISCOVERY_STARTED = 2; /** * Broadcast intent action indicating that peer listen has either started or stopped. * One extra {@link #EXTRA_LISTEN_STATE} indicates whether listen has started or stopped. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_WIFI_P2P_LISTEN_STATE_CHANGED = "android.net.wifi.p2p.action.WIFI_P2P_LISTEN_STATE_CHANGED"; /** * The lookup key for an int that indicates whether p2p listen has started or stopped. * Retrieve it with {@link android.content.Intent#getIntExtra(String,int)}. * * @see #WIFI_P2P_LISTEN_STARTED * @see #WIFI_P2P_LISTEN_STOPPED */ public static final String EXTRA_LISTEN_STATE = "android.net.wifi.p2p.extra.LISTEN_STATE"; /** @hide */ @IntDef({ WIFI_P2P_LISTEN_STOPPED, WIFI_P2P_LISTEN_STARTED}) @Retention(RetentionPolicy.SOURCE) public @interface WifiP2pListenState { } /** * p2p listen has stopped * * @see #ACTION_WIFI_P2P_LISTEN_STATE_CHANGED */ public static final int WIFI_P2P_LISTEN_STOPPED = 1; /** * p2p listen has started * * @see #ACTION_WIFI_P2P_LISTEN_STATE_CHANGED */ public static final int WIFI_P2P_LISTEN_STARTED = 2; /** * Broadcast intent action indicating that this device details have changed. * *
An extra {@link #EXTRA_WIFI_P2P_DEVICE} provides this device details. * The valid device details can also be obtained with * {@link #requestDeviceInfo(Channel, DeviceInfoListener)} when p2p is enabled. * To get information notifications on P2P getting enabled refers * {@link #WIFI_P2P_STATE_ENABLED}. * *
The {@link #EXTRA_WIFI_P2P_DEVICE} extra contains an anonymized version of the device's * MAC address. Callers holding the {@code android.Manifest.permission#LOCAL_MAC_ADDRESS} * permission can use {@link #requestDeviceInfo} to obtain the actual MAC address of this * device. * * All of these permissions are required to receive this broadcast: * {@link android.Manifest.permission#ACCESS_WIFI_STATE} and either * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} or * {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} * * @see #EXTRA_WIFI_P2P_DEVICE */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String WIFI_P2P_THIS_DEVICE_CHANGED_ACTION = "android.net.wifi.p2p.THIS_DEVICE_CHANGED"; /** * The lookup key for a {@link android.net.wifi.p2p.WifiP2pDevice} object * Retrieve with {@link android.content.Intent#getParcelableExtra(String)}. */ public static final String EXTRA_WIFI_P2P_DEVICE = "wifiP2pDevice"; /** * Broadcast intent action indicating that remembered persistent groups have changed. * * You can not receive this through components declared * in manifests, only by explicitly registering for it with * {@link android.content.Context#registerReceiver(android.content.BroadcastReceiver, * android.content.IntentFilter) Context.registerReceiver()}. * * @hide */ @SystemApi public static final String ACTION_WIFI_P2P_PERSISTENT_GROUPS_CHANGED = "android.net.wifi.p2p.action.WIFI_P2P_PERSISTENT_GROUPS_CHANGED"; /** * Broadcast intent action indicating whether or not current connecting * request is accepted. * * The connecting request is initiated by * {@link #connect(Channel, WifiP2pConfig, ActionListener)}. *
The {@link #EXTRA_REQUEST_RESPONSE} extra indicates whether or not current * request is accepted or rejected. *
The {@link #EXTRA_REQUEST_CONFIG} extra indicates the responsed configuration.
*/
public static final String ACTION_WIFI_P2P_REQUEST_RESPONSE_CHANGED =
"android.net.wifi.p2p.action.WIFI_P2P_REQUEST_RESPONSE_CHANGED";
/**
* The lookup key for the result of a request, true if accepted, false otherwise.
*/
public static final String EXTRA_REQUEST_RESPONSE =
"android.net.wifi.p2p.extra.REQUEST_RESPONSE";
/**
* The lookup key for the {@link WifiP2pConfig} object of a request.
*/
public static final String EXTRA_REQUEST_CONFIG =
"android.net.wifi.p2p.extra.REQUEST_CONFIG";
/**
* The lookup key for a handover message returned by the WifiP2pService.
* @hide
*/
public static final String EXTRA_HANDOVER_MESSAGE =
"android.net.wifi.p2p.EXTRA_HANDOVER_MESSAGE";
/**
* The lookup key for a calling package name from WifiP2pManager
* @hide
*/
public static final String CALLING_PACKAGE =
"android.net.wifi.p2p.CALLING_PACKAGE";
/**
* The lookup key for a calling feature id from WifiP2pManager
* @hide
*/
public static final String CALLING_FEATURE_ID =
"android.net.wifi.p2p.CALLING_FEATURE_ID";
/**
* The lookup key for a calling package binder from WifiP2pManager
* @hide
*/
public static final String CALLING_BINDER =
"android.net.wifi.p2p.CALLING_BINDER";
/**
* Run P2P scan on all channels.
*/
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
public static final int WIFI_P2P_SCAN_FULL = 0;
/**
* Run P2P scan only on social channels.
*/
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
public static final int WIFI_P2P_SCAN_SOCIAL = 1;
/**
* Run P2P scan only on a specific channel.
*/
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
public static final int WIFI_P2P_SCAN_SINGLE_FREQ = 2;
/**
* Run P2P scan with config Params.
* @hide
*/
public static final int WIFI_P2P_SCAN_WITH_CONFIG_PARAMS = 3;
/** @hide */
@IntDef(prefix = {"WIFI_P2P_SCAN_"}, value = {
WIFI_P2P_SCAN_FULL,
WIFI_P2P_SCAN_SOCIAL,
WIFI_P2P_SCAN_SINGLE_FREQ})
@Retention(RetentionPolicy.SOURCE)
public @interface WifiP2pScanType {
}
/**
* Enter the P2P listen state with additional parameters.
* @hide
*/
public static final int WIFI_P2P_EXT_LISTEN_WITH_PARAMS = 1;
/**
* No channel specified for discover Peers APIs. Let lower layer decide the frequencies to scan
* based on the WifiP2pScanType.
* @hide
*/
public static final int WIFI_P2P_SCAN_FREQ_UNSPECIFIED = 0;
/**
* Maximum length in bytes of all vendor specific information elements (IEs) allowed to
* set during Wi-Fi Direct (P2P) discovery.
*/
private static final int WIFI_P2P_VENDOR_ELEMENTS_MAXIMUM_LENGTH = 512;
private Context mContext;
IWifiP2pManager mService;
private static final int BASE = Protocol.BASE_WIFI_P2P_MANAGER;
/** @hide */
public static final int DISCOVER_PEERS = BASE + 1;
/** @hide */
public static final int DISCOVER_PEERS_FAILED = BASE + 2;
/** @hide */
public static final int DISCOVER_PEERS_SUCCEEDED = BASE + 3;
/** @hide */
public static final int STOP_DISCOVERY = BASE + 4;
/** @hide */
public static final int STOP_DISCOVERY_FAILED = BASE + 5;
/** @hide */
public static final int STOP_DISCOVERY_SUCCEEDED = BASE + 6;
/** @hide */
public static final int CONNECT = BASE + 7;
/** @hide */
public static final int CONNECT_FAILED = BASE + 8;
/** @hide */
public static final int CONNECT_SUCCEEDED = BASE + 9;
/** @hide */
public static final int CANCEL_CONNECT = BASE + 10;
/** @hide */
public static final int CANCEL_CONNECT_FAILED = BASE + 11;
/** @hide */
public static final int CANCEL_CONNECT_SUCCEEDED = BASE + 12;
/** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public static final int CREATE_GROUP = BASE + 13;
/** @hide */
public static final int CREATE_GROUP_FAILED = BASE + 14;
/** @hide */
public static final int CREATE_GROUP_SUCCEEDED = BASE + 15;
/** @hide */
public static final int REMOVE_GROUP = BASE + 16;
/** @hide */
public static final int REMOVE_GROUP_FAILED = BASE + 17;
/** @hide */
public static final int REMOVE_GROUP_SUCCEEDED = BASE + 18;
/** @hide */
public static final int REQUEST_PEERS = BASE + 19;
/** @hide */
public static final int RESPONSE_PEERS = BASE + 20;
/** @hide */
public static final int REQUEST_CONNECTION_INFO = BASE + 21;
/** @hide */
public static final int RESPONSE_CONNECTION_INFO = BASE + 22;
/** @hide */
public static final int REQUEST_GROUP_INFO = BASE + 23;
/** @hide */
public static final int RESPONSE_GROUP_INFO = BASE + 24;
/** @hide */
public static final int ADD_LOCAL_SERVICE = BASE + 28;
/** @hide */
public static final int ADD_LOCAL_SERVICE_FAILED = BASE + 29;
/** @hide */
public static final int ADD_LOCAL_SERVICE_SUCCEEDED = BASE + 30;
/** @hide */
public static final int REMOVE_LOCAL_SERVICE = BASE + 31;
/** @hide */
public static final int REMOVE_LOCAL_SERVICE_FAILED = BASE + 32;
/** @hide */
public static final int REMOVE_LOCAL_SERVICE_SUCCEEDED = BASE + 33;
/** @hide */
public static final int CLEAR_LOCAL_SERVICES = BASE + 34;
/** @hide */
public static final int CLEAR_LOCAL_SERVICES_FAILED = BASE + 35;
/** @hide */
public static final int CLEAR_LOCAL_SERVICES_SUCCEEDED = BASE + 36;
/** @hide */
public static final int ADD_SERVICE_REQUEST = BASE + 37;
/** @hide */
public static final int ADD_SERVICE_REQUEST_FAILED = BASE + 38;
/** @hide */
public static final int ADD_SERVICE_REQUEST_SUCCEEDED = BASE + 39;
/** @hide */
public static final int REMOVE_SERVICE_REQUEST = BASE + 40;
/** @hide */
public static final int REMOVE_SERVICE_REQUEST_FAILED = BASE + 41;
/** @hide */
public static final int REMOVE_SERVICE_REQUEST_SUCCEEDED = BASE + 42;
/** @hide */
public static final int CLEAR_SERVICE_REQUESTS = BASE + 43;
/** @hide */
public static final int CLEAR_SERVICE_REQUESTS_FAILED = BASE + 44;
/** @hide */
public static final int CLEAR_SERVICE_REQUESTS_SUCCEEDED = BASE + 45;
/** @hide */
public static final int DISCOVER_SERVICES = BASE + 46;
/** @hide */
public static final int DISCOVER_SERVICES_FAILED = BASE + 47;
/** @hide */
public static final int DISCOVER_SERVICES_SUCCEEDED = BASE + 48;
/** @hide */
public static final int PING = BASE + 49;
/** @hide */
public static final int RESPONSE_SERVICE = BASE + 50;
/** @hide */
public static final int SET_DEVICE_NAME = BASE + 51;
/** @hide */
public static final int SET_DEVICE_NAME_FAILED = BASE + 52;
/** @hide */
public static final int SET_DEVICE_NAME_SUCCEEDED = BASE + 53;
/** @hide */
public static final int DELETE_PERSISTENT_GROUP = BASE + 54;
/** @hide */
public static final int DELETE_PERSISTENT_GROUP_FAILED = BASE + 55;
/** @hide */
public static final int DELETE_PERSISTENT_GROUP_SUCCEEDED = BASE + 56;
/** @hide */
public static final int REQUEST_PERSISTENT_GROUP_INFO = BASE + 57;
/** @hide */
public static final int RESPONSE_PERSISTENT_GROUP_INFO = BASE + 58;
/** @hide */
public static final int SET_WFD_INFO = BASE + 59;
/** @hide */
public static final int SET_WFD_INFO_FAILED = BASE + 60;
/** @hide */
public static final int SET_WFD_INFO_SUCCEEDED = BASE + 61;
/** @hide */
public static final int START_WPS = BASE + 62;
/** @hide */
public static final int START_WPS_FAILED = BASE + 63;
/** @hide */
public static final int START_WPS_SUCCEEDED = BASE + 64;
/** @hide */
public static final int START_LISTEN = BASE + 65;
/** @hide */
public static final int START_LISTEN_FAILED = BASE + 66;
/** @hide */
public static final int START_LISTEN_SUCCEEDED = BASE + 67;
/** @hide */
public static final int STOP_LISTEN = BASE + 68;
/** @hide */
public static final int STOP_LISTEN_FAILED = BASE + 69;
/** @hide */
public static final int STOP_LISTEN_SUCCEEDED = BASE + 70;
/** @hide */
public static final int SET_CHANNEL = BASE + 71;
/** @hide */
public static final int SET_CHANNEL_FAILED = BASE + 72;
/** @hide */
public static final int SET_CHANNEL_SUCCEEDED = BASE + 73;
/** @hide */
public static final int GET_HANDOVER_REQUEST = BASE + 75;
/** @hide */
public static final int GET_HANDOVER_SELECT = BASE + 76;
/** @hide */
public static final int RESPONSE_GET_HANDOVER_MESSAGE = BASE + 77;
/** @hide */
public static final int INITIATOR_REPORT_NFC_HANDOVER = BASE + 78;
/** @hide */
public static final int RESPONDER_REPORT_NFC_HANDOVER = BASE + 79;
/** @hide */
public static final int REPORT_NFC_HANDOVER_SUCCEEDED = BASE + 80;
/** @hide */
public static final int REPORT_NFC_HANDOVER_FAILED = BASE + 81;
/** @hide */
public static final int FACTORY_RESET = BASE + 82;
/** @hide */
public static final int FACTORY_RESET_FAILED = BASE + 83;
/** @hide */
public static final int FACTORY_RESET_SUCCEEDED = BASE + 84;
/** @hide */
public static final int REQUEST_ONGOING_PEER_CONFIG = BASE + 85;
/** @hide */
public static final int RESPONSE_ONGOING_PEER_CONFIG = BASE + 86;
/** @hide */
public static final int SET_ONGOING_PEER_CONFIG = BASE + 87;
/** @hide */
public static final int SET_ONGOING_PEER_CONFIG_FAILED = BASE + 88;
/** @hide */
public static final int SET_ONGOING_PEER_CONFIG_SUCCEEDED = BASE + 89;
/** @hide */
public static final int REQUEST_P2P_STATE = BASE + 90;
/** @hide */
public static final int RESPONSE_P2P_STATE = BASE + 91;
/** @hide */
public static final int REQUEST_DISCOVERY_STATE = BASE + 92;
/** @hide */
public static final int RESPONSE_DISCOVERY_STATE = BASE + 93;
/** @hide */
public static final int REQUEST_NETWORK_INFO = BASE + 94;
/** @hide */
public static final int RESPONSE_NETWORK_INFO = BASE + 95;
/** @hide */
public static final int UPDATE_CHANNEL_INFO = BASE + 96;
/** @hide */
public static final int REQUEST_DEVICE_INFO = BASE + 97;
/** @hide */
public static final int RESPONSE_DEVICE_INFO = BASE + 98;
/** @hide */
public static final int REMOVE_CLIENT = BASE + 99;
/** @hide */
public static final int REMOVE_CLIENT_FAILED = BASE + 100;
/** @hide */
public static final int REMOVE_CLIENT_SUCCEEDED = BASE + 101;
/** @hide */
public static final int ADD_EXTERNAL_APPROVER = BASE + 102;
/** @hide */
public static final int EXTERNAL_APPROVER_ATTACH = BASE + 103;
/** @hide */
public static final int EXTERNAL_APPROVER_DETACH = BASE + 104;
/** @hide */
public static final int EXTERNAL_APPROVER_CONNECTION_REQUESTED = BASE + 105;
/** @hide */
public static final int EXTERNAL_APPROVER_PIN_GENERATED = BASE + 106;
/** @hide */
public static final int REMOVE_EXTERNAL_APPROVER = BASE + 107;
/** @hide */
public static final int REMOVE_EXTERNAL_APPROVER_FAILED = BASE + 108;
/** @hide */
public static final int REMOVE_EXTERNAL_APPROVER_SUCCEEDED = BASE + 109;
/** @hide */
public static final int SET_CONNECTION_REQUEST_RESULT = BASE + 110;
/** @hide */
public static final int SET_CONNECTION_REQUEST_RESULT_FAILED = BASE + 111;
/** @hide */
public static final int SET_CONNECTION_REQUEST_RESULT_SUCCEEDED = BASE + 112;
/** @hide */
public static final int SET_VENDOR_ELEMENTS = BASE + 113;
/** @hide */
public static final int SET_VENDOR_ELEMENTS_FAILED = BASE + 114;
/** @hide */
public static final int SET_VENDOR_ELEMENTS_SUCCEEDED = BASE + 115;
/** @hide */
public static final int GET_LISTEN_STATE = BASE + 116;
/** @hide */
public static final int GET_LISTEN_STATE_FAILED = BASE + 117;
/** @hide */
public static final int RESPONSE_GET_LISTEN_STATE = BASE + 118;
private static final SparseArray This function is invoked when the device with the specified Bonjour
* registration type returned the instance name.
* @param instanceName instance name. This function is invoked when the device with the specified full
* service domain service returned TXT record.
*
* @param fullDomainName full domain name. This function is invoked when the specified device or service is found.
*
* @param uniqueServiceNames The list of unique service names. The function call immediately returns after sending a discovery request
* to the framework. The application is notified of a success or failure to initiate
* discovery through listener callbacks {@link ActionListener#onSuccess} or
* {@link ActionListener#onFailure}.
*
* The discovery remains active until a connection is initiated or
* a p2p group is formed. Register for {@link #WIFI_P2P_PEERS_CHANGED_ACTION} intent to
* determine when the framework notifies of a change as peers are discovered.
*
* Upon receiving a {@link #WIFI_P2P_PEERS_CHANGED_ACTION} intent, an application
* can request the list of peers using {@link #requestPeers}.
*
* If targeting {@link android.os.Build.VERSION_CODES#TIRAMISU} or later, the application must
* have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
* android:usesPermissionFlags="neverForLocation". If the application does not declare
* android:usesPermissionFlags="neverForLocation", then it must also have
* {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
*
* If targeting an earlier release than {@link android.os.Build.VERSION_CODES#TIRAMISU}, the
* application must have {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
*
* @param channel is the channel created at {@link #initialize}
* @param listener for callbacks on success or failure. Can be null.
*/
@RequiresPermission(allOf = {
android.Manifest.permission.NEARBY_WIFI_DEVICES,
android.Manifest.permission.ACCESS_FINE_LOCATION
}, conditional = true)
public void discoverPeers(Channel channel, ActionListener listener) {
checkChannel(channel);
Bundle extras = prepareExtrasBundle(channel);
channel.mAsyncChannel.sendMessage(prepareMessage(DISCOVER_PEERS, WIFI_P2P_SCAN_FULL,
channel.putListener(listener), extras, channel.mContext));
}
/**
* Scan only the social channels.
*
* A discovery process involves scanning for available Wi-Fi peers
* for the purpose of establishing a connection.
*
* The function call immediately returns after sending a discovery request
* to the framework. The application is notified of a success or failure to initiate
* discovery through listener callbacks {@link ActionListener#onSuccess} or
* {@link ActionListener#onFailure}.
*
* The discovery remains active until a connection is initiated or
* a p2p group is formed. Register for {@link #WIFI_P2P_PEERS_CHANGED_ACTION} intent to
* determine when the framework notifies of a change as peers are discovered.
*
* Upon receiving a {@link #WIFI_P2P_PEERS_CHANGED_ACTION} intent, an application
* can request the list of peers using {@link #requestPeers}.
*
* The application must have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
* android:usesPermissionFlags="neverForLocation". If the application does not declare
* android:usesPermissionFlags="neverForLocation", then it must also have
* {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
*
* Use {@link #isChannelConstrainedDiscoverySupported()} to determine whether the device
* supports this feature. If {@link #isChannelConstrainedDiscoverySupported()} return
* {@code false} then this method will throw {@link UnsupportedOperationException}.
*
* @param channel is the channel created at {@link #initialize}
* @param listener for callbacks on success or failure.
*/
@RequiresPermission(allOf = {
android.Manifest.permission.NEARBY_WIFI_DEVICES,
android.Manifest.permission.ACCESS_FINE_LOCATION
}, conditional = true)
public void discoverPeersOnSocialChannels(@NonNull Channel channel,
@Nullable ActionListener listener) {
if (!isChannelConstrainedDiscoverySupported()) {
throw new UnsupportedOperationException();
}
checkChannel(channel);
Bundle extras = prepareExtrasBundle(channel);
channel.mAsyncChannel.sendMessage(prepareMessage(DISCOVER_PEERS, WIFI_P2P_SCAN_SOCIAL,
channel.putListener(listener), extras, channel.mContext));
}
/**
* Scan only a single channel specified by frequency.
*
* A discovery process involves scanning for available Wi-Fi peers
* for the purpose of establishing a connection.
*
* The function call immediately returns after sending a discovery request
* to the framework. The application is notified of a success or failure to initiate
* discovery through listener callbacks {@link ActionListener#onSuccess} or
* {@link ActionListener#onFailure}.
*
* The discovery remains active until a connection is initiated or
* a p2p group is formed. Register for {@link #WIFI_P2P_PEERS_CHANGED_ACTION} intent to
* determine when the framework notifies of a change as peers are discovered.
*
* Upon receiving a {@link #WIFI_P2P_PEERS_CHANGED_ACTION} intent, an application
* can request the list of peers using {@link #requestPeers}.
*
* The application must have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
* android:usesPermissionFlags="neverForLocation". If the application does not declare
* android:usesPermissionFlags="neverForLocation", then it must also have
* {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
*
* Use {@link #isChannelConstrainedDiscoverySupported()} to determine whether the device
* supports this feature. If {@link #isChannelConstrainedDiscoverySupported()} return
* {@code false} then this method will throw {@link UnsupportedOperationException}.
*
* @param channel is the channel created at {@link #initialize}
* @param frequencyMhz is the frequency of the channel to use for peer discovery.
* @param listener for callbacks on success or failure.
*/
@RequiresPermission(allOf = {
android.Manifest.permission.NEARBY_WIFI_DEVICES,
android.Manifest.permission.ACCESS_FINE_LOCATION
}, conditional = true)
public void discoverPeersOnSpecificFrequency(
@NonNull Channel channel, int frequencyMhz, @Nullable ActionListener listener) {
if (!isChannelConstrainedDiscoverySupported()) {
throw new UnsupportedOperationException();
}
checkChannel(channel);
if (frequencyMhz <= 0) {
throw new IllegalArgumentException("This frequency must be a positive value.");
}
Bundle extras = prepareExtrasBundle(channel);
extras.putInt(EXTRA_PARAM_KEY_PEER_DISCOVERY_FREQ, frequencyMhz);
channel.mAsyncChannel.sendMessage(prepareMessage(DISCOVER_PEERS, WIFI_P2P_SCAN_SINGLE_FREQ,
channel.putListener(listener), extras, channel.mContext));
}
/**
* Initiate peer discovery. A discovery process involves scanning for available Wi-Fi peers
* for the purpose of establishing a connection. See {@link #discoverPeers(
* Channel, ActionListener)} for more details.
*
* This method accepts a {@link WifiP2pDiscoveryConfig} object specifying the desired
* parameters for the peer discovery. The configuration object allows the specification of the
* scan type (ex. FULL, SOCIAL) and the inclusion of vendor-specific configuration data.
*
* The application must have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
* android:usesPermissionFlags="neverForLocation". If the application does not declare
* android:usesPermissionFlags="neverForLocation", then it must also have
* {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
*
* @param channel is the channel created at {@link #initialize}
* @param config is the configuration for this peer discovery
* @param listener for callbacks on success or failure.
*/
@RequiresPermission(allOf = {
android.Manifest.permission.NEARBY_WIFI_DEVICES,
android.Manifest.permission.ACCESS_FINE_LOCATION
}, conditional = true)
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
@SuppressLint("ExecutorRegistration") // WifiP2pManager is using the async channel
public void startPeerDiscovery(
@NonNull Channel channel,
@NonNull WifiP2pDiscoveryConfig config,
@Nullable ActionListener listener) {
if (!isChannelConstrainedDiscoverySupported()) {
throw new UnsupportedOperationException();
}
checkChannel(channel);
Objects.requireNonNull(config);
Bundle extras = prepareExtrasBundle(channel);
extras.putParcelable(EXTRA_PARAM_KEY_DISCOVERY_CONFIG, config);
channel.mAsyncChannel.sendMessage(prepareMessage(DISCOVER_PEERS,
WIFI_P2P_SCAN_WITH_CONFIG_PARAMS,
channel.putListener(listener), extras, channel.mContext));
}
/**
* Stop an ongoing peer discovery
*
* The function call immediately returns after sending a stop request
* to the framework. The application is notified of a success or failure to initiate
* stop through listener callbacks {@link ActionListener#onSuccess} or
* {@link ActionListener#onFailure}.
*
* If P2P Group is in the process of being created, this call will fail (report failure via
* {@code listener}. The applicantion should listen to
* {@link #WIFI_P2P_CONNECTION_CHANGED_ACTION} to ensure the state is not
* {@link android.net.NetworkInfo.State#CONNECTING} and repeat calling when the state changes.
*
* @param channel is the channel created at {@link #initialize}
* @param listener for callbacks on success or failure. Can be null.
*/
public void stopPeerDiscovery(Channel channel, ActionListener listener) {
checkChannel(channel);
channel.mAsyncChannel.sendMessage(STOP_DISCOVERY, 0, channel.putListener(listener));
}
/**
* Start a p2p connection to a device with the specified configuration.
*
* The function call immediately returns after sending a connection request
* to the framework. The application is notified of a success or failure to initiate
* connect through listener callbacks {@link ActionListener#onSuccess} or
* {@link ActionListener#onFailure}.
*
* An app should use {@link WifiP2pConfig.Builder} to build the configuration
* for this API, ex. call {@link WifiP2pConfig.Builder#setDeviceAddress(MacAddress)}
* to set the peer MAC address and {@link WifiP2pConfig.Builder#enablePersistentMode(boolean)}
* to configure the persistent mode.
*
* Register for {@link #WIFI_P2P_CONNECTION_CHANGED_ACTION} intent to
* determine when the framework notifies of a change in connectivity.
*
* If the current device is not part of a p2p group, a connect request initiates
* a group negotiation with the peer.
*
* If the current device is part of an existing p2p group or has created
* a p2p group with {@link #createGroup}, an invitation to join the group is sent to
* the peer device.
*
* If targeting {@link android.os.Build.VERSION_CODES#TIRAMISU} or later, the application must
* have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
* android:usesPermissionFlags="neverForLocation". If the application does not declare
* android:usesPermissionFlags="neverForLocation", then it must also have
* {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
*
* If targeting an earlier release than {@link android.os.Build.VERSION_CODES#TIRAMISU}, the
* application must have {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
*
* @param channel is the channel created at {@link #initialize}
* @param config options as described in {@link WifiP2pConfig} class
* @param listener for callbacks on success or failure. Can be null.
*/
@RequiresPermission(allOf = {
android.Manifest.permission.NEARBY_WIFI_DEVICES,
android.Manifest.permission.ACCESS_FINE_LOCATION
}, conditional = true)
public void connect(Channel channel, WifiP2pConfig config, ActionListener listener) {
checkChannel(channel);
checkP2pConfig(config);
Bundle extras = prepareExtrasBundle(channel);
extras.putParcelable(EXTRA_PARAM_KEY_CONFIG, config);
channel.mAsyncChannel.sendMessage(prepareMessage(CONNECT, 0, channel.putListener(listener),
extras, channel.mContext));
}
/**
* Cancel any ongoing p2p group negotiation
*
* The function call immediately returns after sending a connection cancellation request
* to the framework. The application is notified of a success or failure to initiate
* cancellation through listener callbacks {@link ActionListener#onSuccess} or
* {@link ActionListener#onFailure}.
*
* @param channel is the channel created at {@link #initialize}
* @param listener for callbacks on success or failure. Can be null.
*/
public void cancelConnect(Channel channel, ActionListener listener) {
checkChannel(channel);
channel.mAsyncChannel.sendMessage(CANCEL_CONNECT, 0, channel.putListener(listener));
}
/**
* Create a p2p group with the current device as the group owner. This essentially creates
* an access point that can accept connections from legacy clients as well as other p2p
* devices.
*
* Note:
* This function would normally not be used unless the current device needs
* to form a p2p connection with a legacy client
*
* The function call immediately returns after sending a group creation request
* to the framework. The application is notified of a success or failure to initiate
* group creation through listener callbacks {@link ActionListener#onSuccess} or
* {@link ActionListener#onFailure}.
*
* Application can request for the group details with {@link #requestGroupInfo}.
*
* If targeting {@link android.os.Build.VERSION_CODES#TIRAMISU} or later, the application must
* have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
* android:usesPermissionFlags="neverForLocation". If the application does not declare
* android:usesPermissionFlags="neverForLocation", then it must also have
* {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
*
* If targeting an earlier release than {@link android.os.Build.VERSION_CODES#TIRAMISU}, the
* application must have {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
*
* @param channel is the channel created at {@link #initialize}
* @param listener for callbacks on success or failure. Can be null.
*/
@RequiresPermission(allOf = {
android.Manifest.permission.NEARBY_WIFI_DEVICES,
android.Manifest.permission.ACCESS_FINE_LOCATION
}, conditional = true)
public void createGroup(Channel channel, ActionListener listener) {
checkChannel(channel);
Bundle extras = prepareExtrasBundle(channel);
channel.mAsyncChannel.sendMessage(prepareMessage(CREATE_GROUP,
WifiP2pGroup.NETWORK_ID_PERSISTENT, channel.putListener(listener), extras,
channel.mContext));
}
/**
* Create a p2p group with the current device as the group owner. This essentially creates
* an access point that can accept connections from legacy clients as well as other p2p
* devices.
*
* An app should use {@link WifiP2pConfig.Builder} to build the configuration
* for a group.
*
* Note:
* This function would normally not be used unless the current device needs
* to form a p2p group as a Group Owner and allow peers to join it as either
* Group Clients or legacy Wi-Fi STAs.
*
* The function call immediately returns after sending a group creation request
* to the framework. The application is notified of a success or failure to initiate
* group creation through listener callbacks {@link ActionListener#onSuccess} or
* {@link ActionListener#onFailure}.
*
* Application can request for the group details with {@link #requestGroupInfo}.
*
* If targeting {@link android.os.Build.VERSION_CODES#TIRAMISU} or later, the application must
* have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
* android:usesPermissionFlags="neverForLocation". If the application does not declare
* android:usesPermissionFlags="neverForLocation", then it must also have
* {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
*
* If targeting an earlier release than {@link android.os.Build.VERSION_CODES#TIRAMISU}, the
* application must have {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
*
* @param channel is the channel created at {@link #initialize}.
* @param config the configuration of a p2p group.
* @param listener for callbacks on success or failure. Can be null.
*/
@RequiresPermission(allOf = {
android.Manifest.permission.NEARBY_WIFI_DEVICES,
android.Manifest.permission.ACCESS_FINE_LOCATION
}, conditional = true)
public void createGroup(@NonNull Channel channel,
@Nullable WifiP2pConfig config,
@Nullable ActionListener listener) {
checkChannel(channel);
Bundle extras = prepareExtrasBundle(channel);
extras.putParcelable(EXTRA_PARAM_KEY_CONFIG, config);
channel.mAsyncChannel.sendMessage(prepareMessage(CREATE_GROUP, 0,
channel.putListener(listener), extras, channel.mContext));
}
/**
* Remove the current p2p group.
*
* The function call immediately returns after sending a group removal request
* to the framework. The application is notified of a success or failure to initiate
* group removal through listener callbacks {@link ActionListener#onSuccess} or
* {@link ActionListener#onFailure}.
*
* @param channel is the channel created at {@link #initialize}
* @param listener for callbacks on success or failure. Can be null.
*/
public void removeGroup(Channel channel, ActionListener listener) {
checkChannel(channel);
channel.mAsyncChannel.sendMessage(REMOVE_GROUP, 0, channel.putListener(listener));
}
/**
* Force p2p to enter listen state.
*
* When this API is called, this device will periodically enter LISTENING state until
* {@link #stopListening(Channel, ActionListener)} or
* {@link #stopPeerDiscovery(Channel, ActionListener)} are called.
* While in LISTENING state, this device will dwell at its social channel and respond
* to probe requests from other Wi-Fi Direct peers.
*
* If targeting {@link android.os.Build.VERSION_CODES#TIRAMISU} or later, the application must
* have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
* android:usesPermissionFlags="neverForLocation". If the application does not declare
* android:usesPermissionFlags="neverForLocation", then it must also have
* {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
*
* If targeting an earlier release than {@link android.os.Build.VERSION_CODES#TIRAMISU}, the
* application must have {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
* @param channel is the channel created at
* {@link #initialize(Context, Looper, ChannelListener)}
* @param listener for callbacks on success or failure.
*/
@RequiresPermission(allOf = {
android.Manifest.permission.NEARBY_WIFI_DEVICES,
android.Manifest.permission.ACCESS_FINE_LOCATION
}, conditional = true)
public void startListening(@NonNull Channel channel, @Nullable ActionListener listener) {
checkChannel(channel);
Bundle extras = prepareExtrasBundle(channel);
channel.mAsyncChannel.sendMessage(prepareMessage(START_LISTEN, 0,
channel.putListener(listener), extras, channel.mContext));
}
/**
* Force P2P to enter the listen state. See {@link #startListening(Channel, ActionListener)}
* for more details.
*
* This method accepts a {@link WifiP2pExtListenParams} object containing additional
* parameters.
*
* @param channel is the channel created at @link #initialize(Context, Looper, ChannelListener)}
* @param params are the parameters for this listen request.
* @param listener for callbacks on success or failure.
* @hide
*/
@SystemApi
@RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
@RequiresPermission(allOf = {
android.Manifest.permission.NEARBY_WIFI_DEVICES,
android.Manifest.permission.ACCESS_FINE_LOCATION
}, conditional = true)
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
@SuppressLint("ExecutorRegistration") // WifiP2pManager is using the async channel
public void startListening(
@NonNull Channel channel,
@NonNull WifiP2pExtListenParams params,
@Nullable ActionListener listener) {
checkChannel(channel);
Bundle extras = prepareExtrasBundle(channel);
Objects.requireNonNull(params);
extras.putParcelable(EXTRA_PARAM_KEY_EXT_LISTEN_PARAMS, params);
channel.mAsyncChannel.sendMessage(prepareMessage(START_LISTEN,
WIFI_P2P_EXT_LISTEN_WITH_PARAMS, channel.putListener(listener), extras,
channel.mContext));
}
/**
* Force p2p to exit listen state.
*
* When this API is called, this device will stop entering LISTENING state periodically
* which is triggered by {@link #startListening(Channel, ActionListener)}.
* If there are running peer discovery which is triggered by
* {@link #discoverPeers(Channel, ActionListener)} or running service discovery which is
* triggered by {@link #discoverServices(Channel, ActionListener)}, they will be stopped
* as well.
*
* @param channel is the channel created at
* {@link #initialize(Context, Looper, ChannelListener)}
* @param listener for callbacks on success or failure.
*/
public void stopListening(@NonNull Channel channel, @Nullable ActionListener listener) {
checkChannel(channel);
channel.mAsyncChannel.sendMessage(STOP_LISTEN, 0, channel.putListener(listener));
}
/**
* Set P2P listening and operating channel.
*
* @param channel is the channel created at {@link #initialize}
* @param listeningChannel the listening channel's Wifi channel number. e.g. 1, 6, 11.
* @param operatingChannel the operating channel's Wifi channel number. e.g. 1, 6, 11.
* @param listener for callbacks on success or failure. Can be null.
*
* @hide
*/
@SystemApi
@RequiresPermission(anyOf = {
android.Manifest.permission.NETWORK_SETTINGS,
android.Manifest.permission.NETWORK_STACK,
android.Manifest.permission.OVERRIDE_WIFI_CONFIG
})
public void setWifiP2pChannels(@NonNull Channel channel, int listeningChannel,
int operatingChannel, @Nullable ActionListener listener) {
checkChannel(channel);
Bundle p2pChannels = new Bundle();
p2pChannels.putInt("lc", listeningChannel);
p2pChannels.putInt("oc", operatingChannel);
channel.mAsyncChannel.sendMessage(
SET_CHANNEL, 0, channel.putListener(listener), p2pChannels);
}
/**
* Start a Wi-Fi Protected Setup (WPS) session.
*
* The function call immediately returns after sending a request to start a
* WPS session. Currently, this is only valid if the current device is running
* as a group owner to allow any new clients to join the group. The application
* is notified of a success or failure to initiate WPS through listener callbacks
* {@link ActionListener#onSuccess} or {@link ActionListener#onFailure}.
* @hide
*/
@UnsupportedAppUsage(trackingBug = 185141982)
public void startWps(Channel channel, WpsInfo wps, ActionListener listener) {
checkChannel(channel);
channel.mAsyncChannel.sendMessage(START_WPS, 0, channel.putListener(listener), wps);
}
/**
* Register a local service for service discovery. If a local service is registered,
* the framework automatically responds to a service discovery request from a peer.
*
* The function call immediately returns after sending a request to add a local
* service to the framework. The application is notified of a success or failure to
* add service through listener callbacks {@link ActionListener#onSuccess} or
* {@link ActionListener#onFailure}.
*
* The service information is set through {@link WifiP2pServiceInfo}. The service information can be cleared with calls to
* {@link #removeLocalService} or {@link #clearLocalServices}.
*
* If targeting {@link android.os.Build.VERSION_CODES#TIRAMISU} or later, the application must
* have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
* android:usesPermissionFlags="neverForLocation". If the application does not declare
* android:usesPermissionFlags="neverForLocation", then it must also have
* {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
*
* If targeting an earlier release than {@link android.os.Build.VERSION_CODES#TIRAMISU}, the
* application must have {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
*
* @param channel is the channel created at {@link #initialize}
* @param servInfo is a local service information.
* @param listener for callbacks on success or failure. Can be null.
*/
@RequiresPermission(allOf = {
android.Manifest.permission.NEARBY_WIFI_DEVICES,
android.Manifest.permission.ACCESS_FINE_LOCATION
}, conditional = true)
public void addLocalService(Channel channel, WifiP2pServiceInfo servInfo,
ActionListener listener) {
checkChannel(channel);
checkServiceInfo(servInfo);
Bundle extras = prepareExtrasBundle(channel);
extras.putParcelable(EXTRA_PARAM_KEY_SERVICE_INFO, servInfo);
channel.mAsyncChannel.sendMessage(prepareMessage(ADD_LOCAL_SERVICE, 0,
channel.putListener(listener), extras, channel.mContext));
}
/**
* Remove a registered local service added with {@link #addLocalService}
*
* The function call immediately returns after sending a request to remove a
* local service to the framework. The application is notified of a success or failure to
* add service through listener callbacks {@link ActionListener#onSuccess} or
* {@link ActionListener#onFailure}.
*
* @param channel is the channel created at {@link #initialize}
* @param servInfo is the local service information.
* @param listener for callbacks on success or failure. Can be null.
*/
public void removeLocalService(Channel channel, WifiP2pServiceInfo servInfo,
ActionListener listener) {
checkChannel(channel);
checkServiceInfo(servInfo);
channel.mAsyncChannel.sendMessage(
REMOVE_LOCAL_SERVICE, 0, channel.putListener(listener), servInfo);
}
/**
* Clear all registered local services of service discovery.
*
* The function call immediately returns after sending a request to clear all
* local services to the framework. The application is notified of a success or failure to
* add service through listener callbacks {@link ActionListener#onSuccess} or
* {@link ActionListener#onFailure}.
*
* @param channel is the channel created at {@link #initialize}
* @param listener for callbacks on success or failure. Can be null.
*/
public void clearLocalServices(Channel channel, ActionListener listener) {
checkChannel(channel);
channel.mAsyncChannel.sendMessage(CLEAR_LOCAL_SERVICES, 0, channel.putListener(listener));
}
/**
* Register a callback to be invoked on receiving service discovery response.
* Used only for vendor specific protocol right now. For Bonjour or Upnp, use
* {@link #setDnsSdResponseListeners} or {@link #setUpnpServiceResponseListener}
* respectively.
*
* see {@link #discoverServices} for the detail.
*
* @param channel is the channel created at {@link #initialize}
* @param listener for callbacks on receiving service discovery response.
*/
public void setServiceResponseListener(Channel channel,
ServiceResponseListener listener) {
checkChannel(channel);
channel.mServRspListener = listener;
}
/**
* Register a callback to be invoked on receiving Bonjour service discovery
* response.
*
* see {@link #discoverServices} for the detail.
*
* @param channel
* @param servListener is for listening to a Bonjour service response
* @param txtListener is for listening to a Bonjour TXT record response
*/
public void setDnsSdResponseListeners(Channel channel,
DnsSdServiceResponseListener servListener, DnsSdTxtRecordListener txtListener) {
checkChannel(channel);
channel.mDnsSdServRspListener = servListener;
channel.mDnsSdTxtListener = txtListener;
}
/**
* Register a callback to be invoked on receiving upnp service discovery
* response.
*
* see {@link #discoverServices} for the detail.
*
* @param channel is the channel created at {@link #initialize}
* @param listener for callbacks on receiving service discovery response.
*/
public void setUpnpServiceResponseListener(Channel channel,
UpnpServiceResponseListener listener) {
checkChannel(channel);
channel.mUpnpServRspListener = listener;
}
/**
* Initiate service discovery. A discovery process involves scanning for
* requested services for the purpose of establishing a connection to a peer
* that supports an available service.
*
* The function call immediately returns after sending a request to start service
* discovery to the framework. The application is notified of a success or failure to initiate
* discovery through listener callbacks {@link ActionListener#onSuccess} or
* {@link ActionListener#onFailure}.
*
* The services to be discovered are specified with calls to {@link #addServiceRequest}.
*
* The application is notified of the response against the service discovery request
* through listener callbacks registered by {@link #setServiceResponseListener} or
* {@link #setDnsSdResponseListeners}, or {@link #setUpnpServiceResponseListener}.
*
* If targeting {@link android.os.Build.VERSION_CODES#TIRAMISU} or later, the application must
* have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
* android:usesPermissionFlags="neverForLocation". If the application does not declare
* android:usesPermissionFlags="neverForLocation", then it must also have
* {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
*
* If targeting an earlier release than {@link android.os.Build.VERSION_CODES#TIRAMISU}, the
* application must have {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
*
* @param channel is the channel created at {@link #initialize}
* @param listener for callbacks on success or failure. Can be null.
*/
@RequiresPermission(allOf = {
android.Manifest.permission.NEARBY_WIFI_DEVICES,
android.Manifest.permission.ACCESS_FINE_LOCATION
}, conditional = true)
public void discoverServices(Channel channel, ActionListener listener) {
checkChannel(channel);
Bundle extras = prepareExtrasBundle(channel);
channel.mAsyncChannel.sendMessage(prepareMessage(DISCOVER_SERVICES, 0,
channel.putListener(listener), extras, channel.mContext));
}
/**
* Add a service discovery request.
*
* The function call immediately returns after sending a request to add service
* discovery request to the framework. The application is notified of a success or failure to
* add service through listener callbacks {@link ActionListener#onSuccess} or
* {@link ActionListener#onFailure}.
*
* After service discovery request is added, you can initiate service discovery by
* {@link #discoverServices}.
*
* The added service requests can be cleared with calls to
* {@link #removeServiceRequest(Channel, WifiP2pServiceRequest, ActionListener)} or
* {@link #clearServiceRequests(Channel, ActionListener)}.
*
* @param channel is the channel created at {@link #initialize}
* @param req is the service discovery request.
* @param listener for callbacks on success or failure. Can be null.
*/
public void addServiceRequest(Channel channel,
WifiP2pServiceRequest req, ActionListener listener) {
checkChannel(channel);
checkServiceRequest(req);
channel.mAsyncChannel.sendMessage(ADD_SERVICE_REQUEST, 0,
channel.putListener(listener), req);
}
/**
* Remove a specified service discovery request added with {@link #addServiceRequest}
*
* The function call immediately returns after sending a request to remove service
* discovery request to the framework. The application is notified of a success or failure to
* add service through listener callbacks {@link ActionListener#onSuccess} or
* {@link ActionListener#onFailure}.
*
* @param channel is the channel created at {@link #initialize}
* @param req is the service discovery request.
* @param listener for callbacks on success or failure. Can be null.
*/
public void removeServiceRequest(Channel channel, WifiP2pServiceRequest req,
ActionListener listener) {
checkChannel(channel);
checkServiceRequest(req);
channel.mAsyncChannel.sendMessage(REMOVE_SERVICE_REQUEST, 0,
channel.putListener(listener), req);
}
/**
* Clear all registered service discovery requests.
*
* The function call immediately returns after sending a request to clear all
* service discovery requests to the framework. The application is notified of a success
* or failure to add service through listener callbacks {@link ActionListener#onSuccess} or
* {@link ActionListener#onFailure}.
*
* @param channel is the channel created at {@link #initialize}
* @param listener for callbacks on success or failure. Can be null.
*/
public void clearServiceRequests(Channel channel, ActionListener listener) {
checkChannel(channel);
channel.mAsyncChannel.sendMessage(CLEAR_SERVICE_REQUESTS,
0, channel.putListener(listener));
}
/**
* Request the current list of peers.
*
* If targeting {@link android.os.Build.VERSION_CODES#TIRAMISU} or later, the application must
* have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
* android:usesPermissionFlags="neverForLocation". If the application does not declare
* android:usesPermissionFlags="neverForLocation", then it must also have
* {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
*
* If targeting an earlier release than {@link android.os.Build.VERSION_CODES#TIRAMISU}, the
* application must have {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
*
* @param channel is the channel created at {@link #initialize}
* @param listener for callback when peer list is available. Can be null.
*/
@RequiresPermission(allOf = {
android.Manifest.permission.NEARBY_WIFI_DEVICES,
android.Manifest.permission.ACCESS_FINE_LOCATION
}, conditional = true)
public void requestPeers(Channel channel, PeerListListener listener) {
checkChannel(channel);
Bundle extras = prepareExtrasBundle(channel);
channel.mAsyncChannel.sendMessage(prepareMessage(REQUEST_PEERS, 0,
channel.putListener(listener), extras, channel.mContext));
}
/**
* Request device connection info.
*
* @param channel is the channel created at {@link #initialize}
* @param listener for callback when connection info is available. Can be null.
*/
public void requestConnectionInfo(Channel channel, ConnectionInfoListener listener) {
checkChannel(channel);
channel.mAsyncChannel.sendMessage(
REQUEST_CONNECTION_INFO, 0, channel.putListener(listener));
}
/**
* Request p2p group info.
*
* If targeting {@link android.os.Build.VERSION_CODES#TIRAMISU} or later, the application must
* have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
* android:usesPermissionFlags="neverForLocation". If the application does not declare
* android:usesPermissionFlags="neverForLocation", then it must also have
* {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
*
* If targeting an earlier release than {@link android.os.Build.VERSION_CODES#TIRAMISU}, the
* application must have {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
*
* @param channel is the channel created at {@link #initialize}
* @param listener for callback when group info is available. Can be null.
*/
@RequiresPermission(allOf = {
android.Manifest.permission.NEARBY_WIFI_DEVICES,
android.Manifest.permission.ACCESS_FINE_LOCATION
}, conditional = true)
public void requestGroupInfo(Channel channel, GroupInfoListener listener) {
checkChannel(channel);
Bundle extras = prepareExtrasBundle(channel);
channel.mAsyncChannel.sendMessage(prepareMessage(REQUEST_GROUP_INFO, 0,
channel.putListener(listener), extras, channel.mContext));
}
/**
* Set p2p device name.
*
* @param channel is the channel created at {@link #initialize}
* @param listener for callback when group info is available. Can be null.
*
* @hide
*/
@SystemApi
@RequiresPermission(anyOf = {
android.Manifest.permission.NETWORK_SETTINGS,
android.Manifest.permission.NETWORK_STACK,
android.Manifest.permission.OVERRIDE_WIFI_CONFIG
})
public void setDeviceName(@NonNull Channel channel, @NonNull String devName,
@Nullable ActionListener listener) {
checkChannel(channel);
WifiP2pDevice d = new WifiP2pDevice();
d.deviceName = devName;
channel.mAsyncChannel.sendMessage(SET_DEVICE_NAME, 0, channel.putListener(listener), d);
}
/**
* Set Wifi Display information.
*
* @param channel is the channel created at {@link #initialize}
* @param wfdInfo the Wifi Display information to set
* @param listener for callbacks on success or failure. Can be null.
*/
@RequiresPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
public void setWfdInfo(@NonNull Channel channel, @NonNull WifiP2pWfdInfo wfdInfo,
@Nullable ActionListener listener) {
setWFDInfo(channel, wfdInfo, listener);
}
/** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@RequiresPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
public void setWFDInfo(@NonNull Channel channel, @NonNull WifiP2pWfdInfo wfdInfo,
@Nullable ActionListener listener) {
checkChannel(channel);
try {
mService.checkConfigureWifiDisplayPermission();
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
channel.mAsyncChannel.sendMessage(SET_WFD_INFO, 0, channel.putListener(listener), wfdInfo);
}
/**
* Remove the client with the MAC address from the group.
*
* The function call immediately returns after sending a client removal request
* to the framework. The application is notified of a success or failure to initiate
* client removal through listener callbacks {@link ActionListener#onSuccess} or
* {@link ActionListener#onFailure}.
*
* The callbacks are triggered on the thread specified when initializing the
* {@code channel}, see {@link #initialize}.
*
* Use {@link #isGroupClientRemovalSupported()} to determine whether the device supports
* this feature. If {@link #isGroupClientRemovalSupported()} return {@code false} then this
* method will throw {@link UnsupportedOperationException}.
*
* @param channel is the channel created at {@link #initialize}
* @param peerAddress MAC address of the client.
* @param listener for callbacks on success or failure. Can be null.
*/
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
public void removeClient(@NonNull Channel channel, @NonNull MacAddress peerAddress,
@Nullable ActionListener listener) {
if (!isGroupClientRemovalSupported()) {
throw new UnsupportedOperationException();
}
checkChannel(channel);
channel.mAsyncChannel.sendMessage(
REMOVE_CLIENT, 0, channel.putListener(listener), peerAddress);
}
/**
* Delete a stored persistent group from the system settings.
*
* The function call immediately returns after sending a persistent group removal request
* to the framework. The application is notified of a success or failure to initiate
* group removal through listener callbacks {@link ActionListener#onSuccess} or
* {@link ActionListener#onFailure}.
*
* The persistent p2p group list stored in the system can be obtained by
* {@link #requestPersistentGroupInfo(Channel, PersistentGroupInfoListener)} and
* a network id can be obtained by {@link WifiP2pGroup#getNetworkId()}.
*
* @param channel is the channel created at {@link #initialize}
* @param netId the network id of the p2p group.
* @param listener for callbacks on success or failure. Can be null.
*
* @hide
*/
@SystemApi
@RequiresPermission(anyOf = {
android.Manifest.permission.NETWORK_SETTINGS,
android.Manifest.permission.NETWORK_STACK,
android.Manifest.permission.OVERRIDE_WIFI_CONFIG
})
public void deletePersistentGroup(@NonNull Channel channel, int netId,
@Nullable ActionListener listener) {
checkChannel(channel);
channel.mAsyncChannel.sendMessage(
DELETE_PERSISTENT_GROUP, netId, channel.putListener(listener));
}
/**
* Request a list of all the persistent p2p groups stored in system.
*
* The caller must have one of {@link android.Manifest.permission.NETWORK_SETTINGS},
* {@link android.Manifest.permission.NETWORK_STACK}, and
* {@link android.Manifest.permission.READ_WIFI_CREDENTIAL}.
*
* If targeting {@link android.os.Build.VERSION_CODES#TIRAMISU} or later,
* the application must have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
* android:usesPermissionFlags="neverForLocation". If the application does not declare
* android:usesPermissionFlags="neverForLocation", then it must also have
* {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
*
* @param channel is the channel created at {@link #initialize}
* @param listener for callback when persistent group info list is available. Can be null.
*
* @hide
*/
@SystemApi
@RequiresPermission(allOf = {
android.Manifest.permission.NETWORK_SETTINGS,
android.Manifest.permission.NETWORK_STACK,
android.Manifest.permission.READ_WIFI_CREDENTIAL,
android.Manifest.permission.NEARBY_WIFI_DEVICES,
android.Manifest.permission.ACCESS_FINE_LOCATION}, conditional = true)
public void requestPersistentGroupInfo(@NonNull Channel channel,
@Nullable PersistentGroupInfoListener listener) {
checkChannel(channel);
Bundle extras = prepareExtrasBundle(channel);
channel.mAsyncChannel.sendMessage(prepareMessage(REQUEST_PERSISTENT_GROUP_INFO, 0,
channel.putListener(listener), extras, channel.mContext));
}
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = {"MIRACAST_"}, value = {
MIRACAST_DISABLED,
MIRACAST_SOURCE,
MIRACAST_SINK})
public @interface MiracastMode {}
/**
* Miracast is disabled.
* @hide
*/
@SystemApi
public static final int MIRACAST_DISABLED = 0;
/**
* Device acts as a Miracast source.
* @hide
*/
@SystemApi
public static final int MIRACAST_SOURCE = 1;
/**
* Device acts as a Miracast sink.
* @hide
*/
@SystemApi
public static final int MIRACAST_SINK = 2;
/**
* Accept the incoming request.
*
* Used in {@link #setConnectionRequestResult(Channel, MacAddress, int, ActionListener)}.
*/
public static final int CONNECTION_REQUEST_ACCEPT = 0;
/**
* Reject the incoming request.
*
* Used in {@link #setConnectionRequestResult(Channel, MacAddress, int, ActionListener)}.
*/
public static final int CONNECTION_REQUEST_REJECT = 1;
/**
* Defer the decision back to the Wi-Fi service (which will display a dialog to the user).
*
* Used in {@link #setConnectionRequestResult(Channel, MacAddress, int, ActionListener)}.
*/
public static final int CONNECTION_REQUEST_DEFER_TO_SERVICE = 2;
/**
* Defer the PIN display to the Wi-Fi service (which will display a dialog to the user).
*
* Used in {@link #setConnectionRequestResult(Channel, MacAddress, int, ActionListener)}.
*/
public static final int CONNECTION_REQUEST_DEFER_SHOW_PIN_TO_SERVICE = 3;
/** @hide */
@IntDef(prefix = {"CONNECTION_REQUEST_"}, value = {
CONNECTION_REQUEST_ACCEPT,
CONNECTION_REQUEST_REJECT,
CONNECTION_REQUEST_DEFER_TO_SERVICE,
CONNECTION_REQUEST_DEFER_SHOW_PIN_TO_SERVICE})
@Retention(RetentionPolicy.SOURCE)
public @interface ConnectionRequestResponse {
}
/**
* This is used to provide information to drivers to optimize performance depending
* on the current mode of operation.
* {@link #MIRACAST_DISABLED} - disabled
* {@link #MIRACAST_SOURCE} - source operation
* {@link #MIRACAST_SINK} - sink operation
*
* As an example, the driver could reduce the channel dwell time during scanning
* when acting as a source or sink to minimize impact on Miracast.
*
* @param mode mode of operation. One of {@link #MIRACAST_DISABLED}, {@link #MIRACAST_SOURCE},
* or {@link #MIRACAST_SINK}
*
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
public void setMiracastMode(@MiracastMode int mode) {
try {
mService.setMiracastMode(mode);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
private Messenger getMessenger(@NonNull Binder binder, @Nullable String packageName,
@NonNull Bundle extras) {
try {
return mService.getMessenger(binder, packageName, extras);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Get a reference to P2pStateMachine handler. This is used to establish
* a priveleged AsyncChannel communication with WifiP2pService.
*
* @return Messenger pointing to the WifiP2pService handler
* @hide
*/
public Messenger getP2pStateMachineMessenger() {
try {
return mService.getP2pStateMachineMessenger();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
private long getSupportedFeatures() {
try {
return mService.getSupportedFeatures();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
private boolean isFeatureSupported(long feature) {
return (getSupportedFeatures() & feature) == feature;
}
/**
* Check if this device supports setting vendor elements.
*
* Gates whether the
* {@link #setVendorElements(Channel, List, ActionListener)}
* method is functional on this device.
*
* @return {@code true} if supported, {@code false} otherwise.
*/
public boolean isSetVendorElementsSupported() {
return isFeatureSupported(FEATURE_SET_VENDOR_ELEMENTS);
}
/**
* Check if this device supports discovery limited to a specific frequency or
* the social channels.
*
* Gates whether
* {@link #discoverPeersOnSpecificFrequency(Channel, int, ActionListener)} and
* {@link #discoverPeersOnSocialChannels(Channel, ActionListener)}
* methods are functional on this device.
*
* @return {@code true} if supported, {@code false} otherwise.
*/
public boolean isChannelConstrainedDiscoverySupported() {
return isFeatureSupported(FEATURE_FLEXIBLE_DISCOVERY);
}
/**
* Check if this device supports removing clients from a group.
*
* Gates whether the
* {@link #removeClient(Channel, MacAddress, ActionListener)}
* method is functional on this device.
* @return {@code true} if supported, {@code false} otherwise.
*/
public boolean isGroupClientRemovalSupported() {
return isFeatureSupported(FEATURE_GROUP_CLIENT_REMOVAL);
}
/**
* Checks whether this device, while being a group client, can discover and deliver the group
* owner's IPv6 link-local address.
*
* If this method returns {@code true} and
* {@link #connect(Channel, WifiP2pConfig, ActionListener)} method is called with
* {@link WifiP2pConfig} having
* {@link WifiP2pConfig#GROUP_CLIENT_IP_PROVISIONING_MODE_IPV6_LINK_LOCAL} as the group client
* IP provisioning mode, then the group owner's IPv6 link-local address will be delivered in the
* group client via {@link #WIFI_P2P_CONNECTION_CHANGED_ACTION} broadcast intent (i.e, group
* owner address in {@link #EXTRA_WIFI_P2P_INFO}).
* If this method returns {@code false}, then IPv6 link-local addresses can still be used, but
* it is the responsibility of the caller to discover that address in other ways, e.g. using
* out-of-band communication.
*
* @return {@code true} if supported, {@code false} otherwise.
*/
public boolean isGroupOwnerIPv6LinkLocalAddressProvided() {
return SdkLevel.isAtLeastT()
&& isFeatureSupported(FEATURE_GROUP_OWNER_IPV6_LINK_LOCAL_ADDRESS_PROVIDED);
}
/**
* Get a handover request message for use in WFA NFC Handover transfer.
* @hide
*/
public void getNfcHandoverRequest(Channel c, HandoverMessageListener listener) {
checkChannel(c);
c.mAsyncChannel.sendMessage(GET_HANDOVER_REQUEST, 0, c.putListener(listener));
}
/**
* Get a handover select message for use in WFA NFC Handover transfer.
* @hide
*/
public void getNfcHandoverSelect(Channel c, HandoverMessageListener listener) {
checkChannel(c);
c.mAsyncChannel.sendMessage(GET_HANDOVER_SELECT, 0, c.putListener(listener));
}
/**
* @hide
*/
public void initiatorReportNfcHandover(Channel c, String handoverSelect,
ActionListener listener) {
checkChannel(c);
Bundle bundle = new Bundle();
bundle.putString(EXTRA_HANDOVER_MESSAGE, handoverSelect);
c.mAsyncChannel.sendMessage(INITIATOR_REPORT_NFC_HANDOVER, 0,
c.putListener(listener), bundle);
}
/**
* @hide
*/
public void responderReportNfcHandover(Channel c, String handoverRequest,
ActionListener listener) {
checkChannel(c);
Bundle bundle = new Bundle();
bundle.putString(EXTRA_HANDOVER_MESSAGE, handoverRequest);
c.mAsyncChannel.sendMessage(RESPONDER_REPORT_NFC_HANDOVER, 0,
c.putListener(listener), bundle);
}
/**
* Removes all saved p2p groups.
*
* @param c is the channel created at {@link #initialize}.
* @param listener for callback on success or failure. Can be null.
*
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
public void factoryReset(@NonNull Channel c, @Nullable ActionListener listener) {
checkChannel(c);
c.mAsyncChannel.sendMessage(FACTORY_RESET, 0, c.putListener(listener));
}
/**
* Request saved WifiP2pConfig which used for an ongoing peer connection
*
* @param c is the channel created at {@link #initialize}
* @param listener for callback when ongoing peer config updated. Can't be null.
*
* @hide
*/
@RequiresPermission(android.Manifest.permission.NETWORK_STACK)
public void requestOngoingPeerConfig(@NonNull Channel c,
@NonNull OngoingPeerInfoListener listener) {
checkChannel(c);
c.mAsyncChannel.sendMessage(REQUEST_ONGOING_PEER_CONFIG,
Binder.getCallingUid(), c.putListener(listener));
}
/**
* Set saved WifiP2pConfig which used for an ongoing peer connection
*
* @param c is the channel created at {@link #initialize}
* @param config used for change an ongoing peer connection
* @param listener for callback when ongoing peer config updated. Can be null.
*
* @hide
*/
@RequiresPermission(android.Manifest.permission.NETWORK_STACK)
public void setOngoingPeerConfig(@NonNull Channel c, @NonNull WifiP2pConfig config,
@Nullable ActionListener listener) {
checkChannel(c);
checkP2pConfig(config);
c.mAsyncChannel.sendMessage(SET_ONGOING_PEER_CONFIG, 0,
c.putListener(listener), config);
}
/**
* Request p2p enabled state.
*
* This state indicates whether Wi-Fi p2p is enabled or disabled.
* The valid value is one of {@link #WIFI_P2P_STATE_DISABLED} or
* {@link #WIFI_P2P_STATE_ENABLED}. The state is returned using the
* {@link P2pStateListener} listener.
*
* This state is also included in the {@link #WIFI_P2P_STATE_CHANGED_ACTION}
* broadcast event with extra {@link #EXTRA_WIFI_STATE}.
*
* @param c is the channel created at {@link #initialize}.
* @param listener for callback when p2p state is available.
*/
public void requestP2pState(@NonNull Channel c,
@NonNull P2pStateListener listener) {
checkChannel(c);
if (listener == null) throw new IllegalArgumentException("This listener cannot be null.");
c.mAsyncChannel.sendMessage(REQUEST_P2P_STATE, 0, c.putListener(listener));
}
/**
* Request p2p discovery state.
*
* This state indicates whether p2p discovery has started or stopped.
* The valid value is one of {@link #WIFI_P2P_DISCOVERY_STARTED} or
* {@link #WIFI_P2P_DISCOVERY_STOPPED}. The state is returned using the
* {@link DiscoveryStateListener} listener.
*
* This state is also included in the {@link #WIFI_P2P_DISCOVERY_CHANGED_ACTION}
* broadcast event with extra {@link #EXTRA_DISCOVERY_STATE}.
*
* @param c is the channel created at {@link #initialize}.
* @param listener for callback when discovery state is available.
*/
public void requestDiscoveryState(@NonNull Channel c,
@NonNull DiscoveryStateListener listener) {
checkChannel(c);
if (listener == null) throw new IllegalArgumentException("This listener cannot be null.");
c.mAsyncChannel.sendMessage(REQUEST_DISCOVERY_STATE, 0, c.putListener(listener));
}
/**
* Get p2p listen state.
*
* This state indicates whether p2p listen has started or stopped.
* The valid value is one of {@link #WIFI_P2P_LISTEN_STOPPED} or
* {@link #WIFI_P2P_LISTEN_STARTED}.
*
* This state is also included in the {@link #ACTION_WIFI_P2P_LISTEN_STATE_CHANGED}
* broadcast event with extra {@link #EXTRA_LISTEN_STATE}.
*
*
* If targeting {@link android.os.Build.VERSION_CODES#TIRAMISU} or later, the application must
* have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
* android:usesPermissionFlags="neverForLocation". If the application does not declare
* android:usesPermissionFlags="neverForLocation", then it must also have
* {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
*
* If targeting an earlier release than {@link android.os.Build.VERSION_CODES#TIRAMISU}, the
* application must have {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
*
* @param c It is the channel created at {@link #initialize}.
* @param executor The executor on which callback will be invoked.
* @param resultsCallback A callback that will return listen state
* {@link #WIFI_P2P_LISTEN_STOPPED} or {@link #WIFI_P2P_LISTEN_STARTED}
*/
@RequiresPermission(allOf = {
android.Manifest.permission.NEARBY_WIFI_DEVICES,
android.Manifest.permission.ACCESS_FINE_LOCATION
}, conditional = true)
public void getListenState(@NonNull Channel c, @NonNull @CallbackExecutor Executor executor,
@NonNull Consumer This method provides the network info in the form of a {@link android.net.NetworkInfo}.
* {@link android.net.NetworkInfo#isAvailable()} indicates the p2p availability and
* {@link android.net.NetworkInfo#getDetailedState()} reports the current fine-grained state
* of the network. This {@link android.net.NetworkInfo} is returned using the
* {@link NetworkInfoListener} listener.
*
* This information is also included in the {@link #WIFI_P2P_CONNECTION_CHANGED_ACTION}
* broadcast event with extra {@link #EXTRA_NETWORK_INFO}.
*
* @param c is the channel created at {@link #initialize}.
* @param listener for callback when network info is available.
*/
public void requestNetworkInfo(@NonNull Channel c,
@NonNull NetworkInfoListener listener) {
checkChannel(c);
if (listener == null) throw new IllegalArgumentException("This listener cannot be null.");
c.mAsyncChannel.sendMessage(REQUEST_NETWORK_INFO, 0, c.putListener(listener));
}
/**
* Request Device Info
*
* This method provides the device info
* in the form of a {@link android.net.wifi.p2p.WifiP2pDevice}.
* Valid {@link android.net.wifi.p2p.WifiP2pDevice} is returned when p2p is enabled.
* To get information notifications on P2P getting enabled refers
* {@link #WIFI_P2P_STATE_ENABLED}.
*
* This {@link android.net.wifi.p2p.WifiP2pDevice} is returned using the
* {@link DeviceInfoListener} listener.
*
* {@link android.net.wifi.p2p.WifiP2pDevice#deviceAddress} is only available if the caller
* holds the {@code android.Manifest.permission#LOCAL_MAC_ADDRESS} permission, and holds the
* anonymized MAC address (02:00:00:00:00:00) otherwise.
*
* This information is also included in the {@link #WIFI_P2P_THIS_DEVICE_CHANGED_ACTION}
* broadcast event with extra {@link #EXTRA_WIFI_P2P_DEVICE}.
*
* If targeting {@link android.os.Build.VERSION_CODES#TIRAMISU} or later, the application must
* have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
* android:usesPermissionFlags="neverForLocation". If the application does not declare
* android:usesPermissionFlags="neverForLocation", then it must also have
* {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
*
* If targeting an earlier release than {@link android.os.Build.VERSION_CODES#TIRAMISU}, the
* application must have {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
*
* @param c is the channel created at {@link #initialize(Context, Looper, ChannelListener)}.
* @param listener for callback when network info is available.
*/
@RequiresPermission(allOf = {
android.Manifest.permission.NEARBY_WIFI_DEVICES,
android.Manifest.permission.ACCESS_FINE_LOCATION
}, conditional = true)
public void requestDeviceInfo(@NonNull Channel c, @NonNull DeviceInfoListener listener) {
checkChannel(c);
if (listener == null) throw new IllegalArgumentException("This listener cannot be null.");
Bundle extras = prepareExtrasBundle(c);
c.mAsyncChannel.sendMessage(prepareMessage(REQUEST_DEVICE_INFO, 0,
c.putListener(listener), extras, c.mContext));
}
/**
* Set the external approver for a specific peer.
*
* This API associates a specific peer with an approver. When an incoming request is received
* from a peer, an authorization request is routed to the attached approver. The approver then
* calls {@link #setConnectionRequestResult(Channel, MacAddress, int, ActionListener)} to send
* the result to the WiFi service. A specific peer (identified by its {@code MacAddress}) can
* only be attached to a single approver. The previous approver will be detached once a new
* approver is attached. The approver will also be detached automatically when the channel is
* closed.
*
* When an approver is attached, {@link ExternalApproverRequestListener#onAttached(MacAddress)}
* is called. When an approver is detached,
* {@link ExternalApproverRequestListener#onDetached(MacAddress, int)} is called.
* When an incoming request is received,
* {@link ExternalApproverRequestListener#onConnectionRequested(int, WifiP2pConfig, WifiP2pDevice)}
* is called. When a WPS PIN is generated,
* {@link ExternalApproverRequestListener#onPinGenerated(MacAddress, String)} is called.
*
* The application must have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
* android:usesPermissionFlags="neverForLocation". If the application does not declare
* android:usesPermissionFlags="neverForLocation", then it must also have
* {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
*
* @param c is the channel created at {@link #initialize(Context, Looper, ChannelListener)}.
* @param deviceAddress the peer which is bound to the external approver.
* @param listener for callback when the framework needs to notify the external approver.
*/
@RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION)
public void addExternalApprover(@NonNull Channel c, @NonNull MacAddress deviceAddress,
@NonNull ExternalApproverRequestListener listener) {
checkChannel(c);
if (listener == null) throw new IllegalArgumentException("This listener cannot be null.");
if (null == deviceAddress) {
throw new IllegalArgumentException("deviceAddress cannot be empty");
}
Bundle extras = prepareExtrasBundle(c);
extras.putParcelable(EXTRA_PARAM_KEY_PEER_ADDRESS, deviceAddress);
c.mAsyncChannel.sendMessage(prepareMessage(ADD_EXTERNAL_APPROVER, 0,
c.putListener(listener), extras, c.mContext));
}
/**
* Remove the external approver for a specific peer.
*
* The application must have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
* android:usesPermissionFlags="neverForLocation". If the application does not declare
* android:usesPermissionFlags="neverForLocation", then it must also have
* {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
*
* @param c is the channel created at {@link #initialize(Context, Looper, ChannelListener)}.
* @param deviceAddress the peer which is bound to the external approver.
* @param listener for callback on success or failure.
*/
@RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION)
public void removeExternalApprover(@NonNull Channel c, @NonNull MacAddress deviceAddress,
@Nullable ActionListener listener) {
checkChannel(c);
if (null == deviceAddress) {
throw new IllegalArgumentException("deviceAddress cannot be empty");
}
Bundle extras = prepareExtrasBundle(c);
extras.putParcelable(EXTRA_PARAM_KEY_PEER_ADDRESS, deviceAddress);
c.mAsyncChannel.sendMessage(prepareMessage(REMOVE_EXTERNAL_APPROVER, 0,
c.putListener(listener), extras, c.mContext));
}
/**
* Set the result for the incoming request from a specific peer.
*
* The application must have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
* android:usesPermissionFlags="neverForLocation". If the application does not declare
* android:usesPermissionFlags="neverForLocation", then it must also have
* {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
*
* @param c is the channel created at {@link #initialize(Context, Looper, ChannelListener)}.
* @param deviceAddress the peer which is bound to the external approver.
* @param result the response for the incoming request.
* @param listener for callback on success or failure.
*/
@RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION)
public void setConnectionRequestResult(@NonNull Channel c, @NonNull MacAddress deviceAddress,
@ConnectionRequestResponse int result, @Nullable ActionListener listener) {
checkChannel(c);
if (null == deviceAddress) {
throw new IllegalArgumentException("deviceAddress cannot be empty");
}
Bundle extras = prepareExtrasBundle(c);
extras.putParcelable(EXTRA_PARAM_KEY_PEER_ADDRESS, deviceAddress);
c.mAsyncChannel.sendMessage(prepareMessage(SET_CONNECTION_REQUEST_RESULT,
result, c.putListener(listener), extras, c.mContext));
}
/**
* Set the result with PIN for the incoming request from a specific peer.
*
* The application must have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
* android:usesPermissionFlags="neverForLocation". If the application does not declare
* android:usesPermissionFlags="neverForLocation", then it must also have
* {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
*
* @param c is the channel created at {@link #initialize(Context, Looper, ChannelListener)}.
* @param deviceAddress the peer which is bound to the external approver.
* @param result the response for the incoming request.
* @param pin the PIN for the incoming request.
* @param listener for callback on success or failure.
*/
@RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION)
public void setConnectionRequestResult(@NonNull Channel c, @NonNull MacAddress deviceAddress,
@ConnectionRequestResponse int result, @Nullable String pin,
@Nullable ActionListener listener) {
checkChannel(c);
if (null == deviceAddress) {
throw new IllegalArgumentException("deviceAddress cannot be empty");
}
if (result == CONNECTION_REQUEST_ACCEPT && TextUtils.isEmpty(pin)) {
throw new IllegalArgumentException("PIN cannot be empty for accepting a request");
}
Bundle extras = prepareExtrasBundle(c);
extras.putParcelable(EXTRA_PARAM_KEY_PEER_ADDRESS, deviceAddress);
extras.putString(EXTRA_PARAM_KEY_WPS_PIN, pin);
c.mAsyncChannel.sendMessage(prepareMessage(SET_CONNECTION_REQUEST_RESULT,
result, c.putListener(listener), extras, c.mContext));
}
/**
* Set/Clear vendor specific information elements (VSIEs) to be published during
* Wi-Fi Direct (P2P) discovery.
*
* Once {@link Channel#close()} is called, the vendor information elements will be cleared from
* framework. The information element format is defined in the IEEE 802.11-2016 spec
* Table 9-77.
*
* To clear the previously set vendor elements, call this API with an empty List.
*
* The maximum accumulated length of all VSIEs must be before the limit specified by
* {@link #getP2pMaxAllowedVendorElementsLengthBytes()}.
*
* To publish vendor elements, this API should be called before peer discovery API, ex.
* {@link #discoverPeers(Channel, ActionListener)}.
*
* Use {@link #isSetVendorElementsSupported()} to determine whether the device supports
* this feature. If {@link #isSetVendorElementsSupported()} return {@code false} then
* this method will throw {@link UnsupportedOperationException}.
*
* @param c is the channel created at {@link #initialize(Context, Looper, ChannelListener)}.
* @param vendorElements application information as vendor-specific information elements.
* @param listener for callback when network info is available.
*/
@RequiresPermission(allOf = {
android.Manifest.permission.NEARBY_WIFI_DEVICES,
android.Manifest.permission.OVERRIDE_WIFI_CONFIG
})
public void setVendorElements(@NonNull Channel c,
@NonNull List
* e.g) "MyPrinter".
* @param registrationType
* e.g) "_ipp._tcp.local."
* @param srcDevice source device.
*/
public void onDnsSdServiceAvailable(String instanceName,
String registrationType, WifiP2pDevice srcDevice);
}
/**
* Interface for callback invocation when Bonjour TXT record is available
* for a service
*/
public interface DnsSdTxtRecordListener {
/**
* The requested Bonjour service response is available.
*
*
* e.g) "MyPrinter._ipp._tcp.local.".
* @param txtRecordMap TXT record data as a map of key/value pairs
* @param srcDevice source device.
*/
public void onDnsSdTxtRecordAvailable(String fullDomainName,
Map
* e.g) uuid:6859dede-8574-59ab-9332-123456789012::urn:schemas-upnp-org:device:
* MediaServer:1
* @param srcDevice source device.
*/
public void onUpnpServiceAvailable(List
* or its subclass calls {@link WifiP2pUpnpServiceInfo#newInstance} or
* {@link WifiP2pDnsSdServiceInfo#newInstance} for a Upnp or Bonjour service
* respectively
*
*