/* * Copyright (C) 2008 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; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SuppressLint; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemApi; import android.annotation.SystemService; import android.content.Context; import android.content.pm.ParceledListSlice; import android.net.ConnectivityManager; import android.net.DhcpInfo; import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkRequest; import android.net.wifi.hotspot2.OsuProvider; import android.net.wifi.hotspot2.PasspointConfiguration; import android.net.wifi.hotspot2.IProvisioningCallback; import android.net.wifi.hotspot2.ProvisioningCallback; import android.os.Binder; import android.os.Build; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.Messenger; import android.os.RemoteException; import android.os.WorkSource; import android.util.Log; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.AsyncChannel; import com.android.internal.util.Protocol; import com.android.server.net.NetworkPinner; import dalvik.system.CloseGuard; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.ref.WeakReference; import java.net.InetAddress; import java.util.Collections; import java.util.List; import java.util.concurrent.CountDownLatch; /** * This class provides the primary API for managing all aspects of Wi-Fi * connectivity. *
* On releases before {@link android.os.Build.VERSION_CODES#N}, this object * should only be obtained from an {@linkplain Context#getApplicationContext() * application context}, and not from any other derived context to avoid memory * leaks within the calling process. *
* It deals with several categories of items: *
** This is the API to use when performing Wi-Fi specific operations. To perform * operations that pertain to network connectivity at an abstract level, use * {@link android.net.ConnectivityManager}. *
*/ @SystemService(Context.WIFI_SERVICE) public class WifiManager { private static final String TAG = "WifiManager"; // Supplicant error codes: /** * The error code if there was a problem authenticating. * @deprecated This is no longer supported. */ @Deprecated public static final int ERROR_AUTHENTICATING = 1; /** * The reason code if there is no error during authentication. * It could also imply that there no authentication in progress, * this reason code also serves as a reset value. * @deprecated This is no longer supported. * @hide */ @Deprecated public static final int ERROR_AUTH_FAILURE_NONE = 0; /** * The reason code if there was a timeout authenticating. * @deprecated This is no longer supported. * @hide */ @Deprecated public static final int ERROR_AUTH_FAILURE_TIMEOUT = 1; /** * The reason code if there was a wrong password while * authenticating. * @deprecated This is no longer supported. * @hide */ @Deprecated public static final int ERROR_AUTH_FAILURE_WRONG_PSWD = 2; /** * The reason code if there was EAP failure while * authenticating. * @deprecated This is no longer supported. * @hide */ @Deprecated public static final int ERROR_AUTH_FAILURE_EAP_FAILURE = 3; /** * Broadcast intent action indicating whether Wi-Fi scanning is allowed currently * @hide */ public static final String WIFI_SCAN_AVAILABLE = "wifi_scan_available"; /** * Extra int indicating scan availability, WIFI_STATE_ENABLED and WIFI_STATE_DISABLED * @hide */ public static final String EXTRA_SCAN_AVAILABLE = "scan_enabled"; /** * Broadcast intent action indicating that the credential of a Wi-Fi network * has been changed. One extra provides the ssid of the network. Another * extra provides the event type, whether the credential is saved or forgot. * @hide */ @SystemApi public static final String WIFI_CREDENTIAL_CHANGED_ACTION = "android.net.wifi.WIFI_CREDENTIAL_CHANGED"; /** @hide */ @SystemApi public static final String EXTRA_WIFI_CREDENTIAL_EVENT_TYPE = "et"; /** @hide */ @SystemApi public static final String EXTRA_WIFI_CREDENTIAL_SSID = "ssid"; /** @hide */ @SystemApi public static final int WIFI_CREDENTIAL_SAVED = 0; /** @hide */ @SystemApi public static final int WIFI_CREDENTIAL_FORGOT = 1; /** * Broadcast intent action indicating that a Passpoint provider icon has been received. * * Included extras: * {@link #EXTRA_BSSID_LONG} * {@link #EXTRA_FILENAME} * {@link #EXTRA_ICON} * * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE * *Note: The broadcast is only delivered to registered receivers - no manifest registered * components will be launched. * * @hide */ public static final String ACTION_PASSPOINT_ICON = "android.net.wifi.action.PASSPOINT_ICON"; /** * BSSID of an AP in long representation. The {@link #EXTRA_BSSID} contains BSSID in * String representation. * * Retrieve with {@link android.content.Intent#getLongExtra(String, long)}. * * @hide */ public static final String EXTRA_BSSID_LONG = "android.net.wifi.extra.BSSID_LONG"; /** * Icon data. * * Retrieve with {@link android.content.Intent#getParcelableExtra(String)} and cast into * {@link android.graphics.drawable.Icon}. * * @hide */ public static final String EXTRA_ICON = "android.net.wifi.extra.ICON"; /** * Name of a file. * * Retrieve with {@link android.content.Intent#getStringExtra(String)}. * * @hide */ public static final String EXTRA_FILENAME = "android.net.wifi.extra.FILENAME"; /** * Broadcast intent action indicating a Passpoint OSU Providers List element has been received. * * Included extras: * {@link #EXTRA_BSSID_LONG} * {@link #EXTRA_ANQP_ELEMENT_DATA} * * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE * *
Note: The broadcast is only delivered to registered receivers - no manifest registered * components will be launched. * * @hide */ public static final String ACTION_PASSPOINT_OSU_PROVIDERS_LIST = "android.net.wifi.action.PASSPOINT_OSU_PROVIDERS_LIST"; /** * Raw binary data of an ANQP (Access Network Query Protocol) element. * * Retrieve with {@link android.content.Intent#getByteArrayExtra(String)}. * * @hide */ public static final String EXTRA_ANQP_ELEMENT_DATA = "android.net.wifi.extra.ANQP_ELEMENT_DATA"; /** * Broadcast intent action indicating that a Passpoint Deauth Imminent frame has been received. * * Included extras: * {@link #EXTRA_BSSID_LONG} * {@link #EXTRA_ESS} * {@link #EXTRA_DELAY} * {@link #EXTRA_URL} * * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE * *
Note: The broadcast is only delivered to registered receivers - no manifest registered * components will be launched. * * @hide */ public static final String ACTION_PASSPOINT_DEAUTH_IMMINENT = "android.net.wifi.action.PASSPOINT_DEAUTH_IMMINENT"; /** * Flag indicating BSS (Basic Service Set) or ESS (Extended Service Set). This will be set to * {@code true} for ESS. * * Retrieve with {@link android.content.Intent#getBooleanExtra(String, boolean)}. * * @hide */ public static final String EXTRA_ESS = "android.net.wifi.extra.ESS"; /** * Delay in seconds. * * Retrieve with {@link android.content.Intent#getIntExtra(String, int)}. * * @hide */ public static final String EXTRA_DELAY = "android.net.wifi.extra.DELAY"; /** * String representation of an URL. * * Retrieve with {@link android.content.Intent#getStringExtra(String)}. * * @hide */ public static final String EXTRA_URL = "android.net.wifi.extra.URL"; /** * Broadcast intent action indicating a Passpoint subscription remediation frame has been * received. * * Included extras: * {@link #EXTRA_BSSID_LONG} * {@link #EXTRA_SUBSCRIPTION_REMEDIATION_METHOD} * {@link #EXTRA_URL} * * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE * *
Note: The broadcast is only delivered to registered receivers - no manifest registered * components will be launched. * * @hide */ public static final String ACTION_PASSPOINT_SUBSCRIPTION_REMEDIATION = "android.net.wifi.action.PASSPOINT_SUBSCRIPTION_REMEDIATION"; /** * The protocol supported by the subscription remediation server. The possible values are: * 0 - OMA DM * 1 - SOAP XML SPP * * Retrieve with {@link android.content.Intent#getIntExtra(String, int)}. * * @hide */ public static final String EXTRA_SUBSCRIPTION_REMEDIATION_METHOD = "android.net.wifi.extra.SUBSCRIPTION_REMEDIATION_METHOD"; /** * Broadcast intent action indicating that Wi-Fi has been enabled, disabled, * enabling, disabling, or unknown. One extra provides this state as an int. * Another extra provides the previous state, if available. * * @see #EXTRA_WIFI_STATE * @see #EXTRA_PREVIOUS_WIFI_STATE */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String WIFI_STATE_CHANGED_ACTION = "android.net.wifi.WIFI_STATE_CHANGED"; /** * The lookup key for an int that indicates whether Wi-Fi is enabled, * disabled, enabling, disabling, or unknown. Retrieve it with * {@link android.content.Intent#getIntExtra(String,int)}. * * @see #WIFI_STATE_DISABLED * @see #WIFI_STATE_DISABLING * @see #WIFI_STATE_ENABLED * @see #WIFI_STATE_ENABLING * @see #WIFI_STATE_UNKNOWN */ public static final String EXTRA_WIFI_STATE = "wifi_state"; /** * The previous Wi-Fi state. * * @see #EXTRA_WIFI_STATE */ public static final String EXTRA_PREVIOUS_WIFI_STATE = "previous_wifi_state"; /** * Wi-Fi is currently being disabled. The state will change to {@link #WIFI_STATE_DISABLED} if * it finishes successfully. * * @see #WIFI_STATE_CHANGED_ACTION * @see #getWifiState() */ public static final int WIFI_STATE_DISABLING = 0; /** * Wi-Fi is disabled. * * @see #WIFI_STATE_CHANGED_ACTION * @see #getWifiState() */ public static final int WIFI_STATE_DISABLED = 1; /** * Wi-Fi is currently being enabled. The state will change to {@link #WIFI_STATE_ENABLED} if * it finishes successfully. * * @see #WIFI_STATE_CHANGED_ACTION * @see #getWifiState() */ public static final int WIFI_STATE_ENABLING = 2; /** * Wi-Fi is enabled. * * @see #WIFI_STATE_CHANGED_ACTION * @see #getWifiState() */ public static final int WIFI_STATE_ENABLED = 3; /** * Wi-Fi is in an unknown state. This state will occur when an error happens while enabling * or disabling. * * @see #WIFI_STATE_CHANGED_ACTION * @see #getWifiState() */ public static final int WIFI_STATE_UNKNOWN = 4; /** * Broadcast intent action indicating that Wi-Fi AP has been enabled, disabled, * enabling, disabling, or failed. * * @hide */ @SystemApi public static final String WIFI_AP_STATE_CHANGED_ACTION = "android.net.wifi.WIFI_AP_STATE_CHANGED"; /** * The lookup key for an int that indicates whether Wi-Fi AP is enabled, * disabled, enabling, disabling, or failed. Retrieve it with * {@link android.content.Intent#getIntExtra(String,int)}. * * @see #WIFI_AP_STATE_DISABLED * @see #WIFI_AP_STATE_DISABLING * @see #WIFI_AP_STATE_ENABLED * @see #WIFI_AP_STATE_ENABLING * @see #WIFI_AP_STATE_FAILED * * @hide */ @SystemApi public static final String EXTRA_WIFI_AP_STATE = "wifi_state"; /** * The look up key for an int that indicates why softAP started failed * currently support general and no_channel * @see #SAP_START_FAILURE_GENERIC * @see #SAP_START_FAILURE_NO_CHANNEL * * @hide */ public static final String EXTRA_WIFI_AP_FAILURE_REASON = "wifi_ap_error_code"; /** * The previous Wi-Fi state. * * @see #EXTRA_WIFI_AP_STATE * * @hide */ @SystemApi public static final String EXTRA_PREVIOUS_WIFI_AP_STATE = "previous_wifi_state"; /** * The interface used for the softap. * * @hide */ public static final String EXTRA_WIFI_AP_INTERFACE_NAME = "wifi_ap_interface_name"; /** * The intended ip mode for this softap. * @see #IFACE_IP_MODE_TETHERED * @see #IFACE_IP_MODE_LOCAL_ONLY * * @hide */ public static final String EXTRA_WIFI_AP_MODE = "wifi_ap_mode"; /** @hide */ @IntDef(flag = false, prefix = { "WIFI_AP_STATE_" }, value = { WIFI_AP_STATE_DISABLING, WIFI_AP_STATE_DISABLED, WIFI_AP_STATE_ENABLING, WIFI_AP_STATE_ENABLED, WIFI_AP_STATE_FAILED, }) @Retention(RetentionPolicy.SOURCE) public @interface WifiApState {} /** * Wi-Fi AP is currently being disabled. The state will change to * {@link #WIFI_AP_STATE_DISABLED} if it finishes successfully. * * @see #WIFI_AP_STATE_CHANGED_ACTION * @see #getWifiApState() * * @hide */ @SystemApi public static final int WIFI_AP_STATE_DISABLING = 10; /** * Wi-Fi AP is disabled. * * @see #WIFI_AP_STATE_CHANGED_ACTION * @see #getWifiState() * * @hide */ @SystemApi public static final int WIFI_AP_STATE_DISABLED = 11; /** * Wi-Fi AP is currently being enabled. The state will change to * {@link #WIFI_AP_STATE_ENABLED} if it finishes successfully. * * @see #WIFI_AP_STATE_CHANGED_ACTION * @see #getWifiApState() * * @hide */ @SystemApi public static final int WIFI_AP_STATE_ENABLING = 12; /** * Wi-Fi AP is enabled. * * @see #WIFI_AP_STATE_CHANGED_ACTION * @see #getWifiApState() * * @hide */ @SystemApi public static final int WIFI_AP_STATE_ENABLED = 13; /** * Wi-Fi AP is in a failed state. This state will occur when an error occurs during * enabling or disabling * * @see #WIFI_AP_STATE_CHANGED_ACTION * @see #getWifiApState() * * @hide */ @SystemApi public static final int WIFI_AP_STATE_FAILED = 14; /** @hide */ @IntDef(flag = false, prefix = { "SAP_START_FAILURE_" }, value = { SAP_START_FAILURE_GENERAL, SAP_START_FAILURE_NO_CHANNEL, }) @Retention(RetentionPolicy.SOURCE) public @interface SapStartFailure {} /** * If WIFI AP start failed, this reason code means there is no legal channel exists on * user selected band by regulatory * * @hide */ public static final int SAP_START_FAILURE_GENERAL= 0; /** * All other reason for AP start failed besides SAP_START_FAILURE_GENERAL * * @hide */ public static final int SAP_START_FAILURE_NO_CHANNEL = 1; /** * Interface IP mode unspecified. * * @see updateInterfaceIpState(String, int) * * @hide */ public static final int IFACE_IP_MODE_UNSPECIFIED = -1; /** * Interface IP mode for configuration error. * * @see updateInterfaceIpState(String, int) * * @hide */ public static final int IFACE_IP_MODE_CONFIGURATION_ERROR = 0; /** * Interface IP mode for tethering. * * @see updateInterfaceIpState(String, int) * * @hide */ public static final int IFACE_IP_MODE_TETHERED = 1; /** * Interface IP mode for Local Only Hotspot. * * @see updateInterfaceIpState(String, int) * * @hide */ public static final int IFACE_IP_MODE_LOCAL_ONLY = 2; /** * Broadcast intent action indicating that a connection to the supplicant has * been established (and it is now possible * to perform Wi-Fi operations) or the connection to the supplicant has been * lost. One extra provides the connection state as a boolean, where {@code true} * means CONNECTED. * @deprecated This is no longer supported. * @see #EXTRA_SUPPLICANT_CONNECTED */ @Deprecated @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String SUPPLICANT_CONNECTION_CHANGE_ACTION = "android.net.wifi.supplicant.CONNECTION_CHANGE"; /** * The lookup key for a boolean that indicates whether a connection to * the supplicant daemon has been gained or lost. {@code true} means * a connection now exists. * Retrieve it with {@link android.content.Intent#getBooleanExtra(String,boolean)}. * @deprecated This is no longer supported. */ @Deprecated public static final String EXTRA_SUPPLICANT_CONNECTED = "connected"; /** * Broadcast intent action indicating that the state of Wi-Fi connectivity * has changed. An extra provides the new state * in the form of a {@link android.net.NetworkInfo} object. * @see #EXTRA_NETWORK_INFO */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String NETWORK_STATE_CHANGED_ACTION = "android.net.wifi.STATE_CHANGE"; /** * The lookup key for a {@link android.net.NetworkInfo} object associated with the * Wi-Fi network. Retrieve with * {@link android.content.Intent#getParcelableExtra(String)}. */ public static final String EXTRA_NETWORK_INFO = "networkInfo"; /** * The lookup key for a String giving the BSSID of the access point to which * we are connected. No longer used. */ @Deprecated public static final String EXTRA_BSSID = "bssid"; /** * The lookup key for a {@link android.net.wifi.WifiInfo} object giving the * information about the access point to which we are connected. * No longer used. */ @Deprecated public static final String EXTRA_WIFI_INFO = "wifiInfo"; /** * Broadcast intent action indicating that the state of establishing a connection to * an access point has changed.One extra provides the new * {@link SupplicantState}. Note that the supplicant state is Wi-Fi specific, and * is not generally the most useful thing to look at if you are just interested in * the overall state of connectivity. * @see #EXTRA_NEW_STATE * @see #EXTRA_SUPPLICANT_ERROR * @deprecated This is no longer supported. */ @Deprecated @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String SUPPLICANT_STATE_CHANGED_ACTION = "android.net.wifi.supplicant.STATE_CHANGE"; /** * The lookup key for a {@link SupplicantState} describing the new state * Retrieve with * {@link android.content.Intent#getParcelableExtra(String)}. * @deprecated This is no longer supported. */ @Deprecated public static final String EXTRA_NEW_STATE = "newState"; /** * The lookup key for a {@link SupplicantState} describing the supplicant * error code if any * Retrieve with * {@link android.content.Intent#getIntExtra(String, int)}. * @see #ERROR_AUTHENTICATING * @deprecated This is no longer supported. */ @Deprecated public static final String EXTRA_SUPPLICANT_ERROR = "supplicantError"; /** * The lookup key for a {@link SupplicantState} describing the supplicant * error reason if any * Retrieve with * {@link android.content.Intent#getIntExtra(String, int)}. * @see #ERROR_AUTH_FAILURE_#REASON_CODE * @deprecated This is no longer supported. * @hide */ @Deprecated public static final String EXTRA_SUPPLICANT_ERROR_REASON = "supplicantErrorReason"; /** * Broadcast intent action indicating that the configured networks changed. * This can be as a result of adding/updating/deleting a network. If * {@link #EXTRA_MULTIPLE_NETWORKS_CHANGED} is set to true the new configuration * can be retreived with the {@link #EXTRA_WIFI_CONFIGURATION} extra. If multiple * Wi-Fi configurations changed, {@link #EXTRA_WIFI_CONFIGURATION} will not be present. * @hide */ @SystemApi public static final String CONFIGURED_NETWORKS_CHANGED_ACTION = "android.net.wifi.CONFIGURED_NETWORKS_CHANGE"; /** * The lookup key for a (@link android.net.wifi.WifiConfiguration} object representing * the changed Wi-Fi configuration when the {@link #CONFIGURED_NETWORKS_CHANGED_ACTION} * broadcast is sent. * @hide */ @SystemApi public static final String EXTRA_WIFI_CONFIGURATION = "wifiConfiguration"; /** * Multiple network configurations have changed. * @see #CONFIGURED_NETWORKS_CHANGED_ACTION * * @hide */ @SystemApi public static final String EXTRA_MULTIPLE_NETWORKS_CHANGED = "multipleChanges"; /** * The lookup key for an integer indicating the reason a Wi-Fi network configuration * has changed. Only present if {@link #EXTRA_MULTIPLE_NETWORKS_CHANGED} is {@code false} * @see #CONFIGURED_NETWORKS_CHANGED_ACTION * @hide */ @SystemApi public static final String EXTRA_CHANGE_REASON = "changeReason"; /** * The configuration is new and was added. * @hide */ @SystemApi public static final int CHANGE_REASON_ADDED = 0; /** * The configuration was removed and is no longer present in the system's list of * configured networks. * @hide */ @SystemApi public static final int CHANGE_REASON_REMOVED = 1; /** * The configuration has changed as a result of explicit action or because the system * took an automated action such as disabling a malfunctioning configuration. * @hide */ @SystemApi public static final int CHANGE_REASON_CONFIG_CHANGE = 2; /** * An access point scan has completed, and results are available. * Call {@link #getScanResults()} to obtain the results. * The broadcast intent may contain an extra field with the key {@link #EXTRA_RESULTS_UPDATED} * and a {@code boolean} value indicating if the scan was successful. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String SCAN_RESULTS_AVAILABLE_ACTION = "android.net.wifi.SCAN_RESULTS"; /** * Lookup key for a {@code boolean} extra in intent {@link #SCAN_RESULTS_AVAILABLE_ACTION} * representing if the scan was successful or not. * Scans may fail for multiple reasons, these may include: *
Notification of the result of this activity is posted using the
* {@link android.app.Activity#onActivityResult} callback. The
* resultCode
* will be {@link android.app.Activity#RESULT_OK} if scan always mode has
* been turned on or {@link android.app.Activity#RESULT_CANCELED} if the user
* has rejected the request or an error has occurred.
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE =
"android.net.wifi.action.REQUEST_SCAN_ALWAYS_AVAILABLE";
/**
* Activity Action: Pick a Wi-Fi network to connect to.
*
Input: Nothing. *
Output: Nothing. */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK"; /** * Activity Action: Show UI to get user approval to enable WiFi. *
Input: {@link android.content.Intent#EXTRA_PACKAGE_NAME} string extra with * the name of the app requesting the action. *
Output: Nothing. * * @hide */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_REQUEST_ENABLE = "android.net.wifi.action.REQUEST_ENABLE"; /** * Activity Action: Show UI to get user approval to disable WiFi. *
Input: {@link android.content.Intent#EXTRA_PACKAGE_NAME} string extra with * the name of the app requesting the action. *
Output: Nothing. * * @hide */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_REQUEST_DISABLE = "android.net.wifi.action.REQUEST_DISABLE"; /** * Internally used Wi-Fi lock mode representing the case were no locks are held. * @hide */ public static final int WIFI_MODE_NO_LOCKS_HELD = 0; /** * In this Wi-Fi lock mode, Wi-Fi will be kept active, * and will behave normally, i.e., it will attempt to automatically * establish a connection to a remembered access point that is * within range, and will do periodic scans if there are remembered * access points but none are in range. */ public static final int WIFI_MODE_FULL = 1; /** * In this Wi-Fi lock mode, Wi-Fi will be kept active, * but the only operation that will be supported is initiation of * scans, and the subsequent reporting of scan results. No attempts * will be made to automatically connect to remembered access points, * nor will periodic scans be automatically performed looking for * remembered access points. Scans must be explicitly requested by * an application in this mode. */ public static final int WIFI_MODE_SCAN_ONLY = 2; /** * In this Wi-Fi lock mode, Wi-Fi will be kept active as in mode * {@link #WIFI_MODE_FULL} but it operates at high performance * with minimum packet loss and low packet latency even when * the device screen is off. This mode will consume more power * and hence should be used only when there is a need for such * an active connection. *
* An example use case is when a voice connection needs to be * kept active even after the device screen goes off. Holding the * regular {@link #WIFI_MODE_FULL} lock will keep the wifi * connection active, but the connection can be lossy. * Holding a {@link #WIFI_MODE_FULL_HIGH_PERF} lock for the * duration of the voice call will improve the call quality. *
* When there is no support from the hardware, this lock mode * will have the same behavior as {@link #WIFI_MODE_FULL} */ public static final int WIFI_MODE_FULL_HIGH_PERF = 3; /** Anything worse than or equal to this will show 0 bars. */ private static final int MIN_RSSI = -100; /** Anything better than or equal to this will show the max bars. */ private static final int MAX_RSSI = -55; /** * Number of RSSI levels used in the framework to initiate * {@link #RSSI_CHANGED_ACTION} broadcast * @hide */ public static final int RSSI_LEVELS = 5; /** * Auto settings in the driver. The driver could choose to operate on both * 2.4 GHz and 5 GHz or make a dynamic decision on selecting the band. * @hide */ public static final int WIFI_FREQUENCY_BAND_AUTO = 0; /** * Operation on 5 GHz alone * @hide */ public static final int WIFI_FREQUENCY_BAND_5GHZ = 1; /** * Operation on 2.4 GHz alone * @hide */ public static final int WIFI_FREQUENCY_BAND_2GHZ = 2; /** List of asyncronous notifications * @hide */ public static final int DATA_ACTIVITY_NOTIFICATION = 1; //Lowest bit indicates data reception and the second lowest //bit indicates data transmitted /** @hide */ public static final int DATA_ACTIVITY_NONE = 0x00; /** @hide */ public static final int DATA_ACTIVITY_IN = 0x01; /** @hide */ public static final int DATA_ACTIVITY_OUT = 0x02; /** @hide */ public static final int DATA_ACTIVITY_INOUT = 0x03; /** @hide */ public static final boolean DEFAULT_POOR_NETWORK_AVOIDANCE_ENABLED = false; /* Maximum number of active locks we allow. * This limit was added to prevent apps from creating a ridiculous number * of locks and crashing the system by overflowing the global ref table. */ private static final int MAX_ACTIVE_LOCKS = 50; /* Number of currently active WifiLocks and MulticastLocks */ private int mActiveLockCount; private Context mContext; IWifiManager mService; private final int mTargetSdkVersion; private static final int INVALID_KEY = 0; private int mListenerKey = 1; private final SparseArray mListenerMap = new SparseArray(); private final Object mListenerMapLock = new Object(); private AsyncChannel mAsyncChannel; private CountDownLatch mConnected; private Looper mLooper; /* LocalOnlyHotspot callback message types */ /** @hide */ public static final int HOTSPOT_STARTED = 0; /** @hide */ public static final int HOTSPOT_STOPPED = 1; /** @hide */ public static final int HOTSPOT_FAILED = 2; /** @hide */ public static final int HOTSPOT_OBSERVER_REGISTERED = 3; private final Object mLock = new Object(); // lock guarding access to the following vars @GuardedBy("mLock") private LocalOnlyHotspotCallbackProxy mLOHSCallbackProxy; @GuardedBy("mLock") private LocalOnlyHotspotObserverProxy mLOHSObserverProxy; /** * Create a new WifiManager instance. * Applications will almost always want to use * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve * the standard {@link android.content.Context#WIFI_SERVICE Context.WIFI_SERVICE}. * @param context the application context * @param service the Binder interface * @hide - hide this because it takes in a parameter of type IWifiManager, which * is a system private class. */ public WifiManager(Context context, IWifiManager service, Looper looper) { mContext = context; mService = service; mLooper = looper; mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion; } /** * Return a list of all the networks configured for the current foreground * user. * Not all fields of WifiConfiguration are returned. Only the following * fields are filled in: *
null
. The {@code networkId} field
* must be set to the ID of the existing network being updated.
* If the {@link WifiConfiguration} has an Http Proxy set
* the calling app must be System, or be provisioned as the Profile or Device Owner.
* @return Returns the {@code networkId} of the supplied
* {@code WifiConfiguration} on success.
* attemptConnect
is true, an attempt to connect to the selected
* network is initiated. This may result in the asynchronous delivery
* of state change events.
* * Note: If an application's target SDK version is * {@link android.os.Build.VERSION_CODES#LOLLIPOP} or newer, network * communication may not use Wi-Fi even if Wi-Fi is connected; traffic may * instead be sent through another network, such as cellular data, * Bluetooth tethering, or Ethernet. For example, traffic will never use a * Wi-Fi network that does not provide Internet access (e.g. a wireless * printer), if another network that does offer Internet access (e.g. * cellular data) is available. Applications that need to ensure that their * network traffic uses Wi-Fi should use APIs such as * {@link Network#bindSocket(java.net.Socket)}, * {@link Network#openConnection(java.net.URL)}, or * {@link ConnectivityManager#bindProcessToNetwork} to do so. * * Applications are not allowed to enable networks created by other * applications. * * @param netId the ID of the network as returned by {@link #addNetwork} or {@link * #getConfiguredNetworks}. * @param attemptConnect The way to select a particular network to connect to is specify * {@code true} for this parameter. * @return {@code true} if the operation succeeded */ public boolean enableNetwork(int netId, boolean attemptConnect) { final boolean pin = attemptConnect && mTargetSdkVersion < Build.VERSION_CODES.LOLLIPOP; if (pin) { NetworkRequest request = new NetworkRequest.Builder() .clearCapabilities() .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) .build(); NetworkPinner.pin(mContext, request); } boolean success; try { success = mService.enableNetwork(netId, attemptConnect, mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } if (pin && !success) { NetworkPinner.unpin(); } return success; } /** * Disable a configured network. The specified network will not be * a candidate for associating. This may result in the asynchronous * delivery of state change events. * * Applications are not allowed to disable networks created by other * applications. * * @param netId the ID of the network as returned by {@link #addNetwork} or {@link * #getConfiguredNetworks}. * @return {@code true} if the operation succeeded */ public boolean disableNetwork(int netId) { try { return mService.disableNetwork(netId, mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Disassociate from the currently active access point. This may result * in the asynchronous delivery of state change events. * @return {@code true} if the operation succeeded */ public boolean disconnect() { try { mService.disconnect(mContext.getOpPackageName()); return true; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Reconnect to the currently active access point, if we are currently * disconnected. This may result in the asynchronous delivery of state * change events. * @return {@code true} if the operation succeeded */ public boolean reconnect() { try { mService.reconnect(mContext.getOpPackageName()); return true; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Reconnect to the currently active access point, even if we are already * connected. This may result in the asynchronous delivery of state * change events. * @return {@code true} if the operation succeeded */ public boolean reassociate() { try { mService.reassociate(mContext.getOpPackageName()); return true; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Check that the supplicant daemon is responding to requests. * @return {@code true} if we were able to communicate with the supplicant and * it returned the expected response to the PING message. * @deprecated Will return the output of {@link #isWifiEnabled()} instead. */ @Deprecated public boolean pingSupplicant() { return isWifiEnabled(); } /** @hide */ public static final int WIFI_FEATURE_INFRA = 0x0001; // Basic infrastructure mode /** @hide */ public static final int WIFI_FEATURE_INFRA_5G = 0x0002; // Support for 5 GHz Band /** @hide */ public static final int WIFI_FEATURE_PASSPOINT = 0x0004; // Support for GAS/ANQP /** @hide */ public static final int WIFI_FEATURE_P2P = 0x0008; // Wifi-Direct /** @hide */ public static final int WIFI_FEATURE_MOBILE_HOTSPOT = 0x0010; // Soft AP /** @hide */ public static final int WIFI_FEATURE_SCANNER = 0x0020; // WifiScanner APIs /** @hide */ public static final int WIFI_FEATURE_AWARE = 0x0040; // Wi-Fi AWare networking /** @hide */ public static final int WIFI_FEATURE_D2D_RTT = 0x0080; // Device-to-device RTT /** @hide */ public static final int WIFI_FEATURE_D2AP_RTT = 0x0100; // Device-to-AP RTT /** @hide */ public static final int WIFI_FEATURE_BATCH_SCAN = 0x0200; // Batched Scan (deprecated) /** @hide */ public static final int WIFI_FEATURE_PNO = 0x0400; // Preferred network offload /** @hide */ public static final int WIFI_FEATURE_ADDITIONAL_STA = 0x0800; // Support for two STAs /** @hide */ public static final int WIFI_FEATURE_TDLS = 0x1000; // Tunnel directed link setup /** @hide */ public static final int WIFI_FEATURE_TDLS_OFFCHANNEL = 0x2000; // Support for TDLS off channel /** @hide */ public static final int WIFI_FEATURE_EPR = 0x4000; // Enhanced power reporting /** @hide */ public static final int WIFI_FEATURE_AP_STA = 0x8000; // AP STA Concurrency /** @hide */ public static final int WIFI_FEATURE_LINK_LAYER_STATS = 0x10000; // Link layer stats collection /** @hide */ public static final int WIFI_FEATURE_LOGGER = 0x20000; // WiFi Logger /** @hide */ public static final int WIFI_FEATURE_HAL_EPNO = 0x40000; // Enhanced PNO /** @hide */ public static final int WIFI_FEATURE_RSSI_MONITOR = 0x80000; // RSSI Monitor /** @hide */ public static final int WIFI_FEATURE_MKEEP_ALIVE = 0x100000; // mkeep_alive /** @hide */ public static final int WIFI_FEATURE_CONFIG_NDO = 0x200000; // ND offload /** @hide */ public static final int WIFI_FEATURE_TRANSMIT_POWER = 0x400000; // Capture transmit power /** @hide */ public static final int WIFI_FEATURE_CONTROL_ROAMING = 0x800000; // Control firmware roaming /** @hide */ public static final int WIFI_FEATURE_IE_WHITELIST = 0x1000000; // Probe IE white listing /** @hide */ public static final int WIFI_FEATURE_SCAN_RAND = 0x2000000; // Random MAC & Probe seq /** @hide */ public static final int WIFI_FEATURE_TX_POWER_LIMIT = 0x4000000; // Set Tx power limit private int getSupportedFeatures() { try { return mService.getSupportedFeatures(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } private boolean isFeatureSupported(int feature) { return (getSupportedFeatures() & feature) == feature; } /** * @return true if this adapter supports 5 GHz band */ public boolean is5GHzBandSupported() { return isFeatureSupported(WIFI_FEATURE_INFRA_5G); } /** * @return true if this adapter supports Passpoint * @hide */ public boolean isPasspointSupported() { return isFeatureSupported(WIFI_FEATURE_PASSPOINT); } /** * @return true if this adapter supports WifiP2pManager (Wi-Fi Direct) */ public boolean isP2pSupported() { return isFeatureSupported(WIFI_FEATURE_P2P); } /** * @return true if this adapter supports portable Wi-Fi hotspot * @hide */ @SystemApi public boolean isPortableHotspotSupported() { return isFeatureSupported(WIFI_FEATURE_MOBILE_HOTSPOT); } /** * @return true if this adapter supports WifiScanner APIs * @hide */ @SystemApi public boolean isWifiScannerSupported() { return isFeatureSupported(WIFI_FEATURE_SCANNER); } /** * @return true if this adapter supports Neighbour Awareness Network APIs * @hide */ public boolean isWifiAwareSupported() { return isFeatureSupported(WIFI_FEATURE_AWARE); } /** * @return true if this adapter supports Device-to-device RTT * @hide */ @SystemApi public boolean isDeviceToDeviceRttSupported() { return isFeatureSupported(WIFI_FEATURE_D2D_RTT); } /** * @return true if this adapter supports Device-to-AP RTT */ @SystemApi public boolean isDeviceToApRttSupported() { return isFeatureSupported(WIFI_FEATURE_D2AP_RTT); } /** * @return true if this adapter supports offloaded connectivity scan */ public boolean isPreferredNetworkOffloadSupported() { return isFeatureSupported(WIFI_FEATURE_PNO); } /** * @return true if this adapter supports multiple simultaneous connections * @hide */ public boolean isAdditionalStaSupported() { return isFeatureSupported(WIFI_FEATURE_ADDITIONAL_STA); } /** * @return true if this adapter supports Tunnel Directed Link Setup */ public boolean isTdlsSupported() { return isFeatureSupported(WIFI_FEATURE_TDLS); } /** * @return true if this adapter supports Off Channel Tunnel Directed Link Setup * @hide */ public boolean isOffChannelTdlsSupported() { return isFeatureSupported(WIFI_FEATURE_TDLS_OFFCHANNEL); } /** * @return true if this adapter supports advanced power/performance counters */ public boolean isEnhancedPowerReportingSupported() { return isFeatureSupported(WIFI_FEATURE_LINK_LAYER_STATS); } /** * Return the record of {@link WifiActivityEnergyInfo} object that * has the activity and energy info. This can be used to ascertain what * the controller has been up to, since the last sample. * @param updateType Type of info, cached vs refreshed. * * @return a record with {@link WifiActivityEnergyInfo} or null if * report is unavailable or unsupported * @hide */ public WifiActivityEnergyInfo getControllerActivityEnergyInfo(int updateType) { if (mService == null) return null; try { synchronized(this) { return mService.reportActivityInfo(); } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Request a scan for access points. Returns immediately. The availability * of the results is made known later by means of an asynchronous event sent * on completion of the scan. *
* To initiate a Wi-Fi scan, declare the * {@link android.Manifest.permission#CHANGE_WIFI_STATE} * permission in the manifest, and perform these steps: *
*
* In the connected state, access to the SSID and BSSID requires
* the same permissions as {@link #getScanResults}. If such access is not allowed,
* {@link WifiInfo#getSSID} will return {@code "
* Note: It is possible for this method to change the network IDs of
* existing networks. You should assume the network IDs can be different
* after calling this method.
*
* @return {@code false} Will always return true.
* @deprecated There is no need to call this method -
* {@link #addNetwork(WifiConfiguration)}, {@link #updateNetwork(WifiConfiguration)}
* and {@link #removeNetwork(int)} already persist the configurations automatically.
*/
@Deprecated
public boolean saveConfiguration() {
return true;
}
/**
* Set the country code.
* @param countryCode country code in ISO 3166 format.
*
* @hide
*/
public void setCountryCode(@NonNull String country) {
try {
mService.setCountryCode(country);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* get the country code.
* @return the country code in ISO 3166 format.
*
* @hide
*/
public String getCountryCode() {
try {
String country = mService.getCountryCode();
return country;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Check if the chipset supports dual frequency band (2.4 GHz and 5 GHz)
* @return {@code true} if supported, {@code false} otherwise.
* @hide
*/
public boolean isDualBandSupported() {
try {
return mService.isDualBandSupported();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Return the DHCP-assigned addresses from the last successful DHCP request,
* if any.
* @return the DHCP information
*/
public DhcpInfo getDhcpInfo() {
try {
return mService.getDhcpInfo();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Enable or disable Wi-Fi.
*
* Applications must have the {@link android.Manifest.permission#CHANGE_WIFI_STATE}
* permission to toggle wifi.
*
* @param enabled {@code true} to enable, {@code false} to disable.
* @return {@code false} if the request cannot be satisfied; {@code true} indicates that wifi is
* either already in the requested state, or in progress toward the requested state.
* @throws {@link java.lang.SecurityException} if the caller is missing required permissions.
*/
public boolean setWifiEnabled(boolean enabled) {
try {
return mService.setWifiEnabled(mContext.getOpPackageName(), enabled);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Gets the Wi-Fi enabled state.
* @return One of {@link #WIFI_STATE_DISABLED},
* {@link #WIFI_STATE_DISABLING}, {@link #WIFI_STATE_ENABLED},
* {@link #WIFI_STATE_ENABLING}, {@link #WIFI_STATE_UNKNOWN}
* @see #isWifiEnabled()
*/
public int getWifiState() {
try {
return mService.getWifiEnabledState();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Return whether Wi-Fi is enabled or disabled.
* @return {@code true} if Wi-Fi is enabled
* @see #getWifiState()
*/
public boolean isWifiEnabled() {
return getWifiState() == WIFI_STATE_ENABLED;
}
/**
* Return TX packet counter, for CTS test of WiFi watchdog.
* @param listener is the interface to receive result
*
* @hide for CTS test only
*/
public void getTxPacketCount(TxPacketCountListener listener) {
getChannel().sendMessage(RSSI_PKTCNT_FETCH, 0, putListener(listener));
}
/**
* Calculates the level of the signal. This should be used any time a signal
* is being shown.
*
* @param rssi The power of the signal measured in RSSI.
* @param numLevels The number of levels to consider in the calculated
* level.
* @return A level of the signal, given in the range of 0 to numLevels-1
* (both inclusive).
*/
public static int calculateSignalLevel(int rssi, int numLevels) {
if (rssi <= MIN_RSSI) {
return 0;
} else if (rssi >= MAX_RSSI) {
return numLevels - 1;
} else {
float inputRange = (MAX_RSSI - MIN_RSSI);
float outputRange = (numLevels - 1);
return (int)((float)(rssi - MIN_RSSI) * outputRange / inputRange);
}
}
/**
* Compares two signal strengths.
*
* @param rssiA The power of the first signal measured in RSSI.
* @param rssiB The power of the second signal measured in RSSI.
* @return Returns <0 if the first signal is weaker than the second signal,
* 0 if the two signals have the same strength, and >0 if the first
* signal is stronger than the second signal.
*/
public static int compareSignalLevel(int rssiA, int rssiB) {
return rssiA - rssiB;
}
/**
* Call allowing ConnectivityService to update WifiService with interface mode changes.
*
* The possible modes include: {@link IFACE_IP_MODE_TETHERED},
* {@link IFACE_IP_MODE_LOCAL_ONLY},
* {@link IFACE_IP_MODE_CONFIGURATION_ERROR}
*
* @param ifaceName String name of the updated interface
* @param mode int representing the new mode
*
* @hide
*/
public void updateInterfaceIpState(String ifaceName, int mode) {
try {
mService.updateInterfaceIpState(ifaceName, mode);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Start SoftAp mode with the specified configuration.
* Note that starting in access point mode disables station
* mode operation
* @param wifiConfig SSID, security and channel details as
* part of WifiConfiguration
* @return {@code true} if the operation succeeds, {@code false} otherwise
*
* @hide
*/
public boolean startSoftAp(@Nullable WifiConfiguration wifiConfig) {
try {
return mService.startSoftAp(wifiConfig);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Stop SoftAp mode.
* Note that stopping softap mode will restore the previous wifi mode.
* @return {@code true} if the operation succeeds, {@code false} otherwise
*
* @hide
*/
public boolean stopSoftAp() {
try {
return mService.stopSoftAp();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Request a local only hotspot that an application can use to communicate between co-located
* devices connected to the created WiFi hotspot. The network created by this method will not
* have Internet access. Each application can make a single request for the hotspot, but
* multiple applications could be requesting the hotspot at the same time. When multiple
* applications have successfully registered concurrently, they will be sharing the underlying
* hotspot. {@link LocalOnlyHotspotCallback#onStarted(LocalOnlyHotspotReservation)} is called
* when the hotspot is ready for use by the application.
*
* Each application can make a single active call to this method. The {@link
* LocalOnlyHotspotCallback#onStarted(LocalOnlyHotspotReservation)} callback supplies the
* requestor with a {@link LocalOnlyHotspotReservation} that contains a
* {@link WifiConfiguration} with the SSID, security type and credentials needed to connect
* to the hotspot. Communicating this information is up to the application.
*
* If the LocalOnlyHotspot cannot be created, the {@link LocalOnlyHotspotCallback#onFailed(int)}
* method will be called. Example failures include errors bringing up the network or if
* there is an incompatible operating mode. For example, if the user is currently using Wifi
* Tethering to provide an upstream to another device, LocalOnlyHotspot will not start due to
* an incompatible mode. The possible error codes include:
* {@link LocalOnlyHotspotCallback#ERROR_NO_CHANNEL},
* {@link LocalOnlyHotspotCallback#ERROR_GENERIC},
* {@link LocalOnlyHotspotCallback#ERROR_INCOMPATIBLE_MODE} and
* {@link LocalOnlyHotspotCallback#ERROR_TETHERING_DISALLOWED}.
*
* Internally, requests will be tracked to prevent the hotspot from being torn down while apps
* are still using it. The {@link LocalOnlyHotspotReservation} object passed in the {@link
* LocalOnlyHotspotCallback#onStarted(LocalOnlyHotspotReservation)} call should be closed when
* the LocalOnlyHotspot is no longer needed using {@link LocalOnlyHotspotReservation#close()}.
* Since the hotspot may be shared among multiple applications, removing the final registered
* application request will trigger the hotspot teardown. This means that applications should
* not listen to broadcasts containing wifi state to determine if the hotspot was stopped after
* they are done using it. Additionally, once {@link LocalOnlyHotspotReservation#close()} is
* called, applications will not receive callbacks of any kind.
*
* Applications should be aware that the user may also stop the LocalOnlyHotspot through the
* Settings UI; it is not guaranteed to stay up as long as there is a requesting application.
* The requestors will be notified of this case via
* {@link LocalOnlyHotspotCallback#onStopped()}. Other cases may arise where the hotspot is
* torn down (Emergency mode, etc). Application developers should be aware that it can stop
* unexpectedly, but they will receive a notification if they have properly registered.
*
* Applications should also be aware that this network will be shared with other applications.
* Applications are responsible for protecting their data on this network (e.g., TLS).
*
* Applications need to have the following permissions to start LocalOnlyHotspot: {@link
* android.Manifest.permission#CHANGE_WIFI_STATE} and {@link
* android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION}. Callers without
* the permissions will trigger a {@link java.lang.SecurityException}.
*
* @param callback LocalOnlyHotspotCallback for the application to receive updates about
* operating status.
* @param handler Handler to be used for callbacks. If the caller passes a null Handler, the
* main thread will be used.
*/
public void startLocalOnlyHotspot(LocalOnlyHotspotCallback callback,
@Nullable Handler handler) {
synchronized (mLock) {
Looper looper = (handler == null) ? mContext.getMainLooper() : handler.getLooper();
LocalOnlyHotspotCallbackProxy proxy =
new LocalOnlyHotspotCallbackProxy(this, looper, callback);
try {
String packageName = mContext.getOpPackageName();
int returnCode = mService.startLocalOnlyHotspot(
proxy.getMessenger(), new Binder(), packageName);
if (returnCode != LocalOnlyHotspotCallback.REQUEST_REGISTERED) {
// Send message to the proxy to make sure we call back on the correct thread
proxy.notifyFailed(returnCode);
return;
}
mLOHSCallbackProxy = proxy;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
/**
* Cancels a pending local only hotspot request. This can be used by the calling application to
* cancel the existing request if the provided callback has not been triggered. Calling this
* method will be equivalent to closing the returned LocalOnlyHotspotReservation, but it is not
* explicitly required.
*
* When cancelling this request, application developers should be aware that there may still be
* outstanding local only hotspot requests and the hotspot may still start, or continue running.
* Additionally, if a callback was registered, it will no longer be triggered after calling
* cancel.
*
* @hide
*/
public void cancelLocalOnlyHotspotRequest() {
synchronized (mLock) {
stopLocalOnlyHotspot();
}
}
/**
* Method used to inform WifiService that the LocalOnlyHotspot is no longer needed. This
* method is used by WifiManager to release LocalOnlyHotspotReservations held by calling
* applications and removes the internal tracking for the hotspot request. When all requesting
* applications are finished using the hotspot, it will be stopped and WiFi will return to the
* previous operational mode.
*
* This method should not be called by applications. Instead, they should call the close()
* method on their LocalOnlyHotspotReservation.
*/
private void stopLocalOnlyHotspot() {
synchronized (mLock) {
if (mLOHSCallbackProxy == null) {
// nothing to do, the callback was already cleaned up.
return;
}
mLOHSCallbackProxy = null;
try {
mService.stopLocalOnlyHotspot();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
/**
* Allow callers (Settings UI) to watch LocalOnlyHotspot state changes. Callers will
* receive a {@link LocalOnlyHotspotSubscription} object as a parameter of the
* {@link LocalOnlyHotspotObserver#onRegistered(LocalOnlyHotspotSubscription)}. The registered
* callers will receive the {@link LocalOnlyHotspotObserver#onStarted(WifiConfiguration)} and
* {@link LocalOnlyHotspotObserver#onStopped()} callbacks.
*
* Applications should have the
* {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION}
* permission. Callers without the permission will trigger a
* {@link java.lang.SecurityException}.
*
* @param observer LocalOnlyHotspotObserver callback.
* @param handler Handler to use for callbacks
*
* @hide
*/
public void watchLocalOnlyHotspot(LocalOnlyHotspotObserver observer,
@Nullable Handler handler) {
synchronized (mLock) {
Looper looper = (handler == null) ? mContext.getMainLooper() : handler.getLooper();
mLOHSObserverProxy = new LocalOnlyHotspotObserverProxy(this, looper, observer);
try {
mService.startWatchLocalOnlyHotspot(
mLOHSObserverProxy.getMessenger(), new Binder());
mLOHSObserverProxy.registered();
} catch (RemoteException e) {
mLOHSObserverProxy = null;
throw e.rethrowFromSystemServer();
}
}
}
/**
* Allow callers to stop watching LocalOnlyHotspot state changes. After calling this method,
* applications will no longer receive callbacks.
*
* @hide
*/
public void unregisterLocalOnlyHotspotObserver() {
synchronized (mLock) {
if (mLOHSObserverProxy == null) {
// nothing to do, the callback was already cleaned up
return;
}
mLOHSObserverProxy = null;
try {
mService.stopWatchLocalOnlyHotspot();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
/**
* Gets the Wi-Fi enabled state.
* @return One of {@link #WIFI_AP_STATE_DISABLED},
* {@link #WIFI_AP_STATE_DISABLING}, {@link #WIFI_AP_STATE_ENABLED},
* {@link #WIFI_AP_STATE_ENABLING}, {@link #WIFI_AP_STATE_FAILED}
* @see #isWifiApEnabled()
*
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE)
public int getWifiApState() {
try {
return mService.getWifiApEnabledState();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Return whether Wi-Fi AP is enabled or disabled.
* @return {@code true} if Wi-Fi AP is enabled
* @see #getWifiApState()
*
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE)
public boolean isWifiApEnabled() {
return getWifiApState() == WIFI_AP_STATE_ENABLED;
}
/**
* Gets the Wi-Fi AP Configuration.
* @return AP details in WifiConfiguration
*
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE)
public WifiConfiguration getWifiApConfiguration() {
try {
return mService.getWifiApConfiguration();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Sets the Wi-Fi AP Configuration.
* @return {@code true} if the operation succeeded, {@code false} otherwise
*
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE)
public boolean setWifiApConfiguration(WifiConfiguration wifiConfig) {
try {
mService.setWifiApConfiguration(wifiConfig, mContext.getOpPackageName());
return true;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Enable/Disable TDLS on a specific local route.
*
*
* TDLS enables two wireless endpoints to talk to each other directly
* without going through the access point that is managing the local
* network. It saves bandwidth and improves quality of the link.
*
* This API enables/disables the option of using TDLS. If enabled, the
* underlying hardware is free to use TDLS or a hop through the access
* point. If disabled, existing TDLS session is torn down and
* hardware is restricted to use access point for transferring wireless
* packets. Default value for all routes is 'disabled', meaning restricted
* to use access point for transferring packets.
*
* Applications should have the
* {@link android.Manifest.permission#NETWORK_SETTINGS NETWORK_SETTINGS} permission. Callers
* without the permission will trigger a {@link java.lang.SecurityException}.
*
*
* @param callback Callback for soft AP events
* @param handler The Handler on whose thread to execute the callbacks of the {@code callback}
* object. If null, then the application's main thread will be used.
*
* @hide
*/
@RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
public void registerSoftApCallback(@NonNull SoftApCallback callback,
@Nullable Handler handler) {
if (callback == null) throw new IllegalArgumentException("callback cannot be null");
Log.v(TAG, "registerSoftApCallback: callback=" + callback + ", handler=" + handler);
Looper looper = (handler == null) ? mContext.getMainLooper() : handler.getLooper();
Binder binder = new Binder();
try {
mService.registerSoftApCallback(binder, new SoftApCallbackProxy(looper, callback),
callback.hashCode());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Allow callers to unregister a previously registered callback. After calling this method,
* applications will no longer receive soft AP events.
*
* @param callback Callback to unregister for soft AP events
*
* @hide
*/
@RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
public void unregisterSoftApCallback(@NonNull SoftApCallback callback) {
if (callback == null) throw new IllegalArgumentException("callback cannot be null");
Log.v(TAG, "unregisterSoftApCallback: callback=" + callback);
try {
mService.unregisterSoftApCallback(callback.hashCode());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* LocalOnlyHotspotReservation that contains the {@link WifiConfiguration} for the active
* LocalOnlyHotspot request.
*
* Applications requesting LocalOnlyHotspot for sharing will receive an instance of the
* LocalOnlyHotspotReservation in the
* {@link LocalOnlyHotspotCallback#onStarted(LocalOnlyHotspotReservation)} call. This
* reservation contains the relevant {@link WifiConfiguration}.
* When an application is done with the LocalOnlyHotspot, they should call {@link
* LocalOnlyHotspotReservation#close()}. Once this happens, the application will not receive
* any further callbacks. If the LocalOnlyHotspot is stopped due to a
* user triggered mode change, applications will be notified via the {@link
* LocalOnlyHotspotCallback#onStopped()} callback.
*/
public class LocalOnlyHotspotReservation implements AutoCloseable {
private final CloseGuard mCloseGuard = CloseGuard.get();
private final WifiConfiguration mConfig;
/** @hide */
@VisibleForTesting
public LocalOnlyHotspotReservation(WifiConfiguration config) {
mConfig = config;
mCloseGuard.open("close");
}
public WifiConfiguration getWifiConfiguration() {
return mConfig;
}
@Override
public void close() {
try {
stopLocalOnlyHotspot();
mCloseGuard.close();
} catch (Exception e) {
Log.e(TAG, "Failed to stop Local Only Hotspot.");
}
}
@Override
protected void finalize() throws Throwable {
try {
if (mCloseGuard != null) {
mCloseGuard.warnIfOpen();
}
close();
} finally {
super.finalize();
}
}
}
/**
* Callback class for applications to receive updates about the LocalOnlyHotspot status.
*/
public static class LocalOnlyHotspotCallback {
/** @hide */
public static final int REQUEST_REGISTERED = 0;
public static final int ERROR_NO_CHANNEL = 1;
public static final int ERROR_GENERIC = 2;
public static final int ERROR_INCOMPATIBLE_MODE = 3;
public static final int ERROR_TETHERING_DISALLOWED = 4;
/** LocalOnlyHotspot start succeeded. */
public void onStarted(LocalOnlyHotspotReservation reservation) {};
/**
* LocalOnlyHotspot stopped.
*
* The LocalOnlyHotspot can be disabled at any time by the user. When this happens,
* applications will be notified that it was stopped. This will not be invoked when an
* application calls {@link LocalOnlyHotspotReservation#close()}.
*/
public void onStopped() {};
/**
* LocalOnlyHotspot failed to start.
*
* Applications can attempt to call
* {@link WifiManager#startLocalOnlyHotspot(LocalOnlyHotspotCallback, Handler)} again at
* a later time.
*
* @param reason The reason for failure could be one of: {@link
* #ERROR_TETHERING_DISALLOWED}, {@link #ERROR_INCOMPATIBLE_MODE},
* {@link #ERROR_NO_CHANNEL}, or {@link #ERROR_GENERIC}.
*/
public void onFailed(int reason) { };
}
/**
* Callback proxy for LocalOnlyHotspotCallback objects.
*/
private static class LocalOnlyHotspotCallbackProxy {
private final Handler mHandler;
private final WeakReference
* Before using a WifiLock, consider carefully if your application requires Wi-Fi access, or
* could function over a mobile network, if available. A program that needs to download large
* files should hold a WifiLock to ensure that the download will complete, but a program whose
* network usage is occasional or low-bandwidth should not hold a WifiLock to avoid adversely
* affecting battery life.
*
* Note that WifiLocks cannot override the user-level "Wi-Fi Enabled" setting, nor Airplane
* Mode. They simply keep the radio from turning off when Wi-Fi is already on but the device
* is idle.
*
* Any application using a WifiLock must request the {@code android.permission.WAKE_LOCK}
* permission in an {@code