FileDocCategorySizeDatePackage
TrustManagerService.javaAPI DocAndroid 5.1 API35951Thu Mar 12 22:22:42 GMT 2015com.android.server.trust

TrustManagerService

public class TrustManagerService extends com.android.server.SystemService
Manages trust agents and trust listeners. It is responsible for binding to the enabled {@link android.service.trust.TrustAgentService}s of each user and notifies them about events that are relevant to them. It start and stops them based on the value of {@link com.android.internal.widget.LockPatternUtils#getEnabledTrustAgents(int)}. It also keeps a set of {@link android.app.trust.ITrustListener}s that are notified whenever the trust state changes for any user. Trust state and the setting of enabled agents is kept per user and each user has its own instance of a {@link android.service.trust.TrustAgentService}.

Fields Summary
private static final boolean
DEBUG
private static final String
TAG
private static final android.content.Intent
TRUST_AGENT_INTENT
private static final String
PERMISSION_PROVIDE_AGENT
private static final int
MSG_REGISTER_LISTENER
private static final int
MSG_UNREGISTER_LISTENER
private static final int
MSG_DISPATCH_UNLOCK_ATTEMPT
private static final int
MSG_ENABLED_AGENTS_CHANGED
private static final int
MSG_REQUIRE_CREDENTIAL_ENTRY
private static final int
MSG_KEYGUARD_SHOWING_CHANGED
private static final int
MSG_START_USER
private static final int
MSG_CLEANUP_USER
private static final int
MSG_SWITCH_USER
private final android.util.ArraySet
mActiveAgents
private final ArrayList
mTrustListeners
private final Receiver
mReceiver
private final android.util.SparseBooleanArray
mUserHasAuthenticatedSinceBoot
final TrustArchive
mArchive
private final android.content.Context
mContext
private final com.android.internal.widget.LockPatternUtils
mLockPatternUtils
private final android.os.UserManager
mUserManager
private final android.app.ActivityManager
mActivityManager
private final android.util.SparseBooleanArray
mUserIsTrusted
private final android.util.SparseBooleanArray
mDeviceLockedForUser
private boolean
mTrustAgentsCanRun
private int
mCurrentUser
private final android.os.IBinder
mService
private final android.os.Handler
mHandler
private final com.android.internal.content.PackageMonitor
mPackageMonitor
Constructors Summary
public TrustManagerService(android.content.Context context)


       
        super(context);
        mContext = context;
        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
        mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
        mLockPatternUtils = new LockPatternUtils(context);
    
Methods Summary
private voidaddListener(android.app.trust.ITrustListener listener)

        for (int i = 0; i < mTrustListeners.size(); i++) {
            if (mTrustListeners.get(i).asBinder() == listener.asBinder()) {
                return;
            }
        }
        mTrustListeners.add(listener);
        updateTrustAll();
    
private booleanaggregateIsTrustManaged(int userId)

        if (!mUserHasAuthenticatedSinceBoot.get(userId)) {
            return false;
        }
        for (int i = 0; i < mActiveAgents.size(); i++) {
            AgentInfo info = mActiveAgents.valueAt(i);
            if (info.userId == userId) {
                if (info.agent.isManagingTrust()) {
                    return true;
                }
            }
        }
        return false;
    
private booleanaggregateIsTrusted(int userId)

        if (!mUserHasAuthenticatedSinceBoot.get(userId)) {
            return false;
        }
        for (int i = 0; i < mActiveAgents.size(); i++) {
            AgentInfo info = mActiveAgents.valueAt(i);
            if (info.userId == userId) {
                if (info.agent.isTrusted()) {
                    return true;
                }
            }
        }
        return false;
    
private voiddispatchDeviceLocked(int userId, boolean isLocked)

        for (int i = 0; i < mActiveAgents.size(); i++) {
            AgentInfo agent = mActiveAgents.valueAt(i);
            if (agent.userId == userId) {
                if (isLocked) {
                    agent.agent.onDeviceLocked();
                } else{
                    agent.agent.onDeviceUnlocked();
                }
            }
        }
    
private voiddispatchOnTrustChanged(boolean enabled, int userId, boolean initiatedByUser)

        if (!enabled) initiatedByUser = false;
        for (int i = 0; i < mTrustListeners.size(); i++) {
            try {
                mTrustListeners.get(i).onTrustChanged(enabled, userId, initiatedByUser);
            } catch (DeadObjectException e) {
                Slog.d(TAG, "Removing dead TrustListener.");
                mTrustListeners.remove(i);
                i--;
            } catch (RemoteException e) {
                Slog.e(TAG, "Exception while notifying TrustListener.", e);
            }
        }
    
private voiddispatchOnTrustManagedChanged(boolean managed, int userId)

        for (int i = 0; i < mTrustListeners.size(); i++) {
            try {
                mTrustListeners.get(i).onTrustManagedChanged(managed, userId);
            } catch (DeadObjectException e) {
                Slog.d(TAG, "Removing dead TrustListener.");
                mTrustListeners.remove(i);
                i--;
            } catch (RemoteException e) {
                Slog.e(TAG, "Exception while notifying TrustListener.", e);
            }
        }
    
private voiddispatchUnlockAttempt(boolean successful, int userId)

        for (int i = 0; i < mActiveAgents.size(); i++) {
            AgentInfo info = mActiveAgents.valueAt(i);
            if (info.userId == userId) {
                info.agent.onUnlockAttempt(successful);
            }
        }

        if (successful) {
            updateUserHasAuthenticated(userId);
        }
    
private android.content.ComponentNamegetComponentName(android.content.pm.ResolveInfo resolveInfo)

        if (resolveInfo == null || resolveInfo.serviceInfo == null) return null;
        return new ComponentName(resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name);
    
private android.content.ComponentNamegetSettingsComponentName(android.content.pm.PackageManager pm, android.content.pm.ResolveInfo resolveInfo)

        if (resolveInfo == null || resolveInfo.serviceInfo == null
                || resolveInfo.serviceInfo.metaData == null) return null;
        String cn = null;
        XmlResourceParser parser = null;
        Exception caughtException = null;
        try {
            parser = resolveInfo.serviceInfo.loadXmlMetaData(pm,
                    TrustAgentService.TRUST_AGENT_META_DATA);
            if (parser == null) {
                Slog.w(TAG, "Can't find " + TrustAgentService.TRUST_AGENT_META_DATA + " meta-data");
                return null;
            }
            Resources res = pm.getResourcesForApplication(resolveInfo.serviceInfo.applicationInfo);
            AttributeSet attrs = Xml.asAttributeSet(parser);
            int type;
            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                    && type != XmlPullParser.START_TAG) {
                // Drain preamble.
            }
            String nodeName = parser.getName();
            if (!"trust-agent".equals(nodeName)) {
                Slog.w(TAG, "Meta-data does not start with trust-agent tag");
                return null;
            }
            TypedArray sa = res
                    .obtainAttributes(attrs, com.android.internal.R.styleable.TrustAgent);
            cn = sa.getString(com.android.internal.R.styleable.TrustAgent_settingsActivity);
            sa.recycle();
        } catch (PackageManager.NameNotFoundException e) {
            caughtException = e;
        } catch (IOException e) {
            caughtException = e;
        } catch (XmlPullParserException e) {
            caughtException = e;
        } finally {
            if (parser != null) parser.close();
        }
        if (caughtException != null) {
            Slog.w(TAG, "Error parsing : " + resolveInfo.serviceInfo.packageName, caughtException);
            return null;
        }
        if (cn == null) {
            return null;
        }
        if (cn.indexOf('/") < 0) {
            cn = resolveInfo.serviceInfo.packageName + "/" + cn;
        }
        return ComponentName.unflattenFromString(cn);
    
booleanisDeviceLockedInner(int userId)

        synchronized (mDeviceLockedForUser) {
            return mDeviceLockedForUser.get(userId, true);
        }
    
private voidmaybeEnableFactoryTrustAgents(com.android.internal.widget.LockPatternUtils utils, int userId)

        if (0 != Settings.Secure.getIntForUser(mContext.getContentResolver(),
                Settings.Secure.TRUST_AGENTS_INITIALIZED, 0, userId)) {
            return;
        }
        PackageManager pm = mContext.getPackageManager();
        List<ResolveInfo> resolveInfos = resolveAllowedTrustAgents(pm, userId);
        ArraySet<ComponentName> discoveredAgents = new ArraySet<>();
        for (ResolveInfo resolveInfo : resolveInfos) {
            ComponentName componentName = getComponentName(resolveInfo);
            int applicationInfoFlags = resolveInfo.serviceInfo.applicationInfo.flags;
            if ((applicationInfoFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
                Log.i(TAG, "Leaving agent " + componentName + " disabled because package "
                        + "is not a system package.");
                continue;
            }
            discoveredAgents.add(componentName);
        }

        List<ComponentName> previouslyEnabledAgents = utils.getEnabledTrustAgents(userId);
        if (previouslyEnabledAgents != null) {
            discoveredAgents.addAll(previouslyEnabledAgents);
        }
        utils.setEnabledTrustAgents(discoveredAgents, userId);
        Settings.Secure.putIntForUser(mContext.getContentResolver(),
                Settings.Secure.TRUST_AGENTS_INITIALIZED, 1, userId);
    
public voidonBootPhase(int phase)

        if (isSafeMode()) {
            // No trust agents in safe mode.
            return;
        }
        if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
            mPackageMonitor.register(mContext, mHandler.getLooper(), UserHandle.ALL, true);
            mReceiver.register(mContext);
        } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
            mTrustAgentsCanRun = true;
            refreshAgentList(UserHandle.USER_ALL);
        } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
            maybeEnableFactoryTrustAgents(mLockPatternUtils, UserHandle.USER_OWNER);
        }
    
public voidonCleanupUser(int userId)

        mHandler.obtainMessage(MSG_CLEANUP_USER, userId, 0, null).sendToTarget();
    
public voidonStart()

        publishBinderService(Context.TRUST_SERVICE, mService);
    
public voidonStartUser(int userId)

        mHandler.obtainMessage(MSG_START_USER, userId, 0, null).sendToTarget();
    
public voidonSwitchUser(int userId)

        mHandler.obtainMessage(MSG_SWITCH_USER, userId, 0, null).sendToTarget();
    
voidrefreshAgentList(int userId)

        if (DEBUG) Slog.d(TAG, "refreshAgentList()");
        if (!mTrustAgentsCanRun) {
            return;
        }
        if (userId != UserHandle.USER_ALL && userId < UserHandle.USER_OWNER) {
            Log.e(TAG, "refreshAgentList(userId=" + userId + "): Invalid user handle,"
                    + " must be USER_ALL or a specific user.", new Throwable("here"));
            userId = UserHandle.USER_ALL;
        }
        PackageManager pm = mContext.getPackageManager();

        List<UserInfo> userInfos;
        if (userId == UserHandle.USER_ALL) {
            userInfos = mUserManager.getUsers(true /* excludeDying */);
        } else {
            userInfos = new ArrayList<>();
            userInfos.add(mUserManager.getUserInfo(userId));
        }
        LockPatternUtils lockPatternUtils = mLockPatternUtils;

        ArraySet<AgentInfo> obsoleteAgents = new ArraySet<>();
        obsoleteAgents.addAll(mActiveAgents);

        for (UserInfo userInfo : userInfos) {
            if (userInfo == null || userInfo.partial || !userInfo.isEnabled()
                    || userInfo.guestToRemove) continue;
            if (!userInfo.supportsSwitchTo()) continue;
            if (!mActivityManager.isUserRunning(userInfo.id)) continue;
            if (!lockPatternUtils.isSecure(userInfo.id)) continue;
            if (!mUserHasAuthenticatedSinceBoot.get(userInfo.id)) continue;
            DevicePolicyManager dpm = lockPatternUtils.getDevicePolicyManager();
            int disabledFeatures = dpm.getKeyguardDisabledFeatures(null, userInfo.id);
            final boolean disableTrustAgents =
                    (disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0;

            List<ComponentName> enabledAgents = lockPatternUtils.getEnabledTrustAgents(userInfo.id);
            if (enabledAgents == null) {
                continue;
            }
            List<ResolveInfo> resolveInfos = resolveAllowedTrustAgents(pm, userInfo.id);
            for (ResolveInfo resolveInfo : resolveInfos) {
                ComponentName name = getComponentName(resolveInfo);

                if (!enabledAgents.contains(name)) continue;
                if (disableTrustAgents) {
                    List<PersistableBundle> config =
                            dpm.getTrustAgentConfiguration(null /* admin */, name, userInfo.id);
                    // Disable agent if no features are enabled.
                    if (config == null || config.isEmpty()) continue;
                }

                AgentInfo agentInfo = new AgentInfo();
                agentInfo.component = name;
                agentInfo.userId = userInfo.id;
                if (!mActiveAgents.contains(agentInfo)) {
                    agentInfo.label = resolveInfo.loadLabel(pm);
                    agentInfo.icon = resolveInfo.loadIcon(pm);
                    agentInfo.settings = getSettingsComponentName(pm, resolveInfo);
                    agentInfo.agent = new TrustAgentWrapper(mContext, this,
                            new Intent().setComponent(name), userInfo.getUserHandle());
                    mActiveAgents.add(agentInfo);
                } else {
                    obsoleteAgents.remove(agentInfo);
                }
            }
        }

        boolean trustMayHaveChanged = false;
        for (int i = 0; i < obsoleteAgents.size(); i++) {
            AgentInfo info = obsoleteAgents.valueAt(i);
            if (userId == UserHandle.USER_ALL || userId == info.userId) {
                if (info.agent.isManagingTrust()) {
                    trustMayHaveChanged = true;
                }
                info.agent.destroy();
                mActiveAgents.remove(info);
            }
        }

        if (trustMayHaveChanged) {
            if (userId == UserHandle.USER_ALL) {
                updateTrustAll();
            } else {
                updateTrust(userId, false /* initiatedByUser */);
            }
        }
    
private voidrefreshDeviceLockedForUser(int userId)

        if (userId != UserHandle.USER_ALL && userId < UserHandle.USER_OWNER) {
            Log.e(TAG, "refreshDeviceLockedForUser(userId=" + userId + "): Invalid user handle,"
                    + " must be USER_ALL or a specific user.", new Throwable("here"));
            userId = UserHandle.USER_ALL;
        }

        List<UserInfo> userInfos;
        if (userId == UserHandle.USER_ALL) {
            userInfos = mUserManager.getUsers(true /* excludeDying */);
        } else {
            userInfos = new ArrayList<>();
            userInfos.add(mUserManager.getUserInfo(userId));
        }

        IWindowManager wm = WindowManagerGlobal.getWindowManagerService();

        for (int i = 0; i < userInfos.size(); i++) {
            UserInfo info = userInfos.get(i);

            if (info == null || info.partial || !info.isEnabled() || info.guestToRemove
                    || !info.supportsSwitchTo()) {
                continue;
            }

            int id = info.id;
            boolean secure = mLockPatternUtils.isSecure(id);
            boolean trusted = aggregateIsTrusted(id);
            boolean showingKeyguard = true;
            if (mCurrentUser == id) {
                try {
                    showingKeyguard = wm.isKeyguardLocked();
                } catch (RemoteException e) {
                }
            }
            boolean deviceLocked = secure && showingKeyguard && !trusted;

            boolean changed;
            synchronized (mDeviceLockedForUser) {
                changed = isDeviceLockedInner(id) != deviceLocked;
                mDeviceLockedForUser.put(id, deviceLocked);
            }
            if (changed) {
                dispatchDeviceLocked(id, deviceLocked);
            }
        }
    
private voidremoveAgentsOfPackage(java.lang.String packageName)

        boolean trustMayHaveChanged = false;
        for (int i = mActiveAgents.size() - 1; i >= 0; i--) {
            AgentInfo info = mActiveAgents.valueAt(i);
            if (packageName.equals(info.component.getPackageName())) {
                Log.i(TAG, "Resetting agent " + info.component.flattenToShortString());
                if (info.agent.isManagingTrust()) {
                    trustMayHaveChanged = true;
                }
                info.agent.destroy();
                mActiveAgents.removeAt(i);
            }
        }
        if (trustMayHaveChanged) {
            updateTrustAll();
        }
    
private voidremoveListener(android.app.trust.ITrustListener listener)

        for (int i = 0; i < mTrustListeners.size(); i++) {
            if (mTrustListeners.get(i).asBinder() == listener.asBinder()) {
                mTrustListeners.remove(i);
                return;
            }
        }
    
private voidrequireCredentialEntry(int userId)

        if (userId == UserHandle.USER_ALL) {
            mUserHasAuthenticatedSinceBoot.clear();
            refreshAgentList(UserHandle.USER_ALL);
        } else {
            mUserHasAuthenticatedSinceBoot.put(userId, false);
            refreshAgentList(userId);
        }
    
public voidresetAgent(android.content.ComponentName name, int userId)

        boolean trustMayHaveChanged = false;
        for (int i = mActiveAgents.size() - 1; i >= 0; i--) {
            AgentInfo info = mActiveAgents.valueAt(i);
            if (name.equals(info.component) && userId == info.userId) {
                Log.i(TAG, "Resetting agent " + info.component.flattenToShortString());
                if (info.agent.isManagingTrust()) {
                    trustMayHaveChanged = true;
                }
                info.agent.destroy();
                mActiveAgents.removeAt(i);
            }
        }
        if (trustMayHaveChanged) {
            updateTrust(userId, false);
        }
        refreshAgentList(userId);
    
private java.util.ListresolveAllowedTrustAgents(android.content.pm.PackageManager pm, int userId)

        List<ResolveInfo> resolveInfos = pm.queryIntentServicesAsUser(TRUST_AGENT_INTENT,
                0 /* flags */, userId);
        ArrayList<ResolveInfo> allowedAgents = new ArrayList<>(resolveInfos.size());
        for (ResolveInfo resolveInfo : resolveInfos) {
            if (resolveInfo.serviceInfo == null) continue;
            if (resolveInfo.serviceInfo.applicationInfo == null) continue;
            String packageName = resolveInfo.serviceInfo.packageName;
            if (pm.checkPermission(PERMISSION_PROVIDE_AGENT, packageName)
                    != PackageManager.PERMISSION_GRANTED) {
                ComponentName name = getComponentName(resolveInfo);
                Log.w(TAG, "Skipping agent " + name + " because package does not have"
                        + " permission " + PERMISSION_PROVIDE_AGENT + ".");
                continue;
            }
            allowedAgents.add(resolveInfo);
        }
        return allowedAgents;
    
private intresolveProfileParent(int userId)


        
        long identity = Binder.clearCallingIdentity();
        try {
            UserInfo parent = mUserManager.getProfileParent(userId);
            if (parent != null) {
                return parent.getUserHandle().getIdentifier();
            }
            return userId;
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    
voidupdateDevicePolicyFeatures()

        for (int i = 0; i < mActiveAgents.size(); i++) {
            AgentInfo info = mActiveAgents.valueAt(i);
            if (info.agent.isConnected()) {
                info.agent.updateDevicePolicyFeatures();
            }
        }
    
public voidupdateTrust(int userId, boolean initiatedByUser)

        dispatchOnTrustManagedChanged(aggregateIsTrustManaged(userId), userId);
        boolean trusted = aggregateIsTrusted(userId);
        boolean changed;
        synchronized (mUserIsTrusted) {
            changed = mUserIsTrusted.get(userId) != trusted;
            mUserIsTrusted.put(userId, trusted);
        }
        dispatchOnTrustChanged(trusted, userId, initiatedByUser);
        if (changed) {
            refreshDeviceLockedForUser(userId);
        }
    
private voidupdateTrustAll()

        List<UserInfo> userInfos = mUserManager.getUsers(true /* excludeDying */);
        for (UserInfo userInfo : userInfos) {
            updateTrust(userInfo.id, false);
        }
    
private voidupdateUserHasAuthenticated(int userId)

        if (!mUserHasAuthenticatedSinceBoot.get(userId)) {
            mUserHasAuthenticatedSinceBoot.put(userId, true);
            refreshAgentList(userId);
        }