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