Support auto-complete in PhoneNumberFormattingTextWatcher. Also, simplify logic.
Previously, the assumption was that only a deletion or an insertion can happen
at a time; but with auto-complete, a deletion and insertion happen at the same time.
Needed for bug 5992672 in the Messaging app and is nice to have in the platform.
Change-Id: I2d80cecc486e7a1ceeaeb34866bcd834074f5ead
diff --git a/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java b/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java
index 6f85c7d..983c349 100644
--- a/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java
+++ b/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java
@@ -39,30 +39,6 @@
* The formatting will be restarted once the text is cleared.
*/
public class PhoneNumberFormattingTextWatcher implements TextWatcher {
- /**
- * One or more characters were removed from the end.
- */
- private final static int STATE_REMOVE_LAST = 0;
-
- /**
- * One or more characters were appended.
- */
- private final static int STATE_APPEND = 1;
-
- /**
- * One or more digits were changed in the beginning or the middle of text.
- */
- private final static int STATE_MODIFY_DIGITS = 2;
-
- /**
- * The changes other than the above.
- */
- private final static int STATE_OTHER = 3;
-
- /**
- * The state of this change could be one value of the above
- */
- private int mState;
/**
* Indicates the change was caused by ourselves.
@@ -97,46 +73,30 @@
mFormatter = PhoneNumberUtil.getInstance().getAsYouTypeFormatter(countryCode);
}
+ @Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
if (mSelfChange || mStopFormatting) {
return;
}
- if (count == 0 && s.length() == start) {
- // Append one or more new chars
- mState = STATE_APPEND;
- } else if (after == 0 && start + count == s.length() && count > 0) {
- // Remove one or more chars from the end of string.
- mState = STATE_REMOVE_LAST;
- } else if (count > 0 && !hasSeparator(s, start, count)) {
- // Remove the dialable chars in the begin or middle of text.
- mState = STATE_MODIFY_DIGITS;
- } else {
- mState = STATE_OTHER;
+ // If the user manually deleted any non-dialable characters, stop formatting
+ if (count > 0 && hasSeparator(s, start, count)) {
+ stopFormatting();
}
}
+ @Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (mSelfChange || mStopFormatting) {
return;
}
- if (mState == STATE_OTHER) {
- if (count > 0 && !hasSeparator(s, start, count)) {
- // User inserted the dialable characters in the middle of text.
- mState = STATE_MODIFY_DIGITS;
- }
- }
- // Check whether we should stop formatting.
- if (mState == STATE_APPEND && count > 0 && hasSeparator(s, start, count)) {
- // User appended the non-dialable character, stop formatting.
- stopFormatting();
- } else if (mState == STATE_OTHER) {
- // User must insert or remove the non-dialable characters in the begin or middle of
- // number, stop formatting.
+ // If the user inserted any non-dialable characters, stop formatting
+ if (count > 0 && hasSeparator(s, start, count)) {
stopFormatting();
}
}
+ @Override
public synchronized void afterTextChanged(Editable s) {
if (mStopFormatting) {
// Restart the formatting when all texts were clear.
diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberWatcherTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberWatcherTest.java
index 6f0175e..a6a0fce 100644
--- a/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberWatcherTest.java
+++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberWatcherTest.java
@@ -182,14 +182,17 @@
public void testTextChangedByOtherTextWatcher() {
final TextWatcher cleanupTextWatcher = new TextWatcher() {
+ @Override
public void afterTextChanged(Editable s) {
s.clear();
}
+ @Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
+ @Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
}
@@ -208,6 +211,81 @@
assertEquals(expected1, number.toString());
}
+ /**
+ * Test the case where some other component is auto-completing what the user is typing
+ */
+ public void testAutoCompleteWithFormattedNumber() {
+ String init = "650-1";
+ String expected = "+1-650-123-4567"; // Different formatting than ours
+ testReplacement(init, expected, expected);
+ }
+
+ /**
+ * Test the case where some other component is auto-completing what the user is typing
+ */
+ public void testAutoCompleteWithFormattedNameAndNumber() {
+ String init = "650-1";
+ String expected = "Test User <650-123-4567>";
+ testReplacement(init, expected, expected);
+ }
+
+ /**
+ * Test the case where some other component is auto-completing what the user is typing
+ */
+ public void testAutoCompleteWithNumericNameAndNumber() {
+ String init = "650";
+ String expected = "2nd Test User <650-123-4567>";
+ testReplacement(init, expected, expected);
+ }
+
+ /**
+ * Test the case where some other component is auto-completing what the user is typing
+ */
+ public void testAutoCompleteWithUnformattedNumber() {
+ String init = "650-1";
+ String expected = "6501234567";
+ testReplacement(init, expected, expected);
+ }
+
+ /**
+ * Test the case where some other component is auto-completing what the user is typing, where
+ * the deleted text doesn't have any formatting and neither does the replacement text: in this
+ * case the replacement text should be formatted by the PhoneNumberFormattingTextWatcher.
+ */
+ public void testAutoCompleteUnformattedWithUnformattedNumber() {
+ String init = "650";
+ String replacement = "6501234567";
+ String expected = "(650) 123-4567";
+ testReplacement(init, replacement, expected);
+
+ String init2 = "650";
+ String replacement2 = "16501234567";
+ String expected2 = "1 650-123-4567";
+ testReplacement(init2, replacement2, expected2);
+ }
+
+ /**
+ * Helper method for testing replacing the entire string with another string
+ * @param init The initial string
+ * @param expected
+ */
+ private void testReplacement(String init, String replacement, String expected) {
+ TextWatcher textWatcher = getTextWatcher();
+
+ SpannableStringBuilder number = new SpannableStringBuilder(init);
+
+ // Replace entire text with the given values
+ textWatcher.beforeTextChanged(number, 0, init.length(), replacement.length());
+ number.replace(0, init.length(), replacement, 0, replacement.length());
+ Selection.setSelection(number, replacement.length()); // move the cursor to the end
+ textWatcher.onTextChanged(number, 0, init.length(), replacement.length());
+ textWatcher.afterTextChanged(number);
+
+ assertEquals(expected, number.toString());
+ // the cursor should be still at the end
+ assertEquals(expected.length(), Selection.getSelectionEnd(number));
+ }
+
private TextWatcher getTextWatcher() {
return new PhoneNumberFormattingTextWatcher("US");
}