Loading services/core/java/com/android/server/ConnectivityService.java +3 −11 Original line number Diff line number Diff line Loading @@ -3557,17 +3557,9 @@ public class ConnectivityService extends IConnectivityManager.Stub existing.shutdown(); } try { if (tracker != null) { mNetd.setFirewallEnabled(true); mNetd.setFirewallInterfaceRule("lo", true); mLockdownTracker = tracker; mLockdownTracker.init(); } else { mNetd.setFirewallEnabled(false); } } catch (RemoteException e) { // ignored; NMS lives inside system_server } } Loading services/core/java/com/android/server/NetworkManagementService.java +1 −2 Original line number Diff line number Diff line Loading @@ -100,7 +100,6 @@ import com.android.internal.util.HexDump; import com.android.internal.util.Preconditions; import com.android.server.NativeDaemonConnector.Command; import com.android.server.NativeDaemonConnector.SensitiveArg; import com.android.server.net.LockdownVpnTracker; import com.google.android.collect.Maps; import java.io.BufferedReader; Loading Loading @@ -660,7 +659,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub } } setFirewallEnabled(mFirewallEnabled || LockdownVpnTracker.isEnabled()); setFirewallEnabled(mFirewallEnabled); syncFirewallChainLocked(FIREWALL_CHAIN_NONE, ""); syncFirewallChainLocked(FIREWALL_CHAIN_STANDBY, "standby "); Loading services/core/java/com/android/server/connectivity/Vpn.java +47 −15 Original line number Diff line number Diff line Loading @@ -271,6 +271,30 @@ public class Vpn { updateAlwaysOnNotification(detailedState); } /** * Chooses whether to force all connections to go though VPN. * * Used to enable/disable legacy VPN lockdown. * * This uses the same ip rule mechanism as {@link #setAlwaysOnPackage(String, boolean)}; * previous settings from calling that function will be replaced and saved with the * always-on state. * * @param lockdown whether to prevent all traffic outside of a VPN. */ public synchronized void setLockdown(boolean lockdown) { enforceControlPermissionOrInternalCaller(); setVpnForcedLocked(lockdown); mLockdown = lockdown; // Update app lockdown setting if it changed. Legacy VPN lockdown status is controlled by // LockdownVpnTracker.isEnabled() which keeps track of its own state. if (mAlwaysOn) { saveAlwaysOnPackage(); } } /** * Configures an always-on VPN connection through a specific application. * This connection is automatically granted and persisted after a reboot. Loading Loading @@ -384,7 +408,7 @@ public class Vpn { mSystemServices.settingsSecurePutStringForUser(Settings.Secure.ALWAYS_ON_VPN_APP, getAlwaysOnPackage(), mUserHandle); mSystemServices.settingsSecurePutIntForUser(Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN, (mLockdown ? 1 : 0), mUserHandle); (mAlwaysOn && mLockdown ? 1 : 0), mUserHandle); } finally { Binder.restoreCallingIdentity(token); } Loading Loading @@ -577,6 +601,7 @@ public class Vpn { mConfig = null; updateState(DetailedState.IDLE, "prepare"); setVpnForcedLocked(mLockdown); } finally { Binder.restoreCallingIdentity(token); } Loading Loading @@ -1023,12 +1048,10 @@ public class Vpn { Log.wtf(TAG, "Failed to add restricted user to owner", e); } } if (mAlwaysOn) { setVpnForcedLocked(mLockdown); } } } } public void onUserRemoved(int userHandle) { // clean up if restricted Loading @@ -1042,19 +1065,17 @@ public class Vpn { Log.wtf(TAG, "Failed to remove restricted user to owner", e); } } if (mAlwaysOn) { setVpnForcedLocked(mLockdown); } } } } /** * Called when the user associated with this VPN has just been stopped. */ public synchronized void onUserStopped() { // Switch off networking lockdown (if it was enabled) setVpnForcedLocked(false); setLockdown(false); mAlwaysOn = false; unregisterPackageChangeReceiverLocked(); Loading @@ -1081,20 +1102,31 @@ public class Vpn { */ @GuardedBy("this") private void setVpnForcedLocked(boolean enforce) { final List<String> exemptedPackages = isNullOrLegacyVpn(mPackage) ? null : Collections.singletonList(mPackage); setVpnForcedWithExemptionsLocked(enforce, exemptedPackages); } /** * @see #setVpnForcedLocked */ @GuardedBy("this") private void setVpnForcedWithExemptionsLocked(boolean enforce, @Nullable List<String> exemptedPackages) { final Set<UidRange> removedRanges = new ArraySet<>(mBlockedUsers); Set<UidRange> addedRanges = Collections.emptySet(); if (enforce) { final Set<UidRange> addedRanges = createUserAndRestrictedProfilesRanges(mUserHandle, addedRanges = createUserAndRestrictedProfilesRanges(mUserHandle, /* allowedApplications */ null, /* disallowedApplications */ Collections.singletonList(mPackage)); /* disallowedApplications */ exemptedPackages); removedRanges.removeAll(addedRanges); addedRanges.removeAll(mBlockedUsers); } setAllowOnlyVpnForUids(false, removedRanges); setAllowOnlyVpnForUids(true, addedRanges); } else { setAllowOnlyVpnForUids(false, removedRanges); } } /** Loading services/core/java/com/android/server/net/LockdownVpnTracker.java +2 −65 Original line number Diff line number Diff line Loading @@ -141,7 +141,6 @@ public class LockdownVpnTracker { " " + mAcceptedEgressIface + "->" + egressIface); if (egressDisconnected || egressChanged) { clearSourceRulesLocked(); mAcceptedEgressIface = null; mVpn.stopLegacyVpnPrivileged(); } Loading Loading @@ -193,24 +192,6 @@ public class LockdownVpnTracker { EventLogTags.writeLockdownVpnConnected(egressType); showNotification(R.string.vpn_lockdown_connected, R.drawable.vpn_connected); try { clearSourceRulesLocked(); mNetService.setFirewallInterfaceRule(iface, true); for (LinkAddress addr : sourceAddrs) { setFirewallEgressSourceRule(addr, true); } mNetService.setFirewallUidRule(FIREWALL_CHAIN_NONE, ROOT_UID, FIREWALL_RULE_ALLOW); mNetService.setFirewallUidRule(FIREWALL_CHAIN_NONE, Os.getuid(), FIREWALL_RULE_ALLOW); mErrorCount = 0; mAcceptedIface = iface; mAcceptedSourceAddr = sourceAddrs; } catch (RemoteException e) { throw new RuntimeException("Problem setting firewall rules", e); } final NetworkInfo clone = new NetworkInfo(egressInfo); augmentNetworkInfo(clone); mConnService.sendConnectedBroadcast(clone); Loading @@ -227,19 +208,11 @@ public class LockdownVpnTracker { Slog.d(TAG, "initLocked()"); mVpn.setEnableTeardown(false); mVpn.setLockdown(true); final IntentFilter resetFilter = new IntentFilter(ACTION_LOCKDOWN_RESET); mContext.registerReceiver(mResetReceiver, resetFilter, CONNECTIVITY_INTERNAL, null); try { // TODO: support non-standard port numbers mNetService.setFirewallEgressDestRule(mProfile.server, 500, true); mNetService.setFirewallEgressDestRule(mProfile.server, 4500, true); mNetService.setFirewallEgressDestRule(mProfile.server, 1701, true); } catch (RemoteException e) { throw new RuntimeException("Problem setting firewall rules", e); } handleStateChangedLocked(); } Loading @@ -256,14 +229,7 @@ public class LockdownVpnTracker { mErrorCount = 0; mVpn.stopLegacyVpnPrivileged(); try { mNetService.setFirewallEgressDestRule(mProfile.server, 500, false); mNetService.setFirewallEgressDestRule(mProfile.server, 4500, false); mNetService.setFirewallEgressDestRule(mProfile.server, 1701, false); } catch (RemoteException e) { throw new RuntimeException("Problem setting firewall rules", e); } clearSourceRulesLocked(); mVpn.setLockdown(false); hideNotification(); mContext.unregisterReceiver(mResetReceiver); Loading @@ -280,35 +246,6 @@ public class LockdownVpnTracker { } } private void clearSourceRulesLocked() { try { if (mAcceptedIface != null) { mNetService.setFirewallInterfaceRule(mAcceptedIface, false); mAcceptedIface = null; } if (mAcceptedSourceAddr != null) { for (LinkAddress addr : mAcceptedSourceAddr) { setFirewallEgressSourceRule(addr, false); } mNetService.setFirewallUidRule(FIREWALL_CHAIN_NONE, ROOT_UID, FIREWALL_RULE_DEFAULT); mNetService.setFirewallUidRule(FIREWALL_CHAIN_NONE,Os.getuid(), FIREWALL_RULE_DEFAULT); mAcceptedSourceAddr = null; } } catch (RemoteException e) { throw new RuntimeException("Problem setting firewall rules", e); } } private void setFirewallEgressSourceRule( LinkAddress address, boolean allow) throws RemoteException { // Our source address based firewall rules must only cover our own source address, not the // whole subnet final String addrString = address.getAddress().getHostAddress(); mNetService.setFirewallEgressSourceRule(addrString, allow); } public void onNetworkInfoChanged() { synchronized (mStateLock) { handleStateChangedLocked(); Loading tests/net/java/com/android/server/connectivity/VpnTest.java +57 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.annotation.UserIdInt; import android.app.AppOpsManager; import android.app.NotificationManager; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.UserInfo; Loading @@ -42,6 +43,8 @@ import android.test.suitebuilder.annotation.SmallTest; import android.util.ArrayMap; import android.util.ArraySet; import com.android.internal.net.VpnConfig; import java.util.ArrayList; import java.util.Arrays; import java.util.Map; Loading Loading @@ -101,8 +104,10 @@ public class VpnTest extends AndroidTestCase { @Override public void setUp() throws Exception { MockitoAnnotations.initMocks(this); when(mContext.getPackageManager()).thenReturn(mPackageManager); setMockedPackages(mPackages); when(mContext.getPackageName()).thenReturn(Vpn.class.getPackage().getName()); when(mContext.getSystemService(eq(Context.USER_SERVICE))).thenReturn(mUserManager); when(mContext.getSystemService(eq(Context.APP_OPS_SERVICE))).thenReturn(mAppOps); Loading Loading @@ -257,6 +262,58 @@ public class VpnTest extends AndroidTestCase { })); } @SmallTest public void testLockdownRuleRepeatability() throws Exception { final Vpn vpn = createVpn(primaryUser.id); // Given legacy lockdown is already enabled, vpn.setLockdown(true); verify(mNetService, times(1)).setAllowOnlyVpnForUids( eq(true), aryEq(new UidRange[] {UidRange.createForUser(primaryUser.id)})); // Enabling legacy lockdown twice should do nothing. vpn.setLockdown(true); verify(mNetService, times(1)).setAllowOnlyVpnForUids(anyBoolean(), any(UidRange[].class)); // And disabling should remove the rules exactly once. vpn.setLockdown(false); verify(mNetService, times(1)).setAllowOnlyVpnForUids( eq(false), aryEq(new UidRange[] {UidRange.createForUser(primaryUser.id)})); // Removing the lockdown again should have no effect. vpn.setLockdown(false); verify(mNetService, times(2)).setAllowOnlyVpnForUids(anyBoolean(), any(UidRange[].class)); } @SmallTest public void testLockdownRuleReversibility() throws Exception { final Vpn vpn = createVpn(primaryUser.id); final UidRange[] entireUser = { UidRange.createForUser(primaryUser.id) }; final UidRange[] exceptPkg0 = { new UidRange(entireUser[0].start, entireUser[0].start + PKG_UIDS[0] - 1), new UidRange(entireUser[0].start + PKG_UIDS[0] + 1, entireUser[0].stop) }; final InOrder order = inOrder(mNetService); // Given lockdown is enabled with no package (legacy VPN), vpn.setLockdown(true); order.verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(entireUser)); // When a new VPN package is set the rules should change to cover that package. vpn.prepare(null, PKGS[0]); order.verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(entireUser)); order.verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(exceptPkg0)); // When that VPN package is unset, everything should be undone again in reverse. vpn.prepare(null, VpnConfig.LEGACY_VPN); order.verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(exceptPkg0)); order.verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(entireUser)); } @SmallTest public void testNotificationShownForAlwaysOnApp() { final UserHandle userHandle = UserHandle.of(primaryUser.id); Loading Loading
services/core/java/com/android/server/ConnectivityService.java +3 −11 Original line number Diff line number Diff line Loading @@ -3557,17 +3557,9 @@ public class ConnectivityService extends IConnectivityManager.Stub existing.shutdown(); } try { if (tracker != null) { mNetd.setFirewallEnabled(true); mNetd.setFirewallInterfaceRule("lo", true); mLockdownTracker = tracker; mLockdownTracker.init(); } else { mNetd.setFirewallEnabled(false); } } catch (RemoteException e) { // ignored; NMS lives inside system_server } } Loading
services/core/java/com/android/server/NetworkManagementService.java +1 −2 Original line number Diff line number Diff line Loading @@ -100,7 +100,6 @@ import com.android.internal.util.HexDump; import com.android.internal.util.Preconditions; import com.android.server.NativeDaemonConnector.Command; import com.android.server.NativeDaemonConnector.SensitiveArg; import com.android.server.net.LockdownVpnTracker; import com.google.android.collect.Maps; import java.io.BufferedReader; Loading Loading @@ -660,7 +659,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub } } setFirewallEnabled(mFirewallEnabled || LockdownVpnTracker.isEnabled()); setFirewallEnabled(mFirewallEnabled); syncFirewallChainLocked(FIREWALL_CHAIN_NONE, ""); syncFirewallChainLocked(FIREWALL_CHAIN_STANDBY, "standby "); Loading
services/core/java/com/android/server/connectivity/Vpn.java +47 −15 Original line number Diff line number Diff line Loading @@ -271,6 +271,30 @@ public class Vpn { updateAlwaysOnNotification(detailedState); } /** * Chooses whether to force all connections to go though VPN. * * Used to enable/disable legacy VPN lockdown. * * This uses the same ip rule mechanism as {@link #setAlwaysOnPackage(String, boolean)}; * previous settings from calling that function will be replaced and saved with the * always-on state. * * @param lockdown whether to prevent all traffic outside of a VPN. */ public synchronized void setLockdown(boolean lockdown) { enforceControlPermissionOrInternalCaller(); setVpnForcedLocked(lockdown); mLockdown = lockdown; // Update app lockdown setting if it changed. Legacy VPN lockdown status is controlled by // LockdownVpnTracker.isEnabled() which keeps track of its own state. if (mAlwaysOn) { saveAlwaysOnPackage(); } } /** * Configures an always-on VPN connection through a specific application. * This connection is automatically granted and persisted after a reboot. Loading Loading @@ -384,7 +408,7 @@ public class Vpn { mSystemServices.settingsSecurePutStringForUser(Settings.Secure.ALWAYS_ON_VPN_APP, getAlwaysOnPackage(), mUserHandle); mSystemServices.settingsSecurePutIntForUser(Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN, (mLockdown ? 1 : 0), mUserHandle); (mAlwaysOn && mLockdown ? 1 : 0), mUserHandle); } finally { Binder.restoreCallingIdentity(token); } Loading Loading @@ -577,6 +601,7 @@ public class Vpn { mConfig = null; updateState(DetailedState.IDLE, "prepare"); setVpnForcedLocked(mLockdown); } finally { Binder.restoreCallingIdentity(token); } Loading Loading @@ -1023,12 +1048,10 @@ public class Vpn { Log.wtf(TAG, "Failed to add restricted user to owner", e); } } if (mAlwaysOn) { setVpnForcedLocked(mLockdown); } } } } public void onUserRemoved(int userHandle) { // clean up if restricted Loading @@ -1042,19 +1065,17 @@ public class Vpn { Log.wtf(TAG, "Failed to remove restricted user to owner", e); } } if (mAlwaysOn) { setVpnForcedLocked(mLockdown); } } } } /** * Called when the user associated with this VPN has just been stopped. */ public synchronized void onUserStopped() { // Switch off networking lockdown (if it was enabled) setVpnForcedLocked(false); setLockdown(false); mAlwaysOn = false; unregisterPackageChangeReceiverLocked(); Loading @@ -1081,20 +1102,31 @@ public class Vpn { */ @GuardedBy("this") private void setVpnForcedLocked(boolean enforce) { final List<String> exemptedPackages = isNullOrLegacyVpn(mPackage) ? null : Collections.singletonList(mPackage); setVpnForcedWithExemptionsLocked(enforce, exemptedPackages); } /** * @see #setVpnForcedLocked */ @GuardedBy("this") private void setVpnForcedWithExemptionsLocked(boolean enforce, @Nullable List<String> exemptedPackages) { final Set<UidRange> removedRanges = new ArraySet<>(mBlockedUsers); Set<UidRange> addedRanges = Collections.emptySet(); if (enforce) { final Set<UidRange> addedRanges = createUserAndRestrictedProfilesRanges(mUserHandle, addedRanges = createUserAndRestrictedProfilesRanges(mUserHandle, /* allowedApplications */ null, /* disallowedApplications */ Collections.singletonList(mPackage)); /* disallowedApplications */ exemptedPackages); removedRanges.removeAll(addedRanges); addedRanges.removeAll(mBlockedUsers); } setAllowOnlyVpnForUids(false, removedRanges); setAllowOnlyVpnForUids(true, addedRanges); } else { setAllowOnlyVpnForUids(false, removedRanges); } } /** Loading
services/core/java/com/android/server/net/LockdownVpnTracker.java +2 −65 Original line number Diff line number Diff line Loading @@ -141,7 +141,6 @@ public class LockdownVpnTracker { " " + mAcceptedEgressIface + "->" + egressIface); if (egressDisconnected || egressChanged) { clearSourceRulesLocked(); mAcceptedEgressIface = null; mVpn.stopLegacyVpnPrivileged(); } Loading Loading @@ -193,24 +192,6 @@ public class LockdownVpnTracker { EventLogTags.writeLockdownVpnConnected(egressType); showNotification(R.string.vpn_lockdown_connected, R.drawable.vpn_connected); try { clearSourceRulesLocked(); mNetService.setFirewallInterfaceRule(iface, true); for (LinkAddress addr : sourceAddrs) { setFirewallEgressSourceRule(addr, true); } mNetService.setFirewallUidRule(FIREWALL_CHAIN_NONE, ROOT_UID, FIREWALL_RULE_ALLOW); mNetService.setFirewallUidRule(FIREWALL_CHAIN_NONE, Os.getuid(), FIREWALL_RULE_ALLOW); mErrorCount = 0; mAcceptedIface = iface; mAcceptedSourceAddr = sourceAddrs; } catch (RemoteException e) { throw new RuntimeException("Problem setting firewall rules", e); } final NetworkInfo clone = new NetworkInfo(egressInfo); augmentNetworkInfo(clone); mConnService.sendConnectedBroadcast(clone); Loading @@ -227,19 +208,11 @@ public class LockdownVpnTracker { Slog.d(TAG, "initLocked()"); mVpn.setEnableTeardown(false); mVpn.setLockdown(true); final IntentFilter resetFilter = new IntentFilter(ACTION_LOCKDOWN_RESET); mContext.registerReceiver(mResetReceiver, resetFilter, CONNECTIVITY_INTERNAL, null); try { // TODO: support non-standard port numbers mNetService.setFirewallEgressDestRule(mProfile.server, 500, true); mNetService.setFirewallEgressDestRule(mProfile.server, 4500, true); mNetService.setFirewallEgressDestRule(mProfile.server, 1701, true); } catch (RemoteException e) { throw new RuntimeException("Problem setting firewall rules", e); } handleStateChangedLocked(); } Loading @@ -256,14 +229,7 @@ public class LockdownVpnTracker { mErrorCount = 0; mVpn.stopLegacyVpnPrivileged(); try { mNetService.setFirewallEgressDestRule(mProfile.server, 500, false); mNetService.setFirewallEgressDestRule(mProfile.server, 4500, false); mNetService.setFirewallEgressDestRule(mProfile.server, 1701, false); } catch (RemoteException e) { throw new RuntimeException("Problem setting firewall rules", e); } clearSourceRulesLocked(); mVpn.setLockdown(false); hideNotification(); mContext.unregisterReceiver(mResetReceiver); Loading @@ -280,35 +246,6 @@ public class LockdownVpnTracker { } } private void clearSourceRulesLocked() { try { if (mAcceptedIface != null) { mNetService.setFirewallInterfaceRule(mAcceptedIface, false); mAcceptedIface = null; } if (mAcceptedSourceAddr != null) { for (LinkAddress addr : mAcceptedSourceAddr) { setFirewallEgressSourceRule(addr, false); } mNetService.setFirewallUidRule(FIREWALL_CHAIN_NONE, ROOT_UID, FIREWALL_RULE_DEFAULT); mNetService.setFirewallUidRule(FIREWALL_CHAIN_NONE,Os.getuid(), FIREWALL_RULE_DEFAULT); mAcceptedSourceAddr = null; } } catch (RemoteException e) { throw new RuntimeException("Problem setting firewall rules", e); } } private void setFirewallEgressSourceRule( LinkAddress address, boolean allow) throws RemoteException { // Our source address based firewall rules must only cover our own source address, not the // whole subnet final String addrString = address.getAddress().getHostAddress(); mNetService.setFirewallEgressSourceRule(addrString, allow); } public void onNetworkInfoChanged() { synchronized (mStateLock) { handleStateChangedLocked(); Loading
tests/net/java/com/android/server/connectivity/VpnTest.java +57 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.annotation.UserIdInt; import android.app.AppOpsManager; import android.app.NotificationManager; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.UserInfo; Loading @@ -42,6 +43,8 @@ import android.test.suitebuilder.annotation.SmallTest; import android.util.ArrayMap; import android.util.ArraySet; import com.android.internal.net.VpnConfig; import java.util.ArrayList; import java.util.Arrays; import java.util.Map; Loading Loading @@ -101,8 +104,10 @@ public class VpnTest extends AndroidTestCase { @Override public void setUp() throws Exception { MockitoAnnotations.initMocks(this); when(mContext.getPackageManager()).thenReturn(mPackageManager); setMockedPackages(mPackages); when(mContext.getPackageName()).thenReturn(Vpn.class.getPackage().getName()); when(mContext.getSystemService(eq(Context.USER_SERVICE))).thenReturn(mUserManager); when(mContext.getSystemService(eq(Context.APP_OPS_SERVICE))).thenReturn(mAppOps); Loading Loading @@ -257,6 +262,58 @@ public class VpnTest extends AndroidTestCase { })); } @SmallTest public void testLockdownRuleRepeatability() throws Exception { final Vpn vpn = createVpn(primaryUser.id); // Given legacy lockdown is already enabled, vpn.setLockdown(true); verify(mNetService, times(1)).setAllowOnlyVpnForUids( eq(true), aryEq(new UidRange[] {UidRange.createForUser(primaryUser.id)})); // Enabling legacy lockdown twice should do nothing. vpn.setLockdown(true); verify(mNetService, times(1)).setAllowOnlyVpnForUids(anyBoolean(), any(UidRange[].class)); // And disabling should remove the rules exactly once. vpn.setLockdown(false); verify(mNetService, times(1)).setAllowOnlyVpnForUids( eq(false), aryEq(new UidRange[] {UidRange.createForUser(primaryUser.id)})); // Removing the lockdown again should have no effect. vpn.setLockdown(false); verify(mNetService, times(2)).setAllowOnlyVpnForUids(anyBoolean(), any(UidRange[].class)); } @SmallTest public void testLockdownRuleReversibility() throws Exception { final Vpn vpn = createVpn(primaryUser.id); final UidRange[] entireUser = { UidRange.createForUser(primaryUser.id) }; final UidRange[] exceptPkg0 = { new UidRange(entireUser[0].start, entireUser[0].start + PKG_UIDS[0] - 1), new UidRange(entireUser[0].start + PKG_UIDS[0] + 1, entireUser[0].stop) }; final InOrder order = inOrder(mNetService); // Given lockdown is enabled with no package (legacy VPN), vpn.setLockdown(true); order.verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(entireUser)); // When a new VPN package is set the rules should change to cover that package. vpn.prepare(null, PKGS[0]); order.verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(entireUser)); order.verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(exceptPkg0)); // When that VPN package is unset, everything should be undone again in reverse. vpn.prepare(null, VpnConfig.LEGACY_VPN); order.verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(exceptPkg0)); order.verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(entireUser)); } @SmallTest public void testNotificationShownForAlwaysOnApp() { final UserHandle userHandle = UserHandle.of(primaryUser.id); Loading