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