aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com/android/inputmethod
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/com/android/inputmethod')
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryFacilitator.java50
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java9
-rw-r--r--java/src/com/android/inputmethod/latin/PersonalizationDictionaryFacilitator.java185
-rw-r--r--java/src/com/android/inputmethod/latin/personalization/PersonalizationDataChunk.java2
4 files changed, 211 insertions, 35 deletions
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java
index 47aaeadcc..46428839f 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java
@@ -24,6 +24,7 @@ import android.view.inputmethod.InputMethodSubtype;
import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.keyboard.ProximityInfo;
+import com.android.inputmethod.latin.ExpandableBinaryDictionary.AddMultipleDictionaryEntriesCallback;
import com.android.inputmethod.latin.PrevWordsInfo.WordInfo;
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import com.android.inputmethod.latin.personalization.ContextualDictionary;
@@ -36,7 +37,6 @@ import com.android.inputmethod.latin.utils.DistracterFilter;
import com.android.inputmethod.latin.utils.DistracterFilterCheckingExactMatchesAndSuggestions;
import com.android.inputmethod.latin.utils.DistracterFilterCheckingIsInDictionary;
import com.android.inputmethod.latin.utils.ExecutorUtils;
-import com.android.inputmethod.latin.utils.LanguageModelParam;
import com.android.inputmethod.latin.utils.SuggestionResults;
import java.io.File;
@@ -67,6 +67,7 @@ public class DictionaryFacilitator {
// To synchronize assigning mDictionaryGroup to ensure closing dictionaries.
private final Object mLock = new Object();
private final DistracterFilter mDistracterFilter;
+ private final PersonalizationDictionaryFacilitator mPersonalizationDictionaryFacilitator;
private static final String[] DICT_TYPES_ORDERED_TO_GET_SUGGESTIONS =
new String[] {
@@ -174,14 +175,22 @@ public class DictionaryFacilitator {
public DictionaryFacilitator() {
mDistracterFilter = DistracterFilter.EMPTY_DISTRACTER_FILTER;
+ mPersonalizationDictionaryFacilitator = null;
}
public DictionaryFacilitator(final Context context) {
mDistracterFilter = new DistracterFilterCheckingExactMatchesAndSuggestions(context);
+ mPersonalizationDictionaryFacilitator =
+ new PersonalizationDictionaryFacilitator(context, mDistracterFilter);
}
public void updateEnabledSubtypes(final List<InputMethodSubtype> enabledSubtypes) {
mDistracterFilter.updateEnabledSubtypes(enabledSubtypes);
+ mPersonalizationDictionaryFacilitator.updateEnabledSubtypes(enabledSubtypes);
+ }
+
+ public void setIsMonolingualUser(final boolean isMonolingualUser) {
+ mPersonalizationDictionaryFacilitator.setIsMonolingualUser(isMonolingualUser);
}
public Locale getLocale() {
@@ -353,6 +362,9 @@ public class DictionaryFacilitator {
dictionaryGroup.closeDict(dictType);
}
mDistracterFilter.close();
+ if (mPersonalizationDictionaryFacilitator != null) {
+ mPersonalizationDictionaryFacilitator.close();
+ }
}
@UsedForTesting
@@ -372,11 +384,11 @@ public class DictionaryFacilitator {
}
public void flushPersonalizationDictionary() {
- final ExpandableBinaryDictionary personalizationDict =
+ final ExpandableBinaryDictionary personalizationDictUsedForSuggestion =
mDictionaryGroup.getSubDict(Dictionary.TYPE_PERSONALIZATION);
- if (personalizationDict != null) {
- personalizationDict.asyncFlushBinaryDictionary();
- }
+ mPersonalizationDictionaryFacilitator.flushPersonalizationDictionariesToUpdate(
+ personalizationDictUsedForSuggestion);
+ mDistracterFilter.close();
}
public void waitForLoadingMainDictionary(final long timeout, final TimeUnit unit)
@@ -580,6 +592,7 @@ public class DictionaryFacilitator {
// personalization dictionary.
public void clearPersonalizationDictionary() {
clearSubDictionary(Dictionary.TYPE_PERSONALIZATION);
+ mPersonalizationDictionaryFacilitator.clearDictionariesToUpdate();
}
public void clearContextualDictionary() {
@@ -589,30 +602,9 @@ public class DictionaryFacilitator {
public void addEntriesToPersonalizationDictionary(
final PersonalizationDataChunk personalizationDataChunk,
final SpacingAndPunctuations spacingAndPunctuations,
- final ExpandableBinaryDictionary.AddMultipleDictionaryEntriesCallback callback) {
- final ExpandableBinaryDictionary personalizationDict =
- mDictionaryGroup.getSubDict(Dictionary.TYPE_PERSONALIZATION);
- if (personalizationDict == null) {
- if (callback != null) {
- callback.onFinished();
- }
- return;
- }
- // TODO: Get locale from personalizationDataChunk.mDetectedLanguage.
- final Locale dataChunkLocale = getLocale();
- final ArrayList<LanguageModelParam> languageModelParams =
- LanguageModelParam.createLanguageModelParamsFrom(
- personalizationDataChunk.mTokens,
- personalizationDataChunk.mTimestampInSeconds, spacingAndPunctuations,
- dataChunkLocale, new DistracterFilterCheckingIsInDictionary(
- mDistracterFilter, personalizationDict));
- if (languageModelParams == null || languageModelParams.isEmpty()) {
- if (callback != null) {
- callback.onFinished();
- }
- return;
- }
- personalizationDict.addMultipleDictionaryEntriesDynamically(languageModelParams, callback);
+ final AddMultipleDictionaryEntriesCallback callback) {
+ mPersonalizationDictionaryFacilitator.addEntriesToPersonalizationDictionariesToUpdate(
+ getLocale(), personalizationDataChunk, spacingAndPunctuations, callback);
}
public void addPhraseToContextualDictionary(final String[] phrase, final int probability,
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index c853d2d68..a6243430b 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -614,9 +614,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private void refreshPersonalizationDictionarySession(
final SettingsValues currentSettingsValues) {
- mPersonalizationDictionaryUpdater.onLoadSettings(
- currentSettingsValues.mUsePersonalizedDicts,
+ mDictionaryFacilitator.setIsMonolingualUser(
mSubtypeSwitcher.isSystemLocaleSameAsLocaleOfAllEnabledSubtypesOfEnabledImes());
+ mPersonalizationDictionaryUpdater.onLoadSettings(
+ currentSettingsValues.mUsePersonalizedDicts);
mContextualDictionaryUpdater.onLoadSettings(currentSettingsValues.mUsePersonalizedDicts);
final boolean shouldKeepUserHistoryDictionaries;
if (currentSettingsValues.mUsePersonalizedDicts) {
@@ -734,10 +735,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
cleanupInternalStateForFinishInput();
}
}
- // TODO: Remove this test.
- if (!conf.locale.equals(mPersonalizationDictionaryUpdater.getLocale())) {
- refreshPersonalizationDictionarySession(settingsValues);
- }
super.onConfigurationChanged(conf);
}
diff --git a/java/src/com/android/inputmethod/latin/PersonalizationDictionaryFacilitator.java b/java/src/com/android/inputmethod/latin/PersonalizationDictionaryFacilitator.java
new file mode 100644
index 000000000..aa8e312a4
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/PersonalizationDictionaryFacilitator.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import android.content.Context;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.latin.ExpandableBinaryDictionary.AddMultipleDictionaryEntriesCallback;
+import com.android.inputmethod.latin.personalization.PersonalizationDataChunk;
+import com.android.inputmethod.latin.personalization.PersonalizationDictionary;
+import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
+import com.android.inputmethod.latin.utils.DistracterFilter;
+import com.android.inputmethod.latin.utils.DistracterFilterCheckingIsInDictionary;
+import com.android.inputmethod.latin.utils.LanguageModelParam;
+import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
+
+/**
+ * Class for managing and updating personalization dictionaries.
+ */
+public class PersonalizationDictionaryFacilitator {
+ private final Context mContext;
+ private final DistracterFilter mDistracterFilter;
+ private final HashMap<String, HashSet<Locale>> mLangToLocalesMap = new HashMap<>();
+ private final HashMap<Locale, ExpandableBinaryDictionary> mPersonalizationDictsToUpdate =
+ new HashMap<>();
+ private boolean mIsMonolingualUser = false;;
+
+ PersonalizationDictionaryFacilitator(final Context context,
+ final DistracterFilter distracterFilter) {
+ mContext = context;
+ mDistracterFilter = distracterFilter;
+ }
+
+ public void close() {
+ mLangToLocalesMap.clear();
+ for (final ExpandableBinaryDictionary dict : mPersonalizationDictsToUpdate.values()) {
+ dict.close();
+ }
+ mPersonalizationDictsToUpdate.clear();
+ }
+
+ public void clearDictionariesToUpdate() {
+ for (final ExpandableBinaryDictionary dict : mPersonalizationDictsToUpdate.values()) {
+ dict.clear();
+ }
+ mPersonalizationDictsToUpdate.clear();
+ }
+
+ public void updateEnabledSubtypes(final List<InputMethodSubtype> enabledSubtypes) {
+ for (final InputMethodSubtype subtype : enabledSubtypes) {
+ final Locale locale = SubtypeLocaleUtils.getSubtypeLocale(subtype);
+ final String language = locale.getLanguage();
+ final HashSet<Locale> locales = mLangToLocalesMap.get(language);
+ if (locales != null) {
+ locales.add(locale);
+ } else {
+ final HashSet<Locale> localeSet = new HashSet<>();
+ localeSet.add(locale);
+ mLangToLocalesMap.put(language, localeSet);
+ }
+ }
+ }
+
+ public void setIsMonolingualUser(final boolean isMonolingualUser) {
+ mIsMonolingualUser = isMonolingualUser;
+ }
+
+ /**
+ * Flush personalization dictionaries to dictionary files. Close dictionaries after writing
+ * files except the dictionary that is used for generating suggestions.
+ *
+ * @param personalizationDictUsedForSuggestion the personalization dictionary used for
+ * generating suggestions that won't be closed.
+ */
+ public void flushPersonalizationDictionariesToUpdate(
+ final ExpandableBinaryDictionary personalizationDictUsedForSuggestion) {
+ for (final ExpandableBinaryDictionary personalizationDict :
+ mPersonalizationDictsToUpdate.values()) {
+ personalizationDict.asyncFlushBinaryDictionary();
+ if (personalizationDict != personalizationDictUsedForSuggestion) {
+ // Close if the dictionary is not being used for suggestion.
+ personalizationDict.close();
+ }
+ }
+ mDistracterFilter.close();
+ mPersonalizationDictsToUpdate.clear();
+ }
+
+ private ExpandableBinaryDictionary getPersonalizationDictToUpdate(final Context context,
+ final Locale locale) {
+ ExpandableBinaryDictionary personalizationDict = mPersonalizationDictsToUpdate.get(locale);
+ if (personalizationDict != null) {
+ return personalizationDict;
+ }
+ personalizationDict = PersonalizationDictionary.getDictionary(context, locale,
+ null /* dictFile */, "" /* dictNamePrefix */);
+ mPersonalizationDictsToUpdate.put(locale, personalizationDict);
+ return personalizationDict;
+ }
+
+ private void addEntriesToPersonalizationDictionariesForLocale(final Locale locale,
+ final PersonalizationDataChunk personalizationDataChunk,
+ final SpacingAndPunctuations spacingAndPunctuations,
+ final AddMultipleDictionaryEntriesCallback callback) {
+ final ExpandableBinaryDictionary personalizationDict =
+ getPersonalizationDictToUpdate(mContext, locale);
+ if (personalizationDict == null) {
+ if (callback != null) {
+ callback.onFinished();
+ }
+ return;
+ }
+ final ArrayList<LanguageModelParam> languageModelParams =
+ LanguageModelParam.createLanguageModelParamsFrom(
+ personalizationDataChunk.mTokens,
+ personalizationDataChunk.mTimestampInSeconds, spacingAndPunctuations,
+ locale, new DistracterFilterCheckingIsInDictionary(
+ mDistracterFilter, personalizationDict));
+ if (languageModelParams == null || languageModelParams.isEmpty()) {
+ if (callback != null) {
+ callback.onFinished();
+ }
+ return;
+ }
+ personalizationDict.addMultipleDictionaryEntriesDynamically(languageModelParams, callback);
+ }
+
+ public void addEntriesToPersonalizationDictionariesToUpdate(final Locale defaultLocale,
+ final PersonalizationDataChunk personalizationDataChunk,
+ final SpacingAndPunctuations spacingAndPunctuations,
+ final AddMultipleDictionaryEntriesCallback callback) {
+ final String language = personalizationDataChunk.mDetectedLanguage;
+ final HashSet<Locale> locales;
+ if (mIsMonolingualUser && PersonalizationDataChunk.LANGUAGE_UNKNOWN.equals(language)
+ && mLangToLocalesMap.size() == 1) {
+ locales = mLangToLocalesMap.get(defaultLocale.getLanguage());
+ } else {
+ locales = mLangToLocalesMap.get(language);
+ }
+ if (locales == null || locales.isEmpty()) {
+ if (callback != null) {
+ callback.onFinished();
+ }
+ return;
+ }
+ final AtomicInteger remainingTaskCount = new AtomicInteger(locales.size());
+ final AddMultipleDictionaryEntriesCallback callbackForLocales =
+ new AddMultipleDictionaryEntriesCallback() {
+ @Override
+ public void onFinished() {
+ if (remainingTaskCount.decrementAndGet() == 0) {
+ // Update tasks for all locales have been finished.
+ if (callback != null) {
+ callback.onFinished();
+ }
+ }
+ }
+ };
+ for (final Locale locale : locales) {
+ addEntriesToPersonalizationDictionariesForLocale(locale, personalizationDataChunk,
+ spacingAndPunctuations, callbackForLocales);
+ }
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDataChunk.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDataChunk.java
index 6f4b09741..734ed5583 100644
--- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDataChunk.java
+++ b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDataChunk.java
@@ -20,6 +20,8 @@ import java.util.Collections;
import java.util.List;
public class PersonalizationDataChunk {
+ public static final String LANGUAGE_UNKNOWN = "";
+
public final boolean mInputByUser;
public final List<String> mTokens;
public final int mTimestampInSeconds;