summaryrefslogtreecommitdiffstats
path: root/wifi
diff options
context:
space:
mode:
authorIrfan Sheriff <isheriff@google.com>2010-07-28 09:35:20 -0700
committerIrfan Sheriff <isheriff@google.com>2010-08-10 15:18:25 -0700
commit0d25534fed91f636def5776ddc4605005bd7471c (patch)
treef1fa39d0989049137c8150f22abe1307bf7b73a3 /wifi
parent926bd956d6d149c12ddfe92d55d4a1de705861ec (diff)
downloadframeworks_base-0d25534fed91f636def5776ddc4605005bd7471c.zip
frameworks_base-0d25534fed91f636def5776ddc4605005bd7471c.tar.gz
frameworks_base-0d25534fed91f636def5776ddc4605005bd7471c.tar.bz2
Split WifiStateMachine from WifiStateTracker
Notifications handled in WifiService. WifiStateTracker tracks state for connectivity service Change-Id: Idb0cf494898d28712af0f95f9e60c5417cd4a053
Diffstat (limited to 'wifi')
-rw-r--r--wifi/java/android/net/wifi/IWifiManager.aidl8
-rw-r--r--wifi/java/android/net/wifi/WifiManager.java91
-rw-r--r--wifi/java/android/net/wifi/WifiMonitor.java33
-rw-r--r--wifi/java/android/net/wifi/WifiStateMachine.java3572
-rw-r--r--wifi/java/android/net/wifi/WifiStateTracker.java3812
5 files changed, 3727 insertions, 3789 deletions
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 6e0bc9d..3426af7 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -85,5 +85,13 @@ interface IWifiManager
WifiConfiguration getWifiApConfiguration();
void setWifiApConfiguration(in WifiConfiguration wifiConfig);
+
+ void startWifi();
+
+ void stopWifi();
+
+ void addToBlacklist(String bssid);
+
+ void clearBlacklist();
}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 6fac902..339763a 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -293,6 +293,21 @@ public class WifiManager {
public static final String EXTRA_NEW_RSSI = "newRssi";
/**
+ * Broadcast intent action indicating that the IP configuration
+ * changed on wifi.
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String CONFIG_CHANGED_ACTION = "android.net.wifi.CONFIG_CHANGED";
+ /**
+ * The lookup key for a {@link android.net.NetworkProperties} object associated with the
+ * Wi-Fi network. Retrieve with
+ * {@link android.content.Intent#getParcelableExtra(String)}.
+ * @hide
+ */
+ public static final String EXTRA_NETWORK_PROPERTIES = "networkProperties";
+
+ /**
* The network IDs of the configured networks could have changed.
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
@@ -838,6 +853,82 @@ public class WifiManager {
}
}
+ /**
+ * 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;
+ }
+ }
+
/**
* Allows an application to keep the Wi-Fi radio awake.
* Normally the Wi-Fi radio may turn off when the user has not used the device in a while.
diff --git a/wifi/java/android/net/wifi/WifiMonitor.java b/wifi/java/android/net/wifi/WifiMonitor.java
index f2f8343..af3132f 100644
--- a/wifi/java/android/net/wifi/WifiMonitor.java
+++ b/wifi/java/android/net/wifi/WifiMonitor.java
@@ -19,14 +19,13 @@ package android.net.wifi;
import android.util.Log;
import android.util.Config;
import android.net.NetworkInfo;
-import android.net.NetworkStateTracker;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
/**
* Listens for events from the wpa_supplicant server, and passes them on
- * to the {@link WifiStateTracker} for handling. Runs in its own thread.
+ * to the {@link WifiStateMachine} for handling. Runs in its own thread.
*
* @hide
*/
@@ -117,7 +116,7 @@ public class WifiMonitor {
private static Pattern mConnectedEventPattern =
Pattern.compile("((?:[0-9a-f]{2}:){5}[0-9a-f]{2}) .* \\[id=([0-9]+) ");
- private final WifiStateTracker mWifiStateTracker;
+ private final WifiStateMachine mWifiStateMachine;
/**
* This indicates the supplicant connection for the monitor is closed
@@ -139,18 +138,14 @@ public class WifiMonitor {
*/
private static final int MAX_RECV_ERRORS = 10;
- public WifiMonitor(WifiStateTracker tracker) {
- mWifiStateTracker = tracker;
+ public WifiMonitor(WifiStateMachine wifiStateMachine) {
+ mWifiStateMachine = wifiStateMachine;
}
public void startMonitoring() {
new MonitorThread().start();
}
- public NetworkStateTracker getNetworkStateTracker() {
- return mWifiStateTracker;
- }
-
class MonitorThread extends Thread {
public MonitorThread() {
super("WifiMonitor");
@@ -161,9 +156,9 @@ public class WifiMonitor {
if (connectToSupplicant()) {
// Send a message indicating that it is now possible to send commands
// to the supplicant
- mWifiStateTracker.notifySupplicantConnection();
+ mWifiStateMachine.notifySupplicantConnection();
} else {
- mWifiStateTracker.notifySupplicantLost();
+ mWifiStateMachine.notifySupplicantLost();
return;
}
@@ -259,7 +254,7 @@ public class WifiMonitor {
}
// notify and exit
- mWifiStateTracker.notifySupplicantLost();
+ mWifiStateMachine.notifySupplicantLost();
break;
} else {
handleEvent(event, eventData);
@@ -285,7 +280,7 @@ public class WifiMonitor {
}
private void handlePasswordKeyMayBeIncorrect() {
- mWifiStateTracker.notifyPasswordKeyMayBeIncorrect();
+ mWifiStateMachine.notifyPasswordKeyMayBeIncorrect();
}
private void handleDriverEvent(String state) {
@@ -293,11 +288,11 @@ public class WifiMonitor {
return;
}
if (state.equals("STOPPED")) {
- mWifiStateTracker.notifyDriverStopped();
+ mWifiStateMachine.notifyDriverStopped();
} else if (state.equals("STARTED")) {
- mWifiStateTracker.notifyDriverStarted();
+ mWifiStateMachine.notifyDriverStarted();
} else if (state.equals("HANGED")) {
- mWifiStateTracker.notifyDriverHung();
+ mWifiStateMachine.notifyDriverHung();
}
}
@@ -318,7 +313,7 @@ public class WifiMonitor {
break;
case SCAN_RESULTS:
- mWifiStateTracker.notifyScanResultsAvailable();
+ mWifiStateMachine.notifyScanResultsAvailable();
break;
case UNKNOWN:
@@ -375,7 +370,7 @@ public class WifiMonitor {
if (newSupplicantState == SupplicantState.INVALID) {
Log.w(TAG, "Invalid supplicant state: " + newState);
}
- mWifiStateTracker.notifySupplicantStateChange(networkId, BSSID, newSupplicantState);
+ mWifiStateMachine.notifySupplicantStateChange(networkId, BSSID, newSupplicantState);
}
}
@@ -395,7 +390,7 @@ public class WifiMonitor {
}
}
}
- mWifiStateTracker.notifyNetworkStateChange(newState, BSSID, networkId);
+ mWifiStateMachine.notifyNetworkStateChange(newState, BSSID, networkId);
}
/**
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
new file mode 100644
index 0000000..6794c05
--- /dev/null
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -0,0 +1,3572 @@
+/*
+ * Copyright (C) 2010 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 static android.net.wifi.WifiManager.WIFI_STATE_DISABLED;
+import static android.net.wifi.WifiManager.WIFI_STATE_DISABLING;
+import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED;
+import static android.net.wifi.WifiManager.WIFI_STATE_ENABLING;
+import static android.net.wifi.WifiManager.WIFI_STATE_UNKNOWN;
+
+/**
+ * TODO: Add soft AP states as part of WIFI_STATE_XXX
+ * Retain WIFI_STATE_ENABLING that indicates driver is loading
+ * Add WIFI_STATE_AP_ENABLED to indicate soft AP has started
+ * and WIFI_STATE_FAILED for failure
+ * Deprecate WIFI_STATE_UNKNOWN
+ *
+ * Doing this will simplify the logic for sending broadcasts
+ */
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLING;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLING;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_FAILED;
+
+import android.app.ActivityManagerNative;
+import android.net.NetworkInfo;
+import android.net.DhcpInfo;
+import android.net.NetworkUtils;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo.DetailedState;
+import android.net.NetworkProperties;
+import android.os.Binder;
+import android.os.Message;
+import android.os.Parcelable;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.INetworkManagementService;
+import android.os.PowerManager;
+import android.os.SystemProperties;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.Process;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.EventLog;
+import android.util.Log;
+import android.util.Slog;
+import android.app.backup.IBackupManager;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHeadset;
+import android.bluetooth.BluetoothA2dp;
+import android.content.ContentResolver;
+import android.content.Intent;
+import android.content.Context;
+import android.database.ContentObserver;
+import com.android.internal.app.IBatteryStats;
+import com.android.internal.util.HierarchicalState;
+import com.android.internal.util.HierarchicalStateMachine;
+
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.regex.Pattern;
+
+/**
+ * Track the state of Wifi connectivity. All event handling is done here,
+ * and all changes in connectivity state are initiated here.
+ *
+ * @hide
+ */
+//TODO: we still need frequent scanning for the case when
+// we issue disconnect but need scan results for open network notification
+public class WifiStateMachine extends HierarchicalStateMachine {
+
+ private static final String TAG = "WifiStateMachine";
+ private static final String NETWORKTYPE = "WIFI";
+ private static final boolean DBG = false;
+
+ /* TODO: fetch a configurable interface */
+ private static final String SOFTAP_IFACE = "wl0.1";
+
+ private WifiMonitor mWifiMonitor;
+ private INetworkManagementService nwService;
+ private ConnectivityManager mCm;
+
+ /* Scan results handling */
+ private List<ScanResult> mScanResults;
+ private static final Pattern scanResultPattern = Pattern.compile("\t+");
+ private static final int SCAN_RESULT_CACHE_SIZE = 80;
+ private final LinkedHashMap<String, ScanResult> mScanResultCache;
+
+ private String mInterfaceName;
+
+ private int mNumAllowedChannels = 0;
+ private int mLastSignalLevel = -1;
+ private String mLastBssid;
+ private int mLastNetworkId;
+ private boolean mEnableRssiPolling = false;
+ private boolean mPasswordKeyMayBeIncorrect = false;
+ private boolean mUseStaticIp = false;
+ private int mReconnectCount = 0;
+ private boolean mIsScanMode = false;
+ private boolean mConfigChanged = false;
+
+ /**
+ * Instance of the bluetooth headset helper. This needs to be created
+ * early because there is a delay before it actually 'connects', as
+ * noted by its javadoc. If we check before it is connected, it will be
+ * in an error state and we will not disable coexistence.
+ */
+ private BluetoothHeadset mBluetoothHeadset;
+
+ private BluetoothA2dp mBluetoothA2dp;
+
+ /**
+ * Observes the static IP address settings.
+ */
+ private SettingsObserver mSettingsObserver;
+ private NetworkProperties mNetworkProperties;
+
+ // Held during driver load and unload
+ private static PowerManager.WakeLock sWakeLock;
+
+ private Context mContext;
+
+ private DhcpInfo mDhcpInfo;
+ private WifiInfo mWifiInfo;
+ private NetworkInfo mNetworkInfo;
+ private SupplicantStateTracker mSupplicantStateTracker;
+
+ // Event log tags (must be in sync with event-log-tags)
+ private static final int EVENTLOG_WIFI_STATE_CHANGED = 50021;
+ private static final int EVENTLOG_WIFI_EVENT_HANDLED = 50022;
+ private static final int EVENTLOG_SUPPLICANT_STATE_CHANGED = 50023;
+
+ /* Load the driver */
+ private static final int CMD_LOAD_DRIVER = 1;
+ /* Unload the driver */
+ private static final int CMD_UNLOAD_DRIVER = 2;
+ /* Indicates driver load succeeded */
+ private static final int CMD_LOAD_DRIVER_SUCCESS = 3;
+ /* Indicates driver load failed */
+ private static final int CMD_LOAD_DRIVER_FAILURE = 4;
+ /* Indicates driver unload succeeded */
+ private static final int CMD_UNLOAD_DRIVER_SUCCESS = 5;
+ /* Indicates driver unload failed */
+ private static final int CMD_UNLOAD_DRIVER_FAILURE = 6;
+
+ /* Start the supplicant */
+ private static final int CMD_START_SUPPLICANT = 11;
+ /* Stop the supplicant */
+ private static final int CMD_STOP_SUPPLICANT = 12;
+ /* Start the driver */
+ private static final int CMD_START_DRIVER = 13;
+ /* Start the driver */
+ private static final int CMD_STOP_DRIVER = 14;
+ /* Indicates DHCP succeded */
+ private static final int CMD_IP_CONFIG_SUCCESS = 15;
+ /* Indicates DHCP failed */
+ private static final int CMD_IP_CONFIG_FAILURE = 16;
+ /* Re-configure interface */
+ private static final int CMD_RECONFIGURE_IP = 17;
+
+
+ /* Start the soft access point */
+ private static final int CMD_START_AP = 21;
+ /* Stop the soft access point */
+ private static final int CMD_STOP_AP = 22;
+
+
+ /* Supplicant events */
+ /* Connection to supplicant established */
+ private static final int SUP_CONNECTION_EVENT = 31;
+ /* Connection to supplicant lost */
+ private static final int SUP_DISCONNECTION_EVENT = 32;
+ /* Driver start completed */
+ private static final int DRIVER_START_EVENT = 33;
+ /* Driver stop completed */
+ private static final int DRIVER_STOP_EVENT = 34;
+ /* Network connection completed */
+ private static final int NETWORK_CONNECTION_EVENT = 36;
+ /* Network disconnection completed */
+ private static final int NETWORK_DISCONNECTION_EVENT = 37;
+ /* Scan results are available */
+ private static final int SCAN_RESULTS_EVENT = 38;
+ /* Supplicate state changed */
+ private static final int SUPPLICANT_STATE_CHANGE_EVENT = 39;
+ /* Password may be incorrect */
+ private static final int PASSWORD_MAY_BE_INCORRECT_EVENT = 40;
+
+ /* Supplicant commands */
+ /* Is supplicant alive ? */
+ private static final int CMD_PING_SUPPLICANT = 51;
+ /* Add/update a network configuration */
+ private static final int CMD_ADD_OR_UPDATE_NETWORK = 52;
+ /* Delete a network */
+ private static final int CMD_REMOVE_NETWORK = 53;
+ /* Enable a network. The device will attempt a connection to the given network. */
+ private static final int CMD_ENABLE_NETWORK = 54;
+ /* Disable a network. The device does not attempt a connection to the given network. */
+ private static final int CMD_DISABLE_NETWORK = 55;
+ /* Blacklist network. De-prioritizes the given BSSID for connection. */
+ private static final int CMD_BLACKLIST_NETWORK = 56;
+ /* Clear the blacklist network list */
+ private static final int CMD_CLEAR_BLACKLIST = 57;
+ /* Get the configured networks */
+ private static final int CMD_GET_NETWORK_CONFIG = 58;
+ /* Save configuration */
+ private static final int CMD_SAVE_CONFIG = 59;
+ /* Connection status */
+ private static final int CMD_CONNECTION_STATUS = 60;
+
+ /* Supplicant commands after driver start*/
+ /* Initiate a scan */
+ private static final int CMD_START_SCAN = 71;
+ /* Set scan mode. CONNECT_MODE or SCAN_ONLY_MODE */
+ private static final int CMD_SET_SCAN_MODE = 72;
+ /* Set scan type. SCAN_ACTIVE or SCAN_PASSIVE */
+ private static final int CMD_SET_SCAN_TYPE = 73;
+ /* Disconnect from a network */
+ private static final int CMD_DISCONNECT = 74;
+ /* Reconnect to a network */
+ private static final int CMD_RECONNECT = 75;
+ /* Reassociate to a network */
+ private static final int CMD_REASSOCIATE = 76;
+ /* Set power mode
+ * POWER_MODE_ACTIVE
+ * POWER_MODE_AUTO
+ */
+ private static final int CMD_SET_POWER_MODE = 77;
+ /* Set bluetooth co-existence
+ * BLUETOOTH_COEXISTENCE_MODE_ENABLED
+ * BLUETOOTH_COEXISTENCE_MODE_DISABLED
+ * BLUETOOTH_COEXISTENCE_MODE_SENSE
+ */
+ private static final int CMD_SET_BLUETOOTH_COEXISTENCE = 78;
+ /* Enable/disable bluetooth scan mode
+ * true(1)
+ * false(0)
+ */
+ private static final int CMD_SET_BLUETOOTH_SCAN_MODE = 79;
+ /* Set number of allowed channels */
+ private static final int CMD_SET_NUM_ALLOWED_CHANNELS = 80;
+ /* Request connectivity manager wake lock before driver stop */
+ private static final int CMD_REQUEST_CM_WAKELOCK = 81;
+ /* Enables RSSI poll */
+ private static final int CMD_ENABLE_RSSI_POLL = 82;
+ /* RSSI poll */
+ private static final int CMD_RSSI_POLL = 83;
+ /* Get current RSSI */
+ private static final int CMD_GET_RSSI = 84;
+ /* Get approx current RSSI */
+ private static final int CMD_GET_RSSI_APPROX = 85;
+ /* Get link speed on connection */
+ private static final int CMD_GET_LINK_SPEED = 86;
+ /* Radio mac address */
+ private static final int CMD_GET_MAC_ADDR = 87;
+ /* Set up packet filtering */
+ private static final int CMD_START_PACKET_FILTERING = 88;
+ /* Clear packet filter */
+ private static final int CMD_STOP_PACKET_FILTERING = 89;
+
+ /**
+ * Interval in milliseconds between polling for connection
+ * status items that are not sent via asynchronous events.
+ * An example is RSSI (signal strength).
+ */
+ private static final int POLL_RSSI_INTERVAL_MSECS = 3000;
+
+ private static final int CONNECT_MODE = 1;
+ private static final int SCAN_ONLY_MODE = 2;
+
+ private static final int SCAN_ACTIVE = 1;
+ private static final int SCAN_PASSIVE = 2;
+
+ /**
+ * The maximum number of times we will retry a connection to an access point
+ * for which we have failed in acquiring an IP address from DHCP. A value of
+ * N means that we will make N+1 connection attempts in all.
+ * <p>
+ * See {@link Settings.Secure#WIFI_MAX_DHCP_RETRY_COUNT}. This is the default
+ * value if a Settings value is not present.
+ */
+ private static final int DEFAULT_MAX_DHCP_RETRIES = 9;
+
+ private static final int DRIVER_POWER_MODE_ACTIVE = 1;
+ private static final int DRIVER_POWER_MODE_AUTO = 0;
+
+ /* Default parent state */
+ private HierarchicalState mDefaultState = new DefaultState();
+ /* Temporary initial state */
+ private HierarchicalState mInitialState = new InitialState();
+ /* Unloading the driver */
+ private HierarchicalState mDriverUnloadingState = new DriverUnloadingState();
+ /* Loading the driver */
+ private HierarchicalState mDriverUnloadedState = new DriverUnloadedState();
+ /* Driver load/unload failed */
+ private HierarchicalState mDriverFailedState = new DriverFailedState();
+ /* Driver loading */
+ private HierarchicalState mDriverLoadingState = new DriverLoadingState();
+ /* Driver loaded */
+ private HierarchicalState mDriverLoadedState = new DriverLoadedState();
+ /* Driver loaded, waiting for supplicant to start */
+ private HierarchicalState mWaitForSupState = new WaitForSupState();
+
+ /* Driver loaded and supplicant ready */
+ private HierarchicalState mDriverSupReadyState = new DriverSupReadyState();
+ /* Driver start issued, waiting for completed event */
+ private HierarchicalState mDriverStartingState = new DriverStartingState();
+ /* Driver started */
+ private HierarchicalState mDriverStartedState = new DriverStartedState();
+ /* Driver stopping */
+ private HierarchicalState mDriverStoppingState = new DriverStoppingState();
+ /* Driver stopped */
+ private HierarchicalState mDriverStoppedState = new DriverStoppedState();
+ /* Scan for networks, no connection will be established */
+ private HierarchicalState mScanModeState = new ScanModeState();
+ /* Connecting to an access point */
+ private HierarchicalState mConnectModeState = new ConnectModeState();
+ /* Fetching IP after network connection (assoc+auth complete) */
+ private HierarchicalState mConnectingState = new ConnectingState();
+ /* Connected with IP addr */
+ private HierarchicalState mConnectedState = new ConnectedState();
+ /* disconnect issued, waiting for network disconnect confirmation */
+ private HierarchicalState mDisconnectingState = new DisconnectingState();
+ /* Network is not connected, supplicant assoc+auth is not complete */
+ private HierarchicalState mDisconnectedState = new DisconnectedState();
+
+ /* Soft Ap is running */
+ private HierarchicalState mSoftApStartedState = new SoftApStartedState();
+
+ /* Argument for Message object to indicate a synchronous call */
+ private static final int SYNCHRONOUS_CALL = 1;
+ private static final int ASYNCHRONOUS_CALL = 0;
+
+
+ /**
+ * One of {@link WifiManager#WIFI_STATE_DISABLED},
+ * {@link WifiManager#WIFI_STATE_DISABLING},
+ * {@link WifiManager#WIFI_STATE_ENABLED},
+ * {@link WifiManager#WIFI_STATE_ENABLING},
+ * {@link WifiManager#WIFI_STATE_UNKNOWN}
+ *
+ */
+ private final AtomicInteger mWifiState = new AtomicInteger(WIFI_STATE_DISABLED);
+
+ /**
+ * One of {@link WifiManager#WIFI_AP_STATE_DISABLED},
+ * {@link WifiManager#WIFI_AP_STATE_DISABLING},
+ * {@link WifiManager#WIFI_AP_STATE_ENABLED},
+ * {@link WifiManager#WIFI_AP_STATE_ENABLING},
+ * {@link WifiManager#WIFI_AP_STATE_FAILED}
+ *
+ */
+ private final AtomicInteger mWifiApState = new AtomicInteger(WIFI_AP_STATE_DISABLED);
+
+ private final AtomicInteger mLastEnableUid = new AtomicInteger(Process.myUid());
+ private final AtomicInteger mLastApEnableUid = new AtomicInteger(Process.myUid());
+
+ private final IBatteryStats mBatteryStats;
+
+ public WifiStateMachine(Context context) {
+ super(TAG);
+
+ mContext = context;
+
+ mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, NETWORKTYPE, "");
+ mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo"));
+
+ IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
+ nwService = INetworkManagementService.Stub.asInterface(b);
+
+ mWifiMonitor = new WifiMonitor(this);
+ mDhcpInfo = new DhcpInfo();
+ mWifiInfo = new WifiInfo();
+ mInterfaceName = SystemProperties.get("wifi.interface", "tiwlan0");
+ mSupplicantStateTracker = new SupplicantStateTracker(context, getHandler());
+
+ mBluetoothHeadset = new BluetoothHeadset(mContext, null);
+ mNetworkProperties = new NetworkProperties();
+
+ mNetworkInfo.setIsAvailable(false);
+ mNetworkProperties.clear();
+ mLastBssid = null;
+ mLastNetworkId = -1;
+ mLastSignalLevel = -1;
+
+ mScanResultCache = new LinkedHashMap<String, ScanResult>(
+ SCAN_RESULT_CACHE_SIZE, 0.75f, true) {
+ /*
+ * Limit the cache size by SCAN_RESULT_CACHE_SIZE
+ * elements
+ */
+ @Override
+ public boolean removeEldestEntry(Map.Entry eldest) {
+ return SCAN_RESULT_CACHE_SIZE < this.size();
+ }
+ };
+
+ mSettingsObserver = new SettingsObserver(new Handler());
+
+ PowerManager powerManager = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
+ sWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
+
+ addState(mDefaultState);
+ addState(mInitialState, mDefaultState);
+ addState(mDriverUnloadingState, mDefaultState);
+ addState(mDriverUnloadedState, mDefaultState);
+ addState(mDriverFailedState, mDriverUnloadedState);
+ addState(mDriverLoadingState, mDefaultState);
+ addState(mDriverLoadedState, mDefaultState);
+ addState(mWaitForSupState, mDriverLoadedState);
+ addState(mDriverSupReadyState, mDefaultState);
+ addState(mDriverStartingState, mDriverSupReadyState);
+ addState(mDriverStartedState, mDriverSupReadyState);
+ addState(mScanModeState, mDriverStartedState);
+ addState(mConnectModeState, mDriverStartedState);
+ addState(mConnectingState, mConnectModeState);
+ addState(mConnectedState, mConnectModeState);
+ addState(mDisconnectingState, mConnectModeState);
+ addState(mDisconnectedState, mConnectModeState);
+ addState(mDriverStoppingState, mDriverSupReadyState);
+ addState(mDriverStoppedState, mDriverSupReadyState);
+ addState(mSoftApStartedState, mDefaultState);
+
+ setInitialState(mInitialState);
+
+ if (DBG) setDbg(true);
+
+ //start the state machine
+ start();
+ }
+
+ /*********************************************************
+ * Methods exposed for public use
+ ********************************************************/
+
+ /**
+ * TODO: doc
+ */
+ public boolean pingSupplicant() {
+ return sendSyncMessage(CMD_PING_SUPPLICANT).boolValue;
+ }
+
+ /**
+ * TODO: doc
+ */
+ public boolean startScan(boolean forceActive) {
+ return sendSyncMessage(obtainMessage(CMD_START_SCAN, forceActive ?
+ SCAN_ACTIVE : SCAN_PASSIVE, 0)).boolValue;
+ }
+
+ /**
+ * TODO: doc
+ */
+ public void setWifiEnabled(boolean enable) {
+ mLastEnableUid.set(Binder.getCallingUid());
+ if (enable) {
+ /* Argument is the state that is entered prior to load */
+ sendMessage(obtainMessage(CMD_LOAD_DRIVER, WIFI_STATE_ENABLING, 0));
+ sendMessage(CMD_START_SUPPLICANT);
+ } else {
+ sendMessage(CMD_STOP_SUPPLICANT);
+ /* Argument is the state that is entered upon success */
+ sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_STATE_DISABLED, 0));
+ }
+ }
+
+ /**
+ * TODO: doc
+ */
+ public void setWifiApEnabled(WifiConfiguration wifiConfig, boolean enable) {
+ mLastApEnableUid.set(Binder.getCallingUid());
+ if (enable) {
+ /* Argument is the state that is entered prior to load */
+ sendMessage(obtainMessage(CMD_LOAD_DRIVER, WIFI_AP_STATE_ENABLING, 0));
+ sendMessage(obtainMessage(CMD_START_AP, wifiConfig));
+ } else {
+ sendMessage(CMD_STOP_AP);
+ /* Argument is the state that is entered upon success */
+ sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_AP_STATE_DISABLED, 0));
+ }
+ }
+
+ /**
+ * TODO: doc
+ */
+ public int getWifiState() {
+ return mWifiState.get();
+ }
+
+ /**
+ * TODO: doc
+ */
+ public String getWifiStateByName() {
+ switch (mWifiState.get()) {
+ case WIFI_STATE_DISABLING:
+ return "disabling";
+ case WIFI_STATE_DISABLED:
+ return "disabled";
+ case WIFI_STATE_ENABLING:
+ return "enabling";
+ case WIFI_STATE_ENABLED:
+ return "enabled";
+ case WIFI_STATE_UNKNOWN:
+ return "unknown state";
+ default:
+ return "[invalid state]";
+ }
+ }
+
+ /**
+ * TODO: doc
+ */
+ public int getWifiApState() {
+ return mWifiApState.get();
+ }
+
+ /**
+ * TODO: doc
+ */
+ public String getWifiApStateByName() {
+ switch (mWifiApState.get()) {
+ case WIFI_AP_STATE_DISABLING:
+ return "disabling";
+ case WIFI_AP_STATE_DISABLED:
+ return "disabled";
+ case WIFI_AP_STATE_ENABLING:
+ return "enabling";
+ case WIFI_AP_STATE_ENABLED:
+ return "enabled";
+ case WIFI_AP_STATE_FAILED:
+ return "failed";
+ default:
+ return "[invalid state]";
+ }
+ }
+
+ /**
+ * Get status information for the current connection, if any.
+ * @return a {@link WifiInfo} object containing information about the current connection
+ *
+ */
+ public WifiInfo requestConnectionInfo() {
+ return mWifiInfo;
+ }
+
+ public DhcpInfo getDhcpInfo() {
+ return mDhcpInfo;
+ }
+
+ /**
+ * TODO: doc
+ */
+ public void setDriverStart(boolean enable) {
+ if (enable) {
+ sendMessage(CMD_START_DRIVER);
+ } else {
+ sendMessage(CMD_STOP_DRIVER);
+ }
+ }
+
+ /**
+ * TODO: doc
+ */
+ public void setScanOnlyMode(boolean enable) {
+ if (enable) {
+ sendMessage(obtainMessage(CMD_SET_SCAN_MODE, SCAN_ONLY_MODE, 0));
+ } else {
+ sendMessage(obtainMessage(CMD_SET_SCAN_MODE, CONNECT_MODE, 0));
+ }
+ }
+
+ /**
+ * TODO: doc
+ */
+ public void setScanType(boolean active) {
+ if (active) {
+ sendMessage(obtainMessage(CMD_SET_SCAN_TYPE, SCAN_ACTIVE, 0));
+ } else {
+ sendMessage(obtainMessage(CMD_SET_SCAN_TYPE, SCAN_PASSIVE, 0));
+ }
+ }
+
+ /**
+ * TODO: doc
+ */
+ public List<ScanResult> getScanResultsList() {
+ return mScanResults;
+ }
+
+ /**
+ * Disconnect from Access Point
+ */
+ public boolean disconnectCommand() {
+ return sendSyncMessage(CMD_DISCONNECT).boolValue;
+ }
+
+ /**
+ * Initiate a reconnection to AP
+ */
+ public boolean reconnectCommand() {
+ return sendSyncMessage(CMD_RECONNECT).boolValue;
+ }
+
+ /**
+ * Initiate a re-association to AP
+ */
+ public boolean reassociateCommand() {
+ return sendSyncMessage(CMD_REASSOCIATE).boolValue;
+ }
+
+ /**
+ * Add a network synchronously
+ *
+ * @return network id of the new network
+ */
+ public int addOrUpdateNetwork(WifiConfiguration config) {
+ return sendSyncMessage(CMD_ADD_OR_UPDATE_NETWORK, config).intValue;
+ }
+
+ public List<WifiConfiguration> getConfiguredNetworks() {
+ return sendSyncMessage(CMD_GET_NETWORK_CONFIG).configList;
+ }
+
+ /**
+ * Delete a network
+ *
+ * @param networkId id of the network to be removed
+ */
+ public boolean removeNetwork(int networkId) {
+ return sendSyncMessage(obtainMessage(CMD_REMOVE_NETWORK, networkId, 0)).boolValue;
+ }
+
+ private class EnableNetParams {
+ private int netId;
+ private boolean disableOthers;
+ EnableNetParams(int n, boolean b) {
+ netId = n;
+ disableOthers = b;
+ }
+ }
+ /**
+ * Enable a network
+ *
+ * @param netId network id of the network
+ * @param disableOthers true, if all other networks have to be disabled
+ * @return {@code true} if the operation succeeds, {@code false} otherwise
+ */
+ public boolean enableNetwork(int netId, boolean disableOthers) {
+ return sendSyncMessage(CMD_ENABLE_NETWORK,
+ new EnableNetParams(netId, disableOthers)).boolValue;
+ }
+
+ /**
+ * Disable a network
+ *
+ * @param netId network id of the network
+ * @return {@code true} if the operation succeeds, {@code false} otherwise
+ */
+ public boolean disableNetwork(int netId) {
+ return sendSyncMessage(obtainMessage(CMD_DISABLE_NETWORK, netId, 0)).boolValue;
+ }
+
+ /**
+ * Blacklist a BSSID. This will avoid the AP if there are
+ * alternate APs to connect
+ *
+ * @param bssid BSSID of the network
+ */
+ public void addToBlacklist(String bssid) {
+ sendMessage(obtainMessage(CMD_BLACKLIST_NETWORK, bssid));
+ }
+
+ /**
+ * Clear the blacklist list
+ *
+ */
+ public void clearBlacklist() {
+ sendMessage(obtainMessage(CMD_CLEAR_BLACKLIST));
+ }
+
+ /**
+ * Get detailed status of the connection
+ *
+ * @return Example status result
+ * bssid=aa:bb:cc:dd:ee:ff
+ * ssid=TestNet
+ * id=3
+ * pairwise_cipher=NONE
+ * group_cipher=NONE
+ * key_mgmt=NONE
+ * wpa_state=COMPLETED
+ * ip_address=X.X.X.X
+ */
+ public String status() {
+ return sendSyncMessage(CMD_CONNECTION_STATUS).stringValue;
+ }
+
+ public void enableRssiPolling(boolean enabled) {
+ sendMessage(obtainMessage(CMD_ENABLE_RSSI_POLL, enabled ? 1 : 0, 0));
+ }
+ /**
+ * Get RSSI to currently connected network
+ *
+ * @return RSSI value, -1 on failure
+ */
+ public int getRssi() {
+ return sendSyncMessage(CMD_GET_RSSI).intValue;
+ }
+
+ /**
+ * Get approx RSSI to currently connected network
+ *
+ * @return RSSI value, -1 on failure
+ */
+ public int getRssiApprox() {
+ return sendSyncMessage(CMD_GET_RSSI_APPROX).intValue;
+ }
+
+ /**
+ * Get link speed to currently connected network
+ *
+ * @return link speed, -1 on failure
+ */
+ public int getLinkSpeed() {
+ return sendSyncMessage(CMD_GET_LINK_SPEED).intValue;
+ }
+
+ /**
+ * Get MAC address of radio
+ *
+ * @return MAC address, null on failure
+ */
+ public String getMacAddress() {
+ return sendSyncMessage(CMD_GET_MAC_ADDR).stringValue;
+ }
+
+ /**
+ * Start packet filtering
+ */
+ public void startPacketFiltering() {
+ sendMessage(CMD_START_PACKET_FILTERING);
+ }
+
+ /**
+ * Stop packet filtering
+ */
+ public void stopPacketFiltering() {
+ sendMessage(CMD_STOP_PACKET_FILTERING);
+ }
+
+ /**
+ * Set power mode
+ * @param mode
+ * DRIVER_POWER_MODE_AUTO
+ * DRIVER_POWER_MODE_ACTIVE
+ */
+ public void setPowerMode(int mode) {
+ sendMessage(obtainMessage(CMD_SET_POWER_MODE, mode, 0));
+ }
+
+ /**
+ * Set the number of allowed radio frequency channels from the system
+ * setting value, if any.
+ */
+ public void setNumAllowedChannels() {
+ try {
+ setNumAllowedChannels(
+ Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.WIFI_NUM_ALLOWED_CHANNELS));
+ } catch (Settings.SettingNotFoundException e) {
+ if (mNumAllowedChannels != 0) {
+ setNumAllowedChannels(mNumAllowedChannels);
+ }
+ // otherwise, use the driver default
+ }
+ }
+
+ /**
+ * Set the number of radio frequency channels that are allowed to be used
+ * in the current regulatory domain.
+ * @param numChannels the number of allowed channels. Must be greater than 0
+ * and less than or equal to 16.
+ */
+ public void setNumAllowedChannels(int numChannels) {
+ sendMessage(obtainMessage(CMD_SET_NUM_ALLOWED_CHANNELS, numChannels, 0));
+ }
+
+ /**
+ * Get number of allowed channels
+ *
+ * @return channel count, -1 on failure
+ *
+ * TODO: this is not a public API and needs to be removed in favor
+ * of asynchronous reporting. unused for now.
+ */
+ public int getNumAllowedChannels() {
+ return -1;
+ }
+
+ /**
+ * Set bluetooth coex mode:
+ *
+ * @param mode
+ * BLUETOOTH_COEXISTENCE_MODE_ENABLED
+ * BLUETOOTH_COEXISTENCE_MODE_DISABLED
+ * BLUETOOTH_COEXISTENCE_MODE_SENSE
+ */
+ public void setBluetoothCoexistenceMode(int mode) {
+ sendMessage(obtainMessage(CMD_SET_BLUETOOTH_COEXISTENCE, mode, 0));
+ }
+
+ /**
+ * Enable or disable Bluetooth coexistence scan mode. When this mode is on,
+ * some of the low-level scan parameters used by the driver are changed to
+ * reduce interference with A2DP streaming.
+ *
+ * @param isBluetoothPlaying whether to enable or disable this mode
+ */
+ public void setBluetoothScanMode(boolean isBluetoothPlaying) {
+ sendMessage(obtainMessage(CMD_SET_BLUETOOTH_SCAN_MODE, isBluetoothPlaying ? 1 : 0, 0));
+ }
+
+ /**
+ * Save configuration on supplicant
+ *
+ * @return {@code true} if the operation succeeds, {@code false} otherwise
+ *
+ * TODO: deprecate this
+ */
+ public boolean saveConfig() {
+ return sendSyncMessage(CMD_SAVE_CONFIG).boolValue;
+ }
+
+ /**
+ * TODO: doc
+ */
+ public void requestCmWakeLock() {
+ sendMessage(CMD_REQUEST_CM_WAKELOCK);
+ }
+
+ /*********************************************************
+ * Internal private functions
+ ********************************************************/
+
+ class SyncReturn {
+ boolean boolValue;
+ int intValue;
+ String stringValue;
+ Object objValue;
+ List<WifiConfiguration> configList;
+ }
+
+ class SyncParams {
+ Object mParameter;
+ SyncReturn mSyncReturn;
+ SyncParams() {
+ mSyncReturn = new SyncReturn();
+ }
+ SyncParams(Object p) {
+ mParameter = p;
+ mSyncReturn = new SyncReturn();
+ }
+ }
+
+ /**
+ * message.arg2 is reserved to indicate synchronized
+ * message.obj is used to store SyncParams
+ */
+ private SyncReturn syncedSend(Message msg) {
+ SyncParams syncParams = (SyncParams) msg.obj;
+ msg.arg2 = SYNCHRONOUS_CALL;
+ synchronized(syncParams) {
+ if (DBG) Log.d(TAG, "syncedSend " + msg);
+ sendMessage(msg);
+ try {
+ syncParams.wait();
+ } catch (InterruptedException e) {
+ Log.e(TAG, "sendSyncMessage: unexpected interruption of wait()");
+ return null;
+ }
+ }
+ return syncParams.mSyncReturn;
+ }
+
+ private SyncReturn sendSyncMessage(Message msg) {
+ SyncParams syncParams = new SyncParams();
+ msg.obj = syncParams;
+ return syncedSend(msg);
+ }
+
+ private SyncReturn sendSyncMessage(int what, Object param) {
+ SyncParams syncParams = new SyncParams(param);
+ Message msg = obtainMessage(what, syncParams);
+ return syncedSend(msg);
+ }
+
+
+ private SyncReturn sendSyncMessage(int what) {
+ return sendSyncMessage(obtainMessage(what));
+ }
+
+ private void notifyOnMsgObject(Message msg) {
+ SyncParams syncParams = (SyncParams) msg.obj;
+ if (syncParams != null) {
+ synchronized(syncParams) {
+ if (DBG) Log.d(TAG, "notifyOnMsgObject " + msg);
+ syncParams.notify();
+ }
+ }
+ else {
+ Log.e(TAG, "Error! syncParams in notifyOnMsgObject is null");
+ }
+ }
+
+ private void setWifiState(int wifiState) {
+ final int previousWifiState = mWifiState.get();
+
+ try {
+ if (wifiState == WIFI_STATE_ENABLED) {
+ mBatteryStats.noteWifiOn(mLastEnableUid.get());
+ } else if (wifiState == WIFI_STATE_DISABLED) {
+ mBatteryStats.noteWifiOff(mLastEnableUid.get());
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to note battery stats in wifi");
+ }
+
+ mWifiState.set(wifiState);
+
+ if (DBG) Log.d(TAG, "setWifiState: " + getWifiStateByName());
+
+ final Intent intent = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ intent.putExtra(WifiManager.EXTRA_WIFI_STATE, wifiState);
+ intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_STATE, previousWifiState);
+ mContext.sendStickyBroadcast(intent);
+ }
+
+ private void setWifiApState(int wifiApState) {
+ final int previousWifiApState = mWifiApState.get();
+
+ try {
+ if (wifiApState == WIFI_AP_STATE_ENABLED) {
+ mBatteryStats.noteWifiOn(mLastApEnableUid.get());
+ } else if (wifiApState == WIFI_AP_STATE_DISABLED) {
+ mBatteryStats.noteWifiOff(mLastApEnableUid.get());
+ }
+ } catch (RemoteException e) {
+ Log.d(TAG, "Failed to note battery stats in wifi");
+ }
+
+ // Update state
+ mWifiApState.set(wifiApState);
+
+ if (DBG) Log.d(TAG, "setWifiApState: " + getWifiApStateByName());
+
+ final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ intent.putExtra(WifiManager.EXTRA_WIFI_AP_STATE, wifiApState);
+ intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_AP_STATE, previousWifiApState);
+ mContext.sendStickyBroadcast(intent);
+ }
+
+ /**
+ * Parse the scan result line passed to us by wpa_supplicant (helper).
+ * @param line the line to parse
+ * @return the {@link ScanResult} object
+ */
+ private ScanResult parseScanResult(String line) {
+ ScanResult scanResult = null;
+ if (line != null) {
+ /*
+ * Cache implementation (LinkedHashMap) is not synchronized, thus,
+ * must synchronized here!
+ */
+ synchronized (mScanResultCache) {
+ String[] result = scanResultPattern.split(line);
+ if (3 <= result.length && result.length <= 5) {
+ String bssid = result[0];
+ // bssid | frequency | level | flags | ssid
+ int frequency;
+ int level;
+ try {
+ frequency = Integer.parseInt(result[1]);
+ level = Integer.parseInt(result[2]);
+ /* some implementations avoid negative values by adding 256
+ * so we need to adjust for that here.
+ */
+ if (level > 0) level -= 256;
+ } catch (NumberFormatException e) {
+ frequency = 0;
+ level = 0;
+ }
+
+ /*
+ * The formatting of the results returned by
+ * wpa_supplicant is intended to make the fields
+ * line up nicely when printed,
+ * not to make them easy to parse. So we have to
+ * apply some heuristics to figure out which field
+ * is the SSID and which field is the flags.
+ */
+ String ssid;
+ String flags;
+ if (result.length == 4) {
+ if (result[3].charAt(0) == '[') {
+ flags = result[3];
+ ssid = "";
+ } else {
+ flags = "";
+ ssid = result[3];
+ }
+ } else if (result.length == 5) {
+ flags = result[3];
+ ssid = result[4];
+ } else {
+ // Here, we must have 3 fields: no flags and ssid
+ // set
+ flags = "";
+ ssid = "";
+ }
+
+ // bssid + ssid is the hash key
+ String key = bssid + ssid;
+ scanResult = mScanResultCache.get(key);
+ if (scanResult != null) {
+ scanResult.level = level;
+ scanResult.SSID = ssid;
+ scanResult.capabilities = flags;
+ scanResult.frequency = frequency;
+ } else {
+ // Do not add scan results that have no SSID set
+ if (0 < ssid.trim().length()) {
+ scanResult =
+ new ScanResult(
+ ssid, bssid, flags, level, frequency);
+ mScanResultCache.put(key, scanResult);
+ }
+ }
+ } else {
+ Log.w(TAG, "Misformatted scan result text with " +
+ result.length + " fields: " + line);
+ }
+ }
+ }
+
+ return scanResult;
+ }
+
+ /**
+ * scanResults input format
+ * 00:bb:cc:dd:cc:ee 2427 166 [WPA-EAP-TKIP][WPA2-EAP-CCMP] Net1
+ * 00:bb:cc:dd:cc:ff 2412 165 [WPA-EAP-TKIP][WPA2-EAP-CCMP] Net2
+ */
+ private void setScanResults(String scanResults) {
+ if (scanResults == null) {
+ return;
+ }
+
+ List<ScanResult> scanList = new ArrayList<ScanResult>();
+
+ int lineCount = 0;
+
+ int scanResultsLen = scanResults.length();
+ // Parse the result string, keeping in mind that the last line does
+ // not end with a newline.
+ for (int lineBeg = 0, lineEnd = 0; lineEnd <= scanResultsLen; ++lineEnd) {
+ if (lineEnd == scanResultsLen || scanResults.charAt(lineEnd) == '\n') {
+ ++lineCount;
+
+ if (lineCount == 1) {
+ lineBeg = lineEnd + 1;
+ continue;
+ }
+ if (lineEnd > lineBeg) {
+ String line = scanResults.substring(lineBeg, lineEnd);
+ ScanResult scanResult = parseScanResult(line);
+ if (scanResult != null) {
+ scanList.add(scanResult);
+ } else {
+ Log.w(TAG, "misformatted scan result for: " + line);
+ }
+ }
+ lineBeg = lineEnd + 1;
+ }
+ }
+
+ mScanResults = scanList;
+ }
+
+ private void configureNetworkProperties() {
+ try {
+ mNetworkProperties.setInterface(NetworkInterface.getByName(mInterfaceName));
+ } catch (SocketException e) {
+ Log.e(TAG, "SocketException creating NetworkInterface from " + mInterfaceName +
+ ". e=" + e);
+ return;
+ } catch (NullPointerException e) {
+ Log.e(TAG, "NPE creating NetworkInterface. e=" + e);
+ return;
+ }
+ // TODO - fix this for v6
+ try {
+ mNetworkProperties.addAddress(InetAddress.getByAddress(
+ NetworkUtils.v4IntToArray(mDhcpInfo.ipAddress)));
+ } catch (UnknownHostException e) {
+ Log.e(TAG, "Exception setting IpAddress using " + mDhcpInfo + ", e=" + e);
+ }
+
+ try {
+ mNetworkProperties.setGateway(InetAddress.getByAddress(NetworkUtils.v4IntToArray(
+ mDhcpInfo.gateway)));
+ } catch (UnknownHostException e) {
+ Log.e(TAG, "Exception setting Gateway using " + mDhcpInfo + ", e=" + e);
+ }
+
+ try {
+ mNetworkProperties.addDns(InetAddress.getByAddress(
+ NetworkUtils.v4IntToArray(mDhcpInfo.dns1)));
+ } catch (UnknownHostException e) {
+ Log.e(TAG, "Exception setting Dns1 using " + mDhcpInfo + ", e=" + e);
+ }
+ try {
+ mNetworkProperties.addDns(InetAddress.getByAddress(
+ NetworkUtils.v4IntToArray(mDhcpInfo.dns2)));
+
+ } catch (UnknownHostException e) {
+ Log.e(TAG, "Exception setting Dns2 using " + mDhcpInfo + ", e=" + e);
+ }
+ // TODO - add proxy info
+ }
+
+
+ private void checkUseStaticIp() {
+ mUseStaticIp = false;
+ final ContentResolver cr = mContext.getContentResolver();
+ try {
+ if (Settings.System.getInt(cr, Settings.System.WIFI_USE_STATIC_IP) == 0) {
+ return;
+ }
+ } catch (Settings.SettingNotFoundException e) {
+ return;
+ }
+
+ try {
+ String addr = Settings.System.getString(cr, Settings.System.WIFI_STATIC_IP);
+ if (addr != null) {
+ mDhcpInfo.ipAddress = stringToIpAddr(addr);
+ } else {
+ return;
+ }
+ addr = Settings.System.getString(cr, Settings.System.WIFI_STATIC_GATEWAY);
+ if (addr != null) {
+ mDhcpInfo.gateway = stringToIpAddr(addr);
+ } else {
+ return;
+ }
+ addr = Settings.System.getString(cr, Settings.System.WIFI_STATIC_NETMASK);
+ if (addr != null) {
+ mDhcpInfo.netmask = stringToIpAddr(addr);
+ } else {
+ return;
+ }
+ addr = Settings.System.getString(cr, Settings.System.WIFI_STATIC_DNS1);
+ if (addr != null) {
+ mDhcpInfo.dns1 = stringToIpAddr(addr);
+ } else {
+ return;
+ }
+ addr = Settings.System.getString(cr, Settings.System.WIFI_STATIC_DNS2);
+ if (addr != null) {
+ mDhcpInfo.dns2 = stringToIpAddr(addr);
+ } else {
+ mDhcpInfo.dns2 = 0;
+ }
+ } catch (UnknownHostException e) {
+ return;
+ }
+ mUseStaticIp = true;
+ }
+
+ private static int stringToIpAddr(String addrString) throws UnknownHostException {
+ try {
+ String[] parts = addrString.split("\\.");
+ if (parts.length != 4) {
+ throw new UnknownHostException(addrString);
+ }
+
+ int a = Integer.parseInt(parts[0]) ;
+ int b = Integer.parseInt(parts[1]) << 8;
+ int c = Integer.parseInt(parts[2]) << 16;
+ int d = Integer.parseInt(parts[3]) << 24;
+
+ return a | b | c | d;
+ } catch (NumberFormatException ex) {
+ throw new UnknownHostException(addrString);
+ }
+ }
+
+ private int getMaxDhcpRetries() {
+ return Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.WIFI_MAX_DHCP_RETRY_COUNT,
+ DEFAULT_MAX_DHCP_RETRIES);
+ }
+
+ private class SettingsObserver extends ContentObserver {
+ public SettingsObserver(Handler handler) {
+ super(handler);
+ ContentResolver cr = mContext.getContentResolver();
+ cr.registerContentObserver(Settings.System.getUriFor(
+ Settings.System.WIFI_USE_STATIC_IP), false, this);
+ cr.registerContentObserver(Settings.System.getUriFor(
+ Settings.System.WIFI_STATIC_IP), false, this);
+ cr.registerContentObserver(Settings.System.getUriFor(
+ Settings.System.WIFI_STATIC_GATEWAY), false, this);
+ cr.registerContentObserver(Settings.System.getUriFor(
+ Settings.System.WIFI_STATIC_NETMASK), false, this);
+ cr.registerContentObserver(Settings.System.getUriFor(
+ Settings.System.WIFI_STATIC_DNS1), false, this);
+ cr.registerContentObserver(Settings.System.getUriFor(
+ Settings.System.WIFI_STATIC_DNS2), false, this);
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ super.onChange(selfChange);
+
+ boolean wasStaticIp = mUseStaticIp;
+ int oIp, oGw, oMsk, oDns1, oDns2;
+ oIp = oGw = oMsk = oDns1 = oDns2 = 0;
+ if (wasStaticIp) {
+ oIp = mDhcpInfo.ipAddress;
+ oGw = mDhcpInfo.gateway;
+ oMsk = mDhcpInfo.netmask;
+ oDns1 = mDhcpInfo.dns1;
+ oDns2 = mDhcpInfo.dns2;
+ }
+ checkUseStaticIp();
+
+ if (mWifiInfo.getSupplicantState() == SupplicantState.UNINITIALIZED) {
+ return;
+ }
+
+ boolean changed =
+ (wasStaticIp != mUseStaticIp) ||
+ (wasStaticIp && (
+ oIp != mDhcpInfo.ipAddress ||
+ oGw != mDhcpInfo.gateway ||
+ oMsk != mDhcpInfo.netmask ||
+ oDns1 != mDhcpInfo.dns1 ||
+ oDns2 != mDhcpInfo.dns2));
+
+ if (changed) {
+ sendMessage(CMD_RECONFIGURE_IP);
+ mConfigChanged = true;
+ }
+ }
+ }
+
+ /**
+ * Whether to disable coexistence mode while obtaining IP address. This
+ * logic will return true only if the current bluetooth
+ * headset/handsfree state is disconnected. This means if it is in an
+ * error state, we will NOT disable coexistence mode to err on the side
+ * of safety.
+ *
+ * @return Whether to disable coexistence mode.
+ */
+ private boolean shouldDisableCoexistenceMode() {
+ int state = mBluetoothHeadset.getState(mBluetoothHeadset.getCurrentHeadset());
+ return state == BluetoothHeadset.STATE_DISCONNECTED;
+ }
+
+ private void checkIsBluetoothPlaying() {
+ boolean isBluetoothPlaying = false;
+ Set<BluetoothDevice> connected = mBluetoothA2dp.getConnectedSinks();
+
+ for (BluetoothDevice device : connected) {
+ if (mBluetoothA2dp.getSinkState(device) == BluetoothA2dp.STATE_PLAYING) {
+ isBluetoothPlaying = true;
+ break;
+ }
+ }
+ setBluetoothScanMode(isBluetoothPlaying);
+ }
+
+ private void sendScanResultsAvailableBroadcast() {
+ if (!ActivityManagerNative.isSystemReady()) return;
+
+ mContext.sendBroadcast(new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
+ }
+
+ private void sendRssiChangeBroadcast(final int newRssi) {
+ if (!ActivityManagerNative.isSystemReady()) return;
+
+ Intent intent = new Intent(WifiManager.RSSI_CHANGED_ACTION);
+ intent.putExtra(WifiManager.EXTRA_NEW_RSSI, newRssi);
+ mContext.sendBroadcast(intent);
+ }
+
+ private void sendNetworkStateChangeBroadcast(String bssid) {
+ Intent intent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
+ | Intent.FLAG_RECEIVER_REPLACE_PENDING);
+ intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, mNetworkInfo);
+ intent.putExtra(WifiManager.EXTRA_NETWORK_PROPERTIES, mNetworkProperties);
+ if (bssid != null)
+ intent.putExtra(WifiManager.EXTRA_BSSID, bssid);
+ mContext.sendStickyBroadcast(intent);
+ }
+
+ private void sendConfigChangeBroadcast() {
+ Intent intent = new Intent(WifiManager.CONFIG_CHANGED_ACTION);
+ intent.putExtra(WifiManager.EXTRA_NETWORK_PROPERTIES, mNetworkProperties);
+ mContext.sendBroadcast(intent);
+ }
+
+ private void sendSupplicantStateChangedBroadcast(StateChangeResult sc, boolean failedAuth) {
+ Intent intent = new Intent(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
+ | Intent.FLAG_RECEIVER_REPLACE_PENDING);
+ intent.putExtra(WifiManager.EXTRA_NEW_STATE, (Parcelable)sc.state);
+ if (failedAuth) {
+ intent.putExtra(
+ WifiManager.EXTRA_SUPPLICANT_ERROR,
+ WifiManager.ERROR_AUTHENTICATING);
+ }
+ mContext.sendStickyBroadcast(intent);
+ }
+
+ private void sendSupplicantConnectionChangedBroadcast(boolean connected) {
+ if (!ActivityManagerNative.isSystemReady()) return;
+
+ Intent intent = new Intent(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
+ intent.putExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, connected);
+ mContext.sendBroadcast(intent);
+ }
+
+ /**
+ * Record the detailed state of a network.
+ * @param state the new @{code DetailedState}
+ */
+ private void setDetailedState(NetworkInfo.DetailedState state) {
+ Log.d(TAG, "setDetailed state, old ="
+ + mNetworkInfo.getDetailedState() + " and new state=" + state);
+ if (state != mNetworkInfo.getDetailedState()) {
+ mNetworkInfo.setDetailedState(state, null, null);
+ }
+ }
+
+ private static String removeDoubleQuotes(String string) {
+ if (string.length() <= 2) return "";
+ return string.substring(1, string.length() - 1);
+ }
+
+ private static String convertToQuotedString(String string) {
+ return "\"" + string + "\"";
+ }
+
+ private static String makeString(BitSet set, String[] strings) {
+ StringBuffer buf = new StringBuffer();
+ int nextSetBit = -1;
+
+ /* Make sure all set bits are in [0, strings.length) to avoid
+ * going out of bounds on strings. (Shouldn't happen, but...) */
+ set = set.get(0, strings.length);
+
+ while ((nextSetBit = set.nextSetBit(nextSetBit + 1)) != -1) {
+ buf.append(strings[nextSetBit].replace('_', '-')).append(' ');
+ }
+
+ // remove trailing space
+ if (set.cardinality() > 0) {
+ buf.setLength(buf.length() - 1);
+ }
+
+ return buf.toString();
+ }
+
+ private static int lookupString(String string, String[] strings) {
+ int size = strings.length;
+
+ string = string.replace('-', '_');
+
+ for (int i = 0; i < size; i++)
+ if (string.equals(strings[i]))
+ return i;
+
+ // if we ever get here, we should probably add the
+ // value to WifiConfiguration to reflect that it's
+ // supported by the WPA supplicant
+ Log.w(TAG, "Failed to look-up a string: " + string);
+
+ return -1;
+ }
+
+ private int addOrUpdateNetworkNative(WifiConfiguration config) {
+ /*
+ * If the supplied networkId is -1, we create a new empty
+ * network configuration. Otherwise, the networkId should
+ * refer to an existing configuration.
+ */
+ int netId = config.networkId;
+ boolean newNetwork = netId == -1;
+ // networkId of -1 means we want to create a new network
+
+ if (newNetwork) {
+ netId = WifiNative.addNetworkCommand();
+ if (netId < 0) {
+ Log.e(TAG, "Failed to add a network!");
+ return -1;
+ }
+ }
+
+ setVariables: {
+
+ if (config.SSID != null &&
+ !WifiNative.setNetworkVariableCommand(
+ netId,
+ WifiConfiguration.ssidVarName,
+ config.SSID)) {
+ Log.d(TAG, "failed to set SSID: "+config.SSID);
+ break setVariables;
+ }
+
+ if (config.BSSID != null &&
+ !WifiNative.setNetworkVariableCommand(
+ netId,
+ WifiConfiguration.bssidVarName,
+ config.BSSID)) {
+ Log.d(TAG, "failed to set BSSID: "+config.BSSID);
+ break setVariables;
+ }
+
+ String allowedKeyManagementString =
+ makeString(config.allowedKeyManagement, WifiConfiguration.KeyMgmt.strings);
+ if (config.allowedKeyManagement.cardinality() != 0 &&
+ !WifiNative.setNetworkVariableCommand(
+ netId,
+ WifiConfiguration.KeyMgmt.varName,
+ allowedKeyManagementString)) {
+ Log.d(TAG, "failed to set key_mgmt: "+
+ allowedKeyManagementString);
+ break setVariables;
+ }
+
+ String allowedProtocolsString =
+ makeString(config.allowedProtocols, WifiConfiguration.Protocol.strings);
+ if (config.allowedProtocols.cardinality() != 0 &&
+ !WifiNative.setNetworkVariableCommand(
+ netId,
+ WifiConfiguration.Protocol.varName,
+ allowedProtocolsString)) {
+ Log.d(TAG, "failed to set proto: "+
+ allowedProtocolsString);
+ break setVariables;
+ }
+
+ String allowedAuthAlgorithmsString =
+ makeString(config.allowedAuthAlgorithms, WifiConfiguration.AuthAlgorithm.strings);
+ if (config.allowedAuthAlgorithms.cardinality() != 0 &&
+ !WifiNative.setNetworkVariableCommand(
+ netId,
+ WifiConfiguration.AuthAlgorithm.varName,
+ allowedAuthAlgorithmsString)) {
+ Log.d(TAG, "failed to set auth_alg: "+
+ allowedAuthAlgorithmsString);
+ break setVariables;
+ }
+
+ String allowedPairwiseCiphersString =
+ makeString(config.allowedPairwiseCiphers,
+ WifiConfiguration.PairwiseCipher.strings);
+ if (config.allowedPairwiseCiphers.cardinality() != 0 &&
+ !WifiNative.setNetworkVariableCommand(
+ netId,
+ WifiConfiguration.PairwiseCipher.varName,
+ allowedPairwiseCiphersString)) {
+ Log.d(TAG, "failed to set pairwise: "+
+ allowedPairwiseCiphersString);
+ break setVariables;
+ }
+
+ String allowedGroupCiphersString =
+ makeString(config.allowedGroupCiphers, WifiConfiguration.GroupCipher.strings);
+ if (config.allowedGroupCiphers.cardinality() != 0 &&
+ !WifiNative.setNetworkVariableCommand(
+ netId,
+ WifiConfiguration.GroupCipher.varName,
+ allowedGroupCiphersString)) {
+ Log.d(TAG, "failed to set group: "+
+ allowedGroupCiphersString);
+ break setVariables;
+ }
+
+ // Prevent client screw-up by passing in a WifiConfiguration we gave it
+ // by preventing "*" as a key.
+ if (config.preSharedKey != null && !config.preSharedKey.equals("*") &&
+ !WifiNative.setNetworkVariableCommand(
+ netId,
+ WifiConfiguration.pskVarName,
+ config.preSharedKey)) {
+ Log.d(TAG, "failed to set psk: "+config.preSharedKey);
+ break setVariables;
+ }
+
+ boolean hasSetKey = false;
+ if (config.wepKeys != null) {
+ for (int i = 0; i < config.wepKeys.length; i++) {
+ // Prevent client screw-up by passing in a WifiConfiguration we gave it
+ // by preventing "*" as a key.
+ if (config.wepKeys[i] != null && !config.wepKeys[i].equals("*")) {
+ if (!WifiNative.setNetworkVariableCommand(
+ netId,
+ WifiConfiguration.wepKeyVarNames[i],
+ config.wepKeys[i])) {
+ Log.d(TAG,
+ "failed to set wep_key"+i+": " +
+ config.wepKeys[i]);
+ break setVariables;
+ }
+ hasSetKey = true;
+ }
+ }
+ }
+
+ if (hasSetKey) {
+ if (!WifiNative.setNetworkVariableCommand(
+ netId,
+ WifiConfiguration.wepTxKeyIdxVarName,
+ Integer.toString(config.wepTxKeyIndex))) {
+ Log.d(TAG,
+ "failed to set wep_tx_keyidx: "+
+ config.wepTxKeyIndex);
+ break setVariables;
+ }
+ }
+
+ if (!WifiNative.setNetworkVariableCommand(
+ netId,
+ WifiConfiguration.priorityVarName,
+ Integer.toString(config.priority))) {
+ Log.d(TAG, config.SSID + ": failed to set priority: "
+ +config.priority);
+ break setVariables;
+ }
+
+ if (config.hiddenSSID && !WifiNative.setNetworkVariableCommand(
+ netId,
+ WifiConfiguration.hiddenSSIDVarName,
+ Integer.toString(config.hiddenSSID ? 1 : 0))) {
+ Log.d(TAG, config.SSID + ": failed to set hiddenSSID: "+
+ config.hiddenSSID);
+ break setVariables;
+ }
+
+ for (WifiConfiguration.EnterpriseField field
+ : config.enterpriseFields) {
+ String varName = field.varName();
+ String value = field.value();
+ if (value != null) {
+ if (field != config.eap) {
+ value = (value.length() == 0) ? "NULL" : convertToQuotedString(value);
+ }
+ if (!WifiNative.setNetworkVariableCommand(
+ netId,
+ varName,
+ value)) {
+ Log.d(TAG, config.SSID + ": failed to set " + varName +
+ ": " + value);
+ break setVariables;
+ }
+ }
+ }
+ return netId;
+ }
+
+ if (newNetwork) {
+ WifiNative.removeNetworkCommand(netId);
+ Log.d(TAG,
+ "Failed to set a network variable, removed network: "
+ + netId);
+ }
+
+ return -1;
+ }
+
+ private List<WifiConfiguration> getConfiguredNetworksNative() {
+ String listStr = WifiNative.listNetworksCommand();
+
+ List<WifiConfiguration> networks =
+ new ArrayList<WifiConfiguration>();
+ if (listStr == null)
+ return networks;
+
+ String[] lines = listStr.split("\n");
+ // Skip the first line, which is a header
+ for (int i = 1; i < lines.length; i++) {
+ String[] result = lines[i].split("\t");
+ // network-id | ssid | bssid | flags
+ WifiConfiguration config = new WifiConfiguration();
+ try {
+ config.networkId = Integer.parseInt(result[0]);
+ } catch(NumberFormatException e) {
+ continue;
+ }
+ if (result.length > 3) {
+ if (result[3].indexOf("[CURRENT]") != -1)
+ config.status = WifiConfiguration.Status.CURRENT;
+ else if (result[3].indexOf("[DISABLED]") != -1)
+ config.status = WifiConfiguration.Status.DISABLED;
+ else
+ config.status = WifiConfiguration.Status.ENABLED;
+ } else {
+ config.status = WifiConfiguration.Status.ENABLED;
+ }
+ readNetworkVariables(config);
+ networks.add(config);
+ }
+ return networks;
+ }
+
+ /**
+ * Read the variables from the supplicant daemon that are needed to
+ * fill in the WifiConfiguration object.
+ *
+ * @param config the {@link WifiConfiguration} object to be filled in.
+ */
+ private void readNetworkVariables(WifiConfiguration config) {
+
+ int netId = config.networkId;
+ if (netId < 0)
+ return;
+
+ /*
+ * TODO: maybe should have a native method that takes an array of
+ * variable names and returns an array of values. But we'd still
+ * be doing a round trip to the supplicant daemon for each variable.
+ */
+ String value;
+
+ value = WifiNative.getNetworkVariableCommand(netId, WifiConfiguration.ssidVarName);
+ if (!TextUtils.isEmpty(value)) {
+ config.SSID = removeDoubleQuotes(value);
+ } else {
+ config.SSID = null;
+ }
+
+ value = WifiNative.getNetworkVariableCommand(netId, WifiConfiguration.bssidVarName);
+ if (!TextUtils.isEmpty(value)) {
+ config.BSSID = value;
+ } else {
+ config.BSSID = null;
+ }
+
+ value = WifiNative.getNetworkVariableCommand(netId, WifiConfiguration.priorityVarName);
+ config.priority = -1;
+ if (!TextUtils.isEmpty(value)) {
+ try {
+ config.priority = Integer.parseInt(value);
+ } catch (NumberFormatException ignore) {
+ }
+ }
+
+ value = WifiNative.getNetworkVariableCommand(netId, WifiConfiguration.hiddenSSIDVarName);
+ config.hiddenSSID = false;
+ if (!TextUtils.isEmpty(value)) {
+ try {
+ config.hiddenSSID = Integer.parseInt(value) != 0;
+ } catch (NumberFormatException ignore) {
+ }
+ }
+
+ value = WifiNative.getNetworkVariableCommand(netId, WifiConfiguration.wepTxKeyIdxVarName);
+ config.wepTxKeyIndex = -1;
+ if (!TextUtils.isEmpty(value)) {
+ try {
+ config.wepTxKeyIndex = Integer.parseInt(value);
+ } catch (NumberFormatException ignore) {
+ }
+ }
+
+ for (int i = 0; i < 4; i++) {
+ value = WifiNative.getNetworkVariableCommand(netId,
+ WifiConfiguration.wepKeyVarNames[i]);
+ if (!TextUtils.isEmpty(value)) {
+ config.wepKeys[i] = value;
+ } else {
+ config.wepKeys[i] = null;
+ }
+ }
+
+ value = WifiNative.getNetworkVariableCommand(netId, WifiConfiguration.pskVarName);
+ if (!TextUtils.isEmpty(value)) {
+ config.preSharedKey = value;
+ } else {
+ config.preSharedKey = null;
+ }
+
+ value = WifiNative.getNetworkVariableCommand(config.networkId,
+ WifiConfiguration.Protocol.varName);
+ if (!TextUtils.isEmpty(value)) {
+ String vals[] = value.split(" ");
+ for (String val : vals) {
+ int index =
+ lookupString(val, WifiConfiguration.Protocol.strings);
+ if (0 <= index) {
+ config.allowedProtocols.set(index);
+ }
+ }
+ }
+
+ value = WifiNative.getNetworkVariableCommand(config.networkId,
+ WifiConfiguration.KeyMgmt.varName);
+ if (!TextUtils.isEmpty(value)) {
+ String vals[] = value.split(" ");
+ for (String val : vals) {
+ int index =
+ lookupString(val, WifiConfiguration.KeyMgmt.strings);
+ if (0 <= index) {
+ config.allowedKeyManagement.set(index);
+ }
+ }
+ }
+
+ value = WifiNative.getNetworkVariableCommand(config.networkId,
+ WifiConfiguration.AuthAlgorithm.varName);
+ if (!TextUtils.isEmpty(value)) {
+ String vals[] = value.split(" ");
+ for (String val : vals) {
+ int index =
+ lookupString(val, WifiConfiguration.AuthAlgorithm.strings);
+ if (0 <= index) {
+ config.allowedAuthAlgorithms.set(index);
+ }
+ }
+ }
+
+ value = WifiNative.getNetworkVariableCommand(config.networkId,
+ WifiConfiguration.PairwiseCipher.varName);
+ if (!TextUtils.isEmpty(value)) {
+ String vals[] = value.split(" ");
+ for (String val : vals) {
+ int index =
+ lookupString(val, WifiConfiguration.PairwiseCipher.strings);
+ if (0 <= index) {
+ config.allowedPairwiseCiphers.set(index);
+ }
+ }
+ }
+
+ value = WifiNative.getNetworkVariableCommand(config.networkId,
+ WifiConfiguration.GroupCipher.varName);
+ if (!TextUtils.isEmpty(value)) {
+ String vals[] = value.split(" ");
+ for (String val : vals) {
+ int index =
+ lookupString(val, WifiConfiguration.GroupCipher.strings);
+ if (0 <= index) {
+ config.allowedGroupCiphers.set(index);
+ }
+ }
+ }
+
+ for (WifiConfiguration.EnterpriseField field :
+ config.enterpriseFields) {
+ value = WifiNative.getNetworkVariableCommand(netId,
+ field.varName());
+ if (!TextUtils.isEmpty(value)) {
+ if (field != config.eap) value = removeDoubleQuotes(value);
+ field.setValue(value);
+ }
+ }
+
+ }
+
+ /**
+ * Poll for info not reported via events
+ * RSSI & Linkspeed
+ */
+ private void requestPolledInfo() {
+ int newRssi = WifiNative.getRssiCommand();
+ if (newRssi != -1 && -200 < newRssi && newRssi < 256) { // screen out invalid values
+ /* some implementations avoid negative values by adding 256
+ * so we need to adjust for that here.
+ */
+ if (newRssi > 0) newRssi -= 256;
+ mWifiInfo.setRssi(newRssi);
+ /*
+ * Rather then sending the raw RSSI out every time it
+ * changes, we precalculate the signal level that would
+ * be displayed in the status bar, and only send the
+ * broadcast if that much more coarse-grained number
+ * changes. This cuts down greatly on the number of
+ * broadcasts, at the cost of not mWifiInforming others
+ * interested in RSSI of all the changes in signal
+ * level.
+ */
+ // TODO: The second arg to the call below needs to be a symbol somewhere, but
+ // it's actually the size of an array of icons that's private
+ // to StatusBar Policy.
+ int newSignalLevel = WifiManager.calculateSignalLevel(newRssi, 4);
+ if (newSignalLevel != mLastSignalLevel) {
+ sendRssiChangeBroadcast(newRssi);
+ }
+ mLastSignalLevel = newSignalLevel;
+ } else {
+ mWifiInfo.setRssi(-200);
+ }
+ int newLinkSpeed = WifiNative.getLinkSpeedCommand();
+ if (newLinkSpeed != -1) {
+ mWifiInfo.setLinkSpeed(newLinkSpeed);
+ }
+ }
+
+ /**
+ * Resets the Wi-Fi Connections by clearing any state, resetting any sockets
+ * using the interface, stopping DHCP & disabling interface
+ */
+ private void handleNetworkDisconnect() {
+ Log.d(TAG, "Reset connections and stopping DHCP");
+
+ /*
+ * Reset connections & stop DHCP
+ */
+ NetworkUtils.resetConnections(mInterfaceName);
+
+ if (!NetworkUtils.stopDhcp(mInterfaceName)) {
+ Log.e(TAG, "Could not stop DHCP");
+ }
+
+ /* Disable interface */
+ NetworkUtils.disableInterface(mInterfaceName);
+
+ /* send event to CM & network change broadcast */
+ setDetailedState(DetailedState.DISCONNECTED);
+ sendNetworkStateChangeBroadcast(mLastBssid);
+
+ /* Reset data structures */
+ mWifiInfo.setIpAddress(0);
+ mWifiInfo.setBSSID(null);
+ mWifiInfo.setSSID(null);
+ mWifiInfo.setNetworkId(-1);
+
+ /* Clear network properties */
+ mNetworkProperties.clear();
+
+ mLastBssid= null;
+ mLastNetworkId = -1;
+
+ }
+
+
+ /*********************************************************
+ * Notifications from WifiMonitor
+ ********************************************************/
+
+ /**
+ * A structure for supplying information about a supplicant state
+ * change in the STATE_CHANGE event message that comes from the
+ * WifiMonitor
+ * thread.
+ */
+ private static class StateChangeResult {
+ StateChangeResult(int networkId, String BSSID, Object state) {
+ this.state = state;
+ this.BSSID = BSSID;
+ this.networkId = networkId;
+ }
+ int networkId;
+ String BSSID;
+ Object state;
+ }
+
+ /**
+ * Send the tracker a notification that a user-entered password key
+ * may be incorrect (i.e., caused authentication to fail).
+ */
+ void notifyPasswordKeyMayBeIncorrect() {
+ sendMessage(PASSWORD_MAY_BE_INCORRECT_EVENT);
+ }
+
+ /**
+ * Send the tracker a notification that a connection to the supplicant
+ * daemon has been established.
+ */
+ void notifySupplicantConnection() {
+ sendMessage(SUP_CONNECTION_EVENT);
+ }
+
+ /**
+ * Send the tracker a notification that a connection to the supplicant
+ * daemon has been established.
+ */
+ void notifySupplicantLost() {
+ sendMessage(SUP_DISCONNECTION_EVENT);
+ }
+
+ /**
+ * Send the tracker a notification that the state of Wifi connectivity
+ * has changed.
+ * @param networkId the configured network on which the state change occurred
+ * @param newState the new network state
+ * @param BSSID when the new state is {@link DetailedState#CONNECTED
+ * NetworkInfo.DetailedState.CONNECTED},
+ * this is the MAC address of the access point. Otherwise, it
+ * is {@code null}.
+ */
+ void notifyNetworkStateChange(DetailedState newState, String BSSID, int networkId) {
+ if (newState == NetworkInfo.DetailedState.CONNECTED) {
+ sendMessage(obtainMessage(NETWORK_CONNECTION_EVENT,
+ new StateChangeResult(networkId, BSSID, newState)));
+ } else {
+ sendMessage(obtainMessage(NETWORK_DISCONNECTION_EVENT,
+ new StateChangeResult(networkId, BSSID, newState)));
+ }
+ }
+
+ /**
+ * Send the tracker a notification that the state of the supplicant
+ * has changed.
+ * @param networkId the configured network on which the state change occurred
+ * @param newState the new {@code SupplicantState}
+ */
+ void notifySupplicantStateChange(int networkId, String BSSID, SupplicantState newState) {
+ sendMessage(obtainMessage(SUPPLICANT_STATE_CHANGE_EVENT,
+ new StateChangeResult(networkId, BSSID, newState)));
+ }
+
+ /**
+ * Send the tracker a notification that a scan has completed, and results
+ * are available.
+ */
+ void notifyScanResultsAvailable() {
+ /**
+ * Switch scan mode over to passive.
+ * Turning off scan-only mode happens only in "Connect" mode
+ */
+ setScanType(false);
+ sendMessage(SCAN_RESULTS_EVENT);
+ }
+
+ void notifyDriverStarted() {
+ sendMessage(DRIVER_START_EVENT);
+ }
+
+ void notifyDriverStopped() {
+ sendMessage(DRIVER_STOP_EVENT);
+ }
+
+ void notifyDriverHung() {
+ setWifiEnabled(false);
+ setWifiEnabled(true);
+ }
+
+
+ /********************************************************
+ * HSM states
+ *******************************************************/
+
+ class DefaultState extends HierarchicalState {
+ @Override
+ public boolean processMessage(Message message) {
+ if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ SyncParams syncParams;
+ switch (message.what) {
+ /* Synchronous call returns */
+ case CMD_PING_SUPPLICANT:
+ case CMD_START_SCAN:
+ case CMD_DISCONNECT:
+ case CMD_RECONNECT:
+ case CMD_REASSOCIATE:
+ case CMD_REMOVE_NETWORK:
+ case CMD_ENABLE_NETWORK:
+ case CMD_DISABLE_NETWORK:
+ case CMD_ADD_OR_UPDATE_NETWORK:
+ case CMD_GET_RSSI:
+ case CMD_GET_RSSI_APPROX:
+ case CMD_GET_LINK_SPEED:
+ case CMD_GET_MAC_ADDR:
+ case CMD_SAVE_CONFIG:
+ case CMD_CONNECTION_STATUS:
+ case CMD_GET_NETWORK_CONFIG:
+ if (message.arg2 == SYNCHRONOUS_CALL) {
+ syncParams = (SyncParams) message.obj;
+ syncParams.mSyncReturn.boolValue = false;
+ syncParams.mSyncReturn.intValue = -1;
+ syncParams.mSyncReturn.stringValue = null;
+ syncParams.mSyncReturn.configList = null;
+ notifyOnMsgObject(message);
+ }
+ break;
+ case CMD_ENABLE_RSSI_POLL:
+ mEnableRssiPolling = (message.arg1 == 1);
+ mSupplicantStateTracker.sendMessage(CMD_ENABLE_RSSI_POLL);
+ break;
+ /* Discard */
+ case CMD_LOAD_DRIVER:
+ case CMD_UNLOAD_DRIVER:
+ case CMD_START_SUPPLICANT:
+ case CMD_STOP_SUPPLICANT:
+ case CMD_START_DRIVER:
+ case CMD_STOP_DRIVER:
+ case CMD_START_AP:
+ case CMD_STOP_AP:
+ case CMD_RECONFIGURE_IP:
+ case SUP_CONNECTION_EVENT:
+ case SUP_DISCONNECTION_EVENT:
+ case DRIVER_START_EVENT:
+ case DRIVER_STOP_EVENT:
+ case DRIVER_HUNG_EVENT:
+ case NETWORK_CONNECTION_EVENT:
+ case NETWORK_DISCONNECTION_EVENT:
+ case SCAN_RESULTS_EVENT:
+ case SUPPLICANT_STATE_CHANGE_EVENT:
+ case PASSWORD_MAY_BE_INCORRECT_EVENT:
+ case CMD_BLACKLIST_NETWORK:
+ case CMD_CLEAR_BLACKLIST:
+ case CMD_SET_SCAN_MODE:
+ case CMD_SET_SCAN_TYPE:
+ case CMD_SET_POWER_MODE:
+ case CMD_SET_BLUETOOTH_COEXISTENCE:
+ case CMD_SET_BLUETOOTH_SCAN_MODE:
+ case CMD_SET_NUM_ALLOWED_CHANNELS:
+ case CMD_REQUEST_CM_WAKELOCK:
+ break;
+ default:
+ Log.e(TAG, "Error! unhandled message" + message);
+ break;
+ }
+ return HANDLED;
+ }
+ }
+
+ class InitialState extends HierarchicalState {
+ @Override
+ //TODO: could move logging into a common class
+ public void enter() {
+ if (DBG) Log.d(TAG, getName() + "\n");
+ // [31-8] Reserved for future use
+ // [7 - 0] HSM state change
+ // 50021 wifi_state_changed (custom|1|5)
+ EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
+
+ if (WifiNative.isDriverLoaded()) {
+ transitionTo(mDriverLoadedState);
+ }
+ else {
+ transitionTo(mDriverUnloadedState);
+ }
+ }
+ }
+
+ class DriverLoadingState extends HierarchicalState {
+ @Override
+ public void enter() {
+ if (DBG) Log.d(TAG, getName() + "\n");
+ EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
+
+ final Message message = new Message();
+ message.copyFrom(getCurrentMessage());
+ /* TODO: add a timeout to fail when driver load is hung.
+ * Similarly for driver unload.
+ */
+ new Thread(new Runnable() {
+ public void run() {
+ sWakeLock.acquire();
+ //enabling state
+ switch(message.arg1) {
+ case WIFI_STATE_ENABLING:
+ setWifiState(WIFI_STATE_ENABLING);
+ break;
+ case WIFI_AP_STATE_ENABLING:
+ setWifiApState(WIFI_AP_STATE_ENABLING);
+ break;
+ }
+
+ if(WifiNative.loadDriver()) {
+ Log.d(TAG, "Driver load successful");
+ sendMessage(CMD_LOAD_DRIVER_SUCCESS);
+ } else {
+ Log.e(TAG, "Failed to load driver!");
+ switch(message.arg1) {
+ case WIFI_STATE_ENABLING:
+ setWifiState(WIFI_STATE_UNKNOWN);
+ break;
+ case WIFI_AP_STATE_ENABLING:
+ setWifiApState(WIFI_AP_STATE_FAILED);
+ break;
+ }
+ sendMessage(CMD_LOAD_DRIVER_FAILURE);
+ }
+ sWakeLock.release();
+ }
+ }).start();
+ }
+
+ @Override
+ public boolean processMessage(Message message) {
+ if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ switch (message.what) {
+ case CMD_LOAD_DRIVER_SUCCESS:
+ transitionTo(mDriverLoadedState);
+ break;
+ case CMD_LOAD_DRIVER_FAILURE:
+ transitionTo(mDriverFailedState);
+ break;
+ case CMD_LOAD_DRIVER:
+ case CMD_UNLOAD_DRIVER:
+ case CMD_START_SUPPLICANT:
+ case CMD_STOP_SUPPLICANT:
+ case CMD_START_AP:
+ case CMD_STOP_AP:
+ case CMD_START_DRIVER:
+ case CMD_STOP_DRIVER:
+ case CMD_SET_SCAN_MODE:
+ case CMD_SET_SCAN_TYPE:
+ case CMD_SET_POWER_MODE:
+ case CMD_SET_BLUETOOTH_COEXISTENCE:
+ case CMD_SET_BLUETOOTH_SCAN_MODE:
+ case CMD_SET_NUM_ALLOWED_CHANNELS:
+ case CMD_START_PACKET_FILTERING:
+ case CMD_STOP_PACKET_FILTERING:
+ deferMessage(message);
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
+ return HANDLED;
+ }
+ }
+
+ class DriverLoadedState extends HierarchicalState {
+ @Override
+ public void enter() {
+ if (DBG) Log.d(TAG, getName() + "\n");
+ EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
+ }
+ @Override
+ public boolean processMessage(Message message) {
+ if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ switch(message.what) {
+ case CMD_UNLOAD_DRIVER:
+ transitionTo(mDriverUnloadingState);
+ break;
+ case CMD_START_SUPPLICANT:
+ if(WifiNative.startSupplicant()) {
+ Log.d(TAG, "Supplicant start successful");
+ mWifiMonitor.startMonitoring();
+ setWifiState(WIFI_STATE_ENABLED);
+ transitionTo(mWaitForSupState);
+ } else {
+ Log.e(TAG, "Failed to start supplicant!");
+ sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_STATE_UNKNOWN, 0));
+ }
+ break;
+ case CMD_START_AP:
+ try {
+ nwService.startAccessPoint((WifiConfiguration) message.obj,
+ mInterfaceName,
+ SOFTAP_IFACE);
+ } catch(Exception e) {
+ Log.e(TAG, "Exception in startAccessPoint()");
+ sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_AP_STATE_FAILED, 0));
+ break;
+ }
+ Log.d(TAG, "Soft AP start successful");
+ setWifiApState(WIFI_AP_STATE_ENABLED);
+ transitionTo(mSoftApStartedState);
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
+ return HANDLED;
+ }
+ }
+
+ class DriverUnloadingState extends HierarchicalState {
+ @Override
+ public void enter() {
+ if (DBG) Log.d(TAG, getName() + "\n");
+ EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
+
+ final Message message = new Message();
+ message.copyFrom(getCurrentMessage());
+ new Thread(new Runnable() {
+ public void run() {
+ if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ sWakeLock.acquire();
+ if(WifiNative.unloadDriver()) {
+ Log.d(TAG, "Driver unload successful");
+ sendMessage(CMD_UNLOAD_DRIVER_SUCCESS);
+
+ switch(message.arg1) {
+ case WIFI_STATE_DISABLED:
+ case WIFI_STATE_UNKNOWN:
+ setWifiState(message.arg1);
+ break;
+ case WIFI_AP_STATE_DISABLED:
+ case WIFI_AP_STATE_FAILED:
+ setWifiApState(message.arg1);
+ break;
+ }
+ } else {
+ Log.e(TAG, "Failed to unload driver!");
+ sendMessage(CMD_UNLOAD_DRIVER_FAILURE);
+
+ switch(message.arg1) {
+ case WIFI_STATE_DISABLED:
+ case WIFI_STATE_UNKNOWN:
+ setWifiState(WIFI_STATE_UNKNOWN);
+ break;
+ case WIFI_AP_STATE_DISABLED:
+ case WIFI_AP_STATE_FAILED:
+ setWifiApState(WIFI_AP_STATE_FAILED);
+ break;
+ }
+ }
+ sWakeLock.release();
+ }
+ }).start();
+ }
+
+ @Override
+ public boolean processMessage(Message message) {
+ if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ switch (message.what) {
+ case CMD_UNLOAD_DRIVER_SUCCESS:
+ transitionTo(mDriverUnloadedState);
+ break;
+ case CMD_UNLOAD_DRIVER_FAILURE:
+ transitionTo(mDriverFailedState);
+ break;
+ case CMD_LOAD_DRIVER:
+ case CMD_UNLOAD_DRIVER:
+ case CMD_START_SUPPLICANT:
+ case CMD_STOP_SUPPLICANT:
+ case CMD_START_AP:
+ case CMD_STOP_AP:
+ case CMD_START_DRIVER:
+ case CMD_STOP_DRIVER:
+ case CMD_SET_SCAN_MODE:
+ case CMD_SET_SCAN_TYPE:
+ case CMD_SET_POWER_MODE:
+ case CMD_SET_BLUETOOTH_COEXISTENCE:
+ case CMD_SET_BLUETOOTH_SCAN_MODE:
+ case CMD_SET_NUM_ALLOWED_CHANNELS:
+ case CMD_START_PACKET_FILTERING:
+ case CMD_STOP_PACKET_FILTERING:
+ deferMessage(message);
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
+ return HANDLED;
+ }
+ }
+
+ class DriverUnloadedState extends HierarchicalState {
+ @Override
+ public void enter() {
+ if (DBG) Log.d(TAG, getName() + "\n");
+ EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
+ }
+ @Override
+ public boolean processMessage(Message message) {
+ if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ switch (message.what) {
+ case CMD_LOAD_DRIVER:
+ transitionTo(mDriverLoadingState);
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
+ return HANDLED;
+ }
+ }
+
+ class DriverFailedState extends HierarchicalState {
+ @Override
+ public void enter() {
+ Log.e(TAG, getName() + "\n");
+ EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
+ }
+ @Override
+ public boolean processMessage(Message message) {
+ if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ return NOT_HANDLED;
+ }
+ }
+
+
+ class WaitForSupState extends HierarchicalState {
+ @Override
+ public void enter() {
+ if (DBG) Log.d(TAG, getName() + "\n");
+ EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
+ }
+ @Override
+ public boolean processMessage(Message message) {
+ if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ switch(message.what) {
+ case SUP_CONNECTION_EVENT:
+ Log.d(TAG, "Supplicant connection established");
+ mSupplicantStateTracker.resetSupplicantState();
+ /* Initialize data structures */
+ mLastBssid = null;
+ mLastNetworkId = -1;
+ mLastSignalLevel = -1;
+
+ mWifiInfo.setMacAddress(WifiNative.getMacAddressCommand());
+
+ //TODO: initialize and fix multicast filtering
+ //mWM.initializeMulticastFiltering();
+
+ if (mBluetoothA2dp == null) {
+ mBluetoothA2dp = new BluetoothA2dp(mContext);
+ }
+ checkIsBluetoothPlaying();
+
+ checkUseStaticIp();
+ sendSupplicantConnectionChangedBroadcast(true);
+ transitionTo(mDriverSupReadyState);
+ break;
+ case CMD_STOP_SUPPLICANT:
+ Log.d(TAG, "Stop supplicant received");
+ WifiNative.stopSupplicant();
+ transitionTo(mDriverLoadedState);
+ break;
+ /* Fail soft ap when waiting for supplicant start */
+ case CMD_START_AP:
+ Log.d(TAG, "Failed to start soft AP with a running supplicant");
+ setWifiApState(WIFI_AP_STATE_FAILED);
+ break;
+ case CMD_START_DRIVER:
+ case CMD_STOP_DRIVER:
+ case CMD_SET_SCAN_MODE:
+ case CMD_SET_SCAN_TYPE:
+ case CMD_SET_POWER_MODE:
+ case CMD_SET_BLUETOOTH_COEXISTENCE:
+ case CMD_SET_BLUETOOTH_SCAN_MODE:
+ case CMD_SET_NUM_ALLOWED_CHANNELS:
+ case CMD_START_PACKET_FILTERING:
+ case CMD_STOP_PACKET_FILTERING:
+ deferMessage(message);
+ break;
+ case CMD_STOP_AP:
+ case CMD_START_SUPPLICANT:
+ case CMD_UNLOAD_DRIVER:
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
+ return HANDLED;
+ }
+ }
+
+ class DriverSupReadyState extends HierarchicalState {
+ @Override
+ public void enter() {
+ if (DBG) Log.d(TAG, getName() + "\n");
+ EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
+ /* Initialize for connect mode operation at start */
+ mIsScanMode = false;
+ }
+ @Override
+ public boolean processMessage(Message message) {
+ if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ SyncParams syncParams;
+ switch(message.what) {
+ case CMD_STOP_SUPPLICANT: /* Supplicant stopped by user */
+ Log.d(TAG, "Stop supplicant received");
+ WifiNative.stopSupplicant();
+ //$FALL-THROUGH$
+ case SUP_DISCONNECTION_EVENT: /* Supplicant died */
+ EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
+ WifiNative.closeSupplicantConnection();
+ handleNetworkDisconnect();
+ sendSupplicantConnectionChangedBroadcast(false);
+ mSupplicantStateTracker.resetSupplicantState();
+ transitionTo(mDriverLoadedState);
+
+ /* When supplicant dies, unload driver and enter failed state */
+ //TODO: consider bringing up supplicant again
+ if (message.what == SUP_DISCONNECTION_EVENT) {
+ Log.d(TAG, "Supplicant died, unloading driver");
+ sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_STATE_UNKNOWN, 0));
+ }
+ break;
+ case CMD_START_DRIVER:
+ EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
+ WifiNative.startDriverCommand();
+ transitionTo(mDriverStartingState);
+ break;
+ case SCAN_RESULTS_EVENT:
+ setScanResults(WifiNative.scanResultsCommand());
+ sendScanResultsAvailableBroadcast();
+ break;
+ case CMD_PING_SUPPLICANT:
+ syncParams = (SyncParams) message.obj;
+ syncParams.mSyncReturn.boolValue = WifiNative.pingCommand();
+ notifyOnMsgObject(message);
+ break;
+ case CMD_ADD_OR_UPDATE_NETWORK:
+ EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
+ syncParams = (SyncParams) message.obj;
+ WifiConfiguration config = (WifiConfiguration) syncParams.mParameter;
+ syncParams.mSyncReturn.intValue = addOrUpdateNetworkNative(config);
+ notifyOnMsgObject(message);
+ break;
+ case CMD_REMOVE_NETWORK:
+ EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
+ if (message.arg2 == SYNCHRONOUS_CALL) {
+ syncParams = (SyncParams) message.obj;
+ syncParams.mSyncReturn.boolValue = WifiNative.removeNetworkCommand(
+ message.arg1);
+ notifyOnMsgObject(message);
+ } else {
+ /* asynchronous handling */
+ WifiNative.removeNetworkCommand(message.arg1);
+ }
+ break;
+ case CMD_ENABLE_NETWORK:
+ EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
+ if (message.arg2 == SYNCHRONOUS_CALL) {
+ syncParams = (SyncParams) message.obj;
+ EnableNetParams enableNetParams = (EnableNetParams) syncParams.mParameter;
+ syncParams.mSyncReturn.boolValue = WifiNative.enableNetworkCommand(
+ enableNetParams.netId, enableNetParams.disableOthers);
+ notifyOnMsgObject(message);
+ } else {
+ /* asynchronous handling */
+ WifiNative.enableNetworkCommand(message.arg1, message.arg2 == 1);
+ }
+ break;
+ case CMD_DISABLE_NETWORK:
+ EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
+ if (message.arg2 == SYNCHRONOUS_CALL) {
+ syncParams = (SyncParams) message.obj;
+ syncParams.mSyncReturn.boolValue = WifiNative.disableNetworkCommand(
+ message.arg1);
+ notifyOnMsgObject(message);
+ } else {
+ /* asynchronous handling */
+ WifiNative.disableNetworkCommand(message.arg1);
+ }
+ break;
+ case CMD_BLACKLIST_NETWORK:
+ EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
+ WifiNative.addToBlacklistCommand((String)message.obj);
+ break;
+ case CMD_CLEAR_BLACKLIST:
+ WifiNative.clearBlacklistCommand();
+ break;
+ case CMD_GET_NETWORK_CONFIG:
+ syncParams = (SyncParams) message.obj;
+ syncParams.mSyncReturn.configList = getConfiguredNetworksNative();
+ notifyOnMsgObject(message);
+ break;
+ case CMD_SAVE_CONFIG:
+ if (message.arg2 == SYNCHRONOUS_CALL) {
+ syncParams = (SyncParams) message.obj;
+ syncParams.mSyncReturn.boolValue = WifiNative.saveConfigCommand();
+ notifyOnMsgObject(message);
+ } else {
+ /* asynchronous handling */
+ WifiNative.saveConfigCommand();
+ }
+ // Inform the backup manager about a data change
+ IBackupManager ibm = IBackupManager.Stub.asInterface(
+ ServiceManager.getService(Context.BACKUP_SERVICE));
+ if (ibm != null) {
+ try {
+ ibm.dataChanged("com.android.providers.settings");
+ } catch (Exception e) {
+ // Try again later
+ }
+ }
+ break;
+ case CMD_CONNECTION_STATUS:
+ syncParams = (SyncParams) message.obj;
+ syncParams.mSyncReturn.stringValue = WifiNative.statusCommand();
+ notifyOnMsgObject(message);
+ break;
+ case CMD_GET_MAC_ADDR:
+ syncParams = (SyncParams) message.obj;
+ syncParams.mSyncReturn.stringValue = WifiNative.getMacAddressCommand();
+ notifyOnMsgObject(message);
+ break;
+ /* Cannot start soft AP while in client mode */
+ case CMD_START_AP:
+ Log.d(TAG, "Failed to start soft AP with a running supplicant");
+ EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
+ setWifiApState(WIFI_AP_STATE_FAILED);
+ break;
+ case CMD_SET_SCAN_MODE:
+ mIsScanMode = (message.arg1 == SCAN_ONLY_MODE);
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ return HANDLED;
+ }
+ }
+
+ class DriverStartingState extends HierarchicalState {
+ @Override
+ public void enter() {
+ if (DBG) Log.d(TAG, getName() + "\n");
+ EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
+ }
+ @Override
+ public boolean processMessage(Message message) {
+ if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ switch(message.what) {
+ case DRIVER_START_EVENT:
+ transitionTo(mDriverStartedState);
+ break;
+ /* Queue driver commands & connection events */
+ case CMD_START_DRIVER:
+ case CMD_STOP_DRIVER:
+ case SUPPLICANT_STATE_CHANGE_EVENT:
+ case NETWORK_CONNECTION_EVENT:
+ case NETWORK_DISCONNECTION_EVENT:
+ case PASSWORD_MAY_BE_INCORRECT_EVENT:
+ case CMD_SET_SCAN_TYPE:
+ case CMD_SET_POWER_MODE:
+ case CMD_SET_BLUETOOTH_COEXISTENCE:
+ case CMD_SET_BLUETOOTH_SCAN_MODE:
+ case CMD_SET_NUM_ALLOWED_CHANNELS:
+ case CMD_START_PACKET_FILTERING:
+ case CMD_STOP_PACKET_FILTERING:
+ deferMessage(message);
+ break;
+ /* Queue the asynchronous version of these commands */
+ case CMD_START_SCAN:
+ case CMD_DISCONNECT:
+ case CMD_REASSOCIATE:
+ case CMD_RECONNECT:
+ if (message.arg2 != SYNCHRONOUS_CALL) {
+ deferMessage(message);
+ }
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
+ return HANDLED;
+ }
+ }
+
+ class DriverStartedState extends HierarchicalState {
+ @Override
+ public void enter() {
+ if (DBG) Log.d(TAG, getName() + "\n");
+ EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
+
+ try {
+ mBatteryStats.noteWifiRunning();
+ } catch (RemoteException ignore) {}
+
+ /* Initialize channel count */
+ setNumAllowedChannels();
+
+ if (mIsScanMode) {
+ WifiNative.setScanResultHandlingCommand(SCAN_ONLY_MODE);
+ WifiNative.disconnectCommand();
+ transitionTo(mScanModeState);
+ } else {
+ WifiNative.setScanResultHandlingCommand(CONNECT_MODE);
+ /* If supplicant has already connected, before we could finish establishing
+ * the control channel connection, we miss all the supplicant events.
+ * Disconnect and reconnect when driver has started to ensure we receive
+ * all supplicant events.
+ *
+ * TODO: This is a bit unclean, ideally the supplicant should never
+ * connect until told to do so by the framework
+ */
+ WifiNative.disconnectCommand();
+ WifiNative.reconnectCommand();
+ transitionTo(mConnectModeState);
+ }
+ }
+ @Override
+ public boolean processMessage(Message message) {
+ if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ SyncParams syncParams;
+ switch(message.what) {
+ case CMD_SET_SCAN_TYPE:
+ if (message.arg1 == SCAN_ACTIVE) {
+ WifiNative.setScanModeCommand(true);
+ } else {
+ WifiNative.setScanModeCommand(false);
+ }
+ break;
+ case CMD_SET_POWER_MODE:
+ WifiNative.setPowerModeCommand(message.arg1);
+ break;
+ case CMD_SET_BLUETOOTH_COEXISTENCE:
+ WifiNative.setBluetoothCoexistenceModeCommand(message.arg1);
+ break;
+ case CMD_SET_BLUETOOTH_SCAN_MODE:
+ WifiNative.setBluetoothCoexistenceScanModeCommand(message.arg1 == 1);
+ break;
+ case CMD_SET_NUM_ALLOWED_CHANNELS:
+ mNumAllowedChannels = message.arg1;
+ WifiNative.setNumAllowedChannelsCommand(message.arg1);
+ break;
+ case CMD_START_DRIVER:
+ /* Ignore another driver start */
+ break;
+ case CMD_STOP_DRIVER:
+ WifiNative.stopDriverCommand();
+ transitionTo(mDriverStoppingState);
+ break;
+ case CMD_REQUEST_CM_WAKELOCK:
+ if (mCm == null) {
+ mCm = (ConnectivityManager)mContext.getSystemService(
+ Context.CONNECTIVITY_SERVICE);
+ }
+ mCm.requestNetworkTransitionWakelock(TAG);
+ break;
+ case CMD_START_PACKET_FILTERING:
+ WifiNative.startPacketFiltering();
+ break;
+ case CMD_STOP_PACKET_FILTERING:
+ WifiNative.stopPacketFiltering();
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
+ return HANDLED;
+ }
+ @Override
+ public void exit() {
+ if (DBG) Log.d(TAG, getName() + "\n");
+ try {
+ mBatteryStats.noteWifiStopped();
+ } catch (RemoteException ignore) { }
+ }
+ }
+
+ class DriverStoppingState extends HierarchicalState {
+ @Override
+ public void enter() {
+ if (DBG) Log.d(TAG, getName() + "\n");
+ EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
+ }
+ @Override
+ public boolean processMessage(Message message) {
+ if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ switch(message.what) {
+ case DRIVER_STOP_EVENT:
+ transitionTo(mDriverStoppedState);
+ break;
+ /* Queue driver commands */
+ case CMD_START_DRIVER:
+ case CMD_STOP_DRIVER:
+ case CMD_SET_SCAN_TYPE:
+ case CMD_SET_POWER_MODE:
+ case CMD_SET_BLUETOOTH_COEXISTENCE:
+ case CMD_SET_BLUETOOTH_SCAN_MODE:
+ case CMD_SET_NUM_ALLOWED_CHANNELS:
+ case CMD_START_PACKET_FILTERING:
+ case CMD_STOP_PACKET_FILTERING:
+ deferMessage(message);
+ break;
+ /* Queue the asynchronous version of these commands */
+ case CMD_START_SCAN:
+ case CMD_DISCONNECT:
+ case CMD_REASSOCIATE:
+ case CMD_RECONNECT:
+ if (message.arg2 != SYNCHRONOUS_CALL) {
+ deferMessage(message);
+ }
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
+ return HANDLED;
+ }
+ }
+
+ class DriverStoppedState extends HierarchicalState {
+ @Override
+ public void enter() {
+ if (DBG) Log.d(TAG, getName() + "\n");
+ EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
+ }
+ @Override
+ public boolean processMessage(Message message) {
+ if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ return NOT_HANDLED;
+ }
+ }
+
+ class ScanModeState extends HierarchicalState {
+ @Override
+ public void enter() {
+ if (DBG) Log.d(TAG, getName() + "\n");
+ EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
+ }
+ @Override
+ public boolean processMessage(Message message) {
+ if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ SyncParams syncParams;
+ switch(message.what) {
+ case CMD_SET_SCAN_MODE:
+ if (message.arg1 == SCAN_ONLY_MODE) {
+ /* Ignore */
+ return HANDLED;
+ } else {
+ WifiNative.setScanResultHandlingCommand(message.arg1);
+ WifiNative.reconnectCommand();
+ mIsScanMode = false;
+ transitionTo(mDisconnectedState);
+ }
+ break;
+ case CMD_START_SCAN:
+ if (message.arg2 == SYNCHRONOUS_CALL) {
+ syncParams = (SyncParams) message.obj;
+ syncParams.mSyncReturn.boolValue = WifiNative.scanCommand(
+ message.arg1 == SCAN_ACTIVE);
+ notifyOnMsgObject(message);
+ } else {
+ /* asynchronous handling */
+ WifiNative.scanCommand(message.arg1 == SCAN_ACTIVE);
+ }
+ break;
+ /* Ignore */
+ case CMD_DISCONNECT:
+ case CMD_RECONNECT:
+ case CMD_REASSOCIATE:
+ case SUPPLICANT_STATE_CHANGE_EVENT:
+ case NETWORK_CONNECTION_EVENT:
+ case NETWORK_DISCONNECTION_EVENT:
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
+ return HANDLED;
+ }
+ }
+
+ class ConnectModeState extends HierarchicalState {
+ @Override
+ public void enter() {
+ if (DBG) Log.d(TAG, getName() + "\n");
+ EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
+ }
+ @Override
+ public boolean processMessage(Message message) {
+ if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ SyncParams syncParams;
+ StateChangeResult stateChangeResult;
+ switch(message.what) {
+ case PASSWORD_MAY_BE_INCORRECT_EVENT:
+ mPasswordKeyMayBeIncorrect = true;
+ break;
+ case SUPPLICANT_STATE_CHANGE_EVENT:
+ stateChangeResult = (StateChangeResult) message.obj;
+ mSupplicantStateTracker.handleEvent(stateChangeResult);
+ break;
+ case CMD_START_SCAN:
+ if (message.arg2 == SYNCHRONOUS_CALL) {
+ syncParams = (SyncParams) message.obj;
+ syncParams.mSyncReturn.boolValue = true;
+ notifyOnMsgObject(message);
+ }
+ /* We need to set scan type in completed state */
+ Message newMsg = obtainMessage();
+ newMsg.copyFrom(message);
+ mSupplicantStateTracker.sendMessage(newMsg);
+ break;
+ /* Do a redundant disconnect without transition */
+ case CMD_DISCONNECT:
+ if (message.arg2 == SYNCHRONOUS_CALL) {
+ syncParams = (SyncParams) message.obj;
+ syncParams.mSyncReturn.boolValue = WifiNative.disconnectCommand();
+ notifyOnMsgObject(message);
+ } else {
+ /* asynchronous handling */
+ WifiNative.disconnectCommand();
+ }
+ break;
+ case CMD_RECONNECT:
+ if (message.arg2 == SYNCHRONOUS_CALL) {
+ syncParams = (SyncParams) message.obj;
+ syncParams.mSyncReturn.boolValue = WifiNative.reconnectCommand();
+ notifyOnMsgObject(message);
+ } else {
+ /* asynchronous handling */
+ WifiNative.reconnectCommand();
+ }
+ break;
+ case CMD_REASSOCIATE:
+ if (message.arg2 == SYNCHRONOUS_CALL) {
+ syncParams = (SyncParams) message.obj;
+ syncParams.mSyncReturn.boolValue = WifiNative.reassociateCommand();
+ notifyOnMsgObject(message);
+ } else {
+ /* asynchronous handling */
+ WifiNative.reassociateCommand();
+ }
+ break;
+ case SCAN_RESULTS_EVENT:
+ /* Set the scan setting back to "connect" mode */
+ WifiNative.setScanResultHandlingCommand(CONNECT_MODE);
+ /* Handle scan results */
+ return NOT_HANDLED;
+ case NETWORK_CONNECTION_EVENT:
+ Log.d(TAG,"Network connection established");
+ stateChangeResult = (StateChangeResult) message.obj;
+
+ mWifiInfo.setBSSID(mLastBssid = stateChangeResult.BSSID);
+ mWifiInfo.setNetworkId(stateChangeResult.networkId);
+ mLastNetworkId = stateChangeResult.networkId;
+
+ /* send event to CM & network change broadcast */
+ setDetailedState(DetailedState.OBTAINING_IPADDR);
+ sendNetworkStateChangeBroadcast(mLastBssid);
+
+ transitionTo(mConnectingState);
+ break;
+ case NETWORK_DISCONNECTION_EVENT:
+ Log.d(TAG,"Network connection lost");
+ handleNetworkDisconnect();
+ transitionTo(mDisconnectedState);
+ break;
+ case CMD_GET_RSSI:
+ syncParams = (SyncParams) message.obj;
+ syncParams.mSyncReturn.intValue = WifiNative.getRssiCommand();
+ notifyOnMsgObject(message);
+ break;
+ case CMD_GET_RSSI_APPROX:
+ syncParams = (SyncParams) message.obj;
+ syncParams.mSyncReturn.intValue = WifiNative.getRssiApproxCommand();
+ notifyOnMsgObject(message);
+ break;
+ case CMD_GET_LINK_SPEED:
+ syncParams = (SyncParams) message.obj;
+ syncParams.mSyncReturn.intValue = WifiNative.getLinkSpeedCommand();
+ notifyOnMsgObject(message);
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
+ return HANDLED;
+ }
+ }
+
+ class ConnectingState extends HierarchicalState {
+ boolean modifiedBluetoothCoexistenceMode;
+ int powerMode;
+ Thread mDhcpThread;
+
+ @Override
+ public void enter() {
+ if (DBG) Log.d(TAG, getName() + "\n");
+ EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
+
+ if (!mUseStaticIp) {
+
+ mDhcpThread = null;
+ modifiedBluetoothCoexistenceMode = false;
+ powerMode = DRIVER_POWER_MODE_AUTO;
+
+ if (shouldDisableCoexistenceMode()) {
+ /*
+ * There are problems setting the Wi-Fi driver's power
+ * mode to active when bluetooth coexistence mode is
+ * enabled or sense.
+ * <p>
+ * We set Wi-Fi to active mode when
+ * obtaining an IP address because we've found
+ * compatibility issues with some routers with low power
+ * mode.
+ * <p>
+ * In order for this active power mode to properly be set,
+ * we disable coexistence mode until we're done with
+ * obtaining an IP address. One exception is if we
+ * are currently connected to a headset, since disabling
+ * coexistence would interrupt that connection.
+ */
+ modifiedBluetoothCoexistenceMode = true;
+
+ // Disable the coexistence mode
+ WifiNative.setBluetoothCoexistenceModeCommand(
+ WifiNative.BLUETOOTH_COEXISTENCE_MODE_DISABLED);
+ }
+
+ powerMode = WifiNative.getPowerModeCommand();
+ if (powerMode < 0) {
+ // Handle the case where supplicant driver does not support
+ // getPowerModeCommand.
+ powerMode = DRIVER_POWER_MODE_AUTO;
+ }
+ if (powerMode != DRIVER_POWER_MODE_ACTIVE) {
+ WifiNative.setPowerModeCommand(DRIVER_POWER_MODE_ACTIVE);
+ }
+
+ Log.d(TAG, "DHCP request started");
+ mDhcpThread = new Thread(new Runnable() {
+ public void run() {
+ if (NetworkUtils.runDhcp(mInterfaceName, mDhcpInfo)) {
+ Log.d(TAG, "DHCP request succeeded");
+ sendMessage(CMD_IP_CONFIG_SUCCESS);
+ } else {
+ Log.d(TAG, "DHCP request failed: " +
+ NetworkUtils.getDhcpError());
+ sendMessage(CMD_IP_CONFIG_FAILURE);
+ }
+ }
+ });
+ mDhcpThread.start();
+ } else {
+ if (NetworkUtils.configureInterface(mInterfaceName, mDhcpInfo)) {
+ Log.v(TAG, "Static IP configuration succeeded");
+ sendMessage(CMD_IP_CONFIG_SUCCESS);
+ } else {
+ Log.v(TAG, "Static IP configuration failed");
+ sendMessage(CMD_IP_CONFIG_FAILURE);
+ }
+ }
+ }
+ @Override
+ public boolean processMessage(Message message) {
+ if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+
+ switch(message.what) {
+ case CMD_IP_CONFIG_SUCCESS:
+ mReconnectCount = 0;
+ mLastSignalLevel = -1; // force update of signal strength
+ mWifiInfo.setIpAddress(mDhcpInfo.ipAddress);
+ Log.d(TAG, "IP configuration: " + mDhcpInfo);
+ configureNetworkProperties();
+ setDetailedState(DetailedState.CONNECTED);
+ sendNetworkStateChangeBroadcast(mLastBssid);
+ //TODO: we could also detect an IP config change
+ // from a DHCP renewal and send out a config change
+ // broadcast
+ if (mConfigChanged) {
+ sendConfigChangeBroadcast();
+ mConfigChanged = false;
+ }
+ transitionTo(mConnectedState);
+ break;
+ case CMD_IP_CONFIG_FAILURE:
+ mWifiInfo.setIpAddress(0);
+
+ Log.e(TAG, "IP configuration failed");
+ /**
+ * If we've exceeded the maximum number of retries for DHCP
+ * to a given network, disable the network
+ */
+ if (++mReconnectCount > getMaxDhcpRetries()) {
+ Log.e(TAG, "Failed " +
+ mReconnectCount + " times, Disabling " + mLastNetworkId);
+ WifiNative.disableNetworkCommand(mLastNetworkId);
+ }
+
+ /* DHCP times out after about 30 seconds, we do a
+ * disconnect and an immediate reconnect to try again
+ */
+ WifiNative.disconnectCommand();
+ WifiNative.reconnectCommand();
+ transitionTo(mDisconnectingState);
+ break;
+ case CMD_DISCONNECT:
+ if (message.arg2 == SYNCHRONOUS_CALL) {
+ SyncParams syncParams = (SyncParams) message.obj;
+ syncParams.mSyncReturn.boolValue = WifiNative.disconnectCommand();
+ notifyOnMsgObject(message);
+ } else {
+ /* asynchronous handling */
+ WifiNative.disconnectCommand();
+ }
+ transitionTo(mDisconnectingState);
+ break;
+ /* Ignore */
+ case NETWORK_CONNECTION_EVENT:
+ break;
+ case CMD_STOP_DRIVER:
+ sendMessage(CMD_DISCONNECT);
+ deferMessage(message);
+ break;
+ case CMD_SET_SCAN_MODE:
+ if (message.arg1 == SCAN_ONLY_MODE) {
+ sendMessage(CMD_DISCONNECT);
+ deferMessage(message);
+ }
+ break;
+ case CMD_RECONFIGURE_IP:
+ deferMessage(message);
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
+ return HANDLED;
+ }
+
+ @Override
+ public void exit() {
+ /* reset power state & bluetooth coexistence if on DHCP */
+ if (!mUseStaticIp) {
+ if (powerMode != DRIVER_POWER_MODE_ACTIVE) {
+ WifiNative.setPowerModeCommand(powerMode);
+ }
+
+ if (modifiedBluetoothCoexistenceMode) {
+ // Set the coexistence mode back to its default value
+ WifiNative.setBluetoothCoexistenceModeCommand(
+ WifiNative.BLUETOOTH_COEXISTENCE_MODE_SENSE);
+ }
+ }
+
+ }
+ }
+
+ class ConnectedState extends HierarchicalState {
+ @Override
+ public void enter() {
+ if (DBG) Log.d(TAG, getName() + "\n");
+ EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
+ }
+ @Override
+ public boolean processMessage(Message message) {
+ if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ switch (message.what) {
+ case CMD_DISCONNECT:
+ if (message.arg2 == SYNCHRONOUS_CALL) {
+ SyncParams syncParams = (SyncParams) message.obj;
+ syncParams.mSyncReturn.boolValue = WifiNative.disconnectCommand();
+ notifyOnMsgObject(message);
+ } else {
+ /* asynchronous handling */
+ WifiNative.disconnectCommand();
+ }
+ transitionTo(mDisconnectingState);
+ break;
+ case CMD_RECONFIGURE_IP:
+ Log.d(TAG,"Reconfiguring IP on connection");
+ NetworkUtils.resetConnections(mInterfaceName);
+ transitionTo(mConnectingState);
+ break;
+ case CMD_STOP_DRIVER:
+ sendMessage(CMD_DISCONNECT);
+ deferMessage(message);
+ break;
+ case CMD_SET_SCAN_MODE:
+ if (message.arg1 == SCAN_ONLY_MODE) {
+ sendMessage(CMD_DISCONNECT);
+ deferMessage(message);
+ }
+ break;
+ /* Ignore */
+ case NETWORK_CONNECTION_EVENT:
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
+ return HANDLED;
+ }
+ }
+
+ class DisconnectingState extends HierarchicalState {
+ @Override
+ public void enter() {
+ if (DBG) Log.d(TAG, getName() + "\n");
+ EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
+ }
+ @Override
+ public boolean processMessage(Message message) {
+ if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ switch (message.what) {
+ case CMD_STOP_DRIVER: /* Stop driver only after disconnect handled */
+ deferMessage(message);
+ break;
+ case CMD_SET_SCAN_MODE:
+ if (message.arg1 == SCAN_ONLY_MODE) {
+ deferMessage(message);
+ }
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
+ return HANDLED;
+ }
+ }
+
+ class DisconnectedState extends HierarchicalState {
+ @Override
+ public void enter() {
+ if (DBG) Log.d(TAG, getName() + "\n");
+ EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
+ }
+ @Override
+ public boolean processMessage(Message message) {
+ if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ switch (message.what) {
+ case CMD_SET_SCAN_MODE:
+ if (message.arg1 == SCAN_ONLY_MODE) {
+ WifiNative.setScanResultHandlingCommand(message.arg1);
+ //Supplicant disconnect to prevent further connects
+ WifiNative.disconnectCommand();
+ mIsScanMode = true;
+ transitionTo(mScanModeState);
+ }
+ break;
+ /* Ignore network disconnect */
+ case NETWORK_DISCONNECTION_EVENT:
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
+ return HANDLED;
+ }
+ }
+
+ class SoftApStartedState extends HierarchicalState {
+ @Override
+ public void enter() {
+ if (DBG) Log.d(TAG, getName() + "\n");
+ EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
+ }
+ @Override
+ public boolean processMessage(Message message) {
+ if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ switch(message.what) {
+ case CMD_STOP_AP:
+ Log.d(TAG,"Stopping Soft AP");
+ setWifiApState(WIFI_AP_STATE_DISABLING);
+ try {
+ nwService.stopAccessPoint();
+ } catch(Exception e) {
+ Log.e(TAG, "Exception in stopAccessPoint()");
+ }
+ transitionTo(mDriverLoadedState);
+ break;
+ case CMD_START_AP:
+ Log.d(TAG,"SoftAP set on a running access point");
+ try {
+ nwService.setAccessPoint((WifiConfiguration) message.obj,
+ mInterfaceName,
+ SOFTAP_IFACE);
+ } catch(Exception e) {
+ Log.e(TAG, "Exception in nwService during soft AP set");
+ try {
+ nwService.stopAccessPoint();
+ } catch (Exception ee) {
+ Slog.e(TAG, "Could not stop AP, :" + ee);
+ }
+ sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_AP_STATE_FAILED, 0));
+ }
+ break;
+ /* Fail client mode operation when soft AP is enabled */
+ case CMD_START_SUPPLICANT:
+ Log.e(TAG,"Cannot start supplicant with a running soft AP");
+ setWifiState(WIFI_STATE_UNKNOWN);
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
+ return HANDLED;
+ }
+ }
+
+
+ class SupplicantStateTracker extends HierarchicalStateMachine {
+
+ private int mRssiPollToken = 0;
+
+ /**
+ * The max number of the WPA supplicant loop iterations before we
+ * decide that the loop should be terminated:
+ */
+ private static final int MAX_SUPPLICANT_LOOP_ITERATIONS = 4;
+ private int mLoopDetectIndex = 0;
+ private int mLoopDetectCount = 0;
+
+ /**
+ * Supplicant state change commands follow
+ * the ordinal values defined in SupplicantState.java
+ */
+ private static final int DISCONNECTED = 0;
+ private static final int INACTIVE = 1;
+ private static final int SCANNING = 2;
+ private static final int ASSOCIATING = 3;
+ private static final int ASSOCIATED = 4;
+ private static final int FOUR_WAY_HANDSHAKE = 5;
+ private static final int GROUP_HANDSHAKE = 6;
+ private static final int COMPLETED = 7;
+ private static final int DORMANT = 8;
+ private static final int UNINITIALIZED = 9;
+ private static final int INVALID = 10;
+
+ private HierarchicalState mUninitializedState = new UninitializedState();
+ private HierarchicalState mInitializedState = new InitializedState();;
+ private HierarchicalState mInactiveState = new InactiveState();
+ private HierarchicalState mDisconnectState = new DisconnectedState();
+ private HierarchicalState mScanState = new ScanState();
+ private HierarchicalState mConnectState = new ConnectState();
+ private HierarchicalState mHandshakeState = new HandshakeState();
+ private HierarchicalState mCompletedState = new CompletedState();
+ private HierarchicalState mDormantState = new DormantState();
+
+ public SupplicantStateTracker(Context context, Handler target) {
+ super(TAG, target.getLooper());
+
+ addState(mUninitializedState);
+ addState(mInitializedState);
+ addState(mInactiveState, mInitializedState);
+ addState(mDisconnectState, mInitializedState);
+ addState(mScanState, mInitializedState);
+ addState(mConnectState, mInitializedState);
+ addState(mHandshakeState, mConnectState);
+ addState(mCompletedState, mConnectState);
+ addState(mDormantState, mInitializedState);
+
+ setInitialState(mUninitializedState);
+
+ //start the state machine
+ start();
+ }
+
+ public void handleEvent(StateChangeResult stateChangeResult) {
+ SupplicantState newState = (SupplicantState) stateChangeResult.state;
+
+ // Supplicant state change
+ // [31-13] Reserved for future use
+ // [8 - 0] Supplicant state (as defined in SupplicantState.java)
+ // 50023 supplicant_state_changed (custom|1|5)
+ EventLog.writeEvent(EVENTLOG_SUPPLICANT_STATE_CHANGED, newState.ordinal());
+
+ sendMessage(obtainMessage(newState.ordinal(), stateChangeResult));
+ }
+
+ public void resetSupplicantState() {
+ transitionTo(mUninitializedState);
+ }
+
+ private void resetLoopDetection() {
+ mLoopDetectCount = 0;
+ mLoopDetectIndex = 0;
+ }
+
+ private boolean handleTransition(Message msg) {
+ if (DBG) Log.d(TAG, getName() + msg.toString() + "\n");
+ switch (msg.what) {
+ case DISCONNECTED:
+ transitionTo(mDisconnectState);
+ break;
+ case SCANNING:
+ transitionTo(mScanState);
+ break;
+ case ASSOCIATING:
+ StateChangeResult stateChangeResult = (StateChangeResult) msg.obj;
+ /* BSSID is valid only in ASSOCIATING state */
+ mWifiInfo.setBSSID(stateChangeResult.BSSID);
+ //$FALL-THROUGH$
+ case ASSOCIATED:
+ case FOUR_WAY_HANDSHAKE:
+ case GROUP_HANDSHAKE:
+ transitionTo(mHandshakeState);
+ break;
+ case COMPLETED:
+ transitionTo(mCompletedState);
+ break;
+ case DORMANT:
+ transitionTo(mDormantState);
+ break;
+ case INACTIVE:
+ transitionTo(mInactiveState);
+ break;
+ case UNINITIALIZED:
+ case INVALID:
+ transitionTo(mUninitializedState);
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ StateChangeResult stateChangeResult = (StateChangeResult) msg.obj;
+ SupplicantState supState = (SupplicantState) stateChangeResult.state;
+ setDetailedState(WifiInfo.getDetailedStateOf(supState));
+ mWifiInfo.setSupplicantState(supState);
+ mWifiInfo.setNetworkId(stateChangeResult.networkId);
+ //TODO: Modify WifiMonitor to report SSID on events
+ //mWifiInfo.setSSID()
+ return HANDLED;
+ }
+
+ /********************************************************
+ * HSM states
+ *******************************************************/
+
+ class InitializedState extends HierarchicalState {
+ @Override
+ public void enter() {
+ if (DBG) Log.d(TAG, getName() + "\n");
+ }
+ @Override
+ public boolean processMessage(Message message) {
+ if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ switch (message.what) {
+ case CMD_START_SCAN:
+ WifiNative.scanCommand(message.arg1 == SCAN_ACTIVE);
+ break;
+ default:
+ if (DBG) Log.w(TAG, "Ignoring " + message);
+ break;
+ }
+ return HANDLED;
+ }
+ }
+
+ class UninitializedState extends HierarchicalState {
+ @Override
+ public void enter() {
+ if (DBG) Log.d(TAG, getName() + "\n");
+ mNetworkInfo.setIsAvailable(false);
+ resetLoopDetection();
+ mPasswordKeyMayBeIncorrect = false;
+ }
+ @Override
+ public boolean processMessage(Message message) {
+ switch(message.what) {
+ default:
+ if (!handleTransition(message)) {
+ if (DBG) Log.w(TAG, "Ignoring " + message);
+ }
+ break;
+ }
+ return HANDLED;
+ }
+ @Override
+ public void exit() {
+ mNetworkInfo.setIsAvailable(true);
+ }
+ }
+
+ class InactiveState extends HierarchicalState {
+ @Override
+ public void enter() {
+ if (DBG) Log.d(TAG, getName() + "\n");
+ Message message = getCurrentMessage();
+ StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
+
+ mNetworkInfo.setIsAvailable(false);
+ resetLoopDetection();
+ mPasswordKeyMayBeIncorrect = false;
+
+ sendSupplicantStateChangedBroadcast(stateChangeResult, false);
+ }
+ @Override
+ public boolean processMessage(Message message) {
+ return handleTransition(message);
+ }
+ @Override
+ public void exit() {
+ mNetworkInfo.setIsAvailable(true);
+ }
+ }
+
+
+ class DisconnectedState extends HierarchicalState {
+ @Override
+ public void enter() {
+ if (DBG) Log.d(TAG, getName() + "\n");
+ Message message = getCurrentMessage();
+ StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
+
+ resetLoopDetection();
+
+ /* If a disconnect event happens after a password key failure
+ * event, disable the network
+ */
+ if (mPasswordKeyMayBeIncorrect) {
+ Log.d(TAG, "Failed to authenticate, disabling network " +
+ mWifiInfo.getNetworkId());
+ WifiNative.disableNetworkCommand(mWifiInfo.getNetworkId());
+ mPasswordKeyMayBeIncorrect = false;
+ sendSupplicantStateChangedBroadcast(stateChangeResult, true);
+ }
+ else {
+ sendSupplicantStateChangedBroadcast(stateChangeResult, false);
+ }
+ }
+ @Override
+ public boolean processMessage(Message message) {
+ return handleTransition(message);
+ }
+ }
+
+ class ScanState extends HierarchicalState {
+ @Override
+ public void enter() {
+ if (DBG) Log.d(TAG, getName() + "\n");
+ Message message = getCurrentMessage();
+ StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
+
+ mPasswordKeyMayBeIncorrect = false;
+ resetLoopDetection();
+ sendSupplicantStateChangedBroadcast(stateChangeResult, false);
+ }
+ @Override
+ public boolean processMessage(Message message) {
+ return handleTransition(message);
+ }
+ }
+
+ class ConnectState extends HierarchicalState {
+ @Override
+ public void enter() {
+ if (DBG) Log.d(TAG, getName() + "\n");
+ }
+ @Override
+ public boolean processMessage(Message message) {
+ switch (message.what) {
+ case CMD_START_SCAN:
+ WifiNative.setScanResultHandlingCommand(SCAN_ONLY_MODE);
+ WifiNative.scanCommand(message.arg1 == SCAN_ACTIVE);
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ return HANDLED;
+ }
+ }
+
+ class HandshakeState extends HierarchicalState {
+ @Override
+ public void enter() {
+ if (DBG) Log.d(TAG, getName() + "\n");
+ final Message message = getCurrentMessage();
+ StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
+
+ if (mLoopDetectIndex > message.what) {
+ mLoopDetectCount++;
+ }
+ if (mLoopDetectCount > MAX_SUPPLICANT_LOOP_ITERATIONS) {
+ WifiNative.disableNetworkCommand(stateChangeResult.networkId);
+ mLoopDetectCount = 0;
+ }
+
+ mLoopDetectIndex = message.what;
+
+ mPasswordKeyMayBeIncorrect = false;
+ sendSupplicantStateChangedBroadcast(stateChangeResult, false);
+ }
+ @Override
+ public boolean processMessage(Message message) {
+ return handleTransition(message);
+ }
+ }
+
+ class CompletedState extends HierarchicalState {
+ @Override
+ public void enter() {
+ if (DBG) Log.d(TAG, getName() + "\n");
+ Message message = getCurrentMessage();
+ StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
+
+ mRssiPollToken++;
+ if (mEnableRssiPolling) {
+ sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, mRssiPollToken, 0),
+ POLL_RSSI_INTERVAL_MSECS);
+ }
+
+ resetLoopDetection();
+
+ mPasswordKeyMayBeIncorrect = false;
+ sendSupplicantStateChangedBroadcast(stateChangeResult, false);
+ }
+ @Override
+ public boolean processMessage(Message message) {
+ switch(message.what) {
+ case ASSOCIATING:
+ case ASSOCIATED:
+ case FOUR_WAY_HANDSHAKE:
+ case GROUP_HANDSHAKE:
+ case COMPLETED:
+ break;
+ case CMD_RSSI_POLL:
+ if (message.arg1 == mRssiPollToken) {
+ // Get Info and continue polling
+ requestPolledInfo();
+ sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, mRssiPollToken, 0),
+ POLL_RSSI_INTERVAL_MSECS);
+ } else {
+ // Polling has completed
+ }
+ break;
+ case CMD_ENABLE_RSSI_POLL:
+ mRssiPollToken++;
+ if (mEnableRssiPolling) {
+ // first poll
+ requestPolledInfo();
+ sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, mRssiPollToken, 0),
+ POLL_RSSI_INTERVAL_MSECS);
+ }
+ break;
+ default:
+ return handleTransition(message);
+ }
+ return HANDLED;
+ }
+ }
+
+ class DormantState extends HierarchicalState {
+ @Override
+ public void enter() {
+ if (DBG) Log.d(TAG, getName() + "\n");
+ Message message = getCurrentMessage();
+ StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
+
+ resetLoopDetection();
+ mPasswordKeyMayBeIncorrect = false;
+
+ sendSupplicantStateChangedBroadcast(stateChangeResult, false);
+
+ /* TODO: reconnect is now being handled at DHCP failure handling
+ * If we run into issues with staying in Dormant state, might
+ * need a reconnect here
+ */
+ }
+ @Override
+ public boolean processMessage(Message message) {
+ return handleTransition(message);
+ }
+ }
+ }
+}
diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java
index 388beea..8e1b236 100644
--- a/wifi/java/android/net/wifi/WifiStateTracker.java
+++ b/wifi/java/android/net/wifi/WifiStateTracker.java
@@ -16,524 +16,59 @@
package android.net.wifi;
-import static android.net.wifi.WifiManager.WIFI_STATE_DISABLED;
-import static android.net.wifi.WifiManager.WIFI_STATE_DISABLING;
-import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED;
-import static android.net.wifi.WifiManager.WIFI_STATE_ENABLING;
-import static android.net.wifi.WifiManager.WIFI_STATE_UNKNOWN;
-/**
- * TODO: Add soft AP states as part of WIFI_STATE_XXX
- * Retain WIFI_STATE_ENABLING that indicates driver is loading
- * Add WIFI_STATE_AP_ENABLED to indicate soft AP has started
- * and WIFI_STATE_FAILED for failure
- * Deprecate WIFI_STATE_UNKNOWN
- *
- * Doing this will simplify the logic for sending broadcasts
- */
-import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED;
-import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLING;
-import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
-import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLING;
-import static android.net.wifi.WifiManager.WIFI_AP_STATE_FAILED;
-import android.app.ActivityManagerNative;
-import android.net.NetworkInfo;
-import android.net.NetworkStateTracker;
-import android.net.DhcpInfo;
-import android.net.NetworkUtils;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.net.ConnectivityManager;
-import android.net.NetworkInfo.DetailedState;
-import android.net.NetworkInfo.State;
+import android.net.NetworkInfo;
import android.net.NetworkProperties;
-import android.os.Binder;
-import android.os.Message;
-import android.os.Parcelable;
+import android.net.NetworkStateTracker;
import android.os.Handler;
-import android.os.IBinder;
-import android.os.INetworkManagementService;
-import android.os.PowerManager;
-import android.os.SystemProperties;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.Process;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.EventLog;
-import android.util.Log;
-import android.util.Slog;
-import android.app.Notification;
-import android.app.PendingIntent;
-import android.app.backup.IBackupManager;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothHeadset;
-import android.bluetooth.BluetoothA2dp;
-import android.content.ContentResolver;
-import android.content.Intent;
-import android.content.Context;
-import android.database.ContentObserver;
-import com.android.internal.app.IBatteryStats;
-import com.android.internal.util.HierarchicalState;
-import com.android.internal.util.HierarchicalStateMachine;
+import android.os.Message;
-import java.net.InetAddress;
-import java.net.NetworkInterface;
-import java.net.SocketException;
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.BitSet;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
-import java.util.regex.Pattern;
/**
- * Track the state of Wifi connectivity. All event handling is done here,
- * and all changes in connectivity state are initiated here.
+ * Track the state of wifi for connectivity service.
*
* @hide
*/
-//TODO: we still need frequent scanning for the case when
-// we issue disconnect but need scan results for open network notification
-public class WifiStateTracker extends HierarchicalStateMachine implements NetworkStateTracker {
+public class WifiStateTracker implements NetworkStateTracker {
- private static final String TAG = "WifiStateTracker";
private static final String NETWORKTYPE = "WIFI";
- private static final boolean DBG = false;
-
- /* TODO: fetch a configurable interface */
- private static final String SOFTAP_IFACE = "wl0.1";
-
- private WifiMonitor mWifiMonitor;
- private INetworkManagementService nwService;
- private ConnectivityManager mCm;
-
- /* Scan results handling */
- private List<ScanResult> mScanResults;
- private static final Pattern scanResultPattern = Pattern.compile("\t+");
- private static final int SCAN_RESULT_CACHE_SIZE = 80;
- private final LinkedHashMap<String, ScanResult> mScanResultCache;
+ private static final String TAG = "WifiStateTracker";
- private String mInterfaceName;
private AtomicBoolean mTeardownRequested = new AtomicBoolean(false);
private AtomicBoolean mPrivateDnsRouteSet = new AtomicBoolean(false);
private AtomicInteger mDefaultGatewayAddr = new AtomicInteger(0);
private AtomicBoolean mDefaultRouteSet = new AtomicBoolean(false);
- private int mNumAllowedChannels = 0;
- private int mLastSignalLevel = -1;
- private String mLastBssid;
- private int mLastNetworkId;
- private boolean mEnableRssiPolling = false;
- private boolean mPasswordKeyMayBeIncorrect = false;
- private boolean mUseStaticIp = false;
- private int mReconnectCount = 0;
- private boolean mIsScanMode = false;
-
- /**
- * Instance of the bluetooth headset helper. This needs to be created
- * early because there is a delay before it actually 'connects', as
- * noted by its javadoc. If we check before it is connected, it will be
- * in an error state and we will not disable coexistence.
- */
- private BluetoothHeadset mBluetoothHeadset;
-
- private BluetoothA2dp mBluetoothA2dp;
-
- /**
- * Observes the static IP address settings.
- */
- private SettingsObserver mSettingsObserver;
private NetworkProperties mNetworkProperties;
-
-
- // Variables relating to the 'available networks' notification
- /**
- * The icon to show in the 'available networks' notification. This will also
- * be the ID of the Notification given to the NotificationManager.
- */
- private static final int ICON_NETWORKS_AVAILABLE =
- com.android.internal.R.drawable.stat_notify_wifi_in_range;
- /**
- * When a notification is shown, we wait this amount before possibly showing it again.
- */
- private final long NOTIFICATION_REPEAT_DELAY_MS;
- /**
- * Whether the user has set the setting to show the 'available networks' notification.
- */
- private boolean mNotificationEnabled;
- /**
- * Observes the user setting to keep {@link #mNotificationEnabled} in sync.
- */
- private NotificationEnabledSettingObserver mNotificationEnabledSettingObserver;
- /**
- * The {@link System#currentTimeMillis()} must be at least this value for us
- * to show the notification again.
- */
- private long mNotificationRepeatTime;
- /**
- * The Notification object given to the NotificationManager.
- */
- private Notification mNotification;
- /**
- * Whether the notification is being shown, as set by us. That is, if the
- * user cancels the notification, we will not receive the callback so this
- * will still be true. We only guarantee if this is false, then the
- * notification is not showing.
- */
- private boolean mNotificationShown;
- /**
- * The number of continuous scans that must occur before consider the
- * supplicant in a scanning state. This allows supplicant to associate with
- * remembered networks that are in the scan results.
- */
- private static final int NUM_SCANS_BEFORE_ACTUALLY_SCANNING = 3;
- /**
- * The number of scans since the last network state change. When this
- * exceeds {@link #NUM_SCANS_BEFORE_ACTUALLY_SCANNING}, we consider the
- * supplicant to actually be scanning. When the network state changes to
- * something other than scanning, we reset this to 0.
- */
- private int mNumScansSinceNetworkStateChange;
-
- // Held during driver load and unload
- private static PowerManager.WakeLock sWakeLock;
+ private NetworkInfo mNetworkInfo;
/* For sending events to connectivity service handler */
private Handler mCsHandler;
private Context mContext;
-
- private DhcpInfo mDhcpInfo;
- private WifiInfo mWifiInfo;
- private NetworkInfo mNetworkInfo;
- private SupplicantStateTracker mSupplicantStateTracker;
-
- // Event log tags (must be in sync with event-log-tags)
- private static final int EVENTLOG_WIFI_STATE_CHANGED = 50021;
- private static final int EVENTLOG_WIFI_EVENT_HANDLED = 50022;
- private static final int EVENTLOG_SUPPLICANT_STATE_CHANGED = 50023;
-
- /* Load the driver */
- private static final int CMD_LOAD_DRIVER = 1;
- /* Unload the driver */
- private static final int CMD_UNLOAD_DRIVER = 2;
- /* Indicates driver load succeeded */
- private static final int CMD_LOAD_DRIVER_SUCCESS = 3;
- /* Indicates driver load failed */
- private static final int CMD_LOAD_DRIVER_FAILURE = 4;
- /* Indicates driver unload succeeded */
- private static final int CMD_UNLOAD_DRIVER_SUCCESS = 5;
- /* Indicates driver unload failed */
- private static final int CMD_UNLOAD_DRIVER_FAILURE = 6;
-
- /* Start the supplicant */
- private static final int CMD_START_SUPPLICANT = 11;
- /* Stop the supplicant */
- private static final int CMD_STOP_SUPPLICANT = 12;
- /* Start the driver */
- private static final int CMD_START_DRIVER = 13;
- /* Start the driver */
- private static final int CMD_STOP_DRIVER = 14;
- /* Indicates DHCP succeded */
- private static final int CMD_IP_CONFIG_SUCCESS = 15;
- /* Indicates DHCP failed */
- private static final int CMD_IP_CONFIG_FAILURE = 16;
- /* Re-configure interface */
- private static final int CMD_RECONFIGURE_IP = 17;
-
-
- /* Start the soft access point */
- private static final int CMD_START_AP = 21;
- /* Stop the soft access point */
- private static final int CMD_STOP_AP = 22;
-
-
- /* Supplicant events */
- /* Connection to supplicant established */
- private static final int SUP_CONNECTION_EVENT = 31;
- /* Connection to supplicant lost */
- private static final int SUP_DISCONNECTION_EVENT = 32;
- /* Driver start completed */
- private static final int DRIVER_START_EVENT = 33;
- /* Driver stop completed */
- private static final int DRIVER_STOP_EVENT = 34;
- /* Network connection completed */
- private static final int NETWORK_CONNECTION_EVENT = 36;
- /* Network disconnection completed */
- private static final int NETWORK_DISCONNECTION_EVENT = 37;
- /* Scan results are available */
- private static final int SCAN_RESULTS_EVENT = 38;
- /* Supplicate state changed */
- private static final int SUPPLICANT_STATE_CHANGE_EVENT = 39;
- /* Password may be incorrect */
- private static final int PASSWORD_MAY_BE_INCORRECT_EVENT = 40;
-
- /* Supplicant commands */
- /* Is supplicant alive ? */
- private static final int CMD_PING_SUPPLICANT = 51;
- /* Add/update a network configuration */
- private static final int CMD_ADD_OR_UPDATE_NETWORK = 52;
- /* Delete a network */
- private static final int CMD_REMOVE_NETWORK = 53;
- /* Enable a network. The device will attempt a connection to the given network. */
- private static final int CMD_ENABLE_NETWORK = 54;
- /* Disable a network. The device does not attempt a connection to the given network. */
- private static final int CMD_DISABLE_NETWORK = 55;
- /* Blacklist network. De-prioritizes the given BSSID for connection. */
- private static final int CMD_BLACKLIST_NETWORK = 56;
- /* Clear the blacklist network list */
- private static final int CMD_CLEAR_BLACKLIST = 57;
- /* Get the configured networks */
- private static final int CMD_GET_NETWORK_CONFIG = 58;
- /* Save configuration */
- private static final int CMD_SAVE_CONFIG = 59;
- /* Connection status */
- private static final int CMD_CONNECTION_STATUS = 60;
-
- /* Supplicant commands after driver start*/
- /* Initiate a scan */
- private static final int CMD_START_SCAN = 71;
- /* Set scan mode. CONNECT_MODE or SCAN_ONLY_MODE */
- private static final int CMD_SET_SCAN_MODE = 72;
- /* Set scan type. SCAN_ACTIVE or SCAN_PASSIVE */
- private static final int CMD_SET_SCAN_TYPE = 73;
- /* Disconnect from a network */
- private static final int CMD_DISCONNECT = 74;
- /* Reconnect to a network */
- private static final int CMD_RECONNECT = 75;
- /* Reassociate to a network */
- private static final int CMD_REASSOCIATE = 76;
- /* Set power mode
- * POWER_MODE_ACTIVE
- * POWER_MODE_AUTO
- */
- private static final int CMD_SET_POWER_MODE = 77;
- /* Set bluetooth co-existence
- * BLUETOOTH_COEXISTENCE_MODE_ENABLED
- * BLUETOOTH_COEXISTENCE_MODE_DISABLED
- * BLUETOOTH_COEXISTENCE_MODE_SENSE
- */
- private static final int CMD_SET_BLUETOOTH_COEXISTENCE = 78;
- /* Enable/disable bluetooth scan mode
- * true(1)
- * false(0)
- */
- private static final int CMD_SET_BLUETOOTH_SCAN_MODE = 79;
- /* Set number of allowed channels */
- private static final int CMD_SET_NUM_ALLOWED_CHANNELS = 80;
- /* Request connectivity manager wake lock before driver stop */
- private static final int CMD_REQUEST_CM_WAKELOCK = 81;
- /* Enables RSSI poll */
- private static final int CMD_ENABLE_RSSI_POLL = 82;
- /* RSSI poll */
- private static final int CMD_RSSI_POLL = 83;
- /* Get current RSSI */
- private static final int CMD_GET_RSSI = 84;
- /* Get approx current RSSI */
- private static final int CMD_GET_RSSI_APPROX = 85;
- /* Get link speed on connection */
- private static final int CMD_GET_LINK_SPEED = 86;
- /* Radio mac address */
- private static final int CMD_GET_MAC_ADDR = 87;
- /* Set up packet filtering */
- private static final int CMD_START_PACKET_FILTERING = 88;
- /* Clear packet filter */
- private static final int CMD_STOP_PACKET_FILTERING = 89;
-
- /* Connectivity service commands */
- /* Bring down wifi connection */
- private static final int CM_CMD_TEARDOWN = 110;
- /* Reconnect to wifi */
- private static final int CM_CMD_RECONNECT = 111;
-
- /**
- * Interval in milliseconds between polling for connection
- * status items that are not sent via asynchronous events.
- * An example is RSSI (signal strength).
- */
- private static final int POLL_RSSI_INTERVAL_MSECS = 3000;
-
- private static final int CONNECT_MODE = 1;
- private static final int SCAN_ONLY_MODE = 2;
-
- private static final int SCAN_ACTIVE = 1;
- private static final int SCAN_PASSIVE = 2;
-
- /**
- * The maximum number of times we will retry a connection to an access point
- * for which we have failed in acquiring an IP address from DHCP. A value of
- * N means that we will make N+1 connection attempts in all.
- * <p>
- * See {@link Settings.Secure#WIFI_MAX_DHCP_RETRY_COUNT}. This is the default
- * value if a Settings value is not present.
- */
- private static final int DEFAULT_MAX_DHCP_RETRIES = 9;
-
- private static final int DRIVER_POWER_MODE_ACTIVE = 1;
- private static final int DRIVER_POWER_MODE_AUTO = 0;
-
- /* Default parent state */
- private HierarchicalState mDefaultState = new DefaultState();
- /* Temporary initial state */
- private HierarchicalState mInitialState = new InitialState();
- /* Unloading the driver */
- private HierarchicalState mDriverUnloadingState = new DriverUnloadingState();
- /* Loading the driver */
- private HierarchicalState mDriverUnloadedState = new DriverUnloadedState();
- /* Driver load/unload failed */
- private HierarchicalState mDriverFailedState = new DriverFailedState();
- /* Driver loading */
- private HierarchicalState mDriverLoadingState = new DriverLoadingState();
- /* Driver loaded */
- private HierarchicalState mDriverLoadedState = new DriverLoadedState();
- /* Driver loaded, waiting for supplicant to start */
- private HierarchicalState mWaitForSupState = new WaitForSupState();
-
- /* Driver loaded and supplicant ready */
- private HierarchicalState mDriverSupReadyState = new DriverSupReadyState();
- /* Driver start issued, waiting for completed event */
- private HierarchicalState mDriverStartingState = new DriverStartingState();
- /* Driver started */
- private HierarchicalState mDriverStartedState = new DriverStartedState();
- /* Driver stopping */
- private HierarchicalState mDriverStoppingState = new DriverStoppingState();
- /* Driver stopped */
- private HierarchicalState mDriverStoppedState = new DriverStoppedState();
- /* Scan for networks, no connection will be established */
- private HierarchicalState mScanModeState = new ScanModeState();
- /* Connecting to an access point */
- private HierarchicalState mConnectModeState = new ConnectModeState();
- /* Fetching IP after network connection (assoc+auth complete) */
- private HierarchicalState mConnectingState = new ConnectingState();
- /* Connected with IP addr */
- private HierarchicalState mConnectedState = new ConnectedState();
- /* disconnect issued, waiting for network disconnect confirmation */
- private HierarchicalState mDisconnectingState = new DisconnectingState();
- /* Network is not connected, supplicant assoc+auth is not complete */
- private HierarchicalState mDisconnectedState = new DisconnectedState();
-
- /* Soft Ap is running */
- private HierarchicalState mSoftApStartedState = new SoftApStartedState();
-
- /* Argument for Message object to indicate a synchronous call */
- private static final int SYNCHRONOUS_CALL = 1;
- private static final int ASYNCHRONOUS_CALL = 0;
-
-
- /**
- * One of {@link WifiManager#WIFI_STATE_DISABLED},
- * {@link WifiManager#WIFI_STATE_DISABLING},
- * {@link WifiManager#WIFI_STATE_ENABLED},
- * {@link WifiManager#WIFI_STATE_ENABLING},
- * {@link WifiManager#WIFI_STATE_UNKNOWN}
- *
- */
- private final AtomicInteger mWifiState = new AtomicInteger(WIFI_STATE_DISABLED);
-
- /**
- * One of {@link WifiManager#WIFI_AP_STATE_DISABLED},
- * {@link WifiManager#WIFI_AP_STATE_DISABLING},
- * {@link WifiManager#WIFI_AP_STATE_ENABLED},
- * {@link WifiManager#WIFI_AP_STATE_ENABLING},
- * {@link WifiManager#WIFI_AP_STATE_FAILED}
- *
- */
- private final AtomicInteger mWifiApState = new AtomicInteger(WIFI_AP_STATE_DISABLED);
-
- private final AtomicInteger mLastEnableUid = new AtomicInteger(Process.myUid());
- private final AtomicInteger mLastApEnableUid = new AtomicInteger(Process.myUid());
-
- private final IBatteryStats mBatteryStats;
+ private BroadcastReceiver mWifiStateReceiver;
+ private WifiManager mWifiManager;
public WifiStateTracker(Context context, Handler target) {
- super(NETWORKTYPE);
-
mCsHandler = target;
mContext = context;
mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, NETWORKTYPE, "");
- mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo"));
-
- IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
- nwService = INetworkManagementService.Stub.asInterface(b);
-
- mWifiMonitor = new WifiMonitor(this);
- mDhcpInfo = new DhcpInfo();
- mWifiInfo = new WifiInfo();
- mInterfaceName = SystemProperties.get("wifi.interface", "tiwlan0");
- mSupplicantStateTracker = new SupplicantStateTracker(context, getHandler());
-
- mBluetoothHeadset = new BluetoothHeadset(mContext, null);
mNetworkProperties = new NetworkProperties();
mNetworkInfo.setIsAvailable(false);
mNetworkProperties.clear();
- resetNotificationTimer();
setTeardownRequested(false);
- mLastBssid = null;
- mLastNetworkId = -1;
- mLastSignalLevel = -1;
-
- mScanResultCache = new LinkedHashMap<String, ScanResult>(
- SCAN_RESULT_CACHE_SIZE, 0.75f, true) {
- /*
- * Limit the cache size by SCAN_RESULT_CACHE_SIZE
- * elements
- */
- @Override
- public boolean removeEldestEntry(Map.Entry eldest) {
- return SCAN_RESULT_CACHE_SIZE < this.size();
- }
- };
-
- // Setting is in seconds
- NOTIFICATION_REPEAT_DELAY_MS = Settings.Secure.getInt(context.getContentResolver(),
- Settings.Secure.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY, 900) * 1000l;
- mNotificationEnabledSettingObserver = new NotificationEnabledSettingObserver(target);
- mNotificationEnabledSettingObserver.register();
-
- mSettingsObserver = new SettingsObserver(new Handler());
-
- PowerManager powerManager = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
- sWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
-
- addState(mDefaultState);
- addState(mInitialState, mDefaultState);
- addState(mDriverUnloadingState, mDefaultState);
- addState(mDriverUnloadedState, mDefaultState);
- addState(mDriverFailedState, mDriverUnloadedState);
- addState(mDriverLoadingState, mDefaultState);
- addState(mDriverLoadedState, mDefaultState);
- addState(mWaitForSupState, mDriverLoadedState);
- addState(mDriverSupReadyState, mDefaultState);
- addState(mDriverStartingState, mDriverSupReadyState);
- addState(mDriverStartedState, mDriverSupReadyState);
- addState(mScanModeState, mDriverStartedState);
- addState(mConnectModeState, mDriverStartedState);
- addState(mConnectingState, mConnectModeState);
- addState(mConnectedState, mConnectModeState);
- addState(mDisconnectingState, mConnectModeState);
- addState(mDisconnectedState, mConnectModeState);
- addState(mDriverStoppingState, mDriverSupReadyState);
- addState(mDriverStoppedState, mDriverSupReadyState);
- addState(mSoftApStartedState, mDefaultState);
-
- setInitialState(mInitialState);
-
- if (DBG) setDbg(true);
-
- //start the state machine
- start();
}
- /*********************************************************
- * NetworkStateTracker interface implementation
- ********************************************************/
-
public void setTeardownRequested(boolean isRequested) {
mTeardownRequested.set(isRequested);
}
@@ -544,11 +79,17 @@ public class WifiStateTracker extends HierarchicalStateMachine implements Networ
/**
* Begin monitoring wifi connectivity
- * @deprecated
- *
- * TODO: remove this from callers
*/
public void startMonitoring() {
+ mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
+ filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+ filter.addAction(WifiManager.CONFIG_CHANGED_ACTION);
+ filter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
+
+ mWifiStateReceiver = new WifiStateReceiver();
+ mContext.registerReceiver(mWifiStateReceiver, filter);
}
/**
@@ -556,7 +97,8 @@ public class WifiStateTracker extends HierarchicalStateMachine implements Networ
* TODO: do away with return value after making MobileDataStateTracker async
*/
public boolean teardown() {
- sendMessage(CM_CMD_TEARDOWN);
+ mTeardownRequested.set(true);
+ mWifiManager.stopWifi();
return true;
}
@@ -565,7 +107,8 @@ public class WifiStateTracker extends HierarchicalStateMachine implements Networ
* TODO: do away with return value after making MobileDataStateTracker async
*/
public boolean reconnect() {
- sendMessage(CM_CMD_RECONNECT);
+ mTeardownRequested.set(false);
+ mWifiManager.startWifi();
return true;
}
@@ -575,7 +118,7 @@ public class WifiStateTracker extends HierarchicalStateMachine implements Networ
* TODO: do away with return value after making MobileDataStateTracker async
*/
public boolean setRadio(boolean turnOn) {
- setWifiEnabled(turnOn);
+ mWifiManager.setWifiEnabled(turnOn);
return true;
}
@@ -626,21 +169,6 @@ public class WifiStateTracker extends HierarchicalStateMachine implements Networ
return -1;
}
- /* TODO: will go away.
- * Notifications are directly handled in WifiStateTracker at checkAndSetNotification()
- */
- public void interpretScanResultsAvailable() {
-
- }
-
- /**
- * Return the name of our WLAN network interface.
- * @return the name of our interface.
- */
- public String getInterfaceName() {
- return mInterfaceName;
- }
-
/**
* Check if private DNS route is set for the network
*/
@@ -698,3279 +226,23 @@ public class WifiStateTracker extends HierarchicalStateMachine implements Networ
return "net.tcp.buffersize.wifi";
}
-
- /*********************************************************
- * Methods exposed for public use
- ********************************************************/
-
- /**
- * TODO: doc
- */
- public boolean pingSupplicant() {
- return sendSyncMessage(CMD_PING_SUPPLICANT).boolValue;
- }
-
- /**
- * TODO: doc
- */
- public boolean startScan(boolean forceActive) {
- return sendSyncMessage(obtainMessage(CMD_START_SCAN, forceActive ?
- SCAN_ACTIVE : SCAN_PASSIVE, 0)).boolValue;
- }
-
- /**
- * TODO: doc
- */
- public void setWifiEnabled(boolean enable) {
- mLastEnableUid.set(Binder.getCallingUid());
- if (enable) {
- /* Argument is the state that is entered prior to load */
- sendMessage(obtainMessage(CMD_LOAD_DRIVER, WIFI_STATE_ENABLING, 0));
- sendMessage(CMD_START_SUPPLICANT);
- } else {
- sendMessage(CMD_STOP_SUPPLICANT);
- /* Argument is the state that is entered upon success */
- sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_STATE_DISABLED, 0));
- }
- }
-
- /**
- * TODO: doc
- */
- public void setWifiApEnabled(WifiConfiguration wifiConfig, boolean enable) {
- mLastApEnableUid.set(Binder.getCallingUid());
- if (enable) {
- /* Argument is the state that is entered prior to load */
- sendMessage(obtainMessage(CMD_LOAD_DRIVER, WIFI_AP_STATE_ENABLING, 0));
- sendMessage(obtainMessage(CMD_START_AP, wifiConfig));
- } else {
- sendMessage(CMD_STOP_AP);
- /* Argument is the state that is entered upon success */
- sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_AP_STATE_DISABLED, 0));
- }
- }
-
- /**
- * TODO: doc
- */
- public int getWifiState() {
- return mWifiState.get();
- }
-
- /**
- * TODO: doc
- */
- public String getWifiStateByName() {
- switch (mWifiState.get()) {
- case WIFI_STATE_DISABLING:
- return "disabling";
- case WIFI_STATE_DISABLED:
- return "disabled";
- case WIFI_STATE_ENABLING:
- return "enabling";
- case WIFI_STATE_ENABLED:
- return "enabled";
- case WIFI_STATE_UNKNOWN:
- return "unknown state";
- default:
- return "[invalid state]";
- }
- }
-
- /**
- * TODO: doc
- */
- public int getWifiApState() {
- return mWifiApState.get();
- }
-
- /**
- * TODO: doc
- */
- public String getWifiApStateByName() {
- switch (mWifiApState.get()) {
- case WIFI_AP_STATE_DISABLING:
- return "disabling";
- case WIFI_AP_STATE_DISABLED:
- return "disabled";
- case WIFI_AP_STATE_ENABLING:
- return "enabling";
- case WIFI_AP_STATE_ENABLED:
- return "enabled";
- case WIFI_AP_STATE_FAILED:
- return "failed";
- default:
- return "[invalid state]";
- }
- }
-
- /**
- * Get status information for the current connection, if any.
- * @return a {@link WifiInfo} object containing information about the current connection
- *
- */
- public WifiInfo requestConnectionInfo() {
- return mWifiInfo;
- }
-
- public DhcpInfo getDhcpInfo() {
- return mDhcpInfo;
- }
-
- /**
- * TODO: doc
- */
- public void startWifi(boolean enable) {
- if (enable) {
- sendMessage(CMD_START_DRIVER);
- } else {
- sendMessage(CMD_STOP_DRIVER);
- }
- }
-
- /**
- * TODO: doc
- */
- public void disconnectAndStop() {
- sendMessage(CMD_DISCONNECT);
- sendMessage(CMD_STOP_DRIVER);
- }
-
- /**
- * TODO: doc
- */
- public void setScanOnlyMode(boolean enable) {
- if (enable) {
- sendMessage(obtainMessage(CMD_SET_SCAN_MODE, SCAN_ONLY_MODE, 0));
- } else {
- sendMessage(obtainMessage(CMD_SET_SCAN_MODE, CONNECT_MODE, 0));
- }
- }
-
- /**
- * TODO: doc
- */
- public void setScanType(boolean active) {
- if (active) {
- sendMessage(obtainMessage(CMD_SET_SCAN_TYPE, SCAN_ACTIVE, 0));
- } else {
- sendMessage(obtainMessage(CMD_SET_SCAN_TYPE, SCAN_PASSIVE, 0));
- }
- }
-
- /**
- * TODO: doc
- */
- public List<ScanResult> getScanResultsList() {
- return mScanResults;
- }
-
- /**
- * Disconnect from Access Point
- */
- public boolean disconnectCommand() {
- return sendSyncMessage(CMD_DISCONNECT).boolValue;
- }
-
- /**
- * Initiate a reconnection to AP
- */
- public boolean reconnectCommand() {
- return sendSyncMessage(CMD_RECONNECT).boolValue;
- }
-
- /**
- * Initiate a re-association to AP
- */
- public boolean reassociateCommand() {
- return sendSyncMessage(CMD_REASSOCIATE).boolValue;
- }
-
- /**
- * Add a network synchronously
- *
- * @return network id of the new network
- */
- public int addOrUpdateNetwork(WifiConfiguration config) {
- return sendSyncMessage(CMD_ADD_OR_UPDATE_NETWORK, config).intValue;
- }
-
- public List<WifiConfiguration> getConfiguredNetworks() {
- return sendSyncMessage(CMD_GET_NETWORK_CONFIG).configList;
- }
-
- /**
- * Delete a network
- *
- * @param networkId id of the network to be removed
- */
- public boolean removeNetwork(int networkId) {
- return sendSyncMessage(obtainMessage(CMD_REMOVE_NETWORK, networkId, 0)).boolValue;
- }
-
- private class EnableNetParams {
- private int netId;
- private boolean disableOthers;
- EnableNetParams(int n, boolean b) {
- netId = n;
- disableOthers = b;
- }
- }
- /**
- * Enable a network
- *
- * @param netId network id of the network
- * @param disableOthers true, if all other networks have to be disabled
- * @return {@code true} if the operation succeeds, {@code false} otherwise
- */
- public boolean enableNetwork(int netId, boolean disableOthers) {
- return sendSyncMessage(CMD_ENABLE_NETWORK,
- new EnableNetParams(netId, disableOthers)).boolValue;
- }
-
- /**
- * Disable a network
- *
- * @param netId network id of the network
- * @return {@code true} if the operation succeeds, {@code false} otherwise
- */
- public boolean disableNetwork(int netId) {
- return sendSyncMessage(obtainMessage(CMD_DISABLE_NETWORK, netId, 0)).boolValue;
- }
-
- /**
- * Blacklist a BSSID. This will avoid the AP if there are
- * alternate APs to connect
- *
- * @param bssid BSSID of the network
- */
- public void addToBlacklist(String bssid) {
- sendMessage(obtainMessage(CMD_BLACKLIST_NETWORK, bssid));
- }
-
- /**
- * Clear the blacklist list
- *
- */
- public void clearBlacklist() {
- sendMessage(obtainMessage(CMD_CLEAR_BLACKLIST));
- }
-
- /**
- * Get detailed status of the connection
- *
- * @return Example status result
- * bssid=aa:bb:cc:dd:ee:ff
- * ssid=TestNet
- * id=3
- * pairwise_cipher=NONE
- * group_cipher=NONE
- * key_mgmt=NONE
- * wpa_state=COMPLETED
- * ip_address=X.X.X.X
- */
- public String status() {
- return sendSyncMessage(CMD_CONNECTION_STATUS).stringValue;
- }
-
- public void enableRssiPolling(boolean enabled) {
- sendMessage(obtainMessage(CMD_ENABLE_RSSI_POLL, enabled ? 1 : 0, 0));
- }
- /**
- * Get RSSI to currently connected network
- *
- * @return RSSI value, -1 on failure
- */
- public int getRssi() {
- return sendSyncMessage(CMD_GET_RSSI).intValue;
- }
-
- /**
- * Get approx RSSI to currently connected network
- *
- * @return RSSI value, -1 on failure
- */
- public int getRssiApprox() {
- return sendSyncMessage(CMD_GET_RSSI_APPROX).intValue;
- }
-
- /**
- * Get link speed to currently connected network
- *
- * @return link speed, -1 on failure
- */
- public int getLinkSpeed() {
- return sendSyncMessage(CMD_GET_LINK_SPEED).intValue;
- }
-
- /**
- * Get MAC address of radio
- *
- * @return MAC address, null on failure
- */
- public String getMacAddress() {
- return sendSyncMessage(CMD_GET_MAC_ADDR).stringValue;
- }
-
- /**
- * Start packet filtering
- */
- public void startPacketFiltering() {
- sendMessage(CMD_START_PACKET_FILTERING);
- }
-
- /**
- * Stop packet filtering
- */
- public void stopPacketFiltering() {
- sendMessage(CMD_STOP_PACKET_FILTERING);
- }
-
- /**
- * Set power mode
- * @param mode
- * DRIVER_POWER_MODE_AUTO
- * DRIVER_POWER_MODE_ACTIVE
- */
- public void setPowerMode(int mode) {
- sendMessage(obtainMessage(CMD_SET_POWER_MODE, mode, 0));
- }
-
- /**
- * Set the number of allowed radio frequency channels from the system
- * setting value, if any.
- */
- public void setNumAllowedChannels() {
- try {
- setNumAllowedChannels(
- Settings.Secure.getInt(mContext.getContentResolver(),
- Settings.Secure.WIFI_NUM_ALLOWED_CHANNELS));
- } catch (Settings.SettingNotFoundException e) {
- if (mNumAllowedChannels != 0) {
- setNumAllowedChannels(mNumAllowedChannels);
- }
- // otherwise, use the driver default
- }
- }
-
- /**
- * Set the number of radio frequency channels that are allowed to be used
- * in the current regulatory domain.
- * @param numChannels the number of allowed channels. Must be greater than 0
- * and less than or equal to 16.
- */
- public void setNumAllowedChannels(int numChannels) {
- sendMessage(obtainMessage(CMD_SET_NUM_ALLOWED_CHANNELS, numChannels, 0));
- }
-
- /**
- * Get number of allowed channels
- *
- * @return channel count, -1 on failure
- *
- * TODO: this is not a public API and needs to be removed in favor
- * of asynchronous reporting. unused for now.
- */
- public int getNumAllowedChannels() {
- return -1;
- }
-
- /**
- * Set bluetooth coex mode:
- *
- * @param mode
- * BLUETOOTH_COEXISTENCE_MODE_ENABLED
- * BLUETOOTH_COEXISTENCE_MODE_DISABLED
- * BLUETOOTH_COEXISTENCE_MODE_SENSE
- */
- public void setBluetoothCoexistenceMode(int mode) {
- sendMessage(obtainMessage(CMD_SET_BLUETOOTH_COEXISTENCE, mode, 0));
- }
-
- /**
- * Enable or disable Bluetooth coexistence scan mode. When this mode is on,
- * some of the low-level scan parameters used by the driver are changed to
- * reduce interference with A2DP streaming.
- *
- * @param isBluetoothPlaying whether to enable or disable this mode
- */
- public void setBluetoothScanMode(boolean isBluetoothPlaying) {
- sendMessage(obtainMessage(CMD_SET_BLUETOOTH_SCAN_MODE, isBluetoothPlaying ? 1 : 0, 0));
- }
-
- /**
- * Save configuration on supplicant
- *
- * @return {@code true} if the operation succeeds, {@code false} otherwise
- *
- * TODO: deprecate this
- */
- public boolean saveConfig() {
- return sendSyncMessage(CMD_SAVE_CONFIG).boolValue;
- }
-
- /**
- * TODO: doc
- */
- public void requestCmWakeLock() {
- sendMessage(CMD_REQUEST_CM_WAKELOCK);
- }
-
- /*********************************************************
- * Internal private functions
- ********************************************************/
-
- class SyncReturn {
- boolean boolValue;
- int intValue;
- String stringValue;
- Object objValue;
- List<WifiConfiguration> configList;
- }
-
- class SyncParams {
- Object mParameter;
- SyncReturn mSyncReturn;
- SyncParams() {
- mSyncReturn = new SyncReturn();
- }
- SyncParams(Object p) {
- mParameter = p;
- mSyncReturn = new SyncReturn();
- }
- }
-
- /**
- * message.arg2 is reserved to indicate synchronized
- * message.obj is used to store SyncParams
- */
- private SyncReturn syncedSend(Message msg) {
- SyncParams syncParams = (SyncParams) msg.obj;
- msg.arg2 = SYNCHRONOUS_CALL;
- synchronized(syncParams) {
- if (DBG) Log.d(TAG, "syncedSend " + msg);
- sendMessage(msg);
- try {
- syncParams.wait();
- } catch (InterruptedException e) {
- Log.e(TAG, "sendSyncMessage: unexpected interruption of wait()");
- return null;
- }
- }
- return syncParams.mSyncReturn;
- }
-
- private SyncReturn sendSyncMessage(Message msg) {
- SyncParams syncParams = new SyncParams();
- msg.obj = syncParams;
- return syncedSend(msg);
- }
-
- private SyncReturn sendSyncMessage(int what, Object param) {
- SyncParams syncParams = new SyncParams(param);
- Message msg = obtainMessage(what, syncParams);
- return syncedSend(msg);
- }
-
-
- private SyncReturn sendSyncMessage(int what) {
- return sendSyncMessage(obtainMessage(what));
- }
-
- private void notifyOnMsgObject(Message msg) {
- SyncParams syncParams = (SyncParams) msg.obj;
- if (syncParams != null) {
- synchronized(syncParams) {
- if (DBG) Log.d(TAG, "notifyOnMsgObject " + msg);
- syncParams.notify();
- }
- }
- else {
- Log.e(TAG, "Error! syncParams in notifyOnMsgObject is null");
- }
- }
-
- private void setWifiState(int wifiState) {
- final int previousWifiState = mWifiState.get();
-
- try {
- if (wifiState == WIFI_STATE_ENABLED) {
- mBatteryStats.noteWifiOn(mLastEnableUid.get());
- } else if (wifiState == WIFI_STATE_DISABLED) {
- mBatteryStats.noteWifiOff(mLastEnableUid.get());
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to note battery stats in wifi");
- }
-
- mWifiState.set(wifiState);
-
- if (DBG) Log.d(TAG, "setWifiState: " + getWifiStateByName());
-
- final Intent intent = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- intent.putExtra(WifiManager.EXTRA_WIFI_STATE, wifiState);
- intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_STATE, previousWifiState);
- mContext.sendStickyBroadcast(intent);
- }
-
- private void setWifiApState(int wifiApState) {
- final int previousWifiApState = mWifiApState.get();
-
- try {
- if (wifiApState == WIFI_AP_STATE_ENABLED) {
- mBatteryStats.noteWifiOn(mLastApEnableUid.get());
- } else if (wifiApState == WIFI_AP_STATE_DISABLED) {
- mBatteryStats.noteWifiOff(mLastApEnableUid.get());
- }
- } catch (RemoteException e) {
- Log.d(TAG, "Failed to note battery stats in wifi");
- }
-
- // Update state
- mWifiApState.set(wifiApState);
-
- if (DBG) Log.d(TAG, "setWifiApState: " + getWifiApStateByName());
-
- // Broadcast
- final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- intent.putExtra(WifiManager.EXTRA_WIFI_AP_STATE, wifiApState);
- intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_AP_STATE, previousWifiApState);
- mContext.sendStickyBroadcast(intent);
- }
-
- /**
- * Parse the scan result line passed to us by wpa_supplicant (helper).
- * @param line the line to parse
- * @return the {@link ScanResult} object
- */
- private ScanResult parseScanResult(String line) {
- ScanResult scanResult = null;
- if (line != null) {
- /*
- * Cache implementation (LinkedHashMap) is not synchronized, thus,
- * must synchronized here!
- */
- synchronized (mScanResultCache) {
- String[] result = scanResultPattern.split(line);
- if (3 <= result.length && result.length <= 5) {
- String bssid = result[0];
- // bssid | frequency | level | flags | ssid
- int frequency;
- int level;
- try {
- frequency = Integer.parseInt(result[1]);
- level = Integer.parseInt(result[2]);
- /* some implementations avoid negative values by adding 256
- * so we need to adjust for that here.
- */
- if (level > 0) level -= 256;
- } catch (NumberFormatException e) {
- frequency = 0;
- level = 0;
- }
-
- /*
- * The formatting of the results returned by
- * wpa_supplicant is intended to make the fields
- * line up nicely when printed,
- * not to make them easy to parse. So we have to
- * apply some heuristics to figure out which field
- * is the SSID and which field is the flags.
- */
- String ssid;
- String flags;
- if (result.length == 4) {
- if (result[3].charAt(0) == '[') {
- flags = result[3];
- ssid = "";
- } else {
- flags = "";
- ssid = result[3];
- }
- } else if (result.length == 5) {
- flags = result[3];
- ssid = result[4];
- } else {
- // Here, we must have 3 fields: no flags and ssid
- // set
- flags = "";
- ssid = "";
- }
-
- // bssid + ssid is the hash key
- String key = bssid + ssid;
- scanResult = mScanResultCache.get(key);
- if (scanResult != null) {
- scanResult.level = level;
- scanResult.SSID = ssid;
- scanResult.capabilities = flags;
- scanResult.frequency = frequency;
- } else {
- // Do not add scan results that have no SSID set
- if (0 < ssid.trim().length()) {
- scanResult =
- new ScanResult(
- ssid, bssid, flags, level, frequency);
- mScanResultCache.put(key, scanResult);
- }
- }
- } else {
- Log.w(TAG, "Misformatted scan result text with " +
- result.length + " fields: " + line);
- }
- }
- }
-
- return scanResult;
- }
-
- /**
- * scanResults input format
- * 00:bb:cc:dd:cc:ee 2427 166 [WPA-EAP-TKIP][WPA2-EAP-CCMP] Net1
- * 00:bb:cc:dd:cc:ff 2412 165 [WPA-EAP-TKIP][WPA2-EAP-CCMP] Net2
- */
- private void setScanResults(String scanResults) {
- if (scanResults == null) {
- return;
- }
-
- List<ScanResult> scanList = new ArrayList<ScanResult>();
-
- int lineCount = 0;
-
- int scanResultsLen = scanResults.length();
- // Parse the result string, keeping in mind that the last line does
- // not end with a newline.
- for (int lineBeg = 0, lineEnd = 0; lineEnd <= scanResultsLen; ++lineEnd) {
- if (lineEnd == scanResultsLen || scanResults.charAt(lineEnd) == '\n') {
- ++lineCount;
-
- if (lineCount == 1) {
- lineBeg = lineEnd + 1;
- continue;
- }
- if (lineEnd > lineBeg) {
- String line = scanResults.substring(lineBeg, lineEnd);
- ScanResult scanResult = parseScanResult(line);
- if (scanResult != null) {
- scanList.add(scanResult);
- } else {
- Log.w(TAG, "misformatted scan result for: " + line);
- }
- }
- lineBeg = lineEnd + 1;
- }
- }
-
- mScanResults = scanList;
- }
-
- private void checkAndSetNotification() {
- // If we shouldn't place a notification on available networks, then
- // don't bother doing any of the following
- if (!mNotificationEnabled) return;
-
- State state = mNetworkInfo.getState();
- if ((state == NetworkInfo.State.DISCONNECTED)
- || (state == NetworkInfo.State.UNKNOWN)) {
- // Look for an open network
- List<ScanResult> scanResults = mScanResults;
- if (scanResults != null) {
- int numOpenNetworks = 0;
- for (int i = scanResults.size() - 1; i >= 0; i--) {
- ScanResult scanResult = scanResults.get(i);
-
- if (TextUtils.isEmpty(scanResult.capabilities)) {
- numOpenNetworks++;
- }
- }
-
- if (numOpenNetworks > 0) {
- if (++mNumScansSinceNetworkStateChange >= NUM_SCANS_BEFORE_ACTUALLY_SCANNING) {
- /*
- * We've scanned continuously at least
- * NUM_SCANS_BEFORE_NOTIFICATION times. The user
- * probably does not have a remembered network in range,
- * since otherwise supplicant would have tried to
- * associate and thus resetting this counter.
- */
- setNotificationVisible(true, numOpenNetworks, false, 0);
- }
- return;
- }
- }
- }
-
- // No open networks in range, remove the notification
- setNotificationVisible(false, 0, false, 0);
- }
-
- /**
- * Display or don't display a notification that there are open Wi-Fi networks.
- * @param visible {@code true} if notification should be visible, {@code false} otherwise
- * @param numNetworks the number networks seen
- * @param force {@code true} to force notification to be shown/not-shown,
- * even if it is already shown/not-shown.
- * @param delay time in milliseconds after which the notification should be made
- * visible or invisible.
- */
- private void setNotificationVisible(boolean visible, int numNetworks, boolean force,
- int delay) {
-
- // Since we use auto cancel on the notification, when the
- // mNetworksAvailableNotificationShown is true, the notification may
- // have actually been canceled. However, when it is false we know
- // for sure that it is not being shown (it will not be shown any other
- // place than here)
-
- // If it should be hidden and it is already hidden, then noop
- if (!visible && !mNotificationShown && !force) {
- return;
- }
-
- Message message;
- if (visible) {
-
- // Not enough time has passed to show the notification again
- if (System.currentTimeMillis() < mNotificationRepeatTime) {
- return;
- }
-
- if (mNotification == null) {
- // Cache the Notification mainly so we can remove the
- // EVENT_NOTIFICATION_CHANGED message with this Notification from
- // the queue later
- mNotification = new Notification();
- mNotification.when = 0;
- mNotification.icon = ICON_NETWORKS_AVAILABLE;
- mNotification.flags = Notification.FLAG_AUTO_CANCEL;
- mNotification.contentIntent = PendingIntent.getActivity(mContext, 0,
- new Intent(WifiManager.ACTION_PICK_WIFI_NETWORK), 0);
- }
-
- CharSequence title = mContext.getResources().getQuantityText(
- com.android.internal.R.plurals.wifi_available, numNetworks);
- CharSequence details = mContext.getResources().getQuantityText(
- com.android.internal.R.plurals.wifi_available_detailed, numNetworks);
- mNotification.tickerText = title;
- mNotification.setLatestEventInfo(mContext, title, details, mNotification.contentIntent);
-
- mNotificationRepeatTime = System.currentTimeMillis() + NOTIFICATION_REPEAT_DELAY_MS;
-
- message = mCsHandler.obtainMessage(EVENT_NOTIFICATION_CHANGED, 1,
- ICON_NETWORKS_AVAILABLE, mNotification);
-
- } else {
-
- // Remove any pending messages to show the notification
- mCsHandler.removeMessages(EVENT_NOTIFICATION_CHANGED, mNotification);
-
- message = mCsHandler.obtainMessage(EVENT_NOTIFICATION_CHANGED, 0,
- ICON_NETWORKS_AVAILABLE);
- }
-
- mCsHandler.sendMessageDelayed(message, delay);
-
- mNotificationShown = visible;
- }
-
- private void configureNetworkProperties() {
- try {
- mNetworkProperties.setInterface(NetworkInterface.getByName(mInterfaceName));
- } catch (SocketException e) {
- Log.e(TAG, "SocketException creating NetworkInterface from " + mInterfaceName +
- ". e=" + e);
- return;
- } catch (NullPointerException e) {
- Log.e(TAG, "NPE creating NetworkInterface. e=" + e);
- return;
- }
- // TODO - fix this for v6
- try {
- mNetworkProperties.addAddress(InetAddress.getByAddress(
- NetworkUtils.v4IntToArray(mDhcpInfo.ipAddress)));
- } catch (UnknownHostException e) {
- Log.e(TAG, "Exception setting IpAddress using " + mDhcpInfo + ", e=" + e);
- }
-
- try {
- mNetworkProperties.setGateway(InetAddress.getByAddress(NetworkUtils.v4IntToArray(
- mDhcpInfo.gateway)));
- } catch (UnknownHostException e) {
- Log.e(TAG, "Exception setting Gateway using " + mDhcpInfo + ", e=" + e);
- }
-
- try {
- mNetworkProperties.addDns(InetAddress.getByAddress(
- NetworkUtils.v4IntToArray(mDhcpInfo.dns1)));
- } catch (UnknownHostException e) {
- Log.e(TAG, "Exception setting Dns1 using " + mDhcpInfo + ", e=" + e);
- }
- try {
- mNetworkProperties.addDns(InetAddress.getByAddress(
- NetworkUtils.v4IntToArray(mDhcpInfo.dns2)));
-
- } catch (UnknownHostException e) {
- Log.e(TAG, "Exception setting Dns2 using " + mDhcpInfo + ", e=" + e);
- }
- // TODO - add proxy info
- }
-
-
- private void checkUseStaticIp() {
- mUseStaticIp = false;
- final ContentResolver cr = mContext.getContentResolver();
- try {
- if (Settings.System.getInt(cr, Settings.System.WIFI_USE_STATIC_IP) == 0) {
- return;
- }
- } catch (Settings.SettingNotFoundException e) {
- return;
- }
-
- try {
- String addr = Settings.System.getString(cr, Settings.System.WIFI_STATIC_IP);
- if (addr != null) {
- mDhcpInfo.ipAddress = stringToIpAddr(addr);
- } else {
- return;
- }
- addr = Settings.System.getString(cr, Settings.System.WIFI_STATIC_GATEWAY);
- if (addr != null) {
- mDhcpInfo.gateway = stringToIpAddr(addr);
- } else {
- return;
- }
- addr = Settings.System.getString(cr, Settings.System.WIFI_STATIC_NETMASK);
- if (addr != null) {
- mDhcpInfo.netmask = stringToIpAddr(addr);
- } else {
- return;
- }
- addr = Settings.System.getString(cr, Settings.System.WIFI_STATIC_DNS1);
- if (addr != null) {
- mDhcpInfo.dns1 = stringToIpAddr(addr);
- } else {
- return;
- }
- addr = Settings.System.getString(cr, Settings.System.WIFI_STATIC_DNS2);
- if (addr != null) {
- mDhcpInfo.dns2 = stringToIpAddr(addr);
- } else {
- mDhcpInfo.dns2 = 0;
- }
- } catch (UnknownHostException e) {
- return;
- }
- mUseStaticIp = true;
- }
-
- private static int stringToIpAddr(String addrString) throws UnknownHostException {
- try {
- String[] parts = addrString.split("\\.");
- if (parts.length != 4) {
- throw new UnknownHostException(addrString);
- }
-
- int a = Integer.parseInt(parts[0]) ;
- int b = Integer.parseInt(parts[1]) << 8;
- int c = Integer.parseInt(parts[2]) << 16;
- int d = Integer.parseInt(parts[3]) << 24;
-
- return a | b | c | d;
- } catch (NumberFormatException ex) {
- throw new UnknownHostException(addrString);
- }
- }
-
- private int getMaxDhcpRetries() {
- return Settings.Secure.getInt(mContext.getContentResolver(),
- Settings.Secure.WIFI_MAX_DHCP_RETRY_COUNT,
- DEFAULT_MAX_DHCP_RETRIES);
- }
-
- private class SettingsObserver extends ContentObserver {
- public SettingsObserver(Handler handler) {
- super(handler);
- ContentResolver cr = mContext.getContentResolver();
- cr.registerContentObserver(Settings.System.getUriFor(
- Settings.System.WIFI_USE_STATIC_IP), false, this);
- cr.registerContentObserver(Settings.System.getUriFor(
- Settings.System.WIFI_STATIC_IP), false, this);
- cr.registerContentObserver(Settings.System.getUriFor(
- Settings.System.WIFI_STATIC_GATEWAY), false, this);
- cr.registerContentObserver(Settings.System.getUriFor(
- Settings.System.WIFI_STATIC_NETMASK), false, this);
- cr.registerContentObserver(Settings.System.getUriFor(
- Settings.System.WIFI_STATIC_DNS1), false, this);
- cr.registerContentObserver(Settings.System.getUriFor(
- Settings.System.WIFI_STATIC_DNS2), false, this);
- }
-
+ private class WifiStateReceiver extends BroadcastReceiver {
@Override
- public void onChange(boolean selfChange) {
- super.onChange(selfChange);
-
- boolean wasStaticIp = mUseStaticIp;
- int oIp, oGw, oMsk, oDns1, oDns2;
- oIp = oGw = oMsk = oDns1 = oDns2 = 0;
- if (wasStaticIp) {
- oIp = mDhcpInfo.ipAddress;
- oGw = mDhcpInfo.gateway;
- oMsk = mDhcpInfo.netmask;
- oDns1 = mDhcpInfo.dns1;
- oDns2 = mDhcpInfo.dns2;
- }
- checkUseStaticIp();
-
- if (mWifiInfo.getSupplicantState() == SupplicantState.UNINITIALIZED) {
- return;
- }
-
- boolean changed =
- (wasStaticIp != mUseStaticIp) ||
- (wasStaticIp && (
- oIp != mDhcpInfo.ipAddress ||
- oGw != mDhcpInfo.gateway ||
- oMsk != mDhcpInfo.netmask ||
- oDns1 != mDhcpInfo.dns1 ||
- oDns2 != mDhcpInfo.dns2));
-
- if (changed) {
- sendMessage(CMD_RECONFIGURE_IP);
- if (mUseStaticIp) {
- mCsHandler.sendEmptyMessage(EVENT_CONFIGURATION_CHANGED);
- }
+ public void onReceive(Context context, Intent intent) {
+ if (intent.getAction().equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
+ mNetworkInfo = (NetworkInfo) intent.getParcelableExtra(
+ WifiManager.EXTRA_NETWORK_INFO);
+ mNetworkProperties = (NetworkProperties) intent.getParcelableExtra(
+ WifiManager.EXTRA_NETWORK_PROPERTIES);
+ Message msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
+ msg.sendToTarget();
+ } else if (intent.getAction().equals(WifiManager.CONFIG_CHANGED_ACTION)) {
+ mNetworkProperties = (NetworkProperties) intent.getParcelableExtra(
+ WifiManager.EXTRA_NETWORK_PROPERTIES);
+ Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo);
+ msg.sendToTarget();
}
}
}
-
- /**
- * Clears variables related to tracking whether a notification has been
- * shown recently.
- * <p>
- * After calling this method, the timer that prevents notifications from
- * being shown too often will be cleared.
- */
- private void resetNotificationTimer() {
- mNotificationRepeatTime = 0;
- mNumScansSinceNetworkStateChange = 0;
- }
-
-
- /**
- * Whether to disable coexistence mode while obtaining IP address. This
- * logic will return true only if the current bluetooth
- * headset/handsfree state is disconnected. This means if it is in an
- * error state, we will NOT disable coexistence mode to err on the side
- * of safety.
- *
- * @return Whether to disable coexistence mode.
- */
- private boolean shouldDisableCoexistenceMode() {
- int state = mBluetoothHeadset.getState(mBluetoothHeadset.getCurrentHeadset());
- return state == BluetoothHeadset.STATE_DISCONNECTED;
- }
-
- private void checkIsBluetoothPlaying() {
- boolean isBluetoothPlaying = false;
- Set<BluetoothDevice> connected = mBluetoothA2dp.getConnectedSinks();
-
- for (BluetoothDevice device : connected) {
- if (mBluetoothA2dp.getSinkState(device) == BluetoothA2dp.STATE_PLAYING) {
- isBluetoothPlaying = true;
- break;
- }
- }
- setBluetoothScanMode(isBluetoothPlaying);
- }
-
- private void sendScanResultsAvailableBroadcast() {
- if (!ActivityManagerNative.isSystemReady()) return;
-
- mContext.sendBroadcast(new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
- }
-
- private void sendRssiChangeBroadcast(final int newRssi) {
- if (!ActivityManagerNative.isSystemReady()) return;
-
- Intent intent = new Intent(WifiManager.RSSI_CHANGED_ACTION);
- intent.putExtra(WifiManager.EXTRA_NEW_RSSI, newRssi);
- mContext.sendBroadcast(intent);
- }
-
- private void sendNetworkStateChangeBroadcast(String bssid) {
- Intent intent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
- | Intent.FLAG_RECEIVER_REPLACE_PENDING);
- intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, mNetworkInfo);
- if (bssid != null)
- intent.putExtra(WifiManager.EXTRA_BSSID, bssid);
- mContext.sendStickyBroadcast(intent);
- }
-
- private void sendSupplicantStateChangedBroadcast(StateChangeResult sc, boolean failedAuth) {
- Intent intent = new Intent(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
- | Intent.FLAG_RECEIVER_REPLACE_PENDING);
- intent.putExtra(WifiManager.EXTRA_NEW_STATE, (Parcelable)sc.state);
- if (failedAuth) {
- intent.putExtra(
- WifiManager.EXTRA_SUPPLICANT_ERROR,
- WifiManager.ERROR_AUTHENTICATING);
- }
- mContext.sendStickyBroadcast(intent);
- }
-
- private void sendSupplicantConnectionChangedBroadcast(boolean connected) {
- if (!ActivityManagerNative.isSystemReady()) return;
-
- Intent intent = new Intent(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
- intent.putExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, connected);
- mContext.sendBroadcast(intent);
- }
-
- /**
- * Record the detailed state of a network, and if it is a
- * change from the previous state, send a notification to
- * any listeners.
- * @param state the new @{code DetailedState}
- */
- private void setDetailedState(NetworkInfo.DetailedState state) {
- Log.d(TAG, "setDetailed state, old ="
- + mNetworkInfo.getDetailedState() + " and new state=" + state);
- if (state != mNetworkInfo.getDetailedState()) {
- mNetworkInfo.setDetailedState(state, null, null);
- Message msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
- msg.sendToTarget();
- }
- }
-
- private static String removeDoubleQuotes(String string) {
- if (string.length() <= 2) return "";
- return string.substring(1, string.length() - 1);
- }
-
- private static String convertToQuotedString(String string) {
- return "\"" + string + "\"";
- }
-
- private static String makeString(BitSet set, String[] strings) {
- StringBuffer buf = new StringBuffer();
- int nextSetBit = -1;
-
- /* Make sure all set bits are in [0, strings.length) to avoid
- * going out of bounds on strings. (Shouldn't happen, but...) */
- set = set.get(0, strings.length);
-
- while ((nextSetBit = set.nextSetBit(nextSetBit + 1)) != -1) {
- buf.append(strings[nextSetBit].replace('_', '-')).append(' ');
- }
-
- // remove trailing space
- if (set.cardinality() > 0) {
- buf.setLength(buf.length() - 1);
- }
-
- return buf.toString();
- }
-
- private static int lookupString(String string, String[] strings) {
- int size = strings.length;
-
- string = string.replace('-', '_');
-
- for (int i = 0; i < size; i++)
- if (string.equals(strings[i]))
- return i;
-
- // if we ever get here, we should probably add the
- // value to WifiConfiguration to reflect that it's
- // supported by the WPA supplicant
- Log.w(TAG, "Failed to look-up a string: " + string);
-
- return -1;
- }
-
- private int addOrUpdateNetworkNative(WifiConfiguration config) {
- /*
- * If the supplied networkId is -1, we create a new empty
- * network configuration. Otherwise, the networkId should
- * refer to an existing configuration.
- */
- int netId = config.networkId;
- boolean newNetwork = netId == -1;
- // networkId of -1 means we want to create a new network
-
- if (newNetwork) {
- netId = WifiNative.addNetworkCommand();
- if (netId < 0) {
- Log.e(TAG, "Failed to add a network!");
- return -1;
- }
- }
-
- setVariables: {
-
- if (config.SSID != null &&
- !WifiNative.setNetworkVariableCommand(
- netId,
- WifiConfiguration.ssidVarName,
- config.SSID)) {
- Log.d(TAG, "failed to set SSID: "+config.SSID);
- break setVariables;
- }
-
- if (config.BSSID != null &&
- !WifiNative.setNetworkVariableCommand(
- netId,
- WifiConfiguration.bssidVarName,
- config.BSSID)) {
- Log.d(TAG, "failed to set BSSID: "+config.BSSID);
- break setVariables;
- }
-
- String allowedKeyManagementString =
- makeString(config.allowedKeyManagement, WifiConfiguration.KeyMgmt.strings);
- if (config.allowedKeyManagement.cardinality() != 0 &&
- !WifiNative.setNetworkVariableCommand(
- netId,
- WifiConfiguration.KeyMgmt.varName,
- allowedKeyManagementString)) {
- Log.d(TAG, "failed to set key_mgmt: "+
- allowedKeyManagementString);
- break setVariables;
- }
-
- String allowedProtocolsString =
- makeString(config.allowedProtocols, WifiConfiguration.Protocol.strings);
- if (config.allowedProtocols.cardinality() != 0 &&
- !WifiNative.setNetworkVariableCommand(
- netId,
- WifiConfiguration.Protocol.varName,
- allowedProtocolsString)) {
- Log.d(TAG, "failed to set proto: "+
- allowedProtocolsString);
- break setVariables;
- }
-
- String allowedAuthAlgorithmsString =
- makeString(config.allowedAuthAlgorithms, WifiConfiguration.AuthAlgorithm.strings);
- if (config.allowedAuthAlgorithms.cardinality() != 0 &&
- !WifiNative.setNetworkVariableCommand(
- netId,
- WifiConfiguration.AuthAlgorithm.varName,
- allowedAuthAlgorithmsString)) {
- Log.d(TAG, "failed to set auth_alg: "+
- allowedAuthAlgorithmsString);
- break setVariables;
- }
-
- String allowedPairwiseCiphersString =
- makeString(config.allowedPairwiseCiphers,
- WifiConfiguration.PairwiseCipher.strings);
- if (config.allowedPairwiseCiphers.cardinality() != 0 &&
- !WifiNative.setNetworkVariableCommand(
- netId,
- WifiConfiguration.PairwiseCipher.varName,
- allowedPairwiseCiphersString)) {
- Log.d(TAG, "failed to set pairwise: "+
- allowedPairwiseCiphersString);
- break setVariables;
- }
-
- String allowedGroupCiphersString =
- makeString(config.allowedGroupCiphers, WifiConfiguration.GroupCipher.strings);
- if (config.allowedGroupCiphers.cardinality() != 0 &&
- !WifiNative.setNetworkVariableCommand(
- netId,
- WifiConfiguration.GroupCipher.varName,
- allowedGroupCiphersString)) {
- Log.d(TAG, "failed to set group: "+
- allowedGroupCiphersString);
- break setVariables;
- }
-
- // Prevent client screw-up by passing in a WifiConfiguration we gave it
- // by preventing "*" as a key.
- if (config.preSharedKey != null && !config.preSharedKey.equals("*") &&
- !WifiNative.setNetworkVariableCommand(
- netId,
- WifiConfiguration.pskVarName,
- config.preSharedKey)) {
- Log.d(TAG, "failed to set psk: "+config.preSharedKey);
- break setVariables;
- }
-
- boolean hasSetKey = false;
- if (config.wepKeys != null) {
- for (int i = 0; i < config.wepKeys.length; i++) {
- // Prevent client screw-up by passing in a WifiConfiguration we gave it
- // by preventing "*" as a key.
- if (config.wepKeys[i] != null && !config.wepKeys[i].equals("*")) {
- if (!WifiNative.setNetworkVariableCommand(
- netId,
- WifiConfiguration.wepKeyVarNames[i],
- config.wepKeys[i])) {
- Log.d(TAG,
- "failed to set wep_key"+i+": " +
- config.wepKeys[i]);
- break setVariables;
- }
- hasSetKey = true;
- }
- }
- }
-
- if (hasSetKey) {
- if (!WifiNative.setNetworkVariableCommand(
- netId,
- WifiConfiguration.wepTxKeyIdxVarName,
- Integer.toString(config.wepTxKeyIndex))) {
- Log.d(TAG,
- "failed to set wep_tx_keyidx: "+
- config.wepTxKeyIndex);
- break setVariables;
- }
- }
-
- if (!WifiNative.setNetworkVariableCommand(
- netId,
- WifiConfiguration.priorityVarName,
- Integer.toString(config.priority))) {
- Log.d(TAG, config.SSID + ": failed to set priority: "
- +config.priority);
- break setVariables;
- }
-
- if (config.hiddenSSID && !WifiNative.setNetworkVariableCommand(
- netId,
- WifiConfiguration.hiddenSSIDVarName,
- Integer.toString(config.hiddenSSID ? 1 : 0))) {
- Log.d(TAG, config.SSID + ": failed to set hiddenSSID: "+
- config.hiddenSSID);
- break setVariables;
- }
-
- for (WifiConfiguration.EnterpriseField field
- : config.enterpriseFields) {
- String varName = field.varName();
- String value = field.value();
- if (value != null) {
- if (field != config.eap) {
- value = (value.length() == 0) ? "NULL" : convertToQuotedString(value);
- }
- if (!WifiNative.setNetworkVariableCommand(
- netId,
- varName,
- value)) {
- Log.d(TAG, config.SSID + ": failed to set " + varName +
- ": " + value);
- break setVariables;
- }
- }
- }
- return netId;
- }
-
- if (newNetwork) {
- WifiNative.removeNetworkCommand(netId);
- Log.d(TAG,
- "Failed to set a network variable, removed network: "
- + netId);
- }
-
- return -1;
- }
-
- private List<WifiConfiguration> getConfiguredNetworksNative() {
- String listStr = WifiNative.listNetworksCommand();
-
- List<WifiConfiguration> networks =
- new ArrayList<WifiConfiguration>();
- if (listStr == null)
- return networks;
-
- String[] lines = listStr.split("\n");
- // Skip the first line, which is a header
- for (int i = 1; i < lines.length; i++) {
- String[] result = lines[i].split("\t");
- // network-id | ssid | bssid | flags
- WifiConfiguration config = new WifiConfiguration();
- try {
- config.networkId = Integer.parseInt(result[0]);
- } catch(NumberFormatException e) {
- continue;
- }
- if (result.length > 3) {
- if (result[3].indexOf("[CURRENT]") != -1)
- config.status = WifiConfiguration.Status.CURRENT;
- else if (result[3].indexOf("[DISABLED]") != -1)
- config.status = WifiConfiguration.Status.DISABLED;
- else
- config.status = WifiConfiguration.Status.ENABLED;
- } else {
- config.status = WifiConfiguration.Status.ENABLED;
- }
- readNetworkVariables(config);
- networks.add(config);
- }
- return networks;
- }
-
- /**
- * Read the variables from the supplicant daemon that are needed to
- * fill in the WifiConfiguration object.
- *
- * @param config the {@link WifiConfiguration} object to be filled in.
- */
- private void readNetworkVariables(WifiConfiguration config) {
-
- int netId = config.networkId;
- if (netId < 0)
- return;
-
- /*
- * TODO: maybe should have a native method that takes an array of
- * variable names and returns an array of values. But we'd still
- * be doing a round trip to the supplicant daemon for each variable.
- */
- String value;
-
- value = WifiNative.getNetworkVariableCommand(netId, WifiConfiguration.ssidVarName);
- if (!TextUtils.isEmpty(value)) {
- config.SSID = removeDoubleQuotes(value);
- } else {
- config.SSID = null;
- }
-
- value = WifiNative.getNetworkVariableCommand(netId, WifiConfiguration.bssidVarName);
- if (!TextUtils.isEmpty(value)) {
- config.BSSID = value;
- } else {
- config.BSSID = null;
- }
-
- value = WifiNative.getNetworkVariableCommand(netId, WifiConfiguration.priorityVarName);
- config.priority = -1;
- if (!TextUtils.isEmpty(value)) {
- try {
- config.priority = Integer.parseInt(value);
- } catch (NumberFormatException ignore) {
- }
- }
-
- value = WifiNative.getNetworkVariableCommand(netId, WifiConfiguration.hiddenSSIDVarName);
- config.hiddenSSID = false;
- if (!TextUtils.isEmpty(value)) {
- try {
- config.hiddenSSID = Integer.parseInt(value) != 0;
- } catch (NumberFormatException ignore) {
- }
- }
-
- value = WifiNative.getNetworkVariableCommand(netId, WifiConfiguration.wepTxKeyIdxVarName);
- config.wepTxKeyIndex = -1;
- if (!TextUtils.isEmpty(value)) {
- try {
- config.wepTxKeyIndex = Integer.parseInt(value);
- } catch (NumberFormatException ignore) {
- }
- }
-
- for (int i = 0; i < 4; i++) {
- value = WifiNative.getNetworkVariableCommand(netId,
- WifiConfiguration.wepKeyVarNames[i]);
- if (!TextUtils.isEmpty(value)) {
- config.wepKeys[i] = value;
- } else {
- config.wepKeys[i] = null;
- }
- }
-
- value = WifiNative.getNetworkVariableCommand(netId, WifiConfiguration.pskVarName);
- if (!TextUtils.isEmpty(value)) {
- config.preSharedKey = value;
- } else {
- config.preSharedKey = null;
- }
-
- value = WifiNative.getNetworkVariableCommand(config.networkId,
- WifiConfiguration.Protocol.varName);
- if (!TextUtils.isEmpty(value)) {
- String vals[] = value.split(" ");
- for (String val : vals) {
- int index =
- lookupString(val, WifiConfiguration.Protocol.strings);
- if (0 <= index) {
- config.allowedProtocols.set(index);
- }
- }
- }
-
- value = WifiNative.getNetworkVariableCommand(config.networkId,
- WifiConfiguration.KeyMgmt.varName);
- if (!TextUtils.isEmpty(value)) {
- String vals[] = value.split(" ");
- for (String val : vals) {
- int index =
- lookupString(val, WifiConfiguration.KeyMgmt.strings);
- if (0 <= index) {
- config.allowedKeyManagement.set(index);
- }
- }
- }
-
- value = WifiNative.getNetworkVariableCommand(config.networkId,
- WifiConfiguration.AuthAlgorithm.varName);
- if (!TextUtils.isEmpty(value)) {
- String vals[] = value.split(" ");
- for (String val : vals) {
- int index =
- lookupString(val, WifiConfiguration.AuthAlgorithm.strings);
- if (0 <= index) {
- config.allowedAuthAlgorithms.set(index);
- }
- }
- }
-
- value = WifiNative.getNetworkVariableCommand(config.networkId,
- WifiConfiguration.PairwiseCipher.varName);
- if (!TextUtils.isEmpty(value)) {
- String vals[] = value.split(" ");
- for (String val : vals) {
- int index =
- lookupString(val, WifiConfiguration.PairwiseCipher.strings);
- if (0 <= index) {
- config.allowedPairwiseCiphers.set(index);
- }
- }
- }
-
- value = WifiNative.getNetworkVariableCommand(config.networkId,
- WifiConfiguration.GroupCipher.varName);
- if (!TextUtils.isEmpty(value)) {
- String vals[] = value.split(" ");
- for (String val : vals) {
- int index =
- lookupString(val, WifiConfiguration.GroupCipher.strings);
- if (0 <= index) {
- config.allowedGroupCiphers.set(index);
- }
- }
- }
-
- for (WifiConfiguration.EnterpriseField field :
- config.enterpriseFields) {
- value = WifiNative.getNetworkVariableCommand(netId,
- field.varName());
- if (!TextUtils.isEmpty(value)) {
- if (field != config.eap) value = removeDoubleQuotes(value);
- field.setValue(value);
- }
- }
-
- }
-
- /**
- * Poll for info not reported via events
- * RSSI & Linkspeed
- */
- private void requestPolledInfo() {
- int newRssi = WifiNative.getRssiCommand();
- if (newRssi != -1 && -200 < newRssi && newRssi < 256) { // screen out invalid values
- /* some implementations avoid negative values by adding 256
- * so we need to adjust for that here.
- */
- if (newRssi > 0) newRssi -= 256;
- mWifiInfo.setRssi(newRssi);
- /*
- * Rather then sending the raw RSSI out every time it
- * changes, we precalculate the signal level that would
- * be displayed in the status bar, and only send the
- * broadcast if that much more coarse-grained number
- * changes. This cuts down greatly on the number of
- * broadcasts, at the cost of not mWifiInforming others
- * interested in RSSI of all the changes in signal
- * level.
- */
- // TODO: The second arg to the call below needs to be a symbol somewhere, but
- // it's actually the size of an array of icons that's private
- // to StatusBar Policy.
- int newSignalLevel = WifiManager.calculateSignalLevel(newRssi, 4);
- if (newSignalLevel != mLastSignalLevel) {
- sendRssiChangeBroadcast(newRssi);
- }
- mLastSignalLevel = newSignalLevel;
- } else {
- mWifiInfo.setRssi(-200);
- }
- int newLinkSpeed = WifiNative.getLinkSpeedCommand();
- if (newLinkSpeed != -1) {
- mWifiInfo.setLinkSpeed(newLinkSpeed);
- }
- }
-
- /**
- * Resets the Wi-Fi Connections by clearing any state, resetting any sockets
- * using the interface, stopping DHCP & disabling interface
- */
- private void handleNetworkDisconnect() {
- Log.d(TAG, "Reset connections and stopping DHCP");
-
- /*
- * Reset connections & stop DHCP
- */
- NetworkUtils.resetConnections(mInterfaceName);
-
- if (!NetworkUtils.stopDhcp(mInterfaceName)) {
- Log.e(TAG, "Could not stop DHCP");
- }
-
- /* Disable interface */
- NetworkUtils.disableInterface(mInterfaceName);
-
- /* send event to CM & network change broadcast */
- setDetailedState(DetailedState.DISCONNECTED);
- sendNetworkStateChangeBroadcast(mLastBssid);
-
- /* Reset data structures */
- mWifiInfo.setIpAddress(0);
- mWifiInfo.setBSSID(null);
- mWifiInfo.setSSID(null);
- mWifiInfo.setNetworkId(-1);
-
- /* Clear network properties */
- mNetworkProperties.clear();
-
- mLastBssid= null;
- mLastNetworkId = -1;
-
- }
-
-
- /*********************************************************
- * Notifications from WifiMonitor
- ********************************************************/
-
- /**
- * A structure for supplying information about a supplicant state
- * change in the STATE_CHANGE event message that comes from the
- * WifiMonitor
- * thread.
- */
- private static class StateChangeResult {
- StateChangeResult(int networkId, String BSSID, Object state) {
- this.state = state;
- this.BSSID = BSSID;
- this.networkId = networkId;
- }
- int networkId;
- String BSSID;
- Object state;
- }
-
- /**
- * Send the tracker a notification that a user-entered password key
- * may be incorrect (i.e., caused authentication to fail).
- */
- void notifyPasswordKeyMayBeIncorrect() {
- sendMessage(PASSWORD_MAY_BE_INCORRECT_EVENT);
- }
-
- /**
- * Send the tracker a notification that a connection to the supplicant
- * daemon has been established.
- */
- void notifySupplicantConnection() {
- sendMessage(SUP_CONNECTION_EVENT);
- }
-
- /**
- * Send the tracker a notification that a connection to the supplicant
- * daemon has been established.
- */
- void notifySupplicantLost() {
- sendMessage(SUP_DISCONNECTION_EVENT);
- }
-
- /**
- * Send the tracker a notification that the state of Wifi connectivity
- * has changed.
- * @param networkId the configured network on which the state change occurred
- * @param newState the new network state
- * @param BSSID when the new state is {@link DetailedState#CONNECTED
- * NetworkInfo.DetailedState.CONNECTED},
- * this is the MAC address of the access point. Otherwise, it
- * is {@code null}.
- */
- void notifyNetworkStateChange(DetailedState newState, String BSSID, int networkId) {
- if (newState == NetworkInfo.DetailedState.CONNECTED) {
- sendMessage(obtainMessage(NETWORK_CONNECTION_EVENT,
- new StateChangeResult(networkId, BSSID, newState)));
- } else {
- sendMessage(obtainMessage(NETWORK_DISCONNECTION_EVENT,
- new StateChangeResult(networkId, BSSID, newState)));
- }
- }
-
- /**
- * Send the tracker a notification that the state of the supplicant
- * has changed.
- * @param networkId the configured network on which the state change occurred
- * @param newState the new {@code SupplicantState}
- */
- void notifySupplicantStateChange(int networkId, String BSSID, SupplicantState newState) {
- sendMessage(obtainMessage(SUPPLICANT_STATE_CHANGE_EVENT,
- new StateChangeResult(networkId, BSSID, newState)));
- }
-
- /**
- * Send the tracker a notification that a scan has completed, and results
- * are available.
- */
- void notifyScanResultsAvailable() {
- /**
- * Switch scan mode over to passive.
- * Turning off scan-only mode happens only in "Connect" mode
- */
- setScanType(false);
- sendMessage(SCAN_RESULTS_EVENT);
- }
-
- void notifyDriverStarted() {
- sendMessage(DRIVER_START_EVENT);
- }
-
- void notifyDriverStopped() {
- sendMessage(DRIVER_STOP_EVENT);
- }
-
- void notifyDriverHung() {
- setWifiEnabled(false);
- setWifiEnabled(true);
- }
-
-
- /********************************************************
- * HSM states
- *******************************************************/
-
- class DefaultState extends HierarchicalState {
- @Override
- public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
- SyncParams syncParams;
- switch (message.what) {
- /* Synchronous call returns */
- case CMD_PING_SUPPLICANT:
- case CMD_START_SCAN:
- case CMD_DISCONNECT:
- case CMD_RECONNECT:
- case CMD_REASSOCIATE:
- case CMD_REMOVE_NETWORK:
- case CMD_ENABLE_NETWORK:
- case CMD_DISABLE_NETWORK:
- case CMD_ADD_OR_UPDATE_NETWORK:
- case CMD_GET_RSSI:
- case CMD_GET_RSSI_APPROX:
- case CMD_GET_LINK_SPEED:
- case CMD_GET_MAC_ADDR:
- case CMD_SAVE_CONFIG:
- case CMD_CONNECTION_STATUS:
- case CMD_GET_NETWORK_CONFIG:
- if (message.arg2 == SYNCHRONOUS_CALL) {
- syncParams = (SyncParams) message.obj;
- syncParams.mSyncReturn.boolValue = false;
- syncParams.mSyncReturn.intValue = -1;
- syncParams.mSyncReturn.stringValue = null;
- syncParams.mSyncReturn.configList = null;
- notifyOnMsgObject(message);
- }
- break;
- case CM_CMD_TEARDOWN:
- EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
- mTeardownRequested.set(true);
- sendMessage(CMD_DISCONNECT);
- sendMessage(CMD_STOP_DRIVER);
- /* Mark wifi available when CM tears down */
- mNetworkInfo.setIsAvailable(true);
- break;
- case CM_CMD_RECONNECT:
- EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
- mTeardownRequested.set(false);
- sendMessage(CMD_START_DRIVER);
- sendMessage(CMD_RECONNECT);
- break;
- case CMD_ENABLE_RSSI_POLL:
- mEnableRssiPolling = (message.arg1 == 1);
- mSupplicantStateTracker.sendMessage(CMD_ENABLE_RSSI_POLL);
- break;
- default:
- if (DBG) Log.w(TAG, "Unhandled " + message);
- break;
- }
- return HANDLED;
- }
- }
-
- class InitialState extends HierarchicalState {
- @Override
- //TODO: could move logging into a common class
- public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
- // [31-8] Reserved for future use
- // [7 - 0] HSM state change
- // 50021 wifi_state_changed (custom|1|5)
- EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
-
- if (WifiNative.isDriverLoaded()) {
- transitionTo(mDriverLoadedState);
- }
- else {
- transitionTo(mDriverUnloadedState);
- }
- }
- }
-
- class DriverLoadingState extends HierarchicalState {
- @Override
- public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
- EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
-
- final Message message = new Message();
- message.copyFrom(getCurrentMessage());
- new Thread(new Runnable() {
- public void run() {
- sWakeLock.acquire();
- //enabling state
- switch(message.arg1) {
- case WIFI_STATE_ENABLING:
- setWifiState(WIFI_STATE_ENABLING);
- break;
- case WIFI_AP_STATE_ENABLING:
- setWifiApState(WIFI_AP_STATE_ENABLING);
- break;
- }
-
- if(WifiNative.loadDriver()) {
- Log.d(TAG, "Driver load successful");
- sendMessage(CMD_LOAD_DRIVER_SUCCESS);
- } else {
- Log.e(TAG, "Failed to load driver!");
- switch(message.arg1) {
- case WIFI_STATE_ENABLING:
- setWifiState(WIFI_STATE_UNKNOWN);
- break;
- case WIFI_AP_STATE_ENABLING:
- setWifiApState(WIFI_AP_STATE_FAILED);
- break;
- }
- sendMessage(CMD_LOAD_DRIVER_FAILURE);
- }
- sWakeLock.release();
- }
- }).start();
- }
-
- @Override
- public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
- switch (message.what) {
- case CMD_LOAD_DRIVER_SUCCESS:
- transitionTo(mDriverLoadedState);
- break;
- case CMD_LOAD_DRIVER_FAILURE:
- transitionTo(mDriverFailedState);
- break;
- case CMD_LOAD_DRIVER:
- case CMD_UNLOAD_DRIVER:
- case CMD_START_SUPPLICANT:
- case CMD_STOP_SUPPLICANT:
- case CMD_START_AP:
- case CMD_STOP_AP:
- case CMD_START_DRIVER:
- case CMD_STOP_DRIVER:
- case CMD_SET_SCAN_MODE:
- case CMD_SET_SCAN_TYPE:
- case CMD_SET_POWER_MODE:
- case CMD_SET_BLUETOOTH_COEXISTENCE:
- case CMD_SET_BLUETOOTH_SCAN_MODE:
- case CMD_SET_NUM_ALLOWED_CHANNELS:
- case CMD_START_PACKET_FILTERING:
- case CMD_STOP_PACKET_FILTERING:
- deferMessage(message);
- break;
- default:
- return NOT_HANDLED;
- }
- EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
- return HANDLED;
- }
- }
-
- class DriverLoadedState extends HierarchicalState {
- @Override
- public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
- EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
- }
- @Override
- public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
- switch(message.what) {
- case CMD_UNLOAD_DRIVER:
- transitionTo(mDriverUnloadingState);
- break;
- case CMD_START_SUPPLICANT:
- if(WifiNative.startSupplicant()) {
- Log.d(TAG, "Supplicant start successful");
- mWifiMonitor.startMonitoring();
- setWifiState(WIFI_STATE_ENABLED);
- transitionTo(mWaitForSupState);
- } else {
- Log.e(TAG, "Failed to start supplicant!");
- sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_STATE_UNKNOWN, 0));
- }
- break;
- case CMD_START_AP:
- try {
- nwService.startAccessPoint((WifiConfiguration) message.obj,
- mInterfaceName,
- SOFTAP_IFACE);
- } catch(Exception e) {
- Log.e(TAG, "Exception in startAccessPoint()");
- sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_AP_STATE_FAILED, 0));
- break;
- }
- Log.d(TAG, "Soft AP start successful");
- setWifiApState(WIFI_AP_STATE_ENABLED);
- transitionTo(mSoftApStartedState);
- break;
- default:
- return NOT_HANDLED;
- }
- EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
- return HANDLED;
- }
- }
-
- class DriverUnloadingState extends HierarchicalState {
- @Override
- public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
- EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
-
- final Message message = new Message();
- message.copyFrom(getCurrentMessage());
- new Thread(new Runnable() {
- public void run() {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
- sWakeLock.acquire();
- if(WifiNative.unloadDriver()) {
- Log.d(TAG, "Driver unload successful");
- sendMessage(CMD_UNLOAD_DRIVER_SUCCESS);
-
- switch(message.arg1) {
- case WIFI_STATE_DISABLED:
- case WIFI_STATE_UNKNOWN:
- setWifiState(message.arg1);
- break;
- case WIFI_AP_STATE_DISABLED:
- case WIFI_AP_STATE_FAILED:
- setWifiApState(message.arg1);
- break;
- }
- } else {
- Log.e(TAG, "Failed to unload driver!");
- sendMessage(CMD_UNLOAD_DRIVER_FAILURE);
-
- switch(message.arg1) {
- case WIFI_STATE_DISABLED:
- case WIFI_STATE_UNKNOWN:
- setWifiState(WIFI_STATE_UNKNOWN);
- break;
- case WIFI_AP_STATE_DISABLED:
- case WIFI_AP_STATE_FAILED:
- setWifiApState(WIFI_AP_STATE_FAILED);
- break;
- }
- }
- sWakeLock.release();
- }
- }).start();
- }
-
- @Override
- public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
- switch (message.what) {
- case CMD_UNLOAD_DRIVER_SUCCESS:
- transitionTo(mDriverUnloadedState);
- break;
- case CMD_UNLOAD_DRIVER_FAILURE:
- transitionTo(mDriverFailedState);
- break;
- case CMD_LOAD_DRIVER:
- case CMD_UNLOAD_DRIVER:
- case CMD_START_SUPPLICANT:
- case CMD_STOP_SUPPLICANT:
- case CMD_START_AP:
- case CMD_STOP_AP:
- case CMD_START_DRIVER:
- case CMD_STOP_DRIVER:
- case CMD_SET_SCAN_MODE:
- case CMD_SET_SCAN_TYPE:
- case CMD_SET_POWER_MODE:
- case CMD_SET_BLUETOOTH_COEXISTENCE:
- case CMD_SET_BLUETOOTH_SCAN_MODE:
- case CMD_SET_NUM_ALLOWED_CHANNELS:
- case CMD_START_PACKET_FILTERING:
- case CMD_STOP_PACKET_FILTERING:
- deferMessage(message);
- break;
- default:
- return NOT_HANDLED;
- }
- EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
- return HANDLED;
- }
- }
-
- class DriverUnloadedState extends HierarchicalState {
- @Override
- public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
- EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
- }
- @Override
- public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
- switch (message.what) {
- case CMD_LOAD_DRIVER:
- transitionTo(mDriverLoadingState);
- break;
- default:
- return NOT_HANDLED;
- }
- EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
- return HANDLED;
- }
- }
-
- class DriverFailedState extends HierarchicalState {
- @Override
- public void enter() {
- Log.e(TAG, getName() + "\n");
- EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
- }
- @Override
- public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
- return NOT_HANDLED;
- }
- }
-
-
- class WaitForSupState extends HierarchicalState {
- @Override
- public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
- EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
- }
- @Override
- public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
- switch(message.what) {
- case SUP_CONNECTION_EVENT:
- Log.d(TAG, "Supplicant connection established");
- mSupplicantStateTracker.resetSupplicantState();
- /* Initialize data structures */
- resetNotificationTimer();
- setTeardownRequested(false);
- mLastBssid = null;
- mLastNetworkId = -1;
- mLastSignalLevel = -1;
-
- mWifiInfo.setMacAddress(WifiNative.getMacAddressCommand());
-
- //TODO: initialize and fix multicast filtering
- //mWM.initializeMulticastFiltering();
-
- if (mBluetoothA2dp == null) {
- mBluetoothA2dp = new BluetoothA2dp(mContext);
- }
- checkIsBluetoothPlaying();
-
- checkUseStaticIp();
- sendSupplicantConnectionChangedBroadcast(true);
- transitionTo(mDriverSupReadyState);
- break;
- case CMD_STOP_SUPPLICANT:
- Log.d(TAG, "Stop supplicant received");
- WifiNative.stopSupplicant();
- transitionTo(mDriverLoadedState);
- break;
- /* Fail soft ap when waiting for supplicant start */
- case CMD_START_AP:
- Log.d(TAG, "Failed to start soft AP with a running supplicant");
- setWifiApState(WIFI_AP_STATE_FAILED);
- break;
- case CMD_START_DRIVER:
- case CMD_STOP_DRIVER:
- case CMD_SET_SCAN_MODE:
- case CMD_SET_SCAN_TYPE:
- case CMD_SET_POWER_MODE:
- case CMD_SET_BLUETOOTH_COEXISTENCE:
- case CMD_SET_BLUETOOTH_SCAN_MODE:
- case CMD_SET_NUM_ALLOWED_CHANNELS:
- case CMD_START_PACKET_FILTERING:
- case CMD_STOP_PACKET_FILTERING:
- deferMessage(message);
- break;
- case CMD_STOP_AP:
- case CMD_START_SUPPLICANT:
- case CMD_UNLOAD_DRIVER:
- break;
- default:
- return NOT_HANDLED;
- }
- EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
- return HANDLED;
- }
- }
-
- class DriverSupReadyState extends HierarchicalState {
- @Override
- public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
- EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
- /* Initialize for connect mode operation at start */
- mIsScanMode = false;
- }
- @Override
- public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
- SyncParams syncParams;
- switch(message.what) {
- case CMD_STOP_SUPPLICANT: /* Supplicant stopped by user */
- Log.d(TAG, "Stop supplicant received");
- WifiNative.stopSupplicant();
- //$FALL-THROUGH$
- case SUP_DISCONNECTION_EVENT: /* Supplicant died */
- EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
- //Remove any notifications on disconnection
- setNotificationVisible(false, 0, false, 0);
- WifiNative.closeSupplicantConnection();
- handleNetworkDisconnect();
- sendSupplicantConnectionChangedBroadcast(false);
- mSupplicantStateTracker.resetSupplicantState();
- transitionTo(mDriverLoadedState);
-
- /* When supplicant dies, unload driver and enter failed state */
- //TODO: consider bringing up supplicant again
- if (message.what == SUP_DISCONNECTION_EVENT) {
- Log.d(TAG, "Supplicant died, unloading driver");
- sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_STATE_UNKNOWN, 0));
- }
- break;
- case CMD_START_DRIVER:
- EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
- WifiNative.startDriverCommand();
- transitionTo(mDriverStartingState);
- break;
- case SCAN_RESULTS_EVENT:
- setScanResults(WifiNative.scanResultsCommand());
- sendScanResultsAvailableBroadcast();
- checkAndSetNotification();
- break;
- case CMD_PING_SUPPLICANT:
- syncParams = (SyncParams) message.obj;
- syncParams.mSyncReturn.boolValue = WifiNative.pingCommand();
- notifyOnMsgObject(message);
- break;
- case CMD_ADD_OR_UPDATE_NETWORK:
- EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
- syncParams = (SyncParams) message.obj;
- WifiConfiguration config = (WifiConfiguration) syncParams.mParameter;
- syncParams.mSyncReturn.intValue = addOrUpdateNetworkNative(config);
- notifyOnMsgObject(message);
- break;
- case CMD_REMOVE_NETWORK:
- EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
- if (message.arg2 == SYNCHRONOUS_CALL) {
- syncParams = (SyncParams) message.obj;
- syncParams.mSyncReturn.boolValue = WifiNative.removeNetworkCommand(
- message.arg1);
- notifyOnMsgObject(message);
- } else {
- /* asynchronous handling */
- WifiNative.removeNetworkCommand(message.arg1);
- }
- break;
- case CMD_ENABLE_NETWORK:
- EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
- if (message.arg2 == SYNCHRONOUS_CALL) {
- syncParams = (SyncParams) message.obj;
- EnableNetParams enableNetParams = (EnableNetParams) syncParams.mParameter;
- syncParams.mSyncReturn.boolValue = WifiNative.enableNetworkCommand(
- enableNetParams.netId, enableNetParams.disableOthers);
- notifyOnMsgObject(message);
- } else {
- /* asynchronous handling */
- WifiNative.enableNetworkCommand(message.arg1, message.arg2 == 1);
- }
- break;
- case CMD_DISABLE_NETWORK:
- EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
- if (message.arg2 == SYNCHRONOUS_CALL) {
- syncParams = (SyncParams) message.obj;
- syncParams.mSyncReturn.boolValue = WifiNative.disableNetworkCommand(
- message.arg1);
- notifyOnMsgObject(message);
- } else {
- /* asynchronous handling */
- WifiNative.disableNetworkCommand(message.arg1);
- }
- break;
- case CMD_BLACKLIST_NETWORK:
- EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
- WifiNative.addToBlacklistCommand((String)message.obj);
- break;
- case CMD_CLEAR_BLACKLIST:
- WifiNative.clearBlacklistCommand();
- break;
- case CMD_GET_NETWORK_CONFIG:
- syncParams = (SyncParams) message.obj;
- syncParams.mSyncReturn.configList = getConfiguredNetworksNative();
- notifyOnMsgObject(message);
- break;
- case CMD_SAVE_CONFIG:
- if (message.arg2 == SYNCHRONOUS_CALL) {
- syncParams = (SyncParams) message.obj;
- syncParams.mSyncReturn.boolValue = WifiNative.saveConfigCommand();
- notifyOnMsgObject(message);
- } else {
- /* asynchronous handling */
- WifiNative.saveConfigCommand();
- }
- // Inform the backup manager about a data change
- IBackupManager ibm = IBackupManager.Stub.asInterface(
- ServiceManager.getService(Context.BACKUP_SERVICE));
- if (ibm != null) {
- try {
- ibm.dataChanged("com.android.providers.settings");
- } catch (Exception e) {
- // Try again later
- }
- }
- break;
- case CMD_CONNECTION_STATUS:
- syncParams = (SyncParams) message.obj;
- syncParams.mSyncReturn.stringValue = WifiNative.statusCommand();
- notifyOnMsgObject(message);
- break;
- case CMD_GET_MAC_ADDR:
- syncParams = (SyncParams) message.obj;
- syncParams.mSyncReturn.stringValue = WifiNative.getMacAddressCommand();
- notifyOnMsgObject(message);
- break;
- /* Cannot start soft AP while in client mode */
- case CMD_START_AP:
- Log.d(TAG, "Failed to start soft AP with a running supplicant");
- EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
- setWifiApState(WIFI_AP_STATE_FAILED);
- break;
- case CMD_SET_SCAN_MODE:
- mIsScanMode = (message.arg1 == SCAN_ONLY_MODE);
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- class DriverStartingState extends HierarchicalState {
- @Override
- public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
- EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
- }
- @Override
- public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
- switch(message.what) {
- case DRIVER_START_EVENT:
- transitionTo(mDriverStartedState);
- break;
- /* Queue driver commands & connection events */
- case CMD_START_DRIVER:
- case CMD_STOP_DRIVER:
- case SUPPLICANT_STATE_CHANGE_EVENT:
- case NETWORK_CONNECTION_EVENT:
- case NETWORK_DISCONNECTION_EVENT:
- case PASSWORD_MAY_BE_INCORRECT_EVENT:
- case CMD_SET_SCAN_TYPE:
- case CMD_SET_POWER_MODE:
- case CMD_SET_BLUETOOTH_COEXISTENCE:
- case CMD_SET_BLUETOOTH_SCAN_MODE:
- case CMD_SET_NUM_ALLOWED_CHANNELS:
- case CMD_START_PACKET_FILTERING:
- case CMD_STOP_PACKET_FILTERING:
- deferMessage(message);
- break;
- /* Queue the asynchronous version of these commands */
- case CMD_START_SCAN:
- case CMD_DISCONNECT:
- case CMD_REASSOCIATE:
- case CMD_RECONNECT:
- if (message.arg2 != SYNCHRONOUS_CALL) {
- deferMessage(message);
- }
- break;
- default:
- return NOT_HANDLED;
- }
- EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
- return HANDLED;
- }
- }
-
- class DriverStartedState extends HierarchicalState {
- @Override
- public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
- EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
-
- try {
- mBatteryStats.noteWifiRunning();
- } catch (RemoteException ignore) {}
-
- /* Initialize channel count */
- setNumAllowedChannels();
-
- if (mIsScanMode) {
- WifiNative.setScanResultHandlingCommand(SCAN_ONLY_MODE);
- WifiNative.disconnectCommand();
- transitionTo(mScanModeState);
- } else {
- WifiNative.setScanResultHandlingCommand(CONNECT_MODE);
- /* If supplicant has already connected, before we could finish establishing
- * the control channel connection, we miss all the supplicant events.
- * Disconnect and reconnect when driver has started to ensure we receive
- * all supplicant events.
- *
- * TODO: This is a bit unclean, ideally the supplicant should never
- * connect until told to do so by the framework
- */
- WifiNative.disconnectCommand();
- WifiNative.reconnectCommand();
- transitionTo(mConnectModeState);
- }
- }
- @Override
- public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
- SyncParams syncParams;
- switch(message.what) {
- case CMD_SET_SCAN_TYPE:
- if (message.arg1 == SCAN_ACTIVE) {
- WifiNative.setScanModeCommand(true);
- } else {
- WifiNative.setScanModeCommand(false);
- }
- break;
- case CMD_SET_POWER_MODE:
- WifiNative.setPowerModeCommand(message.arg1);
- break;
- case CMD_SET_BLUETOOTH_COEXISTENCE:
- WifiNative.setBluetoothCoexistenceModeCommand(message.arg1);
- break;
- case CMD_SET_BLUETOOTH_SCAN_MODE:
- WifiNative.setBluetoothCoexistenceScanModeCommand(message.arg1 == 1);
- break;
- case CMD_SET_NUM_ALLOWED_CHANNELS:
- mNumAllowedChannels = message.arg1;
- WifiNative.setNumAllowedChannelsCommand(message.arg1);
- break;
- case CMD_START_DRIVER:
- /* Ignore another driver start */
- break;
- case CMD_STOP_DRIVER:
- WifiNative.stopDriverCommand();
- transitionTo(mDriverStoppingState);
- break;
- case CMD_REQUEST_CM_WAKELOCK:
- if (mCm == null) {
- mCm = (ConnectivityManager)mContext.getSystemService(
- Context.CONNECTIVITY_SERVICE);
- }
- mCm.requestNetworkTransitionWakelock(TAG);
- break;
- case CMD_START_PACKET_FILTERING:
- WifiNative.startPacketFiltering();
- break;
- case CMD_STOP_PACKET_FILTERING:
- WifiNative.stopPacketFiltering();
- break;
- default:
- return NOT_HANDLED;
- }
- EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
- return HANDLED;
- }
- @Override
- public void exit() {
- if (DBG) Log.d(TAG, getName() + "\n");
- try {
- mBatteryStats.noteWifiStopped();
- } catch (RemoteException ignore) { }
- }
- }
-
- class DriverStoppingState extends HierarchicalState {
- @Override
- public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
- EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
- }
- @Override
- public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
- switch(message.what) {
- case DRIVER_STOP_EVENT:
- transitionTo(mDriverStoppedState);
- break;
- /* Queue driver commands */
- case CMD_START_DRIVER:
- case CMD_STOP_DRIVER:
- case CMD_SET_SCAN_TYPE:
- case CMD_SET_POWER_MODE:
- case CMD_SET_BLUETOOTH_COEXISTENCE:
- case CMD_SET_BLUETOOTH_SCAN_MODE:
- case CMD_SET_NUM_ALLOWED_CHANNELS:
- case CMD_START_PACKET_FILTERING:
- case CMD_STOP_PACKET_FILTERING:
- deferMessage(message);
- break;
- /* Queue the asynchronous version of these commands */
- case CMD_START_SCAN:
- case CMD_DISCONNECT:
- case CMD_REASSOCIATE:
- case CMD_RECONNECT:
- if (message.arg2 != SYNCHRONOUS_CALL) {
- deferMessage(message);
- }
- break;
- default:
- return NOT_HANDLED;
- }
- EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
- return HANDLED;
- }
- }
-
- class DriverStoppedState extends HierarchicalState {
- @Override
- public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
- EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
-
- // Take down any open network notifications on driver stop
- setNotificationVisible(false, 0, false, 0);
- }
- @Override
- public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
- return NOT_HANDLED;
- }
- }
-
- class ScanModeState extends HierarchicalState {
- @Override
- public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
- EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
- }
- @Override
- public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
- SyncParams syncParams;
- switch(message.what) {
- case CMD_SET_SCAN_MODE:
- if (message.arg1 == SCAN_ONLY_MODE) {
- /* Ignore */
- return HANDLED;
- } else {
- WifiNative.setScanResultHandlingCommand(message.arg1);
- WifiNative.reconnectCommand();
- mIsScanMode = false;
- transitionTo(mDisconnectedState);
- }
- break;
- case CMD_START_SCAN:
- if (message.arg2 == SYNCHRONOUS_CALL) {
- syncParams = (SyncParams) message.obj;
- syncParams.mSyncReturn.boolValue = WifiNative.scanCommand(
- message.arg1 == SCAN_ACTIVE);
- notifyOnMsgObject(message);
- } else {
- /* asynchronous handling */
- WifiNative.scanCommand(message.arg1 == SCAN_ACTIVE);
- }
- break;
- /* Ignore */
- case CMD_DISCONNECT:
- case CMD_RECONNECT:
- case CMD_REASSOCIATE:
- case SUPPLICANT_STATE_CHANGE_EVENT:
- case NETWORK_CONNECTION_EVENT:
- case NETWORK_DISCONNECTION_EVENT:
- break;
- default:
- return NOT_HANDLED;
- }
- EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
- return HANDLED;
- }
- }
-
- class ConnectModeState extends HierarchicalState {
- @Override
- public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
- EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
- }
- @Override
- public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
- SyncParams syncParams;
- StateChangeResult stateChangeResult;
- switch(message.what) {
- case PASSWORD_MAY_BE_INCORRECT_EVENT:
- mPasswordKeyMayBeIncorrect = true;
- break;
- case SUPPLICANT_STATE_CHANGE_EVENT:
- stateChangeResult = (StateChangeResult) message.obj;
- mSupplicantStateTracker.handleEvent(stateChangeResult);
- break;
- case CMD_START_SCAN:
- if (message.arg2 == SYNCHRONOUS_CALL) {
- syncParams = (SyncParams) message.obj;
- syncParams.mSyncReturn.boolValue = true;
- notifyOnMsgObject(message);
- }
- /* We need to set scan type in completed state */
- Message newMsg = obtainMessage();
- newMsg.copyFrom(message);
- mSupplicantStateTracker.sendMessage(newMsg);
- break;
- /* Do a redundant disconnect without transition */
- case CMD_DISCONNECT:
- if (message.arg2 == SYNCHRONOUS_CALL) {
- syncParams = (SyncParams) message.obj;
- syncParams.mSyncReturn.boolValue = WifiNative.disconnectCommand();
- notifyOnMsgObject(message);
- } else {
- /* asynchronous handling */
- WifiNative.disconnectCommand();
- }
- break;
- case CMD_RECONNECT:
- if (message.arg2 == SYNCHRONOUS_CALL) {
- syncParams = (SyncParams) message.obj;
- syncParams.mSyncReturn.boolValue = WifiNative.reconnectCommand();
- notifyOnMsgObject(message);
- } else {
- /* asynchronous handling */
- WifiNative.reconnectCommand();
- }
- break;
- case CMD_REASSOCIATE:
- if (message.arg2 == SYNCHRONOUS_CALL) {
- syncParams = (SyncParams) message.obj;
- syncParams.mSyncReturn.boolValue = WifiNative.reassociateCommand();
- notifyOnMsgObject(message);
- } else {
- /* asynchronous handling */
- WifiNative.reassociateCommand();
- }
- break;
- case SCAN_RESULTS_EVENT:
- /* Set the scan setting back to "connect" mode */
- WifiNative.setScanResultHandlingCommand(CONNECT_MODE);
- /* Handle scan results */
- return NOT_HANDLED;
- case NETWORK_CONNECTION_EVENT:
- Log.d(TAG,"Network connection established");
- stateChangeResult = (StateChangeResult) message.obj;
-
- /* Remove any notifications */
- setNotificationVisible(false, 0, false, 0);
- resetNotificationTimer();
-
- mWifiInfo.setBSSID(mLastBssid = stateChangeResult.BSSID);
- mWifiInfo.setNetworkId(stateChangeResult.networkId);
- mLastNetworkId = stateChangeResult.networkId;
-
- /* send event to CM & network change broadcast */
- setDetailedState(DetailedState.OBTAINING_IPADDR);
- sendNetworkStateChangeBroadcast(mLastBssid);
-
- transitionTo(mConnectingState);
- break;
- case NETWORK_DISCONNECTION_EVENT:
- Log.d(TAG,"Network connection lost");
- handleNetworkDisconnect();
- transitionTo(mDisconnectedState);
- break;
- case CMD_GET_RSSI:
- syncParams = (SyncParams) message.obj;
- syncParams.mSyncReturn.intValue = WifiNative.getRssiCommand();
- notifyOnMsgObject(message);
- break;
- case CMD_GET_RSSI_APPROX:
- syncParams = (SyncParams) message.obj;
- syncParams.mSyncReturn.intValue = WifiNative.getRssiApproxCommand();
- notifyOnMsgObject(message);
- break;
- case CMD_GET_LINK_SPEED:
- syncParams = (SyncParams) message.obj;
- syncParams.mSyncReturn.intValue = WifiNative.getLinkSpeedCommand();
- notifyOnMsgObject(message);
- break;
- default:
- return NOT_HANDLED;
- }
- EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
- return HANDLED;
- }
- }
-
- class ConnectingState extends HierarchicalState {
- boolean modifiedBluetoothCoexistenceMode;
- int powerMode;
- Thread mDhcpThread;
-
- @Override
- public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
- EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
-
- if (!mUseStaticIp) {
-
- mDhcpThread = null;
- modifiedBluetoothCoexistenceMode = false;
- powerMode = DRIVER_POWER_MODE_AUTO;
-
- if (shouldDisableCoexistenceMode()) {
- /*
- * There are problems setting the Wi-Fi driver's power
- * mode to active when bluetooth coexistence mode is
- * enabled or sense.
- * <p>
- * We set Wi-Fi to active mode when
- * obtaining an IP address because we've found
- * compatibility issues with some routers with low power
- * mode.
- * <p>
- * In order for this active power mode to properly be set,
- * we disable coexistence mode until we're done with
- * obtaining an IP address. One exception is if we
- * are currently connected to a headset, since disabling
- * coexistence would interrupt that connection.
- */
- modifiedBluetoothCoexistenceMode = true;
-
- // Disable the coexistence mode
- WifiNative.setBluetoothCoexistenceModeCommand(
- WifiNative.BLUETOOTH_COEXISTENCE_MODE_DISABLED);
- }
-
- powerMode = WifiNative.getPowerModeCommand();
- if (powerMode < 0) {
- // Handle the case where supplicant driver does not support
- // getPowerModeCommand.
- powerMode = DRIVER_POWER_MODE_AUTO;
- }
- if (powerMode != DRIVER_POWER_MODE_ACTIVE) {
- WifiNative.setPowerModeCommand(DRIVER_POWER_MODE_ACTIVE);
- }
-
- Log.d(TAG, "DHCP request started");
- mDhcpThread = new Thread(new Runnable() {
- public void run() {
- if (NetworkUtils.runDhcp(mInterfaceName, mDhcpInfo)) {
- Log.d(TAG, "DHCP request succeeded");
- sendMessage(CMD_IP_CONFIG_SUCCESS);
- } else {
- Log.d(TAG, "DHCP request failed: " +
- NetworkUtils.getDhcpError());
- sendMessage(CMD_IP_CONFIG_FAILURE);
- }
- }
- });
- mDhcpThread.start();
- } else {
- if (NetworkUtils.configureInterface(mInterfaceName, mDhcpInfo)) {
- Log.v(TAG, "Static IP configuration succeeded");
- sendMessage(CMD_IP_CONFIG_SUCCESS);
- } else {
- Log.v(TAG, "Static IP configuration failed");
- sendMessage(CMD_IP_CONFIG_FAILURE);
- }
- }
- }
- @Override
- public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
-
- switch(message.what) {
- case CMD_IP_CONFIG_SUCCESS:
- mReconnectCount = 0;
- mLastSignalLevel = -1; // force update of signal strength
- mWifiInfo.setIpAddress(mDhcpInfo.ipAddress);
- Log.d(TAG, "IP configuration: " + mDhcpInfo);
- configureNetworkProperties();
- setDetailedState(DetailedState.CONNECTED);
- sendNetworkStateChangeBroadcast(mLastBssid);
- transitionTo(mConnectedState);
- break;
- case CMD_IP_CONFIG_FAILURE:
- mWifiInfo.setIpAddress(0);
-
- Log.e(TAG, "IP configuration failed");
- /**
- * If we've exceeded the maximum number of retries for DHCP
- * to a given network, disable the network
- */
- if (++mReconnectCount > getMaxDhcpRetries()) {
- Log.e(TAG, "Failed " +
- mReconnectCount + " times, Disabling " + mLastNetworkId);
- WifiNative.disableNetworkCommand(mLastNetworkId);
- }
-
- /* DHCP times out after about 30 seconds, we do a
- * disconnect and an immediate reconnect to try again
- */
- WifiNative.disconnectCommand();
- WifiNative.reconnectCommand();
- transitionTo(mDisconnectingState);
- break;
- case CMD_DISCONNECT:
- if (message.arg2 == SYNCHRONOUS_CALL) {
- SyncParams syncParams = (SyncParams) message.obj;
- syncParams.mSyncReturn.boolValue = WifiNative.disconnectCommand();
- notifyOnMsgObject(message);
- } else {
- /* asynchronous handling */
- WifiNative.disconnectCommand();
- }
- transitionTo(mDisconnectingState);
- break;
- /* Ignore */
- case NETWORK_CONNECTION_EVENT:
- break;
- case CMD_STOP_DRIVER:
- sendMessage(CMD_DISCONNECT);
- deferMessage(message);
- break;
- case CMD_SET_SCAN_MODE:
- if (message.arg1 == SCAN_ONLY_MODE) {
- sendMessage(CMD_DISCONNECT);
- deferMessage(message);
- }
- break;
- case CMD_RECONFIGURE_IP:
- deferMessage(message);
- break;
- default:
- return NOT_HANDLED;
- }
- EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
- return HANDLED;
- }
-
- @Override
- public void exit() {
- /* reset power state & bluetooth coexistence if on DHCP */
- if (!mUseStaticIp) {
- if (powerMode != DRIVER_POWER_MODE_ACTIVE) {
- WifiNative.setPowerModeCommand(powerMode);
- }
-
- if (modifiedBluetoothCoexistenceMode) {
- // Set the coexistence mode back to its default value
- WifiNative.setBluetoothCoexistenceModeCommand(
- WifiNative.BLUETOOTH_COEXISTENCE_MODE_SENSE);
- }
- }
-
- }
- }
-
- class ConnectedState extends HierarchicalState {
- @Override
- public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
- EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
- }
- @Override
- public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
- switch (message.what) {
- case CMD_DISCONNECT:
- if (message.arg2 == SYNCHRONOUS_CALL) {
- SyncParams syncParams = (SyncParams) message.obj;
- syncParams.mSyncReturn.boolValue = WifiNative.disconnectCommand();
- notifyOnMsgObject(message);
- } else {
- /* asynchronous handling */
- WifiNative.disconnectCommand();
- }
- transitionTo(mDisconnectingState);
- break;
- case CMD_RECONFIGURE_IP:
- Log.d(TAG,"Reconfiguring IP on connection");
- NetworkUtils.resetConnections(mInterfaceName);
- transitionTo(mConnectingState);
- break;
- case CMD_STOP_DRIVER:
- sendMessage(CMD_DISCONNECT);
- deferMessage(message);
- break;
- case CMD_SET_SCAN_MODE:
- if (message.arg1 == SCAN_ONLY_MODE) {
- sendMessage(CMD_DISCONNECT);
- deferMessage(message);
- }
- break;
- /* Ignore */
- case NETWORK_CONNECTION_EVENT:
- break;
- default:
- return NOT_HANDLED;
- }
- EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
- return HANDLED;
- }
- }
-
- class DisconnectingState extends HierarchicalState {
- @Override
- public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
- EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
- }
- @Override
- public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
- switch (message.what) {
- case CMD_STOP_DRIVER: /* Stop driver only after disconnect handled */
- deferMessage(message);
- break;
- case CMD_SET_SCAN_MODE:
- if (message.arg1 == SCAN_ONLY_MODE) {
- deferMessage(message);
- }
- break;
- default:
- return NOT_HANDLED;
- }
- EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
- return HANDLED;
- }
- }
-
- class DisconnectedState extends HierarchicalState {
- @Override
- public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
- EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
- }
- @Override
- public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
- switch (message.what) {
- case CMD_SET_SCAN_MODE:
- if (message.arg1 == SCAN_ONLY_MODE) {
- WifiNative.setScanResultHandlingCommand(message.arg1);
- //Supplicant disconnect to prevent further connects
- WifiNative.disconnectCommand();
- mIsScanMode = true;
- transitionTo(mScanModeState);
- }
- break;
- /* Ignore network disconnect */
- case NETWORK_DISCONNECTION_EVENT:
- break;
- default:
- return NOT_HANDLED;
- }
- EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
- return HANDLED;
- }
- }
-
- class SoftApStartedState extends HierarchicalState {
- @Override
- public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
- EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
- }
- @Override
- public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
- switch(message.what) {
- case CMD_STOP_AP:
- Log.d(TAG,"Stopping Soft AP");
- setWifiApState(WIFI_AP_STATE_DISABLING);
- try {
- nwService.stopAccessPoint();
- } catch(Exception e) {
- Log.e(TAG, "Exception in stopAccessPoint()");
- }
- transitionTo(mDriverLoadedState);
- break;
- case CMD_START_AP:
- Log.d(TAG,"SoftAP set on a running access point");
- try {
- nwService.setAccessPoint((WifiConfiguration) message.obj,
- mInterfaceName,
- SOFTAP_IFACE);
- } catch(Exception e) {
- Log.e(TAG, "Exception in nwService during soft AP set");
- try {
- nwService.stopAccessPoint();
- } catch (Exception ee) {
- Slog.e(TAG, "Could not stop AP, :" + ee);
- }
- sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_AP_STATE_FAILED, 0));
- }
- break;
- /* Fail client mode operation when soft AP is enabled */
- case CMD_START_SUPPLICANT:
- Log.e(TAG,"Cannot start supplicant with a running soft AP");
- setWifiState(WIFI_STATE_UNKNOWN);
- break;
- default:
- return NOT_HANDLED;
- }
- EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
- return HANDLED;
- }
- }
-
-
- class SupplicantStateTracker extends HierarchicalStateMachine {
-
- private int mRssiPollToken = 0;
-
- /**
- * The max number of the WPA supplicant loop iterations before we
- * decide that the loop should be terminated:
- */
- private static final int MAX_SUPPLICANT_LOOP_ITERATIONS = 4;
- private int mLoopDetectIndex = 0;
- private int mLoopDetectCount = 0;
-
- /**
- * Supplicant state change commands follow
- * the ordinal values defined in SupplicantState.java
- */
- private static final int DISCONNECTED = 0;
- private static final int INACTIVE = 1;
- private static final int SCANNING = 2;
- private static final int ASSOCIATING = 3;
- private static final int ASSOCIATED = 4;
- private static final int FOUR_WAY_HANDSHAKE = 5;
- private static final int GROUP_HANDSHAKE = 6;
- private static final int COMPLETED = 7;
- private static final int DORMANT = 8;
- private static final int UNINITIALIZED = 9;
- private static final int INVALID = 10;
-
- private HierarchicalState mUninitializedState;
- private HierarchicalState mInitializedState;
- private HierarchicalState mInactiveState;
- private HierarchicalState mDisconnectState;
- private HierarchicalState mScanState;
- private HierarchicalState mConnectState;
- private HierarchicalState mHandshakeState;
- private HierarchicalState mCompletedState;
- private HierarchicalState mDormantState;
-
-
- public SupplicantStateTracker(Context context, Handler target) {
- super(TAG, target.getLooper());
-
- mUninitializedState = new UninitializedState();
- mInitializedState = new InitializedState();
- mInactiveState = new InactiveState();
- mDisconnectState = new DisconnectedState();
- mScanState = new ScanState();
- mConnectState = new ConnectState();
- mHandshakeState = new HandshakeState();
- mCompletedState = new CompletedState();
- mDormantState = new DormantState();
-
-
- addState(mUninitializedState);
- addState(mInitializedState);
- addState(mInactiveState, mInitializedState);
- addState(mDisconnectState, mInitializedState);
- addState(mScanState, mInitializedState);
- addState(mConnectState, mInitializedState);
- addState(mHandshakeState, mConnectState);
- addState(mCompletedState, mConnectState);
- addState(mDormantState, mInitializedState);
-
- setInitialState(mUninitializedState);
-
- //start the state machine
- start();
- }
-
- public void handleEvent(StateChangeResult stateChangeResult) {
- SupplicantState newState = (SupplicantState) stateChangeResult.state;
-
- // Supplicant state change
- // [31-13] Reserved for future use
- // [8 - 0] Supplicant state (as defined in SupplicantState.java)
- // 50023 supplicant_state_changed (custom|1|5)
- EventLog.writeEvent(EVENTLOG_SUPPLICANT_STATE_CHANGED, newState.ordinal());
-
- sendMessage(obtainMessage(newState.ordinal(), stateChangeResult));
- }
-
- public void resetSupplicantState() {
- transitionTo(mUninitializedState);
- }
-
- private void resetLoopDetection() {
- mLoopDetectCount = 0;
- mLoopDetectIndex = 0;
- }
-
- private boolean handleTransition(Message msg) {
- if (DBG) Log.d(TAG, getName() + msg.toString() + "\n");
- switch (msg.what) {
- case DISCONNECTED:
- transitionTo(mDisconnectState);
- break;
- case SCANNING:
- transitionTo(mScanState);
- break;
- case ASSOCIATING:
- StateChangeResult stateChangeResult = (StateChangeResult) msg.obj;
- /* BSSID is valid only in ASSOCIATING state */
- mWifiInfo.setBSSID(stateChangeResult.BSSID);
- //$FALL-THROUGH$
- case ASSOCIATED:
- case FOUR_WAY_HANDSHAKE:
- case GROUP_HANDSHAKE:
- transitionTo(mHandshakeState);
- break;
- case COMPLETED:
- transitionTo(mCompletedState);
- break;
- case DORMANT:
- transitionTo(mDormantState);
- break;
- case INACTIVE:
- transitionTo(mInactiveState);
- break;
- case UNINITIALIZED:
- case INVALID:
- transitionTo(mUninitializedState);
- break;
- default:
- return NOT_HANDLED;
- }
- StateChangeResult stateChangeResult = (StateChangeResult) msg.obj;
- SupplicantState supState = (SupplicantState) stateChangeResult.state;
- setDetailedState(WifiInfo.getDetailedStateOf(supState));
- mWifiInfo.setSupplicantState(supState);
- mWifiInfo.setNetworkId(stateChangeResult.networkId);
- //TODO: Modify WifiMonitor to report SSID on events
- //mWifiInfo.setSSID()
- return HANDLED;
- }
-
- /********************************************************
- * HSM states
- *******************************************************/
-
- class InitializedState extends HierarchicalState {
- @Override
- public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
- }
- @Override
- public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
- switch (message.what) {
- case CMD_START_SCAN:
- WifiNative.scanCommand(message.arg1 == SCAN_ACTIVE);
- break;
- default:
- if (DBG) Log.w(TAG, "Ignoring " + message);
- break;
- }
- return HANDLED;
- }
- }
-
- class UninitializedState extends HierarchicalState {
- @Override
- public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
- mNetworkInfo.setIsAvailable(false);
- resetLoopDetection();
- mPasswordKeyMayBeIncorrect = false;
- }
- @Override
- public boolean processMessage(Message message) {
- switch(message.what) {
- default:
- if (!handleTransition(message)) {
- if (DBG) Log.w(TAG, "Ignoring " + message);
- }
- break;
- }
- return HANDLED;
- }
- }
-
- class InactiveState extends HierarchicalState {
- @Override
- public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
- Message message = getCurrentMessage();
- StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
-
- mNetworkInfo.setIsAvailable(false);
- resetLoopDetection();
- mPasswordKeyMayBeIncorrect = false;
-
- sendSupplicantStateChangedBroadcast(stateChangeResult, false);
- }
- @Override
- public boolean processMessage(Message message) {
- return handleTransition(message);
- }
- }
-
-
- class DisconnectedState extends HierarchicalState {
- @Override
- public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
- Message message = getCurrentMessage();
- StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
-
- mNetworkInfo.setIsAvailable(true);
- resetLoopDetection();
-
- /* If a disconnect event happens after a password key failure
- * event, disable the network
- */
- if (mPasswordKeyMayBeIncorrect) {
- Log.d(TAG, "Failed to authenticate, disabling network " +
- mWifiInfo.getNetworkId());
- WifiNative.disableNetworkCommand(mWifiInfo.getNetworkId());
- mPasswordKeyMayBeIncorrect = false;
- sendSupplicantStateChangedBroadcast(stateChangeResult, true);
- }
- else {
- sendSupplicantStateChangedBroadcast(stateChangeResult, false);
- }
- }
- @Override
- public boolean processMessage(Message message) {
- return handleTransition(message);
- }
- }
-
- class ScanState extends HierarchicalState {
- @Override
- public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
- Message message = getCurrentMessage();
- StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
-
- mNetworkInfo.setIsAvailable(true);
- mPasswordKeyMayBeIncorrect = false;
- resetLoopDetection();
- sendSupplicantStateChangedBroadcast(stateChangeResult, false);
- }
- @Override
- public boolean processMessage(Message message) {
- return handleTransition(message);
- }
- }
-
- class ConnectState extends HierarchicalState {
- @Override
- public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
- }
- @Override
- public boolean processMessage(Message message) {
- switch (message.what) {
- case CMD_START_SCAN:
- WifiNative.setScanResultHandlingCommand(SCAN_ONLY_MODE);
- WifiNative.scanCommand(message.arg1 == SCAN_ACTIVE);
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- class HandshakeState extends HierarchicalState {
- @Override
- public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
- final Message message = getCurrentMessage();
- StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
-
- mNetworkInfo.setIsAvailable(true);
-
- if (mLoopDetectIndex > message.what) {
- mLoopDetectCount++;
- }
- if (mLoopDetectCount > MAX_SUPPLICANT_LOOP_ITERATIONS) {
- WifiNative.disableNetworkCommand(stateChangeResult.networkId);
- mLoopDetectCount = 0;
- }
-
- mLoopDetectIndex = message.what;
-
- mPasswordKeyMayBeIncorrect = false;
- sendSupplicantStateChangedBroadcast(stateChangeResult, false);
- }
- @Override
- public boolean processMessage(Message message) {
- return handleTransition(message);
- }
- }
-
- class CompletedState extends HierarchicalState {
- @Override
- public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
- Message message = getCurrentMessage();
- StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
-
- mNetworkInfo.setIsAvailable(true);
-
- mRssiPollToken++;
- if (mEnableRssiPolling) {
- sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, mRssiPollToken, 0),
- POLL_RSSI_INTERVAL_MSECS);
- }
-
- resetLoopDetection();
-
- mPasswordKeyMayBeIncorrect = false;
- sendSupplicantStateChangedBroadcast(stateChangeResult, false);
- }
- @Override
- public boolean processMessage(Message message) {
- switch(message.what) {
- case ASSOCIATING:
- case ASSOCIATED:
- case FOUR_WAY_HANDSHAKE:
- case GROUP_HANDSHAKE:
- case COMPLETED:
- break;
- case CMD_RSSI_POLL:
- if (message.arg1 == mRssiPollToken) {
- // Get Info and continue polling
- requestPolledInfo();
- sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, mRssiPollToken, 0),
- POLL_RSSI_INTERVAL_MSECS);
- } else {
- // Polling has completed
- }
- break;
- case CMD_ENABLE_RSSI_POLL:
- mRssiPollToken++;
- if (mEnableRssiPolling) {
- // first poll
- requestPolledInfo();
- sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, mRssiPollToken, 0),
- POLL_RSSI_INTERVAL_MSECS);
- }
- break;
- default:
- return handleTransition(message);
- }
- return HANDLED;
- }
- }
-
- class DormantState extends HierarchicalState {
- @Override
- public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
- Message message = getCurrentMessage();
- StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
-
- mNetworkInfo.setIsAvailable(true);
- resetLoopDetection();
- mPasswordKeyMayBeIncorrect = false;
-
- sendSupplicantStateChangedBroadcast(stateChangeResult, false);
-
- /* TODO: reconnect is now being handled at DHCP failure handling
- * If we run into issues with staying in Dormant state, might
- * need a reconnect here
- */
- }
- @Override
- public boolean processMessage(Message message) {
- return handleTransition(message);
- }
- }
- }
-
- private class NotificationEnabledSettingObserver extends ContentObserver {
-
- public NotificationEnabledSettingObserver(Handler handler) {
- super(handler);
- }
-
- public void register() {
- ContentResolver cr = mContext.getContentResolver();
- cr.registerContentObserver(Settings.Secure.getUriFor(
- Settings.Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON), true, this);
- mNotificationEnabled = getValue();
- }
-
- @Override
- public void onChange(boolean selfChange) {
- super.onChange(selfChange);
-
- mNotificationEnabled = getValue();
- if (!mNotificationEnabled) {
- // Remove any notification that may be showing
- setNotificationVisible(false, 0, true, 0);
- }
-
- resetNotificationTimer();
- }
-
- private boolean getValue() {
- return Settings.Secure.getInt(mContext.getContentResolver(),
- Settings.Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 1) == 1;
- }
- }
-}
+} \ No newline at end of file