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.bundleToString;
     23 import static com.android.server.autofill.Helper.sDebug;
     24 import static com.android.server.autofill.Helper.sPartitionMaxCount;
     25 import static com.android.server.autofill.Helper.sVerbose;
     26 
     27 import android.annotation.NonNull;
     28 import android.annotation.Nullable;
     29 import android.app.ActivityManager;
     30 import android.app.ActivityThread;
     31 import android.content.BroadcastReceiver;
     32 import android.content.ComponentName;
     33 import android.content.ContentResolver;
     34 import android.content.Context;
     35 import android.content.Intent;
     36 import android.content.IntentFilter;
     37 import android.content.pm.PackageManager;
     38 import android.content.pm.UserInfo;
     39 import android.database.ContentObserver;
     40 import android.graphics.Rect;
     41 import android.net.Uri;
     42 import android.os.Binder;
     43 import android.os.Build;
     44 import android.os.Bundle;
     45 import android.os.Handler;
     46 import android.os.IBinder;
     47 import android.os.RemoteException;
     48 import android.os.ResultReceiver;
     49 import android.os.ShellCallback;
     50 import android.os.UserHandle;
     51 import android.os.UserManager;
     52 import android.os.UserManagerInternal;
     53 import android.provider.Settings;
     54 import android.service.autofill.FillEventHistory;
     55 import android.util.LocalLog;
     56 import android.util.Slog;
     57 import android.util.SparseArray;
     58 import android.util.SparseBooleanArray;
     59 import android.view.autofill.AutofillId;
     60 import android.view.autofill.AutofillManager;
     61 import android.view.autofill.AutofillManagerInternal;
     62 import android.view.autofill.AutofillValue;
     63 import android.view.autofill.IAutoFillManager;
     64 import android.view.autofill.IAutoFillManagerClient;
     65 
     66 import com.android.internal.annotations.GuardedBy;
     67 import com.android.internal.content.PackageMonitor;
     68 import com.android.internal.os.BackgroundThread;
     69 import com.android.internal.os.IResultReceiver;
     70 import com.android.internal.util.DumpUtils;
     71 import com.android.internal.util.Preconditions;
     72 import com.android.server.FgThread;
     73 import com.android.server.LocalServices;
     74 import com.android.server.SystemService;
     75 import com.android.server.autofill.ui.AutoFillUI;
     76 
     77 import java.io.FileDescriptor;
     78 import java.io.PrintWriter;
     79 import java.util.ArrayList;
     80 import java.util.List;
     81 import java.util.Objects;
     82 
     83 /**
     84  * Entry point service for autofill management.
     85  *
     86  * <p>This service provides the {@link IAutoFillManager} implementation and keeps a list of
     87  * {@link AutofillManagerServiceImpl} per user; the real work is done by
     88  * {@link AutofillManagerServiceImpl} itself.
     89  */
     90 public final class AutofillManagerService extends SystemService {
     91 
     92     private static final String TAG = "AutofillManagerService";
     93 
     94     static final String RECEIVER_BUNDLE_EXTRA_SESSIONS = "sessions";
     95 
     96     private final Context mContext;
     97     private final AutoFillUI mUi;
     98 
     99     private final Object mLock = new Object();
    100 
    101     /**
    102      * Cache of {@link AutofillManagerServiceImpl} per user id.
    103      * <p>
    104      * It has to be mapped by user id because the same current user could have simultaneous sessions
    105      * associated to different user profiles (for example, in a multi-window environment or when
    106      * device has work profiles).
    107      */
    108     @GuardedBy("mLock")
    109     private SparseArray<AutofillManagerServiceImpl> mServicesCache = new SparseArray<>();
    110 
    111     /**
    112      * Users disabled due to {@link UserManager} restrictions.
    113      */
    114     @GuardedBy("mLock")
    115     private final SparseBooleanArray mDisabledUsers = new SparseBooleanArray();
    116 
    117     private final LocalLog mRequestsHistory = new LocalLog(20);
    118     private final LocalLog mUiLatencyHistory = new LocalLog(20);
    119 
    120     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
    121         @Override
    122         public void onReceive(Context context, Intent intent) {
    123             if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) {
    124                 if (sDebug) Slog.d(TAG, "Close system dialogs");
    125 
    126                 // TODO(b/64940307): we need to destroy all sessions that are finished but showing
    127                 // Save UI because there is no way to show the Save UI back when the activity
    128                 // beneath it is brought back to top. Ideally, we should just hide the UI and
    129                 // bring it back when the activity resumes.
    130                 synchronized (mLock) {
    131                     for (int i = 0; i < mServicesCache.size(); i++) {
    132                         mServicesCache.valueAt(i).destroyFinishedSessionsLocked();
    133                     }
    134                 }
    135 
    136                 mUi.hideAll(null);
    137             }
    138         }
    139     };
    140 
    141     public AutofillManagerService(Context context) {
    142         super(context);
    143         mContext = context;
    144         mUi = new AutoFillUI(ActivityThread.currentActivityThread().getSystemUiContext());
    145 
    146         final boolean debug = Build.IS_DEBUGGABLE;
    147         Slog.i(TAG, "Setting debug to " + debug);
    148         setDebugLocked(debug);
    149 
    150         final IntentFilter filter = new IntentFilter();
    151         filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
    152         mContext.registerReceiver(mBroadcastReceiver, filter, null, FgThread.getHandler());
    153 
    154         // Hookup with UserManager to disable service when necessary.
    155         final UserManager um = context.getSystemService(UserManager.class);
    156         final UserManagerInternal umi = LocalServices.getService(UserManagerInternal.class);
    157         final List<UserInfo> users = um.getUsers();
    158         for (int i = 0; i < users.size(); i++) {
    159             final int userId = users.get(i).id;
    160             final boolean disabled = umi.getUserRestriction(userId, UserManager.DISALLOW_AUTOFILL);
    161             if (disabled) {
    162                 if (disabled) {
    163                     Slog.i(TAG, "Disabling Autofill for user " + userId);
    164                 }
    165                 mDisabledUsers.put(userId, disabled);
    166             }
    167         }
    168         umi.addUserRestrictionsListener((userId, newRestrictions, prevRestrictions) -> {
    169             final boolean disabledNow =
    170                     newRestrictions.getBoolean(UserManager.DISALLOW_AUTOFILL, false);
    171             synchronized (mLock) {
    172                 final boolean disabledBefore = mDisabledUsers.get(userId);
    173                 if (disabledBefore == disabledNow) {
    174                     // Nothing changed, do nothing.
    175                     if (sDebug) {
    176                         Slog.d(TAG, "Autofill restriction did not change for user " + userId + ": "
    177                                 + bundleToString(newRestrictions));
    178                         return;
    179                     }
    180                 }
    181                 Slog.i(TAG, "Updating Autofill for user " + userId + ": disabled=" + disabledNow);
    182                 mDisabledUsers.put(userId, disabledNow);
    183                 updateCachedServiceLocked(userId, disabledNow);
    184             }
    185         });
    186         startTrackingPackageChanges();
    187     }
    188 
    189     private void startTrackingPackageChanges() {
    190         PackageMonitor monitor = new PackageMonitor() {
    191             @Override
    192             public void onSomePackagesChanged() {
    193                 synchronized (mLock) {
    194                     updateCachedServiceLocked(getChangingUserId());
    195                 }
    196             }
    197 
    198             @Override
    199             public void onPackageUpdateFinished(String packageName, int uid) {
    200                 synchronized (mLock) {
    201                     final String activePackageName = getActiveAutofillServicePackageName();
    202                     if (packageName.equals(activePackageName)) {
    203                         removeCachedServiceLocked(getChangingUserId());
    204                     }
    205                 }
    206             }
    207 
    208             @Override
    209             public void onPackageRemoved(String packageName, int uid) {
    210                 synchronized (mLock) {
    211                     final int userId = getChangingUserId();
    212                     final AutofillManagerServiceImpl userState = peekServiceForUserLocked(userId);
    213                     if (userState != null) {
    214                         final ComponentName componentName = userState.getServiceComponentName();
    215                         if (componentName != null) {
    216                             if (packageName.equals(componentName.getPackageName())) {
    217                                 handleActiveAutofillServiceRemoved(userId);
    218                             }
    219                         }
    220                     }
    221                 }
    222             }
    223 
    224             @Override
    225             public boolean onHandleForceStop(Intent intent, String[] packages,
    226                     int uid, boolean doit) {
    227                 synchronized (mLock) {
    228                     final String activePackageName = getActiveAutofillServicePackageName();
    229                     for (String pkg : packages) {
    230                         if (pkg.equals(activePackageName)) {
    231                             if (!doit) {
    232                                 return true;
    233                             }
    234                             removeCachedServiceLocked(getChangingUserId());
    235                         }
    236                     }
    237                 }
    238                 return false;
    239             }
    240 
    241             private void handleActiveAutofillServiceRemoved(int userId) {
    242                 removeCachedServiceLocked(userId);
    243                 Settings.Secure.putStringForUser(mContext.getContentResolver(),
    244                         Settings.Secure.AUTOFILL_SERVICE, null, userId);
    245             }
    246 
    247             private String getActiveAutofillServicePackageName() {
    248                 final int userId = getChangingUserId();
    249                 final AutofillManagerServiceImpl userState = peekServiceForUserLocked(userId);
    250                 if (userState == null) {
    251                     return null;
    252                 }
    253                 final ComponentName serviceComponent = userState.getServiceComponentName();
    254                 if (serviceComponent == null) {
    255                     return null;
    256                 }
    257                 return serviceComponent.getPackageName();
    258             }
    259         };
    260 
    261         // package changes
    262         monitor.register(mContext, null,  UserHandle.ALL, true);
    263     }
    264 
    265     @Override
    266     public void onStart() {
    267         publishBinderService(AUTOFILL_MANAGER_SERVICE, new AutoFillManagerServiceStub());
    268         publishLocalService(AutofillManagerInternal.class, new LocalService());
    269     }
    270 
    271     @Override
    272     public void onBootPhase(int phase) {
    273         if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
    274             new SettingsObserver(BackgroundThread.getHandler());
    275         }
    276     }
    277 
    278     @Override
    279     public void onUnlockUser(int userId) {
    280         synchronized (mLock) {
    281             updateCachedServiceLocked(userId);
    282         }
    283     }
    284 
    285     @Override
    286     public void onSwitchUser(int userHandle) {
    287         if (sDebug) Slog.d(TAG, "Hiding UI when user switched");
    288         mUi.hideAll(null);
    289     }
    290 
    291     @Override
    292     public void onCleanupUser(int userId) {
    293         synchronized (mLock) {
    294             removeCachedServiceLocked(userId);
    295         }
    296     }
    297 
    298     /**
    299      * Gets the service instance for an user.
    300      *
    301      * @return service instance.
    302      */
    303     @NonNull
    304     AutofillManagerServiceImpl getServiceForUserLocked(int userId) {
    305         final int resolvedUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
    306                 Binder.getCallingUid(), userId, false, false, null, null);
    307         AutofillManagerServiceImpl service = mServicesCache.get(resolvedUserId);
    308         if (service == null) {
    309             service = new AutofillManagerServiceImpl(mContext, mLock, mRequestsHistory,
    310                     mUiLatencyHistory, resolvedUserId, mUi, mDisabledUsers.get(resolvedUserId));
    311             mServicesCache.put(userId, service);
    312         }
    313         return service;
    314     }
    315 
    316     /**
    317      * Peeks the service instance for a user.
    318      *
    319      * @return service instance or {@code null} if not already present
    320      */
    321     @Nullable
    322     AutofillManagerServiceImpl peekServiceForUserLocked(int userId) {
    323         final int resolvedUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
    324                 Binder.getCallingUid(), userId, false, false, null, null);
    325         return mServicesCache.get(resolvedUserId);
    326     }
    327 
    328     // Called by Shell command.
    329     void destroySessions(int userId, IResultReceiver receiver) {
    330         Slog.i(TAG, "destroySessions() for userId " + userId);
    331         mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
    332 
    333         synchronized (mLock) {
    334             if (userId != UserHandle.USER_ALL) {
    335                 AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
    336                 if (service != null) {
    337                     service.destroySessionsLocked();
    338                 }
    339             } else {
    340                 final int size = mServicesCache.size();
    341                 for (int i = 0; i < size; i++) {
    342                     mServicesCache.valueAt(i).destroySessionsLocked();
    343                 }
    344             }
    345         }
    346 
    347         try {
    348             receiver.send(0, new Bundle());
    349         } catch (RemoteException e) {
    350             // Just ignore it...
    351         }
    352     }
    353 
    354     // Called by Shell command.
    355     void listSessions(int userId, IResultReceiver receiver) {
    356         Slog.i(TAG, "listSessions() for userId " + userId);
    357         mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
    358 
    359         final Bundle resultData = new Bundle();
    360         final ArrayList<String> sessions = new ArrayList<>();
    361 
    362         synchronized (mLock) {
    363             if (userId != UserHandle.USER_ALL) {
    364                 AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
    365                 if (service != null) {
    366                     service.listSessionsLocked(sessions);
    367                 }
    368             } else {
    369                 final int size = mServicesCache.size();
    370                 for (int i = 0; i < size; i++) {
    371                     mServicesCache.valueAt(i).listSessionsLocked(sessions);
    372                 }
    373             }
    374         }
    375 
    376         resultData.putStringArrayList(RECEIVER_BUNDLE_EXTRA_SESSIONS, sessions);
    377         try {
    378             receiver.send(0, resultData);
    379         } catch (RemoteException e) {
    380             // Just ignore it...
    381         }
    382     }
    383 
    384     // Called by Shell command.
    385     void reset() {
    386         Slog.i(TAG, "reset()");
    387         mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
    388 
    389         synchronized (mLock) {
    390             final int size = mServicesCache.size();
    391             for (int i = 0; i < size; i++) {
    392                 mServicesCache.valueAt(i).destroyLocked();
    393             }
    394             mServicesCache.clear();
    395         }
    396     }
    397 
    398     // Called by Shell command.
    399     void setLogLevel(int level) {
    400         Slog.i(TAG, "setLogLevel(): " + level);
    401         mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
    402 
    403         boolean debug = false;
    404         boolean verbose = false;
    405         if (level == AutofillManager.FLAG_ADD_CLIENT_VERBOSE) {
    406             debug = verbose = true;
    407         } else if (level == AutofillManager.FLAG_ADD_CLIENT_DEBUG) {
    408             debug = true;
    409         }
    410         synchronized (mLock) {
    411             setDebugLocked(debug);
    412             setVerboseLocked(verbose);
    413         }
    414     }
    415 
    416     // Called by Shell command.
    417     int getLogLevel() {
    418         mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
    419 
    420         synchronized (mLock) {
    421             if (sVerbose) return AutofillManager.FLAG_ADD_CLIENT_VERBOSE;
    422             if (sDebug) return AutofillManager.FLAG_ADD_CLIENT_DEBUG;
    423             return 0;
    424         }
    425     }
    426 
    427     // Called by Shell command.
    428     public int getMaxPartitions() {
    429         mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
    430 
    431         synchronized (mLock) {
    432             return sPartitionMaxCount;
    433         }
    434     }
    435 
    436     // Called by Shell command.
    437     public void setMaxPartitions(int max) {
    438         mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
    439         Slog.i(TAG, "setMaxPartitions(): " + max);
    440         synchronized (mLock) {
    441             sPartitionMaxCount = max;
    442         }
    443     }
    444 
    445     private void setDebugLocked(boolean debug) {
    446         com.android.server.autofill.Helper.sDebug = debug;
    447         android.view.autofill.Helper.sDebug = debug;
    448     }
    449 
    450 
    451     private void setVerboseLocked(boolean verbose) {
    452         com.android.server.autofill.Helper.sVerbose = verbose;
    453         android.view.autofill.Helper.sVerbose = verbose;
    454     }
    455 
    456     /**
    457      * Removes a cached service for a given user.
    458      */
    459     private void removeCachedServiceLocked(int userId) {
    460         final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
    461         if (service != null) {
    462             mServicesCache.delete(userId);
    463             service.destroyLocked();
    464         }
    465     }
    466 
    467     /**
    468      * Updates a cached service for a given user.
    469      */
    470     private void updateCachedServiceLocked(int userId) {
    471         updateCachedServiceLocked(userId, mDisabledUsers.get(userId));
    472     }
    473 
    474     /**
    475      * Updates a cached service for a given user.
    476      */
    477     private void updateCachedServiceLocked(int userId, boolean disabled) {
    478         AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
    479         if (service != null) {
    480             service.destroySessionsLocked();
    481             service.updateLocked(disabled);
    482             if (!service.isEnabled()) {
    483                 removeCachedServiceLocked(userId);
    484             }
    485         }
    486     }
    487 
    488     private final class LocalService extends AutofillManagerInternal {
    489 
    490         @Override
    491         public void onBackKeyPressed() {
    492             if (sDebug) Slog.d(TAG, "onBackKeyPressed()");
    493             mUi.hideAll(null);
    494         }
    495     }
    496 
    497     final class AutoFillManagerServiceStub extends IAutoFillManager.Stub {
    498         @Override
    499         public int addClient(IAutoFillManagerClient client, int userId) {
    500             synchronized (mLock) {
    501                 int flags = 0;
    502                 if (getServiceForUserLocked(userId).addClientLocked(client)) {
    503                     flags |= AutofillManager.FLAG_ADD_CLIENT_ENABLED;
    504                 }
    505                 if (sDebug) {
    506                     flags |= AutofillManager.FLAG_ADD_CLIENT_DEBUG;
    507                 }
    508                 if (sVerbose) {
    509                     flags |= AutofillManager.FLAG_ADD_CLIENT_VERBOSE;
    510                 }
    511                 return flags;
    512             }
    513         }
    514 
    515         @Override
    516         public void setAuthenticationResult(Bundle data, int sessionId, int authenticationId,
    517                 int userId) {
    518             synchronized (mLock) {
    519                 final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
    520                 service.setAuthenticationResultLocked(data, sessionId, authenticationId,
    521                         getCallingUid());
    522             }
    523         }
    524 
    525         @Override
    526         public void setHasCallback(int sessionId, int userId, boolean hasIt) {
    527             synchronized (mLock) {
    528                 final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
    529                 service.setHasCallback(sessionId, getCallingUid(), hasIt);
    530             }
    531         }
    532 
    533         @Override
    534         public int startSession(IBinder activityToken, IBinder appCallback, AutofillId autofillId,
    535                 Rect bounds, AutofillValue value, int userId, boolean hasCallback, int flags,
    536                 String packageName) {
    537 
    538             activityToken = Preconditions.checkNotNull(activityToken, "activityToken");
    539             appCallback = Preconditions.checkNotNull(appCallback, "appCallback");
    540             autofillId = Preconditions.checkNotNull(autofillId, "autoFillId");
    541             packageName = Preconditions.checkNotNull(packageName, "packageName");
    542 
    543             Preconditions.checkArgument(userId == UserHandle.getUserId(getCallingUid()), "userId");
    544 
    545             try {
    546                 mContext.getPackageManager().getPackageInfoAsUser(packageName, 0, userId);
    547             } catch (PackageManager.NameNotFoundException e) {
    548                 throw new IllegalArgumentException(packageName + " is not a valid package", e);
    549             }
    550 
    551             synchronized (mLock) {
    552                 final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
    553                 return service.startSessionLocked(activityToken, getCallingUid(), appCallback,
    554                         autofillId, bounds, value, hasCallback, flags, packageName);
    555             }
    556         }
    557 
    558         @Override
    559         public FillEventHistory getFillEventHistory() throws RemoteException {
    560             UserHandle user = getCallingUserHandle();
    561             int uid = getCallingUid();
    562 
    563             synchronized (mLock) {
    564                 AutofillManagerServiceImpl service = peekServiceForUserLocked(user.getIdentifier());
    565                 if (service != null) {
    566                     return service.getFillEventHistory(uid);
    567                 }
    568             }
    569 
    570             return null;
    571         }
    572 
    573         @Override
    574         public boolean restoreSession(int sessionId, IBinder activityToken, IBinder appCallback)
    575                 throws RemoteException {
    576             activityToken = Preconditions.checkNotNull(activityToken, "activityToken");
    577             appCallback = Preconditions.checkNotNull(appCallback, "appCallback");
    578 
    579             synchronized (mLock) {
    580                 final AutofillManagerServiceImpl service = mServicesCache.get(
    581                         UserHandle.getCallingUserId());
    582                 if (service != null) {
    583                     return service.restoreSession(sessionId, getCallingUid(), activityToken,
    584                             appCallback);
    585                 }
    586             }
    587 
    588             return false;
    589         }
    590 
    591         @Override
    592         public void updateSession(int sessionId, AutofillId autoFillId, Rect bounds,
    593                 AutofillValue value, int action, int flags, int userId) {
    594             synchronized (mLock) {
    595                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
    596                 if (service != null) {
    597                     service.updateSessionLocked(sessionId, getCallingUid(), autoFillId, bounds,
    598                             value, action, flags);
    599                 }
    600             }
    601         }
    602 
    603         @Override
    604         public int updateOrRestartSession(IBinder activityToken, IBinder appCallback,
    605                 AutofillId autoFillId, Rect bounds, AutofillValue value, int userId,
    606                 boolean hasCallback, int flags, String packageName, int sessionId, int action) {
    607             boolean restart = false;
    608             synchronized (mLock) {
    609                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
    610                 if (service != null) {
    611                     restart = service.updateSessionLocked(sessionId, getCallingUid(), autoFillId,
    612                             bounds, value, action, flags);
    613                 }
    614             }
    615             if (restart) {
    616                 return startSession(activityToken, appCallback, autoFillId, bounds, value, userId,
    617                         hasCallback, flags, packageName);
    618             }
    619 
    620             // Nothing changed...
    621             return sessionId;
    622         }
    623 
    624         @Override
    625         public void finishSession(int sessionId, int userId) {
    626             synchronized (mLock) {
    627                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
    628                 if (service != null) {
    629                     service.finishSessionLocked(sessionId, getCallingUid());
    630                 }
    631             }
    632         }
    633 
    634         @Override
    635         public void cancelSession(int sessionId, int userId) {
    636             synchronized (mLock) {
    637                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
    638                 if (service != null) {
    639                     service.cancelSessionLocked(sessionId, getCallingUid());
    640                 }
    641             }
    642         }
    643 
    644         @Override
    645         public void disableOwnedAutofillServices(int userId) {
    646             synchronized (mLock) {
    647                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
    648                 if (service != null) {
    649                     service.disableOwnedAutofillServicesLocked(Binder.getCallingUid());
    650                 }
    651             }
    652         }
    653 
    654         @Override
    655         public boolean isServiceSupported(int userId) {
    656             synchronized (mLock) {
    657                 return !mDisabledUsers.get(userId);
    658             }
    659         }
    660 
    661         @Override
    662         public boolean isServiceEnabled(int userId, String packageName) {
    663             synchronized (mLock) {
    664                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
    665                 if (service == null) return false;
    666                 return Objects.equals(packageName, service.getServicePackageName());
    667             }
    668         }
    669 
    670         @Override
    671         public void onPendingSaveUi(int operation, IBinder token) {
    672             Preconditions.checkNotNull(token, "token");
    673             Preconditions.checkArgument(operation == AutofillManager.PENDING_UI_OPERATION_CANCEL
    674                     || operation == AutofillManager.PENDING_UI_OPERATION_RESTORE,
    675                     "invalid operation: %d", operation);
    676             synchronized (mLock) {
    677                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(
    678                         UserHandle.getCallingUserId());
    679                 if (service != null) {
    680                     service.onPendingSaveUi(operation, token);
    681                 }
    682             }
    683         }
    684 
    685         @Override
    686         public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
    687             if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
    688 
    689             boolean showHistory = true;
    690             boolean uiOnly = false;
    691             if (args != null) {
    692                 for (String arg : args) {
    693                     switch(arg) {
    694                         case "--no-history":
    695                             showHistory = false;
    696                             break;
    697                         case "--ui-only":
    698                             uiOnly = true;
    699                             break;
    700                         case "--help":
    701                             pw.println("Usage: dumpsys autofill [--ui-only|--no-history]");
    702                             return;
    703                         default:
    704                             Slog.w(TAG, "Ignoring invalid dump arg: " + arg);
    705                     }
    706                 }
    707             }
    708 
    709             if (uiOnly) {
    710                 mUi.dump(pw);
    711                 return;
    712             }
    713 
    714             boolean oldDebug = sDebug;
    715             try {
    716                 synchronized (mLock) {
    717                     oldDebug = sDebug;
    718                     setDebugLocked(true);
    719                     pw.print("Debug mode: "); pw.println(oldDebug);
    720                     pw.print("Verbose mode: "); pw.println(sVerbose);
    721                     pw.print("Disabled users: "); pw.println(mDisabledUsers);
    722                     pw.print("Max partitions per session: "); pw.println(sPartitionMaxCount);
    723                     final int size = mServicesCache.size();
    724                     pw.print("Cached services: ");
    725                     if (size == 0) {
    726                         pw.println("none");
    727                     } else {
    728                         pw.println(size);
    729                         for (int i = 0; i < size; i++) {
    730                             pw.print("\nService at index "); pw.println(i);
    731                             final AutofillManagerServiceImpl impl = mServicesCache.valueAt(i);
    732                             impl.dumpLocked("  ", pw);
    733                         }
    734                     }
    735                     mUi.dump(pw);
    736                 }
    737                 if (showHistory) {
    738                     pw.println("Requests history:");
    739                     mRequestsHistory.reverseDump(fd, pw, args);
    740                     pw.println("UI latency history:");
    741                     mUiLatencyHistory.reverseDump(fd, pw, args);
    742                 }
    743             } finally {
    744                 setDebugLocked(oldDebug);
    745             }
    746         }
    747 
    748         @Override
    749         public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
    750                 String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
    751             (new AutofillManagerServiceShellCommand(AutofillManagerService.this)).exec(
    752                     this, in, out, err, args, callback, resultReceiver);
    753         }
    754     }
    755 
    756     private final class SettingsObserver extends ContentObserver {
    757         SettingsObserver(Handler handler) {
    758             super(handler);
    759             ContentResolver resolver = mContext.getContentResolver();
    760             resolver.registerContentObserver(Settings.Secure.getUriFor(
    761                     Settings.Secure.AUTOFILL_SERVICE), false, this, UserHandle.USER_ALL);
    762             resolver.registerContentObserver(Settings.Secure.getUriFor(
    763                     Settings.Secure.USER_SETUP_COMPLETE), false, this, UserHandle.USER_ALL);
    764         }
    765 
    766         @Override
    767         public void onChange(boolean selfChange, Uri uri, int userId) {
    768             if (sVerbose) Slog.v(TAG, "onChange(): uri=" + uri + ", userId=" + userId);
    769             synchronized (mLock) {
    770                 updateCachedServiceLocked(userId);
    771             }
    772         }
    773     }
    774 }
    775