From 83f5d57e0c1db50533e1125cd595e48859ec2203 Mon Sep 17 00:00:00 2001 From: Paul Jensen Date: Fri, 29 Aug 2014 09:54:01 -0400 Subject: [PATCH] Implement ConnectivityManager.reportBadNetwork() to trigger network validation. Network traffic used to perform the network validation is billed to the UID of the caller of reportBadNetwork. This change does not change the actions taken upon validation failing or succeeding: NetworkMonitor will show the sign-in notification if a captive portal is found. NetworkMonitor will inform ConnectivityService if a network tests functional. NetworkMonitor will not take action if a network lacks any connectivity. Also, remove an unused Thread that was confusing bandwidth billing. bug:17326268 Change-Id: I7fea23480af54211004a0a1c535a71c2793f21bb --- .../android/server/ConnectivityService.java | 66 +++++++++++++++++-- .../server/connectivity/NetworkAgentInfo.java | 2 + 2 files changed, 63 insertions(+), 5 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index ad8f446f31..109c2eef2c 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -793,14 +793,28 @@ public class ConnectivityService extends IConnectivityManager.Stub { } /** - * Check if UID should be blocked from using the network represented by the - * given {@link NetworkStateTracker}. + * Check if UID should be blocked from using the network represented by the given networkType. + * @deprecated Uses mLegacyTypeTracker; cannot deal with multiple Networks of the same type. */ private boolean isNetworkBlocked(int networkType, int uid) { + return isNetworkWithLinkPropertiesBlocked(getLinkPropertiesForType(networkType), uid); + } + + /** + * Check if UID should be blocked from using the network represented by the given + * NetworkAgentInfo. + */ + private boolean isNetworkBlocked(NetworkAgentInfo nai, int uid) { + return isNetworkWithLinkPropertiesBlocked(nai.linkProperties, uid); + } + + /** + * Check if UID should be blocked from using the network with the given LinkProperties. + */ + private boolean isNetworkWithLinkPropertiesBlocked(LinkProperties lp, int uid) { final boolean networkCostly; final int uidRules; - LinkProperties lp = getLinkPropertiesForType(networkType); final String iface = (lp == null ? "" : lp.getInterfaceName()); synchronized (mRulesLock) { networkCostly = mMeteredIfaces.contains(iface); @@ -819,12 +833,16 @@ public class ConnectivityService extends IConnectivityManager.Stub { * Return a filtered {@link NetworkInfo}, potentially marked * {@link DetailedState#BLOCKED} based on * {@link #isNetworkBlocked}. + * @deprecated Uses mLegacyTypeTracker; cannot deal with multiple Networks of the same type. */ private NetworkInfo getFilteredNetworkInfo(int networkType, int uid) { NetworkInfo info = getNetworkInfoForType(networkType); return getFilteredNetworkInfo(info, networkType, uid); } + /* + * @deprecated Uses mLegacyTypeTracker; cannot deal with multiple Networks of the same type. + */ private NetworkInfo getFilteredNetworkInfo(NetworkInfo info, int networkType, int uid) { if (isNetworkBlocked(networkType, uid)) { // network is blocked; clone and override state @@ -839,6 +857,21 @@ public class ConnectivityService extends IConnectivityManager.Stub { return info; } + private NetworkInfo getFilteredNetworkInfo(NetworkAgentInfo nai, int uid) { + NetworkInfo info = nai.networkInfo; + if (isNetworkBlocked(nai, uid)) { + // network is blocked; clone and override state + info = new NetworkInfo(info); + info.setDetailedState(DetailedState.BLOCKED, null, null); + if (VDBG) log("returning Blocked NetworkInfo"); + } + if (mLockdownTracker != null) { + info = mLockdownTracker.augmentNetworkInfo(info); + if (VDBG) log("returning Locked NetworkInfo"); + } + return info; + } + /** * Return NetworkInfo for the active (i.e., connected) network interface. * It is assumed that at most one network is active at a time. If more @@ -946,7 +979,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { synchronized (nai) { if (nai.networkInfo == null) return null; - return getFilteredNetworkInfo(nai.networkInfo, nai.networkInfo.getType(), uid); + return getFilteredNetworkInfo(nai, uid); } } @@ -1304,6 +1337,12 @@ public class ConnectivityService extends IConnectivityManager.Stub { // } } + private void enforceInternetPermission() { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.INTERNET, + "ConnectivityService"); + } + private void enforceAccessPermission() { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.ACCESS_NETWORK_STATE, @@ -2443,7 +2482,22 @@ public class ConnectivityService extends IConnectivityManager.Stub { } public void reportBadNetwork(Network network) { - //TODO + enforceAccessPermission(); + enforceInternetPermission(); + + if (network == null) return; + + final int uid = Binder.getCallingUid(); + NetworkAgentInfo nai = null; + synchronized (mNetworkForNetId) { + nai = mNetworkForNetId.get(network.netId); + } + if (nai == null) return; + synchronized (nai) { + if (isNetworkBlocked(nai, uid)) return; + + nai.networkMonitor.sendMessage(NetworkMonitor.CMD_FORCE_REEVALUATION, uid); + } } public ProxyInfo getProxy() { @@ -4423,6 +4477,8 @@ public class ConnectivityService extends IConnectivityManager.Stub { loge("Unknown NetworkAgentInfo in handleConnectionValidated"); return; } + if (newNetwork.validated) return; + newNetwork.validated = true; boolean keep = newNetwork.isVPN(); boolean isNewDefault = false; if (DBG) log("handleConnectionValidated for "+newNetwork.name()); diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java index 5a97aee972..bba786dc5d 100644 --- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java @@ -47,6 +47,7 @@ public class NetworkAgentInfo { public final NetworkMonitor networkMonitor; public final NetworkMisc networkMisc; public boolean created; + public boolean validated; // The list of NetworkRequests being satisfied by this Network. public final SparseArray networkRequests = new SparseArray(); @@ -68,6 +69,7 @@ public class NetworkAgentInfo { networkMonitor = new NetworkMonitor(context, handler, this); networkMisc = misc; created = false; + validated = false; } public void addRequest(NetworkRequest networkRequest) {