diff options
author | Qiang Chen <cqiang@codeaurora.org> | 2013-12-09 15:06:02 +0800 |
---|---|---|
committer | Ethan Chen <intervigil@gmail.com> | 2014-08-28 10:48:40 -0700 |
commit | 32c6aed6c82c7810e470edc6773978637dbe0ba6 (patch) | |
tree | cc4311036db7e05c83f0d19854a86612cfda6673 | |
parent | b0999e8da2bbdd92af4fac92626de742c19374db (diff) | |
download | android_packages_providers_ContactsProvider-32c6aed6c82c7810e470edc6773978637dbe0ba6.tar.gz android_packages_providers_ContactsProvider-32c6aed6c82c7810e470edc6773978637dbe0ba6.tar.bz2 android_packages_providers_ContactsProvider-32c6aed6c82c7810e470edc6773978637dbe0ba6.zip |
ContactsProvider: Support contact filter in smart dialer
Add query function to match the contacts for smart dialer.
Change-Id: I4eee8654699bd4ec6e1ba66f03e80701d3706865
-rwxr-xr-x[-rw-r--r--] | src/com/android/providers/contacts/ContactLocaleUtils.java | 5 | ||||
-rwxr-xr-x[-rw-r--r--] | src/com/android/providers/contacts/ContactsDatabaseHelper.java | 35 | ||||
-rwxr-xr-x[-rw-r--r--] | src/com/android/providers/contacts/ContactsProvider2.java | 93 | ||||
-rwxr-xr-x[-rw-r--r--] | src/com/android/providers/contacts/DataRowHandlerForPhoneNumber.java | 5 | ||||
-rwxr-xr-x[-rw-r--r--] | src/com/android/providers/contacts/NameNormalizer.java | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | src/com/android/providers/contacts/SearchIndexManager.java | 47 |
6 files changed, 185 insertions, 2 deletions
diff --git a/src/com/android/providers/contacts/ContactLocaleUtils.java b/src/com/android/providers/contacts/ContactLocaleUtils.java index c63f7fca..c2d88034 100644..100755 --- a/src/com/android/providers/contacts/ContactLocaleUtils.java +++ b/src/com/android/providers/contacts/ContactLocaleUtils.java @@ -399,6 +399,8 @@ public class ContactLocaleUtils { private final Locale mLocale; private final String mLanguage; private final ContactLocaleUtilsBase mUtils; + private final ContactLocaleUtilsBase mUtilsChinese = new SimplifiedChineseContactUtils( + Locale.CHINA); private ContactLocaleUtils(Locale locale) { if (locale == null) { @@ -477,6 +479,9 @@ public class ContactLocaleUtils { !KOREAN_LANGUAGE.equals(mLanguage)) { return JapaneseContactUtils.getRomajiNameLookupKeys(name); } + if (nameStyle == FullNameStyle.CHINESE) { + return mUtilsChinese.getNameLookupKeys(name, nameStyle); + } return mUtils.getNameLookupKeys(name, nameStyle); } diff --git a/src/com/android/providers/contacts/ContactsDatabaseHelper.java b/src/com/android/providers/contacts/ContactsDatabaseHelper.java index 78c9b8af..015850b1 100644..100755 --- a/src/com/android/providers/contacts/ContactsDatabaseHelper.java +++ b/src/com/android/providers/contacts/ContactsDatabaseHelper.java @@ -507,6 +507,7 @@ public class ContactsDatabaseHelper extends SQLiteOpenHelper { public static final String RAW_CONTACT_ID = "raw_contact_id"; public static final String NORMALIZED_NUMBER = "normalized_number"; public static final String MIN_MATCH = "min_match"; + public static final String NORMALIZED = "normalized"; } public interface NameLookupColumns { @@ -667,6 +668,7 @@ public class ContactsDatabaseHelper extends SQLiteOpenHelper { public static final String CONTACT_ID = "contact_id"; public static final String CONTENT = "content"; public static final String NAME = "name"; + public static final String NAME_DIGIT = "name_digit"; public static final String TOKENS = "tokens"; } @@ -1153,7 +1155,8 @@ public class ContactsDatabaseHelper extends SQLiteOpenHelper { PhoneLookupColumns.RAW_CONTACT_ID + " INTEGER REFERENCES raw_contacts(_id) NOT NULL," + PhoneLookupColumns.NORMALIZED_NUMBER + " TEXT NOT NULL," + - PhoneLookupColumns.MIN_MATCH + " TEXT NOT NULL" + + PhoneLookupColumns.MIN_MATCH + " TEXT NOT NULL," + + PhoneLookupColumns.NORMALIZED + " TEXT NOT NULL" + ");"); db.execSQL("CREATE INDEX phone_lookup_index ON " + Tables.PHONE_LOOKUP + " (" + @@ -1402,6 +1405,7 @@ public class ContactsDatabaseHelper extends SQLiteOpenHelper { + SearchIndexColumns.CONTACT_ID + " INTEGER REFERENCES contacts(_id) NOT NULL," + SearchIndexColumns.CONTENT + " TEXT, " + SearchIndexColumns.NAME + " TEXT, " + + SearchIndexColumns.NAME_DIGIT + " TEXT, " + SearchIndexColumns.TOKENS + " TEXT" + ")"); if (rebuildSqliteStats) { @@ -4037,11 +4041,40 @@ public class ContactsDatabaseHelper extends SQLiteOpenHelper { try { db.execSQL("ALTER TABLE " + Tables.CALLS + " ADD " + Calls.SUBSCRIPTION + " INTEGER NOT NULL DEFAULT 0;"); + db.execSQL("ALTER TABLE " + Tables.PHONE_LOOKUP + + " ADD " + PhoneLookupColumns.NORMALIZED + " TEXT NOT NULL DEFAULT '0';"); + updateSearchIndexTable(db); } catch (SQLException e) { Log.w(TAG, "Exception upgrading contacts2.db from 803 to 804 " + e); } } + private void updateSearchIndexTable(SQLiteDatabase db) { + db.execSQL("CREATE VIRTUAL TABLE " + "search_index_temp" + + " USING FTS4 (" + + SearchIndexColumns.CONTACT_ID + " INTEGER REFERENCES contacts(_id) NOT NULL," + + SearchIndexColumns.CONTENT + " TEXT, " + + SearchIndexColumns.NAME + " TEXT, " + + SearchIndexColumns.NAME_DIGIT + " TEXT, " + + SearchIndexColumns.TOKENS + " TEXT" + + ")"); + db.execSQL("INSERT INTO search_index_temp " + + "SELECT contact_id,content,name,NULL,tokens from " + Tables.SEARCH_INDEX); + db.execSQL("DROP TABLE IF EXISTS " + Tables.SEARCH_INDEX); + db.execSQL("CREATE VIRTUAL TABLE " + Tables.SEARCH_INDEX + + " USING FTS4 (" + + SearchIndexColumns.CONTACT_ID + " INTEGER REFERENCES contacts(_id) NOT NULL," + + SearchIndexColumns.CONTENT + " TEXT, " + + SearchIndexColumns.NAME + " TEXT, " + + SearchIndexColumns.NAME_DIGIT + " TEXT, " + + SearchIndexColumns.TOKENS + " TEXT" + + ")"); + db.execSQL("INSERT INTO " + Tables.SEARCH_INDEX + + " SELECT contact_id,content,name,name_digit,tokens from search_index_temp"); + db.execSQL("DROP TABLE IF EXISTS search_index_temp"); + updateSqliteStats(db); + } + public String extractHandleFromEmailAddress(String email) { Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(email); if (tokens.length == 0) { diff --git a/src/com/android/providers/contacts/ContactsProvider2.java b/src/com/android/providers/contacts/ContactsProvider2.java index 69a3c70f..04c8c6b2 100644..100755 --- a/src/com/android/providers/contacts/ContactsProvider2.java +++ b/src/com/android/providers/contacts/ContactsProvider2.java @@ -203,6 +203,16 @@ public class ContactsProvider2 extends AbstractContactsProvider private static final int BACKGROUND_TASK_CLEANUP_PHOTOS = 10; private static final int BACKGROUND_TASK_CLEAN_DELETE_LOG = 11; + // add for smart dialer + private static final String[] NUMBER_2 = {"a","b","c"}; + private static final String[] NUMBER_3 = {"d","e","f"}; + private static final String[] NUMBER_4 = {"g","h","i"}; + private static final String[] NUMBER_5 = {"j","k","l"}; + private static final String[] NUMBER_6 = {"m","n","o"}; + private static final String[] NUMBER_7 = {"p","q","r","s"}; + private static final String[] NUMBER_8 = {"t","u","v"}; + private static final String[] NUMBER_9 = {"w","x","y","z"}; + /** Default for the maximum number of returned aggregation suggestions. */ private static final int DEFAULT_MAX_SUGGESTIONS = 5; @@ -376,6 +386,7 @@ public class ContactsProvider2 extends AbstractContactsProvider private static final int DISPLAY_PHOTO_ID = 22000; private static final int PHOTO_DIMENSIONS = 22001; + private static final int SMART_DIALER_FILTER = 22002; private static final int DELETED_CONTACTS = 23000; private static final int DELETED_CONTACTS_ID = 23001; @@ -1277,6 +1288,7 @@ public class ContactsProvider2 extends AbstractContactsProvider matcher.addURI(ContactsContract.AUTHORITY, "pinned_position_update", PINNED_POSITION_UPDATE); + matcher.addURI(ContactsContract.AUTHORITY, "smart_dialer_filter", SMART_DIALER_FILTER); } private static class DirectoryInfo { @@ -5141,6 +5153,62 @@ public class ContactsProvider2 extends AbstractContactsProvider } } + // add for smart dialer + private static final ProjectionMap SMARTR_DIALER_FILTER_PROJECTION = ProjectionMap.builder() + .add("_id") + .add("normalized_number") + .add("display_name") + .add("photo_id") + .add("lookup") + .build(); + + private String[] getStringsFromNumber(char number) { + switch (number) { + case '2': + return NUMBER_2; + case '3': + return NUMBER_3; + case '4': + return NUMBER_4; + case '5': + return NUMBER_5; + case '6': + return NUMBER_6; + case '7': + return NUMBER_7; + case '8': + return NUMBER_8; + case '9': + return NUMBER_9; + } + return null; + } + + private String[] joinStringArray(String[] s1, String[] s2) { + if (null == s1) { + return s2; + } else if (null == s2) { + return s1; + } + String[] temp = new String[s1.length * s2.length]; + int pos = 0; + for (int i = 0; i < s1.length; i++) { + for (int j = 0; j < s2.length; j++) { + temp[pos] = s1[i] + s2[j]; + pos++; + } + } + return temp; + } + + private String[] getStringsFromNumbers(char[] numbers) { + String[] temp = getStringsFromNumber(numbers[0]); + for (int i = 1; i < numbers.length; i++) { + temp = joinStringArray(temp, getStringsFromNumber(numbers[i])); + } + return temp; + } + protected Cursor queryLocal(final Uri uri, final String[] projection, String selection, String[] selectionArgs, String sortOrder, final long directoryId, final CancellationSignal cancellationSignal) { @@ -5632,6 +5700,31 @@ public class ContactsProvider2 extends AbstractContactsProvider new Object[] {getMaxDisplayPhotoDim(), getMaxThumbnailDim()}); } + case SMART_DIALER_FILTER: { + String filter = uri.getQueryParameter("filter"); + if(TextUtils.isEmpty(filter)) break; + + String querySelect = "view_contacts JOIN (SELECT raw_contact_id, " + + "normalized_number, data_id FROM phone_lookup WHERE normalized='0')" + + " ON (name_raw_contact_id=raw_contact_id) " + + " LEFT OUTER JOIN agg_presence ON (_id = agg_presence.presence_contact_id)" + + " LEFT OUTER JOIN status_updates contacts_status_updates" + + " ON (status_update_id=contacts_status_updates.status_update_data_id) " + + " WHERE (_id IN (SELECT contact_id FROM search_index WHERE name_digit like '" + + filter + + "%' or name_digit like '% " + + filter + + "%')" + + " or normalized_number like '%" + + filter + + "%') AND normalized_number is not null AND _id IN default_directory " + + "order by view_contacts.last_time_contacted desc"; + + qb.setTables(querySelect); + qb.setProjectionMap(SMARTR_DIALER_FILTER_PROJECTION); + break; + } + case PHONES: case CALLABLES: { final String mimeTypeIsPhoneExpression = diff --git a/src/com/android/providers/contacts/DataRowHandlerForPhoneNumber.java b/src/com/android/providers/contacts/DataRowHandlerForPhoneNumber.java index 16faf2ab..93eb13ed 100644..100755 --- a/src/com/android/providers/contacts/DataRowHandlerForPhoneNumber.java +++ b/src/com/android/providers/contacts/DataRowHandlerForPhoneNumber.java @@ -33,6 +33,9 @@ import com.android.providers.contacts.aggregation.ContactAggregator; */ public class DataRowHandlerForPhoneNumber extends DataRowHandlerForCommonDataKind { + private static final String NORMALIZED_NUMBER = "0"; + private static final String NUMBERE164 = "1"; + public DataRowHandlerForPhoneNumber(Context context, ContactsDatabaseHelper dbHelper, ContactAggregator aggregator) { super(context, dbHelper, aggregator, Phone.CONTENT_ITEM_TYPE, Phone.TYPE, Phone.LABEL); @@ -122,6 +125,7 @@ public class DataRowHandlerForPhoneNumber extends DataRowHandlerForCommonDataKin phoneValues.put(PhoneLookupColumns.RAW_CONTACT_ID, rawContactId); phoneValues.put(PhoneLookupColumns.DATA_ID, dataId); phoneValues.put(PhoneLookupColumns.NORMALIZED_NUMBER, normalizedNumber); + phoneValues.put(PhoneLookupColumns.NORMALIZED, NORMALIZED_NUMBER); phoneValues.put(PhoneLookupColumns.MIN_MATCH, PhoneNumberUtils.toCallerIDMinMatch(normalizedNumber)); db.insert(Tables.PHONE_LOOKUP, null, phoneValues); @@ -130,6 +134,7 @@ public class DataRowHandlerForPhoneNumber extends DataRowHandlerForCommonDataKin phoneValues.put(PhoneLookupColumns.NORMALIZED_NUMBER, numberE164); phoneValues.put(PhoneLookupColumns.MIN_MATCH, PhoneNumberUtils.toCallerIDMinMatch(numberE164)); + phoneValues.put(PhoneLookupColumns.NORMALIZED, NUMBERE164); db.insert(Tables.PHONE_LOOKUP, null, phoneValues); } } diff --git a/src/com/android/providers/contacts/NameNormalizer.java b/src/com/android/providers/contacts/NameNormalizer.java index e3f98a82..460655fa 100644..100755 --- a/src/com/android/providers/contacts/NameNormalizer.java +++ b/src/com/android/providers/contacts/NameNormalizer.java @@ -103,7 +103,7 @@ public class NameNormalizer { /** * Returns a string containing just the letters and digits from the original string. */ - private static String lettersAndDigitsOnly(String name) { + public static String lettersAndDigitsOnly(String name) { char[] letters = name.toCharArray(); int length = 0; for (int i = 0; i < letters.length; i++) { diff --git a/src/com/android/providers/contacts/SearchIndexManager.java b/src/com/android/providers/contacts/SearchIndexManager.java index aeabaeaf..902940f0 100644..100755 --- a/src/com/android/providers/contacts/SearchIndexManager.java +++ b/src/com/android/providers/contacts/SearchIndexManager.java @@ -74,6 +74,7 @@ public class SearchIndexManager { private StringBuilder mSbContent = new StringBuilder(); private StringBuilder mSbName = new StringBuilder(); + private StringBuilder mSbNameDigit = new StringBuilder(); private StringBuilder mSbTokens = new StringBuilder(); private StringBuilder mSbElementContent = new StringBuilder(); private HashSet<String> mUniqueElements = new HashSet<String>(); @@ -87,6 +88,7 @@ public class SearchIndexManager { mSbContent.setLength(0); mSbTokens.setLength(0); mSbName.setLength(0); + mSbNameDigit.setLength(0); mSbElementContent.setLength(0); mUniqueElements.clear(); } @@ -99,6 +101,10 @@ public class SearchIndexManager { return mSbName.length() == 0 ? null : mSbName.toString(); } + public String getNameDigit() { + return mSbNameDigit.length() == 0 ? null : mSbNameDigit.toString(); + } + public String getTokens() { return mSbTokens.length() == 0 ? null : mSbTokens.toString(); } @@ -224,6 +230,40 @@ public class SearchIndexManager { } } + private String getNumberFromChar(char c) { + if (c >= 'a' && c <= 'c') { + return "2"; + } else if (c >= 'd' && c <= 'f') { + return "3"; + } else if (c >= 'g' && c <= 'i') { + return "4"; + } else if (c >= 'j' && c <= 'l') { + return "5"; + } else if (c >= 'm' && c <= 'o') { + return "6"; + } else if (c >= 'p' && c <= 's') { + return "7"; + } else if (c >= 't' && c <= 'v') { + return "8"; + } else if (c >= 'w' && c <= 'z') { + return "9"; + } else if ('0' <= c && c <= '9') { + return "" + c; + } else { + return " "; + } + } + + private String getNameNumber(String name){ + String number = ""; + String nameLow = name.toLowerCase(); + for(int i=0;i<nameLow.length();i++){ + char c = nameLow.charAt(i); + number = number + getNumberFromChar(c); + } + return number; + } + /** * Normalize a name and add to {@link #mSbName} */ @@ -232,6 +272,12 @@ public class SearchIndexManager { mSbName.append(' '); } mSbName.append(NameNormalizer.normalize(name)); + + if (mSbNameDigit.length() != 0) { + mSbNameDigit.append(' '); + } + mSbNameDigit.append(getNameNumber(NameNormalizer + .lettersAndDigitsOnly(name))); } } @@ -392,6 +438,7 @@ public class SearchIndexManager { mValues.clear(); mValues.put(SearchIndexColumns.CONTENT, builder.getContent()); mValues.put(SearchIndexColumns.NAME, builder.getName()); + mValues.put(SearchIndexColumns.NAME_DIGIT, builder.getNameDigit()); mValues.put(SearchIndexColumns.TOKENS, builder.getTokens()); mValues.put(SearchIndexColumns.CONTACT_ID, contactId); db.insert(Tables.SEARCH_INDEX, null, mValues); |