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

Commit 734afbe6 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Moar changes for Autofill Field Classification mechanism:"

parents 6cca6d50 329d0409
Loading
Loading
Loading
Loading
+21 −8
Original line number Diff line number Diff line
@@ -425,7 +425,7 @@ package android.provider {

  public static final class Settings.Secure extends android.provider.Settings.NameValueTable {
    field public static final java.lang.String ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED = "accessibility_display_magnification_enabled";
    field public static final java.lang.String AUTOFILL_FEATURE_FIELD_DETECTION = "autofill_field_detection";
    field public static final java.lang.String AUTOFILL_FEATURE_FIELD_CLASSIFICATION = "autofill_field_classification";
    field public static final java.lang.String AUTOFILL_SERVICE = "autofill_service";
    field public static final java.lang.String DISABLED_PRINT_SERVICES = "disabled_print_services";
    field public static final deprecated java.lang.String ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES = "enabled_notification_policy_access_packages";
@@ -457,9 +457,17 @@ 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 {
    method public int describeContents();
    method public static android.service.autofill.EditDistanceScorer getInstance();
    method public float getScore(android.view.autofill.AutofillValue, java.lang.String);
    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 implements android.os.Parcelable {
    method public int describeContents();
    method public android.service.autofill.FieldClassification.Match getTopMatch();
    method public java.util.List<android.service.autofill.FieldClassification.Match> getMatches();
    method public void writeToParcel(android.os.Parcel, int);
    field public static final android.os.Parcelable.Creator<android.service.autofill.FieldClassification> CREATOR;
  }
@@ -467,15 +475,11 @@ package android.service.autofill {
  public static final class FieldClassification.Match implements android.os.Parcelable {
    method public int describeContents();
    method public java.lang.String getRemoteId();
    method public int getScore();
    method public float getScore();
    method public void writeToParcel(android.os.Parcel, int);
    field public static final android.os.Parcelable.Creator<android.service.autofill.FieldClassification.Match> CREATOR;
  }

  public final class FieldsClassificationScorer {
    method public static int getScore(android.view.autofill.AutofillValue, java.lang.String);
  }

  public static final class FillEventHistory.Event {
    method public java.util.Map<android.view.autofill.AutofillId, android.service.autofill.FieldClassification> getFieldsClassification();
  }
@@ -492,6 +496,11 @@ 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();
  }
@@ -509,6 +518,9 @@ package android.service.autofill {
    method public boolean isValid(android.service.autofill.ValueFinder);
  }

  public abstract interface Scorer {
  }

  public final class TextValueSanitizer extends android.service.autofill.InternalSanitizer implements android.os.Parcelable android.service.autofill.Sanitizer {
    method public android.view.autofill.AutofillValue sanitize(android.view.autofill.AutofillValue);
  }
@@ -524,7 +536,7 @@ package android.service.autofill {
  }

  public static final class UserData.Builder {
    ctor public UserData.Builder(java.lang.String, java.lang.String);
    ctor public UserData.Builder(android.service.autofill.Scorer, 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();
  }
@@ -978,6 +990,7 @@ package android.view.autofill {

  public final class AutofillManager {
    method public android.service.autofill.UserData getUserData();
    method public boolean isFieldClassificationEnabled();
    method public void setUserData(android.service.autofill.UserData);
  }

+3 −2
Original line number Diff line number Diff line
@@ -5330,11 +5330,12 @@ public final class Settings {
        /**
         * Experimental autofill feature.
         *
         * <p>TODO(b/67867469): remove once feature is finished
         * <p>TODO(b/67867469): document (or remove) once feature is finished
         * @hide
         */
        @TestApi
        public static final String AUTOFILL_FEATURE_FIELD_DETECTION = "autofill_field_detection";
        public static final String AUTOFILL_FEATURE_FIELD_CLASSIFICATION =
                "autofill_field_classification";

        /**
         * Experimental autofill feature.
+103 −0
Original line number Diff line number Diff line
@@ -17,33 +17,43 @@ package android.service.autofill;

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

/**
 * Helper used to calculate the classification score between an actual {@link AutofillValue} filled
 * by the user and the expected value predicted by an autofill service.
 *
 * TODO(b/67867469):
 * - improve javadoc
 * - document algorithm / copy from InternalScorer
 * - unhide / remove testApi
 * @hide
 */
@TestApi
public final class FieldsClassificationScorer {
public final class EditDistanceScorer extends InternalScorer implements Scorer, Parcelable {

    private static final int MAX_VALUE = 100_0000; // 100.0000%
    private static final EditDistanceScorer sInstance = new EditDistanceScorer();

    /**
     * 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 1000000} (representing 100.0000%), a full mismatch is {@code 0} and
     * partial mathces are something in between, typically using edit-distance algorithms.
     * Gets the singleton instance.
     */
    public static int getScore(@NonNull AutofillValue actualValue, @NonNull String userData) {
    public static EditDistanceScorer getInstance() {
        return sInstance;
    }

    private EditDistanceScorer() {
    }

    @Override
    public float getScore(@NonNull AutofillValue actualValue, @NonNull String userData) {
        if (actualValue == null || !actualValue.isText() || userData == null) return 0;
        // TODO(b/67867469): 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 0;
        if (total != userData.length()) return 0F;

        int matches = 0;
        for (int i = 0; i < total; i++) {
@@ -53,12 +63,41 @@ public final class FieldsClassificationScorer {
            }
        }

        final float percentage = ((float) matches) / total;
        final int rounded = (int) (percentage * MAX_VALUE);
        return rounded;
        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();
        }

    private FieldsClassificationScorer() {
        throw new UnsupportedOperationException("contains only static methods");
        @Override
        public EditDistanceScorer[] newArray(int size) {
            return new EditDistanceScorer[size];
        }
    };
}
+21 −13
Original line number Diff line number Diff line
@@ -26,6 +26,10 @@ import android.view.autofill.Helper;

import com.android.internal.util.Preconditions;

import com.google.android.collect.Lists;

import java.util.List;

/**
 * Gets the <a href="#FieldsClassification">fields classification</a> results for a given field.
 *
@@ -46,11 +50,15 @@ public final class FieldClassification implements Parcelable {
    }

    /**
     * Gets the {@link Match} with the highest {@link Match#getScore() score} for the field.
     * Gets the {@link Match matches} with the highest {@link Match#getScore() scores}.
     *
     * <p><b>Note:</b> There's no guarantee of how many matches will be returned. In fact,
     * the Android System might return just the top match to minimize the impact of field
     * classification in the device's health.
     */
    @NonNull
    public Match getTopMatch() {
        return mMatch;
    public List<Match> getMatches() {
        return Lists.newArrayList(mMatch);
    }

    @Override
@@ -101,10 +109,10 @@ public final class FieldClassification implements Parcelable {
    public static final class Match implements Parcelable {

        private final String mRemoteId;
        private final int mScore;
        private final float mScore;

        /** @hide */
        public Match(String remoteId, int score) {
        public Match(String remoteId, float score) {
            mRemoteId = Preconditions.checkNotNull(remoteId);
            mScore = score;
        }
@@ -123,8 +131,8 @@ public final class FieldClassification implements Parcelable {
         * <p>The score is based in a case-insensitive comparisson of all characters from both the
         * field value and the user data entry, and it ranges from {@code 0} to {@code 1000000}:
         * <ul>
         *   <li>{@code 1000000} represents a full match ({@code 100.0000%}).
         *   <li>{@code 0} represents a full mismatch ({@code 0.0000%}).
         *   <li>{@code 1.0} represents a full match ({@code 100%}).
         *   <li>{@code 0.0} represents a full mismatch ({@code 0%}).
         *   <li>Any other value is a partial match.
         * </ul>
         *
@@ -132,14 +140,14 @@ public final class FieldClassification implements Parcelable {
         * For example, if the user  data is {@code "abc"} and the field value us {@code " abc"},
         * the result could be:
         * <ul>
         *   <li>{@code 1000000} if the algorithm trims the values.
         *   <li>{@code 0} if the algorithm compares the values sequentially.
         *   <li>{@code 750000} if the algorithm consideres that 3/4 (75%) of the characters match.
         *   <li>{@code 1.0} if the algorithm trims the values.
         *   <li>{@code 0.0} if the algorithm compares the values sequentially.
         *   <li>{@code 0.75} if the algorithm consideres that 3/4 (75%) of the characters match.
         * </ul>
         *
         * <p>Currently, the autofill service cannot configure the algorithm.
         */
        public int getScore() {
        public float getScore() {
            return mScore;
        }

@@ -164,7 +172,7 @@ public final class FieldClassification implements Parcelable {
        @Override
        public void writeToParcel(Parcel parcel, int flags) {
            parcel.writeString(mRemoteId);
            parcel.writeInt(mScore);
            parcel.writeFloat(mScore);
        }

        @SuppressWarnings("hiding")
@@ -172,7 +180,7 @@ public final class FieldClassification implements Parcelable {

            @Override
            public Match createFromParcel(Parcel parcel) {
                return new Match(parcel.readString(), parcel.readInt());
                return new Match(parcel.readString(), parcel.readFloat());
            }

            @Override
+40 −0
Original line number Diff line number Diff line
/*
 * 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.
 * 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 android.service.autofill;

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

/**
 * Superclass of all scorer the system understands. As this is not public all
 * subclasses have to implement {@link Scorer} again.
 *
 * @hide
 */
@TestApi
public abstract class InternalScorer implements Scorer, Parcelable {

    /**
     * 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.
     */
    public abstract float getScore(@NonNull AutofillValue actualValue, @NonNull String userData);
}
Loading