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