blob: f4869fc427e306b9e3c3ac584a6aee1a1f5b6579 [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;
Adrian Roosb5e47222015-08-14 15:53:06 -070022import com.android.internal.widget.LockPatternUtils.StrongAuthTracker;
Adrian Roos82142c22014-03-27 14:56:59 +010023import com.android.server.SystemService;
24
25import org.xmlpull.v1.XmlPullParser;
26import org.xmlpull.v1.XmlPullParserException;
27
28import android.Manifest;
Adrian Roosbcd07652014-10-22 16:57:16 +020029import android.app.ActivityManager;
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;
Clara Bayarri56878a92015-10-29 15:43:55 +000056import android.os.storage.StorageManager;
Adrian Roos3870d452014-09-05 18:22:28 +020057import android.provider.Settings;
Adrian Roos82142c22014-03-27 14:56:59 +010058import android.service.trust.TrustAgentService;
59import android.util.ArraySet;
60import android.util.AttributeSet;
Adrian Roos18ea8932014-05-28 14:53:06 +020061import android.util.Log;
Adrian Roos82142c22014-03-27 14:56:59 +010062import android.util.Slog;
Adrian Roos7046bfd2014-05-16 21:20:54 +020063import android.util.SparseBooleanArray;
Adrian Roosb5e47222015-08-14 15:53:06 -070064import android.util.SparseIntArray;
Adrian Roos82142c22014-03-27 14:56:59 +010065import android.util.Xml;
Adrian Roos481a6df2014-11-20 19:48:56 +010066import android.view.IWindowManager;
Adrian Roos50bfeec2014-11-20 16:21:11 +010067import android.view.WindowManagerGlobal;
Adrian Roos82142c22014-03-27 14:56:59 +010068
Adrian Roos7a4f3d42014-05-02 12:12:20 +020069import java.io.FileDescriptor;
Adrian Roos82142c22014-03-27 14:56:59 +010070import java.io.IOException;
Adrian Roos7a4f3d42014-05-02 12:12:20 +020071import java.io.PrintWriter;
Adrian Roos82142c22014-03-27 14:56:59 +010072import java.util.ArrayList;
73import java.util.List;
74
75/**
76 * Manages trust agents and trust listeners.
77 *
78 * It is responsible for binding to the enabled {@link android.service.trust.TrustAgentService}s
79 * of each user and notifies them about events that are relevant to them.
80 * It start and stops them based on the value of
81 * {@link com.android.internal.widget.LockPatternUtils#getEnabledTrustAgents(int)}.
82 *
83 * It also keeps a set of {@link android.app.trust.ITrustListener}s that are notified whenever the
84 * trust state changes for any user.
85 *
86 * Trust state and the setting of enabled agents is kept per user and each user has its own
87 * instance of a {@link android.service.trust.TrustAgentService}.
88 */
89public class TrustManagerService extends SystemService {
90
91 private static final boolean DEBUG = false;
92 private static final String TAG = "TrustManagerService";
93
94 private static final Intent TRUST_AGENT_INTENT =
95 new Intent(TrustAgentService.SERVICE_INTERFACE);
Adrian Roos18ea8932014-05-28 14:53:06 +020096 private static final String PERMISSION_PROVIDE_AGENT = Manifest.permission.PROVIDE_TRUST_AGENT;
Adrian Roos82142c22014-03-27 14:56:59 +010097
98 private static final int MSG_REGISTER_LISTENER = 1;
99 private static final int MSG_UNREGISTER_LISTENER = 2;
100 private static final int MSG_DISPATCH_UNLOCK_ATTEMPT = 3;
101 private static final int MSG_ENABLED_AGENTS_CHANGED = 4;
Adrian Roos481a6df2014-11-20 19:48:56 +0100102 private static final int MSG_KEYGUARD_SHOWING_CHANGED = 6;
103 private static final int MSG_START_USER = 7;
104 private static final int MSG_CLEANUP_USER = 8;
105 private static final int MSG_SWITCH_USER = 9;
Clara Bayarri56878a92015-10-29 15:43:55 +0000106 private static final int MSG_SET_DEVICE_LOCKED = 10;
Adrian Roos82142c22014-03-27 14:56:59 +0100107
Adrian Roosb5e47222015-08-14 15:53:06 -0700108 private final ArraySet<AgentInfo> mActiveAgents = new ArraySet<>();
109 private final ArrayList<ITrustListener> mTrustListeners = new ArrayList<>();
Adrian Roos9dbe1902014-08-13 18:25:52 +0200110 private final Receiver mReceiver = new Receiver();
Adrian Roosb5e47222015-08-14 15:53:06 -0700111
Adrian Roos7a4f3d42014-05-02 12:12:20 +0200112 /* package */ final TrustArchive mArchive = new TrustArchive();
Adrian Roos82142c22014-03-27 14:56:59 +0100113 private final Context mContext;
Adrian Roos3870d452014-09-05 18:22:28 +0200114 private final LockPatternUtils mLockPatternUtils;
Adrian Roosbcd07652014-10-22 16:57:16 +0200115 private final UserManager mUserManager;
Adrian Rooscbe614f2014-10-28 20:16:12 +0100116 private final ActivityManager mActivityManager;
Adrian Roos82142c22014-03-27 14:56:59 +0100117
Adrian Roosbcd07652014-10-22 16:57:16 +0200118 @GuardedBy("mUserIsTrusted")
119 private final SparseBooleanArray mUserIsTrusted = new SparseBooleanArray();
Adrian Roos82142c22014-03-27 14:56:59 +0100120
Adrian Roos481a6df2014-11-20 19:48:56 +0100121 @GuardedBy("mDeviceLockedForUser")
122 private final SparseBooleanArray mDeviceLockedForUser = new SparseBooleanArray();
123
Adrian Rooscbe614f2014-10-28 20:16:12 +0100124 private boolean mTrustAgentsCanRun = false;
Xiaohui Chen09e02912015-08-05 09:44:56 -0700125 private int mCurrentUser = UserHandle.USER_SYSTEM;
Adrian Rooscbe614f2014-10-28 20:16:12 +0100126
Adrian Roos82142c22014-03-27 14:56:59 +0100127 public TrustManagerService(Context context) {
128 super(context);
129 mContext = context;
130 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
Adrian Rooscbe614f2014-10-28 20:16:12 +0100131 mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
Adrian Roos3870d452014-09-05 18:22:28 +0200132 mLockPatternUtils = new LockPatternUtils(context);
Adrian Roos82142c22014-03-27 14:56:59 +0100133 }
134
135 @Override
136 public void onStart() {
137 publishBinderService(Context.TRUST_SERVICE, mService);
138 }
139
140 @Override
141 public void onBootPhase(int phase) {
Adrian Roos49d53452014-10-24 15:48:39 +0200142 if (isSafeMode()) {
143 // No trust agents in safe mode.
144 return;
145 }
146 if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
Adrian Roos82142c22014-03-27 14:56:59 +0100147 mPackageMonitor.register(mContext, mHandler.getLooper(), UserHandle.ALL, true);
Adrian Roos9dbe1902014-08-13 18:25:52 +0200148 mReceiver.register(mContext);
Adrian Roosb5e47222015-08-14 15:53:06 -0700149 mLockPatternUtils.registerStrongAuthTracker(mStrongAuthTracker);
Adrian Rooscbe614f2014-10-28 20:16:12 +0100150 } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
151 mTrustAgentsCanRun = true;
Marco Fucci4e68f112014-08-29 12:31:48 -0700152 refreshAgentList(UserHandle.USER_ALL);
Adrian Roos49d53452014-10-24 15:48:39 +0200153 } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
Xiaohui Chen09e02912015-08-05 09:44:56 -0700154 maybeEnableFactoryTrustAgents(mLockPatternUtils, UserHandle.USER_SYSTEM);
Adrian Roos82142c22014-03-27 14:56:59 +0100155 }
156 }
157
158 // Agent management
159
160 private static final class AgentInfo {
161 CharSequence label;
162 Drawable icon;
163 ComponentName component; // service that implements ITrustAgent
164 ComponentName settings; // setting to launch to modify agent.
165 TrustAgentWrapper agent;
166 int userId;
167
168 @Override
169 public boolean equals(Object other) {
170 if (!(other instanceof AgentInfo)) {
171 return false;
172 }
173 AgentInfo o = (AgentInfo) other;
174 return component.equals(o.component) && userId == o.userId;
175 }
176
177 @Override
178 public int hashCode() {
179 return component.hashCode() * 31 + userId;
180 }
181 }
182
183 private void updateTrustAll() {
184 List<UserInfo> userInfos = mUserManager.getUsers(true /* excludeDying */);
185 for (UserInfo userInfo : userInfos) {
Adrian Roos94e15a52015-04-16 12:23:18 -0700186 updateTrust(userInfo.id, 0);
Adrian Roos82142c22014-03-27 14:56:59 +0100187 }
188 }
189
Adrian Roos94e15a52015-04-16 12:23:18 -0700190 public void updateTrust(int userId, int flags) {
Adrian Roos7861c662014-07-25 15:37:28 +0200191 dispatchOnTrustManagedChanged(aggregateIsTrustManaged(userId), userId);
Adrian Roosbcd07652014-10-22 16:57:16 +0200192 boolean trusted = aggregateIsTrusted(userId);
Adrian Roos481a6df2014-11-20 19:48:56 +0100193 boolean changed;
Adrian Roosbcd07652014-10-22 16:57:16 +0200194 synchronized (mUserIsTrusted) {
Adrian Roos481a6df2014-11-20 19:48:56 +0100195 changed = mUserIsTrusted.get(userId) != trusted;
Adrian Roosbcd07652014-10-22 16:57:16 +0200196 mUserIsTrusted.put(userId, trusted);
197 }
Adrian Roos94e15a52015-04-16 12:23:18 -0700198 dispatchOnTrustChanged(trusted, userId, flags);
Adrian Roos481a6df2014-11-20 19:48:56 +0100199 if (changed) {
200 refreshDeviceLockedForUser(userId);
201 }
Adrian Roos82142c22014-03-27 14:56:59 +0100202 }
203
Marco Fucci4e68f112014-08-29 12:31:48 -0700204 void refreshAgentList(int userId) {
Adrian Roos82142c22014-03-27 14:56:59 +0100205 if (DEBUG) Slog.d(TAG, "refreshAgentList()");
Adrian Rooscbe614f2014-10-28 20:16:12 +0100206 if (!mTrustAgentsCanRun) {
Adrian Roos49d53452014-10-24 15:48:39 +0200207 return;
208 }
Xiaohui Chen09e02912015-08-05 09:44:56 -0700209 if (userId != UserHandle.USER_ALL && userId < UserHandle.USER_SYSTEM) {
Adrian Roose681c272014-09-08 14:03:47 +0200210 Log.e(TAG, "refreshAgentList(userId=" + userId + "): Invalid user handle,"
211 + " must be USER_ALL or a specific user.", new Throwable("here"));
212 userId = UserHandle.USER_ALL;
213 }
Adrian Roos82142c22014-03-27 14:56:59 +0100214 PackageManager pm = mContext.getPackageManager();
215
Marco Fucci4e68f112014-08-29 12:31:48 -0700216 List<UserInfo> userInfos;
217 if (userId == UserHandle.USER_ALL) {
218 userInfos = mUserManager.getUsers(true /* excludeDying */);
219 } else {
220 userInfos = new ArrayList<>();
221 userInfos.add(mUserManager.getUserInfo(userId));
222 }
Adrian Roos3870d452014-09-05 18:22:28 +0200223 LockPatternUtils lockPatternUtils = mLockPatternUtils;
Adrian Roos82142c22014-03-27 14:56:59 +0100224
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200225 ArraySet<AgentInfo> obsoleteAgents = new ArraySet<>();
226 obsoleteAgents.addAll(mActiveAgents);
Adrian Roos82142c22014-03-27 14:56:59 +0100227
228 for (UserInfo userInfo : userInfos) {
Adrian Roosfc29e0b2014-11-11 12:55:44 +0100229 if (userInfo == null || userInfo.partial || !userInfo.isEnabled()
230 || userInfo.guestToRemove) continue;
Xiaohui Chen7cb69df2015-07-13 16:01:01 -0700231 if (!userInfo.supportsSwitchToByUser()) continue;
Adrian Rooscbe614f2014-10-28 20:16:12 +0100232 if (!mActivityManager.isUserRunning(userInfo.id)) continue;
Adrian Roos481a6df2014-11-20 19:48:56 +0100233 if (!lockPatternUtils.isSecure(userInfo.id)) continue;
Adrian Roosb5e47222015-08-14 15:53:06 -0700234 if (!mStrongAuthTracker.isTrustAllowedForUser(userInfo.id)) continue;
Adrian Roos8f211582014-07-29 15:09:57 +0200235 DevicePolicyManager dpm = lockPatternUtils.getDevicePolicyManager();
236 int disabledFeatures = dpm.getKeyguardDisabledFeatures(null, userInfo.id);
Jim Miller604e7552014-07-18 19:00:02 -0700237 final boolean disableTrustAgents =
Adrian Roosca36b952014-05-16 18:52:29 +0200238 (disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0;
239
Adrian Roos82142c22014-03-27 14:56:59 +0100240 List<ComponentName> enabledAgents = lockPatternUtils.getEnabledTrustAgents(userInfo.id);
Adrian Roos8f211582014-07-29 15:09:57 +0200241 if (enabledAgents == null) {
Adrian Roos82142c22014-03-27 14:56:59 +0100242 continue;
243 }
Adrian Roos3870d452014-09-05 18:22:28 +0200244 List<ResolveInfo> resolveInfos = resolveAllowedTrustAgents(pm, userInfo.id);
Adrian Roos82142c22014-03-27 14:56:59 +0100245 for (ResolveInfo resolveInfo : resolveInfos) {
Adrian Roos82142c22014-03-27 14:56:59 +0100246 ComponentName name = getComponentName(resolveInfo);
Adrian Roos82142c22014-03-27 14:56:59 +0100247
Adrian Roos3870d452014-09-05 18:22:28 +0200248 if (!enabledAgents.contains(name)) continue;
Adrian Roos8f211582014-07-29 15:09:57 +0200249 if (disableTrustAgents) {
Jim Millere303bf42014-08-26 17:12:29 -0700250 List<PersistableBundle> config =
251 dpm.getTrustAgentConfiguration(null /* admin */, name, userInfo.id);
Adrian Roos8f211582014-07-29 15:09:57 +0200252 // Disable agent if no features are enabled.
Jim Millere303bf42014-08-26 17:12:29 -0700253 if (config == null || config.isEmpty()) continue;
Adrian Roos8f211582014-07-29 15:09:57 +0200254 }
255
Adrian Roos82142c22014-03-27 14:56:59 +0100256 AgentInfo agentInfo = new AgentInfo();
257 agentInfo.component = name;
258 agentInfo.userId = userInfo.id;
259 if (!mActiveAgents.contains(agentInfo)) {
260 agentInfo.label = resolveInfo.loadLabel(pm);
261 agentInfo.icon = resolveInfo.loadIcon(pm);
262 agentInfo.settings = getSettingsComponentName(pm, resolveInfo);
263 agentInfo.agent = new TrustAgentWrapper(mContext, this,
264 new Intent().setComponent(name), userInfo.getUserHandle());
265 mActiveAgents.add(agentInfo);
266 } else {
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200267 obsoleteAgents.remove(agentInfo);
Adrian Roos82142c22014-03-27 14:56:59 +0100268 }
269 }
270 }
271
272 boolean trustMayHaveChanged = false;
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200273 for (int i = 0; i < obsoleteAgents.size(); i++) {
274 AgentInfo info = obsoleteAgents.valueAt(i);
Adrian Roose681c272014-09-08 14:03:47 +0200275 if (userId == UserHandle.USER_ALL || userId == info.userId) {
276 if (info.agent.isManagingTrust()) {
277 trustMayHaveChanged = true;
278 }
Adrian Roosfc29e0b2014-11-11 12:55:44 +0100279 info.agent.destroy();
Adrian Roose681c272014-09-08 14:03:47 +0200280 mActiveAgents.remove(info);
Adrian Roos82142c22014-03-27 14:56:59 +0100281 }
Adrian Roos82142c22014-03-27 14:56:59 +0100282 }
283
284 if (trustMayHaveChanged) {
Adrian Rooscbe614f2014-10-28 20:16:12 +0100285 if (userId == UserHandle.USER_ALL) {
286 updateTrustAll();
287 } else {
Adrian Roos94e15a52015-04-16 12:23:18 -0700288 updateTrust(userId, 0);
Adrian Rooscbe614f2014-10-28 20:16:12 +0100289 }
Adrian Roos82142c22014-03-27 14:56:59 +0100290 }
291 }
292
Clara Bayarri56878a92015-10-29 15:43:55 +0000293 public void setDeviceLockedForUser(int userId, boolean locked) {
294 if (StorageManager.isFileBasedEncryptionEnabled()) {
295 UserInfo info = mUserManager.getUserInfo(userId);
296 if (info.isManagedProfile()) {
297 synchronized (mDeviceLockedForUser) {
298 mDeviceLockedForUser.put(userId, locked);
299 }
300 } else {
301 Log.wtf(TAG, "Requested to change lock state for non-profile user " + userId);
302 }
303 }
304 }
305
Adrian Roos481a6df2014-11-20 19:48:56 +0100306 boolean isDeviceLockedInner(int userId) {
307 synchronized (mDeviceLockedForUser) {
308 return mDeviceLockedForUser.get(userId, true);
309 }
310 }
311
312 private void refreshDeviceLockedForUser(int userId) {
Xiaohui Chen09e02912015-08-05 09:44:56 -0700313 if (userId != UserHandle.USER_ALL && userId < UserHandle.USER_SYSTEM) {
Adrian Roos7e2e40e2014-11-21 15:27:12 +0100314 Log.e(TAG, "refreshDeviceLockedForUser(userId=" + userId + "): Invalid user handle,"
Adrian Roos481a6df2014-11-20 19:48:56 +0100315 + " must be USER_ALL or a specific user.", new Throwable("here"));
316 userId = UserHandle.USER_ALL;
317 }
318
319 List<UserInfo> userInfos;
320 if (userId == UserHandle.USER_ALL) {
321 userInfos = mUserManager.getUsers(true /* excludeDying */);
322 } else {
323 userInfos = new ArrayList<>();
324 userInfos.add(mUserManager.getUserInfo(userId));
325 }
326
327 IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
328
329 for (int i = 0; i < userInfos.size(); i++) {
330 UserInfo info = userInfos.get(i);
331
332 if (info == null || info.partial || !info.isEnabled() || info.guestToRemove
Xiaohui Chen7cb69df2015-07-13 16:01:01 -0700333 || !info.supportsSwitchToByUser()) {
Adrian Roos481a6df2014-11-20 19:48:56 +0100334 continue;
335 }
336
337 int id = info.id;
338 boolean secure = mLockPatternUtils.isSecure(id);
339 boolean trusted = aggregateIsTrusted(id);
340 boolean showingKeyguard = true;
341 if (mCurrentUser == id) {
342 try {
343 showingKeyguard = wm.isKeyguardLocked();
344 } catch (RemoteException e) {
345 }
346 }
347 boolean deviceLocked = secure && showingKeyguard && !trusted;
348
349 boolean changed;
350 synchronized (mDeviceLockedForUser) {
351 changed = isDeviceLockedInner(id) != deviceLocked;
352 mDeviceLockedForUser.put(id, deviceLocked);
353 }
354 if (changed) {
355 dispatchDeviceLocked(id, deviceLocked);
356 }
357 }
358 }
359
360 private void dispatchDeviceLocked(int userId, boolean isLocked) {
361 for (int i = 0; i < mActiveAgents.size(); i++) {
362 AgentInfo agent = mActiveAgents.valueAt(i);
363 if (agent.userId == userId) {
364 if (isLocked) {
365 agent.agent.onDeviceLocked();
366 } else{
367 agent.agent.onDeviceUnlocked();
368 }
369 }
370 }
371 }
372
Marco Fucci4e68f112014-08-29 12:31:48 -0700373 void updateDevicePolicyFeatures() {
Adrian Roos8f211582014-07-29 15:09:57 +0200374 for (int i = 0; i < mActiveAgents.size(); i++) {
375 AgentInfo info = mActiveAgents.valueAt(i);
376 if (info.agent.isConnected()) {
377 info.agent.updateDevicePolicyFeatures();
378 }
379 }
380 }
381
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200382 private void removeAgentsOfPackage(String packageName) {
383 boolean trustMayHaveChanged = false;
384 for (int i = mActiveAgents.size() - 1; i >= 0; i--) {
385 AgentInfo info = mActiveAgents.valueAt(i);
386 if (packageName.equals(info.component.getPackageName())) {
387 Log.i(TAG, "Resetting agent " + info.component.flattenToShortString());
Adrian Roos7861c662014-07-25 15:37:28 +0200388 if (info.agent.isManagingTrust()) {
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200389 trustMayHaveChanged = true;
390 }
Adrian Roosfc29e0b2014-11-11 12:55:44 +0100391 info.agent.destroy();
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200392 mActiveAgents.removeAt(i);
393 }
394 }
395 if (trustMayHaveChanged) {
396 updateTrustAll();
397 }
398 }
399
400 public void resetAgent(ComponentName name, int userId) {
401 boolean trustMayHaveChanged = false;
402 for (int i = mActiveAgents.size() - 1; i >= 0; i--) {
403 AgentInfo info = mActiveAgents.valueAt(i);
404 if (name.equals(info.component) && userId == info.userId) {
405 Log.i(TAG, "Resetting agent " + info.component.flattenToShortString());
Adrian Roos7861c662014-07-25 15:37:28 +0200406 if (info.agent.isManagingTrust()) {
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200407 trustMayHaveChanged = true;
408 }
Adrian Roosfc29e0b2014-11-11 12:55:44 +0100409 info.agent.destroy();
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200410 mActiveAgents.removeAt(i);
411 }
412 }
413 if (trustMayHaveChanged) {
Adrian Roos94e15a52015-04-16 12:23:18 -0700414 updateTrust(userId, 0);
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200415 }
Marco Fucci4e68f112014-08-29 12:31:48 -0700416 refreshAgentList(userId);
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200417 }
418
Adrian Roos82142c22014-03-27 14:56:59 +0100419 private ComponentName getSettingsComponentName(PackageManager pm, ResolveInfo resolveInfo) {
420 if (resolveInfo == null || resolveInfo.serviceInfo == null
421 || resolveInfo.serviceInfo.metaData == null) return null;
422 String cn = null;
423 XmlResourceParser parser = null;
424 Exception caughtException = null;
425 try {
426 parser = resolveInfo.serviceInfo.loadXmlMetaData(pm,
427 TrustAgentService.TRUST_AGENT_META_DATA);
428 if (parser == null) {
429 Slog.w(TAG, "Can't find " + TrustAgentService.TRUST_AGENT_META_DATA + " meta-data");
430 return null;
431 }
432 Resources res = pm.getResourcesForApplication(resolveInfo.serviceInfo.applicationInfo);
433 AttributeSet attrs = Xml.asAttributeSet(parser);
434 int type;
435 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
436 && type != XmlPullParser.START_TAG) {
437 // Drain preamble.
438 }
439 String nodeName = parser.getName();
Adrian Roos7e03dfc2014-05-16 16:06:28 +0200440 if (!"trust-agent".equals(nodeName)) {
441 Slog.w(TAG, "Meta-data does not start with trust-agent tag");
Adrian Roos82142c22014-03-27 14:56:59 +0100442 return null;
443 }
444 TypedArray sa = res
445 .obtainAttributes(attrs, com.android.internal.R.styleable.TrustAgent);
446 cn = sa.getString(com.android.internal.R.styleable.TrustAgent_settingsActivity);
447 sa.recycle();
448 } catch (PackageManager.NameNotFoundException e) {
449 caughtException = e;
450 } catch (IOException e) {
451 caughtException = e;
452 } catch (XmlPullParserException e) {
453 caughtException = e;
454 } finally {
455 if (parser != null) parser.close();
456 }
457 if (caughtException != null) {
458 Slog.w(TAG, "Error parsing : " + resolveInfo.serviceInfo.packageName, caughtException);
459 return null;
460 }
461 if (cn == null) {
462 return null;
463 }
464 if (cn.indexOf('/') < 0) {
465 cn = resolveInfo.serviceInfo.packageName + "/" + cn;
466 }
467 return ComponentName.unflattenFromString(cn);
468 }
469
470 private ComponentName getComponentName(ResolveInfo resolveInfo) {
471 if (resolveInfo == null || resolveInfo.serviceInfo == null) return null;
472 return new ComponentName(resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name);
473 }
474
Adrian Roos3870d452014-09-05 18:22:28 +0200475 private void maybeEnableFactoryTrustAgents(LockPatternUtils utils, int userId) {
476 if (0 != Settings.Secure.getIntForUser(mContext.getContentResolver(),
477 Settings.Secure.TRUST_AGENTS_INITIALIZED, 0, userId)) {
478 return;
479 }
480 PackageManager pm = mContext.getPackageManager();
481 List<ResolveInfo> resolveInfos = resolveAllowedTrustAgents(pm, userId);
482 ArraySet<ComponentName> discoveredAgents = new ArraySet<>();
483 for (ResolveInfo resolveInfo : resolveInfos) {
484 ComponentName componentName = getComponentName(resolveInfo);
485 int applicationInfoFlags = resolveInfo.serviceInfo.applicationInfo.flags;
486 if ((applicationInfoFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
487 Log.i(TAG, "Leaving agent " + componentName + " disabled because package "
488 + "is not a system package.");
489 continue;
490 }
491 discoveredAgents.add(componentName);
492 }
493
494 List<ComponentName> previouslyEnabledAgents = utils.getEnabledTrustAgents(userId);
495 if (previouslyEnabledAgents != null) {
496 discoveredAgents.addAll(previouslyEnabledAgents);
497 }
498 utils.setEnabledTrustAgents(discoveredAgents, userId);
499 Settings.Secure.putIntForUser(mContext.getContentResolver(),
500 Settings.Secure.TRUST_AGENTS_INITIALIZED, 1, userId);
501 }
502
503 private List<ResolveInfo> resolveAllowedTrustAgents(PackageManager pm, int userId) {
504 List<ResolveInfo> resolveInfos = pm.queryIntentServicesAsUser(TRUST_AGENT_INTENT,
505 0 /* flags */, userId);
506 ArrayList<ResolveInfo> allowedAgents = new ArrayList<>(resolveInfos.size());
507 for (ResolveInfo resolveInfo : resolveInfos) {
508 if (resolveInfo.serviceInfo == null) continue;
509 if (resolveInfo.serviceInfo.applicationInfo == null) continue;
510 String packageName = resolveInfo.serviceInfo.packageName;
511 if (pm.checkPermission(PERMISSION_PROVIDE_AGENT, packageName)
512 != PackageManager.PERMISSION_GRANTED) {
513 ComponentName name = getComponentName(resolveInfo);
514 Log.w(TAG, "Skipping agent " + name + " because package does not have"
515 + " permission " + PERMISSION_PROVIDE_AGENT + ".");
516 continue;
517 }
518 allowedAgents.add(resolveInfo);
519 }
520 return allowedAgents;
521 }
522
Adrian Roos82142c22014-03-27 14:56:59 +0100523 // Agent dispatch and aggregation
524
525 private boolean aggregateIsTrusted(int userId) {
Adrian Roosb5e47222015-08-14 15:53:06 -0700526 if (!mStrongAuthTracker.isTrustAllowedForUser(userId)) {
Adrian Roos7046bfd2014-05-16 21:20:54 +0200527 return false;
528 }
Adrian Roos82142c22014-03-27 14:56:59 +0100529 for (int i = 0; i < mActiveAgents.size(); i++) {
530 AgentInfo info = mActiveAgents.valueAt(i);
531 if (info.userId == userId) {
532 if (info.agent.isTrusted()) {
533 return true;
534 }
535 }
536 }
537 return false;
538 }
539
Adrian Roos7861c662014-07-25 15:37:28 +0200540 private boolean aggregateIsTrustManaged(int userId) {
Adrian Roosb5e47222015-08-14 15:53:06 -0700541 if (!mStrongAuthTracker.isTrustAllowedForUser(userId)) {
Adrian Roos7861c662014-07-25 15:37:28 +0200542 return false;
543 }
544 for (int i = 0; i < mActiveAgents.size(); i++) {
545 AgentInfo info = mActiveAgents.valueAt(i);
546 if (info.userId == userId) {
547 if (info.agent.isManagingTrust()) {
548 return true;
549 }
550 }
551 }
552 return false;
553 }
554
Adrian Roos82142c22014-03-27 14:56:59 +0100555 private void dispatchUnlockAttempt(boolean successful, int userId) {
556 for (int i = 0; i < mActiveAgents.size(); i++) {
557 AgentInfo info = mActiveAgents.valueAt(i);
558 if (info.userId == userId) {
559 info.agent.onUnlockAttempt(successful);
560 }
561 }
Adrian Roos2c12cfa2014-06-25 23:28:53 +0200562 }
563
Adrian Roos82142c22014-03-27 14:56:59 +0100564 // Listeners
565
566 private void addListener(ITrustListener listener) {
567 for (int i = 0; i < mTrustListeners.size(); i++) {
568 if (mTrustListeners.get(i).asBinder() == listener.asBinder()) {
569 return;
570 }
571 }
572 mTrustListeners.add(listener);
Adrian Roos3870d452014-09-05 18:22:28 +0200573 updateTrustAll();
Adrian Roos82142c22014-03-27 14:56:59 +0100574 }
575
576 private void removeListener(ITrustListener listener) {
577 for (int i = 0; i < mTrustListeners.size(); i++) {
578 if (mTrustListeners.get(i).asBinder() == listener.asBinder()) {
Jay Civelli979a32e2014-07-18 16:47:36 -0700579 mTrustListeners.remove(i);
Adrian Roos82142c22014-03-27 14:56:59 +0100580 return;
581 }
582 }
583 }
584
Adrian Roos94e15a52015-04-16 12:23:18 -0700585 private void dispatchOnTrustChanged(boolean enabled, int userId, int flags) {
586 if (!enabled) flags = 0;
Adrian Roos82142c22014-03-27 14:56:59 +0100587 for (int i = 0; i < mTrustListeners.size(); i++) {
588 try {
Adrian Roos94e15a52015-04-16 12:23:18 -0700589 mTrustListeners.get(i).onTrustChanged(enabled, userId, flags);
Adrian Roosa4ba56b2014-05-20 12:56:25 +0200590 } catch (DeadObjectException e) {
Adrian Roos7861c662014-07-25 15:37:28 +0200591 Slog.d(TAG, "Removing dead TrustListener.");
592 mTrustListeners.remove(i);
593 i--;
594 } catch (RemoteException e) {
595 Slog.e(TAG, "Exception while notifying TrustListener.", e);
596 }
597 }
598 }
599
600 private void dispatchOnTrustManagedChanged(boolean managed, int userId) {
601 for (int i = 0; i < mTrustListeners.size(); i++) {
602 try {
603 mTrustListeners.get(i).onTrustManagedChanged(managed, userId);
604 } catch (DeadObjectException e) {
605 Slog.d(TAG, "Removing dead TrustListener.");
Adrian Roosa4ba56b2014-05-20 12:56:25 +0200606 mTrustListeners.remove(i);
607 i--;
Adrian Roos82142c22014-03-27 14:56:59 +0100608 } catch (RemoteException e) {
Adrian Roosa4ba56b2014-05-20 12:56:25 +0200609 Slog.e(TAG, "Exception while notifying TrustListener.", e);
Adrian Roos82142c22014-03-27 14:56:59 +0100610 }
611 }
612 }
613
Adrian Rooscbe614f2014-10-28 20:16:12 +0100614 // User lifecycle
615
616 @Override
617 public void onStartUser(int userId) {
Adrian Roos481a6df2014-11-20 19:48:56 +0100618 mHandler.obtainMessage(MSG_START_USER, userId, 0, null).sendToTarget();
Adrian Rooscbe614f2014-10-28 20:16:12 +0100619 }
620
621 @Override
622 public void onCleanupUser(int userId) {
Adrian Roos481a6df2014-11-20 19:48:56 +0100623 mHandler.obtainMessage(MSG_CLEANUP_USER, userId, 0, null).sendToTarget();
624 }
625
626 @Override
627 public void onSwitchUser(int userId) {
628 mHandler.obtainMessage(MSG_SWITCH_USER, userId, 0, null).sendToTarget();
Adrian Rooscbe614f2014-10-28 20:16:12 +0100629 }
630
Adrian Roos82142c22014-03-27 14:56:59 +0100631 // Plumbing
632
633 private final IBinder mService = new ITrustManager.Stub() {
634 @Override
635 public void reportUnlockAttempt(boolean authenticated, int userId) throws RemoteException {
636 enforceReportPermission();
637 mHandler.obtainMessage(MSG_DISPATCH_UNLOCK_ATTEMPT, authenticated ? 1 : 0, userId)
638 .sendToTarget();
639 }
640
641 @Override
642 public void reportEnabledTrustAgentsChanged(int userId) throws RemoteException {
643 enforceReportPermission();
644 // coalesce refresh messages.
645 mHandler.removeMessages(MSG_ENABLED_AGENTS_CHANGED);
646 mHandler.sendEmptyMessage(MSG_ENABLED_AGENTS_CHANGED);
647 }
648
649 @Override
Adrian Roos481a6df2014-11-20 19:48:56 +0100650 public void reportKeyguardShowingChanged() throws RemoteException {
651 enforceReportPermission();
652 // coalesce refresh messages.
653 mHandler.removeMessages(MSG_KEYGUARD_SHOWING_CHANGED);
654 mHandler.sendEmptyMessage(MSG_KEYGUARD_SHOWING_CHANGED);
655 }
656
657 @Override
Adrian Roos82142c22014-03-27 14:56:59 +0100658 public void registerTrustListener(ITrustListener trustListener) throws RemoteException {
659 enforceListenerPermission();
660 mHandler.obtainMessage(MSG_REGISTER_LISTENER, trustListener).sendToTarget();
661 }
662
663 @Override
664 public void unregisterTrustListener(ITrustListener trustListener) throws RemoteException {
665 enforceListenerPermission();
666 mHandler.obtainMessage(MSG_UNREGISTER_LISTENER, trustListener).sendToTarget();
667 }
668
Adrian Roosbcd07652014-10-22 16:57:16 +0200669 @Override
Adrian Roos50bfeec2014-11-20 16:21:11 +0100670 public boolean isDeviceLocked(int userId) throws RemoteException {
Adrian Roosbcd07652014-10-22 16:57:16 +0200671 userId = ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId,
Adrian Roos50bfeec2014-11-20 16:21:11 +0100672 false /* allowAll */, true /* requireFull */, "isDeviceLocked", null);
Clara Bayarri56878a92015-10-29 15:43:55 +0000673 if (!StorageManager.isFileBasedEncryptionEnabled()) {
674 userId = resolveProfileParent(userId);
675 }
Adrian Roos50bfeec2014-11-20 16:21:11 +0100676
Adrian Roos481a6df2014-11-20 19:48:56 +0100677 return isDeviceLockedInner(userId);
Adrian Roosbcd07652014-10-22 16:57:16 +0200678 }
679
Adrian Roos82893682015-04-02 16:17:46 +0200680 @Override
681 public boolean isDeviceSecure(int userId) throws RemoteException {
682 userId = ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId,
683 false /* allowAll */, true /* requireFull */, "isDeviceSecure", null);
684 userId = resolveProfileParent(userId);
685
686 long token = Binder.clearCallingIdentity();
687 try {
688 return new LockPatternUtils(mContext).isSecure(userId);
689 } finally {
690 Binder.restoreCallingIdentity(token);
691 }
692 }
693
Adrian Roos82142c22014-03-27 14:56:59 +0100694 private void enforceReportPermission() {
Adrian Roos2c12cfa2014-06-25 23:28:53 +0200695 mContext.enforceCallingOrSelfPermission(
696 Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE, "reporting trust events");
Adrian Roos82142c22014-03-27 14:56:59 +0100697 }
698
699 private void enforceListenerPermission() {
700 mContext.enforceCallingPermission(Manifest.permission.TRUST_LISTENER,
701 "register trust listener");
702 }
Adrian Roos7a4f3d42014-05-02 12:12:20 +0200703
704 @Override
705 protected void dump(FileDescriptor fd, final PrintWriter fout, String[] args) {
706 mContext.enforceCallingPermission(Manifest.permission.DUMP,
707 "dumping TrustManagerService");
Adrian Roos49d53452014-10-24 15:48:39 +0200708 if (isSafeMode()) {
709 fout.println("disabled because the system is in safe mode.");
710 return;
711 }
Adrian Rooscbe614f2014-10-28 20:16:12 +0100712 if (!mTrustAgentsCanRun) {
713 fout.println("disabled because the third-party apps can't run yet.");
714 return;
715 }
Adrian Roos7a4f3d42014-05-02 12:12:20 +0200716 final List<UserInfo> userInfos = mUserManager.getUsers(true /* excludeDying */);
Adrian Roos7a4f3d42014-05-02 12:12:20 +0200717 mHandler.runWithScissors(new Runnable() {
718 @Override
719 public void run() {
720 fout.println("Trust manager state:");
721 for (UserInfo user : userInfos) {
Adrian Roos481a6df2014-11-20 19:48:56 +0100722 dumpUser(fout, user, user.id == mCurrentUser);
Adrian Roos7a4f3d42014-05-02 12:12:20 +0200723 }
724 }
725 }, 1500);
726 }
727
728 private void dumpUser(PrintWriter fout, UserInfo user, boolean isCurrent) {
729 fout.printf(" User \"%s\" (id=%d, flags=%#x)",
730 user.name, user.id, user.flags);
Xiaohui Chen7cb69df2015-07-13 16:01:01 -0700731 if (!user.supportsSwitchToByUser()) {
Adrian Roos481a6df2014-11-20 19:48:56 +0100732 fout.println("(managed profile)");
733 fout.println(" disabled because switching to this user is not possible.");
734 return;
735 }
Adrian Roos7a4f3d42014-05-02 12:12:20 +0200736 if (isCurrent) {
737 fout.print(" (current)");
738 }
739 fout.print(": trusted=" + dumpBool(aggregateIsTrusted(user.id)));
Adrian Roos7861c662014-07-25 15:37:28 +0200740 fout.print(", trustManaged=" + dumpBool(aggregateIsTrustManaged(user.id)));
Adrian Roos481a6df2014-11-20 19:48:56 +0100741 fout.print(", deviceLocked=" + dumpBool(isDeviceLockedInner(user.id)));
Adrian Roosb5e47222015-08-14 15:53:06 -0700742 fout.print(", strongAuthRequired=" + dumpHex(
743 mStrongAuthTracker.getStrongAuthForUser(user.id)));
Adrian Roos7a4f3d42014-05-02 12:12:20 +0200744 fout.println();
745 fout.println(" Enabled agents:");
746 boolean duplicateSimpleNames = false;
747 ArraySet<String> simpleNames = new ArraySet<String>();
748 for (AgentInfo info : mActiveAgents) {
749 if (info.userId != user.id) { continue; }
750 boolean trusted = info.agent.isTrusted();
751 fout.print(" "); fout.println(info.component.flattenToShortString());
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200752 fout.print(" bound=" + dumpBool(info.agent.isBound()));
753 fout.print(", connected=" + dumpBool(info.agent.isConnected()));
Adrian Roos7861c662014-07-25 15:37:28 +0200754 fout.print(", managingTrust=" + dumpBool(info.agent.isManagingTrust()));
755 fout.print(", trusted=" + dumpBool(trusted));
756 fout.println();
Adrian Roos7a4f3d42014-05-02 12:12:20 +0200757 if (trusted) {
758 fout.println(" message=\"" + info.agent.getMessage() + "\"");
759 }
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200760 if (!info.agent.isConnected()) {
761 String restartTime = TrustArchive.formatDuration(
762 info.agent.getScheduledRestartUptimeMillis()
763 - SystemClock.uptimeMillis());
764 fout.println(" restartScheduledAt=" + restartTime);
765 }
Adrian Roos7a4f3d42014-05-02 12:12:20 +0200766 if (!simpleNames.add(TrustArchive.getSimpleName(info.component))) {
767 duplicateSimpleNames = true;
768 }
769 }
770 fout.println(" Events:");
771 mArchive.dump(fout, 50, user.id, " " /* linePrefix */, duplicateSimpleNames);
772 fout.println();
773 }
774
775 private String dumpBool(boolean b) {
776 return b ? "1" : "0";
777 }
Adrian Roosb5e47222015-08-14 15:53:06 -0700778
779 private String dumpHex(int i) {
780 return "0x" + Integer.toHexString(i);
781 }
Clara Bayarri56878a92015-10-29 15:43:55 +0000782
783 @Override
784 public void setDeviceLockedForUser(int userId, boolean value) {
785 mHandler.obtainMessage(MSG_SET_DEVICE_LOCKED, value ? 1 : 0, userId)
786 .sendToTarget();
787 }
Adrian Roos82142c22014-03-27 14:56:59 +0100788 };
789
Adrian Roosbcd07652014-10-22 16:57:16 +0200790 private int resolveProfileParent(int userId) {
791 long identity = Binder.clearCallingIdentity();
792 try {
793 UserInfo parent = mUserManager.getProfileParent(userId);
794 if (parent != null) {
795 return parent.getUserHandle().getIdentifier();
796 }
797 return userId;
798 } finally {
799 Binder.restoreCallingIdentity(identity);
800 }
801 }
802
Adrian Roos82142c22014-03-27 14:56:59 +0100803 private final Handler mHandler = new Handler() {
804 @Override
805 public void handleMessage(Message msg) {
806 switch (msg.what) {
807 case MSG_REGISTER_LISTENER:
808 addListener((ITrustListener) msg.obj);
809 break;
810 case MSG_UNREGISTER_LISTENER:
811 removeListener((ITrustListener) msg.obj);
812 break;
813 case MSG_DISPATCH_UNLOCK_ATTEMPT:
814 dispatchUnlockAttempt(msg.arg1 != 0, msg.arg2);
815 break;
816 case MSG_ENABLED_AGENTS_CHANGED:
Marco Fucci4e68f112014-08-29 12:31:48 -0700817 refreshAgentList(UserHandle.USER_ALL);
Adrian Roos481a6df2014-11-20 19:48:56 +0100818 // This is also called when the security mode of a user changes.
819 refreshDeviceLockedForUser(UserHandle.USER_ALL);
Adrian Roos82142c22014-03-27 14:56:59 +0100820 break;
Adrian Roos481a6df2014-11-20 19:48:56 +0100821 case MSG_KEYGUARD_SHOWING_CHANGED:
Adrian Roos7e2e40e2014-11-21 15:27:12 +0100822 refreshDeviceLockedForUser(mCurrentUser);
Adrian Roos481a6df2014-11-20 19:48:56 +0100823 break;
824 case MSG_START_USER:
825 case MSG_CLEANUP_USER:
826 refreshAgentList(msg.arg1);
827 break;
828 case MSG_SWITCH_USER:
829 mCurrentUser = msg.arg1;
830 refreshDeviceLockedForUser(UserHandle.USER_ALL);
831 break;
Clara Bayarri56878a92015-10-29 15:43:55 +0000832 case MSG_SET_DEVICE_LOCKED:
833 setDeviceLockedForUser(msg.arg2, msg.arg1 != 0);
834 break;
Adrian Roos82142c22014-03-27 14:56:59 +0100835 }
836 }
837 };
838
839 private final PackageMonitor mPackageMonitor = new PackageMonitor() {
840 @Override
841 public void onSomePackagesChanged() {
Marco Fucci4e68f112014-08-29 12:31:48 -0700842 refreshAgentList(UserHandle.USER_ALL);
Adrian Roos82142c22014-03-27 14:56:59 +0100843 }
844
845 @Override
846 public boolean onPackageChanged(String packageName, int uid, String[] components) {
847 // We're interested in all changes, even if just some components get enabled / disabled.
848 return true;
849 }
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200850
851 @Override
852 public void onPackageDisappeared(String packageName, int reason) {
853 removeAgentsOfPackage(packageName);
854 }
Adrian Roos82142c22014-03-27 14:56:59 +0100855 };
Adrian Roosca36b952014-05-16 18:52:29 +0200856
Adrian Roosb5e47222015-08-14 15:53:06 -0700857 private final StrongAuthTracker mStrongAuthTracker = new StrongAuthTracker() {
858 @Override
859 public void onStrongAuthRequiredChanged(int userId) {
860 refreshAgentList(userId);
861 }
862 };
863
Adrian Roos9dbe1902014-08-13 18:25:52 +0200864 private class Receiver extends BroadcastReceiver {
Adrian Roosca36b952014-05-16 18:52:29 +0200865
866 @Override
867 public void onReceive(Context context, Intent intent) {
Adrian Roos3870d452014-09-05 18:22:28 +0200868 String action = intent.getAction();
869 if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action)) {
Marco Fucci4e68f112014-08-29 12:31:48 -0700870 refreshAgentList(getSendingUserId());
871 updateDevicePolicyFeatures();
Adrian Roos3870d452014-09-05 18:22:28 +0200872 } else if (Intent.ACTION_USER_ADDED.equals(action)) {
Adrian Rooscbe614f2014-10-28 20:16:12 +0100873 int userId = getUserId(intent);
Adrian Roos3870d452014-09-05 18:22:28 +0200874 if (userId > 0) {
875 maybeEnableFactoryTrustAgents(mLockPatternUtils, userId);
Adrian Roos3870d452014-09-05 18:22:28 +0200876 }
Adrian Rooscbe614f2014-10-28 20:16:12 +0100877 } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
878 int userId = getUserId(intent);
879 if (userId > 0) {
Adrian Roos481a6df2014-11-20 19:48:56 +0100880 synchronized (mUserIsTrusted) {
881 mUserIsTrusted.delete(userId);
882 }
883 synchronized (mDeviceLockedForUser) {
884 mDeviceLockedForUser.delete(userId);
885 }
Adrian Rooscbe614f2014-10-28 20:16:12 +0100886 refreshAgentList(userId);
Adrian Roos481a6df2014-11-20 19:48:56 +0100887 refreshDeviceLockedForUser(userId);
Adrian Rooscbe614f2014-10-28 20:16:12 +0100888 }
889 }
890 }
891
892 private int getUserId(Intent intent) {
893 int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -100);
894 if (userId > 0) {
895 return userId;
896 } else {
897 Slog.wtf(TAG, "EXTRA_USER_HANDLE missing or invalid, value=" + userId);
898 return -100;
Adrian Roosca36b952014-05-16 18:52:29 +0200899 }
900 }
901
902 public void register(Context context) {
Adrian Roos9dbe1902014-08-13 18:25:52 +0200903 IntentFilter filter = new IntentFilter();
904 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
905 filter.addAction(Intent.ACTION_USER_PRESENT);
Adrian Roos3870d452014-09-05 18:22:28 +0200906 filter.addAction(Intent.ACTION_USER_ADDED);
Adrian Rooscbe614f2014-10-28 20:16:12 +0100907 filter.addAction(Intent.ACTION_USER_REMOVED);
Adrian Roosca36b952014-05-16 18:52:29 +0200908 context.registerReceiverAsUser(this,
909 UserHandle.ALL,
Adrian Roos9dbe1902014-08-13 18:25:52 +0200910 filter,
Adrian Roosca36b952014-05-16 18:52:29 +0200911 null /* permission */,
912 null /* scheduler */);
913 }
914 }
Adrian Roos82142c22014-03-27 14:56:59 +0100915}