TC: Ensure ABANDON event has an entity type.

Fixes: 80168739
Test: atest android.view.textclassifier
      atest android.widget.TextViewActivityTest

Change-Id: I6af99afcfcfd44960b538e45a2da91eb3f09a94f
diff --git a/core/java/android/view/textclassifier/SelectionEvent.java b/core/java/android/view/textclassifier/SelectionEvent.java
index 9ae0c65..374e667 100644
--- a/core/java/android/view/textclassifier/SelectionEvent.java
+++ b/core/java/android/view/textclassifier/SelectionEvent.java
@@ -120,8 +120,8 @@
 
     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;
@@ -392,6 +392,10 @@
         return mEntityType;
     }
 
+    void setEntityType(@EntityType String entityType) {
+        mEntityType = Preconditions.checkNotNull(entityType);
+    }
+
     /**
      * Returns the package name of the app that this event originated in.
      */
diff --git a/core/java/android/view/textclassifier/TextClassificationSession.java b/core/java/android/view/textclassifier/TextClassificationSession.java
index db0202a..cd2806a 100644
--- a/core/java/android/view/textclassifier/TextClassificationSession.java
+++ b/core/java/android/view/textclassifier/TextClassificationSession.java
@@ -163,6 +163,11 @@
                 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()
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
index 267a9c8..c3ef1c8 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
@@ -76,6 +76,7 @@
 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;
@@ -1020,6 +1021,50 @@
     }
 
     @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);