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