From 44861474fbea784f12fe86bc56d30d5d9be4ad81 Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Tue, 19 Jul 2011 18:16:34 +0900 Subject: Add a number of NULL pointer guards. None of these are expected to actually be null, but those are included for peace of mind and foolproofing against future code changes. Bug: 4580040 Change-Id: Ib112b3e5db5f177aaf61767164b7e78d711f90a0 --- .../android/inputmethod/latin/DictionaryFactory.java | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/DictionaryFactory.java') diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java index bba331868..a35b0f5b0 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java @@ -52,13 +52,23 @@ public class DictionaryFactory { } final List dictList = new LinkedList(); - for (final AssetFileAddress f : BinaryDictionaryGetter.getDictionaryFiles(locale, - context, fallbackResId)) { - dictList.add(new BinaryDictionary(context, f.mFilename, f.mOffset, f.mLength, null)); + final List assetFileList = + BinaryDictionaryGetter.getDictionaryFiles(locale, context, fallbackResId); + if (null != assetFileList) { + for (final AssetFileAddress f : assetFileList) { + dictList.add( + new BinaryDictionary(context, f.mFilename, f.mOffset, f.mLength, null)); + } } - if (null == dictList) return null; - return new DictionaryCollection(dictList); + // null == dictList is not supposed to be possible, but better safe than sorry and it's + // safer for future extension. In this case, rather than returning null, it should be safer + // to return an empty DictionaryCollection. + if (null == dictList) { + return new DictionaryCollection(); + } else { + return new DictionaryCollection(dictList); + } } /** -- cgit v1.2.3-83-g751a From 7e19a64c86147967b39442ba78b175d4c8a0c860 Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Wed, 20 Jul 2011 19:02:29 +0900 Subject: Fallback to the included dict if the passed one is invalid If all dictionaries returned by the dictionary pack are invalid, then fallback to the dictionary included in the resources for this locale. Bug: 5052486 Change-Id: Id875194ca56a74b2ed6f5b0b4fdd55475f6842c8 --- .../android/inputmethod/latin/DictionaryFactory.java | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/DictionaryFactory.java') diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java index a35b0f5b0..f0637b8ce 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java @@ -56,8 +56,11 @@ public class DictionaryFactory { BinaryDictionaryGetter.getDictionaryFiles(locale, context, fallbackResId); if (null != assetFileList) { for (final AssetFileAddress f : assetFileList) { - dictList.add( - new BinaryDictionary(context, f.mFilename, f.mOffset, f.mLength, null)); + final BinaryDictionary binaryDictionary = + new BinaryDictionary(context, f.mFilename, f.mOffset, f.mLength, null); + if (binaryDictionary.isValidDictionary()) { + dictList.add(binaryDictionary); + } } } @@ -67,7 +70,16 @@ public class DictionaryFactory { if (null == dictList) { return new DictionaryCollection(); } else { - return new DictionaryCollection(dictList); + if (dictList.isEmpty()) { + // The list may be empty if no dictionaries have been added. The getter should not + // return an empty list, but if it does we end up here. Likewise, if the files + // we found could not be opened by the native code for any reason (format mismatch, + // file too big to fit in memory, etc) then we could have an empty list. In this + // case we want to fall back on the resource. + return new DictionaryCollection(createBinaryDictionary(context, fallbackResId)); + } else { + return new DictionaryCollection(dictList); + } } } -- cgit v1.2.3-83-g751a From e150ef98569d61078e0f8c67ded8364a9c3d4a20 Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Thu, 21 Jul 2011 17:36:57 +0900 Subject: Set the locale for opening an asset This is necessary because we don't know any more whether the locale of the process is the expected one when the dictionary is loaded asynchronously. Bug: 5023141 Change-Id: Ia9e4741f3b4a04a9f085f5b65ec122471b0c2dff --- .../inputmethod/latin/BinaryDictionaryFileDumper.java | 8 ++++++-- .../inputmethod/latin/BinaryDictionaryGetter.java | 13 ++++++++++--- .../android/inputmethod/latin/DictionaryFactory.java | 18 ++++++++++++++---- 3 files changed, 30 insertions(+), 9 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/DictionaryFactory.java') diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java index 76a230f82..00d80f566 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java @@ -19,6 +19,7 @@ package com.android.inputmethod.latin; import android.content.ContentResolver; import android.content.Context; import android.content.res.AssetFileDescriptor; +import android.content.res.Resources; import android.net.Uri; import android.text.TextUtils; @@ -129,8 +130,11 @@ public class BinaryDictionaryFileDumper { */ public static String getDictionaryFileFromResource(int resource, Locale locale, Context context) throws FileNotFoundException, IOException { - return copyFileTo(context.getResources().openRawResource(resource), - getCacheFileNameForLocale(locale, context)); + final Resources res = context.getResources(); + final Locale savedLocale = Utils.setSystemLocale(res, locale); + final InputStream stream = res.openRawResource(resource); + Utils.setSystemLocale(res, savedLocale); + return copyFileTo(stream, getCacheFileNameForLocale(locale, context)); } /** diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java index bce787db2..989a0e9a0 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java @@ -18,6 +18,7 @@ package com.android.inputmethod.latin; import android.content.Context; import android.content.res.AssetFileDescriptor; +import android.content.res.Resources; import android.util.Log; import java.io.FileNotFoundException; @@ -42,8 +43,13 @@ class BinaryDictionaryGetter { /** * Returns a file address from a resource, or null if it cannot be opened. */ - private static AssetFileAddress loadFallbackResource(Context context, int fallbackResId) { - final AssetFileDescriptor afd = context.getResources().openRawResourceFd(fallbackResId); + private static AssetFileAddress loadFallbackResource(final Context context, + final int fallbackResId, final Locale locale) { + final Resources res = context.getResources(); + final Locale savedLocale = Utils.setSystemLocale(res, locale); + final AssetFileDescriptor afd = res.openRawResourceFd(fallbackResId); + Utils.setSystemLocale(res, savedLocale); + if (afd == null) { Log.e(TAG, "Found the resource but cannot read it. Is it compressed? resId=" + fallbackResId); @@ -91,7 +97,8 @@ class BinaryDictionaryGetter { Log.e(TAG, "Unable to read source data for locale " + locale.toString() + ": falling back to internal dictionary"); } - final AssetFileAddress fallbackAsset = loadFallbackResource(context, fallbackResId); + final AssetFileAddress fallbackAsset = loadFallbackResource(context, fallbackResId, + locale); if (null == fallbackAsset) return null; return Arrays.asList(fallbackAsset); } diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java index f0637b8ce..39b4f63a5 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java @@ -48,7 +48,7 @@ public class DictionaryFactory { int fallbackResId) { if (null == locale) { Log.e(TAG, "No locale defined for dictionary"); - return new DictionaryCollection(createBinaryDictionary(context, fallbackResId)); + return new DictionaryCollection(createBinaryDictionary(context, fallbackResId, locale)); } final List dictList = new LinkedList(); @@ -76,7 +76,8 @@ public class DictionaryFactory { // we found could not be opened by the native code for any reason (format mismatch, // file too big to fit in memory, etc) then we could have an empty list. In this // case we want to fall back on the resource. - return new DictionaryCollection(createBinaryDictionary(context, fallbackResId)); + return new DictionaryCollection(createBinaryDictionary(context, fallbackResId, + locale)); } else { return new DictionaryCollection(dictList); } @@ -87,12 +88,21 @@ public class DictionaryFactory { * Initializes a dictionary from a raw resource file * @param context application context for reading resources * @param resId the resource containing the raw binary dictionary + * @param locale the locale to use for the resource * @return an initialized instance of BinaryDictionary */ - protected static BinaryDictionary createBinaryDictionary(Context context, int resId) { + protected static BinaryDictionary createBinaryDictionary(final Context context, + final int resId, final Locale locale) { AssetFileDescriptor afd = null; try { - afd = context.getResources().openRawResourceFd(resId); + final Resources res = context.getResources(); + if (null != locale) { + final Locale savedLocale = Utils.setSystemLocale(res, locale); + afd = res.openRawResourceFd(resId); + Utils.setSystemLocale(res, savedLocale); + } else { + afd = res.openRawResourceFd(resId); + } if (afd == null) { Log.e(TAG, "Found the resource but it is compressed. resId=" + resId); return null; -- cgit v1.2.3-83-g751a From 150bad6fd4b401177c480acf5640b4db0f821886 Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Thu, 18 Aug 2011 19:29:29 +0900 Subject: Have the spell checker use the User dictionary. Bug: 5175868 Change-Id: I165eee4c865caa5ee1daf3e0b1acde8788b996ef --- .../android/inputmethod/latin/DictionaryFactory.java | 4 ++-- .../inputmethod/latin/ExpandableDictionary.java | 7 +++---- .../latin/spellcheck/AndroidSpellCheckerService.java | 20 ++++++++++++++++++-- 3 files changed, 23 insertions(+), 8 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/DictionaryFactory.java') diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java index 39b4f63a5..ffd204dac 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java @@ -42,9 +42,9 @@ public class DictionaryFactory { * @param context application context for reading resources * @param locale the locale for which to create the dictionary * @param fallbackResId the id of the resource to use as a fallback if no pack is found - * @return an initialized instance of Dictionary + * @return an initialized instance of DictionaryCollection */ - public static Dictionary createDictionaryFromManager(Context context, Locale locale, + public static DictionaryCollection createDictionaryFromManager(Context context, Locale locale, int fallbackResId) { if (null == locale) { Log.e(TAG, "No locale defined for dictionary"); diff --git a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java index 35d1541ff..9f4777f5a 100644 --- a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java +++ b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java @@ -127,7 +127,7 @@ public class ExpandableDictionary extends Dictionary { if (!mUpdatingDictionary) { mUpdatingDictionary = true; mRequiresReload = false; - new LoadDictionaryTask().execute(); + new LoadDictionaryTask().start(); } } @@ -541,14 +541,13 @@ public class ExpandableDictionary extends Dictionary { mRoots = new NodeArray(); } - private class LoadDictionaryTask extends AsyncTask { + private class LoadDictionaryTask extends Thread { @Override - protected Void doInBackground(Void... v) { + public void run() { loadDictionaryAsync(); synchronized (mUpdatingLock) { mUpdatingDictionary = false; } - return null; } } diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java index 649774d78..ec82f9e80 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java @@ -30,7 +30,9 @@ import com.android.inputmethod.keyboard.ProximityInfo; import com.android.inputmethod.latin.Dictionary; import com.android.inputmethod.latin.Dictionary.DataType; import com.android.inputmethod.latin.Dictionary.WordCallback; +import com.android.inputmethod.latin.DictionaryCollection; import com.android.inputmethod.latin.DictionaryFactory; +import com.android.inputmethod.latin.UserDictionary; import com.android.inputmethod.latin.Utils; import com.android.inputmethod.latin.WordComposer; @@ -51,6 +53,8 @@ public class AndroidSpellCheckerService extends SpellCheckerService { private final static String[] emptyArray = new String[0]; private Map mDictionaryPools = Collections.synchronizedMap(new TreeMap()); + private Map mUserDictionaries = + Collections.synchronizedMap(new TreeMap()); @Override public Session createSession() { @@ -109,9 +113,14 @@ public class AndroidSpellCheckerService extends SpellCheckerService { public boolean onUnbind(final Intent intent) { final Map oldPools = mDictionaryPools; mDictionaryPools = Collections.synchronizedMap(new TreeMap()); + final Map oldUserDictionaries = mUserDictionaries; + mUserDictionaries = Collections.synchronizedMap(new TreeMap()); for (DictionaryPool pool : oldPools.values()) { pool.close(); } + for (Dictionary dict : oldUserDictionaries.values()) { + dict.close(); + } return false; } @@ -129,9 +138,16 @@ public class AndroidSpellCheckerService extends SpellCheckerService { final ProximityInfo proximityInfo = ProximityInfo.createSpellCheckerProximityInfo(); final Resources resources = getResources(); final int fallbackResourceId = Utils.getMainDictionaryResourceId(resources); - final Dictionary dictionary = + final DictionaryCollection dictionaryCollection = DictionaryFactory.createDictionaryFromManager(this, locale, fallbackResourceId); - return new DictAndProximity(dictionary, proximityInfo); + final String localeStr = locale.toString(); + Dictionary userDict = mUserDictionaries.get(localeStr); + if (null == userDict) { + userDict = new UserDictionary(this, localeStr); + mUserDictionaries.put(localeStr, userDict); + } + dictionaryCollection.addDictionary(userDict); + return new DictAndProximity(dictionaryCollection, proximityInfo); } private class AndroidSpellCheckerSession extends Session { -- cgit v1.2.3-83-g751a From 0ee3b694833df5488900f521adbd818a6a2e90a5 Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Tue, 23 Aug 2011 17:55:46 +0900 Subject: Fix an excessive fallback problem. LatinIME has several fallbacks to ensure a dictionary is used. However, it should now be possible to deactivate the main dictionary through the dictionary pack settings. In this case, Latin IME should not fallback to the built-in dictionary. Change-Id: Ibd992ad89793169f04a968b40781fce819b87b6f --- .../inputmethod/latin/DictionaryFactory.java | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/DictionaryFactory.java') diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java index ffd204dac..9642151d7 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java @@ -64,24 +64,10 @@ public class DictionaryFactory { } } - // null == dictList is not supposed to be possible, but better safe than sorry and it's - // safer for future extension. In this case, rather than returning null, it should be safer - // to return an empty DictionaryCollection. - if (null == dictList) { - return new DictionaryCollection(); - } else { - if (dictList.isEmpty()) { - // The list may be empty if no dictionaries have been added. The getter should not - // return an empty list, but if it does we end up here. Likewise, if the files - // we found could not be opened by the native code for any reason (format mismatch, - // file too big to fit in memory, etc) then we could have an empty list. In this - // case we want to fall back on the resource. - return new DictionaryCollection(createBinaryDictionary(context, fallbackResId, - locale)); - } else { - return new DictionaryCollection(dictList); - } - } + // If the list is empty, that means we should not use any dictionary (for example, the user + // explicitly disabled the main dictionary), so the following is okay. dictList is never + // null, but if for some reason it is, DictionaryCollection handles it gracefully. + return new DictionaryCollection(dictList); } /** -- cgit v1.2.3-83-g751a From ef35cb631c45c8b106fe7ed9e0d1178c3e5fb963 Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Fri, 26 Aug 2011 20:22:47 +0900 Subject: Move locale-related utility methods to LocaleUtils. Change-Id: I7e9e6e5bc4486d8618d0213b112308c3d305c15e --- .../languageswitcher/InputLanguageSelection.java | 5 ++- .../languageswitcher/LanguageSwitcher.java | 4 +- .../inputmethod/keyboard/KeyboardSwitcher.java | 5 ++- .../inputmethod/latin/BinaryDictionaryGetter.java | 4 +- .../inputmethod/latin/DictionaryFactory.java | 14 +++--- .../com/android/inputmethod/latin/LatinIME.java | 8 ++-- .../com/android/inputmethod/latin/LocaleUtils.java | 51 ++++++++++++++++++++++ .../com/android/inputmethod/latin/Settings.java | 6 +-- .../android/inputmethod/latin/SubtypeSwitcher.java | 2 +- java/src/com/android/inputmethod/latin/Utils.java | 34 +-------------- .../spellcheck/AndroidSpellCheckerService.java | 5 ++- .../inputmethod/latin/SubtypeLocaleTests.java | 4 +- 12 files changed, 82 insertions(+), 60 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/DictionaryFactory.java') diff --git a/java/src/com/android/inputmethod/deprecated/languageswitcher/InputLanguageSelection.java b/java/src/com/android/inputmethod/deprecated/languageswitcher/InputLanguageSelection.java index 7eb5acda8..b6e0ec9cf 100644 --- a/java/src/com/android/inputmethod/deprecated/languageswitcher/InputLanguageSelection.java +++ b/java/src/com/android/inputmethod/deprecated/languageswitcher/InputLanguageSelection.java @@ -18,6 +18,7 @@ package com.android.inputmethod.deprecated.languageswitcher; import com.android.inputmethod.keyboard.internal.KeyboardBuilder; import com.android.inputmethod.latin.DictionaryFactory; +import com.android.inputmethod.latin.LocaleUtils; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.Settings; import com.android.inputmethod.latin.SharedPreferencesCompat; @@ -155,7 +156,7 @@ public class InputLanguageSelection extends PreferenceActivity { private Pair hasDictionaryOrLayout(Locale locale) { if (locale == null) return new Pair(null, false); final Resources res = getResources(); - final Locale saveLocale = Utils.setSystemLocale(res, locale); + final Locale saveLocale = LocaleUtils.setSystemLocale(res, locale); final Long dictionaryId = DictionaryFactory.getDictionaryId(this, locale); boolean hasLayout = false; @@ -174,7 +175,7 @@ public class InputLanguageSelection extends PreferenceActivity { } catch (XmlPullParserException e) { } catch (IOException e) { } - Utils.setSystemLocale(res, saveLocale); + LocaleUtils.setSystemLocale(res, saveLocale); return new Pair(dictionaryId, hasLayout); } diff --git a/java/src/com/android/inputmethod/deprecated/languageswitcher/LanguageSwitcher.java b/java/src/com/android/inputmethod/deprecated/languageswitcher/LanguageSwitcher.java index 1eedb5ee1..8070942d0 100644 --- a/java/src/com/android/inputmethod/deprecated/languageswitcher/LanguageSwitcher.java +++ b/java/src/com/android/inputmethod/deprecated/languageswitcher/LanguageSwitcher.java @@ -18,9 +18,9 @@ package com.android.inputmethod.deprecated.languageswitcher; import com.android.inputmethod.latin.LatinIME; import com.android.inputmethod.latin.LatinImeLogger; +import com.android.inputmethod.latin.LocaleUtils; import com.android.inputmethod.latin.Settings; import com.android.inputmethod.latin.SharedPreferencesCompat; -import com.android.inputmethod.latin.Utils; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; @@ -126,7 +126,7 @@ public class LanguageSwitcher { private void constructLocales() { mLocales.clear(); for (final String lang : mSelectedLanguageArray) { - final Locale locale = Utils.constructLocaleFromString(lang); + final Locale locale = LocaleUtils.constructLocaleFromString(lang); mLocales.add(locale); } } diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java index b1212f424..e43ae55a8 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java @@ -33,6 +33,7 @@ import com.android.inputmethod.keyboard.internal.ModifierKeyState; import com.android.inputmethod.keyboard.internal.ShiftKeyState; import com.android.inputmethod.latin.LatinIME; import com.android.inputmethod.latin.LatinImeLogger; +import com.android.inputmethod.latin.LocaleUtils; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.Settings; import com.android.inputmethod.latin.SubtypeSwitcher; @@ -258,11 +259,11 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha final SoftReference ref = mKeyboardCache.get(id); LatinKeyboard keyboard = (ref == null) ? null : ref.get(); if (keyboard == null) { - final Locale savedLocale = Utils.setSystemLocale(mResources, id.mLocale); + final Locale savedLocale = LocaleUtils.setSystemLocale(mResources, id.mLocale); try { keyboard = new LatinKeyboard.Builder(mThemeContext).load(id).build(); } finally { - Utils.setSystemLocale(mResources, savedLocale); + LocaleUtils.setSystemLocale(mResources, savedLocale); } mKeyboardCache.put(id, new SoftReference(keyboard)); diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java index 360c944d2..5546d48c0 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java @@ -157,9 +157,9 @@ class BinaryDictionaryGetter { private static AssetFileAddress loadFallbackResource(final Context context, final int fallbackResId, final Locale locale) { final Resources res = context.getResources(); - final Locale savedLocale = Utils.setSystemLocale(res, locale); + final Locale savedLocale = LocaleUtils.setSystemLocale(res, locale); final AssetFileDescriptor afd = res.openRawResourceFd(fallbackResId); - Utils.setSystemLocale(res, savedLocale); + LocaleUtils.setSystemLocale(res, savedLocale); if (afd == null) { Log.e(TAG, "Found the resource but cannot read it. Is it compressed? resId=" diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java index 9642151d7..dfaad26bc 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java @@ -83,9 +83,9 @@ public class DictionaryFactory { try { final Resources res = context.getResources(); if (null != locale) { - final Locale savedLocale = Utils.setSystemLocale(res, locale); + final Locale savedLocale = LocaleUtils.setSystemLocale(res, locale); afd = res.openRawResourceFd(resId); - Utils.setSystemLocale(res, savedLocale); + LocaleUtils.setSystemLocale(res, savedLocale); } else { afd = res.openRawResourceFd(resId); } @@ -145,7 +145,7 @@ public class DictionaryFactory { */ public static boolean isDictionaryAvailable(Context context, Locale locale) { final Resources res = context.getResources(); - final Locale saveLocale = Utils.setSystemLocale(res, locale); + final Locale saveLocale = LocaleUtils.setSystemLocale(res, locale); final int resourceId = Utils.getMainDictionaryResourceId(res); final AssetFileDescriptor afd = res.openRawResourceFd(resourceId); @@ -156,14 +156,14 @@ public class DictionaryFactory { /* Um, what can we do here exactly? */ } - Utils.setSystemLocale(res, saveLocale); + LocaleUtils.setSystemLocale(res, saveLocale); return hasDictionary; } // TODO: Do not use the size of the dictionary as an unique dictionary ID. - public static Long getDictionaryId(Context context, Locale locale) { + public static Long getDictionaryId(final Context context, final Locale locale) { final Resources res = context.getResources(); - final Locale saveLocale = Utils.setSystemLocale(res, locale); + final Locale saveLocale = LocaleUtils.setSystemLocale(res, locale); final int resourceId = Utils.getMainDictionaryResourceId(res); final AssetFileDescriptor afd = res.openRawResourceFd(resourceId); @@ -175,7 +175,7 @@ public class DictionaryFactory { } catch (java.io.IOException e) { } - Utils.setSystemLocale(res, saveLocale); + LocaleUtils.setSystemLocale(res, saveLocale); return size; } diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 552517bc8..229bf0f4c 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -479,10 +479,10 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar private void initSuggest() { final String localeStr = mSubtypeSwitcher.getInputLocaleStr(); - final Locale keyboardLocale = Utils.constructLocaleFromString(localeStr); + final Locale keyboardLocale = LocaleUtils.constructLocaleFromString(localeStr); final Resources res = mResources; - final Locale savedLocale = Utils.setSystemLocale(res, keyboardLocale); + final Locale savedLocale = LocaleUtils.setSystemLocale(res, keyboardLocale); final ContactsDictionary oldContactsDictionary; if (mSuggest != null) { oldContactsDictionary = mSuggest.getContactsDictionary(); @@ -514,7 +514,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar updateCorrectionMode(); - Utils.setSystemLocale(res, savedLocale); + LocaleUtils.setSystemLocale(res, savedLocale); } /** @@ -551,7 +551,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar /* package private */ void resetSuggestMainDict() { final String localeStr = mSubtypeSwitcher.getInputLocaleStr(); - final Locale keyboardLocale = Utils.constructLocaleFromString(localeStr); + final Locale keyboardLocale = LocaleUtils.constructLocaleFromString(localeStr); int mainDicResId = Utils.getMainDictionaryResourceId(mResources); mSuggest.resetMainDict(this, mainDicResId, keyboardLocale); } diff --git a/java/src/com/android/inputmethod/latin/LocaleUtils.java b/java/src/com/android/inputmethod/latin/LocaleUtils.java index 054f1f9b8..efa9bfee3 100644 --- a/java/src/com/android/inputmethod/latin/LocaleUtils.java +++ b/java/src/com/android/inputmethod/latin/LocaleUtils.java @@ -16,8 +16,13 @@ package com.android.inputmethod.latin; +import android.content.res.Configuration; +import android.content.res.Resources; import android.text.TextUtils; +import java.util.HashMap; +import java.util.Locale; + /** * A class to help with handling Locales in string form. * @@ -30,6 +35,10 @@ public class LocaleUtils { private final static String TAG = LocaleUtils.class.getSimpleName(); + 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 @@ -154,4 +163,46 @@ public class LocaleUtils { public static boolean isMatch(int level) { return LOCALE_MATCH <= level; } + + /** + * Sets the system locale for this process. + * + * @param res the resources to use. Pass current resources. + * @param newLocale the locale to change to. + * @return the old locale. + */ + public static Locale setSystemLocale(final Resources res, final Locale newLocale) { + final Configuration conf = res.getConfiguration(); + final Locale saveLocale = conf.locale; + conf.locale = newLocale; + res.updateConfiguration(conf, res.getDisplayMetrics()); + return saveLocale; + } + + private static final HashMap sLocaleCache = new HashMap(); + + /** + * Creates a locale from a string specification. + */ + public static Locale constructLocaleFromString(final String localeStr) { + if (localeStr == null) + return null; + synchronized (sLocaleCache) { + if (sLocaleCache.containsKey(localeStr)) + return sLocaleCache.get(localeStr); + Locale retval = null; + 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/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java index 87a713f5c..a5eed9015 100644 --- a/java/src/com/android/inputmethod/latin/Settings.java +++ b/java/src/com/android/inputmethod/latin/Settings.java @@ -128,8 +128,8 @@ public class Settings extends InputMethodSettingsActivity final Resources res = context.getResources(); final Locale savedLocale; if (null != localeStr) { - final Locale keyboardLocale = Utils.constructLocaleFromString(localeStr); - savedLocale = Utils.setSystemLocale(res, keyboardLocale); + final Locale keyboardLocale = LocaleUtils.constructLocaleFromString(localeStr); + savedLocale = LocaleUtils.setSystemLocale(res, keyboardLocale); } else { savedLocale = null; } @@ -191,7 +191,7 @@ public class Settings extends InputMethodSettingsActivity mVoiceKeyEnabled = voiceMode != null && !voiceMode.equals(voiceModeOff); mVoiceKeyOnMain = voiceMode != null && voiceMode.equals(voiceModeMain); - Utils.setSystemLocale(res, savedLocale); + LocaleUtils.setSystemLocale(res, savedLocale); } public boolean isSuggestedPunctuation(int code) { diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java index d969e39eb..87d854940 100644 --- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java +++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java @@ -267,7 +267,7 @@ public class SubtypeSwitcher { // "en" --> language: en // "" --> the system locale if (!TextUtils.isEmpty(inputLocaleStr)) { - mInputLocale = Utils.constructLocaleFromString(inputLocaleStr); + mInputLocale = LocaleUtils.constructLocaleFromString(inputLocaleStr); mInputLocaleStr = inputLocaleStr; } else { mInputLocale = mSystemLocale; diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java index ff051dcbb..60a4cfb38 100644 --- a/java/src/com/android/inputmethod/latin/Utils.java +++ b/java/src/com/android/inputmethod/latin/Utils.java @@ -705,38 +705,6 @@ public class Utils { return (int) (dip * scale + 0.5); } - public static Locale setSystemLocale(Resources res, Locale newLocale) { - final Configuration conf = res.getConfiguration(); - final Locale saveLocale = conf.locale; - conf.locale = newLocale; - res.updateConfiguration(conf, res.getDisplayMetrics()); - return saveLocale; - } - - private static final HashMap sLocaleCache = new HashMap(); - - public static Locale constructLocaleFromString(String localeStr) { - if (localeStr == null) - return null; - synchronized (sLocaleCache) { - if (sLocaleCache.containsKey(localeStr)) - return sLocaleCache.get(localeStr); - Locale retval = null; - 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; - } - } - /** * Remove duplicates from an array of strings. * @@ -783,7 +751,7 @@ public class Utils { } public static String getMiddleDisplayLanguage(Locale locale) { - return toTitleCase((constructLocaleFromString( + return toTitleCase((LocaleUtils.constructLocaleFromString( locale.getLanguage()).getDisplayLanguage(locale)), locale); } diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java index 502ebb52a..3244bcc65 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java @@ -33,6 +33,7 @@ import com.android.inputmethod.latin.Dictionary.DataType; import com.android.inputmethod.latin.Dictionary.WordCallback; import com.android.inputmethod.latin.DictionaryCollection; import com.android.inputmethod.latin.DictionaryFactory; +import com.android.inputmethod.latin.LocaleUtils; import com.android.inputmethod.latin.UserDictionary; import com.android.inputmethod.latin.Utils; import com.android.inputmethod.latin.WordComposer; @@ -139,7 +140,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService { private DictionaryPool getDictionaryPool(final String locale) { DictionaryPool pool = mDictionaryPools.get(locale); if (null == pool) { - final Locale localeObject = Utils.constructLocaleFromString(locale); + final Locale localeObject = LocaleUtils.constructLocaleFromString(locale); pool = new DictionaryPool(POOL_SIZE, this, localeObject); mDictionaryPools.put(locale, pool); } @@ -172,7 +173,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService { public void onCreate() { final String localeString = getLocale(); mDictionaryPool = getDictionaryPool(localeString); - mLocale = Utils.constructLocaleFromString(localeString); + mLocale = LocaleUtils.constructLocaleFromString(localeString); } // Note : this must be reentrant diff --git a/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java b/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java index d102aa4d1..fec3e8ee1 100644 --- a/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java +++ b/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java @@ -16,7 +16,7 @@ package com.android.inputmethod.latin; -import com.android.inputmethod.latin.Utils; +import com.android.inputmethod.latin.LocaleUtils; import android.content.Context; import android.content.res.Resources; @@ -77,7 +77,7 @@ public class SubtypeLocaleTests extends AndroidTestCase { int failedCount = 0; for (final InputMethodSubtype subtype : mKeyboardSubtypes) { final String localeCode = subtype.getLocale(); - final Locale locale = Utils.constructLocaleFromString(localeCode); + final Locale locale = LocaleUtils.constructLocaleFromString(localeCode); // The locale name which will be displayed on spacebar. For example 'English (US)' or // 'Francais (Canada)'. (c=\u008d) final String displayName = SubtypeLocale.getFullDisplayName(locale); -- cgit v1.2.3-83-g751a From 673cebf9e97289b3b0cd343ff7193dff69684a48 Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Thu, 29 Sep 2011 21:07:22 +0900 Subject: Make use of the FULL_EDIT_DISTANCE flag. In effect, this stops the spell checker from suggesting overly long words. More precisely, it takes advantage of the new facility that takes into account the whole length of the dictionary word when computing scores, so words much longer than the input word will see their score demoted accordingly. Bug: 5384578 Change-Id: I326cd7c87c3080e7fa8729f78517f8ba13672a9b --- .../inputmethod/latin/BinaryDictionary.java | 14 ++++++++++-- .../inputmethod/latin/DictionaryFactory.java | 25 ++++++++++++++++++---- .../spellcheck/AndroidSpellCheckerService.java | 16 +++++++++++++- 3 files changed, 48 insertions(+), 7 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/DictionaryFactory.java') diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java index ab9edb110..18a9e3ab1 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java @@ -61,16 +61,26 @@ public class BinaryDictionary extends Dictionary { public static final Flag FLAG_REQUIRES_GERMAN_UMLAUT_PROCESSING = new Flag(R.bool.config_require_umlaut_processing, 0x1); + // FULL_EDIT_DISTANCE is a flag that forces the dictionary to use full words + // when computing edit distance, instead of the default behavior of stopping + // the evaluation at the size the user typed. public static final Flag FLAG_USE_FULL_EDIT_DISTANCE = new Flag(0x2); // Can create a new flag from extravalue : // public static final Flag FLAG_MYFLAG = // new Flag("my_flag", 0x02); - private static final Flag[] ALL_FLAGS = { + // ALL_CONFIG_FLAGS is a collection of flags that enable reading all flags from configuration. + // This is but a mask - it does not mean the flags will be on, only that the configuration + // will be read for this particular flag. + public static final Flag[] ALL_CONFIG_FLAGS = { // Here should reside all flags that trigger some special processing // These *must* match the definition in UnigramDictionary enum in // unigram_dictionary.h so please update both at the same time. + // Please note that flags created with a resource are of type CONFIG while flags + // created with a string are of type EXTRAVALUE. These behave like masks, and the + // actual value will be read from the configuration/extra value at run time for + // the configuration at dictionary creation time. FLAG_REQUIRES_GERMAN_UMLAUT_PROCESSING, }; @@ -93,7 +103,7 @@ public class BinaryDictionary extends Dictionary { // the Suggest class knows everything about every single dictionary. mDicTypeId = Suggest.DIC_MAIN; // TODO: Stop relying on the state of SubtypeSwitcher, get it as a parameter - mFlags = Flag.initFlags(null == flagArray ? ALL_FLAGS : flagArray, context, + mFlags = Flag.initFlags(null == flagArray ? ALL_CONFIG_FLAGS : flagArray, context, SubtypeSwitcher.getInstance()); loadDictionary(filename, offset, length); } diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java index dfaad26bc..1607f86a8 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java @@ -34,7 +34,7 @@ public class DictionaryFactory { private static String TAG = DictionaryFactory.class.getSimpleName(); /** - * Initializes a dictionary from a dictionary pack. + * Initializes a dictionary from a dictionary pack, with explicit flags. * * This searches for a content provider providing a dictionary pack for the specified * locale. If none is found, it falls back to using the resource passed as fallBackResId @@ -42,10 +42,11 @@ public class DictionaryFactory { * @param context application context for reading resources * @param locale the locale for which to create the dictionary * @param fallbackResId the id of the resource to use as a fallback if no pack is found + * @param flagArray an array of flags to use * @return an initialized instance of DictionaryCollection */ - public static DictionaryCollection createDictionaryFromManager(Context context, Locale locale, - int fallbackResId) { + public static DictionaryCollection createDictionaryFromManager(final Context context, + final Locale locale, final int fallbackResId, final Flag[] flagArray) { if (null == locale) { Log.e(TAG, "No locale defined for dictionary"); return new DictionaryCollection(createBinaryDictionary(context, fallbackResId, locale)); @@ -57,7 +58,7 @@ public class DictionaryFactory { if (null != assetFileList) { for (final AssetFileAddress f : assetFileList) { final BinaryDictionary binaryDictionary = - new BinaryDictionary(context, f.mFilename, f.mOffset, f.mLength, null); + new BinaryDictionary(context, f.mFilename, f.mOffset, f.mLength, flagArray); if (binaryDictionary.isValidDictionary()) { dictList.add(binaryDictionary); } @@ -70,6 +71,22 @@ public class DictionaryFactory { return new DictionaryCollection(dictList); } + /** + * Initializes a dictionary from a dictionary pack, with default flags. + * + * This searches for a content provider providing a dictionary pack for the specified + * locale. If none is found, it falls back to using the resource passed as fallBackResId + * as a dictionary. + * @param context application context for reading resources + * @param locale the locale for which to create the dictionary + * @param fallbackResId the id of the resource to use as a fallback if no pack is found + * @return an initialized instance of DictionaryCollection + */ + public static DictionaryCollection createDictionaryFromManager(final Context context, + final Locale locale, final int fallbackResId) { + return createDictionaryFromManager(context, locale, fallbackResId, null); + } + /** * Initializes a dictionary from a raw resource file * @param context application context for reading resources diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java index 1d5986ef9..9e030eb90 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java @@ -28,11 +28,13 @@ import android.text.TextUtils; import com.android.inputmethod.compat.ArraysCompatUtils; import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.keyboard.ProximityInfo; +import com.android.inputmethod.latin.BinaryDictionary; import com.android.inputmethod.latin.Dictionary; import com.android.inputmethod.latin.Dictionary.DataType; import com.android.inputmethod.latin.Dictionary.WordCallback; import com.android.inputmethod.latin.DictionaryCollection; import com.android.inputmethod.latin.DictionaryFactory; +import com.android.inputmethod.latin.Flag; import com.android.inputmethod.latin.LocaleUtils; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.SynchronouslyLoadedUserDictionary; @@ -65,6 +67,17 @@ public class AndroidSpellCheckerService extends SpellCheckerService { private final static SuggestionsInfo IN_DICT_EMPTY_SUGGESTIONS = new SuggestionsInfo(SuggestionsInfo.RESULT_ATTR_IN_THE_DICTIONARY, EMPTY_STRING_ARRAY); + private final static Flag[] USE_FULL_EDIT_DISTANCE_FLAG_ARRAY; + static { + // See BinaryDictionary.java for an explanation of these flags + // Specifially, ALL_CONFIG_FLAGS means that we want to consider all flags with the + // current dictionary configuration - for example, consider the UMLAUT flag + // so that it will be turned on for German dictionaries and off for others. + USE_FULL_EDIT_DISTANCE_FLAG_ARRAY = Arrays.copyOf(BinaryDictionary.ALL_CONFIG_FLAGS, + BinaryDictionary.ALL_CONFIG_FLAGS.length + 1); + USE_FULL_EDIT_DISTANCE_FLAG_ARRAY[BinaryDictionary.ALL_CONFIG_FLAGS.length] = + BinaryDictionary.FLAG_USE_FULL_EDIT_DISTANCE; + } private Map mDictionaryPools = Collections.synchronizedMap(new TreeMap()); private Map mUserDictionaries = @@ -263,7 +276,8 @@ public class AndroidSpellCheckerService extends SpellCheckerService { final Resources resources = getResources(); final int fallbackResourceId = Utils.getMainDictionaryResourceId(resources); final DictionaryCollection dictionaryCollection = - DictionaryFactory.createDictionaryFromManager(this, locale, fallbackResourceId); + DictionaryFactory.createDictionaryFromManager(this, locale, fallbackResourceId, + USE_FULL_EDIT_DISTANCE_FLAG_ARRAY); final String localeStr = locale.toString(); Dictionary userDict = mUserDictionaries.get(localeStr); if (null == userDict) { -- cgit v1.2.3-83-g751a From cc8c8b99bd0463f5977dea82f5e2379ea1dd4e73 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Thu, 8 Mar 2012 17:07:02 +0900 Subject: Split Utils class to StringUtils, SubtypeUtils, and JniUtils Change-Id: I09e91675fe7d573dad8c933ad513b21d7e409144 --- .../compat/InputMethodManagerCompatWrapper.java | 7 +- .../android/inputmethod/deprecated/VoiceProxy.java | 6 +- .../languageswitcher/InputLanguageSelection.java | 24 +- .../deprecated/voice/RecognitionView.java | 10 +- java/src/com/android/inputmethod/keyboard/Key.java | 10 +- .../android/inputmethod/keyboard/KeyboardSet.java | 52 ++- .../android/inputmethod/keyboard/KeyboardView.java | 4 +- .../inputmethod/keyboard/LatinKeyboardView.java | 13 +- .../inputmethod/keyboard/MoreKeysKeyboard.java | 4 +- .../inputmethod/keyboard/ProximityInfo.java | 4 +- .../keyboard/internal/KeySpecParser.java | 12 +- .../inputmethod/latin/BinaryDictionary.java | 2 +- .../inputmethod/latin/DictionaryFactory.java | 14 +- .../com/android/inputmethod/latin/JniUtils.java | 41 +++ .../com/android/inputmethod/latin/LatinIME.java | 23 +- .../com/android/inputmethod/latin/Settings.java | 2 +- .../android/inputmethod/latin/SettingsValues.java | 4 +- .../com/android/inputmethod/latin/StringUtils.java | 198 ++++++++++ .../android/inputmethod/latin/SubtypeSwitcher.java | 2 +- .../android/inputmethod/latin/SubtypeUtils.java | 135 +++++++ .../src/com/android/inputmethod/latin/Suggest.java | 50 ++- java/src/com/android/inputmethod/latin/Utils.java | 398 +-------------------- .../spellcheck/AndroidSpellCheckerService.java | 10 +- 23 files changed, 551 insertions(+), 474 deletions(-) create mode 100644 java/src/com/android/inputmethod/latin/JniUtils.java create mode 100644 java/src/com/android/inputmethod/latin/StringUtils.java create mode 100644 java/src/com/android/inputmethod/latin/SubtypeUtils.java (limited to 'java/src/com/android/inputmethod/latin/DictionaryFactory.java') diff --git a/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java b/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java index 9dd0a599d..bf5f20158 100644 --- a/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java +++ b/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java @@ -32,7 +32,7 @@ import android.view.inputmethod.InputMethodManager; import com.android.inputmethod.deprecated.LanguageSwitcherProxy; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.SubtypeSwitcher; -import com.android.inputmethod.latin.Utils; +import com.android.inputmethod.latin.SubtypeUtils; import java.lang.reflect.Method; import java.util.ArrayList; @@ -163,7 +163,7 @@ public class InputMethodManagerCompatWrapper { private InputMethodInfoCompatWrapper getLatinImeInputMethodInfo() { if (TextUtils.isEmpty(mLatinImePackageName)) return null; - return Utils.getInputMethodInfo(mLatinImePackageName); + return SubtypeUtils.getInputMethodInfo(mLatinImePackageName); } private static InputMethodSubtypeCompatWrapper getLastResortSubtype(String mode) { @@ -260,7 +260,8 @@ public class InputMethodManagerCompatWrapper { // The code below are based on {@link InputMethodManager#showInputMethodMenuInternal}. - final InputMethodInfoCompatWrapper myImi = Utils.getInputMethodInfo(mLatinImePackageName); + final InputMethodInfoCompatWrapper myImi = SubtypeUtils.getInputMethodInfo( + mLatinImePackageName); final List myImsList = getEnabledInputMethodSubtypeList( myImi, true); final InputMethodSubtypeCompatWrapper currentIms = getCurrentInputMethodSubtype(); diff --git a/java/src/com/android/inputmethod/deprecated/VoiceProxy.java b/java/src/com/android/inputmethod/deprecated/VoiceProxy.java index c1c6d31cd..87d1c118b 100644 --- a/java/src/com/android/inputmethod/deprecated/VoiceProxy.java +++ b/java/src/com/android/inputmethod/deprecated/VoiceProxy.java @@ -61,8 +61,8 @@ import com.android.inputmethod.latin.LatinIME; import com.android.inputmethod.latin.LatinIME.UIHandler; import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.StringUtils; import com.android.inputmethod.latin.SubtypeSwitcher; -import com.android.inputmethod.latin.SuggestedWords; import com.android.inputmethod.latin.Utils; import java.util.ArrayList; @@ -662,9 +662,9 @@ public class VoiceProxy implements VoiceInput.UiListener { private boolean shouldShowVoiceButton(FieldContext fieldContext, EditorInfo editorInfo) { @SuppressWarnings("deprecation") - final boolean noMic = Utils.inPrivateImeOptions(null, + final boolean noMic = StringUtils.inPrivateImeOptions(null, LatinIME.IME_OPTION_NO_MICROPHONE_COMPAT, editorInfo) - || Utils.inPrivateImeOptions(mService.getPackageName(), + || StringUtils.inPrivateImeOptions(mService.getPackageName(), LatinIME.IME_OPTION_NO_MICROPHONE, editorInfo); return ENABLE_VOICE_BUTTON && fieldCanDoVoice(fieldContext) && !noMic && SpeechRecognizer.isRecognitionAvailable(mService); diff --git a/java/src/com/android/inputmethod/deprecated/languageswitcher/InputLanguageSelection.java b/java/src/com/android/inputmethod/deprecated/languageswitcher/InputLanguageSelection.java index e75e14861..421ee6529 100644 --- a/java/src/com/android/inputmethod/deprecated/languageswitcher/InputLanguageSelection.java +++ b/java/src/com/android/inputmethod/deprecated/languageswitcher/InputLanguageSelection.java @@ -16,16 +16,6 @@ package com.android.inputmethod.deprecated.languageswitcher; -import com.android.inputmethod.compat.SharedPreferencesCompat; -import com.android.inputmethod.keyboard.KeyboardSet; -import com.android.inputmethod.latin.DictionaryFactory; -import com.android.inputmethod.latin.LocaleUtils; -import com.android.inputmethod.latin.R; -import com.android.inputmethod.latin.Settings; -import com.android.inputmethod.latin.Utils; - -import org.xmlpull.v1.XmlPullParserException; - import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.content.res.Resources; @@ -37,6 +27,16 @@ import android.preference.PreferenceManager; import android.text.TextUtils; import android.util.Pair; +import com.android.inputmethod.compat.SharedPreferencesCompat; +import com.android.inputmethod.keyboard.KeyboardSet; +import com.android.inputmethod.latin.DictionaryFactory; +import com.android.inputmethod.latin.LocaleUtils; +import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.Settings; +import com.android.inputmethod.latin.StringUtils; + +import org.xmlpull.v1.XmlPullParserException; + import java.io.IOException; import java.text.Collator; import java.util.ArrayList; @@ -237,12 +237,12 @@ public class InputLanguageSelection extends PreferenceActivity { if (finalSize == 0) { preprocess[finalSize++] = - new LocaleEntry(Utils.getFullDisplayName(l, false), l); + new LocaleEntry(StringUtils.getFullDisplayName(l, false), l); } else { if (s.equals("zz_ZZ")) { // ignore this locale } else { - final String displayName = Utils.getFullDisplayName(l, false); + final String displayName = StringUtils.getFullDisplayName(l, false); preprocess[finalSize++] = new LocaleEntry(displayName, l); } } diff --git a/java/src/com/android/inputmethod/deprecated/voice/RecognitionView.java b/java/src/com/android/inputmethod/deprecated/voice/RecognitionView.java index 71d15dc3d..ff8b1abce 100644 --- a/java/src/com/android/inputmethod/deprecated/voice/RecognitionView.java +++ b/java/src/com/android/inputmethod/deprecated/voice/RecognitionView.java @@ -16,10 +16,6 @@ package com.android.inputmethod.deprecated.voice; -import com.android.inputmethod.latin.R; -import com.android.inputmethod.latin.SubtypeSwitcher; -import com.android.inputmethod.latin.Utils; - import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; @@ -39,6 +35,10 @@ import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; +import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.StringUtils; +import com.android.inputmethod.latin.SubtypeSwitcher; + import java.io.ByteArrayOutputStream; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -222,7 +222,7 @@ public class RecognitionView { Locale locale = SubtypeSwitcher.getInstance().getInputLocale(); mLanguage.setVisibility(View.VISIBLE); - mLanguage.setText(Utils.getFullDisplayName(locale, true)); + mLanguage.setText(StringUtils.getFullDisplayName(locale, true)); mPopupLayout.setBackgroundDrawable(mListeningBorder); break; diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java index f3923834b..6b4de184f 100644 --- a/java/src/com/android/inputmethod/keyboard/Key.java +++ b/java/src/com/android/inputmethod/keyboard/Key.java @@ -30,7 +30,7 @@ import com.android.inputmethod.keyboard.internal.KeyStyles; import com.android.inputmethod.keyboard.internal.KeyStyles.KeyStyle; import com.android.inputmethod.keyboard.internal.KeyboardIconsSet; import com.android.inputmethod.latin.R; -import com.android.inputmethod.latin.Utils; +import com.android.inputmethod.latin.StringUtils; import com.android.inputmethod.latin.XmlParseUtils; import org.xmlpull.v1.XmlPullParser; @@ -293,7 +293,7 @@ public class Key { // Choose the first letter of the label as primary code if not specified. if (code == Keyboard.CODE_UNSPECIFIED && TextUtils.isEmpty(outputText) && !TextUtils.isEmpty(mLabel)) { - if (Utils.codePointCount(mLabel) == 1) { + if (StringUtils.codePointCount(mLabel) == 1) { // Use the first letter of the hint label if shiftedLetterActivated flag is // specified. if (hasShiftedLetterHint() && isShiftedLetterActivated() @@ -309,7 +309,7 @@ public class Key { mCode = Keyboard.CODE_OUTPUT_TEXT; } } else if (code == Keyboard.CODE_UNSPECIFIED && outputText != null) { - if (Utils.codePointCount(outputText) == 1) { + if (StringUtils.codePointCount(outputText) == 1) { mCode = outputText.codePointAt(0); outputText = null; } else { @@ -336,7 +336,7 @@ public class Key { if (!Keyboard.isLetterCode(code) || preserveCase) return code; final String text = new String(new int[] { code } , 0, 1); final String casedText = adjustCaseOfStringForKeyboardId(text, preserveCase, id); - return Utils.codePointCount(casedText) == 1 + return StringUtils.codePointCount(casedText) == 1 ? casedText.codePointAt(0) : Keyboard.CODE_UNSPECIFIED; } @@ -484,7 +484,7 @@ public class Key { } public int selectTextSize(int letter, int largeLetter, int label, int hintLabel) { - if (Utils.codePointCount(mLabel) > 1 + if (StringUtils.codePointCount(mLabel) > 1 && (mLabelFlags & (LABEL_FLAGS_FOLLOW_KEY_LETTER_RATIO | LABEL_FLAGS_FOLLOW_KEY_HINT_LABEL_RATIO)) == 0) { return label; diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSet.java b/java/src/com/android/inputmethod/keyboard/KeyboardSet.java index 731aaf7c5..5ac6d03a8 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSet.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSet.java @@ -21,16 +21,18 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; +import android.text.InputType; import android.util.Log; import android.util.Xml; import android.view.inputmethod.EditorInfo; import com.android.inputmethod.compat.EditorInfoCompatUtils; +import com.android.inputmethod.compat.InputTypeCompatUtils; import com.android.inputmethod.latin.LatinIME; import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.LocaleUtils; import com.android.inputmethod.latin.R; -import com.android.inputmethod.latin.Utils; +import com.android.inputmethod.latin.StringUtils; import com.android.inputmethod.latin.XmlParseUtils; import org.xmlpull.v1.XmlPullParser; @@ -215,9 +217,9 @@ public class KeyboardSet { mEditorInfo = editorInfo; final Params params = mParams; - params.mMode = Utils.getKeyboardMode(editorInfo); + params.mMode = getKeyboardMode(editorInfo); params.mEditorInfo = (editorInfo != null) ? editorInfo : EMPTY_EDITOR_INFO; - params.mNoSettingsKey = Utils.inPrivateImeOptions( + params.mNoSettingsKey = StringUtils.inPrivateImeOptions( mPackageName, LatinIME.IME_OPTION_NO_SETTINGS_KEY, mEditorInfo); } @@ -230,7 +232,7 @@ public class KeyboardSet { // TODO: Use InputMethodSubtype object as argument. public Builder setSubtype(Locale inputLocale, boolean asciiCapable, boolean touchPositionCorrectionEnabled) { - final boolean deprecatedForceAscii = Utils.inPrivateImeOptions( + final boolean deprecatedForceAscii = StringUtils.inPrivateImeOptions( mPackageName, LatinIME.IME_OPTION_FORCE_ASCII, mEditorInfo); final boolean forceAscii = EditorInfoCompatUtils.hasFlagForceAscii( mParams.mEditorInfo.imeOptions) @@ -243,9 +245,9 @@ public class KeyboardSet { public Builder setOptions(boolean voiceKeyEnabled, boolean voiceKeyOnMain, boolean languageSwitchKeyEnabled) { @SuppressWarnings("deprecation") - final boolean deprecatedNoMicrophone = Utils.inPrivateImeOptions( + final boolean deprecatedNoMicrophone = StringUtils.inPrivateImeOptions( null, LatinIME.IME_OPTION_NO_MICROPHONE_COMPAT, mEditorInfo); - final boolean noMicrophone = Utils.inPrivateImeOptions( + final boolean noMicrophone = StringUtils.inPrivateImeOptions( mPackageName, LatinIME.IME_OPTION_NO_MICROPHONE, mEditorInfo) || deprecatedNoMicrophone; mParams.mVoiceKeyEnabled = voiceKeyEnabled && !noMicrophone; @@ -337,6 +339,44 @@ public class KeyboardSet { a.recycle(); } } + + private static int getKeyboardMode(EditorInfo editorInfo) { + if (editorInfo == null) + return KeyboardId.MODE_TEXT; + + final int inputType = editorInfo.inputType; + final int variation = inputType & InputType.TYPE_MASK_VARIATION; + + switch (inputType & InputType.TYPE_MASK_CLASS) { + case InputType.TYPE_CLASS_NUMBER: + return KeyboardId.MODE_NUMBER; + case InputType.TYPE_CLASS_DATETIME: + switch (variation) { + case InputType.TYPE_DATETIME_VARIATION_DATE: + return KeyboardId.MODE_DATE; + case InputType.TYPE_DATETIME_VARIATION_TIME: + return KeyboardId.MODE_TIME; + default: // InputType.TYPE_DATETIME_VARIATION_NORMAL + return KeyboardId.MODE_DATETIME; + } + case InputType.TYPE_CLASS_PHONE: + return KeyboardId.MODE_PHONE; + case InputType.TYPE_CLASS_TEXT: + if (InputTypeCompatUtils.isEmailVariation(variation)) { + return KeyboardId.MODE_EMAIL; + } else if (variation == InputType.TYPE_TEXT_VARIATION_URI) { + return KeyboardId.MODE_URL; + } else if (variation == InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE) { + return KeyboardId.MODE_IM; + } else if (variation == InputType.TYPE_TEXT_VARIATION_FILTER) { + return KeyboardId.MODE_TEXT; + } else { + return KeyboardId.MODE_TEXT; + } + default: + return KeyboardId.MODE_TEXT; + } + } } public static String parseKeyboardLocale(Resources res, int resId) diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java index 78e0ee230..decd73d45 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java @@ -41,7 +41,7 @@ import com.android.inputmethod.compat.FrameLayoutCompatUtils; import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.StaticInnerHandlerWrapper; -import com.android.inputmethod.latin.Utils; +import com.android.inputmethod.latin.StringUtils; import java.util.HashMap; @@ -853,7 +853,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { if (key.mLabel != null) { // TODO Should take care of temporaryShiftLabel here. previewText.setCompoundDrawables(null, null, null, null); - if (Utils.codePointCount(key.mLabel) > 1) { + if (StringUtils.codePointCount(key.mLabel) > 1) { previewText.setTextSize(TypedValue.COMPLEX_UNIT_PX, params.mKeyLetterSize); previewText.setTypeface(Typeface.DEFAULT_BOLD); } else { diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java index afc4932e9..0a0307500 100644 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java @@ -46,6 +46,8 @@ import com.android.inputmethod.latin.LatinIME; import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.StaticInnerHandlerWrapper; +import com.android.inputmethod.latin.StringUtils; +import com.android.inputmethod.latin.SubtypeUtils; import com.android.inputmethod.latin.Utils; import com.android.inputmethod.latin.Utils.UsabilityStudyLogUtils; @@ -779,12 +781,13 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke // Whether space key needs to show the "..." popup hint for special purposes if (mIsSpacebarTriggeringPopupByLongPress - && Utils.hasMultipleEnabledIMEsOrSubtypes(true /* include aux subtypes */)) { + && SubtypeUtils.hasMultipleEnabledIMEsOrSubtypes( + true /* include aux subtypes */)) { drawKeyPopupHint(key, canvas, paint, params); } } else if (key.mCode == Keyboard.CODE_LANGUAGE_SWITCH) { super.onDrawKeyTopVisuals(key, canvas, paint, params); - if (Utils.hasMultipleEnabledIMEsOrSubtypes(true /* include aux subtypes */)) { + if (SubtypeUtils.hasMultipleEnabledIMEsOrSubtypes(true /* include aux subtypes */)) { drawKeyPopupHint(key, canvas, paint, params); } } else { @@ -810,7 +813,7 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke paint.setTextAlign(Align.CENTER); paint.setTypeface(Typeface.DEFAULT); // Estimate appropriate language name text size to fit in maxTextWidth. - String language = Utils.getFullDisplayName(locale, true); + String language = StringUtils.getFullDisplayName(locale, true); int textWidth = getTextWidth(paint, language, origTextSize); // Assuming text width and text size are proportional to each other. float textSize = origTextSize * Math.min(width / textWidth, 1.0f); @@ -822,7 +825,7 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke final boolean useShortName; if (useMiddleName) { - language = Utils.getMiddleDisplayLanguage(locale); + language = StringUtils.getMiddleDisplayLanguage(locale); textWidth = getTextWidth(paint, language, origTextSize); textSize = origTextSize * Math.min(width / textWidth, 1.0f); useShortName = (textSize / origTextSize < MINIMUM_SCALE_OF_LANGUAGE_NAME) @@ -832,7 +835,7 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke } if (useShortName) { - language = Utils.getShortDisplayLanguage(locale); + language = StringUtils.getShortDisplayLanguage(locale); textWidth = getTextWidth(paint, language, origTextSize); textSize = origTextSize * Math.min(width / textWidth, 1.0f); } diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java index 9f735cff7..904a81de4 100644 --- a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java +++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java @@ -22,7 +22,7 @@ import android.graphics.drawable.Drawable; import com.android.inputmethod.keyboard.internal.KeySpecParser; import com.android.inputmethod.keyboard.internal.KeyboardIconsSet; import com.android.inputmethod.latin.R; -import com.android.inputmethod.latin.Utils; +import com.android.inputmethod.latin.StringUtils; public class MoreKeysKeyboard extends Keyboard { private final int mDefaultKeyCoordX; @@ -301,7 +301,7 @@ public class MoreKeysKeyboard extends Keyboard { for (String moreKeySpec : parentKey.mMoreKeys) { final String label = KeySpecParser.getLabel(moreKeySpec); // If the label is single letter, minKeyWidth is enough to hold the label. - if (label != null && Utils.codePointCount(label) > 1) { + if (label != null && StringUtils.codePointCount(label) > 1) { if (paint == null) { paint = new Paint(); paint.setAntiAlias(true); diff --git a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java index f96f71e8a..582509324 100644 --- a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java +++ b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java @@ -19,7 +19,7 @@ package com.android.inputmethod.keyboard; import android.graphics.Rect; import com.android.inputmethod.keyboard.Keyboard.Params.TouchPositionCorrection; -import com.android.inputmethod.latin.Utils; +import com.android.inputmethod.latin.JniUtils; import com.android.inputmethod.latin.spellcheck.SpellCheckerProximityInfo; import java.util.Arrays; @@ -81,7 +81,7 @@ public class ProximityInfo { private long mNativeProximityInfo; static { - Utils.loadNativeLibrary(); + JniUtils.loadNativeLibrary(); } private native long setProximityInfoNative(int maxProximityCharsSize, int displayWidth, diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java index e3fea3dce..0aba813b2 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java @@ -22,7 +22,7 @@ import android.text.TextUtils; import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.R; -import com.android.inputmethod.latin.Utils; +import com.android.inputmethod.latin.StringUtils; import java.util.ArrayList; import java.util.Arrays; @@ -150,7 +150,7 @@ public class KeySpecParser { } final String outputText = getOutputTextInternal(moreKeySpec); if (outputText != null) { - if (Utils.codePointCount(outputText) == 1) { + if (StringUtils.codePointCount(outputText) == 1) { // If output text is one code point, it should be treated as a code. // See {@link #getCode(Resources, String)}. return null; @@ -165,7 +165,7 @@ public class KeySpecParser { throw new KeySpecParserError("Empty label: " + moreKeySpec); } // Code is automatically generated for one letter label. See {@link getCode()}. - return (Utils.codePointCount(label) == 1) ? null : label; + return (StringUtils.codePointCount(label) == 1) ? null : label; } public static int getCode(Resources res, String moreKeySpec) { @@ -184,14 +184,14 @@ public class KeySpecParser { if (outputText != null) { // If output text is one code point, it should be treated as a code. // See {@link #getOutputText(String)}. - if (Utils.codePointCount(outputText) == 1) { + if (StringUtils.codePointCount(outputText) == 1) { return outputText.codePointAt(0); } return Keyboard.CODE_OUTPUT_TEXT; } final String label = getLabel(moreKeySpec); // Code is automatically generated for one letter label. - if (Utils.codePointCount(label) == 1) { + if (StringUtils.codePointCount(label) == 1) { return label.codePointAt(0); } return Keyboard.CODE_OUTPUT_TEXT; @@ -393,7 +393,7 @@ public class KeySpecParser { if (size == 0) { return null; } - if (Utils.codePointCount(text) == 1) { + if (StringUtils.codePointCount(text) == 1) { return text.codePointAt(0) == COMMA ? null : new String[] { text }; } diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java index 90ced6028..31ff4e7b4 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java @@ -104,7 +104,7 @@ public class BinaryDictionary extends Dictionary { } static { - Utils.loadNativeLibrary(); + JniUtils.loadNativeLibrary(); } private native long openNative(String sourceDir, long dictOffset, long dictSize, diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java index 1607f86a8..7a81f7bd5 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java @@ -164,7 +164,7 @@ public class DictionaryFactory { final Resources res = context.getResources(); final Locale saveLocale = LocaleUtils.setSystemLocale(res, locale); - final int resourceId = Utils.getMainDictionaryResourceId(res); + final int resourceId = getMainDictionaryResourceId(res); final AssetFileDescriptor afd = res.openRawResourceFd(resourceId); final boolean hasDictionary = isFullDictionary(afd); try { @@ -182,7 +182,7 @@ public class DictionaryFactory { final Resources res = context.getResources(); final Locale saveLocale = LocaleUtils.setSystemLocale(res, locale); - final int resourceId = Utils.getMainDictionaryResourceId(res); + final int resourceId = getMainDictionaryResourceId(res); final AssetFileDescriptor afd = res.openRawResourceFd(resourceId); final Long size = (afd != null && afd.getLength() > PLACEHOLDER_LENGTH) ? afd.getLength() @@ -209,4 +209,14 @@ public class DictionaryFactory { protected static boolean isFullDictionary(final AssetFileDescriptor afd) { return (afd != null && afd.getLength() > PLACEHOLDER_LENGTH); } + + /** + * Returns a main dictionary resource id + * @return main dictionary resource id + */ + public static int getMainDictionaryResourceId(Resources res) { + final String MAIN_DIC_NAME = "main"; + String packageName = LatinIME.class.getPackage().getName(); + return res.getIdentifier(MAIN_DIC_NAME, "raw", packageName); + } } diff --git a/java/src/com/android/inputmethod/latin/JniUtils.java b/java/src/com/android/inputmethod/latin/JniUtils.java new file mode 100644 index 000000000..4808b867a --- /dev/null +++ b/java/src/com/android/inputmethod/latin/JniUtils.java @@ -0,0 +1,41 @@ +/* + * 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; + +import android.util.Log; + +import com.android.inputmethod.latin.define.JniLibName; + +public class JniUtils { + private static final String TAG = JniUtils.class.getSimpleName(); + + private JniUtils() { + // This utility class is not publicly instantiable. + } + + public static void loadNativeLibrary() { + try { + System.loadLibrary(JniLibName.JNI_LIB_NAME); + } catch (UnsatisfiedLinkError ule) { + Log.e(TAG, "Could not load native library " + JniLibName.JNI_LIB_NAME); + if (LatinImeLogger.sDBG) { + throw new RuntimeException( + "Could not load native library " + JniLibName.JNI_LIB_NAME); + } + } + } +} diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 1858db949..c16a34fac 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -44,8 +44,8 @@ import android.view.HapticFeedbackConstants; import android.view.KeyEvent; import android.view.View; import android.view.ViewGroup; -import android.view.ViewParent; import android.view.ViewGroup.LayoutParams; +import android.view.ViewParent; import android.view.inputmethod.CompletionInfo; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.ExtractedText; @@ -576,7 +576,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar oldContactsDictionary = null; } - int mainDicResId = Utils.getMainDictionaryResourceId(res); + int mainDicResId = DictionaryFactory.getMainDictionaryResourceId(res); mSuggest = new Suggest(this, mainDicResId, keyboardLocale); if (mSettingsValues.mAutoCorrectEnabled) { mSuggest.setAutoCorrectionThreshold(mSettingsValues.mAutoCorrectionThreshold); @@ -636,7 +636,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar /* package private */ void resetSuggestMainDict() { final String localeStr = mSubtypeSwitcher.getInputLocaleStr(); final Locale keyboardLocale = LocaleUtils.constructLocaleFromString(localeStr); - int mainDicResId = Utils.getMainDictionaryResourceId(mResources); + int mainDicResId = DictionaryFactory.getMainDictionaryResourceId(mResources); mSuggest.resetMainDict(this, mainDicResId, keyboardLocale); } @@ -745,12 +745,12 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar + String.format("inputType=0x%08x imeOptions=0x%08x", editorInfo.inputType, editorInfo.imeOptions)); } - if (Utils.inPrivateImeOptions(null, IME_OPTION_NO_MICROPHONE_COMPAT, editorInfo)) { + if (StringUtils.inPrivateImeOptions(null, IME_OPTION_NO_MICROPHONE_COMPAT, editorInfo)) { Log.w(TAG, "Deprecated private IME option specified: " + editorInfo.privateImeOptions); Log.w(TAG, "Use " + getPackageName() + "." + IME_OPTION_NO_MICROPHONE + " instead"); } - if (Utils.inPrivateImeOptions(getPackageName(), IME_OPTION_FORCE_ASCII, editorInfo)) { + if (StringUtils.inPrivateImeOptions(getPackageName(), IME_OPTION_FORCE_ASCII, editorInfo)) { Log.w(TAG, "Deprecated private IME option specified: " + editorInfo.privateImeOptions); Log.w(TAG, "Use EditorInfo.IME_FLAG_FORCE_ASCII flag instead"); @@ -1207,7 +1207,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar if (ic == null) return false; final CharSequence lastThree = ic.getTextBeforeCursor(3, 0); if (lastThree != null && lastThree.length() == 3 - && Utils.canBeFollowedByPeriod(lastThree.charAt(0)) + && StringUtils.canBeFollowedByPeriod(lastThree.charAt(0)) && lastThree.charAt(1) == Keyboard.CODE_SPACE && lastThree.charAt(2) == Keyboard.CODE_SPACE && mHandler.isAcceptingDoubleSpaces()) { @@ -1247,7 +1247,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar if (isShowingOptionDialog()) return; if (InputMethodServiceCompatWrapper.CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED) { showSubtypeSelectorAndSettings(); - } else if (Utils.hasMultipleEnabledIMEsOrSubtypes(false /* exclude aux subtypes */)) { + } else if (SubtypeUtils.hasMultipleEnabledIMEsOrSubtypes( + false /* exclude aux subtypes */)) { showOptionsMenu(); } else { launchSettings(); @@ -1263,7 +1264,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar if (isShowingOptionDialog()) return false; switch (requestCode) { case CODE_SHOW_INPUT_METHOD_PICKER: - if (Utils.hasMultipleEnabledIMEsOrSubtypes(true /* include aux subtypes */)) { + if (SubtypeUtils.hasMultipleEnabledIMEsOrSubtypes(true /* include aux subtypes */)) { mImm.showInputMethodPicker(); return true; } @@ -1295,7 +1296,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar final IBinder token = getWindow().getWindow().getAttributes().token; if (mShouldSwitchToLastSubtype) { final InputMethodSubtypeCompatWrapper lastSubtype = mImm.getLastInputMethodSubtype(); - final boolean lastSubtypeBelongsToThisIme = Utils.checkIfSubtypeBelongsToThisIme( + final boolean lastSubtypeBelongsToThisIme = SubtypeUtils.checkIfSubtypeBelongsToThisIme( this, lastSubtype); if ((includesOtherImes || lastSubtypeBelongsToThisIme) && mImm.switchToLastInputMethod(token)) { @@ -1884,7 +1885,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar builder.addTypedWordAndPreviousSuggestions(typedWord, previousSuggestions); } } - if (Utils.shouldBlockAutoCorrectionBySafetyNet(builder, mSuggest)) { + if (Suggest.shouldBlockAutoCorrectionBySafetyNet(builder, mSuggest)) { builder.setShouldBlockAutoCorrectionBySafetyNet(); } showSuggestions(builder.build(), typedWord); @@ -2486,7 +2487,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar switch (position) { case 0: Intent intent = CompatUtils.getInputLanguageSelectionIntent( - Utils.getInputMethodId(getPackageName()), + SubtypeUtils.getInputMethodId(getPackageName()), Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED | Intent.FLAG_ACTIVITY_CLEAR_TOP); diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java index 305cef22d..72391f31e 100644 --- a/java/src/com/android/inputmethod/latin/Settings.java +++ b/java/src/com/android/inputmethod/latin/Settings.java @@ -343,7 +343,7 @@ public class Settings extends InputMethodSettingsActivity @Override public boolean onPreferenceClick(Preference pref) { if (pref == mInputLanguageSelection) { - final String imeId = Utils.getInputMethodId( + final String imeId = SubtypeUtils.getInputMethodId( getActivityInternal().getApplicationInfo().packageName); startActivity(CompatUtils.getInputLanguageSelectionIntent(imeId, 0)); return true; diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java index 69e45f619..abd1dc692 100644 --- a/java/src/com/android/inputmethod/latin/SettingsValues.java +++ b/java/src/com/android/inputmethod/latin/SettingsValues.java @@ -326,9 +326,9 @@ public class SettingsValues { return false; } if (mIncludesOtherImesInLanguageSwitchList) { - return Utils.hasMultipleEnabledIMEsOrSubtypes(/* include aux subtypes */false); + return SubtypeUtils.hasMultipleEnabledIMEsOrSubtypes(/* include aux subtypes */false); } else { - return Utils.hasMultipleEnabledSubtypesInThisIme( + return SubtypeUtils.hasMultipleEnabledSubtypesInThisIme( context, /* include aux subtypes */false); } } diff --git a/java/src/com/android/inputmethod/latin/StringUtils.java b/java/src/com/android/inputmethod/latin/StringUtils.java new file mode 100644 index 000000000..81c3b4edf --- /dev/null +++ b/java/src/com/android/inputmethod/latin/StringUtils.java @@ -0,0 +1,198 @@ +/* + * 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; + +import android.text.TextUtils; +import android.view.inputmethod.EditorInfo; + +import com.android.inputmethod.keyboard.Keyboard; + +import java.util.ArrayList; +import java.util.Locale; + +public class StringUtils { + private StringUtils() { + // This utility class is not publicly instantiable. + } + + public static boolean canBeFollowedByPeriod(final int codePoint) { + // TODO: Check again whether there really ain't a better way to check this. + // TODO: This should probably be language-dependant... + return Character.isLetterOrDigit(codePoint) + || codePoint == Keyboard.CODE_SINGLE_QUOTE + || codePoint == Keyboard.CODE_DOUBLE_QUOTE + || codePoint == Keyboard.CODE_CLOSING_PARENTHESIS + || codePoint == Keyboard.CODE_CLOSING_SQUARE_BRACKET + || codePoint == Keyboard.CODE_CLOSING_CURLY_BRACKET + || codePoint == Keyboard.CODE_CLOSING_ANGLE_BRACKET; + } + + public static int codePointCount(String text) { + if (TextUtils.isEmpty(text)) return 0; + return text.codePointCount(0, text.length()); + } + + public static boolean containsInCsv(String key, String csv) { + if (csv == null) + return false; + for (String option : csv.split(",")) { + if (option.equals(key)) + return true; + } + return false; + } + + public static boolean inPrivateImeOptions(String packageName, String key, + EditorInfo editorInfo) { + if (editorInfo == null) + return false; + return containsInCsv(packageName != null ? packageName + "." + key : key, + editorInfo.privateImeOptions); + } + + /** + * Returns true if a and b are equal ignoring the case of the character. + * @param a first character to check + * @param b second character to check + * @return {@code true} if a and b are equal, {@code false} otherwise. + */ + public static boolean equalsIgnoreCase(char a, char b) { + // Some language, such as Turkish, need testing both cases. + return a == b + || Character.toLowerCase(a) == Character.toLowerCase(b) + || Character.toUpperCase(a) == Character.toUpperCase(b); + } + + /** + * Returns true if a and b are equal ignoring the case of the characters, including if they are + * both null. + * @param a first CharSequence to check + * @param b second CharSequence to check + * @return {@code true} if a and b are equal, {@code false} otherwise. + */ + public static boolean equalsIgnoreCase(CharSequence a, CharSequence b) { + if (a == b) + return true; // including both a and b are null. + if (a == null || b == null) + return false; + final int length = a.length(); + if (length != b.length()) + return false; + for (int i = 0; i < length; i++) { + if (!equalsIgnoreCase(a.charAt(i), b.charAt(i))) + return false; + } + return true; + } + + /** + * Returns true if a and b are equal ignoring the case of the characters, including if a is null + * and b is zero length. + * @param a CharSequence to check + * @param b character array to check + * @param offset start offset of array b + * @param length length of characters in array b + * @return {@code true} if a and b are equal, {@code false} otherwise. + * @throws IndexOutOfBoundsException + * if {@code offset < 0 || length < 0 || offset + length > data.length}. + * @throws NullPointerException if {@code b == null}. + */ + public static boolean equalsIgnoreCase(CharSequence a, char[] b, int offset, int length) { + if (offset < 0 || length < 0 || length > b.length - offset) + throw new IndexOutOfBoundsException("array.length=" + b.length + " offset=" + offset + + " length=" + length); + if (a == null) + return length == 0; // including a is null and b is zero length. + if (a.length() != length) + return false; + for (int i = 0; i < length; i++) { + if (!equalsIgnoreCase(a.charAt(i), b[offset + i])) + return false; + } + return true; + } + + /** + * Remove duplicates from an array of strings. + * + * This method will always keep the first occurence of all strings at their position + * in the array, removing the subsequent ones. + */ + public static void removeDupes(final ArrayList suggestions) { + if (suggestions.size() < 2) return; + int i = 1; + // Don't cache suggestions.size(), since we may be removing items + while (i < suggestions.size()) { + final CharSequence cur = suggestions.get(i); + // Compare each suggestion with each previous suggestion + for (int j = 0; j < i; j++) { + CharSequence previous = suggestions.get(j); + if (TextUtils.equals(cur, previous)) { + removeFromSuggestions(suggestions, i); + i--; + break; + } + } + i++; + } + } + + private static void removeFromSuggestions(final ArrayList suggestions, + final int index) { + final CharSequence garbage = suggestions.remove(index); + if (garbage instanceof StringBuilder) { + StringBuilderPool.recycle((StringBuilder)garbage); + } + } + + public static String getFullDisplayName(Locale locale, boolean returnsNameInThisLocale) { + if (returnsNameInThisLocale) { + return toTitleCase(SubtypeLocale.getFullDisplayName(locale), locale); + } else { + return toTitleCase(locale.getDisplayName(), locale); + } + } + + public static String getDisplayLanguage(Locale locale) { + return toTitleCase(SubtypeLocale.getFullDisplayName(locale), locale); + } + + public static String getMiddleDisplayLanguage(Locale locale) { + return toTitleCase((LocaleUtils.constructLocaleFromString( + locale.getLanguage()).getDisplayLanguage(locale)), locale); + } + + public static String getShortDisplayLanguage(Locale locale) { + return toTitleCase(locale.getLanguage(), locale); + } + + public static String toTitleCase(String s, Locale locale) { + if (s.length() <= 1) { + // TODO: is this really correct? Shouldn't this be s.toUpperCase()? + return s; + } + // TODO: fix the bugs below + // - This does not work for Greek, because it returns upper case instead of title case. + // - It does not work for Serbian, because it fails to account for the "lj" character, + // which should be "Lj" in title case and "LJ" in upper case. + // - It does not work for Dutch, because it fails to account for the "ij" digraph, which + // are two different characters but both should be capitalized as "IJ" as if they were + // a single letter. + // - It also does not work with unicode surrogate code points. + return s.toUpperCase(locale).charAt(0) + s.substring(1); + } +} diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java index f5778167a..ffbbf9bb8 100644 --- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java +++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java @@ -512,7 +512,7 @@ public class SubtypeSwitcher { } public String getInputLanguageName() { - return Utils.getDisplayLanguage(getInputLocale()); + return StringUtils.getDisplayLanguage(getInputLocale()); } ///////////////////////////// diff --git a/java/src/com/android/inputmethod/latin/SubtypeUtils.java b/java/src/com/android/inputmethod/latin/SubtypeUtils.java new file mode 100644 index 000000000..cb2bcf43f --- /dev/null +++ b/java/src/com/android/inputmethod/latin/SubtypeUtils.java @@ -0,0 +1,135 @@ +/* + * 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; + +import android.content.Context; + +import com.android.inputmethod.compat.InputMethodInfoCompatWrapper; +import com.android.inputmethod.compat.InputMethodManagerCompatWrapper; +import com.android.inputmethod.compat.InputMethodSubtypeCompatWrapper; + +import java.util.Collections; +import java.util.List; + +public class SubtypeUtils { + private SubtypeUtils() { + // This utility class is not publicly instantiable. + } + + // TODO: Cache my InputMethodInfo and/or InputMethodSubtype list. + public static boolean checkIfSubtypeBelongsToThisIme(Context context, + InputMethodSubtypeCompatWrapper ims) { + final InputMethodManagerCompatWrapper imm = InputMethodManagerCompatWrapper.getInstance(); + if (imm == null) return false; + + final InputMethodInfoCompatWrapper myImi = getInputMethodInfo(context.getPackageName()); + final List subtypes = + imm.getEnabledInputMethodSubtypeList(myImi, true); + for (final InputMethodSubtypeCompatWrapper subtype : subtypes) { + if (subtype.equals(ims)) { + return true; + } + } + return false; + } + + public static boolean hasMultipleEnabledIMEsOrSubtypes( + final boolean shouldIncludeAuxiliarySubtypes) { + final InputMethodManagerCompatWrapper imm = InputMethodManagerCompatWrapper.getInstance(); + if (imm == null) return false; + + final List enabledImis = imm.getEnabledInputMethodList(); + return hasMultipleEnabledSubtypes(shouldIncludeAuxiliarySubtypes, enabledImis); + } + + public static boolean hasMultipleEnabledSubtypesInThisIme(Context context, + final boolean shouldIncludeAuxiliarySubtypes) { + final InputMethodInfoCompatWrapper myImi = getInputMethodInfo(context.getPackageName()); + final List imiList = Collections.singletonList(myImi); + return hasMultipleEnabledSubtypes(shouldIncludeAuxiliarySubtypes, imiList); + } + + private static boolean hasMultipleEnabledSubtypes(final boolean shouldIncludeAuxiliarySubtypes, + List imiList) { + final InputMethodManagerCompatWrapper imm = InputMethodManagerCompatWrapper.getInstance(); + if (imm == null) return false; + + // Number of the filtered IMEs + int filteredImisCount = 0; + + for (InputMethodInfoCompatWrapper imi : imiList) { + // We can return true immediately after we find two or more filtered IMEs. + if (filteredImisCount > 1) return true; + final List subtypes = + imm.getEnabledInputMethodSubtypeList(imi, true); + // IMEs that have no subtypes should be counted. + if (subtypes.isEmpty()) { + ++filteredImisCount; + continue; + } + + int auxCount = 0; + for (InputMethodSubtypeCompatWrapper subtype : subtypes) { + if (subtype.isAuxiliary()) { + ++auxCount; + } + } + final int nonAuxCount = subtypes.size() - auxCount; + + // IMEs that have one or more non-auxiliary subtypes should be counted. + // If shouldIncludeAuxiliarySubtypes is true, IMEs that have two or more auxiliary + // subtypes should be counted as well. + if (nonAuxCount > 0 || (shouldIncludeAuxiliarySubtypes && auxCount > 1)) { + ++filteredImisCount; + continue; + } + } + + if (filteredImisCount > 1) { + return true; + } + final List subtypes = + imm.getEnabledInputMethodSubtypeList(null, true); + int keyboardCount = 0; + // imm.getEnabledInputMethodSubtypeList(null, true) will return the current IME's + // both explicitly and implicitly enabled input method subtype. + // (The current IME should be LatinIME.) + for (InputMethodSubtypeCompatWrapper subtype : subtypes) { + if (SubtypeSwitcher.KEYBOARD_MODE.equals(subtype.getMode())) { + ++keyboardCount; + } + } + return keyboardCount > 1; + } + + public static String getInputMethodId(String packageName) { + return getInputMethodInfo(packageName).getId(); + } + + public static InputMethodInfoCompatWrapper getInputMethodInfo(String packageName) { + final InputMethodManagerCompatWrapper imm = InputMethodManagerCompatWrapper.getInstance(); + if (imm == null) { + throw new RuntimeException("Input method manager not found"); + } + + for (final InputMethodInfoCompatWrapper imi : imm.getEnabledInputMethodList()) { + if (imi.getPackageName().equals(packageName)) + return imi; + } + throw new RuntimeException("Can not find input method id for " + packageName); + } +} diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index 298ead665..671fb905d 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -108,6 +108,8 @@ public class Suggest implements Dictionary.WordCallback { private boolean mIsAllUpperCase; private int mTrailingSingleQuotesCount; + private static final int MINIMUM_SAFETY_NET_CHAR_LENGTH = 4; + public Suggest(final Context context, final int dictionaryResId, final Locale locale) { initAsynchronously(context, dictionaryResId, locale); } @@ -383,7 +385,7 @@ public class Suggest implements Dictionary.WordCallback { if (typedWord != null) { mSuggestions.add(0, typedWord.toString()); } - Utils.removeDupes(mSuggestions); + StringUtils.removeDupes(mSuggestions); if (DBG) { double normalizedScore = mAutoCorrection.getNormalizedScore(); @@ -434,7 +436,7 @@ public class Suggest implements Dictionary.WordCallback { int pos = 0; // Check if it's the same word, only caps are different - if (Utils.equalsIgnoreCase(mConsideredWord, word, offset, length)) { + if (StringUtils.equalsIgnoreCase(mConsideredWord, word, offset, length)) { // TODO: remove this surrounding if clause and move this logic to // getSuggestedWordBuilder. if (suggestions.size() > 0) { @@ -443,7 +445,7 @@ public class Suggest implements Dictionary.WordCallback { // frequency to determine the insertion position. This does not ensure strictly // correct ordering, but ensures the top score is on top which is enough for // removing duplicates correctly. - if (Utils.equalsIgnoreCase(currentHighestWord, word, offset, length) + if (StringUtils.equalsIgnoreCase(currentHighestWord, word, offset, length) && score <= sortedScores[0]) { pos = 1; } @@ -558,4 +560,46 @@ public class Suggest implements Dictionary.WordCallback { } mMainDict = null; } + + // TODO: Resolve the inconsistencies between the native auto correction algorithms and + // this safety net + public static boolean shouldBlockAutoCorrectionBySafetyNet( + SuggestedWords.Builder suggestedWordsBuilder, Suggest suggest) { + // Safety net for auto correction. + // Actually if we hit this safety net, it's actually a bug. + if (suggestedWordsBuilder.size() <= 1 || suggestedWordsBuilder.isTypedWordValid()) { + return false; + } + // If user selected aggressive auto correction mode, there is no need to use the safety + // net. + if (suggest.isAggressiveAutoCorrectionMode()) { + return false; + } + final CharSequence typedWord = suggestedWordsBuilder.getWord(0); + // If the length of typed word is less than MINIMUM_SAFETY_NET_CHAR_LENGTH, + // we should not use net because relatively edit distance can be big. + if (typedWord.length() < Suggest.MINIMUM_SAFETY_NET_CHAR_LENGTH) { + return false; + } + final CharSequence suggestionWord = suggestedWordsBuilder.getWord(1); + final int typedWordLength = typedWord.length(); + final int maxEditDistanceOfNativeDictionary = + (typedWordLength < 5 ? 2 : typedWordLength / 2) + 1; + final int distance = BinaryDictionary.editDistance( + typedWord.toString(), suggestionWord.toString()); + if (DBG) { + Log.d(TAG, "Autocorrected edit distance = " + distance + + ", " + maxEditDistanceOfNativeDictionary); + } + if (distance > maxEditDistanceOfNativeDictionary) { + if (DBG) { + Log.e(TAG, "Safety net: before = " + typedWord + ", after = " + suggestionWord); + Log.e(TAG, "(Error) The edit distance of this correction exceeds limit. " + + "Turning off auto-correction."); + } + return true; + } else { + return false; + } + } } diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java index a8679e07a..f8dd5ae42 100644 --- a/java/src/com/android/inputmethod/latin/Utils.java +++ b/java/src/com/android/inputmethod/latin/Utils.java @@ -19,7 +19,6 @@ package com.android.inputmethod.latin; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; -import android.content.res.Resources; import android.inputmethodservice.InputMethodService; import android.net.Uri; import android.os.AsyncTask; @@ -27,19 +26,9 @@ import android.os.Environment; import android.os.Handler; import android.os.HandlerThread; import android.os.Process; -import android.text.InputType; import android.text.TextUtils; import android.text.format.DateUtils; import android.util.Log; -import android.view.inputmethod.EditorInfo; - -import com.android.inputmethod.compat.InputMethodInfoCompatWrapper; -import com.android.inputmethod.compat.InputMethodManagerCompatWrapper; -import com.android.inputmethod.compat.InputMethodSubtypeCompatWrapper; -import com.android.inputmethod.compat.InputTypeCompatUtils; -import com.android.inputmethod.keyboard.Keyboard; -import com.android.inputmethod.keyboard.KeyboardId; -import com.android.inputmethod.latin.define.JniLibName; import java.io.BufferedReader; import java.io.File; @@ -51,20 +40,11 @@ import java.io.IOException; import java.io.PrintWriter; import java.nio.channels.FileChannel; import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Collections; import java.util.Date; -import java.util.List; -import java.util.Locale; public class Utils { - private static final String TAG = Utils.class.getSimpleName(); - private static final int MINIMUM_SAFETY_NET_CHAR_LENGTH = 4; - private static boolean DBG = LatinImeLogger.sDBG; - private static boolean DBG_EDIT_DISTANCE = false; - private Utils() { - // Intentional empty constructor for utility class. + // This utility class is not publicly instantiable. } /** @@ -118,166 +98,6 @@ public class Utils { } } - // TODO: Move InputMethodSubtype related utility methods to its own utility class. - // TODO: Cache my InputMethodInfo and/or InputMethodSubtype list. - public static boolean checkIfSubtypeBelongsToThisIme(Context context, - InputMethodSubtypeCompatWrapper ims) { - final InputMethodManagerCompatWrapper imm = InputMethodManagerCompatWrapper.getInstance(); - if (imm == null) return false; - - final InputMethodInfoCompatWrapper myImi = Utils.getInputMethodInfo( - context.getPackageName()); - final List subtypes = - imm.getEnabledInputMethodSubtypeList(myImi, true); - for (final InputMethodSubtypeCompatWrapper subtype : subtypes) { - if (subtype.equals(ims)) { - return true; - } - } - return false; - } - - public static boolean hasMultipleEnabledIMEsOrSubtypes( - final boolean shouldIncludeAuxiliarySubtypes) { - final InputMethodManagerCompatWrapper imm = InputMethodManagerCompatWrapper.getInstance(); - if (imm == null) return false; - - final List enabledImis = imm.getEnabledInputMethodList(); - return hasMultipleEnabledSubtypes(shouldIncludeAuxiliarySubtypes, enabledImis); - } - - public static boolean hasMultipleEnabledSubtypesInThisIme(Context context, - final boolean shouldIncludeAuxiliarySubtypes) { - final InputMethodInfoCompatWrapper myImi = Utils.getInputMethodInfo( - context.getPackageName()); - final List imiList = Collections.singletonList(myImi); - return Utils.hasMultipleEnabledSubtypes(shouldIncludeAuxiliarySubtypes, imiList); - } - - private static boolean hasMultipleEnabledSubtypes(final boolean shouldIncludeAuxiliarySubtypes, - List imiList) { - final InputMethodManagerCompatWrapper imm = InputMethodManagerCompatWrapper.getInstance(); - if (imm == null) return false; - - // Number of the filtered IMEs - int filteredImisCount = 0; - - for (InputMethodInfoCompatWrapper imi : imiList) { - // We can return true immediately after we find two or more filtered IMEs. - if (filteredImisCount > 1) return true; - final List subtypes = - imm.getEnabledInputMethodSubtypeList(imi, true); - // IMEs that have no subtypes should be counted. - if (subtypes.isEmpty()) { - ++filteredImisCount; - continue; - } - - int auxCount = 0; - for (InputMethodSubtypeCompatWrapper subtype : subtypes) { - if (subtype.isAuxiliary()) { - ++auxCount; - } - } - final int nonAuxCount = subtypes.size() - auxCount; - - // IMEs that have one or more non-auxiliary subtypes should be counted. - // If shouldIncludeAuxiliarySubtypes is true, IMEs that have two or more auxiliary - // subtypes should be counted as well. - if (nonAuxCount > 0 || (shouldIncludeAuxiliarySubtypes && auxCount > 1)) { - ++filteredImisCount; - continue; - } - } - - if (filteredImisCount > 1) { - return true; - } - final List subtypes = - imm.getEnabledInputMethodSubtypeList(null, true); - int keyboardCount = 0; - // imm.getEnabledInputMethodSubtypeList(null, true) will return the current IME's - // both explicitly and implicitly enabled input method subtype. - // (The current IME should be LatinIME.) - for (InputMethodSubtypeCompatWrapper subtype : subtypes) { - if (SubtypeSwitcher.KEYBOARD_MODE.equals(subtype.getMode())) { - ++keyboardCount; - } - } - return keyboardCount > 1; - } - - public static String getInputMethodId(String packageName) { - return getInputMethodInfo(packageName).getId(); - } - - public static InputMethodInfoCompatWrapper getInputMethodInfo(String packageName) { - final InputMethodManagerCompatWrapper imm = InputMethodManagerCompatWrapper.getInstance(); - if (imm == null) { - throw new RuntimeException("Input method manager not found"); - } - - for (final InputMethodInfoCompatWrapper imi : imm.getEnabledInputMethodList()) { - if (imi.getPackageName().equals(packageName)) - return imi; - } - throw new RuntimeException("Can not find input method id for " + packageName); - } - - // TODO: Resolve the inconsistencies between the native auto correction algorithms and - // this safety net - public static boolean shouldBlockAutoCorrectionBySafetyNet( - SuggestedWords.Builder suggestedWordsBuilder, Suggest suggest) { - // Safety net for auto correction. - // Actually if we hit this safety net, it's actually a bug. - if (suggestedWordsBuilder.size() <= 1 || suggestedWordsBuilder.isTypedWordValid()) { - return false; - } - // If user selected aggressive auto correction mode, there is no need to use the safety - // net. - if (suggest.isAggressiveAutoCorrectionMode()) { - return false; - } - final CharSequence typedWord = suggestedWordsBuilder.getWord(0); - // If the length of typed word is less than MINIMUM_SAFETY_NET_CHAR_LENGTH, - // we should not use net because relatively edit distance can be big. - if (typedWord.length() < MINIMUM_SAFETY_NET_CHAR_LENGTH) { - return false; - } - final CharSequence suggestionWord = suggestedWordsBuilder.getWord(1); - final int typedWordLength = typedWord.length(); - final int maxEditDistanceOfNativeDictionary = - (typedWordLength < 5 ? 2 : typedWordLength / 2) + 1; - final int distance = BinaryDictionary.editDistance( - typedWord.toString(), suggestionWord.toString()); - if (DBG) { - Log.d(TAG, "Autocorrected edit distance = " + distance - + ", " + maxEditDistanceOfNativeDictionary); - } - if (distance > maxEditDistanceOfNativeDictionary) { - if (DBG) { - Log.e(TAG, "Safety net: before = " + typedWord + ", after = " + suggestionWord); - Log.e(TAG, "(Error) The edit distance of this correction exceeds limit. " - + "Turning off auto-correction."); - } - return true; - } else { - return false; - } - } - - public static boolean canBeFollowedByPeriod(final int codePoint) { - // TODO: Check again whether there really ain't a better way to check this. - // TODO: This should probably be language-dependant... - return Character.isLetterOrDigit(codePoint) - || codePoint == Keyboard.CODE_SINGLE_QUOTE - || codePoint == Keyboard.CODE_DOUBLE_QUOTE - || codePoint == Keyboard.CODE_CLOSING_PARENTHESIS - || codePoint == Keyboard.CODE_CLOSING_SQUARE_BRACKET - || codePoint == Keyboard.CODE_CLOSING_CURLY_BRACKET - || codePoint == Keyboard.CODE_CLOSING_ANGLE_BRACKET; - } - /* package */ static class RingCharBuffer { private static RingCharBuffer sRingCharBuffer = new RingCharBuffer(); private static final char PLACEHOLDER_DELIMITER_CHAR = '\uFFFC'; @@ -600,147 +420,6 @@ public class Utils { } } - // TODO: Move this method to KeyboardSet class. - public static int getKeyboardMode(EditorInfo editorInfo) { - if (editorInfo == null) - return KeyboardId.MODE_TEXT; - - final int inputType = editorInfo.inputType; - final int variation = inputType & InputType.TYPE_MASK_VARIATION; - - switch (inputType & InputType.TYPE_MASK_CLASS) { - case InputType.TYPE_CLASS_NUMBER: - return KeyboardId.MODE_NUMBER; - case InputType.TYPE_CLASS_DATETIME: - switch (variation) { - case InputType.TYPE_DATETIME_VARIATION_DATE: - return KeyboardId.MODE_DATE; - case InputType.TYPE_DATETIME_VARIATION_TIME: - return KeyboardId.MODE_TIME; - default: // InputType.TYPE_DATETIME_VARIATION_NORMAL - return KeyboardId.MODE_DATETIME; - } - case InputType.TYPE_CLASS_PHONE: - return KeyboardId.MODE_PHONE; - case InputType.TYPE_CLASS_TEXT: - if (InputTypeCompatUtils.isEmailVariation(variation)) { - return KeyboardId.MODE_EMAIL; - } else if (variation == InputType.TYPE_TEXT_VARIATION_URI) { - return KeyboardId.MODE_URL; - } else if (variation == InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE) { - return KeyboardId.MODE_IM; - } else if (variation == InputType.TYPE_TEXT_VARIATION_FILTER) { - return KeyboardId.MODE_TEXT; - } else { - return KeyboardId.MODE_TEXT; - } - default: - return KeyboardId.MODE_TEXT; - } - } - - public static boolean containsInCsv(String key, String csv) { - if (csv == null) - return false; - for (String option : csv.split(",")) { - if (option.equals(key)) - return true; - } - return false; - } - - public static boolean inPrivateImeOptions(String packageName, String key, - EditorInfo editorInfo) { - if (editorInfo == null) - return false; - return containsInCsv(packageName != null ? packageName + "." + key : key, - editorInfo.privateImeOptions); - } - - /** - * Returns a main dictionary resource id - * @return main dictionary resource id - */ - public static int getMainDictionaryResourceId(Resources res) { - final String MAIN_DIC_NAME = "main"; - String packageName = LatinIME.class.getPackage().getName(); - return res.getIdentifier(MAIN_DIC_NAME, "raw", packageName); - } - - public static void loadNativeLibrary() { - try { - System.loadLibrary(JniLibName.JNI_LIB_NAME); - } catch (UnsatisfiedLinkError ule) { - Log.e(TAG, "Could not load native library " + JniLibName.JNI_LIB_NAME); - if (LatinImeLogger.sDBG) { - throw new RuntimeException( - "Could not load native library " + JniLibName.JNI_LIB_NAME); - } - } - } - - /** - * Returns true if a and b are equal ignoring the case of the character. - * @param a first character to check - * @param b second character to check - * @return {@code true} if a and b are equal, {@code false} otherwise. - */ - public static boolean equalsIgnoreCase(char a, char b) { - // Some language, such as Turkish, need testing both cases. - return a == b - || Character.toLowerCase(a) == Character.toLowerCase(b) - || Character.toUpperCase(a) == Character.toUpperCase(b); - } - - /** - * Returns true if a and b are equal ignoring the case of the characters, including if they are - * both null. - * @param a first CharSequence to check - * @param b second CharSequence to check - * @return {@code true} if a and b are equal, {@code false} otherwise. - */ - public static boolean equalsIgnoreCase(CharSequence a, CharSequence b) { - if (a == b) - return true; // including both a and b are null. - if (a == null || b == null) - return false; - final int length = a.length(); - if (length != b.length()) - return false; - for (int i = 0; i < length; i++) { - if (!equalsIgnoreCase(a.charAt(i), b.charAt(i))) - return false; - } - return true; - } - - /** - * Returns true if a and b are equal ignoring the case of the characters, including if a is null - * and b is zero length. - * @param a CharSequence to check - * @param b character array to check - * @param offset start offset of array b - * @param length length of characters in array b - * @return {@code true} if a and b are equal, {@code false} otherwise. - * @throws IndexOutOfBoundsException - * if {@code offset < 0 || length < 0 || offset + length > data.length}. - * @throws NullPointerException if {@code b == null}. - */ - public static boolean equalsIgnoreCase(CharSequence a, char[] b, int offset, int length) { - if (offset < 0 || length < 0 || length > b.length - offset) - throw new IndexOutOfBoundsException("array.length=" + b.length + " offset=" + offset - + " length=" + length); - if (a == null) - return length == 0; // including a is null and b is zero length. - if (a.length() != length) - return false; - for (int i = 0; i < length; i++) { - if (!equalsIgnoreCase(a.charAt(i), b[offset + i])) - return false; - } - return true; - } - public static float getDipScale(Context context) { final float scale = context.getResources().getDisplayMetrics().density; return scale; @@ -751,76 +430,6 @@ public class Utils { return (int) (dip * scale + 0.5); } - /** - * Remove duplicates from an array of strings. - * - * This method will always keep the first occurence of all strings at their position - * in the array, removing the subsequent ones. - */ - public static void removeDupes(final ArrayList suggestions) { - if (suggestions.size() < 2) return; - int i = 1; - // Don't cache suggestions.size(), since we may be removing items - while (i < suggestions.size()) { - final CharSequence cur = suggestions.get(i); - // Compare each suggestion with each previous suggestion - for (int j = 0; j < i; j++) { - CharSequence previous = suggestions.get(j); - if (TextUtils.equals(cur, previous)) { - removeFromSuggestions(suggestions, i); - i--; - break; - } - } - i++; - } - } - - private static void removeFromSuggestions(final ArrayList suggestions, - final int index) { - final CharSequence garbage = suggestions.remove(index); - if (garbage instanceof StringBuilder) { - StringBuilderPool.recycle((StringBuilder)garbage); - } - } - - public static String getFullDisplayName(Locale locale, boolean returnsNameInThisLocale) { - if (returnsNameInThisLocale) { - return toTitleCase(SubtypeLocale.getFullDisplayName(locale), locale); - } else { - return toTitleCase(locale.getDisplayName(), locale); - } - } - - public static String getDisplayLanguage(Locale locale) { - return toTitleCase(SubtypeLocale.getFullDisplayName(locale), locale); - } - - public static String getMiddleDisplayLanguage(Locale locale) { - return toTitleCase((LocaleUtils.constructLocaleFromString( - locale.getLanguage()).getDisplayLanguage(locale)), locale); - } - - public static String getShortDisplayLanguage(Locale locale) { - return toTitleCase(locale.getLanguage(), locale); - } - - public static String toTitleCase(String s, Locale locale) { - if (s.length() <= 1) { - // TODO: is this really correct? Shouldn't this be s.toUpperCase()? - return s; - } - // TODO: fix the bugs below - // - This does not work for Greek, because it returns upper case instead of title case. - // - It does not work for Serbian, because it fails to account for the "lj" character, - // which should be "Lj" in title case and "LJ" in upper case. - // - It does not work for Dutch, because it fails to account for the "ij" digraph, which - // are two different characters but both should be capitalized as "IJ" as if they were - // a single letter. - // - It also does not work with unicode surrogate code points. - return s.toUpperCase(locale).charAt(0) + s.substring(1); - } - public static class Stats { public static void onNonSeparator(final char code, final int x, final int y) { @@ -845,9 +454,4 @@ public class Utils { LatinImeLogger.logOnAutoCorrectionCancelled(); } } - - public static int codePointCount(String text) { - if (TextUtils.isEmpty(text)) return 0; - return text.codePointCount(0, text.length()); - } } diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java index 755c75b2e..35a5c0f52 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java @@ -37,9 +37,9 @@ import com.android.inputmethod.latin.DictionaryFactory; import com.android.inputmethod.latin.Flag; import com.android.inputmethod.latin.LocaleUtils; import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.StringUtils; import com.android.inputmethod.latin.SynchronouslyLoadedContactsDictionary; import com.android.inputmethod.latin.SynchronouslyLoadedUserDictionary; -import com.android.inputmethod.latin.Utils; import com.android.inputmethod.latin.WhitelistDictionary; import com.android.inputmethod.latin.WordComposer; @@ -47,11 +47,11 @@ import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.HashSet; import java.util.Iterator; import java.util.Locale; import java.util.Map; import java.util.TreeMap; -import java.util.HashSet; /** * Service for spell checking, using LatinIME's dictionaries and mechanisms. @@ -316,7 +316,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService } } Collections.reverse(mSuggestions); - Utils.removeDupes(mSuggestions); + StringUtils.removeDupes(mSuggestions); if (CAPITALIZE_ALL == capitalizeType) { for (int i = 0; i < mSuggestions.size(); ++i) { // get(i) returns a CharSequence which is actually a String so .toString() @@ -326,7 +326,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService } else if (CAPITALIZE_FIRST == capitalizeType) { for (int i = 0; i < mSuggestions.size(); ++i) { // Likewise - mSuggestions.set(i, Utils.toTitleCase(mSuggestions.get(i).toString(), + mSuggestions.set(i, StringUtils.toTitleCase(mSuggestions.get(i).toString(), locale)); } } @@ -396,7 +396,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService final ProximityInfo proximityInfo = ProximityInfo.createSpellCheckerProximityInfo( SpellCheckerProximityInfo.getProximityForScript(script)); final Resources resources = getResources(); - final int fallbackResourceId = Utils.getMainDictionaryResourceId(resources); + final int fallbackResourceId = DictionaryFactory.getMainDictionaryResourceId(resources); final DictionaryCollection dictionaryCollection = DictionaryFactory.createDictionaryFromManager(this, locale, fallbackResourceId, USE_FULL_EDIT_DISTANCE_FLAG_ARRAY); -- cgit v1.2.3-83-g751a From 660776e09b9a3b321074a94721d901a035ca1b9f Mon Sep 17 00:00:00 2001 From: Ken Wakasa Date: Sat, 17 Mar 2012 00:50:51 +0900 Subject: Small performance improvement by removing interface accesses. Change-Id: I6d91f3b086470b79306dbe2874db9748b9e0eb5f --- .../src/com/android/inputmethod/keyboard/KeyboardSet.java | 5 ++--- .../src/com/android/inputmethod/latin/AutoCorrection.java | 14 +++++++------- .../android/inputmethod/latin/BinaryDictionaryGetter.java | 5 ++--- .../android/inputmethod/latin/DictionaryCollection.java | 3 +-- .../com/android/inputmethod/latin/DictionaryFactory.java | 6 +++--- java/src/com/android/inputmethod/latin/LatinIME.java | 3 +-- .../src/com/android/inputmethod/latin/LatinImeLogger.java | 2 -- .../src/com/android/inputmethod/latin/SettingsValues.java | 2 -- java/src/com/android/inputmethod/latin/Suggest.java | 15 +++++++-------- .../src/com/android/inputmethod/latin/SuggestedWords.java | 12 +++++------- java/src/com/android/inputmethod/latin/XmlParseUtils.java | 4 ++++ .../inputmethod/latin/suggestions/SuggestionsView.java | 9 ++++----- 12 files changed, 36 insertions(+), 44 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/DictionaryFactory.java') diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSet.java b/java/src/com/android/inputmethod/keyboard/KeyboardSet.java index 680ff0d25..52096c843 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSet.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSet.java @@ -42,7 +42,6 @@ import java.io.IOException; import java.lang.ref.SoftReference; import java.util.HashMap; import java.util.Locale; -import java.util.Map; /** * This class represents a set of keyboards. Each of them represents a different keyboard @@ -75,7 +74,7 @@ public class KeyboardSet { } public static class KeysCache { - private final Map mMap; + private final HashMap mMap; public KeysCache() { mMap = new HashMap(); @@ -108,7 +107,7 @@ public class KeyboardSet { int mOrientation; int mWidth; // KeyboardSet element id to keyboard layout XML id map. - final Map mKeyboardSetElementIdToXmlIdMap = + final HashMap mKeyboardSetElementIdToXmlIdMap = new HashMap(); Params() {} } diff --git a/java/src/com/android/inputmethod/latin/AutoCorrection.java b/java/src/com/android/inputmethod/latin/AutoCorrection.java index 9c35f8f6f..ef88f9906 100644 --- a/java/src/com/android/inputmethod/latin/AutoCorrection.java +++ b/java/src/com/android/inputmethod/latin/AutoCorrection.java @@ -20,7 +20,7 @@ import android.text.TextUtils; import android.util.Log; import java.util.ArrayList; -import java.util.Map; +import java.util.HashMap; public class AutoCorrection { private static final boolean DBG = LatinImeLogger.sDBG; @@ -30,7 +30,7 @@ public class AutoCorrection { // Purely static class: can't instantiate. } - public static CharSequence computeAutoCorrectionWord(Map dictionaries, + public static CharSequence computeAutoCorrectionWord(HashMap dictionaries, WordComposer wordComposer, ArrayList suggestions, int[] sortedScores, CharSequence consideredWord, double autoCorrectionThreshold, CharSequence whitelistedWord) { @@ -47,7 +47,7 @@ public class AutoCorrection { } public static boolean isValidWord( - Map dictionaries, CharSequence word, boolean ignoreCase) { + HashMap dictionaries, CharSequence word, boolean ignoreCase) { if (TextUtils.isEmpty(word)) { return false; } @@ -72,7 +72,7 @@ public class AutoCorrection { } public static boolean allowsToBeAutoCorrected( - Map dictionaries, CharSequence word, boolean ignoreCase) { + HashMap dictionaries, CharSequence word, boolean ignoreCase) { final WhitelistDictionary whitelistDictionary = (WhitelistDictionary)dictionaries.get(Suggest.DICT_KEY_WHITELIST); // If "word" is in the whitelist dictionary, it should not be auto corrected. @@ -87,9 +87,9 @@ public class AutoCorrection { return whiteListedWord != null; } - private static boolean hasAutoCorrectionForConsideredWord(Map dictionaries, - WordComposer wordComposer, ArrayList suggestions, - CharSequence consideredWord) { + private static boolean hasAutoCorrectionForConsideredWord( + HashMap dictionaries, WordComposer wordComposer, + ArrayList suggestions, CharSequence consideredWord) { if (TextUtils.isEmpty(consideredWord)) return false; return wordComposer.size() > 1 && suggestions.size() > 0 && !allowsToBeAutoCorrected(dictionaries, consideredWord, false); diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java index 79441c557..1c24cd11d 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java @@ -25,7 +25,6 @@ import android.util.Log; import java.io.File; import java.util.ArrayList; -import java.util.List; import java.util.Locale; /** @@ -264,9 +263,9 @@ class BinaryDictionaryGetter { * - Gets a file name from the fallback resource passed as an argument. * If that fails: * - Returns null. - * @return The address of a valid file, or null. + * @return The list of addresses of valid dictionary files, or null. */ - public static List getDictionaryFiles(final Locale locale, + public static ArrayList getDictionaryFiles(final Locale locale, final Context context, final int fallbackResId) { // cacheWordListsFromContentProvider returns the list of files it copied to local diff --git a/java/src/com/android/inputmethod/latin/DictionaryCollection.java b/java/src/com/android/inputmethod/latin/DictionaryCollection.java index c19a5a718..5de770a4a 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryCollection.java +++ b/java/src/com/android/inputmethod/latin/DictionaryCollection.java @@ -22,7 +22,6 @@ import android.util.Log; import java.util.Collection; import java.util.Collections; -import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; /** @@ -30,7 +29,7 @@ import java.util.concurrent.CopyOnWriteArrayList; */ public class DictionaryCollection extends Dictionary { private final String TAG = DictionaryCollection.class.getSimpleName(); - protected final List mDictionaries; + protected final CopyOnWriteArrayList mDictionaries; public DictionaryCollection() { mDictionaries = new CopyOnWriteArrayList(); diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java index 7a81f7bd5..77c685c50 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java @@ -22,8 +22,8 @@ import android.content.res.Resources; import android.util.Log; import java.io.File; +import java.util.ArrayList; import java.util.LinkedList; -import java.util.List; import java.util.Locale; /** @@ -52,8 +52,8 @@ public class DictionaryFactory { return new DictionaryCollection(createBinaryDictionary(context, fallbackResId, locale)); } - final List dictList = new LinkedList(); - final List assetFileList = + final LinkedList dictList = new LinkedList(); + final ArrayList assetFileList = BinaryDictionaryGetter.getDictionaryFiles(locale, context, fallbackResId); if (null != assetFileList) { for (final AssetFileAddress f : assetFileList) { diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 234a501de..d5cd35db6 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -73,7 +73,6 @@ import com.android.inputmethod.latin.suggestions.SuggestionsView; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; -import java.util.List; import java.util.Locale; /** @@ -919,7 +918,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar return; } - final List applicationSuggestedWords = + final ArrayList applicationSuggestedWords = SuggestedWords.getFromApplicationSpecifiedCompletions( applicationSpecifiedCompletions); final SuggestedWords suggestedWords = new SuggestedWords( diff --git a/java/src/com/android/inputmethod/latin/LatinImeLogger.java b/java/src/com/android/inputmethod/latin/LatinImeLogger.java index 5390ee39e..683dafa86 100644 --- a/java/src/com/android/inputmethod/latin/LatinImeLogger.java +++ b/java/src/com/android/inputmethod/latin/LatinImeLogger.java @@ -22,8 +22,6 @@ import android.view.inputmethod.EditorInfo; import com.android.inputmethod.keyboard.Keyboard; -import java.util.List; - public class LatinImeLogger implements SharedPreferences.OnSharedPreferenceChangeListener { public static boolean sDBG = false; diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java index 4346a3671..020b57caf 100644 --- a/java/src/com/android/inputmethod/latin/SettingsValues.java +++ b/java/src/com/android/inputmethod/latin/SettingsValues.java @@ -30,8 +30,6 @@ import com.android.inputmethod.keyboard.internal.KeySpecParser; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; -import java.util.List; import java.util.Locale; public class SettingsValues { diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index 69754d769..08f0e425b 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -30,15 +30,12 @@ import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Locale; -import java.util.Map; -import java.util.Set; /** * This class loads a dictionary and provides a list of suggestions for a given sequence of * characters. This includes corrections and completions. */ public class Suggest implements Dictionary.WordCallback { - public static final String TAG = Suggest.class.getSimpleName(); public static final int APPROX_MAX_WORD_LENGTH = 32; @@ -87,8 +84,10 @@ public class Suggest implements Dictionary.WordCallback { private Dictionary mMainDict; private ContactsDictionary mContactsDict; private WhitelistDictionary mWhiteListDictionary; - private final Map mUnigramDictionaries = new HashMap(); - private final Map mBigramDictionaries = new HashMap(); + private final HashMap mUnigramDictionaries = + new HashMap(); + private final HashMap mBigramDictionaries = + new HashMap(); private int mPrefMaxSuggestions = 18; @@ -142,7 +141,7 @@ public class Suggest implements Dictionary.WordCallback { initWhitelistAndAutocorrectAndPool(context, locale); } - private static void addOrReplaceDictionary(Map dictionaries, String key, + private static void addOrReplaceDictionary(HashMap dictionaries, String key, Dictionary dict) { final Dictionary oldDict = (dict == null) ? dictionaries.remove(key) @@ -177,7 +176,7 @@ public class Suggest implements Dictionary.WordCallback { return mContactsDict; } - public Map getUnigramDictionaries() { + public HashMap getUnigramDictionaries() { return mUnigramDictionaries; } @@ -563,7 +562,7 @@ public class Suggest implements Dictionary.WordCallback { } public void close() { - final Set dictionaries = new HashSet(); + final HashSet dictionaries = new HashSet(); dictionaries.addAll(mUnigramDictionaries.values()); dictionaries.addAll(mBigramDictionaries.values()); for (final Dictionary dictionary : dictionaries) { diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java index b63bc6c29..ef8e58e0c 100644 --- a/java/src/com/android/inputmethod/latin/SuggestedWords.java +++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java @@ -21,22 +21,20 @@ import android.view.inputmethod.CompletionInfo; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.HashSet; -import java.util.List; public class SuggestedWords { public static final SuggestedWords EMPTY = new SuggestedWords( - Collections.emptyList(), false, false, false, false, false); + new ArrayList(0), false, false, false, false, false); public final boolean mTypedWordValid; public final boolean mHasAutoCorrectionCandidate; public final boolean mIsPunctuationSuggestions; public final boolean mAllowsToBeAutoCorrected; public final boolean mIsObsoleteSuggestions; - private final List mSuggestedWordInfoList; + private final ArrayList mSuggestedWordInfoList; - public SuggestedWords(final List suggestedWordInfoList, + public SuggestedWords(final ArrayList suggestedWordInfoList, final boolean typedWordValid, final boolean hasAutoCorrectionCandidate, final boolean allowsToBeAutoCorrected, @@ -82,7 +80,7 @@ public class SuggestedWords { } public static ArrayList getFromCharSequenceList( - final List wordList) { + final ArrayList wordList) { final ArrayList result = new ArrayList(); for (CharSequence word : wordList) { if (null != word) result.add(new SuggestedWordInfo(word)); @@ -90,7 +88,7 @@ public class SuggestedWords { return result; } - public static List getFromApplicationSpecifiedCompletions( + public static ArrayList getFromApplicationSpecifiedCompletions( final CompletionInfo[] infos) { final ArrayList result = new ArrayList(); for (CompletionInfo info : infos) { diff --git a/java/src/com/android/inputmethod/latin/XmlParseUtils.java b/java/src/com/android/inputmethod/latin/XmlParseUtils.java index e14c71cb5..481cdfa47 100644 --- a/java/src/com/android/inputmethod/latin/XmlParseUtils.java +++ b/java/src/com/android/inputmethod/latin/XmlParseUtils.java @@ -24,6 +24,10 @@ import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; public class XmlParseUtils { + private XmlParseUtils() { + // This utility class is not publicly instantiable. + } + @SuppressWarnings("serial") public static class ParseException extends XmlPullParserException { public ParseException(String msg, XmlPullParser parser) { diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java index d3c3afb73..286bf0aea 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java +++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java @@ -66,7 +66,6 @@ import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import com.android.inputmethod.latin.Utils; import java.util.ArrayList; -import java.util.List; public class SuggestionsView extends RelativeLayout implements OnClickListener, OnLongClickListener { @@ -144,9 +143,9 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, public final float mMinMoreSuggestionsWidth; public final int mMoreSuggestionsBottomGap; - private final List mWords; - private final List mDividers; - private final List mInfos; + private final ArrayList mWords; + private final ArrayList mDividers; + private final ArrayList mInfos; private final int mColorValidTypedWord; private final int mColorTypedWord; @@ -174,7 +173,7 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, private final TextView mHintToSaveView; public SuggestionsViewParams(Context context, AttributeSet attrs, int defStyle, - List words, List dividers, List infos) { + ArrayList words, ArrayList dividers, ArrayList infos) { mWords = words; mDividers = dividers; mInfos = infos; -- cgit v1.2.3-83-g751a From 16c6f355700ee5cdaa029f4a25b8b3d40718e6ab Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Tue, 3 Apr 2012 14:28:56 +0900 Subject: Add RunInLocale class to guard locale switching Bug: 6128216 Change-Id: I8d9c75c773c3de886183b291ada7a3836295839b --- .../android/inputmethod/keyboard/KeyboardSet.java | 62 +++++++++-------- .../inputmethod/latin/BinaryDictionaryGetter.java | 14 ++-- .../inputmethod/latin/DictionaryFactory.java | 78 +++++++++++----------- .../com/android/inputmethod/latin/LatinIME.java | 59 +++++++++------- .../com/android/inputmethod/latin/LocaleUtils.java | 43 ++++++++---- .../android/inputmethod/latin/SettingsValues.java | 18 ++--- .../inputmethod/latin/WhitelistDictionary.java | 14 ++-- 7 files changed, 163 insertions(+), 125 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/DictionaryFactory.java') diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSet.java b/java/src/com/android/inputmethod/keyboard/KeyboardSet.java index 4d0f00380..0f3ae2f07 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSet.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSet.java @@ -31,7 +31,7 @@ import com.android.inputmethod.compat.InputTypeCompatUtils; import com.android.inputmethod.keyboard.KeyboardSet.Params.ElementParams; import com.android.inputmethod.latin.LatinIME; import com.android.inputmethod.latin.LatinImeLogger; -import com.android.inputmethod.latin.LocaleUtils; +import com.android.inputmethod.latin.LocaleUtils.RunInLocale; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.StringUtils; import com.android.inputmethod.latin.XmlParseUtils; @@ -66,6 +66,7 @@ public class KeyboardSet { public static class KeyboardSetException extends RuntimeException { public final KeyboardId mKeyboardId; + public KeyboardSetException(Throwable cause, KeyboardId keyboardId) { super(cause); mKeyboardId = keyboardId; @@ -161,26 +162,29 @@ public class KeyboardSet { } } - private Keyboard getKeyboard(Context context, ElementParams elementParams, KeyboardId id) { - final Resources res = context.getResources(); + private Keyboard getKeyboard(Context context, ElementParams elementParams, + final KeyboardId id) { final SoftReference ref = sKeyboardCache.get(id); Keyboard keyboard = (ref == null) ? null : ref.get(); if (keyboard == null) { - final Locale savedLocale = LocaleUtils.setSystemLocale(res, id.mLocale); - try { - final Keyboard.Builder builder = - new Keyboard.Builder(context, new Keyboard.Params()); - if (id.isAlphabetKeyboard()) { - builder.setAutoGenerate(sKeysCache); - } - builder.load(elementParams.mKeyboardXmlId, id); - builder.setTouchPositionCorrectionEnabled(mParams.mTouchPositionCorrectionEnabled); - builder.setProximityCharsCorrectionEnabled( - elementParams.mProximityCharsCorrectionEnabled); - keyboard = builder.build(); - } finally { - LocaleUtils.setSystemLocale(res, savedLocale); + final Keyboard.Builder builder = + new Keyboard.Builder(mContext, new Keyboard.Params()); + if (id.isAlphabetKeyboard()) { + builder.setAutoGenerate(sKeysCache); } + final int keyboardXmlId = elementParams.mKeyboardXmlId; + final RunInLocale job = new RunInLocale() { + @Override + protected Void job(Resources res) { + builder.load(keyboardXmlId, id); + return null; + } + }; + job.runInLocale(context.getResources(), id.mLocale); + builder.setTouchPositionCorrectionEnabled(mParams.mTouchPositionCorrectionEnabled); + builder.setProximityCharsCorrectionEnabled( + elementParams.mProximityCharsCorrectionEnabled); + keyboard = builder.build(); sKeyboardCache.put(id, new SoftReference(keyboard)); if (DEBUG_CACHE) { @@ -271,16 +275,20 @@ public class KeyboardSet { if (mParams.mLocale == null) throw new RuntimeException("KeyboardSet subtype is not specified"); - final Locale savedLocale = LocaleUtils.setSystemLocale(mResources, mParams.mLocale); - try { - parseKeyboardSet(mResources, R.xml.keyboard_set); - } catch (Exception e) { - throw new RuntimeException(e.getMessage() + " in " - + mResources.getResourceName(R.xml.keyboard_set) - + " of locale " + mParams.mLocale); - } finally { - LocaleUtils.setSystemLocale(mResources, savedLocale); - } + final RunInLocale job = new RunInLocale() { + @Override + protected Void job(Resources res) { + try { + parseKeyboardSet(res, R.xml.keyboard_set); + } catch (Exception e) { + throw new RuntimeException(e.getMessage() + " in " + + res.getResourceName(R.xml.keyboard_set) + + " of locale " + mParams.mLocale); + } + return null; + } + }; + job.runInLocale(mResources, mParams.mLocale); return new KeyboardSet(mContext, mParams); } diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java index 1c24cd11d..e4d839690 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java @@ -23,6 +23,8 @@ import android.content.res.AssetFileDescriptor; import android.content.res.Resources; import android.util.Log; +import com.android.inputmethod.latin.LocaleUtils.RunInLocale; + import java.io.File; import java.util.ArrayList; import java.util.Locale; @@ -154,11 +156,13 @@ class BinaryDictionaryGetter { */ private static AssetFileAddress loadFallbackResource(final Context context, final int fallbackResId, final Locale locale) { - final Resources res = context.getResources(); - final Locale savedLocale = LocaleUtils.setSystemLocale(res, locale); - final AssetFileDescriptor afd = res.openRawResourceFd(fallbackResId); - LocaleUtils.setSystemLocale(res, savedLocale); - + final RunInLocale job = new RunInLocale() { + @Override + protected AssetFileDescriptor job(Resources res) { + return res.openRawResourceFd(fallbackResId); + } + }; + final AssetFileDescriptor afd = job.runInLocale(context.getResources(), locale); if (afd == null) { Log.e(TAG, "Found the resource but cannot read it. Is it compressed? resId=" + fallbackResId); diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java index 77c685c50..7be374db5 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java @@ -21,6 +21,8 @@ import android.content.res.AssetFileDescriptor; import android.content.res.Resources; import android.util.Log; +import com.android.inputmethod.latin.LocaleUtils.RunInLocale; + import java.io.File; import java.util.ArrayList; import java.util.LinkedList; @@ -30,7 +32,6 @@ import java.util.Locale; * Factory for dictionary instances. */ public class DictionaryFactory { - private static String TAG = DictionaryFactory.class.getSimpleName(); /** @@ -98,14 +99,13 @@ public class DictionaryFactory { final int resId, final Locale locale) { AssetFileDescriptor afd = null; try { - final Resources res = context.getResources(); - if (null != locale) { - final Locale savedLocale = LocaleUtils.setSystemLocale(res, locale); - afd = res.openRawResourceFd(resId); - LocaleUtils.setSystemLocale(res, savedLocale); - } else { - afd = res.openRawResourceFd(resId); - } + final RunInLocale job = new RunInLocale() { + @Override + protected AssetFileDescriptor job(Resources res) { + return res.openRawResourceFd(resId); + } + }; + afd = job.runInLocale(context.getResources(), locale); if (afd == null) { Log.e(TAG, "Found the resource but it is compressed. resId=" + resId); return null; @@ -161,39 +161,41 @@ public class DictionaryFactory { * @return whether a (non-placeholder) dictionary is available or not. */ public static boolean isDictionaryAvailable(Context context, Locale locale) { - final Resources res = context.getResources(); - final Locale saveLocale = LocaleUtils.setSystemLocale(res, locale); - - final int resourceId = getMainDictionaryResourceId(res); - final AssetFileDescriptor afd = res.openRawResourceFd(resourceId); - final boolean hasDictionary = isFullDictionary(afd); - try { - if (null != afd) afd.close(); - } catch (java.io.IOException e) { - /* Um, what can we do here exactly? */ - } - - LocaleUtils.setSystemLocale(res, saveLocale); - return hasDictionary; + final RunInLocale job = new RunInLocale() { + @Override + protected Boolean job(Resources res) { + final int resourceId = getMainDictionaryResourceId(res); + final AssetFileDescriptor afd = res.openRawResourceFd(resourceId); + final boolean hasDictionary = isFullDictionary(afd); + try { + if (null != afd) afd.close(); + } catch (java.io.IOException e) { + /* Um, what can we do here exactly? */ + } + return hasDictionary; + } + }; + return job.runInLocale(context.getResources(), locale); } // TODO: Do not use the size of the dictionary as an unique dictionary ID. public static Long getDictionaryId(final Context context, final Locale locale) { - final Resources res = context.getResources(); - final Locale saveLocale = LocaleUtils.setSystemLocale(res, locale); - - final int resourceId = getMainDictionaryResourceId(res); - final AssetFileDescriptor afd = res.openRawResourceFd(resourceId); - final Long size = (afd != null && afd.getLength() > PLACEHOLDER_LENGTH) - ? afd.getLength() - : null; - try { - if (null != afd) afd.close(); - } catch (java.io.IOException e) { - } - - LocaleUtils.setSystemLocale(res, saveLocale); - return size; + final RunInLocale job = new RunInLocale() { + @Override + protected Long job(Resources res) { + final int resourceId = getMainDictionaryResourceId(res); + final AssetFileDescriptor afd = res.openRawResourceFd(resourceId); + final Long size = (afd != null && afd.getLength() > PLACEHOLDER_LENGTH) + ? afd.getLength() + : null; + try { + if (null != afd) afd.close(); + } catch (java.io.IOException e) { + } + return size; + } + }; + return job.runInLocale(context.getResources(), locale); } // TODO: Find the Right Way to find out whether the resource is a placeholder or not. diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 177f5e629..1eb9c8d02 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -64,6 +64,7 @@ import com.android.inputmethod.keyboard.KeyboardId; import com.android.inputmethod.keyboard.KeyboardSwitcher; import com.android.inputmethod.keyboard.KeyboardView; import com.android.inputmethod.keyboard.LatinKeyboardView; +import com.android.inputmethod.latin.LocaleUtils.RunInLocale; import com.android.inputmethod.latin.define.ProductionFlag; import com.android.inputmethod.latin.suggestions.SuggestionsView; @@ -478,7 +479,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // Has to be package-visible for unit tests /* package */ void loadSettings() { if (null == mPrefs) mPrefs = PreferenceManager.getDefaultSharedPreferences(this); - mSettingsValues = new SettingsValues(mPrefs, this, mSubtypeSwitcher.getInputLocaleStr()); + final RunInLocale job = new RunInLocale() { + @Override + protected SettingsValues job(Resources res) { + return new SettingsValues(mPrefs, LatinIME.this); + } + }; + mSettingsValues = job.runInLocale(mResources, mSubtypeSwitcher.getInputLocale()); mFeedbackManager = new AudioAndHapticFeedbackManager(this, mSettingsValues); resetContactsDictionary(null == mSuggest ? null : mSuggest.getContactsDictionary()); } @@ -487,33 +494,37 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen final String localeStr = mSubtypeSwitcher.getInputLocaleStr(); final Locale keyboardLocale = mSubtypeSwitcher.getInputLocale(); - final Resources res = mResources; - final Locale savedLocale = LocaleUtils.setSystemLocale(res, keyboardLocale); - final ContactsDictionary oldContactsDictionary; - if (mSuggest != null) { - oldContactsDictionary = mSuggest.getContactsDictionary(); - mSuggest.close(); - } else { - oldContactsDictionary = null; - } - - int mainDicResId = DictionaryFactory.getMainDictionaryResourceId(res); - mSuggest = new Suggest(this, mainDicResId, keyboardLocale); - if (mSettingsValues.mAutoCorrectEnabled) { - mSuggest.setAutoCorrectionThreshold(mSettingsValues.mAutoCorrectionThreshold); - } + final Context context = this; + final RunInLocale job = new RunInLocale() { + @Override + protected Void job(Resources res) { + final ContactsDictionary oldContactsDictionary; + if (mSuggest != null) { + oldContactsDictionary = mSuggest.getContactsDictionary(); + mSuggest.close(); + } else { + oldContactsDictionary = null; + } - mUserDictionary = new UserDictionary(this, localeStr); - mSuggest.setUserDictionary(mUserDictionary); - mIsUserDictionaryAvailable = mUserDictionary.isEnabled(); + int mainDicResId = DictionaryFactory.getMainDictionaryResourceId(res); + mSuggest = new Suggest(context, mainDicResId, keyboardLocale); + if (mSettingsValues.mAutoCorrectEnabled) { + mSuggest.setAutoCorrectionThreshold(mSettingsValues.mAutoCorrectionThreshold); + } - resetContactsDictionary(oldContactsDictionary); + mUserDictionary = new UserDictionary(context, localeStr); + mSuggest.setUserDictionary(mUserDictionary); + mIsUserDictionaryAvailable = mUserDictionary.isEnabled(); - mUserHistoryDictionary - = new UserHistoryDictionary(this, localeStr, Suggest.DIC_USER_HISTORY); - mSuggest.setUserHistoryDictionary(mUserHistoryDictionary); + resetContactsDictionary(oldContactsDictionary); - LocaleUtils.setSystemLocale(res, savedLocale); + mUserHistoryDictionary + = new UserHistoryDictionary(context, localeStr, Suggest.DIC_USER_HISTORY); + mSuggest.setUserHistoryDictionary(mUserHistoryDictionary); + return null; + } + }; + job.runInLocale(mResources, keyboardLocale); } /** diff --git a/java/src/com/android/inputmethod/latin/LocaleUtils.java b/java/src/com/android/inputmethod/latin/LocaleUtils.java index cf60089c5..f19c59a6a 100644 --- a/java/src/com/android/inputmethod/latin/LocaleUtils.java +++ b/java/src/com/android/inputmethod/latin/LocaleUtils.java @@ -161,21 +161,36 @@ public class LocaleUtils { return LOCALE_MATCH <= level; } - /** - * Sets the system locale for this process. - * - * @param res the resources to use. Pass current resources. - * @param newLocale the locale to change to. - * @return the old locale. - */ - public static synchronized Locale setSystemLocale(final Resources res, final Locale newLocale) { - final Configuration conf = res.getConfiguration(); - final Locale oldLocale = conf.locale; - if (newLocale != null && !newLocale.equals(oldLocale)) { - conf.locale = newLocale; - res.updateConfiguration(conf, res.getDisplayMetrics()); + static final Object sLockForRunInLocale = new Object(); + + public abstract static class RunInLocale { + protected abstract T job(Resources res); + + /** + * Execute {@link #job(Resources)} method in specified system locale exclusively. + * + * @param res the resources to use. Pass current resources. + * @param newLocale the locale to change to + * @return the value returned from {@link #job(Resources)}. + */ + public T runInLocale(final Resources res, final Locale newLocale) { + synchronized (sLockForRunInLocale) { + final Configuration conf = res.getConfiguration(); + final Locale oldLocale = conf.locale; + try { + if (newLocale != null && !newLocale.equals(oldLocale)) { + conf.locale = newLocale; + res.updateConfiguration(conf, res.getDisplayMetrics()); + } + return job(res); + } finally { + if (newLocale != null && !newLocale.equals(oldLocale)) { + conf.locale = oldLocale; + res.updateConfiguration(conf, res.getDisplayMetrics()); + } + } + } } - return oldLocale; } private static final HashMap sLocaleCache = new HashMap(); diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java index f76cc7e44..f2abb9c20 100644 --- a/java/src/com/android/inputmethod/latin/SettingsValues.java +++ b/java/src/com/android/inputmethod/latin/SettingsValues.java @@ -25,12 +25,14 @@ import android.view.inputmethod.EditorInfo; import com.android.inputmethod.compat.InputTypeCompatUtils; import com.android.inputmethod.keyboard.internal.KeySpecParser; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; -import com.android.inputmethod.latin.VibratorUtils; import java.util.ArrayList; import java.util.Arrays; -import java.util.Locale; +/** + * When you call the constructor of this class, you may want to change the current system locale by + * using {@link LocaleUtils.RunInLocale}. + */ public class SettingsValues { private static final String TAG = SettingsValues.class.getSimpleName(); @@ -78,16 +80,8 @@ public class SettingsValues { private final boolean mVoiceKeyEnabled; private final boolean mVoiceKeyOnMain; - public SettingsValues(final SharedPreferences prefs, final Context context, - final String localeStr) { + public SettingsValues(final SharedPreferences prefs, final Context context) { final Resources res = context.getResources(); - final Locale savedLocale; - if (null != localeStr) { - final Locale keyboardLocale = LocaleUtils.constructLocaleFromString(localeStr); - savedLocale = LocaleUtils.setSystemLocale(res, keyboardLocale); - } else { - savedLocale = null; - } // Get the resources mDelayUpdateOldSuggestions = res.getInteger(R.integer.config_delay_update_old_suggestions); @@ -152,8 +146,6 @@ public class SettingsValues { mAutoCorrectionThresholdRawValue); mVoiceKeyEnabled = mVoiceMode != null && !mVoiceMode.equals(voiceModeOff); mVoiceKeyOnMain = mVoiceMode != null && mVoiceMode.equals(voiceModeMain); - - LocaleUtils.setSystemLocale(res, savedLocale); } // Helper functions to create member values. diff --git a/java/src/com/android/inputmethod/latin/WhitelistDictionary.java b/java/src/com/android/inputmethod/latin/WhitelistDictionary.java index a90ef290b..7bb307662 100644 --- a/java/src/com/android/inputmethod/latin/WhitelistDictionary.java +++ b/java/src/com/android/inputmethod/latin/WhitelistDictionary.java @@ -22,6 +22,8 @@ import android.text.TextUtils; import android.util.Log; import android.util.Pair; +import com.android.inputmethod.latin.LocaleUtils.RunInLocale; + import java.util.HashMap; import java.util.Locale; @@ -36,10 +38,14 @@ public class WhitelistDictionary extends ExpandableDictionary { // TODO: Conform to the async load contact of ExpandableDictionary public WhitelistDictionary(final Context context, final Locale locale) { super(context, Suggest.DIC_WHITELIST); - final Resources res = context.getResources(); - final Locale previousLocale = LocaleUtils.setSystemLocale(res, locale); - initWordlist(res.getStringArray(R.array.wordlist_whitelist)); - LocaleUtils.setSystemLocale(res, previousLocale); + final RunInLocale job = new RunInLocale() { + @Override + protected Void job(Resources res) { + initWordlist(res.getStringArray(R.array.wordlist_whitelist)); + return null; + } + }; + job.runInLocale(context.getResources(), locale); } private void initWordlist(String[] wordlist) { -- cgit v1.2.3-83-g751a From 43ebd8a035af31244a2d54fce5d8000a1fbada4c Mon Sep 17 00:00:00 2001 From: satok Date: Wed, 4 Apr 2012 21:39:23 +0900 Subject: Fix the locale of flags in BinaryDictionary Bug: 6129372 Change-Id: I4958c2aabf651d7e26648a29b75fcc6c77813451 --- .../android/inputmethod/latin/BinaryDictionary.java | 19 ++++++++++++++++--- .../android/inputmethod/latin/DictionaryFactory.java | 7 ++++--- 2 files changed, 20 insertions(+), 6 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/DictionaryFactory.java') diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java index c43683f2d..92019c0ed 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java @@ -17,10 +17,14 @@ package com.android.inputmethod.latin; import android.content.Context; +import android.content.res.AssetFileDescriptor; +import android.content.res.Resources; import com.android.inputmethod.keyboard.ProximityInfo; +import com.android.inputmethod.latin.LocaleUtils.RunInLocale; import java.util.Arrays; +import java.util.Locale; /** * Implements a static, compacted, binary dictionary of standard words. @@ -94,14 +98,23 @@ public class BinaryDictionary extends Dictionary { * @param flagArray the flags to limit the dictionary to, or null for default. */ public BinaryDictionary(final Context context, - final String filename, final long offset, final long length, Flag[] flagArray) { + final String filename, final long offset, final long length, final Flag[] flagArray, + Locale locale) { // Note: at the moment a binary dictionary is always of the "main" type. // Initializing this here will help transitioning out of the scheme where // the Suggest class knows everything about every single dictionary. mDicTypeId = Suggest.DIC_MAIN; // TODO: Stop relying on the state of SubtypeSwitcher, get it as a parameter - mFlags = Flag.initFlags(null == flagArray ? ALL_CONFIG_FLAGS : flagArray, context, - SubtypeSwitcher.getInstance()); + final RunInLocale job = new RunInLocale() { + @Override + protected Void job(Resources res) { + // TODO: remove this when all flags are moved to the native code + mFlags = Flag.initFlags(null == flagArray ? ALL_CONFIG_FLAGS : flagArray, context, + SubtypeSwitcher.getInstance()); + return null; + } + }; + job.runInLocale(context.getResources(), locale); loadDictionary(filename, offset, length); } diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java index 7be374db5..7a59d80f1 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java @@ -59,7 +59,8 @@ public class DictionaryFactory { if (null != assetFileList) { for (final AssetFileAddress f : assetFileList) { final BinaryDictionary binaryDictionary = - new BinaryDictionary(context, f.mFilename, f.mOffset, f.mLength, flagArray); + new BinaryDictionary(context, f.mFilename, f.mOffset, f.mLength, flagArray, + locale); if (binaryDictionary.isValidDictionary()) { dictList.add(binaryDictionary); } @@ -119,7 +120,7 @@ public class DictionaryFactory { return null; } return new BinaryDictionary(context, - sourceDir, afd.getStartOffset(), afd.getLength(), null); + sourceDir, afd.getStartOffset(), afd.getLength(), null, locale); } catch (android.content.res.Resources.NotFoundException e) { Log.e(TAG, "Could not find the resource. resId=" + resId); return null; @@ -147,7 +148,7 @@ public class DictionaryFactory { long startOffset, long length, Flag[] flagArray) { if (dictionary.isFile()) { return new BinaryDictionary(context, dictionary.getAbsolutePath(), startOffset, length, - flagArray); + flagArray, null); } else { Log.e(TAG, "Could not find the file. path=" + dictionary.getAbsolutePath()); return null; -- cgit v1.2.3-83-g751a From ae234abd215fe22d53c0b5fa6c973a982adba50c Mon Sep 17 00:00:00 2001 From: satok Date: Thu, 5 Apr 2012 12:46:48 +0900 Subject: Fix the locale of the flags in BinaryDicitonary for tests Bug: 6129372 Change-Id: I5611f88b10c44261b6145c9dc8615b80e4341e77 --- java/src/com/android/inputmethod/latin/DictionaryFactory.java | 4 ++-- java/src/com/android/inputmethod/latin/Suggest.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/DictionaryFactory.java') diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java index 7a59d80f1..79dc3f2d3 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java @@ -145,10 +145,10 @@ public class DictionaryFactory { * @return the created dictionary, or null. */ public static Dictionary createDictionaryForTest(Context context, File dictionary, - long startOffset, long length, Flag[] flagArray) { + long startOffset, long length, Flag[] flagArray, Locale locale) { if (dictionary.isFile()) { return new BinaryDictionary(context, dictionary.getAbsolutePath(), startOffset, length, - flagArray, null); + flagArray, locale); } else { Log.e(TAG, "Could not find the file. path=" + dictionary.getAbsolutePath()); return null; diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index b31f3019c..4004f6930 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -112,7 +112,7 @@ public class Suggest implements Dictionary.WordCallback { final long startOffset, final long length, final Flag[] flagArray, final Locale locale) { initSynchronously(context, DictionaryFactory.createDictionaryForTest(context, dictionary, - startOffset, length, flagArray), locale); + startOffset, length, flagArray, locale), locale); } private void initWhitelistAndAutocorrectAndPool(final Context context, final Locale locale) { -- cgit v1.2.3-83-g751a From 24aee9100e92dc4c06cdb54487a4922420fa8660 Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Fri, 6 Apr 2012 19:12:05 +0900 Subject: Change the flags to a boolean in constructors. Change-Id: I9939204f3b16346aaebd4d726315ba9c4faf910a --- .../inputmethod/latin/BinaryDictionary.java | 26 +++++++++------------- .../inputmethod/latin/DictionaryFactory.java | 21 ++++++++--------- .../src/com/android/inputmethod/latin/Suggest.java | 9 +++++++- .../spellcheck/AndroidSpellCheckerService.java | 13 +---------- 4 files changed, 30 insertions(+), 39 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/DictionaryFactory.java') diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java index 92019c0ed..61ecec922 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java @@ -64,7 +64,7 @@ public class BinaryDictionary extends Dictionary { // FULL_EDIT_DISTANCE is a flag that forces the dictionary to use full words // when computing edit distance, instead of the default behavior of stopping // the evaluation at the size the user typed. - public static final Flag FLAG_USE_FULL_EDIT_DISTANCE = new Flag(0x2); + public static final int FLAG_USE_FULL_EDIT_DISTANCE = 0x2; // Can create a new flag from extravalue : // public static final Flag FLAG_MYFLAG = @@ -85,7 +85,7 @@ public class BinaryDictionary extends Dictionary { FLAG_REQUIRES_FRENCH_LIGATURES_PROCESSING, }; - private int mFlags = 0; + private final int mFlags; /** * Constructor for the binary dictionary. This is supposed to be called from the @@ -95,26 +95,20 @@ public class BinaryDictionary extends Dictionary { * @param filename the name of the file to read through native code. * @param offset the offset of the dictionary data within the file. * @param length the length of the binary data. - * @param flagArray the flags to limit the dictionary to, or null for default. + * @param useFullEditDistance whether to use the full edit distance in suggestions */ public BinaryDictionary(final Context context, - final String filename, final long offset, final long length, final Flag[] flagArray, - Locale locale) { + final String filename, final long offset, final long length, + final boolean useFullEditDistance, final Locale locale) { // Note: at the moment a binary dictionary is always of the "main" type. // Initializing this here will help transitioning out of the scheme where // the Suggest class knows everything about every single dictionary. mDicTypeId = Suggest.DIC_MAIN; - // TODO: Stop relying on the state of SubtypeSwitcher, get it as a parameter - final RunInLocale job = new RunInLocale() { - @Override - protected Void job(Resources res) { - // TODO: remove this when all flags are moved to the native code - mFlags = Flag.initFlags(null == flagArray ? ALL_CONFIG_FLAGS : flagArray, context, - SubtypeSwitcher.getInstance()); - return null; - } - }; - job.runInLocale(context.getResources(), locale); + if (useFullEditDistance) { + mFlags = FLAG_USE_FULL_EDIT_DISTANCE; + } else { + mFlags = 0; + } loadDictionary(filename, offset, length); } diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java index 79dc3f2d3..fedb45407 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java @@ -43,11 +43,11 @@ public class DictionaryFactory { * @param context application context for reading resources * @param locale the locale for which to create the dictionary * @param fallbackResId the id of the resource to use as a fallback if no pack is found - * @param flagArray an array of flags to use + * @param useFullEditDistance whether to use the full edit distance in suggestions * @return an initialized instance of DictionaryCollection */ public static DictionaryCollection createDictionaryFromManager(final Context context, - final Locale locale, final int fallbackResId, final Flag[] flagArray) { + final Locale locale, final int fallbackResId, final boolean useFullEditDistance) { if (null == locale) { Log.e(TAG, "No locale defined for dictionary"); return new DictionaryCollection(createBinaryDictionary(context, fallbackResId, locale)); @@ -59,8 +59,8 @@ public class DictionaryFactory { if (null != assetFileList) { for (final AssetFileAddress f : assetFileList) { final BinaryDictionary binaryDictionary = - new BinaryDictionary(context, f.mFilename, f.mOffset, f.mLength, flagArray, - locale); + new BinaryDictionary(context, f.mFilename, f.mOffset, f.mLength, + useFullEditDistance, locale); if (binaryDictionary.isValidDictionary()) { dictList.add(binaryDictionary); } @@ -86,7 +86,8 @@ public class DictionaryFactory { */ public static DictionaryCollection createDictionaryFromManager(final Context context, final Locale locale, final int fallbackResId) { - return createDictionaryFromManager(context, locale, fallbackResId, null); + return createDictionaryFromManager(context, locale, fallbackResId, + false /* useFullEditDistance */); } /** @@ -119,8 +120,8 @@ public class DictionaryFactory { Log.e(TAG, "sourceDir is not a file: " + sourceDir); return null; } - return new BinaryDictionary(context, - sourceDir, afd.getStartOffset(), afd.getLength(), null, locale); + return new BinaryDictionary(context, sourceDir, afd.getStartOffset(), afd.getLength(), + false /* useFullEditDistance */, locale); } catch (android.content.res.Resources.NotFoundException e) { Log.e(TAG, "Could not find the resource. resId=" + resId); return null; @@ -141,14 +142,14 @@ public class DictionaryFactory { * @param dictionary the file to read * @param startOffset the offset in the file where the data starts * @param length the length of the data - * @param flagArray the flags to use with this data for testing + * @param useFullEditDistance whether to use the full edit distance in suggestions * @return the created dictionary, or null. */ public static Dictionary createDictionaryForTest(Context context, File dictionary, - long startOffset, long length, Flag[] flagArray, Locale locale) { + long startOffset, long length, final boolean useFullEditDistance, Locale locale) { if (dictionary.isFile()) { return new BinaryDictionary(context, dictionary.getAbsolutePath(), startOffset, length, - flagArray, locale); + useFullEditDistance, locale); } else { Log.e(TAG, "Could not find the file. path=" + dictionary.getAbsolutePath()); return null; diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index 44c4bc768..cbdc68075 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -108,11 +108,18 @@ public class Suggest implements Dictionary.WordCallback { initAsynchronously(context, dictionaryResId, locale); } + // TODO: remove when the tests are updated /* package for test */ Suggest(final Context context, final File dictionary, final long startOffset, final long length, final Flag[] flagArray, final Locale locale) { initSynchronously(context, DictionaryFactory.createDictionaryForTest(context, dictionary, - startOffset, length, flagArray, locale), locale); + startOffset, length /* useFullEditDistance */, false, locale), locale); + } + + /* package for test */ Suggest(final Context context, final File dictionary, + final long startOffset, final long length, final Locale locale) { + initSynchronously(context, DictionaryFactory.createDictionaryForTest(context, dictionary, + startOffset, length /* useFullEditDistance */, false, locale), locale); } private void initWhitelistAndAutocorrectAndPool(final Context context, final Locale locale) { diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java index 1fc945f3c..86a0824a0 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java @@ -68,17 +68,6 @@ public class AndroidSpellCheckerService extends SpellCheckerService private static final int CAPITALIZE_ALL = 2; // All caps private final static String[] EMPTY_STRING_ARRAY = new String[0]; - private final static Flag[] USE_FULL_EDIT_DISTANCE_FLAG_ARRAY; - static { - // See BinaryDictionary.java for an explanation of these flags - // Specifially, ALL_CONFIG_FLAGS means that we want to consider all flags with the - // current dictionary configuration - for example, consider the UMLAUT flag - // so that it will be turned on for German dictionaries and off for others. - USE_FULL_EDIT_DISTANCE_FLAG_ARRAY = Arrays.copyOf(BinaryDictionary.ALL_CONFIG_FLAGS, - BinaryDictionary.ALL_CONFIG_FLAGS.length + 1); - USE_FULL_EDIT_DISTANCE_FLAG_ARRAY[BinaryDictionary.ALL_CONFIG_FLAGS.length] = - BinaryDictionary.FLAG_USE_FULL_EDIT_DISTANCE; - } private Map mDictionaryPools = Collections.synchronizedMap(new TreeMap()); private Map mUserDictionaries = @@ -402,7 +391,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService final int fallbackResourceId = DictionaryFactory.getMainDictionaryResourceId(resources); final DictionaryCollection dictionaryCollection = DictionaryFactory.createDictionaryFromManager(this, locale, fallbackResourceId, - USE_FULL_EDIT_DISTANCE_FLAG_ARRAY); + true /* useFullEditDistance */); final String localeStr = locale.toString(); Dictionary userDictionary = mUserDictionaries.get(localeStr); if (null == userDictionary) { -- cgit v1.2.3-83-g751a From 78ab80844b4f8e0369f4e86b2a02208197f9bd34 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Wed, 11 Apr 2012 14:58:02 +0900 Subject: Add language suffix to main dictionary Bug: 6319377 Change-Id: Ie6a887fefa12e33c17bfeb5d22984e7c1a7bdb46 --- .../inputmethod/latin/BinaryDictionary.java | 3 - .../inputmethod/latin/BinaryDictionaryGetter.java | 16 +--- .../inputmethod/latin/DictionaryFactory.java | 89 +++++++++++----------- .../com/android/inputmethod/latin/LatinIME.java | 50 ++++++------ .../inputmethod/latin/WhitelistDictionary.java | 1 + .../spellcheck/AndroidSpellCheckerService.java | 3 +- 6 files changed, 73 insertions(+), 89 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/DictionaryFactory.java') diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java index cc7540e4e..2d958e17d 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java @@ -17,11 +17,8 @@ package com.android.inputmethod.latin; import android.content.Context; -import android.content.res.AssetFileDescriptor; -import android.content.res.Resources; import com.android.inputmethod.keyboard.ProximityInfo; -import com.android.inputmethod.latin.LocaleUtils.RunInLocale; import java.util.Arrays; import java.util.Locale; diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java index e4d839690..3fbe70f1b 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java @@ -20,11 +20,8 @@ import android.content.Context; import android.content.SharedPreferences; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.AssetFileDescriptor; -import android.content.res.Resources; import android.util.Log; -import com.android.inputmethod.latin.LocaleUtils.RunInLocale; - import java.io.File; import java.util.ArrayList; import java.util.Locale; @@ -155,14 +152,8 @@ class BinaryDictionaryGetter { * Returns a file address from a resource, or null if it cannot be opened. */ private static AssetFileAddress loadFallbackResource(final Context context, - final int fallbackResId, final Locale locale) { - final RunInLocale job = new RunInLocale() { - @Override - protected AssetFileDescriptor job(Resources res) { - return res.openRawResourceFd(fallbackResId); - } - }; - final AssetFileDescriptor afd = job.runInLocale(context.getResources(), locale); + final int fallbackResId) { + final AssetFileDescriptor afd = context.getResources().openRawResourceFd(fallbackResId); if (afd == null) { Log.e(TAG, "Found the resource but cannot read it. Is it compressed? resId=" + fallbackResId); @@ -299,8 +290,7 @@ class BinaryDictionaryGetter { } if (!foundMainDict && dictPackSettings.isWordListActive(mainDictId)) { - final AssetFileAddress fallbackAsset = loadFallbackResource(context, fallbackResId, - locale); + final AssetFileAddress fallbackAsset = loadFallbackResource(context, fallbackResId); if (null != fallbackAsset) { fileList.add(fallbackAsset); } diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java index fedb45407..490a32794 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java @@ -21,8 +21,6 @@ import android.content.res.AssetFileDescriptor; import android.content.res.Resources; import android.util.Log; -import com.android.inputmethod.latin.LocaleUtils.RunInLocale; - import java.io.File; import java.util.ArrayList; import java.util.LinkedList; @@ -101,13 +99,7 @@ public class DictionaryFactory { final int resId, final Locale locale) { AssetFileDescriptor afd = null; try { - final RunInLocale job = new RunInLocale() { - @Override - protected AssetFileDescriptor job(Resources res) { - return res.openRawResourceFd(resId); - } - }; - afd = job.runInLocale(context.getResources(), locale); + afd = context.getResources().openRawResourceFd(resId); if (afd == null) { Log.e(TAG, "Found the resource but it is compressed. resId=" + resId); return null; @@ -163,41 +155,31 @@ public class DictionaryFactory { * @return whether a (non-placeholder) dictionary is available or not. */ public static boolean isDictionaryAvailable(Context context, Locale locale) { - final RunInLocale job = new RunInLocale() { - @Override - protected Boolean job(Resources res) { - final int resourceId = getMainDictionaryResourceId(res); - final AssetFileDescriptor afd = res.openRawResourceFd(resourceId); - final boolean hasDictionary = isFullDictionary(afd); - try { - if (null != afd) afd.close(); - } catch (java.io.IOException e) { - /* Um, what can we do here exactly? */ - } - return hasDictionary; - } - }; - return job.runInLocale(context.getResources(), locale); + final Resources res = context.getResources(); + final int resourceId = getMainDictionaryResourceId(res, locale); + final AssetFileDescriptor afd = res.openRawResourceFd(resourceId); + final boolean hasDictionary = isFullDictionary(afd); + try { + if (null != afd) afd.close(); + } catch (java.io.IOException e) { + /* Um, what can we do here exactly? */ + } + return hasDictionary; } // TODO: Do not use the size of the dictionary as an unique dictionary ID. public static Long getDictionaryId(final Context context, final Locale locale) { - final RunInLocale job = new RunInLocale() { - @Override - protected Long job(Resources res) { - final int resourceId = getMainDictionaryResourceId(res); - final AssetFileDescriptor afd = res.openRawResourceFd(resourceId); - final Long size = (afd != null && afd.getLength() > PLACEHOLDER_LENGTH) - ? afd.getLength() - : null; - try { - if (null != afd) afd.close(); - } catch (java.io.IOException e) { - } - return size; - } - }; - return job.runInLocale(context.getResources(), locale); + final Resources res = context.getResources(); + final int resourceId = getMainDictionaryResourceId(res, locale); + final AssetFileDescriptor afd = res.openRawResourceFd(resourceId); + final Long size = (afd != null && afd.getLength() > PLACEHOLDER_LENGTH) + ? afd.getLength() + : null; + try { + if (null != afd) afd.close(); + } catch (java.io.IOException e) { + } + return size; } // TODO: Find the Right Way to find out whether the resource is a placeholder or not. @@ -214,13 +196,32 @@ public class DictionaryFactory { return (afd != null && afd.getLength() > PLACEHOLDER_LENGTH); } + private static final String DEFAULT_MAIN_DICT = "main"; + private static final String MAIN_DICT_PREFIX = "main_"; + /** * Returns a main dictionary resource id + * @param locale dictionary locale * @return main dictionary resource id */ - public static int getMainDictionaryResourceId(Resources res) { - final String MAIN_DIC_NAME = "main"; - String packageName = LatinIME.class.getPackage().getName(); - return res.getIdentifier(MAIN_DIC_NAME, "raw", packageName); + public static int getMainDictionaryResourceId(Resources res, Locale locale) { + final String packageName = LatinIME.class.getPackage().getName(); + int resId; + + // Try to find main_language_country dictionary. + if (!locale.getCountry().isEmpty()) { + final String dictLanguageCountry = MAIN_DICT_PREFIX + locale.toString().toLowerCase(); + if ((resId = res.getIdentifier(dictLanguageCountry, "raw", packageName)) != 0) { + return resId; + } + } + + // Try to find main_language dictionary. + final String dictLanguage = MAIN_DICT_PREFIX + locale.getLanguage(); + if ((resId = res.getIdentifier(dictLanguage, "raw", packageName)) != 0) { + return resId; + } + + return res.getIdentifier(DEFAULT_MAIN_DICT, "raw", packageName); } } diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index e0fa2f838..e16be2c97 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -493,37 +493,30 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen final String localeStr = mSubtypeSwitcher.getInputLocaleStr(); final Locale keyboardLocale = mSubtypeSwitcher.getInputLocale(); - final Context context = this; - final RunInLocale job = new RunInLocale() { - @Override - protected Void job(Resources res) { - final ContactsDictionary oldContactsDictionary; - if (mSuggest != null) { - oldContactsDictionary = mSuggest.getContactsDictionary(); - mSuggest.close(); - } else { - oldContactsDictionary = null; - } + final ContactsDictionary oldContactsDictionary; + if (mSuggest != null) { + oldContactsDictionary = mSuggest.getContactsDictionary(); + mSuggest.close(); + } else { + oldContactsDictionary = null; + } - int mainDicResId = DictionaryFactory.getMainDictionaryResourceId(res); - mSuggest = new Suggest(context, mainDicResId, keyboardLocale); - if (mSettingsValues.mAutoCorrectEnabled) { - mSuggest.setAutoCorrectionThreshold(mSettingsValues.mAutoCorrectionThreshold); - } + final int mainDicResId = DictionaryFactory.getMainDictionaryResourceId( + mResources, keyboardLocale); + mSuggest = new Suggest(this, mainDicResId, keyboardLocale); + if (mSettingsValues.mAutoCorrectEnabled) { + mSuggest.setAutoCorrectionThreshold(mSettingsValues.mAutoCorrectionThreshold); + } - mUserDictionary = new UserDictionary(context, localeStr); - mSuggest.setUserDictionary(mUserDictionary); - mIsUserDictionaryAvailable = mUserDictionary.isEnabled(); + mUserDictionary = new UserDictionary(this, localeStr); + mSuggest.setUserDictionary(mUserDictionary); + mIsUserDictionaryAvailable = mUserDictionary.isEnabled(); - resetContactsDictionary(oldContactsDictionary); + resetContactsDictionary(oldContactsDictionary); - mUserHistoryDictionary - = new UserHistoryDictionary(context, localeStr, Suggest.DIC_USER_HISTORY); - mSuggest.setUserHistoryDictionary(mUserHistoryDictionary); - return null; - } - }; - job.runInLocale(mResources, keyboardLocale); + mUserHistoryDictionary = new UserHistoryDictionary( + this, localeStr, Suggest.DIC_USER_HISTORY); + mSuggest.setUserHistoryDictionary(mUserHistoryDictionary); } /** @@ -560,7 +553,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen /* package private */ void resetSuggestMainDict() { final Locale keyboardLocale = mSubtypeSwitcher.getInputLocale(); - int mainDicResId = DictionaryFactory.getMainDictionaryResourceId(mResources); + int mainDicResId = DictionaryFactory.getMainDictionaryResourceId( + mResources, keyboardLocale); mSuggest.resetMainDict(this, mainDicResId, keyboardLocale); } diff --git a/java/src/com/android/inputmethod/latin/WhitelistDictionary.java b/java/src/com/android/inputmethod/latin/WhitelistDictionary.java index 7bb307662..bb3ba8651 100644 --- a/java/src/com/android/inputmethod/latin/WhitelistDictionary.java +++ b/java/src/com/android/inputmethod/latin/WhitelistDictionary.java @@ -38,6 +38,7 @@ public class WhitelistDictionary extends ExpandableDictionary { // TODO: Conform to the async load contact of ExpandableDictionary public WhitelistDictionary(final Context context, final Locale locale) { super(context, Suggest.DIC_WHITELIST); + // TODO: Move whitelist dictionary into main dictionary. final RunInLocale job = new RunInLocale() { @Override protected Void job(Resources res) { diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java index 97296147f..6e4ee3143 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java @@ -387,7 +387,8 @@ public class AndroidSpellCheckerService extends SpellCheckerService final ProximityInfo proximityInfo = ProximityInfo.createSpellCheckerProximityInfo( SpellCheckerProximityInfo.getProximityForScript(script)); final Resources resources = getResources(); - final int fallbackResourceId = DictionaryFactory.getMainDictionaryResourceId(resources); + final int fallbackResourceId = DictionaryFactory.getMainDictionaryResourceId( + resources, locale); final DictionaryCollection dictionaryCollection = DictionaryFactory.createDictionaryFromManager(this, locale, fallbackResourceId, true /* useFullEditDistance */); -- cgit v1.2.3-83-g751a From e6269759d642eac0a03ae6942acb5cd556e7ff46 Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Wed, 11 Apr 2012 21:02:26 +0900 Subject: Read the dictionary resource in a more sensical place. We don't need to pass this down all the way from LatinIME any more. It fetched be done exactly where it needs to be. Change-Id: I9f277f9c4f9de70ae755a1334d86c67bbb24c988 --- .../inputmethod/latin/BinaryDictionaryGetter.java | 6 ++++-- .../inputmethod/latin/DictionaryFactory.java | 24 +++++++++------------- .../com/android/inputmethod/latin/LatinIME.java | 9 ++------ .../src/com/android/inputmethod/latin/Suggest.java | 14 ++++++------- .../spellcheck/AndroidSpellCheckerService.java | 5 +---- 5 files changed, 23 insertions(+), 35 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/DictionaryFactory.java') diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java index 3fbe70f1b..b0c2adc79 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java @@ -255,13 +255,13 @@ class BinaryDictionaryGetter { * - Uses a content provider to get a public dictionary set, as per the protocol described * in BinaryDictionaryFileDumper. * If that fails: - * - Gets a file name from the fallback resource passed as an argument. + * - Gets a file name from the built-in dictionary for this locale, if any. * If that fails: * - Returns null. * @return The list of addresses of valid dictionary files, or null. */ public static ArrayList getDictionaryFiles(final Locale locale, - final Context context, final int fallbackResId) { + final Context context) { // cacheWordListsFromContentProvider returns the list of files it copied to local // storage, but we don't really care about what was copied NOW: what we want is the @@ -290,6 +290,8 @@ class BinaryDictionaryGetter { } if (!foundMainDict && dictPackSettings.isWordListActive(mainDictId)) { + final int fallbackResId = + DictionaryFactory.getMainDictionaryResourceId(context.getResources(), locale); final AssetFileAddress fallbackAsset = loadFallbackResource(context, fallbackResId); if (null != fallbackAsset) { fileList.add(fallbackAsset); diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java index 490a32794..bf05f3bc3 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java @@ -36,24 +36,22 @@ public class DictionaryFactory { * Initializes a dictionary from a dictionary pack, with explicit flags. * * This searches for a content provider providing a dictionary pack for the specified - * locale. If none is found, it falls back to using the resource passed as fallBackResId - * as a dictionary. + * locale. If none is found, it falls back to the built-in dictionary - if any. * @param context application context for reading resources * @param locale the locale for which to create the dictionary - * @param fallbackResId the id of the resource to use as a fallback if no pack is found * @param useFullEditDistance whether to use the full edit distance in suggestions * @return an initialized instance of DictionaryCollection */ public static DictionaryCollection createDictionaryFromManager(final Context context, - final Locale locale, final int fallbackResId, final boolean useFullEditDistance) { + final Locale locale, final boolean useFullEditDistance) { if (null == locale) { Log.e(TAG, "No locale defined for dictionary"); - return new DictionaryCollection(createBinaryDictionary(context, fallbackResId, locale)); + return new DictionaryCollection(createBinaryDictionary(context, locale)); } final LinkedList dictList = new LinkedList(); final ArrayList assetFileList = - BinaryDictionaryGetter.getDictionaryFiles(locale, context, fallbackResId); + BinaryDictionaryGetter.getDictionaryFiles(locale, context); if (null != assetFileList) { for (final AssetFileAddress f : assetFileList) { final BinaryDictionary binaryDictionary = @@ -75,17 +73,14 @@ public class DictionaryFactory { * Initializes a dictionary from a dictionary pack, with default flags. * * This searches for a content provider providing a dictionary pack for the specified - * locale. If none is found, it falls back to using the resource passed as fallBackResId - * as a dictionary. + * locale. If none is found, it falls back to the built-in dictionary, if any. * @param context application context for reading resources * @param locale the locale for which to create the dictionary - * @param fallbackResId the id of the resource to use as a fallback if no pack is found * @return an initialized instance of DictionaryCollection */ public static DictionaryCollection createDictionaryFromManager(final Context context, - final Locale locale, final int fallbackResId) { - return createDictionaryFromManager(context, locale, fallbackResId, - false /* useFullEditDistance */); + final Locale locale) { + return createDictionaryFromManager(context, locale, false /* useFullEditDistance */); } /** @@ -96,9 +91,10 @@ public class DictionaryFactory { * @return an initialized instance of BinaryDictionary */ protected static BinaryDictionary createBinaryDictionary(final Context context, - final int resId, final Locale locale) { + final Locale locale) { AssetFileDescriptor afd = null; try { + final int resId = getMainDictionaryResourceId(context.getResources(), locale); afd = context.getResources().openRawResourceFd(resId); if (afd == null) { Log.e(TAG, "Found the resource but it is compressed. resId=" + resId); @@ -115,7 +111,7 @@ public class DictionaryFactory { return new BinaryDictionary(context, sourceDir, afd.getStartOffset(), afd.getLength(), false /* useFullEditDistance */, locale); } catch (android.content.res.Resources.NotFoundException e) { - Log.e(TAG, "Could not find the resource. resId=" + resId); + Log.e(TAG, "Could not find the resource"); return null; } finally { if (null != afd) { diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index e16be2c97..7cdeef897 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -501,9 +501,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen oldContactsDictionary = null; } - final int mainDicResId = DictionaryFactory.getMainDictionaryResourceId( - mResources, keyboardLocale); - mSuggest = new Suggest(this, mainDicResId, keyboardLocale); + mSuggest = new Suggest(this, keyboardLocale); if (mSettingsValues.mAutoCorrectEnabled) { mSuggest.setAutoCorrectionThreshold(mSettingsValues.mAutoCorrectionThreshold); } @@ -552,10 +550,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } /* package private */ void resetSuggestMainDict() { - final Locale keyboardLocale = mSubtypeSwitcher.getInputLocale(); - int mainDicResId = DictionaryFactory.getMainDictionaryResourceId( - mResources, keyboardLocale); - mSuggest.resetMainDict(this, mainDicResId, keyboardLocale); + mSuggest.resetMainDict(this, mSubtypeSwitcher.getInputLocale()); } @Override diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index fa6664b1a..c3f3bd598 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -104,8 +104,8 @@ public class Suggest implements Dictionary.WordCallback { private static final int MINIMUM_SAFETY_NET_CHAR_LENGTH = 4; - public Suggest(final Context context, final int dictionaryResId, final Locale locale) { - initAsynchronously(context, dictionaryResId, locale); + public Suggest(final Context context, final Locale locale) { + initAsynchronously(context, locale); } /* package for test */ Suggest(final Context context, final File dictionary, @@ -119,9 +119,8 @@ public class Suggest implements Dictionary.WordCallback { addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_WHITELIST, mWhiteListDictionary); } - private void initAsynchronously(final Context context, final int dictionaryResId, - final Locale locale) { - resetMainDict(context, dictionaryResId, locale); + private void initAsynchronously(final Context context, final Locale locale) { + resetMainDict(context, locale); // TODO: read the whitelist and init the pool asynchronously too. // initPool should be done asynchronously now that the pool is thread-safe. @@ -146,14 +145,13 @@ public class Suggest implements Dictionary.WordCallback { } } - public void resetMainDict(final Context context, final int dictionaryResId, - final Locale locale) { + public void resetMainDict(final Context context, final Locale locale) { mMainDict = null; new Thread("InitializeBinaryDictionary") { @Override public void run() { final Dictionary newMainDict = DictionaryFactory.createDictionaryFromManager( - context, locale, dictionaryResId); + context, locale); mMainDict = newMainDict; addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_MAIN, newMainDict); addOrReplaceDictionary(mBigramDictionaries, DICT_KEY_MAIN, newMainDict); diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java index 6e4ee3143..576fbe696 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java @@ -386,11 +386,8 @@ public class AndroidSpellCheckerService extends SpellCheckerService final int script = getScriptFromLocale(locale); final ProximityInfo proximityInfo = ProximityInfo.createSpellCheckerProximityInfo( SpellCheckerProximityInfo.getProximityForScript(script)); - final Resources resources = getResources(); - final int fallbackResourceId = DictionaryFactory.getMainDictionaryResourceId( - resources, locale); final DictionaryCollection dictionaryCollection = - DictionaryFactory.createDictionaryFromManager(this, locale, fallbackResourceId, + DictionaryFactory.createDictionaryFromManager(this, locale, true /* useFullEditDistance */); final String localeStr = locale.toString(); Dictionary userDictionary = mUserDictionaries.get(localeStr); -- cgit v1.2.3-83-g751a From cec8552b18fd74517512a43a8d75f64e64bd12c3 Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Wed, 11 Apr 2012 21:29:53 +0900 Subject: Pass a parameter to the dict pack if we don't have a default dict Also, optimize quite a bit the code that decides whether we have a default dict or not. Bug: 5705834 Change-Id: Ied20fbcbbc42cbe8c01759d11b1804d1156c6960 --- .../latin/BinaryDictionaryFileDumper.java | 27 +++++++--- .../inputmethod/latin/BinaryDictionaryGetter.java | 4 +- .../inputmethod/latin/DictionaryFactory.java | 62 +++++++--------------- 3 files changed, 42 insertions(+), 51 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/DictionaryFactory.java') diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java index 311d3dc9d..e4d081b56 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java @@ -53,17 +53,23 @@ public class BinaryDictionaryFileDumper { private static final String DICTIONARY_PROJECTION[] = { "id" }; + public static final String QUERY_PARAMETER_MAY_PROMPT_USER = "mayPrompt"; + public static final String QUERY_PARAMETER_TRUE = "true"; + // Prevents this class to be accidentally instantiated. private BinaryDictionaryFileDumper() { } /** - * Return for a given locale or dictionary id the provider URI to get the dictionary. + * Returns a URI builder pointing to the dictionary pack. + * + * This creates a URI builder able to build a URI pointing to the dictionary + * pack content provider for a specific dictionary id. */ - private static Uri getProviderUri(String path) { + private static Uri.Builder getProviderUriBuilder(final String path) { return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) .authority(BinaryDictionary.DICTIONARY_PACK_AUTHORITY).appendPath( - path).build(); + path); } /** @@ -71,9 +77,13 @@ public class BinaryDictionaryFileDumper { * available to copy into Latin IME. */ private static List getWordListWordListInfos(final Locale locale, - final Context context) { + final Context context, final boolean hasDefaultWordList) { final ContentResolver resolver = context.getContentResolver(); - final Uri dictionaryPackUri = getProviderUri(locale.toString()); + final Uri.Builder builder = getProviderUriBuilder(locale.toString()); + if (!hasDefaultWordList) { + builder.appendQueryParameter(QUERY_PARAMETER_MAY_PROMPT_USER, QUERY_PARAMETER_TRUE); + } + final Uri dictionaryPackUri = builder.build(); final Cursor c = resolver.query(dictionaryPackUri, DICTIONARY_PROJECTION, null, null, null); if (null == c) return Collections.emptyList(); @@ -132,7 +142,7 @@ public class BinaryDictionaryFileDumper { final int MODE_MIN = COMPRESSED_CRYPTED_COMPRESSED; final int MODE_MAX = NONE; - final Uri wordListUri = getProviderUri(id); + final Uri wordListUri = getProviderUriBuilder(id).build(); final String outputFileName = BinaryDictionaryGetter.getCacheFileName(id, locale, context); for (int mode = MODE_MIN; mode <= MODE_MAX; ++mode) { @@ -231,9 +241,10 @@ public class BinaryDictionaryFileDumper { * @throw IOException if the provider-returned data could not be read. */ public static List cacheWordListsFromContentProvider(final Locale locale, - final Context context) { + final Context context, final boolean hasDefaultWordList) { final ContentResolver resolver = context.getContentResolver(); - final List idList = getWordListWordListInfos(locale, context); + final List idList = getWordListWordListInfos(locale, context, + hasDefaultWordList); final List fileAddressList = new ArrayList(); for (WordListInfo id : idList) { final AssetFileAddress afd = cacheWordList(id.mId, id.mLocale, resolver, context); diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java index b0c2adc79..072dec9d1 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java @@ -263,10 +263,12 @@ class BinaryDictionaryGetter { public static ArrayList getDictionaryFiles(final Locale locale, final Context context) { + final boolean hasDefaultWordList = DictionaryFactory.isDictionaryAvailable(context, locale); // cacheWordListsFromContentProvider returns the list of files it copied to local // storage, but we don't really care about what was copied NOW: what we want is the // list of everything we ever cached, so we ignore the return value. - BinaryDictionaryFileDumper.cacheWordListsFromContentProvider(locale, context); + BinaryDictionaryFileDumper.cacheWordListsFromContentProvider(locale, context, + hasDefaultWordList); final File[] cachedWordLists = getCachedWordLists(locale.toString(), context); final String mainDictId = getMainDictId(locale); diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java index bf05f3bc3..17d75368e 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java @@ -94,13 +94,14 @@ public class DictionaryFactory { final Locale locale) { AssetFileDescriptor afd = null; try { - final int resId = getMainDictionaryResourceId(context.getResources(), locale); + final int resId = + getMainDictionaryResourceIdIfAvailableForLocale(context.getResources(), locale); + if (0 == resId) return null; afd = context.getResources().openRawResourceFd(resId); if (afd == null) { Log.e(TAG, "Found the resource but it is compressed. resId=" + resId); return null; } - if (!isFullDictionary(afd)) return null; final String sourceDir = context.getApplicationInfo().sourceDir; final File packagePath = new File(sourceDir); // TODO: Come up with a way to handle a directory. @@ -152,55 +153,19 @@ public class DictionaryFactory { */ public static boolean isDictionaryAvailable(Context context, Locale locale) { final Resources res = context.getResources(); - final int resourceId = getMainDictionaryResourceId(res, locale); - final AssetFileDescriptor afd = res.openRawResourceFd(resourceId); - final boolean hasDictionary = isFullDictionary(afd); - try { - if (null != afd) afd.close(); - } catch (java.io.IOException e) { - /* Um, what can we do here exactly? */ - } - return hasDictionary; - } - - // TODO: Do not use the size of the dictionary as an unique dictionary ID. - public static Long getDictionaryId(final Context context, final Locale locale) { - final Resources res = context.getResources(); - final int resourceId = getMainDictionaryResourceId(res, locale); - final AssetFileDescriptor afd = res.openRawResourceFd(resourceId); - final Long size = (afd != null && afd.getLength() > PLACEHOLDER_LENGTH) - ? afd.getLength() - : null; - try { - if (null != afd) afd.close(); - } catch (java.io.IOException e) { - } - return size; - } - - // TODO: Find the Right Way to find out whether the resource is a placeholder or not. - // Suggestion : strip the locale, open the placeholder file and store its offset. - // Upon opening the file, if it's the same offset, then it's the placeholder. - private static final long PLACEHOLDER_LENGTH = 34; - /** - * Finds out whether the data pointed out by an AssetFileDescriptor is a full - * dictionary (as opposed to null, or to a place holder). - * @param afd the file descriptor to test, or null - * @return true if the dictionary is a real full dictionary, false if it's null or a placeholder - */ - protected static boolean isFullDictionary(final AssetFileDescriptor afd) { - return (afd != null && afd.getLength() > PLACEHOLDER_LENGTH); + return 0 != getMainDictionaryResourceIdIfAvailableForLocale(res, locale); } private static final String DEFAULT_MAIN_DICT = "main"; private static final String MAIN_DICT_PREFIX = "main_"; /** - * Returns a main dictionary resource id + * Helper method to return a dictionary res id for a locale, or 0 if none. * @param locale dictionary locale * @return main dictionary resource id */ - public static int getMainDictionaryResourceId(Resources res, Locale locale) { + private static int getMainDictionaryResourceIdIfAvailableForLocale(final Resources res, + final Locale locale) { final String packageName = LatinIME.class.getPackage().getName(); int resId; @@ -218,6 +183,19 @@ public class DictionaryFactory { return resId; } + // Not found, return 0 + return 0; + } + + /** + * Returns a main dictionary resource id + * @param locale dictionary locale + * @return main dictionary resource id + */ + public static int getMainDictionaryResourceId(final Resources res, final Locale locale) { + int resourceId = getMainDictionaryResourceIdIfAvailableForLocale(res, locale); + if (0 != resourceId) return resourceId; + final String packageName = LatinIME.class.getPackage().getName(); return res.getIdentifier(DEFAULT_MAIN_DICT, "raw", packageName); } } -- cgit v1.2.3-83-g751a From ab39afca23f69f27b67b7c02353e21f769e8129d Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Thu, 19 Apr 2012 19:53:41 +0900 Subject: Remove LatinIME reference from DictionaryFactor class Change-Id: Iad10e71baa81a1b4eb3c84ead47d658d567b8201 --- .../com/android/inputmethod/latin/DictionaryFactory.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/DictionaryFactory.java') diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java index 17d75368e..f5dc7b34a 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java @@ -30,7 +30,10 @@ import java.util.Locale; * Factory for dictionary instances. */ public class DictionaryFactory { - private static String TAG = DictionaryFactory.class.getSimpleName(); + private static final String TAG = DictionaryFactory.class.getSimpleName(); + // This class must be located in the same package as LatinIME.java. + private static final String RESOURCE_PACKAGE_NAME = + DictionaryFactory.class.getPackage().getName(); /** * Initializes a dictionary from a dictionary pack, with explicit flags. @@ -166,20 +169,19 @@ public class DictionaryFactory { */ private static int getMainDictionaryResourceIdIfAvailableForLocale(final Resources res, final Locale locale) { - final String packageName = LatinIME.class.getPackage().getName(); int resId; - // Try to find main_language_country dictionary. if (!locale.getCountry().isEmpty()) { final String dictLanguageCountry = MAIN_DICT_PREFIX + locale.toString().toLowerCase(); - if ((resId = res.getIdentifier(dictLanguageCountry, "raw", packageName)) != 0) { + if ((resId = res.getIdentifier( + dictLanguageCountry, "raw", RESOURCE_PACKAGE_NAME)) != 0) { return resId; } } // Try to find main_language dictionary. final String dictLanguage = MAIN_DICT_PREFIX + locale.getLanguage(); - if ((resId = res.getIdentifier(dictLanguage, "raw", packageName)) != 0) { + if ((resId = res.getIdentifier(dictLanguage, "raw", RESOURCE_PACKAGE_NAME)) != 0) { return resId; } @@ -195,7 +197,6 @@ public class DictionaryFactory { public static int getMainDictionaryResourceId(final Resources res, final Locale locale) { int resourceId = getMainDictionaryResourceIdIfAvailableForLocale(res, locale); if (0 != resourceId) return resourceId; - final String packageName = LatinIME.class.getPackage().getName(); - return res.getIdentifier(DEFAULT_MAIN_DICT, "raw", packageName); + return res.getIdentifier(DEFAULT_MAIN_DICT, "raw", RESOURCE_PACKAGE_NAME); } } -- cgit v1.2.3-83-g751a From f0e12a969974987f1b97929886c6ebe6a685c538 Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Wed, 16 May 2012 15:08:45 +0900 Subject: Don't auto-correct when there is no main dictionary. Bug: 6502485 Change-Id: I5803b0db8552867110587a1140fc03fc2e0eccef --- .../inputmethod/latin/DictionaryCollection.java | 4 +++ .../inputmethod/latin/DictionaryFactory.java | 10 +++--- .../src/com/android/inputmethod/latin/Suggest.java | 38 ++++++++++++---------- .../spellcheck/AndroidSpellCheckerService.java | 2 +- 4 files changed, 30 insertions(+), 24 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/DictionaryFactory.java') diff --git a/java/src/com/android/inputmethod/latin/DictionaryCollection.java b/java/src/com/android/inputmethod/latin/DictionaryCollection.java index 37deb0c5d..f3aa27a22 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryCollection.java +++ b/java/src/com/android/inputmethod/latin/DictionaryCollection.java @@ -70,6 +70,10 @@ public class DictionaryCollection extends Dictionary { return false; } + public boolean isEmpty() { + return mDictionaries.isEmpty(); + } + @Override public void close() { for (final Dictionary dict : mDictionaries) diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java index f5dc7b34a..4cd1b3883 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java @@ -36,7 +36,7 @@ public class DictionaryFactory { DictionaryFactory.class.getPackage().getName(); /** - * Initializes a dictionary from a dictionary pack, with explicit flags. + * Initializes a main dictionary collection from a dictionary pack, with explicit flags. * * This searches for a content provider providing a dictionary pack for the specified * locale. If none is found, it falls back to the built-in dictionary - if any. @@ -45,7 +45,7 @@ public class DictionaryFactory { * @param useFullEditDistance whether to use the full edit distance in suggestions * @return an initialized instance of DictionaryCollection */ - public static DictionaryCollection createDictionaryFromManager(final Context context, + public static DictionaryCollection createMainDictionaryFromManager(final Context context, final Locale locale, final boolean useFullEditDistance) { if (null == locale) { Log.e(TAG, "No locale defined for dictionary"); @@ -73,7 +73,7 @@ public class DictionaryFactory { } /** - * Initializes a dictionary from a dictionary pack, with default flags. + * Initializes a main dictionary collection from a dictionary pack, with default flags. * * This searches for a content provider providing a dictionary pack for the specified * locale. If none is found, it falls back to the built-in dictionary, if any. @@ -81,9 +81,9 @@ public class DictionaryFactory { * @param locale the locale for which to create the dictionary * @return an initialized instance of DictionaryCollection */ - public static DictionaryCollection createDictionaryFromManager(final Context context, + public static DictionaryCollection createMainDictionaryFromManager(final Context context, final Locale locale) { - return createDictionaryFromManager(context, locale, false /* useFullEditDistance */); + return createMainDictionaryFromManager(context, locale, false /* useFullEditDistance */); } /** diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index 845df81f6..c4877316e 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -79,7 +79,7 @@ public class Suggest implements Dictionary.WordCallback { private static final boolean DBG = LatinImeLogger.sDBG; - private Dictionary mMainDict; + private boolean mHasMainDictionary; private Dictionary mContactsDict; private WhitelistDictionary mWhiteListDictionary; private final HashMap mUnigramDictionaries = @@ -110,8 +110,12 @@ public class Suggest implements Dictionary.WordCallback { /* package for test */ Suggest(final Context context, final File dictionary, final long startOffset, final long length, final Locale locale) { - initSynchronously(context, DictionaryFactory.createDictionaryForTest(context, dictionary, - startOffset, length /* useFullEditDistance */, false, locale), locale); + final Dictionary mainDict = DictionaryFactory.createDictionaryForTest(context, dictionary, + startOffset, length /* useFullEditDistance */, false, locale); + mHasMainDictionary = null != mainDict; + addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_MAIN, mainDict); + addOrReplaceDictionary(mBigramDictionaries, DICT_KEY_MAIN, mainDict); + initWhitelistAndAutocorrectAndPool(context, locale); } private void initWhitelistAndAutocorrectAndPool(final Context context, final Locale locale) { @@ -127,14 +131,6 @@ public class Suggest implements Dictionary.WordCallback { initWhitelistAndAutocorrectAndPool(context, locale); } - private void initSynchronously(final Context context, final Dictionary mainDict, - final Locale locale) { - mMainDict = mainDict; - addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_MAIN, mainDict); - addOrReplaceDictionary(mBigramDictionaries, DICT_KEY_MAIN, mainDict); - initWhitelistAndAutocorrectAndPool(context, locale); - } - private static void addOrReplaceDictionary(HashMap dictionaries, String key, Dictionary dict) { final Dictionary oldDict = (dict == null) @@ -146,13 +142,13 @@ public class Suggest implements Dictionary.WordCallback { } public void resetMainDict(final Context context, final Locale locale) { - mMainDict = null; + mHasMainDictionary = false; new Thread("InitializeBinaryDictionary") { @Override public void run() { - final Dictionary newMainDict = DictionaryFactory.createDictionaryFromManager( - context, locale); - mMainDict = newMainDict; + final DictionaryCollection newMainDict = + DictionaryFactory.createMainDictionaryFromManager(context, locale); + mHasMainDictionary = null != newMainDict && !newMainDict.isEmpty(); addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_MAIN, newMainDict); addOrReplaceDictionary(mBigramDictionaries, DICT_KEY_MAIN, newMainDict); } @@ -162,7 +158,7 @@ public class Suggest implements Dictionary.WordCallback { // The main dictionary could have been loaded asynchronously. Don't cache the return value // of this method. public boolean hasMainDictionary() { - return mMainDict != null; + return mHasMainDictionary; } public Dictionary getContactsDictionary() { @@ -376,7 +372,13 @@ public class Suggest implements Dictionary.WordCallback { // a boolean flag. Right now this is handled with a slight hack in // WhitelistDictionary#shouldForciblyAutoCorrectFrom. final boolean allowsToBeAutoCorrected = AutoCorrection.allowsToBeAutoCorrected( - getUnigramDictionaries(), consideredWord, wordComposer.isFirstCharCapitalized()); + getUnigramDictionaries(), consideredWord, wordComposer.isFirstCharCapitalized()) + // If we don't have a main dictionary, we never want to auto-correct. The reason for this + // is, the user may have a contact whose name happens to match a valid word in their + // language, and it will unexpectedly auto-correct. For example, if the user types in + // English with no dictionary and has a "Will" in their contact list, "will" would + // always auto-correct to "Will" which is unwanted. Hence, no main dict => no auto-correct. + && mHasMainDictionary; boolean autoCorrectionAvailable = hasAutoCorrection; if (correctionMode == CORRECTION_FULL || correctionMode == CORRECTION_FULL_BIGRAM) { @@ -563,7 +565,7 @@ public class Suggest implements Dictionary.WordCallback { for (final Dictionary dictionary : dictionaries) { dictionary.close(); } - mMainDict = null; + mHasMainDictionary = false; } // TODO: Resolve the inconsistencies between the native auto correction algorithms and diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java index 6f7f0c333..0c9f9fb27 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java @@ -398,7 +398,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService SpellCheckerProximityInfo.PROXIMITY_GRID_WIDTH, SpellCheckerProximityInfo.PROXIMITY_GRID_HEIGHT); final DictionaryCollection dictionaryCollection = - DictionaryFactory.createDictionaryFromManager(this, locale, + DictionaryFactory.createMainDictionaryFromManager(this, locale, true /* useFullEditDistance */); final String localeStr = locale.toString(); Dictionary userDictionary = mUserDictionaries.get(localeStr); -- cgit v1.2.3-83-g751a From 93ebf74bae44728e0d5f7e738ea28376187a876e Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Fri, 25 May 2012 19:04:54 +0900 Subject: Clean up some compiler warnings Change-Id: I604da15e65fc3cf807ec4033df4e4cd5ef0196fc --- java/src/com/android/inputmethod/keyboard/PointerTracker.java | 6 ------ java/src/com/android/inputmethod/latin/ContactsDictionary.java | 1 + java/src/com/android/inputmethod/latin/Dictionary.java | 2 +- java/src/com/android/inputmethod/latin/DictionaryFactory.java | 1 - java/src/com/android/inputmethod/latin/ExpandableDictionary.java | 3 ++- java/src/com/android/inputmethod/latin/ResearchLogger.java | 2 +- java/src/com/android/inputmethod/latin/UserDictionary.java | 1 + .../android/inputmethod/latin/makedict/BinaryDictInputOutput.java | 8 ++++---- .../com/android/inputmethod/latin/makedict/FusionDictionary.java | 8 +++++--- .../inputmethod/latin/spellcheck/AndroidSpellCheckerService.java | 4 ---- 10 files changed, 15 insertions(+), 21 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/DictionaryFactory.java') diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index 6ad854d1b..59f53fc21 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -452,12 +452,6 @@ public class PointerTracker { return newKey; } - private Key onUpKey(int x, int y, long eventTime) { - mUpTime = eventTime; - mCurrentKey = null; - return onMoveKeyInternal(x, y); - } - public void processMotionEvent(int action, int x, int y, long eventTime, KeyEventHandler handler) { switch (action) { diff --git a/java/src/com/android/inputmethod/latin/ContactsDictionary.java b/java/src/com/android/inputmethod/latin/ContactsDictionary.java index 2f3395245..c9b8d6eb1 100644 --- a/java/src/com/android/inputmethod/latin/ContactsDictionary.java +++ b/java/src/com/android/inputmethod/latin/ContactsDictionary.java @@ -34,6 +34,7 @@ import com.android.inputmethod.keyboard.Keyboard; * * @deprecated Use {@link ContactsBinaryDictionary}. */ +@Deprecated public class ContactsDictionary extends ExpandableDictionary { private static final String[] PROJECTION = { diff --git a/java/src/com/android/inputmethod/latin/Dictionary.java b/java/src/com/android/inputmethod/latin/Dictionary.java index 1ec678f7f..231e9ab81 100644 --- a/java/src/com/android/inputmethod/latin/Dictionary.java +++ b/java/src/com/android/inputmethod/latin/Dictionary.java @@ -33,7 +33,7 @@ public abstract class Dictionary { /** * Interface to be implemented by classes requesting words to be fetched from the dictionary. - * @see #getWords(WordComposer, WordCallback, ProximityInfo) + * @see #getWords(WordComposer, CharSequence, WordCallback, ProximityInfo) */ public interface WordCallback { /** diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java index 4cd1b3883..a22d73af7 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java @@ -89,7 +89,6 @@ public class DictionaryFactory { /** * Initializes a dictionary from a raw resource file * @param context application context for reading resources - * @param resId the resource containing the raw binary dictionary * @param locale the locale to use for the resource * @return an initialized instance of BinaryDictionary */ diff --git a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java index dd9c57e0c..6c457afd2 100644 --- a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java +++ b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java @@ -309,7 +309,8 @@ public class ExpandableDictionary extends Dictionary { * @param word the word to insert, as an array of code points * @param depth the depth of the node in the tree * @param finalFreq the frequency for this word - * @return whether there is still space for more words. {@see Dictionary.WordCallback#addWord}. + * @return whether there is still space for more words. + * @see Dictionary.WordCallback#addWord(char[], int, int, int, int, int) */ private boolean addWordAndShortcutsFromNode(final Node node, final char[] word, final int depth, final int finalFreq, final WordCallback callback) { diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index aa979a66f..66d6d58b1 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -54,7 +54,7 @@ import java.util.Map; * This class logs operations on the IME keyboard, including what the user has typed. * Data is stored locally in a file in app-specific storage. * - * This functionality is off by default. See {@link ProductionFlag.IS_EXPERIMENTAL}. + * This functionality is off by default. See {@link ProductionFlag#IS_EXPERIMENTAL}. */ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChangeListener { private static final String TAG = ResearchLogger.class.getSimpleName(); diff --git a/java/src/com/android/inputmethod/latin/UserDictionary.java b/java/src/com/android/inputmethod/latin/UserDictionary.java index 81e2fdce4..c1efadd44 100644 --- a/java/src/com/android/inputmethod/latin/UserDictionary.java +++ b/java/src/com/android/inputmethod/latin/UserDictionary.java @@ -35,6 +35,7 @@ import java.util.Arrays; * * @deprecated Use {@link UserBinaryDictionary}. */ +@Deprecated public class UserDictionary extends ExpandableDictionary { // TODO: use Words.SHORTCUT when it's public in the SDK diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java index 563f8a99b..89c59f809 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java @@ -882,9 +882,9 @@ public class BinaryDictInputOutput { final int indexOfShortcutByteSize = index; index += GROUP_SHORTCUT_LIST_SIZE_SIZE; groupAddress += GROUP_SHORTCUT_LIST_SIZE_SIZE; - final Iterator shortcutIterator = group.mShortcutTargets.iterator(); + final Iterator shortcutIterator = group.mShortcutTargets.iterator(); while (shortcutIterator.hasNext()) { - final WeightedString target = (WeightedString)shortcutIterator.next(); + final WeightedString target = shortcutIterator.next(); ++groupAddress; int shortcutFlags = makeShortcutFlags(shortcutIterator.hasNext(), target.mFrequency); @@ -902,9 +902,9 @@ public class BinaryDictInputOutput { } // Write bigrams if (null != group.mBigrams) { - final Iterator bigramIterator = group.mBigrams.iterator(); + final Iterator bigramIterator = group.mBigrams.iterator(); while (bigramIterator.hasNext()) { - final WeightedString bigram = (WeightedString)bigramIterator.next(); + final WeightedString bigram = bigramIterator.next(); final CharGroup target = FusionDictionary.findWordInTree(dict.mRoot, bigram.mWord); final int addressOfBigram = target.mCachedAddress; diff --git a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java index c467ef7d4..8b53c9427 100644 --- a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java +++ b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java @@ -296,7 +296,6 @@ public class FusionDictionary implements Iterable { * @param word the word to add. * @param frequency the frequency of the word, in the range [0..255]. * @param shortcutTargets a list of shortcut targets for this word, or null. - * @param bigrams a list of bigrams, or null. */ public void add(final String word, final int frequency, final ArrayList shortcutTargets) { @@ -435,6 +434,8 @@ public class FusionDictionary implements Iterable { } } + private static int ARRAYS_ARE_EQUAL = 0; + /** * Custom comparison of two int arrays taken to contain character codes. * @@ -450,7 +451,6 @@ public class FusionDictionary implements Iterable { * @param dstOffset the offset in the right-hand side string. * @return the index at which the strings differ, or ARRAYS_ARE_EQUAL = 0 if they don't. */ - private static int ARRAYS_ARE_EQUAL = 0; private static int compareArrays(final int[] src, final int[] dst, int dstOffset) { // We do NOT test the first char, because we come from a method that already // tested it. @@ -469,6 +469,7 @@ public class FusionDictionary implements Iterable { * This comparator imposes orderings that are inconsistent with equals. */ static private class CharGroupComparator implements java.util.Comparator { + @Override public int compare(CharGroup c1, CharGroup c2) { if (c1.mChars[0] == c2.mChars[0]) return 0; return c1.mChars[0] < c2.mChars[0] ? -1 : 1; @@ -487,6 +488,8 @@ public class FusionDictionary implements Iterable { return result >= 0 ? result : -result - 1; } + private static int CHARACTER_NOT_FOUND = -1; + /** * Find the index of a char in a node, if it exists. * @@ -494,7 +497,6 @@ public class FusionDictionary implements Iterable { * @param character the character to search for. * @return the position of the character if it's there, or CHARACTER_NOT_FOUND = -1 else. */ - private static int CHARACTER_NOT_FOUND = -1; private static int findIndexOfChar(final Node node, int character) { final int insertionIndex = findInsertionIndex(node, character); if (node.mData.size() <= insertionIndex) return CHARACTER_NOT_FOUND; diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java index aa3250185..0e3bf8011 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java @@ -499,10 +499,6 @@ public class AndroidSpellCheckerService extends SpellCheckerService } mUnigramSuggestionsInfoCache.put(query, new SuggestionsParams(suggestions, flags)); } - - public void remove(String key) { - mUnigramSuggestionsInfoCache.remove(key); - } } AndroidSpellCheckerSession(final AndroidSpellCheckerService service) { -- cgit v1.2.3-83-g751a From 73680097996ea2ddbca3f84144a00ce3ba66b763 Mon Sep 17 00:00:00 2001 From: Satoshi Kataoka Date: Mon, 25 Jun 2012 17:44:54 +0900 Subject: Change JNI for Gesture Change-Id: I774a0052038d16677f60f7efa11fd266cb5f3088 --- .../inputmethod/latin/BinaryDictionary.java | 45 +++++++++++++--------- .../com/android/inputmethod/latin/Dictionary.java | 5 ++- .../inputmethod/latin/DictionaryFactory.java | 6 +-- .../latin/ExpandableBinaryDictionary.java | 2 +- .../inputmethod/latin/ExpandableDictionary.java | 5 ++- .../src/com/android/inputmethod/latin/Suggest.java | 4 +- java/src/com/android/inputmethod/latin/Utils.java | 2 +- .../spellcheck/AndroidSpellCheckerService.java | 4 +- ..._android_inputmethod_latin_BinaryDictionary.cpp | 25 ++++++++---- native/jni/src/dictionary.h | 14 ++++--- 10 files changed, 68 insertions(+), 44 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/DictionaryFactory.java') diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java index d0613bd72..b7a510021 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java @@ -40,6 +40,7 @@ public class BinaryDictionary extends Dictionary { */ public static final int MAX_WORD_LENGTH = 48; public static final int MAX_WORDS = 18; + public static final int MAX_SPACES = 16; private static final String TAG = "BinaryDictionary"; private static final int MAX_BIGRAMS = 60; @@ -51,6 +52,7 @@ public class BinaryDictionary extends Dictionary { private final int[] mInputCodes = new int[MAX_WORD_LENGTH]; private final char[] mOutputChars = new char[MAX_WORD_LENGTH * MAX_WORDS]; private final char[] mOutputChars_bigrams = new char[MAX_WORD_LENGTH * MAX_BIGRAMS]; + private final int[] mSpaceIndices = new int[MAX_SPACES]; private final int[] mScores = new int[MAX_WORDS]; private final int[] mBigramScores = new int[MAX_BIGRAMS]; @@ -65,14 +67,12 @@ public class BinaryDictionary extends Dictionary { * @param offset the offset of the dictionary data within the file. * @param length the length of the binary data. * @param useFullEditDistance whether to use the full edit distance in suggestions + * @param dicTypeId the dictionary type id of the dictionary */ public BinaryDictionary(final Context context, final String filename, final long offset, final long length, - final boolean useFullEditDistance, final Locale locale) { - // Note: at the moment a binary dictionary is always of the "main" type. - // Initializing this here will help transitioning out of the scheme where - // the Suggest class knows everything about every single dictionary. - mDicTypeId = Suggest.DIC_MAIN; + final boolean useFullEditDistance, final Locale locale, final int dicTypeId) { + mDicTypeId = dicTypeId; mUseFullEditDistance = useFullEditDistance; loadDictionary(filename, offset, length); } @@ -87,8 +87,10 @@ public class BinaryDictionary extends Dictionary { private native int getFrequencyNative(long dict, int[] word, int wordLength); private native boolean isValidBigramNative(long dict, int[] word1, int[] word2); private native int getSuggestionsNative(long dict, long proximityInfo, int[] xCoordinates, - int[] yCoordinates, int[] inputCodes, int codesSize, int[] prevWordForBigrams, - boolean useFullEditDistance, char[] outputChars, int[] scores); + int[] yCoordinates, int[] times, int[] pointerIds, int[] inputCodes, int codesSize, + int commitPoint, boolean isGesture, int dicTypeId, + int[] prevWordCodePointArray, boolean useFullEditDistance, char[] outputChars, + int[] scores, int[] outputIndices); private native int getBigramsNative(long dict, int[] prevWord, int prevWordLength, int[] inputCodes, int inputCodesLength, char[] outputChars, int[] scores, int maxWordLength, int maxBigrams); @@ -131,7 +133,7 @@ public class BinaryDictionary extends Dictionary { ++len; } if (len > 0) { - callback.addWord(mOutputChars_bigrams, start, len, mBigramScores[j], + callback.addWord(mOutputChars_bigrams, null, start, len, mBigramScores[j], mDicTypeId, Dictionary.BIGRAM); } } @@ -141,9 +143,9 @@ public class BinaryDictionary extends Dictionary { @Override public void getWords(final WordComposer codes, final CharSequence prevWordForBigrams, final WordCallback callback, final ProximityInfo proximityInfo) { - final int count = getSuggestions(codes, prevWordForBigrams, proximityInfo, mOutputChars, - mScores); + final int count = getSuggestions(codes, prevWordForBigrams, proximityInfo, mOutputChars, + mScores, mSpaceIndices); for (int j = 0; j < count; ++j) { if (mScores[j] < 1) break; final int start = j * MAX_WORD_LENGTH; @@ -152,7 +154,7 @@ public class BinaryDictionary extends Dictionary { ++len; } if (len > 0) { - callback.addWord(mOutputChars, start, len, mScores[j], mDicTypeId, + callback.addWord(mOutputChars, null, start, len, mScores[j], mDicTypeId, Dictionary.UNIGRAM); } } @@ -165,7 +167,7 @@ public class BinaryDictionary extends Dictionary { // proximityInfo may not be null. /* package for test */ int getSuggestions(final WordComposer codes, final CharSequence prevWordForBigrams, final ProximityInfo proximityInfo, - char[] outputChars, int[] scores) { + char[] outputChars, int[] scores, int[] spaceIndices) { if (!isValidDictionary()) return -1; final int codesSize = codes.size(); @@ -179,14 +181,21 @@ public class BinaryDictionary extends Dictionary { Arrays.fill(outputChars, (char) 0); Arrays.fill(scores, 0); - final int[] prevWordCodePointArray = null == prevWordForBigrams + // TODO: toLowerCase in the native code + final int[] prevWordCodePointArray = (null == prevWordForBigrams) ? null : StringUtils.toCodePointArray(prevWordForBigrams.toString()); - // TODO: pass the previous word to native code - return getSuggestionsNative( - mNativeDict, proximityInfo.getNativeProximityInfo(), - codes.getXCoordinates(), codes.getYCoordinates(), mInputCodes, codesSize, - prevWordCodePointArray, mUseFullEditDistance, outputChars, scores); + int[] emptyArray = new int[codesSize]; + Arrays.fill(emptyArray, 0); + + //final int commitPoint = codes.getCommitPoint(); + //codes.clearCommitPoint(); + + return getSuggestionsNative(mNativeDict, proximityInfo.getNativeProximityInfo(), + codes.getXCoordinates(), codes.getYCoordinates(), emptyArray, emptyArray, mInputCodes, + codesSize, 0 /* unused */, false, mDicTypeId, + prevWordCodePointArray, mUseFullEditDistance, + outputChars, scores, spaceIndices); } public static float calcNormalizedScore(String before, String after, int score) { diff --git a/java/src/com/android/inputmethod/latin/Dictionary.java b/java/src/com/android/inputmethod/latin/Dictionary.java index 9c3d46e70..c75e55d80 100644 --- a/java/src/com/android/inputmethod/latin/Dictionary.java +++ b/java/src/com/android/inputmethod/latin/Dictionary.java @@ -41,6 +41,7 @@ public abstract class Dictionary { * Adds a word to a list of suggestions. The word is expected to be ordered based on * the provided score. * @param word the character array containing the word + * @param spaceIndices the indices of inserted spaces * @param wordOffset starting offset of the word in the character array * @param wordLength length of valid characters in the character array * @param score the score of occurrence. This is normalized between 1 and 255, but @@ -49,8 +50,8 @@ public abstract class Dictionary { * @param dataType tells type of this data, either UNIGRAM or BIGRAM * @return true if the word was added, false if no more words are required */ - boolean addWord(char[] word, int wordOffset, int wordLength, int score, int dicTypeId, - int dataType); + boolean addWord(char[] word, int[] spaceIndices, int wordOffset, int wordLength, int score, + int dicTypeId, int dataType); } /** diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java index a22d73af7..6d77c4dd2 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java @@ -59,7 +59,7 @@ public class DictionaryFactory { for (final AssetFileAddress f : assetFileList) { final BinaryDictionary binaryDictionary = new BinaryDictionary(context, f.mFilename, f.mOffset, f.mLength, - useFullEditDistance, locale); + useFullEditDistance, locale, Suggest.DIC_MAIN); if (binaryDictionary.isValidDictionary()) { dictList.add(binaryDictionary); } @@ -112,7 +112,7 @@ public class DictionaryFactory { return null; } return new BinaryDictionary(context, sourceDir, afd.getStartOffset(), afd.getLength(), - false /* useFullEditDistance */, locale); + false /* useFullEditDistance */, locale, Suggest.DIC_MAIN); } catch (android.content.res.Resources.NotFoundException e) { Log.e(TAG, "Could not find the resource"); return null; @@ -140,7 +140,7 @@ public class DictionaryFactory { long startOffset, long length, final boolean useFullEditDistance, Locale locale) { if (dictionary.isFile()) { return new BinaryDictionary(context, dictionary.getAbsolutePath(), startOffset, length, - useFullEditDistance, locale); + useFullEditDistance, locale, Suggest.DIC_MAIN); } else { Log.e(TAG, "Could not find the file. path=" + dictionary.getAbsolutePath()); return null; diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java index c65404cbc..41d4aa061 100644 --- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java @@ -306,7 +306,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { // Build the new binary dictionary final BinaryDictionary newBinaryDictionary = new BinaryDictionary(mContext, filename, 0, length, true /* useFullEditDistance */, - null); + null, mDicTypeId); if (mBinaryDictionary != null) { // Ensure all threads accessing the current dictionary have finished before swapping in diff --git a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java index f5886aa12..c989614fb 100644 --- a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java +++ b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java @@ -660,8 +660,9 @@ public class ExpandableDictionary extends Dictionary { } while (node != null); if (freq >= 0) { - callback.addWord(mLookedUpString, index, BinaryDictionary.MAX_WORD_LENGTH - index, - freq, mDicTypeId, Dictionary.BIGRAM); + callback.addWord(mLookedUpString, null, index, + BinaryDictionary.MAX_WORD_LENGTH - index, freq, mDicTypeId, + Dictionary.BIGRAM); } } } diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index 892245402..0938bd127 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -439,8 +439,8 @@ public class Suggest implements Dictionary.WordCallback { // TODO: Use codepoint instead of char @Override - public boolean addWord(final char[] word, final int offset, final int length, int score, - final int dicTypeId, final int dataType) { + public boolean addWord(final char[] word, int[] indices, final int offset, final int length, + int score, final int dicTypeId, final int dataType) { int dataTypeForLog = dataType; final ArrayList suggestions; final int prefMaxSuggestions; diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java index a44b1f9ad..19ac71876 100644 --- a/java/src/com/android/inputmethod/latin/Utils.java +++ b/java/src/com/android/inputmethod/latin/Utils.java @@ -537,7 +537,7 @@ public class Utils { final Dictionary.WordCallback callback) { for (SuggestedWordInfo suggestion : suggestions) { final String suggestionStr = suggestion.mWord.toString(); - callback.addWord(suggestionStr.toCharArray(), 0, suggestionStr.length(), + callback.addWord(suggestionStr.toCharArray(), null, 0, suggestionStr.length(), suggestion.mScore, dicTypeId, dataType); } } diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java index 7fffc31c0..0bbf2acb1 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java @@ -238,8 +238,8 @@ public class AndroidSpellCheckerService extends SpellCheckerService } @Override - synchronized public boolean addWord(char[] word, int wordOffset, int wordLength, int score, - int dicTypeId, int dataType) { + synchronized public boolean addWord(char[] word, int[] spaceIndices, int wordOffset, + int wordLength, int score, int dicTypeId, int dataType) { final int positionIndex = Arrays.binarySearch(mScores, 0, mLength, score); // binarySearch returns the index if the element exists, and - - 1 // if it doesn't. See documentation for binarySearch. diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp index d10dc962e..3fa45da55 100644 --- a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp +++ b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp @@ -128,28 +128,37 @@ static jlong latinime_BinaryDictionary_open(JNIEnv *env, jobject object, static int latinime_BinaryDictionary_getSuggestions(JNIEnv *env, jobject object, jlong dict, jlong proximityInfo, jintArray xCoordinatesArray, jintArray yCoordinatesArray, - jintArray inputArray, jint arraySize, jintArray prevWordForBigrams, - jboolean useFullEditDistance, jcharArray outputArray, jintArray frequencyArray) { - Dictionary *dictionary = (Dictionary*)dict; + jintArray timesArray, jintArray pointerIdArray, jintArray inputArray, jint arraySize, + jint commitPoint, jboolean isGesture, jint dicTypeId, + jintArray prevWordForBigrams, jboolean useFullEditDistance, jcharArray outputArray, + jintArray frequencyArray, jintArray spaceIndexArray) { + Dictionary *dictionary = (Dictionary*) dict; if (!dictionary) return 0; ProximityInfo *pInfo = (ProximityInfo*)proximityInfo; int *xCoordinates = env->GetIntArrayElements(xCoordinatesArray, 0); int *yCoordinates = env->GetIntArrayElements(yCoordinatesArray, 0); + int *times = env->GetIntArrayElements(timesArray, 0); + int *pointerIds = env->GetIntArrayElements(pointerIdArray, 0); int *frequencies = env->GetIntArrayElements(frequencyArray, 0); int *inputCodes = env->GetIntArrayElements(inputArray, 0); jchar *outputChars = env->GetCharArrayElements(outputArray, 0); + int *spaceIndices = env->GetIntArrayElements(spaceIndexArray, 0); jint *prevWordChars = prevWordForBigrams ? env->GetIntArrayElements(prevWordForBigrams, 0) : 0; jsize prevWordLength = prevWordChars ? env->GetArrayLength(prevWordForBigrams) : 0; - int count = dictionary->getSuggestions(pInfo, xCoordinates, yCoordinates, inputCodes, - arraySize, prevWordChars, prevWordLength, useFullEditDistance, - (unsigned short*) outputChars, frequencies); + int count = dictionary->getSuggestions(pInfo, xCoordinates, yCoordinates, times, pointerIds, + inputCodes, arraySize, prevWordChars, prevWordLength, commitPoint, isGesture, + dicTypeId, useFullEditDistance, (unsigned short*) outputChars, + frequencies, spaceIndices); if (prevWordChars) { env->ReleaseIntArrayElements(prevWordForBigrams, prevWordChars, JNI_ABORT); } + env->ReleaseIntArrayElements(spaceIndexArray, spaceIndices, 0); env->ReleaseCharArrayElements(outputArray, outputChars, 0); env->ReleaseIntArrayElements(inputArray, inputCodes, JNI_ABORT); env->ReleaseIntArrayElements(frequencyArray, frequencies, 0); + env->ReleaseIntArrayElements(pointerIdArray, pointerIds, 0); + env->ReleaseIntArrayElements(timesArray, times, 0); env->ReleaseIntArrayElements(yCoordinatesArray, yCoordinates, 0); env->ReleaseIntArrayElements(xCoordinatesArray, xCoordinates, 0); return count; @@ -251,8 +260,8 @@ void releaseDictBuf(void* dictBuf, const size_t length, int fd) { static JNINativeMethod sMethods[] = { {"openNative", "(Ljava/lang/String;JJIIII)J", (void*)latinime_BinaryDictionary_open}, {"closeNative", "(J)V", (void*)latinime_BinaryDictionary_close}, - {"getSuggestionsNative", "(JJ[I[I[II[IZ[C[I)I", - (void*)latinime_BinaryDictionary_getSuggestions}, + {"getSuggestionsNative", "(JJ[I[I[I[I[IIIZI[IZ[C[I[I)I", + (void*) latinime_BinaryDictionary_getSuggestions}, {"getFrequencyNative", "(J[II)I", (void*)latinime_BinaryDictionary_getFrequency}, {"isValidBigramNative", "(J[I[I)Z", (void*)latinime_BinaryDictionary_isValidBigram}, {"getBigramsNative", "(J[II[II[C[III)I", (void*)latinime_BinaryDictionary_getBigrams}, diff --git a/native/jni/src/dictionary.h b/native/jni/src/dictionary.h index fd69f79e3..76b25e59a 100644 --- a/native/jni/src/dictionary.h +++ b/native/jni/src/dictionary.h @@ -34,15 +34,19 @@ class Dictionary { int fullWordMultiplier, int maxWordLength, int maxWords); int getSuggestions(ProximityInfo *proximityInfo, int *xcoordinates, int *ycoordinates, - int *codes, int codesSize, const int32_t* prevWordChars, const int prevWordLength, - bool useFullEditDistance, unsigned short *outWords, int *frequencies) const { + int *times, int *pointerIds, int *codes, int codesSize, int *prevWordChars, + int prevWordLength, int commitPoint, bool isGesture, int dicTypeId, + bool useFullEditDistance, unsigned short *outWords, + int *frequencies, int *spaceIndices) { + int result = 0; std::map bigramMap; uint8_t bigramFilter[BIGRAM_FILTER_BYTE_SIZE]; mBigramDictionary->fillBigramAddressToFrequencyMapAndFilter(prevWordChars, prevWordLength, &bigramMap, bigramFilter); - return mUnigramDictionary->getSuggestions(proximityInfo, - xcoordinates, ycoordinates, codes, codesSize, &bigramMap, - bigramFilter, useFullEditDistance, outWords, frequencies); + result = mUnigramDictionary->getSuggestions(proximityInfo, xcoordinates, + ycoordinates, codes, codesSize, &bigramMap, bigramFilter, + useFullEditDistance, outWords, frequencies); + return result; } int getBigrams(const int32_t *word, int length, int *codes, int codesSize, -- cgit v1.2.3-83-g751a From 05efe576f976f5fa280f8d523f2935c15cbb9bd1 Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Wed, 27 Jun 2012 17:31:09 +0900 Subject: Cleanup the dictionary type. Stop storing an int in each of the different class types, and just store a string in the top class. Change-Id: I2af1832743e6fe78e5c1364f6d9cc21252bf5831 --- java/src/com/android/inputmethod/latin/BinaryDictionary.java | 12 +++++------- .../android/inputmethod/latin/ContactsBinaryDictionary.java | 4 ++-- java/src/com/android/inputmethod/latin/Dictionary.java | 6 ++++++ .../com/android/inputmethod/latin/DictionaryCollection.java | 9 ++++++--- .../src/com/android/inputmethod/latin/DictionaryFactory.java | 11 ++++++----- .../inputmethod/latin/ExpandableBinaryDictionary.java | 11 ++++------- .../com/android/inputmethod/latin/ExpandableDictionary.java | 5 ++--- java/src/com/android/inputmethod/latin/LatinIME.java | 5 ++--- .../latin/SynchronouslyLoadedContactsBinaryDictionary.java | 2 +- .../com/android/inputmethod/latin/UserBinaryDictionary.java | 2 +- .../com/android/inputmethod/latin/UserHistoryDictionary.java | 8 ++++---- .../com/android/inputmethod/latin/WhitelistDictionary.java | 2 +- .../jni/com_android_inputmethod_latin_BinaryDictionary.cpp | 6 +++--- native/jni/src/dictionary.h | 4 ++-- native/jni/src/gesture/impl/gesture_decoder_impl.h | 2 +- native/jni/src/gesture/incremental_decoder_interface.h | 2 +- 16 files changed, 47 insertions(+), 44 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/DictionaryFactory.java') diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java index f44e6328b..8d5bc1595 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java @@ -49,7 +49,6 @@ public class BinaryDictionary extends Dictionary { private static final int TYPED_LETTER_MULTIPLIER = 2; - private int mDicTypeId; private long mNativeDict; private final int[] mInputCodes = new int[MAX_WORD_LENGTH]; private final char[] mOutputChars = new char[MAX_WORD_LENGTH * MAX_WORDS]; @@ -69,12 +68,12 @@ public class BinaryDictionary extends Dictionary { * @param offset the offset of the dictionary data within the file. * @param length the length of the binary data. * @param useFullEditDistance whether to use the full edit distance in suggestions - * @param dicTypeId the dictionary type id of the dictionary + * @param dictType the dictionary type, as a human-readable string */ public BinaryDictionary(final Context context, final String filename, final long offset, final long length, - final boolean useFullEditDistance, final Locale locale, final int dicTypeId) { - mDicTypeId = dicTypeId; + final boolean useFullEditDistance, final Locale locale, final String dictType) { + super(dictType); mUseFullEditDistance = useFullEditDistance; loadDictionary(filename, offset, length); } @@ -90,7 +89,7 @@ public class BinaryDictionary extends Dictionary { private native boolean isValidBigramNative(long dict, int[] word1, int[] word2); private native int getSuggestionsNative(long dict, long proximityInfo, int[] xCoordinates, int[] yCoordinates, int[] times, int[] pointerIds, int[] inputCodes, int codesSize, - int commitPoint, boolean isGesture, int dicTypeId, + int commitPoint, boolean isGesture, int[] prevWordCodePointArray, boolean useFullEditDistance, char[] outputChars, int[] scores, int[] outputIndices); private native int getBigramsNative(long dict, int[] prevWord, int prevWordLength, @@ -202,8 +201,7 @@ public class BinaryDictionary extends Dictionary { return getSuggestionsNative(mNativeDict, proximityInfo.getNativeProximityInfo(), codes.getXCoordinates(), codes.getYCoordinates(), emptyArray, emptyArray, mInputCodes, - codesSize, 0 /* unused */, false, mDicTypeId, - prevWordCodePointArray, mUseFullEditDistance, + codesSize, 0 /* unused */, false, prevWordCodePointArray, mUseFullEditDistance, outputChars, scores, spaceIndices); } diff --git a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java index 620c553af..fbcaddae8 100644 --- a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java @@ -62,8 +62,8 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary { */ private final boolean mUseFirstLastBigrams; - public ContactsBinaryDictionary(final Context context, final int dicTypeId, Locale locale) { - super(context, getFilenameWithLocale(NAME, locale.toString()), dicTypeId); + public ContactsBinaryDictionary(final Context context, Locale locale) { + super(context, getFilenameWithLocale(NAME, locale.toString()), Suggest.DICT_KEY_CONTACTS); mLocale = locale; mUseFirstLastBigrams = useFirstLastBigramsForLocale(locale); registerObserver(context); diff --git a/java/src/com/android/inputmethod/latin/Dictionary.java b/java/src/com/android/inputmethod/latin/Dictionary.java index 00896c364..ba1298356 100644 --- a/java/src/com/android/inputmethod/latin/Dictionary.java +++ b/java/src/com/android/inputmethod/latin/Dictionary.java @@ -33,6 +33,12 @@ public abstract class Dictionary { public static final int NOT_A_PROBABILITY = -1; + protected final String mDictType; + + public Dictionary(final String dictType) { + mDictType = dictType; + } + /** * Searches for words in the dictionary that match the characters in the composer. Matched * words are returned as an ArrayList. diff --git a/java/src/com/android/inputmethod/latin/DictionaryCollection.java b/java/src/com/android/inputmethod/latin/DictionaryCollection.java index 169e70745..dcc53c59f 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryCollection.java +++ b/java/src/com/android/inputmethod/latin/DictionaryCollection.java @@ -33,11 +33,13 @@ public class DictionaryCollection extends Dictionary { private final String TAG = DictionaryCollection.class.getSimpleName(); protected final CopyOnWriteArrayList mDictionaries; - public DictionaryCollection() { + public DictionaryCollection(final String dictType) { + super(dictType); mDictionaries = new CopyOnWriteArrayList(); } - public DictionaryCollection(Dictionary... dictionaries) { + public DictionaryCollection(final String dictType, Dictionary... dictionaries) { + super(dictType); if (null == dictionaries) { mDictionaries = new CopyOnWriteArrayList(); } else { @@ -46,7 +48,8 @@ public class DictionaryCollection extends Dictionary { } } - public DictionaryCollection(Collection dictionaries) { + public DictionaryCollection(final String dictType, Collection dictionaries) { + super(dictType); mDictionaries = new CopyOnWriteArrayList(dictionaries); mDictionaries.removeAll(Collections.singleton(null)); } diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java index 6d77c4dd2..7ccfe05cf 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java @@ -49,7 +49,8 @@ public class DictionaryFactory { final Locale locale, final boolean useFullEditDistance) { if (null == locale) { Log.e(TAG, "No locale defined for dictionary"); - return new DictionaryCollection(createBinaryDictionary(context, locale)); + return new DictionaryCollection(Suggest.DICT_KEY_MAIN, + createBinaryDictionary(context, locale)); } final LinkedList dictList = new LinkedList(); @@ -59,7 +60,7 @@ public class DictionaryFactory { for (final AssetFileAddress f : assetFileList) { final BinaryDictionary binaryDictionary = new BinaryDictionary(context, f.mFilename, f.mOffset, f.mLength, - useFullEditDistance, locale, Suggest.DIC_MAIN); + useFullEditDistance, locale, Suggest.DICT_KEY_MAIN); if (binaryDictionary.isValidDictionary()) { dictList.add(binaryDictionary); } @@ -69,7 +70,7 @@ public class DictionaryFactory { // If the list is empty, that means we should not use any dictionary (for example, the user // explicitly disabled the main dictionary), so the following is okay. dictList is never // null, but if for some reason it is, DictionaryCollection handles it gracefully. - return new DictionaryCollection(dictList); + return new DictionaryCollection(Suggest.DICT_KEY_MAIN, dictList); } /** @@ -112,7 +113,7 @@ public class DictionaryFactory { return null; } return new BinaryDictionary(context, sourceDir, afd.getStartOffset(), afd.getLength(), - false /* useFullEditDistance */, locale, Suggest.DIC_MAIN); + false /* useFullEditDistance */, locale, Suggest.DICT_KEY_MAIN); } catch (android.content.res.Resources.NotFoundException e) { Log.e(TAG, "Could not find the resource"); return null; @@ -140,7 +141,7 @@ public class DictionaryFactory { long startOffset, long length, final boolean useFullEditDistance, Locale locale) { if (dictionary.isFile()) { return new BinaryDictionary(context, dictionary.getAbsolutePath(), startOffset, length, - useFullEditDistance, locale, Suggest.DIC_MAIN); + useFullEditDistance, locale, Suggest.DICT_KEY_MAIN); } else { Log.e(TAG, "Could not find the file. path=" + dictionary.getAbsolutePath()); return null; diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java index c076fa0f9..1cda9f257 100644 --- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java @@ -76,9 +76,6 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { /** The expandable fusion dictionary used to generate the binary dictionary. */ private FusionDictionary mFusionDictionary; - /** The dictionary type id. */ - public final int mDicTypeId; - /** * The name of this dictionary, used as the filename for storing the binary dictionary. Multiple * dictionary instances with the same filename is supported, with access controlled by @@ -124,11 +121,11 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { * @param context The application context of the parent. * @param filename The filename for this binary dictionary. Multiple dictionaries with the same * filename is supported. - * @param dictType The type of this dictionary. + * @param dictType the dictionary type, as a human-readable string */ public ExpandableBinaryDictionary( - final Context context, final String filename, final int dictType) { - mDicTypeId = dictType; + final Context context, final String filename, final String dictType) { + super(dictType); mFilename = filename; mContext = context; mBinaryDictionary = null; @@ -308,7 +305,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { // Build the new binary dictionary final BinaryDictionary newBinaryDictionary = new BinaryDictionary(mContext, filename, 0, length, true /* useFullEditDistance */, - null, mDicTypeId); + null, mDictType); if (mBinaryDictionary != null) { // Ensure all threads accessing the current dictionary have finished before swapping in diff --git a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java index f19d77be2..e86a657e9 100644 --- a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java +++ b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java @@ -38,7 +38,6 @@ public class ExpandableDictionary extends Dictionary { private Context mContext; private char[] mWordBuilder = new char[BinaryDictionary.MAX_WORD_LENGTH]; - private int mDicTypeId; private int mMaxDepth; private int mInputLength; @@ -152,11 +151,11 @@ public class ExpandableDictionary extends Dictionary { private int[][] mCodes; - public ExpandableDictionary(Context context, int dicTypeId) { + public ExpandableDictionary(final Context context, final String dictType) { + super(dictType); mContext = context; clearDictionary(); mCodes = new int[BinaryDictionary.MAX_WORD_LENGTH][]; - mDicTypeId = dicTypeId; } public void loadDictionary() { diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 25b8fd566..f6ba78674 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -499,8 +499,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // If the locale has changed then recreate the contacts dictionary. This // allows locale dependent rules for handling bigram name predictions. oldContactsDictionary.close(); - dictionaryToUse = new ContactsBinaryDictionary( - this, Suggest.DIC_CONTACTS, locale); + dictionaryToUse = new ContactsBinaryDictionary(this, locale); } else { // Make sure the old contacts dictionary is opened. If it is already open, // this is a no-op, so it's safe to call it anyways. @@ -508,7 +507,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen dictionaryToUse = oldContactsDictionary; } } else { - dictionaryToUse = new ContactsBinaryDictionary(this, Suggest.DIC_CONTACTS, locale); + dictionaryToUse = new ContactsBinaryDictionary(this, locale); } } diff --git a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java index 74f27e3cc..9b20bd690 100644 --- a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java @@ -28,7 +28,7 @@ public class SynchronouslyLoadedContactsBinaryDictionary extends ContactsBinaryD private boolean mClosed; public SynchronouslyLoadedContactsBinaryDictionary(final Context context, final Locale locale) { - super(context, Suggest.DIC_CONTACTS, locale); + super(context, locale); } @Override diff --git a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java index 5bcdb57b5..54c53df0c 100644 --- a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java @@ -69,7 +69,7 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary { public UserBinaryDictionary(final Context context, final String locale, final boolean alsoUseMoreRestrictiveLocales) { - super(context, getFilenameWithLocale(NAME, locale), Suggest.DIC_USER); + super(context, getFilenameWithLocale(NAME, locale), Suggest.DICT_KEY_USER); if (null == locale) throw new NullPointerException(); // Catch the error earlier mLocale = locale; mAlsoUseMoreRestrictiveLocales = alsoUseMoreRestrictiveLocales; diff --git a/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java b/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java index 5095f6582..d14006651 100644 --- a/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java +++ b/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java @@ -128,14 +128,14 @@ public class UserHistoryDictionary extends ExpandableDictionary { } } final UserHistoryDictionary dict = - new UserHistoryDictionary(context, locale, dictTypeId, sp); + new UserHistoryDictionary(context, locale, sp); sLangDictCache.put(locale, new SoftReference(dict)); return dict; } - private UserHistoryDictionary(final Context context, final String locale, final int dicTypeId, - SharedPreferences sp) { - super(context, dicTypeId); + private UserHistoryDictionary(final Context context, final String locale, + final SharedPreferences sp) { + super(context, Suggest.DICT_KEY_USER_HISTORY); mLocale = locale; mPrefs = sp; if (sOpenHelper == null) { diff --git a/java/src/com/android/inputmethod/latin/WhitelistDictionary.java b/java/src/com/android/inputmethod/latin/WhitelistDictionary.java index a0de2f970..dc5706521 100644 --- a/java/src/com/android/inputmethod/latin/WhitelistDictionary.java +++ b/java/src/com/android/inputmethod/latin/WhitelistDictionary.java @@ -37,7 +37,7 @@ public class WhitelistDictionary extends ExpandableDictionary { // TODO: Conform to the async load contact of ExpandableDictionary public WhitelistDictionary(final Context context, final Locale locale) { - super(context, Suggest.DIC_WHITELIST); + super(context, Suggest.DICT_KEY_WHITELIST); // TODO: Move whitelist dictionary into main dictionary. final RunInLocale job = new RunInLocale() { @Override diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp index 3fa45da55..bee0662ee 100644 --- a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp +++ b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp @@ -129,7 +129,7 @@ static jlong latinime_BinaryDictionary_open(JNIEnv *env, jobject object, static int latinime_BinaryDictionary_getSuggestions(JNIEnv *env, jobject object, jlong dict, jlong proximityInfo, jintArray xCoordinatesArray, jintArray yCoordinatesArray, jintArray timesArray, jintArray pointerIdArray, jintArray inputArray, jint arraySize, - jint commitPoint, jboolean isGesture, jint dicTypeId, + jint commitPoint, jboolean isGesture, jintArray prevWordForBigrams, jboolean useFullEditDistance, jcharArray outputArray, jintArray frequencyArray, jintArray spaceIndexArray) { Dictionary *dictionary = (Dictionary*) dict; @@ -148,7 +148,7 @@ static int latinime_BinaryDictionary_getSuggestions(JNIEnv *env, jobject object, jsize prevWordLength = prevWordChars ? env->GetArrayLength(prevWordForBigrams) : 0; int count = dictionary->getSuggestions(pInfo, xCoordinates, yCoordinates, times, pointerIds, inputCodes, arraySize, prevWordChars, prevWordLength, commitPoint, isGesture, - dicTypeId, useFullEditDistance, (unsigned short*) outputChars, + useFullEditDistance, (unsigned short*) outputChars, frequencies, spaceIndices); if (prevWordChars) { env->ReleaseIntArrayElements(prevWordForBigrams, prevWordChars, JNI_ABORT); @@ -260,7 +260,7 @@ void releaseDictBuf(void* dictBuf, const size_t length, int fd) { static JNINativeMethod sMethods[] = { {"openNative", "(Ljava/lang/String;JJIIII)J", (void*)latinime_BinaryDictionary_open}, {"closeNative", "(J)V", (void*)latinime_BinaryDictionary_close}, - {"getSuggestionsNative", "(JJ[I[I[I[I[IIIZI[IZ[C[I[I)I", + {"getSuggestionsNative", "(JJ[I[I[I[I[IIIZ[IZ[C[I[I)I", (void*) latinime_BinaryDictionary_getSuggestions}, {"getFrequencyNative", "(J[II)I", (void*)latinime_BinaryDictionary_getFrequency}, {"isValidBigramNative", "(J[I[I)Z", (void*)latinime_BinaryDictionary_isValidBigram}, diff --git a/native/jni/src/dictionary.h b/native/jni/src/dictionary.h index 708cb0909..8b4769431 100644 --- a/native/jni/src/dictionary.h +++ b/native/jni/src/dictionary.h @@ -36,14 +36,14 @@ class Dictionary { int getSuggestions(ProximityInfo *proximityInfo, int *xcoordinates, int *ycoordinates, int *times, int *pointerIds, int *codes, int codesSize, int *prevWordChars, - int prevWordLength, int commitPoint, bool isGesture, int dicTypeId, + int prevWordLength, int commitPoint, bool isGesture, bool useFullEditDistance, unsigned short *outWords, int *frequencies, int *spaceIndices) { int result = 0; if (isGesture) { mGestureDecoder->setPrevWord(prevWordChars, prevWordLength); result = mGestureDecoder->getSuggestions(proximityInfo, xcoordinates, ycoordinates, - times, pointerIds, codes, codesSize, commitPoint, dicTypeId == 1 /* main */, + times, pointerIds, codes, codesSize, commitPoint, outWords, frequencies, spaceIndices); } else { std::map bigramMap; diff --git a/native/jni/src/gesture/impl/gesture_decoder_impl.h b/native/jni/src/gesture/impl/gesture_decoder_impl.h index be4e8b3c2..0ca89941c 100644 --- a/native/jni/src/gesture/impl/gesture_decoder_impl.h +++ b/native/jni/src/gesture/impl/gesture_decoder_impl.h @@ -30,7 +30,7 @@ class GestureDecoderImpl : public IncrementalDecoder { } int getSuggestions(ProximityInfo *pInfo, int *inputXs, int *inputYs, int *times, - int *pointerIds, int *codes, int inputSize, int commitPoint, bool isMainDict, + int *pointerIds, int *codes, int inputSize, int commitPoint, unsigned short *outWords, int *frequencies, int *outputIndices) { return 0; } diff --git a/native/jni/src/gesture/incremental_decoder_interface.h b/native/jni/src/gesture/incremental_decoder_interface.h index c5404a40c..565f89c90 100644 --- a/native/jni/src/gesture/incremental_decoder_interface.h +++ b/native/jni/src/gesture/incremental_decoder_interface.h @@ -28,7 +28,7 @@ class IncrementalDecoderInterface { public: virtual int getSuggestions(ProximityInfo *pInfo, int *inputXs, int *inputYs, int *times, - int *pointerIds, int *codes, int inputSize, int commitPoint, bool isMainDict, + int *pointerIds, int *codes, int inputSize, int commitPoint, unsigned short *outWords, int *frequencies, int *outputIndices) = 0; virtual void reset() = 0; virtual void setDict(const UnigramDictionary *dict, const BigramDictionary *bigram, -- cgit v1.2.3-83-g751a From d8f0caa406a0ca1df488baeb3af05528085755b7 Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Wed, 27 Jun 2012 18:08:08 +0900 Subject: Move constants to a better place. Change-Id: I5c27a3ed99b17f850e26a8503de16f001c7111c1 --- .../android/inputmethod/latin/AutoCorrection.java | 6 ++--- .../latin/ContactsBinaryDictionary.java | 2 +- .../com/android/inputmethod/latin/Dictionary.java | 8 +++++++ .../inputmethod/latin/DictionaryFactory.java | 10 ++++----- .../src/com/android/inputmethod/latin/Suggest.java | 26 ++++++++-------------- .../inputmethod/latin/UserBinaryDictionary.java | 2 +- .../inputmethod/latin/UserHistoryDictionary.java | 2 +- .../inputmethod/latin/WhitelistDictionary.java | 2 +- 8 files changed, 29 insertions(+), 29 deletions(-) (limited to 'java/src/com/android/inputmethod/latin/DictionaryFactory.java') diff --git a/java/src/com/android/inputmethod/latin/AutoCorrection.java b/java/src/com/android/inputmethod/latin/AutoCorrection.java index e0452483c..30b681651 100644 --- a/java/src/com/android/inputmethod/latin/AutoCorrection.java +++ b/java/src/com/android/inputmethod/latin/AutoCorrection.java @@ -56,7 +56,7 @@ public class AutoCorrection { } final CharSequence lowerCasedWord = word.toString().toLowerCase(); for (final String key : dictionaries.keySet()) { - if (key.equals(Suggest.DICT_KEY_WHITELIST)) continue; + if (key.equals(Dictionary.TYPE_WHITELIST)) continue; final Dictionary dictionary = dictionaries.get(key); // It's unclear how realistically 'dictionary' can be null, but the monkey is somehow // managing to get null in here. Presumably the language is changing to a language with @@ -81,7 +81,7 @@ public class AutoCorrection { } int maxFreq = -1; for (final String key : dictionaries.keySet()) { - if (key.equals(Suggest.DICT_KEY_WHITELIST)) continue; + if (key.equals(Dictionary.TYPE_WHITELIST)) continue; final Dictionary dictionary = dictionaries.get(key); if (null == dictionary) continue; final int tempFreq = dictionary.getFrequency(word); @@ -96,7 +96,7 @@ public class AutoCorrection { final ConcurrentHashMap dictionaries, final CharSequence word, final boolean ignoreCase) { final WhitelistDictionary whitelistDictionary = - (WhitelistDictionary)dictionaries.get(Suggest.DICT_KEY_WHITELIST); + (WhitelistDictionary)dictionaries.get(Dictionary.TYPE_WHITELIST); // If "word" is in the whitelist dictionary, it should not be auto corrected. if (whitelistDictionary != null && whitelistDictionary.shouldForciblyAutoCorrectFrom(word)) { diff --git a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java index fbcaddae8..5edc4314f 100644 --- a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java @@ -63,7 +63,7 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary { private final boolean mUseFirstLastBigrams; public ContactsBinaryDictionary(final Context context, Locale locale) { - super(context, getFilenameWithLocale(NAME, locale.toString()), Suggest.DICT_KEY_CONTACTS); + super(context, getFilenameWithLocale(NAME, locale.toString()), Dictionary.TYPE_CONTACTS); mLocale = locale; mUseFirstLastBigrams = useFirstLastBigramsForLocale(locale); registerObserver(context); diff --git a/java/src/com/android/inputmethod/latin/Dictionary.java b/java/src/com/android/inputmethod/latin/Dictionary.java index ba1298356..0a853c4cb 100644 --- a/java/src/com/android/inputmethod/latin/Dictionary.java +++ b/java/src/com/android/inputmethod/latin/Dictionary.java @@ -33,6 +33,14 @@ public abstract class Dictionary { public static final int NOT_A_PROBABILITY = -1; + public static final String TYPE_USER_TYPED = "user_typed"; + public static final String TYPE_MAIN = "main"; + public static final String TYPE_CONTACTS = "contacts"; + // User dictionary, the system-managed one. + public static final String TYPE_USER = "user"; + // User history dictionary internal to LatinIME. + public static final String TYPE_USER_HISTORY = "history"; + public static final String TYPE_WHITELIST ="whitelist"; protected final String mDictType; public Dictionary(final String dictType) { diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java index 7ccfe05cf..06a5f4b72 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java @@ -49,7 +49,7 @@ public class DictionaryFactory { final Locale locale, final boolean useFullEditDistance) { if (null == locale) { Log.e(TAG, "No locale defined for dictionary"); - return new DictionaryCollection(Suggest.DICT_KEY_MAIN, + return new DictionaryCollection(Dictionary.TYPE_MAIN, createBinaryDictionary(context, locale)); } @@ -60,7 +60,7 @@ public class DictionaryFactory { for (final AssetFileAddress f : assetFileList) { final BinaryDictionary binaryDictionary = new BinaryDictionary(context, f.mFilename, f.mOffset, f.mLength, - useFullEditDistance, locale, Suggest.DICT_KEY_MAIN); + useFullEditDistance, locale, Dictionary.TYPE_MAIN); if (binaryDictionary.isValidDictionary()) { dictList.add(binaryDictionary); } @@ -70,7 +70,7 @@ public class DictionaryFactory { // If the list is empty, that means we should not use any dictionary (for example, the user // explicitly disabled the main dictionary), so the following is okay. dictList is never // null, but if for some reason it is, DictionaryCollection handles it gracefully. - return new DictionaryCollection(Suggest.DICT_KEY_MAIN, dictList); + return new DictionaryCollection(Dictionary.TYPE_MAIN, dictList); } /** @@ -113,7 +113,7 @@ public class DictionaryFactory { return null; } return new BinaryDictionary(context, sourceDir, afd.getStartOffset(), afd.getLength(), - false /* useFullEditDistance */, locale, Suggest.DICT_KEY_MAIN); + false /* useFullEditDistance */, locale, Dictionary.TYPE_MAIN); } catch (android.content.res.Resources.NotFoundException e) { Log.e(TAG, "Could not find the resource"); return null; @@ -141,7 +141,7 @@ public class DictionaryFactory { long startOffset, long length, final boolean useFullEditDistance, Locale locale) { if (dictionary.isFile()) { return new BinaryDictionary(context, dictionary.getAbsolutePath(), startOffset, length, - useFullEditDistance, locale, Suggest.DICT_KEY_MAIN); + useFullEditDistance, locale, Dictionary.TYPE_MAIN); } else { Log.e(TAG, "Could not find the file. path=" + dictionary.getAbsolutePath()); return null; diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index 7c72f7f9a..9f3df05e7 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -46,15 +46,6 @@ public class Suggest { // TODO: rename this to CORRECTION_ON public static final int CORRECTION_FULL = 1; - public static final String DICT_KEY_USER_TYPED = "user_typed"; - public static final String DICT_KEY_MAIN = "main"; - public static final String DICT_KEY_CONTACTS = "contacts"; - // User dictionary, the system-managed one. - public static final String DICT_KEY_USER = "user"; - // User history dictionary internal to LatinIME - public static final String DICT_KEY_USER_HISTORY = "history"; - public static final String DICT_KEY_WHITELIST ="whitelist"; - private static final boolean DBG = LatinImeLogger.sDBG; private Dictionary mMainDictionary; @@ -88,13 +79,13 @@ public class Suggest { startOffset, length /* useFullEditDistance */, false, locale); mLocale = locale; mMainDictionary = mainDict; - addOrReplaceDictionary(mDictionaries, DICT_KEY_MAIN, mainDict); + addOrReplaceDictionary(mDictionaries, Dictionary.TYPE_MAIN, mainDict); initWhitelistAndAutocorrectAndPool(context, locale); } private void initWhitelistAndAutocorrectAndPool(final Context context, final Locale locale) { mWhiteListDictionary = new WhitelistDictionary(context, locale); - addOrReplaceDictionary(mDictionaries, DICT_KEY_WHITELIST, mWhiteListDictionary); + addOrReplaceDictionary(mDictionaries, Dictionary.TYPE_WHITELIST, mWhiteListDictionary); } private void initAsynchronously(final Context context, final Locale locale) { @@ -123,7 +114,7 @@ public class Suggest { public void run() { final DictionaryCollection newMainDict = DictionaryFactory.createMainDictionaryFromManager(context, locale); - addOrReplaceDictionary(mDictionaries, DICT_KEY_MAIN, newMainDict); + addOrReplaceDictionary(mDictionaries, Dictionary.TYPE_MAIN, newMainDict); mMainDictionary = newMainDict; } }.start(); @@ -156,7 +147,7 @@ public class Suggest { * before the main dictionary, if set. This refers to the system-managed user dictionary. */ public void setUserDictionary(UserBinaryDictionary userDictionary) { - addOrReplaceDictionary(mDictionaries, DICT_KEY_USER, userDictionary); + addOrReplaceDictionary(mDictionaries, Dictionary.TYPE_USER, userDictionary); } /** @@ -166,11 +157,11 @@ public class Suggest { */ public void setContactsDictionary(ContactsBinaryDictionary contactsDictionary) { mContactsDict = contactsDictionary; - addOrReplaceDictionary(mDictionaries, DICT_KEY_CONTACTS, contactsDictionary); + addOrReplaceDictionary(mDictionaries, Dictionary.TYPE_CONTACTS, contactsDictionary); } public void setUserHistoryDictionary(UserHistoryDictionary userHistoryDictionary) { - addOrReplaceDictionary(mDictionaries, DICT_KEY_USER_HISTORY, userHistoryDictionary); + addOrReplaceDictionary(mDictionaries, Dictionary.TYPE_USER_HISTORY, userHistoryDictionary); } public void setAutoCorrectionThreshold(float threshold) { @@ -211,7 +202,7 @@ public class Suggest { ? typedWord.substring(0, typedWord.length() - mTrailingSingleQuotesCount) : typedWord; // Treating USER_TYPED as UNIGRAM suggestion for logging now. - LatinImeLogger.onAddSuggestedWord(typedWord, DICT_KEY_USER_TYPED); + LatinImeLogger.onAddSuggestedWord(typedWord, Dictionary.TYPE_USER_TYPED); if (wordComposer.size() <= 1 && isCorrectionEnabled) { // At first character typed, search only the bigrams @@ -248,7 +239,8 @@ public class Suggest { // At second character typed, search the unigrams (scores being affected by bigrams) for (final String key : mDictionaries.keySet()) { // Skip UserUnigramDictionary and WhitelistDictionary to lookup - if (key.equals(DICT_KEY_USER_HISTORY) || key.equals(DICT_KEY_WHITELIST)) + if (key.equals(Dictionary.TYPE_USER_HISTORY) + || key.equals(Dictionary.TYPE_WHITELIST)) continue; final Dictionary dictionary = mDictionaries.get(key); final ArrayList localSuggestions = dictionary.getWords( diff --git a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java index 54c53df0c..8cef6fa20 100644 --- a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java @@ -69,7 +69,7 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary { public UserBinaryDictionary(final Context context, final String locale, final boolean alsoUseMoreRestrictiveLocales) { - super(context, getFilenameWithLocale(NAME, locale), Suggest.DICT_KEY_USER); + super(context, getFilenameWithLocale(NAME, locale), Dictionary.TYPE_USER); if (null == locale) throw new NullPointerException(); // Catch the error earlier mLocale = locale; mAlsoUseMoreRestrictiveLocales = alsoUseMoreRestrictiveLocales; diff --git a/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java b/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java index 52b197dca..73fa83f9a 100644 --- a/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java +++ b/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java @@ -134,7 +134,7 @@ public class UserHistoryDictionary extends ExpandableDictionary { private UserHistoryDictionary(final Context context, final String locale, final SharedPreferences sp) { - super(context, Suggest.DICT_KEY_USER_HISTORY); + super(context, Dictionary.TYPE_USER_HISTORY); mLocale = locale; mPrefs = sp; if (sOpenHelper == null) { diff --git a/java/src/com/android/inputmethod/latin/WhitelistDictionary.java b/java/src/com/android/inputmethod/latin/WhitelistDictionary.java index dc5706521..3af22140e 100644 --- a/java/src/com/android/inputmethod/latin/WhitelistDictionary.java +++ b/java/src/com/android/inputmethod/latin/WhitelistDictionary.java @@ -37,7 +37,7 @@ public class WhitelistDictionary extends ExpandableDictionary { // TODO: Conform to the async load contact of ExpandableDictionary public WhitelistDictionary(final Context context, final Locale locale) { - super(context, Suggest.DICT_KEY_WHITELIST); + super(context, Dictionary.TYPE_WHITELIST); // TODO: Move whitelist dictionary into main dictionary. final RunInLocale job = new RunInLocale() { @Override -- cgit v1.2.3-83-g751a