am eadf1959: Merge "Track IP addresses in WifiStateMachine." into klp-dev

* commit 'eadf1959fbe2602f2c2b64ab0c4cd71a57d4f98c':
  Track IP addresses in WifiStateMachine.
This commit is contained in:
Lorenzo Colitti
2013-09-05 20:32:32 -07:00
committed by Android Git Automerger

View File

@@ -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());
}
mLinkProperties.setHttpProxy(mWifiConfigStore.getProxyProperties(mLastNetworkId));
}
mLinkProperties.setInterfaceName(mInterfaceName);
if (DBG) log("netId=" + mLastNetworkId + " Link configured: " + mLinkProperties);
// 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();
}
}
}
/**
* 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();