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 import static android.service.autofill.Flags.fixGetAutofillComponent; 22 import static android.view.autofill.AutofillManager.MAX_TEMP_AUGMENTED_SERVICE_DURATION_MS; 23 import static android.view.autofill.AutofillManager.getSmartSuggestionModeToString; 24 25 import static com.android.server.autofill.Helper.sDebug; 26 import static com.android.server.autofill.Helper.sFullScreenMode; 27 import static com.android.server.autofill.Helper.sVerbose; 28 29 import static java.util.Objects.requireNonNull; 30 31 import android.annotation.NonNull; 32 import android.annotation.Nullable; 33 import android.annotation.UserIdInt; 34 import android.app.ActivityManagerInternal; 35 import android.app.ActivityThread; 36 import android.content.AutofillOptions; 37 import android.content.BroadcastReceiver; 38 import android.content.ComponentName; 39 import android.content.ContentResolver; 40 import android.content.Context; 41 import android.content.Intent; 42 import android.content.IntentFilter; 43 import android.content.pm.PackageManager; 44 import android.content.pm.UserInfo; 45 import android.database.ContentObserver; 46 import android.graphics.Rect; 47 import android.os.Binder; 48 import android.os.Build; 49 import android.os.Bundle; 50 import android.os.IBinder; 51 import android.os.Parcelable; 52 import android.os.RemoteCallback; 53 import android.os.RemoteException; 54 import android.os.ResultReceiver; 55 import android.os.ShellCallback; 56 import android.os.SystemClock; 57 import android.os.UserHandle; 58 import android.os.UserManager; 59 import android.provider.DeviceConfig; 60 import android.provider.Settings; 61 import android.service.autofill.FillEventHistory; 62 import android.service.autofill.Flags; 63 import android.service.autofill.UserData; 64 import android.text.TextUtils; 65 import android.text.TextUtils.SimpleStringSplitter; 66 import android.util.ArrayMap; 67 import android.util.LocalLog; 68 import android.util.Log; 69 import android.util.Slog; 70 import android.util.SparseArray; 71 import android.util.SparseBooleanArray; 72 import android.util.TimeUtils; 73 import android.view.autofill.AutofillFeatureFlags; 74 import android.view.autofill.AutofillId; 75 import android.view.autofill.AutofillManager; 76 import android.view.autofill.AutofillManager.AutofillCommitReason; 77 import android.view.autofill.AutofillManager.SmartSuggestionMode; 78 import android.view.autofill.AutofillManagerInternal; 79 import android.view.autofill.AutofillValue; 80 import android.view.autofill.IAutoFillManager; 81 import android.view.autofill.IAutoFillManagerClient; 82 83 import com.android.internal.R; 84 import com.android.internal.annotations.GuardedBy; 85 import com.android.internal.annotations.VisibleForTesting; 86 import com.android.internal.infra.AbstractRemoteService; 87 import com.android.internal.infra.GlobalWhitelistState; 88 import com.android.internal.infra.WhitelistHelper; 89 import com.android.internal.os.IResultReceiver; 90 import com.android.internal.util.DumpUtils; 91 import com.android.internal.util.Preconditions; 92 import com.android.internal.util.SyncResultReceiver; 93 import com.android.server.FgThread; 94 import com.android.server.LocalServices; 95 import com.android.server.autofill.ui.AutoFillUI; 96 import com.android.server.infra.AbstractMasterSystemService; 97 import com.android.server.infra.FrameworkResourcesServiceNameResolver; 98 import com.android.server.infra.SecureSettingsServiceNameResolver; 99 100 import java.io.FileDescriptor; 101 import java.io.PrintWriter; 102 import java.util.ArrayList; 103 import java.util.Arrays; 104 import java.util.List; 105 import java.util.Map; 106 import java.util.Objects; 107 import java.util.Set; 108 109 /** 110 * Entry point service for autofill management. 111 * 112 * <p>This service provides the {@link IAutoFillManager} implementation and keeps a list of 113 * {@link AutofillManagerServiceImpl} per user; the real work is done by 114 * {@link AutofillManagerServiceImpl} itself. 115 */ 116 public final class AutofillManagerService 117 extends AbstractMasterSystemService<AutofillManagerService, AutofillManagerServiceImpl> { 118 119 private static final String TAG = "AutofillManagerService"; 120 121 private static final Object sLock = AutofillManagerService.class; 122 123 static final String RECEIVER_BUNDLE_EXTRA_SESSIONS = "sessions"; 124 125 private static final char COMPAT_PACKAGE_DELIMITER = ':'; 126 private static final char COMPAT_PACKAGE_URL_IDS_DELIMITER = ','; 127 private static final char COMPAT_PACKAGE_URL_IDS_BLOCK_BEGIN = '['; 128 private static final char COMPAT_PACKAGE_URL_IDS_BLOCK_END = ']'; 129 130 private static final int DEFAULT_AUGMENTED_AUTOFILL_REQUEST_TIMEOUT_MILLIS = 5_000; 131 132 /** 133 * Maximum number of partitions that can be allowed in a session. 134 * 135 * <p>Can be modified using {@code cmd autofill set max_partitions} or through 136 * {@link android.provider.Settings.Global#AUTOFILL_MAX_PARTITIONS_SIZE}. 137 */ 138 @GuardedBy("sLock") 139 private static int sPartitionMaxCount = AutofillManager.DEFAULT_MAX_PARTITIONS_SIZE; 140 141 /** 142 * Maximum number of visible datasets in the dataset picker UI, or {@code 0} to use default 143 * value from resources. 144 * 145 * <p>Can be modified using {@code cmd autofill set max_visible_datasets} or through 146 * {@link android.provider.Settings.Global#AUTOFILL_MAX_VISIBLE_DATASETS}. 147 */ 148 @GuardedBy("sLock") 149 private static int sVisibleDatasetsMaxCount = 0; 150 151 /** 152 * Object used to set the name of the augmented autofill service. 153 */ 154 @NonNull 155 final FrameworkResourcesServiceNameResolver mAugmentedAutofillResolver; 156 157 /** 158 * Object used to set the name of the field classification service. 159 */ 160 @NonNull 161 final FrameworkResourcesServiceNameResolver mFieldClassificationResolver; 162 163 private final AutoFillUI mUi; 164 final ComponentName mCredentialAutofillService; 165 166 private final LocalLog mRequestsHistory = new LocalLog(20); 167 private final LocalLog mUiLatencyHistory = new LocalLog(20); 168 private final LocalLog mWtfHistory = new LocalLog(50); 169 170 private final AutofillCompatState mAutofillCompatState = new AutofillCompatState(); 171 private final DisabledInfoCache mDisabledInfoCache = new DisabledInfoCache(); 172 173 private final LocalService mLocalService = new LocalService(); 174 private final ActivityManagerInternal mAm; 175 176 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 177 @Override 178 public void onReceive(Context context, Intent intent) { 179 if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) { 180 if (sDebug) Slog.d(TAG, "Close system dialogs"); 181 182 // TODO(b/64940307): we need to destroy all sessions that are finished but showing 183 // Save UI because there is no way to show the Save UI back when the activity 184 // beneath it is brought back to top. Ideally, we should just hide the UI and 185 // bring it back when the activity resumes. 186 synchronized (mLock) { 187 visitServicesLocked((s) -> s.forceRemoveFinishedSessionsLocked()); 188 } 189 mUi.hideAll(null); 190 } 191 } 192 }; 193 194 /** 195 * Supported modes for Augmented Autofill Smart Suggestions. 196 */ 197 @GuardedBy("mLock") 198 private int mSupportedSmartSuggestionModes; 199 200 @GuardedBy("mLock") 201 int mAugmentedServiceIdleUnbindTimeoutMs; 202 @GuardedBy("mLock") 203 int mAugmentedServiceRequestTimeoutMs; 204 205 final AugmentedAutofillState mAugmentedAutofillState = new AugmentedAutofillState(); 206 207 /** 208 * Lock used to synchronize access to the flags. 209 * DO NOT USE ANY OTHER LOCK while holding this lock. 210 * NOTE: This lock should only be used for accessing flags. It should never call into other 211 * methods holding another lock. It can lead to potential deadlock if it calls into a method 212 * holding mLock. 213 */ 214 private final Object mFlagLock = new Object(); 215 216 // Flag holders for Autofill PCC classification 217 218 @GuardedBy("mFlagLock") 219 private boolean mPccClassificationEnabled; 220 221 @GuardedBy("mFlagLock") 222 private boolean mPccPreferProviderOverPcc; 223 224 @GuardedBy("mFlagLock") 225 private boolean mPccUseFallbackDetection; 226 227 @GuardedBy("mFlagLock") 228 private String mPccProviderHints; 229 230 @GuardedBy("mFlagLock") 231 private int mMaxInputLengthForAutofill; 232 233 @GuardedBy("mFlagLock") 234 private boolean mAutofillCredmanIntegrationEnabled; 235 236 @GuardedBy("mFlagLock") 237 private boolean mIsFillFieldsFromCurrentSessionOnly; 238 239 // Default flag values for Autofill PCC 240 241 private static final String DEFAULT_PCC_FEATURE_PROVIDER_HINTS = ""; 242 private static final boolean DEFAULT_PREFER_PROVIDER_OVER_PCC = true; 243 244 private static final boolean DEFAULT_PCC_USE_FALLBACK = true; 245 AutofillManagerService(Context context)246 public AutofillManagerService(Context context) { 247 super(context, 248 new SecureSettingsServiceNameResolver(context, Settings.Secure.AUTOFILL_SERVICE), 249 UserManager.DISALLOW_AUTOFILL, PACKAGE_UPDATE_POLICY_REFRESH_EAGER); 250 mUi = new AutoFillUI(ActivityThread.currentActivityThread().getSystemUiContext()); 251 mAm = LocalServices.getService(ActivityManagerInternal.class); 252 253 DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_AUTOFILL, 254 ActivityThread.currentApplication().getMainExecutor(), 255 (properties) -> onDeviceConfigChange(properties.getKeyset())); 256 257 setLogLevelFromSettings(); 258 setMaxPartitionsFromSettings(); 259 setMaxVisibleDatasetsFromSettings(); 260 setDeviceConfigProperties(); 261 262 final IntentFilter filter = new IntentFilter(); 263 filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); 264 context.registerReceiver(mBroadcastReceiver, filter, null, FgThread.getHandler(), 265 Context.RECEIVER_EXPORTED); 266 267 mAugmentedAutofillResolver = new FrameworkResourcesServiceNameResolver(getContext(), 268 com.android.internal.R.string.config_defaultAugmentedAutofillService); 269 mAugmentedAutofillResolver.setOnTemporaryServiceNameChangedCallback( 270 (u, s, t) -> onAugmentedServiceNameChanged(u, s, t)); 271 272 mFieldClassificationResolver = new FrameworkResourcesServiceNameResolver(getContext(), 273 com.android.internal.R.string.config_defaultFieldClassificationService); 274 if (sVerbose) { 275 Slog.v(TAG, "Resolving FieldClassificationService to serviceName: " 276 + mFieldClassificationResolver.readServiceName(0)); 277 } 278 mFieldClassificationResolver.setOnTemporaryServiceNameChangedCallback( 279 (u, s, t) -> onFieldClassificationServiceNameChanged(u, s, t)); 280 281 if (mSupportedSmartSuggestionModes != AutofillManager.FLAG_SMART_SUGGESTION_OFF) { 282 final List<UserInfo> users = getSupportedUsers(); 283 for (int i = 0; i < users.size(); i++) { 284 final int userId = users.get(i).id; 285 // Must eager load the services so they bind to the augmented autofill service 286 getServiceForUserLocked(userId); 287 288 // And also set the global state 289 mAugmentedAutofillState.setServiceInfo(userId, 290 mAugmentedAutofillResolver.getServiceName(userId), 291 mAugmentedAutofillResolver.isTemporary(userId)); 292 } 293 } 294 String credentialManagerAutofillCompName = context.getResources().getString( 295 R.string.config_defaultCredentialManagerAutofillService); 296 if (credentialManagerAutofillCompName != null 297 && !credentialManagerAutofillCompName.isEmpty()) { 298 mCredentialAutofillService = ComponentName.unflattenFromString( 299 credentialManagerAutofillCompName); 300 } else { 301 mCredentialAutofillService = null; 302 Slog.w(TAG, "Invalid CredentialAutofillService"); 303 } 304 } 305 306 @Override // from AbstractMasterSystemService getServiceSettingsProperty()307 protected String getServiceSettingsProperty() { 308 return Settings.Secure.AUTOFILL_SERVICE; 309 } 310 311 @Override // from AbstractMasterSystemService registerForExtraSettingsChanges(@onNull ContentResolver resolver, @NonNull ContentObserver observer)312 protected void registerForExtraSettingsChanges(@NonNull ContentResolver resolver, 313 @NonNull ContentObserver observer) { 314 resolver.registerContentObserver(Settings.Global.getUriFor( 315 Settings.Global.AUTOFILL_LOGGING_LEVEL), false, observer, 316 UserHandle.USER_ALL); 317 resolver.registerContentObserver(Settings.Global.getUriFor( 318 Settings.Global.AUTOFILL_MAX_PARTITIONS_SIZE), false, observer, 319 UserHandle.USER_ALL); 320 resolver.registerContentObserver(Settings.Global.getUriFor( 321 Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS), false, observer, 322 UserHandle.USER_ALL); 323 resolver.registerContentObserver(Settings.Secure.getUriFor( 324 Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE), false, observer, 325 UserHandle.USER_ALL); 326 } 327 328 @Override // from AbstractMasterSystemService onSettingsChanged(int userId, @NonNull String property)329 protected void onSettingsChanged(int userId, @NonNull String property) { 330 switch (property) { 331 case Settings.Global.AUTOFILL_LOGGING_LEVEL: 332 setLogLevelFromSettings(); 333 break; 334 case Settings.Global.AUTOFILL_MAX_PARTITIONS_SIZE: 335 setMaxPartitionsFromSettings(); 336 break; 337 case Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS: 338 setMaxVisibleDatasetsFromSettings(); 339 break; 340 case Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE: 341 handleInputMethodSwitch(userId); 342 break; 343 default: 344 Slog.w(TAG, "Unexpected property (" + property + "); updating cache instead"); 345 synchronized (mLock) { 346 updateCachedServiceLocked(userId); 347 } 348 } 349 } 350 handleInputMethodSwitch(@serIdInt int userId)351 private void handleInputMethodSwitch(@UserIdInt int userId) { 352 // TODO(b/156903336): Used the SettingsObserver with a background thread maybe slow to 353 // respond to the IME switch in certain situations. 354 // See: services/core/java/com/android/server/FgThread.java 355 // In particular, the shared background thread could be doing relatively long-running 356 // operations like saving state to disk (in addition to simply being a background priority), 357 // which can cause operations scheduled on it to be delayed for a user-noticeable amount 358 // of time. 359 360 synchronized (mLock) { 361 final AutofillManagerServiceImpl service = 362 peekServiceForUserWithLocalBinderIdentityLocked(userId); 363 if (service != null) { 364 service.onSwitchInputMethod(); 365 } 366 } 367 } 368 onDeviceConfigChange(@onNull Set<String> keys)369 private void onDeviceConfigChange(@NonNull Set<String> keys) { 370 for (String key : keys) { 371 switch (key) { 372 case AutofillFeatureFlags.DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES: 373 case AutofillFeatureFlags.DEVICE_CONFIG_AUGMENTED_SERVICE_IDLE_UNBIND_TIMEOUT: 374 case AutofillFeatureFlags.DEVICE_CONFIG_AUGMENTED_SERVICE_REQUEST_TIMEOUT: 375 case AutofillFeatureFlags.DEVICE_CONFIG_AUTOFILL_PCC_CLASSIFICATION_ENABLED: 376 case AutofillFeatureFlags.DEVICE_CONFIG_AUTOFILL_PCC_FEATURE_PROVIDER_HINTS: 377 case AutofillFeatureFlags.DEVICE_CONFIG_PREFER_PROVIDER_OVER_PCC: 378 case AutofillFeatureFlags.DEVICE_CONFIG_PCC_USE_FALLBACK: 379 case AutofillFeatureFlags.DEVICE_CONFIG_FILL_FIELDS_FROM_CURRENT_SESSION_ONLY: 380 case Flags.FLAG_AUTOFILL_CREDMAN_INTEGRATION: 381 setDeviceConfigProperties(); 382 break; 383 case AutofillFeatureFlags.DEVICE_CONFIG_AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES: 384 updateCachedServices(); 385 break; 386 default: 387 Slog.i(mTag, "Ignoring change on " + key); 388 } 389 } 390 } 391 onAugmentedServiceNameChanged(@serIdInt int userId, @Nullable String serviceName, boolean isTemporary)392 private void onAugmentedServiceNameChanged(@UserIdInt int userId, @Nullable String serviceName, 393 boolean isTemporary) { 394 mAugmentedAutofillState.setServiceInfo(userId, serviceName, isTemporary); 395 synchronized (mLock) { 396 final AutofillManagerServiceImpl service = 397 peekServiceForUserWithLocalBinderIdentityLocked(userId); 398 if (service == null) { 399 // If we cannot get the service from the services cache, it will call 400 // updateRemoteAugmentedAutofillService() finally. Skip call this update again. 401 getServiceForUserWithLocalBinderIdentityLocked(userId); 402 } else { 403 service.updateRemoteAugmentedAutofillService(); 404 } 405 } 406 } 407 onFieldClassificationServiceNameChanged( @serIdInt int userId, @Nullable String serviceName, boolean isTemporary)408 private void onFieldClassificationServiceNameChanged( 409 @UserIdInt int userId, @Nullable String serviceName, boolean isTemporary) { 410 synchronized (mLock) { 411 final AutofillManagerServiceImpl service = 412 peekServiceForUserWithLocalBinderIdentityLocked(userId); 413 if (service == null) { 414 // If we cannot get the service from the services cache, it will call 415 // updateRemoteFieldClassificationService() finally. Skip call this update again. 416 getServiceForUserWithLocalBinderIdentityLocked(userId); 417 } else { 418 service.updateRemoteFieldClassificationService(); 419 } 420 } 421 } 422 423 @GuardedBy("mLock") 424 @Nullable getServiceForUserWithLocalBinderIdentityLocked(int userId)425 private AutofillManagerServiceImpl getServiceForUserWithLocalBinderIdentityLocked(int userId) { 426 final long token = Binder.clearCallingIdentity(); 427 try { 428 return getServiceForUserLocked(userId); 429 } finally { 430 Binder.restoreCallingIdentity(token); 431 } 432 } 433 434 @GuardedBy("mLock") 435 @Nullable peekServiceForUserWithLocalBinderIdentityLocked(int userId)436 private AutofillManagerServiceImpl peekServiceForUserWithLocalBinderIdentityLocked(int userId) { 437 final long token = Binder.clearCallingIdentity(); 438 try { 439 return peekServiceForUserLocked(userId); 440 } finally { 441 Binder.restoreCallingIdentity(token); 442 } 443 } 444 445 @Override // from AbstractMasterSystemService newServiceLocked(@serIdInt int resolvedUserId, boolean disabled)446 protected AutofillManagerServiceImpl newServiceLocked(@UserIdInt int resolvedUserId, 447 boolean disabled) { 448 return new AutofillManagerServiceImpl(this, mLock, mUiLatencyHistory, mWtfHistory, 449 resolvedUserId, mUi, mAutofillCompatState, disabled, mDisabledInfoCache); 450 } 451 452 @Override // AbstractMasterSystemService onServiceRemoved(@onNull AutofillManagerServiceImpl service, @UserIdInt int userId)453 protected void onServiceRemoved(@NonNull AutofillManagerServiceImpl service, 454 @UserIdInt int userId) { 455 service.destroyLocked(); 456 mDisabledInfoCache.remove(userId); 457 mAutofillCompatState.removeCompatibilityModeRequests(userId); 458 } 459 460 @Override // from AbstractMasterSystemService onServiceEnabledLocked(@onNull AutofillManagerServiceImpl service, @UserIdInt int userId)461 protected void onServiceEnabledLocked(@NonNull AutofillManagerServiceImpl service, 462 @UserIdInt int userId) { 463 addCompatibilityModeRequestsLocked(service, userId); 464 } 465 466 @Override // from AbstractMasterSystemService enforceCallingPermissionForManagement()467 protected void enforceCallingPermissionForManagement() { 468 getContext().enforceCallingPermission(MANAGE_AUTO_FILL, TAG); 469 } 470 471 @Override // from SystemService onStart()472 public void onStart() { 473 publishBinderService(AUTOFILL_MANAGER_SERVICE, new AutoFillManagerServiceStub()); 474 publishLocalService(AutofillManagerInternal.class, mLocalService); 475 } 476 477 @Override // from SystemService isUserSupported(TargetUser user)478 public boolean isUserSupported(TargetUser user) { 479 return user.isFull() || user.isProfile(); 480 } 481 482 @Override // from SystemService onUserSwitching(@ullable TargetUser from, @NonNull TargetUser to)483 public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) { 484 if (sDebug) Slog.d(TAG, "Hiding UI when user switched"); 485 mUi.hideAll(null); 486 } 487 getSupportedSmartSuggestionModesLocked()488 @SmartSuggestionMode int getSupportedSmartSuggestionModesLocked() { 489 return mSupportedSmartSuggestionModes; 490 } 491 492 /** 493 * Logs a request so it's dumped later... 494 */ logRequestLocked(@onNull String historyItem)495 void logRequestLocked(@NonNull String historyItem) { 496 mRequestsHistory.log(historyItem); 497 } 498 499 // Called by AutofillManagerServiceImpl, doesn't need to check permission isInstantServiceAllowed()500 boolean isInstantServiceAllowed() { 501 return mAllowInstantService; 502 } 503 504 // Called by Shell command. removeAllSessions(@serIdInt int userId, IResultReceiver receiver)505 void removeAllSessions(@UserIdInt int userId, IResultReceiver receiver) { 506 Slog.i(TAG, "removeAllSessions() for userId " + userId); 507 enforceCallingPermissionForManagement(); 508 509 synchronized (mLock) { 510 if (userId != UserHandle.USER_ALL) { 511 AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 512 if (service != null) { 513 service.forceRemoveAllSessionsLocked(); 514 } 515 } else { 516 visitServicesLocked((s) -> s.forceRemoveAllSessionsLocked()); 517 } 518 } 519 520 try { 521 receiver.send(0, new Bundle()); 522 } catch (RemoteException e) { 523 // Just ignore it... 524 } 525 } 526 527 // Called by Shell command. listSessions(int userId, IResultReceiver receiver)528 void listSessions(int userId, IResultReceiver receiver) { 529 Slog.i(TAG, "listSessions() for userId " + userId); 530 enforceCallingPermissionForManagement(); 531 532 final Bundle resultData = new Bundle(); 533 final ArrayList<String> sessions = new ArrayList<>(); 534 535 synchronized (mLock) { 536 if (userId != UserHandle.USER_ALL) { 537 AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 538 if (service != null) { 539 service.listSessionsLocked(sessions); 540 } 541 } else { 542 visitServicesLocked((s) -> s.listSessionsLocked(sessions)); 543 } 544 } 545 546 resultData.putStringArrayList(RECEIVER_BUNDLE_EXTRA_SESSIONS, sessions); 547 try { 548 receiver.send(0, resultData); 549 } catch (RemoteException e) { 550 // Just ignore it... 551 } 552 } 553 554 // Called by Shell command. reset()555 void reset() { 556 Slog.i(TAG, "reset()"); 557 enforceCallingPermissionForManagement(); 558 559 synchronized (mLock) { 560 visitServicesLocked((s) -> s.destroyLocked()); 561 clearCacheLocked(); 562 } 563 } 564 565 // Called by Shell command. setLogLevel(int level)566 void setLogLevel(int level) { 567 Slog.i(TAG, "setLogLevel(): " + level); 568 enforceCallingPermissionForManagement(); 569 570 final long token = Binder.clearCallingIdentity(); 571 try { 572 Settings.Global.putInt(getContext().getContentResolver(), 573 Settings.Global.AUTOFILL_LOGGING_LEVEL, level); 574 } finally { 575 Binder.restoreCallingIdentity(token); 576 } 577 } 578 setLogLevelFromSettings()579 private void setLogLevelFromSettings() { 580 final int level = Settings.Global.getInt( 581 getContext().getContentResolver(), 582 Settings.Global.AUTOFILL_LOGGING_LEVEL, AutofillManager.DEFAULT_LOGGING_LEVEL); 583 boolean debug = false; 584 boolean verbose = false; 585 if (level != AutofillManager.NO_LOGGING) { 586 if (level == AutofillManager.FLAG_ADD_CLIENT_VERBOSE) { 587 debug = verbose = true; 588 } else if (level == AutofillManager.FLAG_ADD_CLIENT_DEBUG) { 589 debug = true; 590 } else { 591 Slog.w(TAG, "setLogLevelFromSettings(): invalid level: " + level); 592 } 593 } 594 if (debug || sDebug) { 595 Slog.d(TAG, "setLogLevelFromSettings(): level=" + level + ", debug=" + debug 596 + ", verbose=" + verbose); 597 } 598 synchronized (mLock) { 599 setLoggingLevelsLocked(debug, verbose); 600 } 601 } 602 603 // Called by Shell command. getLogLevel()604 int getLogLevel() { 605 enforceCallingPermissionForManagement(); 606 607 synchronized (mLock) { 608 if (sVerbose) return AutofillManager.FLAG_ADD_CLIENT_VERBOSE; 609 if (sDebug) return AutofillManager.FLAG_ADD_CLIENT_DEBUG; 610 return 0; 611 } 612 } 613 614 // Called by Shell command. getMaxPartitions()615 int getMaxPartitions() { 616 synchronized (mLock) { 617 return sPartitionMaxCount; 618 } 619 } 620 621 // Called by Shell command. setMaxPartitions(int max)622 void setMaxPartitions(int max) { 623 Slog.i(TAG, "setMaxPartitions(): " + max); 624 enforceCallingPermissionForManagement(); 625 626 final long token = Binder.clearCallingIdentity(); 627 try { 628 Settings.Global.putInt(getContext().getContentResolver(), 629 Settings.Global.AUTOFILL_MAX_PARTITIONS_SIZE, max); 630 } finally { 631 Binder.restoreCallingIdentity(token); 632 } 633 } 634 setMaxPartitionsFromSettings()635 private void setMaxPartitionsFromSettings() { 636 final int max = Settings.Global.getInt(getContext().getContentResolver(), 637 Settings.Global.AUTOFILL_MAX_PARTITIONS_SIZE, 638 AutofillManager.DEFAULT_MAX_PARTITIONS_SIZE); 639 if (sDebug) Slog.d(TAG, "setMaxPartitionsFromSettings(): " + max); 640 641 synchronized (sLock) { 642 sPartitionMaxCount = max; 643 } 644 } 645 646 // Called by Shell command. getMaxVisibleDatasets()647 int getMaxVisibleDatasets() { 648 synchronized (sLock) { 649 return sVisibleDatasetsMaxCount; 650 } 651 } 652 653 // Called by Shell command. setMaxVisibleDatasets(int max)654 void setMaxVisibleDatasets(int max) { 655 Slog.i(TAG, "setMaxVisibleDatasets(): " + max); 656 enforceCallingPermissionForManagement(); 657 658 final long token = Binder.clearCallingIdentity(); 659 try { 660 Settings.Global.putInt(getContext().getContentResolver(), 661 Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS, max); 662 } finally { 663 Binder.restoreCallingIdentity(token); 664 } 665 } 666 setMaxVisibleDatasetsFromSettings()667 private void setMaxVisibleDatasetsFromSettings() { 668 final int max = Settings.Global.getInt(getContext().getContentResolver(), 669 Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS, 0); 670 671 if (sDebug) Slog.d(TAG, "setMaxVisibleDatasetsFromSettings(): " + max); 672 synchronized (sLock) { 673 sVisibleDatasetsMaxCount = max; 674 } 675 } 676 setDeviceConfigProperties()677 private void setDeviceConfigProperties() { 678 synchronized (mLock) { 679 mAugmentedServiceIdleUnbindTimeoutMs = DeviceConfig.getInt( 680 DeviceConfig.NAMESPACE_AUTOFILL, 681 AutofillFeatureFlags.DEVICE_CONFIG_AUGMENTED_SERVICE_IDLE_UNBIND_TIMEOUT, 682 (int) AbstractRemoteService.PERMANENT_BOUND_TIMEOUT_MS); 683 mAugmentedServiceRequestTimeoutMs = DeviceConfig.getInt( 684 DeviceConfig.NAMESPACE_AUTOFILL, 685 AutofillFeatureFlags.DEVICE_CONFIG_AUGMENTED_SERVICE_REQUEST_TIMEOUT, 686 DEFAULT_AUGMENTED_AUTOFILL_REQUEST_TIMEOUT_MILLIS); 687 mSupportedSmartSuggestionModes = DeviceConfig.getInt( 688 DeviceConfig.NAMESPACE_AUTOFILL, 689 AutofillFeatureFlags.DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES, 690 AutofillManager.FLAG_SMART_SUGGESTION_SYSTEM); 691 if (verbose) { 692 Slog.v(mTag, "setDeviceConfigProperties() for AugmentedAutofill: " 693 + "augmentedIdleTimeout=" + mAugmentedServiceIdleUnbindTimeoutMs 694 + ", augmentedRequestTimeout=" + mAugmentedServiceRequestTimeoutMs 695 + ", smartSuggestionMode=" 696 + getSmartSuggestionModeToString(mSupportedSmartSuggestionModes)); 697 } 698 } 699 synchronized (mFlagLock) { 700 mPccClassificationEnabled = DeviceConfig.getBoolean( 701 DeviceConfig.NAMESPACE_AUTOFILL, 702 AutofillFeatureFlags.DEVICE_CONFIG_AUTOFILL_PCC_CLASSIFICATION_ENABLED, 703 AutofillFeatureFlags.DEFAULT_AUTOFILL_PCC_CLASSIFICATION_ENABLED); 704 mPccPreferProviderOverPcc = DeviceConfig.getBoolean( 705 DeviceConfig.NAMESPACE_AUTOFILL, 706 AutofillFeatureFlags.DEVICE_CONFIG_PREFER_PROVIDER_OVER_PCC, 707 DEFAULT_PREFER_PROVIDER_OVER_PCC); 708 mPccUseFallbackDetection = DeviceConfig.getBoolean( 709 DeviceConfig.NAMESPACE_AUTOFILL, 710 AutofillFeatureFlags.DEVICE_CONFIG_PCC_USE_FALLBACK, 711 DEFAULT_PCC_USE_FALLBACK); 712 mPccProviderHints = DeviceConfig.getString( 713 DeviceConfig.NAMESPACE_AUTOFILL, 714 AutofillFeatureFlags.DEVICE_CONFIG_AUTOFILL_PCC_FEATURE_PROVIDER_HINTS, 715 DEFAULT_PCC_FEATURE_PROVIDER_HINTS); 716 mMaxInputLengthForAutofill = DeviceConfig.getInt( 717 DeviceConfig.NAMESPACE_AUTOFILL, 718 AutofillFeatureFlags.DEVICE_CONFIG_MAX_INPUT_LENGTH_FOR_AUTOFILL, 719 AutofillFeatureFlags.DEFAULT_MAX_INPUT_LENGTH_FOR_AUTOFILL); 720 mAutofillCredmanIntegrationEnabled = Flags.autofillCredmanIntegration(); 721 mIsFillFieldsFromCurrentSessionOnly = AutofillFeatureFlags 722 .shouldFillFieldsFromCurrentSessionOnly(); 723 if (verbose) { 724 Slog.v(mTag, "setDeviceConfigProperties() for PCC: " 725 + "mPccClassificationEnabled=" + mPccClassificationEnabled 726 + ", mPccPreferProviderOverPcc=" + mPccPreferProviderOverPcc 727 + ", mPccUseFallbackDetection=" + mPccUseFallbackDetection 728 + ", mPccProviderHints=" + mPccProviderHints 729 + ", mAutofillCredmanIntegrationEnabled=" 730 + mAutofillCredmanIntegrationEnabled 731 + ", mIsFillFieldsFromCurrentSessionOnly=" 732 + mIsFillFieldsFromCurrentSessionOnly); 733 } 734 } 735 } 736 updateCachedServices()737 private void updateCachedServices() { 738 List<UserInfo> supportedUsers = getSupportedUsers(); 739 for (UserInfo userInfo : supportedUsers) { 740 synchronized (mLock) { 741 updateCachedServiceLocked(userInfo.id); 742 } 743 } 744 } 745 746 // Called by Shell command. calculateScore(@ullable String algorithmName, @NonNull String value1, @NonNull String value2, @NonNull RemoteCallback callback)747 void calculateScore(@Nullable String algorithmName, @NonNull String value1, 748 @NonNull String value2, @NonNull RemoteCallback callback) { 749 enforceCallingPermissionForManagement(); 750 751 final FieldClassificationStrategy strategy = 752 new FieldClassificationStrategy(getContext(), UserHandle.USER_CURRENT); 753 754 strategy.calculateScores(callback, Arrays.asList(AutofillValue.forText(value1)), 755 new String[] { value2 }, new String[] { null }, algorithmName, null, null, null); 756 } 757 758 // Called by Shell command. getFullScreenMode()759 Boolean getFullScreenMode() { 760 enforceCallingPermissionForManagement(); 761 return sFullScreenMode; 762 } 763 764 // Called by Shell command. setFullScreenMode(@ullable Boolean mode)765 void setFullScreenMode(@Nullable Boolean mode) { 766 enforceCallingPermissionForManagement(); 767 sFullScreenMode = mode; 768 } 769 770 // Called by Shell command. setTemporaryAugmentedAutofillService(@serIdInt int userId, @NonNull String serviceName, int durationMs)771 void setTemporaryAugmentedAutofillService(@UserIdInt int userId, @NonNull String serviceName, 772 int durationMs) { 773 Slog.i(mTag, "setTemporaryAugmentedAutofillService(" + userId + ") to " + serviceName 774 + " for " + durationMs + "ms"); 775 enforceCallingPermissionForManagement(); 776 777 Objects.requireNonNull(serviceName); 778 if (durationMs > MAX_TEMP_AUGMENTED_SERVICE_DURATION_MS) { 779 throw new IllegalArgumentException("Max duration is " 780 + MAX_TEMP_AUGMENTED_SERVICE_DURATION_MS + " (called with " + durationMs + ")"); 781 } 782 783 mAugmentedAutofillResolver.setTemporaryService(userId, serviceName, durationMs); 784 } 785 786 // Called by Shell command resetTemporaryAugmentedAutofillService(@serIdInt int userId)787 void resetTemporaryAugmentedAutofillService(@UserIdInt int userId) { 788 enforceCallingPermissionForManagement(); 789 mAugmentedAutofillResolver.resetTemporaryService(userId); 790 } 791 792 // Called by Shell command isDefaultAugmentedServiceEnabled(@serIdInt int userId)793 boolean isDefaultAugmentedServiceEnabled(@UserIdInt int userId) { 794 enforceCallingPermissionForManagement(); 795 return mAugmentedAutofillResolver.isDefaultServiceEnabled(userId); 796 } 797 798 // Called by Shell command setDefaultAugmentedServiceEnabled(@serIdInt int userId, boolean enabled)799 boolean setDefaultAugmentedServiceEnabled(@UserIdInt int userId, boolean enabled) { 800 Slog.i(mTag, "setDefaultAugmentedServiceEnabled() for userId " + userId + ": " + enabled); 801 enforceCallingPermissionForManagement(); 802 803 synchronized (mLock) { 804 final AutofillManagerServiceImpl service = getServiceForUserLocked(userId); 805 if (service != null) { 806 final boolean changed = mAugmentedAutofillResolver 807 .setDefaultServiceEnabled(userId, enabled); 808 if (changed) { 809 service.updateRemoteAugmentedAutofillService(); 810 return true; 811 } else { 812 if (debug) { 813 Slog.d(TAG, "setDefaultAugmentedServiceEnabled(): already " + enabled); 814 } 815 } 816 } 817 } 818 return false; 819 } 820 821 // Called by Shell command isFieldDetectionServiceEnabledForUser(@serIdInt int userId)822 boolean isFieldDetectionServiceEnabledForUser(@UserIdInt int userId) { 823 enforceCallingPermissionForManagement(); 824 synchronized (mLock) { 825 final AutofillManagerServiceImpl service = getServiceForUserLocked(userId); 826 if (service != null) { 827 return service.isPccClassificationEnabled(); 828 } 829 } 830 return false; 831 } 832 833 // Called by Shell command getFieldDetectionServiceName(@serIdInt int userId)834 String getFieldDetectionServiceName(@UserIdInt int userId) { 835 enforceCallingPermissionForManagement(); 836 return mFieldClassificationResolver.readServiceName(userId); 837 } 838 839 // Called by Shell command setTemporaryDetectionService(@serIdInt int userId, @NonNull String serviceName, int durationMs)840 boolean setTemporaryDetectionService(@UserIdInt int userId, @NonNull String serviceName, 841 int durationMs) { 842 Slog.i(mTag, "setTemporaryDetectionService(" + userId + ") to " + serviceName 843 + " for " + durationMs + "ms"); 844 enforceCallingPermissionForManagement(); 845 846 Objects.requireNonNull(serviceName); 847 if (durationMs > 100000) { 848 // limit duration 849 } 850 851 mFieldClassificationResolver.setTemporaryService(userId, serviceName, durationMs); 852 853 return false; 854 } 855 856 // Called by Shell command resetTemporaryDetectionService(@serIdInt int userId)857 void resetTemporaryDetectionService(@UserIdInt int userId) { 858 enforceCallingPermissionForManagement(); 859 mFieldClassificationResolver.resetTemporaryService(userId); 860 } 861 862 /** 863 * Requests a count of saved passwords from the current service. 864 * 865 * @return {@code true} if the request succeeded 866 */ 867 // Called by Shell command requestSavedPasswordCount(@serIdInt int userId, @NonNull IResultReceiver receiver)868 boolean requestSavedPasswordCount(@UserIdInt int userId, @NonNull IResultReceiver receiver) { 869 enforceCallingPermissionForManagement(); 870 synchronized (mLock) { 871 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 872 if (service != null) { 873 service.requestSavedPasswordCount(receiver); 874 return true; 875 } else if (sVerbose) { 876 Slog.v(TAG, "requestSavedPasswordCount(): no service for " + userId); 877 } 878 } 879 return false; 880 } 881 setLoggingLevelsLocked(boolean debug, boolean verbose)882 private void setLoggingLevelsLocked(boolean debug, boolean verbose) { 883 com.android.server.autofill.Helper.sDebug = debug; 884 android.view.autofill.Helper.sDebug = debug; 885 this.debug = debug; 886 887 com.android.server.autofill.Helper.sVerbose = verbose; 888 android.view.autofill.Helper.sVerbose = verbose; 889 this.verbose = verbose; 890 } 891 addCompatibilityModeRequestsLocked(@onNull AutofillManagerServiceImpl service , int userId)892 private void addCompatibilityModeRequestsLocked(@NonNull AutofillManagerServiceImpl service 893 , int userId) { 894 mAutofillCompatState.reset(userId); 895 final ArrayMap<String, Long> compatPackages = 896 service.getCompatibilityPackagesLocked(); 897 if (compatPackages == null || compatPackages.isEmpty()) { 898 return; 899 } 900 901 final Map<String, String[]> allowedPackages = getAllowedCompatModePackages(); 902 final int compatPackageCount = compatPackages.size(); 903 for (int i = 0; i < compatPackageCount; i++) { 904 final String packageName = compatPackages.keyAt(i); 905 if (allowedPackages == null || !allowedPackages.containsKey(packageName)) { 906 Slog.w(TAG, "Ignoring not allowed compat package " + packageName); 907 continue; 908 } 909 final Long maxVersionCode = compatPackages.valueAt(i); 910 if (maxVersionCode != null) { 911 mAutofillCompatState.addCompatibilityModeRequest(packageName, 912 maxVersionCode, allowedPackages.get(packageName), userId); 913 } 914 } 915 } 916 getAllowedCompatModePackagesFromDeviceConfig()917 private String getAllowedCompatModePackagesFromDeviceConfig() { 918 String config = DeviceConfig.getString( 919 DeviceConfig.NAMESPACE_AUTOFILL, 920 AutofillFeatureFlags.DEVICE_CONFIG_AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES, 921 /* defaultValue */ null); 922 if (!TextUtils.isEmpty(config)) { 923 return config; 924 } 925 // Fallback to Settings.Global.AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES if 926 // the device config is null. 927 return getAllowedCompatModePackagesFromSettings(); 928 } 929 getAllowedCompatModePackagesFromSettings()930 private String getAllowedCompatModePackagesFromSettings() { 931 return Settings.Global.getString( 932 getContext().getContentResolver(), 933 Settings.Global.AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES); 934 } 935 936 @Nullable getAllowedCompatModePackages()937 private Map<String, String[]> getAllowedCompatModePackages() { 938 return getAllowedCompatModePackages(getAllowedCompatModePackagesFromDeviceConfig()); 939 } 940 send(@onNull IResultReceiver receiver, int value)941 private void send(@NonNull IResultReceiver receiver, int value) { 942 try { 943 receiver.send(value, null); 944 } catch (RemoteException e) { 945 Slog.w(TAG, "Error async reporting result to client: " + e); 946 } 947 } 948 send(@onNull IResultReceiver receiver, @NonNull Bundle value)949 private void send(@NonNull IResultReceiver receiver, @NonNull Bundle value) { 950 try { 951 receiver.send(0, value); 952 } catch (RemoteException e) { 953 Slog.w(TAG, "Error async reporting result to client: " + e); 954 } 955 } 956 send(@onNull IResultReceiver receiver, @Nullable String value)957 private void send(@NonNull IResultReceiver receiver, @Nullable String value) { 958 send(receiver, SyncResultReceiver.bundleFor(value)); 959 } 960 send(@onNull IResultReceiver receiver, @Nullable String[] value)961 private void send(@NonNull IResultReceiver receiver, @Nullable String[] value) { 962 send(receiver, SyncResultReceiver.bundleFor(value)); 963 } 964 send(@onNull IResultReceiver receiver, @Nullable Parcelable value)965 private void send(@NonNull IResultReceiver receiver, @Nullable Parcelable value) { 966 send(receiver, SyncResultReceiver.bundleFor(value)); 967 } 968 send(@onNull IResultReceiver receiver, boolean value)969 private void send(@NonNull IResultReceiver receiver, boolean value) { 970 send(receiver, value ? 1 : 0); 971 } 972 send(@onNull IResultReceiver receiver, int value1, int value2)973 private void send(@NonNull IResultReceiver receiver, int value1, int value2) { 974 try { 975 receiver.send(value1, SyncResultReceiver.bundleFor(value2)); 976 } catch (RemoteException e) { 977 Slog.w(TAG, "Error async reporting result to client: " + e); 978 } 979 } 980 981 /** 982 * Whether the Autofill PCC Classification feature flag is enabled. 983 */ isPccClassificationFlagEnabled()984 public boolean isPccClassificationFlagEnabled() { 985 synchronized (mFlagLock) { 986 return mPccClassificationEnabled; 987 } 988 } 989 990 /** 991 * Whether the Autofill-Credman integration feature flag is enabled. 992 */ isAutofillCredmanIntegrationEnabled()993 public boolean isAutofillCredmanIntegrationEnabled() { 994 synchronized (mFlagLock) { 995 return mAutofillCredmanIntegrationEnabled; 996 } 997 } 998 999 /** 1000 * Whether the Autofill Provider shouldbe preferred over PCC results for selecting datasets. 1001 */ preferProviderOverPcc()1002 public boolean preferProviderOverPcc() { 1003 synchronized (mFlagLock) { 1004 return mPccPreferProviderOverPcc; 1005 } 1006 } 1007 1008 /** 1009 * Whether to use the fallback for detection. 1010 * If true, use data from secondary source if primary not present . 1011 * For eg: if we prefer PCC over provider, and PCC detection didn't classify a field, however, 1012 * autofill provider did, this flag would decide whether we use that result, and show some 1013 * presentation for that particular field. 1014 */ shouldUsePccFallback()1015 public boolean shouldUsePccFallback() { 1016 synchronized (mFlagLock) { 1017 return mPccUseFallbackDetection; 1018 } 1019 } 1020 1021 /** 1022 * Provides Autofill Hints that would be requested by the service from the Autofill Provider. 1023 */ getPccProviderHints()1024 public String getPccProviderHints() { 1025 synchronized (mFlagLock) { 1026 return mPccProviderHints; 1027 } 1028 } 1029 1030 /** 1031 * Return the max suggestion length 1032 */ getMaxInputLengthForAutofill()1033 public int getMaxInputLengthForAutofill() { 1034 synchronized (mFlagLock) { 1035 return mMaxInputLengthForAutofill; 1036 } 1037 } 1038 1039 /** 1040 * Return if autofill should only fill in fields from current session. 1041 */ getIsFillFieldsFromCurrentSessionOnly()1042 public boolean getIsFillFieldsFromCurrentSessionOnly() { 1043 synchronized (mFlagLock) { 1044 return mIsFillFieldsFromCurrentSessionOnly; 1045 } 1046 } 1047 1048 @Nullable 1049 @VisibleForTesting getAllowedCompatModePackages(String setting)1050 static Map<String, String[]> getAllowedCompatModePackages(String setting) { 1051 if (TextUtils.isEmpty(setting)) { 1052 return null; 1053 } 1054 1055 final ArrayMap<String, String[]> compatPackages = new ArrayMap<>(); 1056 final SimpleStringSplitter splitter = new SimpleStringSplitter(COMPAT_PACKAGE_DELIMITER); 1057 splitter.setString(setting); 1058 while (splitter.hasNext()) { 1059 final String packageBlock = splitter.next(); 1060 final int urlBlockIndex = packageBlock.indexOf(COMPAT_PACKAGE_URL_IDS_BLOCK_BEGIN); 1061 final String packageName; 1062 final List<String> urlBarIds; 1063 if (urlBlockIndex == -1) { 1064 packageName = packageBlock; 1065 urlBarIds = null; 1066 } else { 1067 if (packageBlock.charAt(packageBlock.length() - 1) 1068 != COMPAT_PACKAGE_URL_IDS_BLOCK_END) { 1069 Slog.w(TAG, "Ignoring entry '" + packageBlock + "' on '" + setting 1070 + "'because it does not end on '" + COMPAT_PACKAGE_URL_IDS_BLOCK_END + 1071 "'"); 1072 continue; 1073 } 1074 packageName = packageBlock.substring(0, urlBlockIndex); 1075 urlBarIds = new ArrayList<>(); 1076 final String urlBarIdsBlock = 1077 packageBlock.substring(urlBlockIndex + 1, packageBlock.length() - 1); 1078 if (sVerbose) { 1079 Slog.v(TAG, "pkg:" + packageName + ": block:" + packageBlock + ": urls:" 1080 + urlBarIds + ": block:" + urlBarIdsBlock + ":"); 1081 } 1082 final SimpleStringSplitter splitter2 = 1083 new SimpleStringSplitter(COMPAT_PACKAGE_URL_IDS_DELIMITER); 1084 splitter2.setString(urlBarIdsBlock); 1085 while (splitter2.hasNext()) { 1086 final String urlBarId = splitter2.next(); 1087 urlBarIds.add(urlBarId); 1088 } 1089 } 1090 if (urlBarIds == null) { 1091 compatPackages.put(packageName, null); 1092 } else { 1093 final String[] urlBarIdsArray = new String[urlBarIds.size()]; 1094 urlBarIds.toArray(urlBarIdsArray); 1095 compatPackages.put(packageName, urlBarIdsArray); 1096 } 1097 } 1098 return compatPackages; 1099 } 1100 1101 /** 1102 * Gets the maximum number of partitions / fill requests. 1103 */ getPartitionMaxCount()1104 public static int getPartitionMaxCount() { 1105 synchronized (sLock) { 1106 return sPartitionMaxCount; 1107 } 1108 } 1109 1110 /** 1111 * Gets the maxium number of datasets visible in the UI. 1112 */ getVisibleDatasetsMaxCount()1113 public static int getVisibleDatasetsMaxCount() { 1114 synchronized (sLock) { 1115 return sVisibleDatasetsMaxCount; 1116 } 1117 } 1118 1119 private final class LocalService extends AutofillManagerInternal { 1120 @Override onBackKeyPressed()1121 public void onBackKeyPressed() { 1122 if (sDebug) Slog.d(TAG, "onBackKeyPressed()"); 1123 mUi.hideAll(null); 1124 synchronized (mLock) { 1125 final AutofillManagerServiceImpl service = 1126 getServiceForUserWithLocalBinderIdentityLocked( 1127 UserHandle.getCallingUserId()); 1128 service.onBackKeyPressed(); 1129 } 1130 } 1131 1132 @Override getAutofillOptions(@onNull String packageName, long versionCode, @UserIdInt int userId)1133 public AutofillOptions getAutofillOptions(@NonNull String packageName, 1134 long versionCode, @UserIdInt int userId) { 1135 final int loggingLevel; 1136 if (verbose) { 1137 loggingLevel = AutofillManager.FLAG_ADD_CLIENT_VERBOSE 1138 | AutofillManager.FLAG_ADD_CLIENT_DEBUG; 1139 } else if (debug) { 1140 loggingLevel = AutofillManager.FLAG_ADD_CLIENT_DEBUG; 1141 } else { 1142 loggingLevel = AutofillManager.NO_LOGGING; 1143 } 1144 final boolean compatModeEnabled = mAutofillCompatState.isCompatibilityModeRequested( 1145 packageName, versionCode, userId); 1146 final AutofillOptions options = new AutofillOptions(loggingLevel, compatModeEnabled); 1147 mAugmentedAutofillState.injectAugmentedAutofillInfo(options, userId, packageName); 1148 injectDisableAppInfo(options, userId, packageName); 1149 return options; 1150 } 1151 1152 @Override isAugmentedAutofillServiceForUser(int callingUid, int userId)1153 public boolean isAugmentedAutofillServiceForUser(int callingUid, int userId) { 1154 synchronized (mLock) { 1155 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 1156 if (service != null) { 1157 return service.isAugmentedAutofillServiceForUserLocked(callingUid); 1158 } 1159 } 1160 return false; 1161 } 1162 injectDisableAppInfo(@onNull AutofillOptions options, int userId, String packageName)1163 private void injectDisableAppInfo(@NonNull AutofillOptions options, int userId, 1164 String packageName) { 1165 options.appDisabledExpiration = 1166 mDisabledInfoCache.getAppDisabledExpiration(userId, packageName); 1167 options.disabledActivities = 1168 mDisabledInfoCache.getAppDisabledActivities(userId, packageName); 1169 } 1170 } 1171 1172 /** 1173 * Compatibility mode metadata per package. 1174 */ 1175 static final class PackageCompatState { 1176 private final long maxVersionCode; 1177 private final String[] urlBarResourceIds; 1178 PackageCompatState(long maxVersionCode, String[] urlBarResourceIds)1179 PackageCompatState(long maxVersionCode, String[] urlBarResourceIds) { 1180 this.maxVersionCode = maxVersionCode; 1181 this.urlBarResourceIds = urlBarResourceIds; 1182 } 1183 1184 @Override toString()1185 public String toString() { 1186 return "maxVersionCode=" + maxVersionCode 1187 + ", urlBarResourceIds=" + Arrays.toString(urlBarResourceIds); 1188 } 1189 } 1190 1191 /** 1192 * Stores autofill disable information, i.e. {@link AutofillDisabledInfo}, keyed by user id. 1193 * The information is cleaned up when the service is removed. 1194 */ 1195 static final class DisabledInfoCache { 1196 1197 private final Object mLock = new Object(); 1198 1199 @GuardedBy("mLock") 1200 private final SparseArray<AutofillDisabledInfo> mCache = new SparseArray<>(); 1201 remove(@serIdInt int userId)1202 void remove(@UserIdInt int userId) { 1203 synchronized (mLock) { 1204 mCache.remove(userId); 1205 } 1206 } 1207 addDisabledAppLocked(@serIdInt int userId, @NonNull String packageName, long expiration)1208 void addDisabledAppLocked(@UserIdInt int userId, @NonNull String packageName, 1209 long expiration) { 1210 Objects.requireNonNull(packageName); 1211 synchronized (mLock) { 1212 AutofillDisabledInfo info = 1213 getOrCreateAutofillDisabledInfoByUserIdLocked(userId); 1214 info.putDisableAppsLocked(packageName, expiration); 1215 } 1216 } 1217 addDisabledActivityLocked(@serIdInt int userId, @NonNull ComponentName componentName, long expiration)1218 void addDisabledActivityLocked(@UserIdInt int userId, @NonNull ComponentName componentName, 1219 long expiration) { 1220 Objects.requireNonNull(componentName); 1221 synchronized (mLock) { 1222 AutofillDisabledInfo info = 1223 getOrCreateAutofillDisabledInfoByUserIdLocked(userId); 1224 info.putDisableActivityLocked(componentName, expiration); 1225 } 1226 } 1227 isAutofillDisabledLocked(@serIdInt int userId, @NonNull ComponentName componentName)1228 boolean isAutofillDisabledLocked(@UserIdInt int userId, 1229 @NonNull ComponentName componentName) { 1230 Objects.requireNonNull(componentName); 1231 final boolean disabled; 1232 synchronized (mLock) { 1233 final AutofillDisabledInfo info = mCache.get(userId); 1234 disabled = info != null ? info.isAutofillDisabledLocked(componentName) : false; 1235 } 1236 return disabled; 1237 } 1238 getAppDisabledExpiration(@serIdInt int userId, @NonNull String packageName)1239 long getAppDisabledExpiration(@UserIdInt int userId, @NonNull String packageName) { 1240 Objects.requireNonNull(packageName); 1241 final Long expiration; 1242 synchronized (mLock) { 1243 final AutofillDisabledInfo info = mCache.get(userId); 1244 expiration = info != null ? info.getAppDisabledExpirationLocked(packageName) : 0; 1245 } 1246 return expiration; 1247 } 1248 1249 @Nullable getAppDisabledActivities(@serIdInt int userId, @NonNull String packageName)1250 ArrayMap<String, Long> getAppDisabledActivities(@UserIdInt int userId, 1251 @NonNull String packageName) { 1252 Objects.requireNonNull(packageName); 1253 final ArrayMap<String, Long> disabledList; 1254 synchronized (mLock) { 1255 final AutofillDisabledInfo info = mCache.get(userId); 1256 disabledList = 1257 info != null ? info.getAppDisabledActivitiesLocked(packageName) : null; 1258 } 1259 return disabledList; 1260 } 1261 dump(@serIdInt int userId, String prefix, PrintWriter pw)1262 void dump(@UserIdInt int userId, String prefix, PrintWriter pw) { 1263 synchronized (mLock) { 1264 final AutofillDisabledInfo info = mCache.get(userId); 1265 if (info != null) { 1266 info.dumpLocked(prefix, pw); 1267 } 1268 } 1269 } 1270 1271 @NonNull getOrCreateAutofillDisabledInfoByUserIdLocked( @serIdInt int userId)1272 private AutofillDisabledInfo getOrCreateAutofillDisabledInfoByUserIdLocked( 1273 @UserIdInt int userId) { 1274 AutofillDisabledInfo info = mCache.get(userId); 1275 if (info == null) { 1276 info = new AutofillDisabledInfo(); 1277 mCache.put(userId, info); 1278 } 1279 return info; 1280 } 1281 } 1282 1283 /** 1284 * The autofill disable information. 1285 * <p> 1286 * This contains disable information set by the AutofillService, e.g. disabled application 1287 * expiration, disable activity expiration. 1288 */ 1289 private static final class AutofillDisabledInfo { 1290 /** 1291 * Apps disabled by the service; key is package name, value is when they will be enabled 1292 * again. 1293 */ 1294 private ArrayMap<String, Long> mDisabledApps; 1295 /** 1296 * Activities disabled by the service; key is component name, value is when they will be 1297 * enabled again. 1298 */ 1299 private ArrayMap<ComponentName, Long> mDisabledActivities; 1300 putDisableAppsLocked(@onNull String packageName, long expiration)1301 void putDisableAppsLocked(@NonNull String packageName, long expiration) { 1302 if (mDisabledApps == null) { 1303 mDisabledApps = new ArrayMap<>(1); 1304 } 1305 mDisabledApps.put(packageName, expiration); 1306 } 1307 putDisableActivityLocked(@onNull ComponentName componentName, long expiration)1308 void putDisableActivityLocked(@NonNull ComponentName componentName, long expiration) { 1309 if (mDisabledActivities == null) { 1310 mDisabledActivities = new ArrayMap<>(1); 1311 } 1312 mDisabledActivities.put(componentName, expiration); 1313 } 1314 getAppDisabledExpirationLocked(@onNull String packageName)1315 long getAppDisabledExpirationLocked(@NonNull String packageName) { 1316 if (mDisabledApps == null) { 1317 return 0; 1318 } 1319 final Long expiration = mDisabledApps.get(packageName); 1320 return expiration != null ? expiration : 0; 1321 } 1322 getAppDisabledActivitiesLocked(@onNull String packageName)1323 ArrayMap<String, Long> getAppDisabledActivitiesLocked(@NonNull String packageName) { 1324 if (mDisabledActivities != null) { 1325 final int size = mDisabledActivities.size(); 1326 ArrayMap<String, Long> disabledList = null; 1327 for (int i = 0; i < size; i++) { 1328 final ComponentName component = mDisabledActivities.keyAt(i); 1329 if (packageName.equals(component.getPackageName())) { 1330 if (disabledList == null) { 1331 disabledList = new ArrayMap<>(); 1332 } 1333 final long expiration = mDisabledActivities.valueAt(i); 1334 disabledList.put(component.flattenToShortString(), expiration); 1335 } 1336 } 1337 return disabledList; 1338 } 1339 return null; 1340 } 1341 isAutofillDisabledLocked(@onNull ComponentName componentName)1342 boolean isAutofillDisabledLocked(@NonNull ComponentName componentName) { 1343 // Check activities first. 1344 long elapsedTime = 0; 1345 if (mDisabledActivities != null) { 1346 elapsedTime = SystemClock.elapsedRealtime(); 1347 final Long expiration = mDisabledActivities.get(componentName); 1348 if (expiration != null) { 1349 if (expiration >= elapsedTime) return true; 1350 // Restriction expired - clean it up. 1351 if (sVerbose) { 1352 Slog.v(TAG, "Removing " + componentName.toShortString() 1353 + " from disabled list"); 1354 } 1355 mDisabledActivities.remove(componentName); 1356 } 1357 } 1358 1359 // Then check apps. 1360 final String packageName = componentName.getPackageName(); 1361 if (mDisabledApps == null) return false; 1362 1363 final Long expiration = mDisabledApps.get(packageName); 1364 if (expiration == null) return false; 1365 1366 if (elapsedTime == 0) { 1367 elapsedTime = SystemClock.elapsedRealtime(); 1368 } 1369 1370 if (expiration >= elapsedTime) return true; 1371 1372 // Restriction expired - clean it up. 1373 if (sVerbose) Slog.v(TAG, "Removing " + packageName + " from disabled list"); 1374 mDisabledApps.remove(packageName); 1375 return false; 1376 } 1377 dumpLocked(String prefix, PrintWriter pw)1378 void dumpLocked(String prefix, PrintWriter pw) { 1379 pw.print(prefix); pw.print("Disabled apps: "); 1380 if (mDisabledApps == null) { 1381 pw.println("N/A"); 1382 } else { 1383 final int size = mDisabledApps.size(); 1384 pw.println(size); 1385 final StringBuilder builder = new StringBuilder(); 1386 final long now = SystemClock.elapsedRealtime(); 1387 for (int i = 0; i < size; i++) { 1388 final String packageName = mDisabledApps.keyAt(i); 1389 final long expiration = mDisabledApps.valueAt(i); 1390 builder.append(prefix).append(prefix) 1391 .append(i).append(". ").append(packageName).append(": "); 1392 TimeUtils.formatDuration((expiration - now), builder); 1393 builder.append('\n'); 1394 } 1395 pw.println(builder); 1396 } 1397 1398 pw.print(prefix); pw.print("Disabled activities: "); 1399 if (mDisabledActivities == null) { 1400 pw.println("N/A"); 1401 } else { 1402 final int size = mDisabledActivities.size(); 1403 pw.println(size); 1404 final StringBuilder builder = new StringBuilder(); 1405 final long now = SystemClock.elapsedRealtime(); 1406 for (int i = 0; i < size; i++) { 1407 final ComponentName component = mDisabledActivities.keyAt(i); 1408 final long expiration = mDisabledActivities.valueAt(i); 1409 builder.append(prefix).append(prefix) 1410 .append(i).append(". ").append(component).append(": "); 1411 TimeUtils.formatDuration((expiration - now), builder); 1412 builder.append('\n'); 1413 } 1414 pw.println(builder); 1415 } 1416 } 1417 } 1418 1419 /** 1420 * Compatibility mode metadata associated with all services. 1421 * 1422 * <p>This object is defined here instead of on each {@link AutofillManagerServiceImpl} because 1423 * it cannot hold a lock on the main lock when 1424 * {@link AutofillCompatState#isCompatibilityModeRequested(String, long, int)} is called by 1425 * external services. 1426 */ 1427 static final class AutofillCompatState { 1428 private final Object mLock = new Object(); 1429 1430 /** 1431 * Map of app->compat_state per user. 1432 */ 1433 @GuardedBy("mLock") 1434 private SparseArray<ArrayMap<String, PackageCompatState>> mUserSpecs; 1435 isCompatibilityModeRequested(@onNull String packageName, long versionCode, @UserIdInt int userId)1436 boolean isCompatibilityModeRequested(@NonNull String packageName, 1437 long versionCode, @UserIdInt int userId) { 1438 synchronized (mLock) { 1439 if (mUserSpecs == null) { 1440 return false; 1441 } 1442 final ArrayMap<String, PackageCompatState> userSpec = mUserSpecs.get(userId); 1443 if (userSpec == null) { 1444 return false; 1445 } 1446 final PackageCompatState metadata = userSpec.get(packageName); 1447 if (metadata == null) { 1448 return false; 1449 } 1450 return versionCode <= metadata.maxVersionCode; 1451 } 1452 } 1453 1454 @Nullable getUrlBarResourceIds(@onNull String packageName, @UserIdInt int userId)1455 String[] getUrlBarResourceIds(@NonNull String packageName, @UserIdInt int userId) { 1456 synchronized (mLock) { 1457 if (mUserSpecs == null) { 1458 return null; 1459 } 1460 final ArrayMap<String, PackageCompatState> userSpec = mUserSpecs.get(userId); 1461 if (userSpec == null) { 1462 return null; 1463 } 1464 final PackageCompatState metadata = userSpec.get(packageName); 1465 if (metadata == null) { 1466 return null; 1467 } 1468 return metadata.urlBarResourceIds; 1469 } 1470 } 1471 addCompatibilityModeRequest(@onNull String packageName, long versionCode, @Nullable String[] urlBarResourceIds, @UserIdInt int userId)1472 void addCompatibilityModeRequest(@NonNull String packageName, 1473 long versionCode, @Nullable String[] urlBarResourceIds, @UserIdInt int userId) { 1474 synchronized (mLock) { 1475 if (mUserSpecs == null) { 1476 mUserSpecs = new SparseArray<>(); 1477 } 1478 ArrayMap<String, PackageCompatState> userSpec = mUserSpecs.get(userId); 1479 if (userSpec == null) { 1480 userSpec = new ArrayMap<>(); 1481 mUserSpecs.put(userId, userSpec); 1482 } 1483 userSpec.put(packageName, 1484 new PackageCompatState(versionCode, urlBarResourceIds)); 1485 } 1486 } 1487 removeCompatibilityModeRequests(@serIdInt int userId)1488 void removeCompatibilityModeRequests(@UserIdInt int userId) { 1489 synchronized (mLock) { 1490 if (mUserSpecs != null) { 1491 mUserSpecs.remove(userId); 1492 if (mUserSpecs.size() <= 0) { 1493 mUserSpecs = null; 1494 } 1495 } 1496 } 1497 } 1498 reset(int userId)1499 void reset(int userId) { 1500 synchronized (mLock) { 1501 if (mUserSpecs != null) { 1502 mUserSpecs.delete(userId); 1503 final int newSize = mUserSpecs.size(); 1504 if (newSize == 0) { 1505 if (sVerbose) Slog.v(TAG, "reseting mUserSpecs"); 1506 mUserSpecs = null; 1507 } else { 1508 if (sVerbose) Slog.v(TAG, "mUserSpecs down to " + newSize); 1509 } 1510 } 1511 } 1512 } 1513 dump(String prefix, PrintWriter pw)1514 private void dump(String prefix, PrintWriter pw) { 1515 synchronized (mLock) { 1516 if (mUserSpecs == null) { 1517 pw.println("N/A"); 1518 return; 1519 } 1520 pw.println(); 1521 final String prefix2 = prefix + " "; 1522 for (int i = 0; i < mUserSpecs.size(); i++) { 1523 final int user = mUserSpecs.keyAt(i); 1524 pw.print(prefix); 1525 pw.print("User: "); 1526 pw.println(user); 1527 final ArrayMap<String, PackageCompatState> perUser = mUserSpecs.valueAt(i); 1528 for (int j = 0; j < perUser.size(); j++) { 1529 final String packageName = perUser.keyAt(j); 1530 final PackageCompatState state = perUser.valueAt(j); 1531 pw.print(prefix2); pw.print(packageName); pw.print(": "); pw.println(state); 1532 } 1533 } 1534 } 1535 } 1536 } 1537 1538 /** 1539 * Augmented autofill metadata associated with all services. 1540 * 1541 * <p>This object is defined here instead of on each {@link AutofillManagerServiceImpl} because 1542 * it cannot hold a lock on the main lock when 1543 * {@link AugmentedAutofillState#injectAugmentedAutofillInfo(AutofillOptions, int, String)} 1544 * is called by external services. 1545 */ 1546 static final class AugmentedAutofillState extends GlobalWhitelistState { 1547 1548 @GuardedBy("mGlobalWhitelistStateLock") 1549 private final SparseArray<String> mServicePackages = new SparseArray<>(); 1550 @GuardedBy("mGlobalWhitelistStateLock") 1551 private final SparseBooleanArray mTemporaryServices = new SparseBooleanArray(); 1552 setServiceInfo(@serIdInt int userId, @Nullable String serviceName, boolean isTemporary)1553 private void setServiceInfo(@UserIdInt int userId, @Nullable String serviceName, 1554 boolean isTemporary) { 1555 synchronized (mGlobalWhitelistStateLock) { 1556 if (isTemporary) { 1557 mTemporaryServices.put(userId, true); 1558 } else { 1559 mTemporaryServices.delete(userId); 1560 } 1561 if (serviceName != null) { 1562 final ComponentName componentName = 1563 ComponentName.unflattenFromString(serviceName); 1564 if (componentName == null) { 1565 Slog.w(TAG, "setServiceInfo(): invalid name: " + serviceName); 1566 mServicePackages.remove(userId); 1567 } else { 1568 mServicePackages.put(userId, componentName.getPackageName()); 1569 } 1570 } else { 1571 mServicePackages.remove(userId); 1572 } 1573 } 1574 } 1575 injectAugmentedAutofillInfo(@onNull AutofillOptions options, @UserIdInt int userId, @NonNull String packageName)1576 public void injectAugmentedAutofillInfo(@NonNull AutofillOptions options, 1577 @UserIdInt int userId, @NonNull String packageName) { 1578 synchronized (mGlobalWhitelistStateLock) { 1579 if (mWhitelisterHelpers == null) return; 1580 final WhitelistHelper helper = mWhitelisterHelpers.get(userId); 1581 if (helper != null) { 1582 options.augmentedAutofillEnabled = helper.isWhitelisted(packageName); 1583 options.whitelistedActivitiesForAugmentedAutofill = helper 1584 .getWhitelistedComponents(packageName); 1585 } 1586 } 1587 } 1588 1589 @Override isWhitelisted(@serIdInt int userId, @NonNull ComponentName componentName)1590 public boolean isWhitelisted(@UserIdInt int userId, @NonNull ComponentName componentName) { 1591 synchronized (mGlobalWhitelistStateLock) { 1592 if (!super.isWhitelisted(userId, componentName)) return false; 1593 1594 if (Build.IS_USER && mTemporaryServices.get(userId)) { 1595 final String packageName = componentName.getPackageName(); 1596 if (!packageName.equals(mServicePackages.get(userId))) { 1597 Slog.w(TAG, "Ignoring package " + packageName + " for augmented autofill " 1598 + "while using temporary service " + mServicePackages.get(userId)); 1599 return false; 1600 } 1601 } 1602 } 1603 return true; 1604 } 1605 1606 @Override dump(@onNull String prefix, @NonNull PrintWriter pw)1607 public void dump(@NonNull String prefix, @NonNull PrintWriter pw) { 1608 super.dump(prefix, pw); 1609 1610 synchronized (mGlobalWhitelistStateLock) { 1611 if (mServicePackages.size() > 0) { 1612 pw.print(prefix); pw.print("Service packages: "); pw.println(mServicePackages); 1613 } 1614 if (mTemporaryServices.size() > 0) { 1615 pw.print(prefix); pw.print("Temp services: "); pw.println(mTemporaryServices); 1616 } 1617 } 1618 } 1619 } 1620 1621 final class AutoFillManagerServiceStub extends IAutoFillManager.Stub { 1622 @Override addClient(IAutoFillManagerClient client, ComponentName componentName, int userId, IResultReceiver receiver, boolean credmanRequested)1623 public void addClient(IAutoFillManagerClient client, ComponentName componentName, 1624 int userId, IResultReceiver receiver, boolean credmanRequested) { 1625 int flags = 0; 1626 try { 1627 synchronized (mLock) { 1628 final int enabledFlags = 1629 getServiceForUserWithLocalBinderIdentityLocked(userId) 1630 .addClientLocked(client, componentName, credmanRequested); 1631 if (enabledFlags != 0) { 1632 flags |= enabledFlags; 1633 } 1634 if (sDebug) { 1635 flags |= AutofillManager.FLAG_ADD_CLIENT_DEBUG; 1636 } 1637 if (sVerbose) { 1638 flags |= AutofillManager.FLAG_ADD_CLIENT_VERBOSE; 1639 } 1640 } 1641 } catch (Exception ex) { 1642 // Don't do anything, send back default flags 1643 Log.wtf(TAG, "addClient(): failed " + ex.toString(), ex); 1644 } finally { 1645 send(receiver, flags); 1646 } 1647 } 1648 1649 @Override removeClient(IAutoFillManagerClient client, int userId)1650 public void removeClient(IAutoFillManagerClient client, int userId) { 1651 synchronized (mLock) { 1652 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 1653 if (service != null) { 1654 service.removeClientLocked(client); 1655 } else if (sVerbose) { 1656 Slog.v(TAG, "removeClient(): no service for " + userId); 1657 } 1658 } 1659 } 1660 1661 @Override setAuthenticationResult(Bundle data, int sessionId, int authenticationId, int userId)1662 public void setAuthenticationResult(Bundle data, int sessionId, int authenticationId, 1663 int userId) { 1664 synchronized (mLock) { 1665 final AutofillManagerServiceImpl service = 1666 getServiceForUserWithLocalBinderIdentityLocked(userId); 1667 service.setAuthenticationResultLocked(data, sessionId, authenticationId, 1668 getCallingUid()); 1669 } 1670 } 1671 1672 @Override setHasCallback(int sessionId, int userId, boolean hasIt)1673 public void setHasCallback(int sessionId, int userId, boolean hasIt) { 1674 synchronized (mLock) { 1675 final AutofillManagerServiceImpl service = 1676 getServiceForUserWithLocalBinderIdentityLocked(userId); 1677 service.setHasCallback(sessionId, getCallingUid(), hasIt); 1678 } 1679 } 1680 1681 @Override startSession(IBinder activityToken, IBinder clientCallback, AutofillId autofillId, Rect bounds, AutofillValue value, int userId, boolean hasCallback, int flags, ComponentName clientActivity, boolean compatMode, IResultReceiver receiver)1682 public void startSession(IBinder activityToken, IBinder clientCallback, 1683 AutofillId autofillId, Rect bounds, AutofillValue value, int userId, 1684 boolean hasCallback, int flags, ComponentName clientActivity, 1685 boolean compatMode, IResultReceiver receiver) { 1686 1687 requireNonNull(activityToken, "activityToken"); 1688 requireNonNull(clientCallback, "clientCallback"); 1689 requireNonNull(autofillId, "autofillId"); 1690 requireNonNull(clientActivity, "clientActivity"); 1691 final String packageName = requireNonNull(clientActivity.getPackageName()); 1692 1693 Preconditions.checkArgument(userId == UserHandle.getUserId(getCallingUid()), "userId"); 1694 1695 try { 1696 getContext().getPackageManager().getPackageInfoAsUser(packageName, 0, userId); 1697 } catch (PackageManager.NameNotFoundException e) { 1698 throw new IllegalArgumentException(packageName + " is not a valid package", e); 1699 } 1700 1701 // TODO(b/113281366): add a callback method on AM to be notified when a task is finished 1702 // so we can clean up sessions kept alive 1703 final int taskId = mAm.getTaskIdForActivity(activityToken, false); 1704 final long result; 1705 synchronized (mLock) { 1706 final AutofillManagerServiceImpl service = 1707 getServiceForUserWithLocalBinderIdentityLocked(userId); 1708 result = service.startSessionLocked(activityToken, taskId, getCallingUid(), 1709 clientCallback, autofillId, bounds, value, hasCallback, clientActivity, 1710 compatMode, mAllowInstantService, flags); 1711 } 1712 final int sessionId = (int) result; 1713 final int resultFlags = (int) (result >> 32); 1714 if (resultFlags != 0) { 1715 send(receiver, sessionId, resultFlags); 1716 } else { 1717 send(receiver, sessionId); 1718 } 1719 } 1720 1721 @Override getFillEventHistory(@onNull IResultReceiver receiver)1722 public void getFillEventHistory(@NonNull IResultReceiver receiver) throws RemoteException { 1723 FillEventHistory fillEventHistory = null; 1724 final int userId = UserHandle.getCallingUserId(); 1725 1726 try { 1727 synchronized (mLock) { 1728 final AutofillManagerServiceImpl service = 1729 peekServiceForUserWithLocalBinderIdentityLocked(userId); 1730 if (service != null) { 1731 fillEventHistory = service.getFillEventHistory(getCallingUid()); 1732 } else if (sVerbose) { 1733 Slog.v(TAG, "getFillEventHistory(): no service for " + userId); 1734 } 1735 } 1736 } catch (Exception ex) { 1737 // Do not raise the exception, just send back the null response 1738 Log.wtf(TAG, "getFillEventHistory(): failed " + ex.toString()); 1739 } finally { 1740 send(receiver, fillEventHistory); 1741 } 1742 } 1743 1744 @Override getUserData(@onNull IResultReceiver receiver)1745 public void getUserData(@NonNull IResultReceiver receiver) throws RemoteException { 1746 UserData userData = null; 1747 final int userId = UserHandle.getCallingUserId(); 1748 1749 try { 1750 synchronized (mLock) { 1751 final AutofillManagerServiceImpl service = 1752 peekServiceForUserWithLocalBinderIdentityLocked(userId); 1753 if (service != null) { 1754 userData = service.getUserData(getCallingUid()); 1755 } else if (sVerbose) { 1756 Slog.v(TAG, "getUserData(): no service for " + userId); 1757 } 1758 } 1759 } catch (Exception ex) { 1760 // Do not raise the exception, just send back the null response 1761 Log.wtf(TAG, "getUserData(): failed " + ex.toString()); 1762 } finally { 1763 send(receiver, userData); 1764 } 1765 } 1766 1767 @Override getUserDataId(@onNull IResultReceiver receiver)1768 public void getUserDataId(@NonNull IResultReceiver receiver) throws RemoteException { 1769 UserData userData = null; 1770 final int userId = UserHandle.getCallingUserId(); 1771 1772 try { 1773 synchronized (mLock) { 1774 final AutofillManagerServiceImpl service = 1775 peekServiceForUserWithLocalBinderIdentityLocked(userId); 1776 if (service != null) { 1777 userData = service.getUserData(getCallingUid()); 1778 } else if (sVerbose) { 1779 Slog.v(TAG, "getUserDataId(): no service for " + userId); 1780 } 1781 } 1782 } catch (Exception ex) { 1783 // Do not raise the exception, just send back the null response 1784 Log.wtf(TAG, "getUserDataId(): failed " + ex.toString()); 1785 } finally { 1786 final String userDataId = userData == null ? null : userData.getId(); 1787 send(receiver, userDataId); 1788 } 1789 } 1790 1791 @Override setUserData(UserData userData)1792 public void setUserData(UserData userData) throws RemoteException { 1793 final int userId = UserHandle.getCallingUserId(); 1794 1795 synchronized (mLock) { 1796 final AutofillManagerServiceImpl service = 1797 peekServiceForUserWithLocalBinderIdentityLocked(userId); 1798 if (service != null) { 1799 service.setUserData(getCallingUid(), userData); 1800 } else if (sVerbose) { 1801 Slog.v(TAG, "setUserData(): no service for " + userId); 1802 } 1803 } 1804 } 1805 1806 @Override isFieldClassificationEnabled(@onNull IResultReceiver receiver)1807 public void isFieldClassificationEnabled(@NonNull IResultReceiver receiver) 1808 throws RemoteException { 1809 boolean enabled = false; 1810 final int userId = UserHandle.getCallingUserId(); 1811 1812 try { 1813 synchronized (mLock) { 1814 final AutofillManagerServiceImpl service = 1815 peekServiceForUserWithLocalBinderIdentityLocked(userId); 1816 if (service != null) { 1817 enabled = service.isFieldClassificationEnabled(getCallingUid()); 1818 } else if (sVerbose) { 1819 Slog.v(TAG, "isFieldClassificationEnabled(): no service for " + userId); 1820 } 1821 } 1822 } catch (Exception ex) { 1823 // Do not raise the exception, just send back false 1824 Log.wtf(TAG, "isFieldClassificationEnabled(): failed " + ex.toString()); 1825 } finally { 1826 send(receiver, enabled); 1827 } 1828 } 1829 1830 @Override getDefaultFieldClassificationAlgorithm(@onNull IResultReceiver receiver)1831 public void getDefaultFieldClassificationAlgorithm(@NonNull IResultReceiver receiver) 1832 throws RemoteException { 1833 String algorithm = null; 1834 final int userId = UserHandle.getCallingUserId(); 1835 1836 try { 1837 synchronized (mLock) { 1838 final AutofillManagerServiceImpl service = 1839 peekServiceForUserWithLocalBinderIdentityLocked(userId); 1840 if (service != null) { 1841 algorithm = service.getDefaultFieldClassificationAlgorithm(getCallingUid()); 1842 } else { 1843 if (sVerbose) { 1844 Slog.v(TAG, "getDefaultFcAlgorithm(): no service for " + userId); 1845 } 1846 } 1847 } 1848 } catch (Exception ex) { 1849 // Do not raise the exception, just send back null 1850 Log.wtf(TAG, "getDefaultFieldClassificationAlgorithm(): failed " + ex.toString()); 1851 } finally { 1852 send(receiver, algorithm); 1853 } 1854 1855 } 1856 1857 @Override setAugmentedAutofillWhitelist(@ullable List<String> packages, @Nullable List<ComponentName> activities, @NonNull IResultReceiver receiver)1858 public void setAugmentedAutofillWhitelist(@Nullable List<String> packages, 1859 @Nullable List<ComponentName> activities, @NonNull IResultReceiver receiver) 1860 throws RemoteException { 1861 boolean ok = false; 1862 final int userId = UserHandle.getCallingUserId(); 1863 1864 try { 1865 synchronized (mLock) { 1866 final AutofillManagerServiceImpl service = 1867 peekServiceForUserWithLocalBinderIdentityLocked(userId); 1868 if (service != null) { 1869 ok = service.setAugmentedAutofillWhitelistLocked(packages, activities, 1870 getCallingUid()); 1871 } else { 1872 if (sVerbose) { 1873 Slog.v(TAG, "setAugmentedAutofillWhitelist(): no service for " 1874 + userId); 1875 } 1876 } 1877 } 1878 } catch (Exception ex) { 1879 // Do not raise the exception, return the default value 1880 Log.wtf(TAG, "setAugmentedAutofillWhitelist(): failed " + ex.toString()); 1881 } finally { 1882 send(receiver, 1883 ok ? AutofillManager.RESULT_OK 1884 : AutofillManager.RESULT_CODE_NOT_SERVICE); 1885 } 1886 } 1887 1888 @Override getAvailableFieldClassificationAlgorithms(@onNull IResultReceiver receiver)1889 public void getAvailableFieldClassificationAlgorithms(@NonNull IResultReceiver receiver) 1890 throws RemoteException { 1891 String[] algorithms = null; 1892 final int userId = UserHandle.getCallingUserId(); 1893 1894 try { 1895 synchronized (mLock) { 1896 final AutofillManagerServiceImpl service = 1897 peekServiceForUserWithLocalBinderIdentityLocked(userId); 1898 if (service != null) { 1899 algorithms = service 1900 .getAvailableFieldClassificationAlgorithms(getCallingUid()); 1901 } else { 1902 if (sVerbose) { 1903 Slog.v(TAG, "getAvailableFcAlgorithms(): no service for " + userId); 1904 } 1905 } 1906 } 1907 } catch (Exception ex) { 1908 // Do not raise the exception, return null 1909 Log.wtf(TAG, "getAvailableFieldClassificationAlgorithms(): failed " 1910 + ex.toString()); 1911 } finally { 1912 send(receiver, algorithms); 1913 } 1914 } 1915 1916 @Override getAutofillServiceComponentName(@onNull IResultReceiver receiver)1917 public void getAutofillServiceComponentName(@NonNull IResultReceiver receiver) 1918 throws RemoteException { 1919 ComponentName componentName = null; 1920 final int userId = UserHandle.getCallingUserId(); 1921 1922 try { 1923 synchronized (mLock) { 1924 final AutofillManagerServiceImpl service; 1925 if (fixGetAutofillComponent()) { 1926 service = getServiceForUserWithLocalBinderIdentityLocked(userId); 1927 } else { 1928 service = peekServiceForUserWithLocalBinderIdentityLocked(userId); 1929 } 1930 if (service != null) { 1931 componentName = service.getServiceComponentName(); 1932 } else if (sVerbose) { 1933 Slog.v(TAG, "getAutofillServiceComponentName(): no service for " + userId); 1934 } 1935 } 1936 } catch (Exception ex) { 1937 Log.wtf(TAG, "getAutofillServiceComponentName(): failed " + ex.toString()); 1938 } finally { 1939 send(receiver, componentName); 1940 } 1941 } 1942 1943 @Override restoreSession(int sessionId, @NonNull IBinder activityToken, @NonNull IBinder appCallback, @NonNull IResultReceiver receiver)1944 public void restoreSession(int sessionId, @NonNull IBinder activityToken, 1945 @NonNull IBinder appCallback, @NonNull IResultReceiver receiver) 1946 throws RemoteException { 1947 boolean restored = false; 1948 final int userId = UserHandle.getCallingUserId(); 1949 1950 try { 1951 Objects.requireNonNull(activityToken, "activityToken"); 1952 Objects.requireNonNull(appCallback, "appCallback"); 1953 1954 synchronized (mLock) { 1955 final AutofillManagerServiceImpl service = 1956 peekServiceForUserWithLocalBinderIdentityLocked(userId); 1957 if (service != null) { 1958 restored = service.restoreSession(sessionId, getCallingUid(), activityToken, 1959 appCallback); 1960 } else if (sVerbose) { 1961 Slog.v(TAG, "restoreSession(): no service for " + userId); 1962 } 1963 } 1964 } catch (Exception ex) { 1965 // Do not propagate exception, send back status 1966 Log.wtf(TAG, "restoreSession(): failed " + ex.toString()); 1967 } finally { 1968 send(receiver, restored); 1969 } 1970 } 1971 1972 @Override updateSession(int sessionId, AutofillId autoFillId, Rect bounds, AutofillValue value, int action, int flags, int userId)1973 public void updateSession(int sessionId, AutofillId autoFillId, Rect bounds, 1974 AutofillValue value, int action, int flags, int userId) { 1975 synchronized (mLock) { 1976 final AutofillManagerServiceImpl service = 1977 peekServiceForUserWithLocalBinderIdentityLocked(userId); 1978 if (service != null) { 1979 service.updateSessionLocked(sessionId, getCallingUid(), autoFillId, bounds, 1980 value, action, flags); 1981 } else if (sVerbose) { 1982 Slog.v(TAG, "updateSession(): no service for " + userId); 1983 } 1984 } 1985 } 1986 1987 @Override setAutofillFailure( int sessionId, @NonNull List<AutofillId> ids, boolean isRefill, int userId)1988 public void setAutofillFailure( 1989 int sessionId, @NonNull List<AutofillId> ids, boolean isRefill, int userId) { 1990 synchronized (mLock) { 1991 final AutofillManagerServiceImpl service = 1992 peekServiceForUserWithLocalBinderIdentityLocked(userId); 1993 if (service != null) { 1994 service.setAutofillFailureLocked(sessionId, getCallingUid(), ids, isRefill); 1995 } else if (sVerbose) { 1996 Slog.v(TAG, "setAutofillFailure(): no service for " + userId); 1997 } 1998 } 1999 } 2000 2001 @Override setViewAutofilled(int sessionId, @NonNull AutofillId id, int userId)2002 public void setViewAutofilled(int sessionId, @NonNull AutofillId id, int userId) { 2003 synchronized (mLock) { 2004 final AutofillManagerServiceImpl service = 2005 peekServiceForUserWithLocalBinderIdentityLocked(userId); 2006 if (service != null) { 2007 service.setViewAutofilledLocked(sessionId, getCallingUid(), id); 2008 } else if (sVerbose) { 2009 Slog.v(TAG, "setAutofillFailure(): no service for " + userId); 2010 } 2011 } 2012 } 2013 2014 @Override notifyNotExpiringResponseDuringAuth(int sessionId, int userId)2015 public void notifyNotExpiringResponseDuringAuth(int sessionId, int userId) { 2016 synchronized (mLock) { 2017 final AutofillManagerServiceImpl service = 2018 peekServiceForUserWithLocalBinderIdentityLocked(userId); 2019 if (service != null) { 2020 service.notifyNotExpiringResponseDuringAuth(sessionId, getCallingUid()); 2021 } else if (sVerbose) { 2022 Slog.v(TAG, "notifyNotExpiringResponseDuringAuth(): no service for " + userId); 2023 } 2024 } 2025 } 2026 2027 @Override notifyViewEnteredIgnoredDuringAuthCount(int sessionId, int userId)2028 public void notifyViewEnteredIgnoredDuringAuthCount(int sessionId, int userId) { 2029 synchronized (mLock) { 2030 final AutofillManagerServiceImpl service = 2031 peekServiceForUserWithLocalBinderIdentityLocked(userId); 2032 if (service != null) { 2033 service.notifyViewEnteredIgnoredDuringAuthCount(sessionId, getCallingUid()); 2034 } else if (sVerbose) { 2035 Slog.v(TAG, "notifyNotExpiringResponseDuringAuth(): no service for " + userId); 2036 } 2037 } 2038 } 2039 2040 @Override setAutofillIdsAttemptedForRefill( int sessionId, @NonNull List<AutofillId> ids, int userId)2041 public void setAutofillIdsAttemptedForRefill( 2042 int sessionId, @NonNull List<AutofillId> ids, int userId) { 2043 synchronized (mLock) { 2044 final AutofillManagerServiceImpl service = 2045 peekServiceForUserWithLocalBinderIdentityLocked(userId); 2046 if (service != null) { 2047 service.setAutofillIdsAttemptedForRefill(sessionId, ids, getCallingUid()); 2048 } else if (sVerbose) { 2049 Slog.v(TAG, "setAutofillIdsAttemptedForRefill(): no service for " + userId); 2050 } 2051 } 2052 } 2053 2054 @Override finishSession(int sessionId, int userId, @AutofillCommitReason int commitReason)2055 public void finishSession(int sessionId, int userId, 2056 @AutofillCommitReason int commitReason) { 2057 synchronized (mLock) { 2058 final AutofillManagerServiceImpl service = 2059 peekServiceForUserWithLocalBinderIdentityLocked(userId); 2060 if (service != null) { 2061 service.finishSessionLocked(sessionId, getCallingUid(), commitReason); 2062 } else if (sVerbose) { 2063 Slog.v(TAG, "finishSession(): no service for " + userId); 2064 } 2065 } 2066 } 2067 2068 @Override cancelSession(int sessionId, int userId)2069 public void cancelSession(int sessionId, int userId) { 2070 synchronized (mLock) { 2071 final AutofillManagerServiceImpl service = 2072 peekServiceForUserWithLocalBinderIdentityLocked(userId); 2073 if (service != null) { 2074 service.cancelSessionLocked(sessionId, getCallingUid()); 2075 } else if (sVerbose) { 2076 Slog.v(TAG, "cancelSession(): no service for " + userId); 2077 } 2078 } 2079 2080 } 2081 2082 @Override disableOwnedAutofillServices(int userId)2083 public void disableOwnedAutofillServices(int userId) { 2084 synchronized (mLock) { 2085 final AutofillManagerServiceImpl service = 2086 peekServiceForUserWithLocalBinderIdentityLocked(userId); 2087 if (service != null) { 2088 service.disableOwnedAutofillServicesLocked(Binder.getCallingUid()); 2089 } else if (sVerbose) { 2090 Slog.v(TAG, "cancelSession(): no service for " + userId); 2091 } 2092 } 2093 } 2094 2095 @Override isServiceSupported(int userId, @NonNull IResultReceiver receiver)2096 public void isServiceSupported(int userId, @NonNull IResultReceiver receiver) { 2097 boolean supported = false; 2098 2099 try { 2100 synchronized (mLock) { 2101 supported = !isDisabledLocked(userId); 2102 } 2103 } catch (Exception ex) { 2104 // Do not propagate exception 2105 Log.wtf(TAG, "isServiceSupported(): failed " + ex.toString()); 2106 } finally { 2107 send(receiver, supported); 2108 } 2109 } 2110 2111 @Override isServiceEnabled(int userId, @NonNull String packageName, @NonNull IResultReceiver receiver)2112 public void isServiceEnabled(int userId, @NonNull String packageName, 2113 @NonNull IResultReceiver receiver) { 2114 boolean enabled = false; 2115 2116 try { 2117 synchronized (mLock) { 2118 final AutofillManagerServiceImpl service = 2119 peekServiceForUserWithLocalBinderIdentityLocked(userId); 2120 enabled = Objects.equals(packageName, service.getServicePackageName()); 2121 } 2122 } catch (Exception ex) { 2123 // Do not propagate exception 2124 Log.wtf(TAG, "isServiceEnabled(): failed " + ex.toString()); 2125 } finally { 2126 send(receiver, enabled); 2127 } 2128 } 2129 2130 @Override onPendingSaveUi(int operation, IBinder token)2131 public void onPendingSaveUi(int operation, IBinder token) { 2132 Objects.requireNonNull(token, "token"); 2133 Preconditions.checkArgument(operation == AutofillManager.PENDING_UI_OPERATION_CANCEL 2134 || operation == AutofillManager.PENDING_UI_OPERATION_RESTORE, 2135 "invalid operation: %d", operation); 2136 synchronized (mLock) { 2137 final AutofillManagerServiceImpl service = 2138 peekServiceForUserWithLocalBinderIdentityLocked( 2139 UserHandle.getCallingUserId()); 2140 if (service != null) { 2141 service.onPendingSaveUi(operation, token); 2142 } 2143 } 2144 } 2145 2146 @Override notifyImeAnimationStart(int sessionId, long startTimeMs, int userId)2147 public void notifyImeAnimationStart(int sessionId, long startTimeMs, int userId) { 2148 synchronized (mLock) { 2149 final AutofillManagerServiceImpl service = 2150 peekServiceForUserWithLocalBinderIdentityLocked(userId); 2151 if (service != null) { 2152 service.notifyImeAnimationStart(sessionId, startTimeMs, getCallingUid()); 2153 } else if (sVerbose) { 2154 Slog.v(TAG, "notifyImeAnimationStart(): no service for " + userId); 2155 } 2156 } 2157 } 2158 2159 @Override notifyImeAnimationEnd(int sessionId, long endTimeMs, int userId)2160 public void notifyImeAnimationEnd(int sessionId, long endTimeMs, int userId) { 2161 synchronized (mLock) { 2162 final AutofillManagerServiceImpl service = 2163 peekServiceForUserWithLocalBinderIdentityLocked(userId); 2164 if (service != null) { 2165 service.notifyImeAnimationEnd(sessionId, endTimeMs, getCallingUid()); 2166 } else if (sVerbose) { 2167 Slog.v(TAG, "notifyImeAnimationEnd(): no service for " + userId); 2168 } 2169 } 2170 } 2171 2172 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)2173 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2174 if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return; 2175 2176 boolean showHistory = true; 2177 boolean uiOnly = false; 2178 if (args != null) { 2179 for (String arg : args) { 2180 switch (arg) { 2181 case "--no-history": 2182 showHistory = false; 2183 break; 2184 case "--ui-only": 2185 uiOnly = true; 2186 break; 2187 case "--help": 2188 pw.println("Usage: dumpsys autofill [--ui-only|--no-history]"); 2189 return; 2190 default: 2191 Slog.w(TAG, "Ignoring invalid dump arg: " + arg); 2192 } 2193 } 2194 } 2195 2196 if (uiOnly) { 2197 mUi.dump(pw); 2198 return; 2199 } 2200 2201 final String prefix = " "; 2202 boolean realDebug = sDebug; 2203 boolean realVerbose = sVerbose; 2204 try { 2205 sDebug = sVerbose = true; 2206 synchronized (mLock) { 2207 pw.print("sDebug: "); 2208 pw.print(realDebug); 2209 pw.print(" sVerbose: "); 2210 pw.println(realVerbose); 2211 pw.print("Flags: "); 2212 synchronized (mFlagLock) { 2213 pw.print("mPccClassificationEnabled="); 2214 pw.print(mPccClassificationEnabled); 2215 pw.print(";"); 2216 pw.print("mPccPreferProviderOverPcc="); 2217 pw.print(mPccPreferProviderOverPcc); 2218 pw.print(";"); 2219 pw.print("mPccUseFallbackDetection="); 2220 pw.print(mPccUseFallbackDetection); 2221 pw.print(";"); 2222 pw.print("mPccProviderHints="); 2223 pw.println(mPccProviderHints); 2224 pw.print(";"); 2225 pw.print("mAutofillCredmanIntegrationEnabled="); 2226 pw.println(mAutofillCredmanIntegrationEnabled); 2227 } 2228 // Dump per-user services 2229 dumpLocked("", pw); 2230 mAugmentedAutofillResolver.dumpShort(pw); 2231 pw.println(); 2232 pw.print("Max partitions per session: "); 2233 pw.println(sPartitionMaxCount); 2234 pw.print("Max visible datasets: "); 2235 pw.println(sVisibleDatasetsMaxCount); 2236 if (sFullScreenMode != null) { 2237 pw.print("Overridden full-screen mode: "); 2238 pw.println(sFullScreenMode); 2239 } 2240 pw.println("User data constraints: "); 2241 UserData.dumpConstraints(prefix, pw); 2242 mUi.dump(pw); 2243 pw.print("Autofill Compat State: "); 2244 mAutofillCompatState.dump(prefix, pw); 2245 pw.print("from device config: "); 2246 pw.println(getAllowedCompatModePackagesFromDeviceConfig()); 2247 if (mSupportedSmartSuggestionModes != 0) { 2248 pw.print("Smart Suggestion modes: "); 2249 pw.println(getSmartSuggestionModeToString(mSupportedSmartSuggestionModes)); 2250 } 2251 pw.print("Augmented Service Idle Unbind Timeout: "); 2252 pw.println(mAugmentedServiceIdleUnbindTimeoutMs); 2253 pw.print("Augmented Service Request Timeout: "); 2254 pw.println(mAugmentedServiceRequestTimeoutMs); 2255 if (showHistory) { 2256 pw.println(); 2257 pw.println("Requests history:"); 2258 pw.println(); 2259 mRequestsHistory.reverseDump(fd, pw, args); 2260 pw.println(); 2261 pw.println("UI latency history:"); 2262 pw.println(); 2263 mUiLatencyHistory.reverseDump(fd, pw, args); 2264 pw.println(); 2265 pw.println("WTF history:"); 2266 pw.println(); 2267 mWtfHistory.reverseDump(fd, pw, args); 2268 } 2269 pw.println("Augmented Autofill State: "); 2270 mAugmentedAutofillState.dump(prefix, pw); 2271 } 2272 } finally { 2273 sDebug = realDebug; 2274 sVerbose = realVerbose; 2275 } 2276 } 2277 2278 @Override onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver)2279 public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, 2280 String[] args, ShellCallback callback, ResultReceiver resultReceiver) { 2281 new AutofillManagerServiceShellCommand(AutofillManagerService.this).exec( 2282 this, in, out, err, args, callback, resultReceiver); 2283 } 2284 } 2285 } 2286