diff options
Diffstat (limited to 'java/src')
13 files changed, 91 insertions, 220 deletions
diff --git a/java/src/com/android/inputmethod/dictionarypack/ActionBatch.java b/java/src/com/android/inputmethod/dictionarypack/ActionBatch.java index ee5106b5a..09f8032cc 100644 --- a/java/src/com/android/inputmethod/dictionarypack/ActionBatch.java +++ b/java/src/com/android/inputmethod/dictionarypack/ActionBatch.java @@ -26,9 +26,7 @@ import android.text.TextUtils; import android.util.Log; import com.android.inputmethod.compat.DownloadManagerCompatUtils; -import com.android.inputmethod.latin.BinaryDictionaryFileDumper; import com.android.inputmethod.latin.R; -import com.android.inputmethod.latin.common.LocaleUtils; import com.android.inputmethod.latin.utils.ApplicationUtils; import com.android.inputmethod.latin.utils.DebugLogUtils; @@ -212,17 +210,9 @@ public final class ActionBatch { + " for an InstallAfterDownload action. Bailing out."); return; } - DebugLogUtils.l("Setting word list as installed"); final SQLiteDatabase db = MetadataDbHelper.getDb(context, mClientId); MetadataDbHelper.markEntryAsFinishedDownloadingAndInstalled(db, mWordListValues); - - // Install the downloaded file by un-compressing and moving it to the staging - // directory. Ideally, we should do this before updating the DB, but the - // installDictToStagingFromContentProvider() relies on the db being updated. - final String localeString = mWordListValues.getAsString(MetadataDbHelper.LOCALE_COLUMN); - BinaryDictionaryFileDumper.installDictToStagingFromContentProvider( - LocaleUtils.constructLocaleFromString(localeString), context, false); } } diff --git a/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java b/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java index 6570171a6..e61547a9d 100644 --- a/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java +++ b/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java @@ -592,8 +592,6 @@ public final class UpdateHandler { * Warn Android Keyboard that the state of dictionaries changed and it should refresh its data. */ private static void signalNewDictionaryState(final Context context) { - // TODO: Also provide the locale of the updated dictionary so that the LatinIme - // does not have to reset if it is a different locale. final Intent newDictBroadcast = new Intent(DictionaryPackConstants.NEW_DICTIONARY_INTENT_ACTION); context.sendBroadcast(newDictBroadcast); diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java index 4b242c5f5..bc62f3ae3 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java @@ -29,7 +29,6 @@ import android.util.Log; import com.android.inputmethod.dictionarypack.DictionaryPackConstants; import com.android.inputmethod.dictionarypack.MD5Calculator; -import com.android.inputmethod.latin.common.FileUtils; import com.android.inputmethod.latin.define.DecoderSpecificConstants; import com.android.inputmethod.latin.utils.DictionaryInfoUtils; import com.android.inputmethod.latin.utils.DictionaryInfoUtils.DictionaryInfo; @@ -221,11 +220,11 @@ public final class BinaryDictionaryFileDumper { } /** - * Stages a word list the id of which is passed as an argument. This will write the file + * Caches a word list the id of which is passed as an argument. This will write the file * to the cache file name designated by its id and locale, overwriting it if already present * and creating it (and its containing directory) if necessary. */ - private static void installWordListToStaging(final String wordlistId, final String locale, + private static void cacheWordList(final String wordlistId, final String locale, final String rawChecksum, final ContentProviderClient providerClient, final Context context) { final int COMPRESSED_CRYPTED_COMPRESSED = 0; @@ -247,7 +246,7 @@ public final class BinaryDictionaryFileDumper { return; } final String finalFileName = - DictionaryInfoUtils.getStagingFileName(wordlistId, locale, context); + DictionaryInfoUtils.getCacheFileName(wordlistId, locale, context); String tempFileName; try { tempFileName = BinaryDictionaryGetter.getTempFileName(wordlistId, context); @@ -321,21 +320,23 @@ public final class BinaryDictionaryFileDumper { } } - // move the output file to the final staging file. final File finalFile = new File(finalFileName); - FileUtils.renameTo(outputFile, finalFile); - + finalFile.delete(); + if (!outputFile.renameTo(finalFile)) { + throw new IOException("Can't move the file to its final name"); + } wordListUriBuilder.appendQueryParameter(QUERY_PARAMETER_DELETE_RESULT, QUERY_PARAMETER_SUCCESS); if (0 >= providerClient.delete(wordListUriBuilder.build(), null, null)) { Log.e(TAG, "Could not have the dictionary pack delete a word list"); } - Log.d(TAG, "Successfully copied file for wordlist ID " + wordlistId); + BinaryDictionaryGetter.removeFilesWithIdExcept(context, wordlistId, finalFile); + Log.e(TAG, "Successfully copied file for wordlist ID " + wordlistId); // Success! Close files (through the finally{} clause) and return. return; } catch (Exception e) { if (DEBUG) { - Log.e(TAG, "Can't open word list in mode " + mode, e); + Log.i(TAG, "Can't open word list in mode " + mode, e); } if (null != outputFile) { // This may or may not fail. The file may not have been created if the @@ -402,7 +403,7 @@ public final class BinaryDictionaryFileDumper { } /** - * Queries a content provider for word list data for some locale and stage the returned files + * Queries a content provider for word list data for some locale and cache the returned files * * This will query a content provider for word list data for a given locale, and copy the * files locally so that they can be mmap'ed. This may overwrite previously cached word lists @@ -410,7 +411,7 @@ public final class BinaryDictionaryFileDumper { * @throw FileNotFoundException if the provider returns non-existent data. * @throw IOException if the provider-returned data could not be read. */ - public static void installDictToStagingFromContentProvider(final Locale locale, + public static void cacheWordListsFromContentProvider(final Locale locale, final Context context, final boolean hasDefaultWordList) { final ContentProviderClient providerClient; try { @@ -428,8 +429,7 @@ public final class BinaryDictionaryFileDumper { final List<WordListInfo> idList = getWordListWordListInfos(locale, context, hasDefaultWordList); for (WordListInfo id : idList) { - installWordListToStaging(id.mId, id.mLocale, id.mRawChecksum, providerClient, - context); + cacheWordList(id.mId, id.mLocale, id.mRawChecksum, providerClient, context); } } finally { providerClient.release(); @@ -437,19 +437,6 @@ public final class BinaryDictionaryFileDumper { } /** - * Downloads the dictionary if it was never requested/used. - * - * @param locale locale to download - * @param context the context for resources and providers. - * @param hasDefaultWordList whether the default wordlist exists in the resources. - */ - public static void downloadDictIfNeverRequested(final Locale locale, - final Context context, final boolean hasDefaultWordList) { - Log.d("inamul_tag", "BinaryDictionaryFileDumper.downloadDictIfNeverRequested()"); - getWordListWordListInfos(locale, context, hasDefaultWordList); - } - - /** * Copies the data in an input stream to a target file if the magic number matches. * * If the magic number does not match the expected value, this method throws an diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java index 60016371b..5f2a112ba 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java @@ -195,6 +195,39 @@ final public class BinaryDictionaryGetter { return result; } + /** + * Remove all files with the passed id, except the passed file. + * + * If a dictionary with a given ID has a metadata change that causes it to change + * path, we need to remove the old version. The only way to do this is to check all + * installed files for a matching ID in a different directory. + */ + public static void removeFilesWithIdExcept(final Context context, final String id, + final File fileToKeep) { + try { + final File canonicalFileToKeep = fileToKeep.getCanonicalFile(); + final File[] directoryList = DictionaryInfoUtils.getCachedDirectoryList(context); + if (null == directoryList) return; + for (File directory : directoryList) { + // There is one directory per locale. See #getCachedDirectoryList + if (!directory.isDirectory()) continue; + final File[] wordLists = directory.listFiles(); + if (null == wordLists) continue; + for (File wordList : wordLists) { + final String fileId = + DictionaryInfoUtils.getWordListIdFromFileName(wordList.getName()); + if (fileId.equals(id)) { + if (!canonicalFileToKeep.equals(wordList.getCanonicalFile())) { + wordList.delete(); + } + } + } + } + } catch (java.io.IOException e) { + Log.e(TAG, "IOException trying to cleanup files", e); + } + } + // ## HACK ## we prevent usage of a dictionary before version 18. The reason for this is, since // those do not include whitelist entries, the new code with an old version of the dictionary // would lose whitelist functionality. @@ -241,18 +274,12 @@ final public class BinaryDictionaryGetter { */ public static ArrayList<AssetFileAddress> getDictionaryFiles(final Locale locale, final Context context, boolean notifyDictionaryPackForUpdates) { - if (notifyDictionaryPackForUpdates) { - final boolean hasDefaultWordList = DictionaryInfoUtils.isDictionaryAvailable( - context, locale); - // It makes sure that the first time keyboard comes up and the dictionaries are reset, - // the DB is populated with the appropriate values for each locale. Helps in downloading - // the dictionaries when the user enables and switches new languages before the - // DictionaryService runs. - BinaryDictionaryFileDumper.downloadDictIfNeverRequested( - locale, context, hasDefaultWordList); - // Move a staging files to the cache ddirectories if any. - DictionaryInfoUtils.moveStagingFilesIfExists(context); + final boolean hasDefaultWordList = DictionaryInfoUtils.isDictionaryAvailable( + context, locale); + if (notifyDictionaryPackForUpdates) { + BinaryDictionaryFileDumper.cacheWordListsFromContentProvider(locale, context, + hasDefaultWordList); } final File[] cachedWordLists = getCachedWordLists(locale.toString(), context); final String mainDictId = DictionaryInfoUtils.getMainDictId(locale); diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java index 02015da09..ff798abd6 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java @@ -17,7 +17,6 @@ package com.android.inputmethod.latin; import android.content.Context; -import android.util.LruCache; import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.keyboard.Keyboard; @@ -56,18 +55,6 @@ public interface DictionaryFacilitator { Dictionary.TYPE_USER}; /** - * The facilitator will put words into the cache whenever it decodes them. - * @param cache - */ - void setValidSpellingWordReadCache(final LruCache<String, Boolean> cache); - - /** - * The facilitator will get words from the cache whenever it needs to check their spelling. - * @param cache - */ - void setValidSpellingWordWriteCache(final LruCache<String, Boolean> cache); - - /** * Returns whether this facilitator is exactly for this locale. * * @param locale the locale to test against @@ -101,16 +88,12 @@ public interface DictionaryFacilitator { * * WARNING: The service methods that call start/finish are very spammy. */ - void onFinishInput(Context context); + void onFinishInput(); boolean isActive(); Locale getLocale(); - boolean usesContacts(); - - String getAccount(); - void resetDictionaries( final Context context, final Locale newLocale, @@ -166,7 +149,7 @@ public interface DictionaryFacilitator { boolean isValidSuggestionWord(final String word); - boolean clearUserHistoryDictionary(final Context context); + void clearUserHistoryDictionary(final Context context); String dump(final Context context); diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorImpl.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorImpl.java index 63064ba3e..7233d27ab 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorImpl.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorImpl.java @@ -19,7 +19,6 @@ package com.android.inputmethod.latin; import android.content.Context; import android.text.TextUtils; import android.util.Log; -import android.util.LruCache; import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.keyboard.Keyboard; @@ -83,19 +82,6 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator { private static final Class<?>[] DICT_FACTORY_METHOD_ARG_TYPES = new Class[] { Context.class, Locale.class, File.class, String.class, String.class }; - private LruCache<String, Boolean> mValidSpellingWordReadCache; - private LruCache<String, Boolean> mValidSpellingWordWriteCache; - - @Override - public void setValidSpellingWordReadCache(final LruCache<String, Boolean> cache) { - mValidSpellingWordReadCache = cache; - } - - @Override - public void setValidSpellingWordWriteCache(final LruCache<String, Boolean> cache) { - mValidSpellingWordWriteCache = cache; - } - @Override public boolean isForLocale(final Locale locale) { return locale != null && locale.equals(mDictionaryGroup.mLocale); @@ -221,7 +207,7 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator { } @Override - public void onFinishInput(Context context) { + public void onFinishInput() { } @Override @@ -234,16 +220,6 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator { return mDictionaryGroup.mLocale; } - @Override - public boolean usesContacts() { - return mDictionaryGroup.getSubDict(Dictionary.TYPE_CONTACTS) != null; - } - - @Override - public String getAccount() { - return null; - } - @Nullable private static ExpandableBinaryDictionary getSubDict(final String dictType, final Context context, final Locale locale, final File dictFile, @@ -365,10 +341,6 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator { dictionarySetToCleanup.closeDict(dictType); } } - - if (mValidSpellingWordWriteCache != null) { - mValidSpellingWordWriteCache.evictAll(); - } } private void asyncReloadUninitializedMainDictionaries(final Context context, @@ -492,10 +464,6 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator { public void addToUserHistory(final String suggestion, final boolean wasAutoCapitalized, @Nonnull final NgramContext ngramContext, final long timeStampInSeconds, final boolean blockPotentiallyOffensive) { - // Update the spelling cache before learning. Words that are not yet added to user history - // and appear in no other language model are not considered valid. - putWordIntoValidSpellingWordCache("addToUserHistory", suggestion); - final String[] words = suggestion.split(Constants.WORD_SEPARATOR); NgramContext ngramContextForCurrentWord = ngramContext; for (int i = 0; i < words.length; i++) { @@ -509,12 +477,6 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator { } } - private void putWordIntoValidSpellingWordCache(final String caller, final String word) { - final String spellingWord = word.toLowerCase(getLocale()); - final boolean isValid = isValidSpellingWord(spellingWord); - mValidSpellingWordWriteCache.put(spellingWord, isValid); - } - private void addWordToUserHistory(final DictionaryGroup dictionaryGroup, final NgramContext ngramContext, final String word, final boolean wasAutoCapitalized, final int timeStampInSeconds, final boolean blockPotentiallyOffensive) { @@ -581,10 +543,6 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator { if (eventType != Constants.EVENT_BACKSPACE) { removeWord(Dictionary.TYPE_USER_HISTORY, word); } - - // Update the spelling cache after unlearning. Words that are removed from user history - // and appear in no other language model are not considered valid. - putWordIntoValidSpellingWordCache("unlearnFromUserHistory", word.toLowerCase()); } // TODO: Revise the way to fusion suggestion results. @@ -619,14 +577,6 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator { } public boolean isValidSpellingWord(final String word) { - if (mValidSpellingWordReadCache != null) { - final String spellingWord = word.toLowerCase(getLocale()); - final Boolean cachedValue = mValidSpellingWordReadCache.get(spellingWord); - if (cachedValue != null) { - return cachedValue; - } - } - return isValidWord(word, ALL_DICTIONARY_TYPES); } @@ -670,18 +620,16 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator { return maxFreq; } - private boolean clearSubDictionary(final String dictName) { + private void clearSubDictionary(final String dictName) { final ExpandableBinaryDictionary dictionary = mDictionaryGroup.getSubDict(dictName); - if (dictionary == null) { - return false; + if (dictionary != null) { + dictionary.clear(); } - dictionary.clear(); - return true; } @Override - public boolean clearUserHistoryDictionary(final Context context) { - return clearSubDictionary(Dictionary.TYPE_USER_HISTORY); + public void clearUserHistoryDictionary(final Context context) { + clearSubDictionary(Dictionary.TYPE_USER_HISTORY); } @Override diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 089670ebf..330be377b 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -972,7 +972,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen void onFinishInputInternal() { super.onFinishInput(); - mDictionaryFacilitator.onFinishInput(this); + mDictionaryFacilitator.onFinishInput(); final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView(); if (mainKeyboardView != null) { mainKeyboardView.closing(); diff --git a/java/src/com/android/inputmethod/latin/SystemBroadcastReceiver.java b/java/src/com/android/inputmethod/latin/SystemBroadcastReceiver.java index 26c5e0034..0d081e0d2 100644 --- a/java/src/com/android/inputmethod/latin/SystemBroadcastReceiver.java +++ b/java/src/com/android/inputmethod/latin/SystemBroadcastReceiver.java @@ -29,14 +29,13 @@ import android.util.Log; import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodSubtype; +import com.android.inputmethod.dictionarypack.CommonPreferences; import com.android.inputmethod.dictionarypack.DictionaryPackConstants; import com.android.inputmethod.keyboard.KeyboardLayoutSet; import com.android.inputmethod.latin.settings.Settings; import com.android.inputmethod.latin.setup.SetupActivity; import com.android.inputmethod.latin.utils.UncachedInputMethodManagerUtils; -import java.util.Locale; - /** * This class detects the {@link Intent#ACTION_MY_PACKAGE_REPLACED} broadcast intent when this IME * package has been replaced by a newer version of the same package. This class also detects @@ -77,22 +76,6 @@ public final class SystemBroadcastReceiver extends BroadcastReceiver { richImm.setAdditionalInputMethodSubtypes(additionalSubtypes); toggleAppIcon(context); downloadLatestDictionaries(context); - // TODO: This is only for dogfood builds. Remove this from the final release. - DictionaryFacilitator keyboardFacilitator = - DictionaryFacilitatorProvider.getDictionaryFacilitator(false); - boolean historyCleared = keyboardFacilitator.clearUserHistoryDictionary(context); - Locale keyboardLocale = keyboardFacilitator.getLocale(); - if (historyCleared && keyboardLocale != null) { - keyboardFacilitator.resetDictionaries( - context, - keyboardLocale, - keyboardFacilitator.usesContacts(), - true /* history */, - true /* force */, - keyboardFacilitator.getAccount(), - "" /* prefix */, - null /* listener */); - } } else if (Intent.ACTION_BOOT_COMPLETED.equals(intentAction)) { Log.i(TAG, "Boot has been completed"); toggleAppIcon(context); @@ -126,7 +109,7 @@ public final class SystemBroadcastReceiver extends BroadcastReceiver { context.sendBroadcast(updateIntent); } - public static void toggleAppIcon(final Context context) { + private static void toggleAppIcon(final Context context) { final int appInfoFlags = context.getApplicationInfo().flags; final boolean isSystemApp = (appInfoFlags & ApplicationInfo.FLAG_SYSTEM) > 0; if (Log.isLoggable(TAG, Log.INFO)) { diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java index 975ed7c01..f7dbc0a4d 100644 --- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java +++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java @@ -398,8 +398,9 @@ public final class InputLogic { if (!TextUtils.isEmpty(mWordBeingCorrectedByCursor)) { final int timeStampInSeconds = (int)TimeUnit.MILLISECONDS.toSeconds( System.currentTimeMillis()); - performAdditionToUserHistoryDictionary(settingsValues, mWordBeingCorrectedByCursor, - NgramContext.EMPTY_PREV_WORDS_INFO); + mDictionaryFacilitator.addToUserHistory(mWordBeingCorrectedByCursor, false, + NgramContext.EMPTY_PREV_WORDS_INFO, timeStampInSeconds, + settingsValues.mBlockPotentiallyOffensive); } } else { // resetEntireInputState calls resetCachesUponCursorMove, but forcing the diff --git a/java/src/com/android/inputmethod/latin/settings/AdvancedSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/AdvancedSettingsFragment.java index a6fb7f1f1..f2e1aed4c 100644 --- a/java/src/com/android/inputmethod/latin/settings/AdvancedSettingsFragment.java +++ b/java/src/com/android/inputmethod/latin/settings/AdvancedSettingsFragment.java @@ -26,7 +26,6 @@ import android.preference.Preference; import com.android.inputmethod.latin.AudioAndHapticFeedbackManager; import com.android.inputmethod.latin.R; -import com.android.inputmethod.latin.SystemBroadcastReceiver; import com.android.inputmethod.latin.define.ProductionFlags; /** @@ -107,8 +106,6 @@ public final class AdvancedSettingsFragment extends SubScreenFragment { if (key.equals(Settings.PREF_POPUP_ON)) { setPreferenceEnabled(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY, Settings.readKeyPreviewPopupEnabled(prefs, res)); - } else if (key.equals(Settings.PREF_SHOW_SETUP_WIZARD_ICON)) { - SystemBroadcastReceiver.toggleAppIcon(getActivity()); } updateListPreferenceSummaryToCurrentValue(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY); refreshEnablingsOfKeypressSoundAndVibrationSettings(); diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerSession.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerSession.java index c7622e7a1..2c690aea7 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerSession.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerSession.java @@ -84,7 +84,8 @@ public final class AndroidSpellCheckerSession extends AndroidWordLevelSpellCheck if (TextUtils.isEmpty(splitText)) { continue; } - if (mSuggestionsCache.getSuggestionsFromCache(splitText.toString()) == null) { + if (mSuggestionsCache.getSuggestionsFromCache(splitText.toString(), ngramContext) + == null) { continue; } final int newLength = splitText.length(); diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java index 9223923a7..1322ce240 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java @@ -71,26 +71,30 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session { } protected static final class SuggestionsCache { + private static final char CHAR_DELIMITER = '\uFFFC'; private static final int MAX_CACHE_SIZE = 50; private final LruCache<String, SuggestionsParams> mUnigramSuggestionsInfoCache = new LruCache<>(MAX_CACHE_SIZE); - private static String generateKey(final String query) { - return query + ""; + private static String generateKey(final String query, final NgramContext ngramContext) { + if (TextUtils.isEmpty(query) || !ngramContext.isValid()) { + return query; + } + return query + CHAR_DELIMITER + ngramContext; } - public SuggestionsParams getSuggestionsFromCache(final String query) { - return mUnigramSuggestionsInfoCache.get(query); + public SuggestionsParams getSuggestionsFromCache(String query, + final NgramContext ngramContext) { + return mUnigramSuggestionsInfoCache.get(generateKey(query, ngramContext)); } - public void putSuggestionsToCache( - final String query, final String[] suggestions, final int flags) { + public void putSuggestionsToCache(final String query, final NgramContext ngramContext, + final String[] suggestions, final int flags) { if (suggestions == null || TextUtils.isEmpty(query)) { return; } mUnigramSuggestionsInfoCache.put( - generateKey(query), - new SuggestionsParams(suggestions, flags)); + generateKey(query, ngramContext), new SuggestionsParams(suggestions, flags)); } public void clearCache() { @@ -228,7 +232,16 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session { AndroidSpellCheckerService.SINGLE_QUOTE). replaceAll("^" + quotesRegexp, ""). replaceAll(quotesRegexp + "$", ""); + final SuggestionsParams cachedSuggestionsParams = + mSuggestionsCache.getSuggestionsFromCache(text, ngramContext); + + if (cachedSuggestionsParams != null) { + Log.d(TAG, "onGetSuggestionsInternal() : Cache hit for [" + text + "]"); + return new SuggestionsInfo( + cachedSuggestionsParams.mFlags, cachedSuggestionsParams.mSuggestions); + } + // If spell checking is impossible, return early. if (!mService.hasMainDictionaryForLocale(mLocale)) { return AndroidSpellCheckerService.getNotInDictEmptySuggestions( false /* reportAsTypo */); @@ -316,7 +329,8 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session { .getValueOf_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS() : 0); final SuggestionsInfo retval = new SuggestionsInfo(flags, result.mSuggestions); - mSuggestionsCache.putSuggestionsToCache(text, result.mSuggestions, flags); + mSuggestionsCache.putSuggestionsToCache(text, ngramContext, result.mSuggestions, + flags); return retval; } catch (RuntimeException e) { // Don't kill the keyboard if there is a bug in the spell checker diff --git a/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java b/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java index 096a545e5..cfa977a46 100644 --- a/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java @@ -30,7 +30,6 @@ import com.android.inputmethod.latin.AssetFileAddress; import com.android.inputmethod.latin.BinaryDictionaryGetter; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.RichInputMethodManager; -import com.android.inputmethod.latin.common.FileUtils; import com.android.inputmethod.latin.common.LocaleUtils; import com.android.inputmethod.latin.define.DecoderSpecificConstants; import com.android.inputmethod.latin.makedict.DictionaryHeader; @@ -154,13 +153,6 @@ public class DictionaryInfoUtils { } /** - * Helper method to get the top level cache directory. - */ - public static String getWordListStagingDirectory(final Context context) { - return context.getFilesDir() + File.separator + "staging"; - } - - /** * Helper method to get the top level temp directory. */ public static String getWordListTempDirectory(final Context context) { @@ -196,10 +188,6 @@ public class DictionaryInfoUtils { return new File(DictionaryInfoUtils.getWordListCacheDirectory(context)).listFiles(); } - public static File[] getStagingDirectoryList(final Context context) { - return new File(DictionaryInfoUtils.getWordListStagingDirectory(context)).listFiles(); - } - @Nullable public static File[] getUnusedDictionaryList(final Context context) { return context.getFilesDir().listFiles(new FilenameFilter() { @@ -233,7 +221,7 @@ public class DictionaryInfoUtils { /** * Find out the cache directory associated with a specific locale. */ - public static String getCacheDirectoryForLocale(final String locale, final Context context) { + private static String getCacheDirectoryForLocale(final String locale, final Context context) { final String relativeDirectoryName = replaceFileNameDangerousCharacters(locale); final String absoluteDirectoryName = getWordListCacheDirectory(context) + File.separator + relativeDirectoryName; @@ -266,52 +254,6 @@ public class DictionaryInfoUtils { return getCacheDirectoryForLocale(locale, context) + File.separator + fileName; } - public static String getStagingFileName(String id, String locale, Context context) { - final String stagingDirectory = getWordListStagingDirectory(context); - // create the directory if it does not exist. - final File directory = new File(stagingDirectory); - if (!directory.exists()) { - if (!directory.mkdirs()) { - Log.e(TAG, "Could not create the staging directory."); - } - } - // e.g. id="main:en_in", locale ="en_IN" - final String fileName = replaceFileNameDangerousCharacters( - locale + TEMP_DICT_FILE_SUB + id); - return stagingDirectory + File.separator + fileName; - } - - public static void moveStagingFilesIfExists(Context context) { - final File[] stagingFiles = DictionaryInfoUtils.getStagingDirectoryList(context); - if (stagingFiles != null && stagingFiles.length > 0) { - for (final File stagingFile : stagingFiles) { - final String fileName = stagingFile.getName(); - final int index = fileName.indexOf(TEMP_DICT_FILE_SUB); - if (index == -1) { - // This should never happen. - Log.e(TAG, "Staging file does not have ___ substring."); - continue; - } - final String[] localeAndFileId = fileName.split(TEMP_DICT_FILE_SUB); - if (localeAndFileId.length != 2) { - Log.e(TAG, String.format("malformed staging file %s. Deleting.", - stagingFile.getAbsoluteFile())); - stagingFile.delete(); - continue; - } - - final String locale = localeAndFileId[0]; - // already escaped while moving to staging. - final String fileId = localeAndFileId[1]; - final String cacheDirectoryForLocale = getCacheDirectoryForLocale(locale, context); - final String cacheFilename = cacheDirectoryForLocale + File.separator + fileId; - final File cacheFile = new File(cacheFilename); - // move the staging file to cache file. - FileUtils.renameTo(stagingFile, cacheFile); - } - } - } - public static boolean isMainWordListId(final String id) { final String[] idArray = id.split(BinaryDictionaryGetter.ID_CATEGORY_SEPARATOR); // An id is supposed to be in format category:locale, so splitting on the separator |