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.view.autofill.AutofillManager.MAX_TEMP_AUGMENTED_SERVICE_DURATION_MS; 22 import static android.view.autofill.AutofillManager.getSmartSuggestionModeToString; 23 24 import static com.android.server.autofill.Helper.sDebug; 25 import static com.android.server.autofill.Helper.sFullScreenMode; 26 import static com.android.server.autofill.Helper.sVerbose; 27 28 import static java.util.Objects.requireNonNull; 29 30 import android.annotation.NonNull; 31 import android.annotation.Nullable; 32 import android.annotation.UserIdInt; 33 import android.app.ActivityManagerInternal; 34 import android.app.ActivityThread; 35 import android.content.AutofillOptions; 36 import android.content.BroadcastReceiver; 37 import android.content.ComponentName; 38 import android.content.ContentResolver; 39 import android.content.Context; 40 import android.content.Intent; 41 import android.content.IntentFilter; 42 import android.content.pm.PackageManager; 43 import android.content.pm.UserInfo; 44 import android.database.ContentObserver; 45 import android.graphics.Rect; 46 import android.os.Binder; 47 import android.os.Build; 48 import android.os.Bundle; 49 import android.os.IBinder; 50 import android.os.Parcelable; 51 import android.os.RemoteCallback; 52 import android.os.RemoteException; 53 import android.os.ResultReceiver; 54 import android.os.ShellCallback; 55 import android.os.SystemClock; 56 import android.os.UserHandle; 57 import android.os.UserManager; 58 import android.provider.DeviceConfig; 59 import android.provider.Settings; 60 import android.service.autofill.FillEventHistory; 61 import android.service.autofill.UserData; 62 import android.text.TextUtils; 63 import android.text.TextUtils.SimpleStringSplitter; 64 import android.util.ArrayMap; 65 import android.util.LocalLog; 66 import android.util.Slog; 67 import android.util.SparseArray; 68 import android.util.SparseBooleanArray; 69 import android.util.TimeUtils; 70 import android.view.autofill.AutofillId; 71 import android.view.autofill.AutofillManager; 72 import android.view.autofill.AutofillManager.SmartSuggestionMode; 73 import android.view.autofill.AutofillManagerInternal; 74 import android.view.autofill.AutofillValue; 75 import android.view.autofill.IAutoFillManager; 76 import android.view.autofill.IAutoFillManagerClient; 77 78 import com.android.internal.annotations.GuardedBy; 79 import com.android.internal.annotations.VisibleForTesting; 80 import com.android.internal.infra.AbstractRemoteService; 81 import com.android.internal.infra.GlobalWhitelistState; 82 import com.android.internal.infra.WhitelistHelper; 83 import com.android.internal.os.IResultReceiver; 84 import com.android.internal.util.DumpUtils; 85 import com.android.internal.util.Preconditions; 86 import com.android.internal.util.SyncResultReceiver; 87 import com.android.server.FgThread; 88 import com.android.server.LocalServices; 89 import com.android.server.autofill.ui.AutoFillUI; 90 import com.android.server.infra.AbstractMasterSystemService; 91 import com.android.server.infra.FrameworkResourcesServiceNameResolver; 92 import com.android.server.infra.SecureSettingsServiceNameResolver; 93 94 import java.io.FileDescriptor; 95 import java.io.PrintWriter; 96 import java.util.ArrayList; 97 import java.util.Arrays; 98 import java.util.List; 99 import java.util.Map; 100 import java.util.Objects; 101 import java.util.Set; 102 103 /** 104 * Entry point service for autofill management. 105 * 106 * <p>This service provides the {@link IAutoFillManager} implementation and keeps a list of 107 * {@link AutofillManagerServiceImpl} per user; the real work is done by 108 * {@link AutofillManagerServiceImpl} itself. 109 */ 110 public final class AutofillManagerService 111 extends AbstractMasterSystemService<AutofillManagerService, AutofillManagerServiceImpl> { 112 113 private static final String TAG = "AutofillManagerService"; 114 115 private static final Object sLock = AutofillManagerService.class; 116 117 static final String RECEIVER_BUNDLE_EXTRA_SESSIONS = "sessions"; 118 119 private static final char COMPAT_PACKAGE_DELIMITER = ':'; 120 private static final char COMPAT_PACKAGE_URL_IDS_DELIMITER = ','; 121 private static final char COMPAT_PACKAGE_URL_IDS_BLOCK_BEGIN = '['; 122 private static final char COMPAT_PACKAGE_URL_IDS_BLOCK_END = ']'; 123 124 private static final int DEFAULT_AUGMENTED_AUTOFILL_REQUEST_TIMEOUT_MILLIS = 5_000; 125 126 /** 127 * Maximum number of partitions that can be allowed in a session. 128 * 129 * <p>Can be modified using {@code cmd autofill set max_partitions} or through 130 * {@link android.provider.Settings.Global#AUTOFILL_MAX_PARTITIONS_SIZE}. 131 */ 132 @GuardedBy("sLock") 133 private static int sPartitionMaxCount = AutofillManager.DEFAULT_MAX_PARTITIONS_SIZE; 134 135 /** 136 * Maximum number of visible datasets in the dataset picker UI, or {@code 0} to use default 137 * value from resources. 138 * 139 * <p>Can be modified using {@code cmd autofill set max_visible_datasets} or through 140 * {@link android.provider.Settings.Global#AUTOFILL_MAX_VISIBLE_DATASETS}. 141 */ 142 @GuardedBy("sLock") 143 private static int sVisibleDatasetsMaxCount = 0; 144 145 /** 146 * Object used to set the name of the augmented autofill service. 147 */ 148 @NonNull 149 final FrameworkResourcesServiceNameResolver mAugmentedAutofillResolver; 150 151 private final AutoFillUI mUi; 152 153 private final LocalLog mRequestsHistory = new LocalLog(20); 154 private final LocalLog mUiLatencyHistory = new LocalLog(20); 155 private final LocalLog mWtfHistory = new LocalLog(50); 156 157 private final AutofillCompatState mAutofillCompatState = new AutofillCompatState(); 158 private final DisabledInfoCache mDisabledInfoCache = new DisabledInfoCache(); 159 160 private final LocalService mLocalService = new LocalService(); 161 private final ActivityManagerInternal mAm; 162 163 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 164 @Override 165 public void onReceive(Context context, Intent intent) { 166 if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) { 167 if (sDebug) Slog.d(TAG, "Close system dialogs"); 168 169 // TODO(b/64940307): we need to destroy all sessions that are finished but showing 170 // Save UI because there is no way to show the Save UI back when the activity 171 // beneath it is brought back to top. Ideally, we should just hide the UI and 172 // bring it back when the activity resumes. 173 synchronized (mLock) { 174 visitServicesLocked((s) -> s.forceRemoveFinishedSessionsLocked()); 175 } 176 mUi.hideAll(null); 177 } 178 } 179 }; 180 181 /** 182 * Supported modes for Augmented Autofill Smart Suggestions. 183 */ 184 @GuardedBy("mLock") 185 private int mSupportedSmartSuggestionModes; 186 187 @GuardedBy("mLock") 188 int mAugmentedServiceIdleUnbindTimeoutMs; 189 @GuardedBy("mLock") 190 int mAugmentedServiceRequestTimeoutMs; 191 192 final AugmentedAutofillState mAugmentedAutofillState = new AugmentedAutofillState(); 193 AutofillManagerService(Context context)194 public AutofillManagerService(Context context) { 195 super(context, 196 new SecureSettingsServiceNameResolver(context, Settings.Secure.AUTOFILL_SERVICE), 197 UserManager.DISALLOW_AUTOFILL, PACKAGE_UPDATE_POLICY_REFRESH_EAGER); 198 mUi = new AutoFillUI(ActivityThread.currentActivityThread().getSystemUiContext()); 199 mAm = LocalServices.getService(ActivityManagerInternal.class); 200 201 DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_AUTOFILL, 202 ActivityThread.currentApplication().getMainExecutor(), 203 (properties) -> onDeviceConfigChange(properties.getKeyset())); 204 205 setLogLevelFromSettings(); 206 setMaxPartitionsFromSettings(); 207 setMaxVisibleDatasetsFromSettings(); 208 setDeviceConfigProperties(); 209 210 final IntentFilter filter = new IntentFilter(); 211 filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); 212 context.registerReceiver(mBroadcastReceiver, filter, null, FgThread.getHandler()); 213 214 mAugmentedAutofillResolver = new FrameworkResourcesServiceNameResolver(getContext(), 215 com.android.internal.R.string.config_defaultAugmentedAutofillService); 216 mAugmentedAutofillResolver.setOnTemporaryServiceNameChangedCallback( 217 (u, s, t) -> onAugmentedServiceNameChanged(u, s, t)); 218 219 if (mSupportedSmartSuggestionModes != AutofillManager.FLAG_SMART_SUGGESTION_OFF) { 220 final List<UserInfo> users = getSupportedUsers(); 221 for (int i = 0; i < users.size(); i++) { 222 final int userId = users.get(i).id; 223 // Must eager load the services so they bind to the augmented autofill service 224 getServiceForUserLocked(userId); 225 226 // And also set the global state 227 mAugmentedAutofillState.setServiceInfo(userId, 228 mAugmentedAutofillResolver.getServiceName(userId), 229 mAugmentedAutofillResolver.isTemporary(userId)); 230 } 231 } 232 } 233 234 @Override // from AbstractMasterSystemService getServiceSettingsProperty()235 protected String getServiceSettingsProperty() { 236 return Settings.Secure.AUTOFILL_SERVICE; 237 } 238 239 @Override // from AbstractMasterSystemService registerForExtraSettingsChanges(@onNull ContentResolver resolver, @NonNull ContentObserver observer)240 protected void registerForExtraSettingsChanges(@NonNull ContentResolver resolver, 241 @NonNull ContentObserver observer) { 242 resolver.registerContentObserver(Settings.Global.getUriFor( 243 Settings.Global.AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES), false, observer, 244 UserHandle.USER_ALL); 245 resolver.registerContentObserver(Settings.Global.getUriFor( 246 Settings.Global.AUTOFILL_LOGGING_LEVEL), false, observer, 247 UserHandle.USER_ALL); 248 resolver.registerContentObserver(Settings.Global.getUriFor( 249 Settings.Global.AUTOFILL_MAX_PARTITIONS_SIZE), false, observer, 250 UserHandle.USER_ALL); 251 resolver.registerContentObserver(Settings.Global.getUriFor( 252 Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS), false, observer, 253 UserHandle.USER_ALL); 254 resolver.registerContentObserver(Settings.Secure.getUriFor( 255 Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE), false, observer, 256 UserHandle.USER_ALL); 257 } 258 259 @Override // from AbstractMasterSystemService onSettingsChanged(int userId, @NonNull String property)260 protected void onSettingsChanged(int userId, @NonNull String property) { 261 switch (property) { 262 case Settings.Global.AUTOFILL_LOGGING_LEVEL: 263 setLogLevelFromSettings(); 264 break; 265 case Settings.Global.AUTOFILL_MAX_PARTITIONS_SIZE: 266 setMaxPartitionsFromSettings(); 267 break; 268 case Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS: 269 setMaxVisibleDatasetsFromSettings(); 270 break; 271 case Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE: 272 handleInputMethodSwitch(userId); 273 break; 274 default: 275 Slog.w(TAG, "Unexpected property (" + property + "); updating cache instead"); 276 // fall through 277 case Settings.Global.AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES: 278 synchronized (mLock) { 279 updateCachedServiceLocked(userId); 280 } 281 } 282 } 283 handleInputMethodSwitch(@serIdInt int userId)284 private void handleInputMethodSwitch(@UserIdInt int userId) { 285 // TODO(b/156903336): Used the SettingsObserver with a background thread maybe slow to 286 // respond to the IME switch in certain situations. 287 // See: services/core/java/com/android/server/FgThread.java 288 // In particular, the shared background thread could be doing relatively long-running 289 // operations like saving state to disk (in addition to simply being a background priority), 290 // which can cause operations scheduled on it to be delayed for a user-noticeable amount 291 // of time. 292 293 synchronized (mLock) { 294 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 295 if (service != null) { 296 service.onSwitchInputMethod(); 297 } 298 } 299 } 300 onDeviceConfigChange(@onNull Set<String> keys)301 private void onDeviceConfigChange(@NonNull Set<String> keys) { 302 for (String key : keys) { 303 switch (key) { 304 case AutofillManager.DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES: 305 case AutofillManager.DEVICE_CONFIG_AUGMENTED_SERVICE_IDLE_UNBIND_TIMEOUT: 306 case AutofillManager.DEVICE_CONFIG_AUGMENTED_SERVICE_REQUEST_TIMEOUT: 307 setDeviceConfigProperties(); 308 break; 309 default: 310 Slog.i(mTag, "Ignoring change on " + key); 311 } 312 } 313 } 314 onAugmentedServiceNameChanged(@serIdInt int userId, @Nullable String serviceName, boolean isTemporary)315 private void onAugmentedServiceNameChanged(@UserIdInt int userId, @Nullable String serviceName, 316 boolean isTemporary) { 317 mAugmentedAutofillState.setServiceInfo(userId, serviceName, isTemporary); 318 synchronized (mLock) { 319 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 320 if (service == null) { 321 // If we cannot get the service from the services cache, it will call 322 // updateRemoteAugmentedAutofillService() finally. Skip call this update again. 323 getServiceForUserLocked(userId); 324 } else { 325 service.updateRemoteAugmentedAutofillService(); 326 } 327 } 328 } 329 330 @Override // from AbstractMasterSystemService newServiceLocked(@serIdInt int resolvedUserId, boolean disabled)331 protected AutofillManagerServiceImpl newServiceLocked(@UserIdInt int resolvedUserId, 332 boolean disabled) { 333 return new AutofillManagerServiceImpl(this, mLock, mUiLatencyHistory, mWtfHistory, 334 resolvedUserId, mUi, mAutofillCompatState, disabled, mDisabledInfoCache); 335 } 336 337 @Override // AbstractMasterSystemService onServiceRemoved(@onNull AutofillManagerServiceImpl service, @UserIdInt int userId)338 protected void onServiceRemoved(@NonNull AutofillManagerServiceImpl service, 339 @UserIdInt int userId) { 340 service.destroyLocked(); 341 mDisabledInfoCache.remove(userId); 342 mAutofillCompatState.removeCompatibilityModeRequests(userId); 343 } 344 345 @Override // from AbstractMasterSystemService onServiceEnabledLocked(@onNull AutofillManagerServiceImpl service, @UserIdInt int userId)346 protected void onServiceEnabledLocked(@NonNull AutofillManagerServiceImpl service, 347 @UserIdInt int userId) { 348 addCompatibilityModeRequestsLocked(service, userId); 349 } 350 351 @Override // from AbstractMasterSystemService enforceCallingPermissionForManagement()352 protected void enforceCallingPermissionForManagement() { 353 getContext().enforceCallingPermission(MANAGE_AUTO_FILL, TAG); 354 } 355 356 @Override // from SystemService onStart()357 public void onStart() { 358 publishBinderService(AUTOFILL_MANAGER_SERVICE, new AutoFillManagerServiceStub()); 359 publishLocalService(AutofillManagerInternal.class, mLocalService); 360 } 361 362 @Override // from SystemService isUserSupported(TargetUser user)363 public boolean isUserSupported(TargetUser user) { 364 return user.isFull() || user.isManagedProfile(); 365 } 366 367 @Override // from SystemService onUserSwitching(@ullable TargetUser from, @NonNull TargetUser to)368 public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) { 369 if (sDebug) Slog.d(TAG, "Hiding UI when user switched"); 370 mUi.hideAll(null); 371 } 372 getSupportedSmartSuggestionModesLocked()373 @SmartSuggestionMode int getSupportedSmartSuggestionModesLocked() { 374 return mSupportedSmartSuggestionModes; 375 } 376 377 /** 378 * Logs a request so it's dumped later... 379 */ logRequestLocked(@onNull String historyItem)380 void logRequestLocked(@NonNull String historyItem) { 381 mRequestsHistory.log(historyItem); 382 } 383 384 // Called by AutofillManagerServiceImpl, doesn't need to check permission isInstantServiceAllowed()385 boolean isInstantServiceAllowed() { 386 return mAllowInstantService; 387 } 388 389 // Called by Shell command. removeAllSessions(@serIdInt int userId, IResultReceiver receiver)390 void removeAllSessions(@UserIdInt int userId, IResultReceiver receiver) { 391 Slog.i(TAG, "removeAllSessions() for userId " + userId); 392 enforceCallingPermissionForManagement(); 393 394 synchronized (mLock) { 395 if (userId != UserHandle.USER_ALL) { 396 AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 397 if (service != null) { 398 service.forceRemoveAllSessionsLocked(); 399 } 400 } else { 401 visitServicesLocked((s) -> s.forceRemoveAllSessionsLocked()); 402 } 403 } 404 405 try { 406 receiver.send(0, new Bundle()); 407 } catch (RemoteException e) { 408 // Just ignore it... 409 } 410 } 411 412 // Called by Shell command. listSessions(int userId, IResultReceiver receiver)413 void listSessions(int userId, IResultReceiver receiver) { 414 Slog.i(TAG, "listSessions() for userId " + userId); 415 enforceCallingPermissionForManagement(); 416 417 final Bundle resultData = new Bundle(); 418 final ArrayList<String> sessions = new ArrayList<>(); 419 420 synchronized (mLock) { 421 if (userId != UserHandle.USER_ALL) { 422 AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 423 if (service != null) { 424 service.listSessionsLocked(sessions); 425 } 426 } else { 427 visitServicesLocked((s) -> s.listSessionsLocked(sessions)); 428 } 429 } 430 431 resultData.putStringArrayList(RECEIVER_BUNDLE_EXTRA_SESSIONS, sessions); 432 try { 433 receiver.send(0, resultData); 434 } catch (RemoteException e) { 435 // Just ignore it... 436 } 437 } 438 439 // Called by Shell command. reset()440 void reset() { 441 Slog.i(TAG, "reset()"); 442 enforceCallingPermissionForManagement(); 443 444 synchronized (mLock) { 445 visitServicesLocked((s) -> s.destroyLocked()); 446 clearCacheLocked(); 447 } 448 } 449 450 // Called by Shell command. setLogLevel(int level)451 void setLogLevel(int level) { 452 Slog.i(TAG, "setLogLevel(): " + level); 453 enforceCallingPermissionForManagement(); 454 455 final long token = Binder.clearCallingIdentity(); 456 try { 457 Settings.Global.putInt(getContext().getContentResolver(), 458 Settings.Global.AUTOFILL_LOGGING_LEVEL, level); 459 } finally { 460 Binder.restoreCallingIdentity(token); 461 } 462 } 463 setLogLevelFromSettings()464 private void setLogLevelFromSettings() { 465 final int level = Settings.Global.getInt( 466 getContext().getContentResolver(), 467 Settings.Global.AUTOFILL_LOGGING_LEVEL, AutofillManager.DEFAULT_LOGGING_LEVEL); 468 boolean debug = false; 469 boolean verbose = false; 470 if (level != AutofillManager.NO_LOGGING) { 471 if (level == AutofillManager.FLAG_ADD_CLIENT_VERBOSE) { 472 debug = verbose = true; 473 } else if (level == AutofillManager.FLAG_ADD_CLIENT_DEBUG) { 474 debug = true; 475 } else { 476 Slog.w(TAG, "setLogLevelFromSettings(): invalid level: " + level); 477 } 478 } 479 if (debug || sDebug) { 480 Slog.d(TAG, "setLogLevelFromSettings(): level=" + level + ", debug=" + debug 481 + ", verbose=" + verbose); 482 } 483 synchronized (mLock) { 484 setLoggingLevelsLocked(debug, verbose); 485 } 486 } 487 488 // Called by Shell command. getLogLevel()489 int getLogLevel() { 490 enforceCallingPermissionForManagement(); 491 492 synchronized (mLock) { 493 if (sVerbose) return AutofillManager.FLAG_ADD_CLIENT_VERBOSE; 494 if (sDebug) return AutofillManager.FLAG_ADD_CLIENT_DEBUG; 495 return 0; 496 } 497 } 498 499 // Called by Shell command. getMaxPartitions()500 int getMaxPartitions() { 501 enforceCallingPermissionForManagement(); 502 503 synchronized (mLock) { 504 return sPartitionMaxCount; 505 } 506 } 507 508 // Called by Shell command. setMaxPartitions(int max)509 void setMaxPartitions(int max) { 510 Slog.i(TAG, "setMaxPartitions(): " + max); 511 enforceCallingPermissionForManagement(); 512 513 final long token = Binder.clearCallingIdentity(); 514 try { 515 Settings.Global.putInt(getContext().getContentResolver(), 516 Settings.Global.AUTOFILL_MAX_PARTITIONS_SIZE, max); 517 } finally { 518 Binder.restoreCallingIdentity(token); 519 } 520 } 521 setMaxPartitionsFromSettings()522 private void setMaxPartitionsFromSettings() { 523 final int max = Settings.Global.getInt(getContext().getContentResolver(), 524 Settings.Global.AUTOFILL_MAX_PARTITIONS_SIZE, 525 AutofillManager.DEFAULT_MAX_PARTITIONS_SIZE); 526 if (sDebug) Slog.d(TAG, "setMaxPartitionsFromSettings(): " + max); 527 528 synchronized (sLock) { 529 sPartitionMaxCount = max; 530 } 531 } 532 533 // Called by Shell command. getMaxVisibleDatasets()534 int getMaxVisibleDatasets() { 535 enforceCallingPermissionForManagement(); 536 537 synchronized (sLock) { 538 return sVisibleDatasetsMaxCount; 539 } 540 } 541 542 // Called by Shell command. setMaxVisibleDatasets(int max)543 void setMaxVisibleDatasets(int max) { 544 Slog.i(TAG, "setMaxVisibleDatasets(): " + max); 545 enforceCallingPermissionForManagement(); 546 547 final long token = Binder.clearCallingIdentity(); 548 try { 549 Settings.Global.putInt(getContext().getContentResolver(), 550 Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS, max); 551 } finally { 552 Binder.restoreCallingIdentity(token); 553 } 554 } 555 setMaxVisibleDatasetsFromSettings()556 private void setMaxVisibleDatasetsFromSettings() { 557 final int max = Settings.Global.getInt(getContext().getContentResolver(), 558 Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS, 0); 559 560 if (sDebug) Slog.d(TAG, "setMaxVisibleDatasetsFromSettings(): " + max); 561 synchronized (sLock) { 562 sVisibleDatasetsMaxCount = max; 563 } 564 } 565 setDeviceConfigProperties()566 private void setDeviceConfigProperties() { 567 synchronized (mLock) { 568 mAugmentedServiceIdleUnbindTimeoutMs = DeviceConfig.getInt( 569 DeviceConfig.NAMESPACE_AUTOFILL, 570 AutofillManager.DEVICE_CONFIG_AUGMENTED_SERVICE_IDLE_UNBIND_TIMEOUT, 571 (int) AbstractRemoteService.PERMANENT_BOUND_TIMEOUT_MS); 572 mAugmentedServiceRequestTimeoutMs = DeviceConfig.getInt( 573 DeviceConfig.NAMESPACE_AUTOFILL, 574 AutofillManager.DEVICE_CONFIG_AUGMENTED_SERVICE_REQUEST_TIMEOUT, 575 DEFAULT_AUGMENTED_AUTOFILL_REQUEST_TIMEOUT_MILLIS); 576 mSupportedSmartSuggestionModes = DeviceConfig.getInt( 577 DeviceConfig.NAMESPACE_AUTOFILL, 578 AutofillManager.DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES, 579 AutofillManager.FLAG_SMART_SUGGESTION_SYSTEM); 580 if (verbose) { 581 Slog.v(mTag, "setDeviceConfigProperties(): " 582 + "augmentedIdleTimeout=" + mAugmentedServiceIdleUnbindTimeoutMs 583 + ", augmentedRequestTimeout=" + mAugmentedServiceRequestTimeoutMs 584 + ", smartSuggestionMode=" 585 + getSmartSuggestionModeToString(mSupportedSmartSuggestionModes)); 586 } 587 } 588 } 589 590 // Called by Shell command. calculateScore(@ullable String algorithmName, @NonNull String value1, @NonNull String value2, @NonNull RemoteCallback callback)591 void calculateScore(@Nullable String algorithmName, @NonNull String value1, 592 @NonNull String value2, @NonNull RemoteCallback callback) { 593 enforceCallingPermissionForManagement(); 594 595 final FieldClassificationStrategy strategy = 596 new FieldClassificationStrategy(getContext(), UserHandle.USER_CURRENT); 597 598 strategy.calculateScores(callback, Arrays.asList(AutofillValue.forText(value1)), 599 new String[] { value2 }, new String[] { null }, algorithmName, null, null, null); 600 } 601 602 // Called by Shell command. getFullScreenMode()603 Boolean getFullScreenMode() { 604 enforceCallingPermissionForManagement(); 605 return sFullScreenMode; 606 } 607 608 // Called by Shell command. setFullScreenMode(@ullable Boolean mode)609 void setFullScreenMode(@Nullable Boolean mode) { 610 enforceCallingPermissionForManagement(); 611 sFullScreenMode = mode; 612 } 613 614 // Called by Shell command. setTemporaryAugmentedAutofillService(@serIdInt int userId, @NonNull String serviceName, int durationMs)615 void setTemporaryAugmentedAutofillService(@UserIdInt int userId, @NonNull String serviceName, 616 int durationMs) { 617 Slog.i(mTag, "setTemporaryAugmentedAutofillService(" + userId + ") to " + serviceName 618 + " for " + durationMs + "ms"); 619 enforceCallingPermissionForManagement(); 620 621 Preconditions.checkNotNull(serviceName); 622 if (durationMs > MAX_TEMP_AUGMENTED_SERVICE_DURATION_MS) { 623 throw new IllegalArgumentException("Max duration is " 624 + MAX_TEMP_AUGMENTED_SERVICE_DURATION_MS + " (called with " + durationMs + ")"); 625 } 626 627 mAugmentedAutofillResolver.setTemporaryService(userId, serviceName, durationMs); 628 } 629 630 // Called by Shell command resetTemporaryAugmentedAutofillService(@serIdInt int userId)631 void resetTemporaryAugmentedAutofillService(@UserIdInt int userId) { 632 enforceCallingPermissionForManagement(); 633 mAugmentedAutofillResolver.resetTemporaryService(userId); 634 } 635 636 // Called by Shell command isDefaultAugmentedServiceEnabled(@serIdInt int userId)637 boolean isDefaultAugmentedServiceEnabled(@UserIdInt int userId) { 638 enforceCallingPermissionForManagement(); 639 return mAugmentedAutofillResolver.isDefaultServiceEnabled(userId); 640 } 641 642 // Called by Shell command setDefaultAugmentedServiceEnabled(@serIdInt int userId, boolean enabled)643 boolean setDefaultAugmentedServiceEnabled(@UserIdInt int userId, boolean enabled) { 644 Slog.i(mTag, "setDefaultAugmentedServiceEnabled() for userId " + userId + ": " + enabled); 645 enforceCallingPermissionForManagement(); 646 647 synchronized (mLock) { 648 final AutofillManagerServiceImpl service = getServiceForUserLocked(userId); 649 if (service != null) { 650 final boolean changed = mAugmentedAutofillResolver 651 .setDefaultServiceEnabled(userId, enabled); 652 if (changed) { 653 service.updateRemoteAugmentedAutofillService(); 654 return true; 655 } else { 656 if (debug) { 657 Slog.d(TAG, "setDefaultAugmentedServiceEnabled(): already " + enabled); 658 } 659 } 660 } 661 } 662 return false; 663 } 664 665 /** 666 * Requests a count of saved passwords from the current service. 667 * 668 * @return {@code true} if the request succeeded 669 */ 670 // Called by Shell command requestSavedPasswordCount(@serIdInt int userId, @NonNull IResultReceiver receiver)671 boolean requestSavedPasswordCount(@UserIdInt int userId, @NonNull IResultReceiver receiver) { 672 enforceCallingPermissionForManagement(); 673 synchronized (mLock) { 674 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 675 if (service != null) { 676 service.requestSavedPasswordCount(receiver); 677 return true; 678 } else if (sVerbose) { 679 Slog.v(TAG, "requestSavedPasswordCount(): no service for " + userId); 680 } 681 } 682 return false; 683 } 684 setLoggingLevelsLocked(boolean debug, boolean verbose)685 private void setLoggingLevelsLocked(boolean debug, boolean verbose) { 686 com.android.server.autofill.Helper.sDebug = debug; 687 android.view.autofill.Helper.sDebug = debug; 688 this.debug = debug; 689 690 com.android.server.autofill.Helper.sVerbose = verbose; 691 android.view.autofill.Helper.sVerbose = verbose; 692 this.verbose = verbose; 693 } 694 addCompatibilityModeRequestsLocked(@onNull AutofillManagerServiceImpl service , int userId)695 private void addCompatibilityModeRequestsLocked(@NonNull AutofillManagerServiceImpl service 696 , int userId) { 697 mAutofillCompatState.reset(userId); 698 final ArrayMap<String, Long> compatPackages = 699 service.getCompatibilityPackagesLocked(); 700 if (compatPackages == null || compatPackages.isEmpty()) { 701 return; 702 } 703 704 final Map<String, String[]> whiteListedPackages = getWhitelistedCompatModePackages(); 705 final int compatPackageCount = compatPackages.size(); 706 for (int i = 0; i < compatPackageCount; i++) { 707 final String packageName = compatPackages.keyAt(i); 708 if (whiteListedPackages == null || !whiteListedPackages.containsKey(packageName)) { 709 Slog.w(TAG, "Ignoring not whitelisted compat package " + packageName); 710 continue; 711 } 712 final Long maxVersionCode = compatPackages.valueAt(i); 713 if (maxVersionCode != null) { 714 mAutofillCompatState.addCompatibilityModeRequest(packageName, 715 maxVersionCode, whiteListedPackages.get(packageName), userId); 716 } 717 } 718 } 719 getWhitelistedCompatModePackagesFromSettings()720 private String getWhitelistedCompatModePackagesFromSettings() { 721 return Settings.Global.getString( 722 getContext().getContentResolver(), 723 Settings.Global.AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES); 724 } 725 726 @Nullable getWhitelistedCompatModePackages()727 private Map<String, String[]> getWhitelistedCompatModePackages() { 728 return getWhitelistedCompatModePackages(getWhitelistedCompatModePackagesFromSettings()); 729 } 730 send(@onNull IResultReceiver receiver, int value)731 private void send(@NonNull IResultReceiver receiver, int value) { 732 try { 733 receiver.send(value, null); 734 } catch (RemoteException e) { 735 Slog.w(TAG, "Error async reporting result to client: " + e); 736 } 737 } 738 send(@onNull IResultReceiver receiver, @NonNull Bundle value)739 private void send(@NonNull IResultReceiver receiver, @NonNull Bundle value) { 740 try { 741 receiver.send(0, value); 742 } catch (RemoteException e) { 743 Slog.w(TAG, "Error async reporting result to client: " + e); 744 } 745 } 746 send(@onNull IResultReceiver receiver, @Nullable String value)747 private void send(@NonNull IResultReceiver receiver, @Nullable String value) { 748 send(receiver, SyncResultReceiver.bundleFor(value)); 749 } 750 send(@onNull IResultReceiver receiver, @Nullable String[] value)751 private void send(@NonNull IResultReceiver receiver, @Nullable String[] value) { 752 send(receiver, SyncResultReceiver.bundleFor(value)); 753 } 754 send(@onNull IResultReceiver receiver, @Nullable Parcelable value)755 private void send(@NonNull IResultReceiver receiver, @Nullable Parcelable value) { 756 send(receiver, SyncResultReceiver.bundleFor(value)); 757 } 758 send(@onNull IResultReceiver receiver, boolean value)759 private void send(@NonNull IResultReceiver receiver, boolean value) { 760 send(receiver, value ? 1 : 0); 761 } 762 send(@onNull IResultReceiver receiver, int value1, int value2)763 private void send(@NonNull IResultReceiver receiver, int value1, int value2) { 764 try { 765 receiver.send(value1, SyncResultReceiver.bundleFor(value2)); 766 } catch (RemoteException e) { 767 Slog.w(TAG, "Error async reporting result to client: " + e); 768 } 769 } 770 771 @Nullable 772 @VisibleForTesting getWhitelistedCompatModePackages(String setting)773 static Map<String, String[]> getWhitelistedCompatModePackages(String setting) { 774 if (TextUtils.isEmpty(setting)) { 775 return null; 776 } 777 778 final ArrayMap<String, String[]> compatPackages = new ArrayMap<>(); 779 final SimpleStringSplitter splitter = new SimpleStringSplitter(COMPAT_PACKAGE_DELIMITER); 780 splitter.setString(setting); 781 while (splitter.hasNext()) { 782 final String packageBlock = splitter.next(); 783 final int urlBlockIndex = packageBlock.indexOf(COMPAT_PACKAGE_URL_IDS_BLOCK_BEGIN); 784 final String packageName; 785 final List<String> urlBarIds; 786 if (urlBlockIndex == -1) { 787 packageName = packageBlock; 788 urlBarIds = null; 789 } else { 790 if (packageBlock.charAt(packageBlock.length() - 1) 791 != COMPAT_PACKAGE_URL_IDS_BLOCK_END) { 792 Slog.w(TAG, "Ignoring entry '" + packageBlock + "' on '" + setting 793 + "'because it does not end on '" + COMPAT_PACKAGE_URL_IDS_BLOCK_END + 794 "'"); 795 continue; 796 } 797 packageName = packageBlock.substring(0, urlBlockIndex); 798 urlBarIds = new ArrayList<>(); 799 final String urlBarIdsBlock = 800 packageBlock.substring(urlBlockIndex + 1, packageBlock.length() - 1); 801 if (sVerbose) { 802 Slog.v(TAG, "pkg:" + packageName + ": block:" + packageBlock + ": urls:" 803 + urlBarIds + ": block:" + urlBarIdsBlock + ":"); 804 } 805 final SimpleStringSplitter splitter2 = 806 new SimpleStringSplitter(COMPAT_PACKAGE_URL_IDS_DELIMITER); 807 splitter2.setString(urlBarIdsBlock); 808 while (splitter2.hasNext()) { 809 final String urlBarId = splitter2.next(); 810 urlBarIds.add(urlBarId); 811 } 812 } 813 if (urlBarIds == null) { 814 compatPackages.put(packageName, null); 815 } else { 816 final String[] urlBarIdsArray = new String[urlBarIds.size()]; 817 urlBarIds.toArray(urlBarIdsArray); 818 compatPackages.put(packageName, urlBarIdsArray); 819 } 820 } 821 return compatPackages; 822 } 823 824 /** 825 * Gets the maximum number of partitions / fill requests. 826 */ getPartitionMaxCount()827 public static int getPartitionMaxCount() { 828 synchronized (sLock) { 829 return sPartitionMaxCount; 830 } 831 } 832 833 /** 834 * Gets the maxium number of datasets visible in the UI. 835 */ getVisibleDatasetsMaxCount()836 public static int getVisibleDatasetsMaxCount() { 837 synchronized (sLock) { 838 return sVisibleDatasetsMaxCount; 839 } 840 } 841 842 private final class LocalService extends AutofillManagerInternal { 843 @Override onBackKeyPressed()844 public void onBackKeyPressed() { 845 if (sDebug) Slog.d(TAG, "onBackKeyPressed()"); 846 mUi.hideAll(null); 847 synchronized (mLock) { 848 final AutofillManagerServiceImpl service = 849 getServiceForUserLocked(UserHandle.getCallingUserId()); 850 service.onBackKeyPressed(); 851 } 852 } 853 854 @Override getAutofillOptions(@onNull String packageName, long versionCode, @UserIdInt int userId)855 public AutofillOptions getAutofillOptions(@NonNull String packageName, 856 long versionCode, @UserIdInt int userId) { 857 final int loggingLevel; 858 if (verbose) { 859 loggingLevel = AutofillManager.FLAG_ADD_CLIENT_VERBOSE 860 | AutofillManager.FLAG_ADD_CLIENT_DEBUG; 861 } else if (debug) { 862 loggingLevel = AutofillManager.FLAG_ADD_CLIENT_DEBUG; 863 } else { 864 loggingLevel = AutofillManager.NO_LOGGING; 865 } 866 final boolean compatModeEnabled = mAutofillCompatState.isCompatibilityModeRequested( 867 packageName, versionCode, userId); 868 final AutofillOptions options = new AutofillOptions(loggingLevel, compatModeEnabled); 869 mAugmentedAutofillState.injectAugmentedAutofillInfo(options, userId, packageName); 870 injectDisableAppInfo(options, userId, packageName); 871 return options; 872 } 873 874 @Override isAugmentedAutofillServiceForUser(int callingUid, int userId)875 public boolean isAugmentedAutofillServiceForUser(int callingUid, int userId) { 876 synchronized (mLock) { 877 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 878 if (service != null) { 879 return service.isAugmentedAutofillServiceForUserLocked(callingUid); 880 } 881 } 882 return false; 883 } 884 injectDisableAppInfo(@onNull AutofillOptions options, int userId, String packageName)885 private void injectDisableAppInfo(@NonNull AutofillOptions options, int userId, 886 String packageName) { 887 options.appDisabledExpiration = 888 mDisabledInfoCache.getAppDisabledExpiration(userId, packageName); 889 options.disabledActivities = 890 mDisabledInfoCache.getAppDisabledActivities(userId, packageName); 891 } 892 } 893 894 /** 895 * Compatibility mode metadata per package. 896 */ 897 static final class PackageCompatState { 898 private final long maxVersionCode; 899 private final String[] urlBarResourceIds; 900 PackageCompatState(long maxVersionCode, String[] urlBarResourceIds)901 PackageCompatState(long maxVersionCode, String[] urlBarResourceIds) { 902 this.maxVersionCode = maxVersionCode; 903 this.urlBarResourceIds = urlBarResourceIds; 904 } 905 906 @Override toString()907 public String toString() { 908 return "maxVersionCode=" + maxVersionCode 909 + ", urlBarResourceIds=" + Arrays.toString(urlBarResourceIds); 910 } 911 } 912 913 /** 914 * Stores autofill disable information, i.e. {@link AutofillDisabledInfo}, keyed by user id. 915 * The information is cleaned up when the service is removed. 916 */ 917 static final class DisabledInfoCache { 918 919 private final Object mLock = new Object(); 920 921 @GuardedBy("mLock") 922 private final SparseArray<AutofillDisabledInfo> mCache = new SparseArray<>(); 923 remove(@serIdInt int userId)924 void remove(@UserIdInt int userId) { 925 synchronized (mLock) { 926 mCache.remove(userId); 927 } 928 } 929 addDisabledAppLocked(@serIdInt int userId, @NonNull String packageName, long expiration)930 void addDisabledAppLocked(@UserIdInt int userId, @NonNull String packageName, 931 long expiration) { 932 Preconditions.checkNotNull(packageName); 933 synchronized (mLock) { 934 AutofillDisabledInfo info = 935 getOrCreateAutofillDisabledInfoByUserIdLocked(userId); 936 info.putDisableAppsLocked(packageName, expiration); 937 } 938 } 939 addDisabledActivityLocked(@serIdInt int userId, @NonNull ComponentName componentName, long expiration)940 void addDisabledActivityLocked(@UserIdInt int userId, @NonNull ComponentName componentName, 941 long expiration) { 942 Preconditions.checkNotNull(componentName); 943 synchronized (mLock) { 944 AutofillDisabledInfo info = 945 getOrCreateAutofillDisabledInfoByUserIdLocked(userId); 946 info.putDisableActivityLocked(componentName, expiration); 947 } 948 } 949 isAutofillDisabledLocked(@serIdInt int userId, @NonNull ComponentName componentName)950 boolean isAutofillDisabledLocked(@UserIdInt int userId, 951 @NonNull ComponentName componentName) { 952 Preconditions.checkNotNull(componentName); 953 final boolean disabled; 954 synchronized (mLock) { 955 final AutofillDisabledInfo info = mCache.get(userId); 956 disabled = info != null ? info.isAutofillDisabledLocked(componentName) : false; 957 } 958 return disabled; 959 } 960 getAppDisabledExpiration(@serIdInt int userId, @NonNull String packageName)961 long getAppDisabledExpiration(@UserIdInt int userId, @NonNull String packageName) { 962 Preconditions.checkNotNull(packageName); 963 final Long expiration; 964 synchronized (mLock) { 965 final AutofillDisabledInfo info = mCache.get(userId); 966 expiration = info != null ? info.getAppDisabledExpirationLocked(packageName) : 0; 967 } 968 return expiration; 969 } 970 971 @Nullable getAppDisabledActivities(@serIdInt int userId, @NonNull String packageName)972 ArrayMap<String, Long> getAppDisabledActivities(@UserIdInt int userId, 973 @NonNull String packageName) { 974 Preconditions.checkNotNull(packageName); 975 final ArrayMap<String, Long> disabledList; 976 synchronized (mLock) { 977 final AutofillDisabledInfo info = mCache.get(userId); 978 disabledList = 979 info != null ? info.getAppDisabledActivitiesLocked(packageName) : null; 980 } 981 return disabledList; 982 } 983 dump(@serIdInt int userId, String prefix, PrintWriter pw)984 void dump(@UserIdInt int userId, String prefix, PrintWriter pw) { 985 synchronized (mLock) { 986 final AutofillDisabledInfo info = mCache.get(userId); 987 if (info != null) { 988 info.dumpLocked(prefix, pw); 989 } 990 } 991 } 992 993 @NonNull getOrCreateAutofillDisabledInfoByUserIdLocked( @serIdInt int userId)994 private AutofillDisabledInfo getOrCreateAutofillDisabledInfoByUserIdLocked( 995 @UserIdInt int userId) { 996 AutofillDisabledInfo info = mCache.get(userId); 997 if (info == null) { 998 info = new AutofillDisabledInfo(); 999 mCache.put(userId, info); 1000 } 1001 return info; 1002 } 1003 } 1004 1005 /** 1006 * The autofill disable information. 1007 * <p> 1008 * This contains disable information set by the AutofillService, e.g. disabled application 1009 * expiration, disable activity expiration. 1010 */ 1011 private static final class AutofillDisabledInfo { 1012 /** 1013 * Apps disabled by the service; key is package name, value is when they will be enabled 1014 * again. 1015 */ 1016 private ArrayMap<String, Long> mDisabledApps; 1017 /** 1018 * Activities disabled by the service; key is component name, value is when they will be 1019 * enabled again. 1020 */ 1021 private ArrayMap<ComponentName, Long> mDisabledActivities; 1022 putDisableAppsLocked(@onNull String packageName, long expiration)1023 void putDisableAppsLocked(@NonNull String packageName, long expiration) { 1024 if (mDisabledApps == null) { 1025 mDisabledApps = new ArrayMap<>(1); 1026 } 1027 mDisabledApps.put(packageName, expiration); 1028 } 1029 putDisableActivityLocked(@onNull ComponentName componentName, long expiration)1030 void putDisableActivityLocked(@NonNull ComponentName componentName, long expiration) { 1031 if (mDisabledActivities == null) { 1032 mDisabledActivities = new ArrayMap<>(1); 1033 } 1034 mDisabledActivities.put(componentName, expiration); 1035 } 1036 getAppDisabledExpirationLocked(@onNull String packageName)1037 long getAppDisabledExpirationLocked(@NonNull String packageName) { 1038 if (mDisabledApps == null) { 1039 return 0; 1040 } 1041 final Long expiration = mDisabledApps.get(packageName); 1042 return expiration != null ? expiration : 0; 1043 } 1044 getAppDisabledActivitiesLocked(@onNull String packageName)1045 ArrayMap<String, Long> getAppDisabledActivitiesLocked(@NonNull String packageName) { 1046 if (mDisabledActivities != null) { 1047 final int size = mDisabledActivities.size(); 1048 ArrayMap<String, Long> disabledList = null; 1049 for (int i = 0; i < size; i++) { 1050 final ComponentName component = mDisabledActivities.keyAt(i); 1051 if (packageName.equals(component.getPackageName())) { 1052 if (disabledList == null) { 1053 disabledList = new ArrayMap<>(); 1054 } 1055 final long expiration = mDisabledActivities.valueAt(i); 1056 disabledList.put(component.flattenToShortString(), expiration); 1057 } 1058 } 1059 return disabledList; 1060 } 1061 return null; 1062 } 1063 isAutofillDisabledLocked(@onNull ComponentName componentName)1064 boolean isAutofillDisabledLocked(@NonNull ComponentName componentName) { 1065 // Check activities first. 1066 long elapsedTime = 0; 1067 if (mDisabledActivities != null) { 1068 elapsedTime = SystemClock.elapsedRealtime(); 1069 final Long expiration = mDisabledActivities.get(componentName); 1070 if (expiration != null) { 1071 if (expiration >= elapsedTime) return true; 1072 // Restriction expired - clean it up. 1073 if (sVerbose) { 1074 Slog.v(TAG, "Removing " + componentName.toShortString() 1075 + " from disabled list"); 1076 } 1077 mDisabledActivities.remove(componentName); 1078 } 1079 } 1080 1081 // Then check apps. 1082 final String packageName = componentName.getPackageName(); 1083 if (mDisabledApps == null) return false; 1084 1085 final Long expiration = mDisabledApps.get(packageName); 1086 if (expiration == null) return false; 1087 1088 if (elapsedTime == 0) { 1089 elapsedTime = SystemClock.elapsedRealtime(); 1090 } 1091 1092 if (expiration >= elapsedTime) return true; 1093 1094 // Restriction expired - clean it up. 1095 if (sVerbose) Slog.v(TAG, "Removing " + packageName + " from disabled list"); 1096 mDisabledApps.remove(packageName); 1097 return false; 1098 } 1099 dumpLocked(String prefix, PrintWriter pw)1100 void dumpLocked(String prefix, PrintWriter pw) { 1101 pw.print(prefix); pw.print("Disabled apps: "); 1102 if (mDisabledApps == null) { 1103 pw.println("N/A"); 1104 } else { 1105 final int size = mDisabledApps.size(); 1106 pw.println(size); 1107 final StringBuilder builder = new StringBuilder(); 1108 final long now = SystemClock.elapsedRealtime(); 1109 for (int i = 0; i < size; i++) { 1110 final String packageName = mDisabledApps.keyAt(i); 1111 final long expiration = mDisabledApps.valueAt(i); 1112 builder.append(prefix).append(prefix) 1113 .append(i).append(". ").append(packageName).append(": "); 1114 TimeUtils.formatDuration((expiration - now), builder); 1115 builder.append('\n'); 1116 } 1117 pw.println(builder); 1118 } 1119 1120 pw.print(prefix); pw.print("Disabled activities: "); 1121 if (mDisabledActivities == null) { 1122 pw.println("N/A"); 1123 } else { 1124 final int size = mDisabledActivities.size(); 1125 pw.println(size); 1126 final StringBuilder builder = new StringBuilder(); 1127 final long now = SystemClock.elapsedRealtime(); 1128 for (int i = 0; i < size; i++) { 1129 final ComponentName component = mDisabledActivities.keyAt(i); 1130 final long expiration = mDisabledActivities.valueAt(i); 1131 builder.append(prefix).append(prefix) 1132 .append(i).append(". ").append(component).append(": "); 1133 TimeUtils.formatDuration((expiration - now), builder); 1134 builder.append('\n'); 1135 } 1136 pw.println(builder); 1137 } 1138 } 1139 } 1140 1141 /** 1142 * Compatibility mode metadata associated with all services. 1143 * 1144 * <p>This object is defined here instead of on each {@link AutofillManagerServiceImpl} because 1145 * it cannot hold a lock on the main lock when 1146 * {@link AutofillCompatState#isCompatibilityModeRequested(String, long, int)} is called by 1147 * external services. 1148 */ 1149 static final class AutofillCompatState { 1150 private final Object mLock = new Object(); 1151 1152 /** 1153 * Map of app->compat_state per user. 1154 */ 1155 @GuardedBy("mLock") 1156 private SparseArray<ArrayMap<String, PackageCompatState>> mUserSpecs; 1157 isCompatibilityModeRequested(@onNull String packageName, long versionCode, @UserIdInt int userId)1158 boolean isCompatibilityModeRequested(@NonNull String packageName, 1159 long versionCode, @UserIdInt int userId) { 1160 synchronized (mLock) { 1161 if (mUserSpecs == null) { 1162 return false; 1163 } 1164 final ArrayMap<String, PackageCompatState> userSpec = mUserSpecs.get(userId); 1165 if (userSpec == null) { 1166 return false; 1167 } 1168 final PackageCompatState metadata = userSpec.get(packageName); 1169 if (metadata == null) { 1170 return false; 1171 } 1172 return versionCode <= metadata.maxVersionCode; 1173 } 1174 } 1175 1176 @Nullable getUrlBarResourceIds(@onNull String packageName, @UserIdInt int userId)1177 String[] getUrlBarResourceIds(@NonNull String packageName, @UserIdInt int userId) { 1178 synchronized (mLock) { 1179 if (mUserSpecs == null) { 1180 return null; 1181 } 1182 final ArrayMap<String, PackageCompatState> userSpec = mUserSpecs.get(userId); 1183 if (userSpec == null) { 1184 return null; 1185 } 1186 final PackageCompatState metadata = userSpec.get(packageName); 1187 if (metadata == null) { 1188 return null; 1189 } 1190 return metadata.urlBarResourceIds; 1191 } 1192 } 1193 addCompatibilityModeRequest(@onNull String packageName, long versionCode, @Nullable String[] urlBarResourceIds, @UserIdInt int userId)1194 void addCompatibilityModeRequest(@NonNull String packageName, 1195 long versionCode, @Nullable String[] urlBarResourceIds, @UserIdInt int userId) { 1196 synchronized (mLock) { 1197 if (mUserSpecs == null) { 1198 mUserSpecs = new SparseArray<>(); 1199 } 1200 ArrayMap<String, PackageCompatState> userSpec = mUserSpecs.get(userId); 1201 if (userSpec == null) { 1202 userSpec = new ArrayMap<>(); 1203 mUserSpecs.put(userId, userSpec); 1204 } 1205 userSpec.put(packageName, 1206 new PackageCompatState(versionCode, urlBarResourceIds)); 1207 } 1208 } 1209 removeCompatibilityModeRequests(@serIdInt int userId)1210 void removeCompatibilityModeRequests(@UserIdInt int userId) { 1211 synchronized (mLock) { 1212 if (mUserSpecs != null) { 1213 mUserSpecs.remove(userId); 1214 if (mUserSpecs.size() <= 0) { 1215 mUserSpecs = null; 1216 } 1217 } 1218 } 1219 } 1220 reset(int userId)1221 void reset(int userId) { 1222 synchronized (mLock) { 1223 if (mUserSpecs != null) { 1224 mUserSpecs.delete(userId); 1225 final int newSize = mUserSpecs.size(); 1226 if (newSize == 0) { 1227 if (sVerbose) Slog.v(TAG, "reseting mUserSpecs"); 1228 mUserSpecs = null; 1229 } else { 1230 if (sVerbose) Slog.v(TAG, "mUserSpecs down to " + newSize); 1231 } 1232 } 1233 } 1234 } 1235 dump(String prefix, PrintWriter pw)1236 private void dump(String prefix, PrintWriter pw) { 1237 synchronized (mLock) { 1238 if (mUserSpecs == null) { 1239 pw.println("N/A"); 1240 return; 1241 } 1242 pw.println(); 1243 final String prefix2 = prefix + " "; 1244 for (int i = 0; i < mUserSpecs.size(); i++) { 1245 final int user = mUserSpecs.keyAt(i); 1246 pw.print(prefix); 1247 pw.print("User: "); 1248 pw.println(user); 1249 final ArrayMap<String, PackageCompatState> perUser = mUserSpecs.valueAt(i); 1250 for (int j = 0; j < perUser.size(); j++) { 1251 final String packageName = perUser.keyAt(j); 1252 final PackageCompatState state = perUser.valueAt(j); 1253 pw.print(prefix2); pw.print(packageName); pw.print(": "); pw.println(state); 1254 } 1255 } 1256 } 1257 } 1258 } 1259 1260 /** 1261 * Augmented autofill metadata associated with all services. 1262 * 1263 * <p>This object is defined here instead of on each {@link AutofillManagerServiceImpl} because 1264 * it cannot hold a lock on the main lock when 1265 * {@link AugmentedAutofillState#injectAugmentedAutofillInfo(AutofillOptions, int, String)} 1266 * is called by external services. 1267 */ 1268 static final class AugmentedAutofillState extends GlobalWhitelistState { 1269 1270 @GuardedBy("mGlobalWhitelistStateLock") 1271 private final SparseArray<String> mServicePackages = new SparseArray<>(); 1272 @GuardedBy("mGlobalWhitelistStateLock") 1273 private final SparseBooleanArray mTemporaryServices = new SparseBooleanArray(); 1274 setServiceInfo(@serIdInt int userId, @Nullable String serviceName, boolean isTemporary)1275 private void setServiceInfo(@UserIdInt int userId, @Nullable String serviceName, 1276 boolean isTemporary) { 1277 synchronized (mGlobalWhitelistStateLock) { 1278 if (isTemporary) { 1279 mTemporaryServices.put(userId, true); 1280 } else { 1281 mTemporaryServices.delete(userId); 1282 } 1283 if (serviceName != null) { 1284 final ComponentName componentName = 1285 ComponentName.unflattenFromString(serviceName); 1286 if (componentName == null) { 1287 Slog.w(TAG, "setServiceInfo(): invalid name: " + serviceName); 1288 mServicePackages.remove(userId); 1289 } else { 1290 mServicePackages.put(userId, componentName.getPackageName()); 1291 } 1292 } else { 1293 mServicePackages.remove(userId); 1294 } 1295 } 1296 } 1297 injectAugmentedAutofillInfo(@onNull AutofillOptions options, @UserIdInt int userId, @NonNull String packageName)1298 public void injectAugmentedAutofillInfo(@NonNull AutofillOptions options, 1299 @UserIdInt int userId, @NonNull String packageName) { 1300 synchronized (mGlobalWhitelistStateLock) { 1301 if (mWhitelisterHelpers == null) return; 1302 final WhitelistHelper helper = mWhitelisterHelpers.get(userId); 1303 if (helper != null) { 1304 options.augmentedAutofillEnabled = helper.isWhitelisted(packageName); 1305 options.whitelistedActivitiesForAugmentedAutofill = helper 1306 .getWhitelistedComponents(packageName); 1307 } 1308 } 1309 } 1310 1311 @Override isWhitelisted(@serIdInt int userId, @NonNull ComponentName componentName)1312 public boolean isWhitelisted(@UserIdInt int userId, @NonNull ComponentName componentName) { 1313 synchronized (mGlobalWhitelistStateLock) { 1314 if (!super.isWhitelisted(userId, componentName)) return false; 1315 1316 if (Build.IS_USER && mTemporaryServices.get(userId)) { 1317 final String packageName = componentName.getPackageName(); 1318 if (!packageName.equals(mServicePackages.get(userId))) { 1319 Slog.w(TAG, "Ignoring package " + packageName + " for augmented autofill " 1320 + "while using temporary service " + mServicePackages.get(userId)); 1321 return false; 1322 } 1323 } 1324 } 1325 return true; 1326 } 1327 1328 @Override dump(@onNull String prefix, @NonNull PrintWriter pw)1329 public void dump(@NonNull String prefix, @NonNull PrintWriter pw) { 1330 super.dump(prefix, pw); 1331 1332 synchronized (mGlobalWhitelistStateLock) { 1333 if (mServicePackages.size() > 0) { 1334 pw.print(prefix); pw.print("Service packages: "); pw.println(mServicePackages); 1335 } 1336 if (mTemporaryServices.size() > 0) { 1337 pw.print(prefix); pw.print("Temp services: "); pw.println(mTemporaryServices); 1338 } 1339 } 1340 } 1341 } 1342 1343 final class AutoFillManagerServiceStub extends IAutoFillManager.Stub { 1344 @Override addClient(IAutoFillManagerClient client, ComponentName componentName, int userId, IResultReceiver receiver)1345 public void addClient(IAutoFillManagerClient client, ComponentName componentName, 1346 int userId, IResultReceiver receiver) { 1347 int flags = 0; 1348 synchronized (mLock) { 1349 final int enabledFlags = getServiceForUserLocked(userId).addClientLocked(client, 1350 componentName); 1351 if (enabledFlags != 0) { 1352 flags |= enabledFlags; 1353 } 1354 if (sDebug) { 1355 flags |= AutofillManager.FLAG_ADD_CLIENT_DEBUG; 1356 } 1357 if (sVerbose) { 1358 flags |= AutofillManager.FLAG_ADD_CLIENT_VERBOSE; 1359 } 1360 } 1361 send(receiver, flags); 1362 } 1363 1364 @Override removeClient(IAutoFillManagerClient client, int userId)1365 public void removeClient(IAutoFillManagerClient client, int userId) { 1366 synchronized (mLock) { 1367 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 1368 if (service != null) { 1369 service.removeClientLocked(client); 1370 } else if (sVerbose) { 1371 Slog.v(TAG, "removeClient(): no service for " + userId); 1372 } 1373 } 1374 } 1375 1376 @Override setAuthenticationResult(Bundle data, int sessionId, int authenticationId, int userId)1377 public void setAuthenticationResult(Bundle data, int sessionId, int authenticationId, 1378 int userId) { 1379 synchronized (mLock) { 1380 final AutofillManagerServiceImpl service = getServiceForUserLocked(userId); 1381 service.setAuthenticationResultLocked(data, sessionId, authenticationId, 1382 getCallingUid()); 1383 } 1384 } 1385 1386 @Override setHasCallback(int sessionId, int userId, boolean hasIt)1387 public void setHasCallback(int sessionId, int userId, boolean hasIt) { 1388 synchronized (mLock) { 1389 final AutofillManagerServiceImpl service = getServiceForUserLocked(userId); 1390 service.setHasCallback(sessionId, getCallingUid(), hasIt); 1391 } 1392 } 1393 1394 @Override startSession(IBinder activityToken, IBinder clientCallback, AutofillId autofillId, Rect bounds, AutofillValue value, int userId, boolean hasCallback, int flags, ComponentName clientActivity, boolean compatMode, IResultReceiver receiver)1395 public void startSession(IBinder activityToken, IBinder clientCallback, 1396 AutofillId autofillId, Rect bounds, AutofillValue value, int userId, 1397 boolean hasCallback, int flags, ComponentName clientActivity, 1398 boolean compatMode, IResultReceiver receiver) { 1399 1400 requireNonNull(activityToken, "activityToken"); 1401 requireNonNull(clientCallback, "clientCallback"); 1402 requireNonNull(autofillId, "autofillId"); 1403 requireNonNull(clientActivity, "clientActivity"); 1404 final String packageName = requireNonNull(clientActivity.getPackageName()); 1405 1406 Preconditions.checkArgument(userId == UserHandle.getUserId(getCallingUid()), "userId"); 1407 1408 try { 1409 getContext().getPackageManager().getPackageInfoAsUser(packageName, 0, userId); 1410 } catch (PackageManager.NameNotFoundException e) { 1411 throw new IllegalArgumentException(packageName + " is not a valid package", e); 1412 } 1413 1414 // TODO(b/113281366): add a callback method on AM to be notified when a task is finished 1415 // so we can clean up sessions kept alive 1416 final int taskId = mAm.getTaskIdForActivity(activityToken, false); 1417 final long result; 1418 synchronized (mLock) { 1419 final AutofillManagerServiceImpl service = getServiceForUserLocked(userId); 1420 result = service.startSessionLocked(activityToken, taskId, getCallingUid(), 1421 clientCallback, autofillId, bounds, value, hasCallback, clientActivity, 1422 compatMode, mAllowInstantService, flags); 1423 } 1424 final int sessionId = (int) result; 1425 final int resultFlags = (int) (result >> 32); 1426 if (resultFlags != 0) { 1427 send(receiver, sessionId, resultFlags); 1428 } else { 1429 send(receiver, sessionId); 1430 } 1431 } 1432 1433 @Override getFillEventHistory(@onNull IResultReceiver receiver)1434 public void getFillEventHistory(@NonNull IResultReceiver receiver) throws RemoteException { 1435 final int userId = UserHandle.getCallingUserId(); 1436 1437 FillEventHistory fillEventHistory = null; 1438 synchronized (mLock) { 1439 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 1440 if (service != null) { 1441 fillEventHistory = service.getFillEventHistory(getCallingUid()); 1442 } else if (sVerbose) { 1443 Slog.v(TAG, "getFillEventHistory(): no service for " + userId); 1444 } 1445 } 1446 send(receiver, fillEventHistory); 1447 } 1448 1449 @Override getUserData(@onNull IResultReceiver receiver)1450 public void getUserData(@NonNull IResultReceiver receiver) throws RemoteException { 1451 final int userId = UserHandle.getCallingUserId(); 1452 1453 UserData userData = null; 1454 synchronized (mLock) { 1455 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 1456 if (service != null) { 1457 userData = service.getUserData(getCallingUid()); 1458 } else if (sVerbose) { 1459 Slog.v(TAG, "getUserData(): no service for " + userId); 1460 } 1461 } 1462 send(receiver, userData); 1463 } 1464 1465 @Override getUserDataId(@onNull IResultReceiver receiver)1466 public void getUserDataId(@NonNull IResultReceiver receiver) throws RemoteException { 1467 final int userId = UserHandle.getCallingUserId(); 1468 UserData userData = null; 1469 1470 synchronized (mLock) { 1471 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 1472 if (service != null) { 1473 userData = service.getUserData(getCallingUid()); 1474 } else if (sVerbose) { 1475 Slog.v(TAG, "getUserDataId(): no service for " + userId); 1476 } 1477 } 1478 final String userDataId = userData == null ? null : userData.getId(); 1479 send(receiver, userDataId); 1480 } 1481 1482 @Override setUserData(UserData userData)1483 public void setUserData(UserData userData) throws RemoteException { 1484 final int userId = UserHandle.getCallingUserId(); 1485 1486 synchronized (mLock) { 1487 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 1488 if (service != null) { 1489 service.setUserData(getCallingUid(), userData); 1490 } else if (sVerbose) { 1491 Slog.v(TAG, "setUserData(): no service for " + userId); 1492 } 1493 } 1494 } 1495 1496 @Override isFieldClassificationEnabled(@onNull IResultReceiver receiver)1497 public void isFieldClassificationEnabled(@NonNull IResultReceiver receiver) 1498 throws RemoteException { 1499 final int userId = UserHandle.getCallingUserId(); 1500 boolean enabled = false; 1501 1502 synchronized (mLock) { 1503 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 1504 if (service != null) { 1505 enabled = service.isFieldClassificationEnabled(getCallingUid()); 1506 } else if (sVerbose) { 1507 Slog.v(TAG, "isFieldClassificationEnabled(): no service for " + userId); 1508 } 1509 } 1510 send(receiver, enabled); 1511 } 1512 1513 @Override getDefaultFieldClassificationAlgorithm(@onNull IResultReceiver receiver)1514 public void getDefaultFieldClassificationAlgorithm(@NonNull IResultReceiver receiver) 1515 throws RemoteException { 1516 final int userId = UserHandle.getCallingUserId(); 1517 String algorithm = null; 1518 1519 synchronized (mLock) { 1520 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 1521 if (service != null) { 1522 algorithm = service.getDefaultFieldClassificationAlgorithm(getCallingUid()); 1523 } else { 1524 if (sVerbose) { 1525 Slog.v(TAG, "getDefaultFcAlgorithm(): no service for " + userId); 1526 } 1527 } 1528 } 1529 send(receiver, algorithm); 1530 } 1531 1532 @Override setAugmentedAutofillWhitelist(@ullable List<String> packages, @Nullable List<ComponentName> activities, @NonNull IResultReceiver receiver)1533 public void setAugmentedAutofillWhitelist(@Nullable List<String> packages, 1534 @Nullable List<ComponentName> activities, @NonNull IResultReceiver receiver) 1535 throws RemoteException { 1536 final int userId = UserHandle.getCallingUserId(); 1537 1538 boolean ok; 1539 synchronized (mLock) { 1540 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 1541 if (service != null) { 1542 ok = service.setAugmentedAutofillWhitelistLocked(packages, activities, 1543 getCallingUid()); 1544 } else { 1545 if (sVerbose) { 1546 Slog.v(TAG, "setAugmentedAutofillWhitelist(): no service for " + userId); 1547 } 1548 ok = false; 1549 } 1550 } 1551 send(receiver, 1552 ok ? AutofillManager.RESULT_OK : AutofillManager.RESULT_CODE_NOT_SERVICE); 1553 } 1554 1555 @Override getAvailableFieldClassificationAlgorithms(@onNull IResultReceiver receiver)1556 public void getAvailableFieldClassificationAlgorithms(@NonNull IResultReceiver receiver) 1557 throws RemoteException { 1558 final int userId = UserHandle.getCallingUserId(); 1559 String[] algorithms = null; 1560 1561 synchronized (mLock) { 1562 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 1563 if (service != null) { 1564 algorithms = service.getAvailableFieldClassificationAlgorithms(getCallingUid()); 1565 } else { 1566 if (sVerbose) { 1567 Slog.v(TAG, "getAvailableFcAlgorithms(): no service for " + userId); 1568 } 1569 } 1570 } 1571 send(receiver, algorithms); 1572 } 1573 1574 @Override getAutofillServiceComponentName(@onNull IResultReceiver receiver)1575 public void getAutofillServiceComponentName(@NonNull IResultReceiver receiver) 1576 throws RemoteException { 1577 final int userId = UserHandle.getCallingUserId(); 1578 1579 ComponentName componentName = null; 1580 synchronized (mLock) { 1581 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 1582 if (service != null) { 1583 componentName = service.getServiceComponentName(); 1584 } else if (sVerbose) { 1585 Slog.v(TAG, "getAutofillServiceComponentName(): no service for " + userId); 1586 } 1587 } 1588 send(receiver, componentName); 1589 } 1590 1591 @Override restoreSession(int sessionId, @NonNull IBinder activityToken, @NonNull IBinder appCallback, @NonNull IResultReceiver receiver)1592 public void restoreSession(int sessionId, @NonNull IBinder activityToken, 1593 @NonNull IBinder appCallback, @NonNull IResultReceiver receiver) 1594 throws RemoteException { 1595 final int userId = UserHandle.getCallingUserId(); 1596 activityToken = Preconditions.checkNotNull(activityToken, "activityToken"); 1597 appCallback = Preconditions.checkNotNull(appCallback, "appCallback"); 1598 1599 boolean restored = false; 1600 synchronized (mLock) { 1601 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 1602 if (service != null) { 1603 restored = service.restoreSession(sessionId, getCallingUid(), activityToken, 1604 appCallback); 1605 } else if (sVerbose) { 1606 Slog.v(TAG, "restoreSession(): no service for " + userId); 1607 } 1608 } 1609 send(receiver, restored); 1610 } 1611 1612 @Override updateSession(int sessionId, AutofillId autoFillId, Rect bounds, AutofillValue value, int action, int flags, int userId)1613 public void updateSession(int sessionId, AutofillId autoFillId, Rect bounds, 1614 AutofillValue value, int action, int flags, int userId) { 1615 synchronized (mLock) { 1616 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 1617 if (service != null) { 1618 service.updateSessionLocked(sessionId, getCallingUid(), autoFillId, bounds, 1619 value, action, flags); 1620 } else if (sVerbose) { 1621 Slog.v(TAG, "updateSession(): no service for " + userId); 1622 } 1623 } 1624 } 1625 1626 @Override setAutofillFailure(int sessionId, @NonNull List<AutofillId> ids, int userId)1627 public void setAutofillFailure(int sessionId, @NonNull List<AutofillId> ids, int userId) { 1628 synchronized (mLock) { 1629 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 1630 if (service != null) { 1631 service.setAutofillFailureLocked(sessionId, getCallingUid(), ids); 1632 } else if (sVerbose) { 1633 Slog.v(TAG, "setAutofillFailure(): no service for " + userId); 1634 } 1635 } 1636 } 1637 1638 @Override finishSession(int sessionId, int userId)1639 public void finishSession(int sessionId, int userId) { 1640 synchronized (mLock) { 1641 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 1642 if (service != null) { 1643 service.finishSessionLocked(sessionId, getCallingUid()); 1644 } else if (sVerbose) { 1645 Slog.v(TAG, "finishSession(): no service for " + userId); 1646 } 1647 } 1648 } 1649 1650 @Override cancelSession(int sessionId, int userId)1651 public void cancelSession(int sessionId, int userId) { 1652 synchronized (mLock) { 1653 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 1654 if (service != null) { 1655 service.cancelSessionLocked(sessionId, getCallingUid()); 1656 } else if (sVerbose) { 1657 Slog.v(TAG, "cancelSession(): no service for " + userId); 1658 } 1659 } 1660 } 1661 1662 @Override disableOwnedAutofillServices(int userId)1663 public void disableOwnedAutofillServices(int userId) { 1664 synchronized (mLock) { 1665 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); 1666 if (service != null) { 1667 service.disableOwnedAutofillServicesLocked(Binder.getCallingUid()); 1668 } else if (sVerbose) { 1669 Slog.v(TAG, "cancelSession(): no service for " + userId); 1670 } 1671 } 1672 } 1673 1674 @Override isServiceSupported(int userId, @NonNull IResultReceiver receiver)1675 public void isServiceSupported(int userId, @NonNull IResultReceiver receiver) { 1676 boolean supported = false; 1677 synchronized (mLock) { 1678 supported = !isDisabledLocked(userId); 1679 } 1680 send(receiver, supported); 1681 } 1682 1683 @Override isServiceEnabled(int userId, @NonNull String packageName, @NonNull IResultReceiver receiver)1684 public void isServiceEnabled(int userId, @NonNull String packageName, 1685 @NonNull IResultReceiver receiver) { 1686 boolean enabled = false; 1687 synchronized (mLock) { 1688 final AutofillManagerServiceImpl service = getServiceForUserLocked(userId); 1689 enabled = Objects.equals(packageName, service.getServicePackageName()); 1690 } 1691 send(receiver, enabled); 1692 } 1693 1694 @Override onPendingSaveUi(int operation, IBinder token)1695 public void onPendingSaveUi(int operation, IBinder token) { 1696 Preconditions.checkNotNull(token, "token"); 1697 Preconditions.checkArgument(operation == AutofillManager.PENDING_UI_OPERATION_CANCEL 1698 || operation == AutofillManager.PENDING_UI_OPERATION_RESTORE, 1699 "invalid operation: %d", operation); 1700 synchronized (mLock) { 1701 final AutofillManagerServiceImpl service = peekServiceForUserLocked( 1702 UserHandle.getCallingUserId()); 1703 if (service != null) { 1704 service.onPendingSaveUi(operation, token); 1705 } 1706 } 1707 } 1708 1709 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)1710 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1711 if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return; 1712 1713 boolean showHistory = true; 1714 boolean uiOnly = false; 1715 if (args != null) { 1716 for (String arg : args) { 1717 switch(arg) { 1718 case "--no-history": 1719 showHistory = false; 1720 break; 1721 case "--ui-only": 1722 uiOnly = true; 1723 break; 1724 case "--help": 1725 pw.println("Usage: dumpsys autofill [--ui-only|--no-history]"); 1726 return; 1727 default: 1728 Slog.w(TAG, "Ignoring invalid dump arg: " + arg); 1729 } 1730 } 1731 } 1732 1733 if (uiOnly) { 1734 mUi.dump(pw); 1735 return; 1736 } 1737 1738 final String prefix = " "; 1739 boolean realDebug = sDebug; 1740 boolean realVerbose = sVerbose; 1741 try { 1742 sDebug = sVerbose = true; 1743 synchronized (mLock) { 1744 pw.print("sDebug: "); pw.print(realDebug); 1745 pw.print(" sVerbose: "); pw.println(realVerbose); 1746 // Dump per-user services 1747 dumpLocked("", pw); 1748 mAugmentedAutofillResolver.dumpShort(pw); pw.println(); 1749 pw.print("Max partitions per session: "); pw.println(sPartitionMaxCount); 1750 pw.print("Max visible datasets: "); pw.println(sVisibleDatasetsMaxCount); 1751 if (sFullScreenMode != null) { 1752 pw.print("Overridden full-screen mode: "); pw.println(sFullScreenMode); 1753 } 1754 pw.println("User data constraints: "); UserData.dumpConstraints(prefix, pw); 1755 mUi.dump(pw); 1756 pw.print("Autofill Compat State: "); 1757 mAutofillCompatState.dump(prefix, pw); 1758 pw.print("from settings: "); 1759 pw.println(getWhitelistedCompatModePackagesFromSettings()); 1760 if (mSupportedSmartSuggestionModes != 0) { 1761 pw.print("Smart Suggestion modes: "); 1762 pw.println(getSmartSuggestionModeToString(mSupportedSmartSuggestionModes)); 1763 } 1764 pw.print("Augmented Service Idle Unbind Timeout: "); 1765 pw.println(mAugmentedServiceIdleUnbindTimeoutMs); 1766 pw.print("Augmented Service Request Timeout: "); 1767 pw.println(mAugmentedServiceRequestTimeoutMs); 1768 if (showHistory) { 1769 pw.println(); pw.println("Requests history:"); pw.println(); 1770 mRequestsHistory.reverseDump(fd, pw, args); 1771 pw.println(); pw.println("UI latency history:"); pw.println(); 1772 mUiLatencyHistory.reverseDump(fd, pw, args); 1773 pw.println(); pw.println("WTF history:"); pw.println(); 1774 mWtfHistory.reverseDump(fd, pw, args); 1775 } 1776 pw.println("Augmented Autofill State: "); 1777 mAugmentedAutofillState.dump(prefix, pw); 1778 } 1779 } finally { 1780 sDebug = realDebug; 1781 sVerbose = realVerbose; 1782 } 1783 } 1784 1785 @Override onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver)1786 public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, 1787 String[] args, ShellCallback callback, ResultReceiver resultReceiver) { 1788 new AutofillManagerServiceShellCommand(AutofillManagerService.this).exec( 1789 this, in, out, err, args, callback, resultReceiver); 1790 } 1791 } 1792 } 1793