fwb, settings: Kang Global VPN switch from LMODroid

This enables apps in work profiles to share the same VPN as the main
profile.
This commit is contained in:
Peter Cai 2023-05-17 14:26:36 -04:00
parent 3968f293a8
commit 947bda2f4b
6 changed files with 395 additions and 14 deletions

View file

@ -1,7 +1,7 @@
From b2a523bde06164be9431c4e5f51d3acd2b459bd5 Mon Sep 17 00:00:00 2001 From 6a533d2bf91fcaf9e93e02062f9c420d6abe370a Mon Sep 17 00:00:00 2001
From: Peter Cai <peter@typeblog.net> From: Peter Cai <peter@typeblog.net>
Date: Tue, 12 Oct 2021 21:37:22 -0400 Date: Tue, 12 Oct 2021 21:37:22 -0400
Subject: [PATCH 1/4] PackageParser: support glob matching for properties Subject: [PATCH 1/5] PackageParser: support glob matching for properties
Needed to make phh's vendor overlays work Needed to make phh's vendor overlays work
--- ---
@ -32,5 +32,5 @@ index c15b3e0b80c3..05bb843c0c4d 100644
} }
return true; return true;
-- --
2.39.2 2.40.0

View file

@ -1,7 +1,7 @@
From d5d5ffd0bdf5be719f18b972706948aa87135934 Mon Sep 17 00:00:00 2001 From 5dd2d06d79a5b77ed9ea304812de8420acb86fea Mon Sep 17 00:00:00 2001
From: dhacker29 <dhackerdvm@gmail.com> From: dhacker29 <dhackerdvm@gmail.com>
Date: Tue, 24 Nov 2015 01:53:47 -0500 Date: Tue, 24 Nov 2015 01:53:47 -0500
Subject: [PATCH 2/4] fw/b: Use ro.build.version.incremental to signal OTA Subject: [PATCH 2/5] fw/b: Use ro.build.version.incremental to signal OTA
upgrades upgrades
[PeterCxy]: On T, there is a new class PackagePartitions that is [PeterCxy]: On T, there is a new class PackagePartitions that is
@ -104,10 +104,10 @@ index ff80e614be58..8bf0d5ffff76 100644
} }
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 0b20683185f0..fdc2b4c11fd1 100644 index f303fedde567..66901edb1c1d 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java --- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java +++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -5139,7 +5139,7 @@ public class ShortcutService extends IShortcutService.Stub { @@ -5162,7 +5162,7 @@ public class ShortcutService extends IShortcutService.Stub {
// Injection point. // Injection point.
String injectBuildFingerprint() { String injectBuildFingerprint() {
@ -117,5 +117,5 @@ index 0b20683185f0..fdc2b4c11fd1 100644
final void wtf(String message) { final void wtf(String message) {
-- --
2.39.2 2.40.0

View file

@ -1,7 +1,7 @@
From 61fc857a22f3e11f2d8095041ee7b006106064f0 Mon Sep 17 00:00:00 2001 From afb0e5101e41dc70d05a0f28d9d50fdb5b414d97 Mon Sep 17 00:00:00 2001
From: Danny Lin <danny@kdrag0n.dev> From: Danny Lin <danny@kdrag0n.dev>
Date: Sat, 16 Oct 2021 05:27:57 -0700 Date: Sat, 16 Oct 2021 05:27:57 -0700
Subject: [PATCH 3/4] Add support for app signature spoofing Subject: [PATCH 3/5] Add support for app signature spoofing
This is needed by microG GmsCore to pretend to be the official Google This is needed by microG GmsCore to pretend to be the official Google
Play Services package, because client apps check the package signature Play Services package, because client apps check the package signature
@ -159,5 +159,5 @@ index 46b7460dff1b..40549962436f 100644
if (packageInfo == null) { if (packageInfo == null) {
return null; return null;
-- --
2.39.2 2.40.0

View file

@ -1,7 +1,7 @@
From 7cd264509a929835a1770e931e3ec8001da7aecb Mon Sep 17 00:00:00 2001 From a1b9bed7443c621a72c1bd33765cd836dbea26ef Mon Sep 17 00:00:00 2001
From: Peter Cai <peter@typeblog.net> From: Peter Cai <peter@typeblog.net>
Date: Fri, 2 Sep 2022 21:36:06 -0400 Date: Fri, 2 Sep 2022 21:36:06 -0400
Subject: [PATCH 4/4] FrameworkParsingPackageUtils: Add glob matching support Subject: [PATCH 4/5] FrameworkParsingPackageUtils: Add glob matching support
for properties for properties
This is now required in addition to the one in PackageParser in order This is now required in addition to the one in PackageParser in order
@ -36,5 +36,5 @@ index 3e1c5bb3d7ec..f15978c57574 100644
} }
return true; return true;
-- --
2.39.2 2.40.0

View file

@ -0,0 +1,201 @@
From c2ebf2cf8f1a013c16a9e44a57bdc44e6d132a2f Mon Sep 17 00:00:00 2001
From: Oliver Scott <olivercscott@gmail.com>
Date: Thu, 8 Jul 2021 10:41:43 -0400
Subject: [PATCH 5/5] Global VPN feature [1/2]
* Modify existing VPN user range functions to conditionally have traffic
from all users pass through the global VPN.
These functions are called when:
1. Starting a VPN
2. Adding a user
3. Removing a user
* Disallow starting VPNs in secondary users when a global VPN is set
Also includes:
Author: Oliver Scott <olivercscott@gmail.com>
Date: 2021-08-27 16:30:22 -0400
Show Global VPN icon on all users
Change-Id: I496c0abbdf92b8f823bc57b297473aa14bd968c8
Change-Id: I42616cc1f4e39e1dad739d81f6d5c55e218be995
Signed-off-by: Mohammad Hasan Keramat J <ikeramat@protonmail.com>
---
core/java/android/provider/Settings.java | 6 +++
.../policy/SecurityControllerImpl.java | 8 +++-
.../com/android/server/connectivity/Vpn.java | 37 +++++++++++++++++--
3 files changed, 46 insertions(+), 5 deletions(-)
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 94a6382227f3..e091b47bdddd 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -15970,6 +15970,12 @@ public final class Settings {
CLOCKWORK_HOME_READY,
};
+ /**
+ * Package designated as global VPN provider.
+ * @hide
+ */
+ public static final String GLOBAL_VPN_APP = "global_vpn_app";
+
/**
* Keys we no longer back up under the current schema, but want to continue to
* process when restoring historical backup datasets.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
index ba947149d287..e5eb04c7818d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
@@ -39,6 +39,7 @@ import android.os.Handler;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
+import android.provider.Settings;
import android.security.KeyChain;
import android.util.ArrayMap;
import android.util.Log;
@@ -332,8 +333,13 @@ public class SecurityControllerImpl implements SecurityController {
@Override
public void onUserSwitched(int newUserId) {
mCurrentUserId = newUserId;
+ final String globalVpnApp = Settings.Global.getString(mContext.getContentResolver(),
+ Settings.Global.GLOBAL_VPN_APP);
final UserInfo newUserInfo = mUserManager.getUserInfo(newUserId);
- if (newUserInfo.isRestricted()) {
+ if (mCurrentVpns.get(UserHandle.USER_SYSTEM) != null &&
+ mCurrentVpns.get(UserHandle.USER_SYSTEM).user.equals(globalVpnApp)) {
+ mVpnUserId = UserHandle.USER_SYSTEM;
+ } else if (newUserInfo.isRestricted()) {
// VPN for a restricted profile is routed through its owner user
mVpnUserId = newUserInfo.restrictedProfileParentId;
} else {
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 8510de4ef201..7c02924a711d 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -691,6 +691,15 @@ public class Vpn {
return mAlwaysOn;
}
+ /**
+ * Returns whether currently prepared VPN package is set as the global VPN.
+ */
+ private synchronized boolean isGlobalVpn() {
+ final String globalVpnPkg = Settings.Global.getString(mContext.getContentResolver(),
+ Settings.Global.GLOBAL_VPN_APP);
+ return mUserId == UserHandle.USER_SYSTEM && mPackage.equals(globalVpnPkg);
+ }
+
/**
* Checks if a VPN app supports always-on mode.
*
@@ -1559,6 +1568,7 @@ public class Vpn {
try {
// Restricted users are not allowed to create VPNs, they are tied to Owner
enforceNotRestrictedUser();
+ enforceNotGlobalVpn();
final PackageManager packageManager = mUserIdContext.getPackageManager();
if (packageManager == null) {
@@ -1720,7 +1730,7 @@ public class Vpn {
addUserToRanges(ranges, userId, allowedApplications, disallowedApplications);
// If the user can have restricted profiles, assign all its restricted profiles too
- if (canHaveRestrictedProfile(userId)) {
+ if (canHaveRestrictedProfile(userId) || isGlobalVpn()) {
final long token = Binder.clearCallingIdentity();
List<UserInfo> users;
try {
@@ -1729,7 +1739,8 @@ public class Vpn {
Binder.restoreCallingIdentity(token);
}
for (UserInfo user : users) {
- if (user.isRestricted() && (user.restrictedProfileParentId == userId)) {
+ if ((user.isRestricted() && (user.restrictedProfileParentId == userId))
+ || isGlobalVpn()) {
addUserToRanges(ranges, user.id, allowedApplications, disallowedApplications);
}
}
@@ -1810,7 +1821,8 @@ public class Vpn {
public void onUserAdded(int userId) {
// If the user is restricted tie them to the parent user's VPN
UserInfo user = mUserManager.getUserInfo(userId);
- if (user.isRestricted() && user.restrictedProfileParentId == mUserId) {
+ if ((user.isRestricted() && user.restrictedProfileParentId == mUserId) ||
+ isGlobalVpn()) {
synchronized(Vpn.this) {
final Set<Range<Integer>> existingRanges = mNetworkCapabilities.getUids();
if (existingRanges != null) {
@@ -1839,7 +1851,8 @@ public class Vpn {
public void onUserRemoved(int userId) {
// clean up if restricted
UserInfo user = mUserManager.getUserInfo(userId);
- if (user.isRestricted() && user.restrictedProfileParentId == mUserId) {
+ if ((user.isRestricted() && user.restrictedProfileParentId == mUserId) ||
+ isGlobalVpn()) {
synchronized(Vpn.this) {
final Set<Range<Integer>> existingRanges = mNetworkCapabilities.getUids();
if (existingRanges != null) {
@@ -2278,6 +2291,17 @@ public class Vpn {
}
}
+ private void enforceNotGlobalVpn() {
+ Binder.withCleanCallingIdentity(() -> {
+ if (mUserId != UserHandle.USER_SYSTEM && !TextUtils.isEmpty(
+ Settings.Global.getString(mContext.getContentResolver(),
+ Settings.Global.GLOBAL_VPN_APP))) {
+ throw new SecurityException("Secondary users cannot configure VPNs when" +
+ " global vpn is set");
+ }
+ });
+ }
+
/**
* Start legacy VPN, controlling native daemons as needed. Creates a
* secondary thread to perform connection work, returning quickly.
@@ -2362,6 +2386,7 @@ public class Vpn {
new UserHandle(mUserId))) {
throw new SecurityException("Restricted users cannot establish VPNs");
}
+ enforceNotGlobalVpn();
final RouteInfo ipv4DefaultRoute = findIPv4DefaultRoute(egress);
final String gateway = ipv4DefaultRoute.getGateway().getHostAddress();
@@ -3859,6 +3884,7 @@ public class Vpn {
verifyCallingUidAndPackage(packageName);
enforceNotRestrictedUser();
+ enforceNotGlobalVpn();
validateRequiredFeatures(profile);
if (profile.isRestrictedToTestNetworks) {
@@ -3901,6 +3927,7 @@ public class Vpn {
verifyCallingUidAndPackage(packageName);
enforceNotRestrictedUser();
+ enforceNotGlobalVpn();
final long token = Binder.clearCallingIdentity();
try {
@@ -3964,6 +3991,7 @@ public class Vpn {
requireNonNull(packageName, "No package name provided");
enforceNotRestrictedUser();
+ enforceNotGlobalVpn();
// Prepare VPN for startup
if (!prepare(packageName, null /* newPackage */, VpnManager.TYPE_VPN_PLATFORM)) {
@@ -4085,6 +4113,7 @@ public class Vpn {
requireNonNull(packageName, "No package name provided");
enforceNotRestrictedUser();
+ enforceNotGlobalVpn();
// To stop the VPN profile, the caller must be the current prepared package and must be
// running an Ikev2VpnProfile.
--
2.40.0

View file

@ -0,0 +1,180 @@
From 16c9311e41992ddd8d0bfb5a340cedbf001e3413 Mon Sep 17 00:00:00 2001
From: Oliver Scott <olivercscott@gmail.com>
Date: Thu, 8 Jul 2021 10:40:49 -0400
Subject: [PATCH] Global VPN feature [2/2]
* Create a global VPN toggle for VPNs in the system user. It is only
enabled when no VPN is active in any user.
Change-Id: Ic3b79beb635afe03642fce9473bc481239166566
Signed-off-by: Mohammad Hasan Keramat J <ikeramat@protonmail.com>
---
res/values/strings.xml | 5 ++
res/xml/vpn_app_management.xml | 6 +++
.../settings/vpn2/AppManagementFragment.java | 48 ++++++++++++++++++-
3 files changed, 58 insertions(+), 1 deletion(-)
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 28b35b3fcf..29ca3882e9 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -14457,4 +14457,9 @@
<!-- [CHAR LIMIT=NONE] Hint for QR code process failure -->
<string name="bt_le_audio_qr_code_is_not_valid_format">QR code isn\u0027t a valid format</string>
+ <!-- VPN app management screen, global VPN -->
+ <string name="global_vpn_title">Global VPN</string>
+ <string name="global_vpn_summary">Force all traffic on the device through this VPN, including work profile and other users.</string>
+ <string name="global_vpn_summary_on">Force all traffic on the device through this VPN, including work profile and other users. Note: When enabled, you will not be able to use a separate VPN in a work profile or other users</string>
+ <string name="global_vpn_summary_any_vpn_active">You need to disable all active VPN connections first to enable this</string>
</resources>
diff --git a/res/xml/vpn_app_management.xml b/res/xml/vpn_app_management.xml
index adc441d846..e00f23ccfa 100644
--- a/res/xml/vpn_app_management.xml
+++ b/res/xml/vpn_app_management.xml
@@ -31,6 +31,12 @@
android:selectable="false"/>
-->
+ <SwitchPreference
+ android:key="global_vpn"
+ android:title="@string/global_vpn_title"
+ android:defaultValue="false"
+ android:summary="@string/global_vpn_summary" />
+
<com.android.settingslib.RestrictedSwitchPreference
android:order="10"
android:key="always_on_vpn"
diff --git a/src/com/android/settings/vpn2/AppManagementFragment.java b/src/com/android/settings/vpn2/AppManagementFragment.java
index d4ee5b9c47..7a52e0c42c 100644
--- a/src/com/android/settings/vpn2/AppManagementFragment.java
+++ b/src/com/android/settings/vpn2/AppManagementFragment.java
@@ -28,10 +28,12 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.UserInfo;
import android.net.VpnManager;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
+import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import android.widget.TextView;
@@ -41,6 +43,7 @@ import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment;
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;
+import androidx.preference.SwitchPreference;
import com.android.internal.net.VpnConfig;
import com.android.internal.util.ArrayUtils;
@@ -64,6 +67,7 @@ public class AppManagementFragment extends SettingsPreferenceFragment
private static final String ARG_PACKAGE_NAME = "package";
private static final String KEY_VERSION = "version";
+ private static final String KEY_GLOBAL_VPN = "global_vpn";
private static final String KEY_ALWAYS_ON_VPN = "always_on_vpn";
private static final String KEY_LOCKDOWN_VPN = "lockdown_vpn";
private static final String KEY_FORGET_VPN = "forget_vpn";
@@ -79,6 +83,7 @@ public class AppManagementFragment extends SettingsPreferenceFragment
private String mVpnLabel;
// UI preference
+ private SwitchPreference mPreferenceGlobal;
private RestrictedSwitchPreference mPreferenceAlwaysOn;
private RestrictedSwitchPreference mPreferenceLockdown;
private RestrictedPreference mPreferenceForget;
@@ -123,10 +128,16 @@ public class AppManagementFragment extends SettingsPreferenceFragment
mDevicePolicyManager = getContext().getSystemService(DevicePolicyManager.class);
mVpnManager = getContext().getSystemService(VpnManager.class);
+ mPreferenceGlobal = (SwitchPreference) findPreference(KEY_GLOBAL_VPN);
mPreferenceAlwaysOn = (RestrictedSwitchPreference) findPreference(KEY_ALWAYS_ON_VPN);
mPreferenceLockdown = (RestrictedSwitchPreference) findPreference(KEY_LOCKDOWN_VPN);
mPreferenceForget = (RestrictedPreference) findPreference(KEY_FORGET_VPN);
+ if (mUserId != UserHandle.USER_SYSTEM) {
+ removePreference(KEY_GLOBAL_VPN);
+ }
+
+ mPreferenceGlobal.setOnPreferenceChangeListener(this);
mPreferenceAlwaysOn.setOnPreferenceChangeListener(this);
mPreferenceLockdown.setOnPreferenceChangeListener(this);
mPreferenceForget.setOnPreferenceClickListener(this);
@@ -204,6 +215,8 @@ public class AppManagementFragment extends SettingsPreferenceFragment
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
switch (preference.getKey()) {
+ case KEY_GLOBAL_VPN:
+ return onGlobalVpnClick((Boolean) newValue);
case KEY_ALWAYS_ON_VPN:
return onAlwaysOnVpnClick((Boolean) newValue, mPreferenceLockdown.isChecked());
case KEY_LOCKDOWN_VPN:
@@ -243,6 +256,11 @@ public class AppManagementFragment extends SettingsPreferenceFragment
return setAlwaysOnVpnByUI(alwaysOnSetting, lockdown);
}
+ private boolean onGlobalVpnClick(final boolean global) {
+ return Settings.Global.putString(getContext().getContentResolver(),
+ Settings.Global.GLOBAL_VPN_APP, global ? mPackageName : "");
+ }
+
@Override
public void onConfirmLockdown(Bundle options, boolean isEnabled, boolean isLockdown) {
setAlwaysOnVpnByUI(isEnabled, isLockdown);
@@ -276,7 +294,18 @@ public class AppManagementFragment extends SettingsPreferenceFragment
final boolean alwaysOn = isVpnAlwaysOn();
final boolean lockdown = alwaysOn
&& VpnUtils.isAnyLockdownActive(getActivity());
-
+ final boolean anyVpnActive = isAnyVpnActive();
+ final boolean globalVpn = isGlobalVpn();
+
+ mPreferenceGlobal.setEnabled(!anyVpnActive);
+ mPreferenceGlobal.setChecked(globalVpn);
+ if (globalVpn) {
+ mPreferenceGlobal.setSummary(R.string.global_vpn_summary_on);
+ } else if (anyVpnActive) {
+ mPreferenceGlobal.setSummary(R.string.global_vpn_summary_any_vpn_active);
+ } else {
+ mPreferenceGlobal.setSummary(R.string.global_vpn_summary);
+ }
mPreferenceAlwaysOn.setChecked(alwaysOn);
mPreferenceLockdown.setChecked(lockdown);
updateRestrictedViews();
@@ -322,6 +351,11 @@ public class AppManagementFragment extends SettingsPreferenceFragment
return mPackageName.equals(getAlwaysOnVpnPackage());
}
+ private boolean isGlobalVpn() {
+ return mPackageName.equals(Settings.Global.getString(
+ getContext().getContentResolver(), Settings.Global.GLOBAL_VPN_APP));
+ }
+
/**
* @return false if the intent doesn't contain an existing package or can't retrieve activated
* vpn info.
@@ -376,6 +410,18 @@ public class AppManagementFragment extends SettingsPreferenceFragment
return config != null && !TextUtils.equals(config.user, mPackageName);
}
+ /**
+ * @return {@code true} if any VPN (VpnService or legacy) is connected or set as always-on.
+ */
+ private boolean isAnyVpnActive() {
+ for (UserInfo userInfo : UserManager.get(getContext()).getUsers()) {
+ if (mVpnManager.getVpnConfig(userInfo.id) != null) {
+ return true;
+ }
+ }
+ return false;
+ }
+
public static class CannotConnectFragment extends InstrumentedDialogFragment {
private static final String TAG = "CannotConnect";
private static final String ARG_VPN_LABEL = "label";
--
2.40.0