diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 94124652b9d2a..c5931dd756f0e 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,14 +833,33 @@ 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 + 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; + } + + 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); @@ -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); } } @@ -1315,6 +1348,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, @@ -2468,7 +2507,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() { @@ -4463,6 +4517,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 5a97aee9729c9..bba786dc5d9b0 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) { diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java index ff319d3794218..96872a7ee1c14 100644 --- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java +++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java @@ -27,6 +27,7 @@ import android.net.ConnectivityManager; import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkInfo; +import android.net.TrafficStats; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.Handler; @@ -139,35 +140,29 @@ public class NetworkMonitor extends StateMachine { */ private static final int CMD_REEVALUATE = BASE + 6; - /** - * Message to self indicating network evaluation is complete. - * arg1 = Token to ignore old messages. - * arg2 = HTTP response code of network evaluation. - */ - private static final int EVENT_REEVALUATION_COMPLETE = BASE + 7; - /** * Inform NetworkMonitor that the network has disconnected. */ - public static final int CMD_NETWORK_DISCONNECTED = BASE + 8; + public static final int CMD_NETWORK_DISCONNECTED = BASE + 7; /** * Force evaluation even if it has succeeded in the past. + * arg1 = UID responsible for requesting this reeval. Will be billed for data. */ - public static final int CMD_FORCE_REEVALUATION = BASE + 9; + public static final int CMD_FORCE_REEVALUATION = BASE + 8; /** * Message to self indicating captive portal login is complete. * arg1 = Token to ignore old messages. * arg2 = 1 if we should use this network, 0 otherwise. */ - private static final int CMD_CAPTIVE_PORTAL_LOGGED_IN = BASE + 10; + private static final int CMD_CAPTIVE_PORTAL_LOGGED_IN = BASE + 9; /** * Message to self indicating user desires to log into captive portal. * arg1 = Token to ignore old messages. */ - private static final int CMD_USER_WANTS_SIGN_IN = BASE + 11; + private static final int CMD_USER_WANTS_SIGN_IN = BASE + 10; /** * Request ConnectivityService display provisioning notification. @@ -175,22 +170,22 @@ public class NetworkMonitor extends StateMachine { * arg2 = NetID. * obj = Intent to be launched when notification selected by user, null if !arg1. */ - public static final int EVENT_PROVISIONING_NOTIFICATION = BASE + 12; + public static final int EVENT_PROVISIONING_NOTIFICATION = BASE + 11; /** * Message to self indicating sign-in app bypassed captive portal. */ - private static final int EVENT_APP_BYPASSED_CAPTIVE_PORTAL = BASE + 13; + private static final int EVENT_APP_BYPASSED_CAPTIVE_PORTAL = BASE + 12; /** * Message to self indicating no sign-in app responded. */ - private static final int EVENT_NO_APP_RESPONSE = BASE + 14; + private static final int EVENT_NO_APP_RESPONSE = BASE + 13; /** * Message to self indicating sign-in app indicates sign-in is not possible. */ - private static final int EVENT_APP_INDICATES_SIGN_IN_IMPOSSIBLE = BASE + 15; + private static final int EVENT_APP_INDICATES_SIGN_IN_IMPOSSIBLE = BASE + 14; private static final String LINGER_DELAY_PROPERTY = "persist.netmon.linger"; // Default to 30s linger time-out. @@ -205,6 +200,8 @@ public class NetworkMonitor extends StateMachine { private static final int MAX_RETRIES = 10; private final int mReevaluateDelayMs; private int mReevaluateToken = 0; + private static final int INVALID_UID = -1; + private int mUidResponsibleForReeval = INVALID_UID; private int mCaptivePortalLoggedInToken = 0; private int mUserPromptedToken = 0; @@ -282,6 +279,7 @@ public class NetworkMonitor extends StateMachine { return HANDLED; case CMD_FORCE_REEVALUATION: if (DBG) log("Forcing reevaluation"); + mUidResponsibleForReeval = message.arg1; transitionTo(mEvaluatingState); return HANDLED; default: @@ -322,20 +320,14 @@ public class NetworkMonitor extends StateMachine { private class EvaluatingState extends State { private int mRetries; - private class EvaluateInternetConnectivity extends Thread { - private int mToken; - EvaluateInternetConnectivity(int token) { - mToken = token; - } - public void run() { - sendMessage(EVENT_REEVALUATION_COMPLETE, mToken, isCaptivePortal()); - } - } - @Override public void enter() { mRetries = 0; sendMessage(CMD_REEVALUATE, ++mReevaluateToken, 0); + if (mUidResponsibleForReeval != INVALID_UID) { + TrafficStats.setThreadStatsUid(mUidResponsibleForReeval); + mUidResponsibleForReeval = INVALID_UID; + } } @Override @@ -356,14 +348,7 @@ public class NetworkMonitor extends StateMachine { transitionTo(mValidatedState); return HANDLED; } - // Kick off a thread to perform internet connectivity evaluation. - Thread thread = new EvaluateInternetConnectivity(mReevaluateToken); - thread.run(); - return HANDLED; - case EVENT_REEVALUATION_COMPLETE: - if (message.arg1 != mReevaluateToken) - return HANDLED; - int httpResponseCode = message.arg2; + int httpResponseCode = isCaptivePortal(); if (httpResponseCode == 204) { transitionTo(mValidatedState); } else if (httpResponseCode >= 200 && httpResponseCode <= 399) { @@ -375,10 +360,18 @@ public class NetworkMonitor extends StateMachine { sendMessageDelayed(msg, mReevaluateDelayMs); } return HANDLED; + case CMD_FORCE_REEVALUATION: + // Ignore duplicate requests. + return HANDLED; default: return NOT_HANDLED; } } + + @Override + public void exit() { + TrafficStats.clearThreadStatsUid(); + } } private class UserPromptedState extends State {