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

Commit 78172e70 authored by Felipe Leme's avatar Felipe Leme
Browse files

Made Autofill Field Classification API public and documented it.

Test: mmm frameworks/base/:doc-comment-check-docs
Test: atest FrameworksCoreTests:SettingsBackupTest
Test: m -j 100 update-api

Fixes: 67867469

Change-Id: Iedf56a2bbcde3826eb22f5ed7a96d6ed70b968f4
parent a629e4c3
Loading
Loading
Loading
Loading
+43 −0
Original line number Diff line number Diff line
@@ -37513,6 +37513,25 @@ 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 implements android.os.Parcelable {
    method public int describeContents();
    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;
  }
  public static final class FieldClassification.Match {
    method public java.lang.String getRemoteId();
    method public float getScore();
  }
  public final class FillCallback {
    method public void onFailure(java.lang.CharSequence);
    method public void onSuccess(android.service.autofill.FillResponse);
@@ -37538,6 +37557,7 @@ package android.service.autofill {
    method public java.util.Map<android.view.autofill.AutofillId, java.lang.String> getChangedFields();
    method public android.os.Bundle getClientState();
    method public java.lang.String getDatasetId();
    method public java.util.Map<android.view.autofill.AutofillId, android.service.autofill.FieldClassification> getFieldsClassification();
    method public java.util.Set<java.lang.String> getIgnoredDatasetIds();
    method public java.util.Map<android.view.autofill.AutofillId, java.util.Set<java.lang.String>> getManuallyEnteredField();
    method public java.util.Set<java.lang.String> getSelectedDatasetIds();
@@ -37575,6 +37595,7 @@ package android.service.autofill {
    method public android.service.autofill.FillResponse.Builder disableAutofill(long);
    method public android.service.autofill.FillResponse.Builder setAuthentication(android.view.autofill.AutofillId[], android.content.IntentSender, android.widget.RemoteViews);
    method public android.service.autofill.FillResponse.Builder setClientState(android.os.Bundle);
    method public android.service.autofill.FillResponse.Builder setFieldClassificationIds(android.view.autofill.AutofillId...);
    method public android.service.autofill.FillResponse.Builder setFlags(int);
    method public android.service.autofill.FillResponse.Builder setFooter(android.widget.RemoteViews);
    method public android.service.autofill.FillResponse.Builder setHeader(android.widget.RemoteViews);
@@ -37658,6 +37679,9 @@ 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();
@@ -37668,6 +37692,22 @@ package android.service.autofill {
  public abstract interface Transformation {
  }
  public final class UserData implements android.os.Parcelable {
    method public int describeContents();
    method public static int getMaxFieldClassificationIdsSize();
    method public static int getMaxUserDataSize();
    method public static int getMaxValueLength();
    method public static int getMinValueLength();
    method public void writeToParcel(android.os.Parcel, int);
    field public static final android.os.Parcelable.Creator<android.service.autofill.UserData> CREATOR;
  }
  public static final class UserData.Builder {
    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();
  }
  public abstract interface Validator {
  }
@@ -48755,9 +48795,11 @@ package android.view.autofill {
    method public void cancel();
    method public void commit();
    method public void disableAutofillServices();
    method public android.service.autofill.UserData getUserData();
    method public boolean hasEnabledAutofillServices();
    method public boolean isAutofillSupported();
    method public boolean isEnabled();
    method public boolean isFieldClassificationEnabled();
    method public void notifyValueChanged(android.view.View);
    method public void notifyValueChanged(android.view.View, int, android.view.autofill.AutofillValue);
    method public void notifyViewEntered(android.view.View);
@@ -48769,6 +48811,7 @@ package android.view.autofill {
    method public void registerCallback(android.view.autofill.AutofillManager.AutofillCallback);
    method public void requestAutofill(android.view.View);
    method public void requestAutofill(android.view.View, int, android.graphics.Rect);
    method public void setUserData(android.service.autofill.UserData);
    method public void unregisterCallback(android.view.autofill.AutofillManager.AutofillCallback);
    field public static final java.lang.String EXTRA_ASSIST_STRUCTURE = "android.view.autofill.extra.ASSIST_STRUCTURE";
    field public static final java.lang.String EXTRA_AUTHENTICATION_RESULT = "android.view.autofill.extra.AUTHENTICATION_RESULT";
+5 −0
Original line number Diff line number Diff line
@@ -3531,6 +3531,11 @@ package android.provider {
  public static final class Settings.Secure extends android.provider.Settings.NameValueTable {
    method public static boolean putString(android.content.ContentResolver, java.lang.String, java.lang.String, java.lang.String, boolean);
    method public static void resetToDefaults(android.content.ContentResolver, java.lang.String);
    field public static final java.lang.String AUTOFILL_FEATURE_FIELD_CLASSIFICATION = "autofill_field_classification";
    field public static final java.lang.String AUTOFILL_USER_DATA_MAX_FIELD_CLASSIFICATION_IDS_SIZE = "autofill_user_data_max_field_classification_size";
    field public static final java.lang.String AUTOFILL_USER_DATA_MAX_USER_DATA_SIZE = "autofill_user_data_max_user_data_size";
    field public static final java.lang.String AUTOFILL_USER_DATA_MAX_VALUE_LENGTH = "autofill_user_data_max_value_length";
    field public static final java.lang.String AUTOFILL_USER_DATA_MIN_VALUE_LENGTH = "autofill_user_data_min_value_length";
    field public static final java.lang.String INSTANT_APPS_ENABLED = "instant_apps_enabled";
  }

+2 −50
Original line number Diff line number Diff line
@@ -463,34 +463,11 @@ package android.service.autofill {
  }

  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 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;
  }

  public static final class FieldClassification.Match implements android.os.Parcelable {
    method public int describeContents();
    method public java.lang.String getRemoteId();
    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 static final class FillEventHistory.Event {
    method public java.util.Map<android.view.autofill.AutofillId, android.service.autofill.FieldClassification> getFieldsClassification();
  }

  public static final class FillResponse.Builder {
    method public android.service.autofill.FillResponse.Builder setFieldClassificationIds(android.view.autofill.AutofillId...);
  public final class FillResponse implements android.os.Parcelable {
    method public int getFlags();
  }

  public final class ImageTransformation extends android.service.autofill.InternalTransformation implements android.os.Parcelable android.service.autofill.Transformation {
@@ -523,29 +500,10 @@ 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);
  }

  public final class UserData implements android.os.Parcelable {
    method public int describeContents();
    method public static int getMaxFieldClassificationIdsSize();
    method public static int getMaxUserDataSize();
    method public static int getMaxValueLength();
    method public static int getMinValueLength();
    method public void writeToParcel(android.os.Parcel, int);
    field public static final android.os.Parcelable.Creator<android.service.autofill.UserData> CREATOR;
  }

  public static final class UserData.Builder {
    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();
  }

  public abstract interface ValueFinder {
    method public abstract java.lang.String findByAutofillId(android.view.autofill.AutofillId);
  }
@@ -993,12 +951,6 @@ package android.view.autofill {
    ctor public AutofillId(int);
  }

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

}

package android.widget {
+13 −10
Original line number Diff line number Diff line
@@ -5328,48 +5328,51 @@ public final class Settings {
        public static final String AUTOFILL_SERVICE = "autofill_service";

        /**
         * Experimental autofill feature.
         * Boolean indicating if Autofill supports field classification.
         *
         * @see android.service.autofill.AutofillService
         *
         * <p>TODO(b/67867469): document (or remove) once feature is finished
         * @hide
         */
        @SystemApi
        @TestApi
        public static final String AUTOFILL_FEATURE_FIELD_CLASSIFICATION =
                "autofill_field_classification";

        /**
         * Experimental autofill feature.
         * Defines value returned by {@link android.service.autofill.UserData#getMaxUserDataSize()}.
         *
         * <p>TODO(b/67867469): document (or remove) once feature is finished
         * @hide
         */
        @SystemApi
        public static final String AUTOFILL_USER_DATA_MAX_USER_DATA_SIZE =
                "autofill_user_data_max_user_data_size";

        /**
         * Experimental autofill feature.
         * Defines value returned by
         * {@link android.service.autofill.UserData#getMaxFieldClassificationIdsSize()}.
         *
         * <p>TODO(b/67867469): document (or remove) once feature is finished
         * @hide
         */
        @SystemApi
        public static final String AUTOFILL_USER_DATA_MAX_FIELD_CLASSIFICATION_IDS_SIZE =
                "autofill_user_data_max_field_classification_size";

        /**
         * Experimental autofill feature.
         * Defines value returned by {@link android.service.autofill.UserData#getMaxValueLength()}.
         *
         * <p>TODO(b/67867469): document (or remove) once feature is finished
         * @hide
         */
        @SystemApi
        public static final String AUTOFILL_USER_DATA_MAX_VALUE_LENGTH =
                "autofill_user_data_max_value_length";

        /**
         * Experimental autofill feature.
         * Defines value returned by {@link android.service.autofill.UserData#getMinValueLength()}.
         *
         * <p>TODO(b/67867469): document (or remove) once feature is finished
         * @hide
         */
        @SystemApi
        public static final String AUTOFILL_USER_DATA_MIN_VALUE_LENGTH =
                "autofill_user_data_min_value_length";

+38 −5
Original line number Diff line number Diff line
@@ -453,13 +453,46 @@ import com.android.internal.os.SomeArgs;
 * email address), the service should only use it locally (i.e., in the app's process) for
 * heuristics purposes, but it should not be sent to external servers.
 *
 * <a name="FieldsClassification"></a>
 * <h3>Metrics and fields classification</h3
 * <a name="FieldClassification"></a>
 * <h3>Metrics and field classification</h3
 *
 * <p>TODO(b/67867469): document it or remove this section; in particular, document the relationship
 * between set/getUserData(), FillResponse.setFieldClassificationIds(), and
 * FillEventHistory.getFieldsClassification.
 * <p>The service can call {@link #getFillEventHistory()} to get metrics representing the user
 * actions, and then use these metrics to improve its heuristics.
 *
 * <p>Prior to Android {@link android.os.Build.VERSION_CODES#P}, the metrics covered just the
 * scenarios where the service knew how to autofill an activity, but Android
 * {@link android.os.Build.VERSION_CODES#P} introduced a new mechanism called field classification,
 * which allows the service to dinamically classify the meaning of fields based on the existing user
 * data known by the service.
 *
 * <p>Typically, field classification can be used to detect fields that can be autofilled with
 * user data that is not associated with a specific app&mdash;such as email and physical
 * address. Once the service identifies that a such field was manually filled by the user, the
 * service could use this signal to improve its heuristics, either locally (i.e., in the same
 * device) or globally (i.e., by crowdsourcing the results back to the service's server so it can
 * be used by other users).
 *
 * <p>The field classification workflow involves 4 steps:
 *
 * <ol>
 *   <li>Set the user data through {@link AutofillManager#setUserData(UserData)}. This data is
 *   cached until the system restarts (or the service is disabled), so it doesn't need to be set for
 *   all requests.
 *   <li>Identify which fields should be analysed by calling
 *   {@link FillResponse.Builder#setFieldClassificationIds(AutofillId...)}.
 *   <li>Verify the results through {@link FillEventHistory.Event#getFieldsClassification()}.
 *   <li>Use the results to dynamically create {@link Dataset} or {@link SaveInfo} objects in future
 *   requests.
 * </ol>
 *
 * <p>The field classification is an expensive operation and should be used carefully, otherwise it
 * can reach its rate limit and get blocked by the Android System. Ideally, it should be used just
 * in cases where the service could not determine how an activity can be autofilled, but it has a
 * strong suspicious that it could. For example, if an activity has four or more fields and one of
 * them is a list, chances are that these are address fields (like address, city, state, and
 * zip code).
 */
// TODO(b/70407264): add code snippets above???
public abstract class AutofillService extends Service {
    private static final String TAG = "AutofillService";

Loading