diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java index a069e643afcb0..e07181abe19c8 100644 --- a/core/java/android/widget/SelectionActionModeHelper.java +++ b/core/java/android/widget/SelectionActionModeHelper.java @@ -90,7 +90,7 @@ public final class SelectionActionModeHelper { mTextView = mEditor.getTextView(); mTextClassificationHelper = new TextClassificationHelper( mTextView.getContext(), - mTextView::getTextClassifier, + mTextView::getTextClassificationSession, getText(mTextView), 0, 1, mTextView.getTextLocales()); mSelectionTracker = new SelectionTracker(mTextView); @@ -500,7 +500,7 @@ public final class SelectionActionModeHelper { selectionEnd = sortedSelectionIndices[1]; } mTextClassificationHelper.init( - mTextView::getTextClassifier, + mTextView::getTextClassificationSession, getText(mTextView), selectionStart, selectionEnd, mTextView.getTextLocales()); diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index ec07574f141fa..29914aababe32 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -12626,7 +12626,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return getTextClassifier() == TextClassifier.NO_OP; } - /** * Starts an ActionMode for the specified TextLinkSpan. * @@ -12670,7 +12669,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener .setDefaultLocales(getTextLocales()) .build(); final Supplier supplier = () -> - getTextClassifier().classifyText(request); + getTextClassificationSession().classifyText(request); final Consumer consumer = classification -> { if (classification != null) { if (!classification.getActions().isEmpty()) { diff --git a/core/tests/coretests/src/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java index 45d4b38d82aa5..7cde19c30dd4b 100644 --- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java +++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java @@ -120,8 +120,10 @@ public class TextViewActivityTest { public void setUp() { mActivity = mActivityRule.getActivity(); mInstrumentation = InstrumentationRegistry.getInstrumentation(); - mActivity.getSystemService(TextClassificationManager.class) - .setTextClassifier(TextClassifier.NO_OP); + TextClassificationManager tcm = mActivity.getSystemService( + TextClassificationManager.class); + tcm.setTextClassifier(TextClassifier.NO_OP); + tcm.setTextClassificationSessionFactory(null); } @Test @@ -1173,6 +1175,53 @@ public class TextViewActivityTest { assertEquals(TextClassifier.TYPE_PHONE, lastEvent.getEntityType()); } + @Test + public void testTextClassifierSession() throws Throwable { + useSystemDefaultTextClassifier(); + TextClassificationManager tcm = + mActivity.getSystemService(TextClassificationManager.class); + List testableTextClassifiers = new ArrayList<>(); + tcm.setTextClassificationSessionFactory(classificationContext -> { + TestableTextClassifier textClassifier = new TestableTextClassifier(); + testableTextClassifiers.add(textClassifier); + return new TextClassifier() { + private boolean mIsDestroyed = false; + + @Override + public TextSelection suggestSelection(TextSelection.Request request) { + return textClassifier.suggestSelection(request); + } + + @Override + public void destroy() { + mIsDestroyed = true; + } + + @Override + public boolean isDestroyed() { + return mIsDestroyed; + } + }; + }); + + // Long press to trigger selection + onView(withId(R.id.textview)).perform(replaceText("android.com")); + onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(0)); + sleepForFloatingToolbarPopup(); + // Click "Copy" to dismiss the selection. + clickFloatingToolbarItem(mActivity.getString(com.android.internal.R.string.copy)); + + // Long press to trigger another selection + onView(withId(R.id.textview)).perform(replaceText("android@android.com")); + onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(0)); + sleepForFloatingToolbarPopup(); + + // suggestSelection should be called in two different TextClassifier sessions. + assertEquals(2, testableTextClassifiers.size()); + assertEquals(1, testableTextClassifiers.get(0).getTextSelectionRequests().size()); + assertEquals(1, testableTextClassifiers.get(1).getTextSelectionRequests().size()); + } + @Test public void testPastePlainText_menuAction() { initializeClipboardWithText(TextStyle.STYLED); @@ -1227,6 +1276,7 @@ public class TextViewActivityTest { private final class TestableTextClassifier implements TextClassifier { final List mSelectionEvents = new ArrayList<>(); + final List mTextSelectionRequests = new ArrayList<>(); @Override public void onSelectionEvent(SelectionEvent event) { @@ -1235,6 +1285,7 @@ public class TextViewActivityTest { @Override public TextSelection suggestSelection(TextSelection.Request request) { + mTextSelectionRequests.add(request); return new TextSelection.Builder(request.getStartIndex(), request.getEndIndex()) .setEntityType(TextClassifier.TYPE_PHONE, 1) .build(); @@ -1243,5 +1294,9 @@ public class TextViewActivityTest { List getSelectionEvents() { return mSelectionEvents; } + + List getTextSelectionRequests() { + return mTextSelectionRequests; + } } }