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_FIELD_CLASSIFICATION_EVENT_REPORTED; 20 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FIELD_CLASSIFICATION_EVENT_REPORTED__STATUS__STATUS_CANCELLED; 21 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FIELD_CLASSIFICATION_EVENT_REPORTED__STATUS__STATUS_FAIL; 22 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FIELD_CLASSIFICATION_EVENT_REPORTED__STATUS__STATUS_SUCCESS; 23 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FIELD_CLASSIFICATION_EVENT_REPORTED__STATUS__STATUS_UNKNOWN; 24 import static com.android.server.autofill.Helper.sVerbose; 25 26 import android.annotation.IntDef; 27 import android.util.Slog; 28 29 import com.android.internal.util.FrameworkStatsLog; 30 31 import java.lang.annotation.Retention; 32 import java.lang.annotation.RetentionPolicy; 33 import java.util.Optional; 34 35 /** 36 * Helper class to log Field Classification stats. 37 */ 38 public final class FieldClassificationEventLogger { 39 private static final String TAG = "FieldClassificationEventLogger"; 40 private Optional<FieldClassificationEventInternal> mEventInternal; 41 FieldClassificationEventLogger()42 private FieldClassificationEventLogger() { 43 mEventInternal = Optional.empty(); 44 } 45 46 public static final int STATUS_SUCCESS = 47 AUTOFILL_FIELD_CLASSIFICATION_EVENT_REPORTED__STATUS__STATUS_SUCCESS; 48 public static final int STATUS_UNKNOWN = 49 AUTOFILL_FIELD_CLASSIFICATION_EVENT_REPORTED__STATUS__STATUS_UNKNOWN; 50 public static final int STATUS_FAIL = 51 AUTOFILL_FIELD_CLASSIFICATION_EVENT_REPORTED__STATUS__STATUS_FAIL; 52 public static final int STATUS_CANCELLED = 53 AUTOFILL_FIELD_CLASSIFICATION_EVENT_REPORTED__STATUS__STATUS_CANCELLED; 54 55 /** 56 * Status of the FieldClassification IPC request. These are wrappers around 57 * {@link com.android.os.AtomsProto.AutofillFieldClassificationEventReported.FieldClassificationRequestStatus}. 58 */ 59 @IntDef(prefix = {"STATUS"}, value = { 60 STATUS_UNKNOWN, 61 STATUS_SUCCESS, 62 STATUS_FAIL, 63 STATUS_CANCELLED 64 }) 65 @Retention(RetentionPolicy.SOURCE) 66 public @interface FieldClassificationStatus { 67 } 68 69 /** 70 * A factory constructor to create FieldClassificationEventLogger. 71 */ createLogger()72 public static FieldClassificationEventLogger createLogger() { 73 return new FieldClassificationEventLogger(); 74 } 75 76 /** 77 * Reset mEventInternal before logging for a new request. It shall be called for each 78 * FieldClassification request. 79 */ startNewLogForRequest()80 public void startNewLogForRequest() { 81 if (!mEventInternal.isEmpty()) { 82 Slog.w(TAG, "FieldClassificationEventLogger is not empty before starting for a new " 83 + "request"); 84 } 85 mEventInternal = Optional.of(new FieldClassificationEventInternal()); 86 } 87 88 /** 89 * Set latency_millis as long as mEventInternal presents. 90 */ maybeSetLatencyMillis(long timestamp)91 public void maybeSetLatencyMillis(long timestamp) { 92 mEventInternal.ifPresent(event -> { 93 event.mLatencyClassificationRequestMillis = timestamp; 94 }); 95 } 96 97 /** 98 * Set count_classifications as long as mEventInternal presents. 99 */ maybeSetCountClassifications(int countClassifications)100 public void maybeSetCountClassifications(int countClassifications) { 101 mEventInternal.ifPresent(event -> { 102 event.mCountClassifications = countClassifications; 103 }); 104 } 105 106 /** 107 * Set session_id as long as mEventInternal presents. 108 */ maybeSetSessionId(int sessionId)109 public void maybeSetSessionId(int sessionId) { 110 mEventInternal.ifPresent(event -> { 111 event.mSessionId = sessionId; 112 }); 113 } 114 115 /** 116 * Set request_id as long as mEventInternal presents. 117 */ maybeSetRequestId(int requestId)118 public void maybeSetRequestId(int requestId) { 119 mEventInternal.ifPresent(event -> { 120 event.mRequestId = requestId; 121 }); 122 } 123 124 /** 125 * Set next_fill_request_id as long as mEventInternal presents. 126 */ maybeSetNextFillRequestId(int nextFillRequestId)127 public void maybeSetNextFillRequestId(int nextFillRequestId) { 128 mEventInternal.ifPresent(event -> { 129 event.mNextFillRequestId = nextFillRequestId; 130 }); 131 } 132 133 /** 134 * Set app_package_uid as long as mEventInternal presents. 135 */ maybeSetAppPackageUid(int uid)136 public void maybeSetAppPackageUid(int uid) { 137 mEventInternal.ifPresent(event -> { 138 event.mAppPackageUid = uid; 139 }); 140 } 141 142 /** 143 * Set status as long as mEventInternal presents. 144 */ maybeSetRequestStatus(@ieldClassificationStatus int status)145 public void maybeSetRequestStatus(@FieldClassificationStatus int status) { 146 mEventInternal.ifPresent(event -> { 147 event.mStatus = status; 148 }); 149 } 150 151 /** 152 * Set is_session_gc as long as mEventInternal presents. 153 */ maybeSetSessionGc(boolean isSessionGc)154 public void maybeSetSessionGc(boolean isSessionGc) { 155 mEventInternal.ifPresent(event -> { 156 event.mIsSessionGc = isSessionGc; 157 }); 158 } 159 160 /** 161 * Log an AUTOFILL_FIELD_CLASSIFICATION_EVENT_REPORTED event. 162 */ logAndEndEvent()163 public void logAndEndEvent() { 164 if (!mEventInternal.isPresent()) { 165 Slog.w(TAG, "Shouldn't be logging AutofillFieldClassificationEventInternal again for " 166 + "same event"); 167 return; 168 } 169 FieldClassificationEventInternal event = mEventInternal.get(); 170 if (sVerbose) { 171 Slog.v(TAG, "Log AutofillFieldClassificationEventReported:" 172 + " mLatencyClassificationRequestMillis=" 173 + event.mLatencyClassificationRequestMillis 174 + " mCountClassifications=" + event.mCountClassifications 175 + " mSessionId=" + event.mSessionId 176 + " mRequestId=" + event.mRequestId 177 + " mNextFillRequestId=" + event.mNextFillRequestId 178 + " mAppPackageUid=" + event.mAppPackageUid 179 + " mStatus=" + event.mStatus 180 + " mIsSessionGc=" + event.mIsSessionGc); 181 } 182 FrameworkStatsLog.write( 183 AUTOFILL_FIELD_CLASSIFICATION_EVENT_REPORTED, 184 event.mLatencyClassificationRequestMillis, 185 event.mCountClassifications, 186 event.mSessionId, 187 event.mRequestId, 188 event.mNextFillRequestId, 189 event.mAppPackageUid, 190 event.mStatus, 191 event.mIsSessionGc); 192 mEventInternal = Optional.empty(); 193 } 194 195 private static final class FieldClassificationEventInternal { 196 long mLatencyClassificationRequestMillis = -1; 197 int mCountClassifications = -1; 198 int mSessionId = -1; 199 int mRequestId = -1; 200 int mNextFillRequestId = -1; 201 int mAppPackageUid = -1; 202 int mStatus; 203 boolean mIsSessionGc; 204 FieldClassificationEventInternal()205 FieldClassificationEventInternal() { 206 } 207 } 208 } 209