Refactor to mock package add and remove event
Use mock intent receiver to handle intent related events instead
of exposing the private methods even for testing only.
The visibility for onPackageAdded, onPackageRemoved and
onUserStarted were exposed for testing only in former commit.
The test coverage for intent receiver part may be missed.
The other intent related methods will be verified in the
follow up commits. This refactor will also help to not to
expose further private methods.
Bug: 230548427
Test: atest VpnManagerServiceTest
Change-Id: If2aa88d8d5c1643e8bd4937673aa792186047fd8
diff --git a/tests/unit/java/com/android/server/VpnManagerServiceTest.java b/tests/unit/java/com/android/server/VpnManagerServiceTest.java
index eb9a752..164f825 100644
--- a/tests/unit/java/com/android/server/VpnManagerServiceTest.java
+++ b/tests/unit/java/com/android/server/VpnManagerServiceTest.java
@@ -24,7 +24,6 @@
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.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 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 @@
@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,23 +115,31 @@
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
- mService.onUserStarted(SYSTEM_USER_ID);
+ onUserStarted(SYSTEM_USER_ID);
assertNotNull(mService.mVpns.get(SYSTEM_USER_ID));
}
@@ -134,19 +150,19 @@
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();
}
@@ -172,4 +188,47 @@
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);
+ }
}