summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQiang Chen <cqiang@codeaurora.org>2013-12-09 15:06:02 +0800
committerEthan Chen <intervigil@gmail.com>2014-08-28 10:48:40 -0700
commit32c6aed6c82c7810e470edc6773978637dbe0ba6 (patch)
treecc4311036db7e05c83f0d19854a86612cfda6673
parentb0999e8da2bbdd92af4fac92626de742c19374db (diff)
downloadandroid_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.java5
-rwxr-xr-x[-rw-r--r--]src/com/android/providers/contacts/ContactsDatabaseHelper.java35
-rwxr-xr-x[-rw-r--r--]src/com/android/providers/contacts/ContactsProvider2.java93
-rwxr-xr-x[-rw-r--r--]src/com/android/providers/contacts/DataRowHandlerForPhoneNumber.java5
-rwxr-xr-x[-rw-r--r--]src/com/android/providers/contacts/NameNormalizer.java2
-rwxr-xr-x[-rw-r--r--]src/com/android/providers/contacts/SearchIndexManager.java47
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);