Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit acb5bad3 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Autofill Fix Presentation Log Issues" into main

parents 21b4cfef 5f033a51
Loading
Loading
Loading
Loading
+76 −35
Original line number Diff line number Diff line
@@ -71,6 +71,7 @@ import android.util.ArraySet;
import android.util.Slog;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillManager;
import android.view.autofill.AutofillValue;

import com.android.internal.util.FrameworkStatsLog;

@@ -244,9 +245,17 @@ public final class PresentationStatsEventLogger {
            Slog.e(TAG, "Failed to start new event because already have active event.");
            return;
        }
        Slog.d(TAG, "Started new PresentationStatsEvent");
        mEventInternal = Optional.of(new PresentationStatsEventInternal());
    }

    /**
     * Test use only, returns a copy of the events object
     */
    Optional<PresentationStatsEventInternal> getInternalEvent() {
        return mEventInternal;
    }

    /**
     * Set request_id
     */
@@ -339,10 +348,16 @@ public final class PresentationStatsEventLogger {
        });
    }

    public void maybeSetCountShown(int datasets) {
    /**
     * This is called when a dataset is shown to the user. Will set the count shown,
     * related timestamps and presentation reason.
     */
    public void logWhenDatasetShown(int datasets) {
        mEventInternal.ifPresent(
                event -> {
                    maybeSetSuggestionPresentedTimestampMs();
                    event.mCountShown = datasets;
                    event.mNoPresentationReason = NOT_SHOWN_REASON_ANY_SHOWN;
                });
    }

@@ -405,7 +420,12 @@ public final class PresentationStatsEventLogger {

    public void maybeSetDisplayPresentationType(@UiType int uiType) {
        mEventInternal.ifPresent(event -> {
            // There are cases in which another UI type will show up after selects a dataset
            // such as with Inline after Fill Dialog. Set as the first presentation type only.
            if (event.mDisplayPresentationType
                    == AUTOFILL_PRESENTATION_EVENT_REPORTED__DISPLAY_PRESENTATION_TYPE__UNKNOWN_AUTOFILL_DISPLAY_PRESENTATION_TYPE) {
                event.mDisplayPresentationType = getDisplayPresentationType(uiType);
            }
        });
    }

@@ -430,8 +450,11 @@ public final class PresentationStatsEventLogger {
    }

    public void maybeSetSuggestionSentTimestampMs(int timestamp) {
        mEventInternal.ifPresent(event -> {
        mEventInternal.ifPresent(
                event -> {
                    if (event.mSuggestionSentTimestampMs == DEFAULT_VALUE_INT) {
                        event.mSuggestionSentTimestampMs = timestamp;
                    }
                });
    }

@@ -481,8 +504,6 @@ public final class PresentationStatsEventLogger {

    public void maybeSetInlinePresentationAndSuggestionHostUid(Context context, int userId) {
        mEventInternal.ifPresent(event -> {
            event.mDisplayPresentationType =
                    AUTOFILL_PRESENTATION_EVENT_REPORTED__DISPLAY_PRESENTATION_TYPE__INLINE;
            String imeString = Settings.Secure.getStringForUser(context.getContentResolver(),
                    Settings.Secure.DEFAULT_INPUT_METHOD, userId);
            if (TextUtils.isEmpty(imeString)) {
@@ -601,13 +622,32 @@ public final class PresentationStatsEventLogger {
        });
    }

    /**
     * Sets the field length whenever the text changes. Will keep track of the first
     * and last modification lengths.
     */
    public void updateTextFieldLength(AutofillValue value) {
        mEventInternal.ifPresent(event -> {
            if (value == null || !value.isText()) {
                return;
            }

            int length = value.getTextValue().length();

            if (event.mFieldFirstLength == DEFAULT_VALUE_INT) {
                event.mFieldFirstLength = length;
            }
            event.mFieldLastLength = length;
        });
    }

    /**
     * Set various timestamps whenever the ViewState is modified
     *
     * <p>If the ViewState contains ViewState.STATE_AUTOFILLED, sets field_autofilled_timestamp_ms
     * else, set field_first_modified_timestamp_ms (if unset) and field_last_modified_timestamp_ms
     */
    public void onFieldTextUpdated(ViewState state, int length) {
    public void onFieldTextUpdated(ViewState state, AutofillValue value) {
        mEventInternal.ifPresent(event -> {
            int timestamp = getElapsedTime();
            // Focused id should be set before this is called
@@ -615,21 +655,18 @@ public final class PresentationStatsEventLogger {
                // if these don't match, the currently field different than before
                Slog.w(
                        TAG,
                                "Bad view state for: " + event.mFocusedId);
                        "Bad view state for: " + event.mFocusedId + ", state: " + state);
                return;
            }

            updateTextFieldLength(value);

            // Text changed because filling into form, just log Autofill timestamp
            if ((state.getState() & ViewState.STATE_AUTOFILLED) != 0) {
                event.mAutofilledTimestampMs = timestamp;
                return;
            }

                    // Set length variables
                    if (event.mFieldFirstLength == DEFAULT_VALUE_INT) {
                        event.mFieldFirstLength = length;
                    }
                    event.mFieldLastLength = length;

            // Set timestamp variables
            if (event.mFieldModifiedFirstTimestampMs == DEFAULT_VALUE_INT) {
@@ -796,7 +833,10 @@ public final class PresentationStatsEventLogger {
        });
    }

    public void logAndEndEvent() {
    /**
     * Finish and log the event.
     */
    public void logAndEndEvent(String caller) {
        if (!mEventInternal.isPresent()) {
            Slog.w(TAG, "Shouldn't be logging AutofillPresentationEventReported again for same "
                    + "event");
@@ -804,7 +844,8 @@ public final class PresentationStatsEventLogger {
        }
        PresentationStatsEventInternal event = mEventInternal.get();
        if (sVerbose) {
            Slog.v(TAG, "Log AutofillPresentationEventReported:"
            Slog.v(TAG, "(" + caller + ") "
                    + "Log AutofillPresentationEventReported:"
                    + " requestId=" + event.mRequestId
                    + " sessionId=" + mSessionId
                    + " mNoPresentationEventReason=" + event.mNoPresentationReason
@@ -926,7 +967,7 @@ public final class PresentationStatsEventLogger {
        mEventInternal = Optional.empty();
    }

    private static final class PresentationStatsEventInternal {
    static final class PresentationStatsEventInternal {
        int mRequestId;
        @NotShownReason int mNoPresentationReason = NOT_SHOWN_REASON_UNKNOWN;
        boolean mIsDatasetAvailable;
+86 −82

File changed.

Preview size limit exceeded, changes collapsed.

+2 −2
Original line number Diff line number Diff line
@@ -461,9 +461,9 @@ public final class AutoFillUI {
                        }

                        @Override
                        public void onShown() {
                        public void onShown(int datasetsShown) {
                            if (mCallback != null) {
                                mCallback.onShown(UI_TYPE_DIALOG, response.getDatasets().size());
                                mCallback.onShown(UI_TYPE_DIALOG, datasetsShown);
                            }
                        }

+3 −2
Original line number Diff line number Diff line
@@ -85,7 +85,7 @@ final class DialogFillUi {
        void onDatasetPicked(@NonNull Dataset dataset);
        void onDismissed();
        void onCanceled();
        void onShown();
        void onShown(int datasetsShown);
        void startIntentSender(IntentSender intentSender);
    }

@@ -155,7 +155,8 @@ final class DialogFillUi {
        mDialog.setContentView(decor);
        setDialogParamsAsBottomSheet();
        mDialog.setOnCancelListener((d) -> mCallback.onCanceled());
        mDialog.setOnShowListener((d) -> mCallback.onShown());
        int datasetsShown = (mAdapter != null) ? mAdapter.getCount() : 0;
        mDialog.setOnShowListener((d) -> mCallback.onShown(datasetsShown));
        show();
    }

+132 −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 android.view.autofill.AutofillId;
import android.view.autofill.AutofillValue;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

@RunWith(JUnit4.class)
public class PresentationEventLoggerTest {

    @Test
    public void testViewEntered() {
        PresentationStatsEventLogger pEventLogger =
                PresentationStatsEventLogger.createPresentationLog(1, 1, 1);

        AutofillId id = new AutofillId(13);
        AutofillValue initialValue = AutofillValue.forText("hello");
        AutofillValue lastValue = AutofillValue.forText("hello world");
        ViewState vState = new ViewState(id, null, 0, false);

        pEventLogger.startNewEvent();
        pEventLogger.maybeSetFocusedId(id);
        pEventLogger.onFieldTextUpdated(vState, initialValue);
        pEventLogger.onFieldTextUpdated(vState, lastValue);

        PresentationStatsEventLogger.PresentationStatsEventInternal event =
                pEventLogger.getInternalEvent().get();
        assertThat(event).isNotNull();
        assertThat(event.mFieldFirstLength).isEqualTo(initialValue.getTextValue().length());
        assertThat(event.mFieldLastLength).isEqualTo(lastValue.getTextValue().length());
        assertThat(event.mFieldModifiedFirstTimestampMs).isNotEqualTo(-1);
        assertThat(event.mFieldModifiedLastTimestampMs).isNotEqualTo(-1);
    }

    @Test
    public void testViewAutofilled() {
        PresentationStatsEventLogger pEventLogger =
                PresentationStatsEventLogger.createPresentationLog(1, 1, 1);

        String newTextValue = "hello";
        AutofillValue value = AutofillValue.forText(newTextValue);
        AutofillId id = new AutofillId(13);
        ViewState vState = new ViewState(id, null, ViewState.STATE_AUTOFILLED, false);

        pEventLogger.startNewEvent();
        pEventLogger.maybeSetFocusedId(id);
        pEventLogger.onFieldTextUpdated(vState, value);

        PresentationStatsEventLogger.PresentationStatsEventInternal event =
                pEventLogger.getInternalEvent().get();
        assertThat(event).isNotNull();
        assertThat(event.mFieldFirstLength).isEqualTo(newTextValue.length());
        assertThat(event.mFieldLastLength).isEqualTo(newTextValue.length());
        assertThat(event.mAutofilledTimestampMs).isNotEqualTo(-1);
        assertThat(event.mFieldModifiedFirstTimestampMs).isEqualTo(-1);
        assertThat(event.mFieldModifiedLastTimestampMs).isEqualTo(-1);
    }

    @Test
    public void testModifiedOnDifferentView() {
        PresentationStatsEventLogger pEventLogger =
                PresentationStatsEventLogger.createPresentationLog(1, 1, 1);

        String newTextValue = "hello";
        AutofillValue value = AutofillValue.forText(newTextValue);
        AutofillId id = new AutofillId(13);
        ViewState vState = new ViewState(id, null, ViewState.STATE_AUTOFILLED, false);

        pEventLogger.startNewEvent();
        pEventLogger.onFieldTextUpdated(vState, value);

        PresentationStatsEventLogger.PresentationStatsEventInternal event =
                pEventLogger.getInternalEvent().get();
        assertThat(event).isNotNull();
        assertThat(event.mFieldFirstLength).isEqualTo(-1);
        assertThat(event.mFieldLastLength).isEqualTo(-1);
        assertThat(event.mFieldModifiedFirstTimestampMs).isEqualTo(-1);
        assertThat(event.mFieldModifiedLastTimestampMs).isEqualTo(-1);
        assertThat(event.mAutofilledTimestampMs).isEqualTo(-1);
    }

    @Test
    public void testSetCountShown() {
        PresentationStatsEventLogger pEventLogger =
                PresentationStatsEventLogger.createPresentationLog(1, 1, 1);

        pEventLogger.startNewEvent();
        pEventLogger.logWhenDatasetShown(7);

        PresentationStatsEventLogger.PresentationStatsEventInternal event =
                pEventLogger.getInternalEvent().get();
        assertThat(event).isNotNull();
        assertThat(event.mCountShown).isEqualTo(7);
        assertThat(event.mNoPresentationReason)
                .isEqualTo(PresentationStatsEventLogger.NOT_SHOWN_REASON_ANY_SHOWN);
    }

    @Test
    public void testFillDialogShownThenInline() {
        PresentationStatsEventLogger pEventLogger =
                PresentationStatsEventLogger.createPresentationLog(1, 1, 1);

        pEventLogger.startNewEvent();
        pEventLogger.maybeSetDisplayPresentationType(3);
        pEventLogger.maybeSetDisplayPresentationType(2);

        PresentationStatsEventLogger.PresentationStatsEventInternal event =
                pEventLogger.getInternalEvent().get();
        assertThat(event).isNotNull();
        assertThat(event.mDisplayPresentationType).isEqualTo(3);
    }
}