Add stacked interfaces to LinkProperties.
Bug: 8276725 Change-Id: I2f592d4c690e9af0459ae742ab16107a10d89353
This commit is contained in:
@@ -23,10 +23,13 @@ import android.text.TextUtils;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
|
import java.net.Inet4Address;
|
||||||
|
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describes the properties of a network link.
|
* Describes the properties of a network link.
|
||||||
@@ -48,10 +51,15 @@ import java.util.Collections;
|
|||||||
* don't care which is used. The gateways will be
|
* don't care which is used. The gateways will be
|
||||||
* selected based on the destination address and the
|
* selected based on the destination address and the
|
||||||
* source address has no relavence.
|
* source address has no relavence.
|
||||||
|
*
|
||||||
|
* Links can also be stacked on top of each other.
|
||||||
|
* This can be used, for example, to represent a tunnel
|
||||||
|
* interface that runs on top of a physical interface.
|
||||||
|
*
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public class LinkProperties implements Parcelable {
|
public class LinkProperties implements Parcelable {
|
||||||
|
// The interface described by the network link.
|
||||||
private String mIfaceName;
|
private String mIfaceName;
|
||||||
private Collection<LinkAddress> mLinkAddresses = new ArrayList<LinkAddress>();
|
private Collection<LinkAddress> mLinkAddresses = new ArrayList<LinkAddress>();
|
||||||
private Collection<InetAddress> mDnses = new ArrayList<InetAddress>();
|
private Collection<InetAddress> mDnses = new ArrayList<InetAddress>();
|
||||||
@@ -60,6 +68,11 @@ public class LinkProperties implements Parcelable {
|
|||||||
private ProxyProperties mHttpProxy;
|
private ProxyProperties mHttpProxy;
|
||||||
public boolean mLogMe;
|
public boolean mLogMe;
|
||||||
|
|
||||||
|
// Stores the properties of links that are "stacked" above this link.
|
||||||
|
// Indexed by interface name to allow modification and to prevent duplicates being added.
|
||||||
|
private Hashtable<String, LinkProperties> mStackedLinks =
|
||||||
|
new Hashtable<String, LinkProperties>();
|
||||||
|
|
||||||
public static class CompareResult<T> {
|
public static class CompareResult<T> {
|
||||||
public Collection<T> removed = new ArrayList<T>();
|
public Collection<T> removed = new ArrayList<T>();
|
||||||
public Collection<T> added = new ArrayList<T>();
|
public Collection<T> added = new ArrayList<T>();
|
||||||
@@ -90,6 +103,9 @@ public class LinkProperties implements Parcelable {
|
|||||||
for (RouteInfo r : source.getRoutes()) mRoutes.add(r);
|
for (RouteInfo r : source.getRoutes()) mRoutes.add(r);
|
||||||
mHttpProxy = (source.getHttpProxy() == null) ?
|
mHttpProxy = (source.getHttpProxy() == null) ?
|
||||||
null : new ProxyProperties(source.getHttpProxy());
|
null : new ProxyProperties(source.getHttpProxy());
|
||||||
|
for (LinkProperties l: source.mStackedLinks.values()) {
|
||||||
|
addStackedLink(l);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,10 +181,25 @@ public class LinkProperties implements Parcelable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all the routes on this link.
|
||||||
|
*/
|
||||||
public Collection<RouteInfo> getRoutes() {
|
public Collection<RouteInfo> getRoutes() {
|
||||||
return Collections.unmodifiableCollection(mRoutes);
|
return Collections.unmodifiableCollection(mRoutes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all the routes on this link and all the links stacked above it.
|
||||||
|
*/
|
||||||
|
public Collection<RouteInfo> getAllRoutes() {
|
||||||
|
Collection<RouteInfo> routes = new ArrayList();
|
||||||
|
routes.addAll(mRoutes);
|
||||||
|
for (LinkProperties stacked: mStackedLinks.values()) {
|
||||||
|
routes.addAll(stacked.getAllRoutes());
|
||||||
|
}
|
||||||
|
return Collections.unmodifiableCollection(routes);
|
||||||
|
}
|
||||||
|
|
||||||
public void setHttpProxy(ProxyProperties proxy) {
|
public void setHttpProxy(ProxyProperties proxy) {
|
||||||
mHttpProxy = proxy;
|
mHttpProxy = proxy;
|
||||||
}
|
}
|
||||||
@@ -176,6 +207,46 @@ public class LinkProperties implements Parcelable {
|
|||||||
return mHttpProxy;
|
return mHttpProxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a stacked link.
|
||||||
|
*
|
||||||
|
* If there is already a stacked link with the same interfacename as link,
|
||||||
|
* that link is replaced with link. Otherwise, link is added to the list
|
||||||
|
* of stacked links. If link is null, nothing changes.
|
||||||
|
*
|
||||||
|
* @param link The link to add.
|
||||||
|
*/
|
||||||
|
public void addStackedLink(LinkProperties link) {
|
||||||
|
if (link != null && link.getInterfaceName() != null) {
|
||||||
|
mStackedLinks.put(link.getInterfaceName(), link);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a stacked link.
|
||||||
|
*
|
||||||
|
* If there a stacked link with the same interfacename as link, it is
|
||||||
|
* removed. Otherwise, nothing changes.
|
||||||
|
*
|
||||||
|
* @param link The link to add.
|
||||||
|
*/
|
||||||
|
public void removeStackedLink(LinkProperties link) {
|
||||||
|
if (link != null && link.getInterfaceName() != null) {
|
||||||
|
mStackedLinks.remove(link.getInterfaceName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all the links stacked on top of this link.
|
||||||
|
*/
|
||||||
|
public Collection<LinkProperties> getStackedLinks() {
|
||||||
|
Collection<LinkProperties> stacked = new ArrayList<LinkProperties>();
|
||||||
|
for (LinkProperties link : mStackedLinks.values()) {
|
||||||
|
stacked.add(new LinkProperties(link));
|
||||||
|
}
|
||||||
|
return Collections.unmodifiableCollection(stacked);
|
||||||
|
}
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
if (mLogMe) {
|
if (mLogMe) {
|
||||||
Log.d("LinkProperties", "clear from " + mIfaceName);
|
Log.d("LinkProperties", "clear from " + mIfaceName);
|
||||||
@@ -190,6 +261,7 @@ public class LinkProperties implements Parcelable {
|
|||||||
mDomains = null;
|
mDomains = null;
|
||||||
mRoutes.clear();
|
mRoutes.clear();
|
||||||
mHttpProxy = null;
|
mHttpProxy = null;
|
||||||
|
mStackedLinks.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -219,7 +291,29 @@ public class LinkProperties implements Parcelable {
|
|||||||
routes += "] ";
|
routes += "] ";
|
||||||
String proxy = (mHttpProxy == null ? "" : "HttpProxy: " + mHttpProxy.toString() + " ");
|
String proxy = (mHttpProxy == null ? "" : "HttpProxy: " + mHttpProxy.toString() + " ");
|
||||||
|
|
||||||
return ifaceName + linkAddresses + routes + dns + domainName + proxy;
|
String stacked = "";
|
||||||
|
if (mStackedLinks.values().size() > 0) {
|
||||||
|
stacked += " Stacked: [";
|
||||||
|
for (LinkProperties link: mStackedLinks.values()) {
|
||||||
|
stacked += " [" + link.toString() + " ],";
|
||||||
|
}
|
||||||
|
stacked += "] ";
|
||||||
|
}
|
||||||
|
return ifaceName + linkAddresses + routes + dns + domainName + proxy + stacked;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if this link has an IPv4 address.
|
||||||
|
*
|
||||||
|
* @return {@code true} if there is an IPv4 address, {@code false} otherwise.
|
||||||
|
*/
|
||||||
|
public boolean hasIPv4Address() {
|
||||||
|
for (LinkAddress address : mLinkAddresses) {
|
||||||
|
if (address.getAddress() instanceof Inet4Address) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -286,6 +380,26 @@ public class LinkProperties implements Parcelable {
|
|||||||
getHttpProxy().equals(target.getHttpProxy());
|
getHttpProxy().equals(target.getHttpProxy());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compares this {@code LinkProperties} stacked links against the target
|
||||||
|
*
|
||||||
|
* @param target LinkProperties to compare.
|
||||||
|
* @return {@code true} if both are identical, {@code false} otherwise.
|
||||||
|
*/
|
||||||
|
public boolean isIdenticalStackedLinks(LinkProperties target) {
|
||||||
|
if (!mStackedLinks.keys().equals(target.mStackedLinks.keys())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (LinkProperties stacked : mStackedLinks.values()) {
|
||||||
|
// Hashtable values can never be null.
|
||||||
|
String iface = stacked.getInterfaceName();
|
||||||
|
if (!stacked.equals(target.mStackedLinks.get(iface))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
/**
|
/**
|
||||||
* Compares this {@code LinkProperties} instance against the target
|
* Compares this {@code LinkProperties} instance against the target
|
||||||
@@ -298,6 +412,10 @@ public class LinkProperties implements Parcelable {
|
|||||||
* 1. Duplicated elements. eg, (A, B, B) and (A, A, B) are equal.
|
* 1. Duplicated elements. eg, (A, B, B) and (A, A, B) are equal.
|
||||||
* 2. Worst case performance is O(n^2).
|
* 2. Worst case performance is O(n^2).
|
||||||
*
|
*
|
||||||
|
* This method does not check that stacked interfaces are equal, because
|
||||||
|
* stacked interfaces are not so much a property of the link as a
|
||||||
|
* description of connections between links.
|
||||||
|
*
|
||||||
* @param obj the object to be tested for equality.
|
* @param obj the object to be tested for equality.
|
||||||
* @return {@code true} if both objects are equal, {@code false} otherwise.
|
* @return {@code true} if both objects are equal, {@code false} otherwise.
|
||||||
*/
|
*/
|
||||||
@@ -312,7 +430,8 @@ public class LinkProperties implements Parcelable {
|
|||||||
isIdenticalAddresses(target) &&
|
isIdenticalAddresses(target) &&
|
||||||
isIdenticalDnses(target) &&
|
isIdenticalDnses(target) &&
|
||||||
isIdenticalRoutes(target) &&
|
isIdenticalRoutes(target) &&
|
||||||
isIdenticalHttpProxy(target);
|
isIdenticalHttpProxy(target) &&
|
||||||
|
isIdenticalStackedLinks(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -394,10 +513,10 @@ public class LinkProperties implements Parcelable {
|
|||||||
*/
|
*/
|
||||||
CompareResult<RouteInfo> result = new CompareResult<RouteInfo>();
|
CompareResult<RouteInfo> result = new CompareResult<RouteInfo>();
|
||||||
|
|
||||||
result.removed = new ArrayList<RouteInfo>(mRoutes);
|
result.removed = getAllRoutes();
|
||||||
result.added.clear();
|
result.added.clear();
|
||||||
if (target != null) {
|
if (target != null) {
|
||||||
for (RouteInfo r : target.getRoutes()) {
|
for (RouteInfo r : target.getAllRoutes()) {
|
||||||
if (! result.removed.remove(r)) {
|
if (! result.removed.remove(r)) {
|
||||||
result.added.add(r);
|
result.added.add(r);
|
||||||
}
|
}
|
||||||
@@ -419,7 +538,8 @@ public class LinkProperties implements Parcelable {
|
|||||||
+ mDnses.size() * 37
|
+ mDnses.size() * 37
|
||||||
+ ((null == mDomains) ? 0 : mDomains.hashCode())
|
+ ((null == mDomains) ? 0 : mDomains.hashCode())
|
||||||
+ mRoutes.size() * 41
|
+ mRoutes.size() * 41
|
||||||
+ ((null == mHttpProxy) ? 0 : mHttpProxy.hashCode()));
|
+ ((null == mHttpProxy) ? 0 : mHttpProxy.hashCode())
|
||||||
|
+ mStackedLinks.hashCode() * 47);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -449,6 +569,8 @@ public class LinkProperties implements Parcelable {
|
|||||||
} else {
|
} else {
|
||||||
dest.writeByte((byte)0);
|
dest.writeByte((byte)0);
|
||||||
}
|
}
|
||||||
|
ArrayList<LinkProperties> stackedLinks = new ArrayList(mStackedLinks.values());
|
||||||
|
dest.writeList(stackedLinks);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -481,6 +603,11 @@ public class LinkProperties implements Parcelable {
|
|||||||
if (in.readByte() == 1) {
|
if (in.readByte() == 1) {
|
||||||
netProp.setHttpProxy((ProxyProperties)in.readParcelable(null));
|
netProp.setHttpProxy((ProxyProperties)in.readParcelable(null));
|
||||||
}
|
}
|
||||||
|
ArrayList<LinkProperties> stackedLinks = new ArrayList<LinkProperties>();
|
||||||
|
in.readList(stackedLinks, LinkProperties.class.getClassLoader());
|
||||||
|
for (LinkProperties stackedLink: stackedLinks) {
|
||||||
|
netProp.addStackedLink(stackedLink);
|
||||||
|
}
|
||||||
return netProp;
|
return netProp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import android.test.suitebuilder.annotation.SmallTest;
|
|||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public class LinkPropertiesTest extends TestCase {
|
public class LinkPropertiesTest extends TestCase {
|
||||||
private static String ADDRV4 = "75.208.6.1";
|
private static String ADDRV4 = "75.208.6.1";
|
||||||
@@ -255,5 +256,30 @@ public class LinkPropertiesTest extends TestCase {
|
|||||||
assertAllRoutesHaveInterface("p2p0", lp2);
|
assertAllRoutesHaveInterface("p2p0", lp2);
|
||||||
assertEquals(3, lp.compareRoutes(lp2).added.size());
|
assertEquals(3, lp.compareRoutes(lp2).added.size());
|
||||||
assertEquals(3, lp.compareRoutes(lp2).removed.size());
|
assertEquals(3, lp.compareRoutes(lp2).removed.size());
|
||||||
|
|
||||||
|
@SmallTest
|
||||||
|
public void testStackedInterfaces() {
|
||||||
|
LinkProperties rmnet0 = new LinkProperties();
|
||||||
|
rmnet0.setInterfaceName("rmnet0");
|
||||||
|
|
||||||
|
LinkProperties clat4 = new LinkProperties();
|
||||||
|
clat4.setInterfaceName("clat4");
|
||||||
|
|
||||||
|
assertEquals(0, rmnet0.getStackedLinks().size());
|
||||||
|
rmnet0.addStackedLink(clat4);
|
||||||
|
assertEquals(1, rmnet0.getStackedLinks().size());
|
||||||
|
rmnet0.addStackedLink(clat4);
|
||||||
|
assertEquals(1, rmnet0.getStackedLinks().size());
|
||||||
|
assertEquals(0, clat4.getStackedLinks().size());
|
||||||
|
|
||||||
|
// Modify an item in the returned collection to see what happens.
|
||||||
|
for (LinkProperties link : rmnet0.getStackedLinks()) {
|
||||||
|
if (link.getInterfaceName().equals("clat4")) {
|
||||||
|
link.setInterfaceName("newname");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (LinkProperties link : rmnet0.getStackedLinks()) {
|
||||||
|
assertFalse("newname".equals(link.getInterfaceName()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user