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

Commit 27f4573d authored by Felipe Leme's avatar Felipe Leme
Browse files

Refactored Field Classification score logic so it can be moved to ExtServices.

Bug: 70939974
Test: atest CtsAutoFillServiceTestCases:FieldsClassificationTest \
            CtsAutoFillServiceTestCases:UserDataTest
Test: atest CtsAutoFillServiceTestCases

Change-Id: If584ab3a55744a62f427065bfd44c8c219df83e9
parent c0f8195b
Loading
Loading
Loading
Loading
+6 −11
Original line number Diff line number Diff line
@@ -37697,18 +37697,12 @@ package android.service.autofill {
    method public android.service.autofill.Dataset.Builder setValue(android.view.autofill.AutofillId, android.view.autofill.AutofillValue, java.util.regex.Pattern, android.widget.RemoteViews);
  }
  public final class EditDistanceScorer implements android.os.Parcelable android.service.autofill.Scorer {
    method public int describeContents();
    method public static android.service.autofill.EditDistanceScorer getInstance();
    method public void writeToParcel(android.os.Parcel, int);
    field public static final android.os.Parcelable.Creator<android.service.autofill.EditDistanceScorer> CREATOR;
  }
  public final class FieldClassification {
    method public java.util.List<android.service.autofill.FieldClassification.Match> getMatches();
  }
  public static final class FieldClassification.Match {
    method public java.lang.String getAlgorithm();
    method public java.lang.String getRemoteId();
    method public float getScore();
  }
@@ -37860,9 +37854,6 @@ package android.service.autofill {
    field public static final android.os.Parcelable.Creator<android.service.autofill.SaveRequest> CREATOR;
  }
  public abstract interface Scorer {
  }
  public final class TextValueSanitizer implements android.os.Parcelable android.service.autofill.Sanitizer {
    ctor public TextValueSanitizer(java.util.regex.Pattern, java.lang.String);
    method public int describeContents();
@@ -37875,6 +37866,7 @@ package android.service.autofill {
  public final class UserData implements android.os.Parcelable {
    method public int describeContents();
    method public java.lang.String getFieldClassificationAlgorithm();
    method public static int getMaxFieldClassificationIdsSize();
    method public static int getMaxUserDataSize();
    method public static int getMaxValueLength();
@@ -37884,9 +37876,10 @@ package android.service.autofill {
  }
  public static final class UserData.Builder {
    ctor public UserData.Builder(android.service.autofill.Scorer, java.lang.String, java.lang.String);
    ctor public UserData.Builder(java.lang.String, java.lang.String);
    method public android.service.autofill.UserData.Builder add(java.lang.String, java.lang.String);
    method public android.service.autofill.UserData build();
    method public android.service.autofill.UserData.Builder setFieldClassificationAlgorithm(java.lang.String, android.os.Bundle);
  }
  public abstract interface Validator {
@@ -48348,6 +48341,8 @@ package android.view.autofill {
    method public void commit();
    method public void disableAutofillServices();
    method public android.content.ComponentName getAutofillServiceComponentName();
    method public java.util.List<java.lang.String> getAvailableFieldClassificationAlgorithms();
    method public java.lang.String getDefaultFieldClassificationAlgorithm();
    method public android.service.autofill.UserData getUserData();
    method public boolean hasEnabledAutofillServices();
    method public boolean isAutofillSupported();
+2 −6
Original line number Diff line number Diff line
@@ -477,7 +477,8 @@ package android.service.autofill {
    method public void apply(android.service.autofill.ValueFinder, android.widget.RemoteViews, int) throws java.lang.Exception;
  }

  public final class EditDistanceScorer extends android.service.autofill.InternalScorer implements android.os.Parcelable android.service.autofill.Scorer {
  public final class EditDistanceScorer {
    method public static android.service.autofill.EditDistanceScorer getInstance();
    method public float getScore(android.view.autofill.AutofillValue, java.lang.String);
  }

@@ -493,11 +494,6 @@ package android.service.autofill {
    ctor public InternalSanitizer();
  }

  public abstract class InternalScorer implements android.os.Parcelable android.service.autofill.Scorer {
    ctor public InternalScorer();
    method public abstract float getScore(android.view.autofill.AutofillValue, java.lang.String);
  }

  public abstract class InternalTransformation implements android.os.Parcelable android.service.autofill.Transformation {
    ctor public InternalTransformation();
  }
+23 −44
Original line number Diff line number Diff line
@@ -16,8 +16,7 @@
package android.service.autofill;

import android.annotation.NonNull;
import android.os.Parcel;
import android.os.Parcelable;
import android.annotation.TestApi;
import android.view.autofill.AutofillValue;

/**
@@ -25,13 +24,20 @@ import android.view.autofill.AutofillValue;
 * by the user and the expected value predicted by an autofill service.
 */
// TODO(b/70291841): explain algorithm once it's fully implemented
public final class EditDistanceScorer extends InternalScorer implements Scorer, Parcelable {
/** @hide */
@TestApi
public final class EditDistanceScorer {

    private static final EditDistanceScorer sInstance = new EditDistanceScorer();

    /** @hide */
    public static final String NAME = "EDIT_DISTANCE";

    /**
     * Gets the singleton instance.
     */
    @TestApi
    /** @hide */
    public static EditDistanceScorer getInstance() {
        return sInstance;
    }
@@ -39,59 +45,32 @@ public final class EditDistanceScorer extends InternalScorer implements Scorer,
    private EditDistanceScorer() {
    }

    /** @hide */
    @Override
    public float getScore(@NonNull AutofillValue actualValue, @NonNull String userData) {
        if (actualValue == null || !actualValue.isText() || userData == null) return 0;
    /**
     * Returns the classification score between an actual {@link AutofillValue} filled
     * by the user and the expected value predicted by an autofill service.
     *
     * <p>A full-match is {@code 1.0} (representing 100%), a full mismatch is {@code 0.0} and
     * partial mathces are something in between, typically using edit-distance algorithms.
     *
     * @hide
     */
    @TestApi
    public float getScore(@NonNull AutofillValue actualValue, @NonNull String userDataValue) {
        if (actualValue == null || !actualValue.isText() || userDataValue == null) return 0;
        // TODO(b/70291841): implement edit distance - currently it's returning either 0, 100%, or
        // partial match when number of chars match
        final String textValue = actualValue.getTextValue().toString();
        final int total = textValue.length();
        if (total != userData.length()) return 0F;
        if (total != userDataValue.length()) return 0F;

        int matches = 0;
        for (int i = 0; i < total; i++) {
            if (Character.toLowerCase(textValue.charAt(i)) == Character
                    .toLowerCase(userData.charAt(i))) {
                    .toLowerCase(userDataValue.charAt(i))) {
                matches++;
            }
        }

        return ((float) matches) / total;
    }

    /////////////////////////////////////
    // Object "contract" methods. //
    /////////////////////////////////////
    @Override
    public String toString() {
        return "EditDistanceScorer";
    }

    /////////////////////////////////////
    // Parcelable "contract" methods. //
    /////////////////////////////////////

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel parcel, int flags) {
        // Do nothing
    }

    public static final Parcelable.Creator<EditDistanceScorer> CREATOR =
            new Parcelable.Creator<EditDistanceScorer>() {
        @Override
        public EditDistanceScorer createFromParcel(Parcel parcel) {
            return EditDistanceScorer.getInstance();
        }

        @Override
        public EditDistanceScorer[] newArray(int size) {
            return new EditDistanceScorer[size];
        }
    };
}
+5 −14
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 The Android Open Source Project
/**
 * Copyright (c) 2017, 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.
@@ -13,16 +13,7 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package android.service.autofill;

/**
 * Helper class used to calculate a score.
 *
 * <p>Typically used to calculate the
 * <a href="AutofillService.html#FieldClassification">field classification</a> score between an
 * actual {@link android.view.autofill.AutofillValue} filled by the user and the expected value
 * predicted by an autofill service.
 */
public interface Scorer {
package android.service.autofill;

}
parcelable FieldClassification.AlgorithmInfo;
+26 −7
Original line number Diff line number Diff line
@@ -106,18 +106,20 @@ public final class FieldClassification {
    /**
     * Represents the score of a {@link UserData} entry for the field.
     *
     * <p>The score is defined by {@link #getScore()} and the entry is identified by
     * {@link #getRemoteId()}.
     * <p>The score is calculated by the given {@link #getAlgorithm() algorithm} and
     * the entry is identified by {@link #getRemoteId()}.
     */
    public static final class Match {

        private final String mRemoteId;
        private final float mScore;
        private final String mAlgorithm;

        /** @hide */
        public Match(String remoteId, float score) {
        public Match(String remoteId, float score, String algorithm) {
            mRemoteId = Preconditions.checkNotNull(remoteId);
            mScore = score;
            mAlgorithm = algorithm;
        }

        /**
@@ -140,29 +142,46 @@ public final class FieldClassification {
         *   <li>Any other value is a partial match.
         * </ul>
         *
         * <p>How the score is calculated depends on the algorithm used by the {@link Scorer}
         * implementation.
         * <p>How the score is calculated depends on the
         * {@link UserData.Builder#setFieldClassificationAlgorithm(String, android.os.Bundle)
         * algorithm} used.
         */
        public float getScore() {
            return mScore;
        }

        /**
         * Gets the algorithm used to calculate this score.
         *
         * <p>Typically, this is either the algorithm set by
         * {@link UserData.Builder#setFieldClassificationAlgorithm(String, android.os.Bundle)},
         * or the
         * {@link android.view.autofill.AutofillManager#getDefaultFieldClassificationAlgorithm()}.
         */
        @NonNull
        public String getAlgorithm() {
            return mAlgorithm;
        }

        @Override
        public String toString() {
            if (!sDebug) return super.toString();

            final StringBuilder string = new StringBuilder("Match: remoteId=");
            Helper.appendRedacted(string, mRemoteId);
            return string.append(", score=").append(mScore).toString();
            return string.append(", score=").append(mScore)
                    .append(", algorithm=").append(mAlgorithm)
                    .toString();
        }

        private void writeToParcel(@NonNull Parcel parcel) {
            parcel.writeString(mRemoteId);
            parcel.writeFloat(mScore);
            parcel.writeString(mAlgorithm);
        }

        private static Match readFromParcel(@NonNull Parcel parcel) {
            return new Match(parcel.readString(), parcel.readFloat());
            return new Match(parcel.readString(), parcel.readFloat(), parcel.readString());
        }
    }
}
Loading