Merge changes Ia68f482a,I4911e214,Ied379654,I66d18512,Ie8e1bd63
* changes:
Check registering system default callback needs NETWORK_SETTINGS.
Move VPN code from ConnectivityService to VpnManagerService.
Add a skeleton VpnManagerService, and start it on boot.
Convert LockdownVpnTracker to NetworkCallbacks.
Minor fixes to VpnTransportInfo.
diff --git a/framework/src/android/net/ConnectivityFrameworkInitializer.java b/framework/src/android/net/ConnectivityFrameworkInitializer.java
index 9afa5d1..92a792b 100644
--- a/framework/src/android/net/ConnectivityFrameworkInitializer.java
+++ b/framework/src/android/net/ConnectivityFrameworkInitializer.java
@@ -49,17 +49,6 @@
}
);
- // TODO: move outside of the connectivity JAR
- SystemServiceRegistry.registerContextAwareService(
- Context.VPN_MANAGEMENT_SERVICE,
- VpnManager.class,
- (context) -> {
- final ConnectivityManager cm = context.getSystemService(
- ConnectivityManager.class);
- return cm.createVpnManager();
- }
- );
-
SystemServiceRegistry.registerContextAwareService(
Context.CONNECTIVITY_DIAGNOSTICS_SERVICE,
ConnectivityDiagnosticsManager.class,
diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java
index a972d9f..27386bc 100644
--- a/framework/src/android/net/ConnectivityManager.java
+++ b/framework/src/android/net/ConnectivityManager.java
@@ -824,6 +824,7 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562)
private final IConnectivityManager mService;
+
/**
* A kludge to facilitate static access where a Context pointer isn't available, like in the
* case of the static set/getProcessDefaultNetwork methods and from the Network class.
@@ -1069,106 +1070,55 @@
}
/**
- * Checks if a VPN app supports always-on mode.
- *
- * In order to support the always-on feature, an app has to
- * <ul>
- * <li>target {@link VERSION_CODES#N API 24} or above, and
- * <li>not opt out through the {@link VpnService#SERVICE_META_DATA_SUPPORTS_ALWAYS_ON}
- * meta-data field.
- * </ul>
- *
- * @param userId The identifier of the user for whom the VPN app is installed.
- * @param vpnPackage The canonical package name of the VPN app.
- * @return {@code true} if and only if the VPN app exists and supports always-on mode.
+ * Calls VpnManager#isAlwaysOnVpnPackageSupportedForUser.
+ * @deprecated TODO: remove when callers have migrated to VpnManager.
* @hide
*/
+ @Deprecated
public boolean isAlwaysOnVpnPackageSupportedForUser(int userId, @Nullable String vpnPackage) {
- try {
- return mService.isAlwaysOnVpnPackageSupported(userId, vpnPackage);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return getVpnManager().isAlwaysOnVpnPackageSupportedForUser(userId, vpnPackage);
}
/**
- * Configures an always-on VPN connection through a specific application.
- * This connection is automatically granted and persisted after a reboot.
- *
- * <p>The designated package should declare a {@link VpnService} in its
- * manifest guarded by {@link android.Manifest.permission.BIND_VPN_SERVICE},
- * otherwise the call will fail.
- *
- * @param userId The identifier of the user to set an always-on VPN for.
- * @param vpnPackage The package name for an installed VPN app on the device, or {@code null}
- * to remove an existing always-on VPN configuration.
- * @param lockdownEnabled {@code true} to disallow networking when the VPN is not connected or
- * {@code false} otherwise.
- * @param lockdownAllowlist The list of packages that are allowed to access network directly
- * when VPN is in lockdown mode but is not running. Non-existent packages are ignored so
- * this method must be called when a package that should be allowed is installed or
- * uninstalled.
- * @return {@code true} if the package is set as always-on VPN controller;
- * {@code false} otherwise.
+ * Calls VpnManager#setAlwaysOnVpnPackageForUser.
+ * @deprecated TODO: remove when callers have migrated to VpnManager.
* @hide
*/
- @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN)
+ @Deprecated
public boolean setAlwaysOnVpnPackageForUser(int userId, @Nullable String vpnPackage,
boolean lockdownEnabled, @Nullable List<String> lockdownAllowlist) {
- try {
- return mService.setAlwaysOnVpnPackage(
- userId, vpnPackage, lockdownEnabled, lockdownAllowlist);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return getVpnManager().setAlwaysOnVpnPackageForUser(userId, vpnPackage, lockdownEnabled,
+ lockdownAllowlist);
}
- /**
- * Returns the package name of the currently set always-on VPN application.
- * If there is no always-on VPN set, or the VPN is provided by the system instead
- * of by an app, {@code null} will be returned.
- *
- * @return Package name of VPN controller responsible for always-on VPN,
- * or {@code null} if none is set.
+ /**
+ * Calls VpnManager#getAlwaysOnVpnPackageForUser.
+ * @deprecated TODO: remove when callers have migrated to VpnManager.
* @hide
*/
- @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN)
+ @Deprecated
public String getAlwaysOnVpnPackageForUser(int userId) {
- try {
- return mService.getAlwaysOnVpnPackage(userId);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return getVpnManager().getAlwaysOnVpnPackageForUser(userId);
}
/**
- * @return whether always-on VPN is in lockdown mode.
- *
+ * Calls VpnManager#isVpnLockdownEnabled.
+ * @deprecated TODO: remove when callers have migrated to VpnManager.
* @hide
- **/
- @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN)
+ */
+ @Deprecated
public boolean isVpnLockdownEnabled(int userId) {
- try {
- return mService.isVpnLockdownEnabled(userId);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
-
+ return getVpnManager().isVpnLockdownEnabled(userId);
}
/**
- * @return the list of packages that are allowed to access network when always-on VPN is in
- * lockdown mode but not connected. Returns {@code null} when VPN lockdown is not active.
- *
+ * Calls VpnManager#getVpnLockdownAllowlist.
+ * @deprecated TODO: remove when callers have migrated to VpnManager.
* @hide
- **/
- @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN)
+ */
+ @Deprecated
public List<String> getVpnLockdownWhitelist(int userId) {
- try {
- return mService.getVpnLockdownWhitelist(userId);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return getVpnManager().getVpnLockdownAllowlist(userId);
}
/**
@@ -1221,6 +1171,45 @@
}
/**
+ * Informs ConnectivityService of whether the legacy lockdown VPN, as implemented by
+ * LockdownVpnTracker, is in use. This is deprecated for new devices starting from Android 12
+ * but is still supported for backwards compatibility.
+ * <p>
+ * This type of VPN is assumed always to use the system default network, and must always declare
+ * exactly one underlying network, which is the network that was the default when the VPN
+ * connected.
+ * <p>
+ * Calling this method with {@code true} enables legacy behaviour, specifically:
+ * <ul>
+ * <li>Any VPN that applies to userId 0 behaves specially with respect to deprecated
+ * {@link #CONNECTIVITY_ACTION} broadcasts. Any such broadcasts will have the state in the
+ * {@link #EXTRA_NETWORK_INFO} replaced by state of the VPN network. Also, any time the VPN
+ * connects, a {@link #CONNECTIVITY_ACTION} broadcast will be sent for the network
+ * underlying the VPN.</li>
+ * <li>Deprecated APIs that return {@link NetworkInfo} objects will have their state
+ * similarly replaced by the VPN network state.</li>
+ * <li>Information on current network interfaces passed to NetworkStatsService will not
+ * include any VPN interfaces.</li>
+ * </ul>
+ *
+ * @param enabled whether legacy lockdown VPN is enabled or disabled
+ *
+ * TODO: @SystemApi(client = MODULE_LIBRARIES)
+ *
+ * @hide
+ */
+ @RequiresPermission(anyOf = {
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+ android.Manifest.permission.NETWORK_SETTINGS})
+ public void setLegacyLockdownVpnEnabled(boolean enabled) {
+ try {
+ mService.setLegacyLockdownVpnEnabled(enabled);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Returns details about the currently active default data network
* for a given uid. This is for internal use only to avoid spying
* other apps.
@@ -3180,20 +3169,13 @@
}
/**
- * If the LockdownVpn mechanism is enabled, updates the vpn
- * with a reload of its profile.
- *
- * @return a boolean with {@code} indicating success
- *
- * <p>This method can only be called by the system UID
- * {@hide}
+ * Calls VpnManager#updateLockdownVpn.
+ * @deprecated TODO: remove when callers have migrated to VpnManager.
+ * @hide
*/
+ @Deprecated
public boolean updateLockdownVpn() {
- try {
- return mService.updateLockdownVpn();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return getVpnManager().updateLockdownVpn();
}
/**
@@ -4557,6 +4539,8 @@
try {
mService.factoryReset();
mTetheringManager.stopAllTethering();
+ // TODO: Migrate callers to VpnManager#factoryReset.
+ getVpnManager().factoryReset();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -4850,9 +4834,13 @@
return new TestNetworkManager(ITestNetworkManager.Stub.asInterface(tnBinder));
}
- /** @hide */
- public VpnManager createVpnManager() {
- return new VpnManager(mContext, mService);
+ /**
+ * Temporary hack to shim calls from ConnectivityManager to VpnManager. We cannot store a
+ * private final mVpnManager because ConnectivityManager is initialized before VpnManager.
+ * @hide TODO: remove.
+ */
+ public VpnManager getVpnManager() {
+ return mContext.getSystemService(VpnManager.class);
}
/** @hide */
diff --git a/framework/src/android/net/IConnectivityManager.aidl b/framework/src/android/net/IConnectivityManager.aidl
index befd4fb..6391802 100644
--- a/framework/src/android/net/IConnectivityManager.aidl
+++ b/framework/src/android/net/IConnectivityManager.aidl
@@ -43,9 +43,6 @@
import android.os.ResultReceiver;
import com.android.connectivity.aidl.INetworkAgent;
-import com.android.internal.net.LegacyVpnInfo;
-import com.android.internal.net.VpnConfig;
-import com.android.internal.net.VpnProfile;
/**
* Interface that answers queries about, and allows changing, the
@@ -123,35 +120,8 @@
ProxyInfo getProxyForNetwork(in Network nework);
- boolean prepareVpn(String oldPackage, String newPackage, int userId);
-
- void setVpnPackageAuthorization(String packageName, int userId, int vpnType);
-
- ParcelFileDescriptor establishVpn(in VpnConfig config);
-
- boolean provisionVpnProfile(in VpnProfile profile, String packageName);
-
- void deleteVpnProfile(String packageName);
-
- void startVpnProfile(String packageName);
-
- void stopVpnProfile(String packageName);
-
- VpnConfig getVpnConfig(int userId);
-
- @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
- void startLegacyVpn(in VpnProfile profile);
-
- LegacyVpnInfo getLegacyVpnInfo(int userId);
-
- boolean updateLockdownVpn();
- boolean isAlwaysOnVpnPackageSupported(int userId, String packageName);
- boolean setAlwaysOnVpnPackage(int userId, String packageName, boolean lockdown,
- in List<String> lockdownWhitelist);
- String getAlwaysOnVpnPackage(int userId);
- boolean isVpnLockdownEnabled(int userId);
- List<String> getVpnLockdownWhitelist(int userId);
void setRequireVpnForUids(boolean requireVpn, in UidRange[] ranges);
+ void setLegacyLockdownVpnEnabled(boolean enabled);
void setProvisioningNotificationVisible(boolean visible, int networkType, in String action);
@@ -200,10 +170,6 @@
int getRestoreDefaultNetworkDelay(int networkType);
- boolean addVpnAddress(String address, int prefixLength);
- boolean removeVpnAddress(String address, int prefixLength);
- boolean setUnderlyingNetworksForVpn(in Network[] networks);
-
void factoryReset();
void startNattKeepalive(in Network network, int intervalSeconds,
@@ -223,8 +189,6 @@
byte[] getNetworkWatchlistConfigHash();
int getConnectionOwnerUid(in ConnectionInfo connectionInfo);
- boolean isCallerCurrentAlwaysOnVpnApp();
- boolean isCallerCurrentAlwaysOnVpnLockdownApp();
void registerConnectivityDiagnosticsCallback(in IConnectivityDiagnosticsCallback callback,
in NetworkRequest request, String callingPackageName);
diff --git a/framework/src/android/net/VpnManager.java b/framework/src/android/net/VpnManager.java
index 1e30283..f472ed4 100644
--- a/framework/src/android/net/VpnManager.java
+++ b/framework/src/android/net/VpnManager.java
@@ -21,6 +21,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.UserIdInt;
import android.app.Activity;
import android.content.ComponentName;
@@ -37,6 +38,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.security.GeneralSecurityException;
+import java.util.List;
/**
* This class provides an interface for apps to manage platform VPN profiles
@@ -76,13 +78,19 @@
@Deprecated
public static final int TYPE_VPN_LEGACY = 3;
+ /**
+ * Channel for VPN notifications.
+ * @hide
+ */
+ public static final String NOTIFICATION_CHANNEL_VPN = "VPN";
+
/** @hide */
@IntDef(value = {TYPE_VPN_NONE, TYPE_VPN_SERVICE, TYPE_VPN_PLATFORM, TYPE_VPN_LEGACY})
@Retention(RetentionPolicy.SOURCE)
public @interface VpnType {}
@NonNull private final Context mContext;
- @NonNull private final IConnectivityManager mService;
+ @NonNull private final IVpnManager mService;
private static Intent getIntentForConfirmation() {
final Intent intent = new Intent();
@@ -101,9 +109,9 @@
*
* @hide
*/
- public VpnManager(@NonNull Context ctx, @NonNull IConnectivityManager service) {
+ public VpnManager(@NonNull Context ctx, @NonNull IVpnManager service) {
mContext = checkNotNull(ctx, "missing Context");
- mService = checkNotNull(service, "missing IConnectivityManager");
+ mService = checkNotNull(service, "missing IVpnManager");
}
/**
@@ -195,6 +203,19 @@
}
/**
+ * Resets all VPN settings back to factory defaults.
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+ public void factoryReset() {
+ try {
+ mService.factoryReset();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Prepare for a VPN application.
* VPN permissions are checked in the {@link Vpn} class. If the caller is not {@code userId},
* {@link android.Manifest.permission.INTERACT_ACROSS_USERS_FULL} permission is required.
@@ -240,6 +261,108 @@
}
/**
+ * Checks if a VPN app supports always-on mode.
+ *
+ * In order to support the always-on feature, an app has to
+ * <ul>
+ * <li>target {@link VERSION_CODES#N API 24} or above, and
+ * <li>not opt out through the {@link VpnService#SERVICE_META_DATA_SUPPORTS_ALWAYS_ON}
+ * meta-data field.
+ * </ul>
+ *
+ * @param userId The identifier of the user for whom the VPN app is installed.
+ * @param vpnPackage The canonical package name of the VPN app.
+ * @return {@code true} if and only if the VPN app exists and supports always-on mode.
+ * @hide
+ */
+ public boolean isAlwaysOnVpnPackageSupportedForUser(int userId, @Nullable String vpnPackage) {
+ try {
+ return mService.isAlwaysOnVpnPackageSupported(userId, vpnPackage);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Configures an always-on VPN connection through a specific application.
+ * This connection is automatically granted and persisted after a reboot.
+ *
+ * <p>The designated package should declare a {@link VpnService} in its
+ * manifest guarded by {@link android.Manifest.permission.BIND_VPN_SERVICE},
+ * otherwise the call will fail.
+ *
+ * @param userId The identifier of the user to set an always-on VPN for.
+ * @param vpnPackage The package name for an installed VPN app on the device, or {@code null}
+ * to remove an existing always-on VPN configuration.
+ * @param lockdownEnabled {@code true} to disallow networking when the VPN is not connected or
+ * {@code false} otherwise.
+ * @param lockdownAllowlist The list of packages that are allowed to access network directly
+ * when VPN is in lockdown mode but is not running. Non-existent packages are ignored so
+ * this method must be called when a package that should be allowed is installed or
+ * uninstalled.
+ * @return {@code true} if the package is set as always-on VPN controller;
+ * {@code false} otherwise.
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN)
+ public boolean setAlwaysOnVpnPackageForUser(int userId, @Nullable String vpnPackage,
+ boolean lockdownEnabled, @Nullable List<String> lockdownAllowlist) {
+ try {
+ return mService.setAlwaysOnVpnPackage(
+ userId, vpnPackage, lockdownEnabled, lockdownAllowlist);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns the package name of the currently set always-on VPN application.
+ * If there is no always-on VPN set, or the VPN is provided by the system instead
+ * of by an app, {@code null} will be returned.
+ *
+ * @return Package name of VPN controller responsible for always-on VPN,
+ * or {@code null} if none is set.
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN)
+ public String getAlwaysOnVpnPackageForUser(int userId) {
+ try {
+ return mService.getAlwaysOnVpnPackage(userId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * @return whether always-on VPN is in lockdown mode.
+ *
+ * @hide
+ **/
+ @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN)
+ public boolean isVpnLockdownEnabled(int userId) {
+ try {
+ return mService.isVpnLockdownEnabled(userId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * @return the list of packages that are allowed to access network when always-on VPN is in
+ * lockdown mode but not connected. Returns {@code null} when VPN lockdown is not active.
+ *
+ * @hide
+ **/
+ @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN)
+ public List<String> getVpnLockdownAllowlist(int userId) {
+ try {
+ return mService.getVpnLockdownAllowlist(userId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Return the legacy VPN information for the specified user ID.
* @hide
*/
diff --git a/framework/src/android/net/VpnService.java b/framework/src/android/net/VpnService.java
index 8e90a11..e43b0b6 100644
--- a/framework/src/android/net/VpnService.java
+++ b/framework/src/android/net/VpnService.java
@@ -170,12 +170,11 @@
"android.net.VpnService.SUPPORTS_ALWAYS_ON";
/**
- * Use IConnectivityManager since those methods are hidden and not
- * available in ConnectivityManager.
+ * Use IVpnManager since those methods are hidden and not available in VpnManager.
*/
- private static IConnectivityManager getService() {
- return IConnectivityManager.Stub.asInterface(
- ServiceManager.getService(Context.CONNECTIVITY_SERVICE));
+ private static IVpnManager getService() {
+ return IVpnManager.Stub.asInterface(
+ ServiceManager.getService(Context.VPN_MANAGEMENT_SERVICE));
}
/**
@@ -226,15 +225,15 @@
@SystemApi
@RequiresPermission(android.Manifest.permission.CONTROL_VPN)
public static void prepareAndAuthorize(Context context) {
- IConnectivityManager cm = getService();
+ IVpnManager vm = getService();
String packageName = context.getPackageName();
try {
// Only prepare if we're not already prepared.
int userId = context.getUserId();
- if (!cm.prepareVpn(packageName, null, userId)) {
- cm.prepareVpn(null, packageName, userId);
+ if (!vm.prepareVpn(packageName, null, userId)) {
+ vm.prepareVpn(null, packageName, userId);
}
- cm.setVpnPackageAuthorization(packageName, userId, VpnManager.TYPE_VPN_SERVICE);
+ vm.setVpnPackageAuthorization(packageName, userId, VpnManager.TYPE_VPN_SERVICE);
} catch (RemoteException e) {
// ignore
}