1 /* 2 * Copyright (C) 2023 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 com.android.internal.util.FrameworkStatsLog.AUTOFILL_SAVE_EVENT_REPORTED; 20 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_NOT_SHOWN_REASON__NO_SAVE_REASON_DATASET_MATCH; 21 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_NOT_SHOWN_REASON__NO_SAVE_REASON_FIELD_VALIDATION_FAILED; 22 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_NOT_SHOWN_REASON__NO_SAVE_REASON_HAS_EMPTY_REQUIRED; 23 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_NOT_SHOWN_REASON__NO_SAVE_REASON_NONE; 24 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_NOT_SHOWN_REASON__NO_SAVE_REASON_NO_SAVE_INFO; 25 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_NOT_SHOWN_REASON__NO_SAVE_REASON_NO_VALUE_CHANGED; 26 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_NOT_SHOWN_REASON__NO_SAVE_REASON_SCREEN_HAS_CREDMAN_FIELD; 27 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_NOT_SHOWN_REASON__NO_SAVE_REASON_SESSION_DESTROYED; 28 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_NOT_SHOWN_REASON__NO_SAVE_REASON_UNKNOWN; 29 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_NOT_SHOWN_REASON__NO_SAVE_REASON_WITH_DELAY_SAVE_FLAG; 30 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_NOT_SHOWN_REASON__NO_SAVE_REASON_WITH_DONT_SAVE_ON_FINISH_FLAG; 31 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_SHOWN_REASON__SAVE_UI_SHOWN_REASON_OPTIONAL_ID_CHANGE; 32 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_SHOWN_REASON__SAVE_UI_SHOWN_REASON_REQUIRED_ID_CHANGE; 33 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_SHOWN_REASON__SAVE_UI_SHOWN_REASON_TRIGGER_ID_SET; 34 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_SHOWN_REASON__SAVE_UI_SHOWN_REASON_UNKNOWN; 35 import static com.android.server.autofill.Helper.sVerbose; 36 37 import android.annotation.IntDef; 38 import android.os.SystemClock; 39 import android.util.Slog; 40 41 import com.android.internal.util.FrameworkStatsLog; 42 43 import java.lang.annotation.Retention; 44 import java.lang.annotation.RetentionPolicy; 45 import java.util.Optional; 46 47 /** 48 * Helper class to log Autofill Save event stats. 49 */ 50 public class SaveEventLogger { 51 private static final String TAG = "SaveEventLogger"; 52 53 /** 54 * Reasons why presentation was not shown. These are wrappers around 55 * {@link com.android.os.AtomsProto.AutofillSaveEventReported.SaveUiShownReason}. 56 */ 57 @IntDef(prefix = {"SAVE_UI_SHOWN_REASON"}, value = { 58 SAVE_UI_SHOWN_REASON_UNKNOWN, 59 SAVE_UI_SHOWN_REASON_REQUIRED_ID_CHANGE, 60 SAVE_UI_SHOWN_REASON_OPTIONAL_ID_CHANGE, 61 SAVE_UI_SHOWN_REASON_TRIGGER_ID_SET 62 }) 63 @Retention(RetentionPolicy.SOURCE) 64 public @interface SaveUiShownReason { 65 } 66 67 /** 68 * Reasons why presentation was not shown. These are wrappers around 69 * {@link com.android.os.AtomsProto.AutofillSaveEventReported.SaveUiNotShownReason}. 70 */ 71 @IntDef(prefix = {"SAVE_UI_NOT_SHOWN_REASON"}, value = { 72 NO_SAVE_REASON_UNKNOWN, 73 NO_SAVE_REASON_NONE, 74 NO_SAVE_REASON_NO_SAVE_INFO, 75 NO_SAVE_REASON_WITH_DELAY_SAVE_FLAG, 76 NO_SAVE_REASON_WITH_DONT_SAVE_ON_FINISH_FLAG, 77 NO_SAVE_REASON_HAS_EMPTY_REQUIRED, 78 NO_SAVE_REASON_NO_VALUE_CHANGED, 79 NO_SAVE_REASON_FIELD_VALIDATION_FAILED, 80 NO_SAVE_REASON_DATASET_MATCH, 81 NO_SAVE_REASON_SESSION_DESTROYED 82 }) 83 @Retention(RetentionPolicy.SOURCE) 84 public @interface SaveUiNotShownReason { 85 } 86 87 public static final int SAVE_UI_SHOWN_REASON_UNKNOWN = 88 AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_SHOWN_REASON__SAVE_UI_SHOWN_REASON_UNKNOWN; 89 public static final int SAVE_UI_SHOWN_REASON_REQUIRED_ID_CHANGE = 90 AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_SHOWN_REASON__SAVE_UI_SHOWN_REASON_REQUIRED_ID_CHANGE; 91 public static final int SAVE_UI_SHOWN_REASON_OPTIONAL_ID_CHANGE = 92 AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_SHOWN_REASON__SAVE_UI_SHOWN_REASON_OPTIONAL_ID_CHANGE; 93 public static final int SAVE_UI_SHOWN_REASON_TRIGGER_ID_SET = 94 AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_SHOWN_REASON__SAVE_UI_SHOWN_REASON_TRIGGER_ID_SET; 95 96 public static final int NO_SAVE_REASON_UNKNOWN = 97 AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_NOT_SHOWN_REASON__NO_SAVE_REASON_UNKNOWN; 98 public static final int NO_SAVE_REASON_NONE = 99 AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_NOT_SHOWN_REASON__NO_SAVE_REASON_NONE; 100 public static final int NO_SAVE_REASON_NO_SAVE_INFO = 101 AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_NOT_SHOWN_REASON__NO_SAVE_REASON_NO_SAVE_INFO; 102 public static final int NO_SAVE_REASON_WITH_DELAY_SAVE_FLAG = 103 AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_NOT_SHOWN_REASON__NO_SAVE_REASON_WITH_DELAY_SAVE_FLAG; 104 public static final int NO_SAVE_REASON_HAS_EMPTY_REQUIRED = 105 AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_NOT_SHOWN_REASON__NO_SAVE_REASON_HAS_EMPTY_REQUIRED; 106 public static final int NO_SAVE_REASON_NO_VALUE_CHANGED = 107 AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_NOT_SHOWN_REASON__NO_SAVE_REASON_NO_VALUE_CHANGED; 108 public static final int NO_SAVE_REASON_FIELD_VALIDATION_FAILED = 109 AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_NOT_SHOWN_REASON__NO_SAVE_REASON_FIELD_VALIDATION_FAILED; 110 public static final int NO_SAVE_REASON_DATASET_MATCH = 111 AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_NOT_SHOWN_REASON__NO_SAVE_REASON_DATASET_MATCH; 112 public static final int NO_SAVE_REASON_SESSION_DESTROYED = 113 AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_NOT_SHOWN_REASON__NO_SAVE_REASON_SESSION_DESTROYED; 114 public static final int NO_SAVE_REASON_WITH_DONT_SAVE_ON_FINISH_FLAG = 115 AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_NOT_SHOWN_REASON__NO_SAVE_REASON_WITH_DONT_SAVE_ON_FINISH_FLAG; 116 public static final int NO_SAVE_REASON_SCREEN_HAS_CREDMAN_FIELD = 117 AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_NOT_SHOWN_REASON__NO_SAVE_REASON_SCREEN_HAS_CREDMAN_FIELD; 118 119 public static final long UNINITIATED_TIMESTAMP = Long.MIN_VALUE; 120 121 private final int mSessionId; 122 private Optional<SaveEventInternal> mEventInternal; 123 private final long mSessionStartTimestamp; 124 SaveEventLogger(int sessionId, long sessionStartTimestamp)125 private SaveEventLogger(int sessionId, long sessionStartTimestamp) { 126 mSessionId = sessionId; 127 mEventInternal = Optional.of(new SaveEventInternal()); 128 mSessionStartTimestamp = sessionStartTimestamp; 129 } 130 131 /** A factory constructor to create FillRequestEventLogger. */ forSessionId(int sessionId, long sessionStartTimestamp)132 public static SaveEventLogger forSessionId(int sessionId, long sessionStartTimestamp) { 133 return new SaveEventLogger(sessionId, sessionStartTimestamp); 134 } 135 136 /** 137 * Set request_id as long as mEventInternal presents. 138 */ maybeSetRequestId(int requestId)139 public void maybeSetRequestId(int requestId) { 140 mEventInternal.ifPresent(event -> event.mRequestId = requestId); 141 } 142 143 /** 144 * Set app_package_uid as long as mEventInternal presents. 145 */ maybeSetAppPackageUid(int val)146 public void maybeSetAppPackageUid(int val) { 147 mEventInternal.ifPresent(event -> { 148 event.mAppPackageUid = val; 149 }); 150 } 151 152 /** 153 * Set save_ui_trigger_ids as long as mEventInternal presents. 154 */ maybeSetSaveUiTriggerIds(int val)155 public void maybeSetSaveUiTriggerIds(int val) { 156 mEventInternal.ifPresent(event -> { 157 event.mSaveUiTriggerIds = val; 158 }); 159 } 160 161 /** 162 * Set flag as long as mEventInternal presents. 163 */ maybeSetFlag(int val)164 public void maybeSetFlag(int val) { 165 mEventInternal.ifPresent(event -> { 166 event.mFlag = val; 167 }); 168 } 169 170 /** 171 * Set is_new_field as long as mEventInternal presents. 172 */ maybeSetIsNewField(boolean val)173 public void maybeSetIsNewField(boolean val) { 174 mEventInternal.ifPresent(event -> { 175 event.mIsNewField = val; 176 }); 177 } 178 179 /** 180 * Set save_ui_shown_reason as long as mEventInternal presents. 181 */ maybeSetSaveUiShownReason(@aveUiShownReason int reason)182 public void maybeSetSaveUiShownReason(@SaveUiShownReason int reason) { 183 mEventInternal.ifPresent(event -> { 184 event.mSaveUiShownReason = reason; 185 }); 186 } 187 188 /** 189 * Set save_ui_not_shown_reason as long as mEventInternal presents. 190 */ maybeSetSaveUiNotShownReason(@aveUiNotShownReason int reason)191 public void maybeSetSaveUiNotShownReason(@SaveUiNotShownReason int reason) { 192 mEventInternal.ifPresent(event -> { 193 event.mSaveUiNotShownReason = reason; 194 }); 195 } 196 197 /** 198 * Set save_button_clicked as long as mEventInternal presents. 199 */ maybeSetSaveButtonClicked(boolean val)200 public void maybeSetSaveButtonClicked(boolean val) { 201 mEventInternal.ifPresent(event -> { 202 event.mSaveButtonClicked = val; 203 }); 204 } 205 206 /** 207 * Set cancel_button_clicked as long as mEventInternal presents. 208 */ maybeSetCancelButtonClicked(boolean val)209 public void maybeSetCancelButtonClicked(boolean val) { 210 mEventInternal.ifPresent(event -> { 211 event.mCancelButtonClicked = val; 212 }); 213 } 214 215 /** 216 * Set dialog_dismissed as long as mEventInternal presents. 217 */ maybeSetDialogDismissed(boolean val)218 public void maybeSetDialogDismissed(boolean val) { 219 mEventInternal.ifPresent(event -> { 220 event.mDialogDismissed = val; 221 }); 222 } 223 224 /** 225 * Set is_saved as long as mEventInternal presents. 226 */ maybeSetIsSaved(boolean val)227 public void maybeSetIsSaved(boolean val) { 228 mEventInternal.ifPresent(event -> { 229 event.mIsSaved = val; 230 }); 231 } 232 233 /** 234 * Returns timestamp (relative to mSessionStartTimestamp) 235 */ getElapsedTime()236 private long getElapsedTime() { 237 return SystemClock.elapsedRealtime() - mSessionStartTimestamp; 238 } 239 240 /** 241 * Set latency_save_ui_display_millis as long as mEventInternal presents. 242 */ maybeSetLatencySaveUiDisplayMillis(long timestamp)243 public void maybeSetLatencySaveUiDisplayMillis(long timestamp) { 244 mEventInternal.ifPresent(event -> { 245 event.mLatencySaveUiDisplayMillis = timestamp; 246 }); 247 } 248 249 /** Set latency_save_ui_display_millis as long as mEventInternal presents. */ maybeSetLatencySaveUiDisplayMillis()250 public void maybeSetLatencySaveUiDisplayMillis() { 251 maybeSetLatencySaveUiDisplayMillis(getElapsedTime()); 252 } 253 254 /** 255 * Set latency_save_request_millis as long as mEventInternal presents. 256 */ maybeSetLatencySaveRequestMillis(long timestamp)257 public void maybeSetLatencySaveRequestMillis(long timestamp) { 258 mEventInternal.ifPresent(event -> { 259 event.mLatencySaveRequestMillis = timestamp; 260 }); 261 } 262 263 /** Set latency_save_request_millis as long as mEventInternal presents. */ maybeSetLatencySaveRequestMillis()264 public void maybeSetLatencySaveRequestMillis() { 265 maybeSetLatencySaveRequestMillis(getElapsedTime()); 266 } 267 268 /** 269 * Set latency_save_finish_millis as long as mEventInternal presents. 270 */ maybeSetLatencySaveFinishMillis(long timestamp)271 public void maybeSetLatencySaveFinishMillis(long timestamp) { 272 mEventInternal.ifPresent(event -> { 273 event.mLatencySaveFinishMillis = timestamp; 274 }); 275 } 276 277 /** Set latency_save_finish_millis as long as mEventInternal presents. */ maybeSetLatencySaveFinishMillis()278 public void maybeSetLatencySaveFinishMillis() { 279 maybeSetLatencySaveFinishMillis(getElapsedTime()); 280 } 281 282 /** 283 * Set is_framework_created_save_info as long as mEventInternal presents. 284 */ maybeSetIsFrameworkCreatedSaveInfo(boolean val)285 public void maybeSetIsFrameworkCreatedSaveInfo(boolean val) { 286 mEventInternal.ifPresent(event -> { 287 event.mIsFrameworkCreatedSaveInfo = val; 288 }); 289 } 290 291 /** 292 * Set autofill_service_uid as long as mEventInternal presents. 293 */ maybeSetAutofillServiceUid(int uid)294 public void maybeSetAutofillServiceUid(int uid) { 295 mEventInternal.ifPresent( 296 event -> { 297 event.mServiceUid = uid; 298 }); 299 } 300 301 /** 302 * Log an AUTOFILL_SAVE_EVENT_REPORTED event. 303 */ logAndEndEvent()304 public void logAndEndEvent() { 305 if (!mEventInternal.isPresent()) { 306 Slog.w(TAG, "Shouldn't be logging AutofillSaveEventReported again for same " 307 + "event"); 308 return; 309 } 310 SaveEventInternal event = mEventInternal.get(); 311 if (sVerbose) { 312 Slog.v(TAG, "Log AutofillSaveEventReported:" 313 + " requestId=" + event.mRequestId 314 + " sessionId=" + mSessionId 315 + " mAppPackageUid=" + event.mAppPackageUid 316 + " mSaveUiTriggerIds=" + event.mSaveUiTriggerIds 317 + " mFlag=" + event.mFlag 318 + " mIsNewField=" + event.mIsNewField 319 + " mSaveUiShownReason=" + event.mSaveUiShownReason 320 + " mSaveUiNotShownReason=" + event.mSaveUiNotShownReason 321 + " mSaveButtonClicked=" + event.mSaveButtonClicked 322 + " mCancelButtonClicked=" + event.mCancelButtonClicked 323 + " mDialogDismissed=" + event.mDialogDismissed 324 + " mIsSaved=" + event.mIsSaved 325 + " mLatencySaveUiDisplayMillis=" + event.mLatencySaveUiDisplayMillis 326 + " mLatencySaveRequestMillis=" + event.mLatencySaveRequestMillis 327 + " mLatencySaveFinishMillis=" + event.mLatencySaveFinishMillis 328 + " mIsFrameworkCreatedSaveInfo=" + event.mIsFrameworkCreatedSaveInfo 329 + " mServiceUid=" + event.mServiceUid); 330 } 331 FrameworkStatsLog.write( 332 AUTOFILL_SAVE_EVENT_REPORTED, 333 event.mRequestId, 334 mSessionId, 335 event.mAppPackageUid, 336 event.mSaveUiTriggerIds, 337 event.mFlag, 338 event.mIsNewField, 339 event.mSaveUiShownReason, 340 event.mSaveUiNotShownReason, 341 event.mSaveButtonClicked, 342 event.mCancelButtonClicked, 343 event.mDialogDismissed, 344 event.mIsSaved, 345 event.mLatencySaveUiDisplayMillis, 346 event.mLatencySaveRequestMillis, 347 event.mLatencySaveFinishMillis, 348 event.mIsFrameworkCreatedSaveInfo, 349 event.mServiceUid); 350 mEventInternal = Optional.empty(); 351 } 352 353 private static final class SaveEventInternal { 354 int mRequestId; 355 int mAppPackageUid = -1; 356 int mSaveUiTriggerIds = -1; 357 long mFlag = -1; 358 boolean mIsNewField = false; 359 int mSaveUiShownReason = SAVE_UI_SHOWN_REASON_UNKNOWN; 360 int mSaveUiNotShownReason = NO_SAVE_REASON_UNKNOWN; 361 boolean mSaveButtonClicked = false; 362 boolean mCancelButtonClicked = false; 363 boolean mDialogDismissed = false; 364 boolean mIsSaved = false; 365 long mLatencySaveUiDisplayMillis = UNINITIATED_TIMESTAMP; 366 long mLatencySaveRequestMillis = UNINITIATED_TIMESTAMP; 367 long mLatencySaveFinishMillis = UNINITIATED_TIMESTAMP; 368 boolean mIsFrameworkCreatedSaveInfo = false; 369 int mServiceUid = -1; SaveEventInternal()370 SaveEventInternal() { 371 } 372 } 373 } 374