Skip to content

Commit

Permalink
Merge "Fix app crash if the selection is from reverse direction."
Browse files Browse the repository at this point in the history
  • Loading branch information
Joanne Chung authored and Gerrit Code Review committed Jul 6, 2020
2 parents 75a5b44 + 6dfbe83 commit 769acc4
Showing 1 changed file with 55 additions and 17 deletions.
72 changes: 55 additions & 17 deletions core/java/android/widget/SelectionActionModeHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -104,17 +104,44 @@ public final class SelectionActionModeHelper {
}
}

/**
* Swap the selection index if the start index is greater than end index.
*
* @return the swap result, index 0 is the start index and index 1 is the end index.
*/
private static int[] sortSelctionIndices(int selectionStart, int selectionEnd) {
if (selectionStart < selectionEnd) {
return new int[]{selectionStart, selectionEnd};
}
return new int[]{selectionEnd, selectionStart};
}

/**
* The {@link TextView} selection start and end index may not be sorted, this method will swap
* the {@link TextView} selection index if the start index is greater than end index.
*
* @param textView the selected TextView.
* @return the swap result, index 0 is the start index and index 1 is the end index.
*/
private static int[] sortSelctionIndicesFromTextView(TextView textView) {
int selectionStart = textView.getSelectionStart();
int selectionEnd = textView.getSelectionEnd();

return sortSelctionIndices(selectionStart, selectionEnd);
}

/**
* Starts Selection ActionMode.
*/
public void startSelectionActionModeAsync(boolean adjustSelection) {
// Check if the smart selection should run for editable text.
adjustSelection &= getTextClassificationSettings().isSmartSelectionEnabled();
int[] sortedSelectionIndices = sortSelctionIndicesFromTextView(mTextView);

mSelectionTracker.onOriginalSelection(
getText(mTextView),
mTextView.getSelectionStart(),
mTextView.getSelectionEnd(),
sortedSelectionIndices[0],
sortedSelectionIndices[1],
false /*isLink*/);
cancelAsyncTask();
if (skipTextClassification()) {
Expand All @@ -139,12 +166,14 @@ public void startSelectionActionModeAsync(boolean adjustSelection) {
* Starts Link ActionMode.
*/
public void startLinkActionModeAsync(int start, int end) {
mSelectionTracker.onOriginalSelection(getText(mTextView), start, end, true /*isLink*/);
int[] indexResult = sortSelctionIndices(start, end);
mSelectionTracker.onOriginalSelection(getText(mTextView), indexResult[0], indexResult[1],
true /*isLink*/);
cancelAsyncTask();
if (skipTextClassification()) {
startLinkActionMode(null);
} else {
resetTextClassificationHelper(start, end);
resetTextClassificationHelper(indexResult[0], indexResult[1]);
mTextClassificationAsyncTask = new TextClassificationAsyncTask(
mTextView,
mTextClassificationHelper.getTimeoutDuration(),
Expand Down Expand Up @@ -173,19 +202,23 @@ public void invalidateActionModeAsync() {

/** Reports a selection action event. */
public void onSelectionAction(int menuItemId, @Nullable String actionLabel) {
int[] sortedSelectionIndices = sortSelctionIndicesFromTextView(mTextView);
mSelectionTracker.onSelectionAction(
mTextView.getSelectionStart(), mTextView.getSelectionEnd(),
sortedSelectionIndices[0], sortedSelectionIndices[1],
getActionType(menuItemId), actionLabel, mTextClassification);
}

public void onSelectionDrag() {
int[] sortedSelectionIndices = sortSelctionIndicesFromTextView(mTextView);
mSelectionTracker.onSelectionAction(
mTextView.getSelectionStart(), mTextView.getSelectionEnd(),
sortedSelectionIndices[0], sortedSelectionIndices[1],
SelectionEvent.ACTION_DRAG, /* actionLabel= */ null, mTextClassification);
}

public void onTextChanged(int start, int end) {
mSelectionTracker.onTextChanged(start, end, mTextClassification);
int[] sortedSelectionIndices = sortSelctionIndices(start, end);
mSelectionTracker.onTextChanged(sortedSelectionIndices[0], sortedSelectionIndices[1],
mTextClassification);
}

public boolean resetSelection(int textIndex) {
Expand Down Expand Up @@ -302,9 +335,10 @@ private void startSelectionActionModeWithSmartSelectAnimation(
startSelectionActionMode(startSelectionResult);
};
// TODO do not trigger the animation if the change included only non-printable characters
int[] sortedSelectionIndices = sortSelctionIndicesFromTextView(mTextView);
final boolean didSelectionChange =
result != null && (mTextView.getSelectionStart() != result.mStart
|| mTextView.getSelectionEnd() != result.mEnd);
result != null && (sortedSelectionIndices[0] != result.mStart
|| sortedSelectionIndices[1] != result.mEnd);

if (!didSelectionChange) {
onAnimationEndCallback.run();
Expand Down Expand Up @@ -454,16 +488,18 @@ private void invalidateActionMode(@Nullable SelectionResult result) {
if (actionMode != null) {
actionMode.invalidate();
}
final int[] sortedSelectionIndices = sortSelctionIndicesFromTextView(mTextView);
mSelectionTracker.onSelectionUpdated(
mTextView.getSelectionStart(), mTextView.getSelectionEnd(), mTextClassification);
sortedSelectionIndices[0], sortedSelectionIndices[1], mTextClassification);
mTextClassificationAsyncTask = null;
}

private void resetTextClassificationHelper(int selectionStart, int selectionEnd) {
if (selectionStart < 0 || selectionEnd < 0) {
// Use selection indices
selectionStart = mTextView.getSelectionStart();
selectionEnd = mTextView.getSelectionEnd();
int[] sortedSelectionIndices = sortSelctionIndicesFromTextView(mTextView);
selectionStart = sortedSelectionIndices[0];
selectionEnd = sortedSelectionIndices[1];
}
mTextClassificationHelper.init(
mTextView::getTextClassifier,
Expand Down Expand Up @@ -603,10 +639,11 @@ && getText(textView) instanceof Spannable) {
mAllowReset = false;
boolean selected = editor.selectCurrentWord();
if (selected) {
mSelectionStart = editor.getTextView().getSelectionStart();
mSelectionEnd = editor.getTextView().getSelectionEnd();
final int[] sortedSelectionIndices = sortSelctionIndicesFromTextView(textView);
mSelectionStart = sortedSelectionIndices[0];
mSelectionEnd = sortedSelectionIndices[1];
mLogger.logSelectionAction(
textView.getSelectionStart(), textView.getSelectionEnd(),
sortedSelectionIndices[0], sortedSelectionIndices[1],
SelectionEvent.ACTION_RESET,
/* actionLabel= */ null, /* classification= */ null);
}
Expand Down Expand Up @@ -1179,8 +1216,9 @@ private static final class SelectionResult {

SelectionResult(int start, int end,
@Nullable TextClassification classification, @Nullable TextSelection selection) {
mStart = start;
mEnd = end;
int[] sortedIndices = sortSelctionIndices(start, end);
mStart = sortedIndices[0];
mEnd = sortedIndices[1];
mClassification = classification;
mSelection = selection;
}
Expand Down

0 comments on commit 769acc4

Please sign in to comment.