blob: fe5cb3381dbe746472e17bc966a0d19b4571d7ff [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 Rooscbe614f2014-10-28 20:16:12 +0100211 if (userInfo.partial || !userInfo.isEnabled() || userInfo.guestToRemove) continue;
Adrian Roos3870d452014-09-05 18:22:28 +0200212 if (!userInfo.supportsSwitchTo()) continue;
Adrian Rooscbe614f2014-10-28 20:16:12 +0100213 if (!mActivityManager.isUserRunning(userInfo.id)) continue;
Adrian Roos1572ee32014-09-01 16:24:32 +0200214 if (lockPatternUtils.getKeyguardStoredPasswordQuality(userInfo.id)
Adrian Roos4b9e3242014-08-20 23:36:25 +0200215 == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) continue;
Marco Fucci4e68f112014-08-29 12:31:48 -0700216 if (!mUserHasAuthenticatedSinceBoot.get(userInfo.id)) continue;
Adrian Roos8f211582014-07-29 15:09:57 +0200217 DevicePolicyManager dpm = lockPatternUtils.getDevicePolicyManager();
218 int disabledFeatures = dpm.getKeyguardDisabledFeatures(null, userInfo.id);
Jim Miller604e7552014-07-18 19:00:02 -0700219 final boolean disableTrustAgents =
Adrian Roosca36b952014-05-16 18:52:29 +0200220 (disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0;
221
Adrian Roos82142c22014-03-27 14:56:59 +0100222 List<ComponentName> enabledAgents = lockPatternUtils.getEnabledTrustAgents(userInfo.id);
Adrian Roos8f211582014-07-29 15:09:57 +0200223 if (enabledAgents == null) {
Adrian Roos82142c22014-03-27 14:56:59 +0100224 continue;
225 }
Adrian Roos3870d452014-09-05 18:22:28 +0200226 List<ResolveInfo> resolveInfos = resolveAllowedTrustAgents(pm, userInfo.id);
Adrian Roos82142c22014-03-27 14:56:59 +0100227 for (ResolveInfo resolveInfo : resolveInfos) {
Adrian Roos82142c22014-03-27 14:56:59 +0100228 ComponentName name = getComponentName(resolveInfo);
Adrian Roos82142c22014-03-27 14:56:59 +0100229
Adrian Roos3870d452014-09-05 18:22:28 +0200230 if (!enabledAgents.contains(name)) continue;
Adrian Roos8f211582014-07-29 15:09:57 +0200231 if (disableTrustAgents) {
Jim Millere303bf42014-08-26 17:12:29 -0700232 List<PersistableBundle> config =
233 dpm.getTrustAgentConfiguration(null /* admin */, name, userInfo.id);
Adrian Roos8f211582014-07-29 15:09:57 +0200234 // Disable agent if no features are enabled.
Jim Millere303bf42014-08-26 17:12:29 -0700235 if (config == null || config.isEmpty()) continue;
Adrian Roos8f211582014-07-29 15:09:57 +0200236 }
237
Adrian Roos82142c22014-03-27 14:56:59 +0100238 AgentInfo agentInfo = new AgentInfo();
239 agentInfo.component = name;
240 agentInfo.userId = userInfo.id;
241 if (!mActiveAgents.contains(agentInfo)) {
242 agentInfo.label = resolveInfo.loadLabel(pm);
243 agentInfo.icon = resolveInfo.loadIcon(pm);
244 agentInfo.settings = getSettingsComponentName(pm, resolveInfo);
245 agentInfo.agent = new TrustAgentWrapper(mContext, this,
246 new Intent().setComponent(name), userInfo.getUserHandle());
247 mActiveAgents.add(agentInfo);
248 } else {
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200249 obsoleteAgents.remove(agentInfo);
Adrian Roos82142c22014-03-27 14:56:59 +0100250 }
251 }
252 }
253
254 boolean trustMayHaveChanged = false;
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200255 for (int i = 0; i < obsoleteAgents.size(); i++) {
256 AgentInfo info = obsoleteAgents.valueAt(i);
Adrian Roose681c272014-09-08 14:03:47 +0200257 if (userId == UserHandle.USER_ALL || userId == info.userId) {
258 if (info.agent.isManagingTrust()) {
259 trustMayHaveChanged = true;
260 }
261 info.agent.unbind();
262 mActiveAgents.remove(info);
Adrian Roos82142c22014-03-27 14:56:59 +0100263 }
Adrian Roos82142c22014-03-27 14:56:59 +0100264 }
265
266 if (trustMayHaveChanged) {
Adrian Rooscbe614f2014-10-28 20:16:12 +0100267 if (userId == UserHandle.USER_ALL) {
268 updateTrustAll();
269 } else {
270 updateTrust(userId, false /* initiatedByUser */);
271 }
Adrian Roos82142c22014-03-27 14:56:59 +0100272 }
273 }
274
Marco Fucci4e68f112014-08-29 12:31:48 -0700275 void updateDevicePolicyFeatures() {
Adrian Roos8f211582014-07-29 15:09:57 +0200276 for (int i = 0; i < mActiveAgents.size(); i++) {
277 AgentInfo info = mActiveAgents.valueAt(i);
278 if (info.agent.isConnected()) {
279 info.agent.updateDevicePolicyFeatures();
280 }
281 }
282 }
283
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200284 private void removeAgentsOfPackage(String packageName) {
285 boolean trustMayHaveChanged = false;
286 for (int i = mActiveAgents.size() - 1; i >= 0; i--) {
287 AgentInfo info = mActiveAgents.valueAt(i);
288 if (packageName.equals(info.component.getPackageName())) {
289 Log.i(TAG, "Resetting agent " + info.component.flattenToShortString());
Adrian Roos7861c662014-07-25 15:37:28 +0200290 if (info.agent.isManagingTrust()) {
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200291 trustMayHaveChanged = true;
292 }
293 info.agent.unbind();
294 mActiveAgents.removeAt(i);
295 }
296 }
297 if (trustMayHaveChanged) {
298 updateTrustAll();
299 }
300 }
301
302 public void resetAgent(ComponentName name, int userId) {
303 boolean trustMayHaveChanged = false;
304 for (int i = mActiveAgents.size() - 1; i >= 0; i--) {
305 AgentInfo info = mActiveAgents.valueAt(i);
306 if (name.equals(info.component) && userId == info.userId) {
307 Log.i(TAG, "Resetting agent " + info.component.flattenToShortString());
Adrian Roos7861c662014-07-25 15:37:28 +0200308 if (info.agent.isManagingTrust()) {
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200309 trustMayHaveChanged = true;
310 }
311 info.agent.unbind();
312 mActiveAgents.removeAt(i);
313 }
314 }
315 if (trustMayHaveChanged) {
Adrian Roos3c9a3502014-08-06 19:09:45 +0200316 updateTrust(userId, false);
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200317 }
Marco Fucci4e68f112014-08-29 12:31:48 -0700318 refreshAgentList(userId);
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200319 }
320
Adrian Roos82142c22014-03-27 14:56:59 +0100321 private ComponentName getSettingsComponentName(PackageManager pm, ResolveInfo resolveInfo) {
322 if (resolveInfo == null || resolveInfo.serviceInfo == null
323 || resolveInfo.serviceInfo.metaData == null) return null;
324 String cn = null;
325 XmlResourceParser parser = null;
326 Exception caughtException = null;
327 try {
328 parser = resolveInfo.serviceInfo.loadXmlMetaData(pm,
329 TrustAgentService.TRUST_AGENT_META_DATA);
330 if (parser == null) {
331 Slog.w(TAG, "Can't find " + TrustAgentService.TRUST_AGENT_META_DATA + " meta-data");
332 return null;
333 }
334 Resources res = pm.getResourcesForApplication(resolveInfo.serviceInfo.applicationInfo);
335 AttributeSet attrs = Xml.asAttributeSet(parser);
336 int type;
337 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
338 && type != XmlPullParser.START_TAG) {
339 // Drain preamble.
340 }
341 String nodeName = parser.getName();
Adrian Roos7e03dfc2014-05-16 16:06:28 +0200342 if (!"trust-agent".equals(nodeName)) {
343 Slog.w(TAG, "Meta-data does not start with trust-agent tag");
Adrian Roos82142c22014-03-27 14:56:59 +0100344 return null;
345 }
346 TypedArray sa = res
347 .obtainAttributes(attrs, com.android.internal.R.styleable.TrustAgent);
348 cn = sa.getString(com.android.internal.R.styleable.TrustAgent_settingsActivity);
349 sa.recycle();
350 } catch (PackageManager.NameNotFoundException e) {
351 caughtException = e;
352 } catch (IOException e) {
353 caughtException = e;
354 } catch (XmlPullParserException e) {
355 caughtException = e;
356 } finally {
357 if (parser != null) parser.close();
358 }
359 if (caughtException != null) {
360 Slog.w(TAG, "Error parsing : " + resolveInfo.serviceInfo.packageName, caughtException);
361 return null;
362 }
363 if (cn == null) {
364 return null;
365 }
366 if (cn.indexOf('/') < 0) {
367 cn = resolveInfo.serviceInfo.packageName + "/" + cn;
368 }
369 return ComponentName.unflattenFromString(cn);
370 }
371
372 private ComponentName getComponentName(ResolveInfo resolveInfo) {
373 if (resolveInfo == null || resolveInfo.serviceInfo == null) return null;
374 return new ComponentName(resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name);
375 }
376
Adrian Roos3870d452014-09-05 18:22:28 +0200377 private void maybeEnableFactoryTrustAgents(LockPatternUtils utils, int userId) {
378 if (0 != Settings.Secure.getIntForUser(mContext.getContentResolver(),
379 Settings.Secure.TRUST_AGENTS_INITIALIZED, 0, userId)) {
380 return;
381 }
382 PackageManager pm = mContext.getPackageManager();
383 List<ResolveInfo> resolveInfos = resolveAllowedTrustAgents(pm, userId);
384 ArraySet<ComponentName> discoveredAgents = new ArraySet<>();
385 for (ResolveInfo resolveInfo : resolveInfos) {
386 ComponentName componentName = getComponentName(resolveInfo);
387 int applicationInfoFlags = resolveInfo.serviceInfo.applicationInfo.flags;
388 if ((applicationInfoFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
389 Log.i(TAG, "Leaving agent " + componentName + " disabled because package "
390 + "is not a system package.");
391 continue;
392 }
393 discoveredAgents.add(componentName);
394 }
395
396 List<ComponentName> previouslyEnabledAgents = utils.getEnabledTrustAgents(userId);
397 if (previouslyEnabledAgents != null) {
398 discoveredAgents.addAll(previouslyEnabledAgents);
399 }
400 utils.setEnabledTrustAgents(discoveredAgents, userId);
401 Settings.Secure.putIntForUser(mContext.getContentResolver(),
402 Settings.Secure.TRUST_AGENTS_INITIALIZED, 1, userId);
403 }
404
405 private List<ResolveInfo> resolveAllowedTrustAgents(PackageManager pm, int userId) {
406 List<ResolveInfo> resolveInfos = pm.queryIntentServicesAsUser(TRUST_AGENT_INTENT,
407 0 /* flags */, userId);
408 ArrayList<ResolveInfo> allowedAgents = new ArrayList<>(resolveInfos.size());
409 for (ResolveInfo resolveInfo : resolveInfos) {
410 if (resolveInfo.serviceInfo == null) continue;
411 if (resolveInfo.serviceInfo.applicationInfo == null) continue;
412 String packageName = resolveInfo.serviceInfo.packageName;
413 if (pm.checkPermission(PERMISSION_PROVIDE_AGENT, packageName)
414 != PackageManager.PERMISSION_GRANTED) {
415 ComponentName name = getComponentName(resolveInfo);
416 Log.w(TAG, "Skipping agent " + name + " because package does not have"
417 + " permission " + PERMISSION_PROVIDE_AGENT + ".");
418 continue;
419 }
420 allowedAgents.add(resolveInfo);
421 }
422 return allowedAgents;
423 }
424
Adrian Roos82142c22014-03-27 14:56:59 +0100425 // Agent dispatch and aggregation
426
427 private boolean aggregateIsTrusted(int userId) {
Adrian Roos7046bfd2014-05-16 21:20:54 +0200428 if (!mUserHasAuthenticatedSinceBoot.get(userId)) {
429 return false;
430 }
Adrian Roos82142c22014-03-27 14:56:59 +0100431 for (int i = 0; i < mActiveAgents.size(); i++) {
432 AgentInfo info = mActiveAgents.valueAt(i);
433 if (info.userId == userId) {
434 if (info.agent.isTrusted()) {
435 return true;
436 }
437 }
438 }
439 return false;
440 }
441
Adrian Roos7861c662014-07-25 15:37:28 +0200442 private boolean aggregateIsTrustManaged(int userId) {
443 if (!mUserHasAuthenticatedSinceBoot.get(userId)) {
444 return false;
445 }
446 for (int i = 0; i < mActiveAgents.size(); i++) {
447 AgentInfo info = mActiveAgents.valueAt(i);
448 if (info.userId == userId) {
449 if (info.agent.isManagingTrust()) {
450 return true;
451 }
452 }
453 }
454 return false;
455 }
456
Adrian Roos82142c22014-03-27 14:56:59 +0100457 private void dispatchUnlockAttempt(boolean successful, int userId) {
458 for (int i = 0; i < mActiveAgents.size(); i++) {
459 AgentInfo info = mActiveAgents.valueAt(i);
460 if (info.userId == userId) {
461 info.agent.onUnlockAttempt(successful);
462 }
463 }
Adrian Roos7046bfd2014-05-16 21:20:54 +0200464
Adrian Roos9dbe1902014-08-13 18:25:52 +0200465 if (successful) {
466 updateUserHasAuthenticated(userId);
467 }
468 }
469
470 private void updateUserHasAuthenticated(int userId) {
471 if (!mUserHasAuthenticatedSinceBoot.get(userId)) {
Adrian Roos7046bfd2014-05-16 21:20:54 +0200472 mUserHasAuthenticatedSinceBoot.put(userId, true);
Marco Fucci4e68f112014-08-29 12:31:48 -0700473 refreshAgentList(userId);
Adrian Roos7046bfd2014-05-16 21:20:54 +0200474 }
Adrian Roos82142c22014-03-27 14:56:59 +0100475 }
476
Adrian Roos2c12cfa2014-06-25 23:28:53 +0200477
478 private void requireCredentialEntry(int userId) {
479 if (userId == UserHandle.USER_ALL) {
480 mUserHasAuthenticatedSinceBoot.clear();
Marco Fucci4e68f112014-08-29 12:31:48 -0700481 refreshAgentList(UserHandle.USER_ALL);
Adrian Roos2c12cfa2014-06-25 23:28:53 +0200482 } else {
483 mUserHasAuthenticatedSinceBoot.put(userId, false);
Marco Fucci4e68f112014-08-29 12:31:48 -0700484 refreshAgentList(userId);
Adrian Roos2c12cfa2014-06-25 23:28:53 +0200485 }
486 }
487
Adrian Roos82142c22014-03-27 14:56:59 +0100488 // Listeners
489
490 private void addListener(ITrustListener listener) {
491 for (int i = 0; i < mTrustListeners.size(); i++) {
492 if (mTrustListeners.get(i).asBinder() == listener.asBinder()) {
493 return;
494 }
495 }
496 mTrustListeners.add(listener);
Adrian Roos3870d452014-09-05 18:22:28 +0200497 updateTrustAll();
Adrian Roos82142c22014-03-27 14:56:59 +0100498 }
499
500 private void removeListener(ITrustListener listener) {
501 for (int i = 0; i < mTrustListeners.size(); i++) {
502 if (mTrustListeners.get(i).asBinder() == listener.asBinder()) {
Jay Civelli979a32e2014-07-18 16:47:36 -0700503 mTrustListeners.remove(i);
Adrian Roos82142c22014-03-27 14:56:59 +0100504 return;
505 }
506 }
507 }
508
Adrian Roos3c9a3502014-08-06 19:09:45 +0200509 private void dispatchOnTrustChanged(boolean enabled, int userId, boolean initiatedByUser) {
510 if (!enabled) initiatedByUser = false;
Adrian Roos82142c22014-03-27 14:56:59 +0100511 for (int i = 0; i < mTrustListeners.size(); i++) {
512 try {
Adrian Roos3c9a3502014-08-06 19:09:45 +0200513 mTrustListeners.get(i).onTrustChanged(enabled, userId, initiatedByUser);
Adrian Roosa4ba56b2014-05-20 12:56:25 +0200514 } catch (DeadObjectException e) {
Adrian Roos7861c662014-07-25 15:37:28 +0200515 Slog.d(TAG, "Removing dead TrustListener.");
516 mTrustListeners.remove(i);
517 i--;
518 } catch (RemoteException e) {
519 Slog.e(TAG, "Exception while notifying TrustListener.", e);
520 }
521 }
522 }
523
524 private void dispatchOnTrustManagedChanged(boolean managed, int userId) {
525 for (int i = 0; i < mTrustListeners.size(); i++) {
526 try {
527 mTrustListeners.get(i).onTrustManagedChanged(managed, userId);
528 } catch (DeadObjectException e) {
529 Slog.d(TAG, "Removing dead TrustListener.");
Adrian Roosa4ba56b2014-05-20 12:56:25 +0200530 mTrustListeners.remove(i);
531 i--;
Adrian Roos82142c22014-03-27 14:56:59 +0100532 } catch (RemoteException e) {
Adrian Roosa4ba56b2014-05-20 12:56:25 +0200533 Slog.e(TAG, "Exception while notifying TrustListener.", e);
Adrian Roos82142c22014-03-27 14:56:59 +0100534 }
535 }
536 }
537
Adrian Rooscbe614f2014-10-28 20:16:12 +0100538 // User lifecycle
539
540 @Override
541 public void onStartUser(int userId) {
542 refreshAgentList(userId);
543 }
544
545 @Override
546 public void onCleanupUser(int userId) {
547 refreshAgentList(userId);
548 }
549
Adrian Roos82142c22014-03-27 14:56:59 +0100550 // Plumbing
551
552 private final IBinder mService = new ITrustManager.Stub() {
553 @Override
554 public void reportUnlockAttempt(boolean authenticated, int userId) throws RemoteException {
555 enforceReportPermission();
556 mHandler.obtainMessage(MSG_DISPATCH_UNLOCK_ATTEMPT, authenticated ? 1 : 0, userId)
557 .sendToTarget();
558 }
559
560 @Override
561 public void reportEnabledTrustAgentsChanged(int userId) throws RemoteException {
562 enforceReportPermission();
563 // coalesce refresh messages.
564 mHandler.removeMessages(MSG_ENABLED_AGENTS_CHANGED);
565 mHandler.sendEmptyMessage(MSG_ENABLED_AGENTS_CHANGED);
566 }
567
568 @Override
Adrian Roos2c12cfa2014-06-25 23:28:53 +0200569 public void reportRequireCredentialEntry(int userId) throws RemoteException {
570 enforceReportPermission();
571 if (userId == UserHandle.USER_ALL || userId >= UserHandle.USER_OWNER) {
572 mHandler.obtainMessage(MSG_REQUIRE_CREDENTIAL_ENTRY, userId, 0).sendToTarget();
573 } else {
574 throw new IllegalArgumentException(
575 "userId must be an explicit user id or USER_ALL");
576 }
577 }
578
579 @Override
Adrian Roos82142c22014-03-27 14:56:59 +0100580 public void registerTrustListener(ITrustListener trustListener) throws RemoteException {
581 enforceListenerPermission();
582 mHandler.obtainMessage(MSG_REGISTER_LISTENER, trustListener).sendToTarget();
583 }
584
585 @Override
586 public void unregisterTrustListener(ITrustListener trustListener) throws RemoteException {
587 enforceListenerPermission();
588 mHandler.obtainMessage(MSG_UNREGISTER_LISTENER, trustListener).sendToTarget();
589 }
590
Adrian Roosbcd07652014-10-22 16:57:16 +0200591 @Override
592 public boolean isTrusted(int userId) throws RemoteException {
593 userId = ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId,
594 false /* allowAll */, true /* requireFull */, "isTrusted", null);
595 userId = resolveProfileParent(userId);
596 synchronized (mUserIsTrusted) {
597 return mUserIsTrusted.get(userId);
598 }
599 }
600
Adrian Roos82142c22014-03-27 14:56:59 +0100601 private void enforceReportPermission() {
Adrian Roos2c12cfa2014-06-25 23:28:53 +0200602 mContext.enforceCallingOrSelfPermission(
603 Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE, "reporting trust events");
Adrian Roos82142c22014-03-27 14:56:59 +0100604 }
605
606 private void enforceListenerPermission() {
607 mContext.enforceCallingPermission(Manifest.permission.TRUST_LISTENER,
608 "register trust listener");
609 }
Adrian Roos7a4f3d42014-05-02 12:12:20 +0200610
611 @Override
612 protected void dump(FileDescriptor fd, final PrintWriter fout, String[] args) {
613 mContext.enforceCallingPermission(Manifest.permission.DUMP,
614 "dumping TrustManagerService");
Adrian Roos49d53452014-10-24 15:48:39 +0200615 if (isSafeMode()) {
616 fout.println("disabled because the system is in safe mode.");
617 return;
618 }
Adrian Rooscbe614f2014-10-28 20:16:12 +0100619 if (!mTrustAgentsCanRun) {
620 fout.println("disabled because the third-party apps can't run yet.");
621 return;
622 }
Adrian Roos7a4f3d42014-05-02 12:12:20 +0200623 final UserInfo currentUser;
624 final List<UserInfo> userInfos = mUserManager.getUsers(true /* excludeDying */);
625 try {
626 currentUser = ActivityManagerNative.getDefault().getCurrentUser();
627 } catch (RemoteException e) {
628 throw new RuntimeException(e);
629 }
630 mHandler.runWithScissors(new Runnable() {
631 @Override
632 public void run() {
633 fout.println("Trust manager state:");
634 for (UserInfo user : userInfos) {
635 dumpUser(fout, user, user.id == currentUser.id);
636 }
637 }
638 }, 1500);
639 }
640
641 private void dumpUser(PrintWriter fout, UserInfo user, boolean isCurrent) {
642 fout.printf(" User \"%s\" (id=%d, flags=%#x)",
643 user.name, user.id, user.flags);
644 if (isCurrent) {
645 fout.print(" (current)");
646 }
647 fout.print(": trusted=" + dumpBool(aggregateIsTrusted(user.id)));
Adrian Roos7861c662014-07-25 15:37:28 +0200648 fout.print(", trustManaged=" + dumpBool(aggregateIsTrustManaged(user.id)));
Adrian Roos7a4f3d42014-05-02 12:12:20 +0200649 fout.println();
650 fout.println(" Enabled agents:");
651 boolean duplicateSimpleNames = false;
652 ArraySet<String> simpleNames = new ArraySet<String>();
653 for (AgentInfo info : mActiveAgents) {
654 if (info.userId != user.id) { continue; }
655 boolean trusted = info.agent.isTrusted();
656 fout.print(" "); fout.println(info.component.flattenToShortString());
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200657 fout.print(" bound=" + dumpBool(info.agent.isBound()));
658 fout.print(", connected=" + dumpBool(info.agent.isConnected()));
Adrian Roos7861c662014-07-25 15:37:28 +0200659 fout.print(", managingTrust=" + dumpBool(info.agent.isManagingTrust()));
660 fout.print(", trusted=" + dumpBool(trusted));
661 fout.println();
Adrian Roos7a4f3d42014-05-02 12:12:20 +0200662 if (trusted) {
663 fout.println(" message=\"" + info.agent.getMessage() + "\"");
664 }
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200665 if (!info.agent.isConnected()) {
666 String restartTime = TrustArchive.formatDuration(
667 info.agent.getScheduledRestartUptimeMillis()
668 - SystemClock.uptimeMillis());
669 fout.println(" restartScheduledAt=" + restartTime);
670 }
Adrian Roos7a4f3d42014-05-02 12:12:20 +0200671 if (!simpleNames.add(TrustArchive.getSimpleName(info.component))) {
672 duplicateSimpleNames = true;
673 }
674 }
675 fout.println(" Events:");
676 mArchive.dump(fout, 50, user.id, " " /* linePrefix */, duplicateSimpleNames);
677 fout.println();
678 }
679
680 private String dumpBool(boolean b) {
681 return b ? "1" : "0";
682 }
Adrian Roos82142c22014-03-27 14:56:59 +0100683 };
684
Adrian Roosbcd07652014-10-22 16:57:16 +0200685 private int resolveProfileParent(int userId) {
686 long identity = Binder.clearCallingIdentity();
687 try {
688 UserInfo parent = mUserManager.getProfileParent(userId);
689 if (parent != null) {
690 return parent.getUserHandle().getIdentifier();
691 }
692 return userId;
693 } finally {
694 Binder.restoreCallingIdentity(identity);
695 }
696 }
697
Adrian Roos82142c22014-03-27 14:56:59 +0100698 private final Handler mHandler = new Handler() {
699 @Override
700 public void handleMessage(Message msg) {
701 switch (msg.what) {
702 case MSG_REGISTER_LISTENER:
703 addListener((ITrustListener) msg.obj);
704 break;
705 case MSG_UNREGISTER_LISTENER:
706 removeListener((ITrustListener) msg.obj);
707 break;
708 case MSG_DISPATCH_UNLOCK_ATTEMPT:
709 dispatchUnlockAttempt(msg.arg1 != 0, msg.arg2);
710 break;
711 case MSG_ENABLED_AGENTS_CHANGED:
Marco Fucci4e68f112014-08-29 12:31:48 -0700712 refreshAgentList(UserHandle.USER_ALL);
Adrian Roos82142c22014-03-27 14:56:59 +0100713 break;
Adrian Roos2c12cfa2014-06-25 23:28:53 +0200714 case MSG_REQUIRE_CREDENTIAL_ENTRY:
715 requireCredentialEntry(msg.arg1);
716 break;
Adrian Roos82142c22014-03-27 14:56:59 +0100717 }
718 }
719 };
720
721 private final PackageMonitor mPackageMonitor = new PackageMonitor() {
722 @Override
723 public void onSomePackagesChanged() {
Marco Fucci4e68f112014-08-29 12:31:48 -0700724 refreshAgentList(UserHandle.USER_ALL);
Adrian Roos82142c22014-03-27 14:56:59 +0100725 }
726
727 @Override
728 public boolean onPackageChanged(String packageName, int uid, String[] components) {
729 // We're interested in all changes, even if just some components get enabled / disabled.
730 return true;
731 }
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200732
733 @Override
734 public void onPackageDisappeared(String packageName, int reason) {
735 removeAgentsOfPackage(packageName);
736 }
Adrian Roos82142c22014-03-27 14:56:59 +0100737 };
Adrian Roosca36b952014-05-16 18:52:29 +0200738
Adrian Roos9dbe1902014-08-13 18:25:52 +0200739 private class Receiver extends BroadcastReceiver {
Adrian Roosca36b952014-05-16 18:52:29 +0200740
741 @Override
742 public void onReceive(Context context, Intent intent) {
Adrian Roos3870d452014-09-05 18:22:28 +0200743 String action = intent.getAction();
744 if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action)) {
Marco Fucci4e68f112014-08-29 12:31:48 -0700745 refreshAgentList(getSendingUserId());
746 updateDevicePolicyFeatures();
Adrian Roos3870d452014-09-05 18:22:28 +0200747 } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
Adrian Roos9dbe1902014-08-13 18:25:52 +0200748 updateUserHasAuthenticated(getSendingUserId());
Adrian Roos3870d452014-09-05 18:22:28 +0200749 } else if (Intent.ACTION_USER_ADDED.equals(action)) {
Adrian Rooscbe614f2014-10-28 20:16:12 +0100750 int userId = getUserId(intent);
Adrian Roos3870d452014-09-05 18:22:28 +0200751 if (userId > 0) {
752 maybeEnableFactoryTrustAgents(mLockPatternUtils, userId);
Adrian Roos3870d452014-09-05 18:22:28 +0200753 }
Adrian Rooscbe614f2014-10-28 20:16:12 +0100754 } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
755 int userId = getUserId(intent);
756 if (userId > 0) {
757 mUserHasAuthenticatedSinceBoot.delete(userId);
758 mUserIsTrusted.delete(userId);
759 refreshAgentList(userId);
760 }
761 }
762 }
763
764 private int getUserId(Intent intent) {
765 int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -100);
766 if (userId > 0) {
767 return userId;
768 } else {
769 Slog.wtf(TAG, "EXTRA_USER_HANDLE missing or invalid, value=" + userId);
770 return -100;
Adrian Roosca36b952014-05-16 18:52:29 +0200771 }
772 }
773
774 public void register(Context context) {
Adrian Roos9dbe1902014-08-13 18:25:52 +0200775 IntentFilter filter = new IntentFilter();
776 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
777 filter.addAction(Intent.ACTION_USER_PRESENT);
Adrian Roos3870d452014-09-05 18:22:28 +0200778 filter.addAction(Intent.ACTION_USER_ADDED);
Adrian Rooscbe614f2014-10-28 20:16:12 +0100779 filter.addAction(Intent.ACTION_USER_REMOVED);
Adrian Roosca36b952014-05-16 18:52:29 +0200780 context.registerReceiverAsUser(this,
781 UserHandle.ALL,
Adrian Roos9dbe1902014-08-13 18:25:52 +0200782 filter,
Adrian Roosca36b952014-05-16 18:52:29 +0200783 null /* permission */,
784 null /* scheduler */);
785 }
786 }
Adrian Roos82142c22014-03-27 14:56:59 +0100787}