Merge "End the TC session on terminal selection event actions" into pi-dev
am: d0a4dddb9b
Change-Id: I81e90afd13d03846e240fc1fe5bef49bc01a668c
This commit is contained in:
@@ -641,7 +641,7 @@ public final class SelectionActionModeHelper {
|
||||
mSelectionStart, mSelectionEnd,
|
||||
SelectionEvent.ACTION_ABANDON, null /* classification */);
|
||||
mSelectionStart = mSelectionEnd = -1;
|
||||
mTextView.getTextClassificationSession().destroy();
|
||||
mLogger.endTextClassificationSession();
|
||||
mIsPending = false;
|
||||
}
|
||||
}
|
||||
@@ -707,8 +707,10 @@ public final class SelectionActionModeHelper {
|
||||
mTokenIterator.setText(mText);
|
||||
mStartIndex = index;
|
||||
mClassificationSession = classificationSession;
|
||||
mClassificationSession.onSelectionEvent(
|
||||
SelectionEvent.createSelectionStartedEvent(invocationMethod, 0));
|
||||
if (hasActiveClassificationSession()) {
|
||||
mClassificationSession.onSelectionEvent(
|
||||
SelectionEvent.createSelectionStartedEvent(invocationMethod, 0));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Avoid crashes due to logging.
|
||||
Log.e(LOG_TAG, "" + e.getMessage(), e);
|
||||
@@ -718,23 +720,19 @@ public final class SelectionActionModeHelper {
|
||||
public void logSelectionModified(int start, int end,
|
||||
@Nullable TextClassification classification, @Nullable TextSelection selection) {
|
||||
try {
|
||||
Preconditions.checkArgumentInRange(start, 0, mText.length(), "start");
|
||||
Preconditions.checkArgumentInRange(end, start, mText.length(), "end");
|
||||
int[] wordIndices = getWordDelta(start, end);
|
||||
if (selection != null) {
|
||||
if (mClassificationSession != null) {
|
||||
if (hasActiveClassificationSession()) {
|
||||
Preconditions.checkArgumentInRange(start, 0, mText.length(), "start");
|
||||
Preconditions.checkArgumentInRange(end, start, mText.length(), "end");
|
||||
int[] wordIndices = getWordDelta(start, end);
|
||||
if (selection != null) {
|
||||
mClassificationSession.onSelectionEvent(
|
||||
SelectionEvent.createSelectionModifiedEvent(
|
||||
wordIndices[0], wordIndices[1], selection));
|
||||
}
|
||||
} else if (classification != null) {
|
||||
if (mClassificationSession != null) {
|
||||
} else if (classification != null) {
|
||||
mClassificationSession.onSelectionEvent(
|
||||
SelectionEvent.createSelectionModifiedEvent(
|
||||
wordIndices[0], wordIndices[1], classification));
|
||||
}
|
||||
} else {
|
||||
if (mClassificationSession != null) {
|
||||
} else {
|
||||
mClassificationSession.onSelectionEvent(
|
||||
SelectionEvent.createSelectionModifiedEvent(
|
||||
wordIndices[0], wordIndices[1]));
|
||||
@@ -751,21 +749,23 @@ public final class SelectionActionModeHelper {
|
||||
@SelectionEvent.ActionType int action,
|
||||
@Nullable TextClassification classification) {
|
||||
try {
|
||||
Preconditions.checkArgumentInRange(start, 0, mText.length(), "start");
|
||||
Preconditions.checkArgumentInRange(end, start, mText.length(), "end");
|
||||
int[] wordIndices = getWordDelta(start, end);
|
||||
if (classification != null) {
|
||||
if (mClassificationSession != null) {
|
||||
if (hasActiveClassificationSession()) {
|
||||
Preconditions.checkArgumentInRange(start, 0, mText.length(), "start");
|
||||
Preconditions.checkArgumentInRange(end, start, mText.length(), "end");
|
||||
int[] wordIndices = getWordDelta(start, end);
|
||||
if (classification != null) {
|
||||
mClassificationSession.onSelectionEvent(
|
||||
SelectionEvent.createSelectionActionEvent(
|
||||
wordIndices[0], wordIndices[1], action, classification));
|
||||
}
|
||||
} else {
|
||||
if (mClassificationSession != null) {
|
||||
wordIndices[0], wordIndices[1], action,
|
||||
classification));
|
||||
} else {
|
||||
mClassificationSession.onSelectionEvent(
|
||||
SelectionEvent.createSelectionActionEvent(
|
||||
wordIndices[0], wordIndices[1], action));
|
||||
}
|
||||
if (SelectionEvent.isTerminal(action)) {
|
||||
endTextClassificationSession();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Avoid crashes due to logging.
|
||||
@@ -777,6 +777,16 @@ public final class SelectionActionModeHelper {
|
||||
return mEditTextLogger;
|
||||
}
|
||||
|
||||
public void endTextClassificationSession() {
|
||||
if (hasActiveClassificationSession()) {
|
||||
mClassificationSession.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasActiveClassificationSession() {
|
||||
return mClassificationSession != null && !mClassificationSession.isDestroyed();
|
||||
}
|
||||
|
||||
private int[] getWordDelta(int start, int end) {
|
||||
int[] wordIndices = new int[2];
|
||||
|
||||
|
||||
@@ -11527,12 +11527,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
} else {
|
||||
widgetType = TextClassifier.WIDGET_TYPE_UNSELECTABLE_TEXTVIEW;
|
||||
}
|
||||
// TODO: Tagged this widgetType with a * so it we can monitor if it reports
|
||||
// SelectionEvents exactly as the older Logger does. Remove once investigations
|
||||
// are complete.
|
||||
final TextClassificationContext textClassificationContext =
|
||||
new TextClassificationContext.Builder(
|
||||
mContext.getPackageName(), "*" + widgetType)
|
||||
mContext.getPackageName(), widgetType)
|
||||
.build();
|
||||
if (mTextClassifier != null) {
|
||||
mTextClassificationSession = tcm.createTextClassificationSession(
|
||||
|
||||
@@ -46,6 +46,7 @@ import static android.widget.espresso.TextViewAssertions.doesNotHaveStyledText;
|
||||
import static android.widget.espresso.TextViewAssertions.hasInsertionPointerAtIndex;
|
||||
import static android.widget.espresso.TextViewAssertions.hasSelection;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertFalse;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
|
||||
@@ -77,6 +78,7 @@ import android.view.ActionMode;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.textclassifier.SelectionEvent;
|
||||
import android.view.textclassifier.TextClassificationManager;
|
||||
import android.view.textclassifier.TextClassifier;
|
||||
import android.view.textclassifier.TextLinks;
|
||||
@@ -90,6 +92,9 @@ import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Tests the TextView widget from an Activity
|
||||
*/
|
||||
@@ -977,6 +982,30 @@ public class TextViewActivityTest {
|
||||
assertFloatingToolbarDoesNotContainItem(android.R.id.textAssist);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectionMetricsLogger_noAbandonAfterCopy() throws Throwable {
|
||||
final List<SelectionEvent> selectionEvents = new ArrayList<>();
|
||||
final TextClassifier classifier = new TextClassifier() {
|
||||
@Override
|
||||
public void onSelectionEvent(SelectionEvent event) {
|
||||
selectionEvents.add(event);
|
||||
}
|
||||
};
|
||||
final TextView textView = mActivity.findViewById(R.id.textview);
|
||||
mActivityRule.runOnUiThread(() -> textView.setTextClassifier(classifier));
|
||||
mInstrumentation.waitForIdleSync();
|
||||
final String text = "andyroid@android.com";
|
||||
|
||||
onView(withId(R.id.textview)).perform(replaceText(text));
|
||||
onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('@')));
|
||||
sleepForFloatingToolbarPopup();
|
||||
clickFloatingToolbarItem(mActivity.getString(com.android.internal.R.string.copy));
|
||||
mInstrumentation.waitForIdleSync();
|
||||
|
||||
final SelectionEvent lastEvent = selectionEvents.get(selectionEvents.size() - 1);
|
||||
assertEquals(SelectionEvent.ACTION_COPY, lastEvent.getEventType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPastePlainText_menuAction() {
|
||||
initializeClipboardWithText(TextStyle.STYLED);
|
||||
|
||||
Reference in New Issue
Block a user