Prevent disconnecting admin-configured VPN
First, if the VPN is configured by an admin, the preference is
disabled and tapping on it will results in a policy disclouser
dialog.
In addition restriction checks in the dialog also check if the
VPN is admin-configured.
Bug: 179975048
Test: Manual, setting VPN in profile and primary user and via DPM API.
Test: make RunSettingsRoboTests -j ROBOTEST_FILTER=com.android.settings.vpn2
Change-Id: Id59d2ac2782e83601bc3093d3a092faea36ff5d9
diff --git a/src/com/android/settings/vpn2/AppDialogFragment.java b/src/com/android/settings/vpn2/AppDialogFragment.java
index 626a271..b5623fd 100644
--- a/src/com/android/settings/vpn2/AppDialogFragment.java
+++ b/src/com/android/settings/vpn2/AppDialogFragment.java
@@ -17,6 +17,7 @@
package com.android.settings.vpn2;
import android.app.Dialog;
+import android.app.admin.DevicePolicyManager;
import android.app.settings.SettingsEnums;
import android.content.DialogInterface;
import android.content.pm.PackageInfo;
@@ -48,6 +49,7 @@
private Listener mListener;
private UserManager mUserManager;
+ private DevicePolicyManager mDevicePolicyManager;
private VpnManager mVpnManager;
@Override
@@ -91,7 +93,11 @@
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ mPackageInfo = getArguments().getParcelable(ARG_PACKAGE);
mUserManager = UserManager.get(getContext());
+ mDevicePolicyManager = getContext()
+ .createContextAsUser(UserHandle.of(getUserId()), /* flags= */ 0)
+ .getSystemService(DevicePolicyManager.class);
mVpnManager = getContext().getSystemService(VpnManager.class);
}
@@ -101,7 +107,6 @@
final String label = args.getString(ARG_LABEL);
boolean managing = args.getBoolean(ARG_MANAGING);
boolean connected = args.getBoolean(ARG_CONNECTED);
- mPackageInfo = args.getParcelable(ARG_PACKAGE);
if (managing) {
return new AppDialog(getActivity(), this, mPackageInfo, label);
@@ -163,7 +168,10 @@
private boolean isUiRestricted() {
final UserHandle userHandle = UserHandle.of(getUserId());
- return mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN, userHandle);
+ if (mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN, userHandle)) {
+ return true;
+ }
+ return mPackageInfo.packageName.equals(mDevicePolicyManager.getAlwaysOnVpnPackage());
}
private int getUserId() {
diff --git a/src/com/android/settings/vpn2/AppPreference.java b/src/com/android/settings/vpn2/AppPreference.java
index 6b64250..8ee2f5f 100644
--- a/src/com/android/settings/vpn2/AppPreference.java
+++ b/src/com/android/settings/vpn2/AppPreference.java
@@ -16,6 +16,7 @@
package com.android.settings.vpn2;
+import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
@@ -26,6 +27,8 @@
import com.android.internal.net.LegacyVpnInfo;
import com.android.internal.net.VpnConfig;
+import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
/**
* {@link androidx.preference.Preference} containing information about a VPN
@@ -43,6 +46,7 @@
super.setUserId(userId);
mPackageName = packageName;
+ disableIfConfiguredByAdmin();
// Fetch icon and VPN label
String label = packageName;
@@ -74,6 +78,25 @@
setIcon(icon);
}
+ /**
+ * Disable this preference if VPN is set as always on by a profile or device owner.
+ * NB: it should be called after super.setUserId() otherwise admin information can be lost.
+ */
+ private void disableIfConfiguredByAdmin() {
+ if (isDisabledByAdmin()) {
+ // Already disabled due to user restriction.
+ return;
+ }
+ final DevicePolicyManager dpm = getContext()
+ .createContextAsUser(UserHandle.of(getUserId()), /* flags= */ 0)
+ .getSystemService(DevicePolicyManager.class);
+ if (mPackageName.equals(dpm.getAlwaysOnVpnPackage())) {
+ final EnforcedAdmin admin = RestrictedLockUtils.getProfileOrDeviceOwner(
+ getContext(), UserHandle.of(mUserId));
+ setDisabledByAdmin(admin);
+ }
+ }
+
public PackageInfo getPackageInfo() {
try {
PackageManager pm = getUserContext().getPackageManager();