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.sDebug; 23 import static com.android.server.autofill.Helper.sFullScreenMode; 24 import static com.android.server.autofill.Helper.sPartitionMaxCount; 25 import static com.android.server.autofill.Helper.sVisibleDatasetsMaxCount; 26 import static com.android.server.autofill.Helper.sVerbose; 27 28 import android.annotation.NonNull; 29 import android.annotation.Nullable; 30 import android.annotation.UserIdInt; 31 import android.app.ActivityManager; 32 import android.app.ActivityThread; 33 import android.content.BroadcastReceiver; 34 import android.content.ComponentName; 35 import android.content.ContentResolver; 36 import android.content.Context; 37 import android.content.Intent; 38 import android.content.IntentFilter; 39 import android.content.pm.PackageManager; 40 import android.content.pm.UserInfo; 41 import android.database.ContentObserver; 42 import android.graphics.Rect; 43 import android.net.Uri; 44 import android.os.Binder; 45 import android.os.Build; 46 import android.os.Bundle; 47 import android.os.Handler; 48 import android.os.IBinder; 49 import android.os.RemoteCallback; 50 import android.os.RemoteException; 51 import android.os.ResultReceiver; 52 import android.os.ShellCallback; 53 import android.os.UserHandle; 54 import android.os.UserManager; 55 import android.os.UserManagerInternal; 56 import android.provider.Settings; 57 import android.service.autofill.FillEventHistory; 58 import android.service.autofill.UserData; 59 import android.text.TextUtils; 60 import android.text.TextUtils.SimpleStringSplitter; 61 import android.util.ArrayMap; 62 import android.util.LocalLog; 63 import android.util.Slog; 64 import android.util.SparseArray; 65 import android.util.SparseBooleanArray; 66 import android.view.autofill.AutofillId; 67 import android.view.autofill.AutofillManager; 68 import android.view.autofill.AutofillManagerInternal; 69 import android.view.autofill.AutofillValue; 70 import android.view.autofill.IAutoFillManager; 71 import android.view.autofill.IAutoFillManagerClient; 72 73 import com.android.internal.annotations.GuardedBy; 74 import com.android.internal.annotations.VisibleForTesting; 75 import com.android.internal.content.PackageMonitor; 76 import com.android.internal.os.BackgroundThread; 77 import com.android.internal.os.IResultReceiver; 78 import com.android.internal.util.DumpUtils; 79 import com.android.internal.util.Preconditions; 80 import com.android.server.FgThread; 81 import com.android.server.LocalServices; 82 import com.android.server.SystemService; 83 import com.android.server.autofill.ui.AutoFillUI; 84 85 import java.io.FileDescriptor; 86 import java.io.PrintWriter; 87 import java.util.ArrayList; 88 import java.util.Arrays; 89 import java.util.List; 90 import java.util.Map; 91 import java.util.Objects; 92 93 /** 94 * Entry point service for autofill management. 95 * 96 * <p>This service provides the {@link IAutoFillManager} implementation and keeps a list of 97 * {@link AutofillManagerServiceImpl} per user; the real work is done by 98 * {@link AutofillManagerServiceImpl} itself. 99 */ 100 public final class AutofillManagerService extends SystemService { 101 102 private static final String TAG = "AutofillManagerService"; 103 104 static final String RECEIVER_BUNDLE_EXTRA_SESSIONS = "sessions"; 105 106 private static final char COMPAT_PACKAGE_DELIMITER = ':'; 107 private static final char COMPAT_PACKAGE_URL_IDS_DELIMITER = ','; 108 private static final char COMPAT_PACKAGE_URL_IDS_BLOCK_BEGIN = '['; 109 private static final char COMPAT_PACKAGE_URL_IDS_BLOCK_END = ']'; 110 111 private final Context mContext; 112 private final AutoFillUI mUi; 113 114 private final Object mLock = new Object(); 115 116 /** 117 * Cache of {@link AutofillManagerServiceImpl} per user id. 118 * <p> 119 * It has to be mapped by user id because the same current user could have simultaneous sessions 120 * associated to different user profiles (for example, in a multi-window environment or when 121 * device has work profiles). 122 */ 123 @GuardedBy("mLock") 124 private SparseArray<AutofillManagerServiceImpl> mServicesCache = new SparseArray<>(); 125 126 /** 127 * Users disabled due to {@link UserManager} restrictions. 128 */ 129 @GuardedBy("mLock") 130 private final SparseBooleanArray mDisabledUsers = new SparseBooleanArray(); 131 132 private final LocalLog mRequestsHistory = new LocalLog(20); 133 private final LocalLog mUiLatencyHistory = new LocalLog(20); 134 private final LocalLog mWtfHistory = new LocalLog(50); 135 136 private final AutofillCompatState mAutofillCompatState = new AutofillCompatState(); 137 private final LocalService mLocalService = new LocalService(); 138 139 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 140 @Override 141 public void onReceive(Context context, Intent intent) { 142 if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) { 143 if (sDebug) Slog.d(TAG, "Close system dialogs"); 144 145 // TODO(b/64940307): we need to destroy all sessions that are finished but showing 146 // Save UI because there is no way to show the Save UI back when the activity 147 // beneath it is brought back to top. Ideally, we should just hide the UI and 148 // bring it back when the activity resumes. 149 synchronized (mLock) { 150 for (int i = 0; i < mServicesCache.size(); i++) { 151 mServicesCache.valueAt(i).destroyFinishedSessionsLocked(); 152 } 153 } 154 155 mUi.hideAll(null); 156 } 157 } 158 }; 159 160 @GuardedBy("mLock") 161 private boolean mAllowInstantService; 162 163 public AutofillManagerService(Context context) { 164 super(context); 165 mContext = context; 166 mUi = new AutoFillUI(ActivityThread.currentActivityThread().getSystemUiContext()); 167 168 final boolean debug = Build.IS_DEBUGGABLE; 169 Slog.i(TAG, "Setting debug to " + debug); 170 setDebugLocked(debug); 171 172 final IntentFilter filter = new IntentFilter(); 173 filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); 174 mContext.registerReceiver(mBroadcastReceiver, filter, null, FgThread.getHandler()); 175 176 // Hookup with UserManager to disable service when necessary. 177 final UserManager um = context.getSystemService(UserManager.class); 178 final UserManagerInternal umi = LocalServices.getService(UserManagerInternal.class); 179 final List<UserInfo> users = um.getUsers(); 180 for (int i = 0; i < users.size(); i++) { 181 final int userId = users.get(i).id; 182 final boolean disabled = umi.getUserRestriction(userId, UserManager.DISALLOW_AUTOFILL); 183 if (disabled) { 184 if (disabled) { 185 Slog.i(TAG, "Disabling Autofill for user " + userId); 186 } 187 mDisabledUsers.put(userId, disabled); 188 } 189 } 190 umi.addUserRestrictionsListener((userId, newRestrictions, prevRestrictions) -> { 191 final boolean disabledNow = 192 newRestrictions.getBoolean(UserManager.DISALLOW_AUTOFILL, false); 193 synchronized (mLock) { 194 final boolean disabledBefore = mDisabledUsers.get(userId); 195 if (disabledBefore == disabledNow) { 196 // Nothing changed, do nothing. 197 if (sDebug) { 198 Slog.d(TAG, "Autofill restriction did not change for user " + userId); 199 return; 200 } 201 } 202 Slog.i(TAG, "Updating Autofill for user " + userId + ": disabled=" + disabledNow); 203 mDisabledUsers.put(userId, disabledNow); 204 updateCachedServiceLocked(userId, disabledNow); 205 } 206 }); 207 startTrackingPackageChanges(); 208 } 209 210 private void startTrackingPackageChanges() { 211 PackageMonitor monitor = new PackageMonitor() { 212 @Override 213 public void onSomePackagesChanged() { 214 synchronized (mLock) { 215 updateCachedServiceLocked(getChangingUserId()); 216 } 217 } 218 219 @Override 220 public void onPackageUpdateFinished(String packageName, int uid) { 221 synchronized (mLock) { 222 final String activePackageName = getActiveAutofillServicePackageName(); 223 if (packageName.equals(activePackageName)) { 224 removeCachedServiceLocked(getChangingUserId()); 225 } else { 226 handlePackageUpdateLocked(packageName); 227 } 228 } 229 } 230 231 @Override 232 public void onPackageRemoved(String packageName, int uid) { 233 synchronized (mLock) { 234 final int userId = getChangingUserId(); 235 final AutofillManagerServiceImpl userState = peekServiceForUserLocked(userId); 236 if (userState != null) { 237 final ComponentName componentName = userState.getServiceComponentName(); 238 if (componentName != null) { 239 if (packageName.equals(componentName.getPackageName())) { 240 handleActiveAutofillServiceRemoved(userId); 241 } 242 } 243 } 244 } 245 } 246 247 @Override 248 public boolean onHandleForceStop(Intent intent, String[] packages, 249 int uid, boolean doit) { 250 synchronized (mLock) { 251 final String activePackageName = getActiveAutofillServicePackageName(); 252 for (String pkg : packages) { 253 if (pkg.equals(activePackageName)) { 254 if (!doit) { 255 return true; 256 } 257 removeCachedServiceLocked(getChangingUserId()); 258 } else { 259 handlePackageUpdateLocked(pkg); 260 } 261 } 262 } 263 return false; 264 } 265 266 private void handleActiveAutofillServiceRemoved(int userId) { 267 removeCachedServiceLocked(userId); 268 Settings.Secure.putStringForUser(mContext.getContentResolver(), 269 Settings.Secure.AUTOFILL_SERVICE, null, userId); 270 } 271 272 private String getActiveAutofillServicePackageName() { 273 final int userId = getChangingUserId(); 274 final AutofillManagerServiceImpl userState = peekServiceForUserLocked(userId); 275 if (userState == null) { 276 return null; 277 } 278 final ComponentName serviceComponent = userState.getServiceComponentName(); 279 if (serviceComponent == null) { 280 return null; 281 } 282 return serviceComponent.getPackageName(); 283 } 284 285 @GuardedBy("mLock") 286 private void handlePackageUpdateLocked(String packageName) { 287 final int size = mServicesCache.size(); 288 for (int i = 0; i < size; i++) { 289 mServicesCache.valueAt(i).handlePackageUpdateLocked(packageName); 290 } 291 } 292 }; 293 294 // package changes 295 monitor.register(mContext, null, UserHandle.ALL, true); 296 } 297 298 @Override 299 public void onStart() { 300 publishBinderService(AUTOFILL_MANAGER_SERVICE, new AutoFillManagerServiceStub()); 301 publishLocalService(AutofillManagerInternal.class, mLocalService); 302 } 303 304 @Override 305 public void onBootPhase(int phase) { 306 if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) { 307 new SettingsObserver(BackgroundThread.getHandler()); 308 } 309 } 310 311 @Override 312 public void onUnlockUser(int userId) { 313 synchronized (mLock) { 314 updateCachedServiceLocked(userId); 315 } 316 } 317 318 @Override 319 public void onSwitchUser(int userHandle) { 320 if (sDebug) Slog.d(TAG, "Hiding UI when user switched"); 321 mUi.hideAll(null); 322 } 323 324 @Override 325 public void onCleanupUser(int userId) { 326 synchronized (mLock) { 327 removeCachedServiceLocked(userId); 328 } 329 } 330 331 /** 332 * Gets the service instance for an user. 333 * 334 * @return service instance. 335 */ 336 @GuardedBy("mLock") 337 @NonNull 338 AutofillManagerServiceImpl getServiceForUserLocked(int userId) { 339 final int resolvedUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), 340 Binder.getCallingUid(), userId, false, false, null, null); 341 AutofillManagerServiceImpl service = mServicesCache.get(resolvedUserId); 342 if (service == null) { 343 service = new AutofillManagerServiceImpl(mContext, mLock, mRequestsHistory, 344 mUiLatencyHistory, mWtfHistory, resolvedUserId, mUi, 345 mAutofillCompatState, mDisabledUsers.get(resolvedUserId)); 346 mServicesCache.put(userId, service); 347 addCompatibilityModeRequestsLocked(service, userId); 348 } 349 return service; 350 } 351 352 /** 353 * Peeks the service instance for a user. 354 * 355 * @return service instance or {@code null} if not already present 356 */ 357 @GuardedBy("mLock") 358 @Nullable 359 AutofillManagerServiceImpl peekServiceForUserLocked(int userId) { 360 final int resolvedUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), 361 Binder.getCallingUid(), userId, false, false, null, null); 362 return mServicesCache.get(resolvedUserId); 363 } 364 365 // Called by Shell command. 366 void destroySessions(int userId, IResultReceiver receiver) { 367 Slog.i(TAG, "destroySessions() for userId " + userId); 368 mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG); 369 370 synchronized (mLock) { 371 if (userId != UserHandle.USER_ALL) { 372 AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 373 if (service != null) { 374 service.destroySessionsLocked(); 375 } 376 } else { 377 final int size = mServicesCache.size(); 378 for (int i = 0; i < size; i++) { 379 mServicesCache.valueAt(i).destroySessionsLocked(); 380 } 381 } 382 } 383 384 try { 385 receiver.send(0, new Bundle()); 386 } catch (RemoteException e) { 387 // Just ignore it... 388 } 389 } 390 391 // Called by Shell command. 392 void listSessions(int userId, IResultReceiver receiver) { 393 Slog.i(TAG, "listSessions() for userId " + userId); 394 mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG); 395 396 final Bundle resultData = new Bundle(); 397 final ArrayList<String> sessions = new ArrayList<>(); 398 399 synchronized (mLock) { 400 if (userId != UserHandle.USER_ALL) { 401 AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 402 if (service != null) { 403 service.listSessionsLocked(sessions); 404 } 405 } else { 406 final int size = mServicesCache.size(); 407 for (int i = 0; i < size; i++) { 408 mServicesCache.valueAt(i).listSessionsLocked(sessions); 409 } 410 } 411 } 412 413 resultData.putStringArrayList(RECEIVER_BUNDLE_EXTRA_SESSIONS, sessions); 414 try { 415 receiver.send(0, resultData); 416 } catch (RemoteException e) { 417 // Just ignore it... 418 } 419 } 420 421 // Called by Shell command. 422 void reset() { 423 Slog.i(TAG, "reset()"); 424 mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG); 425 426 synchronized (mLock) { 427 final int size = mServicesCache.size(); 428 for (int i = 0; i < size; i++) { 429 mServicesCache.valueAt(i).destroyLocked(); 430 } 431 mServicesCache.clear(); 432 } 433 } 434 435 // Called by Shell command. 436 void setLogLevel(int level) { 437 Slog.i(TAG, "setLogLevel(): " + level); 438 mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG); 439 440 boolean debug = false; 441 boolean verbose = false; 442 if (level == AutofillManager.FLAG_ADD_CLIENT_VERBOSE) { 443 debug = verbose = true; 444 } else if (level == AutofillManager.FLAG_ADD_CLIENT_DEBUG) { 445 debug = true; 446 } 447 synchronized (mLock) { 448 setDebugLocked(debug); 449 setVerboseLocked(verbose); 450 } 451 } 452 453 // Called by Shell command. 454 int getLogLevel() { 455 mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG); 456 457 synchronized (mLock) { 458 if (sVerbose) return AutofillManager.FLAG_ADD_CLIENT_VERBOSE; 459 if (sDebug) return AutofillManager.FLAG_ADD_CLIENT_DEBUG; 460 return 0; 461 } 462 } 463 464 // Called by Shell command. 465 int getMaxPartitions() { 466 mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG); 467 468 synchronized (mLock) { 469 return sPartitionMaxCount; 470 } 471 } 472 473 // Called by Shell command. 474 void setMaxPartitions(int max) { 475 mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG); 476 Slog.i(TAG, "setMaxPartitions(): " + max); 477 synchronized (mLock) { 478 sPartitionMaxCount = max; 479 } 480 } 481 482 // Called by Shell command. 483 int getMaxVisibleDatasets() { 484 mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG); 485 486 synchronized (mLock) { 487 return sVisibleDatasetsMaxCount; 488 } 489 } 490 491 // Called by Shell command. 492 void setMaxVisibleDatasets(int max) { 493 mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG); 494 Slog.i(TAG, "setMaxVisibleDatasets(): " + max); 495 synchronized (mLock) { 496 sVisibleDatasetsMaxCount = max; 497 } 498 } 499 500 // Called by Shell command. 501 void getScore(@Nullable String algorithmName, @NonNull String value1, 502 @NonNull String value2, @NonNull RemoteCallback callback) { 503 mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG); 504 505 final FieldClassificationStrategy strategy = 506 new FieldClassificationStrategy(mContext, UserHandle.USER_CURRENT); 507 508 strategy.getScores(callback, algorithmName, null, 509 Arrays.asList(AutofillValue.forText(value1)), new String[] { value2 }); 510 } 511 512 // Called by Shell command. 513 Boolean getFullScreenMode() { 514 mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG); 515 return sFullScreenMode; 516 } 517 518 // Called by Shell command. 519 void setFullScreenMode(@Nullable Boolean mode) { 520 mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG); 521 sFullScreenMode = mode; 522 } 523 524 // Called by Shell command. 525 boolean getAllowInstantService() { 526 mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG); 527 synchronized (mLock) { 528 return mAllowInstantService; 529 } 530 } 531 532 // Called by Shell command. 533 void setAllowInstantService(boolean mode) { 534 mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG); 535 Slog.i(TAG, "setAllowInstantService(): " + mode); 536 synchronized (mLock) { 537 mAllowInstantService = mode; 538 } 539 } 540 541 private void setDebugLocked(boolean debug) { 542 com.android.server.autofill.Helper.sDebug = debug; 543 android.view.autofill.Helper.sDebug = debug; 544 } 545 546 private void setVerboseLocked(boolean verbose) { 547 com.android.server.autofill.Helper.sVerbose = verbose; 548 android.view.autofill.Helper.sVerbose = verbose; 549 } 550 551 /** 552 * Removes a cached service for a given user. 553 */ 554 @GuardedBy("mLock") 555 private void removeCachedServiceLocked(int userId) { 556 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 557 if (service != null) { 558 mServicesCache.delete(userId); 559 service.destroyLocked(); 560 mAutofillCompatState.removeCompatibilityModeRequests(userId); 561 } 562 } 563 564 /** 565 * Updates a cached service for a given user. 566 */ 567 @GuardedBy("mLock") 568 private void updateCachedServiceLocked(int userId) { 569 updateCachedServiceLocked(userId, mDisabledUsers.get(userId)); 570 } 571 572 /** 573 * Updates a cached service for a given user. 574 */ 575 @GuardedBy("mLock") 576 private void updateCachedServiceLocked(int userId, boolean disabled) { 577 AutofillManagerServiceImpl service = getServiceForUserLocked(userId); 578 if (service != null) { 579 service.destroySessionsLocked(); 580 service.updateLocked(disabled); 581 if (!service.isEnabledLocked()) { 582 removeCachedServiceLocked(userId); 583 } else { 584 addCompatibilityModeRequestsLocked(service, userId); 585 } 586 } 587 } 588 589 private void addCompatibilityModeRequestsLocked(@NonNull AutofillManagerServiceImpl service 590 , int userId) { 591 mAutofillCompatState.reset(userId); 592 final ArrayMap<String, Long> compatPackages = 593 service.getCompatibilityPackagesLocked(); 594 if (compatPackages == null || compatPackages.isEmpty()) { 595 return; 596 } 597 598 final Map<String, String[]> whiteListedPackages = getWhitelistedCompatModePackages(); 599 final int compatPackageCount = compatPackages.size(); 600 for (int i = 0; i < compatPackageCount; i++) { 601 final String packageName = compatPackages.keyAt(i); 602 if (whiteListedPackages == null || !whiteListedPackages.containsKey(packageName)) { 603 Slog.w(TAG, "Ignoring not whitelisted compat package " + packageName); 604 continue; 605 } 606 final Long maxVersionCode = compatPackages.valueAt(i); 607 if (maxVersionCode != null) { 608 mAutofillCompatState.addCompatibilityModeRequest(packageName, 609 maxVersionCode, whiteListedPackages.get(packageName), userId); 610 } 611 } 612 } 613 614 private String getWhitelistedCompatModePackagesFromSettings() { 615 return Settings.Global.getString( 616 mContext.getContentResolver(), 617 Settings.Global.AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES); 618 } 619 620 @Nullable 621 private Map<String, String[]> getWhitelistedCompatModePackages() { 622 return getWhitelistedCompatModePackages(getWhitelistedCompatModePackagesFromSettings()); 623 } 624 625 @Nullable 626 @VisibleForTesting 627 static Map<String, String[]> getWhitelistedCompatModePackages(String setting) { 628 if (TextUtils.isEmpty(setting)) { 629 return null; 630 } 631 632 final ArrayMap<String, String[]> compatPackages = new ArrayMap<>(); 633 final SimpleStringSplitter splitter = new SimpleStringSplitter(COMPAT_PACKAGE_DELIMITER); 634 splitter.setString(setting); 635 while (splitter.hasNext()) { 636 final String packageBlock = splitter.next(); 637 final int urlBlockIndex = packageBlock.indexOf(COMPAT_PACKAGE_URL_IDS_BLOCK_BEGIN); 638 final String packageName; 639 final List<String> urlBarIds; 640 if (urlBlockIndex == -1) { 641 packageName = packageBlock; 642 urlBarIds = null; 643 } else { 644 if (packageBlock.charAt(packageBlock.length() - 1) 645 != COMPAT_PACKAGE_URL_IDS_BLOCK_END) { 646 Slog.w(TAG, "Ignoring entry '" + packageBlock + "' on '" + setting 647 + "'because it does not end on '" + COMPAT_PACKAGE_URL_IDS_BLOCK_END + 648 "'"); 649 continue; 650 } 651 packageName = packageBlock.substring(0, urlBlockIndex); 652 urlBarIds = new ArrayList<>(); 653 final String urlBarIdsBlock = 654 packageBlock.substring(urlBlockIndex + 1, packageBlock.length() - 1); 655 if (sVerbose) { 656 Slog.v(TAG, "pkg:" + packageName + ": block:" + packageBlock + ": urls:" 657 + urlBarIds + ": block:" + urlBarIdsBlock + ":"); 658 } 659 final SimpleStringSplitter splitter2 = 660 new SimpleStringSplitter(COMPAT_PACKAGE_URL_IDS_DELIMITER); 661 splitter2.setString(urlBarIdsBlock); 662 while (splitter2.hasNext()) { 663 final String urlBarId = splitter2.next(); 664 urlBarIds.add(urlBarId); 665 } 666 } 667 if (urlBarIds == null) { 668 compatPackages.put(packageName, null); 669 } else { 670 final String[] urlBarIdsArray = new String[urlBarIds.size()]; 671 urlBarIds.toArray(urlBarIdsArray); 672 compatPackages.put(packageName, urlBarIdsArray); 673 } 674 } 675 return compatPackages; 676 } 677 678 private final class LocalService extends AutofillManagerInternal { 679 @Override 680 public void onBackKeyPressed() { 681 if (sDebug) Slog.d(TAG, "onBackKeyPressed()"); 682 mUi.hideAll(null); 683 } 684 685 @Override 686 public boolean isCompatibilityModeRequested(@NonNull String packageName, 687 long versionCode, @UserIdInt int userId) { 688 return mAutofillCompatState.isCompatibilityModeRequested( 689 packageName, versionCode, userId); 690 } 691 692 } 693 694 /** 695 * Compatibility mode metadata per package. 696 */ 697 static final class PackageCompatState { 698 private final long maxVersionCode; 699 private final String[] urlBarResourceIds; 700 701 PackageCompatState(long maxVersionCode, String[] urlBarResourceIds) { 702 this.maxVersionCode = maxVersionCode; 703 this.urlBarResourceIds = urlBarResourceIds; 704 } 705 706 @Override 707 public String toString() { 708 return "maxVersionCode=" + maxVersionCode 709 + ", urlBarResourceIds=" + Arrays.toString(urlBarResourceIds); 710 } 711 } 712 713 /** 714 * Compatibility mode metadata associated with all services. 715 * 716 * <p>This object is defined here instead of on each {@link AutofillManagerServiceImpl} because 717 * it cannot hold a lock on the main lock when 718 * {@link AutofillCompatState#isCompatibilityModeRequested(String, long, int)} is called by 719 * external services. 720 */ 721 static final class AutofillCompatState { 722 private final Object mLock = new Object(); 723 724 /** 725 * Map of app->compat_state per user. 726 */ 727 @GuardedBy("mLock") 728 private SparseArray<ArrayMap<String, PackageCompatState>> mUserSpecs; 729 730 boolean isCompatibilityModeRequested(@NonNull String packageName, 731 long versionCode, @UserIdInt int userId) { 732 synchronized (mLock) { 733 if (mUserSpecs == null) { 734 return false; 735 } 736 final ArrayMap<String, PackageCompatState> userSpec = mUserSpecs.get(userId); 737 if (userSpec == null) { 738 return false; 739 } 740 final PackageCompatState metadata = userSpec.get(packageName); 741 if (metadata == null) { 742 return false; 743 } 744 return versionCode <= metadata.maxVersionCode; 745 } 746 } 747 748 @Nullable 749 String[] getUrlBarResourceIds(@NonNull String packageName, @UserIdInt int userId) { 750 synchronized (mLock) { 751 if (mUserSpecs == null) { 752 return null; 753 } 754 final ArrayMap<String, PackageCompatState> userSpec = mUserSpecs.get(userId); 755 if (userSpec == null) { 756 return null; 757 } 758 final PackageCompatState metadata = userSpec.get(packageName); 759 if (metadata == null) { 760 return null; 761 } 762 return metadata.urlBarResourceIds; 763 } 764 } 765 766 void addCompatibilityModeRequest(@NonNull String packageName, 767 long versionCode, @Nullable String[] urlBarResourceIds, @UserIdInt int userId) { 768 synchronized (mLock) { 769 if (mUserSpecs == null) { 770 mUserSpecs = new SparseArray<>(); 771 } 772 ArrayMap<String, PackageCompatState> userSpec = mUserSpecs.get(userId); 773 if (userSpec == null) { 774 userSpec = new ArrayMap<>(); 775 mUserSpecs.put(userId, userSpec); 776 } 777 userSpec.put(packageName, 778 new PackageCompatState(versionCode, urlBarResourceIds)); 779 } 780 } 781 782 void removeCompatibilityModeRequests(@UserIdInt int userId) { 783 synchronized (mLock) { 784 if (mUserSpecs != null) { 785 mUserSpecs.remove(userId); 786 if (mUserSpecs.size() <= 0) { 787 mUserSpecs = null; 788 } 789 } 790 } 791 } 792 793 void reset(int userId) { 794 synchronized (mLock) { 795 if (mUserSpecs != null) { 796 mUserSpecs.delete(userId); 797 final int newSize = mUserSpecs.size(); 798 if (newSize == 0) { 799 if (sVerbose) Slog.v(TAG, "reseting mUserSpecs"); 800 mUserSpecs = null; 801 } else { 802 if (sVerbose) Slog.v(TAG, "mUserSpecs down to " + newSize); 803 } 804 } 805 } 806 } 807 808 private void dump(String prefix, PrintWriter pw) { 809 if (mUserSpecs == null) { 810 pw.println("N/A"); 811 return; 812 } 813 pw.println(); 814 final String prefix2 = prefix + " "; 815 for (int i = 0; i < mUserSpecs.size(); i++) { 816 final int user = mUserSpecs.keyAt(i); 817 pw.print(prefix); pw.print("User: "); pw.println(user); 818 final ArrayMap<String, PackageCompatState> perUser = mUserSpecs.valueAt(i); 819 for (int j = 0; j < perUser.size(); j++) { 820 final String packageName = perUser.keyAt(j); 821 final PackageCompatState state = perUser.valueAt(j); 822 pw.print(prefix2); pw.print(packageName); pw.print(": "); pw.println(state); 823 } 824 } 825 } 826 } 827 828 final class AutoFillManagerServiceStub extends IAutoFillManager.Stub { 829 @Override 830 public int addClient(IAutoFillManagerClient client, int userId) { 831 synchronized (mLock) { 832 int flags = 0; 833 if (getServiceForUserLocked(userId).addClientLocked(client)) { 834 flags |= AutofillManager.FLAG_ADD_CLIENT_ENABLED; 835 } 836 if (sDebug) { 837 flags |= AutofillManager.FLAG_ADD_CLIENT_DEBUG; 838 } 839 if (sVerbose) { 840 flags |= AutofillManager.FLAG_ADD_CLIENT_VERBOSE; 841 } 842 return flags; 843 } 844 } 845 846 @Override 847 public void removeClient(IAutoFillManagerClient client, int userId) { 848 synchronized (mLock) { 849 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 850 if (service != null) { 851 service.removeClientLocked(client); 852 } else if (sVerbose) { 853 Slog.v(TAG, "removeClient(): no service for " + userId); 854 } 855 } 856 } 857 858 @Override 859 public void setAuthenticationResult(Bundle data, int sessionId, int authenticationId, 860 int userId) { 861 synchronized (mLock) { 862 final AutofillManagerServiceImpl service = getServiceForUserLocked(userId); 863 service.setAuthenticationResultLocked(data, sessionId, authenticationId, 864 getCallingUid()); 865 } 866 } 867 868 @Override 869 public void setHasCallback(int sessionId, int userId, boolean hasIt) { 870 synchronized (mLock) { 871 final AutofillManagerServiceImpl service = getServiceForUserLocked(userId); 872 service.setHasCallback(sessionId, getCallingUid(), hasIt); 873 } 874 } 875 876 @Override 877 public int startSession(IBinder activityToken, IBinder appCallback, AutofillId autofillId, 878 Rect bounds, AutofillValue value, int userId, boolean hasCallback, int flags, 879 ComponentName componentName, boolean compatMode) { 880 881 activityToken = Preconditions.checkNotNull(activityToken, "activityToken"); 882 appCallback = Preconditions.checkNotNull(appCallback, "appCallback"); 883 autofillId = Preconditions.checkNotNull(autofillId, "autoFillId"); 884 componentName = Preconditions.checkNotNull(componentName, "componentName"); 885 final String packageName = Preconditions.checkNotNull(componentName.getPackageName()); 886 887 Preconditions.checkArgument(userId == UserHandle.getUserId(getCallingUid()), "userId"); 888 889 try { 890 mContext.getPackageManager().getPackageInfoAsUser(packageName, 0, userId); 891 } catch (PackageManager.NameNotFoundException e) { 892 throw new IllegalArgumentException(packageName + " is not a valid package", e); 893 } 894 895 synchronized (mLock) { 896 final AutofillManagerServiceImpl service = getServiceForUserLocked(userId); 897 return service.startSessionLocked(activityToken, getCallingUid(), appCallback, 898 autofillId, bounds, value, hasCallback, componentName, compatMode, 899 mAllowInstantService, flags); 900 } 901 } 902 903 @Override 904 public FillEventHistory getFillEventHistory() throws RemoteException { 905 final int userId = UserHandle.getCallingUserId(); 906 907 synchronized (mLock) { 908 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 909 if (service != null) { 910 return service.getFillEventHistory(getCallingUid()); 911 } else if (sVerbose) { 912 Slog.v(TAG, "getFillEventHistory(): no service for " + userId); 913 } 914 } 915 916 return null; 917 } 918 919 @Override 920 public UserData getUserData() throws RemoteException { 921 final int userId = UserHandle.getCallingUserId(); 922 923 synchronized (mLock) { 924 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 925 if (service != null) { 926 return service.getUserData(getCallingUid()); 927 } else if (sVerbose) { 928 Slog.v(TAG, "getUserData(): no service for " + userId); 929 } 930 } 931 932 return null; 933 } 934 935 @Override 936 public String getUserDataId() throws RemoteException { 937 final int userId = UserHandle.getCallingUserId(); 938 939 synchronized (mLock) { 940 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 941 if (service != null) { 942 final UserData userData = service.getUserData(getCallingUid()); 943 return userData == null ? null : userData.getId(); 944 } else if (sVerbose) { 945 Slog.v(TAG, "getUserDataId(): no service for " + userId); 946 } 947 } 948 949 return null; 950 } 951 952 @Override 953 public void setUserData(UserData userData) throws RemoteException { 954 final int userId = UserHandle.getCallingUserId(); 955 956 synchronized (mLock) { 957 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 958 if (service != null) { 959 service.setUserData(getCallingUid(), userData); 960 } else if (sVerbose) { 961 Slog.v(TAG, "setUserData(): no service for " + userId); 962 } 963 } 964 } 965 966 @Override 967 public boolean isFieldClassificationEnabled() throws RemoteException { 968 final int userId = UserHandle.getCallingUserId(); 969 970 synchronized (mLock) { 971 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 972 if (service != null) { 973 return service.isFieldClassificationEnabled(getCallingUid()); 974 } else if (sVerbose) { 975 Slog.v(TAG, "isFieldClassificationEnabled(): no service for " + userId); 976 } 977 } 978 979 return false; 980 } 981 982 @Override 983 public String getDefaultFieldClassificationAlgorithm() throws RemoteException { 984 final int userId = UserHandle.getCallingUserId(); 985 986 synchronized (mLock) { 987 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 988 if (service != null) { 989 return service.getDefaultFieldClassificationAlgorithm(getCallingUid()); 990 } else { 991 if (sVerbose) { 992 Slog.v(TAG, "getDefaultFcAlgorithm(): no service for " + userId); 993 } 994 return null; 995 } 996 } 997 } 998 999 @Override 1000 public String[] getAvailableFieldClassificationAlgorithms() throws RemoteException { 1001 final int userId = UserHandle.getCallingUserId(); 1002 1003 synchronized (mLock) { 1004 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 1005 if (service != null) { 1006 return service.getAvailableFieldClassificationAlgorithms(getCallingUid()); 1007 } else { 1008 if (sVerbose) { 1009 Slog.v(TAG, "getAvailableFcAlgorithms(): no service for " + userId); 1010 } 1011 return null; 1012 } 1013 } 1014 } 1015 1016 @Override 1017 public ComponentName getAutofillServiceComponentName() throws RemoteException { 1018 final int userId = UserHandle.getCallingUserId(); 1019 1020 synchronized (mLock) { 1021 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 1022 if (service != null) { 1023 return service.getServiceComponentName(); 1024 } else if (sVerbose) { 1025 Slog.v(TAG, "getAutofillServiceComponentName(): no service for " + userId); 1026 } 1027 } 1028 1029 return null; 1030 } 1031 1032 @Override 1033 public boolean restoreSession(int sessionId, IBinder activityToken, IBinder appCallback) 1034 throws RemoteException { 1035 final int userId = UserHandle.getCallingUserId(); 1036 activityToken = Preconditions.checkNotNull(activityToken, "activityToken"); 1037 appCallback = Preconditions.checkNotNull(appCallback, "appCallback"); 1038 1039 synchronized (mLock) { 1040 final AutofillManagerServiceImpl service = mServicesCache.get(userId); 1041 if (service != null) { 1042 return service.restoreSession(sessionId, getCallingUid(), activityToken, 1043 appCallback); 1044 } else if (sVerbose) { 1045 Slog.v(TAG, "restoreSession(): no service for " + userId); 1046 } 1047 } 1048 1049 return false; 1050 } 1051 1052 @Override 1053 public void updateSession(int sessionId, AutofillId autoFillId, Rect bounds, 1054 AutofillValue value, int action, int flags, int userId) { 1055 synchronized (mLock) { 1056 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 1057 if (service != null) { 1058 service.updateSessionLocked(sessionId, getCallingUid(), autoFillId, bounds, 1059 value, action, flags); 1060 } else if (sVerbose) { 1061 Slog.v(TAG, "updateSession(): no service for " + userId); 1062 } 1063 } 1064 } 1065 1066 @Override 1067 public int updateOrRestartSession(IBinder activityToken, IBinder appCallback, 1068 AutofillId autoFillId, Rect bounds, AutofillValue value, int userId, 1069 boolean hasCallback, int flags, ComponentName componentName, int sessionId, 1070 int action, boolean compatMode) { 1071 boolean restart = false; 1072 synchronized (mLock) { 1073 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 1074 if (service != null) { 1075 restart = service.updateSessionLocked(sessionId, getCallingUid(), autoFillId, 1076 bounds, value, action, flags); 1077 } else if (sVerbose) { 1078 Slog.v(TAG, "updateOrRestartSession(): no service for " + userId); 1079 } 1080 } 1081 if (restart) { 1082 return startSession(activityToken, appCallback, autoFillId, bounds, value, userId, 1083 hasCallback, flags, componentName, compatMode); 1084 } 1085 1086 // Nothing changed... 1087 return sessionId; 1088 } 1089 1090 @Override 1091 public void setAutofillFailure(int sessionId, @NonNull List<AutofillId> ids, int userId) { 1092 synchronized (mLock) { 1093 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 1094 if (service != null) { 1095 service.setAutofillFailureLocked(sessionId, getCallingUid(), ids); 1096 } else if (sVerbose) { 1097 Slog.v(TAG, "setAutofillFailure(): no service for " + userId); 1098 } 1099 } 1100 } 1101 1102 @Override 1103 public void finishSession(int sessionId, int userId) { 1104 synchronized (mLock) { 1105 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 1106 if (service != null) { 1107 service.finishSessionLocked(sessionId, getCallingUid()); 1108 } else if (sVerbose) { 1109 Slog.v(TAG, "finishSession(): no service for " + userId); 1110 } 1111 } 1112 } 1113 1114 @Override 1115 public void cancelSession(int sessionId, int userId) { 1116 synchronized (mLock) { 1117 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 1118 if (service != null) { 1119 service.cancelSessionLocked(sessionId, getCallingUid()); 1120 } else if (sVerbose) { 1121 Slog.v(TAG, "cancelSession(): no service for " + userId); 1122 } 1123 } 1124 } 1125 1126 @Override 1127 public void disableOwnedAutofillServices(int userId) { 1128 synchronized (mLock) { 1129 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 1130 if (service != null) { 1131 service.disableOwnedAutofillServicesLocked(Binder.getCallingUid()); 1132 } else if (sVerbose) { 1133 Slog.v(TAG, "cancelSession(): no service for " + userId); 1134 } 1135 } 1136 } 1137 1138 @Override 1139 public boolean isServiceSupported(int userId) { 1140 synchronized (mLock) { 1141 return !mDisabledUsers.get(userId); 1142 } 1143 } 1144 1145 @Override 1146 public boolean isServiceEnabled(int userId, String packageName) { 1147 synchronized (mLock) { 1148 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 1149 if (service != null) { 1150 return Objects.equals(packageName, service.getServicePackageName()); 1151 } else if (sVerbose) { 1152 Slog.v(TAG, "isServiceEnabled(): no service for " + userId); 1153 } 1154 return false; 1155 } 1156 } 1157 1158 @Override 1159 public void onPendingSaveUi(int operation, IBinder token) { 1160 Preconditions.checkNotNull(token, "token"); 1161 Preconditions.checkArgument(operation == AutofillManager.PENDING_UI_OPERATION_CANCEL 1162 || operation == AutofillManager.PENDING_UI_OPERATION_RESTORE, 1163 "invalid operation: %d", operation); 1164 synchronized (mLock) { 1165 final AutofillManagerServiceImpl service = peekServiceForUserLocked( 1166 UserHandle.getCallingUserId()); 1167 if (service != null) { 1168 service.onPendingSaveUi(operation, token); 1169 } 1170 } 1171 } 1172 1173 @Override 1174 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1175 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; 1176 1177 boolean showHistory = true; 1178 boolean uiOnly = false; 1179 if (args != null) { 1180 for (String arg : args) { 1181 switch(arg) { 1182 case "--no-history": 1183 showHistory = false; 1184 break; 1185 case "--ui-only": 1186 uiOnly = true; 1187 break; 1188 case "--help": 1189 pw.println("Usage: dumpsys autofill [--ui-only|--no-history]"); 1190 return; 1191 default: 1192 Slog.w(TAG, "Ignoring invalid dump arg: " + arg); 1193 } 1194 } 1195 } 1196 1197 if (uiOnly) { 1198 mUi.dump(pw); 1199 return; 1200 } 1201 1202 boolean oldDebug = sDebug; 1203 final String prefix = " "; 1204 final String prefix2 = " "; 1205 try { 1206 synchronized (mLock) { 1207 oldDebug = sDebug; 1208 setDebugLocked(true); 1209 pw.print("Debug mode: "); pw.println(oldDebug); 1210 pw.print("Verbose mode: "); pw.println(sVerbose); 1211 pw.print("Disabled users: "); pw.println(mDisabledUsers); 1212 pw.print("Max partitions per session: "); pw.println(sPartitionMaxCount); 1213 pw.print("Max visible datasets: "); pw.println(sVisibleDatasetsMaxCount); 1214 if (sFullScreenMode != null) { 1215 pw.print("Overridden full-screen mode: "); pw.println(sFullScreenMode); 1216 } 1217 pw.println("User data constraints: "); UserData.dumpConstraints(prefix, pw); 1218 final int size = mServicesCache.size(); 1219 pw.print("Cached services: "); 1220 if (size == 0) { 1221 pw.println("none"); 1222 } else { 1223 pw.println(size); 1224 for (int i = 0; i < size; i++) { 1225 pw.print("\nService at index "); pw.println(i); 1226 final AutofillManagerServiceImpl impl = mServicesCache.valueAt(i); 1227 impl.dumpLocked(prefix, pw); 1228 } 1229 } 1230 mUi.dump(pw); 1231 pw.print("Autofill Compat State: "); 1232 mAutofillCompatState.dump(prefix2, pw); 1233 pw.print(prefix2); pw.print("from settings: "); 1234 pw.println(getWhitelistedCompatModePackagesFromSettings()); 1235 pw.print("Allow instant service: "); pw.println(mAllowInstantService); 1236 } 1237 if (showHistory) { 1238 pw.println(); pw.println("Requests history:"); pw.println(); 1239 mRequestsHistory.reverseDump(fd, pw, args); 1240 pw.println(); pw.println("UI latency history:"); pw.println(); 1241 mUiLatencyHistory.reverseDump(fd, pw, args); 1242 pw.println(); pw.println("WTF history:"); pw.println(); 1243 mWtfHistory.reverseDump(fd, pw, args); 1244 } 1245 } finally { 1246 setDebugLocked(oldDebug); 1247 } 1248 } 1249 1250 @Override 1251 public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, 1252 String[] args, ShellCallback callback, ResultReceiver resultReceiver) { 1253 (new AutofillManagerServiceShellCommand(AutofillManagerService.this)).exec( 1254 this, in, out, err, args, callback, resultReceiver); 1255 } 1256 } 1257 1258 private final class SettingsObserver extends ContentObserver { 1259 SettingsObserver(Handler handler) { 1260 super(handler); 1261 ContentResolver resolver = mContext.getContentResolver(); 1262 resolver.registerContentObserver(Settings.Secure.getUriFor( 1263 Settings.Secure.AUTOFILL_SERVICE), false, this, UserHandle.USER_ALL); 1264 resolver.registerContentObserver(Settings.Secure.getUriFor( 1265 Settings.Secure.USER_SETUP_COMPLETE), false, this, UserHandle.USER_ALL); 1266 resolver.registerContentObserver(Settings.Global.getUriFor( 1267 Settings.Global.AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES), false, this, 1268 UserHandle.USER_ALL); 1269 } 1270 1271 @Override 1272 public void onChange(boolean selfChange, Uri uri, int userId) { 1273 if (sVerbose) Slog.v(TAG, "onChange(): uri=" + uri + ", userId=" + userId); 1274 synchronized (mLock) { 1275 updateCachedServiceLocked(userId); 1276 } 1277 } 1278 } 1279 } 1280