Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2d10bd04 authored by Android Build Merger (Role)'s avatar Android Build Merger (Role) Committed by Android (Google) Code Review
Browse files

Merge "Merge "Whitelist packages from VPN lockdown: DPM API." into pi-dev-plus-aosp am: 299f8256"

parents 06cb6f52 0c0af4b0
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -6606,6 +6606,7 @@ package android.app.admin {
    method @Nullable public String[] getAccountTypesWithManagementDisabled();
    method @Nullable public java.util.List<android.content.ComponentName> getActiveAdmins();
    method @NonNull public java.util.Set<java.lang.String> getAffiliationIds(@NonNull android.content.ComponentName);
    method @Nullable public java.util.List<java.lang.String> getAlwaysOnVpnLockdownWhitelist(@NonNull android.content.ComponentName);
    method @Nullable public String getAlwaysOnVpnPackage(@NonNull android.content.ComponentName);
    method @WorkerThread @NonNull public android.os.Bundle getApplicationRestrictions(@Nullable android.content.ComponentName, String);
    method @Deprecated @Nullable public String getApplicationRestrictionsManagingPackage(@NonNull android.content.ComponentName);
@@ -6680,6 +6681,7 @@ package android.app.admin {
    method public boolean isActivePasswordSufficient();
    method public boolean isAdminActive(@NonNull android.content.ComponentName);
    method public boolean isAffiliatedUser();
    method public boolean isAlwaysOnVpnLockdownEnabled(@NonNull android.content.ComponentName);
    method public boolean isApplicationHidden(@NonNull android.content.ComponentName, String);
    method public boolean isBackupServiceEnabled(@NonNull android.content.ComponentName);
    method @Deprecated public boolean isCallerApplicationRestrictionsManagingPackage();
@@ -6716,7 +6718,8 @@ package android.app.admin {
    method @Nullable public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrieveSecurityLogs(@NonNull android.content.ComponentName);
    method public void setAccountManagementDisabled(@NonNull android.content.ComponentName, String, boolean);
    method public void setAffiliationIds(@NonNull android.content.ComponentName, @NonNull java.util.Set<java.lang.String>);
    method public void setAlwaysOnVpnPackage(@NonNull android.content.ComponentName, @Nullable String, boolean) throws android.content.pm.PackageManager.NameNotFoundException, java.lang.UnsupportedOperationException;
    method public void setAlwaysOnVpnPackage(@NonNull android.content.ComponentName, @Nullable String, boolean) throws android.content.pm.PackageManager.NameNotFoundException;
    method public void setAlwaysOnVpnPackage(@NonNull android.content.ComponentName, @Nullable String, boolean, @Nullable java.util.List<java.lang.String>) throws android.content.pm.PackageManager.NameNotFoundException;
    method public boolean setApplicationHidden(@NonNull android.content.ComponentName, String, boolean);
    method @WorkerThread public void setApplicationRestrictions(@Nullable android.content.ComponentName, String, android.os.Bundle);
    method @Deprecated public void setApplicationRestrictionsManagingPackage(@NonNull android.content.ComponentName, @Nullable String) throws android.content.pm.PackageManager.NameNotFoundException;
+94 −8
Original line number Diff line number Diff line
@@ -5058,12 +5058,17 @@ public class DevicePolicyManager {
        return null;
    }

    /**
     * Service-specific error code used in implementation of {@code setAlwaysOnVpnPackage} methods.
     * @hide
     */
    public static final int ERROR_VPN_PACKAGE_NOT_FOUND = 1;

    /**
     * Called by a device or profile owner to configure an always-on VPN connection through a
     * specific application for the current user. This connection is automatically granted and
     * persisted after a reboot.
     * <p>
     * To support the always-on feature, an app must
     * <p> To support the always-on feature, an app must
     * <ul>
     *     <li>declare a {@link android.net.VpnService} in its manifest, guarded by
     *         {@link android.Manifest.permission#BIND_VPN_SERVICE};</li>
@@ -5072,30 +5077,111 @@ public class DevicePolicyManager {
     *         {@link android.net.VpnService#SERVICE_META_DATA_SUPPORTS_ALWAYS_ON}.</li>
     * </ul>
     * The call will fail if called with the package name of an unsupported VPN app.
     * <p> Enabling lockdown via {@code lockdownEnabled} argument carries the risk that any failure
     * of the VPN provider could break networking for all apps.
     *
     * @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. This carries the risk that any failure of the VPN provider
     *        could break networking for all apps. This has no effect when clearing.
     *        {@code false} otherwise. This has no effect when clearing.
     * @throws SecurityException if {@code admin} is not a device or a profile owner.
     * @throws NameNotFoundException if {@code vpnPackage} is not installed.
     * @throws UnsupportedOperationException if {@code vpnPackage} exists but does not support being
     *         set as always-on, or if always-on VPN is not available.
     * @see #setAlwaysOnVpnPackage(ComponentName, String, boolean, List)
     */
    public void setAlwaysOnVpnPackage(@NonNull ComponentName admin, @Nullable String vpnPackage,
            boolean lockdownEnabled) throws NameNotFoundException {
        setAlwaysOnVpnPackage(admin, vpnPackage, lockdownEnabled, Collections.emptyList());
    }

    /**
     * A version of {@link #setAlwaysOnVpnPackage(ComponentName, String, boolean)} that allows the
     * admin to specify a set of apps that should be able to access the network directly when VPN
     * is not connected. When VPN connects these apps switch over to VPN if allowed to use that VPN.
     * System apps can always bypass VPN.
     * <p> Note that the system doesn't update the whitelist when packages are installed or
     * uninstalled, the admin app must call this method to keep the list up to date.
     *
     * @param vpnPackage 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. This has no effect when clearing.
     * @param lockdownWhitelist Packages that will be able to access the network directly when VPN
     *         is in lockdown mode but not connected. Has no effect when clearing.
     * @throws SecurityException if {@code admin} is not a device or a profile
     *         owner.
     * @throws NameNotFoundException if {@code vpnPackage} or one of
     *         {@code lockdownWhitelist} is not installed.
     * @throws UnsupportedOperationException if {@code vpnPackage} exists but does
     *         not support being set as always-on, or if always-on VPN is not
     *         available.
     */
    public void setAlwaysOnVpnPackage(@NonNull ComponentName admin, @Nullable String vpnPackage,
            boolean lockdownEnabled)
            throws NameNotFoundException, UnsupportedOperationException {
            boolean lockdownEnabled, @Nullable List<String> lockdownWhitelist)
            throws NameNotFoundException {
        throwIfParentInstance("setAlwaysOnVpnPackage");
        if (mService != null) {
            try {
                if (!mService.setAlwaysOnVpnPackage(admin, vpnPackage, lockdownEnabled)) {
                    throw new NameNotFoundException(vpnPackage);
                mService.setAlwaysOnVpnPackage(
                        admin, vpnPackage, lockdownEnabled, lockdownWhitelist);
            } catch (ServiceSpecificException e) {
                switch (e.errorCode) {
                    case ERROR_VPN_PACKAGE_NOT_FOUND:
                        throw new NameNotFoundException(e.getMessage());
                    default:
                        throw new RuntimeException(
                                "Unknown error setting always-on VPN: " + e.errorCode, e);
                }
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    }

    /**
     * Called by device or profile owner to query whether current always-on VPN is configured in
     * lockdown mode. Returns {@code false} when no always-on configuration is set.
     *
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
     *
     * @throws SecurityException if {@code admin} is not a device or a profile owner.
     *
     * @see #setAlwaysOnVpnPackage(ComponentName, String, boolean)
     */
    public boolean isAlwaysOnVpnLockdownEnabled(@NonNull ComponentName admin) {
        throwIfParentInstance("isAlwaysOnVpnLockdownEnabled");
        if (mService != null) {
            try {
                return mService.isAlwaysOnVpnLockdownEnabled(admin);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
        return false;
    }

    /**
     * Called by device or profile owner to query the list of packages that are allowed to access
     * the network directly when always-on VPN is in lockdown mode but not connected. Returns
     * {@code null} when always-on VPN is not active or not in lockdown mode.
     *
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
     *
     * @throws SecurityException if {@code admin} is not a device or a profile owner.
     *
     * @see #setAlwaysOnVpnPackage(ComponentName, String, boolean, List)
     */
    public @Nullable List<String> getAlwaysOnVpnLockdownWhitelist(@NonNull ComponentName admin) {
        throwIfParentInstance("getAlwaysOnVpnLockdownWhitelist");
        if (mService != null) {
            try {
                return mService.getAlwaysOnVpnLockdownWhitelist(admin);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
        return null;
    }

    /**
+3 −1
Original line number Diff line number Diff line
@@ -187,8 +187,10 @@ interface IDevicePolicyManager {
    void setCertInstallerPackage(in ComponentName who, String installerPackage);
    String getCertInstallerPackage(in ComponentName who);

    boolean setAlwaysOnVpnPackage(in ComponentName who, String vpnPackage, boolean lockdown);
    boolean setAlwaysOnVpnPackage(in ComponentName who, String vpnPackage, boolean lockdown, in List<String> lockdownWhitelist);
    String getAlwaysOnVpnPackage(in ComponentName who);
    boolean isAlwaysOnVpnLockdownEnabled(in ComponentName who);
    List<String> getAlwaysOnVpnLockdownWhitelist(in ComponentName who);

    void addPersistentPreferredActivity(in ComponentName admin, in IntentFilter filter, in ComponentName activity);
    void clearPackagePersistentPreferredActivities(in ComponentName admin, String packageName);
+53 −14
Original line number Diff line number Diff line
@@ -1925,7 +1925,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        }
        AlarmManager getAlarmManager() {
            return (AlarmManager) mContext.getSystemService(AlarmManager.class);
            return mContext.getSystemService(AlarmManager.class);
        }
        ConnectivityManager getConnectivityManager() {
            return mContext.getSystemService(ConnectivityManager.class);
        }
        IWindowManager getIWindowManager() {
@@ -6308,7 +6312,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
     * @throws UnsupportedOperationException if the package does not support being set as always-on.
     */
    @Override
    public boolean setAlwaysOnVpnPackage(ComponentName admin, String vpnPackage, boolean lockdown)
    public boolean setAlwaysOnVpnPackage(ComponentName admin, String vpnPackage, boolean lockdown,
            List<String> lockdownWhitelist)
            throws SecurityException {
        enforceProfileOrDeviceOwner(admin);
@@ -6316,11 +6321,23 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        final long token = mInjector.binderClearCallingIdentity();
        try {
            if (vpnPackage != null && !isPackageInstalledForUser(vpnPackage, userId)) {
                return false;
                Slog.w(LOG_TAG, "Non-existent VPN package specified: " + vpnPackage);
                throw new ServiceSpecificException(
                        DevicePolicyManager.ERROR_VPN_PACKAGE_NOT_FOUND, vpnPackage);
            }
            if (vpnPackage != null && lockdown && lockdownWhitelist != null) {
                for (String packageName : lockdownWhitelist) {
                    if (!isPackageInstalledForUser(packageName, userId)) {
                        Slog.w(LOG_TAG, "Non-existent package in VPN whitelist: " + packageName);
                        throw new ServiceSpecificException(
                                DevicePolicyManager.ERROR_VPN_PACKAGE_NOT_FOUND, packageName);
                    }
                }
            ConnectivityManager connectivityManager = (ConnectivityManager)
                    mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
            if (!connectivityManager.setAlwaysOnVpnPackageForUser(userId, vpnPackage, lockdown)) {
            }
            // If some package is uninstalled after the check above, it will be ignored by CM.
            if (!mInjector.getConnectivityManager().setAlwaysOnVpnPackageForUser(
                    userId, vpnPackage, lockdown, lockdownWhitelist)) {
                throw new UnsupportedOperationException();
            }
            DevicePolicyEventLogger
@@ -6337,16 +6354,40 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
    }
    @Override
    public String getAlwaysOnVpnPackage(ComponentName admin)
    public String getAlwaysOnVpnPackage(ComponentName admin) throws SecurityException {
        enforceProfileOrDeviceOwner(admin);
        final int userId = mInjector.userHandleGetCallingUserId();
        final long token = mInjector.binderClearCallingIdentity();
        try {
            return mInjector.getConnectivityManager().getAlwaysOnVpnPackageForUser(userId);
        } finally {
            mInjector.binderRestoreCallingIdentity(token);
        }
    }
    @Override
    public boolean isAlwaysOnVpnLockdownEnabled(ComponentName admin) throws SecurityException {
        enforceProfileOrDeviceOwner(admin);
        final int userId = mInjector.userHandleGetCallingUserId();
        final long token = mInjector.binderClearCallingIdentity();
        try {
            return mInjector.getConnectivityManager().isVpnLockdownEnabled(userId);
        } finally {
            mInjector.binderRestoreCallingIdentity(token);
        }
    }
    @Override
    public List<String> getAlwaysOnVpnLockdownWhitelist(ComponentName admin)
            throws SecurityException {
        enforceProfileOrDeviceOwner(admin);
        final int userId = mInjector.userHandleGetCallingUserId();
        final long token = mInjector.binderClearCallingIdentity();
        try {
            ConnectivityManager connectivityManager = (ConnectivityManager)
                    mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
            return connectivityManager.getAlwaysOnVpnPackageForUser(userId);
            return mInjector.getConnectivityManager().getVpnLockdownWhitelist(userId);
        } finally {
            mInjector.binderRestoreCallingIdentity(token);
        }
@@ -6819,9 +6860,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        enforceDeviceOwner(who);
        long token = mInjector.binderClearCallingIdentity();
        try {
            ConnectivityManager connectivityManager = (ConnectivityManager)
                    mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
            connectivityManager.setGlobalProxy(proxyInfo);
            mInjector.getConnectivityManager().setGlobalProxy(proxyInfo);
        } finally {
            mInjector.binderRestoreCallingIdentity(token);
        }