LinkProperties function to compare provisioning and remove DNS servers
Adds:
- enum ProvisioningChange
- LinkProperties#compareProvisioning()
return a ProvisioningChange value describing the delta in
provisioning between two LinkProperties objects
- LinkProperties#removeDnsServer()
- make "@hide public" isIPv4Provisioned() and isIPv6Provisioned()
Bug: 18581716
Change-Id: I3df90b2b89617f693346f2dbe72e77c88ce91ffd
This commit is contained in:
@@ -85,6 +85,54 @@ public final class LinkProperties implements Parcelable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public enum ProvisioningChange {
|
||||||
|
STILL_NOT_PROVISIONED,
|
||||||
|
LOST_PROVISIONING,
|
||||||
|
GAINED_PROVISIONING,
|
||||||
|
STILL_PROVISIONED,
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare the provisioning states of two LinkProperties instances.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public static ProvisioningChange compareProvisioning(
|
||||||
|
LinkProperties before, LinkProperties after) {
|
||||||
|
if (before.isProvisioned() && after.isProvisioned()) {
|
||||||
|
// On dualstack networks, DHCPv4 renewals can occasionally fail.
|
||||||
|
// When this happens, IPv6-reachable services continue to function
|
||||||
|
// normally but IPv4-only services (naturally) fail.
|
||||||
|
//
|
||||||
|
// When an application using an IPv4-only service reports a bad
|
||||||
|
// network condition to the framework, attempts to re-validate
|
||||||
|
// the network succeed (since we support IPv6-only networks) and
|
||||||
|
// nothing is changed.
|
||||||
|
//
|
||||||
|
// For users, this is confusing and unexpected behaviour, and is
|
||||||
|
// not necessarily easy to diagnose. Therefore, we treat changing
|
||||||
|
// from a dualstack network to an IPv6-only network equivalent to
|
||||||
|
// a total loss of provisioning.
|
||||||
|
//
|
||||||
|
// For one such example of this, see b/18867306.
|
||||||
|
//
|
||||||
|
// TODO: Remove this special case altogether.
|
||||||
|
if (before.isIPv4Provisioned() && !after.isIPv4Provisioned()) {
|
||||||
|
return ProvisioningChange.LOST_PROVISIONING;
|
||||||
|
}
|
||||||
|
return ProvisioningChange.STILL_PROVISIONED;
|
||||||
|
} else if (before.isProvisioned() && !after.isProvisioned()) {
|
||||||
|
return ProvisioningChange.LOST_PROVISIONING;
|
||||||
|
} else if (!before.isProvisioned() && after.isProvisioned()) {
|
||||||
|
return ProvisioningChange.GAINED_PROVISIONING;
|
||||||
|
} else { // !before.isProvisioned() && !after.isProvisioned()
|
||||||
|
return ProvisioningChange.STILL_NOT_PROVISIONED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
@@ -286,6 +334,20 @@ public final class LinkProperties implements Parcelable {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the given {@link InetAddress} from the list of DNS servers.
|
||||||
|
*
|
||||||
|
* @param dnsServer The {@link InetAddress} to remove from the list of DNS servers.
|
||||||
|
* @return true if the DNS server was removed, false if it did not exist.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public boolean removeDnsServer(InetAddress dnsServer) {
|
||||||
|
if (dnsServer != null) {
|
||||||
|
return mDnses.remove(dnsServer);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replaces the DNS servers in this {@code LinkProperties} with
|
* Replaces the DNS servers in this {@code LinkProperties} with
|
||||||
* the given {@link Collection} of {@link InetAddress} objects.
|
* the given {@link Collection} of {@link InetAddress} objects.
|
||||||
@@ -679,8 +741,9 @@ public final class LinkProperties implements Parcelable {
|
|||||||
* This requires an IP address, default route, and DNS server.
|
* This requires an IP address, default route, and DNS server.
|
||||||
*
|
*
|
||||||
* @return {@code true} if the link is provisioned, {@code false} otherwise.
|
* @return {@code true} if the link is provisioned, {@code false} otherwise.
|
||||||
|
* @hide
|
||||||
*/
|
*/
|
||||||
private boolean hasIPv4() {
|
public boolean isIPv4Provisioned() {
|
||||||
return (hasIPv4Address() &&
|
return (hasIPv4Address() &&
|
||||||
hasIPv4DefaultRoute() &&
|
hasIPv4DefaultRoute() &&
|
||||||
hasIPv4DnsServer());
|
hasIPv4DnsServer());
|
||||||
@@ -691,8 +754,9 @@ public final class LinkProperties implements Parcelable {
|
|||||||
* This requires an IP address, default route, and DNS server.
|
* This requires an IP address, default route, and DNS server.
|
||||||
*
|
*
|
||||||
* @return {@code true} if the link is provisioned, {@code false} otherwise.
|
* @return {@code true} if the link is provisioned, {@code false} otherwise.
|
||||||
|
* @hide
|
||||||
*/
|
*/
|
||||||
private boolean hasIPv6() {
|
public boolean isIPv6Provisioned() {
|
||||||
return (hasGlobalIPv6Address() &&
|
return (hasGlobalIPv6Address() &&
|
||||||
hasIPv6DefaultRoute() &&
|
hasIPv6DefaultRoute() &&
|
||||||
hasIPv6DnsServer());
|
hasIPv6DnsServer());
|
||||||
@@ -706,7 +770,7 @@ public final class LinkProperties implements Parcelable {
|
|||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public boolean isProvisioned() {
|
public boolean isProvisioned() {
|
||||||
return (hasIPv4() || hasIPv6());
|
return (isIPv4Provisioned() || isIPv6Provisioned());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package android.net;
|
package android.net;
|
||||||
|
|
||||||
import android.net.LinkProperties;
|
import android.net.LinkProperties;
|
||||||
|
import android.net.LinkProperties.ProvisioningChange;
|
||||||
import android.net.RouteInfo;
|
import android.net.RouteInfo;
|
||||||
import android.system.OsConstants;
|
import android.system.OsConstants;
|
||||||
import android.test.suitebuilder.annotation.SmallTest;
|
import android.test.suitebuilder.annotation.SmallTest;
|
||||||
@@ -34,7 +35,8 @@ public class LinkPropertiesTest extends TestCase {
|
|||||||
private static InetAddress DNS6 = NetworkUtils.numericToInetAddress("2001:4860:4860::8888");
|
private static InetAddress DNS6 = NetworkUtils.numericToInetAddress("2001:4860:4860::8888");
|
||||||
private static InetAddress GATEWAY1 = NetworkUtils.numericToInetAddress("75.208.8.1");
|
private static InetAddress GATEWAY1 = NetworkUtils.numericToInetAddress("75.208.8.1");
|
||||||
private static InetAddress GATEWAY2 = NetworkUtils.numericToInetAddress("69.78.8.1");
|
private static InetAddress GATEWAY2 = NetworkUtils.numericToInetAddress("69.78.8.1");
|
||||||
private static InetAddress GATEWAY6 = NetworkUtils.numericToInetAddress("fe80::6:0000:613");
|
private static InetAddress GATEWAY61 = NetworkUtils.numericToInetAddress("fe80::6:0000:613");
|
||||||
|
private static InetAddress GATEWAY62 = NetworkUtils.numericToInetAddress("fe80::6:2222");
|
||||||
private static String NAME = "qmi0";
|
private static String NAME = "qmi0";
|
||||||
private static int MTU = 1500;
|
private static int MTU = 1500;
|
||||||
|
|
||||||
@@ -466,6 +468,8 @@ public class LinkPropertiesTest extends TestCase {
|
|||||||
assertFalse("v4only:addr+dns", lp4.isProvisioned());
|
assertFalse("v4only:addr+dns", lp4.isProvisioned());
|
||||||
lp4.addRoute(new RouteInfo(GATEWAY1));
|
lp4.addRoute(new RouteInfo(GATEWAY1));
|
||||||
assertTrue("v4only:addr+dns+route", lp4.isProvisioned());
|
assertTrue("v4only:addr+dns+route", lp4.isProvisioned());
|
||||||
|
assertTrue("v4only:addr+dns+route", lp4.isIPv4Provisioned());
|
||||||
|
assertFalse("v4only:addr+dns+route", lp4.isIPv6Provisioned());
|
||||||
|
|
||||||
LinkProperties lp6 = new LinkProperties();
|
LinkProperties lp6 = new LinkProperties();
|
||||||
assertFalse("v6only:empty", lp6.isProvisioned());
|
assertFalse("v6only:empty", lp6.isProvisioned());
|
||||||
@@ -473,11 +477,14 @@ public class LinkPropertiesTest extends TestCase {
|
|||||||
assertFalse("v6only:fe80-only", lp6.isProvisioned());
|
assertFalse("v6only:fe80-only", lp6.isProvisioned());
|
||||||
lp6.addDnsServer(DNS6);
|
lp6.addDnsServer(DNS6);
|
||||||
assertFalse("v6only:fe80+dns", lp6.isProvisioned());
|
assertFalse("v6only:fe80+dns", lp6.isProvisioned());
|
||||||
lp6.addRoute(new RouteInfo(GATEWAY6));
|
lp6.addRoute(new RouteInfo(GATEWAY61));
|
||||||
assertFalse("v6only:fe80+dns+route", lp6.isProvisioned());
|
assertFalse("v6only:fe80+dns+route", lp6.isProvisioned());
|
||||||
lp6.addLinkAddress(LINKADDRV6);
|
lp6.addLinkAddress(LINKADDRV6);
|
||||||
|
assertTrue("v6only:fe80+global+dns+route", lp6.isIPv6Provisioned());
|
||||||
assertTrue("v6only:fe80+global+dns+route", lp6.isProvisioned());
|
assertTrue("v6only:fe80+global+dns+route", lp6.isProvisioned());
|
||||||
lp6.removeLinkAddress(LINKADDRV6LINKLOCAL);
|
lp6.removeLinkAddress(LINKADDRV6LINKLOCAL);
|
||||||
|
assertFalse("v6only:global+dns+route", lp6.isIPv4Provisioned());
|
||||||
|
assertTrue("v6only:global+dns+route", lp6.isIPv6Provisioned());
|
||||||
assertTrue("v6only:global+dns+route", lp6.isProvisioned());
|
assertTrue("v6only:global+dns+route", lp6.isProvisioned());
|
||||||
|
|
||||||
LinkProperties lp46 = new LinkProperties();
|
LinkProperties lp46 = new LinkProperties();
|
||||||
@@ -487,15 +494,77 @@ public class LinkPropertiesTest extends TestCase {
|
|||||||
lp46.addDnsServer(DNS6);
|
lp46.addDnsServer(DNS6);
|
||||||
assertFalse("dualstack:missing-routes", lp46.isProvisioned());
|
assertFalse("dualstack:missing-routes", lp46.isProvisioned());
|
||||||
lp46.addRoute(new RouteInfo(GATEWAY1));
|
lp46.addRoute(new RouteInfo(GATEWAY1));
|
||||||
|
assertTrue("dualstack:v4-provisioned", lp46.isIPv4Provisioned());
|
||||||
|
assertFalse("dualstack:v4-provisioned", lp46.isIPv6Provisioned());
|
||||||
assertTrue("dualstack:v4-provisioned", lp46.isProvisioned());
|
assertTrue("dualstack:v4-provisioned", lp46.isProvisioned());
|
||||||
lp6.addRoute(new RouteInfo(GATEWAY6));
|
lp46.addRoute(new RouteInfo(GATEWAY61));
|
||||||
|
assertTrue("dualstack:both-provisioned", lp46.isIPv4Provisioned());
|
||||||
|
assertTrue("dualstack:both-provisioned", lp46.isIPv6Provisioned());
|
||||||
assertTrue("dualstack:both-provisioned", lp46.isProvisioned());
|
assertTrue("dualstack:both-provisioned", lp46.isProvisioned());
|
||||||
|
|
||||||
// A link with an IPv6 address and default route, but IPv4 DNS server.
|
// A link with an IPv6 address and default route, but IPv4 DNS server.
|
||||||
LinkProperties mixed = new LinkProperties();
|
LinkProperties mixed = new LinkProperties();
|
||||||
mixed.addLinkAddress(LINKADDRV6);
|
mixed.addLinkAddress(LINKADDRV6);
|
||||||
mixed.addDnsServer(DNS1);
|
mixed.addDnsServer(DNS1);
|
||||||
mixed.addRoute(new RouteInfo(GATEWAY6));
|
mixed.addRoute(new RouteInfo(GATEWAY61));
|
||||||
|
assertFalse("mixed:addr6+route6+dns4", mixed.isIPv4Provisioned());
|
||||||
|
assertFalse("mixed:addr6+route6+dns4", mixed.isIPv6Provisioned());
|
||||||
assertFalse("mixed:addr6+route6+dns4", mixed.isProvisioned());
|
assertFalse("mixed:addr6+route6+dns4", mixed.isProvisioned());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SmallTest
|
||||||
|
public void testCompareProvisioning() {
|
||||||
|
LinkProperties v4lp = new LinkProperties();
|
||||||
|
v4lp.addLinkAddress(LINKADDRV4);
|
||||||
|
v4lp.addRoute(new RouteInfo(GATEWAY1));
|
||||||
|
v4lp.addDnsServer(DNS1);
|
||||||
|
assertTrue(v4lp.isProvisioned());
|
||||||
|
|
||||||
|
LinkProperties v4r = new LinkProperties(v4lp);
|
||||||
|
v4r.removeDnsServer(DNS1);
|
||||||
|
assertFalse(v4r.isProvisioned());
|
||||||
|
|
||||||
|
assertEquals(ProvisioningChange.STILL_NOT_PROVISIONED,
|
||||||
|
LinkProperties.compareProvisioning(v4r, v4r));
|
||||||
|
assertEquals(ProvisioningChange.LOST_PROVISIONING,
|
||||||
|
LinkProperties.compareProvisioning(v4lp, v4r));
|
||||||
|
assertEquals(ProvisioningChange.GAINED_PROVISIONING,
|
||||||
|
LinkProperties.compareProvisioning(v4r, v4lp));
|
||||||
|
assertEquals(ProvisioningChange.STILL_PROVISIONED,
|
||||||
|
LinkProperties.compareProvisioning(v4lp, v4lp));
|
||||||
|
|
||||||
|
// Check that losing IPv4 provisioning on a dualstack network is
|
||||||
|
// seen as a total loss of provisioning.
|
||||||
|
LinkProperties v6lp = new LinkProperties();
|
||||||
|
v6lp.addLinkAddress(LINKADDRV6);
|
||||||
|
v6lp.addRoute(new RouteInfo(GATEWAY61));
|
||||||
|
v6lp.addDnsServer(DNS6);
|
||||||
|
assertFalse(v6lp.isIPv4Provisioned());
|
||||||
|
assertTrue(v6lp.isIPv6Provisioned());
|
||||||
|
assertTrue(v6lp.isProvisioned());
|
||||||
|
|
||||||
|
LinkProperties v46lp = new LinkProperties(v6lp);
|
||||||
|
v46lp.addLinkAddress(LINKADDRV4);
|
||||||
|
v46lp.addRoute(new RouteInfo(GATEWAY1));
|
||||||
|
v46lp.addDnsServer(DNS1);
|
||||||
|
assertTrue(v46lp.isIPv4Provisioned());
|
||||||
|
assertTrue(v46lp.isIPv6Provisioned());
|
||||||
|
assertTrue(v46lp.isProvisioned());
|
||||||
|
|
||||||
|
assertEquals(ProvisioningChange.STILL_PROVISIONED,
|
||||||
|
LinkProperties.compareProvisioning(v6lp, v46lp));
|
||||||
|
assertEquals(ProvisioningChange.LOST_PROVISIONING,
|
||||||
|
LinkProperties.compareProvisioning(v46lp, v6lp));
|
||||||
|
|
||||||
|
// Check that losing and gaining a secondary router does not change
|
||||||
|
// the provisioning status.
|
||||||
|
LinkProperties v6lp2 = new LinkProperties(v6lp);
|
||||||
|
v6lp2.addRoute(new RouteInfo(GATEWAY62));
|
||||||
|
assertTrue(v6lp2.isProvisioned());
|
||||||
|
|
||||||
|
assertEquals(ProvisioningChange.STILL_PROVISIONED,
|
||||||
|
LinkProperties.compareProvisioning(v6lp2, v6lp));
|
||||||
|
assertEquals(ProvisioningChange.STILL_PROVISIONED,
|
||||||
|
LinkProperties.compareProvisioning(v6lp, v6lp2));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user