1 /* 2 * Copyright (C) 2022 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.UI_TYPE_DIALOG; 20 import static android.service.autofill.FillEventHistory.Event.UI_TYPE_INLINE; 21 import static android.service.autofill.FillEventHistory.Event.UI_TYPE_MENU; 22 import static android.service.autofill.FillEventHistory.Event.UiType; 23 import static android.view.autofill.AutofillManager.COMMIT_REASON_ACTIVITY_FINISHED; 24 import static android.view.autofill.AutofillManager.COMMIT_REASON_VIEW_CHANGED; 25 import static android.view.autofill.AutofillManager.COMMIT_REASON_VIEW_CLICKED; 26 import static android.view.autofill.AutofillManager.COMMIT_REASON_VIEW_COMMITTED; 27 28 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__DETECTION_PREFERENCE__DETECTION_PREFER_AUTOFILL_PROVIDER; 29 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__DETECTION_PREFERENCE__DETECTION_PREFER_PCC; 30 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__DETECTION_PREFERENCE__DETECTION_PREFER_UNKONWN; 31 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_PRESENTATION_EVENT_REPORTED; 32 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_PRESENTATION_EVENT_REPORTED__AUTHENTICATION_RESULT__AUTHENTICATION_FAILURE; 33 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_PRESENTATION_EVENT_REPORTED__AUTHENTICATION_RESULT__AUTHENTICATION_RESULT_UNKNOWN; 34 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_PRESENTATION_EVENT_REPORTED__AUTHENTICATION_RESULT__AUTHENTICATION_SUCCESS; 35 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_PRESENTATION_EVENT_REPORTED__AUTHENTICATION_TYPE__AUTHENTICATION_TYPE_UNKNOWN; 36 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_PRESENTATION_EVENT_REPORTED__AUTHENTICATION_TYPE__DATASET_AUTHENTICATION; 37 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_PRESENTATION_EVENT_REPORTED__AUTHENTICATION_TYPE__FULL_AUTHENTICATION; 38 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_PRESENTATION_EVENT_REPORTED__DISPLAY_PRESENTATION_TYPE__DIALOG; 39 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_PRESENTATION_EVENT_REPORTED__DISPLAY_PRESENTATION_TYPE__INLINE; 40 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_PRESENTATION_EVENT_REPORTED__DISPLAY_PRESENTATION_TYPE__MENU; 41 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_PRESENTATION_EVENT_REPORTED__DISPLAY_PRESENTATION_TYPE__UNKNOWN_AUTOFILL_DISPLAY_PRESENTATION_TYPE; 42 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_PRESENTATION_EVENT_REPORTED__PRESENTATION_EVENT_RESULT__ANY_SHOWN; 43 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_PRESENTATION_EVENT_REPORTED__PRESENTATION_EVENT_RESULT__NONE_SHOWN_ACTIVITY_FINISHED; 44 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_PRESENTATION_EVENT_REPORTED__PRESENTATION_EVENT_RESULT__NONE_SHOWN_FILL_REQUEST_FAILED; 45 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_PRESENTATION_EVENT_REPORTED__PRESENTATION_EVENT_RESULT__NONE_SHOWN_NO_FOCUS; 46 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_PRESENTATION_EVENT_REPORTED__PRESENTATION_EVENT_RESULT__NONE_SHOWN_REQUEST_TIMEOUT; 47 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_PRESENTATION_EVENT_REPORTED__PRESENTATION_EVENT_RESULT__NONE_SHOWN_SESSION_COMMITTED_PREMATURELY; 48 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_PRESENTATION_EVENT_REPORTED__PRESENTATION_EVENT_RESULT__NONE_SHOWN_UNKNOWN_REASON; 49 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_PRESENTATION_EVENT_REPORTED__PRESENTATION_EVENT_RESULT__NONE_SHOWN_VIEW_CHANGED; 50 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_PRESENTATION_EVENT_REPORTED__PRESENTATION_EVENT_RESULT__NONE_SHOWN_VIEW_FOCUSED_BEFORE_FILL_DIALOG_RESPONSE; 51 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_PRESENTATION_EVENT_REPORTED__PRESENTATION_EVENT_RESULT__NONE_SHOWN_VIEW_FOCUS_CHANGED; 52 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_PRESENTATION_EVENT_REPORTED__SELECTED_DATASET_PICKED_REASON__PICK_REASON_NO_PCC; 53 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_PRESENTATION_EVENT_REPORTED__SELECTED_DATASET_PICKED_REASON__PICK_REASON_PCC_DETECTION_ONLY; 54 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_PRESENTATION_EVENT_REPORTED__SELECTED_DATASET_PICKED_REASON__PICK_REASON_PCC_DETECTION_PREFERRED_WITH_PROVIDER; 55 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_PRESENTATION_EVENT_REPORTED__SELECTED_DATASET_PICKED_REASON__PICK_REASON_PROVIDER_DETECTION_ONLY; 56 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_PRESENTATION_EVENT_REPORTED__SELECTED_DATASET_PICKED_REASON__PICK_REASON_PROVIDER_DETECTION_PREFERRED_WITH_PCC; 57 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_PRESENTATION_EVENT_REPORTED__SELECTED_DATASET_PICKED_REASON__PICK_REASON_UNKNOWN; 58 import static com.android.server.autofill.Helper.sVerbose; 59 60 import android.annotation.IntDef; 61 import android.annotation.Nullable; 62 import android.content.ComponentName; 63 import android.content.Context; 64 import android.content.pm.PackageManager; 65 import android.os.SystemClock; 66 import android.provider.Settings; 67 import android.service.autofill.Dataset; 68 import android.text.TextUtils; 69 import android.util.ArraySet; 70 import android.util.Slog; 71 import android.view.autofill.AutofillId; 72 import android.view.autofill.AutofillManager; 73 74 import com.android.internal.util.FrameworkStatsLog; 75 76 import java.lang.annotation.Retention; 77 import java.lang.annotation.RetentionPolicy; 78 import java.util.List; 79 import java.util.Optional; 80 81 /** Helper class to track and log Autofill presentation stats. */ 82 public final class PresentationStatsEventLogger { 83 private static final String TAG = "PresentationStatsEventLogger"; 84 85 /** 86 * Reasons why presentation was not shown. These are wrappers around 87 * {@link com.android.os.AtomsProto.AutofillPresentationEventReported.PresentationEventResult}. 88 */ 89 @IntDef(prefix = {"NOT_SHOWN_REASON"}, value = { 90 NOT_SHOWN_REASON_ANY_SHOWN, 91 NOT_SHOWN_REASON_VIEW_FOCUS_CHANGED, 92 NOT_SHOWN_REASON_VIEW_FOCUSED_BEFORE_FILL_DIALOG_RESPONSE, 93 NOT_SHOWN_REASON_VIEW_CHANGED, 94 NOT_SHOWN_REASON_ACTIVITY_FINISHED, 95 NOT_SHOWN_REASON_REQUEST_TIMEOUT, 96 NOT_SHOWN_REASON_REQUEST_FAILED, 97 NOT_SHOWN_REASON_NO_FOCUS, 98 NOT_SHOWN_REASON_SESSION_COMMITTED_PREMATURELY, 99 NOT_SHOWN_REASON_UNKNOWN 100 }) 101 @Retention(RetentionPolicy.SOURCE) 102 public @interface NotShownReason {} 103 104 /** 105 * Reasons why presentation was not shown. These are wrappers around 106 * {@link com.android.os.AtomsProto.AutofillPresentationEventReported.AuthenticationType}. 107 */ 108 @IntDef(prefix = {"AUTHENTICATION_TYPE"}, value = { 109 AUTHENTICATION_TYPE_UNKNOWN, 110 AUTHENTICATION_TYPE_DATASET_AUTHENTICATION, 111 AUTHENTICATION_TYPE_FULL_AUTHENTICATION 112 }) 113 @Retention(RetentionPolicy.SOURCE) 114 public @interface AuthenticationType { 115 } 116 117 /** 118 * Reasons why presentation was not shown. These are wrappers around 119 * {@link com.android.os.AtomsProto.AutofillPresentationEventReported.AuthenticationResult}. 120 */ 121 @IntDef(prefix = {"AUTHENTICATION_RESULT"}, value = { 122 AUTHENTICATION_RESULT_UNKNOWN, 123 AUTHENTICATION_RESULT_SUCCESS, 124 AUTHENTICATION_RESULT_FAILURE 125 }) 126 @Retention(RetentionPolicy.SOURCE) 127 public @interface AuthenticationResult { 128 } 129 130 /** 131 * Reasons why the picked dataset was present. These are wrappers around 132 * {@link com.android.os.AtomsProto.AutofillPresentationEventReported.DatasetPickedReason}. 133 * This enum is similar to {@link android.service.autofill.Dataset.DatasetEligibleReason} 134 */ 135 @IntDef(prefix = {"PICK_REASON"}, value = { 136 PICK_REASON_UNKNOWN, 137 PICK_REASON_NO_PCC, 138 PICK_REASON_PROVIDER_DETECTION_ONLY, 139 PICK_REASON_PROVIDER_DETECTION_PREFERRED_WITH_PCC, 140 PICK_REASON_PCC_DETECTION_ONLY, 141 PICK_REASON_PCC_DETECTION_PREFERRED_WITH_PROVIDER, 142 }) 143 @Retention(RetentionPolicy.SOURCE) 144 public @interface DatasetPickedReason {} 145 146 /** 147 * The type of detection that was preferred. These are wrappers around 148 * {@link com.android.os.AtomsProto.AutofillPresentationEventReported.DetectionPreference}. 149 */ 150 @IntDef(prefix = {"DETECTION_PREFER"}, value = { 151 DETECTION_PREFER_UNKNOWN, 152 DETECTION_PREFER_AUTOFILL_PROVIDER, 153 DETECTION_PREFER_PCC 154 }) 155 @Retention(RetentionPolicy.SOURCE) 156 public @interface DetectionPreference { 157 } 158 159 public static final int NOT_SHOWN_REASON_ANY_SHOWN = 160 AUTOFILL_PRESENTATION_EVENT_REPORTED__PRESENTATION_EVENT_RESULT__ANY_SHOWN; 161 public static final int NOT_SHOWN_REASON_VIEW_FOCUS_CHANGED = 162 AUTOFILL_PRESENTATION_EVENT_REPORTED__PRESENTATION_EVENT_RESULT__NONE_SHOWN_VIEW_FOCUS_CHANGED; 163 public static final int NOT_SHOWN_REASON_VIEW_FOCUSED_BEFORE_FILL_DIALOG_RESPONSE = 164 AUTOFILL_PRESENTATION_EVENT_REPORTED__PRESENTATION_EVENT_RESULT__NONE_SHOWN_VIEW_FOCUSED_BEFORE_FILL_DIALOG_RESPONSE; 165 public static final int NOT_SHOWN_REASON_VIEW_CHANGED = 166 AUTOFILL_PRESENTATION_EVENT_REPORTED__PRESENTATION_EVENT_RESULT__NONE_SHOWN_VIEW_CHANGED; 167 public static final int NOT_SHOWN_REASON_ACTIVITY_FINISHED = 168 AUTOFILL_PRESENTATION_EVENT_REPORTED__PRESENTATION_EVENT_RESULT__NONE_SHOWN_ACTIVITY_FINISHED; 169 public static final int NOT_SHOWN_REASON_REQUEST_TIMEOUT = 170 AUTOFILL_PRESENTATION_EVENT_REPORTED__PRESENTATION_EVENT_RESULT__NONE_SHOWN_REQUEST_TIMEOUT; 171 public static final int NOT_SHOWN_REASON_REQUEST_FAILED = 172 AUTOFILL_PRESENTATION_EVENT_REPORTED__PRESENTATION_EVENT_RESULT__NONE_SHOWN_FILL_REQUEST_FAILED; 173 public static final int NOT_SHOWN_REASON_NO_FOCUS = 174 AUTOFILL_PRESENTATION_EVENT_REPORTED__PRESENTATION_EVENT_RESULT__NONE_SHOWN_NO_FOCUS; 175 public static final int NOT_SHOWN_REASON_SESSION_COMMITTED_PREMATURELY = 176 AUTOFILL_PRESENTATION_EVENT_REPORTED__PRESENTATION_EVENT_RESULT__NONE_SHOWN_SESSION_COMMITTED_PREMATURELY; 177 public static final int NOT_SHOWN_REASON_UNKNOWN = 178 AUTOFILL_PRESENTATION_EVENT_REPORTED__PRESENTATION_EVENT_RESULT__NONE_SHOWN_UNKNOWN_REASON; 179 180 public static final int AUTHENTICATION_TYPE_UNKNOWN = 181 AUTOFILL_PRESENTATION_EVENT_REPORTED__AUTHENTICATION_TYPE__AUTHENTICATION_TYPE_UNKNOWN; 182 public static final int AUTHENTICATION_TYPE_DATASET_AUTHENTICATION = 183 AUTOFILL_PRESENTATION_EVENT_REPORTED__AUTHENTICATION_TYPE__DATASET_AUTHENTICATION; 184 public static final int AUTHENTICATION_TYPE_FULL_AUTHENTICATION = 185 AUTOFILL_PRESENTATION_EVENT_REPORTED__AUTHENTICATION_TYPE__FULL_AUTHENTICATION; 186 187 public static final int AUTHENTICATION_RESULT_UNKNOWN = 188 AUTOFILL_PRESENTATION_EVENT_REPORTED__AUTHENTICATION_RESULT__AUTHENTICATION_RESULT_UNKNOWN; 189 public static final int AUTHENTICATION_RESULT_SUCCESS = 190 AUTOFILL_PRESENTATION_EVENT_REPORTED__AUTHENTICATION_RESULT__AUTHENTICATION_SUCCESS; 191 public static final int AUTHENTICATION_RESULT_FAILURE = 192 AUTOFILL_PRESENTATION_EVENT_REPORTED__AUTHENTICATION_RESULT__AUTHENTICATION_FAILURE; 193 194 public static final int PICK_REASON_UNKNOWN = 195 AUTOFILL_PRESENTATION_EVENT_REPORTED__SELECTED_DATASET_PICKED_REASON__PICK_REASON_UNKNOWN; 196 public static final int PICK_REASON_NO_PCC = 197 AUTOFILL_PRESENTATION_EVENT_REPORTED__SELECTED_DATASET_PICKED_REASON__PICK_REASON_NO_PCC; 198 public static final int PICK_REASON_PROVIDER_DETECTION_ONLY = 199 AUTOFILL_PRESENTATION_EVENT_REPORTED__SELECTED_DATASET_PICKED_REASON__PICK_REASON_PROVIDER_DETECTION_ONLY; 200 public static final int PICK_REASON_PROVIDER_DETECTION_PREFERRED_WITH_PCC = 201 AUTOFILL_PRESENTATION_EVENT_REPORTED__SELECTED_DATASET_PICKED_REASON__PICK_REASON_PROVIDER_DETECTION_PREFERRED_WITH_PCC; 202 public static final int PICK_REASON_PCC_DETECTION_ONLY = 203 AUTOFILL_PRESENTATION_EVENT_REPORTED__SELECTED_DATASET_PICKED_REASON__PICK_REASON_PCC_DETECTION_ONLY; 204 public static final int PICK_REASON_PCC_DETECTION_PREFERRED_WITH_PROVIDER = 205 AUTOFILL_PRESENTATION_EVENT_REPORTED__SELECTED_DATASET_PICKED_REASON__PICK_REASON_PCC_DETECTION_PREFERRED_WITH_PROVIDER; 206 207 208 // Values for AutofillFillResponseReported.detection_preference 209 public static final int DETECTION_PREFER_UNKNOWN = 210 AUTOFILL_FILL_RESPONSE_REPORTED__DETECTION_PREFERENCE__DETECTION_PREFER_UNKONWN; 211 public static final int DETECTION_PREFER_AUTOFILL_PROVIDER = 212 AUTOFILL_FILL_RESPONSE_REPORTED__DETECTION_PREFERENCE__DETECTION_PREFER_AUTOFILL_PROVIDER; 213 public static final int DETECTION_PREFER_PCC = 214 AUTOFILL_FILL_RESPONSE_REPORTED__DETECTION_PREFERENCE__DETECTION_PREFER_PCC; 215 216 private static final int DEFAULT_VALUE_INT = -1; 217 218 private final int mSessionId; 219 /** 220 * For app_package_uid. 221 */ 222 private final int mCallingAppUid; 223 private Optional<PresentationStatsEventInternal> mEventInternal; 224 private final long mSessionStartTimestamp; 225 PresentationStatsEventLogger(int sessionId, int callingAppUid, long timestamp)226 private PresentationStatsEventLogger(int sessionId, int callingAppUid, long timestamp) { 227 mSessionId = sessionId; 228 mCallingAppUid = callingAppUid; 229 mSessionStartTimestamp = timestamp; 230 mEventInternal = Optional.empty(); 231 } 232 233 /** 234 * Create PresentationStatsEventLogger, populated with sessionId and the callingAppUid 235 */ createPresentationLog( int sessionId, int callingAppUid, long timestamp)236 public static PresentationStatsEventLogger createPresentationLog( 237 int sessionId, int callingAppUid, long timestamp) { 238 return new PresentationStatsEventLogger(sessionId, callingAppUid, timestamp); 239 } 240 startNewEvent()241 public void startNewEvent() { 242 if (mEventInternal.isPresent()) { 243 Slog.e(TAG, "Failed to start new event because already have active event."); 244 return; 245 } 246 mEventInternal = Optional.of(new PresentationStatsEventInternal()); 247 } 248 249 /** 250 * Set request_id 251 */ maybeSetRequestId(int requestId)252 public void maybeSetRequestId(int requestId) { 253 mEventInternal.ifPresent(event -> event.mRequestId = requestId); 254 } 255 256 /** 257 * Set is_credential_request 258 */ maybeSetIsCredentialRequest(boolean isCredentialRequest)259 public void maybeSetIsCredentialRequest(boolean isCredentialRequest) { 260 mEventInternal.ifPresent(event -> event.mIsCredentialRequest = isCredentialRequest); 261 } 262 263 /** 264 * Set webview_requested_credential 265 */ maybeSetWebviewRequestedCredential(boolean webviewRequestedCredential)266 public void maybeSetWebviewRequestedCredential(boolean webviewRequestedCredential) { 267 mEventInternal.ifPresent(event -> 268 event.mWebviewRequestedCredential = webviewRequestedCredential); 269 } 270 maybeSetNoPresentationEventReason(@otShownReason int reason)271 public void maybeSetNoPresentationEventReason(@NotShownReason int reason) { 272 mEventInternal.ifPresent(event -> { 273 if (event.mCountShown == 0) { 274 event.mNoPresentationReason = reason; 275 } 276 }); 277 } 278 maybeSetNoPresentationEventReasonIfNoReasonExists(@otShownReason int reason)279 public void maybeSetNoPresentationEventReasonIfNoReasonExists(@NotShownReason int reason) { 280 mEventInternal.ifPresent(event -> { 281 if (event.mCountShown == 0 && event.mNoPresentationReason == NOT_SHOWN_REASON_UNKNOWN) { 282 event.mNoPresentationReason = reason; 283 } 284 }); 285 } 286 maybeSetAvailableCount(@ullable List<Dataset> datasetList, AutofillId currentViewId)287 public void maybeSetAvailableCount(@Nullable List<Dataset> datasetList, 288 AutofillId currentViewId) { 289 mEventInternal.ifPresent(event -> { 290 CountContainer container = getDatasetCountForAutofillId(datasetList, currentViewId); 291 event.mAvailableCount = container.mAvailableCount; 292 event.mAvailablePccCount = container.mAvailablePccCount; 293 event.mAvailablePccOnlyCount = container.mAvailablePccOnlyCount; 294 event.mIsDatasetAvailable = container.mAvailableCount > 0; 295 }); 296 } 297 298 /** 299 * Called for inline suggestions - inflated one at 300 * a time. If InlineSuggestions were filtered, 301 * reset the count be incrementing 302 */ maybeIncrementCountShown()303 public void maybeIncrementCountShown() { 304 mEventInternal.ifPresent(event -> { 305 if (event.shouldResetShownCount) { 306 event.shouldResetShownCount = false; 307 event.mCountShown = 0; 308 } 309 310 if (event.mCountShown == 0) { 311 // The first time suggestions are rendered 312 // set time stamp 313 maybeSetSuggestionPresentedTimestampMs(); 314 } 315 316 event.mCountShown += 1; 317 }); 318 } 319 320 /** 321 * Call this when UI is hidden. This will set a flag to reset count for inline. We do this 322 * instead of resetting right away in case there are 0 inline presentations after. 323 */ markShownCountAsResettable()324 public void markShownCountAsResettable() { 325 mEventInternal.ifPresent(event -> { 326 event.shouldResetShownCount = true; 327 }); 328 } 329 maybeSetCountShown(@ullable List<Dataset> datasetList, AutofillId currentViewId)330 public void maybeSetCountShown(@Nullable List<Dataset> datasetList, 331 AutofillId currentViewId) { 332 mEventInternal.ifPresent(event -> { 333 CountContainer container = getDatasetCountForAutofillId(datasetList, currentViewId); 334 event.mCountShown = container.mAvailableCount; 335 if (container.mAvailableCount > 0) { 336 event.mNoPresentationReason = NOT_SHOWN_REASON_ANY_SHOWN; 337 } 338 }); 339 } 340 maybeSetCountShown(int datasets)341 public void maybeSetCountShown(int datasets) { 342 mEventInternal.ifPresent( 343 event -> { 344 event.mCountShown = datasets; 345 }); 346 } 347 getDatasetCountForAutofillId(@ullable List<Dataset> datasetList, AutofillId currentViewId)348 private static CountContainer getDatasetCountForAutofillId(@Nullable List<Dataset> datasetList, 349 AutofillId currentViewId) { 350 351 CountContainer container = new CountContainer(); 352 if (datasetList != null) { 353 for (int i = 0; i < datasetList.size(); i++) { 354 Dataset data = datasetList.get(i); 355 if (data != null && data.getFieldIds() != null 356 && data.getFieldIds().contains(currentViewId)) { 357 container.mAvailableCount += 1; 358 if (data.getEligibleReason() == PICK_REASON_PCC_DETECTION_ONLY) { 359 container.mAvailablePccOnlyCount++; 360 container.mAvailablePccCount++; 361 } else if (data.getEligibleReason() 362 == PICK_REASON_PCC_DETECTION_PREFERRED_WITH_PROVIDER) { 363 container.mAvailablePccCount++; 364 } 365 } 366 } 367 } 368 return container; 369 } 370 371 private static class CountContainer{ 372 int mAvailableCount = 0; 373 int mAvailablePccCount = 0; 374 int mAvailablePccOnlyCount = 0; 375 CountContainer()376 CountContainer() {} 377 CountContainer(int availableCount, int availablePccCount, int availablePccOnlyCount)378 CountContainer(int availableCount, int availablePccCount, 379 int availablePccOnlyCount) { 380 mAvailableCount = availableCount; 381 mAvailablePccCount = availablePccCount; 382 mAvailablePccOnlyCount = availablePccOnlyCount; 383 } 384 } 385 maybeSetCountFilteredUserTyping(int countFilteredUserTyping)386 public void maybeSetCountFilteredUserTyping(int countFilteredUserTyping) { 387 mEventInternal.ifPresent(event -> { 388 event.mCountFilteredUserTyping = countFilteredUserTyping; 389 }); 390 } 391 maybeSetCountNotShownImePresentationNotDrawn( int countNotShownImePresentationNotDrawn)392 public void maybeSetCountNotShownImePresentationNotDrawn( 393 int countNotShownImePresentationNotDrawn) { 394 mEventInternal.ifPresent(event -> { 395 event.mCountNotShownImePresentationNotDrawn = countNotShownImePresentationNotDrawn; 396 }); 397 } 398 maybeSetCountNotShownImeUserNotSeen(int countNotShownImeUserNotSeen)399 public void maybeSetCountNotShownImeUserNotSeen(int countNotShownImeUserNotSeen) { 400 mEventInternal.ifPresent(event -> { 401 event.mCountNotShownImeUserNotSeen = countNotShownImeUserNotSeen; 402 }); 403 } 404 maybeSetDisplayPresentationType(@iType int uiType)405 public void maybeSetDisplayPresentationType(@UiType int uiType) { 406 mEventInternal.ifPresent(event -> { 407 event.mDisplayPresentationType = getDisplayPresentationType(uiType); 408 }); 409 } 410 maybeSetFillRequestSentTimestampMs(int timestamp)411 public void maybeSetFillRequestSentTimestampMs(int timestamp) { 412 mEventInternal.ifPresent(event -> { 413 event.mFillRequestSentTimestampMs = timestamp; 414 }); 415 } 416 maybeSetFillRequestSentTimestampMs()417 public void maybeSetFillRequestSentTimestampMs() { 418 maybeSetFillRequestSentTimestampMs(getElapsedTime()); 419 } 420 maybeSetFillResponseReceivedTimestampMs(int timestamp)421 public void maybeSetFillResponseReceivedTimestampMs(int timestamp) { 422 mEventInternal.ifPresent(event -> { 423 event.mFillResponseReceivedTimestampMs = timestamp; 424 }); 425 } 426 maybeSetFillResponseReceivedTimestampMs()427 public void maybeSetFillResponseReceivedTimestampMs() { 428 maybeSetFillResponseReceivedTimestampMs(getElapsedTime()); 429 } 430 maybeSetSuggestionSentTimestampMs(int timestamp)431 public void maybeSetSuggestionSentTimestampMs(int timestamp) { 432 mEventInternal.ifPresent(event -> { 433 event.mSuggestionSentTimestampMs = timestamp; 434 }); 435 } 436 maybeSetSuggestionSentTimestampMs()437 public void maybeSetSuggestionSentTimestampMs() { 438 maybeSetSuggestionSentTimestampMs(getElapsedTime()); 439 } 440 maybeSetSuggestionPresentedTimestampMs(int timestamp)441 public void maybeSetSuggestionPresentedTimestampMs(int timestamp) { 442 mEventInternal.ifPresent(event -> { 443 // mSuggestionPresentedTimestampMs only tracks the first suggested timestamp. 444 if (event.mSuggestionPresentedTimestampMs == DEFAULT_VALUE_INT) { 445 event.mSuggestionPresentedTimestampMs = timestamp; 446 } 447 448 event.mSuggestionPresentedLastTimestampMs = timestamp; 449 }); 450 } 451 maybeSetSuggestionPresentedTimestampMs()452 public void maybeSetSuggestionPresentedTimestampMs() { 453 maybeSetSuggestionPresentedTimestampMs(getElapsedTime()); 454 } 455 maybeSetSelectedDatasetId(int selectedDatasetId)456 public void maybeSetSelectedDatasetId(int selectedDatasetId) { 457 mEventInternal.ifPresent(event -> { 458 event.mSelectedDatasetId = selectedDatasetId; 459 }); 460 setPresentationSelectedTimestamp(); 461 } 462 maybeSetDialogDismissed(boolean dialogDismissed)463 public void maybeSetDialogDismissed(boolean dialogDismissed) { 464 mEventInternal.ifPresent(event -> { 465 event.mDialogDismissed = dialogDismissed; 466 }); 467 } 468 maybeSetNegativeCtaButtonClicked(boolean negativeCtaButtonClicked)469 public void maybeSetNegativeCtaButtonClicked(boolean negativeCtaButtonClicked) { 470 mEventInternal.ifPresent(event -> { 471 event.mNegativeCtaButtonClicked = negativeCtaButtonClicked; 472 }); 473 } 474 maybeSetPositiveCtaButtonClicked(boolean positiveCtaButtonClicked)475 public void maybeSetPositiveCtaButtonClicked(boolean positiveCtaButtonClicked) { 476 mEventInternal.ifPresent(event -> { 477 event.mPositiveCtaButtonClicked = positiveCtaButtonClicked; 478 }); 479 } 480 maybeSetInlinePresentationAndSuggestionHostUid(Context context, int userId)481 public void maybeSetInlinePresentationAndSuggestionHostUid(Context context, int userId) { 482 mEventInternal.ifPresent(event -> { 483 event.mDisplayPresentationType = 484 AUTOFILL_PRESENTATION_EVENT_REPORTED__DISPLAY_PRESENTATION_TYPE__INLINE; 485 String imeString = Settings.Secure.getStringForUser(context.getContentResolver(), 486 Settings.Secure.DEFAULT_INPUT_METHOD, userId); 487 if (TextUtils.isEmpty(imeString)) { 488 Slog.w(TAG, "No default IME found"); 489 return; 490 } 491 ComponentName imeComponent = ComponentName.unflattenFromString(imeString); 492 if (imeComponent == null) { 493 Slog.w(TAG, "No default IME found"); 494 return; 495 } 496 int imeUid; 497 String packageName = imeComponent.getPackageName(); 498 try { 499 imeUid = context.getPackageManager().getApplicationInfoAsUser(packageName, 500 PackageManager.ApplicationInfoFlags.of(0), userId).uid; 501 } catch (PackageManager.NameNotFoundException e) { 502 Slog.w(TAG, "Couldn't find packageName: " + packageName); 503 return; 504 } 505 event.mInlineSuggestionHostUid = imeUid; 506 }); 507 } 508 maybeSetAutofillServiceUid(int uid)509 public void maybeSetAutofillServiceUid(int uid) { 510 mEventInternal.ifPresent(event -> { 511 event.mAutofillServiceUid = uid; 512 }); 513 } 514 maybeSetIsNewRequest(boolean isRequestTriggered)515 public void maybeSetIsNewRequest(boolean isRequestTriggered) { 516 mEventInternal.ifPresent(event -> { 517 event.mIsRequestTriggered = isRequestTriggered; 518 }); 519 } 520 521 /** 522 * Set authentication_type as long as mEventInternal presents. 523 */ maybeSetAuthenticationType(@uthenticationType int val)524 public void maybeSetAuthenticationType(@AuthenticationType int val) { 525 mEventInternal.ifPresent(event -> { 526 event.mAuthenticationType = val; 527 }); 528 } 529 530 /** 531 * Set authentication_result as long as mEventInternal presents. 532 */ maybeSetAuthenticationResult(@uthenticationResult int val)533 public void maybeSetAuthenticationResult(@AuthenticationResult int val) { 534 mEventInternal.ifPresent(event -> { 535 event.mAuthenticationResult = val; 536 }); 537 } 538 539 /** 540 * Set latency_authentication_ui_display_millis as long as mEventInternal presents. 541 */ maybeSetLatencyAuthenticationUiDisplayMillis(int val)542 public void maybeSetLatencyAuthenticationUiDisplayMillis(int val) { 543 mEventInternal.ifPresent(event -> { 544 event.mLatencyAuthenticationUiDisplayMillis = val; 545 }); 546 } 547 548 /** Set latency_authentication_ui_display_millis as long as mEventInternal presents. */ maybeSetLatencyAuthenticationUiDisplayMillis()549 public void maybeSetLatencyAuthenticationUiDisplayMillis() { 550 maybeSetLatencyAuthenticationUiDisplayMillis(getElapsedTime()); 551 } 552 553 /** 554 * Set latency_dataset_display_millis as long as mEventInternal presents. 555 */ maybeSetLatencyDatasetDisplayMillis(int val)556 public void maybeSetLatencyDatasetDisplayMillis(int val) { 557 mEventInternal.ifPresent(event -> { 558 event.mLatencyDatasetDisplayMillis = val; 559 }); 560 } 561 562 /** Set latency_dataset_display_millis as long as mEventInternal presents. */ maybeSetLatencyDatasetDisplayMillis()563 public void maybeSetLatencyDatasetDisplayMillis() { 564 maybeSetLatencyDatasetDisplayMillis(getElapsedTime()); 565 } 566 567 /** 568 * Set available_pcc_count. 569 */ maybeSetAvailablePccCount(int val)570 public void maybeSetAvailablePccCount(int val) { 571 mEventInternal.ifPresent(event -> { 572 event.mAvailablePccCount = val; 573 }); 574 } 575 576 /** 577 * Set available_pcc_only_count. 578 */ maybeSetAvailablePccOnlyCount(int val)579 public void maybeSetAvailablePccOnlyCount(int val) { 580 mEventInternal.ifPresent(event -> { 581 event.mAvailablePccOnlyCount = val; 582 }); 583 } 584 585 /** 586 * Set selected_dataset_picked_reason. 587 */ maybeSetSelectedDatasetPickReason(@ataset.DatasetEligibleReason int val)588 public void maybeSetSelectedDatasetPickReason(@Dataset.DatasetEligibleReason int val) { 589 mEventInternal.ifPresent(event -> { 590 event.mSelectedDatasetPickedReason = convertDatasetPickReason(val); 591 }); 592 } 593 594 /** 595 * Set detection_pref 596 */ maybeSetDetectionPreference(@etectionPreference int detectionPreference)597 public void maybeSetDetectionPreference(@DetectionPreference int detectionPreference) { 598 mEventInternal.ifPresent(event -> { 599 event.mDetectionPreference = detectionPreference; 600 }); 601 } 602 603 /** 604 * Set various timestamps whenever the ViewState is modified 605 * 606 * <p>If the ViewState contains ViewState.STATE_AUTOFILLED, sets field_autofilled_timestamp_ms 607 * else, set field_first_modified_timestamp_ms (if unset) and field_last_modified_timestamp_ms 608 */ onFieldTextUpdated(ViewState state, int length)609 public void onFieldTextUpdated(ViewState state, int length) { 610 mEventInternal.ifPresent(event -> { 611 int timestamp = getElapsedTime(); 612 // Focused id should be set before this is called 613 if (state == null || state.id == null || state.id.getViewId() != event.mFocusedId) { 614 // if these don't match, the currently field different than before 615 Slog.w( 616 TAG, 617 "Bad view state for: " + event.mFocusedId); 618 return; 619 } 620 621 // Text changed because filling into form, just log Autofill timestamp 622 if ((state.getState() & ViewState.STATE_AUTOFILLED) != 0) { 623 event.mAutofilledTimestampMs = timestamp; 624 return; 625 } 626 627 // Set length variables 628 if (event.mFieldFirstLength == DEFAULT_VALUE_INT) { 629 event.mFieldFirstLength = length; 630 } 631 event.mFieldLastLength = length; 632 633 // Set timestamp variables 634 if (event.mFieldModifiedFirstTimestampMs == DEFAULT_VALUE_INT) { 635 event.mFieldModifiedFirstTimestampMs = timestamp; 636 } 637 event.mFieldModifiedLastTimestampMs = timestamp; 638 }); 639 } 640 setPresentationSelectedTimestamp()641 public void setPresentationSelectedTimestamp() { 642 mEventInternal.ifPresent(event -> { 643 event.mSelectionTimestamp = getElapsedTime(); 644 }); 645 } 646 647 /** 648 * Returns timestamp (relative to mSessionStartTimestamp) 649 */ getElapsedTime()650 private int getElapsedTime() { 651 return (int)(SystemClock.elapsedRealtime() - mSessionStartTimestamp); 652 } 653 654 convertDatasetPickReason(@ataset.DatasetEligibleReason int val)655 private int convertDatasetPickReason(@Dataset.DatasetEligibleReason int val) { 656 switch (val) { 657 case 0: 658 case 1: 659 case 2: 660 case 3: 661 case 4: 662 case 5: 663 return val; 664 } 665 return PICK_REASON_UNKNOWN; 666 } 667 668 /** 669 * Set field_classification_request_id as long as mEventInternal presents. 670 */ maybeSetFieldClassificationRequestId(int requestId)671 public void maybeSetFieldClassificationRequestId(int requestId) { 672 mEventInternal.ifPresent(event -> { 673 event.mFieldClassificationRequestId = requestId; 674 }); 675 } 676 677 /** 678 * Set views_fillable_total_count as long as mEventInternal presents. 679 */ maybeSetViewFillablesAndCount(List<AutofillId> autofillIds)680 public void maybeSetViewFillablesAndCount(List<AutofillId> autofillIds) { 681 mEventInternal.ifPresent(event -> { 682 event.mAutofillIdsAttemptedAutofill = new ArraySet<>(autofillIds); 683 event.mViewFillableTotalCount = event.mAutofillIdsAttemptedAutofill.size(); 684 }); 685 } 686 687 /** 688 * Set views_filled_failure_count using failure count as long as mEventInternal 689 * presents. 690 */ maybeSetViewFillFailureCounts(int failureCount)691 public void maybeSetViewFillFailureCounts(int failureCount) { 692 mEventInternal.ifPresent(event -> { 693 event.mViewFillFailureCount = failureCount; 694 }); 695 } 696 697 /** Sets focused_autofill_id using view id */ maybeSetFocusedId(AutofillId id)698 public void maybeSetFocusedId(AutofillId id) { 699 mEventInternal.ifPresent( 700 event -> { 701 event.mFocusedId = id.getViewId(); 702 if (id.isVirtualInt()) { 703 event.mFocusedVirtualAutofillId = 704 id.getVirtualChildIntId() % 100; 705 } 706 }); 707 } 708 709 /** 710 * Set views_filled_failure_count using failure count as long as mEventInternal 711 * presents. 712 */ maybeAddSuccessId(AutofillId autofillId)713 public void maybeAddSuccessId(AutofillId autofillId) { 714 mEventInternal.ifPresent(event -> { 715 ArraySet<AutofillId> autofillIds = event.mAutofillIdsAttemptedAutofill; 716 if (autofillIds == null) { 717 Slog.w(TAG, "Attempted autofill ids is null, but received autofillId:" + autofillId 718 + " successfully filled"); 719 event.mViewFilledButUnexpectedCount++; 720 } else if (autofillIds.contains(autofillId)) { 721 if (sVerbose) { 722 Slog.v(TAG, "Logging autofill for id:" + autofillId); 723 } 724 event.mViewFillSuccessCount++; 725 autofillIds.remove(autofillId); 726 event.mAlreadyFilledAutofillIds.add(autofillId); 727 } else if (event.mAlreadyFilledAutofillIds.contains(autofillId)) { 728 if (sVerbose) { 729 Slog.v(TAG, "Successfully filled autofillId:" + autofillId 730 + " already processed "); 731 } 732 } else { 733 Slog.w(TAG, "Successfully filled autofillId:" + autofillId 734 + " not found in list of attempted autofill ids: " + autofillIds); 735 event.mViewFilledButUnexpectedCount++; 736 } 737 }); 738 } 739 logAndEndEvent()740 public void logAndEndEvent() { 741 if (!mEventInternal.isPresent()) { 742 Slog.w(TAG, "Shouldn't be logging AutofillPresentationEventReported again for same " 743 + "event"); 744 return; 745 } 746 PresentationStatsEventInternal event = mEventInternal.get(); 747 if (sVerbose) { 748 Slog.v(TAG, "Log AutofillPresentationEventReported:" 749 + " requestId=" + event.mRequestId 750 + " sessionId=" + mSessionId 751 + " mNoPresentationEventReason=" + event.mNoPresentationReason 752 + " mAvailableCount=" + event.mAvailableCount 753 + " mCountShown=" + event.mCountShown 754 + " mCountFilteredUserTyping=" + event.mCountFilteredUserTyping 755 + " mCountNotShownImePresentationNotDrawn=" 756 + event.mCountNotShownImePresentationNotDrawn 757 + " mCountNotShownImeUserNotSeen=" + event.mCountNotShownImeUserNotSeen 758 + " mDisplayPresentationType=" + event.mDisplayPresentationType 759 + " mAutofillServiceUid=" + event.mAutofillServiceUid 760 + " mInlineSuggestionHostUid=" + event.mInlineSuggestionHostUid 761 + " mIsRequestTriggered=" + event.mIsRequestTriggered 762 + " mFillRequestSentTimestampMs=" + event.mFillRequestSentTimestampMs 763 + " mFillResponseReceivedTimestampMs=" + event.mFillResponseReceivedTimestampMs 764 + " mSuggestionSentTimestampMs=" + event.mSuggestionSentTimestampMs 765 + " mSuggestionPresentedTimestampMs=" + event.mSuggestionPresentedTimestampMs 766 + " mSelectedDatasetId=" + event.mSelectedDatasetId 767 + " mDialogDismissed=" + event.mDialogDismissed 768 + " mNegativeCtaButtonClicked=" + event.mNegativeCtaButtonClicked 769 + " mPositiveCtaButtonClicked=" + event.mPositiveCtaButtonClicked 770 + " mAuthenticationType=" + event.mAuthenticationType 771 + " mAuthenticationResult=" + event.mAuthenticationResult 772 + " mLatencyAuthenticationUiDisplayMillis=" 773 + event.mLatencyAuthenticationUiDisplayMillis 774 + " mLatencyDatasetDisplayMillis=" + event.mLatencyDatasetDisplayMillis 775 + " mAvailablePccCount=" + event.mAvailablePccCount 776 + " mAvailablePccOnlyCount=" + event.mAvailablePccOnlyCount 777 + " mSelectedDatasetPickedReason=" + event.mSelectedDatasetPickedReason 778 + " mDetectionPreference=" + event.mDetectionPreference 779 + " mFieldClassificationRequestId=" + event.mFieldClassificationRequestId 780 + " mAppPackageUid=" + mCallingAppUid 781 + " mIsCredentialRequest=" + event.mIsCredentialRequest 782 + " mWebviewRequestedCredential=" + event.mWebviewRequestedCredential 783 + " mViewFillableTotalCount=" + event.mViewFillableTotalCount 784 + " mViewFillFailureCount=" + event.mViewFillFailureCount 785 + " mFocusedId=" + event.mFocusedId 786 + " mViewFillSuccessCount=" + event.mViewFillSuccessCount 787 + " mViewFilledButUnexpectedCount=" + event.mViewFilledButUnexpectedCount 788 + " event.mSelectionTimestamp=" + event.mSelectionTimestamp 789 + " event.mAutofilledTimestampMs=" + event.mAutofilledTimestampMs 790 + " event.mFieldModifiedFirstTimestampMs=" 791 + event.mFieldModifiedFirstTimestampMs 792 + " event.mFieldModifiedLastTimestampMs=" + event.mFieldModifiedLastTimestampMs 793 + " event.mSuggestionPresentedLastTimestampMs=" 794 + event.mSuggestionPresentedLastTimestampMs 795 + " event.mFocusedVirtualAutofillId=" + event.mFocusedVirtualAutofillId 796 + " event.mFieldFirstLength=" + event.mFieldFirstLength 797 + " event.mFieldLastLength=" + event.mFieldLastLength); 798 } 799 800 // TODO(b/234185326): Distinguish empty responses from other no presentation reasons. 801 if (!event.mIsDatasetAvailable) { 802 mEventInternal = Optional.empty(); 803 return; 804 } 805 FrameworkStatsLog.write( 806 AUTOFILL_PRESENTATION_EVENT_REPORTED, 807 event.mRequestId, 808 mSessionId, 809 event.mNoPresentationReason, 810 event.mAvailableCount, 811 event.mCountShown, 812 event.mCountFilteredUserTyping, 813 event.mCountNotShownImePresentationNotDrawn, 814 event.mCountNotShownImeUserNotSeen, 815 event.mDisplayPresentationType, 816 event.mAutofillServiceUid, 817 event.mInlineSuggestionHostUid, 818 event.mIsRequestTriggered, 819 event.mFillRequestSentTimestampMs, 820 event.mFillResponseReceivedTimestampMs, 821 event.mSuggestionSentTimestampMs, 822 event.mSuggestionPresentedTimestampMs, 823 event.mSelectedDatasetId, 824 event.mDialogDismissed, 825 event.mNegativeCtaButtonClicked, 826 event.mPositiveCtaButtonClicked, 827 event.mAuthenticationType, 828 event.mAuthenticationResult, 829 event.mLatencyAuthenticationUiDisplayMillis, 830 event.mLatencyDatasetDisplayMillis, 831 event.mAvailablePccCount, 832 event.mAvailablePccOnlyCount, 833 event.mSelectedDatasetPickedReason, 834 event.mDetectionPreference, 835 event.mFieldClassificationRequestId, 836 mCallingAppUid, 837 event.mIsCredentialRequest, 838 event.mWebviewRequestedCredential, 839 event.mViewFillableTotalCount, 840 event.mViewFillFailureCount, 841 event.mFocusedId, 842 event.mViewFillSuccessCount, 843 event.mViewFilledButUnexpectedCount, 844 event.mSelectionTimestamp, 845 event.mAutofilledTimestampMs, 846 event.mFieldModifiedFirstTimestampMs, 847 event.mFieldModifiedLastTimestampMs, 848 event.mSuggestionPresentedLastTimestampMs, 849 event.mFocusedVirtualAutofillId, 850 event.mFieldFirstLength, 851 event.mFieldLastLength); 852 mEventInternal = Optional.empty(); 853 } 854 855 private static final class PresentationStatsEventInternal { 856 int mRequestId; 857 @NotShownReason int mNoPresentationReason = NOT_SHOWN_REASON_UNKNOWN; 858 boolean mIsDatasetAvailable; 859 int mAvailableCount; 860 int mCountShown = 0; 861 int mCountFilteredUserTyping; 862 int mCountNotShownImePresentationNotDrawn; 863 int mCountNotShownImeUserNotSeen; 864 int mDisplayPresentationType = AUTOFILL_PRESENTATION_EVENT_REPORTED__DISPLAY_PRESENTATION_TYPE__UNKNOWN_AUTOFILL_DISPLAY_PRESENTATION_TYPE; 865 int mAutofillServiceUid = DEFAULT_VALUE_INT; 866 int mInlineSuggestionHostUid = DEFAULT_VALUE_INT; 867 boolean mIsRequestTriggered; 868 int mFillRequestSentTimestampMs = DEFAULT_VALUE_INT; 869 int mFillResponseReceivedTimestampMs = DEFAULT_VALUE_INT; 870 int mSuggestionSentTimestampMs = DEFAULT_VALUE_INT; 871 int mSuggestionPresentedTimestampMs = DEFAULT_VALUE_INT; 872 int mSelectedDatasetId = DEFAULT_VALUE_INT; 873 boolean mDialogDismissed = false; 874 boolean mNegativeCtaButtonClicked = false; 875 boolean mPositiveCtaButtonClicked = false; 876 int mAuthenticationType = AUTHENTICATION_TYPE_UNKNOWN; 877 int mAuthenticationResult = AUTHENTICATION_RESULT_UNKNOWN; 878 int mLatencyAuthenticationUiDisplayMillis = DEFAULT_VALUE_INT; 879 int mLatencyDatasetDisplayMillis = DEFAULT_VALUE_INT; 880 int mAvailablePccCount = DEFAULT_VALUE_INT; 881 int mAvailablePccOnlyCount = DEFAULT_VALUE_INT; 882 @DatasetPickedReason int mSelectedDatasetPickedReason = PICK_REASON_UNKNOWN; 883 @DetectionPreference int mDetectionPreference = DETECTION_PREFER_UNKNOWN; 884 int mFieldClassificationRequestId = DEFAULT_VALUE_INT; 885 boolean mIsCredentialRequest = false; 886 boolean mWebviewRequestedCredential = false; 887 int mViewFillableTotalCount = DEFAULT_VALUE_INT; 888 int mViewFillFailureCount = DEFAULT_VALUE_INT; 889 int mFocusedId = DEFAULT_VALUE_INT; 890 int mSelectionTimestamp = DEFAULT_VALUE_INT; 891 int mAutofilledTimestampMs = DEFAULT_VALUE_INT; 892 int mFieldModifiedFirstTimestampMs = DEFAULT_VALUE_INT; 893 int mFieldModifiedLastTimestampMs = DEFAULT_VALUE_INT; 894 int mSuggestionPresentedLastTimestampMs = DEFAULT_VALUE_INT; 895 int mFocusedVirtualAutofillId = DEFAULT_VALUE_INT; 896 int mFieldFirstLength = DEFAULT_VALUE_INT; 897 int mFieldLastLength = DEFAULT_VALUE_INT; 898 899 // Default value for success count is set to 0 explicitly. Setting it to -1 for 900 // uninitialized doesn't help much, as this would be non-zero only if callback is received. 901 int mViewFillSuccessCount = 0; 902 int mViewFilledButUnexpectedCount = 0; 903 904 ArraySet<AutofillId> mAutofillIdsAttemptedAutofill; 905 ArraySet<AutofillId> mAlreadyFilledAutofillIds = new ArraySet<>(); 906 907 // Not logged - used for internal logic 908 boolean shouldResetShownCount = false; PresentationStatsEventInternal()909 PresentationStatsEventInternal() {} 910 } 911 getNoPresentationEventReason( @utofillManager.AutofillCommitReason int commitReason)912 static int getNoPresentationEventReason( 913 @AutofillManager.AutofillCommitReason int commitReason) { 914 switch (commitReason) { 915 case COMMIT_REASON_VIEW_COMMITTED: 916 return NOT_SHOWN_REASON_SESSION_COMMITTED_PREMATURELY; 917 case COMMIT_REASON_ACTIVITY_FINISHED: 918 return NOT_SHOWN_REASON_ACTIVITY_FINISHED; 919 case COMMIT_REASON_VIEW_CHANGED: 920 return NOT_SHOWN_REASON_VIEW_CHANGED; 921 case COMMIT_REASON_VIEW_CLICKED: 922 // TODO(b/234185326): Add separate reason for view clicked. 923 default: 924 return NOT_SHOWN_REASON_UNKNOWN; 925 } 926 } 927 getDisplayPresentationType(@iType int uiType)928 private static int getDisplayPresentationType(@UiType int uiType) { 929 switch (uiType) { 930 case UI_TYPE_MENU: 931 return AUTOFILL_PRESENTATION_EVENT_REPORTED__DISPLAY_PRESENTATION_TYPE__MENU; 932 case UI_TYPE_INLINE: 933 return AUTOFILL_PRESENTATION_EVENT_REPORTED__DISPLAY_PRESENTATION_TYPE__INLINE; 934 case UI_TYPE_DIALOG: 935 return AUTOFILL_PRESENTATION_EVENT_REPORTED__DISPLAY_PRESENTATION_TYPE__DIALOG; 936 default: 937 return AUTOFILL_PRESENTATION_EVENT_REPORTED__DISPLAY_PRESENTATION_TYPE__UNKNOWN_AUTOFILL_DISPLAY_PRESENTATION_TYPE; 938 } 939 } 940 } 941