diff options
| author | 2017-01-04 23:51:42 +0000 | |
|---|---|---|
| committer | 2017-01-24 15:01:24 +0000 | |
| commit | f001fefff3745c29e2ff6903d69ad921df1ea277 (patch) | |
| tree | 416a91a913e252f2e27b461d35467623231e0b6e | |
| parent | 2536cc6872ecdc43d7e9b07a02fbc844e5f124bb (diff) | |
Update TextAssistant interface.
Rename to TextClassifier
Move to android.view.textclassifier package
Adds getTextClassifierInfo(...)
Changes addLinks(...) to getLinks(...)
This CL also integrates this interface with framework components
and passes a context to TextClassificationManager.
Test: Tests will be added with implementation.
Bug: 34661057
Change-Id: If9e90f034ebb702c1f78e72b6a844f39eebf738f
22 files changed, 1169 insertions, 488 deletions
diff --git a/api/current.txt b/api/current.txt index bca65ee5e0bf..cb6939fee4cc 100644 --- a/api/current.txt +++ b/api/current.txt @@ -1817,6 +1817,7 @@ package android { field public static final int tabs = 16908307; // 0x1020013 field public static final int text1 = 16908308; // 0x1020014 field public static final int text2 = 16908309; // 0x1020015 + field public static final int textAssist = 16908353; // 0x1020041 field public static final int title = 16908310; // 0x1020016 field public static final int toggle = 16908311; // 0x1020017 field public static final int undo = 16908338; // 0x1020032 @@ -3536,7 +3537,6 @@ package android.app { method public int getRequestedOrientation(); method public final android.view.SearchEvent getSearchEvent(); method public int getTaskId(); - method public android.text.TextAssistant getTextAssistant(); method public final java.lang.CharSequence getTitle(); method public final int getTitleColor(); method public android.app.VoiceInteractor getVoiceInteractor(); @@ -3686,7 +3686,6 @@ package android.app { method public final void setResult(int, android.content.Intent); method public final deprecated void setSecondaryProgress(int); method public void setTaskDescription(android.app.ActivityManager.TaskDescription); - method public void setTextAssistant(android.text.TextAssistant); method public void setTitle(java.lang.CharSequence); method public void setTitle(int); method public deprecated void setTitleColor(int); @@ -39900,22 +39899,6 @@ package android.text { method public android.text.StaticLayout.Builder setTextDirection(android.text.TextDirectionHeuristic); } - public abstract interface TextAssistant { - method public abstract void addLinks(android.text.Spannable, int); - method public abstract android.text.TextSelection suggestSelection(java.lang.CharSequence, int, int); - } - - public class TextClassification { - ctor public TextClassification(); - method public java.util.Map<java.lang.String, java.lang.Float> getTypeConfidence(); - } - - public final class TextClassificationManager implements android.text.TextAssistant { - method public void addLinks(android.text.Spannable, int); - method public java.util.List<android.text.TextLanguage> detectLanguages(java.lang.CharSequence); - method public android.text.TextSelection suggestSelection(java.lang.CharSequence, int, int); - } - public abstract interface TextDirectionHeuristic { method public abstract boolean isRtl(char[], int, int); method public abstract boolean isRtl(java.lang.CharSequence, int, int); @@ -39931,13 +39914,6 @@ package android.text { field public static final android.text.TextDirectionHeuristic RTL; } - public final class TextLanguage { - ctor public TextLanguage(int, int, java.util.Map<java.lang.String, java.lang.Float>); - method public int getEndIndex(); - method public java.util.Map<java.lang.String, java.lang.Float> getLanguageConfidence(); - method public int getStartIndex(); - } - public class TextPaint extends android.graphics.Paint { ctor public TextPaint(); ctor public TextPaint(int); @@ -39950,13 +39926,6 @@ package android.text { field public int linkColor; } - public class TextSelection { - ctor public TextSelection(); - method public int getSelectionEndIndex(); - method public int getSelectionStartIndex(); - method public android.text.TextClassification getTextClassification(); - } - public class TextUtils { method public static deprecated java.lang.CharSequence commaEllipsize(java.lang.CharSequence, android.text.TextPaint, float, java.lang.String, java.lang.String); method public static java.lang.CharSequence concat(java.lang.CharSequence...); @@ -46472,6 +46441,83 @@ package android.view.inputmethod { } +package android.view.textclassifier { + + public abstract interface LinksInfo { + method public abstract boolean apply(java.lang.CharSequence); + } + + public final class TextClassificationManager { + method public java.util.List<android.view.textclassifier.TextLanguage> detectLanguages(java.lang.CharSequence); + method public android.view.textclassifier.TextClassifier getDefaultTextClassifier(); + } + + public final class TextClassificationResult { + method public float getConfidenceScore(java.lang.String); + method public java.lang.String getEntity(int); + method public int getEntityCount(); + method public android.graphics.drawable.Drawable getIcon(); + method public android.content.Intent getIntent(); + method public java.lang.CharSequence getLabel(); + method public android.view.View.OnClickListener getOnClickListener(); + method public java.lang.String getText(); + } + + public static final class TextClassificationResult.Builder { + ctor public TextClassificationResult.Builder(); + method public android.view.textclassifier.TextClassificationResult build(); + method public android.view.textclassifier.TextClassificationResult.Builder setEntityType(java.lang.String, float); + method public android.view.textclassifier.TextClassificationResult.Builder setIcon(android.graphics.drawable.Drawable); + method public android.view.textclassifier.TextClassificationResult.Builder setIntent(android.content.Intent); + method public android.view.textclassifier.TextClassificationResult.Builder setLabel(java.lang.String); + method public android.view.textclassifier.TextClassificationResult.Builder setOnClickListener(android.view.View.OnClickListener); + method public android.view.textclassifier.TextClassificationResult.Builder setText(java.lang.String); + } + + public abstract interface TextClassifier { + method public abstract android.view.textclassifier.LinksInfo getLinks(java.lang.CharSequence, int); + method public abstract android.view.textclassifier.TextClassificationResult getTextClassificationResult(java.lang.CharSequence, int, int); + method public abstract android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int); + field public static final android.view.textclassifier.TextClassifier NO_OP; + field public static final java.lang.String TYPE_ADDRESS = "address"; + field public static final java.lang.String TYPE_EMAIL = "email"; + field public static final java.lang.String TYPE_OTHER = "other"; + field public static final java.lang.String TYPE_PHONE = "phone"; + } + + public static abstract class TextClassifier.EntityType implements java.lang.annotation.Annotation { + } + + public final class TextLanguage { + method public float getConfidenceScore(java.util.Locale); + method public int getEndIndex(); + method public java.util.Locale getLanguage(int); + method public int getLanguageCount(); + method public int getStartIndex(); + } + + public static final class TextLanguage.Builder { + ctor public TextLanguage.Builder(int, int); + method public android.view.textclassifier.TextLanguage build(); + method public android.view.textclassifier.TextLanguage.Builder setLanguage(java.util.Locale, float); + } + + public final class TextSelection { + method public float getConfidenceScore(java.lang.String); + method public java.lang.String getEntity(int); + method public int getEntityCount(); + method public int getSelectionEndIndex(); + method public int getSelectionStartIndex(); + } + + public static final class TextSelection.Builder { + ctor public TextSelection.Builder(int, int); + method public android.view.textclassifier.TextSelection build(); + method public android.view.textclassifier.TextSelection.Builder setEntityType(java.lang.String, float); + } + +} + package android.view.textservice { public final class SentenceSuggestionsInfo implements android.os.Parcelable { @@ -49561,7 +49607,7 @@ package android.widget { method public float getShadowRadius(); method public final boolean getShowSoftInputOnFocus(); method public java.lang.CharSequence getText(); - method public android.text.TextAssistant getTextAssistant(); + method public android.view.textclassifier.TextClassifier getTextClassifier(); method public final android.content.res.ColorStateList getTextColors(); method public java.util.Locale getTextLocale(); method public android.os.LocaleList getTextLocales(); @@ -49677,7 +49723,7 @@ package android.widget { method public final void setText(int, android.widget.TextView.BufferType); method public void setTextAppearance(int); method public deprecated void setTextAppearance(android.content.Context, int); - method public void setTextAssistant(android.text.TextAssistant); + method public void setTextClassifier(android.view.textclassifier.TextClassifier); method public void setTextColor(int); method public void setTextColor(android.content.res.ColorStateList); method public void setTextIsSelectable(boolean); diff --git a/api/system-current.txt b/api/system-current.txt index 53552fc8cd6e..bab36735a922 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -1930,6 +1930,7 @@ package android { field public static final int tabs = 16908307; // 0x1020013 field public static final int text1 = 16908308; // 0x1020014 field public static final int text2 = 16908309; // 0x1020015 + field public static final int textAssist = 16908353; // 0x1020041 field public static final int title = 16908310; // 0x1020016 field public static final int toggle = 16908311; // 0x1020017 field public static final int undo = 16908338; // 0x1020032 @@ -3655,7 +3656,6 @@ package android.app { method public int getRequestedOrientation(); method public final android.view.SearchEvent getSearchEvent(); method public int getTaskId(); - method public android.text.TextAssistant getTextAssistant(); method public final java.lang.CharSequence getTitle(); method public final int getTitleColor(); method public android.app.VoiceInteractor getVoiceInteractor(); @@ -3807,7 +3807,6 @@ package android.app { method public final void setResult(int, android.content.Intent); method public final deprecated void setSecondaryProgress(int); method public void setTaskDescription(android.app.ActivityManager.TaskDescription); - method public void setTextAssistant(android.text.TextAssistant); method public void setTitle(java.lang.CharSequence); method public void setTitle(int); method public deprecated void setTitleColor(int); @@ -43201,22 +43200,6 @@ package android.text { method public android.text.StaticLayout.Builder setTextDirection(android.text.TextDirectionHeuristic); } - public abstract interface TextAssistant { - method public abstract void addLinks(android.text.Spannable, int); - method public abstract android.text.TextSelection suggestSelection(java.lang.CharSequence, int, int); - } - - public class TextClassification { - ctor public TextClassification(); - method public java.util.Map<java.lang.String, java.lang.Float> getTypeConfidence(); - } - - public final class TextClassificationManager implements android.text.TextAssistant { - method public void addLinks(android.text.Spannable, int); - method public java.util.List<android.text.TextLanguage> detectLanguages(java.lang.CharSequence); - method public android.text.TextSelection suggestSelection(java.lang.CharSequence, int, int); - } - public abstract interface TextDirectionHeuristic { method public abstract boolean isRtl(char[], int, int); method public abstract boolean isRtl(java.lang.CharSequence, int, int); @@ -43232,13 +43215,6 @@ package android.text { field public static final android.text.TextDirectionHeuristic RTL; } - public final class TextLanguage { - ctor public TextLanguage(int, int, java.util.Map<java.lang.String, java.lang.Float>); - method public int getEndIndex(); - method public java.util.Map<java.lang.String, java.lang.Float> getLanguageConfidence(); - method public int getStartIndex(); - } - public class TextPaint extends android.graphics.Paint { ctor public TextPaint(); ctor public TextPaint(int); @@ -43251,13 +43227,6 @@ package android.text { field public int linkColor; } - public class TextSelection { - ctor public TextSelection(); - method public int getSelectionEndIndex(); - method public int getSelectionStartIndex(); - method public android.text.TextClassification getTextClassification(); - } - public class TextUtils { method public static deprecated java.lang.CharSequence commaEllipsize(java.lang.CharSequence, android.text.TextPaint, float, java.lang.String, java.lang.String); method public static java.lang.CharSequence concat(java.lang.CharSequence...); @@ -49777,6 +49746,83 @@ package android.view.inputmethod { } +package android.view.textclassifier { + + public abstract interface LinksInfo { + method public abstract boolean apply(java.lang.CharSequence); + } + + public final class TextClassificationManager { + method public java.util.List<android.view.textclassifier.TextLanguage> detectLanguages(java.lang.CharSequence); + method public android.view.textclassifier.TextClassifier getDefaultTextClassifier(); + } + + public final class TextClassificationResult { + method public float getConfidenceScore(java.lang.String); + method public java.lang.String getEntity(int); + method public int getEntityCount(); + method public android.graphics.drawable.Drawable getIcon(); + method public android.content.Intent getIntent(); + method public java.lang.CharSequence getLabel(); + method public android.view.View.OnClickListener getOnClickListener(); + method public java.lang.String getText(); + } + + public static final class TextClassificationResult.Builder { + ctor public TextClassificationResult.Builder(); + method public android.view.textclassifier.TextClassificationResult build(); + method public android.view.textclassifier.TextClassificationResult.Builder setEntityType(java.lang.String, float); + method public android.view.textclassifier.TextClassificationResult.Builder setIcon(android.graphics.drawable.Drawable); + method public android.view.textclassifier.TextClassificationResult.Builder setIntent(android.content.Intent); + method public android.view.textclassifier.TextClassificationResult.Builder setLabel(java.lang.String); + method public android.view.textclassifier.TextClassificationResult.Builder setOnClickListener(android.view.View.OnClickListener); + method public android.view.textclassifier.TextClassificationResult.Builder setText(java.lang.String); + } + + public abstract interface TextClassifier { + method public abstract android.view.textclassifier.LinksInfo getLinks(java.lang.CharSequence, int); + method public abstract android.view.textclassifier.TextClassificationResult getTextClassificationResult(java.lang.CharSequence, int, int); + method public abstract android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int); + field public static final android.view.textclassifier.TextClassifier NO_OP; + field public static final java.lang.String TYPE_ADDRESS = "address"; + field public static final java.lang.String TYPE_EMAIL = "email"; + field public static final java.lang.String TYPE_OTHER = "other"; + field public static final java.lang.String TYPE_PHONE = "phone"; + } + + public static abstract class TextClassifier.EntityType implements java.lang.annotation.Annotation { + } + + public final class TextLanguage { + method public float getConfidenceScore(java.util.Locale); + method public int getEndIndex(); + method public java.util.Locale getLanguage(int); + method public int getLanguageCount(); + method public int getStartIndex(); + } + + public static final class TextLanguage.Builder { + ctor public TextLanguage.Builder(int, int); + method public android.view.textclassifier.TextLanguage build(); + method public android.view.textclassifier.TextLanguage.Builder setLanguage(java.util.Locale, float); + } + + public final class TextSelection { + method public float getConfidenceScore(java.lang.String); + method public java.lang.String getEntity(int); + method public int getEntityCount(); + method public int getSelectionEndIndex(); + method public int getSelectionStartIndex(); + } + + public static final class TextSelection.Builder { + ctor public TextSelection.Builder(int, int); + method public android.view.textclassifier.TextSelection build(); + method public android.view.textclassifier.TextSelection.Builder setEntityType(java.lang.String, float); + } + +} + package android.view.textservice { public final class SentenceSuggestionsInfo implements android.os.Parcelable { @@ -53227,7 +53273,7 @@ package android.widget { method public float getShadowRadius(); method public final boolean getShowSoftInputOnFocus(); method public java.lang.CharSequence getText(); - method public android.text.TextAssistant getTextAssistant(); + method public android.view.textclassifier.TextClassifier getTextClassifier(); method public final android.content.res.ColorStateList getTextColors(); method public java.util.Locale getTextLocale(); method public android.os.LocaleList getTextLocales(); @@ -53343,7 +53389,7 @@ package android.widget { method public final void setText(int, android.widget.TextView.BufferType); method public void setTextAppearance(int); method public deprecated void setTextAppearance(android.content.Context, int); - method public void setTextAssistant(android.text.TextAssistant); + method public void setTextClassifier(android.view.textclassifier.TextClassifier); method public void setTextColor(int); method public void setTextColor(android.content.res.ColorStateList); method public void setTextIsSelectable(boolean); diff --git a/api/test-current.txt b/api/test-current.txt index d18af4c5b297..9a58df2ec822 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -1817,6 +1817,7 @@ package android { field public static final int tabs = 16908307; // 0x1020013 field public static final int text1 = 16908308; // 0x1020014 field public static final int text2 = 16908309; // 0x1020015 + field public static final int textAssist = 16908353; // 0x1020041 field public static final int title = 16908310; // 0x1020016 field public static final int toggle = 16908311; // 0x1020017 field public static final int undo = 16908338; // 0x1020032 @@ -3538,7 +3539,6 @@ package android.app { method public int getRequestedOrientation(); method public final android.view.SearchEvent getSearchEvent(); method public int getTaskId(); - method public android.text.TextAssistant getTextAssistant(); method public final java.lang.CharSequence getTitle(); method public final int getTitleColor(); method public android.app.VoiceInteractor getVoiceInteractor(); @@ -3688,7 +3688,6 @@ package android.app { method public final void setResult(int, android.content.Intent); method public final deprecated void setSecondaryProgress(int); method public void setTaskDescription(android.app.ActivityManager.TaskDescription); - method public void setTextAssistant(android.text.TextAssistant); method public void setTitle(java.lang.CharSequence); method public void setTitle(int); method public deprecated void setTitleColor(int); @@ -40024,22 +40023,6 @@ package android.text { method public android.text.StaticLayout.Builder setTextDirection(android.text.TextDirectionHeuristic); } - public abstract interface TextAssistant { - method public abstract void addLinks(android.text.Spannable, int); - method public abstract android.text.TextSelection suggestSelection(java.lang.CharSequence, int, int); - } - - public class TextClassification { - ctor public TextClassification(); - method public java.util.Map<java.lang.String, java.lang.Float> getTypeConfidence(); - } - - public final class TextClassificationManager implements android.text.TextAssistant { - method public void addLinks(android.text.Spannable, int); - method public java.util.List<android.text.TextLanguage> detectLanguages(java.lang.CharSequence); - method public android.text.TextSelection suggestSelection(java.lang.CharSequence, int, int); - } - public abstract interface TextDirectionHeuristic { method public abstract boolean isRtl(char[], int, int); method public abstract boolean isRtl(java.lang.CharSequence, int, int); @@ -40055,13 +40038,6 @@ package android.text { field public static final android.text.TextDirectionHeuristic RTL; } - public final class TextLanguage { - ctor public TextLanguage(int, int, java.util.Map<java.lang.String, java.lang.Float>); - method public int getEndIndex(); - method public java.util.Map<java.lang.String, java.lang.Float> getLanguageConfidence(); - method public int getStartIndex(); - } - public class TextPaint extends android.graphics.Paint { ctor public TextPaint(); ctor public TextPaint(int); @@ -40074,13 +40050,6 @@ package android.text { field public int linkColor; } - public class TextSelection { - ctor public TextSelection(); - method public int getSelectionEndIndex(); - method public int getSelectionStartIndex(); - method public android.text.TextClassification getTextClassification(); - } - public class TextUtils { method public static deprecated java.lang.CharSequence commaEllipsize(java.lang.CharSequence, android.text.TextPaint, float, java.lang.String, java.lang.String); method public static java.lang.CharSequence concat(java.lang.CharSequence...); @@ -46770,6 +46739,83 @@ package android.view.inputmethod { } +package android.view.textclassifier { + + public abstract interface LinksInfo { + method public abstract boolean apply(java.lang.CharSequence); + } + + public final class TextClassificationManager { + method public java.util.List<android.view.textclassifier.TextLanguage> detectLanguages(java.lang.CharSequence); + method public android.view.textclassifier.TextClassifier getDefaultTextClassifier(); + } + + public final class TextClassificationResult { + method public float getConfidenceScore(java.lang.String); + method public java.lang.String getEntity(int); + method public int getEntityCount(); + method public android.graphics.drawable.Drawable getIcon(); + method public android.content.Intent getIntent(); + method public java.lang.CharSequence getLabel(); + method public android.view.View.OnClickListener getOnClickListener(); + method public java.lang.String getText(); + } + + public static final class TextClassificationResult.Builder { + ctor public TextClassificationResult.Builder(); + method public android.view.textclassifier.TextClassificationResult build(); + method public android.view.textclassifier.TextClassificationResult.Builder setEntityType(java.lang.String, float); + method public android.view.textclassifier.TextClassificationResult.Builder setIcon(android.graphics.drawable.Drawable); + method public android.view.textclassifier.TextClassificationResult.Builder setIntent(android.content.Intent); + method public android.view.textclassifier.TextClassificationResult.Builder setLabel(java.lang.String); + method public android.view.textclassifier.TextClassificationResult.Builder setOnClickListener(android.view.View.OnClickListener); + method public android.view.textclassifier.TextClassificationResult.Builder setText(java.lang.String); + } + + public abstract interface TextClassifier { + method public abstract android.view.textclassifier.LinksInfo getLinks(java.lang.CharSequence, int); + method public abstract android.view.textclassifier.TextClassificationResult getTextClassificationResult(java.lang.CharSequence, int, int); + method public abstract android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int); + field public static final android.view.textclassifier.TextClassifier NO_OP; + field public static final java.lang.String TYPE_ADDRESS = "address"; + field public static final java.lang.String TYPE_EMAIL = "email"; + field public static final java.lang.String TYPE_OTHER = "other"; + field public static final java.lang.String TYPE_PHONE = "phone"; + } + + public static abstract class TextClassifier.EntityType implements java.lang.annotation.Annotation { + } + + public final class TextLanguage { + method public float getConfidenceScore(java.util.Locale); + method public int getEndIndex(); + method public java.util.Locale getLanguage(int); + method public int getLanguageCount(); + method public int getStartIndex(); + } + + public static final class TextLanguage.Builder { + ctor public TextLanguage.Builder(int, int); + method public android.view.textclassifier.TextLanguage build(); + method public android.view.textclassifier.TextLanguage.Builder setLanguage(java.util.Locale, float); + } + + public final class TextSelection { + method public float getConfidenceScore(java.lang.String); + method public java.lang.String getEntity(int); + method public int getEntityCount(); + method public int getSelectionEndIndex(); + method public int getSelectionStartIndex(); + } + + public static final class TextSelection.Builder { + ctor public TextSelection.Builder(int, int); + method public android.view.textclassifier.TextSelection build(); + method public android.view.textclassifier.TextSelection.Builder setEntityType(java.lang.String, float); + } + +} + package android.view.textservice { public final class SentenceSuggestionsInfo implements android.os.Parcelable { @@ -49866,7 +49912,7 @@ package android.widget { method public float getShadowRadius(); method public final boolean getShowSoftInputOnFocus(); method public java.lang.CharSequence getText(); - method public android.text.TextAssistant getTextAssistant(); + method public android.view.textclassifier.TextClassifier getTextClassifier(); method public final android.content.res.ColorStateList getTextColors(); method public java.util.Locale getTextLocale(); method public android.os.LocaleList getTextLocales(); @@ -49982,7 +50028,7 @@ package android.widget { method public final void setText(int, android.widget.TextView.BufferType); method public void setTextAppearance(int); method public deprecated void setTextAppearance(android.content.Context, int); - method public void setTextAssistant(android.text.TextAssistant); + method public void setTextClassifier(android.view.textclassifier.TextClassifier); method public void setTextColor(int); method public void setTextColor(android.content.res.ColorStateList); method public void setTextIsSelectable(boolean); diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 556d7add513f..a9d1cf6e490f 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -78,8 +78,6 @@ import android.service.autofill.AutoFillService; import android.service.autofill.IAutoFillAppCallback; import android.text.Selection; import android.text.SpannableStringBuilder; -import android.text.TextAssistant; -import android.text.TextClassificationManager; import android.text.TextUtils; import android.text.method.TextKeyListener; import android.transition.Scene; @@ -792,8 +790,6 @@ public class Activity extends ContextThemeWrapper private VoiceInteractor mVoiceInteractor; - private TextAssistant mTextAssistant; - private CharSequence mTitle; private int mTitleColor = 0; @@ -1398,24 +1394,6 @@ public class Activity extends ContextThemeWrapper } /** - * Sets the default {@link TextAssistant} for {@link android.widget.TextView}s in this Activity. - */ - public void setTextAssistant(TextAssistant textAssistant) { - mTextAssistant = textAssistant; - } - - /** - * Returns the default {@link TextAssistant} for {@link android.widget.TextView}s - * in this Activity. - */ - public TextAssistant getTextAssistant() { - if (mTextAssistant != null) { - return mTextAssistant; - } - return getSystemService(TextClassificationManager.class); - } - - /** * This is called for activities that set launchMode to "singleTop" in * their package, or if a client used the {@link Intent#FLAG_ACTIVITY_SINGLE_TOP} * flag when calling {@link #startActivity}. In either case, when the diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index a37f22b888b0..5d8909c1dbae 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -119,7 +119,6 @@ import android.telephony.CarrierConfigManager; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.text.FontManager; -import android.text.TextClassificationManager; import android.util.Log; import android.view.ContextThemeWrapper; import android.view.LayoutInflater; @@ -128,6 +127,7 @@ import android.view.WindowManagerImpl; import android.view.accessibility.AccessibilityManager; import android.view.accessibility.CaptioningManager; import android.view.inputmethod.InputMethodManager; +import android.view.textclassifier.TextClassificationManager; import android.view.textservice.TextServicesManager; import com.android.internal.app.IAppOpsService; @@ -228,10 +228,10 @@ final class SystemServiceRegistry { }}); registerService(Context.TEXT_CLASSIFICATION_SERVICE, TextClassificationManager.class, - new StaticServiceFetcher<TextClassificationManager>() { + new CachedServiceFetcher<TextClassificationManager>() { @Override - public TextClassificationManager createService() { - return new TextClassificationManager(); + public TextClassificationManager createService(ContextImpl ctx) { + return new TextClassificationManager(ctx); }}); registerService(Context.CLIPBOARD_SERVICE, ClipboardManager.class, diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index f41d7f2f168d..38e6fbeb007f 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -34,9 +34,7 @@ import android.annotation.TestApi; import android.annotation.UserIdInt; import android.app.IApplicationThread; import android.app.IServiceConnection; -import android.app.LoadedApk; import android.app.Notification; -import android.app.admin.DevicePolicyManager; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.res.AssetManager; @@ -64,6 +62,7 @@ import android.view.Display; import android.view.DisplayAdjustments; import android.view.ViewDebug; import android.view.WindowManager; +import android.view.textclassifier.TextClassificationManager; import java.io.File; import java.io.FileInputStream; @@ -3348,10 +3347,10 @@ public abstract class Context { /** * Use with {@link #getSystemService} to retrieve a - * {@link android.text.TextClassificationManager} for text classification services. + * {@link TextClassificationManager} for text classification services. * * @see #getSystemService - * @see android.text.TextClassificationManager + * @see TextClassificationManager */ public static final String TEXT_CLASSIFICATION_SERVICE = "textclassification"; diff --git a/core/java/android/text/TextAssistant.java b/core/java/android/text/TextAssistant.java deleted file mode 100644 index b044981cdd95..000000000000 --- a/core/java/android/text/TextAssistant.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2016 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.text; - -/** - * Interface for providing text assistant features. - */ -public interface TextAssistant { - - /** - * NO_OP TextAssistant. This will act as the default TextAssistant until we implement a - * TextClassificationManager. - * @hide - */ - TextAssistant NO_OP = new TextAssistant() { - - private final TextSelection mTextSelection = new TextSelection(); - - @Override - public TextSelection suggestSelection( - CharSequence text, int selectionStartIndex, int selectionEndIndex) { - mTextSelection.mStartIndex = selectionStartIndex; - mTextSelection.mEndIndex = selectionEndIndex; - return mTextSelection; - } - - @Override - public void addLinks(Spannable text, int linkMask) {} - }; - - /** - * Returns suggested text selection indices, recognized types and their associated confidence - * scores. The selections are ordered from highest to lowest scoring. - */ - TextSelection suggestSelection( - CharSequence text, int selectionStartIndex, int selectionEndIndex); - - /** - * Adds assistance clickable spans to the provided text. - */ - void addLinks(Spannable text, int linkMask); -} diff --git a/core/java/android/text/TextClassification.java b/core/java/android/text/TextClassification.java deleted file mode 100644 index bb226daaaeb0..000000000000 --- a/core/java/android/text/TextClassification.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2016 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.text; - -import java.util.Collections; -import java.util.Map; - -/** - * Information about entities that a specific piece of text is classified as. - */ -public class TextClassification { - - /** @hide */ - public static final TextClassification NO_OP = new TextClassification(); - - private Map<String, Float> mTypeConfidence = Collections.unmodifiableMap(Collections.EMPTY_MAP); - - /** - * Returns a map of text classification types to their respective confidence scores. - * The scores range from 0 (low confidence) to 1 (high confidence). The items are ordered from - * high scoring items to low scoring items. - */ - public Map<String, Float> getTypeConfidence() { - return mTypeConfidence; - } -} diff --git a/core/java/android/text/TextClassificationManager.java b/core/java/android/text/TextClassificationManager.java deleted file mode 100644 index d4548f04e0a0..000000000000 --- a/core/java/android/text/TextClassificationManager.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2016 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.text; - -import android.annotation.NonNull; - -import java.util.Collections; -import java.util.List; - -/** - * Interface to the text classification service. - * This class uses machine learning techniques to infer things about text. - * Unless otherwise stated, methods of this class are blocking operations and should most likely not - * be called on the UI thread. - * - * <p> You do not instantiate this class directly; instead, retrieve it through - * {@link android.content.Context#getSystemService}. - * - * The TextClassificationManager serves as the default TextAssistant if none has been set. - * @see android.app.Activity#setTextAssistant(TextAssistant). - */ -public final class TextClassificationManager implements TextAssistant { - // TODO: Consider not making this class implement TextAssistant. - - /** @hide */ - public TextClassificationManager() {} - - /** - * Returns information containing languages that were detected in the provided text. - * This is a blocking operation and should most likely not be called on the UI thread. - */ - public List<TextLanguage> detectLanguages(@NonNull CharSequence text) { - // TODO: Implement this using the cld3 library. - return Collections.emptyList(); - } - - @Override - public TextSelection suggestSelection( - @NonNull CharSequence text, int selectionStartIndex, int selectionEndIndex) { - // TODO: Implement. - return TextAssistant.NO_OP.suggestSelection(text, selectionStartIndex, selectionEndIndex); - } - - @Override - public void addLinks(@NonNull Spannable text, int linkMask) { - // TODO: Implement. - } -} diff --git a/core/java/android/text/TextLanguage.java b/core/java/android/text/TextLanguage.java deleted file mode 100644 index eb834f120dee..000000000000 --- a/core/java/android/text/TextLanguage.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2016 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.text; - -import android.annotation.NonNull; - -import com.android.internal.util.Preconditions; - -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * Specifies detected languages for a section of text indicated by a start and end index. - */ -public final class TextLanguage { - - private final int mStartIndex; - private final int mEndIndex; - private final Map<String, Float> mLanguageConfidence; - - /** - * Initializes a TextLanguage object. - * - * @param startIndex the start index of the detected languages in the text provided to generate - * this object. - * @param endIndex the end index of the detected languages in the text provided to generate this - * object. - * @param languageConfidence a map of detected language to confidence score. The language string - * is a BCP-47 language tag. - * @throws NullPointerException if languageConfidence is null or contains a null key or value. - */ - public TextLanguage(int startIndex, int endIndex, - @NonNull Map<String, Float> languageConfidence) { - mStartIndex = startIndex; - mEndIndex = endIndex; - - Map<String, Float> map = new LinkedHashMap<>(); - Preconditions.checkNotNull(languageConfidence).entrySet().stream() - .sorted(Map.Entry.comparingByValue()) - .forEach(entry -> map.put( - Preconditions.checkNotNull(entry.getKey()), - Preconditions.checkNotNull(entry.getValue()))); - mLanguageConfidence = Collections.unmodifiableMap(map); - } - - /** - * Returns the start index of the detected languages in the text provided to generate this - * object. - */ - public int getStartIndex() { - return mStartIndex; - } - - /** - * Returns the end index of the detected languages in the text provided to generate this object. - */ - public int getEndIndex() { - return mEndIndex; - } - - /** - * Returns an unmodifiable map of detected language to confidence score. The map entries are - * ordered from high confidence score (1) to low confidence score (0). The language string is a - * BCP-47 language tag. - */ - @NonNull - public Map<String, Float> getLanguageConfidence() { - return mLanguageConfidence; - } -} diff --git a/core/java/android/text/TextSelection.java b/core/java/android/text/TextSelection.java deleted file mode 100644 index 9400458582c7..000000000000 --- a/core/java/android/text/TextSelection.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2016 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.text; - -/** - * Text selection information. - */ -public class TextSelection { - - /** @hide */ - int mStartIndex; - /** @hide */ - int mEndIndex; - - private TextClassification mTextClassification = TextClassification.NO_OP; - - /** - * Returns the start index of the text selection. - */ - public int getSelectionStartIndex() { - return mStartIndex; - } - - /** - * Returns the end index of the text selection. - */ - public int getSelectionEndIndex() { - return mEndIndex; - } - - /** - * Returns information about what the text selection is classified as. - */ - public TextClassification getTextClassification() { - return mTextClassification; - } -} diff --git a/core/java/android/view/textclassifier/EntityConfidence.java b/core/java/android/view/textclassifier/EntityConfidence.java new file mode 100644 index 000000000000..7aab71fac76b --- /dev/null +++ b/core/java/android/view/textclassifier/EntityConfidence.java @@ -0,0 +1,106 @@ +/* + * 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.view.textclassifier; + +import android.annotation.FloatRange; +import android.annotation.NonNull; + +import com.android.internal.util.Preconditions; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Helper object for setting and getting entity scores for classified text. + * + * @param <T> the entity type. + * @hide + */ +final class EntityConfidence<T> { + + private final Map<T, Float> mEntityConfidence = new HashMap<>(); + + private final Comparator<T> mEntityComparator = (e1, e2) -> { + float score1 = mEntityConfidence.get(e1); + float score2 = mEntityConfidence.get(e2); + if (score1 > score2) { + return 1; + } + if (score1 < score2) { + return -1; + } + return 0; + }; + + EntityConfidence() {} + + EntityConfidence(@NonNull EntityConfidence<T> source) { + Preconditions.checkNotNull(source); + mEntityConfidence.putAll(source.mEntityConfidence); + } + + /** + * Sets an entity type for the classified text and assigns a confidence score. + * + * @param confidenceScore a value from 0 (low confidence) to 1 (high confidence). + * 0 implies the entity does not exist for the classified text. + * Values greater than 1 are clamped to 1. + */ + public void setEntityType( + @NonNull T type, @FloatRange(from = 0.0, to = 1.0) float confidenceScore) { + Preconditions.checkNotNull(type); + if (confidenceScore > 0) { + mEntityConfidence.put(type, Math.min(1, confidenceScore)); + } else { + mEntityConfidence.remove(type); + } + } + + /** + * Returns an immutable list of entities found in the classified text ordered from + * high confidence to low confidence. + */ + @NonNull + public List<T> getEntities() { + List<T> entities = new ArrayList<>(mEntityConfidence.size()); + entities.addAll(mEntityConfidence.keySet()); + entities.sort(mEntityComparator); + return Collections.unmodifiableList(entities); + } + + /** + * Returns the confidence score for the specified entity. The value ranges from + * 0 (low confidence) to 1 (high confidence). 0 indicates that the entity was not found for the + * classified text. + */ + @FloatRange(from = 0.0, to = 1.0) + public float getConfidenceScore(T entity) { + if (mEntityConfidence.containsKey(entity)) { + return mEntityConfidence.get(entity); + } + return 0; + } + + @Override + public String toString() { + return mEntityConfidence.toString(); + } +} diff --git a/core/java/android/view/textclassifier/LinksInfo.java b/core/java/android/view/textclassifier/LinksInfo.java new file mode 100644 index 000000000000..3acbdc0261bd --- /dev/null +++ b/core/java/android/view/textclassifier/LinksInfo.java @@ -0,0 +1,41 @@ +/* + * 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.view.textclassifier; + +import android.annotation.NonNull; + +/** + * Link information that can be applied to text. See: {@link #apply(CharSequence)}. + * Typical implementations of this interface will annotate spannable text with e.g + * {@link android.text.style.ClickableSpan}s or other annotations. + */ +public interface LinksInfo { + + /** + * @hide + */ + LinksInfo NO_OP = text -> false; + + /** + * Applies link annotations to the specified text. + * These annotations are not guaranteed to be applied. For example, the annotations may not be + * applied if the text has changed from what it was when the link spec was generated for it. + * + * @return Whether or not the link annotations were successfully applied. + */ + boolean apply(@NonNull CharSequence text); +} diff --git a/core/java/android/view/textclassifier/TextClassificationManager.java b/core/java/android/view/textclassifier/TextClassificationManager.java new file mode 100644 index 000000000000..b5ab4bfb1d0a --- /dev/null +++ b/core/java/android/view/textclassifier/TextClassificationManager.java @@ -0,0 +1,53 @@ +/* + * 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.view.textclassifier; + +import android.annotation.NonNull; +import android.content.Context; + +import java.util.Collections; +import java.util.List; + +/** + * Interface to the text classification service. + * + * <p>You do not instantiate this class directly; instead, retrieve it through + * {@link android.content.Context#getSystemService}. + */ +public final class TextClassificationManager { + + /** @hide */ + public TextClassificationManager(Context context) {} + + /** + * Returns the default text classifier. + */ + public TextClassifier getDefaultTextClassifier() { + return TextClassifier.NO_OP; + } + + /** + * Returns information containing languages that were detected in the provided text. + * This is a blocking operation you should avoid calling it on the UI thread. + * + * @throws IllegalArgumentException if text is null + */ + public List<TextLanguage> detectLanguages(@NonNull CharSequence text) { + // TODO: Implement + return Collections.emptyList(); + } +} diff --git a/core/java/android/view/textclassifier/TextClassificationResult.java b/core/java/android/view/textclassifier/TextClassificationResult.java new file mode 100644 index 000000000000..6af0efb5fd08 --- /dev/null +++ b/core/java/android/view/textclassifier/TextClassificationResult.java @@ -0,0 +1,233 @@ +/* + * 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.view.textclassifier; + +import android.annotation.FloatRange; +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.Context; +import android.content.Intent; +import android.graphics.drawable.Drawable; +import android.view.View.OnClickListener; +import android.view.textclassifier.TextClassifier.EntityType; + +import com.android.internal.util.Preconditions; + +import java.util.List; + +/** + * Information for generating a widget to handle classified text. + */ +public final class TextClassificationResult { + + /** + * @hide + */ + static final TextClassificationResult EMPTY = new TextClassificationResult.Builder().build(); + + @NonNull private final String mText; + @Nullable private final Drawable mIcon; + @Nullable private final String mLabel; + @Nullable private final Intent mIntent; + @Nullable private final OnClickListener mOnClickListener; + @NonNull private final EntityConfidence<String> mEntityConfidence; + @NonNull private final List<String> mEntities; + + private TextClassificationResult( + @NonNull String text, + Drawable icon, + String label, + Intent intent, + OnClickListener onClickListener, + @NonNull EntityConfidence<String> entityConfidence) { + mText = text; + mIcon = icon; + mLabel = label; + mIntent = intent; + mOnClickListener = onClickListener; + mEntityConfidence = new EntityConfidence<>(entityConfidence); + mEntities = mEntityConfidence.getEntities(); + } + + /** + * Gets the classified text. + */ + @NonNull + public String getText() { + return mText; + } + + /** + * Returns the number of entities found in the classified text. + */ + @IntRange(from = 0) + public int getEntityCount() { + return mEntities.size(); + } + + /** + * Returns the entity at the specified index. Entities are ordered from high confidence + * to low confidence. + * + * @throws IndexOutOfBoundsException if the specified index is out of range. + * @see #getEntityCount() for the number of entities available. + */ + @NonNull + public @EntityType String getEntity(int index) { + return mEntities.get(index); + } + + /** + * Returns the confidence score for the specified entity. The value ranges from + * 0 (low confidence) to 1 (high confidence). 0 indicates that the entity was not found for the + * classified text. + */ + @FloatRange(from = 0.0, to = 1.0) + public float getConfidenceScore(@EntityType String entity) { + return mEntityConfidence.getConfidenceScore(entity); + } + + /** + * Returns an icon that may be rendered on a widget used to act on the classified text. + */ + @Nullable + public Drawable getIcon() { + return mIcon; + } + + /** + * Returns a label that may be rendered on a widget used to act on the classified text. + */ + @Nullable + public CharSequence getLabel() { + return mLabel; + } + + /** + * Returns an intent that may be fired to act on the classified text. + */ + @Nullable + public Intent getIntent() { + return mIntent; + } + + /** + * Returns an OnClickListener that may be triggered to act on the classified text. + */ + @Nullable + public OnClickListener getOnClickListener() { + return mOnClickListener; + } + + @Override + public String toString() { + return String.format("TextClassificationResult {" + + "text=%s, entities=%s, label=%s, intent=%s}", + mText, mEntityConfidence, mLabel, mIntent); + } + + /** + * Creates an OnClickListener that starts an activity with the specified intent. + * + * @throws IllegalArgumentException if context or intent is null + * @hide + */ + @NonNull + public static OnClickListener createStartActivityOnClick( + @NonNull final Context context, @NonNull final Intent intent) { + Preconditions.checkArgument(context != null); + Preconditions.checkArgument(intent != null); + return v -> context.startActivity(intent); + } + + /** + * Builder for building {@link TextClassificationResult}s. + */ + public static final class Builder { + + @NonNull private String mText; + @Nullable private Drawable mIcon; + @Nullable private String mLabel; + @Nullable private Intent mIntent; + @Nullable private OnClickListener mOnClickListener; + @NonNull private final EntityConfidence<String> mEntityConfidence = + new EntityConfidence<>(); + + /** + * Sets the classified text. + */ + public Builder setText(@NonNull String text) { + mText = Preconditions.checkNotNull(text); + return this; + } + + /** + * Sets an entity type for the classification result and assigns a confidence score. + * + * @param confidenceScore a value from 0 (low confidence) to 1 (high confidence). + * 0 implies the entity does not exist for the classified text. + * Values greater than 1 are clamped to 1. + */ + public Builder setEntityType( + @NonNull @EntityType String type, + @FloatRange(from = 0.0, to = 1.0)float confidenceScore) { + mEntityConfidence.setEntityType(type, confidenceScore); + return this; + } + + /** + * Sets an icon that may be rendered on a widget used to act on the classified text. + */ + public Builder setIcon(@Nullable Drawable icon) { + mIcon = icon; + return this; + } + + /** + * Sets a label that may be rendered on a widget used to act on the classified text. + */ + public Builder setLabel(@Nullable String label) { + mLabel = label; + return this; + } + + /** + * Sets an intent that may be fired to act on the classified text. + */ + public Builder setIntent(@Nullable Intent intent) { + mIntent = intent; + return this; + } + + /** + * Sets an OnClickListener that may be triggered to act on the classified text. + */ + public Builder setOnClickListener(@Nullable OnClickListener onClickListener) { + mOnClickListener = onClickListener; + return this; + } + + /** + * Builds an returns a {@link TextClassificationResult}. + */ + public TextClassificationResult build() { + return new TextClassificationResult( + mText, mIcon, mLabel, mIntent, mOnClickListener, mEntityConfidence); + } + } +} diff --git a/core/java/android/view/textclassifier/TextClassifier.java b/core/java/android/view/textclassifier/TextClassifier.java new file mode 100644 index 000000000000..b84e2ae5e4fd --- /dev/null +++ b/core/java/android/view/textclassifier/TextClassifier.java @@ -0,0 +1,114 @@ +/* + * 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.view.textclassifier; + +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.annotation.StringDef; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Interface for providing text classification related features. + * + * <p>Unless otherwise stated, methods of this interface are blocking operations and you should + * avoid calling them on the UI thread. + */ +public interface TextClassifier { + + String TYPE_OTHER = "other"; + String TYPE_EMAIL = "email"; + String TYPE_PHONE = "phone"; + String TYPE_ADDRESS = "address"; + + @Retention(RetentionPolicy.SOURCE) + @StringDef({ + TYPE_OTHER, TYPE_EMAIL, TYPE_PHONE, TYPE_ADDRESS + }) + @interface EntityType {} + + /** + * No-op TextClassifier. + * This may be used to turn off TextClassifier features. + */ + TextClassifier NO_OP = new TextClassifier() { + + @Override + public TextSelection suggestSelection( + CharSequence text, int selectionStartIndex, int selectionEndIndex) { + return new TextSelection.Builder(selectionStartIndex, selectionEndIndex).build(); + } + + @Override + public TextClassificationResult getTextClassificationResult( + CharSequence text, int startIndex, int endIndex) { + return TextClassificationResult.EMPTY; + } + + @Override + public LinksInfo getLinks(CharSequence text, int linkMask) { + return LinksInfo.NO_OP; + } + }; + + /** + * Returns suggested text selection indices, recognized types and their associated confidence + * scores. The selections are ordered from highest to lowest scoring. + * + * @param text text providing context for the selected text (which is specified + * by the sub sequence starting at selectionStartIndex and ending at selectionEndIndex) + * @param selectionStartIndex start index of the selected part of text + * @param selectionEndIndex end index of the selected part of text + * + * @throws IllegalArgumentException if text is null; selectionStartIndex is negative; + * selectionEndIndex is greater than text.length() or less than selectionStartIndex + */ + @NonNull + TextSelection suggestSelection( + @NonNull CharSequence text, + @IntRange(from = 0) int selectionStartIndex, + @IntRange(from = 0) int selectionEndIndex); + + /** + * Returns a {@link TextClassificationResult} object that can be used to generate a widget for + * handling the classified text. + * + * @param text text providing context for the text to classify (which is specified + * by the sub sequence starting at startIndex and ending at endIndex) + * @param startIndex start index of the text to classify + * @param endIndex end index of the text to classify + * + * @throws IllegalArgumentException if text is null; startIndex is negative; + * endIndex is greater than text.length() or less than startIndex + */ + @NonNull + TextClassificationResult getTextClassificationResult( + @NonNull CharSequence text, int startIndex, int endIndex); + + /** + * Returns a {@link LinksInfo} that may be applied to the text to annotate it with links + * information. + * + * @param text the text to generate annotations for + * @param linkMask See {@link android.text.util.Linkify} for a list of linkMasks that may be + * specified. Subclasses of this interface may specify additional linkMasks + * + * @throws IllegalArgumentException if text is null + */ + LinksInfo getLinks(@NonNull CharSequence text, int linkMask); +} diff --git a/core/java/android/view/textclassifier/TextLanguage.java b/core/java/android/view/textclassifier/TextLanguage.java new file mode 100644 index 000000000000..d94d163577e1 --- /dev/null +++ b/core/java/android/view/textclassifier/TextLanguage.java @@ -0,0 +1,139 @@ +/* + * 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.view.textclassifier; + +import android.annotation.FloatRange; +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.annotation.Nullable; + +import com.android.internal.util.Preconditions; + +import java.util.List; +import java.util.Locale; + +/** + * Specifies detected languages for a section of text indicated by a start and end index. + */ +public final class TextLanguage { + + private final int mStartIndex; + private final int mEndIndex; + @NonNull private final EntityConfidence<Locale> mLanguageConfidence; + @NonNull private final List<Locale> mLanguages; + + private TextLanguage( + int startIndex, int endIndex, @NonNull EntityConfidence<Locale> languageConfidence) { + mStartIndex = startIndex; + mEndIndex = endIndex; + mLanguageConfidence = new EntityConfidence<>(languageConfidence); + mLanguages = mLanguageConfidence.getEntities(); + } + + /** + * Returns the start index of the detected languages in the text provided to generate this + * object. + */ + public int getStartIndex() { + return mStartIndex; + } + + /** + * Returns the end index of the detected languages in the text provided to generate this object. + */ + public int getEndIndex() { + return mEndIndex; + } + + /** + * Returns the number of languages found in the classified text. + */ + @IntRange(from = 0) + public int getLanguageCount() { + return mLanguages.size(); + } + + /** + * Returns the language locale at the specified index. + * Language locales are ordered from high confidence to low confidence. + * + * @throws IndexOutOfBoundsException if the specified index is out of range. + * @see #getLanguageCount() for the number of language locales available. + */ + @NonNull + public Locale getLanguage(int index) { + return mLanguages.get(index); + } + + /** + * Returns the confidence score for the specified language. The value ranges from + * 0 (low confidence) to 1 (high confidence). 0 indicates that the language was + * not found for the classified text. + */ + @FloatRange(from = 0.0, to = 1.0) + public float getConfidenceScore(@Nullable Locale language) { + return mLanguageConfidence.getConfidenceScore(language); + } + + @Override + public String toString() { + return String.format("TextLanguage {%d, %d, %s}", + mStartIndex, mEndIndex, mLanguageConfidence); + } + + /** + * Builder to build {@link TextLanguage} objects. + */ + public static final class Builder { + + private final int mStartIndex; + private final int mEndIndex; + @NonNull private final EntityConfidence<Locale> mLanguageConfidence = + new EntityConfidence<>(); + + /** + * Creates a builder to build {@link TextLanguage} objects. + * + * @param startIndex the start index of the detected languages in the text provided + * to generate the result + * @param endIndex the end index of the detected languages in the text provided + * to generate the result. Must be greater than startIndex + */ + public Builder(@IntRange(from = 0) int startIndex, @IntRange(from = 0) int endIndex) { + Preconditions.checkArgument(startIndex >= 0); + Preconditions.checkArgument(endIndex > startIndex); + mStartIndex = startIndex; + mEndIndex = endIndex; + } + + /** + * Sets a language locale with the associated confidence score. + */ + public Builder setLanguage( + @NonNull Locale locale, @FloatRange(from = 0.0, to = 1.0) float confidenceScore) { + mLanguageConfidence.setEntityType(locale, confidenceScore); + return this; + } + + /** + * Builds and returns a {@link TextLanguage}. + */ + public TextLanguage build() { + return new TextLanguage(mStartIndex, mEndIndex, mLanguageConfidence); + } + } +} diff --git a/core/java/android/view/textclassifier/TextSelection.java b/core/java/android/view/textclassifier/TextSelection.java new file mode 100644 index 000000000000..3172c13daa80 --- /dev/null +++ b/core/java/android/view/textclassifier/TextSelection.java @@ -0,0 +1,140 @@ +/* + * 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.view.textclassifier; + +import android.annotation.FloatRange; +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.view.textclassifier.TextClassifier.EntityType; + +import com.android.internal.util.Preconditions; + +import java.util.List; + +/** + * Information about where text selection should be. + */ +public final class TextSelection { + + private final int mStartIndex; + private final int mEndIndex; + @NonNull private final EntityConfidence<String> mEntityConfidence; + @NonNull private final List<String> mEntities; + + private TextSelection( + int startIndex, int endIndex, @NonNull EntityConfidence<String> entityConfidence) { + mStartIndex = startIndex; + mEndIndex = endIndex; + mEntityConfidence = new EntityConfidence<>(entityConfidence); + mEntities = mEntityConfidence.getEntities(); + } + + /** + * Returns the start index of the text selection. + */ + public int getSelectionStartIndex() { + return mStartIndex; + } + + /** + * Returns the end index of the text selection. + */ + public int getSelectionEndIndex() { + return mEndIndex; + } + + /** + * Returns the number of entities found in the classified text. + */ + @IntRange(from = 0) + public int getEntityCount() { + return mEntities.size(); + } + + /** + * Returns the entity at the specified index. Entities are ordered from high confidence + * to low confidence. + * + * @throws IndexOutOfBoundsException if the specified index is out of range. + * @see #getEntityCount() for the number of entities available. + */ + @NonNull + public @EntityType String getEntity(int index) { + return mEntities.get(index); + } + + /** + * Returns the confidence score for the specified entity. The value ranges from + * 0 (low confidence) to 1 (high confidence). 0 indicates that the entity was not found for the + * classified text. + */ + @FloatRange(from = 0.0, to = 1.0) + public float getConfidenceScore(@EntityType String entity) { + return mEntityConfidence.getConfidenceScore(entity); + } + + @Override + public String toString() { + return String.format("TextSelection {%d, %d, %s}", + mStartIndex, mEndIndex, mEntityConfidence); + } + + /** + * Builder used to build {@link TextSelection} objects. + */ + public static final class Builder { + + private final int mStartIndex; + private final int mEndIndex; + @NonNull private final EntityConfidence<String> mEntityConfidence = + new EntityConfidence<>(); + + /** + * Creates a builder used to build {@link TextSelection} objects. + * + * @param startIndex the start index of the text selection. + * @param endIndex the end index of the text selection. Must be greater than startIndex + */ + public Builder(@IntRange(from = 0) int startIndex, @IntRange(from = 0) int endIndex) { + Preconditions.checkArgument(startIndex >= 0); + Preconditions.checkArgument(endIndex > startIndex); + mStartIndex = startIndex; + mEndIndex = endIndex; + } + + /** + * Sets an entity type for the classified text and assigns a confidence score. + * + * @param confidenceScore a value from 0 (low confidence) to 1 (high confidence). + * 0 implies the entity does not exist for the classified text. + * Values greater than 1 are clamped to 1. + */ + public Builder setEntityType( + @NonNull @EntityType String type, + @FloatRange(from = 0.0, to = 1.0) float confidenceScore) { + mEntityConfidence.setEntityType(type, confidenceScore); + return this; + } + + /** + * Builds and returns {@link TextSelection} object. + */ + public TextSelection build() { + return new TextSelection(mStartIndex, mEndIndex, mEntityConfidence); + } + } +} diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 2fc8ec9c41f2..f7f9a81e45c1 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -60,8 +60,6 @@ import android.text.Spannable; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.StaticLayout; -import android.text.TextClassification; -import android.text.TextSelection; import android.text.TextUtils; import android.text.method.KeyListener; import android.text.method.MetaKeyKeyListener; @@ -108,6 +106,8 @@ import android.view.inputmethod.ExtractedText; import android.view.inputmethod.ExtractedTextRequest; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; +import android.view.textclassifier.TextClassificationResult; +import android.view.textclassifier.TextSelection; import android.widget.AdapterView.OnItemClickListener; import android.widget.TextView.Drawables; import android.widget.TextView.OnEditorActionListener; @@ -149,7 +149,7 @@ public class Editor { private static final String UNDO_OWNER_TAG = "Editor"; // Ordering constants used to place the Action Mode or context menu items in their menu. - // Reserve 1 for the app that the ASSIST logic suggests as the best app to handle the selection. + private static final int MENU_ITEM_ORDER_ASSIST = 1; private static final int MENU_ITEM_ORDER_UNDO = 2; private static final int MENU_ITEM_ORDER_REDO = 3; private static final int MENU_ITEM_ORDER_SHARE = 4; @@ -238,6 +238,8 @@ public class Editor { private boolean mPreserveSelection; private boolean mRestartActionModeOnNextRefresh; + private TextClassificationResult mTextClassificationResult; + boolean mIsBeingLongClicked; private SuggestionsPopupWindow mSuggestionsPopupWindow; @@ -1889,7 +1891,7 @@ public class Editor { mInsertionPointCursorController.invalidateHandle(); } if (mTextActionMode != null) { - mTextActionMode.invalidate(); + invalidateActionMode(getTextClassifierInfo(false)); } } @@ -1982,12 +1984,12 @@ public class Editor { if (mRestartActionModeOnNextRefresh) { // To avoid distraction, newly start action mode only when selection action // mode is being restarted. - startSelectionActionMode(); + startSelectionActionMode(getTextClassifierInfo(true)); } } else if (selectionController == null || !selectionController.isActive()) { // Insertion action mode is active. Avoid dismissing the selection. stopTextActionModeWithPreservingSelection(); - startSelectionActionMode(); + startSelectionActionMode(getTextClassifierInfo(true)); } else { mTextActionMode.invalidateContentRect(); } @@ -2031,7 +2033,8 @@ public class Editor { * * @return true if the selection mode was actually started. */ - boolean startSelectionActionMode() { + boolean startSelectionActionMode(@Nullable TextClassificationResult textClassificationResult) { + mTextClassificationResult = textClassificationResult; boolean selectionStarted = startSelectionActionModeInternal(); if (selectionStarted) { getSelectionController().show(); @@ -2040,6 +2043,40 @@ public class Editor { return selectionStarted; } + private boolean startSelectionActionModeWithTextAssistant() { + return startSelectionActionMode(getTextClassifierInfo(true)); + } + + private void invalidateActionMode(TextClassificationResult textClassificationResult) { + mTextClassificationResult = textClassificationResult; + mTextActionMode.invalidate(); + } + + // TODO: Make this a non-blocking call. + private TextClassificationResult getTextClassifierInfo(boolean updateSelection) { + // TODO: Trim the text so that only text necessary to provide context of the selected + // text is sent to the assistant. + final int trimStartIndex = 0; + final int trimEndIndex = mTextView.getText().length(); + CharSequence trimmedText = + mTextView.getText().subSequence(trimStartIndex, trimEndIndex); + int startIndex = mTextView.getSelectionStart() - trimStartIndex; + int endIndex = mTextView.getSelectionEnd() - trimStartIndex; + + if (updateSelection) { + TextSelection textSelection = mTextView.getTextClassifier() + .suggestSelection(trimmedText, startIndex, endIndex); + startIndex = Math.max(0, textSelection.getSelectionStartIndex() + trimStartIndex); + endIndex = Math.min(mTextView.getText().length(), + textSelection.getSelectionEndIndex() + trimStartIndex); + Selection.setSelection((Spannable) mTextView.getText(), startIndex, endIndex); + return getTextClassifierInfo(false); + } + + return mTextView.getTextClassifier() + .getTextClassificationResult(trimmedText, startIndex, endIndex); + } + /** * If the TextView allows text selection, selects the current word when no existing selection * was available and starts a drag. @@ -2086,7 +2123,7 @@ public class Editor { } if (mTextActionMode != null) { // Text action mode is already started - mTextActionMode.invalidate(); + invalidateActionMode(getTextClassifierInfo(false)); return false; } @@ -3744,8 +3781,7 @@ public class Editor { private final Path mSelectionPath = new Path(); private final RectF mSelectionBounds = new RectF(); private final boolean mHasSelection; - - private int mHandleHeight; + private final int mHandleHeight; public TextActionModeCallback(boolean hasSelection) { mHasSelection = hasSelection; @@ -3765,18 +3801,19 @@ public class Editor { if (insertionController != null) { insertionController.getHandle(); mHandleHeight = mSelectHandleCenter.getMinimumHeight(); + } else { + mHandleHeight = 0; } } } @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { - TextClassification textClassification = updateSelectionWithTextAssistant(); - mode.setTitle(null); mode.setSubtitle(null); mode.setTitleOptionalHint(true); - populateMenuWithItems(menu, textClassification); + populateMenuWithItems(menu); + updateAssistMenuItem(menu, mTextClassificationResult); Callback customCallback = getCustomCallback(); if (customCallback != null) { @@ -3802,30 +3839,13 @@ public class Editor { } } - private TextClassification updateSelectionWithTextAssistant() { - // Trim the text so that only text necessary to provide context of the selected text is - // sent to the assistant. - CharSequence trimmedText = mTextView.getText(); - int textLength = mTextView.getText().length(); - int trimStartIndex = 0; - int startIndex = mTextView.getSelectionStart() - trimStartIndex; - int endIndex = mTextView.getSelectionEnd() - trimStartIndex; - TextSelection textSelection = mTextView.getTextAssistant() - .suggestSelection(trimmedText, startIndex, endIndex); - Selection.setSelection( - (Spannable) mTextView.getText(), - Math.max(0, textSelection.getSelectionStartIndex() + trimStartIndex), - Math.min(textLength, textSelection.getSelectionEndIndex() + trimStartIndex)); - return textSelection.getTextClassification(); - } - private Callback getCustomCallback() { return mHasSelection ? mCustomSelectionActionModeCallback : mCustomInsertionActionModeCallback; } - private void populateMenuWithItems(Menu menu, TextClassification textClassification) { + private void populateMenuWithItems(Menu menu) { if (mTextView.canCut()) { menu.add(Menu.NONE, TextView.ID_CUT, MENU_ITEM_ORDER_CUT, com.android.internal.R.string.cut) @@ -3855,13 +3875,13 @@ public class Editor { updateSelectAllItem(menu); updateReplaceItem(menu); - updateAssistMenuItem(menu, textClassification); } @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { updateSelectAllItem(menu); updateReplaceItem(menu); + updateAssistMenuItem(menu, mTextClassificationResult); Callback customCallback = getCustomCallback(); if (customCallback != null) { @@ -3894,10 +3914,16 @@ public class Editor { } } - private void updateAssistMenuItem(Menu menu, TextClassification textClassification) { - // TODO: Find the best app available to handle the selected text based on information in - // the TextClassification object. - // Add app icon + intent to trigger app to the menu. + private void updateAssistMenuItem( + Menu menu, TextClassificationResult textClassificationResult) { + menu.removeItem(TextView.ID_ASSIST); + if (textClassificationResult != null + && textClassificationResult.getIcon() != null + && textClassificationResult.getOnClickListener() != null) { + menu.add(Menu.NONE, TextView.ID_ASSIST, MENU_ITEM_ORDER_ASSIST, null) + .setIcon(textClassificationResult.getIcon()) + .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); + } } @Override @@ -3909,6 +3935,10 @@ public class Editor { if (customCallback != null && customCallback.onActionItemClicked(mode, item)) { return true; } + if (TextView.ID_ASSIST == item.getItemId() && mTextClassificationResult != null) { + mTextClassificationResult.getOnClickListener().onClick(mTextView); + stopTextActionMode(); + } return mTextView.onTextContextMenuItem(item.getItemId()); } @@ -3916,6 +3946,7 @@ public class Editor { public void onDestroyActionMode(ActionMode mode) { // Clear mTextActionMode not to recursively destroy action mode by clearing selection. mTextActionMode = null; + mTextClassificationResult = null; Callback customCallback = getCustomCallback(); if (customCallback != null) { customCallback.onDestroyActionMode(mode); @@ -4733,7 +4764,7 @@ public class Editor { } positionAtCursorOffset(offset, false); if (mTextActionMode != null) { - mTextActionMode.invalidate(); + invalidateActionMode(getTextClassifierInfo(false)); } } @@ -4817,7 +4848,7 @@ public class Editor { } updateDrawable(); if (mTextActionMode != null) { - mTextActionMode.invalidate(); + invalidateActionMode(getTextClassifierInfo(false)); } } @@ -5465,7 +5496,8 @@ public class Editor { resetDragAcceleratorState(); if (mTextView.hasSelection()) { - startSelectionActionMode(); + // TODO: Do not invoke the text assistant if this was a drag selection. + startSelectionActionMode(getTextClassifierInfo(true)); } break; } diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index b1fc67e56d80..2f303cdba301 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -77,8 +77,6 @@ import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.SpannedString; import android.text.StaticLayout; -import android.text.TextAssistant; -import android.text.TextClassificationManager; import android.text.TextDirectionHeuristic; import android.text.TextDirectionHeuristics; import android.text.TextPaint; @@ -146,6 +144,8 @@ import android.view.inputmethod.ExtractedText; import android.view.inputmethod.ExtractedTextRequest; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; +import android.view.textclassifier.TextClassificationManager; +import android.view.textclassifier.TextClassifier; import android.view.textservice.SpellCheckerSubtype; import android.view.textservice.TextServicesManager; import android.widget.RemoteViews.RemoteView; @@ -352,6 +352,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private boolean mPreDrawRegistered; private boolean mPreDrawListenerDetached; + private TextClassifier mTextClassifier; + // A flag to prevent repeated movements from escaping the enclosing text view. The idea here is // that if a user is holding down a movement key to traverse text, we shouldn't also traverse // the view hierarchy. On the other hand, if the user is using the movement key to traverse @@ -9890,7 +9892,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener Selection.setSelection((Spannable) text, start, end); // Make sure selection mode is engaged. if (mEditor != null) { - mEditor.startSelectionActionMode(); + mEditor.startSelectionActionMode(null); } return true; } @@ -10034,6 +10036,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener static final int ID_SHARE = android.R.id.shareText; static final int ID_PASTE_AS_PLAIN_TEXT = android.R.id.pasteAsPlainText; static final int ID_REPLACE = android.R.id.replaceText; + static final int ID_ASSIST = android.R.id.textAssist; /** * Called when a context menu option for the text view is selected. Currently @@ -10258,33 +10261,30 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return mEditor == null ? null : mEditor.mCustomInsertionActionModeCallback; } - private TextAssistant mTextAssistant; - /** - * Sets the {@link TextAssistant} for this TextView. - * If null, this TextView uses the default TextAssistant which comes from the Activity. + * Sets the {@link TextClassifier} for this TextView. */ - public void setTextAssistant(TextAssistant textAssistant) { - mTextAssistant = textAssistant; + public void setTextClassifier(@Nullable TextClassifier textClassifier) { + mTextClassifier = textClassifier; } /** - * Returns the {@link TextAssistant} used by this TextView. - * If no TextAssistant is set, it'll use the one from this TextView's {@link Activity} or - * {@link Context}. If no TextAssistant is found, it'll use a no-op TextAssistant. + * Returns the {@link TextClassifier} used by this TextView. + * If no TextClassifier has been set, this TextView uses the default set by the + * {@link TextClassificationManager}. */ - public TextAssistant getTextAssistant() { - if (mTextAssistant != null) { - return mTextAssistant; - } - if (mContext instanceof Activity) { - mTextAssistant = ((Activity) mContext).getTextAssistant(); - } else { - // The context of this TextView should be an Activity. If it is not and no - // text assistant has been set, return the TextClassificationManager. - mTextAssistant = mContext.getSystemService(TextClassificationManager.class); + @NonNull + public TextClassifier getTextClassifier() { + if (mTextClassifier == null) { + TextClassificationManager tcm = + mContext.getSystemService(TextClassificationManager.class); + if (tcm != null) { + mTextClassifier = tcm.getDefaultTextClassifier(); + } else { + mTextClassifier = TextClassifier.NO_OP; + } } - return mTextAssistant; + return mTextClassifier; } /** diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml index f351b7008547..613616fa0ea6 100644 --- a/core/res/res/values/ids.xml +++ b/core/res/res/values/ids.xml @@ -97,6 +97,7 @@ <item type="id" name="redo" /> <item type="id" name="replaceText" /> <item type="id" name="shareText" /> + <item type="id" name="textAssist" /> <item type="id" name="selection_start_handle" /> <item type="id" name="selection_end_handle" /> <item type="id" name="insertion_handle" /> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 060c59ed4a31..6c24e0ab8331 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2793,6 +2793,7 @@ </public-group> <public-group type="id" first-id="0x01020041"> + <public name="textAssist" /> </public-group> <public type="attr" name="primaryContentAlpha" /> |