Always-on app VPNs
Bug: 22547950
Change-Id: I46b204170bfac58d944f39b22f815b080de71a58
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index eda0982..ad4e450 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2415,6 +2415,53 @@
}
/**
+ * Called by a device or profile owner to configure an always-on VPN connection through a
+ * specific application for the current user.
+ * This connection is automatically granted and persisted after a reboot.
+ *
+ * <p>The designated package should declare a {@link android.net.VpnService} in its
+ * manifest guarded by {@link android.Manifest.permission#BIND_VPN_SERVICE},
+ * otherwise the call will fail.
+ *
+ * @param vpnPackage The package name for an installed VPN app on the device, or {@code null}
+ * to remove an existing always-on VPN configuration.
+ *
+ * @return {@code true} if the package is set as always-on VPN controller;
+ * {@code false} otherwise.
+ */
+ public boolean setAlwaysOnVpnPackage(@NonNull ComponentName admin,
+ @Nullable String vpnPackage) {
+ if (mService != null) {
+ try {
+ return mService.setAlwaysOnVpnPackage(admin, vpnPackage);
+ } catch (RemoteException e) {
+ Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Called by a device or profile owner to read the name of the package administering an
+ * always-on VPN connection for the current user.
+ * If there is no such package, or the always-on VPN is provided by the system instead
+ * of by an application, {@code null} will be returned.
+ *
+ * @return Package name of VPN controller responsible for always-on VPN,
+ * or {@code null} if none is set.
+ */
+ public String getAlwaysOnVpnPackage(@NonNull ComponentName admin) {
+ if (mService != null) {
+ try {
+ return mService.getAlwaysOnVpnPackage(admin);
+ } catch (RemoteException e) {
+ Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ }
+ }
+ return null;
+ }
+
+ /**
* Called by an application that is administering the device to disable all cameras
* on the device, for this user. After setting this, no applications running as this user
* will be able to access any cameras on the device.
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 30ce682..fb01dfb 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -144,6 +144,9 @@
void setCertInstallerPackage(in ComponentName who, String installerPackage);
String getCertInstallerPackage(in ComponentName who);
+ boolean setAlwaysOnVpnPackage(in ComponentName who, String vpnPackage);
+ String getAlwaysOnVpnPackage(in ComponentName who);
+
void addPersistentPreferredActivity(in ComponentName admin, in IntentFilter filter, in ComponentName activity);
void clearPackagePersistentPreferredActivities(in ComponentName admin, String packageName);
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 515e9a2..523f4c2 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -17,6 +17,7 @@
import static com.android.internal.util.Preconditions.checkNotNull;
+import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.app.PendingIntent;
@@ -686,6 +687,47 @@
}
/**
+ * 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.
+
+ * @return {@code true} if the package is set as always-on VPN controller;
+ * {@code false} otherwise.
+ * @hide
+ */
+ public boolean setAlwaysOnVpnPackageForUser(int userId, @Nullable String vpnPackage) {
+ try {
+ return mService.setAlwaysOnVpnPackage(userId, vpnPackage);
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
+ /**
+ * 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
+ */
+ public String getAlwaysOnVpnPackageForUser(int userId) {
+ try {
+ return mService.getAlwaysOnVpnPackage(userId);
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ /**
* Returns details about the currently active default data network
* for a given uid. This is for internal use only to avoid spying
* other apps.
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index d4dd669..d018731 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -117,6 +117,8 @@
VpnInfo[] getAllVpnInfo();
boolean updateLockdownVpn();
+ boolean setAlwaysOnVpnPackage(int userId, String packageName);
+ String getAlwaysOnVpnPackage(int userId);
int checkMobileProvisioning(int suggestedTimeOutMs);
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 4eaee0b..6eacafb 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -4402,6 +4402,13 @@
public static final String HTTP_PROXY = Global.HTTP_PROXY;
/**
+ * Package designated as always-on VPN provider.
+ *
+ * @hide
+ */
+ public static final String ALWAYS_ON_VPN_APP = "always_on_vpn_app";
+
+ /**
* Whether applications can be installed for this user via the system's
* {@link Intent#ACTION_INSTALL_PACKAGE} mechanism.
*