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 java.net.InetAddress;
|
||||
import java.net.Inet4Address;
|
||||
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Hashtable;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* selected based on the destination address and the
|
||||
* 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
|
||||
*/
|
||||
public class LinkProperties implements Parcelable {
|
||||
|
||||
// The interface described by the network link.
|
||||
private String mIfaceName;
|
||||
private Collection<LinkAddress> mLinkAddresses = new ArrayList<LinkAddress>();
|
||||
private Collection<InetAddress> mDnses = new ArrayList<InetAddress>();
|
||||
@@ -60,6 +68,11 @@ public class LinkProperties implements Parcelable {
|
||||
private ProxyProperties mHttpProxy;
|
||||
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 Collection<T> removed = 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);
|
||||
mHttpProxy = (source.getHttpProxy() == null) ?
|
||||
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() {
|
||||
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) {
|
||||
mHttpProxy = proxy;
|
||||
}
|
||||
@@ -176,6 +207,46 @@ public class LinkProperties implements Parcelable {
|
||||
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() {
|
||||
if (mLogMe) {
|
||||
Log.d("LinkProperties", "clear from " + mIfaceName);
|
||||
@@ -190,6 +261,7 @@ public class LinkProperties implements Parcelable {
|
||||
mDomains = null;
|
||||
mRoutes.clear();
|
||||
mHttpProxy = null;
|
||||
mStackedLinks.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -219,7 +291,29 @@ public class LinkProperties implements Parcelable {
|
||||
routes += "] ";
|
||||
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());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
/**
|
||||
* 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.
|
||||
* 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.
|
||||
* @return {@code true} if both objects are equal, {@code false} otherwise.
|
||||
*/
|
||||
@@ -312,7 +430,8 @@ public class LinkProperties implements Parcelable {
|
||||
isIdenticalAddresses(target) &&
|
||||
isIdenticalDnses(target) &&
|
||||
isIdenticalRoutes(target) &&
|
||||
isIdenticalHttpProxy(target);
|
||||
isIdenticalHttpProxy(target) &&
|
||||
isIdenticalStackedLinks(target);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -394,10 +513,10 @@ public class LinkProperties implements Parcelable {
|
||||
*/
|
||||
CompareResult<RouteInfo> result = new CompareResult<RouteInfo>();
|
||||
|
||||
result.removed = new ArrayList<RouteInfo>(mRoutes);
|
||||
result.removed = getAllRoutes();
|
||||
result.added.clear();
|
||||
if (target != null) {
|
||||
for (RouteInfo r : target.getRoutes()) {
|
||||
for (RouteInfo r : target.getAllRoutes()) {
|
||||
if (! result.removed.remove(r)) {
|
||||
result.added.add(r);
|
||||
}
|
||||
@@ -419,7 +538,8 @@ public class LinkProperties implements Parcelable {
|
||||
+ mDnses.size() * 37
|
||||
+ ((null == mDomains) ? 0 : mDomains.hashCode())
|
||||
+ 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 {
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import android.test.suitebuilder.annotation.SmallTest;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class LinkPropertiesTest extends TestCase {
|
||||
private static String ADDRV4 = "75.208.6.1";
|
||||
@@ -255,5 +256,30 @@ public class LinkPropertiesTest extends TestCase {
|
||||
assertAllRoutesHaveInterface("p2p0", lp2);
|
||||
assertEquals(3, lp.compareRoutes(lp2).added.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