Log the "change selected text" gesture.
This logs when the selected text is changed e.g. by typing on
the hard or soft keyboard.
Bug: 64914512
Test: bit FrameworksCoreTests:android.widget.TextViewActivityTest
Test: bit CtsWidgetTestCases:android.widget.cts.TextViewTest
Merged-In: I82b3b2157856c607d08a82c0a3d9fb938af4c06a
Change-Id: I82b3b2157856c607d08a82c0a3d9fb938af4c06a
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 31d878f..f1f25bf 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -1250,7 +1250,8 @@
}
}
- void sendOnTextChanged(int start, int after) {
+ void sendOnTextChanged(int start, int before, int after) {
+ getSelectionActionModeHelper().onTextChanged(start, start + before);
updateSpellCheckSpans(start, start + after, false);
// Flip flag to indicate the word iterator needs to have the text reset.
diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java
index aafa343..4ebb3cf 100644
--- a/core/java/android/widget/SelectionActionModeHelper.java
+++ b/core/java/android/widget/SelectionActionModeHelper.java
@@ -122,10 +122,8 @@
SelectionEvent.ActionType.DRAG, mTextClassification);
}
- public void onTypeOverSelection() {
- mSelectionTracker.onSelectionAction(
- mTextView.getSelectionStart(), mTextView.getSelectionEnd(),
- SelectionEvent.ActionType.OVERTYPE, mTextClassification);
+ public void onTextChanged(int start, int end) {
+ mSelectionTracker.onTextChanged(start, end, mTextClassification);
}
public boolean resetSelection(int textIndex) {
@@ -217,7 +215,6 @@
private int mOriginalEnd;
private int mSelectionStart;
private int mSelectionEnd;
- private boolean mSelectionStarted;
private boolean mAllowReset;
SelectionTracker(TextView textView) {
@@ -230,9 +227,8 @@
*/
public void onOriginalSelection(
CharSequence text, int selectionStart, int selectionEnd, boolean editableText) {
- mOriginalStart = selectionStart;
- mOriginalEnd = selectionEnd;
- mSelectionStarted = true;
+ mOriginalStart = mSelectionStart = selectionStart;
+ mOriginalEnd = mSelectionEnd = selectionEnd;
mAllowReset = false;
maybeInvalidateLogger();
mLogger.logSelectionStarted(text, selectionStart);
@@ -242,7 +238,7 @@
* Called when selection action mode is started and the results come from a classifier.
*/
public void onSmartSelection(SelectionResult result) {
- if (mSelectionStarted) {
+ if (isSelectionStarted()) {
mSelectionStart = result.mStart;
mSelectionEnd = result.mEnd;
mAllowReset = mSelectionStart != mOriginalStart || mSelectionEnd != mOriginalEnd;
@@ -257,7 +253,9 @@
public void onSelectionUpdated(
int selectionStart, int selectionEnd,
@Nullable TextClassification classification) {
- if (mSelectionStarted) {
+ if (isSelectionStarted()) {
+ mSelectionStart = selectionStart;
+ mSelectionEnd = selectionEnd;
mAllowReset = false;
mLogger.logSelectionModified(selectionStart, selectionEnd, classification, null);
}
@@ -268,10 +266,13 @@
*/
public void onSelectionDestroyed() {
mAllowReset = false;
- mSelectionStarted = false;
- mLogger.logSelectionAction(
- mSelectionStart, mSelectionEnd,
- SelectionEvent.ActionType.ABANDON, null /* classification */);
+ // Wait a few ms to see if the selection was destroyed because of a text change event.
+ mTextView.postDelayed(() -> {
+ mLogger.logSelectionAction(
+ mSelectionStart, mSelectionEnd,
+ SelectionEvent.ActionType.ABANDON, null /* classification */);
+ mSelectionStart = mSelectionEnd = -1;
+ }, 100 /* ms */);
}
/**
@@ -281,7 +282,7 @@
int selectionStart, int selectionEnd,
@SelectionEvent.ActionType int action,
@Nullable TextClassification classification) {
- if (mSelectionStarted) {
+ if (isSelectionStarted()) {
mAllowReset = false;
mLogger.logSelectionAction(selectionStart, selectionEnd, action, classification);
}
@@ -295,13 +296,15 @@
*/
public boolean resetSelection(int textIndex, Editor editor) {
final TextView textView = editor.getTextView();
- if (mSelectionStarted
+ if (isSelectionStarted()
&& mAllowReset
&& textIndex >= mSelectionStart && textIndex <= mSelectionEnd
&& textView.getText() instanceof Spannable) {
mAllowReset = false;
boolean selected = editor.selectCurrentWord();
if (selected) {
+ mSelectionStart = editor.getTextView().getSelectionStart();
+ mSelectionEnd = editor.getTextView().getSelectionEnd();
mLogger.logSelectionAction(
textView.getSelectionStart(), textView.getSelectionEnd(),
SelectionEvent.ActionType.RESET, null /* classification */);
@@ -311,11 +314,21 @@
return false;
}
+ public void onTextChanged(int start, int end, TextClassification classification) {
+ if (isSelectionStarted() && start == mSelectionStart && end == mSelectionEnd) {
+ onSelectionAction(start, end, SelectionEvent.ActionType.OVERTYPE, classification);
+ }
+ }
+
private void maybeInvalidateLogger() {
if (mLogger.isEditTextLogger() != mTextView.isTextEditable()) {
mLogger = new SelectionMetricsLogger(mTextView);
}
}
+
+ private boolean isSelectionStarted() {
+ return mSelectionStart >= 0 && mSelectionEnd >= 0 && mSelectionStart != mSelectionEnd;
+ }
}
// TODO: Write tests
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index cd2d2fd..11fe67c 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -9364,7 +9364,7 @@
}
}
- if (mEditor != null) mEditor.sendOnTextChanged(start, after);
+ if (mEditor != null) mEditor.sendOnTextChanged(start, before, after);
}
/**