blob: 1649535890138be2dc0584779eca11af84d895b8 [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
Adrian Roosbcd07652014-10-22 16:57:16 +020019import com.android.internal.annotations.GuardedBy;
Adrian Roos82142c22014-03-27 14:56:59 +010020import 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;
Adrian Roosbcd07652014-10-22 16:57:16 +020028import android.app.ActivityManager;
Adrian Roos7a4f3d42014-05-02 12:12:20 +020029import android.app.ActivityManagerNative;
Adrian Roosca36b952014-05-16 18:52:29 +020030import android.app.admin.DevicePolicyManager;
Adrian Roos82142c22014-03-27 14:56:59 +010031import android.app.trust.ITrustListener;
32import android.app.trust.ITrustManager;
Adrian Roosca36b952014-05-16 18:52:29 +020033import android.content.BroadcastReceiver;
Adrian Roos82142c22014-03-27 14:56:59 +010034import android.content.ComponentName;
35import android.content.Context;
36import android.content.Intent;
Adrian Roosca36b952014-05-16 18:52:29 +020037import android.content.IntentFilter;
Adrian Roos3870d452014-09-05 18:22:28 +020038import android.content.pm.ApplicationInfo;
Adrian Roos82142c22014-03-27 14:56:59 +010039import 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;
Adrian Roosbcd07652014-10-22 16:57:16 +020046import android.os.Binder;
Adrian Roosa4ba56b2014-05-20 12:56:25 +020047import android.os.DeadObjectException;
Adrian Roos82142c22014-03-27 14:56:59 +010048import android.os.Handler;
49import android.os.IBinder;
50import android.os.Message;
51import android.os.RemoteException;
Adrian Roosc5f95ce2014-07-24 16:00:46 +020052import android.os.SystemClock;
Adrian Roos82142c22014-03-27 14:56:59 +010053import android.os.UserHandle;
54import android.os.UserManager;
Adrian Roos3870d452014-09-05 18:22:28 +020055import android.provider.Settings;
Adrian Roos82142c22014-03-27 14:56:59 +010056import android.service.trust.TrustAgentService;
57import android.util.ArraySet;
58import android.util.AttributeSet;
Adrian Roos18ea8932014-05-28 14:53:06 +020059import android.util.Log;
Adrian Roos82142c22014-03-27 14:56:59 +010060import android.util.Slog;
Adrian Roos7046bfd2014-05-16 21:20:54 +020061import android.util.SparseBooleanArray;
Adrian Roos82142c22014-03-27 14:56:59 +010062import android.util.Xml;
63
Adrian Roos7a4f3d42014-05-02 12:12:20 +020064import java.io.FileDescriptor;
Adrian Roos82142c22014-03-27 14:56:59 +010065import java.io.IOException;
Adrian Roos7a4f3d42014-05-02 12:12:20 +020066import java.io.PrintWriter;
Adrian Roos82142c22014-03-27 14:56:59 +010067import 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);
Adrian Roos18ea8932014-05-28 14:53:06 +020091 private static final String PERMISSION_PROVIDE_AGENT = Manifest.permission.PROVIDE_TRUST_AGENT;
Adrian Roos82142c22014-03-27 14:56:59 +010092
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;
Adrian Roos2c12cfa2014-06-25 23:28:53 +020097 private static final int MSG_REQUIRE_CREDENTIAL_ENTRY = 5;
Adrian Roos82142c22014-03-27 14:56:59 +010098
99 private final ArraySet<AgentInfo> mActiveAgents = new ArraySet<AgentInfo>();
100 private final ArrayList<ITrustListener> mTrustListeners = new ArrayList<ITrustListener>();
Adrian Roos9dbe1902014-08-13 18:25:52 +0200101 private final Receiver mReceiver = new Receiver();
Adrian Roos7046bfd2014-05-16 21:20:54 +0200102 private final SparseBooleanArray mUserHasAuthenticatedSinceBoot = new SparseBooleanArray();
Adrian Roos7a4f3d42014-05-02 12:12:20 +0200103 /* package */ final TrustArchive mArchive = new TrustArchive();
Adrian Roos82142c22014-03-27 14:56:59 +0100104 private final Context mContext;
Adrian Roos3870d452014-09-05 18:22:28 +0200105 private final LockPatternUtils mLockPatternUtils;
Adrian Roosbcd07652014-10-22 16:57:16 +0200106 private final UserManager mUserManager;
Adrian Roos82142c22014-03-27 14:56:59 +0100107
Adrian Roosbcd07652014-10-22 16:57:16 +0200108 @GuardedBy("mUserIsTrusted")
109 private final SparseBooleanArray mUserIsTrusted = new SparseBooleanArray();
Adrian Roos82142c22014-03-27 14:56:59 +0100110
Adrian Roos82142c22014-03-27 14:56:59 +0100111 public TrustManagerService(Context context) {
112 super(context);
113 mContext = context;
114 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
Adrian Roos3870d452014-09-05 18:22:28 +0200115 mLockPatternUtils = new LockPatternUtils(context);
Adrian Roos82142c22014-03-27 14:56:59 +0100116 }
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()) {
Adrian Roos82142c22014-03-27 14:56:59 +0100126 mPackageMonitor.register(mContext, mHandler.getLooper(), UserHandle.ALL, true);
Adrian Roos9dbe1902014-08-13 18:25:52 +0200127 mReceiver.register(mContext);
Marco Fucci4e68f112014-08-29 12:31:48 -0700128 refreshAgentList(UserHandle.USER_ALL);
Adrian Roos7b4a38b2014-10-21 17:07:39 +0200129 } else if (phase == SystemService.PHASE_BOOT_COMPLETED && !isSafeMode()) {
130 maybeEnableFactoryTrustAgents(mLockPatternUtils, UserHandle.USER_OWNER);
Adrian Roos82142c22014-03-27 14:56:59 +0100131 }
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) {
Adrian Roos3c9a3502014-08-06 19:09:45 +0200162 updateTrust(userInfo.id, false);
Adrian Roos82142c22014-03-27 14:56:59 +0100163 }
164 }
165
Adrian Roos3c9a3502014-08-06 19:09:45 +0200166 public void updateTrust(int userId, boolean initiatedByUser) {
Adrian Roos7861c662014-07-25 15:37:28 +0200167 dispatchOnTrustManagedChanged(aggregateIsTrustManaged(userId), userId);
Adrian Roosbcd07652014-10-22 16:57:16 +0200168 boolean trusted = aggregateIsTrusted(userId);
169 synchronized (mUserIsTrusted) {
170 mUserIsTrusted.put(userId, trusted);
171 }
172 dispatchOnTrustChanged(trusted, userId, initiatedByUser);
Adrian Roos82142c22014-03-27 14:56:59 +0100173 }
174
Marco Fucci4e68f112014-08-29 12:31:48 -0700175 void refreshAgentList(int userId) {
Adrian Roos82142c22014-03-27 14:56:59 +0100176 if (DEBUG) Slog.d(TAG, "refreshAgentList()");
Adrian Roose681c272014-09-08 14:03:47 +0200177 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 }
Adrian Roos82142c22014-03-27 14:56:59 +0100182 PackageManager pm = mContext.getPackageManager();
183
Marco Fucci4e68f112014-08-29 12:31:48 -0700184 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 }
Adrian Roos3870d452014-09-05 18:22:28 +0200191 LockPatternUtils lockPatternUtils = mLockPatternUtils;
Adrian Roos82142c22014-03-27 14:56:59 +0100192
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200193 ArraySet<AgentInfo> obsoleteAgents = new ArraySet<>();
194 obsoleteAgents.addAll(mActiveAgents);
Adrian Roos82142c22014-03-27 14:56:59 +0100195
196 for (UserInfo userInfo : userInfos) {
Adrian Roos3870d452014-09-05 18:22:28 +0200197 if (!userInfo.supportsSwitchTo()) continue;
Adrian Roos1572ee32014-09-01 16:24:32 +0200198 if (lockPatternUtils.getKeyguardStoredPasswordQuality(userInfo.id)
Adrian Roos4b9e3242014-08-20 23:36:25 +0200199 == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) continue;
Marco Fucci4e68f112014-08-29 12:31:48 -0700200 if (!mUserHasAuthenticatedSinceBoot.get(userInfo.id)) continue;
Adrian Roos8f211582014-07-29 15:09:57 +0200201 DevicePolicyManager dpm = lockPatternUtils.getDevicePolicyManager();
202 int disabledFeatures = dpm.getKeyguardDisabledFeatures(null, userInfo.id);
Jim Miller604e7552014-07-18 19:00:02 -0700203 final boolean disableTrustAgents =
Adrian Roosca36b952014-05-16 18:52:29 +0200204 (disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0;
205
Adrian Roos82142c22014-03-27 14:56:59 +0100206 List<ComponentName> enabledAgents = lockPatternUtils.getEnabledTrustAgents(userInfo.id);
Adrian Roos8f211582014-07-29 15:09:57 +0200207 if (enabledAgents == null) {
Adrian Roos82142c22014-03-27 14:56:59 +0100208 continue;
209 }
Adrian Roos3870d452014-09-05 18:22:28 +0200210 List<ResolveInfo> resolveInfos = resolveAllowedTrustAgents(pm, userInfo.id);
Adrian Roos82142c22014-03-27 14:56:59 +0100211 for (ResolveInfo resolveInfo : resolveInfos) {
Adrian Roos82142c22014-03-27 14:56:59 +0100212 ComponentName name = getComponentName(resolveInfo);
Adrian Roos82142c22014-03-27 14:56:59 +0100213
Adrian Roos3870d452014-09-05 18:22:28 +0200214 if (!enabledAgents.contains(name)) continue;
Adrian Roos8f211582014-07-29 15:09:57 +0200215 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
Adrian Roos82142c22014-03-27 14:56:59 +0100222 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 {
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200233 obsoleteAgents.remove(agentInfo);
Adrian Roos82142c22014-03-27 14:56:59 +0100234 }
235 }
236 }
237
238 boolean trustMayHaveChanged = false;
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200239 for (int i = 0; i < obsoleteAgents.size(); i++) {
240 AgentInfo info = obsoleteAgents.valueAt(i);
Adrian Roose681c272014-09-08 14:03:47 +0200241 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);
Adrian Roos82142c22014-03-27 14:56:59 +0100247 }
Adrian Roos82142c22014-03-27 14:56:59 +0100248 }
249
250 if (trustMayHaveChanged) {
251 updateTrustAll();
252 }
253 }
254
Marco Fucci4e68f112014-08-29 12:31:48 -0700255 void updateDevicePolicyFeatures() {
Adrian Roos8f211582014-07-29 15:09:57 +0200256 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
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200264 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());
Adrian Roos7861c662014-07-25 15:37:28 +0200270 if (info.agent.isManagingTrust()) {
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200271 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());
Adrian Roos7861c662014-07-25 15:37:28 +0200288 if (info.agent.isManagingTrust()) {
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200289 trustMayHaveChanged = true;
290 }
291 info.agent.unbind();
292 mActiveAgents.removeAt(i);
293 }
294 }
295 if (trustMayHaveChanged) {
Adrian Roos3c9a3502014-08-06 19:09:45 +0200296 updateTrust(userId, false);
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200297 }
Marco Fucci4e68f112014-08-29 12:31:48 -0700298 refreshAgentList(userId);
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200299 }
300
Adrian Roos82142c22014-03-27 14:56:59 +0100301 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();
Adrian Roos7e03dfc2014-05-16 16:06:28 +0200322 if (!"trust-agent".equals(nodeName)) {
323 Slog.w(TAG, "Meta-data does not start with trust-agent tag");
Adrian Roos82142c22014-03-27 14:56:59 +0100324 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
Adrian Roos3870d452014-09-05 18:22:28 +0200357 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
Adrian Roos82142c22014-03-27 14:56:59 +0100405 // Agent dispatch and aggregation
406
407 private boolean aggregateIsTrusted(int userId) {
Adrian Roos7046bfd2014-05-16 21:20:54 +0200408 if (!mUserHasAuthenticatedSinceBoot.get(userId)) {
409 return false;
410 }
Adrian Roos82142c22014-03-27 14:56:59 +0100411 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
Adrian Roos7861c662014-07-25 15:37:28 +0200422 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
Adrian Roos82142c22014-03-27 14:56:59 +0100437 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 }
Adrian Roos7046bfd2014-05-16 21:20:54 +0200444
Adrian Roos9dbe1902014-08-13 18:25:52 +0200445 if (successful) {
446 updateUserHasAuthenticated(userId);
447 }
448 }
449
450 private void updateUserHasAuthenticated(int userId) {
451 if (!mUserHasAuthenticatedSinceBoot.get(userId)) {
Adrian Roos7046bfd2014-05-16 21:20:54 +0200452 mUserHasAuthenticatedSinceBoot.put(userId, true);
Marco Fucci4e68f112014-08-29 12:31:48 -0700453 refreshAgentList(userId);
Adrian Roos7046bfd2014-05-16 21:20:54 +0200454 }
Adrian Roos82142c22014-03-27 14:56:59 +0100455 }
456
Adrian Roos2c12cfa2014-06-25 23:28:53 +0200457
458 private void requireCredentialEntry(int userId) {
459 if (userId == UserHandle.USER_ALL) {
460 mUserHasAuthenticatedSinceBoot.clear();
Marco Fucci4e68f112014-08-29 12:31:48 -0700461 refreshAgentList(UserHandle.USER_ALL);
Adrian Roos2c12cfa2014-06-25 23:28:53 +0200462 } else {
463 mUserHasAuthenticatedSinceBoot.put(userId, false);
Marco Fucci4e68f112014-08-29 12:31:48 -0700464 refreshAgentList(userId);
Adrian Roos2c12cfa2014-06-25 23:28:53 +0200465 }
466 }
467
Adrian Roos82142c22014-03-27 14:56:59 +0100468 // 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);
Adrian Roos3870d452014-09-05 18:22:28 +0200477 updateTrustAll();
Adrian Roos82142c22014-03-27 14:56:59 +0100478 }
479
480 private void removeListener(ITrustListener listener) {
481 for (int i = 0; i < mTrustListeners.size(); i++) {
482 if (mTrustListeners.get(i).asBinder() == listener.asBinder()) {
Jay Civelli979a32e2014-07-18 16:47:36 -0700483 mTrustListeners.remove(i);
Adrian Roos82142c22014-03-27 14:56:59 +0100484 return;
485 }
486 }
487 }
488
Adrian Roos3c9a3502014-08-06 19:09:45 +0200489 private void dispatchOnTrustChanged(boolean enabled, int userId, boolean initiatedByUser) {
490 if (!enabled) initiatedByUser = false;
Adrian Roos82142c22014-03-27 14:56:59 +0100491 for (int i = 0; i < mTrustListeners.size(); i++) {
492 try {
Adrian Roos3c9a3502014-08-06 19:09:45 +0200493 mTrustListeners.get(i).onTrustChanged(enabled, userId, initiatedByUser);
Adrian Roosa4ba56b2014-05-20 12:56:25 +0200494 } catch (DeadObjectException e) {
Adrian Roos7861c662014-07-25 15:37:28 +0200495 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.");
Adrian Roosa4ba56b2014-05-20 12:56:25 +0200510 mTrustListeners.remove(i);
511 i--;
Adrian Roos82142c22014-03-27 14:56:59 +0100512 } catch (RemoteException e) {
Adrian Roosa4ba56b2014-05-20 12:56:25 +0200513 Slog.e(TAG, "Exception while notifying TrustListener.", e);
Adrian Roos82142c22014-03-27 14:56:59 +0100514 }
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
Adrian Roos2c12cfa2014-06-25 23:28:53 +0200537 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
Adrian Roos82142c22014-03-27 14:56:59 +0100548 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
Adrian Roosbcd07652014-10-22 16:57:16 +0200559 @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
Adrian Roos82142c22014-03-27 14:56:59 +0100569 private void enforceReportPermission() {
Adrian Roos2c12cfa2014-06-25 23:28:53 +0200570 mContext.enforceCallingOrSelfPermission(
571 Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE, "reporting trust events");
Adrian Roos82142c22014-03-27 14:56:59 +0100572 }
573
574 private void enforceListenerPermission() {
575 mContext.enforceCallingPermission(Manifest.permission.TRUST_LISTENER,
576 "register trust listener");
577 }
Adrian Roos7a4f3d42014-05-02 12:12:20 +0200578
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)));
Adrian Roos7861c662014-07-25 15:37:28 +0200608 fout.print(", trustManaged=" + dumpBool(aggregateIsTrustManaged(user.id)));
Adrian Roos7a4f3d42014-05-02 12:12:20 +0200609 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());
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200617 fout.print(" bound=" + dumpBool(info.agent.isBound()));
618 fout.print(", connected=" + dumpBool(info.agent.isConnected()));
Adrian Roos7861c662014-07-25 15:37:28 +0200619 fout.print(", managingTrust=" + dumpBool(info.agent.isManagingTrust()));
620 fout.print(", trusted=" + dumpBool(trusted));
621 fout.println();
Adrian Roos7a4f3d42014-05-02 12:12:20 +0200622 if (trusted) {
623 fout.println(" message=\"" + info.agent.getMessage() + "\"");
624 }
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200625 if (!info.agent.isConnected()) {
626 String restartTime = TrustArchive.formatDuration(
627 info.agent.getScheduledRestartUptimeMillis()
628 - SystemClock.uptimeMillis());
629 fout.println(" restartScheduledAt=" + restartTime);
630 }
Adrian Roos7a4f3d42014-05-02 12:12:20 +0200631 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 }
Adrian Roos82142c22014-03-27 14:56:59 +0100643 };
644
Adrian Roosbcd07652014-10-22 16:57:16 +0200645 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
Adrian Roos82142c22014-03-27 14:56:59 +0100658 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:
Marco Fucci4e68f112014-08-29 12:31:48 -0700672 refreshAgentList(UserHandle.USER_ALL);
Adrian Roos82142c22014-03-27 14:56:59 +0100673 break;
Adrian Roos2c12cfa2014-06-25 23:28:53 +0200674 case MSG_REQUIRE_CREDENTIAL_ENTRY:
675 requireCredentialEntry(msg.arg1);
676 break;
Adrian Roos82142c22014-03-27 14:56:59 +0100677 }
678 }
679 };
680
681 private final PackageMonitor mPackageMonitor = new PackageMonitor() {
682 @Override
683 public void onSomePackagesChanged() {
Marco Fucci4e68f112014-08-29 12:31:48 -0700684 refreshAgentList(UserHandle.USER_ALL);
Adrian Roos82142c22014-03-27 14:56:59 +0100685 }
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 }
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200692
693 @Override
694 public void onPackageDisappeared(String packageName, int reason) {
695 removeAgentsOfPackage(packageName);
696 }
Adrian Roos82142c22014-03-27 14:56:59 +0100697 };
Adrian Roosca36b952014-05-16 18:52:29 +0200698
Adrian Roos9dbe1902014-08-13 18:25:52 +0200699 private class Receiver extends BroadcastReceiver {
Adrian Roosca36b952014-05-16 18:52:29 +0200700
701 @Override
702 public void onReceive(Context context, Intent intent) {
Adrian Roos3870d452014-09-05 18:22:28 +0200703 String action = intent.getAction();
704 if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action)) {
Marco Fucci4e68f112014-08-29 12:31:48 -0700705 refreshAgentList(getSendingUserId());
706 updateDevicePolicyFeatures();
Adrian Roos3870d452014-09-05 18:22:28 +0200707 } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
Adrian Roos9dbe1902014-08-13 18:25:52 +0200708 updateUserHasAuthenticated(getSendingUserId());
Adrian Roos3870d452014-09-05 18:22:28 +0200709 } 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 }
Adrian Roosca36b952014-05-16 18:52:29 +0200716 }
717 }
718
719 public void register(Context context) {
Adrian Roos9dbe1902014-08-13 18:25:52 +0200720 IntentFilter filter = new IntentFilter();
721 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
722 filter.addAction(Intent.ACTION_USER_PRESENT);
Adrian Roos3870d452014-09-05 18:22:28 +0200723 filter.addAction(Intent.ACTION_USER_ADDED);
Adrian Roosca36b952014-05-16 18:52:29 +0200724 context.registerReceiverAsUser(this,
725 UserHandle.ALL,
Adrian Roos9dbe1902014-08-13 18:25:52 +0200726 filter,
Adrian Roosca36b952014-05-16 18:52:29 +0200727 null /* permission */,
728 null /* scheduler */);
729 }
730 }
Adrian Roos82142c22014-03-27 14:56:59 +0100731}