diff options
7 files changed, 144 insertions, 61 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index dff51fd10..0f2ba4b5e 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -65,6 +65,8 @@ <meta-data android:name="com.google.android.backup.api_key" android:value="AEdPqrEAAAAIBXgtCEKQ6W0PXVnW-ZVia2KmlV2AxsTw3GjAeQ" /> + <uses-library android:name="com.qualcomm.qti.smartsearch" /> + <!-- The entrance point for Phone UI. stateAlwaysHidden is set to suppress keyboard show up on dialpad screen. --> diff --git a/src/com/android/dialer/database/DialerDatabaseHelper.java b/src/com/android/dialer/database/DialerDatabaseHelper.java index 511c2a7bc..5bdd95d81 100644 --- a/src/com/android/dialer/database/DialerDatabaseHelper.java +++ b/src/com/android/dialer/database/DialerDatabaseHelper.java @@ -46,6 +46,7 @@ import com.google.common.base.Objects; import com.google.common.base.Preconditions; import com.google.common.collect.Lists; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashSet; import java.util.Set; @@ -66,6 +67,10 @@ public class DialerDatabaseHelper extends SQLiteOpenHelper { private static final AtomicBoolean sInUpdate = new AtomicBoolean(false); private final Context mContext; + private Class mMultiMatchClass; + private Object mMultiMatchObject; + private Method mMultiMatchMethod; + /** * SmartDial DB version ranges: * <pre> @@ -82,7 +87,7 @@ public class DialerDatabaseHelper extends SQLiteOpenHelper { private static final String LAST_UPDATED_MILLIS = "last_updated_millis"; private static final String DATABASE_VERSION_PROPERTY = "database_version"; - private static final int MAX_ENTRIES = 20; + private static final int MAX_ENTRIES = 40; public interface Tables { /** Saves the necessary smart dial information of all contacts. */ @@ -342,6 +347,33 @@ public class DialerDatabaseHelper extends SQLiteOpenHelper { mContext = Preconditions.checkNotNull(context, "Context must not be null"); } + private void initMultiLanguageSearch() { + try { + if (mMultiMatchClass == null) { + mMultiMatchClass = Class + .forName("com.qualcomm.qti.smartsearch.SmartMatch"); + Log.d(TAG, "create multi match success"); + } + if (mMultiMatchObject == null && mMultiMatchClass != null) { + mMultiMatchObject = mMultiMatchClass.newInstance(); + } + if (mMultiMatchMethod == null && mMultiMatchClass != null) { + mMultiMatchMethod = mMultiMatchClass.getDeclaredMethod( + "getMatchStringIndex", String.class, String.class, + int.class); + } + } catch (Exception e) { + } + } + + public Object getMultiMatchObject() { + return mMultiMatchObject; + } + + public Method getMultiMatchMethod() { + return mMultiMatchMethod; + } + /** * Creates tables in the database when database is created for the first time. * @@ -749,6 +781,8 @@ public class DialerDatabaseHelper extends SQLiteOpenHelper { * update. */ public void updateSmartDialDatabase() { + initMultiLanguageSearch(); + final SQLiteDatabase db = getWritableDatabase(); synchronized(mLock) { @@ -913,7 +947,7 @@ public class DialerDatabaseHelper extends SQLiteOpenHelper { final SQLiteDatabase db = getReadableDatabase(); /** Uses SQL query wildcard '%' to represent prefix matching.*/ - final String looseQuery = query + "%"; + //final String looseQuery = query + "%"; final ArrayList<ContactNumber> result = Lists.newArrayList(); @@ -929,12 +963,7 @@ public class DialerDatabaseHelper extends SQLiteOpenHelper { SmartDialDbColumns.NUMBER + ", " + SmartDialDbColumns.CONTACT_ID + ", " + SmartDialDbColumns.LOOKUP_KEY + - " FROM " + Tables.SMARTDIAL_TABLE + " WHERE " + - SmartDialDbColumns.CONTACT_ID + " IN " + - " (SELECT " + PrefixColumns.CONTACT_ID + - " FROM " + Tables.PREFIX_TABLE + - " WHERE " + Tables.PREFIX_TABLE + "." + PrefixColumns.PREFIX + - " LIKE '" + looseQuery + "')" + + " FROM " + Tables.SMARTDIAL_TABLE + " ORDER BY " + SmartDialSortingOrder.SORT_ORDER, new String[] {currentTimeStamp}); if (cursor == null) { diff --git a/src/com/android/dialer/dialpad/SmartDialCursorLoader.java b/src/com/android/dialer/dialpad/SmartDialCursorLoader.java index 369079618..6727b5f1b 100644 --- a/src/com/android/dialer/dialpad/SmartDialCursorLoader.java +++ b/src/com/android/dialer/dialpad/SmartDialCursorLoader.java @@ -62,7 +62,7 @@ public class SmartDialCursorLoader extends AsyncTaskLoader<Cursor> { mQuery = SmartDialNameMatcher.normalizeNumber(query, SmartDialPrefix.getMap()); /** Constructs a name matcher object for matching names. */ - mNameMatcher = new SmartDialNameMatcher(mQuery, SmartDialPrefix.getMap()); + mNameMatcher = new SmartDialNameMatcher(mQuery, SmartDialPrefix.getMap(), mContext); } /** diff --git a/src/com/android/dialer/dialpad/SmartDialNameMatcher.java b/src/com/android/dialer/dialpad/SmartDialNameMatcher.java index 01268641d..532a06994 100644 --- a/src/com/android/dialer/dialpad/SmartDialNameMatcher.java +++ b/src/com/android/dialer/dialpad/SmartDialNameMatcher.java @@ -16,13 +16,17 @@ package com.android.dialer.dialpad; +import android.content.Context; import android.text.TextUtils; +import android.util.Log; +import com.android.dialer.database.DialerDatabaseHelper; import com.android.dialer.dialpad.SmartDialPrefix.PhoneNumberTokens; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.Lists; +import java.lang.reflect.Method; import java.util.ArrayList; /** @@ -34,6 +38,8 @@ import java.util.ArrayList; */ public class SmartDialNameMatcher { + private final static String TAG = "SmartDialNameMatcher"; + private String mQuery; // Whether or not we allow matches like 57 - (J)ohn (S)mith @@ -52,14 +58,24 @@ public class SmartDialNameMatcher { private String mNameMatchMask = ""; private String mPhoneNumberMatchMask = ""; + private Context mContext; + private String mSchar = "+*#-.(,)/ "; + private Object mMultiMatchObject; + private Method mMultiMatchMethod; + @VisibleForTesting - public SmartDialNameMatcher(String query) { - this(query, LATIN_SMART_DIAL_MAP); + public SmartDialNameMatcher(String query, Context context) { + this(query, LATIN_SMART_DIAL_MAP, context); } - public SmartDialNameMatcher(String query, SmartDialMap map) { + public SmartDialNameMatcher(String query, SmartDialMap map, Context context) { mQuery = query; mMap = map; + mContext = context; + mMultiMatchObject = DialerDatabaseHelper.getInstance(mContext) + .getMultiMatchObject(); + mMultiMatchMethod = DialerDatabaseHelper.getInstance(mContext) + .getMultiMatchMethod(); } /** @@ -130,22 +146,6 @@ public class SmartDialNameMatcher { // Try matching the number as is SmartDialMatchPosition matchPos = matchesNumberWithOffset(phoneNumber, query, 0); - if (matchPos == null) { - final PhoneNumberTokens phoneNumberTokens = - SmartDialPrefix.parsePhoneNumber(phoneNumber); - - if (phoneNumberTokens == null) { - return matchPos; - } - if (phoneNumberTokens.countryCodeOffset != 0) { - matchPos = matchesNumberWithOffset(phoneNumber, query, - phoneNumberTokens.countryCodeOffset); - } - if (matchPos == null && phoneNumberTokens.nanpCodeOffset != 0 && useNanp) { - matchPos = matchesNumberWithOffset(phoneNumber, query, - phoneNumberTokens.nanpCodeOffset); - } - } if (matchPos != null) { replaceBitInMask(builder, matchPos); mPhoneNumberMatchMask = builder.toString(); @@ -190,40 +190,47 @@ public class SmartDialNameMatcher { */ private SmartDialMatchPosition matchesNumberWithOffset(String phoneNumber, String query, int offset) { - if (TextUtils.isEmpty(phoneNumber) || TextUtils.isEmpty(query)) { + if (TextUtils.isEmpty(phoneNumber) || TextUtils.isEmpty(query) + || query.length() > phoneNumber.length()) { return null; } - int queryAt = 0; - int numberAt = offset; - for (int i = offset; i < phoneNumber.length(); i++) { - if (queryAt == query.length()) { - break; + + String phoneNum = phoneNumber.replaceAll("[\\+\\*\\#\\-\\.\\(\\,\\)\\/ ]", ""); + if (!TextUtils.isEmpty(phoneNum) && phoneNum.contains(query)) { + // firstly, find the start position in original phone number. + int start = phoneNum.indexOf(query); + int length = phoneNumber.length(); + for (int i = start; i < length; i++) { + char ch = phoneNumber.charAt(i); + if (ch != phoneNum.charAt(start)) { + continue; + } + if (phoneNumber.substring(i).replaceAll("[\\+\\*\\#\\-\\.\\(\\,\\)\\/ ]", "") + .indexOf(query) == 0) { + start = i; + break; + } } - char ch = phoneNumber.charAt(i); - if (mMap.isValidDialpadNumericChar(ch)) { - if (ch != query.charAt(queryAt)) { - return null; + // secondly, find the end position in original phone number. + int specialCount = 0; + int queryLength = query.length(); + int end = start + queryLength; + for (int i = start; i < length; i++) { + char ch = phoneNumber.charAt(i); + if (mSchar.indexOf(ch) != -1) { + specialCount++; + continue; } - queryAt++; - } else { - if (queryAt == 0) { - // Found a separator before any part of the query was matched, so advance the - // offset to avoid prematurely highlighting separators before the rest of the - // query. - // E.g. don't highlight the first '-' if we're matching 1-510-111-1111 with - // '510'. - // However, if the current offset is 0, just include the beginning separators - // anyway, otherwise the highlighting ends up looking weird. - // E.g. if we're matching (510)-111-1111 with '510', we should include the - // first '('. - if (offset != 0) { - offset++; - } + + if (i - start + 1 - specialCount == queryLength) { + end = i + 1; + break; } } - numberAt++; + return new SmartDialMatchPosition(start, end); + } else { + return null; } - return new SmartDialMatchPosition(0 + offset, numberAt); } /** @@ -407,7 +414,11 @@ public class SmartDialNameMatcher { public boolean matches(String displayName) { mMatchPositions.clear(); - return matchesCombination(displayName, mQuery, mMatchPositions); + if (mMultiMatchObject != null && mMultiMatchMethod != null) { + return matchesMultiLanguage(displayName, mQuery, mMatchPositions); + } else { + return matchesCombination(displayName, mQuery, mMatchPositions); + } } public ArrayList<SmartDialMatchPosition> getMatchPositions() { @@ -431,4 +442,45 @@ public class SmartDialNameMatcher { public String getQuery() { return mQuery; } + + boolean matchesMultiLanguage(String displayName, String query, + ArrayList<SmartDialMatchPosition> matchList) { + StringBuilder builder = new StringBuilder(); + constructEmptyMask(builder, displayName.length()); + mNameMatchMask = builder.toString(); + final int nameLength = displayName.length(); + final int queryLength = query.length(); + + if (queryLength == 0) { + return false; + } + // contains the start, not the end poing + try { + int[] indexs = (int[]) mMultiMatchMethod.invoke(mMultiMatchObject, + query, displayName, 0); + // mMultimatch.getMatchStringIndex(query, displayName, 0); + if (indexs == null) { + return false; + } + for (int i = 0; i < indexs.length; i = i + 2) { + int start = indexs[i]; + int end = indexs[i + 1]; + if (start >= 0 && end >= 0) { + matchList.add(new SmartDialMatchPosition(start, end + 1)); + } else { + Log.d(TAG, "Invalid index, start is:" + start + " end is:" + + end + " for name:" + displayName); + } + } + } catch (Exception e) { + Log.d(TAG, "Exception:" + e); + return false; + } + + for (SmartDialMatchPosition match : matchList) { + replaceBitInMask(builder, match); + } + mNameMatchMask = builder.toString(); + return true; + } } diff --git a/src/com/android/dialer/list/SmartDialNumberListAdapter.java b/src/com/android/dialer/list/SmartDialNumberListAdapter.java index 04c0d620d..d7e58a231 100644 --- a/src/com/android/dialer/list/SmartDialNumberListAdapter.java +++ b/src/com/android/dialer/list/SmartDialNumberListAdapter.java @@ -48,7 +48,7 @@ public class SmartDialNumberListAdapter extends DialerPhoneNumberListAdapter { public SmartDialNumberListAdapter(Context context) { super(context); - mNameMatcher = new SmartDialNameMatcher("", SmartDialPrefix.getMap()); + mNameMatcher = new SmartDialNameMatcher("", SmartDialPrefix.getMap(), context); if (DEBUG) { Log.v(TAG, "Constructing List Adapter"); diff --git a/tests/src/com/android/dialer/database/SmartDialPrefixTest.java b/tests/src/com/android/dialer/database/SmartDialPrefixTest.java index 9cb842e56..796303d78 100644 --- a/tests/src/com/android/dialer/database/SmartDialPrefixTest.java +++ b/tests/src/com/android/dialer/database/SmartDialPrefixTest.java @@ -163,7 +163,7 @@ public class SmartDialPrefixTest extends AndroidTestCase { private ArrayList<ContactNumber> getLooseMatchesFromDb(String query) { final SmartDialNameMatcher nameMatcher = new SmartDialNameMatcher(query, - SmartDialPrefix.getMap()); + SmartDialPrefix.getMap(), getContext()); return mTestHelper.getLooseMatches(query, nameMatcher); } diff --git a/tests/src/com/android/dialer/dialpad/SmartDialNameMatcherTest.java b/tests/src/com/android/dialer/dialpad/SmartDialNameMatcherTest.java index c1365f5cf..b0dc91d2c 100644 --- a/tests/src/com/android/dialer/dialpad/SmartDialNameMatcherTest.java +++ b/tests/src/com/android/dialer/dialpad/SmartDialNameMatcherTest.java @@ -30,7 +30,7 @@ import java.util.ArrayList; import junit.framework.TestCase; @SmallTest -public class SmartDialNameMatcherTest extends TestCase { +public class SmartDialNameMatcherTest extends AndroidTestCase { private static final String TAG = "SmartDialNameMatcherTest"; public void testMatches() { @@ -239,7 +239,7 @@ public class SmartDialNameMatcherTest extends TestCase { private void checkMatchesNumber(String number, String query, boolean expectedMatches, boolean matchNanp, int matchStart, int matchEnd) { - final SmartDialNameMatcher matcher = new SmartDialNameMatcher(query); + final SmartDialNameMatcher matcher = new SmartDialNameMatcher(query, getContext()); final SmartDialMatchPosition pos = matcher.matchesNumber(number, query, matchNanp); assertEquals(expectedMatches, pos != null); if (expectedMatches) { @@ -250,7 +250,7 @@ public class SmartDialNameMatcherTest extends TestCase { private void checkMatches(String displayName, String query, boolean expectedMatches, int... expectedMatchPositions) { - final SmartDialNameMatcher matcher = new SmartDialNameMatcher(query); + final SmartDialNameMatcher matcher = new SmartDialNameMatcher(query, getContext()); final ArrayList<SmartDialMatchPosition> matchPositions = new ArrayList<SmartDialMatchPosition>(); final boolean matches = matcher.matchesCombination( |