summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt21
-rw-r--r--api/system-current.txt21
-rw-r--r--api/test-current.txt21
-rw-r--r--core/java/android/app/Activity.java21
-rw-r--r--core/java/android/text/TextAssistant.java56
-rw-r--r--core/java/android/text/TextClassification.java40
-rw-r--r--core/java/android/text/TextSelection.java51
-rw-r--r--core/java/android/widget/Editor.java55
-rw-r--r--core/java/android/widget/TextView.java30
9 files changed, 303 insertions, 13 deletions
diff --git a/api/current.txt b/api/current.txt
index 39140213d920..6cb05eba770d 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3497,6 +3497,7 @@ 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();
@@ -3646,6 +3647,7 @@ 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);
@@ -38988,6 +38990,16 @@ 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 abstract interface TextDirectionHeuristic {
method public abstract boolean isRtl(char[], int, int);
method public abstract boolean isRtl(java.lang.CharSequence, int, int);
@@ -39015,6 +39027,13 @@ 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...);
@@ -48487,6 +48506,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 final android.content.res.ColorStateList getTextColors();
method public java.util.Locale getTextLocale();
method public android.os.LocaleList getTextLocales();
@@ -48597,6 +48617,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 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 bcf4897c8661..dc22a2ae9a92 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3614,6 +3614,7 @@ 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();
@@ -3765,6 +3766,7 @@ 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);
@@ -42150,6 +42152,16 @@ 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 abstract interface TextDirectionHeuristic {
method public abstract boolean isRtl(char[], int, int);
method public abstract boolean isRtl(java.lang.CharSequence, int, int);
@@ -42177,6 +42189,13 @@ 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...);
@@ -52008,6 +52027,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 final android.content.res.ColorStateList getTextColors();
method public java.util.Locale getTextLocale();
method public android.os.LocaleList getTextLocales();
@@ -52118,6 +52138,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 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 2dcb743b4a73..813deb904435 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -3499,6 +3499,7 @@ 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();
@@ -3648,6 +3649,7 @@ 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);
@@ -39080,6 +39082,16 @@ 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 abstract interface TextDirectionHeuristic {
method public abstract boolean isRtl(char[], int, int);
method public abstract boolean isRtl(java.lang.CharSequence, int, int);
@@ -39107,6 +39119,13 @@ 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...);
@@ -48745,6 +48764,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 final android.content.res.ColorStateList getTextColors();
method public java.util.Locale getTextLocale();
method public android.os.LocaleList getTextLocales();
@@ -48855,6 +48875,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 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 64e5dfc66bce..90fff8d5f79a 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -74,6 +74,7 @@ import android.service.autofill.AutoFillService;
import android.service.autofill.IAutoFillCallback;
import android.text.Selection;
import android.text.SpannableStringBuilder;
+import android.text.TextAssistant;
import android.text.TextUtils;
import android.text.method.TextKeyListener;
import android.transition.Scene;
@@ -783,6 +784,8 @@ public class Activity extends ContextThemeWrapper
private VoiceInteractor mVoiceInteractor;
+ private TextAssistant mTextAssistant;
+
private CharSequence mTitle;
private int mTitleColor = 0;
@@ -1385,6 +1388,24 @@ 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 TextAssistant.NO_OP;
+ }
+
+ /**
* 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/text/TextAssistant.java b/core/java/android/text/TextAssistant.java
new file mode 100644
index 000000000000..b044981cdd95
--- /dev/null
+++ b/core/java/android/text/TextAssistant.java
@@ -0,0 +1,56 @@
+/*
+ * 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
new file mode 100644
index 000000000000..bb226daaaeb0
--- /dev/null
+++ b/core/java/android/text/TextClassification.java
@@ -0,0 +1,40 @@
+/*
+ * 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/TextSelection.java b/core/java/android/text/TextSelection.java
new file mode 100644
index 000000000000..9400458582c7
--- /dev/null
+++ b/core/java/android/text/TextSelection.java
@@ -0,0 +1,51 @@
+/*
+ * 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/widget/Editor.java b/core/java/android/widget/Editor.java
index 541fbe0528f1..95fafc471816 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -60,6 +60,8 @@ 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;
@@ -147,16 +149,17 @@ 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.
- private static final int MENU_ITEM_ORDER_UNDO = 1;
- private static final int MENU_ITEM_ORDER_REDO = 2;
- private static final int MENU_ITEM_ORDER_CUT = 3;
- private static final int MENU_ITEM_ORDER_COPY = 4;
- private static final int MENU_ITEM_ORDER_PASTE = 5;
- private static final int MENU_ITEM_ORDER_PASTE_AS_PLAIN_TEXT = 6;
- private static final int MENU_ITEM_ORDER_SHARE = 7;
- private static final int MENU_ITEM_ORDER_SELECT_ALL = 8;
- private static final int MENU_ITEM_ORDER_REPLACE = 9;
- private static final int MENU_ITEM_ORDER_PROCESS_TEXT_INTENT_ACTIONS_START = 10;
+ // 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_UNDO = 2;
+ private static final int MENU_ITEM_ORDER_REDO = 3;
+ private static final int MENU_ITEM_ORDER_SHARE = 4;
+ private static final int MENU_ITEM_ORDER_CUT = 5;
+ private static final int MENU_ITEM_ORDER_COPY = 6;
+ private static final int MENU_ITEM_ORDER_PASTE = 7;
+ private static final int MENU_ITEM_ORDER_PASTE_AS_PLAIN_TEXT = 8;
+ private static final int MENU_ITEM_ORDER_SELECT_ALL = 9;
+ private static final int MENU_ITEM_ORDER_REPLACE = 10;
+ private static final int MENU_ITEM_ORDER_PROCESS_TEXT_INTENT_ACTIONS_START = 11;
// Each Editor manages its own undo stack.
private final UndoManager mUndoManager = new UndoManager();
@@ -3767,10 +3770,12 @@ public class Editor {
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+ TextClassification textClassification = updateSelectionWithTextAssistant();
+
mode.setTitle(null);
mode.setSubtitle(null);
mode.setTitleOptionalHint(true);
- populateMenuWithItems(menu);
+ populateMenuWithItems(menu, textClassification);
Callback customCallback = getCustomCallback();
if (customCallback != null) {
@@ -3796,13 +3801,30 @@ 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) {
+ private void populateMenuWithItems(Menu menu, TextClassification textClassification) {
if (mTextView.canCut()) {
menu.add(Menu.NONE, TextView.ID_CUT, MENU_ITEM_ORDER_CUT,
com.android.internal.R.string.cut)
@@ -3827,11 +3849,12 @@ public class Editor {
if (mTextView.canShare()) {
menu.add(Menu.NONE, TextView.ID_SHARE, MENU_ITEM_ORDER_SHARE,
com.android.internal.R.string.share)
- .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+ .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
}
updateSelectAllItem(menu);
updateReplaceItem(menu);
+ updateAssistMenuItem(menu, textClassification);
}
@Override
@@ -3870,6 +3893,12 @@ 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.
+ }
+
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
if (mProcessTextIntentActionsHandler.performMenuItemAction(item)) {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 69f463cdd856..dba86556fd1d 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -76,6 +76,7 @@ import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.SpannedString;
import android.text.StaticLayout;
+import android.text.TextAssistant;
import android.text.TextDirectionHeuristic;
import android.text.TextDirectionHeuristics;
import android.text.TextPaint;
@@ -9819,6 +9820,35 @@ 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.
+ */
+ public void setTextAssistant(TextAssistant textAssistant) {
+ mTextAssistant = textAssistant;
+ }
+
+ /**
+ * 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.
+ */
+ 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 a NO_OP TextAssistant.
+ mTextAssistant = TextAssistant.NO_OP;
+ }
+ return mTextAssistant;
+ }
+
/**
* @hide
*/