Loading services/autofill/java/com/android/server/autofill/SaveEventLogger.java +36 −9 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_SAVE_EVENT_RE import static com.android.server.autofill.Helper.sVerbose; import android.annotation.IntDef; import android.os.SystemClock; import android.util.Slog; import com.android.internal.util.FrameworkStatsLog; Loading @@ -45,7 +46,7 @@ import java.util.Optional; /** * Helper class to log Autofill Save event stats. */ public final class SaveEventLogger { public class SaveEventLogger { private static final String TAG = "SaveEventLogger"; /** Loading Loading @@ -112,19 +113,21 @@ public final class SaveEventLogger { public static final int NO_SAVE_REASON_WITH_DONT_SAVE_ON_FINISH_FLAG = AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_NOT_SHOWN_REASON__NO_SAVE_REASON_WITH_DONT_SAVE_ON_FINISH_FLAG; public static final long UNINITIATED_TIMESTAMP = Long.MIN_VALUE; private final int mSessionId; private Optional<SaveEventInternal> mEventInternal; private long mSessionStartTimestamp; private SaveEventLogger(int sessionId) { private SaveEventLogger(int sessionId, long sessionStartTimestamp) { mSessionId = sessionId; mEventInternal = Optional.of(new SaveEventInternal()); mSessionStartTimestamp = sessionStartTimestamp; } /** * A factory constructor to create FillRequestEventLogger. */ public static SaveEventLogger forSessionId(int sessionId) { return new SaveEventLogger(sessionId); /** A factory constructor to create FillRequestEventLogger. */ public static SaveEventLogger forSessionId(int sessionId, long sessionStartTimestamp) { return new SaveEventLogger(sessionId, sessionStartTimestamp); } /** Loading Loading @@ -224,6 +227,15 @@ public final class SaveEventLogger { }); } /* Returns timestamp (relative to mSessionStartTimestamp) or UNINITIATED_TIMESTAMP if mSessionStartTimestamp is not set */ private long getCurrentTimestamp() { long timestamp = UNINITIATED_TIMESTAMP; if (mSessionStartTimestamp != UNINITIATED_TIMESTAMP) { timestamp = SystemClock.elapsedRealtime() - mSessionStartTimestamp; } return timestamp; } /** * Set latency_save_ui_display_millis as long as mEventInternal presents. */ Loading @@ -233,6 +245,11 @@ public final class SaveEventLogger { }); } /** Set latency_save_ui_display_millis as long as mEventInternal presents. */ public void maybeSetLatencySaveUiDisplayMillis() { maybeSetLatencySaveUiDisplayMillis(getCurrentTimestamp()); } /** * Set latency_save_request_millis as long as mEventInternal presents. */ Loading @@ -242,6 +259,11 @@ public final class SaveEventLogger { }); } /** Set latency_save_request_millis as long as mEventInternal presents. */ public void maybeSetLatencySaveRequestMillis() { maybeSetLatencySaveRequestMillis(getCurrentTimestamp()); } /** * Set latency_save_finish_millis as long as mEventInternal presents. */ Loading @@ -251,6 +273,11 @@ public final class SaveEventLogger { }); } /** Set latency_save_finish_millis as long as mEventInternal presents. */ public void maybeSetLatencySaveFinishMillis() { maybeSetLatencySaveFinishMillis(getCurrentTimestamp()); } /** * Set is_framework_created_save_info as long as mEventInternal presents. */ Loading services/autofill/java/com/android/server/autofill/Session.java +1 −4 Original line number Diff line number Diff line Loading @@ -1531,7 +1531,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mFillResponseEventLogger = FillResponseEventLogger.forSessionId(sessionId); mSessionCommittedEventLogger = SessionCommittedEventLogger.forSessionId(sessionId); mSessionCommittedEventLogger.maybeSetComponentPackageUid(uid); mSaveEventLogger = SaveEventLogger.forSessionId(sessionId); mSaveEventLogger = SaveEventLogger.forSessionId(sessionId, mLatencyBaseTime); mIsPrimaryCredential = isPrimaryCredential; mIgnoreViewStateResetToEmpty = AutofillFeatureFlags.shouldIgnoreViewStateResetToEmpty(); Loading Loading @@ -3931,13 +3931,10 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState return new SaveResult(/* logSaveShown= */ false, /* removeSession= */ true, Event.NO_SAVE_UI_REASON_NONE); } final long saveUiDisplayStartTimestamp = SystemClock.elapsedRealtime(); getUiForShowing().showSaveUi(serviceLabel, serviceIcon, mService.getServicePackageName(), saveInfo, this, mComponentName, this, mContext, mPendingSaveUi, isUpdate, mCompatMode, response.getShowSaveDialogIcon(), mSaveEventLogger); mSaveEventLogger.maybeSetLatencySaveUiDisplayMillis( SystemClock.elapsedRealtime()- saveUiDisplayStartTimestamp); if (client != null) { try { client.setSaveUiState(id, true); Loading services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java +2 −0 Original line number Diff line number Diff line Loading @@ -413,6 +413,8 @@ public final class AutoFillUI { callback.startIntentSender(intentSender, intent); } }, mUiModeMgr.isNightMode(), isUpdate, compatMode, showServiceIcon); mSaveEventLogger.maybeSetLatencySaveUiDisplayMillis(); }); } Loading services/tests/servicestests/src/com/android/server/autofill/SaveEventLoggerTest.java 0 → 100644 +85 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.autofill; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.mockito.ArgumentCaptor; @RunWith(JUnit4.class) public class SaveEventLoggerTest { @Test public void testTimestampsInitialized() { SaveEventLogger mLogger = spy(SaveEventLogger.forSessionId(1, 1)); mLogger.maybeSetLatencySaveUiDisplayMillis(); mLogger.maybeSetLatencySaveRequestMillis(); mLogger.maybeSetLatencySaveFinishMillis(); ArgumentCaptor<Long> latencySaveUiDisplayMillis = ArgumentCaptor.forClass(Long.class); ArgumentCaptor<Long> latencySaveRequestMillis = ArgumentCaptor.forClass(Long.class); ArgumentCaptor<Long> latencySaveFinishMillis = ArgumentCaptor.forClass(Long.class); verify(mLogger, times(1)) .maybeSetLatencySaveUiDisplayMillis(latencySaveUiDisplayMillis.capture()); verify(mLogger, times(1)) .maybeSetLatencySaveRequestMillis(latencySaveRequestMillis.capture()); verify(mLogger, times(1)) .maybeSetLatencySaveFinishMillis(latencySaveFinishMillis.capture()); assertThat(latencySaveUiDisplayMillis.getValue()) .isNotEqualTo(SaveEventLogger.UNINITIATED_TIMESTAMP); assertThat(latencySaveRequestMillis.getValue()) .isNotEqualTo(SaveEventLogger.UNINITIATED_TIMESTAMP); assertThat(latencySaveFinishMillis.getValue()) .isNotEqualTo(SaveEventLogger.UNINITIATED_TIMESTAMP); } @Test public void testTimestampsNotInitialized() { SaveEventLogger mLogger = spy(SaveEventLogger.forSessionId(1, SaveEventLogger.UNINITIATED_TIMESTAMP)); mLogger.maybeSetLatencySaveUiDisplayMillis(); mLogger.maybeSetLatencySaveRequestMillis(); mLogger.maybeSetLatencySaveFinishMillis(); ArgumentCaptor<Long> latencySaveUiDisplayMillis = ArgumentCaptor.forClass(Long.class); ArgumentCaptor<Long> latencySaveRequestMillis = ArgumentCaptor.forClass(Long.class); ArgumentCaptor<Long> latencySaveFinishMillis = ArgumentCaptor.forClass(Long.class); verify(mLogger, times(1)) .maybeSetLatencySaveUiDisplayMillis(latencySaveUiDisplayMillis.capture()); verify(mLogger, times(1)) .maybeSetLatencySaveRequestMillis(latencySaveRequestMillis.capture()); verify(mLogger, times(1)) .maybeSetLatencySaveFinishMillis(latencySaveFinishMillis.capture()); assertThat(latencySaveUiDisplayMillis.getValue()) .isEqualTo(SaveEventLogger.UNINITIATED_TIMESTAMP); assertThat(latencySaveRequestMillis.getValue()) .isEqualTo(SaveEventLogger.UNINITIATED_TIMESTAMP); assertThat(latencySaveFinishMillis.getValue()) .isEqualTo(SaveEventLogger.UNINITIATED_TIMESTAMP); } } Loading
services/autofill/java/com/android/server/autofill/SaveEventLogger.java +36 −9 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_SAVE_EVENT_RE import static com.android.server.autofill.Helper.sVerbose; import android.annotation.IntDef; import android.os.SystemClock; import android.util.Slog; import com.android.internal.util.FrameworkStatsLog; Loading @@ -45,7 +46,7 @@ import java.util.Optional; /** * Helper class to log Autofill Save event stats. */ public final class SaveEventLogger { public class SaveEventLogger { private static final String TAG = "SaveEventLogger"; /** Loading Loading @@ -112,19 +113,21 @@ public final class SaveEventLogger { public static final int NO_SAVE_REASON_WITH_DONT_SAVE_ON_FINISH_FLAG = AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_NOT_SHOWN_REASON__NO_SAVE_REASON_WITH_DONT_SAVE_ON_FINISH_FLAG; public static final long UNINITIATED_TIMESTAMP = Long.MIN_VALUE; private final int mSessionId; private Optional<SaveEventInternal> mEventInternal; private long mSessionStartTimestamp; private SaveEventLogger(int sessionId) { private SaveEventLogger(int sessionId, long sessionStartTimestamp) { mSessionId = sessionId; mEventInternal = Optional.of(new SaveEventInternal()); mSessionStartTimestamp = sessionStartTimestamp; } /** * A factory constructor to create FillRequestEventLogger. */ public static SaveEventLogger forSessionId(int sessionId) { return new SaveEventLogger(sessionId); /** A factory constructor to create FillRequestEventLogger. */ public static SaveEventLogger forSessionId(int sessionId, long sessionStartTimestamp) { return new SaveEventLogger(sessionId, sessionStartTimestamp); } /** Loading Loading @@ -224,6 +227,15 @@ public final class SaveEventLogger { }); } /* Returns timestamp (relative to mSessionStartTimestamp) or UNINITIATED_TIMESTAMP if mSessionStartTimestamp is not set */ private long getCurrentTimestamp() { long timestamp = UNINITIATED_TIMESTAMP; if (mSessionStartTimestamp != UNINITIATED_TIMESTAMP) { timestamp = SystemClock.elapsedRealtime() - mSessionStartTimestamp; } return timestamp; } /** * Set latency_save_ui_display_millis as long as mEventInternal presents. */ Loading @@ -233,6 +245,11 @@ public final class SaveEventLogger { }); } /** Set latency_save_ui_display_millis as long as mEventInternal presents. */ public void maybeSetLatencySaveUiDisplayMillis() { maybeSetLatencySaveUiDisplayMillis(getCurrentTimestamp()); } /** * Set latency_save_request_millis as long as mEventInternal presents. */ Loading @@ -242,6 +259,11 @@ public final class SaveEventLogger { }); } /** Set latency_save_request_millis as long as mEventInternal presents. */ public void maybeSetLatencySaveRequestMillis() { maybeSetLatencySaveRequestMillis(getCurrentTimestamp()); } /** * Set latency_save_finish_millis as long as mEventInternal presents. */ Loading @@ -251,6 +273,11 @@ public final class SaveEventLogger { }); } /** Set latency_save_finish_millis as long as mEventInternal presents. */ public void maybeSetLatencySaveFinishMillis() { maybeSetLatencySaveFinishMillis(getCurrentTimestamp()); } /** * Set is_framework_created_save_info as long as mEventInternal presents. */ Loading
services/autofill/java/com/android/server/autofill/Session.java +1 −4 Original line number Diff line number Diff line Loading @@ -1531,7 +1531,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mFillResponseEventLogger = FillResponseEventLogger.forSessionId(sessionId); mSessionCommittedEventLogger = SessionCommittedEventLogger.forSessionId(sessionId); mSessionCommittedEventLogger.maybeSetComponentPackageUid(uid); mSaveEventLogger = SaveEventLogger.forSessionId(sessionId); mSaveEventLogger = SaveEventLogger.forSessionId(sessionId, mLatencyBaseTime); mIsPrimaryCredential = isPrimaryCredential; mIgnoreViewStateResetToEmpty = AutofillFeatureFlags.shouldIgnoreViewStateResetToEmpty(); Loading Loading @@ -3931,13 +3931,10 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState return new SaveResult(/* logSaveShown= */ false, /* removeSession= */ true, Event.NO_SAVE_UI_REASON_NONE); } final long saveUiDisplayStartTimestamp = SystemClock.elapsedRealtime(); getUiForShowing().showSaveUi(serviceLabel, serviceIcon, mService.getServicePackageName(), saveInfo, this, mComponentName, this, mContext, mPendingSaveUi, isUpdate, mCompatMode, response.getShowSaveDialogIcon(), mSaveEventLogger); mSaveEventLogger.maybeSetLatencySaveUiDisplayMillis( SystemClock.elapsedRealtime()- saveUiDisplayStartTimestamp); if (client != null) { try { client.setSaveUiState(id, true); Loading
services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java +2 −0 Original line number Diff line number Diff line Loading @@ -413,6 +413,8 @@ public final class AutoFillUI { callback.startIntentSender(intentSender, intent); } }, mUiModeMgr.isNightMode(), isUpdate, compatMode, showServiceIcon); mSaveEventLogger.maybeSetLatencySaveUiDisplayMillis(); }); } Loading
services/tests/servicestests/src/com/android/server/autofill/SaveEventLoggerTest.java 0 → 100644 +85 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.autofill; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.mockito.ArgumentCaptor; @RunWith(JUnit4.class) public class SaveEventLoggerTest { @Test public void testTimestampsInitialized() { SaveEventLogger mLogger = spy(SaveEventLogger.forSessionId(1, 1)); mLogger.maybeSetLatencySaveUiDisplayMillis(); mLogger.maybeSetLatencySaveRequestMillis(); mLogger.maybeSetLatencySaveFinishMillis(); ArgumentCaptor<Long> latencySaveUiDisplayMillis = ArgumentCaptor.forClass(Long.class); ArgumentCaptor<Long> latencySaveRequestMillis = ArgumentCaptor.forClass(Long.class); ArgumentCaptor<Long> latencySaveFinishMillis = ArgumentCaptor.forClass(Long.class); verify(mLogger, times(1)) .maybeSetLatencySaveUiDisplayMillis(latencySaveUiDisplayMillis.capture()); verify(mLogger, times(1)) .maybeSetLatencySaveRequestMillis(latencySaveRequestMillis.capture()); verify(mLogger, times(1)) .maybeSetLatencySaveFinishMillis(latencySaveFinishMillis.capture()); assertThat(latencySaveUiDisplayMillis.getValue()) .isNotEqualTo(SaveEventLogger.UNINITIATED_TIMESTAMP); assertThat(latencySaveRequestMillis.getValue()) .isNotEqualTo(SaveEventLogger.UNINITIATED_TIMESTAMP); assertThat(latencySaveFinishMillis.getValue()) .isNotEqualTo(SaveEventLogger.UNINITIATED_TIMESTAMP); } @Test public void testTimestampsNotInitialized() { SaveEventLogger mLogger = spy(SaveEventLogger.forSessionId(1, SaveEventLogger.UNINITIATED_TIMESTAMP)); mLogger.maybeSetLatencySaveUiDisplayMillis(); mLogger.maybeSetLatencySaveRequestMillis(); mLogger.maybeSetLatencySaveFinishMillis(); ArgumentCaptor<Long> latencySaveUiDisplayMillis = ArgumentCaptor.forClass(Long.class); ArgumentCaptor<Long> latencySaveRequestMillis = ArgumentCaptor.forClass(Long.class); ArgumentCaptor<Long> latencySaveFinishMillis = ArgumentCaptor.forClass(Long.class); verify(mLogger, times(1)) .maybeSetLatencySaveUiDisplayMillis(latencySaveUiDisplayMillis.capture()); verify(mLogger, times(1)) .maybeSetLatencySaveRequestMillis(latencySaveRequestMillis.capture()); verify(mLogger, times(1)) .maybeSetLatencySaveFinishMillis(latencySaveFinishMillis.capture()); assertThat(latencySaveUiDisplayMillis.getValue()) .isEqualTo(SaveEventLogger.UNINITIATED_TIMESTAMP); assertThat(latencySaveRequestMillis.getValue()) .isEqualTo(SaveEventLogger.UNINITIATED_TIMESTAMP); assertThat(latencySaveFinishMillis.getValue()) .isEqualTo(SaveEventLogger.UNINITIATED_TIMESTAMP); } }