blob: b9576a598240991f5eb37ea1a154bf6bea8cd328 [file] [log] [blame]
Adrian Roos82142c22014-03-27 14:56:59 +01001/*
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.content.PackageMonitor;
20import com.android.internal.widget.LockPatternUtils;
21import com.android.server.SystemService;
22
23import org.xmlpull.v1.XmlPullParser;
24import org.xmlpull.v1.XmlPullParserException;
25
26import android.Manifest;
Adrian Roos7a4f3d42014-05-02 12:12:20 +020027import android.app.ActivityManagerNative;
Adrian Roosca36b952014-05-16 18:52:29 +020028import android.app.admin.DevicePolicyManager;
Adrian Roos82142c22014-03-27 14:56:59 +010029import android.app.trust.ITrustListener;
30import android.app.trust.ITrustManager;
Adrian Roosca36b952014-05-16 18:52:29 +020031import android.content.BroadcastReceiver;
Adrian Roos82142c22014-03-27 14:56:59 +010032import android.content.ComponentName;
33import android.content.Context;
34import android.content.Intent;
Adrian Roosca36b952014-05-16 18:52:29 +020035import android.content.IntentFilter;
Adrian Roos3870d452014-09-05 18:22:28 +020036import android.content.pm.ApplicationInfo;
Adrian Roos82142c22014-03-27 14:56:59 +010037import android.content.pm.PackageManager;
38import android.content.pm.ResolveInfo;
39import android.content.pm.UserInfo;
40import android.content.res.Resources;
41import android.content.res.TypedArray;
42import android.content.res.XmlResourceParser;
43import android.graphics.drawable.Drawable;
Adrian Roosa4ba56b2014-05-20 12:56:25 +020044import android.os.DeadObjectException;
Adrian Roos82142c22014-03-27 14:56:59 +010045import android.os.Handler;
46import android.os.IBinder;
47import android.os.Message;
48import android.os.RemoteException;
Adrian Roosc5f95ce2014-07-24 16:00:46 +020049import android.os.SystemClock;
Adrian Roos82142c22014-03-27 14:56:59 +010050import android.os.UserHandle;
51import android.os.UserManager;
Adrian Roos3870d452014-09-05 18:22:28 +020052import android.provider.Settings;
Adrian Roos82142c22014-03-27 14:56:59 +010053import android.service.trust.TrustAgentService;
54import android.util.ArraySet;
55import android.util.AttributeSet;
Adrian Roos18ea8932014-05-28 14:53:06 +020056import android.util.Log;
Adrian Roos82142c22014-03-27 14:56:59 +010057import android.util.Slog;
Adrian Roos7046bfd2014-05-16 21:20:54 +020058import android.util.SparseBooleanArray;
Adrian Roos82142c22014-03-27 14:56:59 +010059import android.util.Xml;
60
Adrian Roos7a4f3d42014-05-02 12:12:20 +020061import java.io.FileDescriptor;
Adrian Roos82142c22014-03-27 14:56:59 +010062import java.io.IOException;
Adrian Roos7a4f3d42014-05-02 12:12:20 +020063import java.io.PrintWriter;
Adrian Roos82142c22014-03-27 14:56:59 +010064import java.util.ArrayList;
65import java.util.List;
66
67/**
68 * Manages trust agents and trust listeners.
69 *
70 * It is responsible for binding to the enabled {@link android.service.trust.TrustAgentService}s
71 * of each user and notifies them about events that are relevant to them.
72 * It start and stops them based on the value of
73 * {@link com.android.internal.widget.LockPatternUtils#getEnabledTrustAgents(int)}.
74 *
75 * It also keeps a set of {@link android.app.trust.ITrustListener}s that are notified whenever the
76 * trust state changes for any user.
77 *
78 * Trust state and the setting of enabled agents is kept per user and each user has its own
79 * instance of a {@link android.service.trust.TrustAgentService}.
80 */
81public class TrustManagerService extends SystemService {
82
83 private static final boolean DEBUG = false;
84 private static final String TAG = "TrustManagerService";
85
86 private static final Intent TRUST_AGENT_INTENT =
87 new Intent(TrustAgentService.SERVICE_INTERFACE);
Adrian Roos18ea8932014-05-28 14:53:06 +020088 private static final String PERMISSION_PROVIDE_AGENT = Manifest.permission.PROVIDE_TRUST_AGENT;
Adrian Roos82142c22014-03-27 14:56:59 +010089
90 private static final int MSG_REGISTER_LISTENER = 1;
91 private static final int MSG_UNREGISTER_LISTENER = 2;
92 private static final int MSG_DISPATCH_UNLOCK_ATTEMPT = 3;
93 private static final int MSG_ENABLED_AGENTS_CHANGED = 4;
Adrian Roos2c12cfa2014-06-25 23:28:53 +020094 private static final int MSG_REQUIRE_CREDENTIAL_ENTRY = 5;
Adrian Roos82142c22014-03-27 14:56:59 +010095
96 private final ArraySet<AgentInfo> mActiveAgents = new ArraySet<AgentInfo>();
97 private final ArrayList<ITrustListener> mTrustListeners = new ArrayList<ITrustListener>();
Adrian Roos9dbe1902014-08-13 18:25:52 +020098 private final Receiver mReceiver = new Receiver();
Adrian Roos7046bfd2014-05-16 21:20:54 +020099 private final SparseBooleanArray mUserHasAuthenticatedSinceBoot = new SparseBooleanArray();
Adrian Roos7a4f3d42014-05-02 12:12:20 +0200100 /* package */ final TrustArchive mArchive = new TrustArchive();
Adrian Roos82142c22014-03-27 14:56:59 +0100101 private final Context mContext;
Adrian Roos3870d452014-09-05 18:22:28 +0200102 private final LockPatternUtils mLockPatternUtils;
Adrian Roos82142c22014-03-27 14:56:59 +0100103
104 private UserManager mUserManager;
105
Adrian Roos82142c22014-03-27 14:56:59 +0100106 public TrustManagerService(Context context) {
107 super(context);
108 mContext = context;
109 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
Adrian Roos3870d452014-09-05 18:22:28 +0200110 mLockPatternUtils = new LockPatternUtils(context);
Adrian Roos82142c22014-03-27 14:56:59 +0100111 }
112
113 @Override
114 public void onStart() {
115 publishBinderService(Context.TRUST_SERVICE, mService);
116 }
117
118 @Override
119 public void onBootPhase(int phase) {
120 if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY && !isSafeMode()) {
Adrian Roos82142c22014-03-27 14:56:59 +0100121 mPackageMonitor.register(mContext, mHandler.getLooper(), UserHandle.ALL, true);
Adrian Roos9dbe1902014-08-13 18:25:52 +0200122 mReceiver.register(mContext);
Adrian Roos3870d452014-09-05 18:22:28 +0200123 maybeEnableFactoryTrustAgents(mLockPatternUtils, UserHandle.USER_OWNER);
Marco Fucci4e68f112014-08-29 12:31:48 -0700124 refreshAgentList(UserHandle.USER_ALL);
Adrian Roos82142c22014-03-27 14:56:59 +0100125 }
126 }
127
128 // Agent management
129
130 private static final class AgentInfo {
131 CharSequence label;
132 Drawable icon;
133 ComponentName component; // service that implements ITrustAgent
134 ComponentName settings; // setting to launch to modify agent.
135 TrustAgentWrapper agent;
136 int userId;
137
138 @Override
139 public boolean equals(Object other) {
140 if (!(other instanceof AgentInfo)) {
141 return false;
142 }
143 AgentInfo o = (AgentInfo) other;
144 return component.equals(o.component) && userId == o.userId;
145 }
146
147 @Override
148 public int hashCode() {
149 return component.hashCode() * 31 + userId;
150 }
151 }
152
153 private void updateTrustAll() {
154 List<UserInfo> userInfos = mUserManager.getUsers(true /* excludeDying */);
155 for (UserInfo userInfo : userInfos) {
Adrian Roos3c9a3502014-08-06 19:09:45 +0200156 updateTrust(userInfo.id, false);
Adrian Roos82142c22014-03-27 14:56:59 +0100157 }
158 }
159
Adrian Roos3c9a3502014-08-06 19:09:45 +0200160 public void updateTrust(int userId, boolean initiatedByUser) {
Adrian Roos7861c662014-07-25 15:37:28 +0200161 dispatchOnTrustManagedChanged(aggregateIsTrustManaged(userId), userId);
Adrian Roos3c9a3502014-08-06 19:09:45 +0200162 dispatchOnTrustChanged(aggregateIsTrusted(userId), userId, initiatedByUser);
Adrian Roos82142c22014-03-27 14:56:59 +0100163 }
164
Marco Fucci4e68f112014-08-29 12:31:48 -0700165 void refreshAgentList(int userId) {
Adrian Roos82142c22014-03-27 14:56:59 +0100166 if (DEBUG) Slog.d(TAG, "refreshAgentList()");
167 PackageManager pm = mContext.getPackageManager();
168
Marco Fucci4e68f112014-08-29 12:31:48 -0700169 List<UserInfo> userInfos;
170 if (userId == UserHandle.USER_ALL) {
171 userInfos = mUserManager.getUsers(true /* excludeDying */);
172 } else {
173 userInfos = new ArrayList<>();
174 userInfos.add(mUserManager.getUserInfo(userId));
175 }
Adrian Roos3870d452014-09-05 18:22:28 +0200176 LockPatternUtils lockPatternUtils = mLockPatternUtils;
Adrian Roos82142c22014-03-27 14:56:59 +0100177
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200178 ArraySet<AgentInfo> obsoleteAgents = new ArraySet<>();
179 obsoleteAgents.addAll(mActiveAgents);
Adrian Roos82142c22014-03-27 14:56:59 +0100180
181 for (UserInfo userInfo : userInfos) {
Adrian Roos3870d452014-09-05 18:22:28 +0200182 if (!userInfo.supportsSwitchTo()) continue;
Adrian Roos1572ee32014-09-01 16:24:32 +0200183 if (lockPatternUtils.getKeyguardStoredPasswordQuality(userInfo.id)
Adrian Roos4b9e3242014-08-20 23:36:25 +0200184 == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) continue;
Marco Fucci4e68f112014-08-29 12:31:48 -0700185 if (!mUserHasAuthenticatedSinceBoot.get(userInfo.id)) continue;
Adrian Roos8f211582014-07-29 15:09:57 +0200186 DevicePolicyManager dpm = lockPatternUtils.getDevicePolicyManager();
187 int disabledFeatures = dpm.getKeyguardDisabledFeatures(null, userInfo.id);
Jim Miller604e7552014-07-18 19:00:02 -0700188 final boolean disableTrustAgents =
Adrian Roosca36b952014-05-16 18:52:29 +0200189 (disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0;
190
Adrian Roos82142c22014-03-27 14:56:59 +0100191 List<ComponentName> enabledAgents = lockPatternUtils.getEnabledTrustAgents(userInfo.id);
Adrian Roos8f211582014-07-29 15:09:57 +0200192 if (enabledAgents == null) {
Adrian Roos82142c22014-03-27 14:56:59 +0100193 continue;
194 }
Adrian Roos3870d452014-09-05 18:22:28 +0200195 List<ResolveInfo> resolveInfos = resolveAllowedTrustAgents(pm, userInfo.id);
Adrian Roos82142c22014-03-27 14:56:59 +0100196 for (ResolveInfo resolveInfo : resolveInfos) {
Adrian Roos82142c22014-03-27 14:56:59 +0100197 ComponentName name = getComponentName(resolveInfo);
Adrian Roos82142c22014-03-27 14:56:59 +0100198
Adrian Roos3870d452014-09-05 18:22:28 +0200199 if (!enabledAgents.contains(name)) continue;
Adrian Roos8f211582014-07-29 15:09:57 +0200200 if (disableTrustAgents) {
201 List<String> features =
202 dpm.getTrustAgentFeaturesEnabled(null /* admin */, name);
203 // Disable agent if no features are enabled.
204 if (features == null || features.isEmpty()) continue;
205 }
206
Adrian Roos82142c22014-03-27 14:56:59 +0100207 AgentInfo agentInfo = new AgentInfo();
208 agentInfo.component = name;
209 agentInfo.userId = userInfo.id;
210 if (!mActiveAgents.contains(agentInfo)) {
211 agentInfo.label = resolveInfo.loadLabel(pm);
212 agentInfo.icon = resolveInfo.loadIcon(pm);
213 agentInfo.settings = getSettingsComponentName(pm, resolveInfo);
214 agentInfo.agent = new TrustAgentWrapper(mContext, this,
215 new Intent().setComponent(name), userInfo.getUserHandle());
216 mActiveAgents.add(agentInfo);
217 } else {
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200218 obsoleteAgents.remove(agentInfo);
Adrian Roos82142c22014-03-27 14:56:59 +0100219 }
220 }
221 }
222
223 boolean trustMayHaveChanged = false;
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200224 for (int i = 0; i < obsoleteAgents.size(); i++) {
225 AgentInfo info = obsoleteAgents.valueAt(i);
Adrian Roos7861c662014-07-25 15:37:28 +0200226 if (info.agent.isManagingTrust()) {
Adrian Roos82142c22014-03-27 14:56:59 +0100227 trustMayHaveChanged = true;
228 }
229 info.agent.unbind();
Adrian Roosa5956422014-04-30 18:23:38 +0200230 mActiveAgents.remove(info);
Adrian Roos82142c22014-03-27 14:56:59 +0100231 }
232
233 if (trustMayHaveChanged) {
234 updateTrustAll();
235 }
236 }
237
Marco Fucci4e68f112014-08-29 12:31:48 -0700238 void updateDevicePolicyFeatures() {
Adrian Roos8f211582014-07-29 15:09:57 +0200239 for (int i = 0; i < mActiveAgents.size(); i++) {
240 AgentInfo info = mActiveAgents.valueAt(i);
241 if (info.agent.isConnected()) {
242 info.agent.updateDevicePolicyFeatures();
243 }
244 }
245 }
246
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200247 private void removeAgentsOfPackage(String packageName) {
248 boolean trustMayHaveChanged = false;
249 for (int i = mActiveAgents.size() - 1; i >= 0; i--) {
250 AgentInfo info = mActiveAgents.valueAt(i);
251 if (packageName.equals(info.component.getPackageName())) {
252 Log.i(TAG, "Resetting agent " + info.component.flattenToShortString());
Adrian Roos7861c662014-07-25 15:37:28 +0200253 if (info.agent.isManagingTrust()) {
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200254 trustMayHaveChanged = true;
255 }
256 info.agent.unbind();
257 mActiveAgents.removeAt(i);
258 }
259 }
260 if (trustMayHaveChanged) {
261 updateTrustAll();
262 }
263 }
264
265 public void resetAgent(ComponentName name, int userId) {
266 boolean trustMayHaveChanged = false;
267 for (int i = mActiveAgents.size() - 1; i >= 0; i--) {
268 AgentInfo info = mActiveAgents.valueAt(i);
269 if (name.equals(info.component) && userId == info.userId) {
270 Log.i(TAG, "Resetting agent " + info.component.flattenToShortString());
Adrian Roos7861c662014-07-25 15:37:28 +0200271 if (info.agent.isManagingTrust()) {
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200272 trustMayHaveChanged = true;
273 }
274 info.agent.unbind();
275 mActiveAgents.removeAt(i);
276 }
277 }
278 if (trustMayHaveChanged) {
Adrian Roos3c9a3502014-08-06 19:09:45 +0200279 updateTrust(userId, false);
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200280 }
Marco Fucci4e68f112014-08-29 12:31:48 -0700281 refreshAgentList(userId);
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200282 }
283
Adrian Roos82142c22014-03-27 14:56:59 +0100284 private ComponentName getSettingsComponentName(PackageManager pm, ResolveInfo resolveInfo) {
285 if (resolveInfo == null || resolveInfo.serviceInfo == null
286 || resolveInfo.serviceInfo.metaData == null) return null;
287 String cn = null;
288 XmlResourceParser parser = null;
289 Exception caughtException = null;
290 try {
291 parser = resolveInfo.serviceInfo.loadXmlMetaData(pm,
292 TrustAgentService.TRUST_AGENT_META_DATA);
293 if (parser == null) {
294 Slog.w(TAG, "Can't find " + TrustAgentService.TRUST_AGENT_META_DATA + " meta-data");
295 return null;
296 }
297 Resources res = pm.getResourcesForApplication(resolveInfo.serviceInfo.applicationInfo);
298 AttributeSet attrs = Xml.asAttributeSet(parser);
299 int type;
300 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
301 && type != XmlPullParser.START_TAG) {
302 // Drain preamble.
303 }
304 String nodeName = parser.getName();
Adrian Roos7e03dfc2014-05-16 16:06:28 +0200305 if (!"trust-agent".equals(nodeName)) {
306 Slog.w(TAG, "Meta-data does not start with trust-agent tag");
Adrian Roos82142c22014-03-27 14:56:59 +0100307 return null;
308 }
309 TypedArray sa = res
310 .obtainAttributes(attrs, com.android.internal.R.styleable.TrustAgent);
311 cn = sa.getString(com.android.internal.R.styleable.TrustAgent_settingsActivity);
312 sa.recycle();
313 } catch (PackageManager.NameNotFoundException e) {
314 caughtException = e;
315 } catch (IOException e) {
316 caughtException = e;
317 } catch (XmlPullParserException e) {
318 caughtException = e;
319 } finally {
320 if (parser != null) parser.close();
321 }
322 if (caughtException != null) {
323 Slog.w(TAG, "Error parsing : " + resolveInfo.serviceInfo.packageName, caughtException);
324 return null;
325 }
326 if (cn == null) {
327 return null;
328 }
329 if (cn.indexOf('/') < 0) {
330 cn = resolveInfo.serviceInfo.packageName + "/" + cn;
331 }
332 return ComponentName.unflattenFromString(cn);
333 }
334
335 private ComponentName getComponentName(ResolveInfo resolveInfo) {
336 if (resolveInfo == null || resolveInfo.serviceInfo == null) return null;
337 return new ComponentName(resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name);
338 }
339
Adrian Roos3870d452014-09-05 18:22:28 +0200340 private void maybeEnableFactoryTrustAgents(LockPatternUtils utils, int userId) {
341 if (0 != Settings.Secure.getIntForUser(mContext.getContentResolver(),
342 Settings.Secure.TRUST_AGENTS_INITIALIZED, 0, userId)) {
343 return;
344 }
345 PackageManager pm = mContext.getPackageManager();
346 List<ResolveInfo> resolveInfos = resolveAllowedTrustAgents(pm, userId);
347 ArraySet<ComponentName> discoveredAgents = new ArraySet<>();
348 for (ResolveInfo resolveInfo : resolveInfos) {
349 ComponentName componentName = getComponentName(resolveInfo);
350 int applicationInfoFlags = resolveInfo.serviceInfo.applicationInfo.flags;
351 if ((applicationInfoFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
352 Log.i(TAG, "Leaving agent " + componentName + " disabled because package "
353 + "is not a system package.");
354 continue;
355 }
356 discoveredAgents.add(componentName);
357 }
358
359 List<ComponentName> previouslyEnabledAgents = utils.getEnabledTrustAgents(userId);
360 if (previouslyEnabledAgents != null) {
361 discoveredAgents.addAll(previouslyEnabledAgents);
362 }
363 utils.setEnabledTrustAgents(discoveredAgents, userId);
364 Settings.Secure.putIntForUser(mContext.getContentResolver(),
365 Settings.Secure.TRUST_AGENTS_INITIALIZED, 1, userId);
366 }
367
368 private List<ResolveInfo> resolveAllowedTrustAgents(PackageManager pm, int userId) {
369 List<ResolveInfo> resolveInfos = pm.queryIntentServicesAsUser(TRUST_AGENT_INTENT,
370 0 /* flags */, userId);
371 ArrayList<ResolveInfo> allowedAgents = new ArrayList<>(resolveInfos.size());
372 for (ResolveInfo resolveInfo : resolveInfos) {
373 if (resolveInfo.serviceInfo == null) continue;
374 if (resolveInfo.serviceInfo.applicationInfo == null) continue;
375 String packageName = resolveInfo.serviceInfo.packageName;
376 if (pm.checkPermission(PERMISSION_PROVIDE_AGENT, packageName)
377 != PackageManager.PERMISSION_GRANTED) {
378 ComponentName name = getComponentName(resolveInfo);
379 Log.w(TAG, "Skipping agent " + name + " because package does not have"
380 + " permission " + PERMISSION_PROVIDE_AGENT + ".");
381 continue;
382 }
383 allowedAgents.add(resolveInfo);
384 }
385 return allowedAgents;
386 }
387
Adrian Roos82142c22014-03-27 14:56:59 +0100388 // Agent dispatch and aggregation
389
390 private boolean aggregateIsTrusted(int userId) {
Adrian Roos7046bfd2014-05-16 21:20:54 +0200391 if (!mUserHasAuthenticatedSinceBoot.get(userId)) {
392 return false;
393 }
Adrian Roos82142c22014-03-27 14:56:59 +0100394 for (int i = 0; i < mActiveAgents.size(); i++) {
395 AgentInfo info = mActiveAgents.valueAt(i);
396 if (info.userId == userId) {
397 if (info.agent.isTrusted()) {
398 return true;
399 }
400 }
401 }
402 return false;
403 }
404
Adrian Roos7861c662014-07-25 15:37:28 +0200405 private boolean aggregateIsTrustManaged(int userId) {
406 if (!mUserHasAuthenticatedSinceBoot.get(userId)) {
407 return false;
408 }
409 for (int i = 0; i < mActiveAgents.size(); i++) {
410 AgentInfo info = mActiveAgents.valueAt(i);
411 if (info.userId == userId) {
412 if (info.agent.isManagingTrust()) {
413 return true;
414 }
415 }
416 }
417 return false;
418 }
419
Adrian Roos82142c22014-03-27 14:56:59 +0100420 private void dispatchUnlockAttempt(boolean successful, int userId) {
421 for (int i = 0; i < mActiveAgents.size(); i++) {
422 AgentInfo info = mActiveAgents.valueAt(i);
423 if (info.userId == userId) {
424 info.agent.onUnlockAttempt(successful);
425 }
426 }
Adrian Roos7046bfd2014-05-16 21:20:54 +0200427
Adrian Roos9dbe1902014-08-13 18:25:52 +0200428 if (successful) {
429 updateUserHasAuthenticated(userId);
430 }
431 }
432
433 private void updateUserHasAuthenticated(int userId) {
434 if (!mUserHasAuthenticatedSinceBoot.get(userId)) {
Adrian Roos7046bfd2014-05-16 21:20:54 +0200435 mUserHasAuthenticatedSinceBoot.put(userId, true);
Marco Fucci4e68f112014-08-29 12:31:48 -0700436 refreshAgentList(userId);
Adrian Roos7046bfd2014-05-16 21:20:54 +0200437 }
Adrian Roos82142c22014-03-27 14:56:59 +0100438 }
439
Adrian Roos2c12cfa2014-06-25 23:28:53 +0200440
441 private void requireCredentialEntry(int userId) {
442 if (userId == UserHandle.USER_ALL) {
443 mUserHasAuthenticatedSinceBoot.clear();
Marco Fucci4e68f112014-08-29 12:31:48 -0700444 refreshAgentList(UserHandle.USER_ALL);
Adrian Roos2c12cfa2014-06-25 23:28:53 +0200445 } else {
446 mUserHasAuthenticatedSinceBoot.put(userId, false);
Marco Fucci4e68f112014-08-29 12:31:48 -0700447 refreshAgentList(userId);
Adrian Roos2c12cfa2014-06-25 23:28:53 +0200448 }
449 }
450
Adrian Roos82142c22014-03-27 14:56:59 +0100451 // Listeners
452
453 private void addListener(ITrustListener listener) {
454 for (int i = 0; i < mTrustListeners.size(); i++) {
455 if (mTrustListeners.get(i).asBinder() == listener.asBinder()) {
456 return;
457 }
458 }
459 mTrustListeners.add(listener);
Adrian Roos3870d452014-09-05 18:22:28 +0200460 updateTrustAll();
Adrian Roos82142c22014-03-27 14:56:59 +0100461 }
462
463 private void removeListener(ITrustListener listener) {
464 for (int i = 0; i < mTrustListeners.size(); i++) {
465 if (mTrustListeners.get(i).asBinder() == listener.asBinder()) {
Jay Civelli979a32e2014-07-18 16:47:36 -0700466 mTrustListeners.remove(i);
Adrian Roos82142c22014-03-27 14:56:59 +0100467 return;
468 }
469 }
470 }
471
Adrian Roos3c9a3502014-08-06 19:09:45 +0200472 private void dispatchOnTrustChanged(boolean enabled, int userId, boolean initiatedByUser) {
473 if (!enabled) initiatedByUser = false;
Adrian Roos82142c22014-03-27 14:56:59 +0100474 for (int i = 0; i < mTrustListeners.size(); i++) {
475 try {
Adrian Roos3c9a3502014-08-06 19:09:45 +0200476 mTrustListeners.get(i).onTrustChanged(enabled, userId, initiatedByUser);
Adrian Roosa4ba56b2014-05-20 12:56:25 +0200477 } catch (DeadObjectException e) {
Adrian Roos7861c662014-07-25 15:37:28 +0200478 Slog.d(TAG, "Removing dead TrustListener.");
479 mTrustListeners.remove(i);
480 i--;
481 } catch (RemoteException e) {
482 Slog.e(TAG, "Exception while notifying TrustListener.", e);
483 }
484 }
485 }
486
487 private void dispatchOnTrustManagedChanged(boolean managed, int userId) {
488 for (int i = 0; i < mTrustListeners.size(); i++) {
489 try {
490 mTrustListeners.get(i).onTrustManagedChanged(managed, userId);
491 } catch (DeadObjectException e) {
492 Slog.d(TAG, "Removing dead TrustListener.");
Adrian Roosa4ba56b2014-05-20 12:56:25 +0200493 mTrustListeners.remove(i);
494 i--;
Adrian Roos82142c22014-03-27 14:56:59 +0100495 } catch (RemoteException e) {
Adrian Roosa4ba56b2014-05-20 12:56:25 +0200496 Slog.e(TAG, "Exception while notifying TrustListener.", e);
Adrian Roos82142c22014-03-27 14:56:59 +0100497 }
498 }
499 }
500
501 // Plumbing
502
503 private final IBinder mService = new ITrustManager.Stub() {
504 @Override
505 public void reportUnlockAttempt(boolean authenticated, int userId) throws RemoteException {
506 enforceReportPermission();
507 mHandler.obtainMessage(MSG_DISPATCH_UNLOCK_ATTEMPT, authenticated ? 1 : 0, userId)
508 .sendToTarget();
509 }
510
511 @Override
512 public void reportEnabledTrustAgentsChanged(int userId) throws RemoteException {
513 enforceReportPermission();
514 // coalesce refresh messages.
515 mHandler.removeMessages(MSG_ENABLED_AGENTS_CHANGED);
516 mHandler.sendEmptyMessage(MSG_ENABLED_AGENTS_CHANGED);
517 }
518
519 @Override
Adrian Roos2c12cfa2014-06-25 23:28:53 +0200520 public void reportRequireCredentialEntry(int userId) throws RemoteException {
521 enforceReportPermission();
522 if (userId == UserHandle.USER_ALL || userId >= UserHandle.USER_OWNER) {
523 mHandler.obtainMessage(MSG_REQUIRE_CREDENTIAL_ENTRY, userId, 0).sendToTarget();
524 } else {
525 throw new IllegalArgumentException(
526 "userId must be an explicit user id or USER_ALL");
527 }
528 }
529
530 @Override
Adrian Roos82142c22014-03-27 14:56:59 +0100531 public void registerTrustListener(ITrustListener trustListener) throws RemoteException {
532 enforceListenerPermission();
533 mHandler.obtainMessage(MSG_REGISTER_LISTENER, trustListener).sendToTarget();
534 }
535
536 @Override
537 public void unregisterTrustListener(ITrustListener trustListener) throws RemoteException {
538 enforceListenerPermission();
539 mHandler.obtainMessage(MSG_UNREGISTER_LISTENER, trustListener).sendToTarget();
540 }
541
542 private void enforceReportPermission() {
Adrian Roos2c12cfa2014-06-25 23:28:53 +0200543 mContext.enforceCallingOrSelfPermission(
544 Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE, "reporting trust events");
Adrian Roos82142c22014-03-27 14:56:59 +0100545 }
546
547 private void enforceListenerPermission() {
548 mContext.enforceCallingPermission(Manifest.permission.TRUST_LISTENER,
549 "register trust listener");
550 }
Adrian Roos7a4f3d42014-05-02 12:12:20 +0200551
552 @Override
553 protected void dump(FileDescriptor fd, final PrintWriter fout, String[] args) {
554 mContext.enforceCallingPermission(Manifest.permission.DUMP,
555 "dumping TrustManagerService");
556 final UserInfo currentUser;
557 final List<UserInfo> userInfos = mUserManager.getUsers(true /* excludeDying */);
558 try {
559 currentUser = ActivityManagerNative.getDefault().getCurrentUser();
560 } catch (RemoteException e) {
561 throw new RuntimeException(e);
562 }
563 mHandler.runWithScissors(new Runnable() {
564 @Override
565 public void run() {
566 fout.println("Trust manager state:");
567 for (UserInfo user : userInfos) {
568 dumpUser(fout, user, user.id == currentUser.id);
569 }
570 }
571 }, 1500);
572 }
573
574 private void dumpUser(PrintWriter fout, UserInfo user, boolean isCurrent) {
575 fout.printf(" User \"%s\" (id=%d, flags=%#x)",
576 user.name, user.id, user.flags);
577 if (isCurrent) {
578 fout.print(" (current)");
579 }
580 fout.print(": trusted=" + dumpBool(aggregateIsTrusted(user.id)));
Adrian Roos7861c662014-07-25 15:37:28 +0200581 fout.print(", trustManaged=" + dumpBool(aggregateIsTrustManaged(user.id)));
Adrian Roos7a4f3d42014-05-02 12:12:20 +0200582 fout.println();
583 fout.println(" Enabled agents:");
584 boolean duplicateSimpleNames = false;
585 ArraySet<String> simpleNames = new ArraySet<String>();
586 for (AgentInfo info : mActiveAgents) {
587 if (info.userId != user.id) { continue; }
588 boolean trusted = info.agent.isTrusted();
589 fout.print(" "); fout.println(info.component.flattenToShortString());
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200590 fout.print(" bound=" + dumpBool(info.agent.isBound()));
591 fout.print(", connected=" + dumpBool(info.agent.isConnected()));
Adrian Roos7861c662014-07-25 15:37:28 +0200592 fout.print(", managingTrust=" + dumpBool(info.agent.isManagingTrust()));
593 fout.print(", trusted=" + dumpBool(trusted));
594 fout.println();
Adrian Roos7a4f3d42014-05-02 12:12:20 +0200595 if (trusted) {
596 fout.println(" message=\"" + info.agent.getMessage() + "\"");
597 }
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200598 if (!info.agent.isConnected()) {
599 String restartTime = TrustArchive.formatDuration(
600 info.agent.getScheduledRestartUptimeMillis()
601 - SystemClock.uptimeMillis());
602 fout.println(" restartScheduledAt=" + restartTime);
603 }
Adrian Roos7a4f3d42014-05-02 12:12:20 +0200604 if (!simpleNames.add(TrustArchive.getSimpleName(info.component))) {
605 duplicateSimpleNames = true;
606 }
607 }
608 fout.println(" Events:");
609 mArchive.dump(fout, 50, user.id, " " /* linePrefix */, duplicateSimpleNames);
610 fout.println();
611 }
612
613 private String dumpBool(boolean b) {
614 return b ? "1" : "0";
615 }
Adrian Roos82142c22014-03-27 14:56:59 +0100616 };
617
618 private final Handler mHandler = new Handler() {
619 @Override
620 public void handleMessage(Message msg) {
621 switch (msg.what) {
622 case MSG_REGISTER_LISTENER:
623 addListener((ITrustListener) msg.obj);
624 break;
625 case MSG_UNREGISTER_LISTENER:
626 removeListener((ITrustListener) msg.obj);
627 break;
628 case MSG_DISPATCH_UNLOCK_ATTEMPT:
629 dispatchUnlockAttempt(msg.arg1 != 0, msg.arg2);
630 break;
631 case MSG_ENABLED_AGENTS_CHANGED:
Marco Fucci4e68f112014-08-29 12:31:48 -0700632 refreshAgentList(UserHandle.USER_ALL);
Adrian Roos82142c22014-03-27 14:56:59 +0100633 break;
Adrian Roos2c12cfa2014-06-25 23:28:53 +0200634 case MSG_REQUIRE_CREDENTIAL_ENTRY:
635 requireCredentialEntry(msg.arg1);
636 break;
Adrian Roos82142c22014-03-27 14:56:59 +0100637 }
638 }
639 };
640
641 private final PackageMonitor mPackageMonitor = new PackageMonitor() {
642 @Override
643 public void onSomePackagesChanged() {
Marco Fucci4e68f112014-08-29 12:31:48 -0700644 refreshAgentList(UserHandle.USER_ALL);
Adrian Roos82142c22014-03-27 14:56:59 +0100645 }
646
647 @Override
648 public boolean onPackageChanged(String packageName, int uid, String[] components) {
649 // We're interested in all changes, even if just some components get enabled / disabled.
650 return true;
651 }
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200652
653 @Override
654 public void onPackageDisappeared(String packageName, int reason) {
655 removeAgentsOfPackage(packageName);
656 }
Adrian Roos82142c22014-03-27 14:56:59 +0100657 };
Adrian Roosca36b952014-05-16 18:52:29 +0200658
Adrian Roos9dbe1902014-08-13 18:25:52 +0200659 private class Receiver extends BroadcastReceiver {
Adrian Roosca36b952014-05-16 18:52:29 +0200660
661 @Override
662 public void onReceive(Context context, Intent intent) {
Adrian Roos3870d452014-09-05 18:22:28 +0200663 String action = intent.getAction();
664 if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action)) {
Marco Fucci4e68f112014-08-29 12:31:48 -0700665 refreshAgentList(getSendingUserId());
666 updateDevicePolicyFeatures();
Adrian Roos3870d452014-09-05 18:22:28 +0200667 } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
Adrian Roos9dbe1902014-08-13 18:25:52 +0200668 updateUserHasAuthenticated(getSendingUserId());
Adrian Roos3870d452014-09-05 18:22:28 +0200669 } else if (Intent.ACTION_USER_ADDED.equals(action)) {
670 int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -100);
671 if (userId > 0) {
672 maybeEnableFactoryTrustAgents(mLockPatternUtils, userId);
673 } else {
674 Log.wtf(TAG, "EXTRA_USER_HANDLE missing or invalid, value=" + userId);
675 }
Adrian Roosca36b952014-05-16 18:52:29 +0200676 }
677 }
678
679 public void register(Context context) {
Adrian Roos9dbe1902014-08-13 18:25:52 +0200680 IntentFilter filter = new IntentFilter();
681 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
682 filter.addAction(Intent.ACTION_USER_PRESENT);
Adrian Roos3870d452014-09-05 18:22:28 +0200683 filter.addAction(Intent.ACTION_USER_ADDED);
Adrian Roosca36b952014-05-16 18:52:29 +0200684 context.registerReceiverAsUser(this,
685 UserHandle.ALL,
Adrian Roos9dbe1902014-08-13 18:25:52 +0200686 filter,
Adrian Roosca36b952014-05-16 18:52:29 +0200687 null /* permission */,
688 null /* scheduler */);
689 }
690 }
Adrian Roos82142c22014-03-27 14:56:59 +0100691}