diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index ff1a4414eb..4215f207ea 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -720,6 +720,19 @@ public class ConnectivityManager { } } + /** + * Returns an array of of {@link NetworkCapabilities} objects, representing + * the Networks that applications run by the given user will use by default. + * @hide + */ + public NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser(int userId) { + try { + return mService.getDefaultNetworkCapabilitiesForUser(userId); + } catch (RemoteException e) { + return null; + } + } + /** * Returns details about the Provisioning or currently active default data network. When * connected, this network is the default route for outgoing connections. diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index 79f920e0c2..802121093a 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -49,6 +49,7 @@ interface IConnectivityManager NetworkInfo[] getAllNetworkInfo(); Network getNetworkForType(int networkType); Network[] getAllNetworks(); + NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser(int userId); NetworkInfo getProvisioningOrActiveNetworkInfo(); diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index ce7ad65fef..a7f9c5bcc0 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -154,9 +154,16 @@ public final class NetworkCapabilities implements Parcelable { */ public static final int NET_CAPABILITY_NOT_VPN = 15; + /** + * Indicates that connectivity on this network was successfully validated. For example, for a + * network with NET_CAPABILITY_INTERNET, it means that Internet connectivity was successfully + * detected. + * @hide + */ + public static final int NET_CAPABILITY_VALIDATED = 16; private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS; - private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_NOT_VPN; + private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_VALIDATED; /** * Adds the given capability to this {@code NetworkCapability} instance. diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 5eec0b7692..c5af085d87 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -1065,6 +1065,72 @@ public class ConnectivityService extends IConnectivityManager.Stub return result.toArray(new Network[result.size()]); } + private NetworkCapabilities getNetworkCapabilitiesAndValidation(NetworkAgentInfo nai) { + if (nai != null) { + synchronized (nai) { + if (nai.created) { + NetworkCapabilities nc = new NetworkCapabilities(nai.networkCapabilities); + if (nai.validated) { + nc.addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED); + } else { + nc.removeCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED); + } + return nc; + } + } + } + return null; + } + + @Override + public NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser(int userId) { + // The basic principle is: if an app's traffic could possibly go over a + // network, without the app doing anything multinetwork-specific, + // (hence, by "default"), then include that network's capabilities in + // the array. + // + // In the normal case, app traffic only goes over the system's default + // network connection, so that's the only network returned. + // + // With a VPN in force, some app traffic may go into the VPN, and thus + // over whatever underlying networks the VPN specifies, while other app + // traffic may go over the system default network (e.g.: a split-tunnel + // VPN, or an app disallowed by the VPN), so the set of networks + // returned includes the VPN's underlying networks and the system + // default. + enforceAccessPermission(); + + HashMap result = new HashMap(); + + NetworkAgentInfo nai = getDefaultNetwork(); + NetworkCapabilities nc = getNetworkCapabilitiesAndValidation(getDefaultNetwork()); + if (nc != null) { + result.put(nai.network, nc); + } + + if (!mLockdownEnabled) { + synchronized (mVpns) { + Vpn vpn = mVpns.get(userId); + if (vpn != null) { + Network[] networks = vpn.getUnderlyingNetworks(); + if (networks != null) { + for (Network network : networks) { + nai = getNetworkAgentInfoForNetwork(network); + nc = getNetworkCapabilitiesAndValidation(nai); + if (nc != null) { + result.put(nai.network, nc); + } + } + } + } + } + } + + NetworkCapabilities[] out = new NetworkCapabilities[result.size()]; + out = result.values().toArray(out); + return out; + } + @Override public boolean isNetworkSupported(int networkType) { enforceAccessPermission(); @@ -3544,8 +3610,12 @@ public class ConnectivityService extends IConnectivityManager.Stub // Note: if mDefaultRequest is changed, NetworkMonitor needs to be updated. private final NetworkRequest mDefaultRequest; + private NetworkAgentInfo getDefaultNetwork() { + return mNetworkForRequestId.get(mDefaultRequest.requestId); + } + private boolean isDefaultNetwork(NetworkAgentInfo nai) { - return mNetworkForRequestId.get(mDefaultRequest.requestId) == nai; + return nai == getDefaultNetwork(); } public void registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,