aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java')
-rw-r--r--java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java168
1 files changed, 90 insertions, 78 deletions
diff --git a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
index 47891c6b7..09d0ea210 100644
--- a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
@@ -16,8 +16,6 @@
package com.android.inputmethod.latin;
-import com.android.inputmethod.latin.personalization.AccountUtils;
-
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
@@ -31,8 +29,10 @@ import android.provider.ContactsContract.Contacts;
import android.text.TextUtils;
import android.util.Log;
+import com.android.inputmethod.latin.personalization.AccountUtils;
import com.android.inputmethod.latin.utils.StringUtils;
+import java.io.File;
import java.util.List;
import java.util.Locale;
@@ -44,7 +44,8 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
private static final String TAG = ContactsBinaryDictionary.class.getSimpleName();
private static final String NAME = "contacts";
- private static boolean DEBUG = false;
+ private static final boolean DEBUG = false;
+ private static final boolean DEBUG_DUMP = false;
/**
* Frequency for contacts information into the dictionary
@@ -71,35 +72,36 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
private final boolean mUseFirstLastBigrams;
public ContactsBinaryDictionary(final Context context, final Locale locale) {
- super(context, getFilenameWithLocale(NAME, locale.toString()), Dictionary.TYPE_CONTACTS,
- false /* isUpdatable */);
+ this(context, locale, null /* dictFile */);
+ }
+
+ public ContactsBinaryDictionary(final Context context, final Locale locale,
+ final File dictFile) {
+ this(context, locale, dictFile, NAME);
+ }
+
+ protected ContactsBinaryDictionary(final Context context, final Locale locale,
+ final File dictFile, final String name) {
+ super(context, getDictName(name, locale, dictFile), locale, Dictionary.TYPE_CONTACTS,
+ dictFile);
mLocale = locale;
mUseFirstLastBigrams = useFirstLastBigramsForLocale(locale);
registerObserver(context);
-
- // Load the current binary dictionary from internal storage. If no binary dictionary exists,
- // loadDictionary will start a new thread to generate one asynchronously.
- loadDictionary();
+ reloadDictionaryIfRequired();
}
private synchronized void registerObserver(final Context context) {
- // Perform a managed query. The Activity will handle closing and requerying the cursor
- // when needed.
if (mObserver != null) return;
ContentResolver cres = context.getContentResolver();
cres.registerContentObserver(Contacts.CONTENT_URI, true, mObserver =
new ContentObserver(null) {
@Override
public void onChange(boolean self) {
- setRequiresReload(true);
+ setNeedsToReload();
}
});
}
- public void reopen(final Context context) {
- registerObserver(context);
- }
-
@Override
public synchronized void close() {
if (mObserver != null) {
@@ -110,14 +112,14 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
}
@Override
- public void loadDictionaryAsync() {
- loadDeviceAccountsEmailAddresses();
- loadDictionaryAsyncForUri(ContactsContract.Profile.CONTENT_URI);
+ public void loadInitialContentsLocked() {
+ loadDeviceAccountsEmailAddressesLocked();
+ loadDictionaryForUriLocked(ContactsContract.Profile.CONTENT_URI);
// TODO: Switch this URL to the newer ContactsContract too
- loadDictionaryAsyncForUri(Contacts.CONTENT_URI);
+ loadDictionaryForUriLocked(Contacts.CONTENT_URI);
}
- private void loadDeviceAccountsEmailAddresses() {
+ private void loadDeviceAccountsEmailAddressesLocked() {
final List<String> accountVocabulary =
AccountUtils.getDeviceAccountsEmailAddresses(mContext);
if (accountVocabulary == null || accountVocabulary.isEmpty()) {
@@ -127,29 +129,32 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
if (DEBUG) {
Log.d(TAG, "loadAccountVocabulary: " + word);
}
- super.addWord(word, null /* shortcut */, FREQUENCY_FOR_CONTACTS, 0 /* shortcutFreq */,
- false /* isNotAWord */);
+ runGCIfRequiredLocked(true /* mindsBlockByGC */);
+ addWordDynamicallyLocked(word, FREQUENCY_FOR_CONTACTS, null /* shortcut */,
+ 0 /* shortcutFreq */, false /* isNotAWord */, false /* isBlacklisted */,
+ BinaryDictionary.NOT_A_VALID_TIMESTAMP);
}
}
- private void loadDictionaryAsyncForUri(final Uri uri) {
+ private void loadDictionaryForUriLocked(final Uri uri) {
+ Cursor cursor = null;
try {
- Cursor cursor = mContext.getContentResolver()
- .query(uri, PROJECTION, null, null, null);
- if (cursor != null) {
- try {
- if (cursor.moveToFirst()) {
- sContactCountAtLastRebuild = getContactCount();
- addWords(cursor);
- }
- } finally {
- cursor.close();
- }
+ cursor = mContext.getContentResolver().query(uri, PROJECTION, null, null, null);
+ if (null == cursor) {
+ return;
+ }
+ if (cursor.moveToFirst()) {
+ sContactCountAtLastRebuild = getContactCount();
+ addWordsLocked(cursor);
}
} catch (final SQLiteException e) {
Log.e(TAG, "SQLiteException in the remote Contacts process.", e);
} catch (final IllegalStateException e) {
Log.e(TAG, "Contacts DB is having problems", e);
+ } finally {
+ if (null != cursor) {
+ cursor.close();
+ }
}
}
@@ -161,13 +166,17 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
return false;
}
- private void addWords(final Cursor cursor) {
+ private void addWordsLocked(final Cursor cursor) {
int count = 0;
while (!cursor.isAfterLast() && count < MAX_CONTACT_COUNT) {
String name = cursor.getString(INDEX_NAME);
if (isValidName(name)) {
- addName(name);
+ addNameLocked(name);
++count;
+ } else {
+ if (DEBUG_DUMP) {
+ Log.d(TAG, "Invalid name: " + name);
+ }
}
cursor.moveToNext();
}
@@ -176,18 +185,20 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
private int getContactCount() {
// TODO: consider switching to a rawQuery("select count(*)...") on the database if
// performance is a bottleneck.
+ Cursor cursor = null;
try {
- final Cursor cursor = mContext.getContentResolver().query(
- Contacts.CONTENT_URI, PROJECTION_ID_ONLY, null, null, null);
- if (cursor != null) {
- try {
- return cursor.getCount();
- } finally {
- cursor.close();
- }
+ cursor = mContext.getContentResolver().query(Contacts.CONTENT_URI, PROJECTION_ID_ONLY,
+ null, null, null);
+ if (null == cursor) {
+ return 0;
}
+ return cursor.getCount();
} catch (final SQLiteException e) {
Log.e(TAG, "SQLiteException in the remote Contacts process.", e);
+ } finally {
+ if (null != cursor) {
+ cursor.close();
+ }
}
return 0;
}
@@ -196,7 +207,7 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
* Adds the words in a name (e.g., firstname/lastname) to the binary dictionary along with their
* bigrams depending on locale.
*/
- private void addName(final String name) {
+ private void addNameLocked(final String name) {
int len = StringUtils.codePointCount(name);
String prevWord = null;
// TODO: Better tokenization for non-Latin writing systems
@@ -204,6 +215,9 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
if (Character.isLetter(name.codePointAt(i))) {
int end = getWordEndPosition(name, len, i);
String word = name.substring(i, end);
+ if (DEBUG_DUMP) {
+ Log.d(TAG, "addName word = " + word);
+ }
i = end - 1;
// Don't add single letter words, possibly confuses
// capitalization of i.
@@ -212,13 +226,15 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
if (DEBUG) {
Log.d(TAG, "addName " + name + ", " + word + ", " + prevWord);
}
- super.addWord(word, null /* shortcut */, FREQUENCY_FOR_CONTACTS,
- 0 /* shortcutFreq */, false /* isNotAWord */);
- if (!TextUtils.isEmpty(prevWord)) {
- if (mUseFirstLastBigrams) {
- super.addBigram(prevWord, word, FREQUENCY_FOR_CONTACTS_BIGRAM,
- 0 /* lastModifiedTime */);
- }
+ runGCIfRequiredLocked(true /* mindsBlockByGC */);
+ addWordDynamicallyLocked(word, FREQUENCY_FOR_CONTACTS,
+ null /* shortcut */, 0 /* shortcutFreq */, false /* isNotAWord */,
+ false /* isBlacklisted */, BinaryDictionary.NOT_A_VALID_TIMESTAMP);
+ if (!TextUtils.isEmpty(prevWord) && mUseFirstLastBigrams) {
+ runGCIfRequiredLocked(true /* mindsBlockByGC */);
+ addBigramDynamicallyLocked(prevWord, word,
+ FREQUENCY_FOR_CONTACTS_BIGRAM,
+ BinaryDictionary.NOT_A_VALID_TIMESTAMP);
}
prevWord = word;
}
@@ -244,12 +260,7 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
}
@Override
- protected boolean needsToReloadBeforeWriting() {
- return true;
- }
-
- @Override
- protected boolean hasContentChanged() {
+ protected boolean haveContentsChanged() {
final long startTime = SystemClock.uptimeMillis();
final int contactCount = getContactCount();
if (contactCount > MAX_CONTACT_COUNT) {
@@ -268,26 +279,27 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
// Check all contacts since it's not possible to find out which names have changed.
// This is needed because it's possible to receive extraneous onChange events even when no
// name has changed.
- Cursor cursor = mContext.getContentResolver().query(
- Contacts.CONTENT_URI, PROJECTION, null, null, null);
- if (cursor != null) {
- try {
- if (cursor.moveToFirst()) {
- while (!cursor.isAfterLast()) {
- String name = cursor.getString(INDEX_NAME);
- if (isValidName(name) && !isNameInDictionary(name)) {
- if (DEBUG) {
- Log.d(TAG, "Contact name missing: " + name + " (runtime = "
- + (SystemClock.uptimeMillis() - startTime) + " ms)");
- }
- return true;
+ final Cursor cursor = mContext.getContentResolver().query(Contacts.CONTENT_URI, PROJECTION,
+ null, null, null);
+ if (null == cursor) {
+ return false;
+ }
+ try {
+ if (cursor.moveToFirst()) {
+ while (!cursor.isAfterLast()) {
+ String name = cursor.getString(INDEX_NAME);
+ if (isValidName(name) && !isNameInDictionaryLocked(name)) {
+ if (DEBUG) {
+ Log.d(TAG, "Contact name missing: " + name + " (runtime = "
+ + (SystemClock.uptimeMillis() - startTime) + " ms)");
}
- cursor.moveToNext();
+ return true;
}
+ cursor.moveToNext();
}
- } finally {
- cursor.close();
}
+ } finally {
+ cursor.close();
}
if (DEBUG) {
Log.d(TAG, "No contacts changed. (runtime = " + (SystemClock.uptimeMillis() - startTime)
@@ -306,7 +318,7 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
/**
* Checks if the words in a name are in the current binary dictionary.
*/
- private boolean isNameInDictionary(final String name) {
+ private boolean isNameInDictionaryLocked(final String name) {
int len = StringUtils.codePointCount(name);
String prevWord = null;
for (int i = 0; i < len; i++) {
@@ -317,11 +329,11 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
final int wordLen = StringUtils.codePointCount(word);
if (wordLen < MAX_WORD_LENGTH && wordLen > 1) {
if (!TextUtils.isEmpty(prevWord) && mUseFirstLastBigrams) {
- if (!super.isValidBigramLocked(prevWord, word)) {
+ if (!isValidBigramLocked(prevWord, word)) {
return false;
}
} else {
- if (!super.isValidWordLocked(word)) {
+ if (!isValidWordLocked(word)) {
return false;
}
}