IOOB in text selection.
Several issues here:
1. when selection has been set to size 0 (should not be possible, but see 2.),
moving any of the selection handles will create an IOOB because we add/substract 1
with no test. Added min/max.
2. the text change detection, which stop selection mode, was done in
handleTextChanged. We need to go deeper. Some methods (such as setText())
directly call the more atomic sendOnTextChange(). Moved the test down
to this method. As a result, pressing the 'x' button in the QuickSearchBox
correctly stops selection mode (it used to leave an empty selection).
This change may also solve some weird similar issues in extracted mode where
it is sometimes possible to end up with a 0-length selection.
It may also impact Bug 5555929 since spellCheckSpans will now be correctly
updated on ANY text change.
3. the before != after test is flawed. When this method is called, the text
has been changed and selection mode should be stopped even when the new text
happens to have the same size.
Change-Id: I869ef728662f4350f22ed6149dd42db193c333ed
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index b106cc5..60c1ce9 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -7616,6 +7616,13 @@
list.get(i).onTextChanged(text, start, before, after);
}
}
+
+ updateSpellCheckSpans(start, start + after);
+
+ // Hide the controllers as soon as text is modified (typing, procedural...)
+ // We do not hide the span controllers, since they can be added when a new text is
+ // inserted into the text view (voice IME).
+ hideCursorControllers();
}
/**
@@ -7655,15 +7662,6 @@
sendOnTextChanged(buffer, start, before, after);
onTextChanged(buffer, start, before, after);
-
- updateSpellCheckSpans(start, start + after);
-
- // Hide the controllers if the amount of content changed
- if (before != after) {
- // We do not hide the span controllers, as they can be added when a new text is
- // inserted into the text view
- hideCursorControllers();
- }
}
/**
@@ -10840,7 +10838,7 @@
// Handles can not cross and selection is at least one character
final int selectionEnd = getSelectionEnd();
- if (offset >= selectionEnd) offset = selectionEnd - 1;
+ if (offset >= selectionEnd) offset = Math.max(0, selectionEnd - 1);
positionAtCursorOffset(offset, false);
}
@@ -10882,7 +10880,7 @@
// Handles can not cross and selection is at least one character
final int selectionStart = getSelectionStart();
- if (offset <= selectionStart) offset = selectionStart + 1;
+ if (offset <= selectionStart) offset = Math.min(selectionStart + 1, mText.length());
positionAtCursorOffset(offset, false);
}