Merge changes from topics "RefactorIR", "appExclusionPrefix", "reStartVpnProfile"

* changes:
  Refactor to mock package add and remove event
  Test reconnect VpnManager VPN with always on enabled
  Update the prefix of VPN_APP_EXCLUDED in the test
  Add tests to verify getProvisionedVpnProfileState
This commit is contained in:
Chiachang Wang
2022-07-11 01:24:28 +00:00
committed by Gerrit Code Review
2 changed files with 117 additions and 21 deletions

View File

@@ -24,7 +24,6 @@ import static com.android.testutils.MiscAsserts.assertThrows;
import static org.junit.Assert.assertNotNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
@@ -32,15 +31,18 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.annotation.UserIdInt;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.INetd;
import android.net.Uri;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.INetworkManagementService;
import android.os.Looper;
import android.os.UserHandle;
import android.os.UserManager;
import androidx.test.filters.SmallTest;
@@ -48,14 +50,15 @@ import androidx.test.filters.SmallTest;
import com.android.server.connectivity.Vpn;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRunner;
import com.android.testutils.HandlerUtils;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
@RunWith(DevSdkIgnoreRunner.class)
@IgnoreUpTo(R) // VpnManagerService is not available before R
@@ -64,18 +67,23 @@ public class VpnManagerServiceTest extends VpnTestBase {
@Rule
public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule();
@Spy Context mContext;
private static final int TIMEOUT_MS = 2_000;
@Mock Context mContext;
@Mock Context mSystemContext;
@Mock Context mUserAllContext;
private HandlerThread mHandlerThread;
@Mock private Handler mHandler;
@Mock private Vpn mVpn;
@Mock private INetworkManagementService mNms;
@Mock private ConnectivityManager mCm;
@Mock private UserManager mUserManager;
@Mock private INetd mNetd;
@Mock private PackageManager mPackageManager;
private VpnManagerServiceDependencies mDeps;
private VpnManagerService mService;
private BroadcastReceiver mUserPresentReceiver;
private BroadcastReceiver mIntentReceiver;
private final String mNotMyVpnPkg = "com.not.my.vpn";
class VpnManagerServiceDependencies extends VpnManagerService.Dependencies {
@@ -107,46 +115,54 @@ public class VpnManagerServiceTest extends VpnTestBase {
mHandlerThread = new HandlerThread("TestVpnManagerService");
mDeps = new VpnManagerServiceDependencies();
doReturn(mContext).when(mContext).createContextAsUser(any(), anyInt());
doReturn(mUserAllContext).when(mContext).createContextAsUser(UserHandle.ALL, 0);
doReturn(mSystemContext).when(mContext).createContextAsUser(UserHandle.SYSTEM, 0);
doReturn(mPackageManager).when(mContext).getPackageManager();
setMockedPackages(mPackageManager, sPackages);
mockService(mContext, ConnectivityManager.class, Context.CONNECTIVITY_SERVICE, mCm);
mockService(mContext, UserManager.class, Context.USER_SERVICE, mUserManager);
doReturn(new Intent()).when(mContext).registerReceiver(
any() /* receiver */,
any() /* intentFilter */,
any() /* broadcastPermission */,
eq(mHandler) /* scheduler */);
doReturn(SYSTEM_USER).when(mUserManager).getUserInfo(eq(SYSTEM_USER_ID));
mService = new VpnManagerService(mContext, mDeps);
mService.systemReady();
final ArgumentCaptor<BroadcastReceiver> intentReceiverCaptor =
ArgumentCaptor.forClass(BroadcastReceiver.class);
final ArgumentCaptor<BroadcastReceiver> userPresentReceiverCaptor =
ArgumentCaptor.forClass(BroadcastReceiver.class);
verify(mSystemContext).registerReceiver(
userPresentReceiverCaptor.capture(), any(), any(), any());
verify(mUserAllContext, times(2)).registerReceiver(
intentReceiverCaptor.capture(), any(), any(), any());
mUserPresentReceiver = userPresentReceiverCaptor.getValue();
mIntentReceiver = intentReceiverCaptor.getValue();
// Add user to create vpn in mVpn
onUserStarted(SYSTEM_USER_ID);
assertNotNull(mService.mVpns.get(SYSTEM_USER_ID));
}
@Test
public void testUpdateAppExclusionList() {
// Add user to create vpn in mVpn
mService.onUserStarted(SYSTEM_USER_ID);
assertNotNull(mService.mVpns.get(SYSTEM_USER_ID));
// Start vpn
mService.startVpnProfile(TEST_VPN_PKG);
verify(mVpn).startVpnProfile(eq(TEST_VPN_PKG));
// Remove package due to package replaced.
mService.onPackageRemoved(PKGS[0], PKG_UIDS[0], true /* isReplacing */);
onPackageRemoved(PKGS[0], PKG_UIDS[0], true /* isReplacing */);
verify(mVpn, never()).refreshPlatformVpnAppExclusionList();
// Add package due to package replaced.
mService.onPackageAdded(PKGS[0], PKG_UIDS[0], true /* isReplacing */);
onPackageAdded(PKGS[0], PKG_UIDS[0], true /* isReplacing */);
verify(mVpn, never()).refreshPlatformVpnAppExclusionList();
// Remove package
mService.onPackageRemoved(PKGS[0], PKG_UIDS[0], false /* isReplacing */);
onPackageRemoved(PKGS[0], PKG_UIDS[0], false /* isReplacing */);
verify(mVpn).refreshPlatformVpnAppExclusionList();
// Add the package back
mService.onPackageAdded(PKGS[0], PKG_UIDS[0], false /* isReplacing */);
onPackageAdded(PKGS[0], PKG_UIDS[0], false /* isReplacing */);
verify(mVpn, times(2)).refreshPlatformVpnAppExclusionList();
}
@@ -160,4 +176,59 @@ public class VpnManagerServiceTest extends VpnTestBase {
public void testStopVpnProfileFromDiffPackage() {
assertThrows(SecurityException.class, () -> mService.stopVpnProfile(mNotMyVpnPkg));
}
@Test
public void testGetProvisionedVpnProfileStateFromDiffPackage() {
assertThrows(SecurityException.class, () ->
mService.getProvisionedVpnProfileState(mNotMyVpnPkg));
}
@Test
public void testGetProvisionedVpnProfileState() {
mService.getProvisionedVpnProfileState(TEST_VPN_PKG);
verify(mVpn).getProvisionedVpnProfileState(TEST_VPN_PKG);
}
private Intent buildIntent(String action, String packageName, int userId, int uid,
boolean isReplacing) {
final Intent intent = new Intent(action);
intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
intent.putExtra(Intent.EXTRA_UID, uid);
intent.putExtra(Intent.EXTRA_REPLACING, isReplacing);
if (packageName != null) {
intent.setData(Uri.fromParts("package" /* scheme */, packageName, null /* fragment */));
}
return intent;
}
private void sendIntent(Intent intent) {
final Handler h = mHandlerThread.getThreadHandler();
// Send in handler thread.
h.post(() -> mIntentReceiver.onReceive(mContext, intent));
HandlerUtils.waitForIdle(mHandlerThread, TIMEOUT_MS);
}
private void onUserStarted(int userId) {
sendIntent(buildIntent(Intent.ACTION_USER_STARTED,
null /* packageName */, userId, -1 /* uid */, false /* isReplacing */));
}
private void onPackageAdded(String packageName, int userId, int uid, boolean isReplacing) {
sendIntent(buildIntent(Intent.ACTION_PACKAGE_ADDED, packageName, userId, uid, isReplacing));
}
private void onPackageAdded(String packageName, int uid, boolean isReplacing) {
onPackageAdded(packageName, UserHandle.USER_SYSTEM, uid, isReplacing);
}
private void onPackageRemoved(String packageName, int userId, int uid, boolean isReplacing) {
sendIntent(buildIntent(Intent.ACTION_PACKAGE_REMOVED, packageName, userId, uid,
isReplacing));
}
private void onPackageRemoved(String packageName, int uid, boolean isReplacing) {
onPackageRemoved(packageName, UserHandle.USER_SYSTEM, uid, isReplacing);
}
}

View File

@@ -232,7 +232,7 @@ public class VpnTest extends VpnTestBase {
private static final int TEST_TUNNEL_RESOURCE_ID = 0x2345;
private static final long TEST_TIMEOUT_MS = 500L;
private static final String PRIMARY_USER_APP_EXCLUDE_KEY =
"VPN_APP_EXCLUDED_27_com.testvpn.vpn";
"VPNAPPEXCLUDED_27_com.testvpn.vpn";
static final String PKGS_BYTES = getPackageByteString(List.of(PKGS));
private static final Range<Integer> PRIMARY_USER_RANGE = uidRangeForUser(PRIMARY_USER.id);
@@ -1359,6 +1359,31 @@ public class VpnTest extends VpnTestBase {
null /* sessionKey */, true /* alwaysOn */, false /* lockdown */));
}
@Test
public void testReconnectVpnManagerVpnWithAlwaysOnEnabled() throws Exception {
final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG)))
.thenReturn(mVpnProfile.encode());
vpn.startVpnProfile(TEST_VPN_PKG);
verifyPlatformVpnIsActivated(TEST_VPN_PKG);
// Enable VPN always-on for TEST_VPN_PKG.
assertTrue(vpn.setAlwaysOnPackage(TEST_VPN_PKG, false /* lockdown */,
null /* lockdownAllowlist */));
// Reset to verify next startVpnProfile.
reset(mAppOps);
vpn.stopVpnProfile(TEST_VPN_PKG);
// Reconnect the vpn with different package will cause exception.
assertThrows(SecurityException.class, () -> vpn.startVpnProfile(PKGS[0]));
// Reconnect the vpn again with the vpn always on package w/o exception.
vpn.startVpnProfile(TEST_VPN_PKG);
verifyPlatformVpnIsActivated(TEST_VPN_PKG);
}
@Test
public void testSetPackageAuthorizationVpnService() throws Exception {
final Vpn vpn = createVpnAndSetupUidChecks();