summaryrefslogtreecommitdiffstats
path: root/wifi
diff options
context:
space:
mode:
authorLorenzo Colitti <lorenzo@google.com>2013-09-06 03:30:14 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2013-09-06 03:30:15 +0000
commiteadf1959fbe2602f2c2b64ab0c4cd71a57d4f98c (patch)
tree949fcd2378e6e28423a6f01999c47ac8503b4e69 /wifi
parent86974463e9e28108e14fa255efd3c429358c0605 (diff)
parent34b2b9b6db7d57993bd71c2b62191c1fc533ebff (diff)
downloadframeworks_base-eadf1959fbe2602f2c2b64ab0c4cd71a57d4f98c.zip
frameworks_base-eadf1959fbe2602f2c2b64ab0c4cd71a57d4f98c.tar.gz
frameworks_base-eadf1959fbe2602f2c2b64ab0c4cd71a57d4f98c.tar.bz2
Merge "Track IP addresses in WifiStateMachine." into klp-dev
Diffstat (limited to 'wifi')
-rw-r--r--wifi/java/android/net/wifi/WifiStateMachine.java185
1 files changed, 151 insertions, 34 deletions
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index d4e98c5..3ccdbea 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -51,6 +51,7 @@ import android.net.LinkProperties;
import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;
import android.net.NetworkUtils;
+import android.net.RouteInfo;
import android.net.wifi.WpsResult.Status;
import android.net.wifi.p2p.WifiP2pManager;
import android.net.wifi.p2p.WifiP2pService;
@@ -79,9 +80,12 @@ import com.android.internal.util.Protocol;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
+import com.android.server.net.BaseNetworkObserver;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.net.InetAddress;
+import java.net.Inet6Address;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
@@ -198,8 +202,19 @@ public class WifiStateMachine extends StateMachine {
/* Tracks sequence number on a driver time out */
private int mDriverStartToken = 0;
+ /**
+ * The link properties of the wifi interface.
+ * Do not modify this directly; use updateLinkProperties instead.
+ */
private LinkProperties mLinkProperties;
+ /**
+ * Subset of link properties coming from netlink.
+ * Currently includes IPv4 and IPv6 addresses. In the future will also include IPv6 DNS servers
+ * and domains obtained from router advertisements (RFC 6106).
+ */
+ private final LinkProperties mNetlinkLinkProperties;
+
/* Tracks sequence number on a periodic scan message */
private int mPeriodicScanToken = 0;
@@ -215,6 +230,39 @@ public class WifiStateMachine extends StateMachine {
private SupplicantStateTracker mSupplicantStateTracker;
private DhcpStateMachine mDhcpStateMachine;
+ private class InterfaceObserver extends BaseNetworkObserver {
+ private WifiStateMachine mWifiStateMachine;
+
+ InterfaceObserver(WifiStateMachine wifiStateMachine) {
+ super();
+ mWifiStateMachine = wifiStateMachine;
+ }
+
+ @Override
+ public void addressUpdated(String address, String iface, int flags, int scope) {
+ if (mWifiStateMachine.mInterfaceName.equals(iface)) {
+ if (DBG) {
+ log("addressUpdated: " + address + " on " + iface +
+ " flags " + flags + " scope " + scope);
+ }
+ mWifiStateMachine.sendMessage(CMD_IP_ADDRESS_UPDATED, new LinkAddress(address));
+ }
+ }
+
+ @Override
+ public void addressRemoved(String address, String iface, int flags, int scope) {
+ if (mWifiStateMachine.mInterfaceName.equals(iface)) {
+ if (DBG) {
+ log("addressRemoved: " + address + " on " + iface +
+ " flags " + flags + " scope " + scope);
+ }
+ mWifiStateMachine.sendMessage(CMD_IP_ADDRESS_REMOVED, new LinkAddress(address));
+ }
+ }
+ }
+
+ private InterfaceObserver mInterfaceObserver;
+
private AlarmManager mAlarmManager;
private PendingIntent mScanIntent;
private PendingIntent mDriverStopIntent;
@@ -372,6 +420,12 @@ public class WifiStateMachine extends StateMachine {
public static final int CMD_START_NEXT_BATCHED_SCAN = BASE + 136;
public static final int CMD_POLL_BATCHED_SCAN = BASE + 137;
+ /* Link configuration (IP address, DNS, ...) changes */
+ /* An new IP address was added to our interface, or an existing IP address was updated */
+ static final int CMD_IP_ADDRESS_UPDATED = BASE + 140;
+ /* An IP address was removed from our interface */
+ static final int CMD_IP_ADDRESS_REMOVED = BASE + 141;
+
public static final int CONNECT_MODE = 1;
public static final int SCAN_ONLY_MODE = 2;
public static final int SCAN_ONLY_WITH_WIFI_OFF_MODE = 3;
@@ -585,15 +639,22 @@ public class WifiStateMachine extends StateMachine {
mSupplicantStateTracker = new SupplicantStateTracker(context, this, mWifiConfigStore,
getHandler());
mLinkProperties = new LinkProperties();
+ mNetlinkLinkProperties = new LinkProperties();
mWifiP2pManager = (WifiP2pManager) mContext.getSystemService(Context.WIFI_P2P_SERVICE);
mNetworkInfo.setIsAvailable(false);
- mLinkProperties.clear();
mLastBssid = null;
mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
mLastSignalLevel = -1;
+ mInterfaceObserver = new InterfaceObserver(this);
+ try {
+ mNwService.registerObserver(mInterfaceObserver);
+ } catch (RemoteException e) {
+ loge("Couldn't register interface observer: " + e.toString());
+ }
+
mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
Intent scanIntent = new Intent(ACTION_START_SCAN, null);
mScanIntent = PendingIntent.getBroadcast(mContext, SCAN_REQUEST, scanIntent, 0);
@@ -1906,19 +1967,82 @@ public class WifiStateMachine extends StateMachine {
}
}
- private void configureLinkProperties() {
- if (mWifiConfigStore.isUsingStaticIp(mLastNetworkId)) {
- mLinkProperties = mWifiConfigStore.getLinkProperties(mLastNetworkId);
- } else {
- synchronized (mDhcpResultsLock) {
- if ((mDhcpResults != null) && (mDhcpResults.linkProperties != null)) {
- mLinkProperties = mDhcpResults.linkProperties;
+ /**
+ * Updates mLinkProperties by merging information from various sources.
+ *
+ * This is needed because the information in mLinkProperties comes from multiple sources (DHCP,
+ * netlink, static configuration, ...). When one of these sources of information has updated
+ * link properties, we can't just assign them to mLinkProperties or we'd lose track of the
+ * information that came from other sources. Instead, when one of those sources has new
+ * information, we update the object that tracks the information from that source and then
+ * call this method to apply the change to mLinkProperties.
+ *
+ * The information in mLinkProperties is currently obtained as follows:
+ * - Interface name: set in the constructor.
+ * - IPv4 and IPv6 addresses: netlink, via mInterfaceObserver.
+ * - IPv4 routes, DNS servers, and domains: DHCP.
+ * - HTTP proxy: the wifi config store.
+ */
+ private void updateLinkProperties() {
+ LinkProperties newLp = new LinkProperties();
+
+ // Interface name and proxy are locally configured.
+ newLp.setInterfaceName(mInterfaceName);
+ newLp.setHttpProxy(mWifiConfigStore.getProxyProperties(mLastNetworkId));
+
+ // IPv4 and IPv6 addresses come from netlink.
+ newLp.setLinkAddresses(mNetlinkLinkProperties.getLinkAddresses());
+
+ // For now, routing and DNS only come from DHCP or static configuration. In the future,
+ // we'll need to merge IPv6 DNS servers and domains coming from netlink.
+ synchronized (mDhcpResultsLock) {
+ // Even when we're using static configuration, we don't need to look at the config
+ // store, because static IP configuration also populates mDhcpResults.
+ if ((mDhcpResults != null) && (mDhcpResults.linkProperties != null)) {
+ LinkProperties lp = mDhcpResults.linkProperties;
+ for (RouteInfo route: lp.getRoutes()) {
+ newLp.addRoute(route);
+ }
+ for (InetAddress dns: lp.getDnses()) {
+ newLp.addDns(dns);
}
+ newLp.setDomains(lp.getDomains());
+ }
+ }
+
+ // If anything has changed, and we're already connected, send out a notification.
+ // If we're still connecting, apps will be notified when we connect.
+ if (!newLp.equals(mLinkProperties)) {
+ if (DBG) {
+ log("Link configuration changed for netId: " + mLastNetworkId
+ + " old: " + mLinkProperties + "new: " + newLp);
+ }
+ mLinkProperties = newLp;
+ if (getNetworkDetailedState() == DetailedState.CONNECTED) {
+ sendLinkConfigurationChangedBroadcast();
}
- mLinkProperties.setHttpProxy(mWifiConfigStore.getProxyProperties(mLastNetworkId));
}
- mLinkProperties.setInterfaceName(mInterfaceName);
- if (DBG) log("netId=" + mLastNetworkId + " Link configured: " + mLinkProperties);
+ }
+
+ /**
+ * Clears all our link properties.
+ */
+ private void clearLinkProperties() {
+ // If the network used DHCP, clear the LinkProperties we stored in the config store.
+ if (!mWifiConfigStore.isUsingStaticIp(mLastNetworkId)) {
+ mWifiConfigStore.clearLinkProperties(mLastNetworkId);
+ }
+
+ // Clear the link properties obtained from DHCP and netlink.
+ synchronized(mDhcpResultsLock) {
+ if (mDhcpResults != null && mDhcpResults.linkProperties != null) {
+ mDhcpResults.linkProperties.clear();
+ }
+ }
+ mNetlinkLinkProperties.clear();
+
+ // Now clear the merged link properties.
+ mLinkProperties.clear();
}
private int getMaxDhcpRetries() {
@@ -2041,16 +2165,11 @@ public class WifiStateMachine extends StateMachine {
mWifiConfigStore.updateStatus(mLastNetworkId, DetailedState.DISCONNECTED);
/* Clear network properties */
- mLinkProperties.clear();
+ clearLinkProperties();
/* send event to CM & network change broadcast */
sendNetworkStateChangeBroadcast(mLastBssid);
- /* Clear IP settings if the network used DHCP */
- if (!mWifiConfigStore.isUsingStaticIp(mLastNetworkId)) {
- mWifiConfigStore.clearLinkProperties(mLastNetworkId);
- }
-
mLastBssid= null;
mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
}
@@ -2149,20 +2268,7 @@ public class WifiStateMachine extends StateMachine {
}
mWifiInfo.setInetAddress(addr);
mWifiInfo.setMeteredHint(dhcpResults.hasMeteredHint());
- if (getNetworkDetailedState() == DetailedState.CONNECTED) {
- //DHCP renewal in connected state
- linkProperties.setHttpProxy(mWifiConfigStore.getProxyProperties(mLastNetworkId));
- if (!linkProperties.equals(mLinkProperties)) {
- if (DBG) {
- log("Link configuration changed for netId: " + mLastNetworkId
- + " old: " + mLinkProperties + "new: " + linkProperties);
- }
- mLinkProperties = linkProperties;
- sendLinkConfigurationChangedBroadcast();
- }
- } else {
- configureLinkProperties();
- }
+ updateLinkProperties();
}
private void handleFailedIpConfiguration() {
@@ -2387,6 +2493,17 @@ public class WifiStateMachine extends StateMachine {
mTemporarilyDisconnectWifi = (message.arg1 == 1);
replyToMessage(message, WifiP2pService.DISCONNECT_WIFI_RESPONSE);
break;
+ case CMD_IP_ADDRESS_UPDATED:
+ // addLinkAddress is a no-op if called more than once with the same address.
+ if (mNetlinkLinkProperties.addLinkAddress((LinkAddress) message.obj)) {
+ updateLinkProperties();
+ }
+ break;
+ case CMD_IP_ADDRESS_REMOVED:
+ if (mNetlinkLinkProperties.removeLinkAddress((LinkAddress) message.obj)) {
+ updateLinkProperties();
+ }
+ break;
default:
loge("Error! unhandled message" + message);
break;
@@ -3405,8 +3522,7 @@ public class WifiStateMachine extends StateMachine {
}
if (result.hasProxyChanged()) {
log("Reconfiguring proxy on connection");
- configureLinkProperties();
- sendLinkConfigurationChangedBroadcast();
+ updateLinkProperties();
}
}
@@ -3460,13 +3576,14 @@ public class WifiStateMachine extends StateMachine {
@Override
public void enter() {
if (!mWifiConfigStore.isUsingStaticIp(mLastNetworkId)) {
+ // TODO: If we're switching between static IP configuration and DHCP, remove the
+ // static configuration first.
startDhcp();
} else {
// stop any running dhcp before assigning static IP
stopDhcp();
DhcpResults dhcpResults = new DhcpResults(
mWifiConfigStore.getLinkProperties(mLastNetworkId));
- dhcpResults.linkProperties.setInterfaceName(mInterfaceName);
InterfaceConfiguration ifcg = new InterfaceConfiguration();
Iterator<LinkAddress> addrs =
dhcpResults.linkProperties.getLinkAddresses().iterator();