Fix and improve TrustManagerServiceTest
- Make these unit tests have fewer dependencies on the system. For
example, don't use the system's real UserManagerService and
LockSettingsService. Use userId 50 instead of userId 0 to help avoid
unwanted dependencies.
- Set up more things in setUp() so that individual tests don't need to.
- Run the TrustManagerService handler on a separate thread so that code
that flushes the message queue does not cause a deadlock. The
existing tests are fine without this, but this is needed for a later
CL that adds tests that call reportKeyguardShowingChanged().
This fixes failures in firstBootCompleted_defaultTrustAgentEnabled,
newSystemTrustAgent_notEnabledWhenDefaultAgentIsSet, and
serviceBooted_knownAgentsNotSet_enabledAgentsNotUpdated.
Bug: 296464083
Test: atest TrustManagerServiceTest
Change-Id: I6d1baacd38275b3cc9ba583b98ed1b139123ea9b
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 1ebad9b..d2d2a0c 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -75,6 +75,7 @@
import android.view.WindowManagerGlobal;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.PackageMonitor;
import com.android.internal.infra.AndroidFuture;
import com.android.internal.util.DumpUtils;
@@ -1807,6 +1808,11 @@
}
};
+ @VisibleForTesting
+ void waitForIdle() {
+ mHandler.runWithScissors(() -> {}, 0);
+ }
+
private boolean isTrustUsuallyManagedInternal(int userId) {
synchronized (mTrustUsuallyManagedForUser) {
int i = mTrustUsuallyManagedForUser.indexOfKey(userId);
diff --git a/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java
index 9851bc1..c42c735 100644
--- a/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java
@@ -16,24 +16,23 @@
package com.android.server.trust;
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-
import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.argThat;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.anyBoolean;
-
import android.Manifest;
import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.app.admin.DevicePolicyManager;
import android.app.trust.ITrustListener;
import android.app.trust.ITrustManager;
import android.content.BroadcastReceiver;
@@ -45,13 +44,15 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
+import android.content.pm.UserInfo;
import android.net.Uri;
import android.os.Handler;
+import android.os.HandlerThread;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
-import android.os.test.TestLooper;
+import android.os.UserManager;
import android.provider.Settings;
import android.service.trust.TrustAgentService;
import android.testing.TestableContext;
@@ -61,12 +62,11 @@
import androidx.test.core.app.ApplicationProvider;
import com.android.internal.widget.LockPatternUtils;
+import com.android.modules.utils.testing.ExtendedMockitoRule;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.SystemServiceManager;
-import com.google.android.collect.Lists;
-
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
@@ -74,37 +74,60 @@
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
-import org.mockito.MockitoSession;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Random;
+import java.util.Collection;
+import java.util.List;
public class TrustManagerServiceTest {
@Rule
- public MockitoRule mMockitoRule = MockitoJUnit.rule();
+ public final ExtendedMockitoRule mExtendedMockitoRule = new ExtendedMockitoRule.Builder(this)
+ .mockStatic(ServiceManager.class)
+ .mockStatic(WindowManagerGlobal.class)
+ .build();
+
@Rule
public final MockContext mMockContext = new MockContext(
ApplicationProvider.getApplicationContext());
private static final String URI_SCHEME_PACKAGE = "package";
- private static final int TEST_USER_ID = UserHandle.USER_SYSTEM;
+ private static final int TEST_USER_ID = 50;
- private final TestLooper mLooper = new TestLooper();
private final ArrayList<ResolveInfo> mTrustAgentResolveInfoList = new ArrayList<>();
- private final LockPatternUtils mLockPatternUtils = new LockPatternUtils(mMockContext);
- private final TrustManagerService mService = new TrustManagerService(mMockContext);
+ private final ArrayList<ComponentName> mKnownTrustAgents = new ArrayList<>();
+ private final ArrayList<ComponentName> mEnabledTrustAgents = new ArrayList<>();
- @Mock
- private PackageManager mPackageManagerMock;
+ private @Mock ActivityManager mActivityManager;
+ private @Mock DevicePolicyManager mDevicePolicyManager;
+ private @Mock LockPatternUtils mLockPatternUtils;
+ private @Mock PackageManager mPackageManager;
+ private @Mock UserManager mUserManager;
+ private @Mock IWindowManager mWindowManager;
+
+ private HandlerThread mHandlerThread;
+ private TrustManagerService.Injector mInjector;
+ private TrustManagerService mService;
+ private ITrustManager mTrustManager;
@Before
- public void setUp() {
- resetTrustAgentLockSettings();
- LocalServices.addService(SystemServiceManager.class, mock(SystemServiceManager.class));
+ public void setUp() throws Exception {
+ when(mActivityManager.isUserRunning(TEST_USER_ID)).thenReturn(true);
+
+ when(mLockPatternUtils.getDevicePolicyManager()).thenReturn(mDevicePolicyManager);
+ when(mLockPatternUtils.isSecure(TEST_USER_ID)).thenReturn(true);
+ when(mLockPatternUtils.getKnownTrustAgents(TEST_USER_ID)).thenReturn(mKnownTrustAgents);
+ when(mLockPatternUtils.getEnabledTrustAgents(TEST_USER_ID)).thenReturn(mEnabledTrustAgents);
+ doAnswer(invocation -> {
+ mKnownTrustAgents.clear();
+ mKnownTrustAgents.addAll((Collection<ComponentName>) invocation.getArgument(0));
+ return null;
+ }).when(mLockPatternUtils).setKnownTrustAgents(any(), eq(TEST_USER_ID));
+ doAnswer(invocation -> {
+ mEnabledTrustAgents.clear();
+ mEnabledTrustAgents.addAll((Collection<ComponentName>) invocation.getArgument(0));
+ return null;
+ }).when(mLockPatternUtils).setEnabledTrustAgents(any(), eq(TEST_USER_ID));
ArgumentMatcher<Intent> trustAgentIntentMatcher = new ArgumentMatcher<Intent>() {
@Override
@@ -112,17 +135,42 @@
return TrustAgentService.SERVICE_INTERFACE.equals(argument.getAction());
}
};
- when(mPackageManagerMock.queryIntentServicesAsUser(argThat(trustAgentIntentMatcher),
+ when(mPackageManager.queryIntentServicesAsUser(argThat(trustAgentIntentMatcher),
anyInt(), anyInt())).thenReturn(mTrustAgentResolveInfoList);
- when(mPackageManagerMock.checkPermission(any(), any())).thenReturn(
+ when(mPackageManager.checkPermission(any(), any())).thenReturn(
PackageManager.PERMISSION_GRANTED);
- mMockContext.setMockPackageManager(mPackageManagerMock);
+
+ when(mUserManager.getAliveUsers()).thenReturn(
+ List.of(new UserInfo(TEST_USER_ID, "user", UserInfo.FLAG_FULL)));
+
+ when(mWindowManager.isKeyguardLocked()).thenReturn(true);
+
+ mMockContext.addMockSystemService(ActivityManager.class, mActivityManager);
+ mMockContext.setMockPackageManager(mPackageManager);
+ mMockContext.addMockSystemService(UserManager.class, mUserManager);
+ doReturn(mWindowManager).when(() -> WindowManagerGlobal.getWindowManagerService());
+ LocalServices.addService(SystemServiceManager.class, mock(SystemServiceManager.class));
+
+ grantPermission(Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE);
+ grantPermission(Manifest.permission.TRUST_LISTENER);
+
+ mHandlerThread = new HandlerThread("handler");
+ mHandlerThread.start();
+ mInjector = new TrustManagerService.Injector(mLockPatternUtils, mHandlerThread.getLooper());
+ mService = new TrustManagerService(mMockContext, mInjector);
+
+ // Get the ITrustManager from the new TrustManagerService.
+ mService.onStart();
+ ArgumentCaptor<IBinder> binderArgumentCaptor = ArgumentCaptor.forClass(IBinder.class);
+ verify(() -> ServiceManager.addService(eq(Context.TRUST_SERVICE),
+ binderArgumentCaptor.capture(), anyBoolean(), anyInt()));
+ mTrustManager = ITrustManager.Stub.asInterface(binderArgumentCaptor.getValue());
}
@After
public void tearDown() {
- resetTrustAgentLockSettings();
LocalServices.removeServiceForTest(SystemServiceManager.class);
+ mHandlerThread.quit();
}
@Test
@@ -142,10 +190,9 @@
bootService();
- assertThat(mLockPatternUtils.getEnabledTrustAgents(TEST_USER_ID)).containsExactly(
- systemTrustAgent1, systemTrustAgent2);
- assertThat(mLockPatternUtils.getKnownTrustAgents(TEST_USER_ID)).containsExactly(
- systemTrustAgent1, systemTrustAgent2, userTrustAgent1, userTrustAgent2);
+ assertThat(mEnabledTrustAgents).containsExactly(systemTrustAgent1, systemTrustAgent2);
+ assertThat(mKnownTrustAgents).containsExactly(systemTrustAgent1, systemTrustAgent2,
+ userTrustAgent1, userTrustAgent2);
}
@Test
@@ -162,10 +209,8 @@
bootService();
- assertThat(mLockPatternUtils.getEnabledTrustAgents(TEST_USER_ID)).containsExactly(
- defaultTrustAgent);
- assertThat(mLockPatternUtils.getKnownTrustAgents(TEST_USER_ID)).containsExactly(
- systemTrustAgent, defaultTrustAgent);
+ assertThat(mEnabledTrustAgents).containsExactly(defaultTrustAgent);
+ assertThat(mKnownTrustAgents).containsExactly(systemTrustAgent, defaultTrustAgent);
}
@Test
@@ -174,16 +219,16 @@
"com.android/.SystemTrustAgent");
ComponentName trustAgent2 = ComponentName.unflattenFromString(
"com.android/.AnotherSystemTrustAgent");
- initializeEnabledAgents(trustAgent1);
+ mEnabledTrustAgents.add(trustAgent1);
+ Settings.Secure.putIntForUser(mMockContext.getContentResolver(),
+ Settings.Secure.TRUST_AGENTS_INITIALIZED, 1, TEST_USER_ID);
addTrustAgent(trustAgent1, /* isSystemApp= */ true);
addTrustAgent(trustAgent2, /* isSystemApp= */ true);
bootService();
- assertThat(mLockPatternUtils.getEnabledTrustAgents(TEST_USER_ID)).containsExactly(
- trustAgent1);
- assertThat(mLockPatternUtils.getKnownTrustAgents(TEST_USER_ID)).containsExactly(
- trustAgent1, trustAgent2);
+ assertThat(mEnabledTrustAgents).containsExactly(trustAgent1);
+ assertThat(mKnownTrustAgents).containsExactly(trustAgent1, trustAgent2);
}
@Test
@@ -192,17 +237,17 @@
"com.android/.SystemTrustAgent");
ComponentName trustAgent2 = ComponentName.unflattenFromString(
"com.android/.AnotherSystemTrustAgent");
- initializeEnabledAgents(trustAgent1);
- initializeKnownAgents(trustAgent1);
+ Settings.Secure.putIntForUser(mMockContext.getContentResolver(),
+ Settings.Secure.TRUST_AGENTS_INITIALIZED, 1, TEST_USER_ID);
+ Settings.Secure.putIntForUser(mMockContext.getContentResolver(),
+ Settings.Secure.KNOWN_TRUST_AGENTS_INITIALIZED, 1, TEST_USER_ID);
addTrustAgent(trustAgent1, /* isSystemApp= */ true);
addTrustAgent(trustAgent2, /* isSystemApp= */ true);
bootService();
- assertThat(mLockPatternUtils.getEnabledTrustAgents(TEST_USER_ID)).containsExactly(
- trustAgent1, trustAgent2);
- assertThat(mLockPatternUtils.getKnownTrustAgents(TEST_USER_ID)).containsExactly(
- trustAgent1, trustAgent2);
+ assertThat(mEnabledTrustAgents).containsExactly(trustAgent1, trustAgent2);
+ assertThat(mKnownTrustAgents).containsExactly(trustAgent1, trustAgent2);
}
@Test
@@ -214,10 +259,8 @@
mMockContext.sendPackageChangedBroadcast(newAgentComponentName);
- assertThat(mLockPatternUtils.getEnabledTrustAgents(TEST_USER_ID)).containsExactly(
- newAgentComponentName);
- assertThat(mLockPatternUtils.getKnownTrustAgents(TEST_USER_ID)).containsExactly(
- newAgentComponentName);
+ assertThat(mEnabledTrustAgents).containsExactly(newAgentComponentName);
+ assertThat(mKnownTrustAgents).containsExactly(newAgentComponentName);
}
@Test
@@ -235,10 +278,8 @@
mMockContext.sendPackageChangedBroadcast(newAgentComponentName);
- assertThat(mLockPatternUtils.getEnabledTrustAgents(TEST_USER_ID)).containsExactly(
- defaultTrustAgent);
- assertThat(mLockPatternUtils.getKnownTrustAgents(TEST_USER_ID)).containsExactly(
- defaultTrustAgent, newAgentComponentName);
+ assertThat(mEnabledTrustAgents).containsExactly(defaultTrustAgent);
+ assertThat(mKnownTrustAgents).containsExactly(defaultTrustAgent, newAgentComponentName);
}
@Test
@@ -250,9 +291,8 @@
mMockContext.sendPackageChangedBroadcast(newAgentComponentName);
- assertThat(mLockPatternUtils.getEnabledTrustAgents(TEST_USER_ID)).isEmpty();
- assertThat(mLockPatternUtils.getKnownTrustAgents(TEST_USER_ID)).containsExactly(
- newAgentComponentName);
+ assertThat(mEnabledTrustAgents).isEmpty();
+ assertThat(mKnownTrustAgents).containsExactly(newAgentComponentName);
}
@Test
@@ -265,50 +305,21 @@
addTrustAgent(systemTrustAgent2, /* isSystemApp= */ true);
bootService();
// Simulate user turning off systemTrustAgent2
- mLockPatternUtils.setEnabledTrustAgents(Collections.singletonList(systemTrustAgent1),
- TEST_USER_ID);
+ mLockPatternUtils.setEnabledTrustAgents(List.of(systemTrustAgent1), TEST_USER_ID);
mMockContext.sendPackageChangedBroadcast(systemTrustAgent2);
- assertThat(mLockPatternUtils.getEnabledTrustAgents(TEST_USER_ID)).containsExactly(
- systemTrustAgent1);
+ assertThat(mEnabledTrustAgents).containsExactly(systemTrustAgent1);
}
@Test
public void reportEnabledTrustAgentsChangedInformsListener() throws RemoteException {
- final LockPatternUtils utils = mock(LockPatternUtils.class);
- final TrustManagerService service = new TrustManagerService(mMockContext,
- new TrustManagerService.Injector(utils, mLooper.getLooper()));
final ITrustListener trustListener = mock(ITrustListener.class);
- final IWindowManager windowManager = mock(IWindowManager.class);
- final int userId = new Random().nextInt();
-
- mMockContext.getTestablePermissions().setPermission(Manifest.permission.TRUST_LISTENER,
- PERMISSION_GRANTED);
-
- when(utils.getKnownTrustAgents(anyInt())).thenReturn(new ArrayList<>());
-
- MockitoSession mockSession = mockitoSession()
- .initMocks(this)
- .mockStatic(ServiceManager.class)
- .mockStatic(WindowManagerGlobal.class)
- .startMocking();
-
- doReturn(windowManager).when(() -> {
- WindowManagerGlobal.getWindowManagerService();
- });
-
- service.onStart();
- ArgumentCaptor<IBinder> binderArgumentCaptor = ArgumentCaptor.forClass(IBinder.class);
- verify(() -> ServiceManager.addService(eq(Context.TRUST_SERVICE),
- binderArgumentCaptor.capture(), anyBoolean(), anyInt()));
- ITrustManager manager = ITrustManager.Stub.asInterface(binderArgumentCaptor.getValue());
- manager.registerTrustListener(trustListener);
- mLooper.dispatchAll();
- manager.reportEnabledTrustAgentsChanged(userId);
- mLooper.dispatchAll();
- verify(trustListener).onEnabledTrustAgentsChanged(eq(userId));
- mockSession.finishMocking();
+ mTrustManager.registerTrustListener(trustListener);
+ mService.waitForIdle();
+ mTrustManager.reportEnabledTrustAgentsChanged(TEST_USER_ID);
+ mService.waitForIdle();
+ verify(trustListener).onEnabledTrustAgentsChanged(TEST_USER_ID);
}
private void addTrustAgent(ComponentName agentComponentName, boolean isSystemApp) {
@@ -327,27 +338,16 @@
mTrustAgentResolveInfoList.add(resolveInfo);
}
- private void initializeEnabledAgents(ComponentName... enabledAgents) {
- mLockPatternUtils.setEnabledTrustAgents(Lists.newArrayList(enabledAgents), TEST_USER_ID);
- Settings.Secure.putIntForUser(mMockContext.getContentResolver(),
- Settings.Secure.TRUST_AGENTS_INITIALIZED, 1, TEST_USER_ID);
- }
-
- private void initializeKnownAgents(ComponentName... knownAgents) {
- mLockPatternUtils.setKnownTrustAgents(Lists.newArrayList(knownAgents), TEST_USER_ID);
- Settings.Secure.putIntForUser(mMockContext.getContentResolver(),
- Settings.Secure.KNOWN_TRUST_AGENTS_INITIALIZED, 1, TEST_USER_ID);
- }
-
private void bootService() {
mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
mService.onBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
+ mMockContext.sendUserStartedBroadcast();
}
- private void resetTrustAgentLockSettings() {
- mLockPatternUtils.setEnabledTrustAgents(Collections.emptyList(), TEST_USER_ID);
- mLockPatternUtils.setKnownTrustAgents(Collections.emptyList(), TEST_USER_ID);
+ private void grantPermission(String permission) {
+ mMockContext.getTestablePermissions().setPermission(
+ permission, PackageManager.PERMISSION_GRANTED);
}
/** A mock Context that allows the test process to send protected broadcasts. */
@@ -355,6 +355,8 @@
private final ArrayList<BroadcastReceiver> mPackageChangedBroadcastReceivers =
new ArrayList<>();
+ private final ArrayList<BroadcastReceiver> mUserStartedBroadcastReceivers =
+ new ArrayList<>();
MockContext(Context base) {
super(base);
@@ -369,6 +371,9 @@
if (filter.hasAction(Intent.ACTION_PACKAGE_CHANGED)) {
mPackageChangedBroadcastReceivers.add(receiver);
}
+ if (filter.hasAction(Intent.ACTION_USER_STARTED)) {
+ mUserStartedBroadcastReceivers.add(receiver);
+ }
return super.registerReceiverAsUser(receiver, user, filter, broadcastPermission,
scheduler);
}
@@ -386,5 +391,13 @@
receiver.onReceive(this, intent);
}
}
+
+ void sendUserStartedBroadcast() {
+ Intent intent = new Intent(Intent.ACTION_USER_STARTED)
+ .putExtra(Intent.EXTRA_USER_HANDLE, TEST_USER_ID);
+ for (BroadcastReceiver receiver : mUserStartedBroadcastReceivers) {
+ receiver.onReceive(this, intent);
+ }
+ }
}
}