• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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