• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.autofill;
18 
19 import static android.Manifest.permission.MANAGE_AUTO_FILL;
20 import static android.content.Context.AUTOFILL_MANAGER_SERVICE;
21 
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 
AutofillManagerService(Context context)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 
startTrackingPackageChanges()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
onStart()266     public void onStart() {
267         publishBinderService(AUTOFILL_MANAGER_SERVICE, new AutoFillManagerServiceStub());
268         publishLocalService(AutofillManagerInternal.class, new LocalService());
269     }
270 
271     @Override
onBootPhase(int phase)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
onUnlockUser(int userId)279     public void onUnlockUser(int userId) {
280         synchronized (mLock) {
281             updateCachedServiceLocked(userId);
282         }
283     }
284 
285     @Override
onSwitchUser(int userHandle)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
onCleanupUser(int userId)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
getServiceForUserLocked(int userId)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
peekServiceForUserLocked(int userId)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.
destroySessions(int userId, IResultReceiver receiver)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.
listSessions(int userId, IResultReceiver receiver)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.
reset()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.
setLogLevel(int level)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.
getLogLevel()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.
getMaxPartitions()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.
setMaxPartitions(int max)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 
setDebugLocked(boolean debug)445     private void setDebugLocked(boolean debug) {
446         com.android.server.autofill.Helper.sDebug = debug;
447         android.view.autofill.Helper.sDebug = debug;
448     }
449 
450 
setVerboseLocked(boolean verbose)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      */
removeCachedServiceLocked(int userId)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      */
updateCachedServiceLocked(int userId)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      */
updateCachedServiceLocked(int userId, boolean disabled)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
onBackKeyPressed()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
addClient(IAutoFillManagerClient client, int userId)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
setAuthenticationResult(Bundle data, int sessionId, int authenticationId, int userId)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
setHasCallback(int sessionId, int userId, boolean hasIt)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
startSession(IBinder activityToken, IBinder appCallback, AutofillId autofillId, Rect bounds, AutofillValue value, int userId, boolean hasCallback, int flags, ComponentName componentName)534         public int startSession(IBinder activityToken, IBinder appCallback, AutofillId autofillId,
535                 Rect bounds, AutofillValue value, int userId, boolean hasCallback, int flags,
536                 ComponentName componentName) {
537 
538             activityToken = Preconditions.checkNotNull(activityToken, "activityToken");
539             appCallback = Preconditions.checkNotNull(appCallback, "appCallback");
540             autofillId = Preconditions.checkNotNull(autofillId, "autoFillId");
541             componentName = Preconditions.checkNotNull(componentName, "componentName");
542             final String packageName = Preconditions.checkNotNull(componentName.getPackageName());
543 
544             Preconditions.checkArgument(userId == UserHandle.getUserId(getCallingUid()), "userId");
545 
546             try {
547                 mContext.getPackageManager().getPackageInfoAsUser(packageName, 0, userId);
548             } catch (PackageManager.NameNotFoundException e) {
549                 throw new IllegalArgumentException(componentName + " is not a valid package", e);
550             }
551 
552             synchronized (mLock) {
553                 final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
554                 return service.startSessionLocked(activityToken, getCallingUid(), appCallback,
555                         autofillId, bounds, value, hasCallback, flags, componentName);
556             }
557         }
558 
559         @Override
getFillEventHistory()560         public FillEventHistory getFillEventHistory() throws RemoteException {
561             UserHandle user = getCallingUserHandle();
562             int uid = getCallingUid();
563 
564             synchronized (mLock) {
565                 AutofillManagerServiceImpl service = peekServiceForUserLocked(user.getIdentifier());
566                 if (service != null) {
567                     return service.getFillEventHistory(uid);
568                 }
569             }
570 
571             return null;
572         }
573 
574         @Override
restoreSession(int sessionId, IBinder activityToken, IBinder appCallback)575         public boolean restoreSession(int sessionId, IBinder activityToken, IBinder appCallback)
576                 throws RemoteException {
577             activityToken = Preconditions.checkNotNull(activityToken, "activityToken");
578             appCallback = Preconditions.checkNotNull(appCallback, "appCallback");
579 
580             synchronized (mLock) {
581                 final AutofillManagerServiceImpl service = mServicesCache.get(
582                         UserHandle.getCallingUserId());
583                 if (service != null) {
584                     return service.restoreSession(sessionId, getCallingUid(), activityToken,
585                             appCallback);
586                 }
587             }
588 
589             return false;
590         }
591 
592         @Override
updateSession(int sessionId, AutofillId autoFillId, Rect bounds, AutofillValue value, int action, int flags, int userId)593         public void updateSession(int sessionId, AutofillId autoFillId, Rect bounds,
594                 AutofillValue value, int action, int flags, int userId) {
595             synchronized (mLock) {
596                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
597                 if (service != null) {
598                     service.updateSessionLocked(sessionId, getCallingUid(), autoFillId, bounds,
599                             value, action, flags);
600                 }
601             }
602         }
603 
604         @Override
updateOrRestartSession(IBinder activityToken, IBinder appCallback, AutofillId autoFillId, Rect bounds, AutofillValue value, int userId, boolean hasCallback, int flags, ComponentName componentName, int sessionId, int action)605         public int updateOrRestartSession(IBinder activityToken, IBinder appCallback,
606                 AutofillId autoFillId, Rect bounds, AutofillValue value, int userId,
607                 boolean hasCallback, int flags, ComponentName componentName, int sessionId,
608                 int action) {
609             boolean restart = false;
610             synchronized (mLock) {
611                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
612                 if (service != null) {
613                     restart = service.updateSessionLocked(sessionId, getCallingUid(), autoFillId,
614                             bounds, value, action, flags);
615                 }
616             }
617             if (restart) {
618                 return startSession(activityToken, appCallback, autoFillId, bounds, value, userId,
619                         hasCallback, flags, componentName);
620             }
621 
622             // Nothing changed...
623             return sessionId;
624         }
625 
626         @Override
finishSession(int sessionId, int userId)627         public void finishSession(int sessionId, int userId) {
628             synchronized (mLock) {
629                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
630                 if (service != null) {
631                     service.finishSessionLocked(sessionId, getCallingUid());
632                 }
633             }
634         }
635 
636         @Override
cancelSession(int sessionId, int userId)637         public void cancelSession(int sessionId, int userId) {
638             synchronized (mLock) {
639                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
640                 if (service != null) {
641                     service.cancelSessionLocked(sessionId, getCallingUid());
642                 }
643             }
644         }
645 
646         @Override
disableOwnedAutofillServices(int userId)647         public void disableOwnedAutofillServices(int userId) {
648             synchronized (mLock) {
649                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
650                 if (service != null) {
651                     service.disableOwnedAutofillServicesLocked(Binder.getCallingUid());
652                 }
653             }
654         }
655 
656         @Override
isServiceSupported(int userId)657         public boolean isServiceSupported(int userId) {
658             synchronized (mLock) {
659                 return !mDisabledUsers.get(userId);
660             }
661         }
662 
663         @Override
isServiceEnabled(int userId, String packageName)664         public boolean isServiceEnabled(int userId, String packageName) {
665             synchronized (mLock) {
666                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
667                 if (service == null) return false;
668                 return Objects.equals(packageName, service.getServicePackageName());
669             }
670         }
671 
672         @Override
onPendingSaveUi(int operation, IBinder token)673         public void onPendingSaveUi(int operation, IBinder token) {
674             Preconditions.checkNotNull(token, "token");
675             Preconditions.checkArgument(operation == AutofillManager.PENDING_UI_OPERATION_CANCEL
676                     || operation == AutofillManager.PENDING_UI_OPERATION_RESTORE,
677                     "invalid operation: %d", operation);
678             synchronized (mLock) {
679                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(
680                         UserHandle.getCallingUserId());
681                 if (service != null) {
682                     service.onPendingSaveUi(operation, token);
683                 }
684             }
685         }
686 
687         @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)688         public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
689             if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
690 
691             boolean showHistory = true;
692             boolean uiOnly = false;
693             if (args != null) {
694                 for (String arg : args) {
695                     switch(arg) {
696                         case "--no-history":
697                             showHistory = false;
698                             break;
699                         case "--ui-only":
700                             uiOnly = true;
701                             break;
702                         case "--help":
703                             pw.println("Usage: dumpsys autofill [--ui-only|--no-history]");
704                             return;
705                         default:
706                             Slog.w(TAG, "Ignoring invalid dump arg: " + arg);
707                     }
708                 }
709             }
710 
711             if (uiOnly) {
712                 mUi.dump(pw);
713                 return;
714             }
715 
716             boolean oldDebug = sDebug;
717             try {
718                 synchronized (mLock) {
719                     oldDebug = sDebug;
720                     setDebugLocked(true);
721                     pw.print("Debug mode: "); pw.println(oldDebug);
722                     pw.print("Verbose mode: "); pw.println(sVerbose);
723                     pw.print("Disabled users: "); pw.println(mDisabledUsers);
724                     pw.print("Max partitions per session: "); pw.println(sPartitionMaxCount);
725                     final int size = mServicesCache.size();
726                     pw.print("Cached services: ");
727                     if (size == 0) {
728                         pw.println("none");
729                     } else {
730                         pw.println(size);
731                         for (int i = 0; i < size; i++) {
732                             pw.print("\nService at index "); pw.println(i);
733                             final AutofillManagerServiceImpl impl = mServicesCache.valueAt(i);
734                             impl.dumpLocked("  ", pw);
735                         }
736                     }
737                     mUi.dump(pw);
738                 }
739                 if (showHistory) {
740                     pw.println("Requests history:");
741                     mRequestsHistory.reverseDump(fd, pw, args);
742                     pw.println("UI latency history:");
743                     mUiLatencyHistory.reverseDump(fd, pw, args);
744                 }
745             } finally {
746                 setDebugLocked(oldDebug);
747             }
748         }
749 
750         @Override
onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver)751         public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
752                 String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
753             (new AutofillManagerServiceShellCommand(AutofillManagerService.this)).exec(
754                     this, in, out, err, args, callback, resultReceiver);
755         }
756     }
757 
758     private final class SettingsObserver extends ContentObserver {
SettingsObserver(Handler handler)759         SettingsObserver(Handler handler) {
760             super(handler);
761             ContentResolver resolver = mContext.getContentResolver();
762             resolver.registerContentObserver(Settings.Secure.getUriFor(
763                     Settings.Secure.AUTOFILL_SERVICE), false, this, UserHandle.USER_ALL);
764             resolver.registerContentObserver(Settings.Secure.getUriFor(
765                     Settings.Secure.USER_SETUP_COMPLETE), false, this, UserHandle.USER_ALL);
766         }
767 
768         @Override
onChange(boolean selfChange, Uri uri, int userId)769         public void onChange(boolean selfChange, Uri uri, int userId) {
770             if (sVerbose) Slog.v(TAG, "onChange(): uri=" + uri + ", userId=" + userId);
771             synchronized (mLock) {
772                 updateCachedServiceLocked(userId);
773             }
774         }
775     }
776 }
777