AutofillManagerService.java revision 7a1deb7c5f2c57df4f905ba997863a03d363a53e
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 176 private void startTrackingPackageChanges() { 177 PackageMonitor monitor = new PackageMonitor() { 178 @Override 179 public void onSomePackagesChanged() { 180 synchronized (mLock) { 181 updateCachedServiceLocked(getChangingUserId()); 182 } 183 } 184 185 @Override 186 public void onPackageUpdateFinished(String packageName, int uid) { 187 synchronized (mLock) { 188 final String activePackageName = getActiveAutofillServicePackageName(); 189 if (packageName.equals(activePackageName)) { 190 removeCachedServiceLocked(getChangingUserId()); 191 } 192 } 193 } 194 195 @Override 196 public void onPackageRemoved(String packageName, int uid) { 197 synchronized (mLock) { 198 final int userId = getChangingUserId(); 199 final AutofillManagerServiceImpl userState = peekServiceForUserLocked(userId); 200 if (userState != null) { 201 final ComponentName componentName = userState.getServiceComponentName(); 202 if (componentName != null) { 203 if (packageName.equals(componentName.getPackageName())) { 204 handleActiveAutofillServiceRemoved(userId); 205 } 206 } 207 } 208 } 209 } 210 211 @Override 212 public boolean onHandleForceStop(Intent intent, String[] packages, 213 int uid, boolean doit) { 214 synchronized (mLock) { 215 final String activePackageName = getActiveAutofillServicePackageName(); 216 for (String pkg : packages) { 217 if (pkg.equals(activePackageName)) { 218 if (!doit) { 219 return true; 220 } 221 removeCachedServiceLocked(getChangingUserId()); 222 } 223 } 224 } 225 return false; 226 } 227 228 private void handleActiveAutofillServiceRemoved(int userId) { 229 removeCachedServiceLocked(userId); 230 Settings.Secure.putStringForUser(mContext.getContentResolver(), 231 Settings.Secure.AUTOFILL_SERVICE, null, userId); 232 } 233 234 private String getActiveAutofillServicePackageName() { 235 final int userId = getChangingUserId(); 236 final AutofillManagerServiceImpl userState = peekServiceForUserLocked(userId); 237 if (userState == null) { 238 return null; 239 } 240 final ComponentName serviceComponent = userState.getServiceComponentName(); 241 if (serviceComponent == null) { 242 return null; 243 } 244 return serviceComponent.getPackageName(); 245 } 246 }; 247 248 // package changes 249 monitor.register(mContext, null, UserHandle.ALL, true); 250 } 251 252 @Override 253 public void onStart() { 254 publishBinderService(AUTOFILL_MANAGER_SERVICE, new AutoFillManagerServiceStub()); 255 } 256 257 @Override 258 public void onBootPhase(int phase) { 259 if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) { 260 new SettingsObserver(BackgroundThread.getHandler()); 261 } 262 } 263 264 @Override 265 public void onUnlockUser(int userId) { 266 synchronized (mLock) { 267 updateCachedServiceLocked(userId); 268 } 269 } 270 271 @Override 272 public void onCleanupUser(int userId) { 273 synchronized (mLock) { 274 removeCachedServiceLocked(userId); 275 } 276 } 277 278 /** 279 * Gets the service instance for an user. 280 * 281 * @return service instance. 282 */ 283 @NonNull 284 AutofillManagerServiceImpl getServiceForUserLocked(int userId) { 285 final int resolvedUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), 286 Binder.getCallingUid(), userId, false, false, null, null); 287 AutofillManagerServiceImpl service = mServicesCache.get(resolvedUserId); 288 if (service == null) { 289 service = new AutofillManagerServiceImpl(mContext, mLock, mRequestsHistory, 290 resolvedUserId, mUi, mDisabledUsers.get(resolvedUserId)); 291 mServicesCache.put(userId, service); 292 } 293 return service; 294 } 295 296 /** 297 * Peeks the service instance for a user. 298 * 299 * @return service instance or {@code null} if not already present 300 */ 301 @Nullable 302 AutofillManagerServiceImpl peekServiceForUserLocked(int userId) { 303 final int resolvedUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), 304 Binder.getCallingUid(), userId, false, false, null, null); 305 return mServicesCache.get(resolvedUserId); 306 } 307 308 // Called by Shell command. 309 void destroySessions(int userId, IResultReceiver receiver) { 310 Slog.i(TAG, "destroySessions() for userId " + userId); 311 mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG); 312 313 synchronized (mLock) { 314 if (userId != UserHandle.USER_ALL) { 315 AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 316 if (service != null) { 317 service.destroySessionsLocked(); 318 } 319 } else { 320 final int size = mServicesCache.size(); 321 for (int i = 0; i < size; i++) { 322 mServicesCache.valueAt(i).destroySessionsLocked(); 323 } 324 } 325 } 326 327 try { 328 receiver.send(0, new Bundle()); 329 } catch (RemoteException e) { 330 // Just ignore it... 331 } 332 } 333 334 // Called by Shell command. 335 void listSessions(int userId, IResultReceiver receiver) { 336 Slog.i(TAG, "listSessions() for userId " + userId); 337 mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG); 338 339 final Bundle resultData = new Bundle(); 340 final ArrayList<String> sessions = new ArrayList<>(); 341 342 synchronized (mLock) { 343 if (userId != UserHandle.USER_ALL) { 344 AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 345 if (service != null) { 346 service.listSessionsLocked(sessions); 347 } 348 } else { 349 final int size = mServicesCache.size(); 350 for (int i = 0; i < size; i++) { 351 mServicesCache.valueAt(i).listSessionsLocked(sessions); 352 } 353 } 354 } 355 356 resultData.putStringArrayList(RECEIVER_BUNDLE_EXTRA_SESSIONS, sessions); 357 try { 358 receiver.send(0, resultData); 359 } catch (RemoteException e) { 360 // Just ignore it... 361 } 362 } 363 364 // Called by Shell command. 365 void reset() { 366 Slog.i(TAG, "reset()"); 367 mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG); 368 369 synchronized (mLock) { 370 final int size = mServicesCache.size(); 371 for (int i = 0; i < size; i++) { 372 mServicesCache.valueAt(i).destroyLocked(); 373 } 374 mServicesCache.clear(); 375 } 376 } 377 378 // Called by Shell command. 379 void setLogLevel(int level) { 380 Slog.i(TAG, "setLogLevel(): " + level); 381 mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG); 382 383 boolean debug = false; 384 boolean verbose = false; 385 if (level == AutofillManager.FLAG_ADD_CLIENT_VERBOSE) { 386 debug = verbose = true; 387 } else if (level == AutofillManager.FLAG_ADD_CLIENT_DEBUG) { 388 debug = true; 389 } 390 synchronized (mLock) { 391 setDebugLocked(debug); 392 setVerboseLocked(verbose); 393 } 394 } 395 396 // Called by Shell command. 397 int getLogLevel() { 398 mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG); 399 400 synchronized (mLock) { 401 if (sVerbose) return AutofillManager.FLAG_ADD_CLIENT_VERBOSE; 402 if (sDebug) return AutofillManager.FLAG_ADD_CLIENT_DEBUG; 403 return 0; 404 } 405 } 406 407 // Called by Shell command. 408 public int getMaxPartitions() { 409 mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG); 410 411 synchronized (mLock) { 412 return sPartitionMaxCount; 413 } 414 } 415 416 // Called by Shell command. 417 public void setMaxPartitions(int max) { 418 mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG); 419 Slog.i(TAG, "setMaxPartitions(): " + max); 420 synchronized (mLock) { 421 sPartitionMaxCount = max; 422 } 423 } 424 425 private void setDebugLocked(boolean debug) { 426 com.android.server.autofill.Helper.sDebug = debug; 427 android.view.autofill.Helper.sDebug = debug; 428 } 429 430 431 private void setVerboseLocked(boolean verbose) { 432 com.android.server.autofill.Helper.sVerbose = verbose; 433 android.view.autofill.Helper.sVerbose = verbose; 434 } 435 436 /** 437 * Removes a cached service for a given user. 438 */ 439 private void removeCachedServiceLocked(int userId) { 440 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 441 if (service != null) { 442 mServicesCache.delete(userId); 443 service.destroyLocked(); 444 } 445 } 446 447 /** 448 * Updates a cached service for a given user. 449 */ 450 private void updateCachedServiceLocked(int userId) { 451 updateCachedServiceLocked(userId, mDisabledUsers.get(userId)); 452 } 453 454 /** 455 * Updates a cached service for a given user. 456 */ 457 private void updateCachedServiceLocked(int userId, boolean disabled) { 458 AutofillManagerServiceImpl service = getServiceForUserLocked(userId); 459 if (service != null) { 460 service.updateLocked(disabled); 461 if (!service.isEnabled()) { 462 removeCachedServiceLocked(userId); 463 } 464 } 465 } 466 467 final class AutoFillManagerServiceStub extends IAutoFillManager.Stub { 468 @Override 469 public int addClient(IAutoFillManagerClient client, int userId) { 470 synchronized (mLock) { 471 int flags = 0; 472 if (getServiceForUserLocked(userId).addClientLocked(client)) { 473 flags |= AutofillManager.FLAG_ADD_CLIENT_ENABLED; 474 } 475 if (sDebug) { 476 flags |= AutofillManager.FLAG_ADD_CLIENT_DEBUG; 477 } 478 if (sVerbose) { 479 flags |= AutofillManager.FLAG_ADD_CLIENT_VERBOSE; 480 } 481 return flags; 482 } 483 } 484 485 @Override 486 public void setAuthenticationResult(Bundle data, int sessionId, int authenticationId, 487 int userId) { 488 synchronized (mLock) { 489 final AutofillManagerServiceImpl service = getServiceForUserLocked(userId); 490 service.setAuthenticationResultLocked(data, sessionId, authenticationId, 491 getCallingUid()); 492 } 493 } 494 495 @Override 496 public void setHasCallback(int sessionId, int userId, boolean hasIt) { 497 synchronized (mLock) { 498 final AutofillManagerServiceImpl service = getServiceForUserLocked(userId); 499 service.setHasCallback(sessionId, getCallingUid(), hasIt); 500 } 501 } 502 503 @Override 504 public int startSession(IBinder activityToken, IBinder appCallback, AutofillId autofillId, 505 Rect bounds, AutofillValue value, int userId, boolean hasCallback, int flags, 506 String packageName) { 507 508 activityToken = Preconditions.checkNotNull(activityToken, "activityToken"); 509 appCallback = Preconditions.checkNotNull(appCallback, "appCallback"); 510 autofillId = Preconditions.checkNotNull(autofillId, "autoFillId"); 511 packageName = Preconditions.checkNotNull(packageName, "packageName"); 512 513 Preconditions.checkArgument(userId == UserHandle.getUserId(getCallingUid()), "userId"); 514 515 try { 516 mContext.getPackageManager().getPackageInfoAsUser(packageName, 0, userId); 517 } catch (PackageManager.NameNotFoundException e) { 518 throw new IllegalArgumentException(packageName + " is not a valid package", e); 519 } 520 521 synchronized (mLock) { 522 final AutofillManagerServiceImpl service = getServiceForUserLocked(userId); 523 return service.startSessionLocked(activityToken, getCallingUid(), appCallback, 524 autofillId, bounds, value, hasCallback, flags, packageName); 525 } 526 } 527 528 @Override 529 public FillEventHistory getFillEventHistory() throws RemoteException { 530 UserHandle user = getCallingUserHandle(); 531 int uid = getCallingUid(); 532 533 synchronized (mLock) { 534 AutofillManagerServiceImpl service = peekServiceForUserLocked(user.getIdentifier()); 535 if (service != null) { 536 return service.getFillEventHistory(uid); 537 } 538 } 539 540 return null; 541 } 542 543 @Override 544 public boolean restoreSession(int sessionId, IBinder activityToken, IBinder appCallback) 545 throws RemoteException { 546 activityToken = Preconditions.checkNotNull(activityToken, "activityToken"); 547 appCallback = Preconditions.checkNotNull(appCallback, "appCallback"); 548 549 synchronized (mLock) { 550 final AutofillManagerServiceImpl service = mServicesCache.get( 551 UserHandle.getCallingUserId()); 552 if (service != null) { 553 return service.restoreSession(sessionId, getCallingUid(), activityToken, 554 appCallback); 555 } 556 } 557 558 return false; 559 } 560 561 @Override 562 public void updateSession(int sessionId, AutofillId id, Rect bounds, 563 AutofillValue value, int action, int flags, int userId) { 564 synchronized (mLock) { 565 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 566 if (service != null) { 567 service.updateSessionLocked(sessionId, getCallingUid(), id, bounds, value, 568 action, flags); 569 } 570 } 571 } 572 573 @Override 574 public void finishSession(int sessionId, int userId) { 575 synchronized (mLock) { 576 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 577 if (service != null) { 578 service.finishSessionLocked(sessionId, getCallingUid()); 579 } 580 } 581 } 582 583 @Override 584 public void cancelSession(int sessionId, int userId) { 585 synchronized (mLock) { 586 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 587 if (service != null) { 588 service.cancelSessionLocked(sessionId, getCallingUid()); 589 } 590 } 591 } 592 593 @Override 594 public void disableOwnedAutofillServices(int userId) { 595 synchronized (mLock) { 596 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 597 if (service != null) { 598 service.disableOwnedAutofillServicesLocked(Binder.getCallingUid()); 599 } 600 } 601 } 602 603 @Override 604 public boolean isServiceSupported(int userId) { 605 synchronized (mLock) { 606 return !mDisabledUsers.get(userId); 607 } 608 } 609 610 @Override 611 public boolean isServiceEnabled(int userId, String packageName) { 612 synchronized (mLock) { 613 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 614 if (service == null) return false; 615 return Objects.equals(packageName, service.getPackageName()); 616 } 617 } 618 619 @Override 620 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 621 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; 622 623 boolean showHistory = true; 624 boolean uiOnly = false; 625 if (args != null) { 626 for (String arg : args) { 627 switch(arg) { 628 case "--no-history": 629 showHistory = false; 630 break; 631 case "--ui-only": 632 uiOnly = true; 633 break; 634 case "--help": 635 pw.println("Usage: dumpsys autofill [--ui-only|--no-history]"); 636 return; 637 default: 638 Slog.w(TAG, "Ignoring invalid dump arg: " + arg); 639 } 640 } 641 } 642 643 if (uiOnly) { 644 mUi.dump(pw); 645 return; 646 } 647 648 boolean oldDebug = sDebug; 649 try { 650 synchronized (mLock) { 651 oldDebug = sDebug; 652 setDebugLocked(true); 653 pw.print("Debug mode: "); pw.println(oldDebug); 654 pw.print("Verbose mode: "); pw.println(sVerbose); 655 pw.print("Disabled users: "); pw.println(mDisabledUsers); 656 pw.print("Max partitions per session: "); pw.println(sPartitionMaxCount); 657 final int size = mServicesCache.size(); 658 pw.print("Cached services: "); 659 if (size == 0) { 660 pw.println("none"); 661 } else { 662 pw.println(size); 663 for (int i = 0; i < size; i++) { 664 pw.print("\nService at index "); pw.println(i); 665 final AutofillManagerServiceImpl impl = mServicesCache.valueAt(i); 666 impl.dumpLocked(" ", pw); 667 } 668 } 669 mUi.dump(pw); 670 } 671 if (showHistory) { 672 pw.println("Requests history:"); 673 mRequestsHistory.reverseDump(fd, pw, args); 674 } 675 } finally { 676 setDebugLocked(oldDebug); 677 } 678 } 679 680 @Override 681 public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, 682 String[] args, ShellCallback callback, ResultReceiver resultReceiver) { 683 (new AutofillManagerServiceShellCommand(AutofillManagerService.this)).exec( 684 this, in, out, err, args, callback, resultReceiver); 685 } 686 } 687 688 private final class SettingsObserver extends ContentObserver { 689 SettingsObserver(Handler handler) { 690 super(handler); 691 ContentResolver resolver = mContext.getContentResolver(); 692 resolver.registerContentObserver(Settings.Secure.getUriFor( 693 Settings.Secure.AUTOFILL_SERVICE), false, this, UserHandle.USER_ALL); 694 } 695 696 @Override 697 public void onChange(boolean selfChange, Uri uri, int userId) { 698 synchronized (mLock) { 699 updateCachedServiceLocked(userId); 700 } 701 } 702 } 703} 704