am bc4ae6bd: Passing account info to dictionaryFacilitator

* commit 'bc4ae6bdc0249f9282efea5d1fe7ccfefd6f93b0':
  Passing account info to dictionaryFacilitator
main
Jatin Matani 2014-12-17 00:08:14 +00:00 committed by Android Git Automerger
commit aadf94944e
14 changed files with 190 additions and 116 deletions

View File

@ -39,6 +39,8 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import javax.annotation.Nullable;
public class ContactsBinaryDictionary extends ExpandableBinaryDictionary { public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
private static final String[] PROJECTION = {BaseColumns._ID, Contacts.DISPLAY_NAME}; private static final String[] PROJECTION = {BaseColumns._ID, Contacts.DISPLAY_NAME};
@ -86,7 +88,7 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
// Note: This method is called by {@link DictionaryFacilitator} using Java reflection. // Note: This method is called by {@link DictionaryFacilitator} using Java reflection.
@ExternallyReferenced @ExternallyReferenced
public static ContactsBinaryDictionary getDictionary(final Context context, final Locale locale, public static ContactsBinaryDictionary getDictionary(final Context context, final Locale locale,
final File dictFile, final String dictNamePrefix) { final File dictFile, final String dictNamePrefix, @Nullable final String account) {
return new ContactsBinaryDictionary(context, locale, dictFile, dictNamePrefix + NAME); return new ContactsBinaryDictionary(context, locale, dictFile, dictNamePrefix + NAME);
} }

View File

@ -44,6 +44,7 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@ -56,8 +57,16 @@ import java.util.concurrent.TimeUnit;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
// TODO: Consolidate dictionaries in native code. /**
* Facilitates interaction with different kinds of dictionaries. Provides APIs
* to instantiate and select the correct dictionaries (based on language or account),
* update entries and fetch suggestions.
*
* Currently AndroidSpellCheckerService and LatinIME both use DictionaryFacilitator as
* a client for interacting with dictionaries.
*/
public class DictionaryFacilitator { public class DictionaryFacilitator {
// TODO: Consolidate dictionaries in native code.
public static final String TAG = DictionaryFacilitator.class.getSimpleName(); public static final String TAG = DictionaryFacilitator.class.getSimpleName();
// HACK: This threshold is being used when adding a capitalized entry in the User History // HACK: This threshold is being used when adding a capitalized entry in the User History
@ -99,7 +108,7 @@ public class DictionaryFacilitator {
private static final String DICT_FACTORY_METHOD_NAME = "getDictionary"; private static final String DICT_FACTORY_METHOD_NAME = "getDictionary";
private static final Class<?>[] DICT_FACTORY_METHOD_ARG_TYPES = private static final Class<?>[] DICT_FACTORY_METHOD_ARG_TYPES =
new Class[] { Context.class, Locale.class, File.class, String.class }; new Class[] { Context.class, Locale.class, File.class, String.class, String.class };
private static final String[] SUB_DICT_TYPES = private static final String[] SUB_DICT_TYPES =
Arrays.copyOfRange(DICT_TYPES_ORDERED_TO_GET_SUGGESTIONS, 1 /* start */, Arrays.copyOfRange(DICT_TYPES_ORDERED_TO_GET_SUGGESTIONS, 1 /* start */,
@ -107,8 +116,8 @@ public class DictionaryFacilitator {
/** /**
* Returns whether this facilitator is exactly for this list of locales. * Returns whether this facilitator is exactly for this list of locales.
*
* @param locales the list of locales to test against * @param locales the list of locales to test against
* @return true if this facilitator handles exactly this list of locales, false otherwise
*/ */
public boolean isForLocales(final Locale[] locales) { public boolean isForLocales(final Locale[] locales) {
if (locales.length != mDictionaryGroups.length) { if (locales.length != mDictionaryGroups.length) {
@ -129,34 +138,63 @@ public class DictionaryFacilitator {
return true; return true;
} }
/**
* Returns whether this facilitator is exactly for this account.
*
* @param account the account to test against.
*/
public boolean isForAccount(@Nullable final String account) {
for (final DictionaryGroup group : mDictionaryGroups) {
if (!TextUtils.equals(group.mAccount, account)) {
return false;
}
}
return true;
}
/** /**
* A group of dictionaries that work together for a single language. * A group of dictionaries that work together for a single language.
*/ */
private static class DictionaryGroup { private static class DictionaryGroup {
// TODO: Add null analysis annotations.
// TODO: Run evaluation to determine a reasonable value for these constants. The current // TODO: Run evaluation to determine a reasonable value for these constants. The current
// values are ad-hoc and chosen without any particular care or methodology. // values are ad-hoc and chosen without any particular care or methodology.
public static final float WEIGHT_FOR_MOST_PROBABLE_LANGUAGE = 1.0f; public static final float WEIGHT_FOR_MOST_PROBABLE_LANGUAGE = 1.0f;
public static final float WEIGHT_FOR_GESTURING_IN_NOT_MOST_PROBABLE_LANGUAGE = 0.95f; public static final float WEIGHT_FOR_GESTURING_IN_NOT_MOST_PROBABLE_LANGUAGE = 0.95f;
public static final float WEIGHT_FOR_TYPING_IN_NOT_MOST_PROBABLE_LANGUAGE = 0.6f; public static final float WEIGHT_FOR_TYPING_IN_NOT_MOST_PROBABLE_LANGUAGE = 0.6f;
public final Locale mLocale; /**
private Dictionary mMainDict; * The locale associated with the dictionary group.
*/
@Nullable public final Locale mLocale;
/**
* The user account associated with the dictionary group.
*/
@Nullable public final String mAccount;
@Nullable private Dictionary mMainDict;
// Confidence that the most probable language is actually the language the user is // Confidence that the most probable language is actually the language the user is
// typing in. For now, this is simply the number of times a word from this language // typing in. For now, this is simply the number of times a word from this language
// has been committed in a row. // has been committed in a row.
private int mConfidence = 0; private int mConfidence = 0;
public float mWeightForTypingInLocale = WEIGHT_FOR_MOST_PROBABLE_LANGUAGE; public float mWeightForTypingInLocale = WEIGHT_FOR_MOST_PROBABLE_LANGUAGE;
public float mWeightForGesturingInLocale = WEIGHT_FOR_MOST_PROBABLE_LANGUAGE; public float mWeightForGesturingInLocale = WEIGHT_FOR_MOST_PROBABLE_LANGUAGE;
public final ConcurrentHashMap<String, ExpandableBinaryDictionary> mSubDictMap = public final ConcurrentHashMap<String, ExpandableBinaryDictionary> mSubDictMap =
new ConcurrentHashMap<>(); new ConcurrentHashMap<>();
public DictionaryGroup() { public DictionaryGroup() {
mLocale = null; this(null /* locale */, null /* mainDict */, null /* account */,
Collections.<String, ExpandableBinaryDictionary>emptyMap() /* subDicts */);
} }
public DictionaryGroup(final Locale locale, final Dictionary mainDict, public DictionaryGroup(@Nullable final Locale locale,
@Nullable final Dictionary mainDict,
@Nullable final String account,
final Map<String, ExpandableBinaryDictionary> subDicts) { final Map<String, ExpandableBinaryDictionary> subDicts) {
mLocale = locale; mLocale = locale;
mAccount = account;
// The main dictionary can be asynchronously loaded. // The main dictionary can be asynchronously loaded.
setMainDict(mainDict); setMainDict(mainDict);
for (final Map.Entry<String, ExpandableBinaryDictionary> entry : subDicts.entrySet()) { for (final Map.Entry<String, ExpandableBinaryDictionary> entry : subDicts.entrySet()) {
@ -190,10 +228,17 @@ public class DictionaryFacilitator {
return mSubDictMap.get(dictType); return mSubDictMap.get(dictType);
} }
public boolean hasDict(final String dictType) { public boolean hasDict(final String dictType, @Nullable final String account) {
if (Dictionary.TYPE_MAIN.equals(dictType)) { if (Dictionary.TYPE_MAIN.equals(dictType)) {
return mMainDict != null; return mMainDict != null;
} }
if (Dictionary.TYPE_USER_HISTORY.equals(dictType) &&
!TextUtils.equals(account, mAccount)) {
// If the dictionary type is user history, & if the account doesn't match,
// return immediately. If the account matches, continue looking it up in the
// sub dictionary map.
return false;
}
return mSubDictMap.containsKey(dictType); return mSubDictMap.containsKey(dictType);
} }
@ -310,7 +355,7 @@ public class DictionaryFacilitator {
@Nullable @Nullable
private static ExpandableBinaryDictionary getSubDict(final String dictType, private static ExpandableBinaryDictionary getSubDict(final String dictType,
final Context context, final Locale locale, final File dictFile, final Context context, final Locale locale, final File dictFile,
final String dictNamePrefix) { final String dictNamePrefix, @Nullable final String account) {
final Class<? extends ExpandableBinaryDictionary> dictClass = final Class<? extends ExpandableBinaryDictionary> dictClass =
DICT_TYPE_TO_CLASS.get(dictType); DICT_TYPE_TO_CLASS.get(dictType);
if (dictClass == null) { if (dictClass == null) {
@ -320,7 +365,7 @@ public class DictionaryFacilitator {
final Method factoryMethod = dictClass.getMethod(DICT_FACTORY_METHOD_NAME, final Method factoryMethod = dictClass.getMethod(DICT_FACTORY_METHOD_NAME,
DICT_FACTORY_METHOD_ARG_TYPES); DICT_FACTORY_METHOD_ARG_TYPES);
final Object dict = factoryMethod.invoke(null /* obj */, final Object dict = factoryMethod.invoke(null /* obj */,
new Object[] { context, locale, dictFile, dictNamePrefix }); new Object[] { context, locale, dictFile, dictNamePrefix, account });
return (ExpandableBinaryDictionary) dict; return (ExpandableBinaryDictionary) dict;
} catch (final NoSuchMethodException | SecurityException | IllegalAccessException } catch (final NoSuchMethodException | SecurityException | IllegalAccessException
| IllegalArgumentException | InvocationTargetException e) { | IllegalArgumentException | InvocationTargetException e) {
@ -332,17 +377,19 @@ public class DictionaryFacilitator {
public void resetDictionaries(final Context context, final Locale[] newLocales, public void resetDictionaries(final Context context, final Locale[] newLocales,
final boolean useContactsDict, final boolean usePersonalizedDicts, final boolean useContactsDict, final boolean usePersonalizedDicts,
final boolean forceReloadMainDictionary, final boolean forceReloadMainDictionary,
@Nullable final String account,
final DictionaryInitializationListener listener) { final DictionaryInitializationListener listener) {
resetDictionariesWithDictNamePrefix(context, newLocales, useContactsDict, resetDictionariesWithDictNamePrefix(context, newLocales, useContactsDict,
usePersonalizedDicts, forceReloadMainDictionary, listener, "" /* dictNamePrefix */); usePersonalizedDicts, forceReloadMainDictionary, listener, "" /* dictNamePrefix */,
account);
} }
@Nullable @Nullable
static DictionaryGroup findDictionaryGroupWithLocale(final DictionaryGroup[] dictionaryGroups, static DictionaryGroup findDictionaryGroupWithLocale(final DictionaryGroup[] dictionaryGroups,
final Locale locale) { final Locale locale) {
for (int i = 0; i < dictionaryGroups.length; ++i) { for (DictionaryGroup dictionaryGroup : dictionaryGroups) {
if (locale.equals(dictionaryGroups[i].mLocale)) { if (locale.equals(dictionaryGroup.mLocale)) {
return dictionaryGroups[i]; return dictionaryGroup;
} }
} }
return null; return null;
@ -350,11 +397,13 @@ public class DictionaryFacilitator {
public void resetDictionariesWithDictNamePrefix(final Context context, public void resetDictionariesWithDictNamePrefix(final Context context,
final Locale[] newLocales, final Locale[] newLocales,
final boolean useContactsDict, final boolean usePersonalizedDicts, final boolean useContactsDict,
final boolean usePersonalizedDicts,
final boolean forceReloadMainDictionary, final boolean forceReloadMainDictionary,
@Nullable final DictionaryInitializationListener listener, @Nullable final DictionaryInitializationListener listener,
final String dictNamePrefix) { final String dictNamePrefix,
final HashMap<Locale, ArrayList<String>> existingDictsToCleanup = new HashMap<>(); @Nullable final String account) {
final HashMap<Locale, ArrayList<String>> existingDictionariesToCleanup = new HashMap<>();
// TODO: Make subDictTypesToUse configurable by resource or a static final list. // TODO: Make subDictTypesToUse configurable by resource or a static final list.
final HashSet<String> subDictTypesToUse = new HashSet<>(); final HashSet<String> subDictTypesToUse = new HashSet<>();
subDictTypesToUse.add(Dictionary.TYPE_USER); subDictTypesToUse.add(Dictionary.TYPE_USER);
@ -369,20 +418,20 @@ public class DictionaryFacilitator {
// Gather all dictionaries. We'll remove them from the list to clean up later. // Gather all dictionaries. We'll remove them from the list to clean up later.
for (final Locale newLocale : newLocales) { for (final Locale newLocale : newLocales) {
final ArrayList<String> dictsForLocale = new ArrayList<>(); final ArrayList<String> dictTypeForLocale = new ArrayList<>();
existingDictsToCleanup.put(newLocale, dictsForLocale); existingDictionariesToCleanup.put(newLocale, dictTypeForLocale);
final DictionaryGroup currentDictionaryGroupForLocale = final DictionaryGroup currentDictionaryGroupForLocale =
findDictionaryGroupWithLocale(mDictionaryGroups, newLocale); findDictionaryGroupWithLocale(mDictionaryGroups, newLocale);
if (null == currentDictionaryGroupForLocale) { if (null == currentDictionaryGroupForLocale) {
continue; continue;
} }
for (final String dictType : SUB_DICT_TYPES) { for (final String dictType : SUB_DICT_TYPES) {
if (currentDictionaryGroupForLocale.hasDict(dictType)) { if (currentDictionaryGroupForLocale.hasDict(dictType, account)) {
dictsForLocale.add(dictType); dictTypeForLocale.add(dictType);
} }
} }
if (currentDictionaryGroupForLocale.hasDict(Dictionary.TYPE_MAIN)) { if (currentDictionaryGroupForLocale.hasDict(Dictionary.TYPE_MAIN, account)) {
dictsForLocale.add(Dictionary.TYPE_MAIN); dictTypeForLocale.add(Dictionary.TYPE_MAIN);
} }
} }
@ -391,34 +440,35 @@ public class DictionaryFacilitator {
final Locale newLocale = newLocales[i]; final Locale newLocale = newLocales[i];
final DictionaryGroup dictionaryGroupForLocale = final DictionaryGroup dictionaryGroupForLocale =
findDictionaryGroupWithLocale(mDictionaryGroups, newLocale); findDictionaryGroupWithLocale(mDictionaryGroups, newLocale);
final ArrayList<String> dictsToCleanupForLocale = existingDictsToCleanup.get(newLocale); final ArrayList<String> dictTypesToCleanupForLocale =
existingDictionariesToCleanup.get(newLocale);
final boolean noExistingDictsForThisLocale = (null == dictionaryGroupForLocale); final boolean noExistingDictsForThisLocale = (null == dictionaryGroupForLocale);
final Dictionary mainDict; final Dictionary mainDict;
if (forceReloadMainDictionary || noExistingDictsForThisLocale if (forceReloadMainDictionary || noExistingDictsForThisLocale
|| !dictionaryGroupForLocale.hasDict(Dictionary.TYPE_MAIN)) { || !dictionaryGroupForLocale.hasDict(Dictionary.TYPE_MAIN, account)) {
mainDict = null; mainDict = null;
} else { } else {
mainDict = dictionaryGroupForLocale.getDict(Dictionary.TYPE_MAIN); mainDict = dictionaryGroupForLocale.getDict(Dictionary.TYPE_MAIN);
dictsToCleanupForLocale.remove(Dictionary.TYPE_MAIN); dictTypesToCleanupForLocale.remove(Dictionary.TYPE_MAIN);
} }
final Map<String, ExpandableBinaryDictionary> subDicts = new HashMap<>(); final Map<String, ExpandableBinaryDictionary> subDicts = new HashMap<>();
for (final String subDictType : subDictTypesToUse) { for (final String subDictType : subDictTypesToUse) {
final ExpandableBinaryDictionary subDict; final ExpandableBinaryDictionary subDict;
if (noExistingDictsForThisLocale if (noExistingDictsForThisLocale
|| !dictionaryGroupForLocale.hasDict(subDictType)) { || !dictionaryGroupForLocale.hasDict(subDictType, account)) {
// Create a new dictionary. // Create a new dictionary.
subDict = getSubDict(subDictType, context, newLocale, null /* dictFile */, subDict = getSubDict(subDictType, context, newLocale, null /* dictFile */,
dictNamePrefix); dictNamePrefix, account);
} else { } else {
// Reuse the existing dictionary, and don't close it at the end // Reuse the existing dictionary, and don't close it at the end
subDict = dictionaryGroupForLocale.getSubDict(subDictType); subDict = dictionaryGroupForLocale.getSubDict(subDictType);
dictsToCleanupForLocale.remove(subDictType); dictTypesToCleanupForLocale.remove(subDictType);
} }
subDicts.put(subDictType, subDict); subDicts.put(subDictType, subDict);
} }
newDictionaryGroups[i] = new DictionaryGroup(newLocale, mainDict, subDicts); newDictionaryGroups[i] = new DictionaryGroup(newLocale, mainDict, account, subDicts);
} }
// Replace Dictionaries. // Replace Dictionaries.
@ -437,9 +487,9 @@ public class DictionaryFacilitator {
} }
// Clean up old dictionaries. // Clean up old dictionaries.
for (final Locale localeToCleanUp : existingDictsToCleanup.keySet()) { for (final Locale localeToCleanUp : existingDictionariesToCleanup.keySet()) {
final ArrayList<String> dictTypesToCleanUp = final ArrayList<String> dictTypesToCleanUp =
existingDictsToCleanup.get(localeToCleanUp); existingDictionariesToCleanup.get(localeToCleanUp);
final DictionaryGroup dictionarySetToCleanup = final DictionaryGroup dictionarySetToCleanup =
findDictionaryGroupWithLocale(oldDictionaryGroups, localeToCleanUp); findDictionaryGroupWithLocale(oldDictionaryGroups, localeToCleanUp);
for (final String dictType : dictTypesToCleanUp) { for (final String dictType : dictTypesToCleanUp) {
@ -493,7 +543,8 @@ public class DictionaryFacilitator {
@UsedForTesting @UsedForTesting
public void resetDictionariesForTesting(final Context context, final Locale[] locales, public void resetDictionariesForTesting(final Context context, final Locale[] locales,
final ArrayList<String> dictionaryTypes, final HashMap<String, File> dictionaryFiles, final ArrayList<String> dictionaryTypes, final HashMap<String, File> dictionaryFiles,
final Map<String, Map<String, String>> additionalDictAttributes) { final Map<String, Map<String, String>> additionalDictAttributes,
@Nullable final String account) {
Dictionary mainDictionary = null; Dictionary mainDictionary = null;
final Map<String, ExpandableBinaryDictionary> subDicts = new HashMap<>(); final Map<String, ExpandableBinaryDictionary> subDicts = new HashMap<>();
@ -507,7 +558,7 @@ public class DictionaryFacilitator {
} else { } else {
final File dictFile = dictionaryFiles.get(dictType); final File dictFile = dictionaryFiles.get(dictType);
final ExpandableBinaryDictionary dict = getSubDict( final ExpandableBinaryDictionary dict = getSubDict(
dictType, context, locale, dictFile, "" /* dictNamePrefix */); dictType, context, locale, dictFile, "" /* dictNamePrefix */, account);
if (additionalDictAttributes.containsKey(dictType)) { if (additionalDictAttributes.containsKey(dictType)) {
dict.clearAndFlushDictionaryWithAdditionalAttributes( dict.clearAndFlushDictionaryWithAdditionalAttributes(
additionalDictAttributes.get(dictType)); additionalDictAttributes.get(dictType));
@ -520,7 +571,7 @@ public class DictionaryFacilitator {
subDicts.put(dictType, dict); subDicts.put(dictType, dict);
} }
} }
dictionaryGroups[i] = new DictionaryGroup(locale, mainDictionary, subDicts); dictionaryGroups[i] = new DictionaryGroup(locale, mainDictionary, account, subDicts);
} }
mDictionaryGroups = dictionaryGroups; mDictionaryGroups = dictionaryGroups;
mMostProbableDictionaryGroup = dictionaryGroups[0]; mMostProbableDictionaryGroup = dictionaryGroups[0];
@ -576,7 +627,7 @@ public class DictionaryFacilitator {
public boolean hasPersonalizationDictionary() { public boolean hasPersonalizationDictionary() {
final DictionaryGroup[] dictionaryGroups = mDictionaryGroups; final DictionaryGroup[] dictionaryGroups = mDictionaryGroups;
for (final DictionaryGroup dictionaryGroup : dictionaryGroups) { for (final DictionaryGroup dictionaryGroup : dictionaryGroups) {
if (dictionaryGroup.hasDict(Dictionary.TYPE_PERSONALIZATION)) { if (dictionaryGroup.hasDict(Dictionary.TYPE_PERSONALIZATION, null /* account */)) {
return true; return true;
} }
} }
@ -677,7 +728,8 @@ public class DictionaryFacilitator {
// History dictionary in order to avoid suggesting them until the dictionary // History dictionary in order to avoid suggesting them until the dictionary
// consolidation is done. // consolidation is done.
// TODO: Remove this hack when ready. // TODO: Remove this hack when ready.
final int lowerCaseFreqInMainDict = dictionaryGroup.hasDict(Dictionary.TYPE_MAIN) ? final int lowerCaseFreqInMainDict = dictionaryGroup.hasDict(Dictionary.TYPE_MAIN,
null /* account */) ?
dictionaryGroup.getDict(Dictionary.TYPE_MAIN).getFrequency(lowerCasedWord) : dictionaryGroup.getDict(Dictionary.TYPE_MAIN).getFrequency(lowerCasedWord) :
Dictionary.NOT_A_PROBABILITY; Dictionary.NOT_A_PROBABILITY;
if (maxFreq < lowerCaseFreqInMainDict if (maxFreq < lowerCaseFreqInMainDict

View File

@ -102,10 +102,12 @@ public class DictionaryFacilitatorLruCache {
private void resetDictionariesForLocaleLocked(final DictionaryFacilitator dictionaryFacilitator, private void resetDictionariesForLocaleLocked(final DictionaryFacilitator dictionaryFacilitator,
final Locale locale) { final Locale locale) {
// Note: Given that personalized dictionaries are not used here; we can pass null account.
dictionaryFacilitator.resetDictionariesWithDictNamePrefix(mContext, new Locale[] { locale }, dictionaryFacilitator.resetDictionariesWithDictNamePrefix(mContext, new Locale[] { locale },
mUseContactsDictionary, false /* usePersonalizedDicts */, mUseContactsDictionary, false /* usePersonalizedDicts */,
false /* forceReloadMainDictionary */, null /* listener */, false /* forceReloadMainDictionary */, null /* listener */,
mDictionaryNamePrefix); mDictionaryNamePrefix,
null /* account */);
} }
public void setUseContactsDictionary(final boolean useContectsDictionary) { public void setUseContactsDictionary(final boolean useContectsDictionary) {

View File

@ -633,12 +633,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// been displayed. Opening dictionaries never affects responsivity as dictionaries are // been displayed. Opening dictionaries never affects responsivity as dictionaries are
// asynchronously loaded. // asynchronously loaded.
if (!mHandler.hasPendingReopenDictionaries()) { if (!mHandler.hasPendingReopenDictionaries()) {
resetDictionaryFacilitatorForLocale(locales); resetDictionaryFacilitator(locales);
} }
mDictionaryFacilitator.updateEnabledSubtypes(mRichImm.getMyEnabledInputMethodSubtypeList( mDictionaryFacilitator.updateEnabledSubtypes(mRichImm.getMyEnabledInputMethodSubtypeList(
true /* allowsImplicitlySelectedSubtypes */)); true /* allowsImplicitlySelectedSubtypes */));
refreshPersonalizationDictionarySession(currentSettingsValues); refreshPersonalizationDictionarySession(currentSettingsValues);
mStatsUtilsManager.onLoadSettings(currentSettingsValues); mStatsUtilsManager.onLoadSettings(currentSettingsValues);
resetDictionaryFacilitatorIfNecessary();
} }
private void refreshPersonalizationDictionarySession( private void refreshPersonalizationDictionarySession(
@ -676,7 +677,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
void resetDictionaryFacilitatorIfNecessary() { void resetDictionaryFacilitatorIfNecessary() {
final Locale[] subtypeSwitcherLocales = mRichImm.getCurrentSubtypeLocales(); final Locale[] subtypeSwitcherLocales = mRichImm.getCurrentSubtypeLocales();
if (mDictionaryFacilitator.isForLocales(subtypeSwitcherLocales)) { if (mDictionaryFacilitator.isForLocales(subtypeSwitcherLocales)
&& mDictionaryFacilitator.isForAccount(mSettings.getCurrent().mAccount)) {
return; return;
} }
final Locale[] subtypeLocales; final Locale[] subtypeLocales;
@ -690,20 +692,23 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
} else { } else {
subtypeLocales = subtypeSwitcherLocales; subtypeLocales = subtypeSwitcherLocales;
} }
resetDictionaryFacilitatorForLocale(subtypeLocales); resetDictionaryFacilitator(subtypeLocales);
} }
/** /**
* Reset the facilitator by loading dictionaries for the locales and the current settings values * Reset the facilitator by loading dictionaries for the locales and
* the current settings values.
* *
* @param locales the locales * @param locales the locales
*/ */
// TODO: make sure the current settings always have the right locales, and read from them // TODO: make sure the current settings always have the right locales, and read from them.
private void resetDictionaryFacilitatorForLocale(final Locale[] locales) { private void resetDictionaryFacilitator(final Locale[] locales) {
final SettingsValues settingsValues = mSettings.getCurrent(); final SettingsValues settingsValues = mSettings.getCurrent();
mDictionaryFacilitator.resetDictionaries(this /* context */, locales, mDictionaryFacilitator.resetDictionaries(this /* context */, locales,
settingsValues.mUseContactsDict, settingsValues.mUsePersonalizedDicts, settingsValues.mUseContactsDict, settingsValues.mUsePersonalizedDicts,
false /* forceReloadMainDictionary */, this); false /* forceReloadMainDictionary */,
settingsValues.mAccount,
this /* DictionaryInitializationListener */);
if (settingsValues.mAutoCorrectionEnabledPerUserSettings) { if (settingsValues.mAutoCorrectionEnabledPerUserSettings) {
mInputLogic.mSuggest.setAutoCorrectionThreshold( mInputLogic.mSuggest.setAutoCorrectionThreshold(
settingsValues.mAutoCorrectionThreshold); settingsValues.mAutoCorrectionThreshold);
@ -718,7 +723,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
final SettingsValues settingsValues = mSettings.getCurrent(); final SettingsValues settingsValues = mSettings.getCurrent();
mDictionaryFacilitator.resetDictionaries(this /* context */, mDictionaryFacilitator.resetDictionaries(this /* context */,
mDictionaryFacilitator.getLocales(), settingsValues.mUseContactsDict, mDictionaryFacilitator.getLocales(), settingsValues.mUseContactsDict,
settingsValues.mUsePersonalizedDicts, true /* forceReloadMainDictionary */, this); settingsValues.mUsePersonalizedDicts,
true /* forceReloadMainDictionary */,
settingsValues.mAccount,
this /* DictionaryInitializationListener */);
} }
@Override @Override
@ -1934,7 +1942,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
final SettingsValues settingsValues = mSettings.getCurrent(); final SettingsValues settingsValues = mSettings.getCurrent();
mDictionaryFacilitator.resetDictionaries(this, new Locale[] { locale }, mDictionaryFacilitator.resetDictionaries(this, new Locale[] { locale },
settingsValues.mUseContactsDict, settingsValues.mUsePersonalizedDicts, settingsValues.mUseContactsDict, settingsValues.mUsePersonalizedDicts,
false /* forceReloadMainDictionary */, this /* listener */); false /* forceReloadMainDictionary */,
settingsValues.mAccount,
this /* DictionaryInitializationListener */);
} }
// DO NOT USE THIS for any other purpose than testing. // DO NOT USE THIS for any other purpose than testing.

View File

@ -114,7 +114,7 @@ public class PersonalizationHelperForDictionaryFacilitator {
return personalizationDict; return personalizationDict;
} }
personalizationDict = PersonalizationDictionary.getDictionary(context, locale, personalizationDict = PersonalizationDictionary.getDictionary(context, locale,
null /* dictFile */, "" /* dictNamePrefix */); null /* dictFile */, "" /* dictNamePrefix */, null /* account */);
mPersonalizationDictsToUpdate.put(locale, personalizationDict); mPersonalizationDictsToUpdate.put(locale, personalizationDict);
return personalizationDict; return personalizationDict;
} }

View File

@ -36,6 +36,8 @@ import java.io.File;
import java.util.Arrays; import java.util.Arrays;
import java.util.Locale; import java.util.Locale;
import javax.annotation.Nullable;
/** /**
* An expandable dictionary that stores the words in the user dictionary provider into a binary * An expandable dictionary that stores the words in the user dictionary provider into a binary
* dictionary file to use it from native code. * dictionary file to use it from native code.
@ -104,7 +106,7 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary {
// Note: This method is called by {@link DictionaryFacilitator} using Java reflection. // Note: This method is called by {@link DictionaryFacilitator} using Java reflection.
@ExternallyReferenced @ExternallyReferenced
public static UserBinaryDictionary getDictionary(final Context context, final Locale locale, public static UserBinaryDictionary getDictionary(final Context context, final Locale locale,
final File dictFile, final String dictNamePrefix) { final File dictFile, final String dictNamePrefix, @Nullable final String account) {
return new UserBinaryDictionary(context, locale, false /* alsoUseMoreRestrictiveLocales */, return new UserBinaryDictionary(context, locale, false /* alsoUseMoreRestrictiveLocales */,
dictFile, dictNamePrefix + NAME); dictFile, dictNamePrefix + NAME);
} }

View File

@ -25,6 +25,8 @@ import com.android.inputmethod.latin.ExpandableBinaryDictionary;
import java.io.File; import java.io.File;
import java.util.Locale; import java.util.Locale;
import javax.annotation.Nullable;
public class ContextualDictionary extends ExpandableBinaryDictionary { public class ContextualDictionary extends ExpandableBinaryDictionary {
/* package */ static final String NAME = ContextualDictionary.class.getSimpleName(); /* package */ static final String NAME = ContextualDictionary.class.getSimpleName();
@ -40,7 +42,7 @@ public class ContextualDictionary extends ExpandableBinaryDictionary {
@SuppressWarnings("unused") @SuppressWarnings("unused")
@ExternallyReferenced @ExternallyReferenced
public static ContextualDictionary getDictionary(final Context context, final Locale locale, public static ContextualDictionary getDictionary(final Context context, final Locale locale,
final File dictFile, final String dictNamePrefix) { final File dictFile, final String dictNamePrefix, @Nullable final String account) {
return new ContextualDictionary(context, locale, dictFile); return new ContextualDictionary(context, locale, dictFile);
} }

View File

@ -24,6 +24,8 @@ import com.android.inputmethod.latin.Dictionary;
import java.io.File; import java.io.File;
import java.util.Locale; import java.util.Locale;
import javax.annotation.Nullable;
public class PersonalizationDictionary extends DecayingExpandableBinaryDictionaryBase { public class PersonalizationDictionary extends DecayingExpandableBinaryDictionaryBase {
/* package */ static final String NAME = PersonalizationDictionary.class.getSimpleName(); /* package */ static final String NAME = PersonalizationDictionary.class.getSimpleName();
@ -37,7 +39,8 @@ public class PersonalizationDictionary extends DecayingExpandableBinaryDictionar
@SuppressWarnings("unused") @SuppressWarnings("unused")
@ExternallyReferenced @ExternallyReferenced
public static PersonalizationDictionary getDictionary(final Context context, public static PersonalizationDictionary getDictionary(final Context context,
final Locale locale, final File dictFile, final String dictNamePrefix) { final Locale locale, final File dictFile, final String dictNamePrefix,
@Nullable final String account) {
return PersonalizationHelper.getPersonalizationDictionary(context, locale); return PersonalizationHelper.getPersonalizationDictionary(context, locale);
} }
} }

View File

@ -64,7 +64,8 @@ public class PersonalizationHelper {
return dict; return dict;
} }
} }
final UserHistoryDictionary dict = new UserHistoryDictionary(context, locale); final UserHistoryDictionary dict = new UserHistoryDictionary(
context, locale, accountName);
sLangUserHistoryDictCache.put(lookupStr, new SoftReference<>(dict)); sLangUserHistoryDictCache.put(lookupStr, new SoftReference<>(dict));
return dict; return dict;
} }

View File

@ -37,20 +37,18 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
/** /**
* Locally gathers stats about the words user types and various other signals like auto-correction * Locally gathers statistics about the words user types and various other signals like
* cancellation or manual picks. This allows the keyboard to adapt to the typist over time. * auto-correction cancellation or manual picks. This allows the keyboard to adapt to the
* typist over time.
*/ */
public class UserHistoryDictionary extends DecayingExpandableBinaryDictionaryBase { public class UserHistoryDictionary extends DecayingExpandableBinaryDictionaryBase {
static final String NAME = UserHistoryDictionary.class.getSimpleName(); static final String NAME = UserHistoryDictionary.class.getSimpleName();
// TODO: Make this constructor private // TODO: Make this constructor private
UserHistoryDictionary(final Context context, final Locale locale) { UserHistoryDictionary(final Context context, final Locale locale,
@Nullable final String account) {
super(context, super(context,
getUserHistoryDictName( getUserHistoryDictName(NAME, locale, null /* dictFile */, account),
NAME,
locale,
null /* dictFile */,
context),
locale, locale,
Dictionary.TYPE_USER_HISTORY, Dictionary.TYPE_USER_HISTORY,
null /* dictFile */); null /* dictFile */);
@ -61,24 +59,21 @@ public class UserHistoryDictionary extends DecayingExpandableBinaryDictionaryBas
*/ */
@UsedForTesting @UsedForTesting
static String getUserHistoryDictName(final String name, final Locale locale, static String getUserHistoryDictName(final String name, final Locale locale,
@Nullable final File dictFile, final Context context) { @Nullable final File dictFile, @Nullable final String account) {
if (!ProductionFlags.ENABLE_PER_ACCOUNT_USER_HISTORY_DICTIONARY) { if (!ProductionFlags.ENABLE_PER_ACCOUNT_USER_HISTORY_DICTIONARY) {
return getDictName(name, locale, dictFile); return getDictName(name, locale, dictFile);
} }
return getUserHistoryDictNamePerAccount(name, locale, dictFile, context); return getUserHistoryDictNamePerAccount(name, locale, dictFile, account);
} }
/** /**
* Uses the currently signed in account to determine the dictionary name. * Uses the currently signed in account to determine the dictionary name.
*/ */
private static String getUserHistoryDictNamePerAccount(final String name, final Locale locale, private static String getUserHistoryDictNamePerAccount(final String name, final Locale locale,
@Nullable final File dictFile, final Context context) { @Nullable final File dictFile, @Nullable final String account) {
if (dictFile != null) { if (dictFile != null) {
return dictFile.getName(); return dictFile.getName();
} }
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
final String account = prefs.getString(LocalSettingsConstants.PREF_ACCOUNT_NAME,
null /* default */);
String dictName = name + "." + locale.toString(); String dictName = name + "." + locale.toString();
if (account != null) { if (account != null) {
dictName += "." + account; dictName += "." + account;
@ -90,14 +85,7 @@ public class UserHistoryDictionary extends DecayingExpandableBinaryDictionaryBas
@SuppressWarnings("unused") @SuppressWarnings("unused")
@ExternallyReferenced @ExternallyReferenced
public static UserHistoryDictionary getDictionary(final Context context, final Locale locale, public static UserHistoryDictionary getDictionary(final Context context, final Locale locale,
final File dictFile, final String dictNamePrefix) { final File dictFile, final String dictNamePrefix, @Nullable final String account) {
final String account;
if (ProductionFlags.ENABLE_PER_ACCOUNT_USER_HISTORY_DICTIONARY) {
account = PreferenceManager.getDefaultSharedPreferences(context)
.getString(LocalSettingsConstants.PREF_ACCOUNT_NAME, null /* default */);
} else {
account = null;
}
return PersonalizationHelper.getUserHistoryDictionary(context, locale, account); return PersonalizationHelper.getUserHistoryDictionary(context, locale, account);
} }

View File

@ -36,6 +36,7 @@ import java.util.Arrays;
import java.util.Locale; import java.util.Locale;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/** /**
* When you call the constructor of this class, you may want to change the current system locale by * When you call the constructor of this class, you may want to change the current system locale by
@ -120,6 +121,8 @@ public class SettingsValues {
public final float mKeyPreviewDismissEndXScale; public final float mKeyPreviewDismissEndXScale;
public final float mKeyPreviewDismissEndYScale; public final float mKeyPreviewDismissEndYScale;
@Nullable public final String mAccount;
public SettingsValues(final Context context, final SharedPreferences prefs, final Resources res, public SettingsValues(final Context context, final SharedPreferences prefs, final Resources res,
@Nonnull final InputAttributes inputAttributes) { @Nonnull final InputAttributes inputAttributes) {
mLocale = res.getConfiguration().locale; mLocale = res.getConfiguration().locale;
@ -176,6 +179,8 @@ public class SettingsValues {
mPlausibilityThreshold = Settings.readPlausibilityThreshold(res); mPlausibilityThreshold = Settings.readPlausibilityThreshold(res);
mGestureInputEnabled = Settings.readGestureInputEnabled(prefs, res); mGestureInputEnabled = Settings.readGestureInputEnabled(prefs, res);
mGestureTrailEnabled = prefs.getBoolean(Settings.PREF_GESTURE_PREVIEW_TRAIL, true); mGestureTrailEnabled = prefs.getBoolean(Settings.PREF_GESTURE_PREVIEW_TRAIL, true);
mAccount = prefs.getString(LocalSettingsConstants.PREF_ACCOUNT_NAME,
null /* default */);
mGestureFloatingPreviewTextEnabled = !mInputAttributes.mDisableGestureFloatingPreviewText mGestureFloatingPreviewTextEnabled = !mInputAttributes.mDisableGestureFloatingPreviewText
&& prefs.getBoolean(Settings.PREF_GESTURE_FLOATING_PREVIEW_TEXT, true); && prefs.getBoolean(Settings.PREF_GESTURE_FLOATING_PREVIEW_TEXT, true);
mPhraseGestureEnabled = Settings.readPhraseGestureEnabled(prefs, res); mPhraseGestureEnabled = Settings.readPhraseGestureEnabled(prefs, res);

View File

@ -18,6 +18,7 @@ package com.android.inputmethod.latin.personalization;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
@ -42,7 +43,7 @@ public class ContextualDictionaryTests extends AndroidTestCase {
final DictionaryFacilitator dictionaryFacilitator = new DictionaryFacilitator(); final DictionaryFacilitator dictionaryFacilitator = new DictionaryFacilitator();
dictionaryFacilitator.resetDictionariesForTesting(getContext(), dictionaryFacilitator.resetDictionariesForTesting(getContext(),
new Locale[] { LOCALE_EN_US }, dictTypes, new HashMap<String, File>(), new Locale[] { LOCALE_EN_US }, dictTypes, new HashMap<String, File>(),
new HashMap<String, Map<String, String>>()); Collections.<String, Map<String, String>>emptyMap(), null /* account */);
return dictionaryFacilitator; return dictionaryFacilitator;
} }

View File

@ -18,6 +18,7 @@ package com.android.inputmethod.latin.personalization;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
@ -57,7 +58,7 @@ public class PersonalizationDictionaryTests extends AndroidTestCase {
final DictionaryFacilitator dictionaryFacilitator = new DictionaryFacilitator(getContext()); final DictionaryFacilitator dictionaryFacilitator = new DictionaryFacilitator(getContext());
dictionaryFacilitator.resetDictionariesForTesting(getContext(), dictionaryFacilitator.resetDictionariesForTesting(getContext(),
new Locale[] { LOCALE_EN_US }, dictTypes, new HashMap<String, File>(), new Locale[] { LOCALE_EN_US }, dictTypes, new HashMap<String, File>(),
new HashMap<String, Map<String, String>>()); Collections.<String, Map<String, String>>emptyMap(), null /* account */);
// Set subtypes. // Set subtypes.
RichInputMethodManager.init(getContext()); RichInputMethodManager.init(getContext());
final RichInputMethodManager richImm = RichInputMethodManager.getInstance(); final RichInputMethodManager richImm = RichInputMethodManager.getInstance();

View File

@ -16,8 +16,6 @@
package com.android.inputmethod.latin.personalization; package com.android.inputmethod.latin.personalization;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.test.AndroidTestCase; import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.LargeTest; import android.test.suitebuilder.annotation.LargeTest;
import android.util.Log; import android.util.Log;
@ -25,7 +23,6 @@ import android.util.Log;
import com.android.inputmethod.latin.ExpandableBinaryDictionary; import com.android.inputmethod.latin.ExpandableBinaryDictionary;
import com.android.inputmethod.latin.NgramContext; import com.android.inputmethod.latin.NgramContext;
import com.android.inputmethod.latin.NgramContext.WordInfo; import com.android.inputmethod.latin.NgramContext.WordInfo;
import com.android.inputmethod.latin.settings.LocalSettingsConstants;
import com.android.inputmethod.latin.utils.BinaryDictionaryUtils; import com.android.inputmethod.latin.utils.BinaryDictionaryUtils;
import com.android.inputmethod.latin.utils.DistracterFilter; import com.android.inputmethod.latin.utils.DistracterFilter;
@ -35,8 +32,6 @@ import java.util.Locale;
import java.util.Random; import java.util.Random;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
/** /**
* Unit tests for UserHistoryDictionary * Unit tests for UserHistoryDictionary
*/ */
@ -48,9 +43,6 @@ public class UserHistoryDictionaryTests extends AndroidTestCase {
private int mCurrentTime = 0; private int mCurrentTime = 0;
private SharedPreferences mPrefs;
private String mLastKnownAccount = null;
private static void printAllFiles(final File dir) { private static void printAllFiles(final File dir) {
Log.d(TAG, dir.getAbsolutePath()); Log.d(TAG, dir.getAbsolutePath());
for (final File file : dir.listFiles()) { for (final File file : dir.listFiles()) {
@ -78,12 +70,6 @@ public class UserHistoryDictionaryTests extends AndroidTestCase {
@Override @Override
protected void setUp() throws Exception { protected void setUp() throws Exception {
super.setUp(); super.setUp();
mPrefs = PreferenceManager.getDefaultSharedPreferences(getContext());
// Keep track of the current account so that we restore it when the test finishes.
mLastKnownAccount = mPrefs.getString(LocalSettingsConstants.PREF_ACCOUNT_NAME, null);
updateAccountName(TEST_ACCOUNT);
resetCurrentTimeForTestMode(); resetCurrentTimeForTestMode();
UserHistoryDictionaryTestsHelper.removeAllTestDictFiles( UserHistoryDictionaryTestsHelper.removeAllTestDictFiles(
UserHistoryDictionaryTestsHelper.TEST_LOCALE_PREFIX, mContext); UserHistoryDictionaryTestsHelper.TEST_LOCALE_PREFIX, mContext);
@ -94,10 +80,6 @@ public class UserHistoryDictionaryTests extends AndroidTestCase {
UserHistoryDictionaryTestsHelper.removeAllTestDictFiles( UserHistoryDictionaryTestsHelper.removeAllTestDictFiles(
UserHistoryDictionaryTestsHelper.TEST_LOCALE_PREFIX, mContext); UserHistoryDictionaryTestsHelper.TEST_LOCALE_PREFIX, mContext);
stopTestModeInNativeCode(); stopTestModeInNativeCode();
// Restore the account that was present before running the test.
updateAccountName(mLastKnownAccount);
super.tearDown(); super.tearDown();
} }
@ -106,14 +88,6 @@ public class UserHistoryDictionaryTests extends AndroidTestCase {
setCurrentTimeForTestMode(mCurrentTime); setCurrentTimeForTestMode(mCurrentTime);
} }
private void updateAccountName(@Nullable final String accountName) {
if (accountName == null) {
mPrefs.edit().remove(LocalSettingsConstants.PREF_ACCOUNT_NAME).apply();
} else {
mPrefs.edit().putString(LocalSettingsConstants.PREF_ACCOUNT_NAME, accountName).apply();
}
}
private void forcePassingShortTime() { private void forcePassingShortTime() {
// 3 days. // 3 days.
final int timeToElapse = (int)TimeUnit.DAYS.toSeconds(3); final int timeToElapse = (int)TimeUnit.DAYS.toSeconds(3);
@ -147,17 +121,20 @@ public class UserHistoryDictionaryTests extends AndroidTestCase {
dict.waitAllTasksForTests(); dict.waitAllTasksForTests();
} }
public void testRandomWords() { private void doTestRandomWords(final String testAccount) {
Log.d(TAG, "This test can be used for profiling."); Log.d(TAG, "This test can be used for profiling.");
Log.d(TAG, "Usage: please set UserHistoryDictionary.PROFILE_SAVE_RESTORE to true."); Log.d(TAG, "Usage: please set UserHistoryDictionary.PROFILE_SAVE_RESTORE to true.");
final Locale dummyLocale = UserHistoryDictionaryTestsHelper.getDummyLocale("random_words"); final Locale dummyLocale = UserHistoryDictionaryTestsHelper.getDummyLocale("random_words");
final String dictName = UserHistoryDictionary.getUserHistoryDictName( final String dictName = UserHistoryDictionary.getUserHistoryDictName(
UserHistoryDictionary.NAME, dummyLocale, null /* dictFile */, getContext()); UserHistoryDictionary.NAME, dummyLocale,
null /* dictFile */,
testAccount /* account */);
final File dictFile = ExpandableBinaryDictionary.getDictFile( final File dictFile = ExpandableBinaryDictionary.getDictFile(
mContext, dictName, null /* dictFile */); mContext, dictName, null /* dictFile */);
final UserHistoryDictionary dict = PersonalizationHelper.getUserHistoryDictionary( final UserHistoryDictionary dict = PersonalizationHelper.getUserHistoryDictionary(
getContext(), dummyLocale, TEST_ACCOUNT); getContext(), dummyLocale, testAccount);
clearHistory(dict); clearHistory(dict);
final int numberOfWords = 1000; final int numberOfWords = 1000;
final Random random = new Random(123456); final Random random = new Random(123456);
assertTrue(UserHistoryDictionaryTestsHelper.addAndWriteRandomWords( assertTrue(UserHistoryDictionaryTestsHelper.addAndWriteRandomWords(
@ -165,7 +142,23 @@ public class UserHistoryDictionaryTests extends AndroidTestCase {
assertDictionaryExists(dict, dictFile); assertDictionaryExists(dict, dictFile);
} }
public void testRandomWords_NullAccount() {
doTestRandomWords(null /* testAccount */);
}
public void testRandomWords() {
doTestRandomWords(TEST_ACCOUNT);
}
public void testStressTestForSwitchingLanguagesAndAddingWords() { public void testStressTestForSwitchingLanguagesAndAddingWords() {
doTestStressTestForSwitchingLanguagesAndAddingWords(TEST_ACCOUNT);
}
public void testStressTestForSwitchingLanguagesAndAddingWords_NullAccount() {
doTestStressTestForSwitchingLanguagesAndAddingWords(null /* testAccount */);
}
private void doTestStressTestForSwitchingLanguagesAndAddingWords(final String testAccount) {
final int numberOfLanguages = 2; final int numberOfLanguages = 2;
final int numberOfLanguageSwitching = 80; final int numberOfLanguageSwitching = 80;
final int numberOfWordsInsertedForEachLanguageSwitch = 100; final int numberOfWordsInsertedForEachLanguageSwitch = 100;
@ -181,11 +174,12 @@ public class UserHistoryDictionaryTests extends AndroidTestCase {
final Locale dummyLocale = final Locale dummyLocale =
UserHistoryDictionaryTestsHelper.getDummyLocale("switching_languages" + i); UserHistoryDictionaryTestsHelper.getDummyLocale("switching_languages" + i);
final String dictName = UserHistoryDictionary.getUserHistoryDictName( final String dictName = UserHistoryDictionary.getUserHistoryDictName(
UserHistoryDictionary.NAME, dummyLocale, null /* dictFile */, getContext()); UserHistoryDictionary.NAME, dummyLocale, null /* dictFile */,
testAccount /* account */);
dictFiles[i] = ExpandableBinaryDictionary.getDictFile( dictFiles[i] = ExpandableBinaryDictionary.getDictFile(
mContext, dictName, null /* dictFile */); mContext, dictName, null /* dictFile */);
dicts[i] = PersonalizationHelper.getUserHistoryDictionary(getContext(), dicts[i] = PersonalizationHelper.getUserHistoryDictionary(getContext(),
dummyLocale, TEST_ACCOUNT); dummyLocale, testAccount);
clearHistory(dicts[i]); clearHistory(dicts[i]);
} }
@ -212,16 +206,24 @@ public class UserHistoryDictionaryTests extends AndroidTestCase {
} }
public void testAddManyWords() { public void testAddManyWords() {
doTestAddManyWords(TEST_ACCOUNT);
}
public void testAddManyWords_NullAccount() {
doTestAddManyWords(null /* testAccount */);
}
private void doTestAddManyWords(final String testAccount) {
final Locale dummyLocale = final Locale dummyLocale =
UserHistoryDictionaryTestsHelper.getDummyLocale("many_random_words"); UserHistoryDictionaryTestsHelper.getDummyLocale("many_random_words");
final String dictName = UserHistoryDictionary.getUserHistoryDictName( final String dictName = UserHistoryDictionary.getUserHistoryDictName(
UserHistoryDictionary.NAME, dummyLocale, null /* dictFile */, getContext()); UserHistoryDictionary.NAME, dummyLocale, null /* dictFile */, testAccount);
final File dictFile = ExpandableBinaryDictionary.getDictFile( final File dictFile = ExpandableBinaryDictionary.getDictFile(
mContext, dictName, null /* dictFile */); mContext, dictName, null /* dictFile */);
final int numberOfWords = 10000; final int numberOfWords = 10000;
final Random random = new Random(123456); final Random random = new Random(123456);
final UserHistoryDictionary dict = PersonalizationHelper.getUserHistoryDictionary( final UserHistoryDictionary dict = PersonalizationHelper.getUserHistoryDictionary(
getContext(), dummyLocale, TEST_ACCOUNT); getContext(), dummyLocale, testAccount);
clearHistory(dict); clearHistory(dict);
assertTrue(UserHistoryDictionaryTestsHelper.addAndWriteRandomWords(dict, assertTrue(UserHistoryDictionaryTestsHelper.addAndWriteRandomWords(dict,
numberOfWords, random, true /* checksContents */, mCurrentTime)); numberOfWords, random, true /* checksContents */, mCurrentTime));
@ -229,9 +231,17 @@ public class UserHistoryDictionaryTests extends AndroidTestCase {
} }
public void testDecaying() { public void testDecaying() {
doTestDecaying(TEST_ACCOUNT);
}
public void testDecaying_NullAccount() {
doTestDecaying(null /* testAccount */);
}
private void doTestDecaying(final String testAccount) {
final Locale dummyLocale = UserHistoryDictionaryTestsHelper.getDummyLocale("decaying"); final Locale dummyLocale = UserHistoryDictionaryTestsHelper.getDummyLocale("decaying");
final UserHistoryDictionary dict = PersonalizationHelper.getUserHistoryDictionary( final UserHistoryDictionary dict = PersonalizationHelper.getUserHistoryDictionary(
getContext(), dummyLocale, TEST_ACCOUNT); getContext(), dummyLocale, testAccount);
resetCurrentTimeForTestMode(); resetCurrentTimeForTestMode();
clearHistory(dict); clearHistory(dict);
dict.waitAllTasksForTests(); dict.waitAllTasksForTests();
@ -262,9 +272,4 @@ public class UserHistoryDictionaryTests extends AndroidTestCase {
assertFalse(dict.isInDictionary(word)); assertFalse(dict.isInDictionary(word));
} }
} }
public void testRandomWords_NullAccount() {
updateAccountName(null);
testRandomWords();
}
} }