/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.net;

import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;

import static com.android.internal.util.Preconditions.checkNotNull;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
import android.annotation.UserIdInt;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.os.RemoteException;

import com.android.internal.net.LegacyVpnInfo;
import com.android.internal.net.VpnConfig;
import com.android.internal.net.VpnProfile;

import java.io.IOException;
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
 *
 * <p>Apps can use this API to provide profiles with which the platform can set up a VPN without
 * further app intermediation. When a VPN profile is present and the app is selected as an always-on
 * VPN, the platform will directly trigger the negotiation of the VPN without starting or waking the
 * app (unlike VpnService).
 *
 * <p>VPN apps using supported protocols should preferentially use this API over the {@link
 * VpnService} API for ease-of-development and reduced maintenance burden. This also give the user
 * the guarantee that VPN network traffic is not subjected to on-device packet interception.
 *
 * @see Ikev2VpnProfile
 */
public class VpnManager {
    /** Type representing a lack of VPN @hide */
    @SystemApi(client = MODULE_LIBRARIES)
    public static final int TYPE_VPN_NONE = -1;

    /**
     * A VPN created by an app using the {@link VpnService} API.
     * @hide
     */
    @SystemApi(client = MODULE_LIBRARIES)
    public static final int TYPE_VPN_SERVICE = 1;

    /**
     * A VPN created using a {@link VpnManager} API such as {@link #startProvisionedVpnProfile}.
     * @hide
     */
    @SystemApi(client = MODULE_LIBRARIES)
    public static final int TYPE_VPN_PLATFORM = 2;

    /**
     * An IPsec VPN created by the built-in LegacyVpnRunner.
     * @hide
     */
    @SystemApi(client = MODULE_LIBRARIES)
    public static final int TYPE_VPN_LEGACY = 3;

    /**
     * An VPN created by OEM code through other means than {@link VpnService} or {@link VpnManager}.
     * @hide
     */
    @SystemApi(client = MODULE_LIBRARIES)
    public static final int TYPE_VPN_OEM = 4;

    /**
     * Channel for VPN notifications.
     * @hide
     */
    public static final String NOTIFICATION_CHANNEL_VPN = "VPN";

    /**
     * Action sent in {@link android.content.Intent}s to VpnManager clients when an event occurred.
     *
     * <p>If the provisioning application declares a service handling this intent action, but is not
     * already running, it will be started. Upon starting, the application is granted a short grace
     * period to run in the background even while the device is idle to handle any potential
     * failures. Applications requiring long-running actions triggered by one of these events should
     * declare a foreground service to prevent being killed once the grace period expires.
     *
     * This action will have a category of either {@link #CATEGORY_EVENT_IKE_ERROR},
     * {@link #CATEGORY_EVENT_NETWORK_ERROR}, or {@link #CATEGORY_EVENT_DEACTIVATED_BY_USER},
     * that the app can use to filter events it's interested in reacting to.
     *
     * It will also contain the following extras :
     * <ul>
     *   <li>{@link #EXTRA_SESSION_KEY}, a {@code String} for the session key, as returned by
     *       {@link #startProvisionedVpnProfileSession}.
     *   <li>{@link #EXTRA_TIMESTAMP_MILLIS}, a long for the timestamp at which the error occurred,
     *       in milliseconds since the epoch, as returned by
     *       {@link java.lang.System#currentTimeMillis}.
     *   <li>{@link #EXTRA_UNDERLYING_NETWORK}, a {@link Network} containing the underlying
     *       network at the time the error occurred, or null if none. Note that this network
     *       may have disconnected already.
     *   <li>{@link #EXTRA_UNDERLYING_NETWORK_CAPABILITIES}, a {@link NetworkCapabilities} for
     *       the underlying network at the time the error occurred.
     *   <li>{@link #EXTRA_UNDERLYING_LINK_PROPERTIES}, a {@link LinkProperties} for the underlying
     *       network at the time the error occurred.
     * </ul>
     * When this event is an error, either {@link #CATEGORY_EVENT_IKE_ERROR} or
     * {@link #CATEGORY_EVENT_NETWORK_ERROR}, the following extras will be populated :
     * <ul>
     *   <li>{@link #EXTRA_ERROR_CLASS}, an {@code int} for the class of error, either
     *       {@link #ERROR_CLASS_RECOVERABLE} or {@link #ERROR_CLASS_NOT_RECOVERABLE}.
     *   <li>{@link #EXTRA_ERROR_CODE}, an {@code int} error code specific to the error. See
     *       {@link #EXTRA_ERROR_CODE} for details.
     * </ul>
     */
    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
    public static final String ACTION_VPN_MANAGER_EVENT = "android.net.action.VPN_MANAGER_EVENT";

    /**
     * An IKE protocol error occurred.
     *
     * Codes (in {@link #EXTRA_ERROR_CODE}) are the codes from
     * {@link android.net.ipsec.ike.exceptions.IkeProtocolException}, as defined by IANA in
     * "IKEv2 Notify Message Types - Error Types".
     */
    @SdkConstant(SdkConstant.SdkConstantType.INTENT_CATEGORY)
    public static final String CATEGORY_EVENT_IKE_ERROR = "android.net.category.EVENT_IKE_ERROR";

    /**
     * A network error occurred.
     *
     * Error codes (in {@link #EXTRA_ERROR_CODE}) are ERROR_CODE_NETWORK_*.
     */
    @SdkConstant(SdkConstant.SdkConstantType.INTENT_CATEGORY)
    public static final String CATEGORY_EVENT_NETWORK_ERROR =
            "android.net.category.EVENT_NETWORK_ERROR";

    /**
     * The user deactivated the VPN.
     *
     * This can happen either when the user turns the VPN off explicitly, or when they select
     * a different VPN provider.
     */
    @SdkConstant(SdkConstant.SdkConstantType.INTENT_CATEGORY)
    public static final String CATEGORY_EVENT_DEACTIVATED_BY_USER =
            "android.net.category.EVENT_DEACTIVATED_BY_USER";

    /**
     * The always-on state of this VPN was changed
     *
     * <p>This may be the result of a user changing VPN settings, or a Device Policy Manager app
     * having changed the VPN policy.
     */
    @SdkConstant(SdkConstant.SdkConstantType.INTENT_CATEGORY)
    public static final String CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED =
            "android.net.category.EVENT_ALWAYS_ON_STATE_CHANGED";

    /**
     * The VpnProfileState at the time that this event occurred.
     *
     * <p>This extra may be null if the VPN was revoked by the user, or the profile was deleted.
     */
    public static final String EXTRA_VPN_PROFILE_STATE = "android.net.extra.VPN_PROFILE_STATE";

    /**
     * The key of the session that experienced this event, as a {@code String}.
     *
     * This is the same key that was returned by {@link #startProvisionedVpnProfileSession}.
     */
    public static final String EXTRA_SESSION_KEY = "android.net.extra.SESSION_KEY";

    /**
     * The network that was underlying the VPN when the event occurred, as a {@link Network}.
     *
     * <p>This extra will be null if there was no underlying network at the time of the event, or
     *    the underlying network has no bearing on the event, as in the case of:
     * <ul>
     *   <li>CATEGORY_EVENT_DEACTIVATED_BY_USER
     *   <li>CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED
     * </ul>
     */
    public static final String EXTRA_UNDERLYING_NETWORK = "android.net.extra.UNDERLYING_NETWORK";

    /**
     * The {@link NetworkCapabilities} of the underlying network when the event occurred.
     *
     * <p>This extra will be null if there was no underlying network at the time of the event, or
     *    the underlying network has no bearing on the event, as in the case of:
     * <ul>
     *   <li>CATEGORY_EVENT_DEACTIVATED_BY_USER
     *   <li>CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED
     * </ul>
     */
    public static final String EXTRA_UNDERLYING_NETWORK_CAPABILITIES =
            "android.net.extra.UNDERLYING_NETWORK_CAPABILITIES";

    /**
     * The {@link LinkProperties} of the underlying network when the event occurred.
     *
     * <p>This extra will be null if there was no underlying network at the time of the event, or
     *    the underlying network has no bearing on the event, as in the case of:
     * <ul>
     *   <li>CATEGORY_EVENT_DEACTIVATED_BY_USER
     *   <li>CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED
     * </ul>
     */
    public static final String EXTRA_UNDERLYING_LINK_PROPERTIES =
            "android.net.extra.UNDERLYING_LINK_PROPERTIES";

    /**
     * A {@code long} timestamp containing the time at which the event occurred.
     *
     * This is a number of milliseconds since the epoch, suitable to be compared with
     * {@link java.lang.System#currentTimeMillis}.
     */
    public static final String EXTRA_TIMESTAMP_MILLIS = "android.net.extra.TIMESTAMP_MILLIS";

    /**
     * Extra for the error class, as an {@code int}.
     *
     * This is always either {@link #ERROR_CLASS_NOT_RECOVERABLE} or
     * {@link #ERROR_CLASS_RECOVERABLE}. This extra is only populated for error categories.
     */
    public static final String EXTRA_ERROR_CLASS = "android.net.extra.ERROR_CLASS";

    /**
     * Extra for an error code, as an {@code int}.
     *
     * <ul>
     *   <li>For {@link #CATEGORY_EVENT_NETWORK_ERROR}, this is one of the
     *       {@code ERROR_CODE_NETWORK_*} constants.
     *   <li>For {@link #CATEGORY_EVENT_IKE_ERROR}, this is one of values defined in
     *       {@link android.net.ipsec.ike.exceptions.IkeProtocolException}.ERROR_TYPE_*.
     * </ul>
     * For non-error categories, this extra is not populated.
     */
    public static final String EXTRA_ERROR_CODE = "android.net.extra.ERROR_CODE";

    /**
     * {@link #EXTRA_ERROR_CLASS} coding for a non-recoverable error.
     *
     * This error is fatal, e.g. configuration error. The stack will not retry connection.
     */
    public static final int ERROR_CLASS_NOT_RECOVERABLE = 1;

    /**
     * {@link #EXTRA_ERROR_CLASS} coding for a recoverable error.
     *
     * The stack experienced an error but will retry with exponential backoff, e.g. network timeout.
     */
    public static final int ERROR_CLASS_RECOVERABLE = 2;

    /**
     * An {@link #EXTRA_ERROR_CODE} for {@link #CATEGORY_EVENT_NETWORK_ERROR} to indicate that the
     * network host isn't known.
     *
     * This happens when domain name resolution could not resolve an IP address for the
     * specified host. {@see java.net.UnknownHostException}
     */
    public static final int ERROR_CODE_NETWORK_UNKNOWN_HOST = 0;

    /**
     * An {@link #EXTRA_ERROR_CODE} for {@link #CATEGORY_EVENT_NETWORK_ERROR} indicating a timeout.
     *
     * For Ikev2 VPNs, this happens typically after a retransmission failure.
     * {@see android.net.ipsec.ike.exceptions.IkeTimeoutException}
     */
    public static final int ERROR_CODE_NETWORK_PROTOCOL_TIMEOUT = 1;

    /**
     * An {@link #EXTRA_ERROR_CODE} for {@link #CATEGORY_EVENT_NETWORK_ERROR} indicating that
     * network connectivity was lost.
     *
     * The most common reason for this error is that the underlying network was disconnected,
     * {@see android.net.ipsec.ike.exceptions.IkeNetworkLostException}.
     */
    public static final int ERROR_CODE_NETWORK_LOST = 2;

    /**
     * An {@link #EXTRA_ERROR_CODE} for {@link #CATEGORY_EVENT_NETWORK_ERROR} indicating an
     * input/output error.
     *
     * This code happens when reading or writing to sockets on the underlying networks was
     * terminated by an I/O error. {@see IOException}.
     */
    public static final int ERROR_CODE_NETWORK_IO = 3;

    /** @hide */
    @IntDef(value = {TYPE_VPN_NONE, TYPE_VPN_SERVICE, TYPE_VPN_PLATFORM, TYPE_VPN_LEGACY,
            TYPE_VPN_OEM})
    @Retention(RetentionPolicy.SOURCE)
    public @interface VpnType {}

    @NonNull private final Context mContext;
    @NonNull private final IVpnManager mService;

    private static Intent getIntentForConfirmation() {
        final Intent intent = new Intent();
        final ComponentName componentName = ComponentName.unflattenFromString(
                Resources.getSystem().getString(
                        com.android.internal.R.string.config_platformVpnConfirmDialogComponent));
        intent.setComponent(componentName);
        return intent;
    }

    /**
     * Create an instance of the VpnManager with the given context.
     *
     * <p>Internal only. Applications are expected to obtain an instance of the VpnManager via the
     * {@link Context.getSystemService()} method call.
     *
     * @hide
     */
    public VpnManager(@NonNull Context ctx, @NonNull IVpnManager service) {
        mContext = checkNotNull(ctx, "missing Context");
        mService = checkNotNull(service, "missing IVpnManager");
    }

    /**
     * Install a VpnProfile configuration keyed on the calling app's package name.
     *
     * <p>This method returns {@code null} if user consent has already been granted, or an {@link
     * Intent} to a system activity. If an intent is returned, the application should launch the
     * activity using {@link Activity#startActivityForResult} to request user consent. The activity
     * may pop up a dialog to require user action, and the result will come back via its {@link
     * Activity#onActivityResult}. If the result is {@link Activity#RESULT_OK}, the user has
     * consented, and the VPN profile can be started.
     *
     * @param profile the VpnProfile provided by this package. Will override any previous VpnProfile
     *     stored for this package.
     * @return an Intent requesting user consent to start the VPN, or null if consent is not
     *     required based on privileges or previous user consent.
     */
    @Nullable
    public Intent provisionVpnProfile(@NonNull PlatformVpnProfile profile) {
        final VpnProfile internalProfile;

        try {
            internalProfile = profile.toVpnProfile();
        } catch (GeneralSecurityException | IOException e) {
            // Conversion to VpnProfile failed; this is an invalid profile. Both of these exceptions
            // indicate a failure to convert a PrivateKey or X509Certificate to a Base64 encoded
            // string as required by the VpnProfile.
            throw new IllegalArgumentException("Failed to serialize PlatformVpnProfile", e);
        }

        try {
            // Profile can never be null; it either gets set, or an exception is thrown.
            if (mService.provisionVpnProfile(internalProfile, mContext.getOpPackageName())) {
                return null;
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
        return getIntentForConfirmation();
    }

    /**
     * Delete the VPN profile configuration that was provisioned by the calling app
     *
     * @throws SecurityException if this would violate user settings
     */
    public void deleteProvisionedVpnProfile() {
        try {
            mService.deleteVpnProfile(mContext.getOpPackageName());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Request the startup of a previously provisioned VPN.
     *
     * @return A unique key corresponding to this session.
     * @throws SecurityException exception if user or device settings prevent this VPN from being
     *         setup, or if user consent has not been granted
     */
    @NonNull
    public String startProvisionedVpnProfileSession() {
        try {
            return mService.startVpnProfile(mContext.getOpPackageName());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Request the startup of a previously provisioned VPN.
     *
     * @throws SecurityException exception if user or device settings prevent this VPN from being
     *         setup, or if user consent has not been granted
     * @deprecated This method is replaced by startProvisionedVpnProfileSession which returns a
     *             session key for the caller to diagnose the errors.
     */
    @Deprecated
    public void startProvisionedVpnProfile() {
        startProvisionedVpnProfileSession();
    }

    /** Tear down the VPN provided by the calling app (if any) */
    public void stopProvisionedVpnProfile() {
        try {
            mService.stopVpnProfile(mContext.getOpPackageName());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Return the VPN configuration for the given user ID.
     * @hide
     */
    @Nullable
    public VpnConfig getVpnConfig(@UserIdInt int userId) {
        try {
            return mService.getVpnConfig(userId);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Retrieve the VpnProfileState for the profile provisioned by the calling package.
     *
     * @return the VpnProfileState with current information, or null if there was no profile
     *         provisioned by the calling package.
     */
    @Nullable
    public VpnProfileState getProvisionedVpnProfileState() {
        try {
            return mService.getProvisionedVpnProfileState(mContext.getOpPackageName());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * 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.
     *
     * @param oldPackage Package name of the application which currently controls VPN, which will
     *                   be replaced. If there is no such application, this should should either be
     *                   {@code null} or {@link VpnConfig.LEGACY_VPN}.
     * @param newPackage Package name of the application which should gain control of VPN, or
     *                   {@code null} to disable.
     * @param userId User for whom to prepare the new VPN.
     *
     * @hide
     */
    public boolean prepareVpn(@Nullable String oldPackage, @Nullable String newPackage,
            int userId) {
        try {
            return mService.prepareVpn(oldPackage, newPackage, userId);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Set whether the VPN package has the ability to launch VPNs without user intervention. This
     * method is used by system-privileged apps. 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.
     *
     * @param packageName The package for which authorization state should change.
     * @param userId User for whom {@code packageName} is installed.
     * @param vpnType The {@link VpnManager.VpnType} constant representing what class of VPN
     *     permissions should be granted. When unauthorizing an app, {@link
     *     VpnManager.TYPE_VPN_NONE} should be used.
     * @hide
     */
    public void setVpnPackageAuthorization(
            String packageName, int userId, @VpnManager.VpnType int vpnType) {
        try {
            mService.setVpnPackageAuthorization(packageName, userId, vpnType);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * 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();
        }
    }

    /**
     * Sets the application exclusion list for the specified VPN profile.
     *
     * <p>If an app in the set of excluded apps is not installed for the given user, it will be
     * skipped in the list of app exclusions. If apps are installed or removed, any active VPN will
     * have its UID set updated automatically. If the caller is not {@code userId},
     * {@link android.Manifest.permission.INTERACT_ACROSS_USERS_FULL} permission is required.
     *
     * <p>This will ONLY affect VpnManager profiles. As such, the NETWORK_SETTINGS provider MUST NOT
     * allow configuration of these options if the application has not provided a VPN profile.
     *
     * @param userId the identifier of the user to set app exclusion list
     * @param vpnPackage The package name for an installed VPN app on the device
     * @param excludedApps the app exclusion list
     * @throws IllegalStateException exception if vpn for the @code userId} is not ready yet.
     *
     * @return whether setting the list is successful or not
     * @hide
     */
    @RequiresPermission(anyOf = {
            android.Manifest.permission.NETWORK_SETTINGS,
            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
            android.Manifest.permission.NETWORK_STACK})
    public boolean setAppExclusionList(int userId, @NonNull String vpnPackage,
            @NonNull List<String> excludedApps) {
        try {
            return mService.setAppExclusionList(userId, vpnPackage, excludedApps);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Gets the application exclusion list for the specified VPN profile. If the caller is not
     * {@code userId}, {@link android.Manifest.permission.INTERACT_ACROSS_USERS_FULL} permission
     * is required.
     *
     * @param userId the identifier of the user to set app exclusion list
     * @param vpnPackage The package name for an installed VPN app on the device
     * @return the list of packages for the specified VPN profile or null if no corresponding VPN
     *         profile configured.
     *
     * @hide
     */
    @RequiresPermission(anyOf = {
            android.Manifest.permission.NETWORK_SETTINGS,
            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
            android.Manifest.permission.NETWORK_STACK})
    @Nullable
    public List<String> getAppExclusionList(int userId, @NonNull String vpnPackage) {
        try {
            return mService.getAppExclusionList(userId, vpnPackage);
        } 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
     */
    public LegacyVpnInfo getLegacyVpnInfo(@UserIdInt int userId) {
        try {
            return mService.getLegacyVpnInfo(userId);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Starts a legacy VPN.
     *
     * Legacy VPN is deprecated starting from Android S. So this API shouldn't be called if the
     * initial SDK version of device is Android S+. Otherwise, UnsupportedOperationException will be
     * thrown.
     * @hide
     */
    public void startLegacyVpn(VpnProfile profile) {
        try {
            mService.startLegacyVpn(profile);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Informs the service that legacy lockdown VPN state should be updated (e.g., if its keystore
     * entry has been updated). If the LockdownVpn mechanism is enabled, updates the vpn
     * with a reload of its profile.
     *
     * <p>This method can only be called by the system UID
     * @return a boolean indicating success
     *
     * @hide
     */
    public boolean updateLockdownVpn() {
        try {
            return mService.updateLockdownVpn();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
}
