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