Loading api/current.txt +2 −0 Original line number Diff line number Diff line Loading @@ -17686,6 +17686,7 @@ package android.net { method public boolean protect(int); method public boolean protect(java.net.Socket); method public boolean protect(java.net.DatagramSocket); method public boolean setUnderlyingNetworks(android.net.Network[]); field public static final java.lang.String SERVICE_INTERFACE = "android.net.VpnService"; } Loading @@ -17707,6 +17708,7 @@ package android.net { method public android.net.VpnService.Builder setConfigureIntent(android.app.PendingIntent); method public android.net.VpnService.Builder setMtu(int); method public android.net.VpnService.Builder setSession(java.lang.String); method public android.net.VpnService.Builder setUnderlyingNetworks(android.net.Network[]); } } core/java/android/net/IConnectivityManager.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -170,4 +170,5 @@ interface IConnectivityManager boolean addVpnAddress(String address, int prefixLength); boolean removeVpnAddress(String address, int prefixLength); boolean setUnderlyingNetworksForVpn(in Network[] networks); } core/java/android/net/VpnService.java +55 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.net.Network; import android.net.NetworkUtils; import android.os.Binder; import android.os.IBinder; Loading Loading @@ -287,6 +288,46 @@ public class VpnService extends Service { } } /** * Sets the underlying networks used by the VPN for its upstream connections. * * Used by the system to know the actual networks that carry traffic for apps affected by this * VPN in order to present this information to the user (e.g., via status bar icons). * * This method only needs to be called if the VPN has explicitly bound its underlying * communications channels — such as the socket(s) passed to {@link #protect(int)} — * to a {@code Network} using APIs such as {@link Network#bindSocket} or {@link * Network#bindDatagramSocket}. The VPN should call this method every time the set of {@code * Network}s it is using changes. * * {@code networks} is one of the following: * <ul> * <li><strong>a non-empty array</strong>: an array of one or more {@link Network}s, in * decreasing preference order. For example, if this VPN uses both wifi and mobile (cellular) * networks to carry app traffic, but prefers or uses wifi more than mobile, wifi should appear * first in the array.</li> * <li><strong>an empty array</strong>: a zero-element array, meaning that the VPN has no * underlying network connection, and thus, app traffic will not be sent or received.</li> * <li><strong>null</strong>: (default) signifies that the VPN uses whatever is the system's * default network. I.e., it doesn't use the {@code bindSocket} or {@code bindDatagramSocket} * APIs mentioned above to send traffic over specific channels. * </ul> * * This call will succeed only if the VPN is currently established. For setting this value when * the VPN has not yet been established, see {@link Builder#setUnderlyingNetworks}. * * @param networks An array of networks the VPN uses to tunnel traffic to/from its servers. * * @return {@code true} on success. */ public boolean setUnderlyingNetworks(Network[] networks) { try { return getService().setUnderlyingNetworksForVpn(networks); } catch (RemoteException e) { throw new IllegalStateException(e); } } /** * Return the communication interface to the service. This method returns * {@code null} on {@link Intent}s other than {@link #SERVICE_INTERFACE} Loading Loading @@ -662,6 +703,20 @@ public class VpnService extends Service { return this; } /** * Sets the underlying networks used by the VPN for its upstream connections. * * @see VpnService#setUnderlyingNetworks * * @param networks An array of networks the VPN uses to tunnel traffic to/from its servers. * * @return this {@link Builder} object to facilitate chaining method calls. */ public Builder setUnderlyingNetworks(Network[] networks) { mConfig.underlyingNetworks = networks != null ? networks.clone() : null; return this; } /** * Create a VPN interface using the parameters supplied to this * builder. The interface works on IP packets, and a file descriptor Loading core/java/com/android/internal/net/VpnConfig.java +4 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; import android.content.res.Resources; import android.net.LinkAddress; import android.net.Network; import android.net.RouteInfo; import android.os.Parcel; import android.os.Parcelable; Loading Loading @@ -99,6 +100,7 @@ public class VpnConfig implements Parcelable { public boolean allowBypass; public boolean allowIPv4; public boolean allowIPv6; public Network[] underlyingNetworks; public void updateAllowedFamilies(InetAddress address) { if (address instanceof Inet4Address) { Loading Loading @@ -162,6 +164,7 @@ public class VpnConfig implements Parcelable { out.writeInt(allowBypass ? 1 : 0); out.writeInt(allowIPv4 ? 1 : 0); out.writeInt(allowIPv6 ? 1 : 0); out.writeTypedArray(underlyingNetworks, flags); } public static final Parcelable.Creator<VpnConfig> CREATOR = Loading @@ -186,6 +189,7 @@ public class VpnConfig implements Parcelable { config.allowBypass = in.readInt() != 0; config.allowIPv4 = in.readInt() != 0; config.allowIPv6 = in.readInt() != 0; config.underlyingNetworks = in.createTypedArray(Network.CREATOR); return config; } Loading services/core/java/com/android/server/ConnectivityService.java +32 −0 Original line number Diff line number Diff line Loading @@ -865,6 +865,29 @@ public class ConnectivityService extends IConnectivityManager.Stub Network network = null; NetworkAgentInfo nai = mNetworkForRequestId.get(mDefaultRequest.requestId); if (!mLockdownEnabled) { int user = UserHandle.getUserId(uid); synchronized (mVpns) { Vpn vpn = mVpns.get(user); if (vpn != null && vpn.appliesToUid(uid)) { // getUnderlyingNetworks() returns: // null => the VPN didn't specify anything, so we use the default. // empty array => the VPN explicitly said "no default network". // non-empty array => the VPN specified one or more default networks; we use the // first one. Network[] networks = vpn.getUnderlyingNetworks(); if (networks != null) { if (networks.length > 0) { nai = getNetworkAgentInfoForNetwork(networks[0]); } else { nai = null; } } } } } if (nai != null) { synchronized (nai) { info = new NetworkInfo(nai.networkInfo); Loading Loading @@ -4376,4 +4399,13 @@ public class ConnectivityService extends IConnectivityManager.Stub return mVpns.get(user).removeAddress(address, prefixLength); } } @Override public boolean setUnderlyingNetworksForVpn(Network[] networks) { throwIfLockdownEnabled(); int user = UserHandle.getUserId(Binder.getCallingUid()); synchronized (mVpns) { return mVpns.get(user).setUnderlyingNetworks(networks); } } } Loading
api/current.txt +2 −0 Original line number Diff line number Diff line Loading @@ -17686,6 +17686,7 @@ package android.net { method public boolean protect(int); method public boolean protect(java.net.Socket); method public boolean protect(java.net.DatagramSocket); method public boolean setUnderlyingNetworks(android.net.Network[]); field public static final java.lang.String SERVICE_INTERFACE = "android.net.VpnService"; } Loading @@ -17707,6 +17708,7 @@ package android.net { method public android.net.VpnService.Builder setConfigureIntent(android.app.PendingIntent); method public android.net.VpnService.Builder setMtu(int); method public android.net.VpnService.Builder setSession(java.lang.String); method public android.net.VpnService.Builder setUnderlyingNetworks(android.net.Network[]); } }
core/java/android/net/IConnectivityManager.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -170,4 +170,5 @@ interface IConnectivityManager boolean addVpnAddress(String address, int prefixLength); boolean removeVpnAddress(String address, int prefixLength); boolean setUnderlyingNetworksForVpn(in Network[] networks); }
core/java/android/net/VpnService.java +55 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.net.Network; import android.net.NetworkUtils; import android.os.Binder; import android.os.IBinder; Loading Loading @@ -287,6 +288,46 @@ public class VpnService extends Service { } } /** * Sets the underlying networks used by the VPN for its upstream connections. * * Used by the system to know the actual networks that carry traffic for apps affected by this * VPN in order to present this information to the user (e.g., via status bar icons). * * This method only needs to be called if the VPN has explicitly bound its underlying * communications channels — such as the socket(s) passed to {@link #protect(int)} — * to a {@code Network} using APIs such as {@link Network#bindSocket} or {@link * Network#bindDatagramSocket}. The VPN should call this method every time the set of {@code * Network}s it is using changes. * * {@code networks} is one of the following: * <ul> * <li><strong>a non-empty array</strong>: an array of one or more {@link Network}s, in * decreasing preference order. For example, if this VPN uses both wifi and mobile (cellular) * networks to carry app traffic, but prefers or uses wifi more than mobile, wifi should appear * first in the array.</li> * <li><strong>an empty array</strong>: a zero-element array, meaning that the VPN has no * underlying network connection, and thus, app traffic will not be sent or received.</li> * <li><strong>null</strong>: (default) signifies that the VPN uses whatever is the system's * default network. I.e., it doesn't use the {@code bindSocket} or {@code bindDatagramSocket} * APIs mentioned above to send traffic over specific channels. * </ul> * * This call will succeed only if the VPN is currently established. For setting this value when * the VPN has not yet been established, see {@link Builder#setUnderlyingNetworks}. * * @param networks An array of networks the VPN uses to tunnel traffic to/from its servers. * * @return {@code true} on success. */ public boolean setUnderlyingNetworks(Network[] networks) { try { return getService().setUnderlyingNetworksForVpn(networks); } catch (RemoteException e) { throw new IllegalStateException(e); } } /** * Return the communication interface to the service. This method returns * {@code null} on {@link Intent}s other than {@link #SERVICE_INTERFACE} Loading Loading @@ -662,6 +703,20 @@ public class VpnService extends Service { return this; } /** * Sets the underlying networks used by the VPN for its upstream connections. * * @see VpnService#setUnderlyingNetworks * * @param networks An array of networks the VPN uses to tunnel traffic to/from its servers. * * @return this {@link Builder} object to facilitate chaining method calls. */ public Builder setUnderlyingNetworks(Network[] networks) { mConfig.underlyingNetworks = networks != null ? networks.clone() : null; return this; } /** * Create a VPN interface using the parameters supplied to this * builder. The interface works on IP packets, and a file descriptor Loading
core/java/com/android/internal/net/VpnConfig.java +4 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; import android.content.res.Resources; import android.net.LinkAddress; import android.net.Network; import android.net.RouteInfo; import android.os.Parcel; import android.os.Parcelable; Loading Loading @@ -99,6 +100,7 @@ public class VpnConfig implements Parcelable { public boolean allowBypass; public boolean allowIPv4; public boolean allowIPv6; public Network[] underlyingNetworks; public void updateAllowedFamilies(InetAddress address) { if (address instanceof Inet4Address) { Loading Loading @@ -162,6 +164,7 @@ public class VpnConfig implements Parcelable { out.writeInt(allowBypass ? 1 : 0); out.writeInt(allowIPv4 ? 1 : 0); out.writeInt(allowIPv6 ? 1 : 0); out.writeTypedArray(underlyingNetworks, flags); } public static final Parcelable.Creator<VpnConfig> CREATOR = Loading @@ -186,6 +189,7 @@ public class VpnConfig implements Parcelable { config.allowBypass = in.readInt() != 0; config.allowIPv4 = in.readInt() != 0; config.allowIPv6 = in.readInt() != 0; config.underlyingNetworks = in.createTypedArray(Network.CREATOR); return config; } Loading
services/core/java/com/android/server/ConnectivityService.java +32 −0 Original line number Diff line number Diff line Loading @@ -865,6 +865,29 @@ public class ConnectivityService extends IConnectivityManager.Stub Network network = null; NetworkAgentInfo nai = mNetworkForRequestId.get(mDefaultRequest.requestId); if (!mLockdownEnabled) { int user = UserHandle.getUserId(uid); synchronized (mVpns) { Vpn vpn = mVpns.get(user); if (vpn != null && vpn.appliesToUid(uid)) { // getUnderlyingNetworks() returns: // null => the VPN didn't specify anything, so we use the default. // empty array => the VPN explicitly said "no default network". // non-empty array => the VPN specified one or more default networks; we use the // first one. Network[] networks = vpn.getUnderlyingNetworks(); if (networks != null) { if (networks.length > 0) { nai = getNetworkAgentInfoForNetwork(networks[0]); } else { nai = null; } } } } } if (nai != null) { synchronized (nai) { info = new NetworkInfo(nai.networkInfo); Loading Loading @@ -4376,4 +4399,13 @@ public class ConnectivityService extends IConnectivityManager.Stub return mVpns.get(user).removeAddress(address, prefixLength); } } @Override public boolean setUnderlyingNetworksForVpn(Network[] networks) { throwIfLockdownEnabled(); int user = UserHandle.getUserId(Binder.getCallingUid()); synchronized (mVpns) { return mVpns.get(user).setUnderlyingNetworks(networks); } } }