/* * 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.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.content.Context; import android.net.DhcpInfo; import android.os.Binder; import android.os.IBinder; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.RemoteException; import android.os.WorkSource; import android.os.Messenger; import android.util.SparseArray; import com.android.internal.util.AsyncChannel; import com.android.internal.util.Protocol; import java.util.List; /** * This class provides the primary API for managing all aspects of Wi-Fi * connectivity. Get an instance of this class by calling * {@link android.content.Context#getSystemService(String) Context.getSystemService(Context.WIFI_SERVICE)}. * It deals with several categories of items: *
Input: Nothing. *
Output: Nothing. */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK"; /** * 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; IWifiManager mService; Handler mHandler; /* 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; /** * 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 service the Binder interface * @param handler target for messages * @hide - hide this because it takes in a parameter of type IWifiManager, which * is a system private class. */ public WifiManager(IWifiManager service, Handler handler) { mService = service; mHandler = handler; } /** * Return a list of all the networks configured in the supplicant. * 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.
* @return Returns the {@code networkId} of the supplied
* {@code WifiConfiguration} on success.
* disableOthers
is true, then all other configured
* networks are disabled, and an attempt to connect to the selected
* network is initiated. This may result in the asynchronous delivery
* of state change events.
* @param netId the ID of the network in the list of configured networks
* @param disableOthers if true, disable all other networks. 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 disableOthers) {
try {
return mService.enableNetwork(netId, disableOthers);
} catch (RemoteException e) {
return false;
}
}
/**
* 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.
* @param netId the ID of the network as returned by {@link #addNetwork}.
* @return {@code true} if the operation succeeded
*/
public boolean disableNetwork(int netId) {
try {
return mService.disableNetwork(netId);
} catch (RemoteException e) {
return false;
}
}
/**
* 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();
return true;
} catch (RemoteException e) {
return false;
}
}
/**
* 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();
return true;
} catch (RemoteException e) {
return false;
}
}
/**
* 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();
return true;
} catch (RemoteException e) {
return false;
}
}
/**
* 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.
*/
public boolean pingSupplicant() {
if (mService == null)
return false;
try {
return mService.pingSupplicant();
} catch (RemoteException e) {
return false;
}
}
/**
* 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.
* @return {@code true} if the operation succeeded, i.e., the scan was initiated
*/
public boolean startScan() {
try {
mService.startScan(false);
return true;
} catch (RemoteException e) {
return false;
}
}
/**
* 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.
* This is a variant of startScan that forces an active scan, even if passive
* scans are the current default
* @return {@code true} if the operation succeeded, i.e., the scan was initiated
*
* @hide
*/
public boolean startScanActive() {
try {
mService.startScan(true);
return true;
} catch (RemoteException e) {
return false;
}
}
/**
* Return dynamic information about the current Wi-Fi connection, if any is active.
* @return the Wi-Fi information, contained in {@link WifiInfo}.
*/
public WifiInfo getConnectionInfo() {
try {
return mService.getConnectionInfo();
} catch (RemoteException e) {
return null;
}
}
/**
* Return the results of the latest access point scan.
* @return the list of access points found in the most recent scan.
*/
public List* 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 true} if the operation succeeded */ public boolean saveConfiguration() { try { return mService.saveConfiguration(); } catch (RemoteException e) { return false; } } /** * Set the country code. * @param countryCode country code in ISO 3166 format. * @param persist {@code true} if this needs to be remembered * * @hide */ public void setCountryCode(String country, boolean persist) { try { mService.setCountryCode(country, persist); } catch (RemoteException e) { } } /** * Set the operational frequency band. * @param band One of * {@link #WIFI_FREQUENCY_BAND_AUTO}, * {@link #WIFI_FREQUENCY_BAND_5GHZ}, * {@link #WIFI_FREQUENCY_BAND_2GHZ}, * @param persist {@code true} if this needs to be remembered * @hide */ public void setFrequencyBand(int band, boolean persist) { try { mService.setFrequencyBand(band, persist); } catch (RemoteException e) { } } /** * Get the operational frequency band. * @return One of * {@link #WIFI_FREQUENCY_BAND_AUTO}, * {@link #WIFI_FREQUENCY_BAND_5GHZ}, * {@link #WIFI_FREQUENCY_BAND_2GHZ} or * {@code -1} on failure. * @hide */ public int getFrequencyBand() { try { return mService.getFrequencyBand(); } catch (RemoteException e) { return -1; } } /** * 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) { return false; } } /** * 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) { return null; } } /** * Enable or disable Wi-Fi. * @param enabled {@code true} to enable, {@code false} to disable. * @return {@code true} if the operation succeeds (or if the existing state * is the same as the requested state). */ public boolean setWifiEnabled(boolean enabled) { try { return mService.setWifiEnabled(enabled); } catch (RemoteException e) { return false; } } /** * 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) { return WIFI_STATE_UNKNOWN; } } /** * 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; } /** * 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; } /** * Start AccessPoint mode with the specified * configuration. If the radio is already running in * AP mode, update the new 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 Dont open up yet */ public boolean setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) { try { mService.setWifiApEnabled(wifiConfig, enabled); return true; } catch (RemoteException e) { return false; } } /** * 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 Dont open yet */ public int getWifiApState() { try { return mService.getWifiApEnabledState(); } catch (RemoteException e) { return WIFI_AP_STATE_FAILED; } } /** * Return whether Wi-Fi AP is enabled or disabled. * @return {@code true} if Wi-Fi AP is enabled * @see #getWifiApState() * * @hide Dont open yet */ public boolean isWifiApEnabled() { return getWifiApState() == WIFI_AP_STATE_ENABLED; } /** * Gets the Wi-Fi AP Configuration. * @return AP details in WifiConfiguration * * @hide Dont open yet */ public WifiConfiguration getWifiApConfiguration() { try { return mService.getWifiApConfiguration(); } catch (RemoteException e) { return null; } } /** * Sets the Wi-Fi AP Configuration. * @return {@code true} if the operation succeeded, {@code false} otherwise * * @hide Dont open yet */ public boolean setWifiApConfiguration(WifiConfiguration wifiConfig) { try { mService.setWifiApConfiguration(wifiConfig); return true; } catch (RemoteException e) { return false; } } /** * Start the driver and connect to network. * * This function will over-ride WifiLock and device idle status. For example, * even if the device is idle or there is only a scan-only lock held, * a start wifi would mean that wifi connection is kept active until * a stopWifi() is sent. * * This API is used by WifiStateTracker * * @return {@code true} if the operation succeeds else {@code false} * @hide */ public boolean startWifi() { try { mService.startWifi(); return true; } catch (RemoteException e) { return false; } } /** * Disconnect from a network (if any) and stop the driver. * * This function will over-ride WifiLock and device idle status. Wi-Fi * stays inactive until a startWifi() is issued. * * This API is used by WifiStateTracker * * @return {@code true} if the operation succeeds else {@code false} * @hide */ public boolean stopWifi() { try { mService.stopWifi(); return true; } catch (RemoteException e) { return false; } } /** * Add a bssid to the supplicant blacklist * * This API is used by WifiWatchdogService * * @return {@code true} if the operation succeeds else {@code false} * @hide */ public boolean addToBlacklist(String bssid) { try { mService.addToBlacklist(bssid); return true; } catch (RemoteException e) { return false; } } /** * Clear the supplicant blacklist * * This API is used by WifiWatchdogService * * @return {@code true} if the operation succeeds else {@code false} * @hide */ public boolean clearBlacklist() { try { mService.clearBlacklist(); return true; } catch (RemoteException e) { return false; } } /* TODO: deprecate synchronous API and open up the following API */ private static final int BASE = Protocol.BASE_WIFI_MANAGER; /* Commands to WifiService */ /** @hide */ public static final int CONNECT_NETWORK = BASE + 1; /** @hide */ public static final int CONNECT_NETWORK_FAILED = BASE + 2; /** @hide */ public static final int CONNECT_NETWORK_SUCCEEDED = BASE + 3; /** @hide */ public static final int FORGET_NETWORK = BASE + 4; /** @hide */ public static final int FORGET_NETWORK_FAILED = BASE + 5; /** @hide */ public static final int FORGET_NETWORK_SUCCEEDED = BASE + 6; /** @hide */ public static final int SAVE_NETWORK = BASE + 7; /** @hide */ public static final int SAVE_NETWORK_FAILED = BASE + 8; /** @hide */ public static final int SAVE_NETWORK_SUCCEEDED = BASE + 9; /** @hide */ public static final int START_WPS = BASE + 10; /** @hide */ public static final int START_WPS_SUCCEEDED = BASE + 11; /** @hide */ public static final int WPS_FAILED = BASE + 12; /** @hide */ public static final int WPS_COMPLETED = BASE + 13; /** @hide */ public static final int CANCEL_WPS = BASE + 14; /** @hide */ public static final int CANCEL_WPS_FAILED = BASE + 15; /** @hide */ public static final int CANCEL_WPS_SUCCEDED = BASE + 16; /** @hide */ public static final int DISABLE_NETWORK = BASE + 17; /** @hide */ public static final int DISABLE_NETWORK_FAILED = BASE + 18; /** @hide */ public static final int DISABLE_NETWORK_SUCCEEDED = BASE + 19; /* For system use only */ /** @hide */ public static final int ENABLE_TRAFFIC_STATS_POLL = BASE + 21; /** @hide */ public static final int TRAFFIC_STATS_POLL = BASE + 22; /** * Passed with {@link ActionListener#onFailure}. * Indicates that the operation failed due to an internal error. * @hide */ public static final int ERROR = 0; /** * Passed with {@link ActionListener#onFailure}. * Indicates that the operation is already in progress * @hide */ public static final int IN_PROGRESS = 1; /** * Passed with {@link ActionListener#onFailure}. * Indicates that the operation failed because the framework is busy and * unable to service the request * @hide */ public static final int BUSY = 2; /* WPS specific errors */ /** WPS overlap detected {@hide} */ public static final int WPS_OVERLAP_ERROR = 3; /** WEP on WPS is prohibited {@hide} */ public static final int WPS_WEP_PROHIBITED = 4; /** TKIP only prohibited {@hide} */ public static final int WPS_TKIP_ONLY_PROHIBITED = 5; /** Authentication failure on WPS {@hide} */ public static final int WPS_AUTH_FAILURE = 6; /** WPS timed out {@hide} */ public static final int WPS_TIMED_OUT = 7; /** Interface for callback invocation when framework channel is lost {@hide} */ public interface ChannelListener { /** * The channel to the framework has been disconnected. * Application could try re-initializing using {@link #initialize} */ public void onChannelDisconnected(); } /** Interface for callback invocation on an application action {@hide} */ public interface ActionListener { /** The operation succeeded */ public void onSuccess(); /** * The operation failed * @param reason The reason for failure could be one of * {@link #ERROR}, {@link #IN_PROGRESS} or {@link #BUSY} */ public void onFailure(int reason); } /** Interface for callback invocation on a start WPS action {@hide} */ public interface WpsListener { /** WPS start succeeded */ public void onStartSuccess(String pin); /** WPS operation completed succesfully */ public void onCompletion(); /** * WPS operation failed * @param reason The reason for failure could be one of * {@link #IN_PROGRESS}, {@link #WPS_OVERLAP_ERROR},{@link #ERROR} or {@link #BUSY} */ public void onFailure(int reason); } /** * A channel that connects the application to the Wifi framework. * Most operations require a Channel as an argument. An instance of Channel is obtained * by doing a call on {@link #initialize} * @hide */ public static class Channel { Channel(Looper looper, ChannelListener l) { mAsyncChannel = new AsyncChannel(); mHandler = new WifiHandler(looper); mChannelListener = l; } private ChannelListener mChannelListener; private SparseArray