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

Commit fb3f361d authored by Jason Sun's avatar Jason Sun
Browse files

Auto enable new system trust agents

Previously we only auto enable factory system trust agents when the
devices is booted for the first time. This change added logic to detect
newly installed/enabled trust agents, and enable them if appropriate.

Fixes: b/243705470
Test: atest FrameworksMockingServicesTests:TrustManagerServiceTest
Change-Id: I3c345a44cfcfccc6f7e2507ba37e378b6b16bd98
parent abcf028a
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -7406,6 +7406,13 @@ public final class Settings {
        public static final String TRUST_AGENTS_INITIALIZED =
                "trust_agents_initialized";
        /**
         * Set to 1 by the system after the list of known trust agents have been initialized.
         * @hide
         */
        public static final String KNOWN_TRUST_AGENTS_INITIALIZED =
                "known_trust_agents_initialized";
        /**
         * The Logging ID (a unique 64-bit value) as a hex string.
         * Used as a pseudonymous identifier for logging.
+31 −13
Original line number Diff line number Diff line
@@ -39,7 +39,6 @@ import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
@@ -47,7 +46,6 @@ import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.IStorageManager;
import android.os.storage.StorageManager;
import android.provider.Settings;
import android.text.TextUtils;
@@ -175,6 +173,7 @@ public class LockPatternUtils {
    private static final String LOCK_SCREEN_DEVICE_OWNER_INFO = "lockscreen.device_owner_info";

    private static final String ENABLED_TRUST_AGENTS = "lockscreen.enabledtrustagents";
    private static final String KNOWN_TRUST_AGENTS = "lockscreen.knowntrustagents";
    private static final String IS_TRUST_USUALLY_MANAGED = "lockscreen.istrustusuallymanaged";

    public static final String PROFILE_KEY_NAME_ENCRYPT = "profile_key_name_encrypt_";
@@ -1106,31 +1105,50 @@ public class LockPatternUtils {
        return getString(LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, userId) != null;
    }

    /** Updates the list of enabled trust agent in LockSettings storage for the given user. */
    public void setEnabledTrustAgents(Collection<ComponentName> activeTrustAgents, int userId) {
        setString(ENABLED_TRUST_AGENTS, serializeTrustAgents(activeTrustAgents), userId);
        getTrustManager().reportEnabledTrustAgentsChanged(userId);
    }

    /** Returns the list of enabled trust agent in LockSettings storage for the given user. */
    public List<ComponentName> getEnabledTrustAgents(int userId) {
        return deserializeTrustAgents(getString(ENABLED_TRUST_AGENTS, userId));
    }

    /** Updates the list of known trust agent in LockSettings storage for the given user. */
    public void setKnownTrustAgents(Collection<ComponentName> knownTrustAgents, int userId) {
        setString(KNOWN_TRUST_AGENTS, serializeTrustAgents(knownTrustAgents), userId);
    }

    /** Returns the list of known trust agent in LockSettings storage for the given user. */
    public List<ComponentName> getKnownTrustAgents(int userId) {
        return deserializeTrustAgents(getString(KNOWN_TRUST_AGENTS, userId));
    }

    private String serializeTrustAgents(Collection<ComponentName> trustAgents) {
        StringBuilder sb = new StringBuilder();
        for (ComponentName cn : activeTrustAgents) {
        for (ComponentName cn : trustAgents) {
            if (sb.length() > 0) {
                sb.append(',');
            }
            sb.append(cn.flattenToShortString());
        }
        setString(ENABLED_TRUST_AGENTS, sb.toString(), userId);
        getTrustManager().reportEnabledTrustAgentsChanged(userId);
        return sb.toString();
    }

    public List<ComponentName> getEnabledTrustAgents(int userId) {
        String serialized = getString(ENABLED_TRUST_AGENTS, userId);
        if (TextUtils.isEmpty(serialized)) {
            return new ArrayList<ComponentName>();
    private List<ComponentName> deserializeTrustAgents(String serializedTrustAgents) {
        if (TextUtils.isEmpty(serializedTrustAgents)) {
            return new ArrayList<>();
        }
        String[] split = serialized.split(",");
        ArrayList<ComponentName> activeTrustAgents = new ArrayList<ComponentName>(split.length);
        String[] split = serializedTrustAgents.split(",");
        ArrayList<ComponentName> trustAgents = new ArrayList<>(split.length);
        for (String s : split) {
            if (!TextUtils.isEmpty(s)) {
                activeTrustAgents.add(ComponentName.unflattenFromString(s));
                trustAgents.add(ComponentName.unflattenFromString(s));
            }
        }
        return activeTrustAgents;
        return trustAgents;
    }

    /**
+58 −6
Original line number Diff line number Diff line
@@ -19,14 +19,15 @@ package com.android.internal.util;
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_MANAGED;
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;

import static org.junit.Assert.assertEquals;
import static com.google.common.truth.Truth.assertThat;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -51,8 +52,11 @@ import com.android.internal.widget.IWeakEscrowTokenActivatedListener;
import com.android.internal.widget.IWeakEscrowTokenRemovedListener;
import com.android.internal.widget.LockPatternUtils;

import com.google.android.collect.Lists;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;

import java.nio.charset.StandardCharsets;
@@ -172,13 +176,61 @@ public class LockPatternUtilsTest {
    }

    @Test
    public void testGetEnabledTrustAgentsNotNull() throws RemoteException {
    public void testSetEnabledTrustAgents() throws RemoteException {
        int testUserId = 10;
        ILockSettings ils = createTestLockSettings();
        when(ils.getString(anyString(), any(), anyInt())).thenReturn("");
        ArgumentCaptor<String> valueCaptor = ArgumentCaptor.forClass(String.class);
        doNothing().when(ils).setString(anyString(), valueCaptor.capture(), anyInt());
        List<ComponentName> enabledTrustAgents = Lists.newArrayList(
                ComponentName.unflattenFromString("com.android/.TrustAgent"),
                ComponentName.unflattenFromString("com.test/.TestAgent"));

        mLockPatternUtils.setEnabledTrustAgents(enabledTrustAgents, testUserId);

        assertThat(valueCaptor.getValue()).isEqualTo("com.android/.TrustAgent,com.test/.TestAgent");
    }

    @Test
    public void testGetEnabledTrustAgents() throws RemoteException {
        int testUserId = 10;
        ILockSettings ils = createTestLockSettings();
        when(ils.getString(anyString(), any(), anyInt())).thenReturn(
                "com.android/.TrustAgent,com.test/.TestAgent");

        List<ComponentName> trustAgents = mLockPatternUtils.getEnabledTrustAgents(testUserId);
        assertNotNull(trustAgents);
        assertEquals(0, trustAgents.size());

        assertThat(trustAgents).containsExactly(
                ComponentName.unflattenFromString("com.android/.TrustAgent"),
                ComponentName.unflattenFromString("com.test/.TestAgent"));
    }

    @Test
    public void testSetKnownTrustAgents() throws RemoteException {
        int testUserId = 10;
        ILockSettings ils = createTestLockSettings();
        ArgumentCaptor<String> valueCaptor = ArgumentCaptor.forClass(String.class);
        doNothing().when(ils).setString(anyString(), valueCaptor.capture(), anyInt());
        List<ComponentName> knownTrustAgents = Lists.newArrayList(
                ComponentName.unflattenFromString("com.android/.TrustAgent"),
                ComponentName.unflattenFromString("com.test/.TestAgent"));

        mLockPatternUtils.setKnownTrustAgents(knownTrustAgents, testUserId);

        assertThat(valueCaptor.getValue()).isEqualTo("com.android/.TrustAgent,com.test/.TestAgent");
    }

    @Test
    public void testGetKnownTrustAgents() throws RemoteException {
        int testUserId = 10;
        ILockSettings ils = createTestLockSettings();
        when(ils.getString(anyString(), any(), anyInt())).thenReturn(
                "com.android/.TrustAgent,com.test/.TestAgent");

        List<ComponentName> trustAgents = mLockPatternUtils.getKnownTrustAgents(testUserId);

        assertThat(trustAgents).containsExactly(
                ComponentName.unflattenFromString("com.android/.TrustAgent"),
                ComponentName.unflattenFromString("com.test/.TestAgent"));
    }

    private ILockSettings createTestLockSettings() {
+1 −0
Original line number Diff line number Diff line
@@ -780,6 +780,7 @@ public class SettingsBackupTest {
                 Settings.Secure.SMS_DEFAULT_APPLICATION,
                 Settings.Secure.SPELL_CHECKER_ENABLED,  // Intentionally removed in Q
                 Settings.Secure.TRUST_AGENTS_INITIALIZED,
                 Settings.Secure.KNOWN_TRUST_AGENTS_INITIALIZED,
                 Settings.Secure.TV_APP_USES_NON_SYSTEM_INPUTS,
                 Settings.Secure.TV_INPUT_CUSTOM_LABELS,
                 Settings.Secure.TV_INPUT_HIDDEN_INPUTS,
+94 −8
Original line number Diff line number Diff line
@@ -93,6 +93,7 @@ import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;


@@ -254,6 +255,7 @@ public class TrustManagerService extends SystemService {
            return;
        }
        if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
            checkNewAgents();
            mPackageMonitor.register(mContext, mHandler.getLooper(), UserHandle.ALL, true);
            mReceiver.register(mContext);
            mLockPatternUtils.registerStrongAuthTracker(mStrongAuthTracker);
@@ -262,7 +264,7 @@ public class TrustManagerService extends SystemService {
            refreshAgentList(UserHandle.USER_ALL);
            refreshDeviceLockedForUser(UserHandle.USER_ALL);
        } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
            maybeEnableFactoryTrustAgents(mLockPatternUtils, UserHandle.USER_SYSTEM);
            maybeEnableFactoryTrustAgents(UserHandle.USER_SYSTEM);
        }
    }

@@ -1083,7 +1085,7 @@ public class TrustManagerService extends SystemService {
        return new ComponentName(resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name);
    }

    private void maybeEnableFactoryTrustAgents(LockPatternUtils utils, int userId) {
    private void maybeEnableFactoryTrustAgents(int userId) {
        if (0 != Settings.Secure.getIntForUser(mContext.getContentResolver(),
                Settings.Secure.TRUST_AGENTS_INITIALIZED, 0, userId)) {
            return;
@@ -1100,8 +1102,7 @@ public class TrustManagerService extends SystemService {
        } else { // A default agent is not set; perform regular trust agent discovery
            for (ResolveInfo resolveInfo : resolveInfos) {
                ComponentName componentName = getComponentName(resolveInfo);
                int applicationInfoFlags = resolveInfo.serviceInfo.applicationInfo.flags;
                if ((applicationInfoFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
                if (!isSystemTrustAgent(resolveInfo)) {
                    Log.i(TAG, "Leaving agent " + componentName + " disabled because package "
                            + "is not a system package.");
                    continue;
@@ -1110,13 +1111,88 @@ public class TrustManagerService extends SystemService {
            }
        }

        List<ComponentName> previouslyEnabledAgents = utils.getEnabledTrustAgents(userId);
        discoveredAgents.addAll(previouslyEnabledAgents);
        utils.setEnabledTrustAgents(discoveredAgents, userId);
        enableNewAgents(discoveredAgents, userId);
        Settings.Secure.putIntForUser(mContext.getContentResolver(),
                Settings.Secure.TRUST_AGENTS_INITIALIZED, 1, userId);
    }

    private void checkNewAgents() {
        for (UserInfo userInfo : mUserManager.getAliveUsers()) {
            checkNewAgentsForUser(userInfo.id);
        }
    }

    /**
     * Checks for any new trust agents that become available after the first boot, add them to the
     * list of known agents, and enable them if they should be enabled by default.
     */
    private void checkNewAgentsForUser(int userId) {
        // When KNOWN_TRUST_AGENTS_INITIALIZED is not set, only update the known agent list but do
        // not enable any agent.
        // These agents will be enabled by #maybeEnableFactoryTrustAgents if this is the first time
        // that this device boots and TRUST_AGENTS_INITIALIZED is not already set.
        // Otherwise, these agents may have been manually disabled by the user, and we should not
        // re-enable them.
        if (0 == Settings.Secure.getIntForUser(mContext.getContentResolver(),
                Settings.Secure.KNOWN_TRUST_AGENTS_INITIALIZED, 0, userId)) {
            initializeKnownAgents(userId);
            return;
        }

        List<ComponentName> knownAgents = mLockPatternUtils.getKnownTrustAgents(userId);
        List<ResolveInfo> agentInfoList = resolveAllowedTrustAgents(mContext.getPackageManager(),
                userId);
        ArraySet<ComponentName> newAgents = new ArraySet<>(agentInfoList.size());
        ArraySet<ComponentName> newSystemAgents = new ArraySet<>(agentInfoList.size());

        for (ResolveInfo agentInfo : agentInfoList) {
            ComponentName agentComponentName = getComponentName(agentInfo);
            if (knownAgents.contains(agentComponentName)) {
                continue;
            }
            newAgents.add(agentComponentName);
            if (isSystemTrustAgent(agentInfo)) {
                newSystemAgents.add(agentComponentName);
            }
        }

        if (newAgents.isEmpty()) {
            return;
        }

        ArraySet<ComponentName> updatedKnowAgents = new ArraySet<>(knownAgents);
        updatedKnowAgents.addAll(newAgents);
        mLockPatternUtils.setKnownTrustAgents(updatedKnowAgents, userId);

        // Do not auto enable new trust agents when the default agent is set
        boolean hasDefaultAgent = getDefaultFactoryTrustAgent(mContext) != null;
        if (!hasDefaultAgent) {
            enableNewAgents(newSystemAgents, userId);
        }
    }

    private void enableNewAgents(Collection<ComponentName> agents, int userId) {
        if (agents.isEmpty()) {
            return;
        }

        ArraySet<ComponentName> agentsToEnable = new ArraySet<>(agents);
        agentsToEnable.addAll(mLockPatternUtils.getEnabledTrustAgents(userId));
        mLockPatternUtils.setEnabledTrustAgents(agentsToEnable, userId);
    }

    private void initializeKnownAgents(int userId) {
        List<ResolveInfo> agentInfoList = resolveAllowedTrustAgents(mContext.getPackageManager(),
                userId);
        ArraySet<ComponentName> agentComponentNames = new ArraySet<>(agentInfoList.size());
        for (ResolveInfo agentInfo : agentInfoList) {
            agentComponentNames.add(getComponentName(agentInfo));
        }
        mLockPatternUtils.setKnownTrustAgents(agentComponentNames, userId);
        Settings.Secure.putIntForUser(mContext.getContentResolver(),
                Settings.Secure.KNOWN_TRUST_AGENTS_INITIALIZED, 1, userId);
    }

    /**
     * Returns the {@link ComponentName} for the default trust agent, or {@code null} if there
     * is no trust agent set.
@@ -1152,6 +1228,10 @@ public class TrustManagerService extends SystemService {
        return allowedAgents;
    }

    private static boolean isSystemTrustAgent(ResolveInfo agentInfo) {
        return (agentInfo.serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
    }

    // Agent dispatch and aggregation

    private boolean aggregateIsTrusted(int userId) {
@@ -1825,8 +1905,14 @@ public class TrustManagerService extends SystemService {
            refreshAgentList(UserHandle.USER_ALL);
        }

        @Override
        public void onPackageAdded(String packageName, int uid) {
            checkNewAgentsForUser(UserHandle.getUserId(uid));
        }

        @Override
        public boolean onPackageChanged(String packageName, int uid, String[] components) {
            checkNewAgentsForUser(UserHandle.getUserId(uid));
            // We're interested in all changes, even if just some components get enabled / disabled.
            return true;
        }
@@ -1861,7 +1947,7 @@ public class TrustManagerService extends SystemService {
                    action)) {
                int userId = getUserId(intent);
                if (userId > 0) {
                    maybeEnableFactoryTrustAgents(mLockPatternUtils, userId);
                    maybeEnableFactoryTrustAgents(userId);
                }
            } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
                int userId = getUserId(intent);
Loading