From 135e465360dc36f1b9602660e290825d1e1fd00e Mon Sep 17 00:00:00 2001 From: Yorke Lee Date: Fri, 23 Oct 2015 18:12:51 -0700 Subject: Fix issue with entering '+' with switch access Distinguish between a manual long press and system long press (via accessibility) when modifying the current dial string. Bug: 23554996 Change-Id: I3fc610c8e24bdb39729b827715e08a3e7d73ba1f --- src/com/android/dialer/DialtactsActivity.java | 5 +- .../android/dialer/dialpad/DialpadFragment.java | 24 ++-- .../DialpadFragmentInstrumentationTest.java | 121 +++++++++++++++++++++ 3 files changed, 142 insertions(+), 8 deletions(-) create mode 100644 tests/src/com/android/dialer/dialpad/DialpadFragmentInstrumentationTest.java diff --git a/src/com/android/dialer/DialtactsActivity.java b/src/com/android/dialer/DialtactsActivity.java index 0893b1c56..140437e40 100644 --- a/src/com/android/dialer/DialtactsActivity.java +++ b/src/com/android/dialer/DialtactsActivity.java @@ -16,6 +16,8 @@ package com.android.dialer; +import com.google.common.annotations.VisibleForTesting; + import android.app.Fragment; import android.app.FragmentTransaction; import android.content.ActivityNotFoundException; @@ -128,7 +130,8 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O private static final String KEY_FIRST_LAUNCH = "first_launch"; private static final String KEY_IS_DIALPAD_SHOWN = "is_dialpad_shown"; - private static final String TAG_DIALPAD_FRAGMENT = "dialpad"; + @VisibleForTesting + public static final String TAG_DIALPAD_FRAGMENT = "dialpad"; private static final String TAG_REGULAR_SEARCH_FRAGMENT = "search"; private static final String TAG_SMARTDIAL_SEARCH_FRAGMENT = "smartdial"; private static final String TAG_FAVORITES_FRAGMENT = "favorites"; diff --git a/src/com/android/dialer/dialpad/DialpadFragment.java b/src/com/android/dialer/dialpad/DialpadFragment.java index 9c77f30c5..517711016 100644 --- a/src/com/android/dialer/dialpad/DialpadFragment.java +++ b/src/com/android/dialer/dialpad/DialpadFragment.java @@ -414,6 +414,7 @@ public class DialpadFragment extends Fragment return mDigits != null; } + @VisibleForTesting public EditText getDigitsWidget() { return mDigits; } @@ -970,7 +971,7 @@ public class DialpadFragment extends Fragment // Just for safety we also check if the digits field is empty or not. if (isDigitsEmpty() || TextUtils.equals(mDigits.getText(), "1")) { // We'll try to initiate voicemail and thus we want to remove irrelevant string. - removePreviousDigitIfPossible(); + removePreviousDigitIfPossible('1'); List subscriptionAccountHandles = PhoneAccountUtils.getSubscriptionPhoneAccounts(getActivity()); @@ -1007,8 +1008,13 @@ public class DialpadFragment extends Fragment return false; } case R.id.zero: { - // Remove tentative input ('0') done by onTouch(). - removePreviousDigitIfPossible(); + if (mPressedDialpadKeys.contains(view)) { + // If the zero key is currently pressed, then the long press occurred by touch + // (and not via other means like certain accessibility input methods). + // Remove the '0' that was input when the key was first pressed. + removePreviousDigitIfPossible('0'); + } + keyPressed(KeyEvent.KEYCODE_PLUS); // Stop tone immediately @@ -1029,12 +1035,16 @@ public class DialpadFragment extends Fragment } /** - * Remove the digit just before the current position. This can be used if we want to replace - * the previous digit or cancel previously entered character. + * Remove the digit just before the current position of the cursor, iff the following conditions + * are true: + * 1) The cursor is not positioned at index 0. + * 2) The digit before the current cursor position matches the current digit. + * + * @param digit to remove from the digits view. */ - private void removePreviousDigitIfPossible() { + private void removePreviousDigitIfPossible(char digit) { final int currentPosition = mDigits.getSelectionStart(); - if (currentPosition > 0) { + if (currentPosition > 0 && digit == mDigits.getText().charAt(currentPosition - 1)) { mDigits.setSelection(currentPosition); mDigits.getText().delete(currentPosition - 1, currentPosition); } diff --git a/tests/src/com/android/dialer/dialpad/DialpadFragmentInstrumentationTest.java b/tests/src/com/android/dialer/dialpad/DialpadFragmentInstrumentationTest.java new file mode 100644 index 000000000..876c13ba1 --- /dev/null +++ b/tests/src/com/android/dialer/dialpad/DialpadFragmentInstrumentationTest.java @@ -0,0 +1,121 @@ +package com.android.dialer.dialpad; + +import android.test.ActivityInstrumentationTestCase2; +import android.view.View; + +import com.android.dialer.DialtactsActivity; +import com.android.dialer.R; + +/** + * Tests that rely on instrumenting an actual instance of a {@link DialpadFragment}. + */ +public class DialpadFragmentInstrumentationTest extends + ActivityInstrumentationTestCase2 { + private DialtactsActivity mActivity; + + public DialpadFragmentInstrumentationTest() { + super(DialtactsActivity.class); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + mActivity = getActivity(); + } + + /** + * Simulates a long click event on the zero key with a prior onPressed callback. + * + */ + public void testManualLongClickZero_DeletesPreviousCharacter() { + final DialpadFragment fragment = showDialpad(); + pressAndReleaseKey(9, fragment); + + getInstrumentation().runOnMainSync(new Runnable() { + @Override + public void run() { + final View zeroKey = findViewByDigit(0, fragment); + fragment.onPressed(zeroKey, true); + fragment.onLongClick(zeroKey); + } + }); + + assertEquals("9+", fragment.getDigitsWidget().getText().toString()); + } + + /** + * Simulates a long click event on the zero key without a prior onPressed + * callback. + */ + public void testSystemLongClickZero_PreservesPreviousCharacter() { + final DialpadFragment fragment = showDialpad(); + pressAndReleaseKey(9, fragment); + + getInstrumentation().runOnMainSync(new Runnable() { + @Override + public void run() { + final View zeroKey = findViewByDigit(0, fragment); + fragment.onLongClick(zeroKey); + } + }); + + assertEquals("9+", fragment.getDigitsWidget().getText().toString()); + } + + private DialpadFragment showDialpad() { + getInstrumentation().runOnMainSync(new Runnable() { + @Override + public void run() { + mActivity.showDialpad(); + } + }); + getInstrumentation().waitForIdleSync(); + return (DialpadFragment) mActivity.getFragmentManager().findFragmentByTag( + DialtactsActivity.TAG_DIALPAD_FRAGMENT); + } + + private void pressAndReleaseKey(int digit, final DialpadFragment fragment) { + final View dialpadKey = findViewByDigit(digit, fragment); + final String digitsBefore = fragment.getDigitsWidget().getText().toString(); + getInstrumentation().runOnMainSync(new Runnable() { + @Override + public void run() { + fragment.onPressed(dialpadKey, true); + fragment.onPressed(dialpadKey, false); + } + }); + assertEquals(digitsBefore + String.valueOf(digit), + fragment.getDigitsWidget().getText().toString()); + } + + private View findViewByDigit(int digit, DialpadFragment fragment) { + return fragment.getView().findViewById(getViewIdByDigit(digit)); + } + + private int getViewIdByDigit(int digit) { + switch (digit) { + case 0: + return R.id.zero; + case 1: + return R.id.one; + case 2: + return R.id.two; + case 3: + return R.id.three; + case 4: + return R.id.four; + case 5: + return R.id.five; + case 6: + return R.id.six; + case 7: + return R.id.seven; + case 8: + return R.id.eight; + case 9: + return R.id.nine; + default: + return 0; + } + } +} -- cgit v1.2.3