diff options
author | emancebo <emancebo@cyngn.com> | 2014-07-25 17:37:28 -0700 |
---|---|---|
committer | Ed Mancebo <emancebo@cyngn.com> | 2015-01-06 21:41:26 +0000 |
commit | 86c9b695c49037c031a47637fa975136555c6287 (patch) | |
tree | 417eb43fe8d2c27cc658395868a3fbaf6d03ff48 | |
parent | 1f62ee2c3335c501c42aa5060b56efdbd9681534 (diff) | |
download | android_packages_apps_Dialer-86c9b695c49037c031a47637fa975136555c6287.tar.gz android_packages_apps_Dialer-86c9b695c49037c031a47637fa975136555c6287.tar.bz2 android_packages_apps_Dialer-86c9b695c49037c031a47637fa975136555c6287.zip |
Return match positions to enable highlighting for CN smart dial
Change-Id: I9255c582708c2fbfe22e7a2bf3ad971da692e2a9
3 files changed, 88 insertions, 14 deletions
diff --git a/src/com/android/dialer/dialpad/ChineseSmartDialMap.java b/src/com/android/dialer/dialpad/ChineseSmartDialMap.java index 3e2c13cca..5e63f8857 100644 --- a/src/com/android/dialer/dialpad/ChineseSmartDialMap.java +++ b/src/com/android/dialer/dialpad/ChineseSmartDialMap.java @@ -5,6 +5,8 @@ import com.android.providers.contacts.HanziToPinyin; import android.text.TextUtils; import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; public class ChineseSmartDialMap implements SmartDialMap { @@ -439,28 +441,63 @@ public class ChineseSmartDialMap implements SmartDialMap { } /* - * Since the dialpad is matching off the generated pinyin, the - * Chinese characters can't be highlighted. Just return true if - * there is a match without highlighting a character position. + * Uses the default matching logic on the pinyin name and attempts to map the match positions + * back to the original display name */ @Override public boolean matchesCombination(SmartDialNameMatcher smartDialNameMatcher, String displayName, String query, ArrayList<SmartDialMatchPosition> matchList) { + String pinyinName = tokenizeToPinyins(displayName); - if (displayName.equals(pinyinName)) { - return smartDialNameMatcher.matchesCombination(displayName, query, matchList); - } - final int nameLength = pinyinName.length(); - final int queryLength = query.length(); - if (nameLength < queryLength) { + ArrayList<SmartDialMatchPosition> computedMatchList = new ArrayList<SmartDialMatchPosition>(); + boolean matches = smartDialNameMatcher.matchesCombination(pinyinName, query, computedMatchList); + if (!matches) return false; - } - if (queryLength == 0) { - return false; + // name was translated to pinyin before matching. attempt to map the match positions + // back to the original display string + if (!displayName.equals(pinyinName)) { + + // construct an array that maps each character of the pinyin name back to the index of + // the hanzi token from which it came + // For example, if: + // displayName = 红霞李 + // pinyinName = "hong xia li" + // then: + // pinyinMapping = 0,0,0,0,-1,1,1,1,-1,2,2 + int[] pinyinMapping = new int[pinyinName.length()]; + int curToken = 0; + for (int i=0; i < pinyinName.length(); ++i) { + char c = pinyinName.charAt(i); + if (c == ' ') { + ++curToken; + pinyinMapping[i] = -1; + } + else { + pinyinMapping[i] = curToken; + } + } + + // calculate unique hanzi characters that are matched + Set<Integer> positionsToHighlight = new HashSet<Integer>(); + for (SmartDialMatchPosition matchPosition : computedMatchList) { + for (int pos = matchPosition.start; pos < matchPosition.end; ++pos) { + int mappedPos = pinyinMapping[pos]; + if (mappedPos >= 0) + positionsToHighlight.add(mappedPos); + } + } + + // reset computed matches + computedMatchList = new ArrayList<SmartDialMatchPosition>(); + for (int matchPos : positionsToHighlight) { + // use one object per position for simplicity + computedMatchList.add(new SmartDialMatchPosition(matchPos, matchPos+1)); + } } + matchList.addAll(computedMatchList); return true; } diff --git a/src/com/android/dialer/dialpad/SmartDialPrefix.java b/src/com/android/dialer/dialpad/SmartDialPrefix.java index e80e133e3..1026ebb60 100644 --- a/src/com/android/dialer/dialpad/SmartDialPrefix.java +++ b/src/com/android/dialer/dialpad/SmartDialPrefix.java @@ -127,6 +127,12 @@ public class SmartDialPrefix { sNanpInitialized = true; } + // for testing only + @VisibleForTesting + static void setSmartDialMap(SmartDialMap map) { + mMap = map; + } + /** * Explicitly setting the user Nanp to the given boolean */ diff --git a/tests/src/com/android/dialer/dialpad/SmartDialNameMatcherTest.java b/tests/src/com/android/dialer/dialpad/SmartDialNameMatcherTest.java index b0dc91d2c..0c910670c 100644 --- a/tests/src/com/android/dialer/dialpad/SmartDialNameMatcherTest.java +++ b/tests/src/com/android/dialer/dialpad/SmartDialNameMatcherTest.java @@ -33,6 +33,12 @@ import junit.framework.TestCase; public class SmartDialNameMatcherTest extends AndroidTestCase { private static final String TAG = "SmartDialNameMatcherTest"; + @Override + public void setUp() { + SmartDialPrefix.setSmartDialMap(new LatinSmartDialMap()); + SmartDialPrefix.setUserInNanpRegion(true); + } + public void testMatches() { // Test to ensure that all alphabetic characters are covered checkMatches("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", @@ -162,6 +168,30 @@ public class SmartDialNameMatcherTest extends AndroidTestCase { fail("Cyrillic letters aren't supported yet."); } + public void testMatches_chinese() { + SmartDialPrefix.setSmartDialMap(new ChineseSmartDialMap()); + + // basic cases + checkMatches("红霞李", "46", true, 0, 1); + checkMatches("红霞李", "46649", true, 0, 1, 1, 2); + checkMatches("红霞李", "5", true, 2, 3); + checkMatches("红霞李", "466494254", true, 0, 1, 1, 2, 2, 3); + + // test with spaces + checkMatches("红霞 李", "466494254", true, 0, 1, 1, 2, 2, 3); + checkMatches(" 红 霞 李", "466494254", true, 0, 1, 1, 2, 2, 3); + + // when character sets are mixed, match english only + checkMatches("Hongxia 李", "46", true, 0, 2); + checkMatches("Hongxia 李", "5", false); + + // make sure regular english cases still work + checkMatches("Meow Face", "63", true, 0, 2); + checkMatches("Meow Face", "32", true, 5, 7); + checkMatches("Meow Face", "632", true, 0, 1, 5, 7); + + SmartDialPrefix.setSmartDialMap(new LatinSmartDialMap()); + } public void testMatches_NumberBasic() { // Simple basic examples that start the match from the start of the number @@ -199,6 +229,7 @@ public class SmartDialNameMatcherTest extends AndroidTestCase { public void testMatches_NumberNANP() { SmartDialPrefix.setUserInNanpRegion(true); + // An 11 digit number prefixed with 1 should be matched by the 10 digit number, as well as // the 7 digit number (without area code) checkMatchesNumber("1-510-333-7596", "5103337596", true, true, 2, 14); @@ -253,8 +284,8 @@ public class SmartDialNameMatcherTest extends AndroidTestCase { final SmartDialNameMatcher matcher = new SmartDialNameMatcher(query, getContext()); final ArrayList<SmartDialMatchPosition> matchPositions = new ArrayList<SmartDialMatchPosition>(); - final boolean matches = matcher.matchesCombination( - displayName, query, matchPositions); + final boolean matches = + SmartDialPrefix.getMap().matchesCombination(matcher, displayName, query, matchPositions); Log.d(TAG, "query=" + query + " text=" + displayName + " nfd=" + Normalizer.normalize(displayName, Normalizer.Form.NFD) + " nfc=" + Normalizer.normalize(displayName, Normalizer.Form.NFC) |