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