am 6801c1b7: Merge "Implement ConnectivityManager.reportBadNetwork() to trigger network validation." into lmp-dev
* commit '6801c1b710eb7d1cbd3411abe0ef7a6cc7fd476a':
Implement ConnectivityManager.reportBadNetwork() to trigger network validation.
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 9412465..c5931dd 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -793,14 +793,28 @@
}
/**
- * 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,17 +833,36 @@
* 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);
if (DBG) log("returning Blocked NetworkInfo");
}
if (mLockdownTracker != null) {
@@ -946,7 +979,7 @@
synchronized (nai) {
if (nai.networkInfo == null) return null;
- return getFilteredNetworkInfo(nai.networkInfo, nai.networkInfo.getType(), uid);
+ return getFilteredNetworkInfo(nai, uid);
}
}
@@ -1315,6 +1348,12 @@
// }
}
+ 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 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 @@
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 5a97aee..bba786d 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 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<NetworkRequest> networkRequests = new SparseArray<NetworkRequest>();
@@ -68,6 +69,7 @@
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 ff319d3..96872a7 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.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;
@@ -140,34 +141,28 @@
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 @@
* 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 @@
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 @@
return HANDLED;
case CMD_FORCE_REEVALUATION:
if (DBG) log("Forcing reevaluation");
+ mUidResponsibleForReeval = message.arg1;
transitionTo(mEvaluatingState);
return HANDLED;
default:
@@ -322,20 +320,14 @@
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 @@
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 @@
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 {