Home | History | Annotate | Download | only in autofill
      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 
     22 import static com.android.server.autofill.Helper.sDebug;
     23 import static com.android.server.autofill.Helper.sFullScreenMode;
     24 import static com.android.server.autofill.Helper.sPartitionMaxCount;
     25 import static com.android.server.autofill.Helper.sVisibleDatasetsMaxCount;
     26 import static com.android.server.autofill.Helper.sVerbose;
     27 
     28 import android.annotation.NonNull;
     29 import android.annotation.Nullable;
     30 import android.annotation.UserIdInt;
     31 import android.app.ActivityManager;
     32 import android.app.ActivityThread;
     33 import android.content.BroadcastReceiver;
     34 import android.content.ComponentName;
     35 import android.content.ContentResolver;
     36 import android.content.Context;
     37 import android.content.Intent;
     38 import android.content.IntentFilter;
     39 import android.content.pm.PackageManager;
     40 import android.content.pm.UserInfo;
     41 import android.database.ContentObserver;
     42 import android.graphics.Rect;
     43 import android.net.Uri;
     44 import android.os.Binder;
     45 import android.os.Build;
     46 import android.os.Bundle;
     47 import android.os.Handler;
     48 import android.os.IBinder;
     49 import android.os.RemoteCallback;
     50 import android.os.RemoteException;
     51 import android.os.ResultReceiver;
     52 import android.os.ShellCallback;
     53 import android.os.UserHandle;
     54 import android.os.UserManager;
     55 import android.os.UserManagerInternal;
     56 import android.provider.Settings;
     57 import android.service.autofill.FillEventHistory;
     58 import android.service.autofill.UserData;
     59 import android.text.TextUtils;
     60 import android.text.TextUtils.SimpleStringSplitter;
     61 import android.util.ArrayMap;
     62 import android.util.LocalLog;
     63 import android.util.Slog;
     64 import android.util.SparseArray;
     65 import android.util.SparseBooleanArray;
     66 import android.view.autofill.AutofillId;
     67 import android.view.autofill.AutofillManager;
     68 import android.view.autofill.AutofillManagerInternal;
     69 import android.view.autofill.AutofillValue;
     70 import android.view.autofill.IAutoFillManager;
     71 import android.view.autofill.IAutoFillManagerClient;
     72 
     73 import com.android.internal.annotations.GuardedBy;
     74 import com.android.internal.annotations.VisibleForTesting;
     75 import com.android.internal.content.PackageMonitor;
     76 import com.android.internal.os.BackgroundThread;
     77 import com.android.internal.os.IResultReceiver;
     78 import com.android.internal.util.DumpUtils;
     79 import com.android.internal.util.Preconditions;
     80 import com.android.server.FgThread;
     81 import com.android.server.LocalServices;
     82 import com.android.server.SystemService;
     83 import com.android.server.autofill.ui.AutoFillUI;
     84 
     85 import java.io.FileDescriptor;
     86 import java.io.PrintWriter;
     87 import java.util.ArrayList;
     88 import java.util.Arrays;
     89 import java.util.List;
     90 import java.util.Map;
     91 import java.util.Objects;
     92 
     93 /**
     94  * Entry point service for autofill management.
     95  *
     96  * <p>This service provides the {@link IAutoFillManager} implementation and keeps a list of
     97  * {@link AutofillManagerServiceImpl} per user; the real work is done by
     98  * {@link AutofillManagerServiceImpl} itself.
     99  */
    100 public final class AutofillManagerService extends SystemService {
    101 
    102     private static final String TAG = "AutofillManagerService";
    103 
    104     static final String RECEIVER_BUNDLE_EXTRA_SESSIONS = "sessions";
    105 
    106     private static final char COMPAT_PACKAGE_DELIMITER = ':';
    107     private static final char COMPAT_PACKAGE_URL_IDS_DELIMITER = ',';
    108     private static final char COMPAT_PACKAGE_URL_IDS_BLOCK_BEGIN = '[';
    109     private static final char COMPAT_PACKAGE_URL_IDS_BLOCK_END = ']';
    110 
    111     private final Context mContext;
    112     private final AutoFillUI mUi;
    113 
    114     private final Object mLock = new Object();
    115 
    116     /**
    117      * Cache of {@link AutofillManagerServiceImpl} per user id.
    118      * <p>
    119      * It has to be mapped by user id because the same current user could have simultaneous sessions
    120      * associated to different user profiles (for example, in a multi-window environment or when
    121      * device has work profiles).
    122      */
    123     @GuardedBy("mLock")
    124     private SparseArray<AutofillManagerServiceImpl> mServicesCache = new SparseArray<>();
    125 
    126     /**
    127      * Users disabled due to {@link UserManager} restrictions.
    128      */
    129     @GuardedBy("mLock")
    130     private final SparseBooleanArray mDisabledUsers = new SparseBooleanArray();
    131 
    132     private final LocalLog mRequestsHistory = new LocalLog(20);
    133     private final LocalLog mUiLatencyHistory = new LocalLog(20);
    134     private final LocalLog mWtfHistory = new LocalLog(50);
    135 
    136     private final AutofillCompatState mAutofillCompatState = new AutofillCompatState();
    137     private final LocalService mLocalService = new LocalService();
    138 
    139     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
    140         @Override
    141         public void onReceive(Context context, Intent intent) {
    142             if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) {
    143                 if (sDebug) Slog.d(TAG, "Close system dialogs");
    144 
    145                 // TODO(b/64940307): we need to destroy all sessions that are finished but showing
    146                 // Save UI because there is no way to show the Save UI back when the activity
    147                 // beneath it is brought back to top. Ideally, we should just hide the UI and
    148                 // bring it back when the activity resumes.
    149                 synchronized (mLock) {
    150                     for (int i = 0; i < mServicesCache.size(); i++) {
    151                         mServicesCache.valueAt(i).destroyFinishedSessionsLocked();
    152                     }
    153                 }
    154 
    155                 mUi.hideAll(null);
    156             }
    157         }
    158     };
    159 
    160     @GuardedBy("mLock")
    161     private boolean mAllowInstantService;
    162 
    163     public AutofillManagerService(Context context) {
    164         super(context);
    165         mContext = context;
    166         mUi = new AutoFillUI(ActivityThread.currentActivityThread().getSystemUiContext());
    167 
    168         final boolean debug = Build.IS_DEBUGGABLE;
    169         Slog.i(TAG, "Setting debug to " + debug);
    170         setDebugLocked(debug);
    171 
    172         final IntentFilter filter = new IntentFilter();
    173         filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
    174         mContext.registerReceiver(mBroadcastReceiver, filter, null, FgThread.getHandler());
    175 
    176         // Hookup with UserManager to disable service when necessary.
    177         final UserManager um = context.getSystemService(UserManager.class);
    178         final UserManagerInternal umi = LocalServices.getService(UserManagerInternal.class);
    179         final List<UserInfo> users = um.getUsers();
    180         for (int i = 0; i < users.size(); i++) {
    181             final int userId = users.get(i).id;
    182             final boolean disabled = umi.getUserRestriction(userId, UserManager.DISALLOW_AUTOFILL);
    183             if (disabled) {
    184                 if (disabled) {
    185                     Slog.i(TAG, "Disabling Autofill for user " + userId);
    186                 }
    187                 mDisabledUsers.put(userId, disabled);
    188             }
    189         }
    190         umi.addUserRestrictionsListener((userId, newRestrictions, prevRestrictions) -> {
    191             final boolean disabledNow =
    192                     newRestrictions.getBoolean(UserManager.DISALLOW_AUTOFILL, false);
    193             synchronized (mLock) {
    194                 final boolean disabledBefore = mDisabledUsers.get(userId);
    195                 if (disabledBefore == disabledNow) {
    196                     // Nothing changed, do nothing.
    197                     if (sDebug) {
    198                         Slog.d(TAG, "Autofill restriction did not change for user " + userId);
    199                         return;
    200                     }
    201                 }
    202                 Slog.i(TAG, "Updating Autofill for user " + userId + ": disabled=" + disabledNow);
    203                 mDisabledUsers.put(userId, disabledNow);
    204                 updateCachedServiceLocked(userId, disabledNow);
    205             }
    206         });
    207         startTrackingPackageChanges();
    208     }
    209 
    210     private void startTrackingPackageChanges() {
    211         PackageMonitor monitor = new PackageMonitor() {
    212             @Override
    213             public void onSomePackagesChanged() {
    214                 synchronized (mLock) {
    215                     updateCachedServiceLocked(getChangingUserId());
    216                 }
    217             }
    218 
    219             @Override
    220             public void onPackageUpdateFinished(String packageName, int uid) {
    221                 synchronized (mLock) {
    222                     final String activePackageName = getActiveAutofillServicePackageName();
    223                     if (packageName.equals(activePackageName)) {
    224                         removeCachedServiceLocked(getChangingUserId());
    225                     } else {
    226                         handlePackageUpdateLocked(packageName);
    227                     }
    228                 }
    229             }
    230 
    231             @Override
    232             public void onPackageRemoved(String packageName, int uid) {
    233                 synchronized (mLock) {
    234                     final int userId = getChangingUserId();
    235                     final AutofillManagerServiceImpl userState = peekServiceForUserLocked(userId);
    236                     if (userState != null) {
    237                         final ComponentName componentName = userState.getServiceComponentName();
    238                         if (componentName != null) {
    239                             if (packageName.equals(componentName.getPackageName())) {
    240                                 handleActiveAutofillServiceRemoved(userId);
    241                             }
    242                         }
    243                     }
    244                 }
    245             }
    246 
    247             @Override
    248             public boolean onHandleForceStop(Intent intent, String[] packages,
    249                     int uid, boolean doit) {
    250                 synchronized (mLock) {
    251                     final String activePackageName = getActiveAutofillServicePackageName();
    252                     for (String pkg : packages) {
    253                         if (pkg.equals(activePackageName)) {
    254                             if (!doit) {
    255                                 return true;
    256                             }
    257                             removeCachedServiceLocked(getChangingUserId());
    258                         } else {
    259                           handlePackageUpdateLocked(pkg);
    260                         }
    261                     }
    262                 }
    263                 return false;
    264             }
    265 
    266             private void handleActiveAutofillServiceRemoved(int userId) {
    267                 removeCachedServiceLocked(userId);
    268                 Settings.Secure.putStringForUser(mContext.getContentResolver(),
    269                         Settings.Secure.AUTOFILL_SERVICE, null, userId);
    270             }
    271 
    272             private String getActiveAutofillServicePackageName() {
    273                 final int userId = getChangingUserId();
    274                 final AutofillManagerServiceImpl userState = peekServiceForUserLocked(userId);
    275                 if (userState == null) {
    276                     return null;
    277                 }
    278                 final ComponentName serviceComponent = userState.getServiceComponentName();
    279                 if (serviceComponent == null) {
    280                     return null;
    281                 }
    282                 return serviceComponent.getPackageName();
    283             }
    284 
    285             @GuardedBy("mLock")
    286             private void handlePackageUpdateLocked(String packageName) {
    287                 final int size = mServicesCache.size();
    288                 for (int i = 0; i < size; i++) {
    289                     mServicesCache.valueAt(i).handlePackageUpdateLocked(packageName);
    290                 }
    291             }
    292         };
    293 
    294         // package changes
    295         monitor.register(mContext, null,  UserHandle.ALL, true);
    296     }
    297 
    298     @Override
    299     public void onStart() {
    300         publishBinderService(AUTOFILL_MANAGER_SERVICE, new AutoFillManagerServiceStub());
    301         publishLocalService(AutofillManagerInternal.class, mLocalService);
    302     }
    303 
    304     @Override
    305     public void onBootPhase(int phase) {
    306         if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
    307             new SettingsObserver(BackgroundThread.getHandler());
    308         }
    309     }
    310 
    311     @Override
    312     public void onUnlockUser(int userId) {
    313         synchronized (mLock) {
    314             updateCachedServiceLocked(userId);
    315         }
    316     }
    317 
    318     @Override
    319     public void onSwitchUser(int userHandle) {
    320         if (sDebug) Slog.d(TAG, "Hiding UI when user switched");
    321         mUi.hideAll(null);
    322     }
    323 
    324     @Override
    325     public void onCleanupUser(int userId) {
    326         synchronized (mLock) {
    327             removeCachedServiceLocked(userId);
    328         }
    329     }
    330 
    331     /**
    332      * Gets the service instance for an user.
    333      *
    334      * @return service instance.
    335      */
    336     @GuardedBy("mLock")
    337     @NonNull
    338     AutofillManagerServiceImpl getServiceForUserLocked(int userId) {
    339         final int resolvedUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
    340                 Binder.getCallingUid(), userId, false, false, null, null);
    341         AutofillManagerServiceImpl service = mServicesCache.get(resolvedUserId);
    342         if (service == null) {
    343             service = new AutofillManagerServiceImpl(mContext, mLock, mRequestsHistory,
    344                     mUiLatencyHistory, mWtfHistory, resolvedUserId, mUi,
    345                     mAutofillCompatState, mDisabledUsers.get(resolvedUserId));
    346             mServicesCache.put(userId, service);
    347             addCompatibilityModeRequestsLocked(service, userId);
    348         }
    349         return service;
    350     }
    351 
    352     /**
    353      * Peeks the service instance for a user.
    354      *
    355      * @return service instance or {@code null} if not already present
    356      */
    357     @GuardedBy("mLock")
    358     @Nullable
    359     AutofillManagerServiceImpl peekServiceForUserLocked(int userId) {
    360         final int resolvedUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
    361                 Binder.getCallingUid(), userId, false, false, null, null);
    362         return mServicesCache.get(resolvedUserId);
    363     }
    364 
    365     // Called by Shell command.
    366     void destroySessions(int userId, IResultReceiver receiver) {
    367         Slog.i(TAG, "destroySessions() for userId " + userId);
    368         mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
    369 
    370         synchronized (mLock) {
    371             if (userId != UserHandle.USER_ALL) {
    372                 AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
    373                 if (service != null) {
    374                     service.destroySessionsLocked();
    375                 }
    376             } else {
    377                 final int size = mServicesCache.size();
    378                 for (int i = 0; i < size; i++) {
    379                     mServicesCache.valueAt(i).destroySessionsLocked();
    380                 }
    381             }
    382         }
    383 
    384         try {
    385             receiver.send(0, new Bundle());
    386         } catch (RemoteException e) {
    387             // Just ignore it...
    388         }
    389     }
    390 
    391     // Called by Shell command.
    392     void listSessions(int userId, IResultReceiver receiver) {
    393         Slog.i(TAG, "listSessions() for userId " + userId);
    394         mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
    395 
    396         final Bundle resultData = new Bundle();
    397         final ArrayList<String> sessions = new ArrayList<>();
    398 
    399         synchronized (mLock) {
    400             if (userId != UserHandle.USER_ALL) {
    401                 AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
    402                 if (service != null) {
    403                     service.listSessionsLocked(sessions);
    404                 }
    405             } else {
    406                 final int size = mServicesCache.size();
    407                 for (int i = 0; i < size; i++) {
    408                     mServicesCache.valueAt(i).listSessionsLocked(sessions);
    409                 }
    410             }
    411         }
    412 
    413         resultData.putStringArrayList(RECEIVER_BUNDLE_EXTRA_SESSIONS, sessions);
    414         try {
    415             receiver.send(0, resultData);
    416         } catch (RemoteException e) {
    417             // Just ignore it...
    418         }
    419     }
    420 
    421     // Called by Shell command.
    422     void reset() {
    423         Slog.i(TAG, "reset()");
    424         mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
    425 
    426         synchronized (mLock) {
    427             final int size = mServicesCache.size();
    428             for (int i = 0; i < size; i++) {
    429                 mServicesCache.valueAt(i).destroyLocked();
    430             }
    431             mServicesCache.clear();
    432         }
    433     }
    434 
    435     // Called by Shell command.
    436     void setLogLevel(int level) {
    437         Slog.i(TAG, "setLogLevel(): " + level);
    438         mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
    439 
    440         boolean debug = false;
    441         boolean verbose = false;
    442         if (level == AutofillManager.FLAG_ADD_CLIENT_VERBOSE) {
    443             debug = verbose = true;
    444         } else if (level == AutofillManager.FLAG_ADD_CLIENT_DEBUG) {
    445             debug = true;
    446         }
    447         synchronized (mLock) {
    448             setDebugLocked(debug);
    449             setVerboseLocked(verbose);
    450         }
    451     }
    452 
    453     // Called by Shell command.
    454     int getLogLevel() {
    455         mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
    456 
    457         synchronized (mLock) {
    458             if (sVerbose) return AutofillManager.FLAG_ADD_CLIENT_VERBOSE;
    459             if (sDebug) return AutofillManager.FLAG_ADD_CLIENT_DEBUG;
    460             return 0;
    461         }
    462     }
    463 
    464     // Called by Shell command.
    465     int getMaxPartitions() {
    466         mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
    467 
    468         synchronized (mLock) {
    469             return sPartitionMaxCount;
    470         }
    471     }
    472 
    473     // Called by Shell command.
    474     void setMaxPartitions(int max) {
    475         mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
    476         Slog.i(TAG, "setMaxPartitions(): " + max);
    477         synchronized (mLock) {
    478             sPartitionMaxCount = max;
    479         }
    480     }
    481 
    482     // Called by Shell command.
    483     int getMaxVisibleDatasets() {
    484         mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
    485 
    486         synchronized (mLock) {
    487             return sVisibleDatasetsMaxCount;
    488         }
    489     }
    490 
    491     // Called by Shell command.
    492     void setMaxVisibleDatasets(int max) {
    493         mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
    494         Slog.i(TAG, "setMaxVisibleDatasets(): " + max);
    495         synchronized (mLock) {
    496             sVisibleDatasetsMaxCount = max;
    497         }
    498     }
    499 
    500     // Called by Shell command.
    501     void getScore(@Nullable String algorithmName, @NonNull String value1,
    502             @NonNull String value2, @NonNull RemoteCallback callback) {
    503         mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
    504 
    505         final FieldClassificationStrategy strategy =
    506                 new FieldClassificationStrategy(mContext, UserHandle.USER_CURRENT);
    507 
    508         strategy.getScores(callback, algorithmName, null,
    509                 Arrays.asList(AutofillValue.forText(value1)), new String[] { value2 });
    510     }
    511 
    512     // Called by Shell command.
    513     Boolean getFullScreenMode() {
    514         mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
    515         return sFullScreenMode;
    516     }
    517 
    518     // Called by Shell command.
    519     void setFullScreenMode(@Nullable Boolean mode) {
    520         mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
    521         sFullScreenMode = mode;
    522     }
    523 
    524     // Called by Shell command.
    525     boolean getAllowInstantService() {
    526         mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
    527         synchronized (mLock) {
    528             return mAllowInstantService;
    529         }
    530     }
    531 
    532     // Called by Shell command.
    533     void setAllowInstantService(boolean mode) {
    534         mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
    535         Slog.i(TAG, "setAllowInstantService(): " + mode);
    536         synchronized (mLock) {
    537             mAllowInstantService = mode;
    538         }
    539     }
    540 
    541     private void setDebugLocked(boolean debug) {
    542         com.android.server.autofill.Helper.sDebug = debug;
    543         android.view.autofill.Helper.sDebug = debug;
    544     }
    545 
    546     private void setVerboseLocked(boolean verbose) {
    547         com.android.server.autofill.Helper.sVerbose = verbose;
    548         android.view.autofill.Helper.sVerbose = verbose;
    549     }
    550 
    551     /**
    552      * Removes a cached service for a given user.
    553      */
    554     @GuardedBy("mLock")
    555     private void removeCachedServiceLocked(int userId) {
    556         final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
    557         if (service != null) {
    558             mServicesCache.delete(userId);
    559             service.destroyLocked();
    560             mAutofillCompatState.removeCompatibilityModeRequests(userId);
    561         }
    562     }
    563 
    564     /**
    565      * Updates a cached service for a given user.
    566      */
    567     @GuardedBy("mLock")
    568     private void updateCachedServiceLocked(int userId) {
    569         updateCachedServiceLocked(userId, mDisabledUsers.get(userId));
    570     }
    571 
    572     /**
    573      * Updates a cached service for a given user.
    574      */
    575     @GuardedBy("mLock")
    576     private void updateCachedServiceLocked(int userId, boolean disabled) {
    577         AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
    578         if (service != null) {
    579             service.destroySessionsLocked();
    580             service.updateLocked(disabled);
    581             if (!service.isEnabledLocked()) {
    582                 removeCachedServiceLocked(userId);
    583             } else {
    584                 addCompatibilityModeRequestsLocked(service, userId);
    585             }
    586         }
    587     }
    588 
    589     private void addCompatibilityModeRequestsLocked(@NonNull AutofillManagerServiceImpl service
    590             , int userId) {
    591         mAutofillCompatState.reset(userId);
    592         final ArrayMap<String, Long> compatPackages =
    593                 service.getCompatibilityPackagesLocked();
    594         if (compatPackages == null || compatPackages.isEmpty()) {
    595             return;
    596         }
    597 
    598         final Map<String, String[]> whiteListedPackages = getWhitelistedCompatModePackages();
    599         final int compatPackageCount = compatPackages.size();
    600         for (int i = 0; i < compatPackageCount; i++) {
    601             final String packageName = compatPackages.keyAt(i);
    602             if (whiteListedPackages == null || !whiteListedPackages.containsKey(packageName)) {
    603                 Slog.w(TAG, "Ignoring not whitelisted compat package " + packageName);
    604                 continue;
    605             }
    606             final Long maxVersionCode = compatPackages.valueAt(i);
    607             if (maxVersionCode != null) {
    608                 mAutofillCompatState.addCompatibilityModeRequest(packageName,
    609                         maxVersionCode, whiteListedPackages.get(packageName), userId);
    610             }
    611         }
    612     }
    613 
    614     private String getWhitelistedCompatModePackagesFromSettings() {
    615         return Settings.Global.getString(
    616                 mContext.getContentResolver(),
    617                 Settings.Global.AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES);
    618     }
    619 
    620     @Nullable
    621     private Map<String, String[]> getWhitelistedCompatModePackages() {
    622         return getWhitelistedCompatModePackages(getWhitelistedCompatModePackagesFromSettings());
    623     }
    624 
    625     @Nullable
    626     @VisibleForTesting
    627     static Map<String, String[]> getWhitelistedCompatModePackages(String setting) {
    628         if (TextUtils.isEmpty(setting)) {
    629             return null;
    630         }
    631 
    632         final ArrayMap<String, String[]> compatPackages = new ArrayMap<>();
    633         final SimpleStringSplitter splitter = new SimpleStringSplitter(COMPAT_PACKAGE_DELIMITER);
    634         splitter.setString(setting);
    635         while (splitter.hasNext()) {
    636             final String packageBlock = splitter.next();
    637             final int urlBlockIndex = packageBlock.indexOf(COMPAT_PACKAGE_URL_IDS_BLOCK_BEGIN);
    638             final String packageName;
    639             final List<String> urlBarIds;
    640             if (urlBlockIndex == -1) {
    641                 packageName = packageBlock;
    642                 urlBarIds = null;
    643             } else {
    644                 if (packageBlock.charAt(packageBlock.length() - 1)
    645                         != COMPAT_PACKAGE_URL_IDS_BLOCK_END) {
    646                     Slog.w(TAG, "Ignoring entry '" + packageBlock + "' on '" + setting
    647                             + "'because it does not end on '" + COMPAT_PACKAGE_URL_IDS_BLOCK_END +
    648                             "'");
    649                     continue;
    650                 }
    651                 packageName = packageBlock.substring(0, urlBlockIndex);
    652                 urlBarIds = new ArrayList<>();
    653                 final String urlBarIdsBlock =
    654                         packageBlock.substring(urlBlockIndex + 1, packageBlock.length() - 1);
    655                 if (sVerbose) {
    656                     Slog.v(TAG, "pkg:" + packageName + ": block:" + packageBlock + ": urls:"
    657                             + urlBarIds + ": block:" + urlBarIdsBlock + ":");
    658                 }
    659                 final SimpleStringSplitter splitter2 =
    660                         new SimpleStringSplitter(COMPAT_PACKAGE_URL_IDS_DELIMITER);
    661                 splitter2.setString(urlBarIdsBlock);
    662                 while (splitter2.hasNext()) {
    663                     final String urlBarId = splitter2.next();
    664                     urlBarIds.add(urlBarId);
    665                 }
    666             }
    667             if (urlBarIds == null) {
    668                 compatPackages.put(packageName, null);
    669             } else {
    670                 final String[] urlBarIdsArray = new String[urlBarIds.size()];
    671                 urlBarIds.toArray(urlBarIdsArray);
    672                 compatPackages.put(packageName, urlBarIdsArray);
    673             }
    674         }
    675         return compatPackages;
    676     }
    677 
    678     private final class LocalService extends AutofillManagerInternal {
    679         @Override
    680         public void onBackKeyPressed() {
    681             if (sDebug) Slog.d(TAG, "onBackKeyPressed()");
    682             mUi.hideAll(null);
    683         }
    684 
    685         @Override
    686         public boolean isCompatibilityModeRequested(@NonNull String packageName,
    687                 long versionCode, @UserIdInt int userId) {
    688             return mAutofillCompatState.isCompatibilityModeRequested(
    689                     packageName, versionCode, userId);
    690         }
    691 
    692     }
    693 
    694     /**
    695      * Compatibility mode metadata per package.
    696      */
    697     static final class PackageCompatState {
    698         private final long maxVersionCode;
    699         private final String[] urlBarResourceIds;
    700 
    701         PackageCompatState(long maxVersionCode, String[] urlBarResourceIds) {
    702             this.maxVersionCode = maxVersionCode;
    703             this.urlBarResourceIds = urlBarResourceIds;
    704         }
    705 
    706         @Override
    707         public String toString() {
    708             return "maxVersionCode=" + maxVersionCode
    709                     + ", urlBarResourceIds=" + Arrays.toString(urlBarResourceIds);
    710         }
    711     }
    712 
    713     /**
    714      * Compatibility mode metadata associated with all services.
    715      *
    716      * <p>This object is defined here instead of on each {@link AutofillManagerServiceImpl} because
    717      * it cannot hold a lock on the main lock when
    718      * {@link AutofillCompatState#isCompatibilityModeRequested(String, long, int)} is called by
    719      * external services.
    720      */
    721     static final class AutofillCompatState {
    722         private final Object mLock = new Object();
    723 
    724         /**
    725          * Map of app->compat_state per user.
    726          */
    727         @GuardedBy("mLock")
    728         private SparseArray<ArrayMap<String, PackageCompatState>> mUserSpecs;
    729 
    730         boolean isCompatibilityModeRequested(@NonNull String packageName,
    731                 long versionCode, @UserIdInt int userId) {
    732             synchronized (mLock) {
    733                 if (mUserSpecs == null) {
    734                     return false;
    735                 }
    736                 final ArrayMap<String, PackageCompatState> userSpec = mUserSpecs.get(userId);
    737                 if (userSpec == null) {
    738                     return false;
    739                 }
    740                 final PackageCompatState metadata = userSpec.get(packageName);
    741                 if (metadata == null) {
    742                     return false;
    743                 }
    744                 return versionCode <= metadata.maxVersionCode;
    745             }
    746         }
    747 
    748         @Nullable
    749         String[] getUrlBarResourceIds(@NonNull String packageName, @UserIdInt int userId) {
    750             synchronized (mLock) {
    751                 if (mUserSpecs == null) {
    752                     return null;
    753                 }
    754                 final ArrayMap<String, PackageCompatState> userSpec = mUserSpecs.get(userId);
    755                 if (userSpec == null) {
    756                     return null;
    757                 }
    758                 final PackageCompatState metadata = userSpec.get(packageName);
    759                 if (metadata == null) {
    760                     return null;
    761                 }
    762                 return metadata.urlBarResourceIds;
    763             }
    764         }
    765 
    766         void addCompatibilityModeRequest(@NonNull String packageName,
    767                 long versionCode, @Nullable String[] urlBarResourceIds, @UserIdInt int userId) {
    768             synchronized (mLock) {
    769                 if (mUserSpecs == null) {
    770                     mUserSpecs = new SparseArray<>();
    771                 }
    772                 ArrayMap<String, PackageCompatState> userSpec = mUserSpecs.get(userId);
    773                 if (userSpec == null) {
    774                     userSpec = new ArrayMap<>();
    775                     mUserSpecs.put(userId, userSpec);
    776                 }
    777                 userSpec.put(packageName,
    778                         new PackageCompatState(versionCode, urlBarResourceIds));
    779             }
    780         }
    781 
    782         void removeCompatibilityModeRequests(@UserIdInt int userId) {
    783             synchronized (mLock) {
    784                 if (mUserSpecs != null) {
    785                     mUserSpecs.remove(userId);
    786                     if (mUserSpecs.size() <= 0) {
    787                         mUserSpecs = null;
    788                     }
    789                 }
    790             }
    791         }
    792 
    793         void reset(int userId) {
    794             synchronized (mLock) {
    795                 if (mUserSpecs != null) {
    796                     mUserSpecs.delete(userId);
    797                     final int newSize = mUserSpecs.size();
    798                     if (newSize == 0) {
    799                         if (sVerbose) Slog.v(TAG, "reseting mUserSpecs");
    800                         mUserSpecs = null;
    801                     } else {
    802                         if (sVerbose) Slog.v(TAG, "mUserSpecs down to " + newSize);
    803                     }
    804                 }
    805             }
    806         }
    807 
    808         private void dump(String prefix, PrintWriter pw) {
    809              if (mUserSpecs == null) {
    810                  pw.println("N/A");
    811                  return;
    812              }
    813              pw.println();
    814              final String prefix2 = prefix + "  ";
    815              for (int i = 0; i < mUserSpecs.size(); i++) {
    816                  final int user = mUserSpecs.keyAt(i);
    817                  pw.print(prefix); pw.print("User: "); pw.println(user);
    818                  final ArrayMap<String, PackageCompatState> perUser = mUserSpecs.valueAt(i);
    819                  for (int j = 0; j < perUser.size(); j++) {
    820                      final String packageName = perUser.keyAt(j);
    821                      final PackageCompatState state = perUser.valueAt(j);
    822                      pw.print(prefix2); pw.print(packageName); pw.print(": "); pw.println(state);
    823                 }
    824             }
    825         }
    826     }
    827 
    828     final class AutoFillManagerServiceStub extends IAutoFillManager.Stub {
    829         @Override
    830         public int addClient(IAutoFillManagerClient client, int userId) {
    831             synchronized (mLock) {
    832                 int flags = 0;
    833                 if (getServiceForUserLocked(userId).addClientLocked(client)) {
    834                     flags |= AutofillManager.FLAG_ADD_CLIENT_ENABLED;
    835                 }
    836                 if (sDebug) {
    837                     flags |= AutofillManager.FLAG_ADD_CLIENT_DEBUG;
    838                 }
    839                 if (sVerbose) {
    840                     flags |= AutofillManager.FLAG_ADD_CLIENT_VERBOSE;
    841                 }
    842                 return flags;
    843             }
    844         }
    845 
    846         @Override
    847         public void removeClient(IAutoFillManagerClient client, int userId) {
    848             synchronized (mLock) {
    849                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
    850                 if (service != null) {
    851                     service.removeClientLocked(client);
    852                 } else if (sVerbose) {
    853                     Slog.v(TAG, "removeClient(): no service for " + userId);
    854                 }
    855             }
    856         }
    857 
    858         @Override
    859         public void setAuthenticationResult(Bundle data, int sessionId, int authenticationId,
    860                 int userId) {
    861             synchronized (mLock) {
    862                 final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
    863                 service.setAuthenticationResultLocked(data, sessionId, authenticationId,
    864                         getCallingUid());
    865             }
    866         }
    867 
    868         @Override
    869         public void setHasCallback(int sessionId, int userId, boolean hasIt) {
    870             synchronized (mLock) {
    871                 final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
    872                 service.setHasCallback(sessionId, getCallingUid(), hasIt);
    873             }
    874         }
    875 
    876         @Override
    877         public int startSession(IBinder activityToken, IBinder appCallback, AutofillId autofillId,
    878                 Rect bounds, AutofillValue value, int userId, boolean hasCallback, int flags,
    879                 ComponentName componentName, boolean compatMode) {
    880 
    881             activityToken = Preconditions.checkNotNull(activityToken, "activityToken");
    882             appCallback = Preconditions.checkNotNull(appCallback, "appCallback");
    883             autofillId = Preconditions.checkNotNull(autofillId, "autoFillId");
    884             componentName = Preconditions.checkNotNull(componentName, "componentName");
    885             final String packageName = Preconditions.checkNotNull(componentName.getPackageName());
    886 
    887             Preconditions.checkArgument(userId == UserHandle.getUserId(getCallingUid()), "userId");
    888 
    889             try {
    890                 mContext.getPackageManager().getPackageInfoAsUser(packageName, 0, userId);
    891             } catch (PackageManager.NameNotFoundException e) {
    892                 throw new IllegalArgumentException(packageName + " is not a valid package", e);
    893             }
    894 
    895             synchronized (mLock) {
    896                 final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
    897                 return service.startSessionLocked(activityToken, getCallingUid(), appCallback,
    898                         autofillId, bounds, value, hasCallback, componentName, compatMode,
    899                         mAllowInstantService, flags);
    900             }
    901         }
    902 
    903         @Override
    904         public FillEventHistory getFillEventHistory() throws RemoteException {
    905             final int userId = UserHandle.getCallingUserId();
    906 
    907             synchronized (mLock) {
    908                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
    909                 if (service != null) {
    910                     return service.getFillEventHistory(getCallingUid());
    911                 } else if (sVerbose) {
    912                     Slog.v(TAG, "getFillEventHistory(): no service for " + userId);
    913                 }
    914             }
    915 
    916             return null;
    917         }
    918 
    919         @Override
    920         public UserData getUserData() throws RemoteException {
    921             final int userId = UserHandle.getCallingUserId();
    922 
    923             synchronized (mLock) {
    924                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
    925                 if (service != null) {
    926                     return service.getUserData(getCallingUid());
    927                 } else if (sVerbose) {
    928                     Slog.v(TAG, "getUserData(): no service for " + userId);
    929                 }
    930             }
    931 
    932             return null;
    933         }
    934 
    935         @Override
    936         public String getUserDataId() throws RemoteException {
    937             final int userId = UserHandle.getCallingUserId();
    938 
    939             synchronized (mLock) {
    940                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
    941                 if (service != null) {
    942                     final UserData userData = service.getUserData(getCallingUid());
    943                     return userData == null ? null : userData.getId();
    944                 } else if (sVerbose) {
    945                     Slog.v(TAG, "getUserDataId(): no service for " + userId);
    946                 }
    947             }
    948 
    949             return null;
    950         }
    951 
    952         @Override
    953         public void setUserData(UserData userData) throws RemoteException {
    954             final int userId = UserHandle.getCallingUserId();
    955 
    956             synchronized (mLock) {
    957                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
    958                 if (service != null) {
    959                     service.setUserData(getCallingUid(), userData);
    960                 } else if (sVerbose) {
    961                     Slog.v(TAG, "setUserData(): no service for " + userId);
    962                 }
    963             }
    964         }
    965 
    966         @Override
    967         public boolean isFieldClassificationEnabled() throws RemoteException {
    968             final int userId = UserHandle.getCallingUserId();
    969 
    970             synchronized (mLock) {
    971                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
    972                 if (service != null) {
    973                     return service.isFieldClassificationEnabled(getCallingUid());
    974                 } else if (sVerbose) {
    975                     Slog.v(TAG, "isFieldClassificationEnabled(): no service for " + userId);
    976                 }
    977             }
    978 
    979             return false;
    980         }
    981 
    982         @Override
    983         public String getDefaultFieldClassificationAlgorithm() throws RemoteException {
    984             final int userId = UserHandle.getCallingUserId();
    985 
    986             synchronized (mLock) {
    987                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
    988                 if (service != null) {
    989                     return service.getDefaultFieldClassificationAlgorithm(getCallingUid());
    990                 } else {
    991                     if (sVerbose) {
    992                         Slog.v(TAG, "getDefaultFcAlgorithm(): no service for " + userId);
    993                     }
    994                     return null;
    995                }
    996             }
    997         }
    998 
    999         @Override
   1000         public String[] getAvailableFieldClassificationAlgorithms() throws RemoteException {
   1001             final int userId = UserHandle.getCallingUserId();
   1002 
   1003             synchronized (mLock) {
   1004                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
   1005                 if (service != null) {
   1006                     return service.getAvailableFieldClassificationAlgorithms(getCallingUid());
   1007                 } else {
   1008                     if (sVerbose) {
   1009                         Slog.v(TAG, "getAvailableFcAlgorithms(): no service for " + userId);
   1010                     }
   1011                     return null;
   1012                 }
   1013             }
   1014         }
   1015 
   1016         @Override
   1017         public ComponentName getAutofillServiceComponentName() throws RemoteException {
   1018             final int userId = UserHandle.getCallingUserId();
   1019 
   1020             synchronized (mLock) {
   1021                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
   1022                 if (service != null) {
   1023                     return service.getServiceComponentName();
   1024                 } else if (sVerbose) {
   1025                     Slog.v(TAG, "getAutofillServiceComponentName(): no service for " + userId);
   1026                 }
   1027             }
   1028 
   1029             return null;
   1030         }
   1031 
   1032         @Override
   1033         public boolean restoreSession(int sessionId, IBinder activityToken, IBinder appCallback)
   1034                 throws RemoteException {
   1035             final int userId = UserHandle.getCallingUserId();
   1036             activityToken = Preconditions.checkNotNull(activityToken, "activityToken");
   1037             appCallback = Preconditions.checkNotNull(appCallback, "appCallback");
   1038 
   1039             synchronized (mLock) {
   1040                 final AutofillManagerServiceImpl service = mServicesCache.get(userId);
   1041                 if (service != null) {
   1042                     return service.restoreSession(sessionId, getCallingUid(), activityToken,
   1043                             appCallback);
   1044                 } else if (sVerbose) {
   1045                     Slog.v(TAG, "restoreSession(): no service for " + userId);
   1046                 }
   1047             }
   1048 
   1049             return false;
   1050         }
   1051 
   1052         @Override
   1053         public void updateSession(int sessionId, AutofillId autoFillId, Rect bounds,
   1054                 AutofillValue value, int action, int flags, int userId) {
   1055             synchronized (mLock) {
   1056                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
   1057                 if (service != null) {
   1058                     service.updateSessionLocked(sessionId, getCallingUid(), autoFillId, bounds,
   1059                             value, action, flags);
   1060                 } else if (sVerbose) {
   1061                     Slog.v(TAG, "updateSession(): no service for " + userId);
   1062                 }
   1063             }
   1064         }
   1065 
   1066         @Override
   1067         public int updateOrRestartSession(IBinder activityToken, IBinder appCallback,
   1068                 AutofillId autoFillId, Rect bounds, AutofillValue value, int userId,
   1069                 boolean hasCallback, int flags, ComponentName componentName, int sessionId,
   1070                 int action, boolean compatMode) {
   1071             boolean restart = false;
   1072             synchronized (mLock) {
   1073                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
   1074                 if (service != null) {
   1075                     restart = service.updateSessionLocked(sessionId, getCallingUid(), autoFillId,
   1076                             bounds, value, action, flags);
   1077                 } else if (sVerbose) {
   1078                     Slog.v(TAG, "updateOrRestartSession(): no service for " + userId);
   1079                 }
   1080             }
   1081             if (restart) {
   1082                 return startSession(activityToken, appCallback, autoFillId, bounds, value, userId,
   1083                         hasCallback, flags, componentName, compatMode);
   1084             }
   1085 
   1086             // Nothing changed...
   1087             return sessionId;
   1088         }
   1089 
   1090         @Override
   1091         public void setAutofillFailure(int sessionId, @NonNull List<AutofillId> ids, int userId) {
   1092             synchronized (mLock) {
   1093                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
   1094                 if (service != null) {
   1095                     service.setAutofillFailureLocked(sessionId, getCallingUid(), ids);
   1096                 } else if (sVerbose) {
   1097                     Slog.v(TAG, "setAutofillFailure(): no service for " + userId);
   1098                 }
   1099             }
   1100         }
   1101 
   1102         @Override
   1103         public void finishSession(int sessionId, int userId) {
   1104             synchronized (mLock) {
   1105                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
   1106                 if (service != null) {
   1107                     service.finishSessionLocked(sessionId, getCallingUid());
   1108                 } else if (sVerbose) {
   1109                     Slog.v(TAG, "finishSession(): no service for " + userId);
   1110                 }
   1111             }
   1112         }
   1113 
   1114         @Override
   1115         public void cancelSession(int sessionId, int userId) {
   1116             synchronized (mLock) {
   1117                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
   1118                 if (service != null) {
   1119                     service.cancelSessionLocked(sessionId, getCallingUid());
   1120                 } else if (sVerbose) {
   1121                     Slog.v(TAG, "cancelSession(): no service for " + userId);
   1122                 }
   1123             }
   1124         }
   1125 
   1126         @Override
   1127         public void disableOwnedAutofillServices(int userId) {
   1128             synchronized (mLock) {
   1129                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
   1130                 if (service != null) {
   1131                     service.disableOwnedAutofillServicesLocked(Binder.getCallingUid());
   1132                 } else if (sVerbose) {
   1133                     Slog.v(TAG, "cancelSession(): no service for " + userId);
   1134                 }
   1135             }
   1136         }
   1137 
   1138         @Override
   1139         public boolean isServiceSupported(int userId) {
   1140             synchronized (mLock) {
   1141                 return !mDisabledUsers.get(userId);
   1142             }
   1143         }
   1144 
   1145         @Override
   1146         public boolean isServiceEnabled(int userId, String packageName) {
   1147             synchronized (mLock) {
   1148                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
   1149                 if (service != null) {
   1150                     return Objects.equals(packageName, service.getServicePackageName());
   1151                 } else if (sVerbose) {
   1152                     Slog.v(TAG, "isServiceEnabled(): no service for " + userId);
   1153                 }
   1154                 return false;
   1155             }
   1156         }
   1157 
   1158         @Override
   1159         public void onPendingSaveUi(int operation, IBinder token) {
   1160             Preconditions.checkNotNull(token, "token");
   1161             Preconditions.checkArgument(operation == AutofillManager.PENDING_UI_OPERATION_CANCEL
   1162                     || operation == AutofillManager.PENDING_UI_OPERATION_RESTORE,
   1163                     "invalid operation: %d", operation);
   1164             synchronized (mLock) {
   1165                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(
   1166                         UserHandle.getCallingUserId());
   1167                 if (service != null) {
   1168                     service.onPendingSaveUi(operation, token);
   1169                 }
   1170             }
   1171         }
   1172 
   1173         @Override
   1174         public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
   1175             if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
   1176 
   1177             boolean showHistory = true;
   1178             boolean uiOnly = false;
   1179             if (args != null) {
   1180                 for (String arg : args) {
   1181                     switch(arg) {
   1182                         case "--no-history":
   1183                             showHistory = false;
   1184                             break;
   1185                         case "--ui-only":
   1186                             uiOnly = true;
   1187                             break;
   1188                         case "--help":
   1189                             pw.println("Usage: dumpsys autofill [--ui-only|--no-history]");
   1190                             return;
   1191                         default:
   1192                             Slog.w(TAG, "Ignoring invalid dump arg: " + arg);
   1193                     }
   1194                 }
   1195             }
   1196 
   1197             if (uiOnly) {
   1198                 mUi.dump(pw);
   1199                 return;
   1200             }
   1201 
   1202             boolean oldDebug = sDebug;
   1203             final String prefix = "  ";
   1204             final String prefix2 = "    ";
   1205             try {
   1206                 synchronized (mLock) {
   1207                     oldDebug = sDebug;
   1208                     setDebugLocked(true);
   1209                     pw.print("Debug mode: "); pw.println(oldDebug);
   1210                     pw.print("Verbose mode: "); pw.println(sVerbose);
   1211                     pw.print("Disabled users: "); pw.println(mDisabledUsers);
   1212                     pw.print("Max partitions per session: "); pw.println(sPartitionMaxCount);
   1213                     pw.print("Max visible datasets: "); pw.println(sVisibleDatasetsMaxCount);
   1214                     if (sFullScreenMode != null) {
   1215                         pw.print("Overridden full-screen mode: "); pw.println(sFullScreenMode);
   1216                     }
   1217                     pw.println("User data constraints: "); UserData.dumpConstraints(prefix, pw);
   1218                     final int size = mServicesCache.size();
   1219                     pw.print("Cached services: ");
   1220                     if (size == 0) {
   1221                         pw.println("none");
   1222                     } else {
   1223                         pw.println(size);
   1224                         for (int i = 0; i < size; i++) {
   1225                             pw.print("\nService at index "); pw.println(i);
   1226                             final AutofillManagerServiceImpl impl = mServicesCache.valueAt(i);
   1227                             impl.dumpLocked(prefix, pw);
   1228                         }
   1229                     }
   1230                     mUi.dump(pw);
   1231                     pw.print("Autofill Compat State: ");
   1232                     mAutofillCompatState.dump(prefix2, pw);
   1233                     pw.print(prefix2); pw.print("from settings: ");
   1234                     pw.println(getWhitelistedCompatModePackagesFromSettings());
   1235                     pw.print("Allow instant service: "); pw.println(mAllowInstantService);
   1236                 }
   1237                 if (showHistory) {
   1238                     pw.println(); pw.println("Requests history:"); pw.println();
   1239                     mRequestsHistory.reverseDump(fd, pw, args);
   1240                     pw.println(); pw.println("UI latency history:"); pw.println();
   1241                     mUiLatencyHistory.reverseDump(fd, pw, args);
   1242                     pw.println(); pw.println("WTF history:"); pw.println();
   1243                     mWtfHistory.reverseDump(fd, pw, args);
   1244                 }
   1245             } finally {
   1246                 setDebugLocked(oldDebug);
   1247             }
   1248         }
   1249 
   1250         @Override
   1251         public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
   1252                 String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
   1253             (new AutofillManagerServiceShellCommand(AutofillManagerService.this)).exec(
   1254                     this, in, out, err, args, callback, resultReceiver);
   1255         }
   1256     }
   1257 
   1258     private final class SettingsObserver extends ContentObserver {
   1259         SettingsObserver(Handler handler) {
   1260             super(handler);
   1261             ContentResolver resolver = mContext.getContentResolver();
   1262             resolver.registerContentObserver(Settings.Secure.getUriFor(
   1263                     Settings.Secure.AUTOFILL_SERVICE), false, this, UserHandle.USER_ALL);
   1264             resolver.registerContentObserver(Settings.Secure.getUriFor(
   1265                     Settings.Secure.USER_SETUP_COMPLETE), false, this, UserHandle.USER_ALL);
   1266             resolver.registerContentObserver(Settings.Global.getUriFor(
   1267                     Settings.Global.AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES), false, this,
   1268                     UserHandle.USER_ALL);
   1269         }
   1270 
   1271         @Override
   1272         public void onChange(boolean selfChange, Uri uri, int userId) {
   1273             if (sVerbose) Slog.v(TAG, "onChange(): uri=" + uri + ", userId=" + userId);
   1274             synchronized (mLock) {
   1275                 updateCachedServiceLocked(userId);
   1276             }
   1277         }
   1278     }
   1279 }
   1280