blob: 6c70fe9a55010448e8cf593b5933762c1040f010 [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;
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 Roosb5e47222015-08-14 15:53:06 -070063import android.util.SparseIntArray;
Adrian Roos82142c22014-03-27 14:56:59 +010064import android.util.Xml;
Adrian Roos481a6df2014-11-20 19:48:56 +010065import android.view.IWindowManager;
Adrian Roos50bfeec2014-11-20 16:21:11 +010066import android.view.WindowManagerGlobal;
Adrian Roos82142c22014-03-27 14:56:59 +010067
Adrian Roos7a4f3d42014-05-02 12:12:20 +020068import java.io.FileDescriptor;
Adrian Roos82142c22014-03-27 14:56:59 +010069import java.io.IOException;
Adrian Roos7a4f3d42014-05-02 12:12:20 +020070import java.io.PrintWriter;
Adrian Roos82142c22014-03-27 14:56:59 +010071import java.util.ArrayList;
72import java.util.List;
73
74/**
75 * Manages trust agents and trust listeners.
76 *
77 * It is responsible for binding to the enabled {@link android.service.trust.TrustAgentService}s
78 * of each user and notifies them about events that are relevant to them.
79 * It start and stops them based on the value of
80 * {@link com.android.internal.widget.LockPatternUtils#getEnabledTrustAgents(int)}.
81 *
82 * It also keeps a set of {@link android.app.trust.ITrustListener}s that are notified whenever the
83 * trust state changes for any user.
84 *
85 * Trust state and the setting of enabled agents is kept per user and each user has its own
86 * instance of a {@link android.service.trust.TrustAgentService}.
87 */
88public class TrustManagerService extends SystemService {
89
90 private static final boolean DEBUG = false;
91 private static final String TAG = "TrustManagerService";
92
93 private static final Intent TRUST_AGENT_INTENT =
94 new Intent(TrustAgentService.SERVICE_INTERFACE);
Adrian Roos18ea8932014-05-28 14:53:06 +020095 private static final String PERMISSION_PROVIDE_AGENT = Manifest.permission.PROVIDE_TRUST_AGENT;
Adrian Roos82142c22014-03-27 14:56:59 +010096
97 private static final int MSG_REGISTER_LISTENER = 1;
98 private static final int MSG_UNREGISTER_LISTENER = 2;
99 private static final int MSG_DISPATCH_UNLOCK_ATTEMPT = 3;
100 private static final int MSG_ENABLED_AGENTS_CHANGED = 4;
Adrian Roos481a6df2014-11-20 19:48:56 +0100101 private static final int MSG_KEYGUARD_SHOWING_CHANGED = 6;
102 private static final int MSG_START_USER = 7;
103 private static final int MSG_CLEANUP_USER = 8;
104 private static final int MSG_SWITCH_USER = 9;
Adrian Roos82142c22014-03-27 14:56:59 +0100105
Adrian Roosb5e47222015-08-14 15:53:06 -0700106 private final ArraySet<AgentInfo> mActiveAgents = new ArraySet<>();
107 private final ArrayList<ITrustListener> mTrustListeners = new ArrayList<>();
Adrian Roos9dbe1902014-08-13 18:25:52 +0200108 private final Receiver mReceiver = new Receiver();
Adrian Roosb5e47222015-08-14 15:53:06 -0700109
Adrian Roos7a4f3d42014-05-02 12:12:20 +0200110 /* package */ final TrustArchive mArchive = new TrustArchive();
Adrian Roos82142c22014-03-27 14:56:59 +0100111 private final Context mContext;
Adrian Roos3870d452014-09-05 18:22:28 +0200112 private final LockPatternUtils mLockPatternUtils;
Adrian Roosbcd07652014-10-22 16:57:16 +0200113 private final UserManager mUserManager;
Adrian Rooscbe614f2014-10-28 20:16:12 +0100114 private final ActivityManager mActivityManager;
Adrian Roos82142c22014-03-27 14:56:59 +0100115
Adrian Roosbcd07652014-10-22 16:57:16 +0200116 @GuardedBy("mUserIsTrusted")
117 private final SparseBooleanArray mUserIsTrusted = new SparseBooleanArray();
Adrian Roos82142c22014-03-27 14:56:59 +0100118
Adrian Roos481a6df2014-11-20 19:48:56 +0100119 @GuardedBy("mDeviceLockedForUser")
120 private final SparseBooleanArray mDeviceLockedForUser = new SparseBooleanArray();
121
Adrian Rooscbe614f2014-10-28 20:16:12 +0100122 private boolean mTrustAgentsCanRun = false;
Adrian Roos481a6df2014-11-20 19:48:56 +0100123 private int mCurrentUser = UserHandle.USER_OWNER;
Adrian Rooscbe614f2014-10-28 20:16:12 +0100124
Adrian Roos82142c22014-03-27 14:56:59 +0100125 public TrustManagerService(Context context) {
126 super(context);
127 mContext = context;
128 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
Adrian Rooscbe614f2014-10-28 20:16:12 +0100129 mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
Adrian Roos3870d452014-09-05 18:22:28 +0200130 mLockPatternUtils = new LockPatternUtils(context);
Adrian Roos82142c22014-03-27 14:56:59 +0100131 }
132
133 @Override
134 public void onStart() {
135 publishBinderService(Context.TRUST_SERVICE, mService);
136 }
137
138 @Override
139 public void onBootPhase(int phase) {
Adrian Roos49d53452014-10-24 15:48:39 +0200140 if (isSafeMode()) {
141 // No trust agents in safe mode.
142 return;
143 }
144 if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
Adrian Roos82142c22014-03-27 14:56:59 +0100145 mPackageMonitor.register(mContext, mHandler.getLooper(), UserHandle.ALL, true);
Adrian Roos9dbe1902014-08-13 18:25:52 +0200146 mReceiver.register(mContext);
Adrian Roosb5e47222015-08-14 15:53:06 -0700147 mLockPatternUtils.registerStrongAuthTracker(mStrongAuthTracker);
Adrian Rooscbe614f2014-10-28 20:16:12 +0100148 } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
149 mTrustAgentsCanRun = true;
Marco Fucci4e68f112014-08-29 12:31:48 -0700150 refreshAgentList(UserHandle.USER_ALL);
Adrian Roos49d53452014-10-24 15:48:39 +0200151 } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
Adrian Roos7b4a38b2014-10-21 17:07:39 +0200152 maybeEnableFactoryTrustAgents(mLockPatternUtils, UserHandle.USER_OWNER);
Adrian Roos82142c22014-03-27 14:56:59 +0100153 }
154 }
155
156 // Agent management
157
158 private static final class AgentInfo {
159 CharSequence label;
160 Drawable icon;
161 ComponentName component; // service that implements ITrustAgent
162 ComponentName settings; // setting to launch to modify agent.
163 TrustAgentWrapper agent;
164 int userId;
165
166 @Override
167 public boolean equals(Object other) {
168 if (!(other instanceof AgentInfo)) {
169 return false;
170 }
171 AgentInfo o = (AgentInfo) other;
172 return component.equals(o.component) && userId == o.userId;
173 }
174
175 @Override
176 public int hashCode() {
177 return component.hashCode() * 31 + userId;
178 }
179 }
180
181 private void updateTrustAll() {
182 List<UserInfo> userInfos = mUserManager.getUsers(true /* excludeDying */);
183 for (UserInfo userInfo : userInfos) {
Adrian Roos94e15a52015-04-16 12:23:18 -0700184 updateTrust(userInfo.id, 0);
Adrian Roos82142c22014-03-27 14:56:59 +0100185 }
186 }
187
Adrian Roos94e15a52015-04-16 12:23:18 -0700188 public void updateTrust(int userId, int flags) {
Adrian Roos7861c662014-07-25 15:37:28 +0200189 dispatchOnTrustManagedChanged(aggregateIsTrustManaged(userId), userId);
Adrian Roosbcd07652014-10-22 16:57:16 +0200190 boolean trusted = aggregateIsTrusted(userId);
Adrian Roos481a6df2014-11-20 19:48:56 +0100191 boolean changed;
Adrian Roosbcd07652014-10-22 16:57:16 +0200192 synchronized (mUserIsTrusted) {
Adrian Roos481a6df2014-11-20 19:48:56 +0100193 changed = mUserIsTrusted.get(userId) != trusted;
Adrian Roosbcd07652014-10-22 16:57:16 +0200194 mUserIsTrusted.put(userId, trusted);
195 }
Adrian Roos94e15a52015-04-16 12:23:18 -0700196 dispatchOnTrustChanged(trusted, userId, flags);
Adrian Roos481a6df2014-11-20 19:48:56 +0100197 if (changed) {
198 refreshDeviceLockedForUser(userId);
199 }
Adrian Roos82142c22014-03-27 14:56:59 +0100200 }
201
Marco Fucci4e68f112014-08-29 12:31:48 -0700202 void refreshAgentList(int userId) {
Adrian Roos82142c22014-03-27 14:56:59 +0100203 if (DEBUG) Slog.d(TAG, "refreshAgentList()");
Adrian Rooscbe614f2014-10-28 20:16:12 +0100204 if (!mTrustAgentsCanRun) {
Adrian Roos49d53452014-10-24 15:48:39 +0200205 return;
206 }
Adrian Roose681c272014-09-08 14:03:47 +0200207 if (userId != UserHandle.USER_ALL && userId < UserHandle.USER_OWNER) {
208 Log.e(TAG, "refreshAgentList(userId=" + userId + "): Invalid user handle,"
209 + " must be USER_ALL or a specific user.", new Throwable("here"));
210 userId = UserHandle.USER_ALL;
211 }
Adrian Roos82142c22014-03-27 14:56:59 +0100212 PackageManager pm = mContext.getPackageManager();
213
Marco Fucci4e68f112014-08-29 12:31:48 -0700214 List<UserInfo> userInfos;
215 if (userId == UserHandle.USER_ALL) {
216 userInfos = mUserManager.getUsers(true /* excludeDying */);
217 } else {
218 userInfos = new ArrayList<>();
219 userInfos.add(mUserManager.getUserInfo(userId));
220 }
Adrian Roos3870d452014-09-05 18:22:28 +0200221 LockPatternUtils lockPatternUtils = mLockPatternUtils;
Adrian Roos82142c22014-03-27 14:56:59 +0100222
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200223 ArraySet<AgentInfo> obsoleteAgents = new ArraySet<>();
224 obsoleteAgents.addAll(mActiveAgents);
Adrian Roos82142c22014-03-27 14:56:59 +0100225
226 for (UserInfo userInfo : userInfos) {
Adrian Roosfc29e0b2014-11-11 12:55:44 +0100227 if (userInfo == null || userInfo.partial || !userInfo.isEnabled()
228 || userInfo.guestToRemove) continue;
Adrian Roos3870d452014-09-05 18:22:28 +0200229 if (!userInfo.supportsSwitchTo()) continue;
Adrian Rooscbe614f2014-10-28 20:16:12 +0100230 if (!mActivityManager.isUserRunning(userInfo.id)) continue;
Adrian Roos481a6df2014-11-20 19:48:56 +0100231 if (!lockPatternUtils.isSecure(userInfo.id)) continue;
Adrian Roosb5e47222015-08-14 15:53:06 -0700232 if (!mStrongAuthTracker.isTrustAllowedForUser(userInfo.id)) continue;
Adrian Roos8f211582014-07-29 15:09:57 +0200233 DevicePolicyManager dpm = lockPatternUtils.getDevicePolicyManager();
234 int disabledFeatures = dpm.getKeyguardDisabledFeatures(null, userInfo.id);
Jim Miller604e7552014-07-18 19:00:02 -0700235 final boolean disableTrustAgents =
Adrian Roosca36b952014-05-16 18:52:29 +0200236 (disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0;
237
Adrian Roos82142c22014-03-27 14:56:59 +0100238 List<ComponentName> enabledAgents = lockPatternUtils.getEnabledTrustAgents(userInfo.id);
Adrian Roos8f211582014-07-29 15:09:57 +0200239 if (enabledAgents == null) {
Adrian Roos82142c22014-03-27 14:56:59 +0100240 continue;
241 }
Adrian Roos3870d452014-09-05 18:22:28 +0200242 List<ResolveInfo> resolveInfos = resolveAllowedTrustAgents(pm, userInfo.id);
Adrian Roos82142c22014-03-27 14:56:59 +0100243 for (ResolveInfo resolveInfo : resolveInfos) {
Adrian Roos82142c22014-03-27 14:56:59 +0100244 ComponentName name = getComponentName(resolveInfo);
Adrian Roos82142c22014-03-27 14:56:59 +0100245
Adrian Roos3870d452014-09-05 18:22:28 +0200246 if (!enabledAgents.contains(name)) continue;
Adrian Roos8f211582014-07-29 15:09:57 +0200247 if (disableTrustAgents) {
Jim Millere303bf42014-08-26 17:12:29 -0700248 List<PersistableBundle> config =
249 dpm.getTrustAgentConfiguration(null /* admin */, name, userInfo.id);
Adrian Roos8f211582014-07-29 15:09:57 +0200250 // Disable agent if no features are enabled.
Jim Millere303bf42014-08-26 17:12:29 -0700251 if (config == null || config.isEmpty()) continue;
Adrian Roos8f211582014-07-29 15:09:57 +0200252 }
253
Adrian Roos82142c22014-03-27 14:56:59 +0100254 AgentInfo agentInfo = new AgentInfo();
255 agentInfo.component = name;
256 agentInfo.userId = userInfo.id;
257 if (!mActiveAgents.contains(agentInfo)) {
258 agentInfo.label = resolveInfo.loadLabel(pm);
259 agentInfo.icon = resolveInfo.loadIcon(pm);
260 agentInfo.settings = getSettingsComponentName(pm, resolveInfo);
261 agentInfo.agent = new TrustAgentWrapper(mContext, this,
262 new Intent().setComponent(name), userInfo.getUserHandle());
263 mActiveAgents.add(agentInfo);
264 } else {
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200265 obsoleteAgents.remove(agentInfo);
Adrian Roos82142c22014-03-27 14:56:59 +0100266 }
267 }
268 }
269
270 boolean trustMayHaveChanged = false;
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200271 for (int i = 0; i < obsoleteAgents.size(); i++) {
272 AgentInfo info = obsoleteAgents.valueAt(i);
Adrian Roose681c272014-09-08 14:03:47 +0200273 if (userId == UserHandle.USER_ALL || userId == info.userId) {
274 if (info.agent.isManagingTrust()) {
275 trustMayHaveChanged = true;
276 }
Adrian Roosfc29e0b2014-11-11 12:55:44 +0100277 info.agent.destroy();
Adrian Roose681c272014-09-08 14:03:47 +0200278 mActiveAgents.remove(info);
Adrian Roos82142c22014-03-27 14:56:59 +0100279 }
Adrian Roos82142c22014-03-27 14:56:59 +0100280 }
281
282 if (trustMayHaveChanged) {
Adrian Rooscbe614f2014-10-28 20:16:12 +0100283 if (userId == UserHandle.USER_ALL) {
284 updateTrustAll();
285 } else {
Adrian Roos94e15a52015-04-16 12:23:18 -0700286 updateTrust(userId, 0);
Adrian Rooscbe614f2014-10-28 20:16:12 +0100287 }
Adrian Roos82142c22014-03-27 14:56:59 +0100288 }
289 }
290
Adrian Roos481a6df2014-11-20 19:48:56 +0100291 boolean isDeviceLockedInner(int userId) {
292 synchronized (mDeviceLockedForUser) {
293 return mDeviceLockedForUser.get(userId, true);
294 }
295 }
296
297 private void refreshDeviceLockedForUser(int userId) {
298 if (userId != UserHandle.USER_ALL && userId < UserHandle.USER_OWNER) {
Adrian Roos7e2e40e2014-11-21 15:27:12 +0100299 Log.e(TAG, "refreshDeviceLockedForUser(userId=" + userId + "): Invalid user handle,"
Adrian Roos481a6df2014-11-20 19:48:56 +0100300 + " must be USER_ALL or a specific user.", new Throwable("here"));
301 userId = UserHandle.USER_ALL;
302 }
303
304 List<UserInfo> userInfos;
305 if (userId == UserHandle.USER_ALL) {
306 userInfos = mUserManager.getUsers(true /* excludeDying */);
307 } else {
308 userInfos = new ArrayList<>();
309 userInfos.add(mUserManager.getUserInfo(userId));
310 }
311
312 IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
313
314 for (int i = 0; i < userInfos.size(); i++) {
315 UserInfo info = userInfos.get(i);
316
317 if (info == null || info.partial || !info.isEnabled() || info.guestToRemove
318 || !info.supportsSwitchTo()) {
319 continue;
320 }
321
322 int id = info.id;
323 boolean secure = mLockPatternUtils.isSecure(id);
324 boolean trusted = aggregateIsTrusted(id);
325 boolean showingKeyguard = true;
326 if (mCurrentUser == id) {
327 try {
328 showingKeyguard = wm.isKeyguardLocked();
329 } catch (RemoteException e) {
330 }
331 }
332 boolean deviceLocked = secure && showingKeyguard && !trusted;
333
334 boolean changed;
335 synchronized (mDeviceLockedForUser) {
336 changed = isDeviceLockedInner(id) != deviceLocked;
337 mDeviceLockedForUser.put(id, deviceLocked);
338 }
339 if (changed) {
340 dispatchDeviceLocked(id, deviceLocked);
341 }
342 }
343 }
344
345 private void dispatchDeviceLocked(int userId, boolean isLocked) {
346 for (int i = 0; i < mActiveAgents.size(); i++) {
347 AgentInfo agent = mActiveAgents.valueAt(i);
348 if (agent.userId == userId) {
349 if (isLocked) {
350 agent.agent.onDeviceLocked();
351 } else{
352 agent.agent.onDeviceUnlocked();
353 }
354 }
355 }
356 }
357
Marco Fucci4e68f112014-08-29 12:31:48 -0700358 void updateDevicePolicyFeatures() {
Adrian Roos8f211582014-07-29 15:09:57 +0200359 for (int i = 0; i < mActiveAgents.size(); i++) {
360 AgentInfo info = mActiveAgents.valueAt(i);
361 if (info.agent.isConnected()) {
362 info.agent.updateDevicePolicyFeatures();
363 }
364 }
365 }
366
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200367 private void removeAgentsOfPackage(String packageName) {
368 boolean trustMayHaveChanged = false;
369 for (int i = mActiveAgents.size() - 1; i >= 0; i--) {
370 AgentInfo info = mActiveAgents.valueAt(i);
371 if (packageName.equals(info.component.getPackageName())) {
372 Log.i(TAG, "Resetting agent " + info.component.flattenToShortString());
Adrian Roos7861c662014-07-25 15:37:28 +0200373 if (info.agent.isManagingTrust()) {
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200374 trustMayHaveChanged = true;
375 }
Adrian Roosfc29e0b2014-11-11 12:55:44 +0100376 info.agent.destroy();
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200377 mActiveAgents.removeAt(i);
378 }
379 }
380 if (trustMayHaveChanged) {
381 updateTrustAll();
382 }
383 }
384
385 public void resetAgent(ComponentName name, int userId) {
386 boolean trustMayHaveChanged = false;
387 for (int i = mActiveAgents.size() - 1; i >= 0; i--) {
388 AgentInfo info = mActiveAgents.valueAt(i);
389 if (name.equals(info.component) && userId == info.userId) {
390 Log.i(TAG, "Resetting agent " + info.component.flattenToShortString());
Adrian Roos7861c662014-07-25 15:37:28 +0200391 if (info.agent.isManagingTrust()) {
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200392 trustMayHaveChanged = true;
393 }
Adrian Roosfc29e0b2014-11-11 12:55:44 +0100394 info.agent.destroy();
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200395 mActiveAgents.removeAt(i);
396 }
397 }
398 if (trustMayHaveChanged) {
Adrian Roos94e15a52015-04-16 12:23:18 -0700399 updateTrust(userId, 0);
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200400 }
Marco Fucci4e68f112014-08-29 12:31:48 -0700401 refreshAgentList(userId);
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200402 }
403
Adrian Roos82142c22014-03-27 14:56:59 +0100404 private ComponentName getSettingsComponentName(PackageManager pm, ResolveInfo resolveInfo) {
405 if (resolveInfo == null || resolveInfo.serviceInfo == null
406 || resolveInfo.serviceInfo.metaData == null) return null;
407 String cn = null;
408 XmlResourceParser parser = null;
409 Exception caughtException = null;
410 try {
411 parser = resolveInfo.serviceInfo.loadXmlMetaData(pm,
412 TrustAgentService.TRUST_AGENT_META_DATA);
413 if (parser == null) {
414 Slog.w(TAG, "Can't find " + TrustAgentService.TRUST_AGENT_META_DATA + " meta-data");
415 return null;
416 }
417 Resources res = pm.getResourcesForApplication(resolveInfo.serviceInfo.applicationInfo);
418 AttributeSet attrs = Xml.asAttributeSet(parser);
419 int type;
420 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
421 && type != XmlPullParser.START_TAG) {
422 // Drain preamble.
423 }
424 String nodeName = parser.getName();
Adrian Roos7e03dfc2014-05-16 16:06:28 +0200425 if (!"trust-agent".equals(nodeName)) {
426 Slog.w(TAG, "Meta-data does not start with trust-agent tag");
Adrian Roos82142c22014-03-27 14:56:59 +0100427 return null;
428 }
429 TypedArray sa = res
430 .obtainAttributes(attrs, com.android.internal.R.styleable.TrustAgent);
431 cn = sa.getString(com.android.internal.R.styleable.TrustAgent_settingsActivity);
432 sa.recycle();
433 } catch (PackageManager.NameNotFoundException e) {
434 caughtException = e;
435 } catch (IOException e) {
436 caughtException = e;
437 } catch (XmlPullParserException e) {
438 caughtException = e;
439 } finally {
440 if (parser != null) parser.close();
441 }
442 if (caughtException != null) {
443 Slog.w(TAG, "Error parsing : " + resolveInfo.serviceInfo.packageName, caughtException);
444 return null;
445 }
446 if (cn == null) {
447 return null;
448 }
449 if (cn.indexOf('/') < 0) {
450 cn = resolveInfo.serviceInfo.packageName + "/" + cn;
451 }
452 return ComponentName.unflattenFromString(cn);
453 }
454
455 private ComponentName getComponentName(ResolveInfo resolveInfo) {
456 if (resolveInfo == null || resolveInfo.serviceInfo == null) return null;
457 return new ComponentName(resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name);
458 }
459
Adrian Roos3870d452014-09-05 18:22:28 +0200460 private void maybeEnableFactoryTrustAgents(LockPatternUtils utils, int userId) {
461 if (0 != Settings.Secure.getIntForUser(mContext.getContentResolver(),
462 Settings.Secure.TRUST_AGENTS_INITIALIZED, 0, userId)) {
463 return;
464 }
465 PackageManager pm = mContext.getPackageManager();
466 List<ResolveInfo> resolveInfos = resolveAllowedTrustAgents(pm, userId);
467 ArraySet<ComponentName> discoveredAgents = new ArraySet<>();
468 for (ResolveInfo resolveInfo : resolveInfos) {
469 ComponentName componentName = getComponentName(resolveInfo);
470 int applicationInfoFlags = resolveInfo.serviceInfo.applicationInfo.flags;
471 if ((applicationInfoFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
472 Log.i(TAG, "Leaving agent " + componentName + " disabled because package "
473 + "is not a system package.");
474 continue;
475 }
476 discoveredAgents.add(componentName);
477 }
478
479 List<ComponentName> previouslyEnabledAgents = utils.getEnabledTrustAgents(userId);
480 if (previouslyEnabledAgents != null) {
481 discoveredAgents.addAll(previouslyEnabledAgents);
482 }
483 utils.setEnabledTrustAgents(discoveredAgents, userId);
484 Settings.Secure.putIntForUser(mContext.getContentResolver(),
485 Settings.Secure.TRUST_AGENTS_INITIALIZED, 1, userId);
486 }
487
488 private List<ResolveInfo> resolveAllowedTrustAgents(PackageManager pm, int userId) {
489 List<ResolveInfo> resolveInfos = pm.queryIntentServicesAsUser(TRUST_AGENT_INTENT,
490 0 /* flags */, userId);
491 ArrayList<ResolveInfo> allowedAgents = new ArrayList<>(resolveInfos.size());
492 for (ResolveInfo resolveInfo : resolveInfos) {
493 if (resolveInfo.serviceInfo == null) continue;
494 if (resolveInfo.serviceInfo.applicationInfo == null) continue;
495 String packageName = resolveInfo.serviceInfo.packageName;
496 if (pm.checkPermission(PERMISSION_PROVIDE_AGENT, packageName)
497 != PackageManager.PERMISSION_GRANTED) {
498 ComponentName name = getComponentName(resolveInfo);
499 Log.w(TAG, "Skipping agent " + name + " because package does not have"
500 + " permission " + PERMISSION_PROVIDE_AGENT + ".");
501 continue;
502 }
503 allowedAgents.add(resolveInfo);
504 }
505 return allowedAgents;
506 }
507
Adrian Roos82142c22014-03-27 14:56:59 +0100508 // Agent dispatch and aggregation
509
510 private boolean aggregateIsTrusted(int userId) {
Adrian Roosb5e47222015-08-14 15:53:06 -0700511 if (!mStrongAuthTracker.isTrustAllowedForUser(userId)) {
Adrian Roos7046bfd2014-05-16 21:20:54 +0200512 return false;
513 }
Adrian Roos82142c22014-03-27 14:56:59 +0100514 for (int i = 0; i < mActiveAgents.size(); i++) {
515 AgentInfo info = mActiveAgents.valueAt(i);
516 if (info.userId == userId) {
517 if (info.agent.isTrusted()) {
518 return true;
519 }
520 }
521 }
522 return false;
523 }
524
Adrian Roos7861c662014-07-25 15:37:28 +0200525 private boolean aggregateIsTrustManaged(int userId) {
Adrian Roosb5e47222015-08-14 15:53:06 -0700526 if (!mStrongAuthTracker.isTrustAllowedForUser(userId)) {
Adrian Roos7861c662014-07-25 15:37:28 +0200527 return false;
528 }
529 for (int i = 0; i < mActiveAgents.size(); i++) {
530 AgentInfo info = mActiveAgents.valueAt(i);
531 if (info.userId == userId) {
532 if (info.agent.isManagingTrust()) {
533 return true;
534 }
535 }
536 }
537 return false;
538 }
539
Adrian Roos82142c22014-03-27 14:56:59 +0100540 private void dispatchUnlockAttempt(boolean successful, int userId) {
541 for (int i = 0; i < mActiveAgents.size(); i++) {
542 AgentInfo info = mActiveAgents.valueAt(i);
543 if (info.userId == userId) {
544 info.agent.onUnlockAttempt(successful);
545 }
546 }
Adrian Roos2c12cfa2014-06-25 23:28:53 +0200547 }
548
Adrian Roos82142c22014-03-27 14:56:59 +0100549 // Listeners
550
551 private void addListener(ITrustListener listener) {
552 for (int i = 0; i < mTrustListeners.size(); i++) {
553 if (mTrustListeners.get(i).asBinder() == listener.asBinder()) {
554 return;
555 }
556 }
557 mTrustListeners.add(listener);
Adrian Roos3870d452014-09-05 18:22:28 +0200558 updateTrustAll();
Adrian Roos82142c22014-03-27 14:56:59 +0100559 }
560
561 private void removeListener(ITrustListener listener) {
562 for (int i = 0; i < mTrustListeners.size(); i++) {
563 if (mTrustListeners.get(i).asBinder() == listener.asBinder()) {
Jay Civelli979a32e2014-07-18 16:47:36 -0700564 mTrustListeners.remove(i);
Adrian Roos82142c22014-03-27 14:56:59 +0100565 return;
566 }
567 }
568 }
569
Adrian Roos94e15a52015-04-16 12:23:18 -0700570 private void dispatchOnTrustChanged(boolean enabled, int userId, int flags) {
571 if (!enabled) flags = 0;
Adrian Roos82142c22014-03-27 14:56:59 +0100572 for (int i = 0; i < mTrustListeners.size(); i++) {
573 try {
Adrian Roos94e15a52015-04-16 12:23:18 -0700574 mTrustListeners.get(i).onTrustChanged(enabled, userId, flags);
Adrian Roosa4ba56b2014-05-20 12:56:25 +0200575 } catch (DeadObjectException e) {
Adrian Roos7861c662014-07-25 15:37:28 +0200576 Slog.d(TAG, "Removing dead TrustListener.");
577 mTrustListeners.remove(i);
578 i--;
579 } catch (RemoteException e) {
580 Slog.e(TAG, "Exception while notifying TrustListener.", e);
581 }
582 }
583 }
584
585 private void dispatchOnTrustManagedChanged(boolean managed, int userId) {
586 for (int i = 0; i < mTrustListeners.size(); i++) {
587 try {
588 mTrustListeners.get(i).onTrustManagedChanged(managed, userId);
589 } catch (DeadObjectException e) {
590 Slog.d(TAG, "Removing dead TrustListener.");
Adrian Roosa4ba56b2014-05-20 12:56:25 +0200591 mTrustListeners.remove(i);
592 i--;
Adrian Roos82142c22014-03-27 14:56:59 +0100593 } catch (RemoteException e) {
Adrian Roosa4ba56b2014-05-20 12:56:25 +0200594 Slog.e(TAG, "Exception while notifying TrustListener.", e);
Adrian Roos82142c22014-03-27 14:56:59 +0100595 }
596 }
597 }
598
Adrian Rooscbe614f2014-10-28 20:16:12 +0100599 // User lifecycle
600
601 @Override
602 public void onStartUser(int userId) {
Adrian Roos481a6df2014-11-20 19:48:56 +0100603 mHandler.obtainMessage(MSG_START_USER, userId, 0, null).sendToTarget();
Adrian Rooscbe614f2014-10-28 20:16:12 +0100604 }
605
606 @Override
607 public void onCleanupUser(int userId) {
Adrian Roos481a6df2014-11-20 19:48:56 +0100608 mHandler.obtainMessage(MSG_CLEANUP_USER, userId, 0, null).sendToTarget();
609 }
610
611 @Override
612 public void onSwitchUser(int userId) {
613 mHandler.obtainMessage(MSG_SWITCH_USER, userId, 0, null).sendToTarget();
Adrian Rooscbe614f2014-10-28 20:16:12 +0100614 }
615
Adrian Roos82142c22014-03-27 14:56:59 +0100616 // Plumbing
617
618 private final IBinder mService = new ITrustManager.Stub() {
619 @Override
620 public void reportUnlockAttempt(boolean authenticated, int userId) throws RemoteException {
621 enforceReportPermission();
622 mHandler.obtainMessage(MSG_DISPATCH_UNLOCK_ATTEMPT, authenticated ? 1 : 0, userId)
623 .sendToTarget();
624 }
625
626 @Override
627 public void reportEnabledTrustAgentsChanged(int userId) throws RemoteException {
628 enforceReportPermission();
629 // coalesce refresh messages.
630 mHandler.removeMessages(MSG_ENABLED_AGENTS_CHANGED);
631 mHandler.sendEmptyMessage(MSG_ENABLED_AGENTS_CHANGED);
632 }
633
634 @Override
Adrian Roos481a6df2014-11-20 19:48:56 +0100635 public void reportKeyguardShowingChanged() throws RemoteException {
636 enforceReportPermission();
637 // coalesce refresh messages.
638 mHandler.removeMessages(MSG_KEYGUARD_SHOWING_CHANGED);
639 mHandler.sendEmptyMessage(MSG_KEYGUARD_SHOWING_CHANGED);
640 }
641
642 @Override
Adrian Roos82142c22014-03-27 14:56:59 +0100643 public void registerTrustListener(ITrustListener trustListener) throws RemoteException {
644 enforceListenerPermission();
645 mHandler.obtainMessage(MSG_REGISTER_LISTENER, trustListener).sendToTarget();
646 }
647
648 @Override
649 public void unregisterTrustListener(ITrustListener trustListener) throws RemoteException {
650 enforceListenerPermission();
651 mHandler.obtainMessage(MSG_UNREGISTER_LISTENER, trustListener).sendToTarget();
652 }
653
Adrian Roosbcd07652014-10-22 16:57:16 +0200654 @Override
Adrian Roos50bfeec2014-11-20 16:21:11 +0100655 public boolean isDeviceLocked(int userId) throws RemoteException {
Adrian Roosbcd07652014-10-22 16:57:16 +0200656 userId = ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId,
Adrian Roos50bfeec2014-11-20 16:21:11 +0100657 false /* allowAll */, true /* requireFull */, "isDeviceLocked", null);
Adrian Roosbcd07652014-10-22 16:57:16 +0200658 userId = resolveProfileParent(userId);
Adrian Roos50bfeec2014-11-20 16:21:11 +0100659
Adrian Roos481a6df2014-11-20 19:48:56 +0100660 return isDeviceLockedInner(userId);
Adrian Roosbcd07652014-10-22 16:57:16 +0200661 }
662
Adrian Roos82893682015-04-02 16:17:46 +0200663 @Override
664 public boolean isDeviceSecure(int userId) throws RemoteException {
665 userId = ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId,
666 false /* allowAll */, true /* requireFull */, "isDeviceSecure", null);
667 userId = resolveProfileParent(userId);
668
669 long token = Binder.clearCallingIdentity();
670 try {
671 return new LockPatternUtils(mContext).isSecure(userId);
672 } finally {
673 Binder.restoreCallingIdentity(token);
674 }
675 }
676
Adrian Roos82142c22014-03-27 14:56:59 +0100677 private void enforceReportPermission() {
Adrian Roos2c12cfa2014-06-25 23:28:53 +0200678 mContext.enforceCallingOrSelfPermission(
679 Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE, "reporting trust events");
Adrian Roos82142c22014-03-27 14:56:59 +0100680 }
681
682 private void enforceListenerPermission() {
683 mContext.enforceCallingPermission(Manifest.permission.TRUST_LISTENER,
684 "register trust listener");
685 }
Adrian Roos7a4f3d42014-05-02 12:12:20 +0200686
687 @Override
688 protected void dump(FileDescriptor fd, final PrintWriter fout, String[] args) {
689 mContext.enforceCallingPermission(Manifest.permission.DUMP,
690 "dumping TrustManagerService");
Adrian Roos49d53452014-10-24 15:48:39 +0200691 if (isSafeMode()) {
692 fout.println("disabled because the system is in safe mode.");
693 return;
694 }
Adrian Rooscbe614f2014-10-28 20:16:12 +0100695 if (!mTrustAgentsCanRun) {
696 fout.println("disabled because the third-party apps can't run yet.");
697 return;
698 }
Adrian Roos7a4f3d42014-05-02 12:12:20 +0200699 final List<UserInfo> userInfos = mUserManager.getUsers(true /* excludeDying */);
Adrian Roos7a4f3d42014-05-02 12:12:20 +0200700 mHandler.runWithScissors(new Runnable() {
701 @Override
702 public void run() {
703 fout.println("Trust manager state:");
704 for (UserInfo user : userInfos) {
Adrian Roos481a6df2014-11-20 19:48:56 +0100705 dumpUser(fout, user, user.id == mCurrentUser);
Adrian Roos7a4f3d42014-05-02 12:12:20 +0200706 }
707 }
708 }, 1500);
709 }
710
711 private void dumpUser(PrintWriter fout, UserInfo user, boolean isCurrent) {
712 fout.printf(" User \"%s\" (id=%d, flags=%#x)",
713 user.name, user.id, user.flags);
Adrian Roos481a6df2014-11-20 19:48:56 +0100714 if (!user.supportsSwitchTo()) {
715 fout.println("(managed profile)");
716 fout.println(" disabled because switching to this user is not possible.");
717 return;
718 }
Adrian Roos7a4f3d42014-05-02 12:12:20 +0200719 if (isCurrent) {
720 fout.print(" (current)");
721 }
722 fout.print(": trusted=" + dumpBool(aggregateIsTrusted(user.id)));
Adrian Roos7861c662014-07-25 15:37:28 +0200723 fout.print(", trustManaged=" + dumpBool(aggregateIsTrustManaged(user.id)));
Adrian Roos481a6df2014-11-20 19:48:56 +0100724 fout.print(", deviceLocked=" + dumpBool(isDeviceLockedInner(user.id)));
Adrian Roosb5e47222015-08-14 15:53:06 -0700725 fout.print(", strongAuthRequired=" + dumpHex(
726 mStrongAuthTracker.getStrongAuthForUser(user.id)));
Adrian Roos7a4f3d42014-05-02 12:12:20 +0200727 fout.println();
728 fout.println(" Enabled agents:");
729 boolean duplicateSimpleNames = false;
730 ArraySet<String> simpleNames = new ArraySet<String>();
731 for (AgentInfo info : mActiveAgents) {
732 if (info.userId != user.id) { continue; }
733 boolean trusted = info.agent.isTrusted();
734 fout.print(" "); fout.println(info.component.flattenToShortString());
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200735 fout.print(" bound=" + dumpBool(info.agent.isBound()));
736 fout.print(", connected=" + dumpBool(info.agent.isConnected()));
Adrian Roos7861c662014-07-25 15:37:28 +0200737 fout.print(", managingTrust=" + dumpBool(info.agent.isManagingTrust()));
738 fout.print(", trusted=" + dumpBool(trusted));
739 fout.println();
Adrian Roos7a4f3d42014-05-02 12:12:20 +0200740 if (trusted) {
741 fout.println(" message=\"" + info.agent.getMessage() + "\"");
742 }
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200743 if (!info.agent.isConnected()) {
744 String restartTime = TrustArchive.formatDuration(
745 info.agent.getScheduledRestartUptimeMillis()
746 - SystemClock.uptimeMillis());
747 fout.println(" restartScheduledAt=" + restartTime);
748 }
Adrian Roos7a4f3d42014-05-02 12:12:20 +0200749 if (!simpleNames.add(TrustArchive.getSimpleName(info.component))) {
750 duplicateSimpleNames = true;
751 }
752 }
753 fout.println(" Events:");
754 mArchive.dump(fout, 50, user.id, " " /* linePrefix */, duplicateSimpleNames);
755 fout.println();
756 }
757
758 private String dumpBool(boolean b) {
759 return b ? "1" : "0";
760 }
Adrian Roosb5e47222015-08-14 15:53:06 -0700761
762 private String dumpHex(int i) {
763 return "0x" + Integer.toHexString(i);
764 }
Adrian Roos82142c22014-03-27 14:56:59 +0100765 };
766
Adrian Roosbcd07652014-10-22 16:57:16 +0200767 private int resolveProfileParent(int userId) {
768 long identity = Binder.clearCallingIdentity();
769 try {
770 UserInfo parent = mUserManager.getProfileParent(userId);
771 if (parent != null) {
772 return parent.getUserHandle().getIdentifier();
773 }
774 return userId;
775 } finally {
776 Binder.restoreCallingIdentity(identity);
777 }
778 }
779
Adrian Roos82142c22014-03-27 14:56:59 +0100780 private final Handler mHandler = new Handler() {
781 @Override
782 public void handleMessage(Message msg) {
783 switch (msg.what) {
784 case MSG_REGISTER_LISTENER:
785 addListener((ITrustListener) msg.obj);
786 break;
787 case MSG_UNREGISTER_LISTENER:
788 removeListener((ITrustListener) msg.obj);
789 break;
790 case MSG_DISPATCH_UNLOCK_ATTEMPT:
791 dispatchUnlockAttempt(msg.arg1 != 0, msg.arg2);
792 break;
793 case MSG_ENABLED_AGENTS_CHANGED:
Marco Fucci4e68f112014-08-29 12:31:48 -0700794 refreshAgentList(UserHandle.USER_ALL);
Adrian Roos481a6df2014-11-20 19:48:56 +0100795 // This is also called when the security mode of a user changes.
796 refreshDeviceLockedForUser(UserHandle.USER_ALL);
Adrian Roos82142c22014-03-27 14:56:59 +0100797 break;
Adrian Roos481a6df2014-11-20 19:48:56 +0100798 case MSG_KEYGUARD_SHOWING_CHANGED:
Adrian Roos7e2e40e2014-11-21 15:27:12 +0100799 refreshDeviceLockedForUser(mCurrentUser);
Adrian Roos481a6df2014-11-20 19:48:56 +0100800 break;
801 case MSG_START_USER:
802 case MSG_CLEANUP_USER:
803 refreshAgentList(msg.arg1);
804 break;
805 case MSG_SWITCH_USER:
806 mCurrentUser = msg.arg1;
807 refreshDeviceLockedForUser(UserHandle.USER_ALL);
808 break;
Adrian Roos82142c22014-03-27 14:56:59 +0100809 }
810 }
811 };
812
813 private final PackageMonitor mPackageMonitor = new PackageMonitor() {
814 @Override
815 public void onSomePackagesChanged() {
Marco Fucci4e68f112014-08-29 12:31:48 -0700816 refreshAgentList(UserHandle.USER_ALL);
Adrian Roos82142c22014-03-27 14:56:59 +0100817 }
818
819 @Override
820 public boolean onPackageChanged(String packageName, int uid, String[] components) {
821 // We're interested in all changes, even if just some components get enabled / disabled.
822 return true;
823 }
Adrian Roosc5f95ce2014-07-24 16:00:46 +0200824
825 @Override
826 public void onPackageDisappeared(String packageName, int reason) {
827 removeAgentsOfPackage(packageName);
828 }
Adrian Roos82142c22014-03-27 14:56:59 +0100829 };
Adrian Roosca36b952014-05-16 18:52:29 +0200830
Adrian Roosb5e47222015-08-14 15:53:06 -0700831 private final StrongAuthTracker mStrongAuthTracker = new StrongAuthTracker() {
832 @Override
833 public void onStrongAuthRequiredChanged(int userId) {
834 refreshAgentList(userId);
835 }
836 };
837
Adrian Roos9dbe1902014-08-13 18:25:52 +0200838 private class Receiver extends BroadcastReceiver {
Adrian Roosca36b952014-05-16 18:52:29 +0200839
840 @Override
841 public void onReceive(Context context, Intent intent) {
Adrian Roos3870d452014-09-05 18:22:28 +0200842 String action = intent.getAction();
843 if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action)) {
Marco Fucci4e68f112014-08-29 12:31:48 -0700844 refreshAgentList(getSendingUserId());
845 updateDevicePolicyFeatures();
Adrian Roos3870d452014-09-05 18:22:28 +0200846 } else if (Intent.ACTION_USER_ADDED.equals(action)) {
Adrian Rooscbe614f2014-10-28 20:16:12 +0100847 int userId = getUserId(intent);
Adrian Roos3870d452014-09-05 18:22:28 +0200848 if (userId > 0) {
849 maybeEnableFactoryTrustAgents(mLockPatternUtils, userId);
Adrian Roos3870d452014-09-05 18:22:28 +0200850 }
Adrian Rooscbe614f2014-10-28 20:16:12 +0100851 } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
852 int userId = getUserId(intent);
853 if (userId > 0) {
Adrian Roos481a6df2014-11-20 19:48:56 +0100854 synchronized (mUserIsTrusted) {
855 mUserIsTrusted.delete(userId);
856 }
857 synchronized (mDeviceLockedForUser) {
858 mDeviceLockedForUser.delete(userId);
859 }
Adrian Rooscbe614f2014-10-28 20:16:12 +0100860 refreshAgentList(userId);
Adrian Roos481a6df2014-11-20 19:48:56 +0100861 refreshDeviceLockedForUser(userId);
Adrian Rooscbe614f2014-10-28 20:16:12 +0100862 }
863 }
864 }
865
866 private int getUserId(Intent intent) {
867 int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -100);
868 if (userId > 0) {
869 return userId;
870 } else {
871 Slog.wtf(TAG, "EXTRA_USER_HANDLE missing or invalid, value=" + userId);
872 return -100;
Adrian Roosca36b952014-05-16 18:52:29 +0200873 }
874 }
875
876 public void register(Context context) {
Adrian Roos9dbe1902014-08-13 18:25:52 +0200877 IntentFilter filter = new IntentFilter();
878 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
879 filter.addAction(Intent.ACTION_USER_PRESENT);
Adrian Roos3870d452014-09-05 18:22:28 +0200880 filter.addAction(Intent.ACTION_USER_ADDED);
Adrian Rooscbe614f2014-10-28 20:16:12 +0100881 filter.addAction(Intent.ACTION_USER_REMOVED);
Adrian Roosca36b952014-05-16 18:52:29 +0200882 context.registerReceiverAsUser(this,
883 UserHandle.ALL,
Adrian Roos9dbe1902014-08-13 18:25:52 +0200884 filter,
Adrian Roosca36b952014-05-16 18:52:29 +0200885 null /* permission */,
886 null /* scheduler */);
887 }
888 }
Adrian Roos82142c22014-03-27 14:56:59 +0100889}