diff options
Diffstat (limited to 'java/src')
16 files changed, 130 insertions, 321 deletions
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java index 6b939cdfe..9ea1950f5 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java @@ -20,7 +20,7 @@ import android.content.Context; import android.util.Pair; import com.android.inputmethod.annotations.UsedForTesting; -import com.android.inputmethod.keyboard.KeyboardLayout; +import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.latin.common.ComposedData; import com.android.inputmethod.latin.settings.SettingsValuesForSuggestion; import com.android.inputmethod.latin.utils.SuggestionResults; @@ -157,9 +157,9 @@ public interface DictionaryFacilitator { // TODO: Revise the way to fusion suggestion results. SuggestionResults getSuggestionResults(final ComposedData composedData, - final NgramContext ngramContext, final long proximityInfoHandle, + final NgramContext ngramContext, @Nonnull final Keyboard keyboard, final SettingsValuesForSuggestion settingsValuesForSuggestion, final int sessionId, - final int inputStyle, final KeyboardLayout keyboardLayout); + final int inputStyle); boolean isValidSpellingWord(final String word); diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorImpl.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorImpl.java index e96300020..763cfa26d 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorImpl.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorImpl.java @@ -22,7 +22,7 @@ import android.util.Log; import android.util.Pair; import com.android.inputmethod.annotations.UsedForTesting; -import com.android.inputmethod.keyboard.KeyboardLayout; +import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.latin.NgramContext.WordInfo; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import com.android.inputmethod.latin.common.ComposedData; @@ -668,12 +668,14 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator { // TODO: Revise the way to fusion suggestion results. @Override public SuggestionResults getSuggestionResults(ComposedData composedData, - NgramContext ngramContext, long proximityInfoHandle, + NgramContext ngramContext, @Nonnull final Keyboard keyboard, SettingsValuesForSuggestion settingsValuesForSuggestion, int sessionId, - int inputStyle, KeyboardLayout keyboardLayout) { + int inputStyle) { + long proximityInfoHandle = keyboard.getProximityInfo().getNativeProximityInfo(); final DictionaryGroup[] dictionaryGroups = mDictionaryGroups; final SuggestionResults suggestionResults = new SuggestionResults( - SuggestedWords.MAX_SUGGESTIONS, ngramContext.isBeginningOfSentenceContext()); + SuggestedWords.MAX_SUGGESTIONS, ngramContext.isBeginningOfSentenceContext(), + false /* firstSuggestionExceedsConfidenceThreshold */); final float[] weightOfLangModelVsSpatialModel = new float[] { Dictionary.NOT_A_WEIGHT_OF_LANG_MODEL_VS_SPATIAL_MODEL }; for (final DictionaryGroup dictionaryGroup : dictionaryGroups) { diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java index 781ab06c5..49608d830 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java @@ -80,7 +80,7 @@ public final class DictionaryFactory { * @param context The context to contact the dictionary provider, if possible. * @param f A file address to the dictionary to kill. */ - private static void killDictionary(final Context context, final AssetFileAddress f) { + public static void killDictionary(final Context context, final AssetFileAddress f) { if (f.pointsToPhysicalFile()) { f.deleteUnderlyingFile(); // Warn the dictionary provider if the dictionary came from there. diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java index 064d79b3c..b0fb91bec 100644 --- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java @@ -259,7 +259,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { /** * Check whether GC is needed and run GC if required. */ - protected void runGCIfRequired(final boolean mindsBlockByGC) { + public void runGCIfRequired(final boolean mindsBlockByGC) { asyncExecuteTaskWithWriteLock(new Runnable() { @Override public void run() { diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 5b62135c1..c5c7d2d2c 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.common.InputPointers; import com.android.inputmethod.latin.define.DebugFlags; import com.android.inputmethod.latin.define.ProductionFlags; import com.android.inputmethod.latin.inputlogic.InputLogic; -import com.android.inputmethod.latin.personalization.DictionaryDecayBroadcastReciever; import com.android.inputmethod.latin.personalization.PersonalizationHelper; import com.android.inputmethod.latin.settings.Settings; import com.android.inputmethod.latin.settings.SettingsActivity; @@ -585,7 +584,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen dictDumpFilter.addAction(DictionaryDumpBroadcastReceiver.DICTIONARY_DUMP_INTENT_ACTION); registerReceiver(mDictionaryDumpBroadcastReceiver, dictDumpFilter); - DictionaryDecayBroadcastReciever.setUpIntervalAlarmForDictionaryDecaying(this); StatsUtils.onCreate(mSettings.getCurrent(), mRichImm); } @@ -705,7 +703,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen unregisterReceiver(mDictionaryPackInstallReceiver); unregisterReceiver(mDictionaryDumpBroadcastReceiver); mStatsUtilsManager.onDestroy(this /* context */); - DictionaryDecayBroadcastReciever.cancelIntervalAlarmForDictionaryDecaying(this); super.onDestroy(); } @@ -1515,9 +1512,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen callback.onGetSuggestedWords(SuggestedWords.getEmptyInstance()); return; } - mInputLogic.getSuggestedWords(mSettings.getCurrent(), keyboard.getProximityInfo(), - mKeyboardSwitcher.getKeyboardShiftMode(), inputStyle, sequenceNumber, callback, - keyboard.getKeyboardLayout()); + mInputLogic.getSuggestedWords(mSettings.getCurrent(), keyboard, + mKeyboardSwitcher.getKeyboardShiftMode(), inputStyle, sequenceNumber, callback); } @Override diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index 832fcbcb0..f4680fc88 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -20,8 +20,7 @@ import android.text.TextUtils; import static com.android.inputmethod.latin.define.DecoderSpecificConstants.SHOULD_AUTO_CORRECT_USING_NON_WHITE_LISTED_SUGGESTION; -import com.android.inputmethod.keyboard.KeyboardLayout; -import com.android.inputmethod.keyboard.ProximityInfo; +import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.common.StringUtils; @@ -97,19 +96,17 @@ public final class Suggest { } public void getSuggestedWords(final WordComposer wordComposer, - final NgramContext ngramContext, final ProximityInfo proximityInfo, + final NgramContext ngramContext, final Keyboard keyboard, final SettingsValuesForSuggestion settingsValuesForSuggestion, final boolean isCorrectionEnabled, final int inputStyle, final int sequenceNumber, - final OnGetSuggestedWordsCallback callback, - final KeyboardLayout keyboardLayout) { + final OnGetSuggestedWordsCallback callback) { if (wordComposer.isBatchMode()) { - getSuggestedWordsForBatchInput(wordComposer, ngramContext, proximityInfo, - settingsValuesForSuggestion, inputStyle, sequenceNumber, callback, - keyboardLayout); + getSuggestedWordsForBatchInput(wordComposer, ngramContext, keyboard, + settingsValuesForSuggestion, inputStyle, sequenceNumber, callback); } else { - getSuggestedWordsForNonBatchInput(wordComposer, ngramContext, proximityInfo, + getSuggestedWordsForNonBatchInput(wordComposer, ngramContext, keyboard, settingsValuesForSuggestion, inputStyle, isCorrectionEnabled, - sequenceNumber, callback, keyboardLayout); + sequenceNumber, callback); } } @@ -165,11 +162,10 @@ public final class Suggest { // Retrieves suggestions for non-batch input (typing, recorrection, predictions...) // and calls the callback function with the suggestions. private void getSuggestedWordsForNonBatchInput(final WordComposer wordComposer, - final NgramContext ngramContext, final ProximityInfo proximityInfo, + final NgramContext ngramContext, final Keyboard keyboard, final SettingsValuesForSuggestion settingsValuesForSuggestion, final int inputStyleIfNotPrediction, final boolean isCorrectionEnabled, - final int sequenceNumber, final OnGetSuggestedWordsCallback callback, - final KeyboardLayout keyboardLayout) { + final int sequenceNumber, final OnGetSuggestedWordsCallback callback) { final String typedWordString = wordComposer.getTypedWord(); final int trailingSingleQuotesCount = StringUtils.getTrailingSingleQuotesCount(typedWordString); @@ -178,9 +174,8 @@ public final class Suggest { : typedWordString; final SuggestionResults suggestionResults = mDictionaryFacilitator.getSuggestionResults( - wordComposer.getComposedDataSnapshot(), ngramContext, - proximityInfo.getNativeProximityInfo(), settingsValuesForSuggestion, - SESSION_ID_TYPING, inputStyleIfNotPrediction, keyboardLayout); + wordComposer.getComposedDataSnapshot(), ngramContext, keyboard, + settingsValuesForSuggestion, SESSION_ID_TYPING, inputStyleIfNotPrediction); final Locale mostProbableLocale = mDictionaryFacilitator.getMostProbableLocale(); final ArrayList<SuggestedWordInfo> suggestionsContainer = getTransformedSuggestedWordInfoList(wordComposer, suggestionResults, @@ -215,7 +210,8 @@ public final class Suggest { } } - SuggestedWordInfo.removeDups(typedWordString, suggestionsContainer); + final int firstOcurrenceOfTypedWordInSuggestions = + SuggestedWordInfo.removeDups(typedWordString, suggestionsContainer); final SuggestedWordInfo whitelistedWordInfo = getWhitelistedWordInfoOrNull(suggestionsContainer); @@ -278,7 +274,8 @@ public final class Suggest { hasAutoCorrection = false; } else { final SuggestedWordInfo firstSuggestion = suggestionResults.first(); - if (suggestionResults.mAutocorrectRecommendation) { + if (suggestionResults.mFirstSuggestionExceedsConfidenceThreshold + && firstOcurrenceOfTypedWordInSuggestions != 0) { hasAutoCorrection = true; } else if (!AutoCorrectionUtils.suggestionExceedsThreshold( firstSuggestion, consideredWord, mAutoCorrectionThreshold)) { @@ -319,12 +316,12 @@ public final class Suggest { } else { inputStyle = inputStyleIfNotPrediction; } + + final boolean isTypedWordValid = firstOcurrenceOfTypedWordInSuggestions > -1 + || (!resultsArePredictions && !allowsToBeAutoCorrected); callback.onGetSuggestedWords(new SuggestedWords(suggestionsList, suggestionResults.mRawSuggestions, typedWordInfo, - // TODO: this first argument is lying. If this is a whitelisted word which is an - // actual word, it says typedWordValid = false, which looks wrong. We should either - // rename the attribute or change the value. - !resultsArePredictions && !allowsToBeAutoCorrected /* typedWordValid */, + isTypedWordValid, hasAutoCorrection /* willAutoCorrect */, false /* isObsoleteSuggestions */, inputStyle, sequenceNumber)); } @@ -346,15 +343,13 @@ public final class Suggest { // Retrieves suggestions for the batch input // and calls the callback function with the suggestions. private void getSuggestedWordsForBatchInput(final WordComposer wordComposer, - final NgramContext ngramContext, final ProximityInfo proximityInfo, + final NgramContext ngramContext, final Keyboard keyboard, final SettingsValuesForSuggestion settingsValuesForSuggestion, final int inputStyle, final int sequenceNumber, - final OnGetSuggestedWordsCallback callback, - final KeyboardLayout keyboardLayout) { + final OnGetSuggestedWordsCallback callback) { final SuggestionResults suggestionResults = mDictionaryFacilitator.getSuggestionResults( - wordComposer.getComposedDataSnapshot(), ngramContext, - proximityInfo.getNativeProximityInfo(), settingsValuesForSuggestion, - SESSION_ID_GESTURE, inputStyle, keyboardLayout); + wordComposer.getComposedDataSnapshot(), ngramContext, keyboard, + settingsValuesForSuggestion, SESSION_ID_GESTURE, inputStyle); // For transforming words that don't come from a dictionary, because it's our best bet final Locale defaultLocale = mDictionaryFacilitator.getMostProbableLocale(); final ArrayList<SuggestedWordInfo> suggestionsContainer = diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java index 913b63a61..3816c0870 100644 --- a/java/src/com/android/inputmethod/latin/SuggestedWords.java +++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java @@ -17,6 +17,7 @@ package com.android.inputmethod.latin; import android.text.TextUtils; +import android.util.Log; import android.view.inputmethod.CompletionInfo; import com.android.inputmethod.annotations.UsedForTesting; @@ -375,31 +376,45 @@ public class SuggestedWords { return mWord + " (" + mDebugString + ")"; } - // This will always remove the higher index if a duplicate is found. - public static void removeDups(@Nullable final String typedWord, - @Nonnull ArrayList<SuggestedWordInfo> candidates) { + /** + * This will always remove the higher index if a duplicate is found. + * + * @return position of typed word in the candidate list + */ + public static int removeDups( + @Nullable final String typedWord, + @Nonnull final ArrayList<SuggestedWordInfo> candidates) { if (candidates.isEmpty()) { - return; + return -1; } + int firstOccurrenceOfWord = -1; if (!TextUtils.isEmpty(typedWord)) { - removeSuggestedWordInfoFromList(typedWord, candidates, -1 /* startIndexExclusive */); + firstOccurrenceOfWord = removeSuggestedWordInfoFromList( + typedWord, candidates, -1 /* startIndexExclusive */); } for (int i = 0; i < candidates.size(); ++i) { - removeSuggestedWordInfoFromList(candidates.get(i).mWord, candidates, - i /* startIndexExclusive */); + removeSuggestedWordInfoFromList( + candidates.get(i).mWord, candidates, i /* startIndexExclusive */); } + return firstOccurrenceOfWord; } - private static void removeSuggestedWordInfoFromList( - @Nonnull final String word, @Nonnull final ArrayList<SuggestedWordInfo> candidates, + private static int removeSuggestedWordInfoFromList( + @Nonnull final String word, + @Nonnull final ArrayList<SuggestedWordInfo> candidates, final int startIndexExclusive) { + int firstOccurrenceOfWord = -1; for (int i = startIndexExclusive + 1; i < candidates.size(); ++i) { final SuggestedWordInfo previous = candidates.get(i); if (word.equals(previous.mWord)) { + if (firstOccurrenceOfWord == -1) { + firstOccurrenceOfWord = i; + } candidates.remove(i); --i; } } + return firstOccurrenceOfWord; } } diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java index 57aa59190..7907aaa16 100644 --- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java +++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java @@ -32,9 +32,8 @@ import android.view.inputmethod.EditorInfo; import com.android.inputmethod.compat.SuggestionSpanUtils; import com.android.inputmethod.event.Event; import com.android.inputmethod.event.InputTransaction; -import com.android.inputmethod.keyboard.KeyboardLayout; +import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.KeyboardSwitcher; -import com.android.inputmethod.keyboard.ProximityInfo; import com.android.inputmethod.latin.Dictionary; import com.android.inputmethod.latin.DictionaryFacilitator; import com.android.inputmethod.latin.LastComposedWord; @@ -2165,9 +2164,8 @@ public final class InputLogic { } public void getSuggestedWords(final SettingsValues settingsValues, - final ProximityInfo proximityInfo, final int keyboardShiftMode, final int inputStyle, - final int sequenceNumber, final OnGetSuggestedWordsCallback callback, - final KeyboardLayout keyboardLayout) { + final Keyboard keyboard, final int keyboardShiftMode, final int inputStyle, + final int sequenceNumber, final OnGetSuggestedWordsCallback callback) { mWordComposer.adviseCapitalizedModeBeforeFetchingSuggestions( getActualCapsMode(settingsValues, keyboardShiftMode)); mSuggest.getSuggestedWords(mWordComposer, @@ -2177,11 +2175,11 @@ public final class InputLogic { // a word, it's whatever is *before* the half-committed word in the buffer, // hence 2; if we aren't, we should just skip whitespace if any, so 1. mWordComposer.isComposingWord() ? 2 : 1), - proximityInfo, + keyboard, new SettingsValuesForSuggestion(settingsValues.mBlockPotentiallyOffensive, settingsValues.mPhraseGestureEnabled), settingsValues.mAutoCorrectionEnabledPerUserSettings, - inputStyle, sequenceNumber, callback, keyboardLayout); + inputStyle, sequenceNumber, callback); } /** diff --git a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java deleted file mode 100644 index 78b51d9f4..000000000 --- a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.inputmethod.latin.personalization; - -import android.content.Context; - -import com.android.inputmethod.latin.Dictionary; -import com.android.inputmethod.latin.ExpandableBinaryDictionary; -import com.android.inputmethod.latin.makedict.DictionaryHeader; - -import java.io.File; -import java.util.Locale; -import java.util.Map; - -/** - * This class is a base class of a dictionary that supports decaying for the personalized language - * model. - */ -public abstract class DecayingExpandableBinaryDictionaryBase extends ExpandableBinaryDictionary { - private static final boolean DBG_DUMP_ON_CLOSE = false; - - /** Any pair being typed or picked */ - public static final int FREQUENCY_FOR_TYPED = 2; - - public static final int FREQUENCY_FOR_WORDS_IN_DICTS = FREQUENCY_FOR_TYPED; - public static final int FREQUENCY_FOR_WORDS_NOT_IN_DICTS = Dictionary.NOT_A_PROBABILITY; - - protected DecayingExpandableBinaryDictionaryBase(final Context context, - final String dictName, final Locale locale, final String dictionaryType, - final File dictFile) { - super(context, dictName, locale, dictionaryType, dictFile); - if (mLocale != null && mLocale.toString().length() > 1) { - reloadDictionaryIfRequired(); - } - } - - @Override - public void close() { - if (DBG_DUMP_ON_CLOSE) { - dumpAllWordsForDebug(); - } - // Flush pending writes. - asyncFlushBinaryDictionary(); - super.close(); - } - - @Override - protected Map<String, String> getHeaderAttributeMap() { - final Map<String, String> attributeMap = super.getHeaderAttributeMap(); - attributeMap.put(DictionaryHeader.USES_FORGETTING_CURVE_KEY, - DictionaryHeader.ATTRIBUTE_VALUE_TRUE); - attributeMap.put(DictionaryHeader.HAS_HISTORICAL_INFO_KEY, - DictionaryHeader.ATTRIBUTE_VALUE_TRUE); - return attributeMap; - } - - @Override - protected void loadInitialContentsLocked() { - // No initial contents. - } - - /* package */ void runGCIfRequired() { - runGCIfRequired(false /* mindsBlockByGC */); - } - - @Override - public boolean isValidWord(final String word) { - // Strings out of this dictionary should not be considered existing words. - return false; - } -} diff --git a/java/src/com/android/inputmethod/latin/personalization/DictionaryDecayBroadcastReciever.java b/java/src/com/android/inputmethod/latin/personalization/DictionaryDecayBroadcastReciever.java deleted file mode 100644 index 0c5e5d010..000000000 --- a/java/src/com/android/inputmethod/latin/personalization/DictionaryDecayBroadcastReciever.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.inputmethod.latin.personalization; - -import android.app.AlarmManager; -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; - -import java.util.concurrent.TimeUnit; - -/** - * Broadcast receiver for periodically updating decaying dictionaries. - */ -public class DictionaryDecayBroadcastReciever extends BroadcastReceiver { - /** - * The root domain for the personalization. - */ - private static final String PERSONALIZATION_DOMAIN = - "com.android.inputmethod.latin.personalization"; - - /** - * The action of the intent to tell the time to decay dictionaries. - */ - private static final String DICTIONARY_DECAY_INTENT_ACTION = - PERSONALIZATION_DOMAIN + ".DICT_DECAY"; - - /** - * Interval to update for decaying dictionaries. - */ - static final long DICTIONARY_DECAY_INTERVAL_IN_MILLIS = TimeUnit.MINUTES.toMillis(60); - - private static PendingIntent getPendingIntentForDictionaryDecay(final Context context) { - final Intent updateIntent = new Intent(DICTIONARY_DECAY_INTENT_ACTION); - updateIntent.setClass(context, DictionaryDecayBroadcastReciever.class); - return PendingIntent.getBroadcast(context, 0 /* requestCode */, - updateIntent, PendingIntent.FLAG_CANCEL_CURRENT); - } - - /** - * Set up interval alarm for dynamic dictionaries. - */ - public static void setUpIntervalAlarmForDictionaryDecaying(final Context context) { - final AlarmManager alarmManager = - (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); - if (null == alarmManager) { - return; - } - final long alarmTriggerTimeInMillis = - System.currentTimeMillis() + DICTIONARY_DECAY_INTERVAL_IN_MILLIS; - alarmManager.setInexactRepeating(AlarmManager.RTC, alarmTriggerTimeInMillis, - DICTIONARY_DECAY_INTERVAL_IN_MILLIS, getPendingIntentForDictionaryDecay(context)); - } - - /** - * Cancel interval alarm that has been set up. - */ - public static void cancelIntervalAlarmForDictionaryDecaying(final Context context) { - final AlarmManager alarmManager = - (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); - if (null == alarmManager) { - return; - } - alarmManager.cancel(getPendingIntentForDictionaryDecay(context)); - } - - @Override - public void onReceive(final Context context, final Intent intent) { - final String action = intent.getAction(); - if (action.equals(DICTIONARY_DECAY_INTENT_ACTION)) { - PersonalizationHelper.runGCOnAllOpenedUserHistoryDictionaries(); - } - } -} diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java index 1c1cb4f95..298e46c0a 100644 --- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java +++ b/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java @@ -26,7 +26,6 @@ import java.io.FilenameFilter; import java.lang.ref.SoftReference; import java.util.Locale; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -68,60 +67,28 @@ public class PersonalizationHelper { } } - private static int sCurrentTimestampForTesting = 0; - public static void currentTimeChangedForTesting(final int currentTimestamp) { - if (TimeUnit.MILLISECONDS.toSeconds( - DictionaryDecayBroadcastReciever.DICTIONARY_DECAY_INTERVAL_IN_MILLIS) - < currentTimestamp - sCurrentTimestampForTesting) { - runGCOnAllOpenedUserHistoryDictionaries(); - } - } - - public static void runGCOnAllOpenedUserHistoryDictionaries() { - runGCOnAllDictionariesIfRequired(sLangUserHistoryDictCache); - } - - private static <T extends DecayingExpandableBinaryDictionaryBase> - void runGCOnAllDictionariesIfRequired( - final ConcurrentHashMap<String, SoftReference<T>> dictionaryMap) { - for (final ConcurrentHashMap.Entry<String, SoftReference<T>> entry - : dictionaryMap.entrySet()) { - final DecayingExpandableBinaryDictionaryBase dict = entry.getValue().get(); - if (dict != null) { - dict.runGCIfRequired(); - } else { - dictionaryMap.remove(entry.getKey()); - } - } - } - public static void removeAllUserHistoryDictionaries(final Context context) { - removeAllDictionaries(context, sLangUserHistoryDictCache, - UserHistoryDictionary.NAME); - } - - private static <T extends DecayingExpandableBinaryDictionaryBase> void removeAllDictionaries( - final Context context, final ConcurrentHashMap<String, SoftReference<T>> dictionaryMap, - final String dictNamePrefix) { - synchronized (dictionaryMap) { - for (final ConcurrentHashMap.Entry<String, SoftReference<T>> entry - : dictionaryMap.entrySet()) { + synchronized (sLangUserHistoryDictCache) { + for (final ConcurrentHashMap.Entry<String, SoftReference<UserHistoryDictionary>> entry + : sLangUserHistoryDictCache.entrySet()) { if (entry.getValue() != null) { - final DecayingExpandableBinaryDictionaryBase dict = entry.getValue().get(); + final UserHistoryDictionary dict = entry.getValue().get(); if (dict != null) { dict.clear(); } } } - dictionaryMap.clear(); + sLangUserHistoryDictCache.clear(); final File filesDir = context.getFilesDir(); if (filesDir == null) { Log.e(TAG, "context.getFilesDir() returned null."); return; } - if (!FileUtils.deleteFilteredFiles(filesDir, new DictFilter(dictNamePrefix))) { - Log.e(TAG, "Cannot remove all existing dictionary files. filesDir: " - + filesDir.getAbsolutePath() + ", dictNamePrefix: " + dictNamePrefix); + final boolean filesDeleted = FileUtils.deleteFilteredFiles( + filesDir, new DictFilter(UserHistoryDictionary.NAME)); + if (!filesDeleted) { + Log.e(TAG, "Cannot remove dictionary files. filesDir: " + filesDir.getAbsolutePath() + + ", dictNamePrefix: " + UserHistoryDictionary.NAME); } } } diff --git a/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java b/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java index b6286b203..54ee68d65 100644 --- a/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java +++ b/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java @@ -25,9 +25,11 @@ import com.android.inputmethod.latin.ExpandableBinaryDictionary; import com.android.inputmethod.latin.NgramContext; import com.android.inputmethod.latin.define.DecoderSpecificConstants; import com.android.inputmethod.latin.define.ProductionFlags; +import com.android.inputmethod.latin.makedict.DictionaryHeader; import java.io.File; import java.util.Locale; +import java.util.Map; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -37,17 +39,16 @@ import javax.annotation.Nullable; * auto-correction cancellation or manual picks. This allows the keyboard to adapt to the * typist over time. */ -public class UserHistoryDictionary extends DecayingExpandableBinaryDictionaryBase { +public class UserHistoryDictionary extends ExpandableBinaryDictionary { static final String NAME = UserHistoryDictionary.class.getSimpleName(); // TODO: Make this constructor private UserHistoryDictionary(final Context context, final Locale locale, @Nullable final String account) { - super(context, - getUserHistoryDictName(NAME, locale, null /* dictFile */, account), - locale, - Dictionary.TYPE_USER_HISTORY, - null /* dictFile */); + super(context, getUserHistoryDictName(NAME, locale, null /* dictFile */, account), locale, Dictionary.TYPE_USER_HISTORY, null); + if (mLocale != null && mLocale.toString().length() > 1) { + reloadDictionaryIfRequired(); + } } /** @@ -103,4 +104,32 @@ public class UserHistoryDictionary extends DecayingExpandableBinaryDictionaryBas userHistoryDictionary.updateEntriesForWord(ngramContext, word, isValid, 1 /* count */, timestamp); } + + @Override + public void close() { + // Flush pending writes. + asyncFlushBinaryDictionary(); + super.close(); + } + + @Override + protected Map<String, String> getHeaderAttributeMap() { + final Map<String, String> attributeMap = super.getHeaderAttributeMap(); + attributeMap.put(DictionaryHeader.USES_FORGETTING_CURVE_KEY, + DictionaryHeader.ATTRIBUTE_VALUE_TRUE); + attributeMap.put(DictionaryHeader.HAS_HISTORICAL_INFO_KEY, + DictionaryHeader.ATTRIBUTE_VALUE_TRUE); + return attributeMap; + } + + @Override + protected void loadInitialContentsLocked() { + // No initial contents. + } + + @Override + public boolean isValidWord(final String word) { + // Strings out of this dictionary should not be considered existing words. + return false; + } } diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java index 9822c5725..f04f093f0 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java @@ -28,9 +28,7 @@ import android.util.Log; import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.KeyboardId; -import com.android.inputmethod.keyboard.KeyboardLayout; import com.android.inputmethod.keyboard.KeyboardLayoutSet; -import com.android.inputmethod.keyboard.ProximityInfo; import com.android.inputmethod.latin.DictionaryFacilitator; import com.android.inputmethod.latin.DictionaryFacilitatorLruCache; import com.android.inputmethod.latin.NgramContext; @@ -48,6 +46,8 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Semaphore; +import javax.annotation.Nonnull; + /** * Service for spell checking, using LatinIME's dictionaries and mechanisms. */ @@ -193,7 +193,7 @@ public final class AndroidSpellCheckerService extends SpellCheckerService public SuggestionResults getSuggestionResults(final Locale locale, final ComposedData composedData, final NgramContext ngramContext, - final ProximityInfo proximityInfo, final KeyboardLayout keyboardLayout) { + @Nonnull final Keyboard keyboard) { Integer sessionId = null; mSemaphore.acquireUninterruptibly(); try { @@ -201,8 +201,8 @@ public final class AndroidSpellCheckerService extends SpellCheckerService DictionaryFacilitator dictionaryFacilitatorForLocale = mDictionaryFacilitatorCache.get(locale); return dictionaryFacilitatorForLocale.getSuggestionResults(composedData, ngramContext, - proximityInfo.getNativeProximityInfo(), mSettingsValuesForSuggestion, - sessionId, SuggestedWords.INPUT_STYLE_TYPING, keyboardLayout); + keyboard, mSettingsValuesForSuggestion, + sessionId, SuggestedWords.INPUT_STYLE_TYPING); } finally { if (sessionId != null) { mSessionIdPool.add(sessionId); diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java index 1c43a4b71..5c1915c6c 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java @@ -29,18 +29,11 @@ import android.view.textservice.TextInfo; import com.android.inputmethod.compat.SuggestionsInfoCompatUtils; import com.android.inputmethod.keyboard.Keyboard; -import com.android.inputmethod.keyboard.KeyboardLayout; -import com.android.inputmethod.keyboard.ProximityInfo; import com.android.inputmethod.latin.NgramContext; -import com.android.inputmethod.latin.SuggestedWords; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import com.android.inputmethod.latin.WordComposer; -import com.android.inputmethod.latin.common.ComposedData; import com.android.inputmethod.latin.common.Constants; -import com.android.inputmethod.latin.common.CoordinateUtils; -import com.android.inputmethod.latin.common.InputPointers; import com.android.inputmethod.latin.common.LocaleUtils; -import com.android.inputmethod.latin.common.ResizableIntArray; import com.android.inputmethod.latin.common.StringUtils; import com.android.inputmethod.latin.utils.BinaryDictionaryUtils; import com.android.inputmethod.latin.utils.ScriptUtils; @@ -272,26 +265,20 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session { false /* reportAsTypo */); } final Keyboard keyboard = mService.getKeyboardForLocale(mLocale); + if (null == keyboard) { + Log.d(TAG, "No keyboard for locale: " + mLocale); + // If there is no keyboard for this locale, don't do any spell-checking. + return AndroidSpellCheckerService.getNotInDictEmptySuggestions( + false /* reportAsTypo */); + } final WordComposer composer = new WordComposer(); final int[] codePoints = StringUtils.toCodePointArray(text); final int[] coordinates; - final ProximityInfo proximityInfo; - final KeyboardLayout keyboardLayout; - if (null == keyboard) { - coordinates = CoordinateUtils.newCoordinateArray(codePoints.length, - Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE); - proximityInfo = null; - keyboardLayout = null; - } else { - coordinates = keyboard.getCoordinates(codePoints); - proximityInfo = keyboard.getProximityInfo(); - keyboardLayout = keyboard.getKeyboardLayout(); - } + coordinates = keyboard.getCoordinates(codePoints); composer.setComposingWord(codePoints, coordinates); // TODO: Don't gather suggestions if the limit is <= 0 unless necessary final SuggestionResults suggestionResults = mService.getSuggestionResults( - mLocale, composer.getComposedDataSnapshot(), ngramContext, proximityInfo, - keyboardLayout); + mLocale, composer.getComposedDataSnapshot(), ngramContext, keyboard); final Result result = getResult(capitalizeType, mLocale, suggestionsLimit, mService.getRecommendedThreshold(), text, suggestionResults); isInDict = isInDictForAnyCapitalization(text, capitalizeType); diff --git a/java/src/com/android/inputmethod/latin/utils/BinaryDictionaryUtils.java b/java/src/com/android/inputmethod/latin/utils/BinaryDictionaryUtils.java index 23ffde2a2..892b967c4 100644 --- a/java/src/com/android/inputmethod/latin/utils/BinaryDictionaryUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/BinaryDictionaryUtils.java @@ -21,7 +21,6 @@ import com.android.inputmethod.latin.BinaryDictionary; import com.android.inputmethod.latin.common.StringUtils; import com.android.inputmethod.latin.makedict.DictionaryHeader; import com.android.inputmethod.latin.makedict.UnsupportedFormatException; -import com.android.inputmethod.latin.personalization.PersonalizationHelper; import java.io.File; import java.io.IOException; @@ -123,8 +122,6 @@ public final class BinaryDictionaryUtils { */ @UsedForTesting public static int setCurrentTimeForTest(final int currentTime) { - final int currentNativeTimestamp = setCurrentTimeForTestNative(currentTime); - PersonalizationHelper.currentTimeChangedForTesting(currentNativeTimestamp); - return currentNativeTimestamp; + return setCurrentTimeForTestNative(currentTime); } } diff --git a/java/src/com/android/inputmethod/latin/utils/SuggestionResults.java b/java/src/com/android/inputmethod/latin/utils/SuggestionResults.java index 10e3994b6..981355115 100644 --- a/java/src/com/android/inputmethod/latin/utils/SuggestionResults.java +++ b/java/src/com/android/inputmethod/latin/utils/SuggestionResults.java @@ -33,21 +33,18 @@ public final class SuggestionResults extends TreeSet<SuggestedWordInfo> { // TODO: Instead of a boolean , we may want to include the context of this suggestion results, // such as {@link NgramContext}. public final boolean mIsBeginningOfSentence; - public final boolean mAutocorrectRecommendation; + public final boolean mFirstSuggestionExceedsConfidenceThreshold; private final int mCapacity; - public SuggestionResults(final int capacity, final boolean isBeginningOfSentence) { - this(sSuggestedWordInfoComparator, capacity, isBeginningOfSentence, false); - } - public SuggestionResults(final int capacity, final boolean isBeginningOfSentence, - final boolean autocorrectRecommendation) { + final boolean firstSuggestionExceedsConfidenceThreshold) { this(sSuggestedWordInfoComparator, capacity, isBeginningOfSentence, - autocorrectRecommendation); + firstSuggestionExceedsConfidenceThreshold); } private SuggestionResults(final Comparator<SuggestedWordInfo> comparator, final int capacity, - final boolean isBeginningOfSentence, final boolean autocorrectRecommendation) { + final boolean isBeginningOfSentence, + final boolean firstSuggestionExceedsConfidenceThreshold) { super(comparator); mCapacity = capacity; if (ProductionFlags.INCLUDE_RAW_SUGGESTIONS) { @@ -56,7 +53,7 @@ public final class SuggestionResults extends TreeSet<SuggestedWordInfo> { mRawSuggestions = null; } mIsBeginningOfSentence = isBeginningOfSentence; - mAutocorrectRecommendation = autocorrectRecommendation; + mFirstSuggestionExceedsConfidenceThreshold = firstSuggestionExceedsConfidenceThreshold; } @Override |