am 4157cb24: am 02eab434: am 3f58ba89: Merge "If in a mobile captive portal is detected enable fail fast." into jb-mr2-dev
* commit '4157cb2477457e99077d1a69f2de043b3186aa3f':
If in a mobile captive portal is detected enable fail fast.
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index aa2d4ce..1b418fa 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -355,11 +355,17 @@
*/
public static final int TYPE_WIFI_P2P = 13;
- /** {@hide} */
- public static final int MAX_RADIO_TYPE = TYPE_WIFI_P2P;
+ /**
+ * The network to use for initially attaching to the network
+ * {@hide}
+ */
+ public static final int TYPE_MOBILE_IA = 14;
/** {@hide} */
- public static final int MAX_NETWORK_TYPE = TYPE_WIFI_P2P;
+ public static final int MAX_RADIO_TYPE = TYPE_MOBILE_IA;
+
+ /** {@hide} */
+ public static final int MAX_NETWORK_TYPE = TYPE_MOBILE_IA;
/**
* If you want to set the default network preference,you can directly
@@ -436,6 +442,8 @@
return "MOBILE_CBS";
case TYPE_WIFI_P2P:
return "WIFI_P2P";
+ case TYPE_MOBILE_IA:
+ return "MOBILE_IA";
default:
return Integer.toString(type);
}
@@ -458,6 +466,39 @@
case TYPE_MOBILE_FOTA:
case TYPE_MOBILE_IMS:
case TYPE_MOBILE_CBS:
+ case TYPE_MOBILE_IA:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * Checks if the given network type is backed by a Wi-Fi radio.
+ *
+ * @hide
+ */
+ public static boolean isNetworkTypeWifi(int networkType) {
+ switch (networkType) {
+ case TYPE_WIFI:
+ case TYPE_WIFI_P2P:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * Checks if the given network type should be exempt from VPN routing rules
+ *
+ * @hide
+ */
+ public static boolean isNetworkTypeExempt(int networkType) {
+ switch (networkType) {
+ case TYPE_MOBILE_MMS:
+ case TYPE_MOBILE_SUPL:
+ case TYPE_MOBILE_HIPRI:
+ case TYPE_MOBILE_IA:
return true;
default:
return false;
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 3ac5f13..992ec37 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -37,6 +37,9 @@
/** {@hide} */
interface IConnectivityManager
{
+ // Keep this in sync with framework/native/services/connectivitymanager/ConnectivityManager.h
+ void markSocketAsUser(in ParcelFileDescriptor socket, int uid);
+
void setNetworkPreference(int pref);
int getNetworkPreference();
@@ -121,6 +124,8 @@
ParcelFileDescriptor establishVpn(in VpnConfig config);
+ VpnConfig getVpnConfig();
+
void startLegacyVpn(in VpnProfile profile);
LegacyVpnInfo getLegacyVpnInfo();
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 75f8b59..6ab810c 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -128,6 +128,9 @@
return interfaceNames;
}
+ /**
+ * Returns all the addresses on this link.
+ */
public Collection<InetAddress> getAddresses() {
Collection<InetAddress> addresses = new ArrayList<InetAddress>();
for (LinkAddress linkAddress : mLinkAddresses) {
@@ -136,14 +139,43 @@
return Collections.unmodifiableCollection(addresses);
}
+ /**
+ * Returns all the addresses on this link and all the links stacked above it.
+ */
+ public Collection<InetAddress> getAllAddresses() {
+ Collection<InetAddress> addresses = new ArrayList<InetAddress>();
+ for (LinkAddress linkAddress : mLinkAddresses) {
+ addresses.add(linkAddress.getAddress());
+ }
+ for (LinkProperties stacked: mStackedLinks.values()) {
+ addresses.addAll(stacked.getAllAddresses());
+ }
+ return addresses;
+ }
+
public void addLinkAddress(LinkAddress address) {
if (address != null) mLinkAddresses.add(address);
}
+ /**
+ * Returns all the addresses on this link.
+ */
public Collection<LinkAddress> getLinkAddresses() {
return Collections.unmodifiableCollection(mLinkAddresses);
}
+ /**
+ * Returns all the addresses on this link and all the links stacked above it.
+ */
+ public Collection<LinkAddress> getAllLinkAddresses() {
+ Collection<LinkAddress> addresses = new ArrayList<LinkAddress>();
+ addresses.addAll(mLinkAddresses);
+ for (LinkProperties stacked: mStackedLinks.values()) {
+ addresses.addAll(stacked.getAllLinkAddresses());
+ }
+ return addresses;
+ }
+
public void addDns(InetAddress dns) {
if (dns != null) mDnses.add(dns);
}
@@ -426,13 +458,11 @@
}
/**
- * Return two lists, a list of addresses that would be removed from
- * mLinkAddresses and a list of addresses that would be added to
- * mLinkAddress which would then result in target and mLinkAddresses
- * being the same list.
+ * Compares the addresses in this LinkProperties with another
+ * LinkProperties, examining only addresses on the base link.
*
- * @param target is a LinkProperties with the new list of addresses
- * @return the removed and added lists.
+ * @param target a LinkProperties with the new list of addresses
+ * @return the differences between the addresses.
*/
public CompareResult<LinkAddress> compareAddresses(LinkProperties target) {
/*
@@ -456,13 +486,11 @@
}
/**
- * 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.
+ * Compares the DNS addresses in this LinkProperties with another
+ * LinkProperties, examining only DNS addresses on the base link.
*
- * @param target is a LinkProperties with the new list of dns addresses
- * @return the removed and added lists.
+ * @param target a LinkProperties with the new list of dns addresses
+ * @return the differences between the DNS addresses.
*/
public CompareResult<InetAddress> compareDnses(LinkProperties target) {
/*
@@ -487,15 +515,13 @@
}
/**
- * 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.
+ * Compares all routes in this LinkProperties with another LinkProperties,
+ * examining both the the base link and all stacked links.
*
- * @param target is a LinkProperties with the new list of routes
- * @return the removed and added lists.
+ * @param target a LinkProperties with the new list of routes
+ * @return the differences between the routes.
*/
- public CompareResult<RouteInfo> compareRoutes(LinkProperties target) {
+ public CompareResult<RouteInfo> compareAllRoutes(LinkProperties target) {
/*
* Duplicate the RouteInfos into removed, we will be removing
* routes which are common between mRoutes and target
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index 4ab479e..b24d396 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -21,6 +21,7 @@
import java.net.Inet6Address;
import java.net.UnknownHostException;
import java.util.Collection;
+import java.util.Locale;
import android.util.Log;
@@ -103,6 +104,11 @@
public native static String getDhcpError();
/**
+ * Set the SO_MARK of {@code socketfd} to {@code mark}
+ */
+ public native static void markSocket(int socketfd, int mark);
+
+ /**
* Convert a IPv4 address from an integer to an InetAddress.
* @param hostAddress an int corresponding to the IPv4 address in network byte order
*/
@@ -223,7 +229,7 @@
public static InetAddress hexToInet6Address(String addrHexString)
throws IllegalArgumentException {
try {
- return numericToInetAddress(String.format("%s:%s:%s:%s:%s:%s:%s:%s",
+ return numericToInetAddress(String.format(Locale.US, "%s:%s:%s:%s:%s:%s:%s:%s",
addrHexString.substring(0,4), addrHexString.substring(4,8),
addrHexString.substring(8,12), addrHexString.substring(12,16),
addrHexString.substring(16,20), addrHexString.substring(20,24),
diff --git a/core/java/android/net/ProxyProperties.java b/core/java/android/net/ProxyProperties.java
index 9c4772b..76aea9f 100644
--- a/core/java/android/net/ProxyProperties.java
+++ b/core/java/android/net/ProxyProperties.java
@@ -20,9 +20,7 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
-import android.util.Log;
-import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.Locale;
@@ -38,17 +36,30 @@
private String mExclusionList;
private String[] mParsedExclusionList;
+ private String mPacFileUrl;
+ public static final String LOCAL_EXCL_LIST = "";
+ public static final int LOCAL_PORT = 8182;
+ public static final String LOCAL_HOST = "localhost";
+
public ProxyProperties(String host, int port, String exclList) {
mHost = host;
mPort = port;
setExclusionList(exclList);
}
+ public ProxyProperties(String pacFileUrl) {
+ mHost = LOCAL_HOST;
+ mPort = LOCAL_PORT;
+ setExclusionList(LOCAL_EXCL_LIST);
+ mPacFileUrl = pacFileUrl;
+ }
+
private ProxyProperties(String host, int port, String exclList, String[] parsedExclList) {
mHost = host;
mPort = port;
mExclusionList = exclList;
mParsedExclusionList = parsedExclList;
+ mPacFileUrl = null;
}
// copy constructor instead of clone
@@ -56,6 +67,7 @@
if (source != null) {
mHost = source.getHost();
mPort = source.getPort();
+ mPacFileUrl = source.getPacFileUrl();
mExclusionList = source.getExclusionList();
mParsedExclusionList = source.mParsedExclusionList;
}
@@ -69,6 +81,10 @@
return inetSocketAddress;
}
+ public String getPacFileUrl() {
+ return mPacFileUrl;
+ }
+
public String getHost() {
return mHost;
}
@@ -130,7 +146,10 @@
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
- if (mHost != null) {
+ if (mPacFileUrl != null) {
+ sb.append("PAC Script: ");
+ sb.append(mPacFileUrl);
+ } else if (mHost != null) {
sb.append("[");
sb.append(mHost);
sb.append("] ");
@@ -148,6 +167,14 @@
public boolean equals(Object o) {
if (!(o instanceof ProxyProperties)) return false;
ProxyProperties p = (ProxyProperties)o;
+ // If PAC URL is present in either then they must be equal.
+ // Other parameters will only be for fall back.
+ if (!TextUtils.isEmpty(mPacFileUrl)) {
+ return mPacFileUrl.equals(p.getPacFileUrl());
+ }
+ if (!TextUtils.isEmpty(p.getPacFileUrl())) {
+ return false;
+ }
if (mExclusionList != null && !mExclusionList.equals(p.getExclusionList())) return false;
if (mHost != null && p.getHost() != null && mHost.equals(p.getHost()) == false) {
return false;
@@ -181,6 +208,13 @@
* @hide
*/
public void writeToParcel(Parcel dest, int flags) {
+ if (mPacFileUrl != null) {
+ dest.writeByte((byte)1);
+ dest.writeString(mPacFileUrl);
+ return;
+ } else {
+ dest.writeByte((byte)0);
+ }
if (mHost != null) {
dest.writeByte((byte)1);
dest.writeString(mHost);
@@ -201,7 +235,10 @@
public ProxyProperties createFromParcel(Parcel in) {
String host = null;
int port = 0;
- if (in.readByte() == 1) {
+ if (in.readByte() != 0) {
+ return new ProxyProperties(in.readString());
+ }
+ if (in.readByte() != 0) {
host = in.readString();
port = in.readInt();
}
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index faae11e..6d23c32 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "NetUtils"
#include "jni.h"
+#include "JNIHelp.h"
#include <utils/misc.h>
#include <android_runtime/AndroidRuntime.h>
#include <utils/Log.h>
@@ -36,7 +37,8 @@
const char *server,
uint32_t *lease,
const char *vendorInfo,
- const char *domains);
+ const char *domains,
+ const char *mtu);
int dhcp_do_request_renew(const char * const ifname,
const char *ipaddr,
@@ -46,7 +48,8 @@
const char *server,
uint32_t *lease,
const char *vendorInfo,
- const char *domains);
+ const char *domains,
+ const char *mtu);
int dhcp_stop(const char *ifname);
int dhcp_release_lease(const char *ifname);
@@ -125,19 +128,20 @@
uint32_t lease;
char vendorInfo[PROPERTY_VALUE_MAX];
char domains[PROPERTY_VALUE_MAX];
+ char mtu[PROPERTY_VALUE_MAX];
const char *nameStr = env->GetStringUTFChars(ifname, NULL);
if (nameStr == NULL) return (jboolean)false;
if (renew) {
result = ::dhcp_do_request_renew(nameStr, ipaddr, gateway, &prefixLength,
- dns, server, &lease, vendorInfo, domains);
+ dns, server, &lease, vendorInfo, domains, mtu);
} else {
result = ::dhcp_do_request(nameStr, ipaddr, gateway, &prefixLength,
- dns, server, &lease, vendorInfo, domains);
+ dns, server, &lease, vendorInfo, domains, mtu);
}
if (result != 0) {
- ALOGD("dhcp_do_request failed");
+ ALOGD("dhcp_do_request failed : %s (%s)", nameStr, renew ? "renew" : "new");
}
env->ReleaseStringUTFChars(ifname, nameStr);
@@ -239,6 +243,13 @@
return env->NewStringUTF(::dhcp_get_errmsg());
}
+static void android_net_utils_markSocket(JNIEnv *env, jobject thiz, jint socket, jint mark)
+{
+ if (setsockopt(socket, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)) < 0) {
+ jniThrowException(env, "java/lang/IllegalStateException", "Error marking socket");
+ }
+}
+
// ----------------------------------------------------------------------------
/*
@@ -255,6 +266,7 @@
{ "stopDhcp", "(Ljava/lang/String;)Z", (void *)android_net_utils_stopDhcp },
{ "releaseDhcpLease", "(Ljava/lang/String;)Z", (void *)android_net_utils_releaseDhcpLease },
{ "getDhcpError", "()Ljava/lang/String;", (void*) android_net_utils_getDhcpError },
+ { "markSocket", "(II)V", (void*) android_net_utils_markSocket },
};
int register_android_net_NetworkUtils(JNIEnv* env)
diff --git a/core/tests/coretests/src/android/net/LinkPropertiesTest.java b/core/tests/coretests/src/android/net/LinkPropertiesTest.java
index d6a7ee2..9fdfd0e 100644
--- a/core/tests/coretests/src/android/net/LinkPropertiesTest.java
+++ b/core/tests/coretests/src/android/net/LinkPropertiesTest.java
@@ -25,14 +25,18 @@
import java.util.ArrayList;
public class LinkPropertiesTest extends TestCase {
- private static String ADDRV4 = "75.208.6.1";
- private static String ADDRV6 = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";
- private static String DNS1 = "75.208.7.1";
- private static String DNS2 = "69.78.7.1";
- private static String GATEWAY1 = "75.208.8.1";
- private static String GATEWAY2 = "69.78.8.1";
+ private static InetAddress ADDRV4 = NetworkUtils.numericToInetAddress("75.208.6.1");
+ private static InetAddress ADDRV6 = NetworkUtils.numericToInetAddress(
+ "2001:0db8:85a3:0000:0000:8a2e:0370:7334");
+ private static InetAddress DNS1 = NetworkUtils.numericToInetAddress("75.208.7.1");
+ private static InetAddress DNS2 = NetworkUtils.numericToInetAddress("69.78.7.1");
+ private static InetAddress GATEWAY1 = NetworkUtils.numericToInetAddress("75.208.8.1");
+ private static InetAddress GATEWAY2 = NetworkUtils.numericToInetAddress("69.78.8.1");
private static String NAME = "qmi0";
+ private static LinkAddress LINKADDRV4 = new LinkAddress(ADDRV4, 32);
+ private static LinkAddress LINKADDRV6 = new LinkAddress(ADDRV6, 128);
+
public void assertLinkPropertiesEqual(LinkProperties source, LinkProperties target) {
// Check implementation of equals(), element by element.
assertTrue(source.isIdenticalInterfaceName(target));
@@ -76,43 +80,37 @@
LinkProperties source = new LinkProperties();
source.setInterfaceName(NAME);
// set 2 link addresses
- source.addLinkAddress(new LinkAddress(
- NetworkUtils.numericToInetAddress(ADDRV4), 32));
- source.addLinkAddress(new LinkAddress(
- NetworkUtils.numericToInetAddress(ADDRV6), 128));
+ source.addLinkAddress(LINKADDRV4);
+ source.addLinkAddress(LINKADDRV6);
// set 2 dnses
- source.addDns(NetworkUtils.numericToInetAddress(DNS1));
- source.addDns(NetworkUtils.numericToInetAddress(DNS2));
+ source.addDns(DNS1);
+ source.addDns(DNS2);
// set 2 gateways
- source.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY1)));
- source.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY2)));
+ source.addRoute(new RouteInfo(GATEWAY1));
+ source.addRoute(new RouteInfo(GATEWAY2));
LinkProperties target = new LinkProperties();
// All fields are same
target.setInterfaceName(NAME);
- target.addLinkAddress(new LinkAddress(
- NetworkUtils.numericToInetAddress(ADDRV4), 32));
- target.addLinkAddress(new LinkAddress(
- NetworkUtils.numericToInetAddress(ADDRV6), 128));
- target.addDns(NetworkUtils.numericToInetAddress(DNS1));
- target.addDns(NetworkUtils.numericToInetAddress(DNS2));
- target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY1)));
- target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY2)));
+ target.addLinkAddress(LINKADDRV4);
+ target.addLinkAddress(LINKADDRV6);
+ target.addDns(DNS1);
+ target.addDns(DNS2);
+ target.addRoute(new RouteInfo(GATEWAY1));
+ target.addRoute(new RouteInfo(GATEWAY2));
assertLinkPropertiesEqual(source, target);
target.clear();
// change Interface Name
target.setInterfaceName("qmi1");
- target.addLinkAddress(new LinkAddress(
- NetworkUtils.numericToInetAddress(ADDRV4), 32));
- target.addLinkAddress(new LinkAddress(
- NetworkUtils.numericToInetAddress(ADDRV6), 128));
- target.addDns(NetworkUtils.numericToInetAddress(DNS1));
- target.addDns(NetworkUtils.numericToInetAddress(DNS2));
- target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY1)));
- target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY2)));
+ target.addLinkAddress(LINKADDRV4);
+ target.addLinkAddress(LINKADDRV6);
+ target.addDns(DNS1);
+ target.addDns(DNS2);
+ target.addRoute(new RouteInfo(GATEWAY1));
+ target.addRoute(new RouteInfo(GATEWAY2));
assertFalse(source.equals(target));
target.clear();
@@ -120,38 +118,33 @@
// change link addresses
target.addLinkAddress(new LinkAddress(
NetworkUtils.numericToInetAddress("75.208.6.2"), 32));
- target.addLinkAddress(new LinkAddress(
- NetworkUtils.numericToInetAddress(ADDRV6), 128));
- target.addDns(NetworkUtils.numericToInetAddress(DNS1));
- target.addDns(NetworkUtils.numericToInetAddress(DNS2));
- target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY1)));
- target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY2)));
+ target.addLinkAddress(LINKADDRV6);
+ target.addDns(DNS1);
+ target.addDns(DNS2);
+ target.addRoute(new RouteInfo(GATEWAY1));
+ target.addRoute(new RouteInfo(GATEWAY2));
assertFalse(source.equals(target));
target.clear();
target.setInterfaceName(NAME);
- target.addLinkAddress(new LinkAddress(
- NetworkUtils.numericToInetAddress(ADDRV4), 32));
- target.addLinkAddress(new LinkAddress(
- NetworkUtils.numericToInetAddress(ADDRV6), 128));
+ target.addLinkAddress(LINKADDRV4);
+ target.addLinkAddress(LINKADDRV6);
// change dnses
target.addDns(NetworkUtils.numericToInetAddress("75.208.7.2"));
- target.addDns(NetworkUtils.numericToInetAddress(DNS2));
- target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY1)));
- target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY2)));
+ target.addDns(DNS2);
+ target.addRoute(new RouteInfo(GATEWAY1));
+ target.addRoute(new RouteInfo(GATEWAY2));
assertFalse(source.equals(target));
target.clear();
target.setInterfaceName(NAME);
- target.addLinkAddress(new LinkAddress(
- NetworkUtils.numericToInetAddress(ADDRV4), 32));
- target.addLinkAddress(new LinkAddress(
- NetworkUtils.numericToInetAddress(ADDRV6), 128));
- target.addDns(NetworkUtils.numericToInetAddress(DNS1));
- target.addDns(NetworkUtils.numericToInetAddress(DNS2));
+ target.addLinkAddress(LINKADDRV4);
+ target.addLinkAddress(LINKADDRV6);
+ target.addDns(DNS1);
+ target.addDns(DNS2);
// change gateway
target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress("75.208.8.2")));
- target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY2)));
+ target.addRoute(new RouteInfo(GATEWAY2));
assertFalse(source.equals(target));
} catch (Exception e) {
@@ -166,28 +159,24 @@
LinkProperties source = new LinkProperties();
source.setInterfaceName(NAME);
// set 2 link addresses
- source.addLinkAddress(new LinkAddress(
- NetworkUtils.numericToInetAddress(ADDRV4), 32));
- source.addLinkAddress(new LinkAddress(
- NetworkUtils.numericToInetAddress(ADDRV6), 128));
+ source.addLinkAddress(LINKADDRV4);
+ source.addLinkAddress(LINKADDRV6);
// set 2 dnses
- source.addDns(NetworkUtils.numericToInetAddress(DNS1));
- source.addDns(NetworkUtils.numericToInetAddress(DNS2));
+ source.addDns(DNS1);
+ source.addDns(DNS2);
// set 2 gateways
- source.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY1)));
- source.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY2)));
+ source.addRoute(new RouteInfo(GATEWAY1));
+ source.addRoute(new RouteInfo(GATEWAY2));
LinkProperties target = new LinkProperties();
// Exchange order
target.setInterfaceName(NAME);
- target.addLinkAddress(new LinkAddress(
- NetworkUtils.numericToInetAddress(ADDRV6), 128));
- target.addLinkAddress(new LinkAddress(
- NetworkUtils.numericToInetAddress(ADDRV4), 32));
- target.addDns(NetworkUtils.numericToInetAddress(DNS2));
- target.addDns(NetworkUtils.numericToInetAddress(DNS1));
- target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY2)));
- target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY1)));
+ target.addLinkAddress(LINKADDRV6);
+ target.addLinkAddress(LINKADDRV4);
+ target.addDns(DNS2);
+ target.addDns(DNS1);
+ target.addRoute(new RouteInfo(GATEWAY2));
+ target.addRoute(new RouteInfo(GATEWAY1));
assertLinkPropertiesEqual(source, target);
} catch (Exception e) {
@@ -200,21 +189,15 @@
try {
LinkProperties source = new LinkProperties();
// set 3 link addresses, eg, [A, A, B]
- source.addLinkAddress(new LinkAddress(
- NetworkUtils.numericToInetAddress(ADDRV4), 32));
- source.addLinkAddress(new LinkAddress(
- NetworkUtils.numericToInetAddress(ADDRV4), 32));
- source.addLinkAddress(new LinkAddress(
- NetworkUtils.numericToInetAddress(ADDRV6), 128));
+ source.addLinkAddress(LINKADDRV4);
+ source.addLinkAddress(LINKADDRV4);
+ source.addLinkAddress(LINKADDRV6);
LinkProperties target = new LinkProperties();
// set 3 link addresses, eg, [A, B, B]
- target.addLinkAddress(new LinkAddress(
- NetworkUtils.numericToInetAddress(ADDRV4), 32));
- target.addLinkAddress(new LinkAddress(
- NetworkUtils.numericToInetAddress(ADDRV6), 128));
- target.addLinkAddress(new LinkAddress(
- NetworkUtils.numericToInetAddress(ADDRV6), 128));
+ target.addLinkAddress(LINKADDRV4);
+ target.addLinkAddress(LINKADDRV6);
+ target.addLinkAddress(LINKADDRV6);
assertLinkPropertiesEqual(source, target);
} catch (Exception e) {
@@ -232,7 +215,7 @@
public void testRouteInterfaces() {
LinkAddress prefix = new LinkAddress(
NetworkUtils.numericToInetAddress("2001:db8::"), 32);
- InetAddress address = NetworkUtils.numericToInetAddress(ADDRV6);
+ InetAddress address = ADDRV6;
// Add a route with no interface to a LinkProperties with no interface. No errors.
LinkProperties lp = new LinkProperties();
@@ -265,7 +248,7 @@
assertAllRoutesHaveInterface("wlan0", lp);
// Routes with null interfaces are converted to wlan0.
- r = RouteInfo.makeHostRoute(NetworkUtils.numericToInetAddress(ADDRV6), null);
+ r = RouteInfo.makeHostRoute(ADDRV6, null);
lp.addRoute(r);
assertEquals(3, lp.getRoutes().size());
assertAllRoutesHaveInterface("wlan0", lp);
@@ -273,28 +256,45 @@
// Check comparisons work.
LinkProperties lp2 = new LinkProperties(lp);
assertAllRoutesHaveInterface("wlan0", lp);
- assertEquals(0, lp.compareRoutes(lp2).added.size());
- assertEquals(0, lp.compareRoutes(lp2).removed.size());
+ assertEquals(0, lp.compareAllRoutes(lp2).added.size());
+ assertEquals(0, lp.compareAllRoutes(lp2).removed.size());
lp2.setInterfaceName("p2p0");
assertAllRoutesHaveInterface("p2p0", lp2);
- assertEquals(3, lp.compareRoutes(lp2).added.size());
- assertEquals(3, lp.compareRoutes(lp2).removed.size());
+ assertEquals(3, lp.compareAllRoutes(lp2).added.size());
+ assertEquals(3, lp.compareAllRoutes(lp2).removed.size());
}
@SmallTest
public void testStackedInterfaces() {
LinkProperties rmnet0 = new LinkProperties();
rmnet0.setInterfaceName("rmnet0");
+ rmnet0.addLinkAddress(LINKADDRV6);
LinkProperties clat4 = new LinkProperties();
clat4.setInterfaceName("clat4");
+ clat4.addLinkAddress(LINKADDRV4);
assertEquals(0, rmnet0.getStackedLinks().size());
+ assertEquals(1, rmnet0.getAddresses().size());
+ assertEquals(1, rmnet0.getLinkAddresses().size());
+ assertEquals(1, rmnet0.getAllAddresses().size());
+ assertEquals(1, rmnet0.getAllLinkAddresses().size());
+
rmnet0.addStackedLink(clat4);
assertEquals(1, rmnet0.getStackedLinks().size());
+ assertEquals(1, rmnet0.getAddresses().size());
+ assertEquals(1, rmnet0.getLinkAddresses().size());
+ assertEquals(2, rmnet0.getAllAddresses().size());
+ assertEquals(2, rmnet0.getAllLinkAddresses().size());
+
rmnet0.addStackedLink(clat4);
assertEquals(1, rmnet0.getStackedLinks().size());
+ assertEquals(1, rmnet0.getAddresses().size());
+ assertEquals(1, rmnet0.getLinkAddresses().size());
+ assertEquals(2, rmnet0.getAllAddresses().size());
+ assertEquals(2, rmnet0.getAllLinkAddresses().size());
+
assertEquals(0, clat4.getStackedLinks().size());
// Modify an item in the returned collection to see what happens.
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 00935f3..bb0d248 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -56,13 +56,11 @@
import android.net.INetworkStatsService;
import android.net.LinkAddress;
import android.net.LinkProperties;
-import android.net.Uri;
import android.net.LinkProperties.CompareResult;
import android.net.MobileDataStateTracker;
import android.net.NetworkConfig;
import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;
-import android.net.NetworkInfo.State;
import android.net.NetworkQuotaInfo;
import android.net.NetworkState;
import android.net.NetworkStateTracker;
@@ -70,6 +68,7 @@
import android.net.Proxy;
import android.net.ProxyProperties;
import android.net.RouteInfo;
+import android.net.Uri;
import android.net.wifi.WifiStateTracker;
import android.net.wimax.WimaxManagerConstants;
import android.os.AsyncTask;
@@ -97,10 +96,12 @@
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Slog;
+import android.util.SparseArray;
import android.util.SparseIntArray;
import android.util.Xml;
import com.android.internal.R;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.net.LegacyVpnInfo;
import com.android.internal.net.VpnConfig;
import com.android.internal.net.VpnProfile;
@@ -109,8 +110,11 @@
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.XmlUtils;
+import com.android.net.IProxyService;
import com.android.server.am.BatteryStatsService;
+import com.android.server.connectivity.DataConnectionStats;
import com.android.server.connectivity.Nat464Xlat;
+import com.android.server.connectivity.PacManager;
import com.android.server.connectivity.Tethering;
import com.android.server.connectivity.Vpn;
import com.android.server.net.BaseNetworkObserver;
@@ -178,7 +182,8 @@
private KeyStore mKeyStore;
- private Vpn mVpn;
+ @GuardedBy("mVpns")
+ private final SparseArray<Vpn> mVpns = new SparseArray<Vpn>();
private VpnCallback mVpnCallback = new VpnCallback();
private boolean mLockdownEnabled;
@@ -230,7 +235,6 @@
private Object mDnsLock = new Object();
private int mNumDnsEntries;
- private boolean mDnsOverridden = false;
private boolean mTestMode;
private static ConnectivityService sServiceInstance;
@@ -247,6 +251,9 @@
private static final boolean TO_DEFAULT_TABLE = true;
private static final boolean TO_SECONDARY_TABLE = false;
+ private static final boolean EXEMPT = true;
+ private static final boolean UNEXEMPT = false;
+
/**
* used internally as a delayed event to make us switch back to the
* default network
@@ -302,28 +309,22 @@
private static final int EVENT_SET_DEPENDENCY_MET = 10;
/**
- * used internally to restore DNS properties back to the
- * default network
- */
- private static final int EVENT_RESTORE_DNS = 11;
-
- /**
* used internally to send a sticky broadcast delayed.
*/
- private static final int EVENT_SEND_STICKY_BROADCAST_INTENT = 12;
+ private static final int EVENT_SEND_STICKY_BROADCAST_INTENT = 11;
/**
* Used internally to
* {@link NetworkStateTracker#setPolicyDataEnable(boolean)}.
*/
- private static final int EVENT_SET_POLICY_DATA_ENABLE = 13;
+ private static final int EVENT_SET_POLICY_DATA_ENABLE = 12;
- private static final int EVENT_VPN_STATE_CHANGED = 14;
+ private static final int EVENT_VPN_STATE_CHANGED = 13;
/**
* Used internally to disable fail fast of mobile data
*/
- private static final int EVENT_ENABLE_FAIL_FAST_MOBILE_DATA = 15;
+ private static final int EVENT_ENABLE_FAIL_FAST_MOBILE_DATA = 14;
/** Handler used for internal events. */
private InternalHandler mHandler;
@@ -344,10 +345,19 @@
private InetAddress mDefaultDns;
+ // Lock for protecting access to mAddedRoutes and mExemptAddresses
+ private final Object mRoutesLock = new Object();
+
// 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
+ @GuardedBy("mRoutesLock")
private Collection<RouteInfo> mAddedRoutes = new ArrayList<RouteInfo>();
+ // this collection corresponds to the entries of mAddedRoutes that have routing exemptions
+ // used to handle cleanup of exempt rules
+ @GuardedBy("mRoutesLock")
+ private Collection<LinkAddress> mExemptAddresses = new ArrayList<LinkAddress>();
+
// used in DBG mode to track inet condition reports
private static final int INET_CONDITION_LOG_MAX_SIZE = 15;
private ArrayList mInetLog;
@@ -360,6 +370,8 @@
// track the global proxy.
private ProxyProperties mGlobalProxy = null;
+ private PacManager mPacManager = null;
+
private SettingsObserver mSettingsObserver;
NetworkConfig[] mNetConfigs;
@@ -379,6 +391,7 @@
// the set of network types that can only be enabled by system/sig apps
List mProtectedNetworks;
+ private DataConnectionStats mDataConnectionStats;
private AtomicInteger mEnableFailFastMobileDataTag = new AtomicInteger(0);
TelephonyManager mTelephonyManager;
@@ -461,6 +474,7 @@
com.android.internal.R.array.radioAttributes);
for (String raString : raStrings) {
RadioAttributes r = new RadioAttributes(raString);
+ if (VDBG) log("raString=" + raString + " r=" + r);
if (r.mType > ConnectivityManager.MAX_RADIO_TYPE) {
loge("Error in radioAttributes - ignoring attempt to define type " + r.mType);
continue;
@@ -481,6 +495,7 @@
for (String naString : naStrings) {
try {
NetworkConfig n = new NetworkConfig(naString);
+ if (VDBG) log("naString=" + naString + " config=" + n);
if (n.type > ConnectivityManager.MAX_NETWORK_TYPE) {
loge("Error in networkAttributes - ignoring attempt to define type " +
n.type);
@@ -507,6 +522,7 @@
// ignore it - leave the entry null
}
}
+ if (VDBG) log("mNetworksDefined=" + mNetworksDefined);
mProtectedNetworks = new ArrayList<Integer>();
int[] protectedNetworks = context.getResources().getIntArray(
@@ -589,9 +605,12 @@
mTethering = new Tethering(mContext, mNetd, statsService, this, mHandler.getLooper());
- mVpn = new Vpn(mContext, mVpnCallback, mNetd, this);
- mVpn.startMonitoring(mContext, mTrackerHandler);
-
+ //set up the listener for user state for creating user VPNs
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(Intent.ACTION_USER_STARTING);
+ intentFilter.addAction(Intent.ACTION_USER_STOPPING);
+ mContext.registerReceiverAsUser(
+ mUserIntentReceiver, UserHandle.ALL, intentFilter, null, null);
mClat = new Nat464Xlat(mContext, mNetd, this, mTrackerHandler);
try {
@@ -611,6 +630,11 @@
mCaptivePortalTracker = CaptivePortalTracker.makeCaptivePortalTracker(mContext, this);
loadGlobalProxy();
+
+ mDataConnectionStats = new DataConnectionStats(mContext);
+ mDataConnectionStats.startMonitoring();
+
+ mPacManager = new PacManager(mContext);
}
/**
@@ -1458,7 +1482,7 @@
try {
InetAddress addr = InetAddress.getByAddress(hostAddress);
LinkProperties lp = tracker.getLinkProperties();
- boolean ok = addRouteToAddress(lp, addr);
+ boolean ok = addRouteToAddress(lp, addr, EXEMPT);
if (DBG) log("requestRouteToHostAddress ok=" + ok);
return ok;
} catch (UnknownHostException e) {
@@ -1470,24 +1494,25 @@
return false;
}
- private boolean addRoute(LinkProperties p, RouteInfo r, boolean toDefaultTable) {
- return modifyRoute(p, r, 0, ADD, toDefaultTable);
+ private boolean addRoute(LinkProperties p, RouteInfo r, boolean toDefaultTable,
+ boolean exempt) {
+ return modifyRoute(p, r, 0, ADD, toDefaultTable, exempt);
}
private boolean removeRoute(LinkProperties p, RouteInfo r, boolean toDefaultTable) {
- return modifyRoute(p, r, 0, REMOVE, toDefaultTable);
+ return modifyRoute(p, r, 0, REMOVE, toDefaultTable, UNEXEMPT);
}
- private boolean addRouteToAddress(LinkProperties lp, InetAddress addr) {
- return modifyRouteToAddress(lp, addr, ADD, TO_DEFAULT_TABLE);
+ private boolean addRouteToAddress(LinkProperties lp, InetAddress addr, boolean exempt) {
+ return modifyRouteToAddress(lp, addr, ADD, TO_DEFAULT_TABLE, exempt);
}
private boolean removeRouteToAddress(LinkProperties lp, InetAddress addr) {
- return modifyRouteToAddress(lp, addr, REMOVE, TO_DEFAULT_TABLE);
+ return modifyRouteToAddress(lp, addr, REMOVE, TO_DEFAULT_TABLE, UNEXEMPT);
}
private boolean modifyRouteToAddress(LinkProperties lp, InetAddress addr, boolean doAdd,
- boolean toDefaultTable) {
+ boolean toDefaultTable, boolean exempt) {
RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getAllRoutes(), addr);
if (bestRoute == null) {
bestRoute = RouteInfo.makeHostRoute(addr, lp.getInterfaceName());
@@ -1502,11 +1527,11 @@
bestRoute = RouteInfo.makeHostRoute(addr, bestRoute.getGateway(), iface);
}
}
- return modifyRoute(lp, bestRoute, 0, doAdd, toDefaultTable);
+ return modifyRoute(lp, bestRoute, 0, doAdd, toDefaultTable, exempt);
}
private boolean modifyRoute(LinkProperties lp, RouteInfo r, int cycleCount, boolean doAdd,
- boolean toDefaultTable) {
+ boolean toDefaultTable, boolean exempt) {
if ((lp == null) || (r == null)) {
if (DBG) log("modifyRoute got unexpected null: " + lp + ", " + r);
return false;
@@ -1535,15 +1560,25 @@
bestRoute.getGateway(),
ifaceName);
}
- modifyRoute(lp, bestRoute, cycleCount+1, doAdd, toDefaultTable);
+ modifyRoute(lp, bestRoute, cycleCount+1, doAdd, toDefaultTable, exempt);
}
}
if (doAdd) {
if (VDBG) log("Adding " + r + " for interface " + ifaceName);
try {
if (toDefaultTable) {
- mAddedRoutes.add(r); // only track default table - only one apps can effect
- mNetd.addRoute(ifaceName, r);
+ synchronized (mRoutesLock) {
+ // only track default table - only one apps can effect
+ mAddedRoutes.add(r);
+ mNetd.addRoute(ifaceName, r);
+ if (exempt) {
+ LinkAddress dest = r.getDestination();
+ if (!mExemptAddresses.contains(dest)) {
+ mNetd.setHostExemption(dest);
+ mExemptAddresses.add(dest);
+ }
+ }
+ }
} else {
mNetd.addSecondaryRoute(ifaceName, r);
}
@@ -1556,18 +1591,25 @@
// if we remove this one and there are no more like it, then refcount==0 and
// we can remove it from the table
if (toDefaultTable) {
- mAddedRoutes.remove(r);
- if (mAddedRoutes.contains(r) == false) {
- if (VDBG) log("Removing " + r + " for interface " + ifaceName);
- try {
- mNetd.removeRoute(ifaceName, r);
- } catch (Exception e) {
- // never crash - catch them all
- if (VDBG) loge("Exception trying to remove a route: " + e);
- return false;
+ synchronized (mRoutesLock) {
+ mAddedRoutes.remove(r);
+ if (mAddedRoutes.contains(r) == false) {
+ if (VDBG) log("Removing " + r + " for interface " + ifaceName);
+ try {
+ mNetd.removeRoute(ifaceName, r);
+ LinkAddress dest = r.getDestination();
+ if (mExemptAddresses.contains(dest)) {
+ mNetd.clearHostExemption(dest);
+ mExemptAddresses.remove(dest);
+ }
+ } catch (Exception e) {
+ // never crash - catch them all
+ if (VDBG) loge("Exception trying to remove a route: " + e);
+ return false;
+ }
+ } else {
+ if (VDBG) log("not removing " + r + " as it's still in use");
}
- } else {
- if (VDBG) log("not removing " + r + " as it's still in use");
}
} else {
if (VDBG) log("Removing " + r + " for interface " + ifaceName);
@@ -1744,6 +1786,16 @@
"ConnectivityService");
}
+ private void enforceMarkNetworkSocketPermission() {
+ //Media server special case
+ if (Binder.getCallingUid() == Process.MEDIA_UID) {
+ return;
+ }
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.MARK_NETWORK_SOCKET,
+ "ConnectivityService");
+ }
+
/**
* Handle a {@code DISCONNECTED} event. If this pertains to the non-active
* network, we ignore it. If it is for the active network, we send out a
@@ -2249,6 +2301,7 @@
*/
private void handleConnectivityChange(int netType, boolean doReset) {
int resetMask = doReset ? NetworkUtils.RESET_ALL_ADDRESSES : 0;
+ boolean exempt = ConnectivityManager.isNetworkTypeExempt(netType);
/*
* If a non-default network is enabled, add the host routes that
@@ -2313,7 +2366,7 @@
}
}
mCurrentLinkProperties[netType] = newLp;
- boolean resetDns = updateRoutes(newLp, curLp, mNetConfigs[netType].isDefault());
+ boolean resetDns = updateRoutes(newLp, curLp, mNetConfigs[netType].isDefault(), exempt);
if (resetMask != 0 || resetDns) {
if (curLp != null) {
@@ -2326,7 +2379,11 @@
// Tell VPN the interface is down. It is a temporary
// but effective fix to make VPN aware of the change.
if ((resetMask & NetworkUtils.RESET_IPV4_ADDRESSES) != 0) {
- mVpn.interfaceStatusChanged(iface, false);
+ synchronized(mVpns) {
+ for (int i = 0; i < mVpns.size(); i++) {
+ mVpns.valueAt(i).interfaceStatusChanged(iface, false);
+ }
+ }
}
}
if (resetDns) {
@@ -2385,13 +2442,13 @@
* returns a boolean indicating the routes changed
*/
private boolean updateRoutes(LinkProperties newLp, LinkProperties curLp,
- boolean isLinkDefault) {
+ boolean isLinkDefault, boolean exempt) {
Collection<RouteInfo> routesToAdd = null;
CompareResult<InetAddress> dnsDiff = new CompareResult<InetAddress>();
CompareResult<RouteInfo> routeDiff = new CompareResult<RouteInfo>();
if (curLp != null) {
// check for the delta between the current set and the new
- routeDiff = curLp.compareRoutes(newLp);
+ routeDiff = curLp.compareAllRoutes(newLp);
dnsDiff = curLp.compareDnses(newLp);
} else if (newLp != null) {
routeDiff.added = newLp.getAllRoutes();
@@ -2421,7 +2478,7 @@
}
if (newLp != null) {
for (InetAddress newDns : newLp.getDnses()) {
- addRouteToAddress(newLp, newDns);
+ addRouteToAddress(newLp, newDns, exempt);
}
}
} else {
@@ -2430,28 +2487,30 @@
removeRouteToAddress(curLp, oldDns);
}
for (InetAddress newDns : dnsDiff.added) {
- addRouteToAddress(newLp, newDns);
+ addRouteToAddress(newLp, newDns, exempt);
}
}
}
for (RouteInfo r : routeDiff.added) {
if (isLinkDefault || ! r.isDefaultRoute()) {
- addRoute(newLp, r, TO_DEFAULT_TABLE);
+ addRoute(newLp, r, TO_DEFAULT_TABLE, exempt);
} else {
// add to a secondary route table
- addRoute(newLp, r, TO_SECONDARY_TABLE);
+ addRoute(newLp, r, TO_SECONDARY_TABLE, UNEXEMPT);
// many radios add a default route even when we don't want one.
// remove the default route unless somebody else has asked for it
String ifaceName = newLp.getInterfaceName();
- if (TextUtils.isEmpty(ifaceName) == false && mAddedRoutes.contains(r) == false) {
- if (VDBG) log("Removing " + r + " for interface " + ifaceName);
- try {
- mNetd.removeRoute(ifaceName, r);
- } catch (Exception e) {
- // never crash - catch them all
- if (DBG) loge("Exception trying to remove a route: " + e);
+ synchronized (mRoutesLock) {
+ if (!TextUtils.isEmpty(ifaceName) && !mAddedRoutes.contains(r)) {
+ if (VDBG) log("Removing " + r + " for interface " + ifaceName);
+ try {
+ mNetd.removeRoute(ifaceName, r);
+ } catch (Exception e) {
+ // never crash - catch them all
+ if (DBG) loge("Exception trying to remove a route: " + e);
+ }
}
}
}
@@ -2571,7 +2630,7 @@
// Caller must grab mDnsLock.
private void updateDnsLocked(String network, String iface,
- Collection<InetAddress> dnses, String domains) {
+ Collection<InetAddress> dnses, String domains, boolean defaultDns) {
int last = 0;
if (dnses.size() == 0 && mDefaultDns != null) {
dnses = new ArrayList();
@@ -2583,7 +2642,10 @@
try {
mNetd.setDnsServersForInterface(iface, NetworkUtils.makeStrings(dnses), domains);
- mNetd.setDefaultInterfaceForDns(iface);
+ if (defaultDns) {
+ mNetd.setDefaultInterfaceForDns(iface);
+ }
+
for (InetAddress dns : dnses) {
++last;
String key = "net.dns" + last;
@@ -2610,9 +2672,7 @@
if (mNetConfigs[netType].isDefault()) {
String network = nt.getNetworkInfo().getTypeName();
synchronized (mDnsLock) {
- if (!mDnsOverridden) {
- updateDnsLocked(network, p.getInterfaceName(), dnses, p.getDomains());
- }
+ updateDnsLocked(network, p.getInterfaceName(), dnses, p.getDomains(), true);
}
} else {
try {
@@ -2865,13 +2925,6 @@
handleSetDependencyMet(msg.arg2, met);
break;
}
- case EVENT_RESTORE_DNS:
- {
- if (mActiveDefaultNetwork != -1) {
- handleDnsConfigurationChange(mActiveDefaultNetwork);
- }
- break;
- }
case EVENT_SEND_STICKY_BROADCAST_INTENT:
{
Intent intent = (Intent)msg.obj;
@@ -3130,13 +3183,15 @@
// of proxy info to all the JVMs.
// enforceAccessPermission();
synchronized (mProxyLock) {
- if (mGlobalProxy != null) return mGlobalProxy;
- return (mDefaultProxyDisabled ? null : mDefaultProxy);
+ ProxyProperties ret = mGlobalProxy;
+ if ((ret == null) && !mDefaultProxyDisabled) ret = mDefaultProxy;
+ return ret;
}
}
public void setGlobalProxy(ProxyProperties proxyProperties) {
enforceConnectivityInternalPermission();
+
synchronized (mProxyLock) {
if (proxyProperties == mGlobalProxy) return;
if (proxyProperties != null && proxyProperties.equals(mGlobalProxy)) return;
@@ -3145,11 +3200,16 @@
String host = "";
int port = 0;
String exclList = "";
- if (proxyProperties != null && !TextUtils.isEmpty(proxyProperties.getHost())) {
+ String pacFileUrl = "";
+ if (proxyProperties != null && (!TextUtils.isEmpty(proxyProperties.getHost()) ||
+ !TextUtils.isEmpty(proxyProperties.getPacFileUrl()))) {
mGlobalProxy = new ProxyProperties(proxyProperties);
host = mGlobalProxy.getHost();
port = mGlobalProxy.getPort();
exclList = mGlobalProxy.getExclusionList();
+ if (proxyProperties.getPacFileUrl() != null) {
+ pacFileUrl = proxyProperties.getPacFileUrl();
+ }
} else {
mGlobalProxy = null;
}
@@ -3160,6 +3220,7 @@
Settings.Global.putInt(res, Settings.Global.GLOBAL_HTTP_PROXY_PORT, port);
Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
exclList);
+ Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_PAC, pacFileUrl);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -3177,8 +3238,14 @@
int port = Settings.Global.getInt(res, Settings.Global.GLOBAL_HTTP_PROXY_PORT, 0);
String exclList = Settings.Global.getString(res,
Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST);
- if (!TextUtils.isEmpty(host)) {
- ProxyProperties proxyProperties = new ProxyProperties(host, port, exclList);
+ String pacFileUrl = Settings.Global.getString(res, Settings.Global.GLOBAL_HTTP_PROXY_PAC);
+ if (!TextUtils.isEmpty(host) || !TextUtils.isEmpty(pacFileUrl)) {
+ ProxyProperties proxyProperties;
+ if (!TextUtils.isEmpty(pacFileUrl)) {
+ proxyProperties = new ProxyProperties(pacFileUrl);
+ } else {
+ proxyProperties = new ProxyProperties(host, port, exclList);
+ }
synchronized (mProxyLock) {
mGlobalProxy = proxyProperties;
}
@@ -3196,7 +3263,8 @@
}
private void handleApplyDefaultProxy(ProxyProperties proxy) {
- if (proxy != null && TextUtils.isEmpty(proxy.getHost())) {
+ if (proxy != null && TextUtils.isEmpty(proxy.getHost())
+ && TextUtils.isEmpty(proxy.getPacFileUrl())) {
proxy = null;
}
synchronized (mProxyLock) {
@@ -3216,6 +3284,10 @@
Settings.Global.HTTP_PROXY);
if (!TextUtils.isEmpty(proxy)) {
String data[] = proxy.split(":");
+ if (data.length == 0) {
+ return;
+ }
+
String proxyHost = data[0];
int proxyPort = 8080;
if (data.length > 1) {
@@ -3227,11 +3299,14 @@
}
ProxyProperties p = new ProxyProperties(data[0], proxyPort, "");
setGlobalProxy(p);
+ } else {
+ setGlobalProxy(null);
}
}
private void sendProxyBroadcast(ProxyProperties proxy) {
if (proxy == null) proxy = new ProxyProperties("", 0, "");
+ mPacManager.setCurrentProxyScriptUrl(proxy);
if (DBG) log("sending Proxy Broadcast for " + proxy);
Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
@@ -3326,8 +3401,12 @@
throwIfLockdownEnabled();
try {
int type = mActiveDefaultNetwork;
+ int user = UserHandle.getUserId(Binder.getCallingUid());
if (ConnectivityManager.isNetworkTypeValid(type) && mNetTrackers[type] != null) {
- mVpn.protect(socket, mNetTrackers[type].getLinkProperties().getInterfaceName());
+ synchronized(mVpns) {
+ mVpns.get(user).protect(socket,
+ mNetTrackers[type].getLinkProperties().getInterfaceName());
+ }
return true;
}
} catch (Exception e) {
@@ -3351,7 +3430,27 @@
@Override
public boolean prepareVpn(String oldPackage, String newPackage) {
throwIfLockdownEnabled();
- return mVpn.prepare(oldPackage, newPackage);
+ int user = UserHandle.getUserId(Binder.getCallingUid());
+ synchronized(mVpns) {
+ return mVpns.get(user).prepare(oldPackage, newPackage);
+ }
+ }
+
+ @Override
+ public void markSocketAsUser(ParcelFileDescriptor socket, int uid) {
+ enforceMarkNetworkSocketPermission();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ int mark = mNetd.getMarkForUid(uid);
+ // Clear the mark on the socket if no mark is needed to prevent socket reuse issues
+ if (mark == -1) {
+ mark = 0;
+ }
+ NetworkUtils.markSocket(socket.getFd(), mark);
+ } catch (RemoteException e) {
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
/**
@@ -3364,7 +3463,10 @@
@Override
public ParcelFileDescriptor establishVpn(VpnConfig config) {
throwIfLockdownEnabled();
- return mVpn.establish(config);
+ int user = UserHandle.getUserId(Binder.getCallingUid());
+ synchronized(mVpns) {
+ return mVpns.get(user).establish(config);
+ }
}
/**
@@ -3378,7 +3480,10 @@
if (egress == null) {
throw new IllegalStateException("Missing active network connection");
}
- mVpn.startLegacyVpn(profile, mKeyStore, egress);
+ int user = UserHandle.getUserId(Binder.getCallingUid());
+ synchronized(mVpns) {
+ mVpns.get(user).startLegacyVpn(profile, mKeyStore, egress);
+ }
}
/**
@@ -3390,7 +3495,24 @@
@Override
public LegacyVpnInfo getLegacyVpnInfo() {
throwIfLockdownEnabled();
- return mVpn.getLegacyVpnInfo();
+ int user = UserHandle.getUserId(Binder.getCallingUid());
+ synchronized(mVpns) {
+ return mVpns.get(user).getLegacyVpnInfo();
+ }
+ }
+
+ /**
+ * Returns the information of the ongoing VPN. This method is used by VpnDialogs and
+ * not available in ConnectivityManager.
+ * Permissions are checked in Vpn class.
+ * @hide
+ */
+ @Override
+ public VpnConfig getVpnConfig() {
+ int user = UserHandle.getUserId(Binder.getCallingUid());
+ synchronized(mVpns) {
+ return mVpns.get(user).getVpnConfig();
+ }
}
/**
@@ -3411,7 +3533,7 @@
mHandler.obtainMessage(EVENT_VPN_STATE_CHANGED, info).sendToTarget();
}
- public void override(List<String> dnsServers, List<String> searchDomains) {
+ public void override(String iface, List<String> dnsServers, List<String> searchDomains) {
if (dnsServers == null) {
restore();
return;
@@ -3443,8 +3565,7 @@
// Apply DNS changes.
synchronized (mDnsLock) {
- updateDnsLocked("VPN", "VPN", addresses, domains);
- mDnsOverridden = true;
+ updateDnsLocked("VPN", iface, addresses, domains, false);
}
// Temporarily disable the default proxy (not global).
@@ -3459,12 +3580,6 @@
}
public void restore() {
- synchronized (mDnsLock) {
- if (mDnsOverridden) {
- mDnsOverridden = false;
- mHandler.sendEmptyMessage(EVENT_RESTORE_DNS);
- }
- }
synchronized (mProxyLock) {
mDefaultProxyDisabled = false;
if (mGlobalProxy == null && mDefaultProxy != null) {
@@ -3472,6 +3587,67 @@
}
}
}
+
+ public void protect(ParcelFileDescriptor socket) {
+ try {
+ final int mark = mNetd.getMarkForProtect();
+ NetworkUtils.markSocket(socket.getFd(), mark);
+ } catch (RemoteException e) {
+ }
+ }
+
+ public void setRoutes(String interfaze, List<RouteInfo> routes) {
+ for (RouteInfo route : routes) {
+ try {
+ mNetd.setMarkedForwardingRoute(interfaze, route);
+ } catch (RemoteException e) {
+ }
+ }
+ }
+
+ public void setMarkedForwarding(String interfaze) {
+ try {
+ mNetd.setMarkedForwarding(interfaze);
+ } catch (RemoteException e) {
+ }
+ }
+
+ public void clearMarkedForwarding(String interfaze) {
+ try {
+ mNetd.clearMarkedForwarding(interfaze);
+ } catch (RemoteException e) {
+ }
+ }
+
+ public void addUserForwarding(String interfaze, int uid) {
+ int uidStart = uid * UserHandle.PER_USER_RANGE;
+ int uidEnd = uidStart + UserHandle.PER_USER_RANGE - 1;
+ addUidForwarding(interfaze, uidStart, uidEnd);
+ }
+
+ public void clearUserForwarding(String interfaze, int uid) {
+ int uidStart = uid * UserHandle.PER_USER_RANGE;
+ int uidEnd = uidStart + UserHandle.PER_USER_RANGE - 1;
+ clearUidForwarding(interfaze, uidStart, uidEnd);
+ }
+
+ public void addUidForwarding(String interfaze, int uidStart, int uidEnd) {
+ try {
+ mNetd.setUidRangeRoute(interfaze,uidStart, uidEnd);
+ mNetd.setDnsInterfaceForUidRange(interfaze, uidStart, uidEnd);
+ } catch (RemoteException e) {
+ }
+
+ }
+
+ public void clearUidForwarding(String interfaze, int uidStart, int uidEnd) {
+ try {
+ mNetd.clearUidRangeRoute(interfaze, uidStart, uidEnd);
+ mNetd.clearDnsInterfaceForUidRange(uidStart, uidEnd);
+ } catch (RemoteException e) {
+ }
+
+ }
}
@Override
@@ -3492,7 +3668,11 @@
final String profileName = new String(mKeyStore.get(Credentials.LOCKDOWN_VPN));
final VpnProfile profile = VpnProfile.decode(
profileName, mKeyStore.get(Credentials.VPN + profileName));
- setLockdownTracker(new LockdownVpnTracker(mContext, mNetd, this, mVpn, profile));
+ int user = UserHandle.getUserId(Binder.getCallingUid());
+ synchronized(mVpns) {
+ setLockdownTracker(new LockdownVpnTracker(mContext, mNetd, this, mVpns.get(user),
+ profile));
+ }
} else {
setLockdownTracker(null);
}
@@ -3573,7 +3753,7 @@
}
@Override
- public int checkMobileProvisioning(boolean sendNotification, int suggestedTimeOutMs,
+ public int checkMobileProvisioning(final boolean sendNotification, int suggestedTimeOutMs,
final ResultReceiver resultReceiver) {
log("checkMobileProvisioning: E sendNotification=" + sendNotification
+ " suggestedTimeOutMs=" + suggestedTimeOutMs
@@ -3608,6 +3788,10 @@
log("CheckMp.onComplete: send result");
resultReceiver.send(result, null);
}
+ if (!sendNotification) {
+ log("CheckMp.onComplete: done, not sending notification");
+ return;
+ }
NetworkInfo ni =
mNetTrackers[ConnectivityManager.TYPE_MOBILE_HIPRI].getNetworkInfo();
switch(result) {
@@ -4148,4 +4332,43 @@
return url;
}
+
+ private void onUserStart(int userId) {
+ synchronized(mVpns) {
+ Vpn userVpn = mVpns.get(userId);
+ if (userVpn != null) {
+ loge("Starting user already has a VPN");
+ return;
+ }
+ userVpn = new Vpn(mContext, mVpnCallback, mNetd, this, userId);
+ mVpns.put(userId, userVpn);
+ userVpn.startMonitoring(mContext, mTrackerHandler);
+ }
+ }
+
+ private void onUserStop(int userId) {
+ synchronized(mVpns) {
+ Vpn userVpn = mVpns.get(userId);
+ if (userVpn == null) {
+ loge("Stopping user has no VPN");
+ return;
+ }
+ mVpns.delete(userId);
+ }
+ }
+
+ private BroadcastReceiver mUserIntentReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
+ if (userId == UserHandle.USER_NULL) return;
+
+ if (Intent.ACTION_USER_STARTING.equals(action)) {
+ onUserStart(userId);
+ } else if (Intent.ACTION_USER_STOPPING.equals(action)) {
+ onUserStop(userId);
+ }
+ }
+ };
}
diff --git a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
index cdc4d78..a9909b2 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
@@ -63,6 +63,7 @@
import android.net.NetworkStatsHistory;
import android.net.NetworkTemplate;
import android.os.INetworkManagementService;
+import android.os.WorkSource;
import android.telephony.TelephonyManager;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.LargeTest;
@@ -878,8 +879,8 @@
mAlarmManager.remove(isA(PendingIntent.class));
expectLastCall().anyTimes();
- mAlarmManager.setInexactRepeating(
- eq(AlarmManager.ELAPSED_REALTIME), anyLong(), anyLong(), isA(PendingIntent.class));
+ mAlarmManager.set(eq(AlarmManager.ELAPSED_REALTIME), anyLong(), anyLong(), anyLong(),
+ isA(PendingIntent.class), isA(WorkSource.class));
expectLastCall().atLeastOnce();
mNetManager.setGlobalAlert(anyLong());