resolved conflicts for merge of e8d2a4a8 to honeycomb-plus-aosp

Change-Id: I0f1bea54d999ab3ef10400ee67bd4d3b2a5d1783
This commit is contained in:
Robert Greenwalt
2011-07-15 09:55:48 -07:00
3 changed files with 230 additions and 199 deletions

View File

@@ -57,16 +57,16 @@ public class LinkProperties implements Parcelable {
private Collection<RouteInfo> mRoutes = new ArrayList<RouteInfo>(); private Collection<RouteInfo> mRoutes = new ArrayList<RouteInfo>();
private ProxyProperties mHttpProxy; private ProxyProperties mHttpProxy;
public static class CompareAddressesResult { public static class CompareResult<T> {
public ArrayList<LinkAddress> removed = new ArrayList<LinkAddress>(); public ArrayList<T> removed = new ArrayList<T>();
public ArrayList<LinkAddress> added = new ArrayList<LinkAddress>(); public ArrayList<T> added = new ArrayList<T>();
@Override @Override
public String toString() { public String toString() {
String retVal = "removedAddresses=["; String retVal = "removed=[";
for (LinkAddress addr : removed) retVal += addr.toString() + ","; for (T addr : removed) retVal += addr.toString() + ",";
retVal += "] addedAddresses=["; retVal += "] added=[";
for (LinkAddress addr : added) retVal += addr.toString() + ","; for (T addr : added) retVal += addr.toString() + ",";
retVal += "]"; retVal += "]";
return retVal; return retVal;
} }
@@ -263,10 +263,10 @@ public class LinkProperties implements Parcelable {
* mLinkAddress which would then result in target and mLinkAddresses * mLinkAddress which would then result in target and mLinkAddresses
* being the same list. * being the same list.
* *
* @param target is a new list of addresses * @param target is a LinkProperties with the new list of addresses
* @return the removed and added lists. * @return the removed and added lists.
*/ */
public CompareAddressesResult compareAddresses(LinkProperties target) { public CompareResult<LinkAddress> compareAddresses(LinkProperties target) {
/* /*
* Duplicate the LinkAddresses into removed, we will be removing * Duplicate the LinkAddresses into removed, we will be removing
* address which are common between mLinkAddresses and target * address which are common between mLinkAddresses and target
@@ -274,17 +274,81 @@ public class LinkProperties implements Parcelable {
* are in target but not in mLinkAddresses are placed in the * are in target but not in mLinkAddresses are placed in the
* addedAddresses. * addedAddresses.
*/ */
CompareAddressesResult result = new CompareAddressesResult(); CompareResult<LinkAddress> result = new CompareResult<LinkAddress>();
result.removed = new ArrayList<LinkAddress>(mLinkAddresses); result.removed = new ArrayList<LinkAddress>(mLinkAddresses);
result.added.clear(); result.added.clear();
for (LinkAddress newAddress : target.getLinkAddresses()) { if (target != null) {
if (! result.removed.remove(newAddress)) { for (LinkAddress newAddress : target.getLinkAddresses()) {
result.added.add(newAddress); if (! result.removed.remove(newAddress)) {
result.added.add(newAddress);
}
} }
} }
return result; return result;
} }
/**
* Return two lists, a list of dns addresses that would be removed from
* mDnses and a list of addresses that would be added to
* mDnses which would then result in target and mDnses
* being the same list.
*
* @param target is a LinkProperties with the new list of dns addresses
* @return the removed and added lists.
*/
public CompareResult<InetAddress> compareDnses(LinkProperties target) {
/*
* Duplicate the InetAddresses into removed, we will be removing
* dns address which are common between mDnses and target
* leaving the addresses that are different. And dns address which
* are in target but not in mDnses are placed in the
* addedAddresses.
*/
CompareResult<InetAddress> result = new CompareResult<InetAddress>();
result.removed = new ArrayList<InetAddress>(mDnses);
result.added.clear();
if (target != null) {
for (InetAddress newAddress : target.getDnses()) {
if (! result.removed.remove(newAddress)) {
result.added.add(newAddress);
}
}
}
return result;
}
/**
* Return two lists, a list of routes that would be removed from
* mRoutes and a list of routes that would be added to
* mRoutes which would then result in target and mRoutes
* being the same list.
*
* @param target is a LinkProperties with the new list of routes
* @return the removed and added lists.
*/
public CompareResult<RouteInfo> compareRoutes(LinkProperties target) {
/*
* Duplicate the RouteInfos into removed, we will be removing
* routes which are common between mDnses and target
* leaving the routes that are different. And route address which
* are in target but not in mRoutes are placed in added.
*/
CompareResult<RouteInfo> result = new CompareResult<RouteInfo>();
result.removed = new ArrayList<RouteInfo>(mRoutes);
result.added.clear();
if (target != null) {
for (RouteInfo r : target.getRoutes()) {
if (! result.removed.remove(r)) {
result.added.add(r);
}
}
}
return result;
}
@Override @Override
/** /**
* generate hashcode based on significant fields * generate hashcode based on significant fields

View File

@@ -43,6 +43,7 @@ public class RouteInfo implements Parcelable {
private final InetAddress mGateway; private final InetAddress mGateway;
private final boolean mIsDefault; private final boolean mIsDefault;
private final boolean mIsHost;
public RouteInfo(LinkAddress destination, InetAddress gateway) { public RouteInfo(LinkAddress destination, InetAddress gateway) {
if (destination == null) { if (destination == null) {
@@ -68,6 +69,7 @@ public class RouteInfo implements Parcelable {
destination.getNetworkPrefixLength()), destination.getNetworkPrefixLength()); destination.getNetworkPrefixLength()), destination.getNetworkPrefixLength());
mGateway = gateway; mGateway = gateway;
mIsDefault = isDefault(); mIsDefault = isDefault();
mIsHost = isHost();
} }
public RouteInfo(InetAddress gateway) { public RouteInfo(InetAddress gateway) {
@@ -88,6 +90,10 @@ public class RouteInfo implements Parcelable {
} }
} }
private boolean isHost() {
return (mGateway.equals(Inet4Address.ANY) || mGateway.equals(Inet6Address.ANY));
}
private boolean isDefault() { private boolean isDefault() {
boolean val = false; boolean val = false;
if (mGateway != null) { if (mGateway != null) {
@@ -100,6 +106,7 @@ public class RouteInfo implements Parcelable {
return val; return val;
} }
public LinkAddress getDestination() { public LinkAddress getDestination() {
return mDestination; return mDestination;
} }
@@ -112,6 +119,10 @@ public class RouteInfo implements Parcelable {
return mIsDefault; return mIsDefault;
} }
public boolean isHostRoute() {
return mIsHost;
}
public String toString() { public String toString() {
String val = ""; String val = "";
if (mDestination != null) val = mDestination.toString(); if (mDestination != null) val = mDestination.toString();

View File

@@ -28,7 +28,7 @@ import android.net.EthernetDataTracker;
import android.net.IConnectivityManager; import android.net.IConnectivityManager;
import android.net.LinkAddress; import android.net.LinkAddress;
import android.net.LinkProperties; import android.net.LinkProperties;
import android.net.LinkProperties.CompareAddressesResult; import android.net.LinkProperties.CompareResult;
import android.net.MobileDataStateTracker; import android.net.MobileDataStateTracker;
import android.net.NetworkConfig; import android.net.NetworkConfig;
import android.net.NetworkInfo; import android.net.NetworkInfo;
@@ -232,6 +232,10 @@ public class ConnectivityService extends IConnectivityManager.Stub {
private InetAddress mDefaultDns; private InetAddress mDefaultDns;
// this collection is used to refcount the added routes - if there are none left
// it's time to remove the route from the route table
private Collection<RouteInfo> mAddedRoutes = new ArrayList<RouteInfo>();
// used in DBG mode to track inet condition reports // used in DBG mode to track inet condition reports
private static final int INET_CONDITION_LOG_MAX_SIZE = 15; private static final int INET_CONDITION_LOG_MAX_SIZE = 15;
private ArrayList mInetLog; private ArrayList mInetLog;
@@ -451,7 +455,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
mNetConfigs[netType].radio); mNetConfigs[netType].radio);
continue; continue;
} }
mCurrentLinkProperties[netType] = mNetTrackers[netType].getLinkProperties(); mCurrentLinkProperties[netType] = null;
} }
mTethering = new Tethering(mContext, mHandler.getLooper()); mTethering = new Tethering(mContext, mHandler.getLooper());
@@ -936,62 +940,68 @@ public class ConnectivityService extends IConnectivityManager.Stub {
} }
try { try {
InetAddress addr = InetAddress.getByAddress(hostAddress); InetAddress addr = InetAddress.getByAddress(hostAddress);
return addHostRoute(tracker, addr, 0); LinkProperties lp = tracker.getLinkProperties();
return addRoute(lp, RouteInfo.makeHostRoute(addr));
} catch (UnknownHostException e) {} } catch (UnknownHostException e) {}
return false; return false;
} }
/** private boolean addRoute(LinkProperties p, RouteInfo r) {
* Ensure that a network route exists to deliver traffic to the specified return modifyRoute(p.getInterfaceName(), p, r, 0, true);
* host via the mobile data network.
* @param hostAddress the IP address of the host to which the route is desired,
* in network byte order.
* TODO - deprecate
* @return {@code true} on success, {@code false} on failure
*/
private boolean addHostRoute(NetworkStateTracker nt, InetAddress hostAddress, int cycleCount) {
LinkProperties lp = nt.getLinkProperties();
if ((lp == null) || (hostAddress == null)) return false;
String interfaceName = lp.getInterfaceName();
if (DBG) {
log("Requested host route to " + hostAddress + "(" + interfaceName + "), cycleCount=" +
cycleCount);
}
if (interfaceName == null) {
if (DBG) loge("addHostRoute failed due to null interface name");
return false;
}
RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getRoutes(), hostAddress);
InetAddress gatewayAddress = null;
if (bestRoute != null) {
gatewayAddress = bestRoute.getGateway();
// if the best route is ourself, don't relf-reference, just add the host route
if (hostAddress.equals(gatewayAddress)) gatewayAddress = null;
}
if (gatewayAddress != null) {
if (cycleCount > MAX_HOSTROUTE_CYCLE_COUNT) {
loge("Error adding hostroute - too much recursion");
return false;
}
if (!addHostRoute(nt, gatewayAddress, cycleCount+1)) return false;
}
RouteInfo route = RouteInfo.makeHostRoute(hostAddress, gatewayAddress);
try {
mNetd.addRoute(interfaceName, route);
return true;
} catch (Exception ex) {
return false;
}
} }
// TODO support the removal of single host routes. Keep a ref count of them so we private boolean removeRoute(LinkProperties p, RouteInfo r) {
// aren't over-zealous return modifyRoute(p.getInterfaceName(), p, r, 0, false);
private boolean removeHostRoute(NetworkStateTracker nt, InetAddress hostAddress) { }
return false;
private boolean modifyRoute(String ifaceName, LinkProperties lp, RouteInfo r, int cycleCount,
boolean doAdd) {
if ((ifaceName == null) || (lp == null) || (r == null)) return false;
if (cycleCount > MAX_HOSTROUTE_CYCLE_COUNT) {
loge("Error adding route - too much recursion");
return false;
}
if (r.isHostRoute() == false) {
RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getRoutes(), r.getGateway());
if (bestRoute != null) {
if (bestRoute.getGateway().equals(r.getGateway()) == false) {
bestRoute = RouteInfo.makeHostRoute(r.getGateway(), bestRoute.getGateway());
} else {
bestRoute = RouteInfo.makeHostRoute(r.getGateway());
}
if (!modifyRoute(ifaceName, lp, bestRoute, cycleCount+1, doAdd)) return false;
}
}
if (doAdd) {
if (DBG) log("Adding " + r + " for interface " + ifaceName);
mAddedRoutes.add(r);
try {
mNetd.addRoute(ifaceName, r);
} catch (Exception e) {
// never crash - catch them all
loge("Exception trying to add a route: " + e);
return false;
}
} else {
// if we remove this one and there are no more like it, then refcount==0 and
// we can remove it from the table
mAddedRoutes.remove(r);
if (mAddedRoutes.contains(r) == false) {
if (DBG) log("Removing " + r + " for interface " + ifaceName);
try {
mNetd.removeRoute(ifaceName, r);
} catch (Exception e) {
// never crash - catch them all
loge("Exception trying to remove a route: " + e);
return false;
}
} else {
if (DBG) log("not removing " + r + " as it's still in use");
}
}
return true;
} }
/** /**
@@ -1428,10 +1438,11 @@ public class ConnectivityService extends IConnectivityManager.Stub {
*/ */
handleDnsConfigurationChange(netType); handleDnsConfigurationChange(netType);
LinkProperties curLp = mCurrentLinkProperties[netType];
LinkProperties newLp = null;
if (mNetTrackers[netType].getNetworkInfo().isConnected()) { if (mNetTrackers[netType].getNetworkInfo().isConnected()) {
LinkProperties newLp = mNetTrackers[netType].getLinkProperties(); newLp = mNetTrackers[netType].getLinkProperties();
LinkProperties curLp = mCurrentLinkProperties[netType];
mCurrentLinkProperties[netType] = newLp;
if (VDBG) { if (VDBG) {
log("handleConnectivityChange: changed linkProperty[" + netType + "]:" + log("handleConnectivityChange: changed linkProperty[" + netType + "]:" +
" doReset=" + doReset + " resetMask=" + resetMask + " doReset=" + doReset + " resetMask=" + resetMask +
@@ -1439,61 +1450,50 @@ public class ConnectivityService extends IConnectivityManager.Stub {
"\n newLp=" + newLp); "\n newLp=" + newLp);
} }
if (curLp.isIdenticalInterfaceName(newLp)) { if (curLp != null) {
CompareAddressesResult car = curLp.compareAddresses(newLp); if (curLp.isIdenticalInterfaceName(newLp)) {
if ((car.removed.size() != 0) || (car.added.size() != 0)) { CompareResult<LinkAddress> car = curLp.compareAddresses(newLp);
for (LinkAddress linkAddr : car.removed) { if ((car.removed.size() != 0) || (car.added.size() != 0)) {
if (linkAddr.getAddress() instanceof Inet4Address) { for (LinkAddress linkAddr : car.removed) {
resetMask |= NetworkUtils.RESET_IPV4_ADDRESSES; if (linkAddr.getAddress() instanceof Inet4Address) {
resetMask |= NetworkUtils.RESET_IPV4_ADDRESSES;
}
if (linkAddr.getAddress() instanceof Inet6Address) {
resetMask |= NetworkUtils.RESET_IPV6_ADDRESSES;
}
} }
if (linkAddr.getAddress() instanceof Inet6Address) { if (DBG) {
resetMask |= NetworkUtils.RESET_IPV6_ADDRESSES; log("handleConnectivityChange: addresses changed" +
" linkProperty[" + netType + "]:" + " resetMask=" + resetMask +
"\n car=" + car);
}
} else {
if (DBG) {
log("handleConnectivityChange: address are the same reset per doReset" +
" linkProperty[" + netType + "]:" +
" resetMask=" + resetMask);
} }
}
if (DBG) {
log("handleConnectivityChange: addresses changed" +
" linkProperty[" + netType + "]:" + " resetMask=" + resetMask +
"\n car=" + car);
} }
} else { } else {
if (DBG) { resetMask = NetworkUtils.RESET_ALL_ADDRESSES;
log("handleConnectivityChange: address are the same reset per doReset" + log("handleConnectivityChange: interface not not equivalent reset both" +
" linkProperty[" + netType + "]:" + " linkProperty[" + netType + "]:" +
" resetMask=" + resetMask); " resetMask=" + resetMask);
}
} }
} else {
resetMask = NetworkUtils.RESET_ALL_ADDRESSES;
log("handleConnectivityChange: interface not not equivalent reset both" +
" linkProperty[" + netType + "]:" +
" resetMask=" + resetMask);
} }
if (mNetConfigs[netType].isDefault()) { if (mNetConfigs[netType].isDefault()) {
handleApplyDefaultProxy(netType); handleApplyDefaultProxy(netType);
addDefaultRoute(mNetTrackers[netType]);
} else {
// many radios add a default route even when we don't want one.
// remove the default interface unless we need it for our active network
if (mActiveDefaultNetwork != -1) {
LinkProperties linkProperties =
mNetTrackers[mActiveDefaultNetwork].getLinkProperties();
LinkProperties newLinkProperties =
mNetTrackers[netType].getLinkProperties();
String defaultIface = linkProperties.getInterfaceName();
if (defaultIface != null &&
!defaultIface.equals(newLinkProperties.getInterfaceName())) {
removeDefaultRoute(mNetTrackers[netType]);
}
}
addPrivateDnsRoutes(mNetTrackers[netType]);
} }
} else { } else {
if (mNetConfigs[netType].isDefault()) { if (VDBG) {
removeDefaultRoute(mNetTrackers[netType]); log("handleConnectivityChange: changed linkProperty[" + netType + "]:" +
} else { " doReset=" + doReset + " resetMask=" + resetMask +
removePrivateDnsRoutes(mNetTrackers[netType]); "\n curLp=" + curLp +
"\n newLp= null");
} }
} }
mCurrentLinkProperties[netType] = newLp;
updateRoutes(newLp, curLp, mNetConfigs[netType].isDefault());
if (doReset || resetMask != 0) { if (doReset || resetMask != 0) {
LinkProperties linkProperties = mNetTrackers[netType].getLinkProperties(); LinkProperties linkProperties = mNetTrackers[netType].getLinkProperties();
@@ -1517,108 +1517,64 @@ public class ConnectivityService extends IConnectivityManager.Stub {
} }
} }
private void addPrivateDnsRoutes(NetworkStateTracker nt) { /**
boolean privateDnsRouteSet = nt.isPrivateDnsRouteSet(); * Add and remove routes using the old properties (null if not previously connected),
LinkProperties p = nt.getLinkProperties(); * new properties (null if becoming disconnected). May even be double null, which
if (p == null) return; * is a noop.
String interfaceName = p.getInterfaceName(); * Uses isLinkDefault to determine if default routes should be set or conversely if
* host routes should be set to the dns servers
*/
private void updateRoutes(LinkProperties newLp, LinkProperties curLp, boolean isLinkDefault) {
Collection<RouteInfo> routesToAdd = null;
CompareResult<InetAddress> dnsDiff = null;
if (DBG) { if (curLp != null) {
log("addPrivateDnsRoutes for " + nt + // check for the delta between the current set and the new
"(" + interfaceName + ") - mPrivateDnsRouteSet = " + privateDnsRouteSet); CompareResult<RouteInfo> routeDiff = curLp.compareRoutes(newLp);
} dnsDiff = curLp.compareDnses(newLp);
if (interfaceName != null && !privateDnsRouteSet) {
Collection<InetAddress> dnsList = p.getDnses();
for (InetAddress dns : dnsList) {
addHostRoute(nt, dns, 0);
}
nt.privateDnsRouteSet(true);
}
}
private void removePrivateDnsRoutes(NetworkStateTracker nt) { for (RouteInfo r : routeDiff.removed) {
LinkProperties p = nt.getLinkProperties(); if (isLinkDefault || ! r.isDefaultRoute()) {
if (p == null) return; removeRoute(curLp, r);
String interfaceName = p.getInterfaceName();
boolean privateDnsRouteSet = nt.isPrivateDnsRouteSet();
if (interfaceName != null && privateDnsRouteSet) {
if (DBG) {
log("removePrivateDnsRoutes for " + nt.getNetworkInfo().getTypeName() +
" (" + interfaceName + ")");
}
Collection<InetAddress> dnsList = p.getDnses();
for (InetAddress dns : dnsList) {
if (DBG) log(" removing " + dns);
RouteInfo route = RouteInfo.makeHostRoute(dns);
try {
mNetd.removeRoute(interfaceName, route);
} catch (Exception ex) {
loge("error (" + ex + ") removing dns route " + route);
} }
} }
nt.privateDnsRouteSet(false); routesToAdd = routeDiff.added;
} }
}
if (newLp != null) {
// if we didn't get a diff from cur -> new, then just use the new
if (routesToAdd == null) {
routesToAdd = newLp.getRoutes();
}
private void addDefaultRoute(NetworkStateTracker nt) { for (RouteInfo r : routesToAdd) {
LinkProperties p = nt.getLinkProperties(); if (isLinkDefault || ! r.isDefaultRoute()) {
if (p == null) return; addRoute(newLp, r);
String interfaceName = p.getInterfaceName(); }
if (TextUtils.isEmpty(interfaceName)) return; }
}
for (RouteInfo route : p.getRoutes()) { if (!isLinkDefault) {
//TODO - handle non-default routes // handle DNS routes
if (route.isDefaultRoute()) { Collection<InetAddress> dnsToAdd = null;
if (DBG) log("adding default route " + route); if (dnsDiff != null) {
InetAddress gateway = route.getGateway(); dnsToAdd = dnsDiff.added;
if (addHostRoute(nt, gateway, 0)) { for (InetAddress dnsAddress : dnsDiff.removed) {
try { removeRoute(curLp, RouteInfo.makeHostRoute(dnsAddress));
mNetd.addRoute(interfaceName, route); }
} catch (Exception e) { }
loge("error adding default route " + route); if (newLp != null) {
continue; if (dnsToAdd == null) {
} dnsToAdd = newLp.getDnses();
if (DBG) { }
NetworkInfo networkInfo = nt.getNetworkInfo(); for(InetAddress dnsAddress : dnsToAdd) {
log("addDefaultRoute for " + networkInfo.getTypeName() + addRoute(newLp, RouteInfo.makeHostRoute(dnsAddress));
" (" + interfaceName + "), GatewayAddr=" +
gateway.getHostAddress());
}
} else {
loge("error adding host route for default route " + route);
} }
} }
} }
} }
public void removeDefaultRoute(NetworkStateTracker nt) {
LinkProperties p = nt.getLinkProperties();
if (p == null) return;
String interfaceName = p.getInterfaceName();
if (interfaceName == null) return;
for (RouteInfo route : p.getRoutes()) {
//TODO - handle non-default routes
if (route.isDefaultRoute()) {
try {
mNetd.removeRoute(interfaceName, route);
} catch (Exception ex) {
loge("error (" + ex + ") removing default route " + route);
continue;
}
if (DBG) {
NetworkInfo networkInfo = nt.getNetworkInfo();
log("removeDefaultRoute for " + networkInfo.getTypeName() + " (" +
interfaceName + ")");
}
}
}
}
/** /**
* Reads the network specific TCP buffer sizes from SystemProperties * Reads the network specific TCP buffer sizes from SystemProperties
* net.tcp.buffersize.[default|wifi|umts|edge|gprs] and set them for system * net.tcp.buffersize.[default|wifi|umts|edge|gprs] and set them for system