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 03656f000c071b8fd42b7b765eb60e9bf4632df6..77a57097becd0a27b80e4a98529910eda8980b5a 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;
@@ -58,6 +59,8 @@ import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.settings.UserTracker;
 
+import com.libremobileos.providers.LMOSettings;
+
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
@@ -338,8 +341,13 @@ public class SecurityControllerImpl implements SecurityController {
     @Override
     public void onUserSwitched(int newUserId) {
         mCurrentUserId = newUserId;
+        final String globalVpnApp = Settings.Global.getString(mContext.getContentResolver(),
+                LMOSettings.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 e3262cfbd30be378816c38c6b877f43090f2ab11..7e83b087dd3aac63fbd9cb9be8817d055df69046 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -163,6 +163,8 @@ import com.android.server.net.BaseNetworkObserver;
 import com.android.server.vcn.util.MtuUtils;
 import com.android.server.vcn.util.PersistableBundleUtils;
 
+import com.libremobileos.providers.LMOSettings;
+
 import libcore.io.IoUtils;
 
 import java.io.File;
@@ -915,6 +917,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(),
+                LMOSettings.Global.GLOBAL_VPN_APP);
+        return mUserId == UserHandle.USER_SYSTEM && mPackage.equals(globalVpnPkg);
+    }
+
     /**
      * Checks if a VPN app supports always-on mode.
      *
@@ -1864,6 +1875,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) {
@@ -2016,7 +2028,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 {
@@ -2025,7 +2037,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);
                 }
             }
@@ -2106,7 +2119,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) {
@@ -2135,7 +2149,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) {
@@ -2580,6 +2595,17 @@ public class Vpn {
         }
     }
 
+    private void enforceNotGlobalVpn() {
+        Binder.withCleanCallingIdentity(() -> {
+            if (mUserId != UserHandle.USER_SYSTEM && !TextUtils.isEmpty(
+                    Settings.Global.getString(mContext.getContentResolver(),
+                            LMOSettings.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.
@@ -2664,6 +2690,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();
@@ -4621,6 +4648,7 @@ public class Vpn {
 
         verifyCallingUidAndPackage(packageName);
         enforceNotRestrictedUser();
+        enforceNotGlobalVpn();
         validateRequiredFeatures(profile);
 
         if (profile.isRestrictedToTestNetworks) {
@@ -4663,6 +4691,7 @@ public class Vpn {
 
         verifyCallingUidAndPackage(packageName);
         enforceNotRestrictedUser();
+        enforceNotGlobalVpn();
 
         final long token = Binder.clearCallingIdentity();
         try {
@@ -4732,6 +4761,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)) {
@@ -4856,6 +4886,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.