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