TrustManagerService.java revision bcd076525ccb8a3dfe7d1002bcae059661c1d111
1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package com.android.server.trust;
18
19import com.android.internal.annotations.GuardedBy;
20import com.android.internal.content.PackageMonitor;
21import com.android.internal.widget.LockPatternUtils;
22import com.android.server.SystemService;
23
24import org.xmlpull.v1.XmlPullParser;
25import org.xmlpull.v1.XmlPullParserException;
26
27import android.Manifest;
28import android.app.ActivityManager;
29import android.app.ActivityManagerNative;
30import android.app.admin.DevicePolicyManager;
31import android.app.trust.ITrustListener;
32import android.app.trust.ITrustManager;
33import android.content.BroadcastReceiver;
34import android.content.ComponentName;
35import android.content.Context;
36import android.content.Intent;
37import android.content.IntentFilter;
38import android.content.pm.ApplicationInfo;
39import android.content.pm.PackageManager;
40import android.content.pm.ResolveInfo;
41import android.content.pm.UserInfo;
42import android.content.res.Resources;
43import android.content.res.TypedArray;
44import android.content.res.XmlResourceParser;
45import android.graphics.drawable.Drawable;
46import android.os.Binder;
47import android.os.DeadObjectException;
48import android.os.Handler;
49import android.os.IBinder;
50import android.os.Message;
51import android.os.RemoteException;
52import android.os.SystemClock;
53import android.os.UserHandle;
54import android.os.UserManager;
55import android.provider.Settings;
56import android.service.trust.TrustAgentService;
57import android.util.ArraySet;
58import android.util.AttributeSet;
59import android.util.Log;
60import android.util.Slog;
61import android.util.SparseBooleanArray;
62import android.util.Xml;
63
64import java.io.FileDescriptor;
65import java.io.IOException;
66import java.io.PrintWriter;
67import java.util.ArrayList;
68import java.util.List;
69
70/**
71 * Manages trust agents and trust listeners.
72 *
73 * It is responsible for binding to the enabled {@link android.service.trust.TrustAgentService}s
74 * of each user and notifies them about events that are relevant to them.
75 * It start and stops them based on the value of
76 * {@link com.android.internal.widget.LockPatternUtils#getEnabledTrustAgents(int)}.
77 *
78 * It also keeps a set of {@link android.app.trust.ITrustListener}s that are notified whenever the
79 * trust state changes for any user.
80 *
81 * Trust state and the setting of enabled agents is kept per user and each user has its own
82 * instance of a {@link android.service.trust.TrustAgentService}.
83 */
84public class TrustManagerService extends SystemService {
85
86    private static final boolean DEBUG = false;
87    private static final String TAG = "TrustManagerService";
88
89    private static final Intent TRUST_AGENT_INTENT =
90            new Intent(TrustAgentService.SERVICE_INTERFACE);
91    private static final String PERMISSION_PROVIDE_AGENT = Manifest.permission.PROVIDE_TRUST_AGENT;
92
93    private static final int MSG_REGISTER_LISTENER = 1;
94    private static final int MSG_UNREGISTER_LISTENER = 2;
95    private static final int MSG_DISPATCH_UNLOCK_ATTEMPT = 3;
96    private static final int MSG_ENABLED_AGENTS_CHANGED = 4;
97    private static final int MSG_REQUIRE_CREDENTIAL_ENTRY = 5;
98
99    private final ArraySet<AgentInfo> mActiveAgents = new ArraySet<AgentInfo>();
100    private final ArrayList<ITrustListener> mTrustListeners = new ArrayList<ITrustListener>();
101    private final Receiver mReceiver = new Receiver();
102    private final SparseBooleanArray mUserHasAuthenticatedSinceBoot = new SparseBooleanArray();
103    /* package */ final TrustArchive mArchive = new TrustArchive();
104    private final Context mContext;
105    private final LockPatternUtils mLockPatternUtils;
106    private final UserManager mUserManager;
107
108    @GuardedBy("mUserIsTrusted")
109    private final SparseBooleanArray mUserIsTrusted = new SparseBooleanArray();
110
111    public TrustManagerService(Context context) {
112        super(context);
113        mContext = context;
114        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
115        mLockPatternUtils = new LockPatternUtils(context);
116    }
117
118    @Override
119    public void onStart() {
120        publishBinderService(Context.TRUST_SERVICE, mService);
121    }
122
123    @Override
124    public void onBootPhase(int phase) {
125        if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY && !isSafeMode()) {
126            mPackageMonitor.register(mContext, mHandler.getLooper(), UserHandle.ALL, true);
127            mReceiver.register(mContext);
128            refreshAgentList(UserHandle.USER_ALL);
129        } else if (phase == SystemService.PHASE_BOOT_COMPLETED && !isSafeMode()) {
130            maybeEnableFactoryTrustAgents(mLockPatternUtils, UserHandle.USER_OWNER);
131        }
132    }
133
134    // Agent management
135
136    private static final class AgentInfo {
137        CharSequence label;
138        Drawable icon;
139        ComponentName component; // service that implements ITrustAgent
140        ComponentName settings; // setting to launch to modify agent.
141        TrustAgentWrapper agent;
142        int userId;
143
144        @Override
145        public boolean equals(Object other) {
146            if (!(other instanceof AgentInfo)) {
147                return false;
148            }
149            AgentInfo o = (AgentInfo) other;
150            return component.equals(o.component) && userId == o.userId;
151        }
152
153        @Override
154        public int hashCode() {
155            return component.hashCode() * 31 + userId;
156        }
157    }
158
159    private void updateTrustAll() {
160        List<UserInfo> userInfos = mUserManager.getUsers(true /* excludeDying */);
161        for (UserInfo userInfo : userInfos) {
162            updateTrust(userInfo.id, false);
163        }
164    }
165
166    public void updateTrust(int userId, boolean initiatedByUser) {
167        dispatchOnTrustManagedChanged(aggregateIsTrustManaged(userId), userId);
168        boolean trusted = aggregateIsTrusted(userId);
169        synchronized (mUserIsTrusted) {
170            mUserIsTrusted.put(userId, trusted);
171        }
172        dispatchOnTrustChanged(trusted, userId, initiatedByUser);
173    }
174
175    void refreshAgentList(int userId) {
176        if (DEBUG) Slog.d(TAG, "refreshAgentList()");
177        if (userId != UserHandle.USER_ALL && userId < UserHandle.USER_OWNER) {
178            Log.e(TAG, "refreshAgentList(userId=" + userId + "): Invalid user handle,"
179                    + " must be USER_ALL or a specific user.", new Throwable("here"));
180            userId = UserHandle.USER_ALL;
181        }
182        PackageManager pm = mContext.getPackageManager();
183
184        List<UserInfo> userInfos;
185        if (userId == UserHandle.USER_ALL) {
186            userInfos = mUserManager.getUsers(true /* excludeDying */);
187        } else {
188            userInfos = new ArrayList<>();
189            userInfos.add(mUserManager.getUserInfo(userId));
190        }
191        LockPatternUtils lockPatternUtils = mLockPatternUtils;
192
193        ArraySet<AgentInfo> obsoleteAgents = new ArraySet<>();
194        obsoleteAgents.addAll(mActiveAgents);
195
196        for (UserInfo userInfo : userInfos) {
197            if (!userInfo.supportsSwitchTo()) continue;
198            if (lockPatternUtils.getKeyguardStoredPasswordQuality(userInfo.id)
199                    == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) continue;
200            if (!mUserHasAuthenticatedSinceBoot.get(userInfo.id)) continue;
201            DevicePolicyManager dpm = lockPatternUtils.getDevicePolicyManager();
202            int disabledFeatures = dpm.getKeyguardDisabledFeatures(null, userInfo.id);
203            final boolean disableTrustAgents =
204                    (disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0;
205
206            List<ComponentName> enabledAgents = lockPatternUtils.getEnabledTrustAgents(userInfo.id);
207            if (enabledAgents == null) {
208                continue;
209            }
210            List<ResolveInfo> resolveInfos = resolveAllowedTrustAgents(pm, userInfo.id);
211            for (ResolveInfo resolveInfo : resolveInfos) {
212                ComponentName name = getComponentName(resolveInfo);
213
214                if (!enabledAgents.contains(name)) continue;
215                if (disableTrustAgents) {
216                    List<String> features =
217                            dpm.getTrustAgentFeaturesEnabled(null /* admin */, name);
218                    // Disable agent if no features are enabled.
219                    if (features == null || features.isEmpty()) continue;
220                }
221
222                AgentInfo agentInfo = new AgentInfo();
223                agentInfo.component = name;
224                agentInfo.userId = userInfo.id;
225                if (!mActiveAgents.contains(agentInfo)) {
226                    agentInfo.label = resolveInfo.loadLabel(pm);
227                    agentInfo.icon = resolveInfo.loadIcon(pm);
228                    agentInfo.settings = getSettingsComponentName(pm, resolveInfo);
229                    agentInfo.agent = new TrustAgentWrapper(mContext, this,
230                            new Intent().setComponent(name), userInfo.getUserHandle());
231                    mActiveAgents.add(agentInfo);
232                } else {
233                    obsoleteAgents.remove(agentInfo);
234                }
235            }
236        }
237
238        boolean trustMayHaveChanged = false;
239        for (int i = 0; i < obsoleteAgents.size(); i++) {
240            AgentInfo info = obsoleteAgents.valueAt(i);
241            if (userId == UserHandle.USER_ALL || userId == info.userId) {
242                if (info.agent.isManagingTrust()) {
243                    trustMayHaveChanged = true;
244                }
245                info.agent.unbind();
246                mActiveAgents.remove(info);
247            }
248        }
249
250        if (trustMayHaveChanged) {
251            updateTrustAll();
252        }
253    }
254
255    void updateDevicePolicyFeatures() {
256        for (int i = 0; i < mActiveAgents.size(); i++) {
257            AgentInfo info = mActiveAgents.valueAt(i);
258            if (info.agent.isConnected()) {
259                info.agent.updateDevicePolicyFeatures();
260            }
261        }
262    }
263
264    private void removeAgentsOfPackage(String packageName) {
265        boolean trustMayHaveChanged = false;
266        for (int i = mActiveAgents.size() - 1; i >= 0; i--) {
267            AgentInfo info = mActiveAgents.valueAt(i);
268            if (packageName.equals(info.component.getPackageName())) {
269                Log.i(TAG, "Resetting agent " + info.component.flattenToShortString());
270                if (info.agent.isManagingTrust()) {
271                    trustMayHaveChanged = true;
272                }
273                info.agent.unbind();
274                mActiveAgents.removeAt(i);
275            }
276        }
277        if (trustMayHaveChanged) {
278            updateTrustAll();
279        }
280    }
281
282    public void resetAgent(ComponentName name, int userId) {
283        boolean trustMayHaveChanged = false;
284        for (int i = mActiveAgents.size() - 1; i >= 0; i--) {
285            AgentInfo info = mActiveAgents.valueAt(i);
286            if (name.equals(info.component) && userId == info.userId) {
287                Log.i(TAG, "Resetting agent " + info.component.flattenToShortString());
288                if (info.agent.isManagingTrust()) {
289                    trustMayHaveChanged = true;
290                }
291                info.agent.unbind();
292                mActiveAgents.removeAt(i);
293            }
294        }
295        if (trustMayHaveChanged) {
296            updateTrust(userId, false);
297        }
298        refreshAgentList(userId);
299    }
300
301    private ComponentName getSettingsComponentName(PackageManager pm, ResolveInfo resolveInfo) {
302        if (resolveInfo == null || resolveInfo.serviceInfo == null
303                || resolveInfo.serviceInfo.metaData == null) return null;
304        String cn = null;
305        XmlResourceParser parser = null;
306        Exception caughtException = null;
307        try {
308            parser = resolveInfo.serviceInfo.loadXmlMetaData(pm,
309                    TrustAgentService.TRUST_AGENT_META_DATA);
310            if (parser == null) {
311                Slog.w(TAG, "Can't find " + TrustAgentService.TRUST_AGENT_META_DATA + " meta-data");
312                return null;
313            }
314            Resources res = pm.getResourcesForApplication(resolveInfo.serviceInfo.applicationInfo);
315            AttributeSet attrs = Xml.asAttributeSet(parser);
316            int type;
317            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
318                    && type != XmlPullParser.START_TAG) {
319                // Drain preamble.
320            }
321            String nodeName = parser.getName();
322            if (!"trust-agent".equals(nodeName)) {
323                Slog.w(TAG, "Meta-data does not start with trust-agent tag");
324                return null;
325            }
326            TypedArray sa = res
327                    .obtainAttributes(attrs, com.android.internal.R.styleable.TrustAgent);
328            cn = sa.getString(com.android.internal.R.styleable.TrustAgent_settingsActivity);
329            sa.recycle();
330        } catch (PackageManager.NameNotFoundException e) {
331            caughtException = e;
332        } catch (IOException e) {
333            caughtException = e;
334        } catch (XmlPullParserException e) {
335            caughtException = e;
336        } finally {
337            if (parser != null) parser.close();
338        }
339        if (caughtException != null) {
340            Slog.w(TAG, "Error parsing : " + resolveInfo.serviceInfo.packageName, caughtException);
341            return null;
342        }
343        if (cn == null) {
344            return null;
345        }
346        if (cn.indexOf('/') < 0) {
347            cn = resolveInfo.serviceInfo.packageName + "/" + cn;
348        }
349        return ComponentName.unflattenFromString(cn);
350    }
351
352    private ComponentName getComponentName(ResolveInfo resolveInfo) {
353        if (resolveInfo == null || resolveInfo.serviceInfo == null) return null;
354        return new ComponentName(resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name);
355    }
356
357    private void maybeEnableFactoryTrustAgents(LockPatternUtils utils, int userId) {
358        if (0 != Settings.Secure.getIntForUser(mContext.getContentResolver(),
359                Settings.Secure.TRUST_AGENTS_INITIALIZED, 0, userId)) {
360            return;
361        }
362        PackageManager pm = mContext.getPackageManager();
363        List<ResolveInfo> resolveInfos = resolveAllowedTrustAgents(pm, userId);
364        ArraySet<ComponentName> discoveredAgents = new ArraySet<>();
365        for (ResolveInfo resolveInfo : resolveInfos) {
366            ComponentName componentName = getComponentName(resolveInfo);
367            int applicationInfoFlags = resolveInfo.serviceInfo.applicationInfo.flags;
368            if ((applicationInfoFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
369                Log.i(TAG, "Leaving agent " + componentName + " disabled because package "
370                        + "is not a system package.");
371                continue;
372            }
373            discoveredAgents.add(componentName);
374        }
375
376        List<ComponentName> previouslyEnabledAgents = utils.getEnabledTrustAgents(userId);
377        if (previouslyEnabledAgents != null) {
378            discoveredAgents.addAll(previouslyEnabledAgents);
379        }
380        utils.setEnabledTrustAgents(discoveredAgents, userId);
381        Settings.Secure.putIntForUser(mContext.getContentResolver(),
382                Settings.Secure.TRUST_AGENTS_INITIALIZED, 1, userId);
383    }
384
385    private List<ResolveInfo> resolveAllowedTrustAgents(PackageManager pm, int userId) {
386        List<ResolveInfo> resolveInfos = pm.queryIntentServicesAsUser(TRUST_AGENT_INTENT,
387                0 /* flags */, userId);
388        ArrayList<ResolveInfo> allowedAgents = new ArrayList<>(resolveInfos.size());
389        for (ResolveInfo resolveInfo : resolveInfos) {
390            if (resolveInfo.serviceInfo == null) continue;
391            if (resolveInfo.serviceInfo.applicationInfo == null) continue;
392            String packageName = resolveInfo.serviceInfo.packageName;
393            if (pm.checkPermission(PERMISSION_PROVIDE_AGENT, packageName)
394                    != PackageManager.PERMISSION_GRANTED) {
395                ComponentName name = getComponentName(resolveInfo);
396                Log.w(TAG, "Skipping agent " + name + " because package does not have"
397                        + " permission " + PERMISSION_PROVIDE_AGENT + ".");
398                continue;
399            }
400            allowedAgents.add(resolveInfo);
401        }
402        return allowedAgents;
403    }
404
405    // Agent dispatch and aggregation
406
407    private boolean aggregateIsTrusted(int userId) {
408        if (!mUserHasAuthenticatedSinceBoot.get(userId)) {
409            return false;
410        }
411        for (int i = 0; i < mActiveAgents.size(); i++) {
412            AgentInfo info = mActiveAgents.valueAt(i);
413            if (info.userId == userId) {
414                if (info.agent.isTrusted()) {
415                    return true;
416                }
417            }
418        }
419        return false;
420    }
421
422    private boolean aggregateIsTrustManaged(int userId) {
423        if (!mUserHasAuthenticatedSinceBoot.get(userId)) {
424            return false;
425        }
426        for (int i = 0; i < mActiveAgents.size(); i++) {
427            AgentInfo info = mActiveAgents.valueAt(i);
428            if (info.userId == userId) {
429                if (info.agent.isManagingTrust()) {
430                    return true;
431                }
432            }
433        }
434        return false;
435    }
436
437    private void dispatchUnlockAttempt(boolean successful, int userId) {
438        for (int i = 0; i < mActiveAgents.size(); i++) {
439            AgentInfo info = mActiveAgents.valueAt(i);
440            if (info.userId == userId) {
441                info.agent.onUnlockAttempt(successful);
442            }
443        }
444
445        if (successful) {
446            updateUserHasAuthenticated(userId);
447        }
448    }
449
450    private void updateUserHasAuthenticated(int userId) {
451        if (!mUserHasAuthenticatedSinceBoot.get(userId)) {
452            mUserHasAuthenticatedSinceBoot.put(userId, true);
453            refreshAgentList(userId);
454        }
455    }
456
457
458    private void requireCredentialEntry(int userId) {
459        if (userId == UserHandle.USER_ALL) {
460            mUserHasAuthenticatedSinceBoot.clear();
461            refreshAgentList(UserHandle.USER_ALL);
462        } else {
463            mUserHasAuthenticatedSinceBoot.put(userId, false);
464            refreshAgentList(userId);
465        }
466    }
467
468    // Listeners
469
470    private void addListener(ITrustListener listener) {
471        for (int i = 0; i < mTrustListeners.size(); i++) {
472            if (mTrustListeners.get(i).asBinder() == listener.asBinder()) {
473                return;
474            }
475        }
476        mTrustListeners.add(listener);
477        updateTrustAll();
478    }
479
480    private void removeListener(ITrustListener listener) {
481        for (int i = 0; i < mTrustListeners.size(); i++) {
482            if (mTrustListeners.get(i).asBinder() == listener.asBinder()) {
483                mTrustListeners.remove(i);
484                return;
485            }
486        }
487    }
488
489    private void dispatchOnTrustChanged(boolean enabled, int userId, boolean initiatedByUser) {
490        if (!enabled) initiatedByUser = false;
491        for (int i = 0; i < mTrustListeners.size(); i++) {
492            try {
493                mTrustListeners.get(i).onTrustChanged(enabled, userId, initiatedByUser);
494            } catch (DeadObjectException e) {
495                Slog.d(TAG, "Removing dead TrustListener.");
496                mTrustListeners.remove(i);
497                i--;
498            } catch (RemoteException e) {
499                Slog.e(TAG, "Exception while notifying TrustListener.", e);
500            }
501        }
502    }
503
504    private void dispatchOnTrustManagedChanged(boolean managed, int userId) {
505        for (int i = 0; i < mTrustListeners.size(); i++) {
506            try {
507                mTrustListeners.get(i).onTrustManagedChanged(managed, userId);
508            } catch (DeadObjectException e) {
509                Slog.d(TAG, "Removing dead TrustListener.");
510                mTrustListeners.remove(i);
511                i--;
512            } catch (RemoteException e) {
513                Slog.e(TAG, "Exception while notifying TrustListener.", e);
514            }
515        }
516    }
517
518    // Plumbing
519
520    private final IBinder mService = new ITrustManager.Stub() {
521        @Override
522        public void reportUnlockAttempt(boolean authenticated, int userId) throws RemoteException {
523            enforceReportPermission();
524            mHandler.obtainMessage(MSG_DISPATCH_UNLOCK_ATTEMPT, authenticated ? 1 : 0, userId)
525                    .sendToTarget();
526        }
527
528        @Override
529        public void reportEnabledTrustAgentsChanged(int userId) throws RemoteException {
530            enforceReportPermission();
531            // coalesce refresh messages.
532            mHandler.removeMessages(MSG_ENABLED_AGENTS_CHANGED);
533            mHandler.sendEmptyMessage(MSG_ENABLED_AGENTS_CHANGED);
534        }
535
536        @Override
537        public void reportRequireCredentialEntry(int userId) throws RemoteException {
538            enforceReportPermission();
539            if (userId == UserHandle.USER_ALL || userId >= UserHandle.USER_OWNER) {
540                mHandler.obtainMessage(MSG_REQUIRE_CREDENTIAL_ENTRY, userId, 0).sendToTarget();
541            } else {
542                throw new IllegalArgumentException(
543                        "userId must be an explicit user id or USER_ALL");
544            }
545        }
546
547        @Override
548        public void registerTrustListener(ITrustListener trustListener) throws RemoteException {
549            enforceListenerPermission();
550            mHandler.obtainMessage(MSG_REGISTER_LISTENER, trustListener).sendToTarget();
551        }
552
553        @Override
554        public void unregisterTrustListener(ITrustListener trustListener) throws RemoteException {
555            enforceListenerPermission();
556            mHandler.obtainMessage(MSG_UNREGISTER_LISTENER, trustListener).sendToTarget();
557        }
558
559        @Override
560        public boolean isTrusted(int userId) throws RemoteException {
561            userId = ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId,
562                    false /* allowAll */, true /* requireFull */, "isTrusted", null);
563            userId = resolveProfileParent(userId);
564            synchronized (mUserIsTrusted) {
565                return mUserIsTrusted.get(userId);
566            }
567        }
568
569        private void enforceReportPermission() {
570            mContext.enforceCallingOrSelfPermission(
571                    Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE, "reporting trust events");
572        }
573
574        private void enforceListenerPermission() {
575            mContext.enforceCallingPermission(Manifest.permission.TRUST_LISTENER,
576                    "register trust listener");
577        }
578
579        @Override
580        protected void dump(FileDescriptor fd, final PrintWriter fout, String[] args) {
581            mContext.enforceCallingPermission(Manifest.permission.DUMP,
582                    "dumping TrustManagerService");
583            final UserInfo currentUser;
584            final List<UserInfo> userInfos = mUserManager.getUsers(true /* excludeDying */);
585            try {
586                currentUser = ActivityManagerNative.getDefault().getCurrentUser();
587            } catch (RemoteException e) {
588                throw new RuntimeException(e);
589            }
590            mHandler.runWithScissors(new Runnable() {
591                @Override
592                public void run() {
593                    fout.println("Trust manager state:");
594                    for (UserInfo user : userInfos) {
595                        dumpUser(fout, user, user.id == currentUser.id);
596                    }
597                }
598            }, 1500);
599        }
600
601        private void dumpUser(PrintWriter fout, UserInfo user, boolean isCurrent) {
602            fout.printf(" User \"%s\" (id=%d, flags=%#x)",
603                    user.name, user.id, user.flags);
604            if (isCurrent) {
605                fout.print(" (current)");
606            }
607            fout.print(": trusted=" + dumpBool(aggregateIsTrusted(user.id)));
608            fout.print(", trustManaged=" + dumpBool(aggregateIsTrustManaged(user.id)));
609            fout.println();
610            fout.println("   Enabled agents:");
611            boolean duplicateSimpleNames = false;
612            ArraySet<String> simpleNames = new ArraySet<String>();
613            for (AgentInfo info : mActiveAgents) {
614                if (info.userId != user.id) { continue; }
615                boolean trusted = info.agent.isTrusted();
616                fout.print("    "); fout.println(info.component.flattenToShortString());
617                fout.print("     bound=" + dumpBool(info.agent.isBound()));
618                fout.print(", connected=" + dumpBool(info.agent.isConnected()));
619                fout.print(", managingTrust=" + dumpBool(info.agent.isManagingTrust()));
620                fout.print(", trusted=" + dumpBool(trusted));
621                fout.println();
622                if (trusted) {
623                    fout.println("      message=\"" + info.agent.getMessage() + "\"");
624                }
625                if (!info.agent.isConnected()) {
626                    String restartTime = TrustArchive.formatDuration(
627                            info.agent.getScheduledRestartUptimeMillis()
628                                    - SystemClock.uptimeMillis());
629                    fout.println("      restartScheduledAt=" + restartTime);
630                }
631                if (!simpleNames.add(TrustArchive.getSimpleName(info.component))) {
632                    duplicateSimpleNames = true;
633                }
634            }
635            fout.println("   Events:");
636            mArchive.dump(fout, 50, user.id, "    " /* linePrefix */, duplicateSimpleNames);
637            fout.println();
638        }
639
640        private String dumpBool(boolean b) {
641            return b ? "1" : "0";
642        }
643    };
644
645    private int resolveProfileParent(int userId) {
646        long identity = Binder.clearCallingIdentity();
647        try {
648            UserInfo parent = mUserManager.getProfileParent(userId);
649            if (parent != null) {
650                return parent.getUserHandle().getIdentifier();
651            }
652            return userId;
653        } finally {
654            Binder.restoreCallingIdentity(identity);
655        }
656    }
657
658    private final Handler mHandler = new Handler() {
659        @Override
660        public void handleMessage(Message msg) {
661            switch (msg.what) {
662                case MSG_REGISTER_LISTENER:
663                    addListener((ITrustListener) msg.obj);
664                    break;
665                case MSG_UNREGISTER_LISTENER:
666                    removeListener((ITrustListener) msg.obj);
667                    break;
668                case MSG_DISPATCH_UNLOCK_ATTEMPT:
669                    dispatchUnlockAttempt(msg.arg1 != 0, msg.arg2);
670                    break;
671                case MSG_ENABLED_AGENTS_CHANGED:
672                    refreshAgentList(UserHandle.USER_ALL);
673                    break;
674                case MSG_REQUIRE_CREDENTIAL_ENTRY:
675                    requireCredentialEntry(msg.arg1);
676                    break;
677            }
678        }
679    };
680
681    private final PackageMonitor mPackageMonitor = new PackageMonitor() {
682        @Override
683        public void onSomePackagesChanged() {
684            refreshAgentList(UserHandle.USER_ALL);
685        }
686
687        @Override
688        public boolean onPackageChanged(String packageName, int uid, String[] components) {
689            // We're interested in all changes, even if just some components get enabled / disabled.
690            return true;
691        }
692
693        @Override
694        public void onPackageDisappeared(String packageName, int reason) {
695            removeAgentsOfPackage(packageName);
696        }
697    };
698
699    private class Receiver extends BroadcastReceiver {
700
701        @Override
702        public void onReceive(Context context, Intent intent) {
703            String action = intent.getAction();
704            if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action)) {
705                refreshAgentList(getSendingUserId());
706                updateDevicePolicyFeatures();
707            } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
708                updateUserHasAuthenticated(getSendingUserId());
709            } else if (Intent.ACTION_USER_ADDED.equals(action)) {
710                int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -100);
711                if (userId > 0) {
712                    maybeEnableFactoryTrustAgents(mLockPatternUtils, userId);
713                } else {
714                    Log.wtf(TAG, "EXTRA_USER_HANDLE missing or invalid, value=" + userId);
715                }
716            }
717        }
718
719        public void register(Context context) {
720            IntentFilter filter = new IntentFilter();
721            filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
722            filter.addAction(Intent.ACTION_USER_PRESENT);
723            filter.addAction(Intent.ACTION_USER_ADDED);
724            context.registerReceiverAsUser(this,
725                    UserHandle.ALL,
726                    filter,
727                    null /* permission */,
728                    null /* scheduler */);
729        }
730    }
731}
732