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