aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com/android/inputmethod/latin
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/com/android/inputmethod/latin')
-rw-r--r--java/src/com/android/inputmethod/latin/AssetFileAddress.java7
-rw-r--r--java/src/com/android/inputmethod/latin/BinaryDictionary.java19
-rw-r--r--java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java5
-rw-r--r--java/src/com/android/inputmethod/latin/DicTraverseSession.java6
-rw-r--r--java/src/com/android/inputmethod/latin/Dictionary.java14
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryCollection.java16
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryFacilitator.java7
-rw-r--r--java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java17
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java41
-rw-r--r--java/src/com/android/inputmethod/latin/ReadOnlyBinaryDictionary.java12
-rw-r--r--java/src/com/android/inputmethod/latin/RichInputMethodManager.java176
-rw-r--r--java/src/com/android/inputmethod/latin/RichInputMethodSubtype.java107
-rw-r--r--java/src/com/android/inputmethod/latin/SubtypeSwitcher.java282
-rw-r--r--java/src/com/android/inputmethod/latin/Suggest.java14
-rw-r--r--java/src/com/android/inputmethod/latin/SuggestedWords.java14
-rw-r--r--java/src/com/android/inputmethod/latin/WordComposer.java39
-rw-r--r--java/src/com/android/inputmethod/latin/debug/ExternalDictionaryGetterForDebug.java2
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/FormatSpec.java14
-rw-r--r--java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java27
-rw-r--r--java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java60
-rw-r--r--java/src/com/android/inputmethod/latin/settings/CustomInputStylePreference.java4
-rw-r--r--java/src/com/android/inputmethod/latin/settings/NativeSuggestOptions.java73
-rw-r--r--java/src/com/android/inputmethod/latin/settings/PreferencesSettingsFragment.java6
-rw-r--r--java/src/com/android/inputmethod/latin/settings/SettingsValues.java3
-rw-r--r--java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java3
-rw-r--r--java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java4
-rw-r--r--java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java5
-rw-r--r--java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryAddWordContents.java2
-rw-r--r--java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryList.java2
-rw-r--r--java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettingsUtils.java2
-rw-r--r--java/src/com/android/inputmethod/latin/utils/CapsModeUtils.java28
-rw-r--r--java/src/com/android/inputmethod/latin/utils/CollectionUtils.java52
-rw-r--r--java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java13
-rw-r--r--java/src/com/android/inputmethod/latin/utils/CoordinateUtils.java94
-rw-r--r--java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java1
-rw-r--r--java/src/com/android/inputmethod/latin/utils/DistracterFilterCheckingExactMatchesAndSuggestions.java5
-rw-r--r--java/src/com/android/inputmethod/latin/utils/FileUtils.java54
-rw-r--r--java/src/com/android/inputmethod/latin/utils/LocaleUtils.java190
-rw-r--r--java/src/com/android/inputmethod/latin/utils/RecapitalizeStatus.java11
-rw-r--r--java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java76
40 files changed, 566 insertions, 941 deletions
diff --git a/java/src/com/android/inputmethod/latin/AssetFileAddress.java b/java/src/com/android/inputmethod/latin/AssetFileAddress.java
index fd6c24dfe..f8d02d6ea 100644
--- a/java/src/com/android/inputmethod/latin/AssetFileAddress.java
+++ b/java/src/com/android/inputmethod/latin/AssetFileAddress.java
@@ -16,7 +16,7 @@
package com.android.inputmethod.latin;
-import com.android.inputmethod.latin.utils.FileUtils;
+import com.android.inputmethod.latin.common.FileUtils;
import java.io.File;
@@ -62,4 +62,9 @@ public final class AssetFileAddress {
public void deleteUnderlyingFile() {
FileUtils.deleteRecursively(new File(mFilename));
}
+
+ @Override
+ public String toString() {
+ return String.format("%s (offset=%d, length=%d)", mFilename, mOffset, mLength);
+ }
}
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index 8e9b5c6f6..46cd3b8b2 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -21,9 +21,10 @@ import android.util.Log;
import android.util.SparseArray;
import com.android.inputmethod.annotations.UsedForTesting;
-import com.android.inputmethod.keyboard.ProximityInfo;
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+import com.android.inputmethod.latin.common.ComposedData;
import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.FileUtils;
import com.android.inputmethod.latin.common.InputPointers;
import com.android.inputmethod.latin.common.StringUtils;
import com.android.inputmethod.latin.makedict.DictionaryHeader;
@@ -33,7 +34,6 @@ import com.android.inputmethod.latin.makedict.UnsupportedFormatException;
import com.android.inputmethod.latin.makedict.WordProperty;
import com.android.inputmethod.latin.settings.SettingsValuesForSuggestion;
import com.android.inputmethod.latin.utils.BinaryDictionaryUtils;
-import com.android.inputmethod.latin.utils.FileUtils;
import com.android.inputmethod.latin.utils.JniUtils;
import com.android.inputmethod.latin.utils.WordInputEventForPersonalization;
@@ -262,8 +262,8 @@ public final class BinaryDictionary extends Dictionary {
}
@Override
- public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer,
- final NgramContext ngramContext, final ProximityInfo proximityInfo,
+ public ArrayList<SuggestedWordInfo> getSuggestions(final ComposedData composedData,
+ final NgramContext ngramContext, final long proximityInfoHandle,
final SettingsValuesForSuggestion settingsValuesForSuggestion,
final int sessionId, final float weightForLocale,
final float[] inOutWeightOfLangModelVsSpatialModel) {
@@ -274,12 +274,13 @@ public final class BinaryDictionary extends Dictionary {
Arrays.fill(session.mInputCodePoints, Constants.NOT_A_CODE);
ngramContext.outputToArray(session.mPrevWordCodePointArrays,
session.mIsBeginningOfSentenceArray);
- final InputPointers inputPointers = composer.getInputPointers();
- final boolean isGesture = composer.isBatchMode();
+ final InputPointers inputPointers = composedData.mInputPointers;
+ final boolean isGesture = composedData.mIsBatchMode;
final int inputSize;
if (!isGesture) {
- inputSize = composer.copyCodePointsExceptTrailingSingleQuotesAndReturnCodePointCount(
- session.mInputCodePoints);
+ inputSize =
+ composedData.copyCodePointsExceptTrailingSingleQuotesAndReturnCodePointCount(
+ session.mInputCodePoints);
if (inputSize < 0) {
return null;
}
@@ -303,7 +304,7 @@ public final class BinaryDictionary extends Dictionary {
Dictionary.NOT_A_WEIGHT_OF_LANG_MODEL_VS_SPATIAL_MODEL;
}
// TOOD: Pass multiple previous words information for n-gram.
- getSuggestionsNative(mNativeDict, proximityInfo.getNativeProximityInfo(),
+ getSuggestionsNative(mNativeDict, proximityInfoHandle,
getTraverseSession(sessionId).getSession(), inputPointers.getXCoordinates(),
inputPointers.getYCoordinates(), inputPointers.getTimes(),
inputPointers.getPointerIds(), session.mInputCodePoints, inputSize,
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
index 1570bdae0..5afb62b69 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
@@ -21,11 +21,11 @@ import android.content.SharedPreferences;
import android.content.res.AssetFileDescriptor;
import android.util.Log;
+import com.android.inputmethod.latin.common.LocaleUtils;
import com.android.inputmethod.latin.makedict.DictionaryHeader;
import com.android.inputmethod.latin.makedict.UnsupportedFormatException;
import com.android.inputmethod.latin.utils.BinaryDictionaryUtils;
import com.android.inputmethod.latin.utils.DictionaryInfoUtils;
-import com.android.inputmethod.latin.utils.LocaleUtils;
import java.io.File;
import java.io.IOException;
@@ -284,7 +284,8 @@ final public class BinaryDictionaryGetter {
final AssetFileAddress afa = AssetFileAddress.makeFromFileName(f.getPath());
if (null != afa) fileList.add(afa);
} else {
- Log.e(TAG, "Found a cached dictionary file but cannot read or use it");
+ Log.e(TAG, "Found a cached dictionary file for " + locale.toString()
+ + " but cannot read or use it");
}
}
diff --git a/java/src/com/android/inputmethod/latin/DicTraverseSession.java b/java/src/com/android/inputmethod/latin/DicTraverseSession.java
index 95390aa9f..aefefd305 100644
--- a/java/src/com/android/inputmethod/latin/DicTraverseSession.java
+++ b/java/src/com/android/inputmethod/latin/DicTraverseSession.java
@@ -17,7 +17,8 @@
package com.android.inputmethod.latin;
import com.android.inputmethod.latin.common.Constants;
-import com.android.inputmethod.latin.settings.NativeSuggestOptions;
+import com.android.inputmethod.latin.common.NativeSuggestOptions;
+import com.android.inputmethod.latin.settings.AdditionalFeaturesSettingUtils;
import com.android.inputmethod.latin.utils.JniUtils;
import java.util.Locale;
@@ -43,7 +44,8 @@ public final class DicTraverseSession {
public final int[] mOutputAutoCommitFirstWordConfidence = new int[1];
public final float[] mInputOutputWeightOfLangModelVsSpatialModel = new float[1];
- public final NativeSuggestOptions mNativeSuggestOptions = new NativeSuggestOptions();
+ public final NativeSuggestOptions mNativeSuggestOptions = new NativeSuggestOptions(
+ AdditionalFeaturesSettingUtils.ADDITIONAL_FEATURES_SETTINGS_SIZE);
private static native long setDicTraverseSessionNative(String locale, long dictSize);
private static native void initDicTraverseSessionNative(long nativeDicTraverseSession,
diff --git a/java/src/com/android/inputmethod/latin/Dictionary.java b/java/src/com/android/inputmethod/latin/Dictionary.java
index 28a62b283..7d7ed77e7 100644
--- a/java/src/com/android/inputmethod/latin/Dictionary.java
+++ b/java/src/com/android/inputmethod/latin/Dictionary.java
@@ -17,8 +17,8 @@
package com.android.inputmethod.latin;
import com.android.inputmethod.annotations.UsedForTesting;
-import com.android.inputmethod.keyboard.ProximityInfo;
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+import com.android.inputmethod.latin.common.ComposedData;
import com.android.inputmethod.latin.settings.SettingsValuesForSuggestion;
import java.util.ArrayList;
@@ -87,9 +87,9 @@ public abstract class Dictionary {
/**
* Searches for suggestions for a given context.
- * @param composer the key sequence to match with coordinate info, as a WordComposer
+ * @param composedData the key sequence to match with coordinate info
* @param ngramContext the context for n-gram.
- * @param proximityInfo the object for key proximity. May be ignored by some implementations.
+ * @param proximityInfoHandle the handle for key proximity. Is ignored by some implementations.
* @param settingsValuesForSuggestion the settings values used for the suggestion.
* @param sessionId the session id.
* @param weightForLocale the weight given to this locale, to multiply the output scores for
@@ -99,8 +99,8 @@ public abstract class Dictionary {
* a float array that has only one element. This can be updated when a different value is used.
* @return the list of suggestions (possibly null if none)
*/
- abstract public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer,
- final NgramContext ngramContext, final ProximityInfo proximityInfo,
+ abstract public ArrayList<SuggestedWordInfo> getSuggestions(final ComposedData composedData,
+ final NgramContext ngramContext, final long proximityInfoHandle,
final SettingsValuesForSuggestion settingsValuesForSuggestion,
final int sessionId, final float weightForLocale,
final float[] inOutWeightOfLangModelVsSpatialModel);
@@ -203,8 +203,8 @@ public abstract class Dictionary {
}
@Override
- public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer,
- final NgramContext ngramContext, final ProximityInfo proximityInfo,
+ public ArrayList<SuggestedWordInfo> getSuggestions(final ComposedData composedData,
+ final NgramContext ngramContext, final long proximityInfoHandle,
final SettingsValuesForSuggestion settingsValuesForSuggestion,
final int sessionId, final float weightForLocale,
final float[] inOutWeightOfLangModelVsSpatialModel) {
diff --git a/java/src/com/android/inputmethod/latin/DictionaryCollection.java b/java/src/com/android/inputmethod/latin/DictionaryCollection.java
index a6d7205e2..96575f629 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryCollection.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryCollection.java
@@ -18,8 +18,8 @@ package com.android.inputmethod.latin;
import android.util.Log;
-import com.android.inputmethod.keyboard.ProximityInfo;
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+import com.android.inputmethod.latin.common.ComposedData;
import com.android.inputmethod.latin.settings.SettingsValuesForSuggestion;
import java.util.ArrayList;
@@ -59,8 +59,8 @@ public final class DictionaryCollection extends Dictionary {
}
@Override
- public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer,
- final NgramContext ngramContext, final ProximityInfo proximityInfo,
+ public ArrayList<SuggestedWordInfo> getSuggestions(final ComposedData composedData,
+ final NgramContext ngramContext, final long proximityInfoHandle,
final SettingsValuesForSuggestion settingsValuesForSuggestion,
final int sessionId, final float weightForLocale,
final float[] inOutWeightOfLangModelVsSpatialModel) {
@@ -68,15 +68,15 @@ public final class DictionaryCollection extends Dictionary {
if (dictionaries.isEmpty()) return null;
// To avoid creating unnecessary objects, we get the list out of the first
// dictionary and add the rest to it if not null, hence the get(0)
- ArrayList<SuggestedWordInfo> suggestions = dictionaries.get(0).getSuggestions(composer,
- ngramContext, proximityInfo, settingsValuesForSuggestion, sessionId,
+ ArrayList<SuggestedWordInfo> suggestions = dictionaries.get(0).getSuggestions(composedData,
+ ngramContext, proximityInfoHandle, settingsValuesForSuggestion, sessionId,
weightForLocale, inOutWeightOfLangModelVsSpatialModel);
if (null == suggestions) suggestions = new ArrayList<>();
final int length = dictionaries.size();
for (int i = 1; i < length; ++ i) {
- final ArrayList<SuggestedWordInfo> sugg = dictionaries.get(i).getSuggestions(composer,
- ngramContext, proximityInfo, settingsValuesForSuggestion, sessionId,
- weightForLocale, inOutWeightOfLangModelVsSpatialModel);
+ final ArrayList<SuggestedWordInfo> sugg = dictionaries.get(i).getSuggestions(
+ composedData, ngramContext, proximityInfoHandle, settingsValuesForSuggestion,
+ sessionId, weightForLocale, inOutWeightOfLangModelVsSpatialModel);
if (null != sugg) suggestions.addAll(sugg);
}
return suggestions;
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java
index 4a22cde7b..d23639a0d 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java
@@ -23,7 +23,6 @@ import android.util.Pair;
import android.view.inputmethod.InputMethodSubtype;
import com.android.inputmethod.annotations.UsedForTesting;
-import com.android.inputmethod.keyboard.ProximityInfo;
import com.android.inputmethod.latin.ExpandableBinaryDictionary.UpdateEntriesForInputEventsCallback;
import com.android.inputmethod.latin.NgramContext.WordInfo;
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
@@ -683,7 +682,7 @@ public class DictionaryFacilitator {
// TODO: Revise the way to fusion suggestion results.
public SuggestionResults getSuggestionResults(final WordComposer composer,
- final NgramContext ngramContext, final ProximityInfo proximityInfo,
+ final NgramContext ngramContext, final long proximityInfoHandle,
final SettingsValuesForSuggestion settingsValuesForSuggestion, final int sessionId) {
final DictionaryGroup[] dictionaryGroups = mDictionaryGroups;
final SuggestionResults suggestionResults = new SuggestionResults(
@@ -698,8 +697,8 @@ public class DictionaryFacilitator {
? dictionaryGroup.mWeightForGesturingInLocale
: dictionaryGroup.mWeightForTypingInLocale;
final ArrayList<SuggestedWordInfo> dictionarySuggestions =
- dictionary.getSuggestions(composer, ngramContext, proximityInfo,
- settingsValuesForSuggestion, sessionId,
+ dictionary.getSuggestions(composer.getComposedDataSnapshot(), ngramContext,
+ proximityInfoHandle, settingsValuesForSuggestion, sessionId,
weightForLocale, weightOfLangModelVsSpatialModel);
if (null == dictionarySuggestions) continue;
suggestionResults.addAll(dictionarySuggestions);
diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
index 702d1536a..d9d22e0fc 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
@@ -20,9 +20,10 @@ import android.content.Context;
import android.util.Log;
import com.android.inputmethod.annotations.UsedForTesting;
-import com.android.inputmethod.keyboard.ProximityInfo;
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+import com.android.inputmethod.latin.common.ComposedData;
import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.FileUtils;
import com.android.inputmethod.latin.makedict.DictionaryHeader;
import com.android.inputmethod.latin.makedict.FormatSpec;
import com.android.inputmethod.latin.makedict.UnsupportedFormatException;
@@ -32,7 +33,6 @@ import com.android.inputmethod.latin.utils.AsyncResultHolder;
import com.android.inputmethod.latin.utils.CombinedFormatUtils;
import com.android.inputmethod.latin.utils.DistracterFilter;
import com.android.inputmethod.latin.utils.ExecutorUtils;
-import com.android.inputmethod.latin.utils.FileUtils;
import com.android.inputmethod.latin.utils.WordInputEventForPersonalization;
import java.io.File;
@@ -120,7 +120,8 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
private static boolean needsToMigrateDictionary(final int formatVersion) {
// When we bump up the dictionary format version, the old version should be added to here
// for supporting migration. Note that native code has to support reading such formats.
- return formatVersion == FormatSpec.VERSION4_ONLY_FOR_TESTING;
+ return formatVersion == FormatSpec.VERSION4_ONLY_FOR_TESTING
+ || formatVersion == FormatSpec.VERSION402;
}
public boolean isValidDictionaryLocked() {
@@ -480,8 +481,8 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
}
@Override
- public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer,
- final NgramContext ngramContext, final ProximityInfo proximityInfo,
+ public ArrayList<SuggestedWordInfo> getSuggestions(final ComposedData composedData,
+ final NgramContext ngramContext, final long proximityInfoHandle,
final SettingsValuesForSuggestion settingsValuesForSuggestion, final int sessionId,
final float weightForLocale, final float[] inOutWeightOfLangModelVsSpatialModel) {
reloadDictionaryIfRequired();
@@ -494,9 +495,9 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
return null;
}
final ArrayList<SuggestedWordInfo> suggestions =
- mBinaryDictionary.getSuggestions(composer, ngramContext, proximityInfo,
- settingsValuesForSuggestion, sessionId, weightForLocale,
- inOutWeightOfLangModelVsSpatialModel);
+ mBinaryDictionary.getSuggestions(composedData, ngramContext,
+ proximityInfoHandle, settingsValuesForSuggestion, sessionId,
+ weightForLocale, inOutWeightOfLangModelVsSpatialModel);
if (mBinaryDictionary.isCorrupted()) {
Log.i(TAG, "Dictionary (" + mDictName +") is corrupted. "
+ "Remove and regenerate it.");
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 3fa127005..719656b07 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -77,6 +77,7 @@ import com.android.inputmethod.keyboard.TextDecoratorUi;
import com.android.inputmethod.latin.Suggest.OnGetSuggestedWordsCallback;
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.CoordinateUtils;
import com.android.inputmethod.latin.common.InputPointers;
import com.android.inputmethod.latin.define.DebugFlags;
import com.android.inputmethod.latin.define.ProductionFlags;
@@ -93,7 +94,6 @@ import com.android.inputmethod.latin.suggestions.SuggestionStripViewAccessor;
import com.android.inputmethod.latin.touchinputconsumer.GestureConsumer;
import com.android.inputmethod.latin.utils.ApplicationUtils;
import com.android.inputmethod.latin.utils.CapsModeUtils;
-import com.android.inputmethod.latin.utils.CoordinateUtils;
import com.android.inputmethod.latin.utils.CursorAnchorInfoUtils;
import com.android.inputmethod.latin.utils.DialogUtils;
import com.android.inputmethod.latin.utils.ImportantNoticeUtils;
@@ -603,7 +603,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// Has to be package-visible for unit tests
@UsedForTesting
void loadSettings() {
- final Locale[] locales = mSubtypeSwitcher.getCurrentSubtypeLocales();
+ final Locale[] locales = mRichImm.getCurrentSubtypeLocales();
final EditorInfo editorInfo = getCurrentInputEditorInfo();
final InputAttributes inputAttributes = new InputAttributes(
editorInfo, isFullscreenMode(), getPackageName());
@@ -626,7 +626,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private void refreshPersonalizationDictionarySession(
final SettingsValues currentSettingsValues) {
mDictionaryFacilitator.setIsMonolingualUser(
- mSubtypeSwitcher.isSystemLocaleSameAsLocaleOfAllEnabledSubtypesOfEnabledImes());
+ mRichImm.isSystemLocaleSameAsLocaleOfAllEnabledSubtypesOfEnabledImes());
mPersonalizationDictionaryUpdater.onLoadSettings(
currentSettingsValues.mUsePersonalizedDicts);
mContextualDictionaryUpdater.onLoadSettings(currentSettingsValues.mUsePersonalizedDicts);
@@ -657,7 +657,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
void resetDictionaryFacilitatorIfNecessary() {
- final Locale[] subtypeSwitcherLocales = mSubtypeSwitcher.getCurrentSubtypeLocales();
+ final Locale[] subtypeSwitcherLocales = mRichImm.getCurrentSubtypeLocales();
if (mDictionaryFacilitator.isForLocales(subtypeSwitcherLocales)) {
return;
}
@@ -863,7 +863,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// also wouldn't be consuming gesture data.
mGestureConsumer = GestureConsumer.NULL_GESTURE_CONSUMER;
mRichImm.clearSubtypeCaches();
- mSubtypeSwitcher.refreshSubtypeInfo();
+ mSubtypeSwitcher.onSubtypeChanged(mRichImm.getCurrentRawSubtype());
final KeyboardSwitcher switcher = mKeyboardSwitcher;
switcher.updateKeyboardTheme();
final MainKeyboardView mainKeyboardView = switcher.getMainKeyboardView();
@@ -909,7 +909,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// Update to a gesture consumer with the current editor and IME state.
mGestureConsumer = GestureConsumer.newInstance(editorInfo,
mInputLogic.getPrivateCommandPerformer(),
- Arrays.asList(mSubtypeSwitcher.getCurrentSubtypeLocales()),
+ Arrays.asList(mRichImm.getCurrentSubtypeLocales()),
switcher.getKeyboard());
// Forward this event to the accessibility utilities, if enabled.
@@ -947,7 +947,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// span, so we should reset our state unconditionally, even if restarting is true.
// We also tell the input logic about the combining rules for the current subtype, so
// it can adjust its combiners if needed.
- mInputLogic.startInput(mSubtypeSwitcher.getCombiningRulesExtraValueOfCurrentSubtype(),
+ mInputLogic.startInput(mRichImm.getCombiningRulesExtraValueOfCurrentSubtype(),
currentSettingsValues);
resetDictionaryFacilitatorIfNecessary();
@@ -1077,11 +1077,12 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
+ ", cs=" + composingSpanStart + ", ce=" + composingSpanEnd);
}
- // This call happens when we have a hardware keyboard as well as when we don't. While we
- // don't support hardware keyboards yet we should avoid doing the processing associated
- // with cursor movement when we have a hardware keyboard since we are not in charge.
+ // This call happens whether our view is displayed or not, but if it's not then we should
+ // not attempt recorrection. This is true even with a hardware keyboard connected: if the
+ // view is not displayed we have no means of showing suggestions anyway, and if it is then
+ // we want to show suggestions anyway.
final SettingsValues settingsValues = mSettings.getCurrent();
- if ((!settingsValues.mHasHardwareKeyboard || ProductionFlags.IS_HARDWARE_KEYBOARD_SUPPORTED)
+ if (isInputViewShown()
&& mInputLogic.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd,
settingsValues)) {
mKeyboardSwitcher.requestUpdatingShiftState(getCurrentAutoCapsState(),
@@ -1194,7 +1195,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (hasHardwareKeyboard && visibleKeyboardView.getVisibility() == View.GONE) {
// If there is a hardware keyboard and a visible software keyboard view has been hidden,
// no visual element will be shown on the screen.
- outInsets.touchableInsets = inputHeight;
+ outInsets.contentTopInsets = inputHeight;
outInsets.visibleTopInsets = inputHeight;
mInsetsUpdater.setInsets(outInsets);
return;
@@ -1204,7 +1205,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
? mSuggestionStripView.getHeight() : 0;
final int visibleTopY = inputHeight - visibleKeyboardView.getHeight() - suggestionsHeight;
mSuggestionStripView.setMoreSuggestionsHeight(visibleTopY);
- // Need to set touchable region only if a keyboard view is being shown.
+ // Need to set expanded touchable region only if a keyboard view is being shown.
if (visibleKeyboardView.isShown()) {
final int touchLeft = 0;
final int touchTop = mKeyboardSwitcher.isShowingMoreKeysPanel() ? 0 : visibleTopY;
@@ -1423,7 +1424,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// completely replace #onCodeInput.
public void onEvent(@Nonnull final Event event) {
if (Constants.CODE_SHORTCUT == event.mKeyCode) {
- mSubtypeSwitcher.switchToShortcutIME(this);
+ mRichImm.switchToShortcutIME(this);
}
final InputTransaction completeInputTransaction =
mInputLogic.onCodeInput(mSettings.getCurrent(), event,
@@ -1467,7 +1468,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
public void onStartBatchInput() {
mInputLogic.onStartBatchInput(mSettings.getCurrent(), mKeyboardSwitcher, mHandler);
mGestureConsumer.onGestureStarted(
- Arrays.asList(mSubtypeSwitcher.getCurrentSubtypeLocales()),
+ Arrays.asList(mRichImm.getCurrentSubtypeLocales()),
mKeyboardSwitcher.getKeyboard());
}
@@ -1489,11 +1490,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
/**
- * To be called after the InputLogic has gotten a chance to act on the on-device decoding
- * for the full gesture, possibly updating the TextView to reflect the first decoding.
+ * To be called after the InputLogic has gotten a chance to act on the suggested words by the
+ * IME for the full gesture, possibly updating the TextView to reflect the first suggestion.
* <p>
* This method must be run on the UI Thread.
- * @param suggestedWords On-device decoding for the full gesture.
+ * @param suggestedWords suggested words by the IME for the full gesture.
*/
public void onTailBatchInputResultShown(final SuggestedWords suggestedWords) {
mGestureConsumer.onImeSuggestionsProcessed(suggestedWords,
@@ -1589,7 +1590,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// We should clear the contextual strip if there is no suggestion from dictionaries.
|| noSuggestionsFromDictionaries) {
mSuggestionStripView.setSuggestions(suggestedWords,
- mSubtypeSwitcher.getCurrentSubtype().isRtlSubtype());
+ mRichImm.getCurrentSubtype().isRtlSubtype());
}
}
@@ -1810,7 +1811,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
public void onReceive(final Context context, final Intent intent) {
final String action = intent.getAction();
if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
- mSubtypeSwitcher.onNetworkStateChanged(intent);
+ mRichImm.onNetworkStateChanged(intent);
} else if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) {
AudioAndHapticFeedbackManager.getInstance().onRingerModeChanged();
}
diff --git a/java/src/com/android/inputmethod/latin/ReadOnlyBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ReadOnlyBinaryDictionary.java
index bc8bd831c..7b1a53a6e 100644
--- a/java/src/com/android/inputmethod/latin/ReadOnlyBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ReadOnlyBinaryDictionary.java
@@ -16,8 +16,8 @@
package com.android.inputmethod.latin;
-import com.android.inputmethod.keyboard.ProximityInfo;
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+import com.android.inputmethod.latin.common.ComposedData;
import com.android.inputmethod.latin.settings.SettingsValuesForSuggestion;
import java.util.ArrayList;
@@ -50,16 +50,16 @@ public final class ReadOnlyBinaryDictionary extends Dictionary {
}
@Override
- public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer,
- final NgramContext ngramContext, final ProximityInfo proximityInfo,
+ public ArrayList<SuggestedWordInfo> getSuggestions(final ComposedData composedData,
+ final NgramContext ngramContext, final long proximityInfoHandle,
final SettingsValuesForSuggestion settingsValuesForSuggestion,
final int sessionId, final float weightForLocale,
final float[] inOutWeightOfLangModelVsSpatialModel) {
if (mLock.readLock().tryLock()) {
try {
- return mBinaryDictionary.getSuggestions(composer, ngramContext, proximityInfo,
- settingsValuesForSuggestion, sessionId, weightForLocale,
- inOutWeightOfLangModelVsSpatialModel);
+ return mBinaryDictionary.getSuggestions(composedData, ngramContext,
+ proximityInfoHandle, settingsValuesForSuggestion, sessionId,
+ weightForLocale, inOutWeightOfLangModelVsSpatialModel);
} finally {
mLock.readLock().unlock();
}
diff --git a/java/src/com/android/inputmethod/latin/RichInputMethodManager.java b/java/src/com/android/inputmethod/latin/RichInputMethodManager.java
index 8d8e7ac38..a1ac55a20 100644
--- a/java/src/com/android/inputmethod/latin/RichInputMethodManager.java
+++ b/java/src/com/android/inputmethod/latin/RichInputMethodManager.java
@@ -17,9 +17,15 @@
package com.android.inputmethod.latin;
import static com.android.inputmethod.latin.common.Constants.Subtype.KEYBOARD_MODE;
+import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.REQ_NETWORK_CONNECTIVITY;
import android.content.Context;
+import android.content.Intent;
import android.content.SharedPreferences;
+import android.inputmethodservice.InputMethodService;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.os.AsyncTask;
import android.os.Build;
import android.os.IBinder;
import android.preference.PreferenceManager;
@@ -28,7 +34,9 @@ import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodSubtype;
+import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
+import com.android.inputmethod.keyboard.KeyboardSwitcher;
import com.android.inputmethod.latin.settings.AdditionalFeaturesSettingUtils;
import com.android.inputmethod.latin.settings.Settings;
import com.android.inputmethod.latin.utils.AdditionalSubtypeUtils;
@@ -36,7 +44,11 @@ import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
import javax.annotation.Nonnull;
@@ -46,6 +58,7 @@ import javax.annotation.Nonnull;
// non final for easy mocking.
public class RichInputMethodManager {
private static final String TAG = RichInputMethodManager.class.getSimpleName();
+ private static final boolean DEBUG = false;
private RichInputMethodManager() {
// This utility class is not publicly instantiable.
@@ -56,6 +69,10 @@ public class RichInputMethodManager {
private Context mContext;
private InputMethodManagerCompatWrapper mImmWrapper;
private InputMethodInfoCache mInputMethodInfoCache;
+ private RichInputMethodSubtype mCurrentRichInputMethodSubtype;
+ private InputMethodInfo mShortcutInputMethodInfo;
+ private InputMethodSubtype mShortcutSubtype;
+ private boolean mIsNetworkConnected;
final HashMap<InputMethodInfo, List<InputMethodSubtype>>
mSubtypeListCacheWithImplicitlySelectedSubtypes = new HashMap<>();
final HashMap<InputMethodInfo, List<InputMethodSubtype>>
@@ -95,6 +112,11 @@ public class RichInputMethodManager {
SubtypeLocaleUtils.init(context);
final InputMethodSubtype[] additionalSubtypes = getAdditionalSubtypes(context);
setAdditionalInputMethodSubtypes(additionalSubtypes);
+
+ final ConnectivityManager connectivityManager =
+ (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ final NetworkInfo info = connectivityManager.getActiveNetworkInfo();
+ mIsNetworkConnected = (info != null && info.isConnected());
}
public InputMethodSubtype[] getAdditionalSubtypes(final Context context) {
@@ -304,10 +326,47 @@ public class RichInputMethodManager {
}
@Nonnull
+ public RichInputMethodSubtype onSubtypeChanged(@Nonnull final InputMethodSubtype newSubtype) {
+ final RichInputMethodSubtype richSubtype = createCurrentRichInputMethodSubtype(newSubtype);
+ if (DEBUG) {
+ Log.w(TAG, "onSubtypeChanged: " + richSubtype.getNameForLogging());
+ }
+ mCurrentRichInputMethodSubtype = richSubtype;
+ return richSubtype;
+ }
+
+ private static RichInputMethodSubtype sForcedSubtypeForTesting = null;
+
+ @UsedForTesting
+ static void forceSubtype(final InputMethodSubtype subtype) {
+ sForcedSubtypeForTesting = new RichInputMethodSubtype(subtype);
+ }
+
+ public Locale[] getCurrentSubtypeLocales() {
+ if (null != sForcedSubtypeForTesting) {
+ return sForcedSubtypeForTesting.getLocales();
+ }
+ return getCurrentSubtype().getLocales();
+ }
+
+ public RichInputMethodSubtype getCurrentSubtype() {
+ if (null != sForcedSubtypeForTesting) {
+ return sForcedSubtypeForTesting;
+ }
+ return mCurrentRichInputMethodSubtype;
+ }
+
+
+ public String getCombiningRulesExtraValueOfCurrentSubtype() {
+ return SubtypeLocaleUtils.getCombiningRulesExtraValue(getCurrentSubtype().getRawSubtype());
+ }
+
+ @Nonnull
public InputMethodSubtype getCurrentRawSubtype() {
return mImmWrapper.mImm.getCurrentInputMethodSubtype();
}
+ @Nonnull
public RichInputMethodSubtype createCurrentRichInputMethodSubtype(
@Nonnull final InputMethodSubtype rawSubtype) {
return AdditionalFeaturesSettingUtils.createRichInputMethodSubtype(this, rawSubtype,
@@ -432,4 +491,121 @@ public class RichInputMethodManager {
}
return mImmWrapper.shouldOfferSwitchingToNextInputMethod(binder);
}
+
+ public boolean isSystemLocaleSameAsLocaleOfAllEnabledSubtypesOfEnabledImes() {
+ final Locale systemLocale = mContext.getResources().getConfiguration().locale;
+ final Set<InputMethodSubtype> enabledSubtypesOfEnabledImes = new HashSet<>();
+ final InputMethodManager inputMethodManager = getInputMethodManager();
+ final List<InputMethodInfo> enabledInputMethodInfoList =
+ inputMethodManager.getEnabledInputMethodList();
+ for (final InputMethodInfo info : enabledInputMethodInfoList) {
+ final List<InputMethodSubtype> enabledSubtypes =
+ inputMethodManager.getEnabledInputMethodSubtypeList(
+ info, true /* allowsImplicitlySelectedSubtypes */);
+ if (enabledSubtypes.isEmpty()) {
+ // An IME with no subtypes is found.
+ return false;
+ }
+ enabledSubtypesOfEnabledImes.addAll(enabledSubtypes);
+ }
+ for (final InputMethodSubtype subtype : enabledSubtypesOfEnabledImes) {
+ if (!subtype.isAuxiliary() && !subtype.getLocale().isEmpty()
+ && !systemLocale.equals(SubtypeLocaleUtils.getSubtypeLocale(subtype))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ // TODO: Make this private
+ void updateShortcutIME() {
+ if (DEBUG) {
+ Log.d(TAG, "Update shortcut IME from : "
+ + (mShortcutInputMethodInfo == null
+ ? "<null>" : mShortcutInputMethodInfo.getId()) + ", "
+ + (mShortcutSubtype == null ? "<null>" : (
+ mShortcutSubtype.getLocale() + ", " + mShortcutSubtype.getMode())));
+ }
+ // TODO: Update an icon for shortcut IME
+ final Map<InputMethodInfo, List<InputMethodSubtype>> shortcuts =
+ getInputMethodManager().getShortcutInputMethodsAndSubtypes();
+ mShortcutInputMethodInfo = null;
+ mShortcutSubtype = null;
+ for (final InputMethodInfo imi : shortcuts.keySet()) {
+ final List<InputMethodSubtype> subtypes = shortcuts.get(imi);
+ // TODO: Returns the first found IMI for now. Should handle all shortcuts as
+ // appropriate.
+ mShortcutInputMethodInfo = imi;
+ // TODO: Pick up the first found subtype for now. Should handle all subtypes
+ // as appropriate.
+ mShortcutSubtype = subtypes.size() > 0 ? subtypes.get(0) : null;
+ break;
+ }
+ if (DEBUG) {
+ Log.d(TAG, "Update shortcut IME to : "
+ + (mShortcutInputMethodInfo == null
+ ? "<null>" : mShortcutInputMethodInfo.getId()) + ", "
+ + (mShortcutSubtype == null ? "<null>" : (
+ mShortcutSubtype.getLocale() + ", " + mShortcutSubtype.getMode())));
+ }
+ }
+
+ public void switchToShortcutIME(final InputMethodService context) {
+ if (mShortcutInputMethodInfo == null) {
+ return;
+ }
+
+ final String imiId = mShortcutInputMethodInfo.getId();
+ switchToTargetIME(imiId, mShortcutSubtype, context);
+ }
+
+ private void switchToTargetIME(final String imiId, final InputMethodSubtype subtype,
+ final InputMethodService context) {
+ final IBinder token = context.getWindow().getWindow().getAttributes().token;
+ if (token == null) {
+ return;
+ }
+ final InputMethodManager imm = getInputMethodManager();
+ new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ imm.setInputMethodAndSubtype(token, imiId, subtype);
+ return null;
+ }
+ }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+
+ public boolean isShortcutImeEnabled() {
+ updateShortcutIME();
+ if (mShortcutInputMethodInfo == null) {
+ return false;
+ }
+ if (mShortcutSubtype == null) {
+ return true;
+ }
+ return checkIfSubtypeBelongsToImeAndEnabled(
+ mShortcutInputMethodInfo, mShortcutSubtype);
+ }
+
+ public boolean isShortcutImeReady() {
+ updateShortcutIME();
+ if (mShortcutInputMethodInfo == null) {
+ return false;
+ }
+ if (mShortcutSubtype == null) {
+ return true;
+ }
+ if (mShortcutSubtype.containsExtraValueKey(REQ_NETWORK_CONNECTIVITY)) {
+ return mIsNetworkConnected;
+ }
+ return true;
+ }
+
+ public void onNetworkStateChanged(final Intent intent) {
+ final boolean noConnection = intent.getBooleanExtra(
+ ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
+ mIsNetworkConnected = !noConnection;
+
+ KeyboardSwitcher.getInstance().onNetworkStateChanged();
+ }
}
diff --git a/java/src/com/android/inputmethod/latin/RichInputMethodSubtype.java b/java/src/com/android/inputmethod/latin/RichInputMethodSubtype.java
index 8d055531c..ea8d4a210 100644
--- a/java/src/com/android/inputmethod/latin/RichInputMethodSubtype.java
+++ b/java/src/com/android/inputmethod/latin/RichInputMethodSubtype.java
@@ -16,33 +16,45 @@
package com.android.inputmethod.latin;
+import static com.android.inputmethod.latin.common.Constants.Subtype.KEYBOARD_MODE;
+
+import android.util.Log;
import android.view.inputmethod.InputMethodSubtype;
-import com.android.inputmethod.latin.utils.LocaleUtils;
+import com.android.inputmethod.compat.InputMethodSubtypeCompatUtils;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.LocaleUtils;
import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
import java.util.Arrays;
import java.util.Locale;
+import javax.annotation.Nonnull;
+
/**
* Enrichment class for InputMethodSubtype to enable concurrent multi-lingual input.
*
* Right now, this returns the extra value of its primary subtype.
*/
public final class RichInputMethodSubtype {
+ private static final String TAG = RichInputMethodSubtype.class.getSimpleName();
+
+ @Nonnull
private final InputMethodSubtype mSubtype;
+ @Nonnull
private final Locale[] mLocales;
- public RichInputMethodSubtype(final InputMethodSubtype subtype, final Locale... locales) {
+ public RichInputMethodSubtype(@Nonnull final InputMethodSubtype subtype,
+ @Nonnull final Locale... locales) {
mSubtype = subtype;
- mLocales = new Locale[locales.length+1];
+ mLocales = new Locale[locales.length + 1];
mLocales[0] = LocaleUtils.constructLocaleFromString(mSubtype.getLocale());
System.arraycopy(locales, 0, mLocales, 1, locales.length);
}
// Extra values are determined by the primary subtype. This is probably right, but
// we may have to revisit this later.
- public String getExtraValueOf(final String key) {
+ public String getExtraValueOf(@Nonnull final String key) {
return mSubtype.getExtraValueOf(key);
}
@@ -80,6 +92,7 @@ public final class RichInputMethodSubtype {
// en_US azerty T English English (US)
// zz azerty T AZERTY AZERTY
// Get the RichInputMethodSubtype's full display name in its locale.
+ @Nonnull
public String getFullDisplayName() {
if (isNoLanguage()) {
return SubtypeLocaleUtils.getKeyboardLayoutSetDisplayName(mSubtype);
@@ -88,6 +101,7 @@ public final class RichInputMethodSubtype {
}
// Get the RichInputMethodSubtype's middle display name in its locale.
+ @Nonnull
public String getMiddleDisplayName() {
if (isNoLanguage()) {
return SubtypeLocaleUtils.getKeyboardLayoutSetDisplayName(mSubtype);
@@ -96,7 +110,7 @@ public final class RichInputMethodSubtype {
}
@Override
- public boolean equals(Object o) {
+ public boolean equals(final Object o) {
if (!(o instanceof RichInputMethodSubtype)) {
return false;
}
@@ -114,15 +128,96 @@ public final class RichInputMethodSubtype {
return "Multi-lingual subtype: " + mSubtype.toString() + ", " + Arrays.toString(mLocales);
}
+ @Nonnull
public Locale[] getLocales() {
return mLocales;
}
public boolean isRtlSubtype() {
// The subtype is considered RTL if the language of the main subtype is RTL.
- return SubtypeLocaleUtils.isRtlLanguage(mLocales[0]);
+ return LocaleUtils.isRtlLanguage(mLocales[0]);
}
// TODO: remove this method
+ @Nonnull
public InputMethodSubtype getRawSubtype() { return mSubtype; }
+
+ @Nonnull
+ public String getKeyboardLayoutSetName() {
+ return SubtypeLocaleUtils.getKeyboardLayoutSetName(mSubtype);
+ }
+
+ // Dummy no language QWERTY subtype. See {@link R.xml.method}.
+ private static final int SUBTYPE_ID_OF_DUMMY_NO_LANGUAGE_SUBTYPE = 0xdde0bfd3;
+ private static final String EXTRA_VALUE_OF_DUMMY_NO_LANGUAGE_SUBTYPE =
+ "KeyboardLayoutSet=" + SubtypeLocaleUtils.QWERTY
+ + "," + Constants.Subtype.ExtraValue.ASCII_CAPABLE
+ + "," + Constants.Subtype.ExtraValue.ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE
+ + "," + Constants.Subtype.ExtraValue.EMOJI_CAPABLE;
+ @Nonnull
+ private static final RichInputMethodSubtype DUMMY_NO_LANGUAGE_SUBTYPE =
+ new RichInputMethodSubtype(InputMethodSubtypeCompatUtils.newInputMethodSubtype(
+ R.string.subtype_no_language_qwerty, R.drawable.ic_ime_switcher_dark,
+ SubtypeLocaleUtils.NO_LANGUAGE, KEYBOARD_MODE,
+ EXTRA_VALUE_OF_DUMMY_NO_LANGUAGE_SUBTYPE,
+ false /* isAuxiliary */, false /* overridesImplicitlyEnabledSubtype */,
+ SUBTYPE_ID_OF_DUMMY_NO_LANGUAGE_SUBTYPE));
+ // Caveat: We probably should remove this when we add an Emoji subtype in {@link R.xml.method}.
+ // Dummy Emoji subtype. See {@link R.xml.method}.
+ private static final int SUBTYPE_ID_OF_DUMMY_EMOJI_SUBTYPE = 0xd78b2ed0;
+ private static final String EXTRA_VALUE_OF_DUMMY_EMOJI_SUBTYPE =
+ "KeyboardLayoutSet=" + SubtypeLocaleUtils.EMOJI
+ + "," + Constants.Subtype.ExtraValue.EMOJI_CAPABLE;
+ @Nonnull
+ private static final RichInputMethodSubtype DUMMY_EMOJI_SUBTYPE = new RichInputMethodSubtype(
+ InputMethodSubtypeCompatUtils.newInputMethodSubtype(
+ R.string.subtype_emoji, R.drawable.ic_ime_switcher_dark,
+ SubtypeLocaleUtils.NO_LANGUAGE, KEYBOARD_MODE,
+ EXTRA_VALUE_OF_DUMMY_EMOJI_SUBTYPE,
+ false /* isAuxiliary */, false /* overridesImplicitlyEnabledSubtype */,
+ SUBTYPE_ID_OF_DUMMY_EMOJI_SUBTYPE));
+ private static RichInputMethodSubtype sNoLanguageSubtype;
+ private static RichInputMethodSubtype sEmojiSubtype;
+
+ @Nonnull
+ public static RichInputMethodSubtype getNoLanguageSubtype() {
+ RichInputMethodSubtype noLanguageSubtype = sNoLanguageSubtype;
+ if (noLanguageSubtype == null) {
+ final InputMethodSubtype rawNoLanguageSubtype = RichInputMethodManager.getInstance()
+ .findSubtypeByLocaleAndKeyboardLayoutSet(
+ SubtypeLocaleUtils.NO_LANGUAGE, SubtypeLocaleUtils.QWERTY);
+ if (rawNoLanguageSubtype != null) {
+ noLanguageSubtype = new RichInputMethodSubtype(rawNoLanguageSubtype);
+ }
+ }
+ if (noLanguageSubtype != null) {
+ sNoLanguageSubtype = noLanguageSubtype;
+ return noLanguageSubtype;
+ }
+ Log.w(TAG, "Can't find any language with QWERTY subtype");
+ Log.w(TAG, "No input method subtype found; returning dummy subtype: "
+ + DUMMY_NO_LANGUAGE_SUBTYPE);
+ return DUMMY_NO_LANGUAGE_SUBTYPE;
+ }
+
+ @Nonnull
+ public static RichInputMethodSubtype getEmojiSubtype() {
+ RichInputMethodSubtype emojiSubtype = sEmojiSubtype;
+ if (emojiSubtype == null) {
+ final InputMethodSubtype rawEmojiSubtype = RichInputMethodManager.getInstance()
+ .findSubtypeByLocaleAndKeyboardLayoutSet(
+ SubtypeLocaleUtils.NO_LANGUAGE, SubtypeLocaleUtils.EMOJI);
+ if (rawEmojiSubtype != null) {
+ emojiSubtype = new RichInputMethodSubtype(rawEmojiSubtype);
+ }
+ }
+ if (emojiSubtype != null) {
+ sEmojiSubtype = emojiSubtype;
+ return emojiSubtype;
+ }
+ Log.w(TAG, "Can't find emoji subtype");
+ Log.w(TAG, "No input method subtype found; returning dummy subtype: "
+ + DUMMY_EMOJI_SUBTYPE);
+ return DUMMY_EMOJI_SUBTYPE;
+ }
}
diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
index 98bce95bd..23e348bff 100644
--- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
+++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
@@ -16,40 +16,18 @@
package com.android.inputmethod.latin;
-import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.REQ_NETWORK_CONNECTIVITY;
import android.content.Context;
-import android.content.Intent;
import android.content.res.Resources;
-import android.inputmethodservice.InputMethodService;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-import android.os.AsyncTask;
-import android.os.IBinder;
-import android.util.Log;
-import android.view.inputmethod.InputMethodInfo;
-import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodSubtype;
-import com.android.inputmethod.annotations.UsedForTesting;
-import com.android.inputmethod.compat.InputMethodSubtypeCompatUtils;
-import com.android.inputmethod.keyboard.KeyboardSwitcher;
import com.android.inputmethod.keyboard.internal.LanguageOnSpacebarHelper;
-import com.android.inputmethod.latin.common.Constants;
-import com.android.inputmethod.latin.define.DebugFlags;
import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
-import java.util.HashSet;
import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
import javax.annotation.Nonnull;
public final class SubtypeSwitcher {
- private static boolean DBG = DebugFlags.DEBUG_ENABLED;
- private static final String TAG = SubtypeSwitcher.class.getSimpleName();
-
private static final SubtypeSwitcher sInstance = new SubtypeSwitcher();
private /* final */ RichInputMethodManager mRichImm;
@@ -57,41 +35,6 @@ public final class SubtypeSwitcher {
private final LanguageOnSpacebarHelper mLanguageOnSpacebarHelper =
new LanguageOnSpacebarHelper();
- private InputMethodInfo mShortcutInputMethodInfo;
- private InputMethodSubtype mShortcutSubtype;
- private RichInputMethodSubtype mCurrentRichInputMethodSubtype;
- private RichInputMethodSubtype mNoLanguageSubtype;
- private RichInputMethodSubtype mEmojiSubtype;
- private boolean mIsNetworkConnected;
-
- private static final String KEYBOARD_MODE = "keyboard";
- // Dummy no language QWERTY subtype. See {@link R.xml.method}.
- private static final int SUBTYPE_ID_OF_DUMMY_NO_LANGUAGE_SUBTYPE = 0xdde0bfd3;
- private static final String EXTRA_VALUE_OF_DUMMY_NO_LANGUAGE_SUBTYPE =
- "KeyboardLayoutSet=" + SubtypeLocaleUtils.QWERTY
- + "," + Constants.Subtype.ExtraValue.ASCII_CAPABLE
- + "," + Constants.Subtype.ExtraValue.ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE
- + "," + Constants.Subtype.ExtraValue.EMOJI_CAPABLE;
- private static final RichInputMethodSubtype DUMMY_NO_LANGUAGE_SUBTYPE =
- new RichInputMethodSubtype(InputMethodSubtypeCompatUtils.newInputMethodSubtype(
- R.string.subtype_no_language_qwerty, R.drawable.ic_ime_switcher_dark,
- SubtypeLocaleUtils.NO_LANGUAGE, KEYBOARD_MODE,
- EXTRA_VALUE_OF_DUMMY_NO_LANGUAGE_SUBTYPE,
- false /* isAuxiliary */, false /* overridesImplicitlyEnabledSubtype */,
- SUBTYPE_ID_OF_DUMMY_NO_LANGUAGE_SUBTYPE));
- // Caveat: We probably should remove this when we add an Emoji subtype in {@link R.xml.method}.
- // Dummy Emoji subtype. See {@link R.xml.method}.
- private static final int SUBTYPE_ID_OF_DUMMY_EMOJI_SUBTYPE = 0xd78b2ed0;
- private static final String EXTRA_VALUE_OF_DUMMY_EMOJI_SUBTYPE =
- "KeyboardLayoutSet=" + SubtypeLocaleUtils.EMOJI
- + "," + Constants.Subtype.ExtraValue.EMOJI_CAPABLE;
- private static final RichInputMethodSubtype DUMMY_EMOJI_SUBTYPE = new RichInputMethodSubtype(
- InputMethodSubtypeCompatUtils.newInputMethodSubtype(
- R.string.subtype_emoji, R.drawable.ic_ime_switcher_dark,
- SubtypeLocaleUtils.NO_LANGUAGE, KEYBOARD_MODE,
- EXTRA_VALUE_OF_DUMMY_EMOJI_SUBTYPE,
- false /* isAuxiliary */, false /* overridesImplicitlyEnabledSubtype */,
- SUBTYPE_ID_OF_DUMMY_EMOJI_SUBTYPE));
public static SubtypeSwitcher getInstance() {
return sInstance;
@@ -113,18 +56,9 @@ public final class SubtypeSwitcher {
}
mResources = context.getResources();
mRichImm = RichInputMethodManager.getInstance();
- ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(
- Context.CONNECTIVITY_SERVICE);
-
- final NetworkInfo info = connectivityManager.getActiveNetworkInfo();
- mIsNetworkConnected = (info != null && info.isConnected());
-
- refreshSubtypeInfo();
- updateParametersOnStartInputView();
- }
- public void refreshSubtypeInfo() {
onSubtypeChanged(mRichImm.getCurrentRawSubtype());
+ updateParametersOnStartInputView();
}
/**
@@ -134,219 +68,21 @@ public final class SubtypeSwitcher {
public void updateParametersOnStartInputView() {
final List<InputMethodSubtype> enabledSubtypesOfThisIme =
mRichImm.getMyEnabledInputMethodSubtypeList(true);
- mLanguageOnSpacebarHelper.updateEnabledSubtypes(enabledSubtypesOfThisIme);
- updateShortcutIME();
- }
-
- private void updateShortcutIME() {
- if (DBG) {
- Log.d(TAG, "Update shortcut IME from : "
- + (mShortcutInputMethodInfo == null
- ? "<null>" : mShortcutInputMethodInfo.getId()) + ", "
- + (mShortcutSubtype == null ? "<null>" : (
- mShortcutSubtype.getLocale() + ", " + mShortcutSubtype.getMode())));
- }
- // TODO: Update an icon for shortcut IME
- final Map<InputMethodInfo, List<InputMethodSubtype>> shortcuts =
- mRichImm.getInputMethodManager().getShortcutInputMethodsAndSubtypes();
- mShortcutInputMethodInfo = null;
- mShortcutSubtype = null;
- for (final InputMethodInfo imi : shortcuts.keySet()) {
- final List<InputMethodSubtype> subtypes = shortcuts.get(imi);
- // TODO: Returns the first found IMI for now. Should handle all shortcuts as
- // appropriate.
- mShortcutInputMethodInfo = imi;
- // TODO: Pick up the first found subtype for now. Should handle all subtypes
- // as appropriate.
- mShortcutSubtype = subtypes.size() > 0 ? subtypes.get(0) : null;
- break;
- }
- if (DBG) {
- Log.d(TAG, "Update shortcut IME to : "
- + (mShortcutInputMethodInfo == null
- ? "<null>" : mShortcutInputMethodInfo.getId()) + ", "
- + (mShortcutSubtype == null ? "<null>" : (
- mShortcutSubtype.getLocale() + ", " + mShortcutSubtype.getMode())));
- }
+ mLanguageOnSpacebarHelper.onUpdateEnabledSubtypes(enabledSubtypesOfThisIme);
+ mRichImm.updateShortcutIME();
}
// Update the current subtype. LatinIME.onCurrentInputMethodSubtypeChanged calls this function.
public void onSubtypeChanged(@Nonnull final InputMethodSubtype newSubtype) {
- final RichInputMethodSubtype richSubtype =
- mRichImm.createCurrentRichInputMethodSubtype(newSubtype);
- if (DBG) {
- Log.w(TAG, "onSubtypeChanged: " + richSubtype.getNameForLogging());
- }
- mCurrentRichInputMethodSubtype = richSubtype;
- final Locale[] newLocales = richSubtype.getLocales();
- if (newLocales.length > 1) {
- // In multi-locales mode, the system language is never the same as the input language
- // because there is no single input language.
- mLanguageOnSpacebarHelper.updateIsSystemLanguageSameAsInputLanguage(false);
- } else {
- final Locale newLocale = newLocales[0];
- final Locale systemLocale = mResources.getConfiguration().locale;
- final boolean sameLocale = systemLocale.equals(newLocale);
- final boolean sameLanguage = systemLocale.getLanguage().equals(newLocale.getLanguage());
- final boolean implicitlyEnabled = mRichImm
- .checkIfSubtypeBelongsToThisImeAndImplicitlyEnabled(newSubtype);
- mLanguageOnSpacebarHelper.updateIsSystemLanguageSameAsInputLanguage(
- sameLocale || (sameLanguage && implicitlyEnabled));
- }
- updateShortcutIME();
- }
-
- ////////////////////////////
- // Shortcut IME functions //
- ////////////////////////////
-
- public void switchToShortcutIME(final InputMethodService context) {
- if (mShortcutInputMethodInfo == null) {
- return;
- }
-
- final String imiId = mShortcutInputMethodInfo.getId();
- switchToTargetIME(imiId, mShortcutSubtype, context);
- }
-
- private void switchToTargetIME(final String imiId, final InputMethodSubtype subtype,
- final InputMethodService context) {
- final IBinder token = context.getWindow().getWindow().getAttributes().token;
- if (token == null) {
- return;
- }
- final InputMethodManager imm = mRichImm.getInputMethodManager();
- new AsyncTask<Void, Void, Void>() {
- @Override
- protected Void doInBackground(Void... params) {
- imm.setInputMethodAndSubtype(token, imiId, subtype);
- return null;
- }
- }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
- }
-
- public boolean isShortcutImeEnabled() {
- updateShortcutIME();
- if (mShortcutInputMethodInfo == null) {
- return false;
- }
- if (mShortcutSubtype == null) {
- return true;
- }
- return mRichImm.checkIfSubtypeBelongsToImeAndEnabled(
- mShortcutInputMethodInfo, mShortcutSubtype);
- }
-
- public boolean isShortcutImeReady() {
- updateShortcutIME();
- if (mShortcutInputMethodInfo == null) {
- return false;
- }
- if (mShortcutSubtype == null) {
- return true;
- }
- if (mShortcutSubtype.containsExtraValueKey(REQ_NETWORK_CONNECTIVITY)) {
- return mIsNetworkConnected;
- }
- return true;
- }
-
- public void onNetworkStateChanged(final Intent intent) {
- final boolean noConnection = intent.getBooleanExtra(
- ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
- mIsNetworkConnected = !noConnection;
-
- KeyboardSwitcher.getInstance().onNetworkStateChanged();
+ final RichInputMethodSubtype richSubtype = mRichImm.onSubtypeChanged(newSubtype);
+ final boolean implicitlyEnabledSubtype = mRichImm
+ .checkIfSubtypeBelongsToThisImeAndImplicitlyEnabled(newSubtype);
+ mLanguageOnSpacebarHelper.onSubtypeChanged(
+ richSubtype, implicitlyEnabledSubtype, mResources.getConfiguration().locale);
+ mRichImm.updateShortcutIME();
}
- //////////////////////////////////
- // Subtype Switching functions //
- //////////////////////////////////
-
public int getLanguageOnSpacebarFormatType(final RichInputMethodSubtype subtype) {
return mLanguageOnSpacebarHelper.getLanguageOnSpacebarFormatType(subtype);
}
-
- public boolean isSystemLocaleSameAsLocaleOfAllEnabledSubtypesOfEnabledImes() {
- final Locale systemLocale = mResources.getConfiguration().locale;
- final Set<InputMethodSubtype> enabledSubtypesOfEnabledImes = new HashSet<>();
- final InputMethodManager inputMethodManager = mRichImm.getInputMethodManager();
- final List<InputMethodInfo> enabledInputMethodInfoList =
- inputMethodManager.getEnabledInputMethodList();
- for (final InputMethodInfo info : enabledInputMethodInfoList) {
- final List<InputMethodSubtype> enabledSubtypes =
- inputMethodManager.getEnabledInputMethodSubtypeList(
- info, true /* allowsImplicitlySelectedSubtypes */);
- if (enabledSubtypes.isEmpty()) {
- // An IME with no subtypes is found.
- return false;
- }
- enabledSubtypesOfEnabledImes.addAll(enabledSubtypes);
- }
- for (final InputMethodSubtype subtype : enabledSubtypesOfEnabledImes) {
- if (!subtype.isAuxiliary() && !subtype.getLocale().isEmpty()
- && !systemLocale.equals(SubtypeLocaleUtils.getSubtypeLocale(subtype))) {
- return false;
- }
- }
- return true;
- }
-
- private static RichInputMethodSubtype sForcedSubtypeForTesting = null;
-
- @UsedForTesting
- static void forceSubtype(final InputMethodSubtype subtype) {
- sForcedSubtypeForTesting = new RichInputMethodSubtype(subtype);
- }
-
- public Locale[] getCurrentSubtypeLocales() {
- if (null != sForcedSubtypeForTesting) {
- return sForcedSubtypeForTesting.getLocales();
- }
- return getCurrentSubtype().getLocales();
- }
-
- public RichInputMethodSubtype getCurrentSubtype() {
- if (null != sForcedSubtypeForTesting) {
- return sForcedSubtypeForTesting;
- }
- return mCurrentRichInputMethodSubtype;
- }
-
- public RichInputMethodSubtype getNoLanguageSubtype() {
- if (mNoLanguageSubtype == null) {
- mNoLanguageSubtype = new RichInputMethodSubtype(
- mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
- SubtypeLocaleUtils.NO_LANGUAGE, SubtypeLocaleUtils.QWERTY));
- }
- if (mNoLanguageSubtype != null) {
- return mNoLanguageSubtype;
- }
- Log.w(TAG, "Can't find any language with QWERTY subtype");
- Log.w(TAG, "No input method subtype found; returning dummy subtype: "
- + DUMMY_NO_LANGUAGE_SUBTYPE);
- return DUMMY_NO_LANGUAGE_SUBTYPE;
- }
-
- public RichInputMethodSubtype getEmojiSubtype() {
- if (mEmojiSubtype == null) {
- final InputMethodSubtype rawEmojiSubtype =
- mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
- SubtypeLocaleUtils.NO_LANGUAGE, SubtypeLocaleUtils.EMOJI);
- if (null != rawEmojiSubtype) {
- mEmojiSubtype = new RichInputMethodSubtype(rawEmojiSubtype);
- }
- }
- if (mEmojiSubtype != null) {
- return mEmojiSubtype;
- }
- Log.w(TAG, "Can't find emoji subtype");
- Log.w(TAG, "No input method subtype found; returning dummy subtype: "
- + DUMMY_EMOJI_SUBTYPE);
- return DUMMY_EMOJI_SUBTYPE;
- }
-
- public String getCombiningRulesExtraValueOfCurrentSubtype() {
- return SubtypeLocaleUtils.getCombiningRulesExtraValue(getCurrentSubtype().getRawSubtype());
- }
}
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index 430f765ea..ee8d3f8cb 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -140,8 +140,8 @@ public final class Suggest {
: typedWord;
final SuggestionResults suggestionResults = mDictionaryFacilitator.getSuggestionResults(
- wordComposer, ngramContext, proximityInfo, settingsValuesForSuggestion,
- SESSION_ID_TYPING);
+ wordComposer, ngramContext, proximityInfo.getNativeProximityInfo(),
+ settingsValuesForSuggestion, SESSION_ID_TYPING);
final ArrayList<SuggestedWordInfo> suggestionsContainer =
getTransformedSuggestedWordInfoList(wordComposer, suggestionResults,
trailingSingleQuotesCount,
@@ -230,7 +230,7 @@ public final class Suggest {
inputStyle = inputStyleIfNotPrediction;
}
callback.onGetSuggestedWords(new SuggestedWords(suggestionsList,
- suggestionResults.mRawSuggestions,
+ suggestionResults.mRawSuggestions, typedWord,
// TODO: this first argument is lying. If this is a whitelisted word which is an
// actual word, it says typedWordValid = false, which looks wrong. We should either
// rename the attribute or change the value.
@@ -247,8 +247,8 @@ public final class Suggest {
final int inputStyle, final int sequenceNumber,
final OnGetSuggestedWordsCallback callback) {
final SuggestionResults suggestionResults = mDictionaryFacilitator.getSuggestionResults(
- wordComposer, ngramContext, proximityInfo, settingsValuesForSuggestion,
- SESSION_ID_GESTURE);
+ wordComposer, ngramContext, proximityInfo.getNativeProximityInfo(),
+ settingsValuesForSuggestion, SESSION_ID_GESTURE);
// For transforming words that don't come from a dictionary, because it's our best bet
final Locale defaultLocale = mDictionaryFacilitator.getMostProbableLocale();
final ArrayList<SuggestedWordInfo> suggestionsContainer =
@@ -286,8 +286,12 @@ public final class Suggest {
// (typedWordValid=true), not as an "auto correct word" (willAutoCorrect=false).
// Note that because this method is never used to get predictions, there is no need to
// modify inputType such in getSuggestedWordsForNonBatchInput.
+ final String pseudoTypedWord = suggestionsContainer.isEmpty() ? null
+ : suggestionsContainer.get(0).mWord;
+
callback.onGetSuggestedWords(new SuggestedWords(suggestionsContainer,
suggestionResults.mRawSuggestions,
+ pseudoTypedWord,
true /* typedWordValid */,
false /* willAutoCorrect */,
false /* isObsoleteSuggestions */,
diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java
index c51e20f21..bddeac495 100644
--- a/java/src/com/android/inputmethod/latin/SuggestedWords.java
+++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java
@@ -73,21 +73,11 @@ public class SuggestedWords {
final boolean willAutoCorrect,
final boolean isObsoleteSuggestions,
final int inputStyle) {
- this(suggestedWordInfoList, rawSuggestions, typedWordValid, willAutoCorrect,
- isObsoleteSuggestions, inputStyle, NOT_A_SEQUENCE_NUMBER);
- }
-
- public SuggestedWords(final ArrayList<SuggestedWordInfo> suggestedWordInfoList,
- final ArrayList<SuggestedWordInfo> rawSuggestions,
- final boolean typedWordValid,
- final boolean willAutoCorrect,
- final boolean isObsoleteSuggestions,
- final int inputStyle,
- final int sequenceNumber) {
this(suggestedWordInfoList, rawSuggestions,
(suggestedWordInfoList.isEmpty() || isPrediction(inputStyle)) ? null
: suggestedWordInfoList.get(INDEX_OF_TYPED_WORD).mWord,
- typedWordValid, willAutoCorrect, isObsoleteSuggestions, inputStyle, sequenceNumber);
+ typedWordValid, willAutoCorrect,
+ isObsoleteSuggestions, inputStyle, NOT_A_SEQUENCE_NUMBER);
}
public SuggestedWords(final ArrayList<SuggestedWordInfo> suggestedWordInfoList,
diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java
index 0b77f2ce3..78860d87d 100644
--- a/java/src/com/android/inputmethod/latin/WordComposer.java
+++ b/java/src/com/android/inputmethod/latin/WordComposer.java
@@ -19,11 +19,12 @@ package com.android.inputmethod.latin;
import com.android.inputmethod.event.CombinerChain;
import com.android.inputmethod.event.Event;
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+import com.android.inputmethod.latin.common.ComposedData;
import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.CoordinateUtils;
import com.android.inputmethod.latin.common.InputPointers;
import com.android.inputmethod.latin.common.StringUtils;
import com.android.inputmethod.latin.define.DebugFlags;
-import com.android.inputmethod.latin.utils.CoordinateUtils;
import java.util.ArrayList;
import java.util.Collections;
@@ -90,6 +91,10 @@ public final class WordComposer {
refreshTypedWordCache();
}
+ public ComposedData getComposedDataSnapshot() {
+ return new ComposedData(getInputPointers(), isBatchMode(), mTypedWordCache.toString());
+ }
+
/**
* Restart the combiners, possibly with a new spec.
* @param combiningSpec The spec string for combining. This is found in the extra value.
@@ -134,38 +139,6 @@ public final class WordComposer {
return mCodePointSize;
}
- /**
- * Copy the code points in the typed word to a destination array of ints.
- *
- * If the array is too small to hold the code points in the typed word, nothing is copied and
- * -1 is returned.
- *
- * @param destination the array of ints.
- * @return the number of copied code points.
- */
- public int copyCodePointsExceptTrailingSingleQuotesAndReturnCodePointCount(
- final int[] destination) {
- // This method can be called on a separate thread and mTypedWordCache can change while we
- // are executing this method.
- final String typedWord = mTypedWordCache.toString();
- // lastIndex is exclusive
- final int lastIndex = typedWord.length()
- - StringUtils.getTrailingSingleQuotesCount(typedWord);
- if (lastIndex <= 0) {
- // The string is empty or contains only single quotes.
- return 0;
- }
-
- // The following function counts the number of code points in the text range which begins
- // at index 0 and extends to the character at lastIndex.
- final int codePointSize = Character.codePointCount(typedWord, 0, lastIndex);
- if (codePointSize > destination.length) {
- return -1;
- }
- return StringUtils.copyCodePointsAndReturnCodePointCount(destination, typedWord, 0,
- lastIndex, true /* downCase */);
- }
-
public boolean isSingleLetter() {
return size() == 1;
}
diff --git a/java/src/com/android/inputmethod/latin/debug/ExternalDictionaryGetterForDebug.java b/java/src/com/android/inputmethod/latin/debug/ExternalDictionaryGetterForDebug.java
index d4be0e397..78bfd2b52 100644
--- a/java/src/com/android/inputmethod/latin/debug/ExternalDictionaryGetterForDebug.java
+++ b/java/src/com/android/inputmethod/latin/debug/ExternalDictionaryGetterForDebug.java
@@ -26,10 +26,10 @@ import android.os.Environment;
import com.android.inputmethod.latin.BinaryDictionaryFileDumper;
import com.android.inputmethod.latin.BinaryDictionaryGetter;
import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.common.LocaleUtils;
import com.android.inputmethod.latin.makedict.DictionaryHeader;
import com.android.inputmethod.latin.utils.DialogUtils;
import com.android.inputmethod.latin.utils.DictionaryInfoUtils;
-import com.android.inputmethod.latin.utils.LocaleUtils;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
diff --git a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java
index 78d79ae50..eba9654a5 100644
--- a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java
+++ b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java
@@ -171,14 +171,18 @@ public final class FormatSpec {
// ExpandableDictionary.matchesExpectedBinaryDictFormatVersionForThisType().
public static final int VERSION2 = 2;
public static final int VERSION201 = 201;
+ public static final int VERSION202 = 202;
public static final int MINIMUM_SUPPORTED_VERSION_OF_CODE_POINT_TABLE = VERSION201;
// Dictionary version used for testing.
public static final int VERSION4_ONLY_FOR_TESTING = 399;
- public static final int VERSION401 = 401;
- public static final int VERSION4 = 402;
- public static final int VERSION4_DEV = 403;
- static final int MINIMUM_SUPPORTED_VERSION = VERSION2;
- static final int MAXIMUM_SUPPORTED_VERSION = VERSION4_DEV;
+ public static final int VERSION402 = 402;
+ public static final int VERSION403 = 403;
+ public static final int VERSION4 = VERSION403;
+ public static final int VERSION4_DEV = VERSION403;
+ public static final int MINIMUM_SUPPORTED_STATIC_VERSION = VERSION202;
+ public static final int MAXIMUM_SUPPORTED_STATIC_VERSION = VERSION202;
+ static final int MINIMUM_SUPPORTED_DYNAMIC_VERSION = VERSION4;
+ static final int MAXIMUM_SUPPORTED_DYNAMIC_VERSION = VERSION4_DEV;
// TODO: Make this value adaptative to content data, store it in the header, and
// use it in the reading code.
diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java
index 331f85e0e..8c5eb0aa7 100644
--- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java
+++ b/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java
@@ -19,7 +19,7 @@ package com.android.inputmethod.latin.personalization;
import android.content.Context;
import android.util.Log;
-import com.android.inputmethod.latin.utils.FileUtils;
+import com.android.inputmethod.latin.common.FileUtils;
import java.io.File;
import java.io.FilenameFilter;
@@ -28,32 +28,45 @@ import java.util.Locale;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+/**
+ * Helps handle and manage personalized dictionaries such as {@link UserHistoryDictionary} and
+ * {@link PersonalizationDictionary}.
+ */
public class PersonalizationHelper {
private static final String TAG = PersonalizationHelper.class.getSimpleName();
private static final boolean DEBUG = false;
+
private static final ConcurrentHashMap<String, SoftReference<UserHistoryDictionary>>
sLangUserHistoryDictCache = new ConcurrentHashMap<>();
private static final ConcurrentHashMap<String, SoftReference<PersonalizationDictionary>>
sLangPersonalizationDictCache = new ConcurrentHashMap<>();
+ @Nonnull
public static UserHistoryDictionary getUserHistoryDictionary(
- final Context context, final Locale locale) {
- final String localeStr = locale.toString();
+ final Context context, final Locale locale, @Nullable final String accountName) {
+ String lookupStr = locale.toString();
+ if (accountName != null) {
+ lookupStr += "." + accountName;
+ }
synchronized (sLangUserHistoryDictCache) {
- if (sLangUserHistoryDictCache.containsKey(localeStr)) {
+ if (sLangUserHistoryDictCache.containsKey(lookupStr)) {
final SoftReference<UserHistoryDictionary> ref =
- sLangUserHistoryDictCache.get(localeStr);
+ sLangUserHistoryDictCache.get(lookupStr);
final UserHistoryDictionary dict = ref == null ? null : ref.get();
if (dict != null) {
if (DEBUG) {
- Log.w(TAG, "Use cached UserHistoryDictionary for " + locale);
+ Log.d(TAG, "Use cached UserHistoryDictionary for " + locale +
+ " & account" + accountName);
}
dict.reloadDictionaryIfRequired();
return dict;
}
}
final UserHistoryDictionary dict = new UserHistoryDictionary(context, locale);
- sLangUserHistoryDictCache.put(localeStr, new SoftReference<>(dict));
+ sLangUserHistoryDictCache.put(lookupStr, new SoftReference<>(dict));
return dict;
}
}
diff --git a/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java b/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java
index 58782c646..946835cbc 100644
--- a/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java
@@ -17,30 +17,73 @@
package com.android.inputmethod.latin.personalization;
import android.content.Context;
+import android.content.SharedPreferences;
+import android.preference.PreferenceManager;
import com.android.inputmethod.annotations.ExternallyReferenced;
+import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.latin.Dictionary;
import com.android.inputmethod.latin.ExpandableBinaryDictionary;
import com.android.inputmethod.latin.NgramContext;
import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.define.ProductionFlags;
+import com.android.inputmethod.latin.settings.LocalSettingsConstants;
import com.android.inputmethod.latin.utils.DistracterFilter;
import java.io.File;
import java.util.Locale;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
/**
* Locally gathers stats about the words user types and various other signals like auto-correction
* cancellation or manual picks. This allows the keyboard to adapt to the typist over time.
*/
public class UserHistoryDictionary extends DecayingExpandableBinaryDictionaryBase {
- /* package */ static final String NAME = UserHistoryDictionary.class.getSimpleName();
+ static final String NAME = UserHistoryDictionary.class.getSimpleName();
// TODO: Make this constructor private
- /* package */ UserHistoryDictionary(final Context context, final Locale locale) {
- super(context, getDictName(NAME, locale, null /* dictFile */), locale,
- Dictionary.TYPE_USER_HISTORY, null /* dictFile */);
+ UserHistoryDictionary(final Context context, final Locale locale) {
+ super(context,
+ getUserHistoryDictName(
+ NAME,
+ locale,
+ null /* dictFile */,
+ context),
+ locale,
+ Dictionary.TYPE_USER_HISTORY,
+ null /* dictFile */);
+ }
+
+ /**
+ * @returns the name of the {@link UserHistoryDictionary}.
+ */
+ @UsedForTesting
+ static String getUserHistoryDictName(final String name, final Locale locale,
+ @Nullable final File dictFile, final Context context) {
+ if (!ProductionFlags.ENABLE_PER_ACCOUNT_USER_HISTORY_DICTIONARY) {
+ return getDictName(name, locale, dictFile);
+ }
+ return getUserHistoryDictNamePerAccount(name, locale, dictFile, context);
+ }
+
+ /**
+ * Uses the currently signed in account to determine the dictionary name.
+ */
+ private static String getUserHistoryDictNamePerAccount(final String name, final Locale locale,
+ @Nullable final File dictFile, final Context context) {
+ if (dictFile != null) {
+ 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();
+ if (account != null) {
+ dictName += "." + account;
+ }
+ return dictName;
}
// Note: This method is called by {@link DictionaryFacilitator} using Java reflection.
@@ -48,7 +91,14 @@ public class UserHistoryDictionary extends DecayingExpandableBinaryDictionaryBas
@ExternallyReferenced
public static UserHistoryDictionary getDictionary(final Context context, final Locale locale,
final File dictFile, final String dictNamePrefix) {
- return PersonalizationHelper.getUserHistoryDictionary(context, locale);
+ 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);
}
/**
diff --git a/java/src/com/android/inputmethod/latin/settings/CustomInputStylePreference.java b/java/src/com/android/inputmethod/latin/settings/CustomInputStylePreference.java
index 01398f467..b749aa51a 100644
--- a/java/src/com/android/inputmethod/latin/settings/CustomInputStylePreference.java
+++ b/java/src/com/android/inputmethod/latin/settings/CustomInputStylePreference.java
@@ -346,8 +346,10 @@ final class CustomInputStylePreference extends DialogPreference
super(context, android.R.layout.simple_spinner_item);
setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ final String[] predefinedKeyboardLayoutSet = context.getResources().getStringArray(
+ R.array.predefined_layouts);
// TODO: Should filter out already existing combinations of locale and layout.
- for (final String layout : SubtypeLocaleUtils.getPredefinedKeyboardLayoutSet()) {
+ for (final String layout : predefinedKeyboardLayoutSet) {
// This is a dummy subtype with NO_LANGUAGE, only for display.
final InputMethodSubtype subtype =
AdditionalSubtypeUtils.createDummyAdditionalSubtype(
diff --git a/java/src/com/android/inputmethod/latin/settings/NativeSuggestOptions.java b/java/src/com/android/inputmethod/latin/settings/NativeSuggestOptions.java
deleted file mode 100644
index 7603dbba5..000000000
--- a/java/src/com/android/inputmethod/latin/settings/NativeSuggestOptions.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2013 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.settings;
-
-public class NativeSuggestOptions {
- // Need to update suggest_options.h when you add, remove or reorder options.
- private static final int IS_GESTURE = 0;
- private static final int USE_FULL_EDIT_DISTANCE = 1;
- private static final int BLOCK_OFFENSIVE_WORDS = 2;
- private static final int SPACE_AWARE_GESTURE_ENABLED = 3;
- private static final int WEIGHT_FOR_LOCALE_IN_THOUSANDS = 4;
- private static final int OPTIONS_SIZE = 5;
-
- private final int[] mOptions = new int[OPTIONS_SIZE
- + AdditionalFeaturesSettingUtils.ADDITIONAL_FEATURES_SETTINGS_SIZE];
-
- public void setIsGesture(final boolean value) {
- setBooleanOption(IS_GESTURE, value);
- }
-
- public void setUseFullEditDistance(final boolean value) {
- setBooleanOption(USE_FULL_EDIT_DISTANCE, value);
- }
-
- public void setBlockOffensiveWords(final boolean value) {
- setBooleanOption(BLOCK_OFFENSIVE_WORDS, value);
- }
-
- public void setSpaceAwareGestureEnabled(final boolean value) {
- setBooleanOption(SPACE_AWARE_GESTURE_ENABLED, value);
- }
-
- public void setWeightForLocale(final float value) {
- // We're passing this option as a fixed point value, in thousands. This is decoded in
- // native code by SuggestOptions#weightForLocale().
- setIntegerOption(WEIGHT_FOR_LOCALE_IN_THOUSANDS, (int) (value * 1000));
- }
-
- public void setAdditionalFeaturesOptions(final int[] additionalOptions) {
- if (additionalOptions == null) {
- return;
- }
- for (int i = 0; i < additionalOptions.length; i++) {
- setIntegerOption(OPTIONS_SIZE + i, additionalOptions[i]);
- }
- }
-
- public int[] getOptions() {
- return mOptions;
- }
-
- private void setBooleanOption(final int key, final boolean value) {
- mOptions[key] = value ? 1 : 0;
- }
-
- private void setIntegerOption(final int key, final int value) {
- mOptions[key] = value;
- }
-}
diff --git a/java/src/com/android/inputmethod/latin/settings/PreferencesSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/PreferencesSettingsFragment.java
index 49db2bdc0..c0ceb8857 100644
--- a/java/src/com/android/inputmethod/latin/settings/PreferencesSettingsFragment.java
+++ b/java/src/com/android/inputmethod/latin/settings/PreferencesSettingsFragment.java
@@ -24,7 +24,7 @@ import android.preference.Preference;
import com.android.inputmethod.latin.AudioAndHapticFeedbackManager;
import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.SubtypeSwitcher;
+import com.android.inputmethod.latin.RichInputMethodManager;
/**
* "Preferences" settings sub screen.
@@ -49,7 +49,7 @@ public final class PreferencesSettingsFragment extends SubScreenFragment {
// When we are called from the Settings application but we are not already running, some
// singleton and utility classes may not have been initialized. We have to call
// initialization method of these classes here. See {@link LatinIME#onCreate()}.
- SubtypeSwitcher.init(context);
+ RichInputMethodManager.init(context);
final boolean showVoiceKeyOption = res.getBoolean(
R.bool.config_enable_show_voice_key_option);
@@ -71,7 +71,7 @@ public final class PreferencesSettingsFragment extends SubScreenFragment {
super.onResume();
final Preference voiceInputKeyOption = findPreference(Settings.PREF_VOICE_INPUT_KEY);
if (voiceInputKeyOption != null) {
- final boolean isShortcutImeEnabled = SubtypeSwitcher.getInstance()
+ final boolean isShortcutImeEnabled = RichInputMethodManager.getInstance()
.isShortcutImeEnabled();
voiceInputKeyOption.setEnabled(isShortcutImeEnabled);
voiceInputKeyOption.setSummary(
diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
index 509b41fd3..26415e7d4 100644
--- a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
+++ b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
@@ -28,7 +28,6 @@ import com.android.inputmethod.compat.AppWorkaroundsUtils;
import com.android.inputmethod.latin.InputAttributes;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.RichInputMethodManager;
-import com.android.inputmethod.latin.SubtypeSwitcher;
import com.android.inputmethod.latin.utils.AsyncResultHolder;
import com.android.inputmethod.latin.utils.ResourceUtils;
import com.android.inputmethod.latin.utils.TargetPackageInfoGetterTask;
@@ -140,7 +139,7 @@ public class SettingsValues {
DebugSettings.PREF_SLIDING_KEY_INPUT_PREVIEW, true);
mShowsVoiceInputKey = needsToShowVoiceInputKey(prefs, res)
&& mInputAttributes.mShouldShowVoiceInputKey
- && SubtypeSwitcher.getInstance().isShortcutImeEnabled();
+ && RichInputMethodManager.getInstance().isShortcutImeEnabled();
final String autoCorrectionThresholdRawValue = prefs.getString(
Settings.PREF_AUTO_CORRECTION_THRESHOLD,
res.getString(R.string.auto_correction_threshold_mode_index_modest));
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
index 315e3696b..bcf7bbfdc 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
@@ -168,7 +168,8 @@ public final class AndroidSpellCheckerService extends SpellCheckerService
DictionaryFacilitator dictionaryFacilitatorForLocale =
mDictionaryFacilitatorCache.get(locale);
return dictionaryFacilitatorForLocale.getSuggestionResults(composer, ngramContext,
- proximityInfo, mSettingsValuesForSuggestion, sessionId);
+ proximityInfo.getNativeProximityInfo(), mSettingsValuesForSuggestion,
+ sessionId);
} finally {
if (sessionId != null) {
mSessionIdPool.add(sessionId);
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java
index 3ad8fb910..c90e8a3cf 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java
@@ -34,10 +34,10 @@ import com.android.inputmethod.latin.NgramContext;
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import com.android.inputmethod.latin.WordComposer;
import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.CoordinateUtils;
+import com.android.inputmethod.latin.common.LocaleUtils;
import com.android.inputmethod.latin.common.StringUtils;
import com.android.inputmethod.latin.utils.BinaryDictionaryUtils;
-import com.android.inputmethod.latin.utils.CoordinateUtils;
-import com.android.inputmethod.latin.utils.LocaleUtils;
import com.android.inputmethod.latin.utils.ScriptUtils;
import com.android.inputmethod.latin.utils.SuggestionResults;
diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
index 27a0f62ff..7991a2473 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
@@ -50,10 +50,10 @@ import com.android.inputmethod.latin.PunctuationSuggestions;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.SuggestedWords;
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+import com.android.inputmethod.latin.common.LocaleUtils;
import com.android.inputmethod.latin.settings.Settings;
import com.android.inputmethod.latin.settings.SettingsValues;
import com.android.inputmethod.latin.utils.ResourceUtils;
-import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
import com.android.inputmethod.latin.utils.ViewLayoutUtils;
import java.util.ArrayList;
@@ -570,8 +570,7 @@ final class SuggestionStripLayoutHelper {
final boolean isRtlLanguage = (ViewCompat.getLayoutDirection(addToDictionaryStrip)
== ViewCompat.LAYOUT_DIRECTION_RTL);
final String arrow = isRtlLanguage ? RIGHTWARDS_ARROW : LEFTWARDS_ARROW;
- final boolean isRtlSystem = SubtypeLocaleUtils.isRtlLanguage(
- res.getConfiguration().locale);
+ final boolean isRtlSystem = LocaleUtils.isRtlLanguage(res.getConfiguration().locale);
final CharSequence hint = res.getText(R.string.hint_add_to_dictionary);
hintText = (isRtlLanguage == isRtlSystem) ? (arrow + hint) : (hint + arrow);
hintWidth = width - wordWidth;
diff --git a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryAddWordContents.java b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryAddWordContents.java
index eda81940f..22fc35a42 100644
--- a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryAddWordContents.java
+++ b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryAddWordContents.java
@@ -28,7 +28,7 @@ import android.widget.EditText;
import com.android.inputmethod.compat.UserDictionaryCompatUtils;
import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.utils.LocaleUtils;
+import com.android.inputmethod.latin.common.LocaleUtils;
import java.util.ArrayList;
import java.util.Locale;
diff --git a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryList.java b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryList.java
index 90e4faafd..b9ed35375 100644
--- a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryList.java
+++ b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryList.java
@@ -31,7 +31,7 @@ import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodSubtype;
import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.utils.LocaleUtils;
+import com.android.inputmethod.latin.common.LocaleUtils;
import java.util.List;
import java.util.Locale;
diff --git a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettingsUtils.java b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettingsUtils.java
index e58727ec4..c0a946e42 100644
--- a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettingsUtils.java
+++ b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettingsUtils.java
@@ -17,7 +17,7 @@
package com.android.inputmethod.latin.userdictionary;
import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.utils.LocaleUtils;
+import com.android.inputmethod.latin.common.LocaleUtils;
import android.content.Context;
import android.text.TextUtils;
diff --git a/java/src/com/android/inputmethod/latin/utils/CapsModeUtils.java b/java/src/com/android/inputmethod/latin/utils/CapsModeUtils.java
index 0db63fd9f..0dbc7c858 100644
--- a/java/src/com/android/inputmethod/latin/utils/CapsModeUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/CapsModeUtils.java
@@ -24,6 +24,7 @@ import com.android.inputmethod.latin.common.Constants;
import com.android.inputmethod.latin.common.StringUtils;
import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
+import java.util.ArrayList;
import java.util.Locale;
public final class CapsModeUtils {
@@ -326,4 +327,31 @@ public final class CapsModeUtils {
// Here we arrived at the start of the line. This should behave exactly like whitespace.
return (START == state || LETTER == state) ? noCaps : caps;
}
+
+ /**
+ * Convert capitalize mode flags into human readable text.
+ *
+ * @param capsFlags The modes flags to be converted. It may be any combination of
+ * {@link TextUtils#CAP_MODE_CHARACTERS}, {@link TextUtils#CAP_MODE_WORDS}, and
+ * {@link TextUtils#CAP_MODE_SENTENCES}.
+ * @return the text that describe the <code>capsMode</code>.
+ */
+ public static String flagsToString(final int capsFlags) {
+ final int capsFlagsMask = TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_WORDS
+ | TextUtils.CAP_MODE_SENTENCES;
+ if ((capsFlags & ~capsFlagsMask) != 0) {
+ return "unknown<0x" + Integer.toHexString(capsFlags) + ">";
+ }
+ final ArrayList<String> builder = new ArrayList<>();
+ if ((capsFlags & android.text.TextUtils.CAP_MODE_CHARACTERS) != 0) {
+ builder.add("characters");
+ }
+ if ((capsFlags & android.text.TextUtils.CAP_MODE_WORDS) != 0) {
+ builder.add("words");
+ }
+ if ((capsFlags & android.text.TextUtils.CAP_MODE_SENTENCES) != 0) {
+ builder.add("sentences");
+ }
+ return builder.isEmpty() ? "none" : TextUtils.join("|", builder);
+ }
}
diff --git a/java/src/com/android/inputmethod/latin/utils/CollectionUtils.java b/java/src/com/android/inputmethod/latin/utils/CollectionUtils.java
deleted file mode 100644
index f9839eb91..000000000
--- a/java/src/com/android/inputmethod/latin/utils/CollectionUtils.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2012 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.utils;
-
-import java.util.ArrayList;
-import java.util.Collection;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-public final class CollectionUtils {
- private CollectionUtils() {
- // This utility class is not publicly instantiable.
- }
-
- @Nonnull
- public static <E> ArrayList<E> arrayAsList(@Nonnull final E[] array, final int start,
- final int end) {
- if (start < 0 || start > end || end > array.length) {
- throw new IllegalArgumentException();
- }
-
- final ArrayList<E> list = new ArrayList<>(end - start);
- for (int i = start; i < end; i++) {
- list.add(array[i]);
- }
- return list;
- }
-
- /**
- * Tests whether c contains no elements, true if c is null or c is empty.
- * @param c Collection to test.
- * @return Whether c contains no elements.
- */
- public static boolean isNullOrEmpty(@Nullable final Collection<?> c) {
- return c == null || c.isEmpty();
- }
-}
diff --git a/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java b/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java
index 4e0f5f583..8699f2ce7 100644
--- a/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java
@@ -36,7 +36,8 @@ public class CombinedFormatUtils {
public static final String WORD_TAG = "word";
public static final String BEGINNING_OF_SENTENCE_TAG = "beginning_of_sentence";
public static final String NOT_A_WORD_TAG = "not_a_word";
- public static final String BLACKLISTED_TAG = "blacklisted";
+ public static final String POSSIBLY_OFFENSIVE_TAG = "possibly_offensive";
+ public static final String TRUE_VALUE = "true";
public static String formatAttributeMap(final HashMap<String, String> attributeMap) {
final StringBuilder builder = new StringBuilder();
@@ -61,13 +62,13 @@ public class CombinedFormatUtils {
builder.append(",");
builder.append(formatProbabilityInfo(wordProperty.mProbabilityInfo));
if (wordProperty.mIsBeginningOfSentence) {
- builder.append("," + BEGINNING_OF_SENTENCE_TAG + "=true");
+ builder.append("," + BEGINNING_OF_SENTENCE_TAG + "=" + TRUE_VALUE);
}
if (wordProperty.mIsNotAWord) {
- builder.append("," + NOT_A_WORD_TAG + "=true");
+ builder.append("," + NOT_A_WORD_TAG + "=" + TRUE_VALUE);
}
if (wordProperty.mIsPossiblyOffensive) {
- builder.append("," + BLACKLISTED_TAG + "=true");
+ builder.append("," + POSSIBLY_OFFENSIVE_TAG + "=" + TRUE_VALUE);
}
builder.append("\n");
if (wordProperty.mHasShortcuts) {
@@ -111,4 +112,8 @@ public class CombinedFormatUtils {
}
return builder.toString();
}
+
+ public static boolean isLiteralTrue(final String value) {
+ return TRUE_VALUE.equalsIgnoreCase(value);
+ }
}
diff --git a/java/src/com/android/inputmethod/latin/utils/CoordinateUtils.java b/java/src/com/android/inputmethod/latin/utils/CoordinateUtils.java
deleted file mode 100644
index 3a9705904..000000000
--- a/java/src/com/android/inputmethod/latin/utils/CoordinateUtils.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2012 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.utils;
-
-import javax.annotation.Nonnull;
-
-public final class CoordinateUtils {
- private static final int INDEX_X = 0;
- private static final int INDEX_Y = 1;
- private static final int ELEMENT_SIZE = INDEX_Y + 1;
-
- private CoordinateUtils() {
- // This utility class is not publicly instantiable.
- }
-
- @Nonnull
- public static int[] newInstance() {
- return new int[ELEMENT_SIZE];
- }
-
- public static int x(@Nonnull final int[] coords) {
- return coords[INDEX_X];
- }
-
- public static int y(@Nonnull final int[] coords) {
- return coords[INDEX_Y];
- }
-
- public static void set(@Nonnull final int[] coords, final int x, final int y) {
- coords[INDEX_X] = x;
- coords[INDEX_Y] = y;
- }
-
- public static void copy(@Nonnull final int[] destination, @Nonnull final int[] source) {
- destination[INDEX_X] = source[INDEX_X];
- destination[INDEX_Y] = source[INDEX_Y];
- }
-
- @Nonnull
- public static int[] newCoordinateArray(final int arraySize) {
- return new int[ELEMENT_SIZE * arraySize];
- }
-
- @Nonnull
- public static int[] newCoordinateArray(final int arraySize,
- final int defaultX, final int defaultY) {
- final int[] result = new int[ELEMENT_SIZE * arraySize];
- for (int i = 0; i < arraySize; ++i) {
- setXYInArray(result, i, defaultX, defaultY);
- }
- return result;
- }
-
- public static int xFromArray(@Nonnull final int[] coordsArray, final int index) {
- return coordsArray[ELEMENT_SIZE * index + INDEX_X];
- }
-
- public static int yFromArray(@Nonnull final int[] coordsArray, final int index) {
- return coordsArray[ELEMENT_SIZE * index + INDEX_Y];
- }
-
- @Nonnull
- public static int[] coordinateFromArray(@Nonnull final int[] coordsArray, final int index) {
- final int[] coords = newInstance();
- set(coords, xFromArray(coordsArray, index), yFromArray(coordsArray, index));
- return coords;
- }
-
- public static void setXYInArray(@Nonnull final int[] coordsArray, final int index,
- final int x, final int y) {
- final int baseIndex = ELEMENT_SIZE * index;
- coordsArray[baseIndex + INDEX_X] = x;
- coordsArray[baseIndex + INDEX_Y] = y;
- }
-
- public static void setCoordinateInArray(@Nonnull final int[] coordsArray, final int index,
- @Nonnull final int[] coords) {
- setXYInArray(coordsArray, index, x(coords), y(coords));
- }
-}
diff --git a/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java b/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java
index 24025b272..81c3e3c61 100644
--- a/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java
@@ -28,6 +28,7 @@ import com.android.inputmethod.latin.AssetFileAddress;
import com.android.inputmethod.latin.BinaryDictionaryGetter;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.LocaleUtils;
import com.android.inputmethod.latin.makedict.DictionaryHeader;
import com.android.inputmethod.latin.makedict.UnsupportedFormatException;
import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
diff --git a/java/src/com/android/inputmethod/latin/utils/DistracterFilterCheckingExactMatchesAndSuggestions.java b/java/src/com/android/inputmethod/latin/utils/DistracterFilterCheckingExactMatchesAndSuggestions.java
index 56c8249bd..9c6a94810 100644
--- a/java/src/com/android/inputmethod/latin/utils/DistracterFilterCheckingExactMatchesAndSuggestions.java
+++ b/java/src/com/android/inputmethod/latin/utils/DistracterFilterCheckingExactMatchesAndSuggestions.java
@@ -250,8 +250,9 @@ public class DistracterFilterCheckingExactMatchesAndSuggestions implements Distr
composer.setComposingWord(codePoints, coordinates);
final SuggestionResults suggestionResults;
synchronized (mLock) {
- suggestionResults = dictionaryFacilitator.getSuggestionResults(
- composer, NgramContext.EMPTY_PREV_WORDS_INFO, keyboard.getProximityInfo(),
+ suggestionResults = dictionaryFacilitator.getSuggestionResults(composer,
+ NgramContext.EMPTY_PREV_WORDS_INFO,
+ keyboard.getProximityInfo().getNativeProximityInfo(),
settingsValuesForSuggestion, 0 /* sessionId */);
}
if (suggestionResults.isEmpty()) {
diff --git a/java/src/com/android/inputmethod/latin/utils/FileUtils.java b/java/src/com/android/inputmethod/latin/utils/FileUtils.java
deleted file mode 100644
index f1106a6c6..000000000
--- a/java/src/com/android/inputmethod/latin/utils/FileUtils.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2013 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.utils;
-
-import java.io.File;
-import java.io.FilenameFilter;
-
-/**
- * A simple class to help with removing directories recursively.
- */
-public class FileUtils {
- public static boolean deleteRecursively(final File path) {
- if (path.isDirectory()) {
- final File[] files = path.listFiles();
- if (files != null) {
- for (final File child : files) {
- deleteRecursively(child);
- }
- }
- }
- return path.delete();
- }
-
- public static boolean deleteFilteredFiles(final File dir, final FilenameFilter fileNameFilter) {
- if (!dir.isDirectory()) {
- return false;
- }
- final File[] files = dir.listFiles(fileNameFilter);
- if (files == null) {
- return false;
- }
- boolean hasDeletedAllFiles = true;
- for (final File file : files) {
- if (!deleteRecursively(file)) {
- hasDeletedAllFiles = false;
- }
- }
- return hasDeletedAllFiles;
- }
-}
diff --git a/java/src/com/android/inputmethod/latin/utils/LocaleUtils.java b/java/src/com/android/inputmethod/latin/utils/LocaleUtils.java
deleted file mode 100644
index c519a0de6..000000000
--- a/java/src/com/android/inputmethod/latin/utils/LocaleUtils.java
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (C) 2011 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.utils;
-
-import android.text.TextUtils;
-
-import java.util.HashMap;
-import java.util.Locale;
-
-/**
- * A class to help with handling Locales in string form.
- *
- * This file has the same meaning and features (and shares all of its code) with
- * the one in the dictionary pack. They need to be kept synchronized; for any
- * update/bugfix to this file, consider also updating/fixing the version in the
- * dictionary pack.
- */
-public final class LocaleUtils {
- private LocaleUtils() {
- // Intentional empty constructor for utility class.
- }
-
- // Locale match level constants.
- // A higher level of match is guaranteed to have a higher numerical value.
- // Some room is left within constants to add match cases that may arise necessary
- // in the future, for example differentiating between the case where the countries
- // are both present and different, and the case where one of the locales does not
- // specify the countries. This difference is not needed now.
-
- // Nothing matches.
- public static final int LOCALE_NO_MATCH = 0;
- // The languages matches, but the country are different. Or, the reference locale requires a
- // country and the tested locale does not have one.
- public static final int LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER = 3;
- // The languages and country match, but the variants are different. Or, the reference locale
- // requires a variant and the tested locale does not have one.
- public static final int LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER = 6;
- // The required locale is null or empty so it will accept anything, and the tested locale
- // is non-null and non-empty.
- public static final int LOCALE_ANY_MATCH = 10;
- // The language matches, and the tested locale specifies a country but the reference locale
- // does not require one.
- public static final int LOCALE_LANGUAGE_MATCH = 15;
- // The language and the country match, and the tested locale specifies a variant but the
- // reference locale does not require one.
- public static final int LOCALE_LANGUAGE_AND_COUNTRY_MATCH = 20;
- // The compared locales are fully identical. This is the best match level.
- public static final int LOCALE_FULL_MATCH = 30;
-
- // The level at which a match is "normally" considered a locale match with standard algorithms.
- // Don't use this directly, use #isMatch to test.
- private static final int LOCALE_MATCH = LOCALE_ANY_MATCH;
-
- // Make this match the maximum match level. If this evolves to have more than 2 digits
- // when written in base 10, also adjust the getMatchLevelSortedString method.
- private static final int MATCH_LEVEL_MAX = 30;
-
- /**
- * Return how well a tested locale matches a reference locale.
- *
- * This will check the tested locale against the reference locale and return a measure of how
- * a well it matches the reference. The general idea is that the tested locale has to match
- * every specified part of the required locale. A full match occur when they are equal, a
- * partial match when the tested locale agrees with the reference locale but is more specific,
- * and a difference when the tested locale does not comply with all requirements from the
- * reference locale.
- * In more detail, if the reference locale specifies at least a language and the testedLocale
- * does not specify one, or specifies a different one, LOCALE_NO_MATCH is returned. If the
- * reference locale is empty or null, it will match anything - in the form of LOCALE_FULL_MATCH
- * if the tested locale is empty or null, and LOCALE_ANY_MATCH otherwise. If the reference and
- * tested locale agree on the language, but not on the country,
- * LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER is returned if the reference locale specifies a country,
- * and LOCALE_LANGUAGE_MATCH otherwise.
- * If they agree on both the language and the country, but not on the variant,
- * LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER is returned if the reference locale
- * specifies a variant, and LOCALE_LANGUAGE_AND_COUNTRY_MATCH otherwise. If everything matches,
- * LOCALE_FULL_MATCH is returned.
- * Examples:
- * en <=> en_US => LOCALE_LANGUAGE_MATCH
- * en_US <=> en => LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER
- * en_US_POSIX <=> en_US_Android => LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER
- * en_US <=> en_US_Android => LOCALE_LANGUAGE_AND_COUNTRY_MATCH
- * sp_US <=> en_US => LOCALE_NO_MATCH
- * de <=> de => LOCALE_FULL_MATCH
- * en_US <=> en_US => LOCALE_FULL_MATCH
- * "" <=> en_US => LOCALE_ANY_MATCH
- *
- * @param referenceLocale the reference locale to test against.
- * @param testedLocale the locale to test.
- * @return a constant that measures how well the tested locale matches the reference locale.
- */
- public static int getMatchLevel(String referenceLocale, String testedLocale) {
- if (TextUtils.isEmpty(referenceLocale)) {
- return TextUtils.isEmpty(testedLocale) ? LOCALE_FULL_MATCH : LOCALE_ANY_MATCH;
- }
- if (null == testedLocale) return LOCALE_NO_MATCH;
- String[] referenceParams = referenceLocale.split("_", 3);
- String[] testedParams = testedLocale.split("_", 3);
- // By spec of String#split, [0] cannot be null and length cannot be 0.
- if (!referenceParams[0].equals(testedParams[0])) return LOCALE_NO_MATCH;
- switch (referenceParams.length) {
- case 1:
- return 1 == testedParams.length ? LOCALE_FULL_MATCH : LOCALE_LANGUAGE_MATCH;
- case 2:
- if (1 == testedParams.length) return LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER;
- if (!referenceParams[1].equals(testedParams[1]))
- return LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER;
- if (3 == testedParams.length) return LOCALE_LANGUAGE_AND_COUNTRY_MATCH;
- return LOCALE_FULL_MATCH;
- case 3:
- if (1 == testedParams.length) return LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER;
- if (!referenceParams[1].equals(testedParams[1]))
- return LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER;
- if (2 == testedParams.length) return LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER;
- if (!referenceParams[2].equals(testedParams[2]))
- return LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER;
- return LOCALE_FULL_MATCH;
- }
- // It should be impossible to come here
- return LOCALE_NO_MATCH;
- }
-
- /**
- * Return a string that represents this match level, with better matches first.
- *
- * The strings are sorted in lexicographic order: a better match will always be less than
- * a worse match when compared together.
- */
- public static String getMatchLevelSortedString(int matchLevel) {
- // This works because the match levels are 0~99 (actually 0~30)
- // Ideally this should use a number of digits equals to the 1og10 of the greater matchLevel
- return String.format(Locale.ROOT, "%02d", MATCH_LEVEL_MAX - matchLevel);
- }
-
- /**
- * Find out whether a match level should be considered a match.
- *
- * This method takes a match level as returned by the #getMatchLevel method, and returns whether
- * it should be considered a match in the usual sense with standard Locale functions.
- *
- * @param level the match level, as returned by getMatchLevel.
- * @return whether this is a match or not.
- */
- public static boolean isMatch(int level) {
- return LOCALE_MATCH <= level;
- }
-
- private static final HashMap<String, Locale> sLocaleCache = new HashMap<>();
-
- /**
- * Creates a locale from a string specification.
- */
- public static Locale constructLocaleFromString(final String localeStr) {
- if (localeStr == null) {
- return null;
- }
- synchronized (sLocaleCache) {
- Locale retval = sLocaleCache.get(localeStr);
- if (retval != null) {
- return retval;
- }
- String[] localeParams = localeStr.split("_", 3);
- if (localeParams.length == 1) {
- retval = new Locale(localeParams[0]);
- } else if (localeParams.length == 2) {
- retval = new Locale(localeParams[0], localeParams[1]);
- } else if (localeParams.length == 3) {
- retval = new Locale(localeParams[0], localeParams[1], localeParams[2]);
- }
- if (retval != null) {
- sLocaleCache.put(localeStr, retval);
- }
- return retval;
- }
- }
-}
diff --git a/java/src/com/android/inputmethod/latin/utils/RecapitalizeStatus.java b/java/src/com/android/inputmethod/latin/utils/RecapitalizeStatus.java
index 21daddce7..a381649a4 100644
--- a/java/src/com/android/inputmethod/latin/utils/RecapitalizeStatus.java
+++ b/java/src/com/android/inputmethod/latin/utils/RecapitalizeStatus.java
@@ -51,6 +51,17 @@ public class RecapitalizeStatus {
}
}
+ public static String modeToString(final int recapitalizeMode) {
+ switch (recapitalizeMode) {
+ case NOT_A_RECAPITALIZE_MODE: return "undefined";
+ case CAPS_MODE_ORIGINAL_MIXED_CASE: return "mixedCase";
+ case CAPS_MODE_ALL_LOWER: return "allLower";
+ case CAPS_MODE_FIRST_WORD_UPPER: return "firstWordUpper";
+ case CAPS_MODE_ALL_UPPER: return "allUpper";
+ default: return "unknown<" + recapitalizeMode + ">";
+ }
+ }
+
/**
* We store the location of the cursor and the string that was there before the recapitalize
* action was done, and the location of the cursor and the string that was there after.
diff --git a/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java b/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java
index 55c1dc9e5..013f024c0 100644
--- a/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java
@@ -27,13 +27,14 @@ import android.util.Log;
import android.view.inputmethod.InputMethodSubtype;
import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.RichInputMethodSubtype;
+import com.android.inputmethod.latin.common.LocaleUtils;
import com.android.inputmethod.latin.common.StringUtils;
-import java.util.Arrays;
import java.util.HashMap;
import java.util.Locale;
+import javax.annotation.Nonnull;
+
/**
* A helper class to deal with subtype locales.
*/
@@ -53,7 +54,6 @@ public final class SubtypeLocaleUtils {
private static volatile boolean sInitialized = false;
private static final Object sInitializeLock = new Object();
private static Resources sResources;
- private static String[] sPredefinedKeyboardLayoutSet;
// Keyboard layout to its display name map.
private static final HashMap<String, String> sKeyboardLayoutToDisplayNameMap = new HashMap<>();
// Keyboard layout to subtype name resource id map.
@@ -100,7 +100,6 @@ public final class SubtypeLocaleUtils {
sResources = res;
final String[] predefinedLayoutSet = res.getStringArray(R.array.predefined_layouts);
- sPredefinedKeyboardLayoutSet = predefinedLayoutSet;
final String[] layoutDisplayNames = res.getStringArray(
R.array.predefined_layout_display_names);
for (int i = 0; i < predefinedLayoutSet.length; i++) {
@@ -149,10 +148,6 @@ public final class SubtypeLocaleUtils {
}
}
- public static String[] getPredefinedKeyboardLayoutSet() {
- return sPredefinedKeyboardLayoutSet;
- }
-
public static boolean isExceptionalLocale(final String localeString) {
return sExceptionalLocaleToNameIdsMap.containsKey(localeString);
}
@@ -173,7 +168,8 @@ public final class SubtypeLocaleUtils {
return nameId == null ? UNKNOWN_KEYBOARD_LAYOUT : nameId;
}
- public static Locale getDisplayLocaleOfSubtypeLocale(final String localeString) {
+ @Nonnull
+ public static Locale getDisplayLocaleOfSubtypeLocale(@Nonnull final String localeString) {
if (NO_LANGUAGE.equals(localeString)) {
return sResources.getConfiguration().locale;
}
@@ -183,17 +179,20 @@ public final class SubtypeLocaleUtils {
return LocaleUtils.constructLocaleFromString(localeString);
}
- public static String getSubtypeLocaleDisplayNameInSystemLocale(final String localeString) {
+ public static String getSubtypeLocaleDisplayNameInSystemLocale(
+ @Nonnull final String localeString) {
final Locale displayLocale = sResources.getConfiguration().locale;
return getSubtypeLocaleDisplayNameInternal(localeString, displayLocale);
}
- public static String getSubtypeLocaleDisplayName(final String localeString) {
+ @Nonnull
+ public static String getSubtypeLocaleDisplayName(@Nonnull final String localeString) {
final Locale displayLocale = getDisplayLocaleOfSubtypeLocale(localeString);
return getSubtypeLocaleDisplayNameInternal(localeString, displayLocale);
}
- public static String getSubtypeLanguageDisplayName(final String localeString) {
+ @Nonnull
+ public static String getSubtypeLanguageDisplayName(@Nonnull final String localeString) {
final Locale displayLocale = getDisplayLocaleOfSubtypeLocale(localeString);
final String languageString;
if (sExceptionalLocaleDisplayedInRootLocale.containsKey(localeString)) {
@@ -205,8 +204,9 @@ public final class SubtypeLocaleUtils {
return getSubtypeLocaleDisplayNameInternal(languageString, displayLocale);
}
- private static String getSubtypeLocaleDisplayNameInternal(final String localeString,
- final Locale displayLocale) {
+ @Nonnull
+ private static String getSubtypeLocaleDisplayNameInternal(@Nonnull final String localeString,
+ @Nonnull final Locale displayLocale) {
if (NO_LANGUAGE.equals(localeString)) {
// No language subtype should be displayed in system locale.
return sResources.getString(R.string.subtype_no_language);
@@ -255,8 +255,9 @@ public final class SubtypeLocaleUtils {
// en_US azerty T English (US) (AZERTY) exception
// zz azerty T Alphabet (AZERTY) in system locale
- private static String getReplacementString(final InputMethodSubtype subtype,
- final Locale displayLocale) {
+ @Nonnull
+ private static String getReplacementString(@Nonnull final InputMethodSubtype subtype,
+ @Nonnull final Locale displayLocale) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN
&& subtype.containsExtraValueKey(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME)) {
return subtype.getExtraValueOf(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME);
@@ -264,20 +265,24 @@ public final class SubtypeLocaleUtils {
return getSubtypeLocaleDisplayNameInternal(subtype.getLocale(), displayLocale);
}
- public static String getSubtypeDisplayNameInSystemLocale(final InputMethodSubtype subtype) {
+ @Nonnull
+ public static String getSubtypeDisplayNameInSystemLocale(
+ @Nonnull final InputMethodSubtype subtype) {
final Locale displayLocale = sResources.getConfiguration().locale;
return getSubtypeDisplayNameInternal(subtype, displayLocale);
}
- public static String getSubtypeNameForLogging(final InputMethodSubtype subtype) {
+ @Nonnull
+ public static String getSubtypeNameForLogging(@Nonnull final InputMethodSubtype subtype) {
if (subtype == null) {
return "<null subtype>";
}
return getSubtypeLocale(subtype) + "/" + getKeyboardLayoutSetName(subtype);
}
- private static String getSubtypeDisplayNameInternal(final InputMethodSubtype subtype,
- final Locale displayLocale) {
+ @Nonnull
+ private static String getSubtypeDisplayNameInternal(@Nonnull final InputMethodSubtype subtype,
+ @Nonnull final Locale displayLocale) {
final String replacementString = getReplacementString(subtype, displayLocale);
// TODO: rework this for multi-lingual subtypes
final int nameResId = subtype.getNameResId();
@@ -302,24 +307,25 @@ public final class SubtypeLocaleUtils {
getSubtypeName.runInLocale(sResources, displayLocale), displayLocale);
}
- public static Locale getSubtypeLocale(final InputMethodSubtype subtype) {
+ @Nonnull
+ public static Locale getSubtypeLocale(@Nonnull final InputMethodSubtype subtype) {
final String localeString = subtype.getLocale();
return LocaleUtils.constructLocaleFromString(localeString);
}
- public static String getKeyboardLayoutSetDisplayName(final InputMethodSubtype subtype) {
+ @Nonnull
+ public static String getKeyboardLayoutSetDisplayName(
+ @Nonnull final InputMethodSubtype subtype) {
final String layoutName = getKeyboardLayoutSetName(subtype);
return getKeyboardLayoutSetDisplayName(layoutName);
}
- public static String getKeyboardLayoutSetDisplayName(final String layoutName) {
+ @Nonnull
+ public static String getKeyboardLayoutSetDisplayName(@Nonnull final String layoutName) {
return sKeyboardLayoutToDisplayNameMap.get(layoutName);
}
- public static String getKeyboardLayoutSetName(final RichInputMethodSubtype subtype) {
- return getKeyboardLayoutSetName(subtype.getRawSubtype());
- }
-
+ @Nonnull
public static String getKeyboardLayoutSetName(final InputMethodSubtype subtype) {
String keyboardLayoutSet = subtype.getExtraValueOf(KEYBOARD_LAYOUT_SET);
if (keyboardLayoutSet == null) {
@@ -339,22 +345,6 @@ public final class SubtypeLocaleUtils {
return keyboardLayoutSet;
}
- // TODO: Get this information from the framework instead of maintaining here by ourselves.
- // Sorted list of known Right-To-Left language codes.
- private static final String[] SORTED_RTL_LANGUAGES = {
- "ar", // Arabic
- "fa", // Persian
- "iw", // Hebrew
- };
- static {
- Arrays.sort(SORTED_RTL_LANGUAGES);
- }
-
- public static boolean isRtlLanguage(final Locale locale) {
- final String language = locale.getLanguage();
- return Arrays.binarySearch(SORTED_RTL_LANGUAGES, language) >= 0;
- }
-
public static String getCombiningRulesExtraValue(final InputMethodSubtype subtype) {
return subtype.getExtraValueOf(COMBINING_RULES);
}