Merge "Handle provisioning APN by turning off/on data." into klp-dev
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index c78a973..70c8750 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -395,6 +395,8 @@
private final IConnectivityManager mService;
+ private final String mPackageName;
+
/**
* Tests if a given integer represents a valid network type.
* @param networkType the type to be tested
@@ -802,7 +804,7 @@
public boolean requestRouteToHostAddress(int networkType, InetAddress hostAddress) {
byte[] address = hostAddress.getAddress();
try {
- return mService.requestRouteToHostAddress(networkType, address);
+ return mService.requestRouteToHostAddress(networkType, address, mPackageName);
} catch (RemoteException e) {
return false;
}
@@ -898,8 +900,9 @@
/**
* {@hide}
*/
- public ConnectivityManager(IConnectivityManager service) {
+ public ConnectivityManager(IConnectivityManager service, String packageName) {
mService = checkNotNull(service, "missing IConnectivityManager");
+ mPackageName = checkNotNull(packageName, "missing package name");
}
/** {@hide} */
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index c1da2e3..4bca7fe 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -71,9 +71,9 @@
int stopUsingNetworkFeature(int networkType, in String feature);
- boolean requestRouteToHost(int networkType, int hostAddress);
+ boolean requestRouteToHost(int networkType, int hostAddress, String packageName);
- boolean requestRouteToHostAddress(int networkType, in byte[] hostAddress);
+ boolean requestRouteToHostAddress(int networkType, in byte[] hostAddress, String packageName);
boolean getMobileDataEnabled();
void setMobileDataEnabled(boolean enabled);
diff --git a/core/java/android/net/ProxyProperties.java b/core/java/android/net/ProxyProperties.java
index 78ac75f..010e527 100644
--- a/core/java/android/net/ProxyProperties.java
+++ b/core/java/android/net/ProxyProperties.java
@@ -139,6 +139,17 @@
return false;
}
+ public boolean isValid() {
+ if (!TextUtils.isEmpty(mPacFileUrl)) return true;
+ try {
+ Proxy.validate(mHost == null ? "" : mHost, mPort == 0 ? "" : Integer.toString(mPort),
+ mExclusionList == null ? "" : mExclusionList);
+ } catch (IllegalArgumentException e) {
+ return false;
+ }
+ return true;
+ }
+
public java.net.Proxy makeProxy() {
java.net.Proxy proxy = java.net.Proxy.NO_PROXY;
if (mHost != null) {
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 47b8b51..3e22792 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -32,6 +32,7 @@
import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
import android.app.AlarmManager;
+import android.app.AppOpsManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
@@ -43,7 +44,9 @@
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.ContentObserver;
@@ -412,6 +415,8 @@
private SettingsObserver mSettingsObserver;
+ private AppOpsManager mAppOpsManager;
+
NetworkConfig[] mNetConfigs;
int mNetworksDefined;
@@ -695,6 +700,8 @@
filter = new IntentFilter();
filter.addAction(CONNECTED_TO_PROVISIONING_NETWORK_ACTION);
mContext.registerReceiver(mProvisioningReceiver, filter);
+
+ mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
}
/**
@@ -1527,6 +1534,40 @@
}
/**
+ * Check if the address falls into any of currently running VPN's route's.
+ */
+ private boolean isAddressUnderVpn(InetAddress address) {
+ synchronized (mVpns) {
+ synchronized (mRoutesLock) {
+ int uid = UserHandle.getCallingUserId();
+ Vpn vpn = mVpns.get(uid);
+ if (vpn == null) {
+ return false;
+ }
+
+ // Check if an exemption exists for this address.
+ for (LinkAddress destination : mExemptAddresses) {
+ if (!NetworkUtils.addressTypeMatches(address, destination.getAddress())) {
+ continue;
+ }
+
+ int prefix = destination.getNetworkPrefixLength();
+ InetAddress addrMasked = NetworkUtils.getNetworkPart(address, prefix);
+ InetAddress destMasked = NetworkUtils.getNetworkPart(destination.getAddress(),
+ prefix);
+
+ if (addrMasked.equals(destMasked)) {
+ return false;
+ }
+ }
+
+ // Finally check if the address is covered by the VPN.
+ return vpn.isAddressCovered(address);
+ }
+ }
+ }
+
+ /**
* @deprecated use requestRouteToHostAddress instead
*
* Ensure that a network route exists to deliver traffic to the specified
@@ -1537,14 +1578,14 @@
* desired
* @return {@code true} on success, {@code false} on failure
*/
- public boolean requestRouteToHost(int networkType, int hostAddress) {
+ public boolean requestRouteToHost(int networkType, int hostAddress, String packageName) {
InetAddress inetAddress = NetworkUtils.intToInetAddress(hostAddress);
if (inetAddress == null) {
return false;
}
- return requestRouteToHostAddress(networkType, inetAddress.getAddress());
+ return requestRouteToHostAddress(networkType, inetAddress.getAddress(), packageName);
}
/**
@@ -1556,11 +1597,40 @@
* desired
* @return {@code true} on success, {@code false} on failure
*/
- public boolean requestRouteToHostAddress(int networkType, byte[] hostAddress) {
+ public boolean requestRouteToHostAddress(int networkType, byte[] hostAddress,
+ String packageName) {
enforceChangePermission();
if (mProtectedNetworks.contains(networkType)) {
enforceConnectivityInternalPermission();
}
+ boolean exempt;
+ InetAddress addr;
+ try {
+ addr = InetAddress.getByAddress(hostAddress);
+ } catch (UnknownHostException e) {
+ if (DBG) log("requestRouteToHostAddress got " + e.toString());
+ return false;
+ }
+ // System apps may request routes bypassing the VPN to keep other networks working.
+ if (Binder.getCallingUid() == Process.SYSTEM_UID) {
+ exempt = true;
+ } else {
+ mAppOpsManager.checkPackage(Binder.getCallingUid(), packageName);
+ try {
+ ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(packageName,
+ 0);
+ exempt = (info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
+ } catch (NameNotFoundException e) {
+ throw new IllegalArgumentException("Failed to find calling package details", e);
+ }
+ }
+
+ // Non-exempt routeToHost's can only be added if the host is not covered by the VPN.
+ // This can be either because the VPN's routes do not cover the destination or a
+ // system application added an exemption that covers this destination.
+ if (!exempt && isAddressUnderVpn(addr)) {
+ return false;
+ }
if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
if (DBG) log("requestRouteToHostAddress on invalid network: " + networkType);
@@ -1584,18 +1654,13 @@
}
final long token = Binder.clearCallingIdentity();
try {
- InetAddress addr = InetAddress.getByAddress(hostAddress);
LinkProperties lp = tracker.getLinkProperties();
- boolean ok = addRouteToAddress(lp, addr, EXEMPT);
+ boolean ok = addRouteToAddress(lp, addr, exempt);
if (DBG) log("requestRouteToHostAddress ok=" + ok);
return ok;
- } catch (UnknownHostException e) {
- if (DBG) log("requestRouteToHostAddress got " + e.toString());
} finally {
Binder.restoreCallingIdentity(token);
}
- if (DBG) log("requestRouteToHostAddress X bottom return false");
- return false;
}
private boolean addRoute(LinkProperties p, RouteInfo r, boolean toDefaultTable,
@@ -2305,9 +2370,9 @@
mInetConditionChangeInFlight = false;
// Don't do this - if we never sign in stay, grey
//reportNetworkCondition(mActiveDefaultNetwork, 100);
+ updateNetworkSettings(thisNet);
}
thisNet.setTeardownRequested(false);
- updateNetworkSettings(thisNet);
updateMtuSizeSettings(thisNet);
handleConnectivityChange(newNetType, false);
sendConnectedBroadcastDelayed(info, getConnectivityChangeDelay());
@@ -2692,6 +2757,15 @@
}
setBufferSize(bufferSizes);
}
+
+ final String defaultRwndKey = "net.tcp.default_init_rwnd";
+ int defaultRwndValue = SystemProperties.getInt(defaultRwndKey, 0);
+ Integer rwndValue = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.TCP_DEFAULT_INIT_RWND, defaultRwndValue);
+ final String sysctlKey = "sys.sysctl.tcp_def_init_rwnd";
+ if (rwndValue != 0) {
+ SystemProperties.set(sysctlKey, rwndValue.toString());
+ }
}
/**
@@ -3034,7 +3108,7 @@
case NetworkStateTracker.EVENT_NETWORK_SUBTYPE_CHANGED: {
info = (NetworkInfo) msg.obj;
int type = info.getType();
- updateNetworkSettings(mNetTrackers[type]);
+ if (mNetConfigs[type].isDefault()) updateNetworkSettings(mNetTrackers[type]);
break;
}
}
@@ -3380,6 +3454,11 @@
String pacFileUrl = "";
if (proxyProperties != null && (!TextUtils.isEmpty(proxyProperties.getHost()) ||
!TextUtils.isEmpty(proxyProperties.getPacFileUrl()))) {
+ if (!proxyProperties.isValid()) {
+ if (DBG)
+ log("Invalid proxy properties, ignoring: " + proxyProperties.toString());
+ return;
+ }
mGlobalProxy = new ProxyProperties(proxyProperties);
host = mGlobalProxy.getHost();
port = mGlobalProxy.getPort();
@@ -3423,6 +3502,11 @@
} else {
proxyProperties = new ProxyProperties(host, port, exclList);
}
+ if (!proxyProperties.isValid()) {
+ if (DBG) log("Invalid proxy properties, ignoring: " + proxyProperties.toString());
+ return;
+ }
+
synchronized (mProxyLock) {
mGlobalProxy = proxyProperties;
}
@@ -3447,6 +3531,10 @@
synchronized (mProxyLock) {
if (mDefaultProxy != null && mDefaultProxy.equals(proxy)) return;
if (mDefaultProxy == proxy) return; // catches repeated nulls
+ if (proxy != null && !proxy.isValid()) {
+ if (DBG) log("Invalid proxy properties, ignoring: " + proxy.toString());
+ return;
+ }
mDefaultProxy = proxy;
if (mGlobalProxy != null) return;
@@ -3579,8 +3667,7 @@
int user = UserHandle.getUserId(Binder.getCallingUid());
if (ConnectivityManager.isNetworkTypeValid(type) && mNetTrackers[type] != null) {
synchronized(mVpns) {
- mVpns.get(user).protect(socket,
- mNetTrackers[type].getLinkProperties().getInterfaceName());
+ mVpns.get(user).protect(socket);
}
return true;
}
@@ -4365,7 +4452,7 @@
// Make a route to host so we check the specific interface.
if (mCs.requestRouteToHostAddress(ConnectivityManager.TYPE_MOBILE_HIPRI,
- hostAddr.getAddress())) {
+ hostAddr.getAddress(), null)) {
// Wait a short time to be sure the route is established ??
log("isMobileOk:"
+ " wait to establish route to hostAddr=" + hostAddr);