blob: 0d4338b0af6b46b547411ac03d9368b9f84f29a3 [file] [log] [blame]
/*
* Copyright 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 android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import com.android.internal.util.Preconditions;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
/**
* A text classifier event.
*/
// TODO: Comprehensive javadoc.
public final class TextClassifierEvent implements Parcelable {
public static final Creator<TextClassifierEvent> CREATOR = new Creator<TextClassifierEvent>() {
@Override
public TextClassifierEvent createFromParcel(Parcel in) {
return readFromParcel(in);
}
@Override
public TextClassifierEvent[] newArray(int size) {
return new TextClassifierEvent[size];
}
};
/** @hide **/
@Retention(RetentionPolicy.SOURCE)
@IntDef({CATEGORY_UNDEFINED, CATEGORY_SELECTION, CATEGORY_LINKIFY,
CATEGORY_CONVERSATION_ACTIONS, CATEGORY_LANGUAGE_DETECTION})
public @interface Category {
// For custom event categories, use range 1000+.
}
/** Undefined category */
public static final int CATEGORY_UNDEFINED = 0;
/** Smart selection */
public static final int CATEGORY_SELECTION = 1;
/** Linkify */
public static final int CATEGORY_LINKIFY = 2;
/** Conversation actions */
public static final int CATEGORY_CONVERSATION_ACTIONS = 3;
/** Language detection */
public static final int CATEGORY_LANGUAGE_DETECTION = 4;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef({TYPE_UNDEFINED, TYPE_SELECTION_STARTED, TYPE_SELECTION_MODIFIED,
TYPE_SMART_SELECTION_SINGLE, TYPE_SMART_SELECTION_MULTI, TYPE_AUTO_SELECTION,
TYPE_ACTIONS_SHOWN, TYPE_LINK_CLICKED, TYPE_OVERTYPE, TYPE_COPY_ACTION,
TYPE_PASTE_ACTION, TYPE_CUT_ACTION, TYPE_SHARE_ACTION, TYPE_SMART_ACTION,
TYPE_SELECTION_DRAG, TYPE_SELECTION_DESTROYED, TYPE_OTHER_ACTION, TYPE_SELECT_ALL,
TYPE_SELECTION_RESET, TYPE_MANUAL_REPLY, TYPE_ACTIONS_GENERATED})
public @interface Type {
// For custom event types, use range 1,000,000+.
}
/** User started a new selection. */
public static final int TYPE_UNDEFINED = 0;
/** User started a new selection. */
public static final int TYPE_SELECTION_STARTED = 1;
/** User modified an existing selection. */
public static final int TYPE_SELECTION_MODIFIED = 2;
/** Smart selection triggered for a single token (word). */
public static final int TYPE_SMART_SELECTION_SINGLE = 3;
/** Smart selection triggered spanning multiple tokens (words). */
public static final int TYPE_SMART_SELECTION_MULTI = 4;
/** Something else other than user or the default TextClassifier triggered a selection. */
public static final int TYPE_AUTO_SELECTION = 5;
/** Smart actions shown to the user. */
public static final int TYPE_ACTIONS_SHOWN = 6;
/** User clicked a link. */
public static final int TYPE_LINK_CLICKED = 7;
/** User typed over the selection. */
public static final int TYPE_OVERTYPE = 8;
/** User clicked on Copy action. */
public static final int TYPE_COPY_ACTION = 9;
/** User clicked on Paste action. */
public static final int TYPE_PASTE_ACTION = 10;
/** User clicked on Cut action. */
public static final int TYPE_CUT_ACTION = 11;
/** User clicked on Share action. */
public static final int TYPE_SHARE_ACTION = 12;
/** User clicked on a Smart action. */
public static final int TYPE_SMART_ACTION = 13;
/** User dragged+dropped the selection. */
public static final int TYPE_SELECTION_DRAG = 14;
/** Selection is destroyed. */
public static final int TYPE_SELECTION_DESTROYED = 15;
/** User clicked on a custom action. */
public static final int TYPE_OTHER_ACTION = 16;
/** User clicked on Select All action */
public static final int TYPE_SELECT_ALL = 17;
/** User reset the smart selection. */
public static final int TYPE_SELECTION_RESET = 18;
/** User composed a reply. */
public static final int TYPE_MANUAL_REPLY = 19;
/** TextClassifier generated some actions */
public static final int TYPE_ACTIONS_GENERATED = 20;
@Category private final int mEventCategory;
@Type private final int mEventType;
@Nullable private final String[] mEntityTypes;
@Nullable private final TextClassificationContext mEventContext;
@Nullable private final String mResultId;
private final int mEventIndex;
private final long mEventTime;
private final Bundle mExtras;
// Smart selection.
private final int mRelativeWordStartIndex;
private final int mRelativeWordEndIndex;
private final int mRelativeSuggestedWordStartIndex;
private final int mRelativeSuggestedWordEndIndex;
// Smart action.
private final int[] mActionIndices;
// Language detection.
@Nullable private final String mLanguage;
private final float mScore;
@Nullable private final String mModelName;
private TextClassifierEvent(
int eventCategory,
int eventType,
String[] entityTypes,
TextClassificationContext eventContext,
String resultId,
int eventIndex,
long eventTime,
Bundle extras,
int relativeWordStartIndex,
int relativeWordEndIndex,
int relativeSuggestedWordStartIndex,
int relativeSuggestedWordEndIndex,
int[] actionIndex,
String language,
float score,
String modelVersion) {
mEventCategory = eventCategory;
mEventType = eventType;
mEntityTypes = entityTypes;
mEventContext = eventContext;
mResultId = resultId;
mEventIndex = eventIndex;
mEventTime = eventTime;
mExtras = extras;
mRelativeWordStartIndex = relativeWordStartIndex;
mRelativeWordEndIndex = relativeWordEndIndex;
mRelativeSuggestedWordStartIndex = relativeSuggestedWordStartIndex;
mRelativeSuggestedWordEndIndex = relativeSuggestedWordEndIndex;
mActionIndices = actionIndex;
mLanguage = language;
mScore = score;
mModelName = modelVersion;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mEventCategory);
dest.writeInt(mEventType);
dest.writeStringArray(mEntityTypes);
dest.writeParcelable(mEventContext, flags);
dest.writeString(mResultId);
dest.writeInt(mEventIndex);
dest.writeLong(mEventTime);
dest.writeBundle(mExtras);
dest.writeInt(mRelativeWordStartIndex);
dest.writeInt(mRelativeWordEndIndex);
dest.writeInt(mRelativeSuggestedWordStartIndex);
dest.writeInt(mRelativeSuggestedWordEndIndex);
dest.writeIntArray(mActionIndices);
dest.writeString(mLanguage);
dest.writeFloat(mScore);
dest.writeString(mModelName);
}
private static TextClassifierEvent readFromParcel(Parcel in) {
return new TextClassifierEvent(
/* eventCategory= */ in.readInt(),
/* eventType= */ in.readInt(),
/* entityTypes=*/ in.readStringArray(),
/* eventContext= */ in.readParcelable(null),
/* resultId= */ in.readString(),
/* eventIndex= */ in.readInt(),
/* eventTime= */ in.readLong(),
/* extras= */ in.readBundle(),
/* relativeWordStartIndex= */ in.readInt(),
/* relativeWordEndIndex= */ in.readInt(),
/* relativeSuggestedWordStartIndex= */ in.readInt(),
/* relativeSuggestedWordEndIndex= */ in.readInt(),
/* actionIndices= */ in.createIntArray(),
/* language= */ in.readString(),
/* score= */ in.readFloat(),
/* modelVersion= */ in.readString());
}
/**
* Returns the event category. e.g. {@link #CATEGORY_SELECTION}.
*/
@Category
public int getEventCategory() {
return mEventCategory;
}
/**
* Returns the event type. e.g. {@link #TYPE_SELECTION_STARTED}.
*/
@Type
public int getEventType() {
return mEventType;
}
/**
* Returns an array of entity types. e.g. {@link TextClassifier#TYPE_ADDRESS}.
*/
@NonNull
public String[] getEntityTypes() {
return mEntityTypes;
}
/**
* Returns the event context.
*/
@Nullable
public TextClassificationContext getEventContext() {
return mEventContext;
}
/**
* Returns the id of the text classifier result related to this event.
*/
@Nullable
public String getResultId() {
return mResultId;
}
/**
* Returns the index of this event in the series of event it belongs to.
*/
public int getEventIndex() {
return mEventIndex;
}
// TODO: Remove this API.
/**
* Returns the time this event occurred. This is the number of milliseconds since
* January 1, 1970, 00:00:00 GMT. 0 indicates not set.
*/
public long getEventTime() {
return mEventTime;
}
/**
* Returns a bundle containing non-structured extra information about this event.
*
* <p><b>NOTE: </b>Do not modify this bundle.
*/
@NonNull
public Bundle getExtras() {
return mExtras;
}
/**
* For smart selection. Returns the relative word index of the start of the selection.
*/
public int getRelativeWordStartIndex() {
return mRelativeWordStartIndex;
}
/**
* For smart selection. Returns the relative word (exclusive) index of the end of the selection.
*/
public int getRelativeWordEndIndex() {
return mRelativeWordEndIndex;
}
/**
* For smart selection. Returns the relative word index of the start of the smart selection.
*/
public int getRelativeSuggestedWordStartIndex() {
return mRelativeSuggestedWordStartIndex;
}
/**
* For smart selection. Returns the relative word (exclusive) index of the end of the
* smart selection.
*/
public int getRelativeSuggestedWordEndIndex() {
return mRelativeSuggestedWordEndIndex;
}
/**
* Returns the indices of the actions relating to this event.
* Actions are usually returned by the text classifier in priority order with the most
* preferred action at index 0. This list gives an indication of the position of the actions
* that are being reported.
*/
@NonNull
public int[] getActionIndices() {
return mActionIndices;
}
/**
* For language detection. Returns the language tag for the detected locale.
* @see java.util.Locale#forLanguageTag(String).
*/
@Nullable
public String getLanguage() {
return mLanguage;
}
/**
* Returns the score of the suggestion.
*/
public float getScore() {
return mScore;
}
/**
* Returns the model name.
* @hide
*/
@Nullable
public String getModelName() {
return mModelName;
}
/**
* Builder to build a text classifier event.
*/
public static final class Builder {
private final int mEventCategory;
private final int mEventType;
private String[] mEntityTypes = new String[0];
@Nullable private TextClassificationContext mEventContext;
@Nullable private String mResultId;
private int mEventIndex;
private long mEventTime;
@Nullable private Bundle mExtras;
private int mRelativeWordStartIndex;
private int mRelativeWordEndIndex;
private int mRelativeSuggestedWordStartIndex;
private int mRelativeSuggestedWordEndIndex;
private int[] mActionIndices = new int[0];
@Nullable private String mLanguage;
private float mScore;
private String mModelName;
/**
* Creates a builder for building {@link TextClassifierEvent}s.
*
* @param eventCategory The event category. e.g. {@link #CATEGORY_SELECTION}
* @param eventType The event type. e.g. {@link #TYPE_SELECTION_STARTED}
*/
public Builder(@Category int eventCategory, @Type int eventType) {
mEventCategory = eventCategory;
mEventType = eventType;
}
/**
* Sets the entity types. e.g. {@link TextClassifier#TYPE_ADDRESS}.
*/
@NonNull
public Builder setEntityTypes(@NonNull String... entityTypes) {
mEntityTypes = new String[entityTypes.length];
System.arraycopy(entityTypes, 0, mEntityTypes, 0, entityTypes.length);
return this;
}
/**
* Sets the event context.
*/
@NonNull
public Builder setEventContext(@Nullable TextClassificationContext eventContext) {
mEventContext = eventContext;
return this;
}
/**
* Sets the id of the text classifier result related to this event.
*/
@NonNull
public Builder setResultId(@Nullable String resultId) {
mResultId = resultId;
return this;
}
/**
* Sets the index of this events in the series of events it belongs to.
*/
@NonNull
public Builder setEventIndex(int eventIndex) {
mEventIndex = eventIndex;
return this;
}
// TODO: Remove this API.
/**
* Sets the time this event occurred. This is the number of milliseconds since
* January 1, 1970, 00:00:00 GMT. 0 indicates not set.
*/
@NonNull
public Builder setEventTime(long eventTime) {
mEventTime = eventTime;
return this;
}
/**
* Sets a bundle containing non-structured extra information about the event.
*
* <p><b>NOTE: </b>Prefer to set only immutable values on the bundle otherwise, avoid
* updating the internals of this bundle as it may have unexpected consequences on the
* clients of the built event object. For similar reasons, avoid depending on mutable
* objects in this bundle.
*/
@NonNull
public Builder setExtras(@NonNull Bundle extras) {
mExtras = Preconditions.checkNotNull(extras);
return this;
}
/**
* For smart selection. Sets the relative word index of the start of the selection.
*/
@NonNull
public Builder setRelativeWordStartIndex(int relativeWordStartIndex) {
mRelativeWordStartIndex = relativeWordStartIndex;
return this;
}
/**
* For smart selection. Sets the relative word (exclusive) index of the end of the
* selection.
*/
@NonNull
public Builder setRelativeWordEndIndex(int relativeWordEndIndex) {
mRelativeWordEndIndex = relativeWordEndIndex;
return this;
}
/**
* For smart selection. Sets the relative word index of the start of the smart selection.
*/
@NonNull
public Builder setRelativeSuggestedWordStartIndex(int relativeSuggestedWordStartIndex) {
mRelativeSuggestedWordStartIndex = relativeSuggestedWordStartIndex;
return this;
}
/**
* For smart selection. Sets the relative word (exclusive) index of the end of the
* smart selection.
*/
@NonNull
public Builder setRelativeSuggestedWordEndIndex(int relativeSuggestedWordEndIndex) {
mRelativeSuggestedWordEndIndex = relativeSuggestedWordEndIndex;
return this;
}
/**
* Sets the indices of the actions involved in this event. Actions are usually returned by
* the text classifier in priority order with the most preferred action at index 0.
* This index gives an indication of the position of the action that is being reported.
*/
@NonNull
public Builder setActionIndices(@NonNull int... actionIndices) {
mActionIndices = new int[actionIndices.length];
System.arraycopy(actionIndices, 0, mActionIndices, 0, actionIndices.length);
return this;
}
/**
* For language detection. Sets the language tag for the detected locale.
* @see java.util.Locale#forLanguageTag(String).
*/
@NonNull
public Builder setLanguage(@Nullable String language) {
mLanguage = language;
return this;
}
/**
* Sets the score of the suggestion.
*/
@NonNull
public Builder setScore(float score) {
mScore = score;
return this;
}
/**
* Sets the model name string.
* @hide
*/
public Builder setModelName(@Nullable String modelVersion) {
mModelName = modelVersion;
return this;
}
/**
* Builds and returns a text classifier event.
*/
@NonNull
public TextClassifierEvent build() {
mExtras = mExtras == null ? Bundle.EMPTY : mExtras;
return new TextClassifierEvent(
mEventCategory,
mEventType,
mEntityTypes,
mEventContext,
mResultId,
mEventIndex,
mEventTime,
mExtras,
mRelativeWordStartIndex,
mRelativeWordEndIndex,
mRelativeSuggestedWordStartIndex,
mRelativeSuggestedWordEndIndex,
mActionIndices,
mLanguage,
mScore,
mModelName);
}
// TODO: Add build(boolean validate).
}
@Override
public String toString() {
StringBuilder out = new StringBuilder(128);
out.append("TextClassifierEvent{");
out.append("mEventCategory=").append(mEventCategory);
out.append(", mEventTypes=").append(Arrays.toString(mEntityTypes));
out.append(", mEventContext=").append(mEventContext);
out.append(", mResultId=").append(mResultId);
out.append(", mEventIndex=").append(mEventIndex);
out.append(", mEventTime=").append(mEventTime);
out.append(", mExtras=").append(mExtras);
out.append(", mRelativeWordStartIndex=").append(mRelativeWordStartIndex);
out.append(", mRelativeWordEndIndex=").append(mRelativeWordEndIndex);
out.append(", mRelativeSuggestedWordStartIndex=").append(mRelativeSuggestedWordStartIndex);
out.append(", mRelativeSuggestedWordEndIndex=").append(mRelativeSuggestedWordEndIndex);
out.append(", mActionIndices=").append(Arrays.toString(mActionIndices));
out.append(", mLanguage=").append(mLanguage);
out.append(", mScore=").append(mScore);
out.append(", mModelName=").append(mModelName);
out.append("}");
return out.toString();
}
}