AutofillManagerService.java revision 350b2dca6c252dad099bc8e2d96cbffd6e98dfef
1/* 2 * Copyright (C) 2016 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.autofill; 18 19import static android.Manifest.permission.MANAGE_AUTO_FILL; 20import static android.content.Context.AUTOFILL_MANAGER_SERVICE; 21 22import static com.android.server.autofill.Helper.sDebug; 23import static com.android.server.autofill.Helper.sPartitionMaxCount; 24import static com.android.server.autofill.Helper.sVerbose; 25import static com.android.server.autofill.Helper.bundleToString; 26 27import android.annotation.NonNull; 28import android.annotation.Nullable; 29import android.app.ActivityManager; 30import android.app.ActivityThread; 31import android.content.BroadcastReceiver; 32import android.content.ComponentName; 33import android.content.ContentResolver; 34import android.content.Context; 35import android.content.Intent; 36import android.content.IntentFilter; 37import android.content.pm.PackageManager; 38import android.content.pm.UserInfo; 39import android.database.ContentObserver; 40import android.graphics.Rect; 41import android.net.Uri; 42import android.os.Binder; 43import android.os.Build; 44import android.os.Bundle; 45import android.os.Handler; 46import android.os.IBinder; 47import android.os.RemoteException; 48import android.os.ResultReceiver; 49import android.os.ShellCallback; 50import android.os.UserHandle; 51import android.os.UserManager; 52import android.os.UserManagerInternal; 53import android.provider.Settings; 54import android.service.autofill.FillEventHistory; 55import android.util.LocalLog; 56import android.util.Slog; 57import android.util.SparseArray; 58import android.util.SparseBooleanArray; 59import android.view.autofill.AutofillId; 60import android.view.autofill.AutofillManager; 61import android.view.autofill.AutofillValue; 62import android.view.autofill.IAutoFillManager; 63import android.view.autofill.IAutoFillManagerClient; 64 65import com.android.internal.annotations.GuardedBy; 66import com.android.internal.content.PackageMonitor; 67import com.android.internal.os.BackgroundThread; 68import com.android.internal.os.IResultReceiver; 69import com.android.internal.util.DumpUtils; 70import com.android.internal.util.Preconditions; 71import com.android.server.FgThread; 72import com.android.server.LocalServices; 73import com.android.server.SystemService; 74import com.android.server.autofill.ui.AutoFillUI; 75 76import java.io.FileDescriptor; 77import java.io.PrintWriter; 78import java.util.ArrayList; 79import java.util.List; 80import java.util.Objects; 81 82/** 83 * Entry point service for autofill management. 84 * 85 * <p>This service provides the {@link IAutoFillManager} implementation and keeps a list of 86 * {@link AutofillManagerServiceImpl} per user; the real work is done by 87 * {@link AutofillManagerServiceImpl} itself. 88 */ 89public final class AutofillManagerService extends SystemService { 90 91 private static final String TAG = "AutofillManagerService"; 92 93 static final String RECEIVER_BUNDLE_EXTRA_SESSIONS = "sessions"; 94 95 private final Context mContext; 96 private final AutoFillUI mUi; 97 98 private final Object mLock = new Object(); 99 100 /** 101 * Cache of {@link AutofillManagerServiceImpl} per user id. 102 * <p> 103 * It has to be mapped by user id because the same current user could have simultaneous sessions 104 * associated to different user profiles (for example, in a multi-window environment or when 105 * device has work profiles). 106 */ 107 @GuardedBy("mLock") 108 private SparseArray<AutofillManagerServiceImpl> mServicesCache = new SparseArray<>(); 109 110 /** 111 * Users disabled due to {@link UserManager} restrictions. 112 */ 113 @GuardedBy("mLock") 114 private final SparseBooleanArray mDisabledUsers = new SparseBooleanArray(); 115 116 private final LocalLog mRequestsHistory = new LocalLog(20); 117 118 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 119 @Override 120 public void onReceive(Context context, Intent intent) { 121 if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) { 122 mUi.hideAll(null); 123 } 124 } 125 }; 126 127 public AutofillManagerService(Context context) { 128 super(context); 129 mContext = context; 130 mUi = new AutoFillUI(ActivityThread.currentActivityThread().getSystemUiContext()); 131 132 final boolean debug = Build.IS_DEBUGGABLE; 133 Slog.i(TAG, "Setting debug to " + debug); 134 setDebugLocked(debug); 135 136 final IntentFilter filter = new IntentFilter(); 137 filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); 138 mContext.registerReceiver(mBroadcastReceiver, filter, null, FgThread.getHandler()); 139 140 // Hookup with UserManager to disable service when necessary. 141 final UserManager um = context.getSystemService(UserManager.class); 142 final UserManagerInternal umi = LocalServices.getService(UserManagerInternal.class); 143 final List<UserInfo> users = um.getUsers(); 144 for (int i = 0; i < users.size(); i++) { 145 final int userId = users.get(i).id; 146 final boolean disabled = umi.getUserRestriction(userId, UserManager.DISALLOW_AUTOFILL); 147 if (disabled) { 148 if (disabled) { 149 Slog.i(TAG, "Disabling Autofill for user " + userId); 150 } 151 mDisabledUsers.put(userId, disabled); 152 } 153 } 154 umi.addUserRestrictionsListener((userId, newRestrictions, prevRestrictions) -> { 155 final boolean disabledNow = 156 newRestrictions.getBoolean(UserManager.DISALLOW_AUTOFILL, false); 157 synchronized (mLock) { 158 final boolean disabledBefore = mDisabledUsers.get(userId); 159 if (disabledBefore == disabledNow) { 160 // Nothing changed, do nothing. 161 if (sDebug) { 162 Slog.d(TAG, "Autofill restriction did not change for user " + userId + ": " 163 + bundleToString(newRestrictions)); 164 return; 165 } 166 } 167 Slog.i(TAG, "Updating Autofill for user " + userId + ": disabled=" + disabledNow); 168 mDisabledUsers.put(userId, disabledNow); 169 updateCachedServiceLocked(userId, disabledNow); 170 } 171 }); 172 startTrackingPackageChanges(); 173 } 174 175 private void startTrackingPackageChanges() { 176 PackageMonitor monitor = new PackageMonitor() { 177 @Override 178 public void onSomePackagesChanged() { 179 synchronized (mLock) { 180 updateCachedServiceLocked(getChangingUserId()); 181 } 182 } 183 184 @Override 185 public void onPackageUpdateFinished(String packageName, int uid) { 186 synchronized (mLock) { 187 final String activePackageName = getActiveAutofillServicePackageName(); 188 if (packageName.equals(activePackageName)) { 189 removeCachedServiceLocked(getChangingUserId()); 190 } 191 } 192 } 193 194 @Override 195 public void onPackageRemoved(String packageName, int uid) { 196 synchronized (mLock) { 197 final int userId = getChangingUserId(); 198 final AutofillManagerServiceImpl userState = peekServiceForUserLocked(userId); 199 if (userState != null) { 200 final ComponentName componentName = userState.getServiceComponentName(); 201 if (componentName != null) { 202 if (packageName.equals(componentName.getPackageName())) { 203 handleActiveAutofillServiceRemoved(userId); 204 } 205 } 206 } 207 } 208 } 209 210 @Override 211 public boolean onHandleForceStop(Intent intent, String[] packages, 212 int uid, boolean doit) { 213 synchronized (mLock) { 214 final String activePackageName = getActiveAutofillServicePackageName(); 215 for (String pkg : packages) { 216 if (pkg.equals(activePackageName)) { 217 if (!doit) { 218 return true; 219 } 220 removeCachedServiceLocked(getChangingUserId()); 221 } 222 } 223 } 224 return false; 225 } 226 227 private void handleActiveAutofillServiceRemoved(int userId) { 228 removeCachedServiceLocked(userId); 229 Settings.Secure.putStringForUser(mContext.getContentResolver(), 230 Settings.Secure.AUTOFILL_SERVICE, null, userId); 231 } 232 233 private String getActiveAutofillServicePackageName() { 234 final int userId = getChangingUserId(); 235 final AutofillManagerServiceImpl userState = peekServiceForUserLocked(userId); 236 if (userState == null) { 237 return null; 238 } 239 final ComponentName serviceComponent = userState.getServiceComponentName(); 240 if (serviceComponent == null) { 241 return null; 242 } 243 return serviceComponent.getPackageName(); 244 } 245 }; 246 247 // package changes 248 monitor.register(mContext, null, UserHandle.ALL, true); 249 } 250 251 @Override 252 public void onStart() { 253 publishBinderService(AUTOFILL_MANAGER_SERVICE, new AutoFillManagerServiceStub()); 254 } 255 256 @Override 257 public void onBootPhase(int phase) { 258 if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) { 259 new SettingsObserver(BackgroundThread.getHandler()); 260 } 261 } 262 263 @Override 264 public void onUnlockUser(int userId) { 265 synchronized (mLock) { 266 updateCachedServiceLocked(userId); 267 } 268 } 269 270 @Override 271 public void onCleanupUser(int userId) { 272 synchronized (mLock) { 273 removeCachedServiceLocked(userId); 274 } 275 } 276 277 /** 278 * Gets the service instance for an user. 279 * 280 * @return service instance. 281 */ 282 @NonNull 283 AutofillManagerServiceImpl getServiceForUserLocked(int userId) { 284 final int resolvedUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), 285 Binder.getCallingUid(), userId, false, false, null, null); 286 AutofillManagerServiceImpl service = mServicesCache.get(resolvedUserId); 287 if (service == null) { 288 service = new AutofillManagerServiceImpl(mContext, mLock, mRequestsHistory, 289 resolvedUserId, mUi, mDisabledUsers.get(resolvedUserId)); 290 mServicesCache.put(userId, service); 291 } 292 return service; 293 } 294 295 /** 296 * Peeks the service instance for a user. 297 * 298 * @return service instance or {@code null} if not already present 299 */ 300 @Nullable 301 AutofillManagerServiceImpl peekServiceForUserLocked(int userId) { 302 final int resolvedUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), 303 Binder.getCallingUid(), userId, false, false, null, null); 304 return mServicesCache.get(resolvedUserId); 305 } 306 307 // Called by Shell command. 308 void destroySessions(int userId, IResultReceiver receiver) { 309 Slog.i(TAG, "destroySessions() for userId " + userId); 310 mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG); 311 312 synchronized (mLock) { 313 if (userId != UserHandle.USER_ALL) { 314 AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 315 if (service != null) { 316 service.destroySessionsLocked(); 317 } 318 } else { 319 final int size = mServicesCache.size(); 320 for (int i = 0; i < size; i++) { 321 mServicesCache.valueAt(i).destroySessionsLocked(); 322 } 323 } 324 } 325 326 try { 327 receiver.send(0, new Bundle()); 328 } catch (RemoteException e) { 329 // Just ignore it... 330 } 331 } 332 333 // Called by Shell command. 334 void listSessions(int userId, IResultReceiver receiver) { 335 Slog.i(TAG, "listSessions() for userId " + userId); 336 mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG); 337 338 final Bundle resultData = new Bundle(); 339 final ArrayList<String> sessions = new ArrayList<>(); 340 341 synchronized (mLock) { 342 if (userId != UserHandle.USER_ALL) { 343 AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 344 if (service != null) { 345 service.listSessionsLocked(sessions); 346 } 347 } else { 348 final int size = mServicesCache.size(); 349 for (int i = 0; i < size; i++) { 350 mServicesCache.valueAt(i).listSessionsLocked(sessions); 351 } 352 } 353 } 354 355 resultData.putStringArrayList(RECEIVER_BUNDLE_EXTRA_SESSIONS, sessions); 356 try { 357 receiver.send(0, resultData); 358 } catch (RemoteException e) { 359 // Just ignore it... 360 } 361 } 362 363 // Called by Shell command. 364 void reset() { 365 Slog.i(TAG, "reset()"); 366 mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG); 367 368 synchronized (mLock) { 369 final int size = mServicesCache.size(); 370 for (int i = 0; i < size; i++) { 371 mServicesCache.valueAt(i).destroyLocked(); 372 } 373 mServicesCache.clear(); 374 } 375 } 376 377 // Called by Shell command. 378 void setLogLevel(int level) { 379 Slog.i(TAG, "setLogLevel(): " + level); 380 mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG); 381 382 boolean debug = false; 383 boolean verbose = false; 384 if (level == AutofillManager.FLAG_ADD_CLIENT_VERBOSE) { 385 debug = verbose = true; 386 } else if (level == AutofillManager.FLAG_ADD_CLIENT_DEBUG) { 387 debug = true; 388 } 389 synchronized (mLock) { 390 setDebugLocked(debug); 391 setVerboseLocked(verbose); 392 } 393 } 394 395 // Called by Shell command. 396 int getLogLevel() { 397 mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG); 398 399 synchronized (mLock) { 400 if (sVerbose) return AutofillManager.FLAG_ADD_CLIENT_VERBOSE; 401 if (sDebug) return AutofillManager.FLAG_ADD_CLIENT_DEBUG; 402 return 0; 403 } 404 } 405 406 // Called by Shell command. 407 public int getMaxPartitions() { 408 mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG); 409 410 synchronized (mLock) { 411 return sPartitionMaxCount; 412 } 413 } 414 415 // Called by Shell command. 416 public void setMaxPartitions(int max) { 417 mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG); 418 Slog.i(TAG, "setMaxPartitions(): " + max); 419 synchronized (mLock) { 420 sPartitionMaxCount = max; 421 } 422 } 423 424 private void setDebugLocked(boolean debug) { 425 com.android.server.autofill.Helper.sDebug = debug; 426 android.view.autofill.Helper.sDebug = debug; 427 } 428 429 430 private void setVerboseLocked(boolean verbose) { 431 com.android.server.autofill.Helper.sVerbose = verbose; 432 android.view.autofill.Helper.sVerbose = verbose; 433 } 434 435 /** 436 * Removes a cached service for a given user. 437 */ 438 private void removeCachedServiceLocked(int userId) { 439 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 440 if (service != null) { 441 mServicesCache.delete(userId); 442 service.destroyLocked(); 443 } 444 } 445 446 /** 447 * Updates a cached service for a given user. 448 */ 449 private void updateCachedServiceLocked(int userId) { 450 updateCachedServiceLocked(userId, mDisabledUsers.get(userId)); 451 } 452 453 /** 454 * Updates a cached service for a given user. 455 */ 456 private void updateCachedServiceLocked(int userId, boolean disabled) { 457 AutofillManagerServiceImpl service = getServiceForUserLocked(userId); 458 if (service != null) { 459 service.updateLocked(disabled); 460 if (!service.isEnabled()) { 461 removeCachedServiceLocked(userId); 462 } 463 } 464 } 465 466 final class AutoFillManagerServiceStub extends IAutoFillManager.Stub { 467 @Override 468 public int addClient(IAutoFillManagerClient client, int userId) { 469 synchronized (mLock) { 470 int flags = 0; 471 if (getServiceForUserLocked(userId).addClientLocked(client)) { 472 flags |= AutofillManager.FLAG_ADD_CLIENT_ENABLED; 473 } 474 if (sDebug) { 475 flags |= AutofillManager.FLAG_ADD_CLIENT_DEBUG; 476 } 477 if (sVerbose) { 478 flags |= AutofillManager.FLAG_ADD_CLIENT_VERBOSE; 479 } 480 return flags; 481 } 482 } 483 484 @Override 485 public void setAuthenticationResult(Bundle data, int sessionId, int authenticationId, 486 int userId) { 487 synchronized (mLock) { 488 final AutofillManagerServiceImpl service = getServiceForUserLocked(userId); 489 service.setAuthenticationResultLocked(data, sessionId, authenticationId, 490 getCallingUid()); 491 } 492 } 493 494 @Override 495 public void setHasCallback(int sessionId, int userId, boolean hasIt) { 496 synchronized (mLock) { 497 final AutofillManagerServiceImpl service = getServiceForUserLocked(userId); 498 service.setHasCallback(sessionId, getCallingUid(), hasIt); 499 } 500 } 501 502 @Override 503 public int startSession(IBinder activityToken, IBinder appCallback, AutofillId autofillId, 504 Rect bounds, AutofillValue value, int userId, boolean hasCallback, int flags, 505 String packageName) { 506 507 activityToken = Preconditions.checkNotNull(activityToken, "activityToken"); 508 appCallback = Preconditions.checkNotNull(appCallback, "appCallback"); 509 autofillId = Preconditions.checkNotNull(autofillId, "autoFillId"); 510 packageName = Preconditions.checkNotNull(packageName, "packageName"); 511 512 Preconditions.checkArgument(userId == UserHandle.getUserId(getCallingUid()), "userId"); 513 514 try { 515 mContext.getPackageManager().getPackageInfoAsUser(packageName, 0, userId); 516 } catch (PackageManager.NameNotFoundException e) { 517 throw new IllegalArgumentException(packageName + " is not a valid package", e); 518 } 519 520 synchronized (mLock) { 521 final AutofillManagerServiceImpl service = getServiceForUserLocked(userId); 522 return service.startSessionLocked(activityToken, getCallingUid(), appCallback, 523 autofillId, bounds, value, hasCallback, flags, packageName); 524 } 525 } 526 527 @Override 528 public FillEventHistory getFillEventHistory() throws RemoteException { 529 UserHandle user = getCallingUserHandle(); 530 int uid = getCallingUid(); 531 532 synchronized (mLock) { 533 AutofillManagerServiceImpl service = peekServiceForUserLocked(user.getIdentifier()); 534 if (service != null) { 535 return service.getFillEventHistory(uid); 536 } 537 } 538 539 return null; 540 } 541 542 @Override 543 public boolean restoreSession(int sessionId, IBinder activityToken, IBinder appCallback) 544 throws RemoteException { 545 activityToken = Preconditions.checkNotNull(activityToken, "activityToken"); 546 appCallback = Preconditions.checkNotNull(appCallback, "appCallback"); 547 548 synchronized (mLock) { 549 final AutofillManagerServiceImpl service = mServicesCache.get( 550 UserHandle.getCallingUserId()); 551 if (service != null) { 552 return service.restoreSession(sessionId, getCallingUid(), activityToken, 553 appCallback); 554 } 555 } 556 557 return false; 558 } 559 560 @Override 561 public void updateSession(int sessionId, AutofillId autoFillId, Rect bounds, 562 AutofillValue value, int action, int flags, int userId) { 563 synchronized (mLock) { 564 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 565 if (service != null) { 566 service.updateSessionLocked(sessionId, getCallingUid(), autoFillId, bounds, 567 value, action, flags); 568 } 569 } 570 } 571 572 @Override 573 public int updateOrRestartSession(IBinder activityToken, IBinder appCallback, 574 AutofillId autoFillId, Rect bounds, AutofillValue value, int userId, 575 boolean hasCallback, int flags, String packageName, int sessionId, int action) { 576 boolean restart = false; 577 synchronized (mLock) { 578 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 579 if (service != null) { 580 restart = service.updateSessionLocked(sessionId, getCallingUid(), autoFillId, 581 bounds, value, action, flags); 582 } 583 } 584 if (restart) { 585 return startSession(activityToken, appCallback, autoFillId, bounds, value, userId, 586 hasCallback, flags, packageName); 587 } 588 589 // Nothing changed... 590 return sessionId; 591 } 592 593 @Override 594 public void finishSession(int sessionId, int userId) { 595 synchronized (mLock) { 596 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 597 if (service != null) { 598 service.finishSessionLocked(sessionId, getCallingUid()); 599 } 600 } 601 } 602 603 @Override 604 public void cancelSession(int sessionId, int userId) { 605 synchronized (mLock) { 606 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 607 if (service != null) { 608 service.cancelSessionLocked(sessionId, getCallingUid()); 609 } 610 } 611 } 612 613 @Override 614 public void disableOwnedAutofillServices(int userId) { 615 synchronized (mLock) { 616 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 617 if (service != null) { 618 service.disableOwnedAutofillServicesLocked(Binder.getCallingUid()); 619 } 620 } 621 } 622 623 @Override 624 public boolean isServiceSupported(int userId) { 625 synchronized (mLock) { 626 return !mDisabledUsers.get(userId); 627 } 628 } 629 630 @Override 631 public boolean isServiceEnabled(int userId, String packageName) { 632 synchronized (mLock) { 633 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 634 if (service == null) return false; 635 return Objects.equals(packageName, service.getPackageName()); 636 } 637 } 638 639 @Override 640 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 641 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; 642 643 boolean showHistory = true; 644 boolean uiOnly = false; 645 if (args != null) { 646 for (String arg : args) { 647 switch(arg) { 648 case "--no-history": 649 showHistory = false; 650 break; 651 case "--ui-only": 652 uiOnly = true; 653 break; 654 case "--help": 655 pw.println("Usage: dumpsys autofill [--ui-only|--no-history]"); 656 return; 657 default: 658 Slog.w(TAG, "Ignoring invalid dump arg: " + arg); 659 } 660 } 661 } 662 663 if (uiOnly) { 664 mUi.dump(pw); 665 return; 666 } 667 668 boolean oldDebug = sDebug; 669 try { 670 synchronized (mLock) { 671 oldDebug = sDebug; 672 setDebugLocked(true); 673 pw.print("Debug mode: "); pw.println(oldDebug); 674 pw.print("Verbose mode: "); pw.println(sVerbose); 675 pw.print("Disabled users: "); pw.println(mDisabledUsers); 676 pw.print("Max partitions per session: "); pw.println(sPartitionMaxCount); 677 final int size = mServicesCache.size(); 678 pw.print("Cached services: "); 679 if (size == 0) { 680 pw.println("none"); 681 } else { 682 pw.println(size); 683 for (int i = 0; i < size; i++) { 684 pw.print("\nService at index "); pw.println(i); 685 final AutofillManagerServiceImpl impl = mServicesCache.valueAt(i); 686 impl.dumpLocked(" ", pw); 687 } 688 } 689 mUi.dump(pw); 690 } 691 if (showHistory) { 692 pw.println("Requests history:"); 693 mRequestsHistory.reverseDump(fd, pw, args); 694 } 695 } finally { 696 setDebugLocked(oldDebug); 697 } 698 } 699 700 @Override 701 public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, 702 String[] args, ShellCallback callback, ResultReceiver resultReceiver) { 703 (new AutofillManagerServiceShellCommand(AutofillManagerService.this)).exec( 704 this, in, out, err, args, callback, resultReceiver); 705 } 706 } 707 708 private final class SettingsObserver extends ContentObserver { 709 SettingsObserver(Handler handler) { 710 super(handler); 711 ContentResolver resolver = mContext.getContentResolver(); 712 resolver.registerContentObserver(Settings.Secure.getUriFor( 713 Settings.Secure.AUTOFILL_SERVICE), false, this, UserHandle.USER_ALL); 714 resolver.registerContentObserver(Settings.Secure.getUriFor( 715 Settings.Secure.USER_SETUP_COMPLETE), false, this, UserHandle.USER_ALL); 716 } 717 718 @Override 719 public void onChange(boolean selfChange, Uri uri, int userId) { 720 if (sVerbose) Slog.v(TAG, "onChange(): uri=" + uri + ", userId=" + userId); 721 synchronized (mLock) { 722 updateCachedServiceLocked(userId); 723 } 724 } 725 } 726} 727