diff options
| -rw-r--r-- | core/java/android/net/DhcpInfo.java | 13 | ||||
| -rw-r--r-- | core/java/android/provider/Settings.java | 1 | ||||
| -rw-r--r-- | wifi/java/android/net/wifi/WifiConfigStore.java | 361 | ||||
| -rw-r--r-- | wifi/java/android/net/wifi/WifiConfiguration.java | 43 | ||||
| -rw-r--r-- | wifi/java/android/net/wifi/WifiStateMachine.java | 201 |
5 files changed, 421 insertions, 198 deletions
diff --git a/core/java/android/net/DhcpInfo.java b/core/java/android/net/DhcpInfo.java index 1178bec..9c81c19 100644 --- a/core/java/android/net/DhcpInfo.java +++ b/core/java/android/net/DhcpInfo.java @@ -37,6 +37,19 @@ public class DhcpInfo implements Parcelable { super(); } + /** copy constructor {@hide} */ + public DhcpInfo(DhcpInfo source) { + if (source != null) { + ipAddress = source.ipAddress; + gateway = source.gateway; + netmask = source.netmask; + dns1 = source.dns1; + dns2 = source.dns2; + serverAddress = source.serverAddress; + leaseDuration = source.leaseDuration; + } + } + public String toString() { StringBuffer str = new StringBuffer(); diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index e1c84ef..5b4aedb 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -1128,6 +1128,7 @@ public final class Settings { */ public static final int WIFI_SLEEP_POLICY_NEVER = 2; + //TODO: deprecate static IP constants /** * Whether to use static IP and other static network attributes. * <p> diff --git a/wifi/java/android/net/wifi/WifiConfigStore.java b/wifi/java/android/net/wifi/WifiConfigStore.java index 78d5b7e..dfa9f75 100644 --- a/wifi/java/android/net/wifi/WifiConfigStore.java +++ b/wifi/java/android/net/wifi/WifiConfigStore.java @@ -19,12 +19,22 @@ package android.net.wifi; import android.app.ActivityManagerNative; import android.content.Context; import android.content.Intent; +import android.net.DhcpInfo; +import android.net.wifi.WifiConfiguration.IpAssignment; +import android.net.wifi.WifiConfiguration.KeyMgmt; import android.net.wifi.WifiConfiguration.Status; +import android.os.Environment; import android.text.TextUtils; import android.util.Log; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileWriter; +import java.io.IOException; import java.util.ArrayList; import java.util.BitSet; +import java.util.HashMap; import java.util.List; /** @@ -34,9 +44,23 @@ import java.util.List; * * It deals with the following * - Add/update/remove a WifiConfiguration + * The configuration contains two types of information. + * = IP configuration that is handled by WifiConfigStore and + * is saved to disk on any change. + * = SSID & security details that is pushed to the supplicant. + * supplicant saves these details to the disk on calling + * saveConfigCommand(). + * + * We have two kinds of APIs exposed: + * > public API calls that provide fine grained control + * - enableNetwork, disableNetwork, addOrUpdateNetwork(), + * removeNetwork(). For these calls, the config is not persisted + * to the disk. (TODO: deprecate these calls in WifiManager) + * > The new API calls - selectNetwork(), saveNetwork() & forgetNetwork(). + * These calls persist the supplicant config to disk. * - Maintain a list of configured networks for quick access + * * TODO: - * - handle static IP per configuration * - handle proxy per configuration */ class WifiConfigStore { @@ -44,10 +68,28 @@ class WifiConfigStore { private static Context sContext; private static final String TAG = "WifiConfigStore"; - private static List<WifiConfiguration> sConfiguredNetworks = new ArrayList<WifiConfiguration>(); + /* configured networks with network id as the key */ + private static HashMap<Integer, WifiConfiguration> sConfiguredNetworks = + new HashMap<Integer, WifiConfiguration>(); + + /* A network id is a unique identifier for a network configured in the + * supplicant. Network ids are generated when the supplicant reads + * the configuration file at start and can thus change for networks. + * We store the IP configuration for networks along with a unique id + * that is generated from SSID and security type of the network. A mapping + * from the generated unique id to network id of the network is needed to + * map supplicant config to IP configuration. */ + private static HashMap<Integer, Integer> sNetworkIds = + new HashMap<Integer, Integer>(); + /* Tracks the highest priority of configured networks */ private static int sLastPriority = -1; + private static final String ipConfigFile = Environment.getDataDirectory() + + "/misc/wifi/ipconfig.txt"; + + private static final int IPCONFIG_FILE_VERSION = 1; + /** * Initialize context, fetch the list of configured networks * and enable all stored networks in supplicant. @@ -66,7 +108,7 @@ class WifiConfigStore { static List<WifiConfiguration> getConfiguredNetworks() { List<WifiConfiguration> networks = new ArrayList<WifiConfiguration>(); synchronized (sConfiguredNetworks) { - for (WifiConfiguration config : sConfiguredNetworks) { + for(WifiConfiguration config : sConfiguredNetworks.values()) { networks.add(config.clone()); } } @@ -78,14 +120,20 @@ class WifiConfigStore { * of configured networks indicates all networks as being enabled */ static void enableAllNetworks() { - for (WifiConfiguration config : sConfiguredNetworks) { - if(config != null && config.status == Status.DISABLED) { - WifiNative.enableNetworkCommand(config.networkId, false); + synchronized (sConfiguredNetworks) { + for(WifiConfiguration config : sConfiguredNetworks.values()) { + if(config != null && config.status == Status.DISABLED) { + if(WifiNative.enableNetworkCommand(config.networkId, false)) { + config.status = Status.ENABLED; + } else { + Log.e(TAG, "Enable network failed on " + config.networkId); + } + } } } WifiNative.saveConfigCommand(); - updateConfigAndSendChangeBroadcast(); + sendConfigChangeBroadcast(); } /** @@ -102,7 +150,11 @@ class WifiConfigStore { static void selectNetwork(WifiConfiguration config) { if (config != null) { int netId = addOrUpdateNetworkNative(config); - selectNetwork(netId); + if (netId != -1) { + selectNetwork(netId); + } else { + Log.e(TAG, "Failed to update network " + config); + } } } @@ -120,10 +172,12 @@ class WifiConfigStore { static void selectNetwork(int netId) { // Reset the priority of each network at start or if it goes too high. if (sLastPriority == -1 || sLastPriority > 1000000) { - for (WifiConfiguration conf : sConfiguredNetworks) { - if (conf.networkId != -1) { - conf.priority = 0; - addOrUpdateNetworkNative(conf); + synchronized (sConfiguredNetworks) { + for(WifiConfiguration config : sConfiguredNetworks.values()) { + if (config.networkId != -1) { + config.priority = 0; + addOrUpdateNetworkNative(config); + } } } sLastPriority = 0; @@ -138,13 +192,10 @@ class WifiConfigStore { WifiNative.saveConfigCommand(); /* Enable the given network while disabling all other networks */ - WifiNative.enableNetworkCommand(netId, true); + enableNetworkWithoutBroadcast(netId, true); - /* update the configured networks list but not send a - * broadcast to avoid a fetch from settings - * during this temporary disabling of networks - */ - updateConfiguredNetworks(); + /* Avoid saving the config & sending a broadcast to prevent settings + * from displaying a disabled list of networks */ } /** @@ -153,13 +204,17 @@ class WifiConfigStore { * @param config WifiConfiguration to be saved */ static void saveNetwork(WifiConfiguration config) { + boolean newNetwork = (config.networkId == -1); int netId = addOrUpdateNetworkNative(config); /* enable a new network */ - if (config.networkId < 0) { + if (newNetwork && netId >= 0) { WifiNative.enableNetworkCommand(netId, false); + synchronized (sConfiguredNetworks) { + sConfiguredNetworks.get(netId).status = Status.ENABLED; + } } WifiNative.saveConfigCommand(); - updateConfigAndSendChangeBroadcast(); + sendConfigChangeBroadcast(); } /** @@ -168,9 +223,15 @@ class WifiConfigStore { * @param netId network to forget */ static void forgetNetwork(int netId) { - WifiNative.removeNetworkCommand(netId); - WifiNative.saveConfigCommand(); - updateConfigAndSendChangeBroadcast(); + if (WifiNative.removeNetworkCommand(netId)) { + WifiNative.saveConfigCommand(); + synchronized (sConfiguredNetworks) { + sConfiguredNetworks.remove(netId); + } + sendConfigChangeBroadcast(); + } else { + Log.e(TAG, "Failed to remove network " + netId); + } } /** @@ -183,7 +244,7 @@ class WifiConfigStore { */ static int addOrUpdateNetwork(WifiConfiguration config) { int ret = addOrUpdateNetworkNative(config); - updateConfigAndSendChangeBroadcast(); + sendConfigChangeBroadcast(); return ret; } @@ -197,7 +258,10 @@ class WifiConfigStore { */ static boolean removeNetwork(int netId) { boolean ret = WifiNative.removeNetworkCommand(netId); - updateConfigAndSendChangeBroadcast(); + synchronized (sConfiguredNetworks) { + if (ret) sConfiguredNetworks.remove(netId); + } + sendConfigChangeBroadcast(); return ret; } @@ -210,8 +274,28 @@ class WifiConfigStore { * @param netId network to be removed */ static boolean enableNetwork(int netId, boolean disableOthers) { + boolean ret = enableNetworkWithoutBroadcast(netId, disableOthers); + sendConfigChangeBroadcast(); + return ret; + } + + static boolean enableNetworkWithoutBroadcast(int netId, boolean disableOthers) { boolean ret = WifiNative.enableNetworkCommand(netId, disableOthers); - updateConfigAndSendChangeBroadcast(); + + synchronized (sConfiguredNetworks) { + WifiConfiguration config = sConfiguredNetworks.get(netId); + if (config != null) config.status = Status.ENABLED; + } + + if (disableOthers) { + synchronized (sConfiguredNetworks) { + for(WifiConfiguration config : sConfiguredNetworks.values()) { + if(config != null && config.networkId != netId) { + config.status = Status.DISABLED; + } + } + } + } return ret; } @@ -221,7 +305,11 @@ class WifiConfigStore { */ static boolean disableNetwork(int netId) { boolean ret = WifiNative.disableNetworkCommand(netId); - updateConfigAndSendChangeBroadcast(); + synchronized (sConfiguredNetworks) { + WifiConfiguration config = sConfiguredNetworks.get(netId); + if (config != null) config.status = Status.DISABLED; + } + sendConfigChangeBroadcast(); return ret; } @@ -232,8 +320,31 @@ class WifiConfigStore { return WifiNative.saveConfigCommand(); } - private static void updateConfigAndSendChangeBroadcast() { - updateConfiguredNetworks(); + /** + * Fetch the IP configuration for a given network id + */ + static DhcpInfo getIpConfiguration(int netId) { + synchronized (sConfiguredNetworks) { + WifiConfiguration config = sConfiguredNetworks.get(netId); + if (config != null) return new DhcpInfo(config.ipConfig); + } + return null; + } + + /** + * Return if the specified network is using static IP + */ + static boolean isUsingStaticIp(int netId) { + synchronized (sConfiguredNetworks) { + WifiConfiguration config = sConfiguredNetworks.get(netId); + if (config != null && config.ipAssignment == IpAssignment.STATIC) { + return true; + } + } + return false; + } + + private static void sendConfigChangeBroadcast() { if (!ActivityManagerNative.isSystemReady()) return; Intent intent = new Intent(WifiManager.SUPPLICANT_CONFIG_CHANGED_ACTION); sContext.sendBroadcast(intent); @@ -245,6 +356,7 @@ class WifiConfigStore { synchronized (sConfiguredNetworks) { sConfiguredNetworks.clear(); + sNetworkIds.clear(); if (listStr == null) return; @@ -274,9 +386,129 @@ class WifiConfigStore { if (config.priority > sLastPriority) { sLastPriority = config.priority; } - sConfiguredNetworks.add(config); + sConfiguredNetworks.put(config.networkId, config); + sNetworkIds.put(configKey(config), config.networkId); } } + readIpConfigurations(); + } + + private static void writeIpConfigurations() { + StringBuilder builder = new StringBuilder(); + BufferedWriter out = null; + + builder.append(IPCONFIG_FILE_VERSION); + builder.append("\n"); + + synchronized (sConfiguredNetworks) { + for(WifiConfiguration config : sConfiguredNetworks.values()) { + if (config.ipAssignment == WifiConfiguration.IpAssignment.STATIC) { + builder.append("id=" + configKey(config)); + builder.append(":"); + builder.append("ip=" + config.ipConfig.ipAddress); + builder.append(":"); + builder.append("gateway=" + config.ipConfig.gateway); + builder.append(":"); + builder.append("netmask=" + config.ipConfig.netmask); + builder.append(":"); + builder.append("dns1=" + config.ipConfig.dns1); + builder.append(":"); + builder.append("dns2=" + config.ipConfig.dns2); + builder.append("\n"); + } + } + } + + try { + out = new BufferedWriter(new FileWriter(ipConfigFile), builder.length()); + out.write(builder.toString()); + } catch (IOException e) { + Log.e(TAG, "Error writing data file"); + return; + } finally { + if (out != null) { + try { + out.close(); + } catch (Exception e) {} + } + } + } + + private static void readIpConfigurations() { + File f = new File(ipConfigFile); + byte[] buffer; + FileInputStream s = null; + try { + buffer = new byte[(int)f.length()]; + s = new FileInputStream(f); + s.read(buffer); + } catch (IOException e) { + Log.e(TAG, "Error reading data file"); + return; + } finally { + if (s != null) { + try { + s.close(); + } catch (Exception e) {} + } + } + + String data = new String(buffer); + if (data == null || data.length() == 0) { + Log.d(TAG, "IP configuration file empty"); + return; + } + + String[] parsed = data.split("\n"); + try { + if (Integer.parseInt(parsed[0]) != IPCONFIG_FILE_VERSION) { + Log.e(TAG, "Bad version on IP configuration file, ignore read"); + return; + } + + for (String line : parsed) { + int hashKey = -1; + DhcpInfo ipConfig = new DhcpInfo(); + String[] keyVals = line.split(":"); + + for (String keyVal : keyVals) { + String[] keyValPair = keyVal.split("="); + if (keyValPair[0].equals("id")) { + hashKey = Integer.parseInt(keyValPair[1]); + } else if (keyValPair[0].equals("ip")) { + ipConfig.ipAddress = Integer.parseInt(keyValPair[1]); + } else if (keyValPair[0].equals("gateway")) { + ipConfig.gateway = Integer.parseInt(keyValPair[1]); + } else if (keyValPair[0].equals("netmask")) { + ipConfig.netmask = Integer.parseInt(keyValPair[1]); + } else if (keyValPair[0].equals("dns1")) { + ipConfig.dns1 = Integer.parseInt(keyValPair[1]); + } else if (keyValPair[0].equals("dns2")) { + ipConfig.dns2 = Integer.parseInt(keyValPair[1]); + } else { + Log.w(TAG, "Ignoring " + keyVal); + } + } + + if (hashKey != -1) { + synchronized (sConfiguredNetworks) { + WifiConfiguration config = sConfiguredNetworks.get( + sNetworkIds.get(hashKey)); + + if (config == null) { + Log.e(TAG, "IP configuration found for missing network, ignored"); + } else { + config.ipAssignment = WifiConfiguration.IpAssignment.STATIC; + config.ipConfig = ipConfig; + } + } + } else { + Log.e(TAG,"Missing id while parsing configuration" + line); + } + } + } catch (NumberFormatException e) { + Log.e(TAG, "Error parsing configuration"); + } } private static int addOrUpdateNetworkNative(WifiConfiguration config) { @@ -286,6 +518,7 @@ class WifiConfigStore { * refer to an existing configuration. */ int netId = config.networkId; + boolean updateFailed = true; boolean newNetwork = netId == -1; // networkId of -1 means we want to create a new network @@ -457,17 +690,53 @@ class WifiConfigStore { } } } - return netId; + updateFailed = false; } - if (newNetwork) { - WifiNative.removeNetworkCommand(netId); - Log.d(TAG, - "Failed to set a network variable, removed network: " - + netId); + if (updateFailed) { + if (newNetwork) { + WifiNative.removeNetworkCommand(netId); + Log.d(TAG, + "Failed to set a network variable, removed network: " + + netId); + } + return -1; } - return -1; + /* An update of the network variables requires reading them + * back from the supplicant to update sConfiguredNetworks. + * This is because some of the variables (SSID, wep keys & + * passphrases) reflect different values when read back than + * when written. For example, wep key is stored as * irrespective + * of the value sent to the supplicant + */ + WifiConfiguration sConfig; + synchronized (sConfiguredNetworks) { + sConfig = sConfiguredNetworks.get(netId); + } + if (sConfig == null) { + sConfig = new WifiConfiguration(); + sConfig.networkId = netId; + synchronized (sConfiguredNetworks) { + sConfiguredNetworks.put(netId, sConfig); + } + } + readNetworkVariables(sConfig); + + if (config.ipAssignment != IpAssignment.UNASSIGNED) { + if (newNetwork || + (sConfig.ipAssignment != config.ipAssignment) || + (sConfig.ipConfig.ipAddress != config.ipConfig.ipAddress) || + (sConfig.ipConfig.gateway != config.ipConfig.gateway) || + (sConfig.ipConfig.netmask != config.ipConfig.netmask) || + (sConfig.ipConfig.dns1 != config.ipConfig.dns1) || + (sConfig.ipConfig.dns2 != config.ipConfig.dns2)) { + sConfig.ipAssignment = config.ipAssignment; + sConfig.ipConfig = config.ipConfig; + writeIpConfigurations(); + } + } + return netId; } /** @@ -669,6 +938,24 @@ class WifiConfigStore { return -1; } + /* Returns a unique for a given configuration */ + private static int configKey(WifiConfiguration config) { + String key; + + if (config.allowedKeyManagement.get(KeyMgmt.WPA_PSK)) { + key = config.SSID + KeyMgmt.strings[KeyMgmt.WPA_PSK]; + } else if (config.allowedKeyManagement.get(KeyMgmt.WPA_EAP) || + config.allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { + key = config.SSID + KeyMgmt.strings[KeyMgmt.WPA_EAP]; + } else if (config.wepKeys[0] != null) { + key = config.SSID + "WEP"; + } else { + key = config.SSID + KeyMgmt.strings[KeyMgmt.NONE]; + } + + return key.hashCode(); + } + static String dump() { StringBuffer sb = new StringBuffer(); String LS = System.getProperty("line.separator"); diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java index ca4f29f..8971bdd 100644 --- a/wifi/java/android/net/wifi/WifiConfiguration.java +++ b/wifi/java/android/net/wifi/WifiConfiguration.java @@ -16,6 +16,7 @@ package android.net.wifi; +import android.net.DhcpInfo; import android.os.Parcelable; import android.os.Parcel; @@ -294,6 +295,22 @@ public class WifiConfiguration implements Parcelable { */ public BitSet allowedGroupCiphers; + /** + * @hide + */ + public enum IpAssignment { + STATIC, + DHCP, + UNASSIGNED + } + /** + * @hide + */ + public IpAssignment ipAssignment; + /** + * @hide + */ + public DhcpInfo ipConfig; public WifiConfiguration() { networkId = -1; @@ -312,6 +329,8 @@ public class WifiConfiguration implements Parcelable { for (EnterpriseField field : enterpriseFields) { field.setValue(null); } + ipAssignment = IpAssignment.UNASSIGNED; + ipConfig = new DhcpInfo(); } public String toString() { @@ -393,6 +412,11 @@ public class WifiConfiguration implements Parcelable { if (value != null) sbuf.append(value); } sbuf.append('\n'); + if (ipAssignment == IpAssignment.STATIC) { + sbuf.append(" ").append("Static IP configuration:").append('\n'); + sbuf.append(" ").append(ipConfig); + } + sbuf.append('\n'); return sbuf.toString(); } @@ -461,6 +485,8 @@ public class WifiConfiguration implements Parcelable { for (int i = 0; i < enterpriseFields.length; i++) { config.enterpriseFields[i].setValue(enterpriseFields[i].value()); } + config.ipAssignment = ipAssignment; + config.ipConfig = new DhcpInfo(ipConfig); return config; } @@ -486,6 +512,14 @@ public class WifiConfiguration implements Parcelable { for (EnterpriseField field : enterpriseFields) { dest.writeString(field.value()); } + dest.writeString(ipAssignment.name()); + dest.writeInt(ipConfig.ipAddress); + dest.writeInt(ipConfig.netmask); + dest.writeInt(ipConfig.gateway); + dest.writeInt(ipConfig.dns1); + dest.writeInt(ipConfig.dns2); + dest.writeInt(ipConfig.serverAddress); + dest.writeInt(ipConfig.leaseDuration); } /** Implement the Parcelable interface {@hide} */ @@ -512,6 +546,15 @@ public class WifiConfiguration implements Parcelable { for (EnterpriseField field : config.enterpriseFields) { field.setValue(in.readString()); } + + config.ipAssignment = IpAssignment.valueOf(in.readString()); + config.ipConfig.ipAddress = in.readInt(); + config.ipConfig.netmask = in.readInt(); + config.ipConfig.gateway = in.readInt(); + config.ipConfig.dns1 = in.readInt(); + config.ipConfig.dns2 = in.readInt(); + config.ipConfig.serverAddress = in.readInt(); + config.ipConfig.leaseDuration = in.readInt(); return config; } diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java index e1cbf5b..075cca4 100644 --- a/wifi/java/android/net/wifi/WifiStateMachine.java +++ b/wifi/java/android/net/wifi/WifiStateMachine.java @@ -123,10 +123,8 @@ public class WifiStateMachine extends HierarchicalStateMachine { 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 @@ -138,10 +136,6 @@ public class WifiStateMachine extends HierarchicalStateMachine { private BluetoothA2dp mBluetoothA2dp; - /** - * Observes the static IP address settings. - */ - private SettingsObserver mSettingsObserver; private LinkProperties mLinkProperties; // Held during driver load and unload @@ -447,8 +441,6 @@ public class WifiStateMachine extends HierarchicalStateMachine { } }; - mSettingsObserver = new SettingsObserver(new Handler()); - PowerManager powerManager = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE); sWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); @@ -596,7 +588,9 @@ public class WifiStateMachine extends HierarchicalStateMachine { } public DhcpInfo syncGetDhcpInfo() { - return mDhcpInfo; + synchronized (mDhcpInfo) { + return new DhcpInfo(mDhcpInfo); + } } /** @@ -909,10 +903,8 @@ public class WifiStateMachine extends HierarchicalStateMachine { sb.append("mEnableAllNetworks ").append(mEnableAllNetworks).append(LS); sb.append("mEnableRssiPolling ").append(mEnableRssiPolling).append(LS); sb.append("mPasswordKeyMayBeIncorrect ").append(mPasswordKeyMayBeIncorrect).append(LS); - sb.append("mUseStaticIp ").append(mUseStaticIp).append(LS); sb.append("mReconnectCount ").append(mReconnectCount).append(LS); sb.append("mIsScanMode ").append(mIsScanMode).append(LS); - sb.append("mConfigChanged ").append(mConfigChanged).append(LS).append(LS); sb.append("Supplicant status").append(LS) .append(WifiNative.statusCommand()).append(LS).append(LS); @@ -1196,78 +1188,13 @@ public class WifiStateMachine extends HierarchicalStateMachine { return; } // TODO - fix this for v6 - mLinkProperties.addAddress(NetworkUtils.intToInetAddress(mDhcpInfo.ipAddress)); - mLinkProperties.setGateway(NetworkUtils.intToInetAddress(mDhcpInfo.gateway)); - mLinkProperties.addDns(NetworkUtils.intToInetAddress(mDhcpInfo.dns1)); - mLinkProperties.addDns(NetworkUtils.intToInetAddress(mDhcpInfo.dns2)); - // 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); + synchronized (mDhcpInfo) { + mLinkProperties.addAddress(NetworkUtils.intToInetAddress(mDhcpInfo.ipAddress)); + mLinkProperties.setGateway(NetworkUtils.intToInetAddress(mDhcpInfo.gateway)); + mLinkProperties.addDns(NetworkUtils.intToInetAddress(mDhcpInfo.dns1)); + mLinkProperties.addDns(NetworkUtils.intToInetAddress(mDhcpInfo.dns2)); } + // TODO - add proxy info } private int getMaxDhcpRetries() { @@ -1276,60 +1203,6 @@ public class WifiStateMachine extends HierarchicalStateMachine { 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 @@ -1382,6 +1255,7 @@ public class WifiStateMachine extends HierarchicalStateMachine { mContext.sendStickyBroadcast(intent); } + /* TODO: Unused for now, will be used when ip change on connected network is handled */ private void sendConfigChangeBroadcast() { if (!ActivityManagerNative.isSystemReady()) return; Intent intent = new Intent(WifiManager.CONFIG_CHANGED_ACTION); @@ -1969,7 +1843,6 @@ public class WifiStateMachine extends HierarchicalStateMachine { } checkIsBluetoothPlaying(); - checkUseStaticIp(); sendSupplicantConnectionChangedBroadcast(true); transitionTo(mDriverSupReadyState); break; @@ -2477,8 +2350,9 @@ public class WifiStateMachine extends HierarchicalStateMachine { } class ConnectingState extends HierarchicalState { - boolean modifiedBluetoothCoexistenceMode; - int powerMode; + boolean mModifiedBluetoothCoexistenceMode; + int mPowerMode; + boolean mUseStaticIp; Thread mDhcpThread; @Override @@ -2486,11 +2360,11 @@ public class WifiStateMachine extends HierarchicalStateMachine { if (DBG) Log.d(TAG, getName() + "\n"); EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); + mUseStaticIp = WifiConfigStore.isUsingStaticIp(mLastNetworkId); if (!mUseStaticIp) { - mDhcpThread = null; - modifiedBluetoothCoexistenceMode = false; - powerMode = DRIVER_POWER_MODE_AUTO; + mModifiedBluetoothCoexistenceMode = false; + mPowerMode = DRIVER_POWER_MODE_AUTO; if (shouldDisableCoexistenceMode()) { /* @@ -2509,28 +2383,32 @@ public class WifiStateMachine extends HierarchicalStateMachine { * are currently connected to a headset, since disabling * coexistence would interrupt that connection. */ - modifiedBluetoothCoexistenceMode = true; + mModifiedBluetoothCoexistenceMode = true; // Disable the coexistence mode WifiNative.setBluetoothCoexistenceModeCommand( WifiNative.BLUETOOTH_COEXISTENCE_MODE_DISABLED); } - powerMode = WifiNative.getPowerModeCommand(); - if (powerMode < 0) { + mPowerMode = WifiNative.getPowerModeCommand(); + if (mPowerMode < 0) { // Handle the case where supplicant driver does not support // getPowerModeCommand. - powerMode = DRIVER_POWER_MODE_AUTO; + mPowerMode = DRIVER_POWER_MODE_AUTO; } - if (powerMode != DRIVER_POWER_MODE_ACTIVE) { + if (mPowerMode != 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)) { + DhcpInfo dhcpInfo = new DhcpInfo(); + if (NetworkUtils.runDhcp(mInterfaceName, dhcpInfo)) { Log.d(TAG, "DHCP request succeeded"); + synchronized (mDhcpInfo) { + mDhcpInfo = dhcpInfo; + } sendMessage(CMD_IP_CONFIG_SUCCESS); } else { Log.d(TAG, "DHCP request failed: " + @@ -2541,8 +2419,12 @@ public class WifiStateMachine extends HierarchicalStateMachine { }); mDhcpThread.start(); } else { - if (NetworkUtils.configureInterface(mInterfaceName, mDhcpInfo)) { + DhcpInfo dhcpInfo = WifiConfigStore.getIpConfiguration(mLastNetworkId); + if (NetworkUtils.configureInterface(mInterfaceName, dhcpInfo)) { Log.v(TAG, "Static IP configuration succeeded"); + synchronized (mDhcpInfo) { + mDhcpInfo = dhcpInfo; + } sendMessage(CMD_IP_CONFIG_SUCCESS); } else { Log.v(TAG, "Static IP configuration failed"); @@ -2558,18 +2440,15 @@ public class WifiStateMachine extends HierarchicalStateMachine { case CMD_IP_CONFIG_SUCCESS: mReconnectCount = 0; mLastSignalLevel = -1; // force update of signal strength - mWifiInfo.setIpAddress(mDhcpInfo.ipAddress); - Log.d(TAG, "IP configuration: " + mDhcpInfo); + synchronized (mDhcpInfo) { + mWifiInfo.setIpAddress(mDhcpInfo.ipAddress); + Log.d(TAG, "IP configuration: " + mDhcpInfo); + } configureLinkProperties(); 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; - } + //TODO: The framework is not detecting a DHCP renewal and a possible + //IP change. we should detect this and send out a config change broadcast transitionTo(mConnectedState); break; case CMD_IP_CONFIG_FAILURE: @@ -2631,11 +2510,11 @@ public class WifiStateMachine extends HierarchicalStateMachine { public void exit() { /* reset power state & bluetooth coexistence if on DHCP */ if (!mUseStaticIp) { - if (powerMode != DRIVER_POWER_MODE_ACTIVE) { - WifiNative.setPowerModeCommand(powerMode); + if (mPowerMode != DRIVER_POWER_MODE_ACTIVE) { + WifiNative.setPowerModeCommand(mPowerMode); } - if (modifiedBluetoothCoexistenceMode) { + if (mModifiedBluetoothCoexistenceMode) { // Set the coexistence mode back to its default value WifiNative.setBluetoothCoexistenceModeCommand( WifiNative.BLUETOOTH_COEXISTENCE_MODE_SENSE); |
