Whitelist packages from VPN lockdown.
Bug: 77468593 Test: atest com.android.server.connectivity.VpnTest Change-Id: I9119c139ab07a761ce5dfd1365b70eb905fd32dc
This commit is contained in:
@@ -1014,20 +1014,54 @@ public class ConnectivityManager {
|
|||||||
* to remove an existing always-on VPN configuration.
|
* to remove an existing always-on VPN configuration.
|
||||||
* @param lockdownEnabled {@code true} to disallow networking when the VPN is not connected or
|
* @param lockdownEnabled {@code true} to disallow networking when the VPN is not connected or
|
||||||
* {@code false} otherwise.
|
* {@code false} otherwise.
|
||||||
|
* @param lockdownWhitelist The list of packages that are allowed to access network directly
|
||||||
|
* when VPN is in lockdown mode but is not running. Non-existent packages are ignored so
|
||||||
|
* this method must be called when a package that should be whitelisted is installed or
|
||||||
|
* uninstalled.
|
||||||
* @return {@code true} if the package is set as always-on VPN controller;
|
* @return {@code true} if the package is set as always-on VPN controller;
|
||||||
* {@code false} otherwise.
|
* {@code false} otherwise.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
|
@RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN)
|
||||||
public boolean setAlwaysOnVpnPackageForUser(int userId, @Nullable String vpnPackage,
|
public boolean setAlwaysOnVpnPackageForUser(int userId, @Nullable String vpnPackage,
|
||||||
boolean lockdownEnabled) {
|
boolean lockdownEnabled, @Nullable List<String> lockdownWhitelist) {
|
||||||
try {
|
try {
|
||||||
return mService.setAlwaysOnVpnPackage(userId, vpnPackage, lockdownEnabled);
|
return mService.setAlwaysOnVpnPackage(
|
||||||
|
userId, vpnPackage, lockdownEnabled, lockdownWhitelist);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
throw e.rethrowFromSystemServer();
|
throw e.rethrowFromSystemServer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Configures an always-on VPN connection through a specific application.
|
||||||
|
* This connection is automatically granted and persisted after a reboot.
|
||||||
|
*
|
||||||
|
* <p>The designated package should declare a {@link VpnService} in its
|
||||||
|
* manifest guarded by {@link android.Manifest.permission.BIND_VPN_SERVICE},
|
||||||
|
* otherwise the call will fail.
|
||||||
|
*
|
||||||
|
* @param userId The identifier of the user to set an always-on VPN for.
|
||||||
|
* @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.
|
||||||
|
* @return {@code true} if the package is set as always-on VPN controller;
|
||||||
|
* {@code false} otherwise.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN)
|
||||||
|
public boolean setAlwaysOnVpnPackageForUser(int userId, @Nullable String vpnPackage,
|
||||||
|
boolean lockdownEnabled) {
|
||||||
|
try {
|
||||||
|
return mService.setAlwaysOnVpnPackage(
|
||||||
|
userId, vpnPackage, lockdownEnabled, /* whitelist */ null);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
throw e.rethrowFromSystemServer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
* Returns the package name of the currently set always-on VPN application.
|
* Returns the package name of the currently set always-on VPN application.
|
||||||
* If there is no always-on VPN set, or the VPN is provided by the system instead
|
* If there is no always-on VPN set, or the VPN is provided by the system instead
|
||||||
* of by an app, {@code null} will be returned.
|
* of by an app, {@code null} will be returned.
|
||||||
@@ -1036,6 +1070,7 @@ public class ConnectivityManager {
|
|||||||
* or {@code null} if none is set.
|
* or {@code null} if none is set.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
|
@RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN)
|
||||||
public String getAlwaysOnVpnPackageForUser(int userId) {
|
public String getAlwaysOnVpnPackageForUser(int userId) {
|
||||||
try {
|
try {
|
||||||
return mService.getAlwaysOnVpnPackage(userId);
|
return mService.getAlwaysOnVpnPackage(userId);
|
||||||
@@ -1044,6 +1079,36 @@ public class ConnectivityManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return whether always-on VPN is in lockdown mode.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
**/
|
||||||
|
@RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN)
|
||||||
|
public boolean isVpnLockdownEnabled(int userId) {
|
||||||
|
try {
|
||||||
|
return mService.isVpnLockdownEnabled(userId);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
throw e.rethrowFromSystemServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the list of packages that are allowed to access network when always-on VPN is in
|
||||||
|
* lockdown mode but not connected. Returns {@code null} when VPN lockdown is not active.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
**/
|
||||||
|
@RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN)
|
||||||
|
public List<String> getVpnLockdownWhitelist(int userId) {
|
||||||
|
try {
|
||||||
|
return mService.getVpnLockdownWhitelist(userId);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
throw e.rethrowFromSystemServer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns details about the currently active default data network
|
* Returns details about the currently active default data network
|
||||||
* for a given uid. This is for internal use only to avoid spying
|
* for a given uid. This is for internal use only to avoid spying
|
||||||
|
|||||||
@@ -125,8 +125,11 @@ interface IConnectivityManager
|
|||||||
|
|
||||||
boolean updateLockdownVpn();
|
boolean updateLockdownVpn();
|
||||||
boolean isAlwaysOnVpnPackageSupported(int userId, String packageName);
|
boolean isAlwaysOnVpnPackageSupported(int userId, String packageName);
|
||||||
boolean setAlwaysOnVpnPackage(int userId, String packageName, boolean lockdown);
|
boolean setAlwaysOnVpnPackage(int userId, String packageName, boolean lockdown,
|
||||||
|
in List<String> lockdownWhitelist);
|
||||||
String getAlwaysOnVpnPackage(int userId);
|
String getAlwaysOnVpnPackage(int userId);
|
||||||
|
boolean isVpnLockdownEnabled(int userId);
|
||||||
|
List<String> getVpnLockdownWhitelist(int userId);
|
||||||
|
|
||||||
int checkMobileProvisioning(int suggestedTimeOutMs);
|
int checkMobileProvisioning(int suggestedTimeOutMs);
|
||||||
|
|
||||||
|
|||||||
@@ -1884,6 +1884,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
"ConnectivityService");
|
"ConnectivityService");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void enforceControlAlwaysOnVpnPermission() {
|
||||||
|
mContext.enforceCallingOrSelfPermission(
|
||||||
|
android.Manifest.permission.CONTROL_ALWAYS_ON_VPN,
|
||||||
|
"ConnectivityService");
|
||||||
|
}
|
||||||
|
|
||||||
private void enforceNetworkStackSettingsOrSetup() {
|
private void enforceNetworkStackSettingsOrSetup() {
|
||||||
enforceAnyPermissionOf(
|
enforceAnyPermissionOf(
|
||||||
android.Manifest.permission.NETWORK_SETTINGS,
|
android.Manifest.permission.NETWORK_SETTINGS,
|
||||||
@@ -1891,6 +1897,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
android.Manifest.permission.NETWORK_STACK);
|
android.Manifest.permission.NETWORK_STACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void enforceNetworkStackPermission() {
|
||||||
|
mContext.enforceCallingOrSelfPermission(
|
||||||
|
android.Manifest.permission.NETWORK_STACK,
|
||||||
|
"ConnectivityService");
|
||||||
|
}
|
||||||
|
|
||||||
private boolean checkNetworkStackPermission() {
|
private boolean checkNetworkStackPermission() {
|
||||||
return PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
|
return PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
|
||||||
android.Manifest.permission.NETWORK_STACK);
|
android.Manifest.permission.NETWORK_STACK);
|
||||||
@@ -4147,8 +4159,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean setAlwaysOnVpnPackage(int userId, String packageName, boolean lockdown) {
|
public boolean setAlwaysOnVpnPackage(
|
||||||
enforceConnectivityInternalPermission();
|
int userId, String packageName, boolean lockdown, List<String> lockdownWhitelist) {
|
||||||
|
enforceControlAlwaysOnVpnPermission();
|
||||||
enforceCrossUserPermission(userId);
|
enforceCrossUserPermission(userId);
|
||||||
|
|
||||||
synchronized (mVpns) {
|
synchronized (mVpns) {
|
||||||
@@ -4162,11 +4175,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
Slog.w(TAG, "User " + userId + " has no Vpn configuration");
|
Slog.w(TAG, "User " + userId + " has no Vpn configuration");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!vpn.setAlwaysOnPackage(packageName, lockdown)) {
|
if (!vpn.setAlwaysOnPackage(packageName, lockdown, lockdownWhitelist)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!startAlwaysOnVpn(userId)) {
|
if (!startAlwaysOnVpn(userId)) {
|
||||||
vpn.setAlwaysOnPackage(null, false);
|
vpn.setAlwaysOnPackage(null, false, null);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4175,7 +4188,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getAlwaysOnVpnPackage(int userId) {
|
public String getAlwaysOnVpnPackage(int userId) {
|
||||||
enforceConnectivityInternalPermission();
|
enforceControlAlwaysOnVpnPermission();
|
||||||
enforceCrossUserPermission(userId);
|
enforceCrossUserPermission(userId);
|
||||||
|
|
||||||
synchronized (mVpns) {
|
synchronized (mVpns) {
|
||||||
@@ -4188,6 +4201,36 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isVpnLockdownEnabled(int userId) {
|
||||||
|
enforceControlAlwaysOnVpnPermission();
|
||||||
|
enforceCrossUserPermission(userId);
|
||||||
|
|
||||||
|
synchronized (mVpns) {
|
||||||
|
Vpn vpn = mVpns.get(userId);
|
||||||
|
if (vpn == null) {
|
||||||
|
Slog.w(TAG, "User " + userId + " has no Vpn configuration");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return vpn.getLockdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getVpnLockdownWhitelist(int userId) {
|
||||||
|
enforceControlAlwaysOnVpnPermission();
|
||||||
|
enforceCrossUserPermission(userId);
|
||||||
|
|
||||||
|
synchronized (mVpns) {
|
||||||
|
Vpn vpn = mVpns.get(userId);
|
||||||
|
if (vpn == null) {
|
||||||
|
Slog.w(TAG, "User " + userId + " has no Vpn configuration");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return vpn.getLockdownWhitelist();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int checkMobileProvisioning(int suggestedTimeOutMs) {
|
public int checkMobileProvisioning(int suggestedTimeOutMs) {
|
||||||
// TODO: Remove? Any reason to trigger a provisioning check?
|
// TODO: Remove? Any reason to trigger a provisioning check?
|
||||||
@@ -4417,7 +4460,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
if (TextUtils.equals(vpn.getAlwaysOnPackage(), packageName) && !isReplacing) {
|
if (TextUtils.equals(vpn.getAlwaysOnPackage(), packageName) && !isReplacing) {
|
||||||
Slog.d(TAG, "Removing always-on VPN package " + packageName + " for user "
|
Slog.d(TAG, "Removing always-on VPN package " + packageName + " for user "
|
||||||
+ userId);
|
+ userId);
|
||||||
vpn.setAlwaysOnPackage(null, false);
|
vpn.setAlwaysOnPackage(null, false, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6297,7 +6340,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
synchronized (mVpns) {
|
synchronized (mVpns) {
|
||||||
final String alwaysOnPackage = getAlwaysOnVpnPackage(userId);
|
final String alwaysOnPackage = getAlwaysOnVpnPackage(userId);
|
||||||
if (alwaysOnPackage != null) {
|
if (alwaysOnPackage != null) {
|
||||||
setAlwaysOnVpnPackage(userId, null, false);
|
setAlwaysOnVpnPackage(userId, null, false, null);
|
||||||
setVpnPackageAuthorization(alwaysOnPackage, userId, false);
|
setVpnPackageAuthorization(alwaysOnPackage, userId, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -246,17 +246,17 @@ public class VpnTest {
|
|||||||
assertFalse(vpn.getLockdown());
|
assertFalse(vpn.getLockdown());
|
||||||
|
|
||||||
// Set always-on without lockdown.
|
// Set always-on without lockdown.
|
||||||
assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false));
|
assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false, Collections.emptyList()));
|
||||||
assertTrue(vpn.getAlwaysOn());
|
assertTrue(vpn.getAlwaysOn());
|
||||||
assertFalse(vpn.getLockdown());
|
assertFalse(vpn.getLockdown());
|
||||||
|
|
||||||
// Set always-on with lockdown.
|
// Set always-on with lockdown.
|
||||||
assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true));
|
assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, Collections.emptyList()));
|
||||||
assertTrue(vpn.getAlwaysOn());
|
assertTrue(vpn.getAlwaysOn());
|
||||||
assertTrue(vpn.getLockdown());
|
assertTrue(vpn.getLockdown());
|
||||||
|
|
||||||
// Remove always-on configuration.
|
// Remove always-on configuration.
|
||||||
assertTrue(vpn.setAlwaysOnPackage(null, false));
|
assertTrue(vpn.setAlwaysOnPackage(null, false, Collections.emptyList()));
|
||||||
assertFalse(vpn.getAlwaysOn());
|
assertFalse(vpn.getAlwaysOn());
|
||||||
assertFalse(vpn.getLockdown());
|
assertFalse(vpn.getLockdown());
|
||||||
}
|
}
|
||||||
@@ -270,11 +270,11 @@ public class VpnTest {
|
|||||||
assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]);
|
assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]);
|
||||||
|
|
||||||
// Set always-on without lockdown.
|
// Set always-on without lockdown.
|
||||||
assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false));
|
assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false, null));
|
||||||
assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]);
|
assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]);
|
||||||
|
|
||||||
// Set always-on with lockdown.
|
// Set always-on with lockdown.
|
||||||
assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true));
|
assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, null));
|
||||||
verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
|
verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
|
||||||
new UidRange(user.start, user.start + PKG_UIDS[1] - 1),
|
new UidRange(user.start, user.start + PKG_UIDS[1] - 1),
|
||||||
new UidRange(user.start + PKG_UIDS[1] + 1, user.stop)
|
new UidRange(user.start + PKG_UIDS[1] + 1, user.stop)
|
||||||
@@ -283,7 +283,7 @@ public class VpnTest {
|
|||||||
assertUnblocked(vpn, user.start + PKG_UIDS[1]);
|
assertUnblocked(vpn, user.start + PKG_UIDS[1]);
|
||||||
|
|
||||||
// Switch to another app.
|
// Switch to another app.
|
||||||
assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true));
|
assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null));
|
||||||
verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] {
|
verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] {
|
||||||
new UidRange(user.start, user.start + PKG_UIDS[1] - 1),
|
new UidRange(user.start, user.start + PKG_UIDS[1] - 1),
|
||||||
new UidRange(user.start + PKG_UIDS[1] + 1, user.stop)
|
new UidRange(user.start + PKG_UIDS[1] + 1, user.stop)
|
||||||
@@ -296,6 +296,87 @@ public class VpnTest {
|
|||||||
assertUnblocked(vpn, user.start + PKG_UIDS[3]);
|
assertUnblocked(vpn, user.start + PKG_UIDS[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLockdownWhitelist() throws Exception {
|
||||||
|
final Vpn vpn = createVpn(primaryUser.id);
|
||||||
|
final UidRange user = UidRange.createForUser(primaryUser.id);
|
||||||
|
|
||||||
|
// Set always-on with lockdown and whitelist app PKGS[2] from lockdown.
|
||||||
|
assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, Collections.singletonList(PKGS[2])));
|
||||||
|
verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
|
||||||
|
new UidRange(user.start, user.start + PKG_UIDS[1] - 1),
|
||||||
|
new UidRange(user.start + PKG_UIDS[2] + 1, user.stop)
|
||||||
|
}));
|
||||||
|
assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[3]);
|
||||||
|
assertUnblocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]);
|
||||||
|
|
||||||
|
// Change whitelisted app to PKGS[3].
|
||||||
|
assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, Collections.singletonList(PKGS[3])));
|
||||||
|
verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] {
|
||||||
|
new UidRange(user.start + PKG_UIDS[2] + 1, user.stop)
|
||||||
|
}));
|
||||||
|
verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
|
||||||
|
new UidRange(user.start + PKG_UIDS[1] + 1, user.start + PKG_UIDS[3] - 1),
|
||||||
|
new UidRange(user.start + PKG_UIDS[3] + 1, user.stop)
|
||||||
|
}));
|
||||||
|
assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[2]);
|
||||||
|
assertUnblocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[3]);
|
||||||
|
|
||||||
|
// Change the VPN app.
|
||||||
|
assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, Collections.singletonList(PKGS[3])));
|
||||||
|
verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] {
|
||||||
|
new UidRange(user.start, user.start + PKG_UIDS[1] - 1),
|
||||||
|
new UidRange(user.start + PKG_UIDS[1] + 1, user.start + PKG_UIDS[3] - 1)
|
||||||
|
}));
|
||||||
|
verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
|
||||||
|
new UidRange(user.start, user.start + PKG_UIDS[0] - 1),
|
||||||
|
new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[3] - 1)
|
||||||
|
}));
|
||||||
|
assertBlocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]);
|
||||||
|
assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[3]);
|
||||||
|
|
||||||
|
// Remove the whitelist.
|
||||||
|
assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, null));
|
||||||
|
verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] {
|
||||||
|
new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[3] - 1),
|
||||||
|
new UidRange(user.start + PKG_UIDS[3] + 1, user.stop)
|
||||||
|
}));
|
||||||
|
verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
|
||||||
|
new UidRange(user.start + PKG_UIDS[0] + 1, user.stop),
|
||||||
|
}));
|
||||||
|
assertBlocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[2],
|
||||||
|
user.start + PKG_UIDS[3]);
|
||||||
|
assertUnblocked(vpn, user.start + PKG_UIDS[0]);
|
||||||
|
|
||||||
|
// Add the whitelist.
|
||||||
|
assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, Collections.singletonList(PKGS[1])));
|
||||||
|
verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] {
|
||||||
|
new UidRange(user.start + PKG_UIDS[0] + 1, user.stop)
|
||||||
|
}));
|
||||||
|
verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
|
||||||
|
new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1),
|
||||||
|
new UidRange(user.start + PKG_UIDS[1] + 1, user.stop)
|
||||||
|
}));
|
||||||
|
assertBlocked(vpn, user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]);
|
||||||
|
assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1]);
|
||||||
|
|
||||||
|
// Try whitelisting a package with a comma, should be rejected.
|
||||||
|
assertFalse(vpn.setAlwaysOnPackage(PKGS[0], true, Collections.singletonList("a.b,c.d")));
|
||||||
|
|
||||||
|
// Pass a non-existent packages in the whitelist, they (and only they) should be ignored.
|
||||||
|
// Whitelisted package should change from PGKS[1] to PKGS[2].
|
||||||
|
assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true,
|
||||||
|
Arrays.asList("com.foo.app", PKGS[2], "com.bar.app")));
|
||||||
|
verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[]{
|
||||||
|
new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1),
|
||||||
|
new UidRange(user.start + PKG_UIDS[1] + 1, user.stop)
|
||||||
|
}));
|
||||||
|
verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[]{
|
||||||
|
new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[2] - 1),
|
||||||
|
new UidRange(user.start + PKG_UIDS[2] + 1, user.stop)
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLockdownAddingAProfile() throws Exception {
|
public void testLockdownAddingAProfile() throws Exception {
|
||||||
final Vpn vpn = createVpn(primaryUser.id);
|
final Vpn vpn = createVpn(primaryUser.id);
|
||||||
@@ -310,7 +391,7 @@ public class VpnTest {
|
|||||||
final UidRange profile = UidRange.createForUser(tempProfile.id);
|
final UidRange profile = UidRange.createForUser(tempProfile.id);
|
||||||
|
|
||||||
// Set lockdown.
|
// Set lockdown.
|
||||||
assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true));
|
assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null));
|
||||||
verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
|
verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
|
||||||
new UidRange(user.start, user.start + PKG_UIDS[3] - 1),
|
new UidRange(user.start, user.start + PKG_UIDS[3] - 1),
|
||||||
new UidRange(user.start + PKG_UIDS[3] + 1, user.stop)
|
new UidRange(user.start + PKG_UIDS[3] + 1, user.stop)
|
||||||
@@ -436,7 +517,7 @@ public class VpnTest {
|
|||||||
.cancelAsUser(anyString(), anyInt(), eq(userHandle));
|
.cancelAsUser(anyString(), anyInt(), eq(userHandle));
|
||||||
|
|
||||||
// Start showing a notification for disconnected once always-on.
|
// Start showing a notification for disconnected once always-on.
|
||||||
vpn.setAlwaysOnPackage(PKGS[0], false);
|
vpn.setAlwaysOnPackage(PKGS[0], false, null);
|
||||||
order.verify(mNotificationManager)
|
order.verify(mNotificationManager)
|
||||||
.notifyAsUser(anyString(), anyInt(), any(), eq(userHandle));
|
.notifyAsUser(anyString(), anyInt(), any(), eq(userHandle));
|
||||||
|
|
||||||
@@ -450,7 +531,7 @@ public class VpnTest {
|
|||||||
.notifyAsUser(anyString(), anyInt(), any(), eq(userHandle));
|
.notifyAsUser(anyString(), anyInt(), any(), eq(userHandle));
|
||||||
|
|
||||||
// Notification should be cleared after unsetting always-on package.
|
// Notification should be cleared after unsetting always-on package.
|
||||||
vpn.setAlwaysOnPackage(null, false);
|
vpn.setAlwaysOnPackage(null, false, null);
|
||||||
order.verify(mNotificationManager).cancelAsUser(anyString(), anyInt(), eq(userHandle));
|
order.verify(mNotificationManager).cancelAsUser(anyString(), anyInt(), eq(userHandle));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -583,7 +664,9 @@ public class VpnTest {
|
|||||||
doAnswer(invocation -> {
|
doAnswer(invocation -> {
|
||||||
final String appName = (String) invocation.getArguments()[0];
|
final String appName = (String) invocation.getArguments()[0];
|
||||||
final int userId = (int) invocation.getArguments()[1];
|
final int userId = (int) invocation.getArguments()[1];
|
||||||
return UserHandle.getUid(userId, packages.get(appName));
|
Integer appId = packages.get(appName);
|
||||||
|
if (appId == null) throw new PackageManager.NameNotFoundException(appName);
|
||||||
|
return UserHandle.getUid(userId, appId);
|
||||||
}).when(mPackageManager).getPackageUidAsUser(anyString(), anyInt());
|
}).when(mPackageManager).getPackageUidAsUser(anyString(), anyInt());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user