• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.net;
18 
19 import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
20 
21 import static com.android.internal.util.Preconditions.checkNotNull;
22 
23 import android.annotation.FlaggedApi;
24 import android.annotation.IntDef;
25 import android.annotation.NonNull;
26 import android.annotation.Nullable;
27 import android.annotation.RequiresPermission;
28 import android.annotation.SdkConstant;
29 import android.annotation.SystemApi;
30 import android.annotation.UserIdInt;
31 import android.app.Activity;
32 import android.content.ComponentName;
33 import android.content.Context;
34 import android.content.Intent;
35 import android.content.res.Resources;
36 import android.net.platform.flags.Flags;
37 import android.os.RemoteException;
38 
39 import com.android.internal.net.LegacyVpnInfo;
40 import com.android.internal.net.VpnConfig;
41 import com.android.internal.net.VpnProfile;
42 
43 import java.io.IOException;
44 import java.lang.annotation.Retention;
45 import java.lang.annotation.RetentionPolicy;
46 import java.security.GeneralSecurityException;
47 import java.util.List;
48 
49 /**
50  * This class provides an interface for apps to manage platform VPN profiles
51  *
52  * <p>Apps can use this API to provide profiles with which the platform can set up a VPN without
53  * further app intermediation. When a VPN profile is present and the app is selected as an always-on
54  * VPN, the platform will directly trigger the negotiation of the VPN without starting or waking the
55  * app (unlike VpnService).
56  *
57  * <p>VPN apps using supported protocols should preferentially use this API over the {@link
58  * VpnService} API for ease-of-development and reduced maintenance burden. This also give the user
59  * the guarantee that VPN network traffic is not subjected to on-device packet interception.
60  *
61  * @see Ikev2VpnProfile
62  */
63 public class VpnManager {
64     /** Type representing a lack of VPN @hide */
65     @SystemApi(client = MODULE_LIBRARIES)
66     public static final int TYPE_VPN_NONE = -1;
67 
68     /**
69      * A VPN created by an app using the {@link VpnService} API.
70      * @hide
71      */
72     @SystemApi(client = MODULE_LIBRARIES)
73     public static final int TYPE_VPN_SERVICE = 1;
74 
75     /**
76      * A VPN created using a {@link VpnManager} API such as {@link #startProvisionedVpnProfile}.
77      * @hide
78      */
79     @SystemApi(client = MODULE_LIBRARIES)
80     public static final int TYPE_VPN_PLATFORM = 2;
81 
82     /**
83      * An IPsec VPN created by the built-in LegacyVpnRunner.
84      * @hide
85      */
86     @SystemApi(client = MODULE_LIBRARIES)
87     public static final int TYPE_VPN_LEGACY = 3;
88 
89     /**
90      * A VPN created by OEM code through other means than {@link VpnService} or {@link VpnManager}.
91      * @hide
92      */
93     @SystemApi(client = MODULE_LIBRARIES)
94     public static final int TYPE_VPN_OEM = 4;
95 
96     /**
97      * A VPN created by OEM code using {@link VpnService}, and which OEM code desires to
98      * differentiate from other VPN types. The core networking stack will treat this VPN type
99      * similarly to {@link #TYPE_VPN_SERVICE}.
100      * @hide
101      */
102     @FlaggedApi(Flags.FLAG_VPN_TYPE_OEM_SERVICE_AND_LEGACY)
103     @SystemApi(client = MODULE_LIBRARIES)
104     public static final int TYPE_VPN_OEM_SERVICE = 5;
105 
106     /**
107      * A VPN created by OEM code using the legacy VPN mechanisms, and which OEM code desires to
108      * differentiate from other VPN types. The core networking stack will treat this VPN type
109      * similarly to {@link #TYPE_VPN_LEGACY}.
110      * @hide
111      */
112     @FlaggedApi(Flags.FLAG_VPN_TYPE_OEM_SERVICE_AND_LEGACY)
113     @SystemApi(client = MODULE_LIBRARIES)
114     public static final int TYPE_VPN_OEM_LEGACY = 6;
115 
116     /**
117      * Channel for VPN notifications.
118      * @hide
119      */
120     public static final String NOTIFICATION_CHANNEL_VPN = "VPN";
121 
122     /**
123      * Action sent in {@link android.content.Intent}s to VpnManager clients when an event occurred.
124      *
125      * <p>If the provisioning application declares a service handling this intent action, but is not
126      * already running, it will be started. Upon starting, the application is granted a short grace
127      * period to run in the background even while the device is idle to handle any potential
128      * failures. Applications requiring long-running actions triggered by one of these events should
129      * declare a foreground service to prevent being killed once the grace period expires.
130      *
131      * This action will have a category of either {@link #CATEGORY_EVENT_IKE_ERROR},
132      * {@link #CATEGORY_EVENT_NETWORK_ERROR}, or {@link #CATEGORY_EVENT_DEACTIVATED_BY_USER},
133      * that the app can use to filter events it's interested in reacting to.
134      *
135      * It will also contain the following extras :
136      * <ul>
137      *   <li>{@link #EXTRA_SESSION_KEY}, a {@code String} for the session key, as returned by
138      *       {@link #startProvisionedVpnProfileSession}.
139      *   <li>{@link #EXTRA_TIMESTAMP_MILLIS}, a long for the timestamp at which the error occurred,
140      *       in milliseconds since the epoch, as returned by
141      *       {@link java.lang.System#currentTimeMillis}.
142      *   <li>{@link #EXTRA_UNDERLYING_NETWORK}, a {@link Network} containing the underlying
143      *       network at the time the error occurred, or null if none. Note that this network
144      *       may have disconnected already.
145      *   <li>{@link #EXTRA_UNDERLYING_NETWORK_CAPABILITIES}, a {@link NetworkCapabilities} for
146      *       the underlying network at the time the error occurred.
147      *   <li>{@link #EXTRA_UNDERLYING_LINK_PROPERTIES}, a {@link LinkProperties} for the underlying
148      *       network at the time the error occurred.
149      * </ul>
150      * When this event is an error, either {@link #CATEGORY_EVENT_IKE_ERROR} or
151      * {@link #CATEGORY_EVENT_NETWORK_ERROR}, the following extras will be populated :
152      * <ul>
153      *   <li>{@link #EXTRA_ERROR_CLASS}, an {@code int} for the class of error, either
154      *       {@link #ERROR_CLASS_RECOVERABLE} or {@link #ERROR_CLASS_NOT_RECOVERABLE}.
155      *   <li>{@link #EXTRA_ERROR_CODE}, an {@code int} error code specific to the error. See
156      *       {@link #EXTRA_ERROR_CODE} for details.
157      * </ul>
158      */
159     @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
160     public static final String ACTION_VPN_MANAGER_EVENT = "android.net.action.VPN_MANAGER_EVENT";
161 
162     /**
163      * An IKE protocol error occurred.
164      *
165      * Codes (in {@link #EXTRA_ERROR_CODE}) are the codes from
166      * {@link android.net.ipsec.ike.exceptions.IkeProtocolException}, as defined by IANA in
167      * "IKEv2 Notify Message Types - Error Types".
168      */
169     @SdkConstant(SdkConstant.SdkConstantType.INTENT_CATEGORY)
170     public static final String CATEGORY_EVENT_IKE_ERROR = "android.net.category.EVENT_IKE_ERROR";
171 
172     /**
173      * A network error occurred.
174      *
175      * Error codes (in {@link #EXTRA_ERROR_CODE}) are ERROR_CODE_NETWORK_*.
176      */
177     @SdkConstant(SdkConstant.SdkConstantType.INTENT_CATEGORY)
178     public static final String CATEGORY_EVENT_NETWORK_ERROR =
179             "android.net.category.EVENT_NETWORK_ERROR";
180 
181     /**
182      * The user deactivated the VPN.
183      *
184      * This can happen either when the user turns the VPN off explicitly, or when they select
185      * a different VPN provider.
186      */
187     @SdkConstant(SdkConstant.SdkConstantType.INTENT_CATEGORY)
188     public static final String CATEGORY_EVENT_DEACTIVATED_BY_USER =
189             "android.net.category.EVENT_DEACTIVATED_BY_USER";
190 
191     /**
192      * The always-on state of this VPN was changed
193      *
194      * <p>This may be the result of a user changing VPN settings, or a Device Policy Manager app
195      * having changed the VPN policy.
196      */
197     @SdkConstant(SdkConstant.SdkConstantType.INTENT_CATEGORY)
198     public static final String CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED =
199             "android.net.category.EVENT_ALWAYS_ON_STATE_CHANGED";
200 
201     /**
202      * The VpnProfileState at the time that this event occurred.
203      *
204      * <p>This extra may be null if the VPN was revoked by the user, or the profile was deleted.
205      */
206     public static final String EXTRA_VPN_PROFILE_STATE = "android.net.extra.VPN_PROFILE_STATE";
207 
208     /**
209      * The key of the session that experienced this event, as a {@code String}.
210      *
211      * This is the same key that was returned by {@link #startProvisionedVpnProfileSession}.
212      */
213     public static final String EXTRA_SESSION_KEY = "android.net.extra.SESSION_KEY";
214 
215     /**
216      * The network that was underlying the VPN when the event occurred, as a {@link Network}.
217      *
218      * <p>This extra will be null if there was no underlying network at the time of the event, or
219      *    the underlying network has no bearing on the event, as in the case of:
220      * <ul>
221      *   <li>CATEGORY_EVENT_DEACTIVATED_BY_USER
222      *   <li>CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED
223      * </ul>
224      */
225     public static final String EXTRA_UNDERLYING_NETWORK = "android.net.extra.UNDERLYING_NETWORK";
226 
227     /**
228      * The {@link NetworkCapabilities} of the underlying network when the event occurred.
229      *
230      * <p>This extra will be null if there was no underlying network at the time of the event, or
231      *    the underlying network has no bearing on the event, as in the case of:
232      * <ul>
233      *   <li>CATEGORY_EVENT_DEACTIVATED_BY_USER
234      *   <li>CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED
235      * </ul>
236      */
237     public static final String EXTRA_UNDERLYING_NETWORK_CAPABILITIES =
238             "android.net.extra.UNDERLYING_NETWORK_CAPABILITIES";
239 
240     /**
241      * The {@link LinkProperties} of the underlying network when the event occurred.
242      *
243      * <p>This extra will be null if there was no underlying network at the time of the event, or
244      *    the underlying network has no bearing on the event, as in the case of:
245      * <ul>
246      *   <li>CATEGORY_EVENT_DEACTIVATED_BY_USER
247      *   <li>CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED
248      * </ul>
249      */
250     public static final String EXTRA_UNDERLYING_LINK_PROPERTIES =
251             "android.net.extra.UNDERLYING_LINK_PROPERTIES";
252 
253     /**
254      * A {@code long} timestamp containing the time at which the event occurred.
255      *
256      * This is a number of milliseconds since the epoch, suitable to be compared with
257      * {@link java.lang.System#currentTimeMillis}.
258      */
259     public static final String EXTRA_TIMESTAMP_MILLIS = "android.net.extra.TIMESTAMP_MILLIS";
260 
261     /**
262      * Extra for the error class, as an {@code int}.
263      *
264      * This is always either {@link #ERROR_CLASS_NOT_RECOVERABLE} or
265      * {@link #ERROR_CLASS_RECOVERABLE}. This extra is only populated for error categories.
266      */
267     public static final String EXTRA_ERROR_CLASS = "android.net.extra.ERROR_CLASS";
268 
269     /**
270      * Extra for an error code, as an {@code int}.
271      *
272      * <ul>
273      *   <li>For {@link #CATEGORY_EVENT_NETWORK_ERROR}, this is one of the
274      *       {@code ERROR_CODE_NETWORK_*} constants.
275      *   <li>For {@link #CATEGORY_EVENT_IKE_ERROR}, this is one of values defined in
276      *       {@link android.net.ipsec.ike.exceptions.IkeProtocolException}.ERROR_TYPE_*.
277      * </ul>
278      * For non-error categories, this extra is not populated.
279      */
280     public static final String EXTRA_ERROR_CODE = "android.net.extra.ERROR_CODE";
281 
282     /**
283      * {@link #EXTRA_ERROR_CLASS} coding for a non-recoverable error.
284      *
285      * This error is fatal, e.g. configuration error. The stack will not retry connection.
286      */
287     public static final int ERROR_CLASS_NOT_RECOVERABLE = 1;
288 
289     /**
290      * {@link #EXTRA_ERROR_CLASS} coding for a recoverable error.
291      *
292      * The stack experienced an error but will retry with exponential backoff, e.g. network timeout.
293      */
294     public static final int ERROR_CLASS_RECOVERABLE = 2;
295 
296     /**
297      * An {@link #EXTRA_ERROR_CODE} for {@link #CATEGORY_EVENT_NETWORK_ERROR} to indicate that the
298      * network host isn't known.
299      *
300      * This happens when domain name resolution could not resolve an IP address for the
301      * specified host. {@see java.net.UnknownHostException}
302      */
303     public static final int ERROR_CODE_NETWORK_UNKNOWN_HOST = 0;
304 
305     /**
306      * An {@link #EXTRA_ERROR_CODE} for {@link #CATEGORY_EVENT_NETWORK_ERROR} indicating a timeout.
307      *
308      * For Ikev2 VPNs, this happens typically after a retransmission failure.
309      * {@see android.net.ipsec.ike.exceptions.IkeTimeoutException}
310      */
311     public static final int ERROR_CODE_NETWORK_PROTOCOL_TIMEOUT = 1;
312 
313     /**
314      * An {@link #EXTRA_ERROR_CODE} for {@link #CATEGORY_EVENT_NETWORK_ERROR} indicating that
315      * network connectivity was lost.
316      *
317      * The most common reason for this error is that the underlying network was disconnected,
318      * {@see android.net.ipsec.ike.exceptions.IkeNetworkLostException}.
319      */
320     public static final int ERROR_CODE_NETWORK_LOST = 2;
321 
322     /**
323      * An {@link #EXTRA_ERROR_CODE} for {@link #CATEGORY_EVENT_NETWORK_ERROR} indicating an
324      * input/output error.
325      *
326      * This code happens when reading or writing to sockets on the underlying networks was
327      * terminated by an I/O error. {@see IOException}.
328      */
329     public static final int ERROR_CODE_NETWORK_IO = 3;
330 
331     /** @hide */
332     @IntDef(value = {TYPE_VPN_NONE, TYPE_VPN_SERVICE, TYPE_VPN_PLATFORM, TYPE_VPN_LEGACY,
333             TYPE_VPN_OEM, TYPE_VPN_OEM_SERVICE, TYPE_VPN_OEM_LEGACY})
334     @Retention(RetentionPolicy.SOURCE)
335     public @interface VpnType {}
336 
337     @NonNull private final Context mContext;
338     @NonNull private final IVpnManager mService;
339 
getIntentForConfirmation()340     private static Intent getIntentForConfirmation() {
341         final Intent intent = new Intent();
342         final ComponentName componentName = ComponentName.unflattenFromString(
343                 Resources.getSystem().getString(
344                         com.android.internal.R.string.config_platformVpnConfirmDialogComponent));
345         intent.setComponent(componentName);
346         return intent;
347     }
348 
349     /**
350      * Create an instance of the VpnManager with the given context.
351      *
352      * <p>Internal only. Applications are expected to obtain an instance of the VpnManager via the
353      * {@link Context.getSystemService()} method call.
354      *
355      * @hide
356      */
VpnManager(@onNull Context ctx, @NonNull IVpnManager service)357     public VpnManager(@NonNull Context ctx, @NonNull IVpnManager service) {
358         mContext = checkNotNull(ctx, "missing Context");
359         mService = checkNotNull(service, "missing IVpnManager");
360     }
361 
362     /**
363      * Install a VpnProfile configuration keyed on the calling app's package name.
364      *
365      * <p>This method returns {@code null} if user consent has already been granted, or an {@link
366      * Intent} to a system activity. If an intent is returned, the application should launch the
367      * activity using {@link Activity#startActivityForResult} to request user consent. The activity
368      * may pop up a dialog to require user action, and the result will come back via its {@link
369      * Activity#onActivityResult}. If the result is {@link Activity#RESULT_OK}, the user has
370      * consented, and the VPN profile can be started.
371      *
372      * @param profile the VpnProfile provided by this package. Will override any previous VpnProfile
373      *     stored for this package.
374      * @return an Intent requesting user consent to start the VPN, or null if consent is not
375      *     required based on privileges or previous user consent.
376      */
377     @Nullable
provisionVpnProfile(@onNull PlatformVpnProfile profile)378     public Intent provisionVpnProfile(@NonNull PlatformVpnProfile profile) {
379         final VpnProfile internalProfile;
380 
381         try {
382             internalProfile = profile.toVpnProfile();
383         } catch (GeneralSecurityException | IOException e) {
384             // Conversion to VpnProfile failed; this is an invalid profile. Both of these exceptions
385             // indicate a failure to convert a PrivateKey or X509Certificate to a Base64 encoded
386             // string as required by the VpnProfile.
387             throw new IllegalArgumentException("Failed to serialize PlatformVpnProfile", e);
388         }
389 
390         try {
391             // Profile can never be null; it either gets set, or an exception is thrown.
392             if (mService.provisionVpnProfile(internalProfile, mContext.getOpPackageName())) {
393                 return null;
394             }
395         } catch (RemoteException e) {
396             throw e.rethrowFromSystemServer();
397         }
398         return getIntentForConfirmation();
399     }
400 
401     /**
402      * Delete the VPN profile configuration that was provisioned by the calling app
403      *
404      * @throws SecurityException if this would violate user settings
405      */
deleteProvisionedVpnProfile()406     public void deleteProvisionedVpnProfile() {
407         try {
408             mService.deleteVpnProfile(mContext.getOpPackageName());
409         } catch (RemoteException e) {
410             throw e.rethrowFromSystemServer();
411         }
412     }
413 
414     /**
415      * Request the startup of a previously provisioned VPN.
416      *
417      * @return A unique key corresponding to this session.
418      * @throws SecurityException exception if user or device settings prevent this VPN from being
419      *         setup, or if user consent has not been granted
420      */
421     @NonNull
startProvisionedVpnProfileSession()422     public String startProvisionedVpnProfileSession() {
423         try {
424             return mService.startVpnProfile(mContext.getOpPackageName());
425         } catch (RemoteException e) {
426             throw e.rethrowFromSystemServer();
427         }
428     }
429 
430     /**
431      * Request the startup of a previously provisioned VPN.
432      *
433      * @throws SecurityException exception if user or device settings prevent this VPN from being
434      *         setup, or if user consent has not been granted
435      * @deprecated This method is replaced by startProvisionedVpnProfileSession which returns a
436      *             session key for the caller to diagnose the errors.
437      */
438     @Deprecated
startProvisionedVpnProfile()439     public void startProvisionedVpnProfile() {
440         startProvisionedVpnProfileSession();
441     }
442 
443     /** Tear down the VPN provided by the calling app (if any) */
stopProvisionedVpnProfile()444     public void stopProvisionedVpnProfile() {
445         try {
446             mService.stopVpnProfile(mContext.getOpPackageName());
447         } catch (RemoteException e) {
448             throw e.rethrowFromSystemServer();
449         }
450     }
451 
452     /**
453      * Return the VPN configuration for the given user ID.
454      * @hide
455      */
456     @Nullable
getVpnConfig(@serIdInt int userId)457     public VpnConfig getVpnConfig(@UserIdInt int userId) {
458         try {
459             return mService.getVpnConfig(userId);
460         } catch (RemoteException e) {
461             throw e.rethrowFromSystemServer();
462         }
463     }
464 
465     /**
466      * Retrieve the VpnProfileState for the profile provisioned by the calling package.
467      *
468      * @return the VpnProfileState with current information, or null if there was no profile
469      *         provisioned and started by the calling package.
470      */
471     @Nullable
getProvisionedVpnProfileState()472     public VpnProfileState getProvisionedVpnProfileState() {
473         try {
474             return mService.getProvisionedVpnProfileState(mContext.getOpPackageName());
475         } catch (RemoteException e) {
476             throw e.rethrowFromSystemServer();
477         }
478     }
479 
480     /**
481      * Resets all VPN settings back to factory defaults.
482      * @hide
483      */
484     @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
factoryReset()485     public void factoryReset() {
486         try {
487             mService.factoryReset();
488         } catch (RemoteException e) {
489             throw e.rethrowFromSystemServer();
490         }
491     }
492 
493     /**
494      * Prepare for a VPN application.
495      * VPN permissions are checked in the {@link Vpn} class. If the caller is not {@code userId},
496      * {@link android.Manifest.permission.INTERACT_ACROSS_USERS_FULL} permission is required.
497      *
498      * @param oldPackage Package name of the application which currently controls VPN, which will
499      *                   be replaced. If there is no such application, this should should either be
500      *                   {@code null} or {@link VpnConfig.LEGACY_VPN}.
501      * @param newPackage Package name of the application which should gain control of VPN, or
502      *                   {@code null} to disable.
503      * @param userId User for whom to prepare the new VPN.
504      *
505      * @hide
506      */
prepareVpn(@ullable String oldPackage, @Nullable String newPackage, int userId)507     public boolean prepareVpn(@Nullable String oldPackage, @Nullable String newPackage,
508             int userId) {
509         try {
510             return mService.prepareVpn(oldPackage, newPackage, userId);
511         } catch (RemoteException e) {
512             throw e.rethrowFromSystemServer();
513         }
514     }
515 
516     /**
517      * Set whether the VPN package has the ability to launch VPNs without user intervention. This
518      * method is used by system-privileged apps. VPN permissions are checked in the {@link Vpn}
519      * class. If the caller is not {@code userId}, {@link
520      * android.Manifest.permission.INTERACT_ACROSS_USERS_FULL} permission is required.
521      *
522      * @param packageName The package for which authorization state should change.
523      * @param userId User for whom {@code packageName} is installed.
524      * @param vpnType The {@link VpnManager.VpnType} constant representing what class of VPN
525      *     permissions should be granted. When unauthorizing an app, {@link
526      *     VpnManager.TYPE_VPN_NONE} should be used.
527      * @hide
528      */
setVpnPackageAuthorization( String packageName, int userId, @VpnManager.VpnType int vpnType)529     public void setVpnPackageAuthorization(
530             String packageName, int userId, @VpnManager.VpnType int vpnType) {
531         try {
532             mService.setVpnPackageAuthorization(packageName, userId, vpnType);
533         } catch (RemoteException e) {
534             throw e.rethrowFromSystemServer();
535         }
536     }
537 
538     /**
539      * Checks if a VPN app supports always-on mode.
540      *
541      * In order to support the always-on feature, an app has to
542      * <ul>
543      *     <li>target {@link VERSION_CODES#N API 24} or above, and
544      *     <li>not opt out through the {@link VpnService#SERVICE_META_DATA_SUPPORTS_ALWAYS_ON}
545      *         meta-data field.
546      * </ul>
547      *
548      * @param userId The identifier of the user for whom the VPN app is installed.
549      * @param vpnPackage The canonical package name of the VPN app.
550      * @return {@code true} if and only if the VPN app exists and supports always-on mode.
551      * @hide
552      */
isAlwaysOnVpnPackageSupportedForUser(int userId, @Nullable String vpnPackage)553     public boolean isAlwaysOnVpnPackageSupportedForUser(int userId, @Nullable String vpnPackage) {
554         try {
555             return mService.isAlwaysOnVpnPackageSupported(userId, vpnPackage);
556         } catch (RemoteException e) {
557             throw e.rethrowFromSystemServer();
558         }
559     }
560 
561     /**
562      * Configures an always-on VPN connection through a specific application.
563      * This connection is automatically granted and persisted after a reboot.
564      *
565      * <p>The designated package should declare a {@link VpnService} in its
566      *    manifest guarded by {@link android.Manifest.permission.BIND_VPN_SERVICE},
567      *    otherwise the call will fail.
568      *
569      * @param userId The identifier of the user to set an always-on VPN for.
570      * @param vpnPackage The package name for an installed VPN app on the device, or {@code null}
571      *                   to remove an existing always-on VPN configuration.
572      * @param lockdownEnabled {@code true} to disallow networking when the VPN is not connected or
573      *        {@code false} otherwise.
574      * @param lockdownAllowlist The list of packages that are allowed to access network directly
575      *         when VPN is in lockdown mode but is not running. Non-existent packages are ignored so
576      *         this method must be called when a package that should be allowed is installed or
577      *         uninstalled.
578      * @return {@code true} if the package is set as always-on VPN controller;
579      *         {@code false} otherwise.
580      * @hide
581      */
582     @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN)
setAlwaysOnVpnPackageForUser(int userId, @Nullable String vpnPackage, boolean lockdownEnabled, @Nullable List<String> lockdownAllowlist)583     public boolean setAlwaysOnVpnPackageForUser(int userId, @Nullable String vpnPackage,
584             boolean lockdownEnabled, @Nullable List<String> lockdownAllowlist) {
585         try {
586             return mService.setAlwaysOnVpnPackage(
587                     userId, vpnPackage, lockdownEnabled, lockdownAllowlist);
588         } catch (RemoteException e) {
589             throw e.rethrowFromSystemServer();
590         }
591     }
592 
593     /**
594      * Returns the package name of the currently set always-on VPN application.
595      * If there is no always-on VPN set, or the VPN is provided by the system instead
596      * of by an app, {@code null} will be returned.
597      *
598      * @return Package name of VPN controller responsible for always-on VPN,
599      *         or {@code null} if none is set.
600      * @hide
601      */
602     @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN)
getAlwaysOnVpnPackageForUser(int userId)603     public String getAlwaysOnVpnPackageForUser(int userId) {
604         try {
605             return mService.getAlwaysOnVpnPackage(userId);
606         } catch (RemoteException e) {
607             throw e.rethrowFromSystemServer();
608         }
609     }
610 
611     /**
612      * @return whether always-on VPN is in lockdown mode.
613      *
614      * @hide
615      **/
616     @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN)
isVpnLockdownEnabled(int userId)617     public boolean isVpnLockdownEnabled(int userId) {
618         try {
619             return mService.isVpnLockdownEnabled(userId);
620         } catch (RemoteException e) {
621             throw e.rethrowFromSystemServer();
622         }
623     }
624 
625     /**
626      * Sets the application exclusion list for the specified VPN profile.
627      *
628      * <p>If an app in the set of excluded apps is not installed for the given user, it will be
629      * skipped in the list of app exclusions. If apps are installed or removed, any active VPN will
630      * have its UID set updated automatically. If the caller is not {@code userId},
631      * {@link android.Manifest.permission.INTERACT_ACROSS_USERS_FULL} permission is required.
632      *
633      * <p>This will ONLY affect VpnManager profiles. As such, the NETWORK_SETTINGS provider MUST NOT
634      * allow configuration of these options if the application has not provided a VPN profile.
635      *
636      * @param userId the identifier of the user to set app exclusion list
637      * @param vpnPackage The package name for an installed VPN app on the device
638      * @param excludedApps the app exclusion list
639      * @throws IllegalStateException exception if vpn for the @code userId} is not ready yet.
640      *
641      * @return whether setting the list is successful or not
642      * @hide
643      */
644     @RequiresPermission(anyOf = {
645             android.Manifest.permission.NETWORK_SETTINGS,
646             NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
647             android.Manifest.permission.NETWORK_STACK})
setAppExclusionList(int userId, @NonNull String vpnPackage, @NonNull List<String> excludedApps)648     public boolean setAppExclusionList(int userId, @NonNull String vpnPackage,
649             @NonNull List<String> excludedApps) {
650         try {
651             return mService.setAppExclusionList(userId, vpnPackage, excludedApps);
652         } catch (RemoteException e) {
653             throw e.rethrowFromSystemServer();
654         }
655     }
656 
657     /**
658      * Gets the application exclusion list for the specified VPN profile. If the caller is not
659      * {@code userId}, {@link android.Manifest.permission.INTERACT_ACROSS_USERS_FULL} permission
660      * is required.
661      *
662      * @param userId the identifier of the user to set app exclusion list
663      * @param vpnPackage The package name for an installed VPN app on the device
664      * @return the list of packages for the specified VPN profile or null if no corresponding VPN
665      *         profile configured.
666      *
667      * @hide
668      */
669     @RequiresPermission(anyOf = {
670             android.Manifest.permission.NETWORK_SETTINGS,
671             NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
672             android.Manifest.permission.NETWORK_STACK})
673     @Nullable
getAppExclusionList(int userId, @NonNull String vpnPackage)674     public List<String> getAppExclusionList(int userId, @NonNull String vpnPackage) {
675         try {
676             return mService.getAppExclusionList(userId, vpnPackage);
677         } catch (RemoteException e) {
678             throw e.rethrowFromSystemServer();
679         }
680     }
681 
682     /**
683      * @return the list of packages that are allowed to access network when always-on VPN is in
684      * lockdown mode but not connected. Returns {@code null} when VPN lockdown is not active.
685      *
686      * @hide
687      **/
688     @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN)
getVpnLockdownAllowlist(int userId)689     public List<String> getVpnLockdownAllowlist(int userId) {
690         try {
691             return mService.getVpnLockdownAllowlist(userId);
692         } catch (RemoteException e) {
693             throw e.rethrowFromSystemServer();
694         }
695     }
696 
697     /**
698      * Return the legacy VPN information for the specified user ID.
699      * @hide
700      */
getLegacyVpnInfo(@serIdInt int userId)701     public LegacyVpnInfo getLegacyVpnInfo(@UserIdInt int userId) {
702         try {
703             return mService.getLegacyVpnInfo(userId);
704         } catch (RemoteException e) {
705             throw e.rethrowFromSystemServer();
706         }
707     }
708 
709     /**
710      * Starts a legacy VPN.
711      *
712      * Legacy VPN is deprecated starting from Android S. So this API shouldn't be called if the
713      * initial SDK version of device is Android S+. Otherwise, UnsupportedOperationException will be
714      * thrown.
715      * @hide
716      */
startLegacyVpn(VpnProfile profile)717     public void startLegacyVpn(VpnProfile profile) {
718         try {
719             mService.startLegacyVpn(profile);
720         } catch (RemoteException e) {
721             throw e.rethrowFromSystemServer();
722         }
723     }
724 
725     /**
726      * Informs the service that legacy lockdown VPN state should be updated (e.g., if its keystore
727      * entry has been updated). If the LockdownVpn mechanism is enabled, updates the vpn
728      * with a reload of its profile.
729      *
730      * <p>This method can only be called by the system UID
731      * @return a boolean indicating success
732      *
733      * @hide
734      */
updateLockdownVpn()735     public boolean updateLockdownVpn() {
736         try {
737             return mService.updateLockdownVpn();
738         } catch (RemoteException e) {
739             throw e.rethrowFromSystemServer();
740         }
741     }
742 
743     /**
744      * Get the vpn profile owned by the calling uid with the given name from the vpn database.
745      *
746      * <p>Note this method should not be used for platform VPN profiles. </p>
747      *
748      * @param name The name of the profile to retrieve.
749      * @return the unstructured blob for the matching vpn profile.
750      * Returns null if no profile with a matching name was found.
751      * @hide
752      */
753     @Nullable
getFromVpnProfileStore(@onNull String name)754     public byte[] getFromVpnProfileStore(@NonNull String name) {
755         try {
756             return mService.getFromVpnProfileStore(name);
757         } catch (RemoteException e) {
758             throw e.rethrowFromSystemServer();
759         }
760     }
761 
762     /**
763      * Put the given vpn profile owned by the calling uid with the given name into the vpn database.
764      * Existing profiles with the same name will be replaced.
765      *
766      * <p>Note this method should not be used for platform VPN profiles.
767      * To update a platform VPN, use provisionVpnProfile() instead. </p>
768      *
769      * @param name The name of the profile to put.
770      * @param blob The profile.
771      * @return true if the profile was successfully added. False otherwise.
772      * @hide
773      */
putIntoVpnProfileStore(@onNull String name, @NonNull byte[] blob)774     public boolean putIntoVpnProfileStore(@NonNull String name, @NonNull byte[] blob) {
775         try {
776             return mService.putIntoVpnProfileStore(name, blob);
777         } catch (RemoteException e) {
778             throw e.rethrowFromSystemServer();
779         }
780     }
781 
782     /**
783      * Removes the vpn profile owned by the calling uid with the given name from the vpn database.
784      *
785      * <p>Note this method should not be used for platform VPN profiles.
786      * To remove a platform VPN, use deleteVpnProfile() instead.</p>
787      *
788      * @param name The name of the profile to be removed.
789      * @return true if a profile was removed. False if no profile with a matching name was found.
790      * @hide
791      */
removeFromVpnProfileStore(@onNull String name)792     public boolean removeFromVpnProfileStore(@NonNull String name) {
793         try {
794             return mService.removeFromVpnProfileStore(name);
795         } catch (RemoteException e) {
796             throw e.rethrowFromSystemServer();
797         }
798     }
799 
800     /**
801      * Returns a list of the name suffixes of the vpn profiles owned by the calling uid in the vpn
802      * database matching the given prefix, sorted in ascending order.
803      *
804      * <p>Note this method should not be used for platform VPN profiles. </p>
805      *
806      * @param prefix The prefix to match.
807      * @return an array of strings representing the name suffixes stored in the profile database
808      * matching the given prefix. The return value may be empty but never null.
809      * @hide
810      */
811     @NonNull
listFromVpnProfileStore(@onNull String prefix)812     public String[] listFromVpnProfileStore(@NonNull String prefix) {
813         try {
814             return mService.listFromVpnProfileStore(prefix);
815         } catch (RemoteException e) {
816             throw e.rethrowFromSystemServer();
817         }
818     }
819 }
820