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.Dataset.PICK_REASON_PCC_DETECTION_ONLY;
20 import static android.service.autofill.Dataset.PICK_REASON_PCC_DETECTION_PREFERRED_WITH_PROVIDER;
21 
22 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED;
23 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__AUTHENTICATION_RESULT__AUTHENTICATION_FAILURE;
24 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__AUTHENTICATION_RESULT__AUTHENTICATION_RESULT_UNKNOWN;
25 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__AUTHENTICATION_RESULT__AUTHENTICATION_SUCCESS;
26 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__AUTHENTICATION_TYPE__AUTHENTICATION_TYPE_UNKNOWN;
27 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__AUTHENTICATION_TYPE__DATASET_AUTHENTICATION;
28 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__AUTHENTICATION_TYPE__FULL_AUTHENTICATION;
29 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__DETECTION_PREFERENCE__DETECTION_PREFER_AUTOFILL_PROVIDER;
30 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__DETECTION_PREFERENCE__DETECTION_PREFER_PCC;
31 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__DETECTION_PREFERENCE__DETECTION_PREFER_UNKONWN;
32 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__DISPLAY_PRESENTATION_TYPE__DIALOG;
33 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__DISPLAY_PRESENTATION_TYPE__INLINE;
34 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__DISPLAY_PRESENTATION_TYPE__MENU;
35 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__DISPLAY_PRESENTATION_TYPE__UNKNOWN_AUTOFILL_DISPLAY_PRESENTATION_TYPE;
36 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__RESPONSE_STATUS__RESPONSE_STATUS_CANCELLED;
37 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__RESPONSE_STATUS__RESPONSE_STATUS_FAILURE;
38 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__RESPONSE_STATUS__RESPONSE_STATUS_SESSION_DESTROYED;
39 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__RESPONSE_STATUS__RESPONSE_STATUS_TRANSACTION_TOO_LARGE;
40 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__RESPONSE_STATUS__RESPONSE_STATUS_SUCCESS;
41 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__RESPONSE_STATUS__RESPONSE_STATUS_TIMEOUT;
42 import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__RESPONSE_STATUS__RESPONSE_STATUS_UNKNOWN;
43 import static com.android.server.autofill.Helper.sVerbose;
44 
45 import android.annotation.IntDef;
46 import android.annotation.Nullable;
47 import android.os.SystemClock;
48 import android.service.autofill.Dataset;
49 import android.util.Slog;
50 import android.view.autofill.AutofillId;
51 
52 import com.android.internal.util.FrameworkStatsLog;
53 
54 import java.lang.annotation.Retention;
55 import java.lang.annotation.RetentionPolicy;
56 import java.util.List;
57 import java.util.Optional;
58 
59 /**
60  * Helper class to log Autofill FillResponse stats.
61  */
62 public final class FillResponseEventLogger {
63   private static final String TAG = "FillResponseEventLogger";
64 
65   private static final long UNINITIALIZED_TIMESTAMP = -1;
66   private long startResponseProcessingTimestamp = UNINITIALIZED_TIMESTAMP;
67 
68   /**
69    * Reasons why presentation was not shown. These are wrappers around
70    * {@link com.android.os.AtomsProto.AutofillFillRequestReported.RequestTriggerReason}.
71    */
72   @IntDef(prefix = {"DISPLAY_PRESENTATION_TYPE"}, value = {
73       DISPLAY_PRESENTATION_TYPE_UNKNOWN,
74       DISPLAY_PRESENTATION_TYPE_MENU,
75       DISPLAY_PRESENTATION_TYPE_INLINE,
76       DISPLAY_PRESENTATION_TYPE_DIALOG
77   })
78   @Retention(RetentionPolicy.SOURCE)
79   public @interface DisplayPresentationType {
80   }
81 
82   /**
83    * Reasons why presentation was not shown. These are wrappers around
84    * {@link com.android.os.AtomsProto.AutofillFillResponseReported.AuthenticationType}.
85    */
86   @IntDef(prefix = {"AUTHENTICATION_TYPE"}, value = {
87       AUTHENTICATION_TYPE_UNKNOWN,
88       AUTHENTICATION_TYPE_DATASET_AHTHENTICATION,
89       AUTHENTICATION_TYPE_FULL_AHTHENTICATION
90   })
91   @Retention(RetentionPolicy.SOURCE)
92   public @interface AuthenticationType {
93   }
94 
95   /**
96    * Reasons why presentation was not shown. These are wrappers around
97    * {@link com.android.os.AtomsProto.AutofillFillResponseReported.FillResponseStatus}.
98    */
99   @IntDef(prefix = {"RESPONSE_STATUS"}, value = {
100       RESPONSE_STATUS_UNKNOWN,
101       RESPONSE_STATUS_FAILURE,
102       RESPONSE_STATUS_SUCCESS,
103       RESPONSE_STATUS_CANCELLED,
104       RESPONSE_STATUS_TIMEOUT,
105       RESPONSE_STATUS_SESSION_DESTROYED
106   })
107   @Retention(RetentionPolicy.SOURCE)
108   public @interface ResponseStatus {
109   }
110 
111 
112   /**
113    * Reasons why presentation was not shown. These are wrappers around
114    * {@link com.android.os.AtomsProto.AutofillFillResponseReported.AuthenticationResult}.
115    */
116   @IntDef(prefix = {"AUTHENTICATION_RESULT"}, value = {
117       AUTHENTICATION_RESULT_UNKNOWN,
118       AUTHENTICATION_RESULT_SUCCESS,
119       AUTHENTICATION_RESULT_FAILURE
120   })
121   @Retention(RetentionPolicy.SOURCE)
122   public @interface AuthenticationResult {
123   }
124 
125 
126   /**
127    * Reasons why presentation was not shown. These are wrappers around
128    * {@link com.android.os.AtomsProto.AutofillFillResponseReported.DetectionPreference}.
129    */
130   @IntDef(prefix = {"DETECTION_PREFER"}, value = {
131       DETECTION_PREFER_UNKNOWN,
132       DETECTION_PREFER_AUTOFILL_PROVIDER,
133       DETECTION_PREFER_PCC
134   })
135   @Retention(RetentionPolicy.SOURCE)
136   public @interface DetectionPreference {
137   }
138 
139   public static final int DISPLAY_PRESENTATION_TYPE_UNKNOWN =
140       AUTOFILL_FILL_RESPONSE_REPORTED__DISPLAY_PRESENTATION_TYPE__UNKNOWN_AUTOFILL_DISPLAY_PRESENTATION_TYPE;
141   public static final int DISPLAY_PRESENTATION_TYPE_MENU =
142       AUTOFILL_FILL_RESPONSE_REPORTED__DISPLAY_PRESENTATION_TYPE__MENU;
143   public static final int DISPLAY_PRESENTATION_TYPE_INLINE =
144       AUTOFILL_FILL_RESPONSE_REPORTED__DISPLAY_PRESENTATION_TYPE__INLINE;
145   public static final int DISPLAY_PRESENTATION_TYPE_DIALOG =
146       AUTOFILL_FILL_RESPONSE_REPORTED__DISPLAY_PRESENTATION_TYPE__DIALOG;
147   public static final int AUTHENTICATION_TYPE_UNKNOWN =
148       AUTOFILL_FILL_RESPONSE_REPORTED__AUTHENTICATION_TYPE__AUTHENTICATION_TYPE_UNKNOWN;
149   public static final int AUTHENTICATION_TYPE_DATASET_AHTHENTICATION =
150       AUTOFILL_FILL_RESPONSE_REPORTED__AUTHENTICATION_TYPE__DATASET_AUTHENTICATION;
151   public static final int AUTHENTICATION_TYPE_FULL_AHTHENTICATION =
152       AUTOFILL_FILL_RESPONSE_REPORTED__AUTHENTICATION_TYPE__FULL_AUTHENTICATION;
153 
154   public static final int AUTHENTICATION_RESULT_UNKNOWN =
155       AUTOFILL_FILL_RESPONSE_REPORTED__AUTHENTICATION_RESULT__AUTHENTICATION_RESULT_UNKNOWN;
156   public static final int AUTHENTICATION_RESULT_SUCCESS =
157       AUTOFILL_FILL_RESPONSE_REPORTED__AUTHENTICATION_RESULT__AUTHENTICATION_SUCCESS;
158   public static final int AUTHENTICATION_RESULT_FAILURE =
159       AUTOFILL_FILL_RESPONSE_REPORTED__AUTHENTICATION_RESULT__AUTHENTICATION_FAILURE;
160   public static final int RESPONSE_STATUS_TIMEOUT =
161       AUTOFILL_FILL_RESPONSE_REPORTED__RESPONSE_STATUS__RESPONSE_STATUS_TIMEOUT;
162   public static final int RESPONSE_STATUS_CANCELLED =
163       AUTOFILL_FILL_RESPONSE_REPORTED__RESPONSE_STATUS__RESPONSE_STATUS_CANCELLED;
164   public static final int RESPONSE_STATUS_FAILURE =
165       AUTOFILL_FILL_RESPONSE_REPORTED__RESPONSE_STATUS__RESPONSE_STATUS_FAILURE;
166   public static final int RESPONSE_STATUS_TRANSACTION_TOO_LARGE =
167       AUTOFILL_FILL_RESPONSE_REPORTED__RESPONSE_STATUS__RESPONSE_STATUS_TRANSACTION_TOO_LARGE;
168   public static final int RESPONSE_STATUS_SESSION_DESTROYED =
169       AUTOFILL_FILL_RESPONSE_REPORTED__RESPONSE_STATUS__RESPONSE_STATUS_SESSION_DESTROYED;
170   public static final int RESPONSE_STATUS_SUCCESS =
171       AUTOFILL_FILL_RESPONSE_REPORTED__RESPONSE_STATUS__RESPONSE_STATUS_SUCCESS;
172   public static final int RESPONSE_STATUS_UNKNOWN =
173       AUTOFILL_FILL_RESPONSE_REPORTED__RESPONSE_STATUS__RESPONSE_STATUS_UNKNOWN;
174 
175   // Values for AutofillFillResponseReported.detection_preference
176   public static final int DETECTION_PREFER_UNKNOWN =
177           AUTOFILL_FILL_RESPONSE_REPORTED__DETECTION_PREFERENCE__DETECTION_PREFER_UNKONWN;
178   public static final int DETECTION_PREFER_AUTOFILL_PROVIDER =
179           AUTOFILL_FILL_RESPONSE_REPORTED__DETECTION_PREFERENCE__DETECTION_PREFER_AUTOFILL_PROVIDER;
180   public static final int DETECTION_PREFER_PCC =
181           AUTOFILL_FILL_RESPONSE_REPORTED__DETECTION_PREFERENCE__DETECTION_PREFER_PCC;
182 
183 
184   // Log a magic number when FillRequest failed or timeout to differentiate with FillRequest
185   // succeeded.
186   public static final int AVAILABLE_COUNT_WHEN_FILL_REQUEST_FAILED_OR_TIMEOUT = -1;
187 
188   // Log a magic number to indicate that the FillResponse contains a saveTriggerId.
189   public static final int HAVE_SAVE_TRIGGER_ID = 1;
190 
191   private final int mSessionId;
192   private Optional<FillResponseEventInternal> mEventInternal;
193 
FillResponseEventLogger(int sessionId)194   private FillResponseEventLogger(int sessionId) {
195     mSessionId = sessionId;
196     mEventInternal = Optional.empty();
197   }
198 
199   /**
200    * A factory constructor to create FillResponseEventLogger.
201    */
forSessionId(int sessionId)202   public static FillResponseEventLogger forSessionId(int sessionId) {
203     return new FillResponseEventLogger(sessionId);
204   }
205 
206   /**
207    * Reset mEventInternal before logging for a new response. It shall be called
208    * for each FillResponse.
209    */
startLogForNewResponse()210   public void startLogForNewResponse() {
211     if (!mEventInternal.isEmpty()) {
212       Slog.w(TAG, "FillResponseEventLogger is not empty before starting " +
213           "for a new request");
214     }
215     mEventInternal = Optional.of(new FillResponseEventInternal());
216   }
217 
218   /**
219    * Set request_id as long as mEventInternal presents.
220    */
maybeSetRequestId(int val)221   public void maybeSetRequestId(int val) {
222     mEventInternal.ifPresent(event -> event.mRequestId = val);
223   }
224 
225   /**
226    * Set app_package_uid as long as mEventInternal presents.
227    */
maybeSetAppPackageUid(int val)228   public void maybeSetAppPackageUid(int val) {
229     mEventInternal.ifPresent(event -> {
230       event.mAppPackageUid = val;
231     });
232   }
233 
234   /**
235    * Set display_presentation_type as long as mEventInternal presents.
236    */
maybeSetDisplayPresentationType(@isplayPresentationType int val)237   public void maybeSetDisplayPresentationType(@DisplayPresentationType int val) {
238     mEventInternal.ifPresent(event -> {
239       event.mDisplayPresentationType = val;
240     });
241   }
242 
243   /**
244    * Set available_count as long as mEventInternal presents.
245    * For cases of FillRequest failed and timeout, set to -1.
246    */
maybeSetAvailableCount(@ullable List<Dataset> datasetList, AutofillId currentViewId)247   public void maybeSetAvailableCount(@Nullable List<Dataset> datasetList,
248       AutofillId currentViewId) {
249     mEventInternal.ifPresent(event -> {
250       int availableCount = getDatasetCountForAutofillId(datasetList, currentViewId);
251       event.mAvailableCount = availableCount;
252     });
253   }
254 
maybeSetAvailableCount(int val)255   public void maybeSetAvailableCount(int val) {
256     mEventInternal.ifPresent(event -> {
257       event.mAvailableCount = val;
258     });
259   }
260 
maybeSetTotalDatasetsProvided(int val)261   public void maybeSetTotalDatasetsProvided(int val) {
262     mEventInternal.ifPresent(event -> {
263       // Don't reset if it's already populated.
264       // This is just a technical limitation of not having complicated logic.
265       // Autofill Provider may return some datasets which are applicable to data types.
266       // In such a case, we set available count to the number of datasets provided.
267       // However, it's possible that those data types aren't detected by PCC, so in effect, there
268       // are 0 datasets. In the codebase, we treat it as null response, which may call this again
269       // to set 0. But we don't want to overwrite already set value.
270       if (event.mTotalDatasetsProvided == -1) {
271         event.mTotalDatasetsProvided = val;
272       }
273     });
274   }
275 
getDatasetCountForAutofillId(@ullable List<Dataset> datasetList, AutofillId currentViewId)276   private static int getDatasetCountForAutofillId(@Nullable List<Dataset> datasetList,
277       AutofillId currentViewId) {
278     int availableCount = 0;
279     if (datasetList != null) {
280       for (int i = 0; i < datasetList.size(); i++) {
281         Dataset data = datasetList.get(i);
282         if (data != null && data.getFieldIds() != null
283             && data.getFieldIds().contains(currentViewId)) {
284           availableCount += 1;
285         }
286       }
287     }
288     return availableCount;
289   }
290 
291   /**
292    * Set save_ui_trigger_ids as long as mEventInternal presents.
293    */
maybeSetSaveUiTriggerIds(int val)294   public void maybeSetSaveUiTriggerIds(int val) {
295     mEventInternal.ifPresent(event -> {
296       event.mSaveUiTriggerIds = val;
297     });
298   }
299 
300   /**
301    * Set latency_fill_response_received_millis as long as mEventInternal presents.
302    */
maybeSetLatencyFillResponseReceivedMillis(int val)303   public void maybeSetLatencyFillResponseReceivedMillis(int val) {
304     mEventInternal.ifPresent(event -> {
305       event.mLatencyFillResponseReceivedMillis = val;
306     });
307   }
308 
309   /**
310    * Set authentication_type as long as mEventInternal presents.
311    */
maybeSetAuthenticationType(@uthenticationType int val)312   public void maybeSetAuthenticationType(@AuthenticationType int val) {
313     mEventInternal.ifPresent(event -> {
314       event.mAuthenticationType = val;
315     });
316   }
317 
318   /**
319    * Set authentication_result as long as mEventInternal presents.
320    */
maybeSetAuthenticationResult(@uthenticationResult int val)321   public void maybeSetAuthenticationResult(@AuthenticationResult int val) {
322     mEventInternal.ifPresent(event -> {
323       event.mAuthenticationResult = val;
324     });
325   }
326 
327   /**
328    * Set authentication_failure_reason as long as mEventInternal presents.
329    */
maybeSetAuthenticationFailureReason(int val)330   public void maybeSetAuthenticationFailureReason(int val) {
331     mEventInternal.ifPresent(event -> {
332       event.mAuthenticationFailureReason = val;
333     });
334   }
335 
336   /**
337    * Set latency_authentication_ui_display_millis as long as mEventInternal presents.
338    */
maybeSetLatencyAuthenticationUiDisplayMillis(int val)339   public void maybeSetLatencyAuthenticationUiDisplayMillis(int val) {
340     mEventInternal.ifPresent(event -> {
341       event.mLatencyAuthenticationUiDisplayMillis = val;
342     });
343   }
344 
345   /**
346    * Set latency_dataset_display_millis as long as mEventInternal presents.
347    */
maybeSetLatencyDatasetDisplayMillis(int val)348   public void maybeSetLatencyDatasetDisplayMillis(int val) {
349     mEventInternal.ifPresent(event -> {
350       event.mLatencyDatasetDisplayMillis = val;
351     });
352   }
353 
354   /**
355    * Set response_status as long as mEventInternal presents.
356    */
maybeSetResponseStatus(@esponseStatus int val)357   public void maybeSetResponseStatus(@ResponseStatus int val) {
358     mEventInternal.ifPresent(event -> {
359       event.mResponseStatus = val;
360     });
361   }
362 
startResponseProcessingTime()363   public void startResponseProcessingTime() {
364     startResponseProcessingTimestamp = SystemClock.elapsedRealtime();
365   }
366 
367   /**
368    * Set latency_response_processing_millis as long as mEventInternal presents.
369    */
maybeSetLatencyResponseProcessingMillis()370   public void maybeSetLatencyResponseProcessingMillis() {
371     mEventInternal.ifPresent(event -> {
372       if (startResponseProcessingTimestamp == UNINITIALIZED_TIMESTAMP && sVerbose) {
373         Slog.v(TAG, "uninitialized startResponseProcessingTimestamp");
374       }
375       event.mLatencyResponseProcessingMillis
376               = SystemClock.elapsedRealtime() - startResponseProcessingTimestamp;
377     });
378   }
379 
380   /**
381    * Set available_pcc_count.
382    */
maybeSetAvailablePccCount(int val)383   public void maybeSetAvailablePccCount(int val) {
384     mEventInternal.ifPresent(event -> {
385       event.mAvailablePccCount = val;
386     });
387   }
388 
389   /**
390    * Set available_pcc_only_count.
391    */
maybeSetAvailablePccOnlyCount(int val)392   public void maybeSetAvailablePccOnlyCount(int val) {
393     mEventInternal.ifPresent(event -> {
394       event.mAvailablePccOnlyCount = val;
395     });
396   }
397 
398   /**
399    * Set available_pcc_count.
400    */
maybeSetDatasetsCountAfterPotentialPccFiltering(@ullable List<Dataset> datasetList)401   public void maybeSetDatasetsCountAfterPotentialPccFiltering(@Nullable List<Dataset> datasetList) {
402     mEventInternal.ifPresent(event -> {
403       int pccOnlyCount = 0;
404       int pccCount = 0;
405       int totalCount = 0;
406       if (datasetList != null) {
407         totalCount = datasetList.size();
408         for (int i = 0; i < datasetList.size(); i++) {
409           Dataset dataset = datasetList.get(i);
410           if (dataset != null) {
411             if (dataset.getEligibleReason() == PICK_REASON_PCC_DETECTION_ONLY) {
412               pccOnlyCount++;
413               pccCount++;
414             } else if (dataset.getEligibleReason()
415                     == PICK_REASON_PCC_DETECTION_PREFERRED_WITH_PROVIDER) {
416               pccCount++;
417             }
418           }
419         }
420       }
421       event.mAvailablePccOnlyCount = pccOnlyCount;
422       event.mAvailablePccCount = pccCount;
423       event.mAvailableCount = totalCount;
424     });
425   }
426 
427   /**
428    * Set detection_pref
429    */
maybeSetDetectionPreference(@etectionPreference int detectionPreference)430   public void maybeSetDetectionPreference(@DetectionPreference int detectionPreference) {
431     mEventInternal.ifPresent(event -> {
432       event.mDetectionPref = detectionPreference;
433     });
434   }
435 
436   /**
437    * Log an AUTOFILL_FILL_RESPONSE_REPORTED event.
438    */
logAndEndEvent()439   public void logAndEndEvent() {
440     if (!mEventInternal.isPresent()) {
441       Slog.w(TAG, "Shouldn't be logging AutofillFillRequestReported again for same "
442           + "event");
443       return;
444     }
445     FillResponseEventInternal event = mEventInternal.get();
446     if (sVerbose) {
447       Slog.v(TAG, "Log AutofillFillResponseReported:"
448           + " requestId=" + event.mRequestId
449           + " sessionId=" + mSessionId
450           + " mAppPackageUid=" + event.mAppPackageUid
451           + " mDisplayPresentationType=" + event.mDisplayPresentationType
452           + " mAvailableCount=" + event.mAvailableCount
453           + " mSaveUiTriggerIds=" + event.mSaveUiTriggerIds
454           + " mLatencyFillResponseReceivedMillis=" + event.mLatencyFillResponseReceivedMillis
455           + " mAuthenticationType=" + event.mAuthenticationType
456           + " mAuthenticationResult=" + event.mAuthenticationResult
457           + " mAuthenticationFailureReason=" + event.mAuthenticationFailureReason
458           + " mLatencyAuthenticationUiDisplayMillis=" + event.mLatencyAuthenticationUiDisplayMillis
459           + " mLatencyDatasetDisplayMillis=" + event.mLatencyDatasetDisplayMillis
460           + " mResponseStatus=" + event.mResponseStatus
461           + " mLatencyResponseProcessingMillis=" + event.mLatencyResponseProcessingMillis
462           + " mAvailablePccCount=" + event.mAvailablePccCount
463           + " mAvailablePccOnlyCount=" + event.mAvailablePccOnlyCount
464           + " mTotalDatasetsProvided=" + event.mTotalDatasetsProvided
465           + " mDetectionPref=" + event.mDetectionPref);
466     }
467     FrameworkStatsLog.write(
468         AUTOFILL_FILL_RESPONSE_REPORTED,
469         event.mRequestId,
470         mSessionId,
471         event.mAppPackageUid,
472         event.mDisplayPresentationType,
473         event.mAvailableCount,
474         event.mSaveUiTriggerIds,
475         event.mLatencyFillResponseReceivedMillis,
476         event.mAuthenticationType,
477         event.mAuthenticationResult,
478         event.mAuthenticationFailureReason,
479         event.mLatencyAuthenticationUiDisplayMillis,
480         event.mLatencyDatasetDisplayMillis,
481         event.mResponseStatus,
482         event.mLatencyResponseProcessingMillis,
483         event.mAvailablePccCount,
484         event.mAvailablePccOnlyCount,
485         event.mTotalDatasetsProvided,
486         event.mDetectionPref);
487     mEventInternal = Optional.empty();
488   }
489 
490   private static final class FillResponseEventInternal {
491     int mRequestId = -1;
492     int mAppPackageUid = -1;
493     int mDisplayPresentationType = DISPLAY_PRESENTATION_TYPE_UNKNOWN;
494     int mAvailableCount = 0;
495     int mSaveUiTriggerIds = -1;
496     int mLatencyFillResponseReceivedMillis = (int) UNINITIALIZED_TIMESTAMP;
497     int mAuthenticationType = AUTHENTICATION_TYPE_UNKNOWN;
498     int mAuthenticationResult = AUTHENTICATION_RESULT_UNKNOWN;
499     int mAuthenticationFailureReason = -1;
500     int mLatencyAuthenticationUiDisplayMillis = (int) UNINITIALIZED_TIMESTAMP;
501     int mLatencyDatasetDisplayMillis = (int) UNINITIALIZED_TIMESTAMP;
502     int mResponseStatus = RESPONSE_STATUS_UNKNOWN;
503     long mLatencyResponseProcessingMillis = UNINITIALIZED_TIMESTAMP;
504     int mAvailablePccCount = -1;
505     int mAvailablePccOnlyCount = -1;
506     int mTotalDatasetsProvided = -1;
507     @DetectionPreference
508     int mDetectionPref = DETECTION_PREFER_UNKNOWN;
509 
FillResponseEventInternal()510     FillResponseEventInternal() {
511     }
512   }
513 }
514