diff options
| author | Tony Mak <tonymak@google.com> | 2019-01-09 15:59:56 +0000 |
|---|---|---|
| committer | Tony Mak <tonymak@google.com> | 2019-01-14 17:06:00 +0000 |
| commit | ae85aae6aa0be83329b588346699f3940d43fc4e (patch) | |
| tree | 3e3cfcc07c78c586bce8cfd1e75c44262a4580b8 /core/java/android | |
| parent | 4a710a85d22e32d86231dd9a91b0bce7447163ec (diff) | |
Cleanup TextClassifier APIs
Major changes:
1. ConversationAction is now in top-level.
2. Removed TypeConfig, and repurposed TextClassifier.EntityConfig for
general use. It would be better to rename it to be something like
TypeConfig. But just a bad name is probably not worth to deprecate
the existing APIs.
3. Hints constants are moved to Request object.
4. Action constants are moved to ConversationAction object.
Test: atest TextClassifierTest.java
BUG: 120841922
Change-Id: Ia466aaf4c5050a9c7e404dcd3b295f5ef7e4ce6f
Diffstat (limited to 'core/java/android')
5 files changed, 456 insertions, 474 deletions
diff --git a/core/java/android/view/textclassifier/ConversationAction.java b/core/java/android/view/textclassifier/ConversationAction.java new file mode 100644 index 000000000000..1a6e5d8e8b03 --- /dev/null +++ b/core/java/android/view/textclassifier/ConversationAction.java @@ -0,0 +1,266 @@ +/* + * Copyright (C) 2018 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.view.textclassifier; + +import static java.lang.annotation.RetentionPolicy.SOURCE; + +import android.annotation.FloatRange; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.StringDef; +import android.app.RemoteAction; +import android.os.Bundle; +import android.os.Parcel; +import android.os.Parcelable; + +import com.android.internal.util.Preconditions; + +import java.lang.annotation.Retention; + +/** Represents the action suggested by a {@link TextClassifier} on a given conversation. */ +public final class ConversationAction implements Parcelable { + + /** @hide */ + @Retention(SOURCE) + @StringDef( + value = { + TYPE_VIEW_CALENDAR, + TYPE_VIEW_MAP, + TYPE_TRACK_FLIGHT, + TYPE_OPEN_URL, + TYPE_SEND_SMS, + TYPE_CALL_PHONE, + TYPE_SEND_EMAIL, + TYPE_TEXT_REPLY, + TYPE_CREATE_REMINDER, + TYPE_SHARE_LOCATION + }, + prefix = "TYPE_") + public @interface ActionType {} + + /** + * Indicates an action to view a calendar at a specified time. + */ + public static final String TYPE_VIEW_CALENDAR = "view_calendar"; + /** + * Indicates an action to view the map at a specified location. + */ + public static final String TYPE_VIEW_MAP = "view_map"; + /** + * Indicates an action to track a flight. + */ + public static final String TYPE_TRACK_FLIGHT = "track_flight"; + /** + * Indicates an action to open an URL. + */ + public static final String TYPE_OPEN_URL = "open_url"; + /** + * Indicates an action to send a SMS. + */ + public static final String TYPE_SEND_SMS = "send_sms"; + /** + * Indicates an action to call a phone number. + */ + public static final String TYPE_CALL_PHONE = "call_phone"; + /** + * Indicates an action to send an email. + */ + public static final String TYPE_SEND_EMAIL = "send_email"; + /** + * Indicates an action to reply with a text message. + */ + public static final String TYPE_TEXT_REPLY = "text_reply"; + /** + * Indicates an action to create a reminder. + */ + public static final String TYPE_CREATE_REMINDER = "create_reminder"; + /** + * Indicates an action to reply with a location. + */ + public static final String TYPE_SHARE_LOCATION = "share_location"; + + public static final Creator<ConversationAction> CREATOR = + new Creator<ConversationAction>() { + @Override + public ConversationAction createFromParcel(Parcel in) { + return new ConversationAction(in); + } + + @Override + public ConversationAction[] newArray(int size) { + return new ConversationAction[size]; + } + }; + + @NonNull + @ActionType + private final String mType; + @NonNull + private final CharSequence mTextReply; + @Nullable + private final RemoteAction mAction; + + @FloatRange(from = 0, to = 1) + private final float mScore; + + @NonNull + private final Bundle mExtras; + + private ConversationAction( + @NonNull String type, + @Nullable RemoteAction action, + @Nullable CharSequence textReply, + float score, + @NonNull Bundle extras) { + mType = Preconditions.checkNotNull(type); + mAction = action; + mTextReply = textReply; + mScore = score; + mExtras = Preconditions.checkNotNull(extras); + } + + private ConversationAction(Parcel in) { + mType = in.readString(); + mAction = in.readParcelable(null); + mTextReply = in.readCharSequence(); + mScore = in.readFloat(); + mExtras = in.readBundle(); + } + + @Override + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeString(mType); + parcel.writeParcelable(mAction, flags); + parcel.writeCharSequence(mTextReply); + parcel.writeFloat(mScore); + parcel.writeBundle(mExtras); + } + + @Override + public int describeContents() { + return 0; + } + + /** Returns the type of this action, for example, {@link #TYPE_VIEW_CALENDAR}. */ + @NonNull + @ActionType + public String getType() { + return mType; + } + + /** + * Returns a RemoteAction object, which contains the icon, label and a PendingIntent, for + * the specified action type. + */ + @Nullable + public RemoteAction getAction() { + return mAction; + } + + /** + * Returns the confidence score for the specified action. The value ranges from 0 (low + * confidence) to 1 (high confidence). + */ + @FloatRange(from = 0, to = 1) + public float getConfidenceScore() { + return mScore; + } + + /** + * Returns the text reply that could be sent as a reply to the given conversation. + * <p> + * This is only available when the type of the action is {@link #TYPE_TEXT_REPLY}. + */ + @Nullable + public CharSequence getTextReply() { + return mTextReply; + } + + /** + * Returns the extended data related to this conversation action. + * + * <p><b>NOTE: </b>Each call to this method returns a new bundle copy so clients should + * prefer to hold a reference to the returned bundle rather than frequently calling this + * method. + */ + @NonNull + public Bundle getExtras() { + return mExtras.deepCopy(); + } + + /** Builder class to construct {@link ConversationAction}. */ + public static final class Builder { + @Nullable + @ActionType + private String mType; + @Nullable + private RemoteAction mAction; + @Nullable + private CharSequence mTextReply; + private float mScore; + @Nullable + private Bundle mExtras; + + public Builder(@NonNull @ActionType String actionType) { + mType = Preconditions.checkNotNull(actionType); + } + + /** + * Sets an action that may be performed on the given conversation. + */ + @NonNull + public Builder setAction(@Nullable RemoteAction action) { + mAction = action; + return this; + } + + /** + * Sets a text reply that may be performed on the given conversation. + */ + @NonNull + public Builder setTextReply(@Nullable CharSequence textReply) { + mTextReply = textReply; + return this; + } + + /** Sets the confident score. */ + @NonNull + public Builder setConfidenceScore(@FloatRange(from = 0, to = 1) float score) { + mScore = score; + return this; + } + + /** + * Sets the extended data for the conversation action object. + */ + @NonNull + public Builder setExtras(@Nullable Bundle extras) { + mExtras = extras; + return this; + } + + /** Builds the {@link ConversationAction} object. */ + @NonNull + public ConversationAction build() { + return new ConversationAction( + mType, + mAction, + mTextReply, + mScore, + mExtras == null ? Bundle.EMPTY : mExtras.deepCopy()); + } + } +} diff --git a/core/java/android/view/textclassifier/ConversationActions.java b/core/java/android/view/textclassifier/ConversationActions.java index 3f690f70d275..f7c1a2640dc5 100644 --- a/core/java/android/view/textclassifier/ConversationActions.java +++ b/core/java/android/view/textclassifier/ConversationActions.java @@ -17,18 +17,15 @@ package android.view.textclassifier; import static java.lang.annotation.RetentionPolicy.SOURCE; -import android.annotation.FloatRange; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.StringDef; import android.app.Person; -import android.app.RemoteAction; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import android.text.SpannedString; -import android.util.ArraySet; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Preconditions; @@ -37,10 +34,8 @@ import java.lang.annotation.Retention; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.List; -import java.util.Set; /** * Represents a list of actions suggested by a {@link TextClassifier} on a given conversation. @@ -62,83 +57,6 @@ public final class ConversationActions implements Parcelable { } }; - /** @hide */ - @Retention(SOURCE) - @StringDef( - value = { - TYPE_VIEW_CALENDAR, - TYPE_VIEW_MAP, - TYPE_TRACK_FLIGHT, - TYPE_OPEN_URL, - TYPE_SEND_SMS, - TYPE_CALL_PHONE, - TYPE_SEND_EMAIL, - TYPE_TEXT_REPLY, - TYPE_CREATE_REMINDER, - TYPE_SHARE_LOCATION - }, - prefix = "TYPE_") - public @interface ActionType {} - - /** - * Indicates an action to view a calendar at a specified time. - */ - public static final String TYPE_VIEW_CALENDAR = "view_calendar"; - /** - * Indicates an action to view the map at a specified location. - */ - public static final String TYPE_VIEW_MAP = "view_map"; - /** - * Indicates an action to track a flight. - */ - public static final String TYPE_TRACK_FLIGHT = "track_flight"; - /** - * Indicates an action to open an URL. - */ - public static final String TYPE_OPEN_URL = "open_url"; - /** - * Indicates an action to send a SMS. - */ - public static final String TYPE_SEND_SMS = "send_sms"; - /** - * Indicates an action to call a phone number. - */ - public static final String TYPE_CALL_PHONE = "call_phone"; - /** - * Indicates an action to send an email. - */ - public static final String TYPE_SEND_EMAIL = "send_email"; - /** - * Indicates an action to reply with a text message. - */ - public static final String TYPE_TEXT_REPLY = "text_reply"; - /** - * Indicates an action to create a reminder. - */ - public static final String TYPE_CREATE_REMINDER = "create_reminder"; - /** - * Indicates an action to reply with a location. - */ - public static final String TYPE_SHARE_LOCATION = "share_location"; - - /** @hide */ - @Retention(SOURCE) - @StringDef( - value = { - HINT_FOR_NOTIFICATION, - HINT_FOR_IN_APP, - }, - prefix = "HINT_") - public @interface Hint {} - /** - * To indicate the generated actions will be used within the app. - */ - public static final String HINT_FOR_IN_APP = "in_app"; - /** - * To indicate the generated actions will be used for notification. - */ - public static final String HINT_FOR_NOTIFICATION = "notification"; - private final List<ConversationAction> mConversationActions; private final String mId; @@ -184,182 +102,6 @@ public final class ConversationActions implements Parcelable { return mId; } - /** Represents the action suggested by a {@link TextClassifier} on a given conversation. */ - public static final class ConversationAction implements Parcelable { - - public static final Creator<ConversationAction> CREATOR = - new Creator<ConversationAction>() { - @Override - public ConversationAction createFromParcel(Parcel in) { - return new ConversationAction(in); - } - - @Override - public ConversationAction[] newArray(int size) { - return new ConversationAction[size]; - } - }; - - @NonNull - @ActionType - private final String mType; - @NonNull - private final CharSequence mTextReply; - @Nullable - private final RemoteAction mAction; - - @FloatRange(from = 0, to = 1) - private final float mScore; - - @NonNull - private final Bundle mExtras; - - private ConversationAction( - @NonNull String type, - @Nullable RemoteAction action, - @Nullable CharSequence textReply, - float score, - @NonNull Bundle extras) { - mType = Preconditions.checkNotNull(type); - mAction = action; - mTextReply = textReply; - mScore = score; - mExtras = Preconditions.checkNotNull(extras); - } - - private ConversationAction(Parcel in) { - mType = in.readString(); - mAction = in.readParcelable(null); - mTextReply = in.readCharSequence(); - mScore = in.readFloat(); - mExtras = in.readBundle(); - } - - @Override - public void writeToParcel(Parcel parcel, int flags) { - parcel.writeString(mType); - parcel.writeParcelable(mAction, flags); - parcel.writeCharSequence(mTextReply); - parcel.writeFloat(mScore); - parcel.writeBundle(mExtras); - } - - @Override - public int describeContents() { - return 0; - } - - @NonNull - @ActionType - /** Returns the type of this action, for example, {@link #TYPE_VIEW_CALENDAR}. */ - public String getType() { - return mType; - } - - @Nullable - /** - * Returns a RemoteAction object, which contains the icon, label and a PendingIntent, for - * the specified action type. - */ - public RemoteAction getAction() { - return mAction; - } - - /** - * Returns the confidence score for the specified action. The value ranges from 0 (low - * confidence) to 1 (high confidence). - */ - @FloatRange(from = 0, to = 1) - public float getConfidenceScore() { - return mScore; - } - - /** - * Returns the text reply that could be sent as a reply to the given conversation. - * <p> - * This is only available when the type of the action is {@link #TYPE_TEXT_REPLY}. - */ - @Nullable - public CharSequence getTextReply() { - return mTextReply; - } - - /** - * Returns the extended data related to this conversation action. - * - * <p><b>NOTE: </b>Each call to this method returns a new bundle copy so clients should - * prefer to hold a reference to the returned bundle rather than frequently calling this - * method. - */ - @NonNull - public Bundle getExtras() { - return mExtras.deepCopy(); - } - - /** Builder class to construct {@link ConversationAction}. */ - public static final class Builder { - @Nullable - @ActionType - private String mType; - @Nullable - private RemoteAction mAction; - @Nullable - private CharSequence mTextReply; - private float mScore; - @Nullable - private Bundle mExtras; - - public Builder(@NonNull @ActionType String actionType) { - mType = Preconditions.checkNotNull(actionType); - } - - /** - * Sets an action that may be performed on the given conversation. - */ - @NonNull - public Builder setAction(@Nullable RemoteAction action) { - mAction = action; - return this; - } - - /** - * Sets a text reply that may be performed on the given conversation. - */ - @NonNull - public Builder setTextReply(@Nullable CharSequence textReply) { - mTextReply = textReply; - return this; - } - - /** Sets the confident score. */ - @NonNull - public Builder setConfidenceScore(@FloatRange(from = 0, to = 1) float score) { - mScore = score; - return this; - } - - /** - * Sets the extended data for the conversation action object. - */ - @NonNull - public Builder setExtras(@Nullable Bundle extras) { - mExtras = extras; - return this; - } - - /** Builds the {@link ConversationAction} object. */ - @NonNull - public ConversationAction build() { - return new ConversationAction( - mType, - mAction, - mTextReply, - mScore, - mExtras == null ? Bundle.EMPTY : mExtras.deepCopy()); - } - } - } - /** Represents a message in the conversation. */ public static final class Message implements Parcelable { /** @@ -538,156 +280,36 @@ public final class ConversationActions implements Parcelable { } } - /** Configuration object for specifying what action types to identify. */ - public static final class TypeConfig implements Parcelable { - @NonNull - @ActionType - private final Set<String> mExcludedTypes; - @NonNull - @ActionType - private final Set<String> mIncludedTypes; - private final boolean mIncludeTypesFromTextClassifier; - - private TypeConfig( - @NonNull Set<String> includedTypes, - @NonNull Set<String> excludedTypes, - boolean includeTypesFromTextClassifier) { - mIncludedTypes = Preconditions.checkNotNull(includedTypes); - mExcludedTypes = Preconditions.checkNotNull(excludedTypes); - mIncludeTypesFromTextClassifier = includeTypesFromTextClassifier; - } - - private TypeConfig(Parcel in) { - mIncludedTypes = new ArraySet<>(in.createStringArrayList()); - mExcludedTypes = new ArraySet<>(in.createStringArrayList()); - mIncludeTypesFromTextClassifier = in.readByte() != 0; - } - - @Override - public void writeToParcel(Parcel parcel, int flags) { - parcel.writeStringList(new ArrayList<>(mIncludedTypes)); - parcel.writeStringList(new ArrayList<>(mExcludedTypes)); - parcel.writeByte((byte) (mIncludeTypesFromTextClassifier ? 1 : 0)); - } - - @Override - public int describeContents() { - return 0; - } - - public static final Creator<TypeConfig> CREATOR = - new Creator<TypeConfig>() { - @Override - public TypeConfig createFromParcel(Parcel in) { - return new TypeConfig(in); - } + /** + * A request object for generating conversation action suggestions. + * + * @see TextClassifier#suggestConversationActions(Request) + */ + public static final class Request implements Parcelable { - @Override - public TypeConfig[] newArray(int size) { - return new TypeConfig[size]; - } - }; + /** @hide */ + @Retention(SOURCE) + @StringDef( + value = { + HINT_FOR_NOTIFICATION, + HINT_FOR_IN_APP, + }, + prefix = "HINT_") + public @interface Hint {} /** - * Returns a final list of types that the text classifier should look for. - * - * <p>NOTE: This method is intended for use by a text classifier. - * - * @param defaultTypes types the text classifier thinks should be included before factoring - * in the included/excluded types given by the client. + * To indicate the generated actions will be used within the app. */ - @NonNull - public Collection<String> resolveTypes(@Nullable Collection<String> defaultTypes) { - Set<String> types = new ArraySet<>(); - if (mIncludeTypesFromTextClassifier && defaultTypes != null) { - types.addAll(defaultTypes); - } - types.addAll(mIncludedTypes); - types.removeAll(mExcludedTypes); - return Collections.unmodifiableCollection(types); - } - + public static final String HINT_FOR_IN_APP = "in_app"; /** - * Return whether the client allows the text classifier to include its own list of default - * types. If this function returns {@code true}, the text classifier can consider specifying - * a default list of entity types in {@link #resolveTypes(Collection)}. - * - * <p>NOTE: This method is intended for use by a text classifier. - * - * @see #resolveTypes(Collection) + * To indicate the generated actions will be used for notification. */ - public boolean shouldIncludeTypesFromTextClassifier() { - return mIncludeTypesFromTextClassifier; - } - - /** Builder class to construct the {@link TypeConfig} object. */ - public static final class Builder { - @Nullable - private Collection<String> mExcludedTypes; - @Nullable - private Collection<String> mIncludedTypes; - private boolean mIncludeTypesFromTextClassifier = true; - - /** - * Sets a collection of types that are explicitly included, for example, {@link - * #TYPE_VIEW_CALENDAR}. - */ - @NonNull - public Builder setIncludedTypes( - @Nullable @ActionType Collection<String> includedTypes) { - mIncludedTypes = includedTypes; - return this; - } - - /** - * Sets a collection of types that are explicitly excluded, for example, {@link - * #TYPE_VIEW_CALENDAR}. - */ - @NonNull - public Builder setExcludedTypes( - @Nullable @ActionType Collection<String> excludedTypes) { - mExcludedTypes = excludedTypes; - return this; - } - - /** - * Specifies whether or not to include the types suggested by the text classifier. By - * default, it is included. - */ - @NonNull - public Builder includeTypesFromTextClassifier(boolean includeTypesFromTextClassifier) { - mIncludeTypesFromTextClassifier = includeTypesFromTextClassifier; - return this; - } - - /** - * Combines all of the options that have been set and returns a new {@link TypeConfig} - * object. - */ - @NonNull - public TypeConfig build() { - return new TypeConfig( - mIncludedTypes == null - ? Collections.emptySet() - : new ArraySet<>(mIncludedTypes), - mExcludedTypes == null - ? Collections.emptySet() - : new ArraySet<>(mExcludedTypes), - mIncludeTypesFromTextClassifier); - } - } - } + public static final String HINT_FOR_NOTIFICATION = "notification"; - /** - * A request object for generating conversation action suggestions. - * - * @see TextClassifier#suggestConversationActions(Request) - */ - public static final class Request implements Parcelable { @NonNull private final List<Message> mConversation; @NonNull - private final TypeConfig mTypeConfig; + private final TextClassifier.EntityConfig mTypeConfig; private final int mMaxSuggestions; @NonNull @Hint @@ -699,7 +321,7 @@ public final class ConversationActions implements Parcelable { private Request( @NonNull List<Message> conversation, - @NonNull TypeConfig typeConfig, + @NonNull TextClassifier.EntityConfig typeConfig, int maxSuggestions, String conversationId, @Nullable @Hint List<String> hints) { @@ -713,7 +335,7 @@ public final class ConversationActions implements Parcelable { private static Request readFromParcel(Parcel in) { List<Message> conversation = new ArrayList<>(); in.readParcelableList(conversation, null); - TypeConfig typeConfig = in.readParcelable(null); + TextClassifier.EntityConfig typeConfig = in.readParcelable(null); int maxSuggestions = in.readInt(); String conversationId = in.readString(); List<String> hints = new ArrayList<>(); @@ -760,7 +382,7 @@ public final class ConversationActions implements Parcelable { /** Returns the type config. */ @NonNull - public TypeConfig getTypeConfig() { + public TextClassifier.EntityConfig getTypeConfig() { return mTypeConfig; } @@ -820,7 +442,7 @@ public final class ConversationActions implements Parcelable { @NonNull private List<Message> mConversation; @Nullable - private TypeConfig mTypeConfig; + private TextClassifier.EntityConfig mTypeConfig; private int mMaxSuggestions; @Nullable private String mConversationId; @@ -849,7 +471,7 @@ public final class ConversationActions implements Parcelable { /** Sets the type config. */ @NonNull - public Builder setTypeConfig(@Nullable TypeConfig typeConfig) { + public Builder setTypeConfig(@Nullable TextClassifier.EntityConfig typeConfig) { mTypeConfig = typeConfig; return this; } @@ -879,7 +501,9 @@ public final class ConversationActions implements Parcelable { public Request build() { return new Request( Collections.unmodifiableList(mConversation), - mTypeConfig == null ? new TypeConfig.Builder().build() : mTypeConfig, + mTypeConfig == null + ? new TextClassifier.EntityConfig.Builder().build() + : mTypeConfig, mMaxSuggestions, mConversationId, mHints == null diff --git a/core/java/android/view/textclassifier/TextClassificationConstants.java b/core/java/android/view/textclassifier/TextClassificationConstants.java index 50801a2b3e3f..ce680ecbd119 100644 --- a/core/java/android/view/textclassifier/TextClassificationConstants.java +++ b/core/java/android/view/textclassifier/TextClassificationConstants.java @@ -117,15 +117,15 @@ public final class TextClassificationConstants { .add(TextClassifier.TYPE_FLIGHT_NUMBER).toString(); private static final String CONVERSATION_ACTIONS_TYPES_DEFAULT_VALUES = new StringJoiner(ENTITY_LIST_DELIMITER) - .add(ConversationActions.TYPE_TEXT_REPLY) - .add(ConversationActions.TYPE_CREATE_REMINDER) - .add(ConversationActions.TYPE_CALL_PHONE) - .add(ConversationActions.TYPE_OPEN_URL) - .add(ConversationActions.TYPE_SEND_EMAIL) - .add(ConversationActions.TYPE_SEND_SMS) - .add(ConversationActions.TYPE_TRACK_FLIGHT) - .add(ConversationActions.TYPE_VIEW_CALENDAR) - .add(ConversationActions.TYPE_VIEW_MAP) + .add(ConversationAction.TYPE_TEXT_REPLY) + .add(ConversationAction.TYPE_CREATE_REMINDER) + .add(ConversationAction.TYPE_CALL_PHONE) + .add(ConversationAction.TYPE_OPEN_URL) + .add(ConversationAction.TYPE_SEND_EMAIL) + .add(ConversationAction.TYPE_SEND_SMS) + .add(ConversationAction.TYPE_TRACK_FLIGHT) + .add(ConversationAction.TYPE_VIEW_CALENDAR) + .add(ConversationAction.TYPE_VIEW_MAP) .toString(); private final boolean mSystemTextClassifierEnabled; diff --git a/core/java/android/view/textclassifier/TextClassifier.java b/core/java/android/view/textclassifier/TextClassifier.java index 8709e09bbf55..5a5613605e36 100644 --- a/core/java/android/view/textclassifier/TextClassifier.java +++ b/core/java/android/view/textclassifier/TextClassifier.java @@ -32,7 +32,6 @@ import android.text.style.URLSpan; import android.text.util.Linkify; import android.text.util.Linkify.LinkifyMask; import android.util.ArrayMap; -import android.util.ArraySet; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.Preconditions; @@ -43,6 +42,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; @@ -324,7 +324,7 @@ public interface TextClassifier { } /** - * Detects the language of the specified text. + * Detects the language of the text in the given request. * * <p><strong>NOTE: </strong>Call on a worker thread. * @@ -403,42 +403,59 @@ public interface TextClassifier { default void dump(@NonNull IndentingPrintWriter printWriter) {} /** - * Configuration object for specifying what entities to identify. + * Configuration object for specifying what entity types to identify. * * Configs are initially based on a predefined preset, and can be modified from there. */ final class EntityConfig implements Parcelable { - private final Collection<String> mHints; - private final Collection<String> mExcludedEntityTypes; - private final Collection<String> mIncludedEntityTypes; - private final boolean mUseHints; - - private EntityConfig(boolean useHints, Collection<String> hints, - Collection<String> includedEntityTypes, Collection<String> excludedEntityTypes) { - mHints = hints == null - ? Collections.EMPTY_LIST - : Collections.unmodifiableCollection(new ArraySet<>(hints)); - mExcludedEntityTypes = excludedEntityTypes == null - ? Collections.EMPTY_LIST : new ArraySet<>(excludedEntityTypes); - mIncludedEntityTypes = includedEntityTypes == null - ? Collections.EMPTY_LIST : new ArraySet<>(includedEntityTypes); - mUseHints = useHints; + private final List<String> mIncludedTypes; + private final List<String> mExcludedTypes; + private final List<String> mHints; + private final boolean mIncludeTypesFromTextClassifier; + + private EntityConfig( + List<String> includedEntityTypes, + List<String> excludedEntityTypes, + List<String> hints, + boolean includeTypesFromTextClassifier) { + mIncludedTypes = Preconditions.checkNotNull(includedEntityTypes); + mExcludedTypes = Preconditions.checkNotNull(excludedEntityTypes); + mHints = Preconditions.checkNotNull(hints); + mIncludeTypesFromTextClassifier = includeTypesFromTextClassifier; + } + + private EntityConfig(Parcel in) { + mIncludedTypes = new ArrayList<>(); + in.readStringList(mIncludedTypes); + mExcludedTypes = new ArrayList<>(); + in.readStringList(mExcludedTypes); + List<String> tmpHints = new ArrayList<>(); + in.readStringList(tmpHints); + mHints = Collections.unmodifiableList(tmpHints); + mIncludeTypesFromTextClassifier = in.readByte() != 0; + } + + @Override + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeStringList(mIncludedTypes); + parcel.writeStringList(mExcludedTypes); + parcel.writeStringList(mHints); + parcel.writeByte((byte) (mIncludeTypesFromTextClassifier ? 1 : 0)); } /** * Creates an EntityConfig. * * @param hints Hints for the TextClassifier to determine what types of entities to find. + * + * @deprecated Use {@link Builder} instead. */ + @Deprecated public static EntityConfig createWithHints(@Nullable Collection<String> hints) { - return new EntityConfig(/* useHints */ true, hints, - /* includedEntityTypes */null, /* excludedEntityTypes */ null); - } - - // TODO: Remove once apps can build against the latest sdk. - /** @hide */ - public static EntityConfig create(@Nullable Collection<String> hints) { - return createWithHints(hints); + return new EntityConfig.Builder() + .includeTypesFromTextClassifier(true) + .setHints(hints) + .build(); } /** @@ -450,12 +467,19 @@ public interface TextClassifier { * * * Note that if an entity has been excluded, the exclusion will take precedence. + * + * @deprecated Use {@link Builder} instead. */ + @Deprecated public static EntityConfig create(@Nullable Collection<String> hints, @Nullable Collection<String> includedEntityTypes, @Nullable Collection<String> excludedEntityTypes) { - return new EntityConfig(/* useHints */ true, hints, - includedEntityTypes, excludedEntityTypes); + return new EntityConfig.Builder() + .setIncludedTypes(includedEntityTypes) + .setExcludedTypes(excludedEntityTypes) + .setHints(hints) + .includeTypesFromTextClassifier(true) + .build(); } /** @@ -463,34 +487,33 @@ public interface TextClassifier { * * @param entityTypes Complete set of entities, e.g. {@link #TYPE_URL} to find. * + * @deprecated Use {@link Builder} instead. */ + @Deprecated public static EntityConfig createWithExplicitEntityList( @Nullable Collection<String> entityTypes) { - return new EntityConfig(/* useHints */ false, /* hints */ null, - /* includedEntityTypes */ entityTypes, /* excludedEntityTypes */ null); - } - - // TODO: Remove once apps can build against the latest sdk. - /** @hide */ - public static EntityConfig createWithEntityList(@Nullable Collection<String> entityTypes) { - return createWithExplicitEntityList(entityTypes); + return new EntityConfig.Builder() + .setIncludedTypes(entityTypes) + .includeTypesFromTextClassifier(false) + .build(); } /** - * Returns a list of the final set of entities to find. + * Returns a final list of entity types to find. * - * @param entities Entities we think should be found before factoring in includes/excludes + * @param entityTypes Entity types we think should be found before factoring in + * includes/excludes * * This method is intended for use by TextClassifier implementations. */ public Collection<String> resolveEntityListModifications( - @NonNull Collection<String> entities) { - final Set<String> finalSet = new HashSet(); - if (mUseHints) { - finalSet.addAll(entities); + @NonNull Collection<String> entityTypes) { + final Set<String> finalSet = new HashSet<>(); + if (mIncludeTypesFromTextClassifier) { + finalSet.addAll(entityTypes); } - finalSet.addAll(mIncludedEntityTypes); - finalSet.removeAll(mExcludedEntityTypes); + finalSet.addAll(mIncludedTypes); + finalSet.removeAll(mExcludedTypes); return finalSet; } @@ -503,17 +526,22 @@ public interface TextClassifier { return mHints; } - @Override - public int describeContents() { - return 0; + /** + * Return whether the client allows the text classifier to include its own list of + * default types. If this function returns {@code true}, a default list of types suggested + * from a text classifier will be taking into account. + * + * <p>NOTE: This method is intended for use by a text classifier. + * + * @see #resolveEntityListModifications(Collection) + */ + public boolean shouldIncludeTypesFromTextClassifier() { + return mIncludeTypesFromTextClassifier; } @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeStringList(new ArrayList<>(mHints)); - dest.writeStringList(new ArrayList<>(mExcludedEntityTypes)); - dest.writeStringList(new ArrayList<>(mIncludedEntityTypes)); - dest.writeInt(mUseHints ? 1 : 0); + public int describeContents() { + return 0; } public static final Parcelable.Creator<EntityConfig> CREATOR = @@ -529,11 +557,75 @@ public interface TextClassifier { } }; - private EntityConfig(Parcel in) { - mHints = new ArraySet<>(in.createStringArrayList()); - mExcludedEntityTypes = new ArraySet<>(in.createStringArrayList()); - mIncludedEntityTypes = new ArraySet<>(in.createStringArrayList()); - mUseHints = in.readInt() == 1; + + + /** Builder class to construct the {@link EntityConfig} object. */ + public static final class Builder { + @Nullable + private Collection<String> mIncludedTypes; + @Nullable + private Collection<String> mExcludedTypes; + @Nullable + private Collection<String> mHints; + private boolean mIncludeTypesFromTextClassifier = true; + + /** + * Sets a collection of types that are explicitly included. + */ + @NonNull + public Builder setIncludedTypes(@Nullable Collection<String> includedTypes) { + mIncludedTypes = includedTypes; + return this; + } + + /** + * Sets a collection of types that are explicitly excluded. + */ + @NonNull + public Builder setExcludedTypes(@Nullable Collection<String> excludedTypes) { + mExcludedTypes = excludedTypes; + return this; + } + + /** + * Specifies whether or not to include the types suggested by the text classifier. By + * default, it is included. + */ + @NonNull + public Builder includeTypesFromTextClassifier(boolean includeTypesFromTextClassifier) { + mIncludeTypesFromTextClassifier = includeTypesFromTextClassifier; + return this; + } + + + /** + * Sets the hints for the TextClassifier to determine what types of entities to find. + * These hints will only be used if {@link #includeTypesFromTextClassifier} is + * set to be true. + */ + public Builder setHints(Collection<String> hints) { + mHints = hints; + return this; + } + + /** + * Combines all of the options that have been set and returns a new {@link EntityConfig} + * object. + */ + @NonNull + public EntityConfig build() { + return new EntityConfig( + mIncludedTypes == null + ? Collections.emptyList() + : new ArrayList<>(mIncludedTypes), + mExcludedTypes == null + ? Collections.emptyList() + : new ArrayList<>(mExcludedTypes), + mHints == null + ? Collections.emptyList() + : Collections.unmodifiableList(new ArrayList<>(mHints)), + mIncludeTypesFromTextClassifier); + } } } diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java index d5b9eb1d09dc..9ab963e372b7 100644 --- a/core/java/android/view/textclassifier/TextClassifierImpl.java +++ b/core/java/android/view/textclassifier/TextClassifierImpl.java @@ -393,7 +393,7 @@ public final class TextClassifierImpl implements TextClassifier { actionsImpl.suggestActions(nativeConversation, null); Collection<String> expectedTypes = resolveActionTypesFromRequest(request); - List<ConversationActions.ConversationAction> conversationActions = new ArrayList<>(); + List<ConversationAction> conversationActions = new ArrayList<>(); int maxSuggestions = nativeSuggestions.length; if (request.getMaxSuggestions() > 0) { maxSuggestions = Math.min(request.getMaxSuggestions(), nativeSuggestions.length); @@ -405,7 +405,7 @@ public final class TextClassifierImpl implements TextClassifier { continue; } conversationActions.add( - new ConversationActions.ConversationAction.Builder(actionType) + new ConversationAction.Builder(actionType) .setTextReply(nativeSuggestion.getResponseText()) .setConfidenceScore(nativeSuggestion.getScore()) .build()); @@ -445,10 +445,10 @@ public final class TextClassifierImpl implements TextClassifier { private Collection<String> resolveActionTypesFromRequest(ConversationActions.Request request) { List<String> defaultActionTypes = - request.getHints().contains(ConversationActions.HINT_FOR_NOTIFICATION) + request.getHints().contains(ConversationActions.Request.HINT_FOR_NOTIFICATION) ? mSettings.getNotificationConversationActionTypes() : mSettings.getInAppConversationActionTypes(); - return request.getTypeConfig().resolveTypes(defaultActionTypes); + return request.getTypeConfig().resolveEntityListModifications(defaultActionTypes); } private AnnotatorModel getAnnotatorImpl(LocaleList localeList) |
