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