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