blob: 2388c854fae0ba718a01a8a7bb5f6ed5e1ec565d [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;
Jim Millere303bf42014-08-26 17:12:29 -070051import android.os.PersistableBundle;
Adrian Roos82142c22014-03-27 14:56:59 +010052import android.os.RemoteException;
Adrian Roosc5f95ce2014-07-24 16:00:46 +020053import android.os.SystemClock;
Adrian Roos82142c22014-03-27 14:56:59 +010054import android.os.UserHandle;
55import android.os.UserManager;
Adrian Roos3870d452014-09-05 18:22:28 +020056import android.provider.Settings;
Adrian Roos82142c22014-03-27 14:56:59 +010057import android.service.trust.TrustAgentService;
58import android.util.ArraySet;
59import android.util.AttributeSet;
Adrian Roos18ea8932014-05-28 14:53:06 +020060import android.util.Log;
Adrian Roos82142c22014-03-27 14:56:59 +010061import android.util.Slog;
Adrian Roos7046bfd2014-05-16 21:20:54 +020062import android.util.SparseBooleanArray;
Adrian Roos82142c22014-03-27 14:56:59 +010063import android.util.Xml;
64
Adrian Roos7a4f3d42014-05-02 12:12:20 +020065import java.io.FileDescriptor;
Adrian Roos82142c22014-03-27 14:56:59 +010066import java.io.IOException;
Adrian Roos7a4f3d42014-05-02 12:12:20 +020067import java.io.PrintWriter;
Adrian Roos82142c22014-03-27 14:56:59 +010068import java.util.ArrayList;
69import java.util.List;
70
71/**
72 * Manages trust agents and trust listeners.
73 *
74 * It is responsible for binding to the enabled {@link android.service.trust.TrustAgentService}s
75 * of each user and notifies them about events that are relevant to them.
76 * It start and stops them based on the value of
77 * {@link com.android.internal.widget.LockPatternUtils#getEnabledTrustAgents(int)}.
78 *
79 * It also keeps a set of {@link android.app.trust.ITrustListener}s that are notified whenever the
80 * trust state changes for any user.
81 *
82 * Trust state and the setting of enabled agents is kept per user and each user has its own
83 * instance of a {@link android.service.trust.TrustAgentService}.
84 */
85public class TrustManagerService extends SystemService {
86
87 private static final boolean DEBUG = false;
88 private static final String TAG = "TrustManagerService";
89
90 private static final Intent TRUST_AGENT_INTENT =
91 new Intent(TrustAgentService.SERVICE_INTERFACE);
Adrian Roos18ea8932014-05-28 14:53:06 +020092 private static final String PERMISSION_PROVIDE_AGENT = Manifest.permission.PROVIDE_TRUST_AGENT;
Adrian Roos82142c22014-03-27 14:56:59 +010093
94 private static final int MSG_REGISTER_LISTENER = 1;
95 private static final int MSG_UNREGISTER_LISTENER = 2;
96 private static final int MSG_DISPATCH_UNLOCK_ATTEMPT = 3;
97 private static final int MSG_ENABLED_AGENTS_CHANGED = 4;
Adrian Roos2c12cfa2014-06-25 23:28:53 +020098 private static final int MSG_REQUIRE_CREDENTIAL_ENTRY = 5;
Adrian Roos82142c22014-03-27 14:56:59 +010099
100 private final ArraySet<AgentInfo> mActiveAgents = new ArraySet<AgentInfo>();
101 private final ArrayList<ITrustListener> mTrustListeners = new ArrayList<ITrustListener>();
Adrian Roos9dbe1902014-08-13 18:25:52 +0200102 private final Receiver mReceiver = new Receiver();
Adrian Roos7046bfd2014-05-16 21:20:54 +0200103 private final SparseBooleanArray mUserHasAuthenticatedSinceBoot = new SparseBooleanArray();
Adrian Roos7a4f3d42014-05-02 12:12:20 +0200104 /* package */ final TrustArchive mArchive = new TrustArchive();
Adrian Roos82142c22014-03-27 14:56:59 +0100105 private final Context mContext;
Adrian Roos3870d452014-09-05 18:22:28 +0200106 private final LockPatternUtils mLockPatternUtils;
Adrian Roosbcd07652014-10-22 16:57:16 +0200107 private final UserManager mUserManager;
Adrian Rooscbe614f2014-10-28 20:16:12 +0100108 private final ActivityManager mActivityManager;
Adrian Roos82142c22014-03-27 14:56:59 +0100109
Adrian Roosbcd07652014-10-22 16:57:16 +0200110 @GuardedBy("mUserIsTrusted")
111 private final SparseBooleanArray mUserIsTrusted = new SparseBooleanArray();
Adrian Roos82142c22014-03-27 14:56:59 +0100112
Adrian Rooscbe614f2014-10-28 20:16:12 +0100113 private boolean mTrustAgentsCanRun = false;
114
Adrian Roos82142c22014-03-27 14:56:59 +0100115 public TrustManagerService(Context context) {
116 super(context);
117 mContext = context;
118 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
Adrian Rooscbe614f2014-10-28 20:16:12 +0100119 mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
Adrian Roos3870d452014-09-05 18:22:28 +0200120 mLockPatternUtils = new LockPatternUtils(context);
Adrian Roos82142c22014-03-27 14:56:59 +0100121 }
122
123 @Override
124 public void onStart() {
125 publishBinderService(Context.TRUST_SERVICE, mService);
126 }
127
128 @Override
129 public void onBootPhase(int phase) {
Adrian Roos49d53452014-10-24 15:48:39 +0200130 if (isSafeMode()) {
131 // No trust agents in safe mode.
132 return;
133 }
134 if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
Adrian Roos82142c22014-03-27 14:56:59 +0100135 mPackageMonitor.register(mContext, mHandler.getLooper(), UserHandle.ALL, true);
Adrian Roos9dbe1902014-08-13 18:25:52 +0200136 mReceiver.register(mContext);
Adrian Rooscbe614f2014-10-28 20:16:12 +0100137 } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
138 mTrustAgentsCanRun = true;
Marco Fucci4e68f112014-08-29 12:31:48 -0700139 refreshAgentList(UserHandle.USER_ALL);
Adrian Roos49d53452014-10-24 15:48:39 +0200140 } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
Adrian Roos7b4a38b2014-10-21 17:07:39 +0200141 maybeEnableFactoryTrustAgents(mLockPatternUtils, UserHandle.USER_OWNER);
Adrian Roos82142c22014-03-27 14:56:59 +0100142 }
143 }
144
145 // Agent management
146
147 private static final class AgentInfo {
148 CharSequence label;
149 Drawable icon;
150 ComponentName component; // service that implements ITrustAgent
151 ComponentName settings; // setting to launch to modify agent.
152 TrustAgentWrapper agent;
153 int userId;
154
155 @Override
156 public boolean equals(Object other) {
157 if (!(other instanceof AgentInfo)) {
158 return false;
159 }
160 AgentInfo o = (AgentInfo) other;
161 return component.equals(o.component) && userId == o.userId;
162 }
163
164 @Override
165 public int hashCode() {
166 return component.hashCode() * 31 + userId;
167 }
168 }
169
170 private void updateTrustAll() {
171 List<UserInfo> userInfos = mUserManager.getUsers(true /* excludeDying */);
172 for (UserInfo userInfo : userInfos) {
Adrian Roos3c9a3502014-08-06 19:09:45 +0200173 updateTrust(userInfo.id, false);
Adrian Roos82142c22014-03-27 14:56:59 +0100174 }
175 }
176
Adrian Roos3c9a3502014-08-06 19:09:45 +0200177 public void updateTrust(int userId, boolean initiatedByUser) {
Adrian Roos7861c662014-07-25 15:37:28 +0200178 dispatchOnTrustManagedChanged(aggregateIsTrustManaged(userId), userId);
Adrian Roosbcd07652014-10-22 16:57:16 +0200179 boolean trusted = aggregateIsTrusted(userId);
180 synchronized (mUserIsTrusted) {
181 mUserIsTrusted.put(userId, trusted);
182 }
183 dispatchOnTrustChanged(trusted, userId, initiatedByUser);
Adrian Roos82142c22014-03-27 14:56:59 +0100184 }
185
Marco Fucci4e68f112014-08-29 12:31:48 -0700186 void refreshAgentList(int userId) {
Adrian Roos82142c22014-03-27 14:56:59 +0100187 if (DEBUG) Slog.d(TAG, "refreshAgentList()");
Adrian Rooscbe614f2014-10-28 20:16:12 +0100188 if (!mTrustAgentsCanRun) {
Adrian Roos49d53452014-10-24 15:48:39 +0200189 return;
190 }
Adrian Roose681c272014-09-08 14:03:47 +0200191 if (userId != UserHandle.USER_ALL && userId < UserHandle.USER_OWNER) {
192 Log.e(TAG, "refreshAgentList(userId=" + userId + "): Invalid user handle,"
193 + " must be USER_ALL or a specific user.", new Throwable("here"));
194 userId = UserHandle.USER_ALL;
195 }
Adrian Roos82142c22014-03-27 14:56:59 +0100196 PackageManager pm = mContext.getPackageManager();
197
Marco Fucci4e68f112014-08-29 12:31:48 -0700198 List<UserInfo> userInfos;
199 if (userId == UserHandle.USER_ALL) {
200 userInfos = mUserManager.getUsers(true /* excludeDying */);
201 } else {
202 userInfos = new ArrayList<>();
203 userInfos.add(mUserManager.getUserInfo(userId));
204 }
Adrian Roos3870d452014-09-05 18:22:28 +0200205 LockPatternUtils lockPatternUtils = mLockPatternUtils;
Adrian Roos82142c22014-03-27 14:56:59 +0100206
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200207 ArraySet<AgentInfo> obsoleteAgents = new ArraySet<>();
208 obsoleteAgents.addAll(mActiveAgents);
Adrian Roos82142c22014-03-27 14:56:59 +0100209
210 for (UserInfo userInfo : userInfos) {
Adrian Roosfc29e0b2014-11-11 12:55:44 +0100211 if (userInfo == null || userInfo.partial || !userInfo.isEnabled()
212 || userInfo.guestToRemove) continue;
Adrian Roos3870d452014-09-05 18:22:28 +0200213 if (!userInfo.supportsSwitchTo()) continue;
Adrian Rooscbe614f2014-10-28 20:16:12 +0100214 if (!mActivityManager.isUserRunning(userInfo.id)) continue;
Adrian Roos1572ee32014-09-01 16:24:32 +0200215 if (lockPatternUtils.getKeyguardStoredPasswordQuality(userInfo.id)
Adrian Roos4b9e3242014-08-20 23:36:25 +0200216 == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) continue;
Marco Fucci4e68f112014-08-29 12:31:48 -0700217 if (!mUserHasAuthenticatedSinceBoot.get(userInfo.id)) continue;
Adrian Roos8f211582014-07-29 15:09:57 +0200218 DevicePolicyManager dpm = lockPatternUtils.getDevicePolicyManager();
219 int disabledFeatures = dpm.getKeyguardDisabledFeatures(null, userInfo.id);
Jim Miller604e7552014-07-18 19:00:02 -0700220 final boolean disableTrustAgents =
Adrian Roosca36b952014-05-16 18:52:29 +0200221 (disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0;
222
Adrian Roos82142c22014-03-27 14:56:59 +0100223 List<ComponentName> enabledAgents = lockPatternUtils.getEnabledTrustAgents(userInfo.id);
Adrian Roos8f211582014-07-29 15:09:57 +0200224 if (enabledAgents == null) {
Adrian Roos82142c22014-03-27 14:56:59 +0100225 continue;
226 }
Adrian Roos3870d452014-09-05 18:22:28 +0200227 List<ResolveInfo> resolveInfos = resolveAllowedTrustAgents(pm, userInfo.id);
Adrian Roos82142c22014-03-27 14:56:59 +0100228 for (ResolveInfo resolveInfo : resolveInfos) {
Adrian Roos82142c22014-03-27 14:56:59 +0100229 ComponentName name = getComponentName(resolveInfo);
Adrian Roos82142c22014-03-27 14:56:59 +0100230
Adrian Roos3870d452014-09-05 18:22:28 +0200231 if (!enabledAgents.contains(name)) continue;
Adrian Roos8f211582014-07-29 15:09:57 +0200232 if (disableTrustAgents) {
Jim Millere303bf42014-08-26 17:12:29 -0700233 List<PersistableBundle> config =
234 dpm.getTrustAgentConfiguration(null /* admin */, name, userInfo.id);
Adrian Roos8f211582014-07-29 15:09:57 +0200235 // Disable agent if no features are enabled.
Jim Millere303bf42014-08-26 17:12:29 -0700236 if (config == null || config.isEmpty()) continue;
Adrian Roos8f211582014-07-29 15:09:57 +0200237 }
238
Adrian Roos82142c22014-03-27 14:56:59 +0100239 AgentInfo agentInfo = new AgentInfo();
240 agentInfo.component = name;
241 agentInfo.userId = userInfo.id;
242 if (!mActiveAgents.contains(agentInfo)) {
243 agentInfo.label = resolveInfo.loadLabel(pm);
244 agentInfo.icon = resolveInfo.loadIcon(pm);
245 agentInfo.settings = getSettingsComponentName(pm, resolveInfo);
246 agentInfo.agent = new TrustAgentWrapper(mContext, this,
247 new Intent().setComponent(name), userInfo.getUserHandle());
248 mActiveAgents.add(agentInfo);
249 } else {
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200250 obsoleteAgents.remove(agentInfo);
Adrian Roos82142c22014-03-27 14:56:59 +0100251 }
252 }
253 }
254
255 boolean trustMayHaveChanged = false;
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200256 for (int i = 0; i < obsoleteAgents.size(); i++) {
257 AgentInfo info = obsoleteAgents.valueAt(i);
Adrian Roose681c272014-09-08 14:03:47 +0200258 if (userId == UserHandle.USER_ALL || userId == info.userId) {
259 if (info.agent.isManagingTrust()) {
260 trustMayHaveChanged = true;
261 }
Adrian Roosfc29e0b2014-11-11 12:55:44 +0100262 info.agent.destroy();
Adrian Roose681c272014-09-08 14:03:47 +0200263 mActiveAgents.remove(info);
Adrian Roos82142c22014-03-27 14:56:59 +0100264 }
Adrian Roos82142c22014-03-27 14:56:59 +0100265 }
266
267 if (trustMayHaveChanged) {
Adrian Rooscbe614f2014-10-28 20:16:12 +0100268 if (userId == UserHandle.USER_ALL) {
269 updateTrustAll();
270 } else {
271 updateTrust(userId, false /* initiatedByUser */);
272 }
Adrian Roos82142c22014-03-27 14:56:59 +0100273 }
274 }
275
Marco Fucci4e68f112014-08-29 12:31:48 -0700276 void updateDevicePolicyFeatures() {
Adrian Roos8f211582014-07-29 15:09:57 +0200277 for (int i = 0; i < mActiveAgents.size(); i++) {
278 AgentInfo info = mActiveAgents.valueAt(i);
279 if (info.agent.isConnected()) {
280 info.agent.updateDevicePolicyFeatures();
281 }
282 }
283 }
284
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200285 private void removeAgentsOfPackage(String packageName) {
286 boolean trustMayHaveChanged = false;
287 for (int i = mActiveAgents.size() - 1; i >= 0; i--) {
288 AgentInfo info = mActiveAgents.valueAt(i);
289 if (packageName.equals(info.component.getPackageName())) {
290 Log.i(TAG, "Resetting agent " + info.component.flattenToShortString());
Adrian Roos7861c662014-07-25 15:37:28 +0200291 if (info.agent.isManagingTrust()) {
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200292 trustMayHaveChanged = true;
293 }
Adrian Roosfc29e0b2014-11-11 12:55:44 +0100294 info.agent.destroy();
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200295 mActiveAgents.removeAt(i);
296 }
297 }
298 if (trustMayHaveChanged) {
299 updateTrustAll();
300 }
301 }
302
303 public void resetAgent(ComponentName name, int userId) {
304 boolean trustMayHaveChanged = false;
305 for (int i = mActiveAgents.size() - 1; i >= 0; i--) {
306 AgentInfo info = mActiveAgents.valueAt(i);
307 if (name.equals(info.component) && userId == info.userId) {
308 Log.i(TAG, "Resetting agent " + info.component.flattenToShortString());
Adrian Roos7861c662014-07-25 15:37:28 +0200309 if (info.agent.isManagingTrust()) {
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200310 trustMayHaveChanged = true;
311 }
Adrian Roosfc29e0b2014-11-11 12:55:44 +0100312 info.agent.destroy();
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200313 mActiveAgents.removeAt(i);
314 }
315 }
316 if (trustMayHaveChanged) {
Adrian Roos3c9a3502014-08-06 19:09:45 +0200317 updateTrust(userId, false);
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200318 }
Marco Fucci4e68f112014-08-29 12:31:48 -0700319 refreshAgentList(userId);
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200320 }
321
Adrian Roos82142c22014-03-27 14:56:59 +0100322 private ComponentName getSettingsComponentName(PackageManager pm, ResolveInfo resolveInfo) {
323 if (resolveInfo == null || resolveInfo.serviceInfo == null
324 || resolveInfo.serviceInfo.metaData == null) return null;
325 String cn = null;
326 XmlResourceParser parser = null;
327 Exception caughtException = null;
328 try {
329 parser = resolveInfo.serviceInfo.loadXmlMetaData(pm,
330 TrustAgentService.TRUST_AGENT_META_DATA);
331 if (parser == null) {
332 Slog.w(TAG, "Can't find " + TrustAgentService.TRUST_AGENT_META_DATA + " meta-data");
333 return null;
334 }
335 Resources res = pm.getResourcesForApplication(resolveInfo.serviceInfo.applicationInfo);
336 AttributeSet attrs = Xml.asAttributeSet(parser);
337 int type;
338 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
339 && type != XmlPullParser.START_TAG) {
340 // Drain preamble.
341 }
342 String nodeName = parser.getName();
Adrian Roos7e03dfc2014-05-16 16:06:28 +0200343 if (!"trust-agent".equals(nodeName)) {
344 Slog.w(TAG, "Meta-data does not start with trust-agent tag");
Adrian Roos82142c22014-03-27 14:56:59 +0100345 return null;
346 }
347 TypedArray sa = res
348 .obtainAttributes(attrs, com.android.internal.R.styleable.TrustAgent);
349 cn = sa.getString(com.android.internal.R.styleable.TrustAgent_settingsActivity);
350 sa.recycle();
351 } catch (PackageManager.NameNotFoundException e) {
352 caughtException = e;
353 } catch (IOException e) {
354 caughtException = e;
355 } catch (XmlPullParserException e) {
356 caughtException = e;
357 } finally {
358 if (parser != null) parser.close();
359 }
360 if (caughtException != null) {
361 Slog.w(TAG, "Error parsing : " + resolveInfo.serviceInfo.packageName, caughtException);
362 return null;
363 }
364 if (cn == null) {
365 return null;
366 }
367 if (cn.indexOf('/') < 0) {
368 cn = resolveInfo.serviceInfo.packageName + "/" + cn;
369 }
370 return ComponentName.unflattenFromString(cn);
371 }
372
373 private ComponentName getComponentName(ResolveInfo resolveInfo) {
374 if (resolveInfo == null || resolveInfo.serviceInfo == null) return null;
375 return new ComponentName(resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name);
376 }
377
Adrian Roos3870d452014-09-05 18:22:28 +0200378 private void maybeEnableFactoryTrustAgents(LockPatternUtils utils, int userId) {
379 if (0 != Settings.Secure.getIntForUser(mContext.getContentResolver(),
380 Settings.Secure.TRUST_AGENTS_INITIALIZED, 0, userId)) {
381 return;
382 }
383 PackageManager pm = mContext.getPackageManager();
384 List<ResolveInfo> resolveInfos = resolveAllowedTrustAgents(pm, userId);
385 ArraySet<ComponentName> discoveredAgents = new ArraySet<>();
386 for (ResolveInfo resolveInfo : resolveInfos) {
387 ComponentName componentName = getComponentName(resolveInfo);
388 int applicationInfoFlags = resolveInfo.serviceInfo.applicationInfo.flags;
389 if ((applicationInfoFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
390 Log.i(TAG, "Leaving agent " + componentName + " disabled because package "
391 + "is not a system package.");
392 continue;
393 }
394 discoveredAgents.add(componentName);
395 }
396
397 List<ComponentName> previouslyEnabledAgents = utils.getEnabledTrustAgents(userId);
398 if (previouslyEnabledAgents != null) {
399 discoveredAgents.addAll(previouslyEnabledAgents);
400 }
401 utils.setEnabledTrustAgents(discoveredAgents, userId);
402 Settings.Secure.putIntForUser(mContext.getContentResolver(),
403 Settings.Secure.TRUST_AGENTS_INITIALIZED, 1, userId);
404 }
405
406 private List<ResolveInfo> resolveAllowedTrustAgents(PackageManager pm, int userId) {
407 List<ResolveInfo> resolveInfos = pm.queryIntentServicesAsUser(TRUST_AGENT_INTENT,
408 0 /* flags */, userId);
409 ArrayList<ResolveInfo> allowedAgents = new ArrayList<>(resolveInfos.size());
410 for (ResolveInfo resolveInfo : resolveInfos) {
411 if (resolveInfo.serviceInfo == null) continue;
412 if (resolveInfo.serviceInfo.applicationInfo == null) continue;
413 String packageName = resolveInfo.serviceInfo.packageName;
414 if (pm.checkPermission(PERMISSION_PROVIDE_AGENT, packageName)
415 != PackageManager.PERMISSION_GRANTED) {
416 ComponentName name = getComponentName(resolveInfo);
417 Log.w(TAG, "Skipping agent " + name + " because package does not have"
418 + " permission " + PERMISSION_PROVIDE_AGENT + ".");
419 continue;
420 }
421 allowedAgents.add(resolveInfo);
422 }
423 return allowedAgents;
424 }
425
Adrian Roos82142c22014-03-27 14:56:59 +0100426 // Agent dispatch and aggregation
427
428 private boolean aggregateIsTrusted(int userId) {
Adrian Roos7046bfd2014-05-16 21:20:54 +0200429 if (!mUserHasAuthenticatedSinceBoot.get(userId)) {
430 return false;
431 }
Adrian Roos82142c22014-03-27 14:56:59 +0100432 for (int i = 0; i < mActiveAgents.size(); i++) {
433 AgentInfo info = mActiveAgents.valueAt(i);
434 if (info.userId == userId) {
435 if (info.agent.isTrusted()) {
436 return true;
437 }
438 }
439 }
440 return false;
441 }
442
Adrian Roos7861c662014-07-25 15:37:28 +0200443 private boolean aggregateIsTrustManaged(int userId) {
444 if (!mUserHasAuthenticatedSinceBoot.get(userId)) {
445 return false;
446 }
447 for (int i = 0; i < mActiveAgents.size(); i++) {
448 AgentInfo info = mActiveAgents.valueAt(i);
449 if (info.userId == userId) {
450 if (info.agent.isManagingTrust()) {
451 return true;
452 }
453 }
454 }
455 return false;
456 }
457
Adrian Roos82142c22014-03-27 14:56:59 +0100458 private void dispatchUnlockAttempt(boolean successful, int userId) {
459 for (int i = 0; i < mActiveAgents.size(); i++) {
460 AgentInfo info = mActiveAgents.valueAt(i);
461 if (info.userId == userId) {
462 info.agent.onUnlockAttempt(successful);
463 }
464 }
Adrian Roos7046bfd2014-05-16 21:20:54 +0200465
Adrian Roos9dbe1902014-08-13 18:25:52 +0200466 if (successful) {
467 updateUserHasAuthenticated(userId);
468 }
469 }
470
471 private void updateUserHasAuthenticated(int userId) {
472 if (!mUserHasAuthenticatedSinceBoot.get(userId)) {
Adrian Roos7046bfd2014-05-16 21:20:54 +0200473 mUserHasAuthenticatedSinceBoot.put(userId, true);
Marco Fucci4e68f112014-08-29 12:31:48 -0700474 refreshAgentList(userId);
Adrian Roos7046bfd2014-05-16 21:20:54 +0200475 }
Adrian Roos82142c22014-03-27 14:56:59 +0100476 }
477
Adrian Roos2c12cfa2014-06-25 23:28:53 +0200478
479 private void requireCredentialEntry(int userId) {
480 if (userId == UserHandle.USER_ALL) {
481 mUserHasAuthenticatedSinceBoot.clear();
Marco Fucci4e68f112014-08-29 12:31:48 -0700482 refreshAgentList(UserHandle.USER_ALL);
Adrian Roos2c12cfa2014-06-25 23:28:53 +0200483 } else {
484 mUserHasAuthenticatedSinceBoot.put(userId, false);
Marco Fucci4e68f112014-08-29 12:31:48 -0700485 refreshAgentList(userId);
Adrian Roos2c12cfa2014-06-25 23:28:53 +0200486 }
487 }
488
Adrian Roos82142c22014-03-27 14:56:59 +0100489 // Listeners
490
491 private void addListener(ITrustListener listener) {
492 for (int i = 0; i < mTrustListeners.size(); i++) {
493 if (mTrustListeners.get(i).asBinder() == listener.asBinder()) {
494 return;
495 }
496 }
497 mTrustListeners.add(listener);
Adrian Roos3870d452014-09-05 18:22:28 +0200498 updateTrustAll();
Adrian Roos82142c22014-03-27 14:56:59 +0100499 }
500
501 private void removeListener(ITrustListener listener) {
502 for (int i = 0; i < mTrustListeners.size(); i++) {
503 if (mTrustListeners.get(i).asBinder() == listener.asBinder()) {
Jay Civelli979a32e2014-07-18 16:47:36 -0700504 mTrustListeners.remove(i);
Adrian Roos82142c22014-03-27 14:56:59 +0100505 return;
506 }
507 }
508 }
509
Adrian Roos3c9a3502014-08-06 19:09:45 +0200510 private void dispatchOnTrustChanged(boolean enabled, int userId, boolean initiatedByUser) {
511 if (!enabled) initiatedByUser = false;
Adrian Roos82142c22014-03-27 14:56:59 +0100512 for (int i = 0; i < mTrustListeners.size(); i++) {
513 try {
Adrian Roos3c9a3502014-08-06 19:09:45 +0200514 mTrustListeners.get(i).onTrustChanged(enabled, userId, initiatedByUser);
Adrian Roosa4ba56b2014-05-20 12:56:25 +0200515 } catch (DeadObjectException e) {
Adrian Roos7861c662014-07-25 15:37:28 +0200516 Slog.d(TAG, "Removing dead TrustListener.");
517 mTrustListeners.remove(i);
518 i--;
519 } catch (RemoteException e) {
520 Slog.e(TAG, "Exception while notifying TrustListener.", e);
521 }
522 }
523 }
524
525 private void dispatchOnTrustManagedChanged(boolean managed, int userId) {
526 for (int i = 0; i < mTrustListeners.size(); i++) {
527 try {
528 mTrustListeners.get(i).onTrustManagedChanged(managed, userId);
529 } catch (DeadObjectException e) {
530 Slog.d(TAG, "Removing dead TrustListener.");
Adrian Roosa4ba56b2014-05-20 12:56:25 +0200531 mTrustListeners.remove(i);
532 i--;
Adrian Roos82142c22014-03-27 14:56:59 +0100533 } catch (RemoteException e) {
Adrian Roosa4ba56b2014-05-20 12:56:25 +0200534 Slog.e(TAG, "Exception while notifying TrustListener.", e);
Adrian Roos82142c22014-03-27 14:56:59 +0100535 }
536 }
537 }
538
Adrian Rooscbe614f2014-10-28 20:16:12 +0100539 // User lifecycle
540
541 @Override
542 public void onStartUser(int userId) {
543 refreshAgentList(userId);
544 }
545
546 @Override
547 public void onCleanupUser(int userId) {
548 refreshAgentList(userId);
549 }
550
Adrian Roos82142c22014-03-27 14:56:59 +0100551 // Plumbing
552
553 private final IBinder mService = new ITrustManager.Stub() {
554 @Override
555 public void reportUnlockAttempt(boolean authenticated, int userId) throws RemoteException {
556 enforceReportPermission();
557 mHandler.obtainMessage(MSG_DISPATCH_UNLOCK_ATTEMPT, authenticated ? 1 : 0, userId)
558 .sendToTarget();
559 }
560
561 @Override
562 public void reportEnabledTrustAgentsChanged(int userId) throws RemoteException {
563 enforceReportPermission();
564 // coalesce refresh messages.
565 mHandler.removeMessages(MSG_ENABLED_AGENTS_CHANGED);
566 mHandler.sendEmptyMessage(MSG_ENABLED_AGENTS_CHANGED);
567 }
568
569 @Override
Adrian Roos2c12cfa2014-06-25 23:28:53 +0200570 public void reportRequireCredentialEntry(int userId) throws RemoteException {
571 enforceReportPermission();
572 if (userId == UserHandle.USER_ALL || userId >= UserHandle.USER_OWNER) {
573 mHandler.obtainMessage(MSG_REQUIRE_CREDENTIAL_ENTRY, userId, 0).sendToTarget();
574 } else {
575 throw new IllegalArgumentException(
576 "userId must be an explicit user id or USER_ALL");
577 }
578 }
579
580 @Override
Adrian Roos82142c22014-03-27 14:56:59 +0100581 public void registerTrustListener(ITrustListener trustListener) throws RemoteException {
582 enforceListenerPermission();
583 mHandler.obtainMessage(MSG_REGISTER_LISTENER, trustListener).sendToTarget();
584 }
585
586 @Override
587 public void unregisterTrustListener(ITrustListener trustListener) throws RemoteException {
588 enforceListenerPermission();
589 mHandler.obtainMessage(MSG_UNREGISTER_LISTENER, trustListener).sendToTarget();
590 }
591
Adrian Roosbcd07652014-10-22 16:57:16 +0200592 @Override
593 public boolean isTrusted(int userId) throws RemoteException {
594 userId = ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId,
595 false /* allowAll */, true /* requireFull */, "isTrusted", null);
596 userId = resolveProfileParent(userId);
597 synchronized (mUserIsTrusted) {
598 return mUserIsTrusted.get(userId);
599 }
600 }
601
Adrian Roos82142c22014-03-27 14:56:59 +0100602 private void enforceReportPermission() {
Adrian Roos2c12cfa2014-06-25 23:28:53 +0200603 mContext.enforceCallingOrSelfPermission(
604 Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE, "reporting trust events");
Adrian Roos82142c22014-03-27 14:56:59 +0100605 }
606
607 private void enforceListenerPermission() {
608 mContext.enforceCallingPermission(Manifest.permission.TRUST_LISTENER,
609 "register trust listener");
610 }
Adrian Roos7a4f3d42014-05-02 12:12:20 +0200611
612 @Override
613 protected void dump(FileDescriptor fd, final PrintWriter fout, String[] args) {
614 mContext.enforceCallingPermission(Manifest.permission.DUMP,
615 "dumping TrustManagerService");
Adrian Roos49d53452014-10-24 15:48:39 +0200616 if (isSafeMode()) {
617 fout.println("disabled because the system is in safe mode.");
618 return;
619 }
Adrian Rooscbe614f2014-10-28 20:16:12 +0100620 if (!mTrustAgentsCanRun) {
621 fout.println("disabled because the third-party apps can't run yet.");
622 return;
623 }
Adrian Roos7a4f3d42014-05-02 12:12:20 +0200624 final UserInfo currentUser;
625 final List<UserInfo> userInfos = mUserManager.getUsers(true /* excludeDying */);
626 try {
627 currentUser = ActivityManagerNative.getDefault().getCurrentUser();
628 } catch (RemoteException e) {
629 throw new RuntimeException(e);
630 }
631 mHandler.runWithScissors(new Runnable() {
632 @Override
633 public void run() {
634 fout.println("Trust manager state:");
635 for (UserInfo user : userInfos) {
636 dumpUser(fout, user, user.id == currentUser.id);
637 }
638 }
639 }, 1500);
640 }
641
642 private void dumpUser(PrintWriter fout, UserInfo user, boolean isCurrent) {
643 fout.printf(" User \"%s\" (id=%d, flags=%#x)",
644 user.name, user.id, user.flags);
645 if (isCurrent) {
646 fout.print(" (current)");
647 }
648 fout.print(": trusted=" + dumpBool(aggregateIsTrusted(user.id)));
Adrian Roos7861c662014-07-25 15:37:28 +0200649 fout.print(", trustManaged=" + dumpBool(aggregateIsTrustManaged(user.id)));
Adrian Roos7a4f3d42014-05-02 12:12:20 +0200650 fout.println();
651 fout.println(" Enabled agents:");
652 boolean duplicateSimpleNames = false;
653 ArraySet<String> simpleNames = new ArraySet<String>();
654 for (AgentInfo info : mActiveAgents) {
655 if (info.userId != user.id) { continue; }
656 boolean trusted = info.agent.isTrusted();
657 fout.print(" "); fout.println(info.component.flattenToShortString());
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200658 fout.print(" bound=" + dumpBool(info.agent.isBound()));
659 fout.print(", connected=" + dumpBool(info.agent.isConnected()));
Adrian Roos7861c662014-07-25 15:37:28 +0200660 fout.print(", managingTrust=" + dumpBool(info.agent.isManagingTrust()));
661 fout.print(", trusted=" + dumpBool(trusted));
662 fout.println();
Adrian Roos7a4f3d42014-05-02 12:12:20 +0200663 if (trusted) {
664 fout.println(" message=\"" + info.agent.getMessage() + "\"");
665 }
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200666 if (!info.agent.isConnected()) {
667 String restartTime = TrustArchive.formatDuration(
668 info.agent.getScheduledRestartUptimeMillis()
669 - SystemClock.uptimeMillis());
670 fout.println(" restartScheduledAt=" + restartTime);
671 }
Adrian Roos7a4f3d42014-05-02 12:12:20 +0200672 if (!simpleNames.add(TrustArchive.getSimpleName(info.component))) {
673 duplicateSimpleNames = true;
674 }
675 }
676 fout.println(" Events:");
677 mArchive.dump(fout, 50, user.id, " " /* linePrefix */, duplicateSimpleNames);
678 fout.println();
679 }
680
681 private String dumpBool(boolean b) {
682 return b ? "1" : "0";
683 }
Adrian Roos82142c22014-03-27 14:56:59 +0100684 };
685
Adrian Roosbcd07652014-10-22 16:57:16 +0200686 private int resolveProfileParent(int userId) {
687 long identity = Binder.clearCallingIdentity();
688 try {
689 UserInfo parent = mUserManager.getProfileParent(userId);
690 if (parent != null) {
691 return parent.getUserHandle().getIdentifier();
692 }
693 return userId;
694 } finally {
695 Binder.restoreCallingIdentity(identity);
696 }
697 }
698
Adrian Roos82142c22014-03-27 14:56:59 +0100699 private final Handler mHandler = new Handler() {
700 @Override
701 public void handleMessage(Message msg) {
702 switch (msg.what) {
703 case MSG_REGISTER_LISTENER:
704 addListener((ITrustListener) msg.obj);
705 break;
706 case MSG_UNREGISTER_LISTENER:
707 removeListener((ITrustListener) msg.obj);
708 break;
709 case MSG_DISPATCH_UNLOCK_ATTEMPT:
710 dispatchUnlockAttempt(msg.arg1 != 0, msg.arg2);
711 break;
712 case MSG_ENABLED_AGENTS_CHANGED:
Marco Fucci4e68f112014-08-29 12:31:48 -0700713 refreshAgentList(UserHandle.USER_ALL);
Adrian Roos82142c22014-03-27 14:56:59 +0100714 break;
Adrian Roos2c12cfa2014-06-25 23:28:53 +0200715 case MSG_REQUIRE_CREDENTIAL_ENTRY:
716 requireCredentialEntry(msg.arg1);
717 break;
Adrian Roos82142c22014-03-27 14:56:59 +0100718 }
719 }
720 };
721
722 private final PackageMonitor mPackageMonitor = new PackageMonitor() {
723 @Override
724 public void onSomePackagesChanged() {
Marco Fucci4e68f112014-08-29 12:31:48 -0700725 refreshAgentList(UserHandle.USER_ALL);
Adrian Roos82142c22014-03-27 14:56:59 +0100726 }
727
728 @Override
729 public boolean onPackageChanged(String packageName, int uid, String[] components) {
730 // We're interested in all changes, even if just some components get enabled / disabled.
731 return true;
732 }
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200733
734 @Override
735 public void onPackageDisappeared(String packageName, int reason) {
736 removeAgentsOfPackage(packageName);
737 }
Adrian Roos82142c22014-03-27 14:56:59 +0100738 };
Adrian Roosca36b952014-05-16 18:52:29 +0200739
Adrian Roos9dbe1902014-08-13 18:25:52 +0200740 private class Receiver extends BroadcastReceiver {
Adrian Roosca36b952014-05-16 18:52:29 +0200741
742 @Override
743 public void onReceive(Context context, Intent intent) {
Adrian Roos3870d452014-09-05 18:22:28 +0200744 String action = intent.getAction();
745 if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action)) {
Marco Fucci4e68f112014-08-29 12:31:48 -0700746 refreshAgentList(getSendingUserId());
747 updateDevicePolicyFeatures();
Adrian Roos3870d452014-09-05 18:22:28 +0200748 } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
Adrian Roos9dbe1902014-08-13 18:25:52 +0200749 updateUserHasAuthenticated(getSendingUserId());
Adrian Roos3870d452014-09-05 18:22:28 +0200750 } else if (Intent.ACTION_USER_ADDED.equals(action)) {
Adrian Rooscbe614f2014-10-28 20:16:12 +0100751 int userId = getUserId(intent);
Adrian Roos3870d452014-09-05 18:22:28 +0200752 if (userId > 0) {
753 maybeEnableFactoryTrustAgents(mLockPatternUtils, userId);
Adrian Roos3870d452014-09-05 18:22:28 +0200754 }
Adrian Rooscbe614f2014-10-28 20:16:12 +0100755 } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
756 int userId = getUserId(intent);
757 if (userId > 0) {
758 mUserHasAuthenticatedSinceBoot.delete(userId);
759 mUserIsTrusted.delete(userId);
760 refreshAgentList(userId);
761 }
762 }
763 }
764
765 private int getUserId(Intent intent) {
766 int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -100);
767 if (userId > 0) {
768 return userId;
769 } else {
770 Slog.wtf(TAG, "EXTRA_USER_HANDLE missing or invalid, value=" + userId);
771 return -100;
Adrian Roosca36b952014-05-16 18:52:29 +0200772 }
773 }
774
775 public void register(Context context) {
Adrian Roos9dbe1902014-08-13 18:25:52 +0200776 IntentFilter filter = new IntentFilter();
777 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
778 filter.addAction(Intent.ACTION_USER_PRESENT);
Adrian Roos3870d452014-09-05 18:22:28 +0200779 filter.addAction(Intent.ACTION_USER_ADDED);
Adrian Rooscbe614f2014-10-28 20:16:12 +0100780 filter.addAction(Intent.ACTION_USER_REMOVED);
Adrian Roosca36b952014-05-16 18:52:29 +0200781 context.registerReceiverAsUser(this,
782 UserHandle.ALL,
Adrian Roos9dbe1902014-08-13 18:25:52 +0200783 filter,
Adrian Roosca36b952014-05-16 18:52:29 +0200784 null /* permission */,
785 null /* scheduler */);
786 }
787 }
Adrian Roos82142c22014-03-27 14:56:59 +0100788}