Expose a SystemApi method to prepare a VPN without consent.
This is NOT designed to be called normally. Most apps (even
system-privileged ones) should request user consent before launching a
VPN. However, it is needed to support flows where consent can be
obtained through other means external to the VPN flow itself.
The API requires a system-privileged permission, CONTROL_VPN.
Bug: 18327583
Change-Id: I1bcdcf0fb5707faeb861ec4535e7ccffea369ae7
diff --git a/core/java/android/net/VpnService.java b/core/java/android/net/VpnService.java
index c848993..d469487 100644
--- a/core/java/android/net/VpnService.java
+++ b/core/java/android/net/VpnService.java
@@ -19,6 +19,7 @@
import static android.system.OsConstants.AF_INET;
import static android.system.OsConstants.AF_INET6;
+import android.annotation.SystemApi;
import android.app.Activity;
import android.app.PendingIntent;
import android.app.Service;
@@ -164,6 +165,32 @@
}
/**
+ * Version of {@link #prepare(Context)} which does not require user consent.
+ *
+ * <p>Requires {@link android.Manifest.permission#CONTROL_VPN} and should generally not be
+ * used. Only acceptable in situations where user consent has been obtained through other means.
+ *
+ * <p>Once this is run, future preparations may be done with the standard prepare method as this
+ * will authorize the package to prepare the VPN without consent in the future.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static void prepareAndAuthorize(Context context) {
+ IConnectivityManager cm = getService();
+ String packageName = context.getPackageName();
+ try {
+ // Only prepare if we're not already prepared.
+ if (!cm.prepareVpn(packageName, null)) {
+ cm.prepareVpn(null, packageName);
+ }
+ cm.setVpnPackageAuthorization(true);
+ } catch (RemoteException e) {
+ // ignore
+ }
+ }
+
+ /**
* Protect a socket from VPN connections. After protecting, data sent
* through this socket will go directly to the underlying network,
* so its traffic will not be forwarded through the VPN.