Loading core/java/android/view/textclassifier/SelectionEvent.java +5 −1 Original line number Diff line number Diff line Loading @@ -120,8 +120,8 @@ public final class SelectionEvent implements Parcelable { private final int mAbsoluteStart; private final int mAbsoluteEnd; private final @EntityType String mEntityType; private @EntityType String mEntityType; private @EventType int mEventType; private String mPackageName = ""; private String mWidgetType = TextClassifier.WIDGET_TYPE_UNKNOWN; Loading Loading @@ -392,6 +392,10 @@ public final class SelectionEvent implements Parcelable { return mEntityType; } void setEntityType(@EntityType String entityType) { mEntityType = Preconditions.checkNotNull(entityType); } /** * Returns the package name of the app that this event originated in. */ Loading core/java/android/view/textclassifier/TextClassificationSession.java +5 −0 Original line number Diff line number Diff line Loading @@ -163,6 +163,11 @@ final class TextClassificationSession implements TextClassifier { case SelectionEvent.EVENT_AUTO_SELECTION: mSmartEvent = event; break; case SelectionEvent.ACTION_ABANDON: if (mPrevEvent != null) { event.setEntityType(mPrevEvent.getEntityType()); } break; case SelectionEvent.EVENT_SELECTION_MODIFIED: if (mPrevEvent != null && mPrevEvent.getAbsoluteStart() == event.getAbsoluteStart() Loading core/tests/coretests/src/android/widget/TextViewActivityTest.java +45 −0 Original line number Diff line number Diff line Loading @@ -76,6 +76,7 @@ import android.view.textclassifier.TextClassificationManager; import android.view.textclassifier.TextClassifier; import android.view.textclassifier.TextLinks; import android.view.textclassifier.TextLinksParams; import android.view.textclassifier.TextSelection; import android.widget.espresso.CustomViewActions.RelativeCoordinatesProvider; import androidx.test.InstrumentationRegistry; Loading Loading @@ -1019,6 +1020,50 @@ public class TextViewActivityTest { assertEquals(SelectionEvent.ACTION_COPY, lastEvent.getEventType()); } @Test public void testSelectionMetricsLogger_abandonEventIncludesEntityType() throws Throwable { final List<SelectionEvent> selectionEvents = new ArrayList<>(); final TextClassifier classifier = new TextClassifier() { @Override public void onSelectionEvent(SelectionEvent event) { selectionEvents.add(event); } @Override public TextSelection suggestSelection(TextSelection.Request request) { return new TextSelection.Builder(request.getStartIndex(), request.getEndIndex()) .setEntityType(TextClassifier.TYPE_PHONE, 1) .build(); } }; final TextView textView = mActivity.findViewById(R.id.textview); mActivityRule.runOnUiThread(() -> textView.setTextClassifier(classifier)); mInstrumentation.waitForIdleSync(); final String text = "My number is 987654321"; onView(withId(R.id.textview)).perform(replaceText(text)); onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('9'))); sleepForFloatingToolbarPopup(); onView(withId(R.id.textview)).perform(clickOnTextAtIndex(0)); mInstrumentation.waitForIdleSync(); // Abandon event is logged 100ms later. See SelectionActionModeHelper.SelectionTracker final long abandonDelay = 100; final long pollInterval = 10; long waitTime = 0; SelectionEvent lastEvent; do { lastEvent = selectionEvents.get(selectionEvents.size() - 1); if (lastEvent.getEventType() == SelectionEvent.ACTION_ABANDON) { break; } Thread.sleep(pollInterval); waitTime += pollInterval; } while (waitTime < abandonDelay * 10); assertEquals(SelectionEvent.ACTION_ABANDON, lastEvent.getEventType()); assertEquals(TextClassifier.TYPE_PHONE, lastEvent.getEntityType()); } @Test public void testPastePlainText_menuAction() { initializeClipboardWithText(TextStyle.STYLED); Loading Loading
core/java/android/view/textclassifier/SelectionEvent.java +5 −1 Original line number Diff line number Diff line Loading @@ -120,8 +120,8 @@ public final class SelectionEvent implements Parcelable { private final int mAbsoluteStart; private final int mAbsoluteEnd; private final @EntityType String mEntityType; private @EntityType String mEntityType; private @EventType int mEventType; private String mPackageName = ""; private String mWidgetType = TextClassifier.WIDGET_TYPE_UNKNOWN; Loading Loading @@ -392,6 +392,10 @@ public final class SelectionEvent implements Parcelable { return mEntityType; } void setEntityType(@EntityType String entityType) { mEntityType = Preconditions.checkNotNull(entityType); } /** * Returns the package name of the app that this event originated in. */ Loading
core/java/android/view/textclassifier/TextClassificationSession.java +5 −0 Original line number Diff line number Diff line Loading @@ -163,6 +163,11 @@ final class TextClassificationSession implements TextClassifier { case SelectionEvent.EVENT_AUTO_SELECTION: mSmartEvent = event; break; case SelectionEvent.ACTION_ABANDON: if (mPrevEvent != null) { event.setEntityType(mPrevEvent.getEntityType()); } break; case SelectionEvent.EVENT_SELECTION_MODIFIED: if (mPrevEvent != null && mPrevEvent.getAbsoluteStart() == event.getAbsoluteStart() Loading
core/tests/coretests/src/android/widget/TextViewActivityTest.java +45 −0 Original line number Diff line number Diff line Loading @@ -76,6 +76,7 @@ import android.view.textclassifier.TextClassificationManager; import android.view.textclassifier.TextClassifier; import android.view.textclassifier.TextLinks; import android.view.textclassifier.TextLinksParams; import android.view.textclassifier.TextSelection; import android.widget.espresso.CustomViewActions.RelativeCoordinatesProvider; import androidx.test.InstrumentationRegistry; Loading Loading @@ -1019,6 +1020,50 @@ public class TextViewActivityTest { assertEquals(SelectionEvent.ACTION_COPY, lastEvent.getEventType()); } @Test public void testSelectionMetricsLogger_abandonEventIncludesEntityType() throws Throwable { final List<SelectionEvent> selectionEvents = new ArrayList<>(); final TextClassifier classifier = new TextClassifier() { @Override public void onSelectionEvent(SelectionEvent event) { selectionEvents.add(event); } @Override public TextSelection suggestSelection(TextSelection.Request request) { return new TextSelection.Builder(request.getStartIndex(), request.getEndIndex()) .setEntityType(TextClassifier.TYPE_PHONE, 1) .build(); } }; final TextView textView = mActivity.findViewById(R.id.textview); mActivityRule.runOnUiThread(() -> textView.setTextClassifier(classifier)); mInstrumentation.waitForIdleSync(); final String text = "My number is 987654321"; onView(withId(R.id.textview)).perform(replaceText(text)); onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('9'))); sleepForFloatingToolbarPopup(); onView(withId(R.id.textview)).perform(clickOnTextAtIndex(0)); mInstrumentation.waitForIdleSync(); // Abandon event is logged 100ms later. See SelectionActionModeHelper.SelectionTracker final long abandonDelay = 100; final long pollInterval = 10; long waitTime = 0; SelectionEvent lastEvent; do { lastEvent = selectionEvents.get(selectionEvents.size() - 1); if (lastEvent.getEventType() == SelectionEvent.ACTION_ABANDON) { break; } Thread.sleep(pollInterval); waitTime += pollInterval; } while (waitTime < abandonDelay * 10); assertEquals(SelectionEvent.ACTION_ABANDON, lastEvent.getEventType()); assertEquals(TextClassifier.TYPE_PHONE, lastEvent.getEntityType()); } @Test public void testPastePlainText_menuAction() { initializeClipboardWithText(TextStyle.STYLED); Loading