Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 10531da3 authored by Eric Biggers's avatar Eric Biggers
Browse files

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
parent 60b7604d
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -75,6 +75,7 @@ import android.view.IWindowManager;
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 @@ public class TrustManagerService extends SystemService {
        }
    };

    @VisibleForTesting
    void waitForIdle() {
        mHandler.runWithScissors(() -> {}, 0);
    }

    private boolean isTrustUsuallyManagedInternal(int userId) {
        synchronized (mTrustUsuallyManagedForUser) {
            int i = mTrustUsuallyManagedForUser.indexOfKey(userId);
+121 −108
Original line number Diff line number Diff line
@@ -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.ApplicationInfo;
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 android.view.WindowManagerGlobal;
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.junit.Test;
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 @@ public class TrustManagerServiceTest {
                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 @@ public class TrustManagerServiceTest {

        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 @@ public class TrustManagerServiceTest {

        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 @@ public class TrustManagerServiceTest {
                "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 @@ public class TrustManagerServiceTest {
                "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 @@ public class TrustManagerServiceTest {

        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 @@ public class TrustManagerServiceTest {

        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 @@ public class TrustManagerServiceTest {

        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 @@ public class TrustManagerServiceTest {
        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 @@ public class TrustManagerServiceTest {
        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 @@ public class TrustManagerServiceTest {

        private final ArrayList<BroadcastReceiver> mPackageChangedBroadcastReceivers =
                new ArrayList<>();
        private final ArrayList<BroadcastReceiver> mUserStartedBroadcastReceivers =
                new ArrayList<>();

        MockContext(Context base) {
            super(base);
@@ -369,6 +371,9 @@ public class TrustManagerServiceTest {
            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 @@ public class TrustManagerServiceTest {
                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);
            }
        }
    }
}