• 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.service.autofill.FillEventHistory.Event.NO_SAVE_UI_REASON_NONE;
20 import static android.service.autofill.FillEventHistory.Event.UI_TYPE_INLINE;
21 import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST;
22 import static android.view.autofill.AutofillManager.ACTION_START_SESSION;
23 import static android.view.autofill.AutofillManager.FLAG_ADD_CLIENT_ENABLED;
24 import static android.view.autofill.AutofillManager.FLAG_ADD_CLIENT_ENABLED_FOR_AUGMENTED_AUTOFILL_ONLY;
25 import static android.view.autofill.AutofillManager.NO_SESSION;
26 import static android.view.autofill.AutofillManager.RECEIVER_FLAG_SESSION_FOR_AUGMENTED_AUTOFILL_ONLY;
27 
28 import static com.android.server.autofill.Helper.sDebug;
29 import static com.android.server.autofill.Helper.sVerbose;
30 
31 import android.annotation.NonNull;
32 import android.annotation.Nullable;
33 import android.app.ActivityManagerInternal;
34 import android.content.ComponentName;
35 import android.content.pm.PackageManager;
36 import android.content.pm.PackageManager.NameNotFoundException;
37 import android.content.pm.ServiceInfo;
38 import android.graphics.Rect;
39 import android.metrics.LogMaker;
40 import android.os.AsyncTask;
41 import android.os.Binder;
42 import android.os.Bundle;
43 import android.os.Handler;
44 import android.os.IBinder;
45 import android.os.Looper;
46 import android.os.Process;
47 import android.os.RemoteCallbackList;
48 import android.os.RemoteException;
49 import android.os.SystemClock;
50 import android.os.UserHandle;
51 import android.provider.Settings;
52 import android.service.autofill.AutofillService;
53 import android.service.autofill.AutofillServiceInfo;
54 import android.service.autofill.FieldClassification;
55 import android.service.autofill.FieldClassification.Match;
56 import android.service.autofill.FillEventHistory;
57 import android.service.autofill.FillEventHistory.Event;
58 import android.service.autofill.FillEventHistory.Event.NoSaveReason;
59 import android.service.autofill.FillResponse;
60 import android.service.autofill.IAutoFillService;
61 import android.service.autofill.InlineSuggestionRenderService;
62 import android.service.autofill.SaveInfo;
63 import android.service.autofill.UserData;
64 import android.util.ArrayMap;
65 import android.util.ArraySet;
66 import android.util.DebugUtils;
67 import android.util.LocalLog;
68 import android.util.Pair;
69 import android.util.Slog;
70 import android.util.SparseArray;
71 import android.view.autofill.AutofillId;
72 import android.view.autofill.AutofillManager;
73 import android.view.autofill.AutofillManager.AutofillCommitReason;
74 import android.view.autofill.AutofillManager.SmartSuggestionMode;
75 import android.view.autofill.AutofillValue;
76 import android.view.autofill.IAutoFillManagerClient;
77 
78 import com.android.internal.R;
79 import com.android.internal.annotations.GuardedBy;
80 import com.android.internal.logging.MetricsLogger;
81 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
82 import com.android.internal.os.IResultReceiver;
83 import com.android.server.LocalServices;
84 import com.android.server.autofill.AutofillManagerService.AutofillCompatState;
85 import com.android.server.autofill.AutofillManagerService.DisabledInfoCache;
86 import com.android.server.autofill.RemoteAugmentedAutofillService.RemoteAugmentedAutofillServiceCallbacks;
87 import com.android.server.autofill.ui.AutoFillUI;
88 import com.android.server.contentcapture.ContentCaptureManagerInternal;
89 import com.android.server.infra.AbstractPerUserSystemService;
90 import com.android.server.inputmethod.InputMethodManagerInternal;
91 import com.android.server.wm.ActivityTaskManagerInternal;
92 
93 import java.io.PrintWriter;
94 import java.util.ArrayList;
95 import java.util.List;
96 import java.util.Random;
97 /**
98  * Bridge between the {@code system_server}'s {@link AutofillManagerService} and the
99  * app's {@link IAutoFillService} implementation.
100  *
101  */
102 final class AutofillManagerServiceImpl
103         extends AbstractPerUserSystemService<AutofillManagerServiceImpl, AutofillManagerService> {
104 
105     private static final String TAG = "AutofillManagerServiceImpl";
106     private static final int MAX_SESSION_ID_CREATE_TRIES = 2048;
107 
108     /** Minimum interval to prune abandoned sessions */
109     private static final int MAX_ABANDONED_SESSION_MILLIS = 30_000;
110 
111     private final AutoFillUI mUi;
112     private final MetricsLogger mMetricsLogger = new MetricsLogger();
113 
114     @GuardedBy("mLock")
115     private RemoteCallbackList<IAutoFillManagerClient> mClients;
116 
117     @GuardedBy("mLock")
118     private AutofillServiceInfo mInfo;
119 
120     private static final Random sRandom = new Random();
121 
122     private final LocalLog mUiLatencyHistory;
123     private final LocalLog mWtfHistory;
124     private final FieldClassificationStrategy mFieldClassificationStrategy;
125 
126     @GuardedBy("mLock")
127     @Nullable
128     private RemoteInlineSuggestionRenderService mRemoteInlineSuggestionRenderService;
129 
130     /**
131      * Data used for field classification.
132      */
133     @GuardedBy("mLock")
134     private UserData mUserData;
135 
136     private final Handler mHandler = new Handler(Looper.getMainLooper(), null, true);
137 
138     /**
139      * Cache of pending {@link Session}s, keyed by sessionId.
140      *
141      * <p>They're kept until the {@link AutofillService} finished handling a request, an error
142      * occurs, or the session is abandoned.
143      */
144     @GuardedBy("mLock")
145     private final SparseArray<Session> mSessions = new SparseArray<>();
146 
147     /** The last selection */
148     @GuardedBy("mLock")
149     private FillEventHistory mEventHistory;
150 
151     /**
152      * The last inline augmented autofill selection. Note that we don't log the selection from the
153      * dropdown UI since the service owns the UI in that case.
154      */
155     @GuardedBy("mLock")
156     private FillEventHistory mAugmentedAutofillEventHistory;
157 
158     /** Shared instance, doesn't need to be logged */
159     private final AutofillCompatState mAutofillCompatState;
160 
161     /** When was {@link PruneTask} last executed? */
162     private long mLastPrune = 0;
163 
164     /**
165      * Reference to the {@link RemoteAugmentedAutofillService}, is set on demand.
166      */
167     @GuardedBy("mLock")
168     @Nullable
169     private RemoteAugmentedAutofillService mRemoteAugmentedAutofillService;
170 
171     @GuardedBy("mLock")
172     @Nullable
173     private ServiceInfo mRemoteAugmentedAutofillServiceInfo;
174 
175     private final InputMethodManagerInternal mInputMethodManagerInternal;
176 
177     private final ContentCaptureManagerInternal mContentCaptureManagerInternal;
178 
179     private final DisabledInfoCache mDisabledInfoCache;
180 
AutofillManagerServiceImpl(AutofillManagerService master, Object lock, LocalLog uiLatencyHistory, LocalLog wtfHistory, int userId, AutoFillUI ui, AutofillCompatState autofillCompatState, boolean disabled, DisabledInfoCache disableCache)181     AutofillManagerServiceImpl(AutofillManagerService master, Object lock,
182             LocalLog uiLatencyHistory, LocalLog wtfHistory, int userId, AutoFillUI ui,
183             AutofillCompatState autofillCompatState,
184             boolean disabled, DisabledInfoCache disableCache) {
185         super(master, lock, userId);
186 
187         mUiLatencyHistory = uiLatencyHistory;
188         mWtfHistory = wtfHistory;
189         mUi = ui;
190         mFieldClassificationStrategy = new FieldClassificationStrategy(getContext(), userId);
191         mAutofillCompatState = autofillCompatState;
192         mInputMethodManagerInternal = LocalServices.getService(InputMethodManagerInternal.class);
193         mContentCaptureManagerInternal = LocalServices.getService(
194                 ContentCaptureManagerInternal.class);
195         mDisabledInfoCache = disableCache;
196         updateLocked(disabled);
197     }
198 
sendActivityAssistDataToContentCapture(@onNull IBinder activityToken, @NonNull Bundle data)199     boolean sendActivityAssistDataToContentCapture(@NonNull IBinder activityToken,
200             @NonNull Bundle data) {
201         if (mContentCaptureManagerInternal != null) {
202             mContentCaptureManagerInternal.sendActivityAssistData(getUserId(), activityToken, data);
203             return true;
204         }
205 
206         return false;
207     }
208 
209     @GuardedBy("mLock")
onBackKeyPressed()210     void onBackKeyPressed() {
211         final RemoteAugmentedAutofillService remoteService =
212                 getRemoteAugmentedAutofillServiceLocked();
213         if (remoteService != null) {
214             remoteService.onDestroyAutofillWindowsRequest();
215         }
216     }
217 
218     @GuardedBy("mLock")
219     @Override // from PerUserSystemService
updateLocked(boolean disabled)220     protected boolean updateLocked(boolean disabled) {
221         forceRemoveAllSessionsLocked();
222         final boolean enabledChanged = super.updateLocked(disabled);
223         if (enabledChanged) {
224             if (!isEnabledLocked()) {
225                 final int sessionCount = mSessions.size();
226                 for (int i = sessionCount - 1; i >= 0; i--) {
227                     final Session session = mSessions.valueAt(i);
228                     session.removeFromServiceLocked();
229                 }
230             }
231             sendStateToClients(/* resetClient= */ false);
232         }
233         updateRemoteAugmentedAutofillService();
234         updateRemoteInlineSuggestionRenderServiceLocked();
235 
236         return enabledChanged;
237     }
238 
239     @Override // from PerUserSystemService
newServiceInfoLocked(@onNull ComponentName serviceComponent)240     protected ServiceInfo newServiceInfoLocked(@NonNull ComponentName serviceComponent)
241             throws NameNotFoundException {
242         mInfo = new AutofillServiceInfo(getContext(), serviceComponent, mUserId);
243         return mInfo.getServiceInfo();
244     }
245 
246     @Nullable
getUrlBarResourceIdsForCompatMode(@onNull String packageName)247     String[] getUrlBarResourceIdsForCompatMode(@NonNull String packageName) {
248         return mAutofillCompatState.getUrlBarResourceIds(packageName, mUserId);
249     }
250 
251     /**
252      * Adds the client and return the proper flags
253      *
254      * @return {@code 0} if disabled, {@code FLAG_ADD_CLIENT_ENABLED} if enabled (it might be
255      * OR'ed with {@code FLAG_AUGMENTED_AUTOFILL_REQUEST}).
256      */
257     @GuardedBy("mLock")
addClientLocked(IAutoFillManagerClient client, ComponentName componentName)258     int addClientLocked(IAutoFillManagerClient client, ComponentName componentName) {
259         if (mClients == null) {
260             mClients = new RemoteCallbackList<>();
261         }
262         mClients.register(client);
263 
264         if (isEnabledLocked()) return FLAG_ADD_CLIENT_ENABLED;
265 
266         // Check if it's enabled for augmented autofill
267         if (componentName != null && isAugmentedAutofillServiceAvailableLocked()
268                 && isWhitelistedForAugmentedAutofillLocked(componentName)) {
269             return FLAG_ADD_CLIENT_ENABLED_FOR_AUGMENTED_AUTOFILL_ONLY;
270         }
271 
272         // No flags / disabled
273         return 0;
274     }
275 
276     @GuardedBy("mLock")
removeClientLocked(IAutoFillManagerClient client)277     void removeClientLocked(IAutoFillManagerClient client) {
278         if (mClients != null) {
279             mClients.unregister(client);
280         }
281     }
282 
283     @GuardedBy("mLock")
setAuthenticationResultLocked(Bundle data, int sessionId, int authenticationId, int uid)284     void setAuthenticationResultLocked(Bundle data, int sessionId, int authenticationId, int uid) {
285         if (!isEnabledLocked()) {
286             return;
287         }
288         final Session session = mSessions.get(sessionId);
289         if (session != null && uid == session.uid) {
290             synchronized (session.mLock) {
291                 session.setAuthenticationResultLocked(data, authenticationId);
292             }
293         }
294     }
295 
setHasCallback(int sessionId, int uid, boolean hasIt)296     void setHasCallback(int sessionId, int uid, boolean hasIt) {
297         if (!isEnabledLocked()) {
298             return;
299         }
300         final Session session = mSessions.get(sessionId);
301         if (session != null && uid == session.uid) {
302             synchronized (mLock) {
303                 session.setHasCallbackLocked(hasIt);
304             }
305         }
306     }
307 
308     /**
309      * Starts a new session.
310      *
311      * @return {@code long} whose right-most 32 bits represent the session id (which is always
312      * non-negative), and the left-most contains extra flags (currently either {@code 0} or
313      * {@link AutofillManager#RECEIVER_FLAG_SESSION_FOR_AUGMENTED_AUTOFILL_ONLY}).
314      */
315     @GuardedBy("mLock")
startSessionLocked(@onNull IBinder activityToken, int taskId, int clientUid, @NonNull IBinder clientCallback, @NonNull AutofillId autofillId, @NonNull Rect virtualBounds, @Nullable AutofillValue value, boolean hasCallback, @NonNull ComponentName clientActivity, boolean compatMode, boolean bindInstantServiceAllowed, int flags)316     long startSessionLocked(@NonNull IBinder activityToken, int taskId, int clientUid,
317             @NonNull IBinder clientCallback, @NonNull AutofillId autofillId,
318             @NonNull Rect virtualBounds, @Nullable AutofillValue value, boolean hasCallback,
319             @NonNull ComponentName clientActivity, boolean compatMode,
320             boolean bindInstantServiceAllowed, int flags) {
321         // FLAG_AUGMENTED_AUTOFILL_REQUEST is set in the flags when standard autofill is disabled
322         // but the package is allowlisted for augmented autofill
323         boolean forAugmentedAutofillOnly = (flags
324                 & FLAG_ADD_CLIENT_ENABLED_FOR_AUGMENTED_AUTOFILL_ONLY) != 0;
325         if (!isEnabledLocked() && !forAugmentedAutofillOnly) {
326             return 0;
327         }
328 
329         if (!forAugmentedAutofillOnly && isAutofillDisabledLocked(clientActivity)) {
330             // Standard autofill is enabled, but service disabled autofill for this activity; that
331             // means no session, unless the activity is allowlisted for augmented autofill
332             if (isWhitelistedForAugmentedAutofillLocked(clientActivity)) {
333                 if (sDebug) {
334                     Slog.d(TAG, "startSession(" + clientActivity + "): disabled by service but "
335                             + "whitelisted for augmented autofill");
336                 }
337                 forAugmentedAutofillOnly = true;
338 
339             } else {
340                 if (sDebug) {
341                     Slog.d(TAG, "startSession(" + clientActivity + "): ignored because "
342                             + "disabled by service and not whitelisted for augmented autofill");
343                 }
344                 final IAutoFillManagerClient client = IAutoFillManagerClient.Stub
345                         .asInterface(clientCallback);
346                 try {
347                     client.setSessionFinished(AutofillManager.STATE_DISABLED_BY_SERVICE,
348                             /* autofillableIds= */ null);
349                 } catch (RemoteException e) {
350                     Slog.w(TAG,
351                             "Could not notify " + clientActivity + " that it's disabled: " + e);
352                 }
353 
354                 return NO_SESSION;
355             }
356         }
357 
358         if (sVerbose) {
359             Slog.v(TAG, "startSession(): token=" + activityToken + ", flags=" + flags
360                     + ", forAugmentedAutofillOnly=" + forAugmentedAutofillOnly);
361         }
362 
363         // Occasionally clean up abandoned sessions
364         pruneAbandonedSessionsLocked();
365 
366         final Session newSession = createSessionByTokenLocked(activityToken, taskId, clientUid,
367                 clientCallback, hasCallback, clientActivity, compatMode,
368                 bindInstantServiceAllowed, forAugmentedAutofillOnly, flags);
369         if (newSession == null) {
370             return NO_SESSION;
371         }
372 
373         // Service can be null when it's only for augmented autofill
374         String servicePackageName = mInfo == null ? null : mInfo.getServiceInfo().packageName;
375         final String historyItem =
376                 "id=" + newSession.id + " uid=" + clientUid + " a=" + clientActivity.toShortString()
377                 + " s=" + servicePackageName
378                 + " u=" + mUserId + " i=" + autofillId + " b=" + virtualBounds
379                 + " hc=" + hasCallback + " f=" + flags + " aa=" + forAugmentedAutofillOnly;
380         mMaster.logRequestLocked(historyItem);
381 
382         synchronized (newSession.mLock) {
383             newSession.updateLocked(autofillId, virtualBounds, value, ACTION_START_SESSION, flags);
384         }
385 
386         if (forAugmentedAutofillOnly) {
387             // Must embed the flag in the response, at the high-end side of the long.
388             // (session is always positive, so we don't have to worry about the signal bit)
389             final long extraFlags =
390                     ((long) RECEIVER_FLAG_SESSION_FOR_AUGMENTED_AUTOFILL_ONLY) << 32;
391             final long result = extraFlags | newSession.id;
392             return result;
393         } else {
394             return newSession.id;
395         }
396     }
397 
398     /**
399      * Remove abandoned sessions if needed.
400      */
401     @GuardedBy("mLock")
pruneAbandonedSessionsLocked()402     private void pruneAbandonedSessionsLocked() {
403         long now = System.currentTimeMillis();
404         if (mLastPrune < now - MAX_ABANDONED_SESSION_MILLIS) {
405             mLastPrune = now;
406 
407             if (mSessions.size() > 0) {
408                 (new PruneTask()).execute();
409             }
410         }
411     }
412 
413     @GuardedBy("mLock")
setAutofillFailureLocked(int sessionId, int uid, @NonNull List<AutofillId> ids)414     void setAutofillFailureLocked(int sessionId, int uid, @NonNull List<AutofillId> ids) {
415         if (!isEnabledLocked()) {
416             return;
417         }
418         final Session session = mSessions.get(sessionId);
419         if (session == null || uid != session.uid) {
420             Slog.v(TAG, "setAutofillFailure(): no session for " + sessionId + "(" + uid + ")");
421             return;
422         }
423         session.setAutofillFailureLocked(ids);
424     }
425 
426     @GuardedBy("mLock")
finishSessionLocked(int sessionId, int uid, @AutofillCommitReason int commitReason)427     void finishSessionLocked(int sessionId, int uid, @AutofillCommitReason int commitReason) {
428         if (!isEnabledLocked()) {
429             return;
430         }
431 
432         final Session session = mSessions.get(sessionId);
433         if (session == null || uid != session.uid) {
434             if (sVerbose) {
435                 Slog.v(TAG, "finishSessionLocked(): no session for " + sessionId + "(" + uid + ")");
436             }
437             return;
438         }
439 
440         final Session.SaveResult saveResult = session.showSaveLocked();
441 
442         session.logContextCommitted(saveResult.getNoSaveUiReason(), commitReason);
443 
444         if (saveResult.isLogSaveShown()) {
445             session.logSaveUiShown();
446         }
447 
448         final boolean finished = saveResult.isRemoveSession();
449         if (sVerbose) Slog.v(TAG, "finishSessionLocked(): session finished on save? " + finished);
450 
451         if (finished) {
452             session.removeFromServiceLocked();
453         }
454     }
455 
456     @GuardedBy("mLock")
cancelSessionLocked(int sessionId, int uid)457     void cancelSessionLocked(int sessionId, int uid) {
458         if (!isEnabledLocked()) {
459             return;
460         }
461 
462         final Session session = mSessions.get(sessionId);
463         if (session == null || uid != session.uid) {
464             Slog.w(TAG, "cancelSessionLocked(): no session for " + sessionId + "(" + uid + ")");
465             return;
466         }
467         session.removeFromServiceLocked();
468     }
469 
470     @GuardedBy("mLock")
disableOwnedAutofillServicesLocked(int uid)471     void disableOwnedAutofillServicesLocked(int uid) {
472         Slog.i(TAG, "disableOwnedServices(" + uid + "): " + mInfo);
473         if (mInfo == null) return;
474 
475         final ServiceInfo serviceInfo = mInfo.getServiceInfo();
476         if (serviceInfo.applicationInfo.uid != uid) {
477             Slog.w(TAG, "disableOwnedServices(): ignored when called by UID " + uid
478                     + " instead of " + serviceInfo.applicationInfo.uid
479                     + " for service " + mInfo);
480             return;
481         }
482 
483 
484         final long identity = Binder.clearCallingIdentity();
485         try {
486             final String autoFillService = getComponentNameLocked();
487             final ComponentName componentName = serviceInfo.getComponentName();
488             if (componentName.equals(ComponentName.unflattenFromString(autoFillService))) {
489                 mMetricsLogger.action(MetricsEvent.AUTOFILL_SERVICE_DISABLED_SELF,
490                         componentName.getPackageName());
491                 Settings.Secure.putStringForUser(getContext().getContentResolver(),
492                         Settings.Secure.AUTOFILL_SERVICE, null, mUserId);
493                 forceRemoveAllSessionsLocked();
494             } else {
495                 Slog.w(TAG, "disableOwnedServices(): ignored because current service ("
496                         + serviceInfo + ") does not match Settings (" + autoFillService + ")");
497             }
498         } finally {
499             Binder.restoreCallingIdentity(identity);
500         }
501     }
502 
503     @GuardedBy("mLock")
createSessionByTokenLocked(@onNull IBinder clientActivityToken, int taskId, int clientUid, @NonNull IBinder clientCallback, boolean hasCallback, @NonNull ComponentName clientActivity, boolean compatMode, boolean bindInstantServiceAllowed, boolean forAugmentedAutofillOnly, int flags)504     private Session createSessionByTokenLocked(@NonNull IBinder clientActivityToken, int taskId,
505             int clientUid, @NonNull IBinder clientCallback, boolean hasCallback,
506             @NonNull ComponentName clientActivity, boolean compatMode,
507             boolean bindInstantServiceAllowed, boolean forAugmentedAutofillOnly, int flags) {
508         // use random ids so that one app cannot know that another app creates sessions
509         int sessionId;
510         int tries = 0;
511         do {
512             tries++;
513             if (tries > MAX_SESSION_ID_CREATE_TRIES) {
514                 Slog.w(TAG, "Cannot create session in " + MAX_SESSION_ID_CREATE_TRIES + " tries");
515                 return null;
516             }
517 
518             sessionId = Math.abs(sRandom.nextInt());
519         } while (sessionId == 0 || sessionId == NO_SESSION
520                 || mSessions.indexOfKey(sessionId) >= 0);
521 
522         assertCallerLocked(clientActivity, compatMode);
523 
524         // It's null when the session is just for augmented autofill
525         final ComponentName serviceComponentName = mInfo == null ? null
526                 : mInfo.getServiceInfo().getComponentName();
527         final Session newSession = new Session(this, mUi, getContext(), mHandler, mUserId, mLock,
528                 sessionId, taskId, clientUid, clientActivityToken, clientCallback, hasCallback,
529                 mUiLatencyHistory, mWtfHistory, serviceComponentName,
530                 clientActivity, compatMode, bindInstantServiceAllowed, forAugmentedAutofillOnly,
531                 flags, mInputMethodManagerInternal);
532         mSessions.put(newSession.id, newSession);
533 
534         return newSession;
535     }
536 
537     /**
538      * Asserts the component is owned by the caller.
539      */
assertCallerLocked(@onNull ComponentName componentName, boolean compatMode)540     private void assertCallerLocked(@NonNull ComponentName componentName, boolean compatMode) {
541         final String packageName = componentName.getPackageName();
542         final PackageManager pm = getContext().getPackageManager();
543         final int callingUid = Binder.getCallingUid();
544         final int packageUid;
545         try {
546             packageUid = pm.getPackageUidAsUser(packageName, UserHandle.getCallingUserId());
547         } catch (NameNotFoundException e) {
548             throw new SecurityException("Could not verify UID for " + componentName);
549         }
550         if (callingUid != packageUid && !LocalServices.getService(ActivityManagerInternal.class)
551                 .hasRunningActivity(callingUid, packageName)) {
552             final String[] packages = pm.getPackagesForUid(callingUid);
553             final String callingPackage = packages != null ? packages[0] : "uid-" + callingUid;
554             Slog.w(TAG, "App (package=" + callingPackage + ", UID=" + callingUid
555                     + ") passed component (" + componentName + ") owned by UID " + packageUid);
556 
557             // NOTE: not using Helper.newLogMaker() because we don't have the session id
558             final LogMaker log = new LogMaker(MetricsEvent.AUTOFILL_FORGED_COMPONENT_ATTEMPT)
559                     .setPackageName(callingPackage)
560                     .addTaggedData(MetricsEvent.FIELD_AUTOFILL_SERVICE, getServicePackageName())
561                     .addTaggedData(MetricsEvent.FIELD_AUTOFILL_FORGED_COMPONENT_NAME,
562                             componentName == null ? "null" : componentName.flattenToShortString());
563             if (compatMode) {
564                 log.addTaggedData(MetricsEvent.FIELD_AUTOFILL_COMPAT_MODE, 1);
565             }
566             mMetricsLogger.write(log);
567 
568             throw new SecurityException("Invalid component: " + componentName);
569         }
570     }
571 
572     /**
573      * Restores a session after an activity was temporarily destroyed.
574      *
575      * @param sessionId The id of the session to restore
576      * @param uid UID of the process that tries to restore the session
577      * @param activityToken The new instance of the activity
578      * @param appCallback The callbacks to the activity
579      */
restoreSession(int sessionId, int uid, @NonNull IBinder activityToken, @NonNull IBinder appCallback)580     boolean restoreSession(int sessionId, int uid, @NonNull IBinder activityToken,
581             @NonNull IBinder appCallback) {
582         final Session session = mSessions.get(sessionId);
583 
584         if (session == null || uid != session.uid) {
585             return false;
586         } else {
587             session.switchActivity(activityToken, appCallback);
588             return true;
589         }
590     }
591 
592     /**
593      * Updates a session and returns whether it should be restarted.
594      */
595     @GuardedBy("mLock")
updateSessionLocked(int sessionId, int uid, AutofillId autofillId, Rect virtualBounds, AutofillValue value, int action, int flags)596     boolean updateSessionLocked(int sessionId, int uid, AutofillId autofillId, Rect virtualBounds,
597             AutofillValue value, int action, int flags) {
598         final Session session = mSessions.get(sessionId);
599         if (session == null || session.uid != uid) {
600             if ((flags & FLAG_MANUAL_REQUEST) != 0) {
601                 if (sDebug) {
602                     Slog.d(TAG, "restarting session " + sessionId + " due to manual request on "
603                             + autofillId);
604                 }
605                 return true;
606             }
607             if (sVerbose) {
608                 Slog.v(TAG, "updateSessionLocked(): session gone for " + sessionId
609                         + "(" + uid + ")");
610             }
611             return false;
612         }
613 
614         session.updateLocked(autofillId, virtualBounds, value, action, flags);
615         return false;
616     }
617 
618     @GuardedBy("mLock")
removeSessionLocked(int sessionId)619     void removeSessionLocked(int sessionId) {
620         mSessions.remove(sessionId);
621     }
622 
623     /**
624      * Ges the previous sessions asked to be kept alive in a given activity task.
625      *
626      * @param session session calling this method (so it's excluded from the result).
627      */
628     @Nullable
629     @GuardedBy("mLock")
getPreviousSessionsLocked(@onNull Session session)630     ArrayList<Session> getPreviousSessionsLocked(@NonNull Session session) {
631         final int size = mSessions.size();
632         ArrayList<Session> previousSessions = null;
633         for (int i = 0; i < size; i++) {
634             final Session previousSession = mSessions.valueAt(i);
635             if (previousSession.taskId == session.taskId && previousSession.id != session.id
636                     && (previousSession.getSaveInfoFlagsLocked() & SaveInfo.FLAG_DELAY_SAVE) != 0) {
637                 if (previousSessions == null) {
638                     previousSessions = new ArrayList<>(size);
639                 }
640                 previousSessions.add(previousSession);
641             }
642         }
643         // TODO(b/113281366): remove returned sessions / add CTS test
644         return previousSessions;
645     }
646 
handleSessionSave(Session session)647     void handleSessionSave(Session session) {
648         synchronized (mLock) {
649             if (mSessions.get(session.id) == null) {
650                 Slog.w(TAG, "handleSessionSave(): already gone: " + session.id);
651 
652                 return;
653             }
654             session.callSaveLocked();
655         }
656     }
657 
onPendingSaveUi(int operation, @NonNull IBinder token)658     void onPendingSaveUi(int operation, @NonNull IBinder token) {
659         if (sVerbose) Slog.v(TAG, "onPendingSaveUi(" + operation + "): " + token);
660         synchronized (mLock) {
661             final int sessionCount = mSessions.size();
662             for (int i = sessionCount - 1; i >= 0; i--) {
663                 final Session session = mSessions.valueAt(i);
664                 if (session.isSaveUiPendingForTokenLocked(token)) {
665                     session.onPendingSaveUi(operation, token);
666                     return;
667                 }
668             }
669         }
670         if (sDebug) {
671             Slog.d(TAG, "No pending Save UI for token " + token + " and operation "
672                     + DebugUtils.flagsToString(AutofillManager.class, "PENDING_UI_OPERATION_",
673                             operation));
674         }
675     }
676 
677     @GuardedBy("mLock")
678     @Override // from PerUserSystemService
handlePackageUpdateLocked(@onNull String packageName)679     protected void handlePackageUpdateLocked(@NonNull String packageName) {
680         final ServiceInfo serviceInfo = mFieldClassificationStrategy.getServiceInfo();
681         if (serviceInfo != null && serviceInfo.packageName.equals(packageName)) {
682             resetExtServiceLocked();
683         }
684     }
685 
686     @GuardedBy("mLock")
resetExtServiceLocked()687     void resetExtServiceLocked() {
688         if (sVerbose) Slog.v(TAG, "reset autofill service.");
689         mFieldClassificationStrategy.reset();
690     }
691 
692     @GuardedBy("mLock")
destroyLocked()693     void destroyLocked() {
694         if (sVerbose) Slog.v(TAG, "destroyLocked()");
695 
696         resetExtServiceLocked();
697 
698         final int numSessions = mSessions.size();
699         final ArraySet<RemoteFillService> remoteFillServices = new ArraySet<>(numSessions);
700         for (int i = 0; i < numSessions; i++) {
701             final RemoteFillService remoteFillService = mSessions.valueAt(i).destroyLocked();
702             if (remoteFillService != null) {
703                 remoteFillServices.add(remoteFillService);
704             }
705         }
706         mSessions.clear();
707         for (int i = 0; i < remoteFillServices.size(); i++) {
708             remoteFillServices.valueAt(i).destroy();
709         }
710 
711         sendStateToClients(/* resetclient=*/ true);
712         if (mClients != null) {
713             mClients.kill();
714             mClients = null;
715         }
716     }
717 
718     /**
719      * Initializes the last fill selection after an autofill service returned a new
720      * {@link FillResponse}.
721      */
setLastResponse(int sessionId, @NonNull FillResponse response)722     void setLastResponse(int sessionId, @NonNull FillResponse response) {
723         synchronized (mLock) {
724             mEventHistory = new FillEventHistory(sessionId, response.getClientState());
725         }
726     }
727 
setLastAugmentedAutofillResponse(int sessionId)728     void setLastAugmentedAutofillResponse(int sessionId) {
729         synchronized (mLock) {
730             mAugmentedAutofillEventHistory = new FillEventHistory(sessionId, /* clientState= */
731                     null);
732         }
733     }
734 
735     /**
736      * Resets the last fill selection.
737      */
resetLastResponse()738     void resetLastResponse() {
739         synchronized (mLock) {
740             mEventHistory = null;
741         }
742     }
743 
resetLastAugmentedAutofillResponse()744     void resetLastAugmentedAutofillResponse() {
745         synchronized (mLock) {
746             mAugmentedAutofillEventHistory = null;
747         }
748     }
749 
750     @GuardedBy("mLock")
isValidEventLocked(String method, int sessionId)751     private boolean isValidEventLocked(String method, int sessionId) {
752         if (mEventHistory == null) {
753             Slog.w(TAG, method + ": not logging event because history is null");
754             return false;
755         }
756         if (sessionId != mEventHistory.getSessionId()) {
757             if (sDebug) {
758                 Slog.d(TAG, method + ": not logging event for session " + sessionId
759                         + " because tracked session is " + mEventHistory.getSessionId());
760             }
761             return false;
762         }
763         return true;
764     }
765 
766     /**
767      * Updates the last fill selection when an authentication was selected.
768      */
setAuthenticationSelected(int sessionId, @Nullable Bundle clientState, int uiType)769     void setAuthenticationSelected(int sessionId, @Nullable Bundle clientState,
770             int uiType) {
771         synchronized (mLock) {
772             if (isValidEventLocked("setAuthenticationSelected()", sessionId)) {
773                 mEventHistory.addEvent(
774                         new Event(Event.TYPE_AUTHENTICATION_SELECTED, null, clientState, null, null,
775                                 null, null, null, null, null, null,
776                                 NO_SAVE_UI_REASON_NONE, uiType));
777             }
778         }
779     }
780 
781     /**
782      * Updates the last fill selection when an dataset authentication was selected.
783      */
logDatasetAuthenticationSelected(@ullable String selectedDataset, int sessionId, @Nullable Bundle clientState, int uiType)784     void logDatasetAuthenticationSelected(@Nullable String selectedDataset, int sessionId,
785             @Nullable Bundle clientState, int uiType) {
786         synchronized (mLock) {
787             if (isValidEventLocked("logDatasetAuthenticationSelected()", sessionId)) {
788                 mEventHistory.addEvent(
789                         new Event(Event.TYPE_DATASET_AUTHENTICATION_SELECTED, selectedDataset,
790                                 clientState, null, null, null, null, null, null, null, null,
791                                 NO_SAVE_UI_REASON_NONE, uiType));
792             }
793         }
794     }
795 
796     /**
797      * Updates the last fill selection when an save Ui is shown.
798      */
logSaveShown(int sessionId, @Nullable Bundle clientState)799     void logSaveShown(int sessionId, @Nullable Bundle clientState) {
800         synchronized (mLock) {
801             if (isValidEventLocked("logSaveShown()", sessionId)) {
802                 mEventHistory.addEvent(new Event(Event.TYPE_SAVE_SHOWN, null, clientState, null,
803                         null, null, null, null, null, null, null));
804             }
805         }
806     }
807 
808     /**
809      * Updates the last fill response when a dataset was selected.
810      */
logDatasetSelected(@ullable String selectedDataset, int sessionId, @Nullable Bundle clientState, int uiType)811     void logDatasetSelected(@Nullable String selectedDataset, int sessionId,
812             @Nullable Bundle clientState,  int uiType) {
813         synchronized (mLock) {
814             if (isValidEventLocked("logDatasetSelected()", sessionId)) {
815                 mEventHistory.addEvent(
816                         new Event(Event.TYPE_DATASET_SELECTED, selectedDataset, clientState, null,
817                                 null, null, null, null, null, null, null, NO_SAVE_UI_REASON_NONE,
818                                 uiType));
819             }
820         }
821     }
822 
823     /**
824      * Updates the last fill response when a dataset is shown.
825      */
logDatasetShown(int sessionId, @Nullable Bundle clientState, int uiType)826     void logDatasetShown(int sessionId, @Nullable Bundle clientState, int uiType) {
827         synchronized (mLock) {
828             if (isValidEventLocked("logDatasetShown", sessionId)) {
829                 mEventHistory.addEvent(
830                         new Event(Event.TYPE_DATASETS_SHOWN, null, clientState, null, null, null,
831                                 null, null, null, null, null, NO_SAVE_UI_REASON_NONE,
832                                 uiType));
833             }
834         }
835     }
836 
logAugmentedAutofillAuthenticationSelected(int sessionId, @Nullable String selectedDataset, @Nullable Bundle clientState)837     void logAugmentedAutofillAuthenticationSelected(int sessionId, @Nullable String selectedDataset,
838             @Nullable Bundle clientState) {
839         synchronized (mLock) {
840             if (mAugmentedAutofillEventHistory == null
841                     || mAugmentedAutofillEventHistory.getSessionId() != sessionId) {
842                 return;
843             }
844             mAugmentedAutofillEventHistory.addEvent(
845                     new Event(Event.TYPE_DATASET_AUTHENTICATION_SELECTED, selectedDataset,
846                             clientState, null, null, null, null, null, null, null, null));
847         }
848     }
849 
logAugmentedAutofillSelected(int sessionId, @Nullable String suggestionId, @Nullable Bundle clientState)850     void logAugmentedAutofillSelected(int sessionId, @Nullable String suggestionId,
851             @Nullable Bundle clientState) {
852         synchronized (mLock) {
853             if (mAugmentedAutofillEventHistory == null
854                     || mAugmentedAutofillEventHistory.getSessionId() != sessionId) {
855                 return;
856             }
857             mAugmentedAutofillEventHistory.addEvent(
858                     new Event(Event.TYPE_DATASET_SELECTED, suggestionId, clientState, null, null,
859                             null, null, null, null, null, null));
860         }
861     }
862 
logAugmentedAutofillShown(int sessionId, @Nullable Bundle clientState)863     void logAugmentedAutofillShown(int sessionId, @Nullable Bundle clientState) {
864         synchronized (mLock) {
865             if (mAugmentedAutofillEventHistory == null
866                     || mAugmentedAutofillEventHistory.getSessionId() != sessionId) {
867                 return;
868             }
869             // Augmented Autofill only logs for inline now, so set UI_TYPE_INLINE here.
870             // Ideally should not hardcode here and should also log for menu presentation.
871             mAugmentedAutofillEventHistory.addEvent(
872                     new Event(Event.TYPE_DATASETS_SHOWN, null, clientState, null, null, null,
873                             null, null, null, null, null, NO_SAVE_UI_REASON_NONE,
874                             UI_TYPE_INLINE));
875 
876         }
877     }
878 
879     /**
880      * Updates the last fill response when an autofill context is committed.
881      */
882     @GuardedBy("mLock")
logContextCommittedLocked(int sessionId, @Nullable Bundle clientState, @Nullable ArrayList<String> selectedDatasets, @Nullable ArraySet<String> ignoredDatasets, @Nullable ArrayList<AutofillId> changedFieldIds, @Nullable ArrayList<String> changedDatasetIds, @Nullable ArrayList<AutofillId> manuallyFilledFieldIds, @Nullable ArrayList<ArrayList<String>> manuallyFilledDatasetIds, @NonNull ComponentName appComponentName, boolean compatMode)883     void logContextCommittedLocked(int sessionId, @Nullable Bundle clientState,
884             @Nullable ArrayList<String> selectedDatasets,
885             @Nullable ArraySet<String> ignoredDatasets,
886             @Nullable ArrayList<AutofillId> changedFieldIds,
887             @Nullable ArrayList<String> changedDatasetIds,
888             @Nullable ArrayList<AutofillId> manuallyFilledFieldIds,
889             @Nullable ArrayList<ArrayList<String>> manuallyFilledDatasetIds,
890             @NonNull ComponentName appComponentName, boolean compatMode) {
891         logContextCommittedLocked(sessionId, clientState, selectedDatasets, ignoredDatasets,
892                 changedFieldIds, changedDatasetIds, manuallyFilledFieldIds,
893                 manuallyFilledDatasetIds, /* detectedFieldIdsList= */ null,
894                 /* detectedFieldClassificationsList= */ null, appComponentName, compatMode,
895                 Event.NO_SAVE_UI_REASON_NONE);
896     }
897 
898     @GuardedBy("mLock")
logContextCommittedLocked(int sessionId, @Nullable Bundle clientState, @Nullable ArrayList<String> selectedDatasets, @Nullable ArraySet<String> ignoredDatasets, @Nullable ArrayList<AutofillId> changedFieldIds, @Nullable ArrayList<String> changedDatasetIds, @Nullable ArrayList<AutofillId> manuallyFilledFieldIds, @Nullable ArrayList<ArrayList<String>> manuallyFilledDatasetIds, @Nullable ArrayList<AutofillId> detectedFieldIdsList, @Nullable ArrayList<FieldClassification> detectedFieldClassificationsList, @NonNull ComponentName appComponentName, boolean compatMode, @NoSaveReason int saveDialogNotShowReason)899     void logContextCommittedLocked(int sessionId, @Nullable Bundle clientState,
900             @Nullable ArrayList<String> selectedDatasets,
901             @Nullable ArraySet<String> ignoredDatasets,
902             @Nullable ArrayList<AutofillId> changedFieldIds,
903             @Nullable ArrayList<String> changedDatasetIds,
904             @Nullable ArrayList<AutofillId> manuallyFilledFieldIds,
905             @Nullable ArrayList<ArrayList<String>> manuallyFilledDatasetIds,
906             @Nullable ArrayList<AutofillId> detectedFieldIdsList,
907             @Nullable ArrayList<FieldClassification> detectedFieldClassificationsList,
908             @NonNull ComponentName appComponentName, boolean compatMode,
909             @NoSaveReason int saveDialogNotShowReason) {
910         if (isValidEventLocked("logDatasetNotSelected()", sessionId)) {
911             if (sVerbose) {
912                 Slog.v(TAG, "logContextCommitted() with FieldClassification: id=" + sessionId
913                         + ", selectedDatasets=" + selectedDatasets
914                         + ", ignoredDatasetIds=" + ignoredDatasets
915                         + ", changedAutofillIds=" + changedFieldIds
916                         + ", changedDatasetIds=" + changedDatasetIds
917                         + ", manuallyFilledFieldIds=" + manuallyFilledFieldIds
918                         + ", detectedFieldIds=" + detectedFieldIdsList
919                         + ", detectedFieldClassifications=" + detectedFieldClassificationsList
920                         + ", appComponentName=" + appComponentName.toShortString()
921                         + ", compatMode=" + compatMode
922                         + ", saveDialogNotShowReason=" + saveDialogNotShowReason);
923             }
924             AutofillId[] detectedFieldsIds = null;
925             FieldClassification[] detectedFieldClassifications = null;
926             if (detectedFieldIdsList != null) {
927                 detectedFieldsIds = new AutofillId[detectedFieldIdsList.size()];
928                 detectedFieldIdsList.toArray(detectedFieldsIds);
929                 detectedFieldClassifications =
930                         new FieldClassification[detectedFieldClassificationsList.size()];
931                 detectedFieldClassificationsList.toArray(detectedFieldClassifications);
932 
933                 final int numberFields = detectedFieldsIds.length;
934                 int totalSize = 0;
935                 float totalScore = 0;
936                 for (int i = 0; i < numberFields; i++) {
937                     final FieldClassification fc = detectedFieldClassifications[i];
938                     final List<Match> matches = fc.getMatches();
939                     final int size = matches.size();
940                     totalSize += size;
941                     for (int j = 0; j < size; j++) {
942                         totalScore += matches.get(j).getScore();
943                     }
944                 }
945 
946                 final int averageScore = (int) ((totalScore * 100) / totalSize);
947                 mMetricsLogger.write(Helper
948                         .newLogMaker(MetricsEvent.AUTOFILL_FIELD_CLASSIFICATION_MATCHES,
949                                 appComponentName, getServicePackageName(), sessionId, compatMode)
950                         .setCounterValue(numberFields)
951                         .addTaggedData(MetricsEvent.FIELD_AUTOFILL_MATCH_SCORE,
952                                 averageScore));
953             }
954             mEventHistory.addEvent(new Event(Event.TYPE_CONTEXT_COMMITTED, null,
955                     clientState, selectedDatasets, ignoredDatasets,
956                     changedFieldIds, changedDatasetIds,
957                     manuallyFilledFieldIds, manuallyFilledDatasetIds,
958                     detectedFieldsIds, detectedFieldClassifications, saveDialogNotShowReason));
959         }
960     }
961 
962     /**
963      * Gets the fill event history.
964      *
965      * @param callingUid The calling uid
966      * @return The history for the autofill or the augmented autofill events depending on the {@code
967      * callingUid}, or {@code null} if there is none.
968      */
getFillEventHistory(int callingUid)969     FillEventHistory getFillEventHistory(int callingUid) {
970         synchronized (mLock) {
971             if (mEventHistory != null
972                     && isCalledByServiceLocked("getFillEventHistory", callingUid)) {
973                 return mEventHistory;
974             }
975             if (mAugmentedAutofillEventHistory != null && isCalledByAugmentedAutofillServiceLocked(
976                     "getFillEventHistory", callingUid)) {
977                 return mAugmentedAutofillEventHistory;
978             }
979         }
980         return null;
981     }
982 
983     // Called by Session - does not need to check uid
getUserData()984     UserData getUserData() {
985         synchronized (mLock) {
986             return mUserData;
987         }
988     }
989 
990     // Called by AutofillManager
getUserData(int callingUid)991     UserData getUserData(int callingUid) {
992         synchronized (mLock) {
993             if (isCalledByServiceLocked("getUserData", callingUid)) {
994                 return mUserData;
995             }
996         }
997         return null;
998     }
999 
1000     // Called by AutofillManager
setUserData(int callingUid, UserData userData)1001     void setUserData(int callingUid, UserData userData) {
1002         synchronized (mLock) {
1003             if (!isCalledByServiceLocked("setUserData", callingUid)) {
1004                 return;
1005             }
1006             mUserData = userData;
1007             // Log it
1008             final int numberFields = mUserData == null ? 0: mUserData.getCategoryIds().length;
1009             // NOTE: contrary to most metrics, the service name is logged as the main package name
1010             // here, not as MetricsEvent.FIELD_AUTOFILL_SERVICE
1011             mMetricsLogger.write(new LogMaker(MetricsEvent.AUTOFILL_USERDATA_UPDATED)
1012                     .setPackageName(getServicePackageName())
1013                     .addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_VALUES, numberFields));
1014         }
1015     }
1016 
1017     @GuardedBy("mLock")
isCalledByServiceLocked(@onNull String methodName, int callingUid)1018     private boolean isCalledByServiceLocked(@NonNull String methodName, int callingUid) {
1019         final int serviceUid = getServiceUidLocked();
1020         if (serviceUid != callingUid) {
1021             Slog.w(TAG, methodName + "() called by UID " + callingUid
1022                     + ", but service UID is " + serviceUid);
1023             return false;
1024         }
1025         return true;
1026     }
1027 
1028     @GuardedBy("mLock")
getSupportedSmartSuggestionModesLocked()1029     @SmartSuggestionMode int getSupportedSmartSuggestionModesLocked() {
1030         return mMaster.getSupportedSmartSuggestionModesLocked();
1031     }
1032 
1033     @Override
1034     @GuardedBy("mLock")
dumpLocked(String prefix, PrintWriter pw)1035     protected void dumpLocked(String prefix, PrintWriter pw) {
1036         super.dumpLocked(prefix, pw);
1037 
1038         final String prefix2 = prefix + "  ";
1039 
1040         pw.print(prefix); pw.print("UID: "); pw.println(getServiceUidLocked());
1041         pw.print(prefix); pw.print("Autofill Service Info: ");
1042         if (mInfo == null) {
1043             pw.println("N/A");
1044         } else {
1045             pw.println();
1046             mInfo.dump(prefix2, pw);
1047         }
1048         pw.print(prefix); pw.print("Default component: "); pw.println(getContext()
1049                 .getString(R.string.config_defaultAutofillService));
1050 
1051         pw.print(prefix); pw.println("mAugmentedAutofillNamer: ");
1052         pw.print(prefix2); mMaster.mAugmentedAutofillResolver.dumpShort(pw, mUserId); pw.println();
1053 
1054         if (mRemoteAugmentedAutofillService != null) {
1055             pw.print(prefix); pw.println("RemoteAugmentedAutofillService: ");
1056             mRemoteAugmentedAutofillService.dump(prefix2, pw);
1057         }
1058         if (mRemoteAugmentedAutofillServiceInfo != null) {
1059             pw.print(prefix); pw.print("RemoteAugmentedAutofillServiceInfo: ");
1060             pw.println(mRemoteAugmentedAutofillServiceInfo);
1061         }
1062 
1063         pw.print(prefix); pw.print("Field classification enabled: ");
1064             pw.println(isFieldClassificationEnabledLocked());
1065         pw.print(prefix); pw.print("Compat pkgs: ");
1066         final ArrayMap<String, Long> compatPkgs = getCompatibilityPackagesLocked();
1067         if (compatPkgs == null) {
1068             pw.println("N/A");
1069         } else {
1070             pw.println(compatPkgs);
1071         }
1072         pw.print(prefix); pw.print("Inline Suggestions Enabled: ");
1073         pw.println(isInlineSuggestionsEnabledLocked());
1074         pw.print(prefix); pw.print("Last prune: "); pw.println(mLastPrune);
1075 
1076         mDisabledInfoCache.dump(mUserId, prefix, pw);
1077 
1078         final int size = mSessions.size();
1079         if (size == 0) {
1080             pw.print(prefix); pw.println("No sessions");
1081         } else {
1082             pw.print(prefix); pw.print(size); pw.println(" sessions:");
1083             for (int i = 0; i < size; i++) {
1084                 pw.print(prefix); pw.print("#"); pw.println(i + 1);
1085                 mSessions.valueAt(i).dumpLocked(prefix2, pw);
1086             }
1087         }
1088 
1089         pw.print(prefix); pw.print("Clients: ");
1090         if (mClients == null) {
1091             pw.println("N/A");
1092         } else {
1093             pw.println();
1094             mClients.dump(pw, prefix2);
1095         }
1096 
1097         if (mEventHistory == null || mEventHistory.getEvents() == null
1098                 || mEventHistory.getEvents().size() == 0) {
1099             pw.print(prefix); pw.println("No event on last fill response");
1100         } else {
1101             pw.print(prefix); pw.println("Events of last fill response:");
1102             pw.print(prefix);
1103 
1104             int numEvents = mEventHistory.getEvents().size();
1105             for (int i = 0; i < numEvents; i++) {
1106                 final Event event = mEventHistory.getEvents().get(i);
1107                 pw.println("  " + i + ": eventType=" + event.getType() + " datasetId="
1108                         + event.getDatasetId());
1109             }
1110         }
1111 
1112         pw.print(prefix); pw.print("User data: ");
1113         if (mUserData == null) {
1114             pw.println("N/A");
1115         } else {
1116             pw.println();
1117             mUserData.dump(prefix2, pw);
1118         }
1119 
1120         pw.print(prefix); pw.println("Field Classification strategy: ");
1121         mFieldClassificationStrategy.dump(prefix2, pw);
1122     }
1123 
1124     @GuardedBy("mLock")
forceRemoveAllSessionsLocked()1125     void forceRemoveAllSessionsLocked() {
1126         final int sessionCount = mSessions.size();
1127         if (sessionCount == 0) {
1128             mUi.destroyAll(null, null, false);
1129             return;
1130         }
1131 
1132         for (int i = sessionCount - 1; i >= 0; i--) {
1133             mSessions.valueAt(i).forceRemoveFromServiceLocked();
1134         }
1135     }
1136 
1137     @GuardedBy("mLock")
forceRemoveForAugmentedOnlySessionsLocked()1138     void forceRemoveForAugmentedOnlySessionsLocked() {
1139         final int sessionCount = mSessions.size();
1140         for (int i = sessionCount - 1; i >= 0; i--) {
1141             mSessions.valueAt(i).forceRemoveFromServiceIfForAugmentedOnlyLocked();
1142         }
1143     }
1144 
1145     /**
1146      * This method is called exclusively in response to {@code Intent.ACTION_CLOSE_SYSTEM_DIALOGS}.
1147      * The method removes all sessions that are finished but showing SaveUI due to how SaveUI is
1148      * managed (see b/64940307). Otherwise it will remove any augmented autofill generated windows.
1149      */
1150     // TODO(b/64940307): remove this method if SaveUI is refactored to be attached on activities
1151     @GuardedBy("mLock")
forceRemoveFinishedSessionsLocked()1152     void forceRemoveFinishedSessionsLocked() {
1153         final int sessionCount = mSessions.size();
1154         for (int i = sessionCount - 1; i >= 0; i--) {
1155             final Session session = mSessions.valueAt(i);
1156             if (session.isSaveUiShowingLocked()) {
1157                 if (sDebug) Slog.d(TAG, "destroyFinishedSessionsLocked(): " + session.id);
1158                 session.forceRemoveFromServiceLocked();
1159             } else {
1160                 session.destroyAugmentedAutofillWindowsLocked();
1161             }
1162         }
1163     }
1164 
1165     @GuardedBy("mLock")
listSessionsLocked(ArrayList<String> output)1166     void listSessionsLocked(ArrayList<String> output) {
1167         final int numSessions = mSessions.size();
1168         if (numSessions <= 0) return;
1169 
1170         final String fmt = "%d:%s:%s";
1171         for (int i = 0; i < numSessions; i++) {
1172             final int id = mSessions.keyAt(i);
1173             final String service = mInfo == null
1174                     ? "no_svc"
1175                     : mInfo.getServiceInfo().getComponentName().flattenToShortString();
1176             final String augmentedService = mRemoteAugmentedAutofillServiceInfo == null
1177                     ? "no_aug"
1178                     : mRemoteAugmentedAutofillServiceInfo.getComponentName().flattenToShortString();
1179             output.add(String.format(fmt, id, service, augmentedService));
1180         }
1181     }
1182 
1183     @GuardedBy("mLock")
getCompatibilityPackagesLocked()1184     @Nullable ArrayMap<String, Long> getCompatibilityPackagesLocked() {
1185         if (mInfo != null) {
1186             return mInfo.getCompatibilityPackages();
1187         }
1188         return null;
1189     }
1190 
1191     @GuardedBy("mLock")
isInlineSuggestionsEnabledLocked()1192     boolean isInlineSuggestionsEnabledLocked() {
1193         if (mInfo != null) {
1194             return mInfo.isInlineSuggestionsEnabled();
1195         }
1196         return false;
1197     }
1198 
1199     @GuardedBy("mLock")
requestSavedPasswordCount(IResultReceiver receiver)1200     void requestSavedPasswordCount(IResultReceiver receiver) {
1201         RemoteFillService remoteService =
1202                 new RemoteFillService(
1203                         getContext(), mInfo.getServiceInfo().getComponentName(), mUserId,
1204                         /* callbacks= */ null, mMaster.isInstantServiceAllowed());
1205         remoteService.onSavedPasswordCountRequest(receiver);
1206     }
1207 
1208     @GuardedBy("mLock")
getRemoteAugmentedAutofillServiceLocked()1209     @Nullable RemoteAugmentedAutofillService getRemoteAugmentedAutofillServiceLocked() {
1210         if (mRemoteAugmentedAutofillService == null) {
1211             final String serviceName = mMaster.mAugmentedAutofillResolver.getServiceName(mUserId);
1212             if (serviceName == null) {
1213                 if (mMaster.verbose) {
1214                     Slog.v(TAG, "getRemoteAugmentedAutofillServiceLocked(): not set");
1215                 }
1216                 return null;
1217             }
1218             final Pair<ServiceInfo, ComponentName> pair = RemoteAugmentedAutofillService
1219                     .getComponentName(serviceName, mUserId,
1220                             mMaster.mAugmentedAutofillResolver.isTemporary(mUserId));
1221             if (pair == null) return null;
1222 
1223             mRemoteAugmentedAutofillServiceInfo = pair.first;
1224             final ComponentName componentName = pair.second;
1225             if (sVerbose) {
1226                 Slog.v(TAG, "getRemoteAugmentedAutofillServiceLocked(): " + componentName);
1227             }
1228 
1229             final RemoteAugmentedAutofillServiceCallbacks callbacks =
1230                     new RemoteAugmentedAutofillServiceCallbacks() {
1231                         @Override
1232                         public void resetLastResponse() {
1233                             AutofillManagerServiceImpl.this.resetLastAugmentedAutofillResponse();
1234                         }
1235 
1236                         @Override
1237                         public void setLastResponse(int sessionId) {
1238                             AutofillManagerServiceImpl.this.setLastAugmentedAutofillResponse(
1239                                     sessionId);
1240                         }
1241 
1242                         @Override
1243                         public void logAugmentedAutofillShown(int sessionId, Bundle clientState) {
1244                             AutofillManagerServiceImpl.this.logAugmentedAutofillShown(sessionId,
1245                                     clientState);
1246                         }
1247 
1248                         @Override
1249                         public void logAugmentedAutofillSelected(int sessionId,
1250                                 String suggestionId, Bundle clientState) {
1251                             AutofillManagerServiceImpl.this.logAugmentedAutofillSelected(sessionId,
1252                                     suggestionId, clientState);
1253                         }
1254 
1255                         @Override
1256                         public void logAugmentedAutofillAuthenticationSelected(int sessionId,
1257                                 String suggestionId, Bundle clientState) {
1258                             AutofillManagerServiceImpl.this
1259                                     .logAugmentedAutofillAuthenticationSelected(
1260                                             sessionId, suggestionId, clientState);
1261                         }
1262 
1263                         @Override
1264                         public void onServiceDied(@NonNull RemoteAugmentedAutofillService service) {
1265                             Slog.w(TAG, "remote augmented autofill service died");
1266                             final RemoteAugmentedAutofillService remoteService =
1267                                     mRemoteAugmentedAutofillService;
1268                             if (remoteService != null) {
1269                                 remoteService.unbind();
1270                             }
1271                             mRemoteAugmentedAutofillService = null;
1272                         }
1273                     };
1274             final int serviceUid = mRemoteAugmentedAutofillServiceInfo.applicationInfo.uid;
1275             mRemoteAugmentedAutofillService = new RemoteAugmentedAutofillService(getContext(),
1276                     serviceUid, componentName,
1277                     mUserId, callbacks, mMaster.isInstantServiceAllowed(),
1278                     mMaster.verbose, mMaster.mAugmentedServiceIdleUnbindTimeoutMs,
1279                     mMaster.mAugmentedServiceRequestTimeoutMs);
1280         }
1281 
1282         return mRemoteAugmentedAutofillService;
1283     }
1284 
1285     @GuardedBy("mLock")
getRemoteAugmentedAutofillServiceIfCreatedLocked()1286     @Nullable RemoteAugmentedAutofillService getRemoteAugmentedAutofillServiceIfCreatedLocked() {
1287         return mRemoteAugmentedAutofillService;
1288     }
1289 
1290     /**
1291      * Called when the {@link AutofillManagerService#mAugmentedAutofillResolver}
1292      * changed (among other places).
1293      */
updateRemoteAugmentedAutofillService()1294     void updateRemoteAugmentedAutofillService() {
1295         synchronized (mLock) {
1296             if (mRemoteAugmentedAutofillService != null) {
1297                 if (sVerbose) {
1298                     Slog.v(TAG, "updateRemoteAugmentedAutofillService(): "
1299                             + "destroying old remote service");
1300                 }
1301                 forceRemoveForAugmentedOnlySessionsLocked();
1302                 mRemoteAugmentedAutofillService.unbind();
1303                 mRemoteAugmentedAutofillService = null;
1304                 mRemoteAugmentedAutofillServiceInfo = null;
1305                 resetAugmentedAutofillWhitelistLocked();
1306             }
1307 
1308             final boolean available = isAugmentedAutofillServiceAvailableLocked();
1309             if (sVerbose) Slog.v(TAG, "updateRemoteAugmentedAutofillService(): " + available);
1310 
1311             if (available) {
1312                 mRemoteAugmentedAutofillService = getRemoteAugmentedAutofillServiceLocked();
1313             }
1314         }
1315     }
1316 
isAugmentedAutofillServiceAvailableLocked()1317     private boolean isAugmentedAutofillServiceAvailableLocked() {
1318         if (mMaster.verbose) {
1319             Slog.v(TAG, "isAugmentedAutofillService(): "
1320                     + "setupCompleted=" + isSetupCompletedLocked()
1321                     + ", disabled=" + isDisabledByUserRestrictionsLocked()
1322                     + ", augmentedService="
1323                     + mMaster.mAugmentedAutofillResolver.getServiceName(mUserId));
1324         }
1325         if (!isSetupCompletedLocked() || isDisabledByUserRestrictionsLocked()
1326                 || mMaster.mAugmentedAutofillResolver.getServiceName(mUserId) == null) {
1327             return false;
1328         }
1329         return true;
1330     }
1331 
isAugmentedAutofillServiceForUserLocked(int callingUid)1332     boolean isAugmentedAutofillServiceForUserLocked(int callingUid) {
1333         return mRemoteAugmentedAutofillServiceInfo != null
1334                 && mRemoteAugmentedAutofillServiceInfo.applicationInfo.uid == callingUid;
1335     }
1336 
1337     /**
1338      * Sets which packages and activities can trigger augmented autofill.
1339      *
1340      * @return whether caller UID is the augmented autofill service for the user
1341      */
1342     @GuardedBy("mLock")
setAugmentedAutofillWhitelistLocked(@ullable List<String> packages, @Nullable List<ComponentName> activities, int callingUid)1343     boolean setAugmentedAutofillWhitelistLocked(@Nullable List<String> packages,
1344             @Nullable List<ComponentName> activities, int callingUid) {
1345 
1346         if (!isCalledByAugmentedAutofillServiceLocked("setAugmentedAutofillWhitelistLocked",
1347                 callingUid)) {
1348             return false;
1349         }
1350         if (mMaster.verbose) {
1351             Slog.v(TAG, "setAugmentedAutofillWhitelistLocked(packages=" + packages + ", activities="
1352                     + activities + ")");
1353         }
1354         whitelistForAugmentedAutofillPackages(packages, activities);
1355         final String serviceName;
1356         if (mRemoteAugmentedAutofillServiceInfo != null) {
1357             serviceName = mRemoteAugmentedAutofillServiceInfo.getComponentName()
1358                     .flattenToShortString();
1359         } else {
1360             Slog.e(TAG, "setAugmentedAutofillWhitelistLocked(): no service");
1361             serviceName = "N/A";
1362         }
1363 
1364         final LogMaker log = new LogMaker(MetricsEvent.AUTOFILL_AUGMENTED_WHITELIST_REQUEST)
1365                 .addTaggedData(MetricsEvent.FIELD_AUTOFILL_SERVICE, serviceName);
1366         if (packages != null) {
1367             log.addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUMBER_PACKAGES, packages.size());
1368         }
1369         if (activities != null) {
1370             log.addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUMBER_ACTIVITIES, activities.size());
1371         }
1372         mMetricsLogger.write(log);
1373 
1374         return true;
1375     }
1376 
1377     @GuardedBy("mLock")
isCalledByAugmentedAutofillServiceLocked(@onNull String methodName, int callingUid)1378     private boolean isCalledByAugmentedAutofillServiceLocked(@NonNull String methodName,
1379             int callingUid) {
1380         // Lazy load service first
1381         final RemoteAugmentedAutofillService service = getRemoteAugmentedAutofillServiceLocked();
1382         if (service == null) {
1383             Slog.w(TAG, methodName + "() called by UID " + callingUid
1384                     + ", but there is no augmented autofill service defined for user "
1385                     + getUserId());
1386             return false;
1387         }
1388 
1389         if (getAugmentedAutofillServiceUidLocked() != callingUid) {
1390             Slog.w(TAG, methodName + "() called by UID " + callingUid
1391                     + ", but service UID is " + getAugmentedAutofillServiceUidLocked()
1392                     + " for user " + getUserId());
1393             return false;
1394         }
1395         return true;
1396     }
1397 
1398     @GuardedBy("mLock")
getAugmentedAutofillServiceUidLocked()1399     private int getAugmentedAutofillServiceUidLocked() {
1400         if (mRemoteAugmentedAutofillServiceInfo == null) {
1401             if (mMaster.verbose) {
1402                 Slog.v(TAG, "getAugmentedAutofillServiceUid(): "
1403                         + "no mRemoteAugmentedAutofillServiceInfo");
1404             }
1405             return Process.INVALID_UID;
1406         }
1407         return mRemoteAugmentedAutofillServiceInfo.applicationInfo.uid;
1408     }
1409 
1410     @GuardedBy("mLock")
isWhitelistedForAugmentedAutofillLocked(@onNull ComponentName componentName)1411     boolean isWhitelistedForAugmentedAutofillLocked(@NonNull ComponentName componentName) {
1412         return mMaster.mAugmentedAutofillState.isWhitelisted(mUserId, componentName);
1413     }
1414 
1415     /**
1416      * @throws IllegalArgumentException if packages or components are empty.
1417      */
whitelistForAugmentedAutofillPackages(@ullable List<String> packages, @Nullable List<ComponentName> components)1418     private void whitelistForAugmentedAutofillPackages(@Nullable List<String> packages,
1419             @Nullable List<ComponentName> components) {
1420         // TODO(b/123100824): add CTS test for when it's null
1421         synchronized (mLock) {
1422             if (mMaster.verbose) {
1423                 Slog.v(TAG, "whitelisting packages: " + packages + "and activities: " + components);
1424             }
1425             mMaster.mAugmentedAutofillState.setWhitelist(mUserId, packages, components);
1426         }
1427     }
1428 
1429     /**
1430      * Resets the augmented autofill allowlist.
1431      */
1432     @GuardedBy("mLock")
resetAugmentedAutofillWhitelistLocked()1433     void resetAugmentedAutofillWhitelistLocked() {
1434         if (mMaster.verbose) {
1435             Slog.v(TAG, "resetting augmented autofill whitelist");
1436         }
1437         mMaster.mAugmentedAutofillState.resetWhitelist(mUserId);
1438     }
1439 
sendStateToClients(boolean resetClient)1440     private void sendStateToClients(boolean resetClient) {
1441         final RemoteCallbackList<IAutoFillManagerClient> clients;
1442         final int userClientCount;
1443         synchronized (mLock) {
1444             if (mClients == null) {
1445                 return;
1446             }
1447             clients = mClients;
1448             userClientCount = clients.beginBroadcast();
1449         }
1450         try {
1451             for (int i = 0; i < userClientCount; i++) {
1452                 final IAutoFillManagerClient client = clients.getBroadcastItem(i);
1453                 try {
1454                     final boolean resetSession;
1455                     final boolean isEnabled;
1456                     synchronized (mLock) {
1457                         resetSession = resetClient || isClientSessionDestroyedLocked(client);
1458                         isEnabled = isEnabledLocked();
1459                     }
1460                     int flags = 0;
1461                     if (isEnabled) {
1462                         flags |= AutofillManager.SET_STATE_FLAG_ENABLED;
1463                     }
1464                     if (resetSession) {
1465                         flags |= AutofillManager.SET_STATE_FLAG_RESET_SESSION;
1466                     }
1467                     if (resetClient) {
1468                         flags |= AutofillManager.SET_STATE_FLAG_RESET_CLIENT;
1469                     }
1470                     if (sDebug) {
1471                         flags |= AutofillManager.SET_STATE_FLAG_DEBUG;
1472                     }
1473                     if (sVerbose) {
1474                         flags |= AutofillManager.SET_STATE_FLAG_VERBOSE;
1475                     }
1476                     client.setState(flags);
1477                 } catch (RemoteException re) {
1478                     /* ignore */
1479                 }
1480             }
1481         } finally {
1482             clients.finishBroadcast();
1483         }
1484     }
1485 
1486     @GuardedBy("mLock")
isClientSessionDestroyedLocked(IAutoFillManagerClient client)1487     private boolean isClientSessionDestroyedLocked(IAutoFillManagerClient client) {
1488         final int sessionCount = mSessions.size();
1489         for (int i = 0; i < sessionCount; i++) {
1490             final Session session = mSessions.valueAt(i);
1491             if (session.getClient().equals(client)) {
1492                 return session.isDestroyed();
1493             }
1494         }
1495         return true;
1496     }
1497 
1498     /**
1499      * Called by {@link Session} when service asked to disable autofill for an app.
1500      */
disableAutofillForApp(@onNull String packageName, long duration, int sessionId, boolean compatMode)1501     void disableAutofillForApp(@NonNull String packageName, long duration, int sessionId,
1502             boolean compatMode) {
1503         synchronized (mLock) {
1504             long expiration = SystemClock.elapsedRealtime() + duration;
1505             // Protect it against overflow
1506             if (expiration < 0) {
1507                 expiration = Long.MAX_VALUE;
1508             }
1509             mDisabledInfoCache.addDisabledAppLocked(mUserId, packageName, expiration);
1510 
1511             int intDuration = duration > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) duration;
1512             mMetricsLogger.write(Helper.newLogMaker(MetricsEvent.AUTOFILL_SERVICE_DISABLED_APP,
1513                     packageName, getServicePackageName(), sessionId, compatMode)
1514                     .addTaggedData(MetricsEvent.FIELD_AUTOFILL_DURATION, intDuration));
1515         }
1516     }
1517 
1518     /**
1519      * Called by {@link Session} when service asked to disable autofill an app.
1520      */
disableAutofillForActivity(@onNull ComponentName componentName, long duration, int sessionId, boolean compatMode)1521     void disableAutofillForActivity(@NonNull ComponentName componentName, long duration,
1522             int sessionId, boolean compatMode) {
1523         synchronized (mLock) {
1524             long expiration = SystemClock.elapsedRealtime() + duration;
1525             // Protect it against overflow
1526             if (expiration < 0) {
1527                 expiration = Long.MAX_VALUE;
1528             }
1529             mDisabledInfoCache.addDisabledActivityLocked(mUserId, componentName, expiration);
1530             final int intDuration = duration > Integer.MAX_VALUE
1531                     ? Integer.MAX_VALUE
1532                     : (int) duration;
1533 
1534             final LogMaker log = Helper.newLogMaker(MetricsEvent.AUTOFILL_SERVICE_DISABLED_ACTIVITY,
1535                     componentName, getServicePackageName(), sessionId, compatMode)
1536                     .addTaggedData(MetricsEvent.FIELD_AUTOFILL_DURATION, intDuration);
1537             mMetricsLogger.write(log);
1538         }
1539     }
1540 
1541     /**
1542      * Checks if autofill is disabled by service to the given activity.
1543      */
1544     @GuardedBy("mLock")
isAutofillDisabledLocked(@onNull ComponentName componentName)1545     private boolean isAutofillDisabledLocked(@NonNull ComponentName componentName) {
1546         return mDisabledInfoCache.isAutofillDisabledLocked(mUserId, componentName);
1547     }
1548 
1549     // Called by AutofillManager, checks UID.
isFieldClassificationEnabled(int callingUid)1550     boolean isFieldClassificationEnabled(int callingUid) {
1551         synchronized (mLock) {
1552             if (!isCalledByServiceLocked("isFieldClassificationEnabled", callingUid)) {
1553                 return false;
1554             }
1555             return isFieldClassificationEnabledLocked();
1556         }
1557     }
1558 
1559     // Called by internally, no need to check UID.
isFieldClassificationEnabledLocked()1560     boolean isFieldClassificationEnabledLocked() {
1561         return Settings.Secure.getIntForUser(
1562                 getContext().getContentResolver(),
1563                 Settings.Secure.AUTOFILL_FEATURE_FIELD_CLASSIFICATION, 1,
1564                 mUserId) == 1;
1565     }
1566 
getFieldClassificationStrategy()1567     FieldClassificationStrategy getFieldClassificationStrategy() {
1568         return mFieldClassificationStrategy;
1569     }
1570 
getAvailableFieldClassificationAlgorithms(int callingUid)1571     String[] getAvailableFieldClassificationAlgorithms(int callingUid) {
1572         synchronized (mLock) {
1573             if (!isCalledByServiceLocked("getFCAlgorithms()", callingUid)) {
1574                 return null;
1575             }
1576         }
1577         return mFieldClassificationStrategy.getAvailableAlgorithms();
1578     }
1579 
getDefaultFieldClassificationAlgorithm(int callingUid)1580     String getDefaultFieldClassificationAlgorithm(int callingUid) {
1581         synchronized (mLock) {
1582             if (!isCalledByServiceLocked("getDefaultFCAlgorithm()", callingUid)) {
1583                 return null;
1584             }
1585         }
1586         return mFieldClassificationStrategy.getDefaultAlgorithm();
1587     }
1588 
updateRemoteInlineSuggestionRenderServiceLocked()1589     private void updateRemoteInlineSuggestionRenderServiceLocked() {
1590         if (mRemoteInlineSuggestionRenderService != null) {
1591             if (sVerbose) {
1592                 Slog.v(TAG, "updateRemoteInlineSuggestionRenderService(): "
1593                         + "destroying old remote service");
1594             }
1595             mRemoteInlineSuggestionRenderService = null;
1596         }
1597 
1598         mRemoteInlineSuggestionRenderService = getRemoteInlineSuggestionRenderServiceLocked();
1599     }
1600 
getRemoteInlineSuggestionRenderServiceLocked()1601     @Nullable RemoteInlineSuggestionRenderService getRemoteInlineSuggestionRenderServiceLocked() {
1602         if (mRemoteInlineSuggestionRenderService == null) {
1603             final ComponentName componentName = RemoteInlineSuggestionRenderService
1604                 .getServiceComponentName(getContext(), mUserId);
1605             if (componentName == null) {
1606                 Slog.w(TAG, "No valid component found for InlineSuggestionRenderService");
1607                 return null;
1608             }
1609 
1610             mRemoteInlineSuggestionRenderService = new RemoteInlineSuggestionRenderService(
1611                     getContext(), componentName, InlineSuggestionRenderService.SERVICE_INTERFACE,
1612                     mUserId, new InlineSuggestionRenderCallbacksImpl(),
1613                     mMaster.isBindInstantServiceAllowed(), mMaster.verbose);
1614         }
1615 
1616         return mRemoteInlineSuggestionRenderService;
1617     }
1618 
1619     private class InlineSuggestionRenderCallbacksImpl implements
1620             RemoteInlineSuggestionRenderService.InlineSuggestionRenderCallbacks {
1621 
1622         @Override // from InlineSuggestionRenderCallbacksImpl
onServiceDied(@onNull RemoteInlineSuggestionRenderService service)1623         public void onServiceDied(@NonNull RemoteInlineSuggestionRenderService service) {
1624             // Don't do anything; eventually the system will bind to it again...
1625             Slog.w(TAG, "remote service died: " + service);
1626             mRemoteInlineSuggestionRenderService = null;
1627         }
1628     }
1629 
onSwitchInputMethod()1630     void onSwitchInputMethod() {
1631         synchronized (mLock) {
1632             final int sessionCount = mSessions.size();
1633             for (int i = 0; i < sessionCount; i++) {
1634                 final Session session = mSessions.valueAt(i);
1635                 session.onSwitchInputMethodLocked();
1636             }
1637         }
1638     }
1639 
1640     @Override
toString()1641     public String toString() {
1642         return "AutofillManagerServiceImpl: [userId=" + mUserId
1643                 + ", component=" + (mInfo != null
1644                 ? mInfo.getServiceInfo().getComponentName() : null) + "]";
1645     }
1646 
1647     /** Task used to prune abandoned session */
1648     private class PruneTask extends AsyncTask<Void, Void, Void> {
1649         @Override
doInBackground(Void... ignored)1650         protected Void doInBackground(Void... ignored) {
1651             int numSessionsToRemove;
1652 
1653             SparseArray<IBinder> sessionsToRemove;
1654 
1655             synchronized (mLock) {
1656                 numSessionsToRemove = mSessions.size();
1657                 sessionsToRemove = new SparseArray<>(numSessionsToRemove);
1658 
1659                 for (int i = 0; i < numSessionsToRemove; i++) {
1660                     Session session = mSessions.valueAt(i);
1661 
1662                     sessionsToRemove.put(session.id, session.getActivityTokenLocked());
1663                 }
1664             }
1665 
1666             final ActivityTaskManagerInternal atmInternal = LocalServices.getService(
1667                     ActivityTaskManagerInternal.class);
1668 
1669             // Only remove sessions which's activities are not known to the activity manager anymore
1670             for (int i = 0; i < numSessionsToRemove; i++) {
1671                 // The activity task manager cannot resolve activities that have been removed.
1672                 if (atmInternal.getActivityName(sessionsToRemove.valueAt(i)) != null) {
1673                     sessionsToRemove.removeAt(i);
1674                     i--;
1675                     numSessionsToRemove--;
1676                 }
1677             }
1678 
1679             synchronized (mLock) {
1680                 for (int i = 0; i < numSessionsToRemove; i++) {
1681                     Session sessionToRemove = mSessions.get(sessionsToRemove.keyAt(i));
1682 
1683                     if (sessionToRemove != null && sessionsToRemove.valueAt(i)
1684                             == sessionToRemove.getActivityTokenLocked()) {
1685                         if (sessionToRemove.isSaveUiShowingLocked()) {
1686                             if (sVerbose) {
1687                                 Slog.v(TAG, "Session " + sessionToRemove.id + " is saving");
1688                             }
1689                         } else {
1690                             if (sDebug) {
1691                                 Slog.i(TAG, "Prune session " + sessionToRemove.id + " ("
1692                                     + sessionToRemove.getActivityTokenLocked() + ")");
1693                             }
1694                             sessionToRemove.removeFromServiceLocked();
1695                         }
1696                     }
1697                 }
1698             }
1699 
1700             return null;
1701         }
1702     }
1703 }
1704