TrustManagerService.java revision e681c27dc62006358102a250b46726b7a88efe06
1/* 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 19import com.android.internal.content.PackageMonitor; 20import com.android.internal.widget.LockPatternUtils; 21import com.android.server.SystemService; 22 23import org.xmlpull.v1.XmlPullParser; 24import org.xmlpull.v1.XmlPullParserException; 25 26import android.Manifest; 27import android.app.ActivityManagerNative; 28import android.app.admin.DevicePolicyManager; 29import android.app.trust.ITrustListener; 30import android.app.trust.ITrustManager; 31import android.content.BroadcastReceiver; 32import android.content.ComponentName; 33import android.content.Context; 34import android.content.Intent; 35import android.content.IntentFilter; 36import android.content.pm.PackageManager; 37import android.content.pm.ResolveInfo; 38import android.content.pm.UserInfo; 39import android.content.res.Resources; 40import android.content.res.TypedArray; 41import android.content.res.XmlResourceParser; 42import android.graphics.drawable.Drawable; 43import android.os.DeadObjectException; 44import android.os.Handler; 45import android.os.IBinder; 46import android.os.Message; 47import android.os.RemoteException; 48import android.os.SystemClock; 49import android.os.UserHandle; 50import android.os.UserManager; 51import android.service.trust.TrustAgentService; 52import android.util.ArraySet; 53import android.util.AttributeSet; 54import android.util.Log; 55import android.util.Slog; 56import android.util.SparseBooleanArray; 57import android.util.Xml; 58 59import java.io.FileDescriptor; 60import java.io.IOException; 61import java.io.PrintWriter; 62import java.util.ArrayList; 63import java.util.List; 64 65/** 66 * Manages trust agents and trust listeners. 67 * 68 * It is responsible for binding to the enabled {@link android.service.trust.TrustAgentService}s 69 * of each user and notifies them about events that are relevant to them. 70 * It start and stops them based on the value of 71 * {@link com.android.internal.widget.LockPatternUtils#getEnabledTrustAgents(int)}. 72 * 73 * It also keeps a set of {@link android.app.trust.ITrustListener}s that are notified whenever the 74 * trust state changes for any user. 75 * 76 * Trust state and the setting of enabled agents is kept per user and each user has its own 77 * instance of a {@link android.service.trust.TrustAgentService}. 78 */ 79public class TrustManagerService extends SystemService { 80 81 private static final boolean DEBUG = false; 82 private static final String TAG = "TrustManagerService"; 83 84 private static final Intent TRUST_AGENT_INTENT = 85 new Intent(TrustAgentService.SERVICE_INTERFACE); 86 private static final String PERMISSION_PROVIDE_AGENT = Manifest.permission.PROVIDE_TRUST_AGENT; 87 88 private static final int MSG_REGISTER_LISTENER = 1; 89 private static final int MSG_UNREGISTER_LISTENER = 2; 90 private static final int MSG_DISPATCH_UNLOCK_ATTEMPT = 3; 91 private static final int MSG_ENABLED_AGENTS_CHANGED = 4; 92 private static final int MSG_REQUIRE_CREDENTIAL_ENTRY = 5; 93 94 private final ArraySet<AgentInfo> mActiveAgents = new ArraySet<AgentInfo>(); 95 private final ArrayList<ITrustListener> mTrustListeners = new ArrayList<ITrustListener>(); 96 private final Receiver mReceiver = new Receiver(); 97 private final SparseBooleanArray mUserHasAuthenticatedSinceBoot = new SparseBooleanArray(); 98 /* package */ final TrustArchive mArchive = new TrustArchive(); 99 private final Context mContext; 100 101 private UserManager mUserManager; 102 103 public TrustManagerService(Context context) { 104 super(context); 105 mContext = context; 106 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 107 } 108 109 @Override 110 public void onStart() { 111 publishBinderService(Context.TRUST_SERVICE, mService); 112 } 113 114 @Override 115 public void onBootPhase(int phase) { 116 if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY && !isSafeMode()) { 117 mPackageMonitor.register(mContext, mHandler.getLooper(), UserHandle.ALL, true); 118 mReceiver.register(mContext); 119 refreshAgentList(UserHandle.USER_ALL); 120 } 121 } 122 123 // Agent management 124 125 private static final class AgentInfo { 126 CharSequence label; 127 Drawable icon; 128 ComponentName component; // service that implements ITrustAgent 129 ComponentName settings; // setting to launch to modify agent. 130 TrustAgentWrapper agent; 131 int userId; 132 133 @Override 134 public boolean equals(Object other) { 135 if (!(other instanceof AgentInfo)) { 136 return false; 137 } 138 AgentInfo o = (AgentInfo) other; 139 return component.equals(o.component) && userId == o.userId; 140 } 141 142 @Override 143 public int hashCode() { 144 return component.hashCode() * 31 + userId; 145 } 146 } 147 148 private void updateTrustAll() { 149 List<UserInfo> userInfos = mUserManager.getUsers(true /* excludeDying */); 150 for (UserInfo userInfo : userInfos) { 151 updateTrust(userInfo.id, false); 152 } 153 } 154 155 public void updateTrust(int userId, boolean initiatedByUser) { 156 dispatchOnTrustManagedChanged(aggregateIsTrustManaged(userId), userId); 157 dispatchOnTrustChanged(aggregateIsTrusted(userId), userId, initiatedByUser); 158 } 159 160 void refreshAgentList(int userId) { 161 if (DEBUG) Slog.d(TAG, "refreshAgentList()"); 162 if (userId != UserHandle.USER_ALL && userId < UserHandle.USER_OWNER) { 163 Log.e(TAG, "refreshAgentList(userId=" + userId + "): Invalid user handle," 164 + " must be USER_ALL or a specific user.", new Throwable("here")); 165 userId = UserHandle.USER_ALL; 166 } 167 PackageManager pm = mContext.getPackageManager(); 168 169 List<UserInfo> userInfos; 170 if (userId == UserHandle.USER_ALL) { 171 userInfos = mUserManager.getUsers(true /* excludeDying */); 172 } else { 173 userInfos = new ArrayList<>(); 174 userInfos.add(mUserManager.getUserInfo(userId)); 175 } 176 LockPatternUtils lockPatternUtils = new LockPatternUtils(mContext); 177 178 ArraySet<AgentInfo> obsoleteAgents = new ArraySet<>(); 179 obsoleteAgents.addAll(mActiveAgents); 180 181 for (UserInfo userInfo : userInfos) { 182 if (lockPatternUtils.getKeyguardStoredPasswordQuality(userInfo.id) 183 == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) continue; 184 if (!mUserHasAuthenticatedSinceBoot.get(userInfo.id)) continue; 185 DevicePolicyManager dpm = lockPatternUtils.getDevicePolicyManager(); 186 int disabledFeatures = dpm.getKeyguardDisabledFeatures(null, userInfo.id); 187 final boolean disableTrustAgents = 188 (disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0; 189 190 List<ComponentName> enabledAgents = lockPatternUtils.getEnabledTrustAgents(userInfo.id); 191 if (enabledAgents == null) { 192 continue; 193 } 194 List<ResolveInfo> resolveInfos = pm.queryIntentServicesAsUser(TRUST_AGENT_INTENT, 195 PackageManager.GET_META_DATA, userInfo.id); 196 for (ResolveInfo resolveInfo : resolveInfos) { 197 if (resolveInfo.serviceInfo == null) continue; 198 199 String packageName = resolveInfo.serviceInfo.packageName; 200 if (pm.checkPermission(PERMISSION_PROVIDE_AGENT, packageName) 201 != PackageManager.PERMISSION_GRANTED) { 202 Log.w(TAG, "Skipping agent because package " + packageName 203 + " does not have permission " + PERMISSION_PROVIDE_AGENT + "."); 204 continue; 205 } 206 207 ComponentName name = getComponentName(resolveInfo); 208 if (!enabledAgents.contains(name)) continue; 209 210 if (disableTrustAgents) { 211 List<String> features = 212 dpm.getTrustAgentFeaturesEnabled(null /* admin */, name); 213 // Disable agent if no features are enabled. 214 if (features == null || features.isEmpty()) continue; 215 } 216 217 AgentInfo agentInfo = new AgentInfo(); 218 agentInfo.component = name; 219 agentInfo.userId = userInfo.id; 220 if (!mActiveAgents.contains(agentInfo)) { 221 agentInfo.label = resolveInfo.loadLabel(pm); 222 agentInfo.icon = resolveInfo.loadIcon(pm); 223 agentInfo.settings = getSettingsComponentName(pm, resolveInfo); 224 agentInfo.agent = new TrustAgentWrapper(mContext, this, 225 new Intent().setComponent(name), userInfo.getUserHandle()); 226 mActiveAgents.add(agentInfo); 227 } else { 228 obsoleteAgents.remove(agentInfo); 229 } 230 } 231 } 232 233 boolean trustMayHaveChanged = false; 234 for (int i = 0; i < obsoleteAgents.size(); i++) { 235 AgentInfo info = obsoleteAgents.valueAt(i); 236 if (userId == UserHandle.USER_ALL || userId == info.userId) { 237 if (info.agent.isManagingTrust()) { 238 trustMayHaveChanged = true; 239 } 240 info.agent.unbind(); 241 mActiveAgents.remove(info); 242 } 243 } 244 245 if (trustMayHaveChanged) { 246 updateTrustAll(); 247 } 248 } 249 250 void updateDevicePolicyFeatures() { 251 for (int i = 0; i < mActiveAgents.size(); i++) { 252 AgentInfo info = mActiveAgents.valueAt(i); 253 if (info.agent.isConnected()) { 254 info.agent.updateDevicePolicyFeatures(); 255 } 256 } 257 } 258 259 private void removeAgentsOfPackage(String packageName) { 260 boolean trustMayHaveChanged = false; 261 for (int i = mActiveAgents.size() - 1; i >= 0; i--) { 262 AgentInfo info = mActiveAgents.valueAt(i); 263 if (packageName.equals(info.component.getPackageName())) { 264 Log.i(TAG, "Resetting agent " + info.component.flattenToShortString()); 265 if (info.agent.isManagingTrust()) { 266 trustMayHaveChanged = true; 267 } 268 info.agent.unbind(); 269 mActiveAgents.removeAt(i); 270 } 271 } 272 if (trustMayHaveChanged) { 273 updateTrustAll(); 274 } 275 } 276 277 public void resetAgent(ComponentName name, int userId) { 278 boolean trustMayHaveChanged = false; 279 for (int i = mActiveAgents.size() - 1; i >= 0; i--) { 280 AgentInfo info = mActiveAgents.valueAt(i); 281 if (name.equals(info.component) && userId == info.userId) { 282 Log.i(TAG, "Resetting agent " + info.component.flattenToShortString()); 283 if (info.agent.isManagingTrust()) { 284 trustMayHaveChanged = true; 285 } 286 info.agent.unbind(); 287 mActiveAgents.removeAt(i); 288 } 289 } 290 if (trustMayHaveChanged) { 291 updateTrust(userId, false); 292 } 293 refreshAgentList(userId); 294 } 295 296 private ComponentName getSettingsComponentName(PackageManager pm, ResolveInfo resolveInfo) { 297 if (resolveInfo == null || resolveInfo.serviceInfo == null 298 || resolveInfo.serviceInfo.metaData == null) return null; 299 String cn = null; 300 XmlResourceParser parser = null; 301 Exception caughtException = null; 302 try { 303 parser = resolveInfo.serviceInfo.loadXmlMetaData(pm, 304 TrustAgentService.TRUST_AGENT_META_DATA); 305 if (parser == null) { 306 Slog.w(TAG, "Can't find " + TrustAgentService.TRUST_AGENT_META_DATA + " meta-data"); 307 return null; 308 } 309 Resources res = pm.getResourcesForApplication(resolveInfo.serviceInfo.applicationInfo); 310 AttributeSet attrs = Xml.asAttributeSet(parser); 311 int type; 312 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 313 && type != XmlPullParser.START_TAG) { 314 // Drain preamble. 315 } 316 String nodeName = parser.getName(); 317 if (!"trust-agent".equals(nodeName)) { 318 Slog.w(TAG, "Meta-data does not start with trust-agent tag"); 319 return null; 320 } 321 TypedArray sa = res 322 .obtainAttributes(attrs, com.android.internal.R.styleable.TrustAgent); 323 cn = sa.getString(com.android.internal.R.styleable.TrustAgent_settingsActivity); 324 sa.recycle(); 325 } catch (PackageManager.NameNotFoundException e) { 326 caughtException = e; 327 } catch (IOException e) { 328 caughtException = e; 329 } catch (XmlPullParserException e) { 330 caughtException = e; 331 } finally { 332 if (parser != null) parser.close(); 333 } 334 if (caughtException != null) { 335 Slog.w(TAG, "Error parsing : " + resolveInfo.serviceInfo.packageName, caughtException); 336 return null; 337 } 338 if (cn == null) { 339 return null; 340 } 341 if (cn.indexOf('/') < 0) { 342 cn = resolveInfo.serviceInfo.packageName + "/" + cn; 343 } 344 return ComponentName.unflattenFromString(cn); 345 } 346 347 private ComponentName getComponentName(ResolveInfo resolveInfo) { 348 if (resolveInfo == null || resolveInfo.serviceInfo == null) return null; 349 return new ComponentName(resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name); 350 } 351 352 // Agent dispatch and aggregation 353 354 private boolean aggregateIsTrusted(int userId) { 355 if (!mUserHasAuthenticatedSinceBoot.get(userId)) { 356 return false; 357 } 358 for (int i = 0; i < mActiveAgents.size(); i++) { 359 AgentInfo info = mActiveAgents.valueAt(i); 360 if (info.userId == userId) { 361 if (info.agent.isTrusted()) { 362 return true; 363 } 364 } 365 } 366 return false; 367 } 368 369 private boolean aggregateIsTrustManaged(int userId) { 370 if (!mUserHasAuthenticatedSinceBoot.get(userId)) { 371 return false; 372 } 373 for (int i = 0; i < mActiveAgents.size(); i++) { 374 AgentInfo info = mActiveAgents.valueAt(i); 375 if (info.userId == userId) { 376 if (info.agent.isManagingTrust()) { 377 return true; 378 } 379 } 380 } 381 return false; 382 } 383 384 private void dispatchUnlockAttempt(boolean successful, int userId) { 385 for (int i = 0; i < mActiveAgents.size(); i++) { 386 AgentInfo info = mActiveAgents.valueAt(i); 387 if (info.userId == userId) { 388 info.agent.onUnlockAttempt(successful); 389 } 390 } 391 392 if (successful) { 393 updateUserHasAuthenticated(userId); 394 } 395 } 396 397 private void updateUserHasAuthenticated(int userId) { 398 if (!mUserHasAuthenticatedSinceBoot.get(userId)) { 399 mUserHasAuthenticatedSinceBoot.put(userId, true); 400 refreshAgentList(userId); 401 } 402 } 403 404 405 private void requireCredentialEntry(int userId) { 406 if (userId == UserHandle.USER_ALL) { 407 mUserHasAuthenticatedSinceBoot.clear(); 408 refreshAgentList(UserHandle.USER_ALL); 409 } else { 410 mUserHasAuthenticatedSinceBoot.put(userId, false); 411 refreshAgentList(userId); 412 } 413 } 414 415 // Listeners 416 417 private void addListener(ITrustListener listener) { 418 for (int i = 0; i < mTrustListeners.size(); i++) { 419 if (mTrustListeners.get(i).asBinder() == listener.asBinder()) { 420 return; 421 } 422 } 423 mTrustListeners.add(listener); 424 } 425 426 private void removeListener(ITrustListener listener) { 427 for (int i = 0; i < mTrustListeners.size(); i++) { 428 if (mTrustListeners.get(i).asBinder() == listener.asBinder()) { 429 mTrustListeners.remove(i); 430 return; 431 } 432 } 433 } 434 435 private void dispatchOnTrustChanged(boolean enabled, int userId, boolean initiatedByUser) { 436 if (!enabled) initiatedByUser = false; 437 for (int i = 0; i < mTrustListeners.size(); i++) { 438 try { 439 mTrustListeners.get(i).onTrustChanged(enabled, userId, initiatedByUser); 440 } catch (DeadObjectException e) { 441 Slog.d(TAG, "Removing dead TrustListener."); 442 mTrustListeners.remove(i); 443 i--; 444 } catch (RemoteException e) { 445 Slog.e(TAG, "Exception while notifying TrustListener.", e); 446 } 447 } 448 } 449 450 private void dispatchOnTrustManagedChanged(boolean managed, int userId) { 451 for (int i = 0; i < mTrustListeners.size(); i++) { 452 try { 453 mTrustListeners.get(i).onTrustManagedChanged(managed, userId); 454 } catch (DeadObjectException e) { 455 Slog.d(TAG, "Removing dead TrustListener."); 456 mTrustListeners.remove(i); 457 i--; 458 } catch (RemoteException e) { 459 Slog.e(TAG, "Exception while notifying TrustListener.", e); 460 } 461 } 462 } 463 464 // Plumbing 465 466 private final IBinder mService = new ITrustManager.Stub() { 467 @Override 468 public void reportUnlockAttempt(boolean authenticated, int userId) throws RemoteException { 469 enforceReportPermission(); 470 mHandler.obtainMessage(MSG_DISPATCH_UNLOCK_ATTEMPT, authenticated ? 1 : 0, userId) 471 .sendToTarget(); 472 } 473 474 @Override 475 public void reportEnabledTrustAgentsChanged(int userId) throws RemoteException { 476 enforceReportPermission(); 477 // coalesce refresh messages. 478 mHandler.removeMessages(MSG_ENABLED_AGENTS_CHANGED); 479 mHandler.sendEmptyMessage(MSG_ENABLED_AGENTS_CHANGED); 480 } 481 482 @Override 483 public void reportRequireCredentialEntry(int userId) throws RemoteException { 484 enforceReportPermission(); 485 if (userId == UserHandle.USER_ALL || userId >= UserHandle.USER_OWNER) { 486 mHandler.obtainMessage(MSG_REQUIRE_CREDENTIAL_ENTRY, userId, 0).sendToTarget(); 487 } else { 488 throw new IllegalArgumentException( 489 "userId must be an explicit user id or USER_ALL"); 490 } 491 } 492 493 @Override 494 public void registerTrustListener(ITrustListener trustListener) throws RemoteException { 495 enforceListenerPermission(); 496 mHandler.obtainMessage(MSG_REGISTER_LISTENER, trustListener).sendToTarget(); 497 } 498 499 @Override 500 public void unregisterTrustListener(ITrustListener trustListener) throws RemoteException { 501 enforceListenerPermission(); 502 mHandler.obtainMessage(MSG_UNREGISTER_LISTENER, trustListener).sendToTarget(); 503 } 504 505 private void enforceReportPermission() { 506 mContext.enforceCallingOrSelfPermission( 507 Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE, "reporting trust events"); 508 } 509 510 private void enforceListenerPermission() { 511 mContext.enforceCallingPermission(Manifest.permission.TRUST_LISTENER, 512 "register trust listener"); 513 } 514 515 @Override 516 protected void dump(FileDescriptor fd, final PrintWriter fout, String[] args) { 517 mContext.enforceCallingPermission(Manifest.permission.DUMP, 518 "dumping TrustManagerService"); 519 final UserInfo currentUser; 520 final List<UserInfo> userInfos = mUserManager.getUsers(true /* excludeDying */); 521 try { 522 currentUser = ActivityManagerNative.getDefault().getCurrentUser(); 523 } catch (RemoteException e) { 524 throw new RuntimeException(e); 525 } 526 mHandler.runWithScissors(new Runnable() { 527 @Override 528 public void run() { 529 fout.println("Trust manager state:"); 530 for (UserInfo user : userInfos) { 531 dumpUser(fout, user, user.id == currentUser.id); 532 } 533 } 534 }, 1500); 535 } 536 537 private void dumpUser(PrintWriter fout, UserInfo user, boolean isCurrent) { 538 fout.printf(" User \"%s\" (id=%d, flags=%#x)", 539 user.name, user.id, user.flags); 540 if (isCurrent) { 541 fout.print(" (current)"); 542 } 543 fout.print(": trusted=" + dumpBool(aggregateIsTrusted(user.id))); 544 fout.print(", trustManaged=" + dumpBool(aggregateIsTrustManaged(user.id))); 545 fout.println(); 546 fout.println(" Enabled agents:"); 547 boolean duplicateSimpleNames = false; 548 ArraySet<String> simpleNames = new ArraySet<String>(); 549 for (AgentInfo info : mActiveAgents) { 550 if (info.userId != user.id) { continue; } 551 boolean trusted = info.agent.isTrusted(); 552 fout.print(" "); fout.println(info.component.flattenToShortString()); 553 fout.print(" bound=" + dumpBool(info.agent.isBound())); 554 fout.print(", connected=" + dumpBool(info.agent.isConnected())); 555 fout.print(", managingTrust=" + dumpBool(info.agent.isManagingTrust())); 556 fout.print(", trusted=" + dumpBool(trusted)); 557 fout.println(); 558 if (trusted) { 559 fout.println(" message=\"" + info.agent.getMessage() + "\""); 560 } 561 if (!info.agent.isConnected()) { 562 String restartTime = TrustArchive.formatDuration( 563 info.agent.getScheduledRestartUptimeMillis() 564 - SystemClock.uptimeMillis()); 565 fout.println(" restartScheduledAt=" + restartTime); 566 } 567 if (!simpleNames.add(TrustArchive.getSimpleName(info.component))) { 568 duplicateSimpleNames = true; 569 } 570 } 571 fout.println(" Events:"); 572 mArchive.dump(fout, 50, user.id, " " /* linePrefix */, duplicateSimpleNames); 573 fout.println(); 574 } 575 576 private String dumpBool(boolean b) { 577 return b ? "1" : "0"; 578 } 579 }; 580 581 private final Handler mHandler = new Handler() { 582 @Override 583 public void handleMessage(Message msg) { 584 switch (msg.what) { 585 case MSG_REGISTER_LISTENER: 586 addListener((ITrustListener) msg.obj); 587 break; 588 case MSG_UNREGISTER_LISTENER: 589 removeListener((ITrustListener) msg.obj); 590 break; 591 case MSG_DISPATCH_UNLOCK_ATTEMPT: 592 dispatchUnlockAttempt(msg.arg1 != 0, msg.arg2); 593 break; 594 case MSG_ENABLED_AGENTS_CHANGED: 595 refreshAgentList(UserHandle.USER_ALL); 596 break; 597 case MSG_REQUIRE_CREDENTIAL_ENTRY: 598 requireCredentialEntry(msg.arg1); 599 break; 600 } 601 } 602 }; 603 604 private final PackageMonitor mPackageMonitor = new PackageMonitor() { 605 @Override 606 public void onSomePackagesChanged() { 607 refreshAgentList(UserHandle.USER_ALL); 608 } 609 610 @Override 611 public boolean onPackageChanged(String packageName, int uid, String[] components) { 612 // We're interested in all changes, even if just some components get enabled / disabled. 613 return true; 614 } 615 616 @Override 617 public void onPackageDisappeared(String packageName, int reason) { 618 removeAgentsOfPackage(packageName); 619 } 620 }; 621 622 private class Receiver extends BroadcastReceiver { 623 624 @Override 625 public void onReceive(Context context, Intent intent) { 626 if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals( 627 intent.getAction())) { 628 refreshAgentList(getSendingUserId()); 629 updateDevicePolicyFeatures(); 630 } else if (Intent.ACTION_USER_PRESENT.equals(intent.getAction())) { 631 updateUserHasAuthenticated(getSendingUserId()); 632 } 633 } 634 635 public void register(Context context) { 636 IntentFilter filter = new IntentFilter(); 637 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); 638 filter.addAction(Intent.ACTION_USER_PRESENT); 639 context.registerReceiverAsUser(this, 640 UserHandle.ALL, 641 filter, 642 null /* permission */, 643 null /* scheduler */); 644 } 645 } 646} 647