diff options
Diffstat (limited to 'java/src/com/android/inputmethod/latin')
7 files changed, 104 insertions, 50 deletions
diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java index d9d22e0fc..1c54a20e7 100644 --- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java @@ -77,6 +77,9 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { private static final int DICTIONARY_FORMAT_VERSION = FormatSpec.VERSION4; + private static final WordProperty[] DEFAULT_WORD_PROPERTIES_FOR_SYNC = + new WordProperty[0] /* default */; + /** The application context. */ protected final Context mContext; @@ -802,4 +805,38 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { } }); } + + /** + * Returns dictionary content required for syncing. + */ + public WordProperty[] getWordPropertiesForSyncing() { + reloadDictionaryIfRequired(); + final AsyncResultHolder<WordProperty[]> result = new AsyncResultHolder<>(); + asyncExecuteTaskWithLock(mLock.readLock(), "sync-read", new Runnable() { + @Override + public void run() { + final ArrayList<WordProperty> wordPropertyList = new ArrayList<>(); + final BinaryDictionary binaryDictionary = getBinaryDictionary(); + if (binaryDictionary == null) { + return; + } + int token = 0; + do { + // TODO: We need a new API that returns *new* un-synced data. + final BinaryDictionary.GetNextWordPropertyResult nextWordPropertyResult = + binaryDictionary.getNextWordProperty(token); + final WordProperty wordProperty = nextWordPropertyResult.mWordProperty; + if (wordProperty == null) { + break; + } + wordPropertyList.add(wordProperty); + token = nextWordPropertyResult.mNextToken; + } while (token != 0); + result.set(wordPropertyList.toArray(new WordProperty[wordPropertyList.size()])); + } + }); + // TODO: Figure out the best timeout duration for this API. + return result.get(DEFAULT_WORD_PROPERTIES_FOR_SYNC, + TIMEOUT_FOR_READ_OPS_IN_MILLISECONDS); + } } diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 66746cb6a..27115e266 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -590,7 +590,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // TODO: Resolve mutual dependencies of {@link #loadSettings()} and // {@link #resetDictionaryFacilitatorIfNecessary()}. loadSettings(); - mSubtypeSwitcher.onSubtypeChanged(mRichImm.getCurrentRawSubtype()); resetDictionaryFacilitatorIfNecessary(); // Register to receive ringer mode change and network state change. @@ -731,6 +730,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen unregisterReceiver(mDictionaryPackInstallReceiver); unregisterReceiver(mDictionaryDumpBroadcastReceiver); mStatsUtilsManager.onDestroy(); + DictionaryDecayBroadcastReciever.cancelIntervalAlarmForDictionaryDecaying(this); super.onDestroy(); } @@ -865,7 +865,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen public void onCurrentInputMethodSubtypeChanged(final InputMethodSubtype subtype) { // Note that the calling sequence of onCreate() and onCurrentInputMethodSubtypeChanged() // is not guaranteed. It may even be called at the same time on a different thread. - mSubtypeSwitcher.onSubtypeChanged(subtype); + mRichImm.onSubtypeChanged(subtype); + mSubtypeSwitcher.onSubtypeChanged(mRichImm.getCurrentSubtype()); mInputLogic.onSubtypeChanged(SubtypeLocaleUtils.getCombiningRulesExtraValue(subtype), mSettings.getCurrent()); loadKeyboard(); @@ -881,8 +882,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // Switch to the null consumer to handle cases leading to early exit below, for which we // also wouldn't be consuming gesture data. mGestureConsumer = GestureConsumer.NULL_GESTURE_CONSUMER; - mRichImm.clearSubtypeCaches(); - mSubtypeSwitcher.onSubtypeChanged(mRichImm.getCurrentRawSubtype()); + mRichImm.refreshSubtypeCaches(); + mSubtypeSwitcher.onSubtypeChanged(mRichImm.getCurrentSubtype()); final KeyboardSwitcher switcher = mKeyboardSwitcher; switcher.updateKeyboardTheme(); final MainKeyboardView mainKeyboardView = switcher.getMainKeyboardView(); @@ -1448,7 +1449,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // completely replace #onCodeInput. public void onEvent(@Nonnull final Event event) { if (Constants.CODE_SHORTCUT == event.mKeyCode) { - mRichImm.switchToShortcutIME(this); + mRichImm.switchToShortcutIme(this); } final InputTransaction completeInputTransaction = mInputLogic.onCodeInput(mSettings.getCurrent(), event, diff --git a/java/src/com/android/inputmethod/latin/RichInputMethodManager.java b/java/src/com/android/inputmethod/latin/RichInputMethodManager.java index 686c3a4b2..462121789 100644 --- a/java/src/com/android/inputmethod/latin/RichInputMethodManager.java +++ b/java/src/com/android/inputmethod/latin/RichInputMethodManager.java @@ -111,7 +111,11 @@ public class RichInputMethodManager { // Initialize additional subtypes. SubtypeLocaleUtils.init(context); final InputMethodSubtype[] additionalSubtypes = getAdditionalSubtypes(); - setAdditionalInputMethodSubtypes(additionalSubtypes); + mImmWrapper.mImm.setAdditionalInputMethodSubtypes( + getInputMethodIdOfThisIme(), additionalSubtypes); + + // Initialize the current input method subtype and the shortcut IME. + refreshSubtypeCaches(); final ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); @@ -324,23 +328,22 @@ public class RichInputMethodManager { return INDEX_NOT_FOUND; } - @Nonnull - public RichInputMethodSubtype onSubtypeChanged(@Nonnull final InputMethodSubtype newSubtype) { - final RichInputMethodSubtype richSubtype = createCurrentRichInputMethodSubtype(newSubtype); + public void onSubtypeChanged(@Nonnull final InputMethodSubtype newSubtype) { + updateCurrentSubtype(newSubtype); + updateShortcutIme(); if (DEBUG) { - Log.w(TAG, "onSubtypeChanged: " + richSubtype.getNameForLogging()); + Log.w(TAG, "onSubtypeChanged: " + mCurrentRichInputMethodSubtype.getNameForLogging()); } - mCurrentRichInputMethodSubtype = richSubtype; - return richSubtype; } private static RichInputMethodSubtype sForcedSubtypeForTesting = null; @UsedForTesting - static void forceSubtype(final InputMethodSubtype subtype) { + static void forceSubtype(@Nonnull final InputMethodSubtype subtype) { sForcedSubtypeForTesting = new RichInputMethodSubtype(subtype); } + @Nonnull public Locale[] getCurrentSubtypeLocales() { if (null != sForcedSubtypeForTesting) { return sForcedSubtypeForTesting.getLocales(); @@ -348,6 +351,7 @@ public class RichInputMethodManager { return getCurrentSubtype().getLocales(); } + @Nonnull public RichInputMethodSubtype getCurrentSubtype() { if (null != sForcedSubtypeForTesting) { return sForcedSubtypeForTesting; @@ -360,18 +364,6 @@ public class RichInputMethodManager { return SubtypeLocaleUtils.getCombiningRulesExtraValue(getCurrentSubtype().getRawSubtype()); } - @Nonnull - public InputMethodSubtype getCurrentRawSubtype() { - return mImmWrapper.mImm.getCurrentInputMethodSubtype(); - } - - @Nonnull - public RichInputMethodSubtype createCurrentRichInputMethodSubtype( - @Nonnull final InputMethodSubtype rawSubtype) { - return AdditionalFeaturesSettingUtils.createRichInputMethodSubtype(this, rawSubtype, - mContext); - } - public boolean hasMultipleEnabledIMEsOrSubtypes(final boolean shouldIncludeAuxiliarySubtypes) { final List<InputMethodInfo> enabledImis = mImmWrapper.mImm.getEnabledInputMethodList(); return hasMultipleEnabledSubtypes(shouldIncludeAuxiliarySubtypes, enabledImis); @@ -457,7 +449,7 @@ public class RichInputMethodManager { getInputMethodIdOfThisIme(), subtypes); // Clear the cache so that we go read the {@link InputMethodInfo} of this IME and list of // subtypes again next time. - clearSubtypeCaches(); + refreshSubtypeCaches(); } private List<InputMethodSubtype> getEnabledInputMethodSubtypeList(final InputMethodInfo imi, @@ -474,10 +466,12 @@ public class RichInputMethodManager { return result; } - public void clearSubtypeCaches() { + public void refreshSubtypeCaches() { mSubtypeListCacheWithImplicitlySelectedSubtypes.clear(); mSubtypeListCacheWithoutImplicitlySelectedSubtypes.clear(); mInputMethodInfoCache.clear(); + updateCurrentSubtype(mImmWrapper.mImm.getCurrentInputMethodSubtype()); + updateShortcutIme(); } public boolean shouldOfferSwitchingToNextInputMethod(final IBinder binder, @@ -516,8 +510,13 @@ public class RichInputMethodManager { return true; } - // TODO: Make this private - void updateShortcutIME() { + private void updateCurrentSubtype(@Nonnull final InputMethodSubtype subtype) { + final RichInputMethodSubtype richSubtype = AdditionalFeaturesSettingUtils + .createRichInputMethodSubtype(this, subtype, mContext); + mCurrentRichInputMethodSubtype = richSubtype; + } + + private void updateShortcutIme() { if (DEBUG) { Log.d(TAG, "Update shortcut IME from : " + (mShortcutInputMethodInfo == null @@ -549,7 +548,7 @@ public class RichInputMethodManager { } } - public void switchToShortcutIME(final InputMethodService context) { + public void switchToShortcutIme(final InputMethodService context) { if (mShortcutInputMethodInfo == null) { return; } @@ -575,19 +574,16 @@ public class RichInputMethodManager { } public boolean isShortcutImeEnabled() { - updateShortcutIME(); if (mShortcutInputMethodInfo == null) { return false; } if (mShortcutSubtype == null) { return true; } - return checkIfSubtypeBelongsToImeAndEnabled( - mShortcutInputMethodInfo, mShortcutSubtype); + return checkIfSubtypeBelongsToImeAndEnabled(mShortcutInputMethodInfo, mShortcutSubtype); } public boolean isShortcutImeReady() { - updateShortcutIME(); if (mShortcutInputMethodInfo == null) { return false; } diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java index 23e348bff..92ba6c2d9 100644 --- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java +++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java @@ -57,7 +57,7 @@ public final class SubtypeSwitcher { mResources = context.getResources(); mRichImm = RichInputMethodManager.getInstance(); - onSubtypeChanged(mRichImm.getCurrentRawSubtype()); + onSubtypeChanged(mRichImm.getCurrentSubtype()); updateParametersOnStartInputView(); } @@ -69,17 +69,14 @@ public final class SubtypeSwitcher { final List<InputMethodSubtype> enabledSubtypesOfThisIme = mRichImm.getMyEnabledInputMethodSubtypeList(true); mLanguageOnSpacebarHelper.onUpdateEnabledSubtypes(enabledSubtypesOfThisIme); - mRichImm.updateShortcutIME(); } // Update the current subtype. LatinIME.onCurrentInputMethodSubtypeChanged calls this function. - public void onSubtypeChanged(@Nonnull final InputMethodSubtype newSubtype) { - final RichInputMethodSubtype richSubtype = mRichImm.onSubtypeChanged(newSubtype); + public void onSubtypeChanged(@Nonnull final RichInputMethodSubtype richSubtype) { final boolean implicitlyEnabledSubtype = mRichImm - .checkIfSubtypeBelongsToThisImeAndImplicitlyEnabled(newSubtype); + .checkIfSubtypeBelongsToThisImeAndImplicitlyEnabled(richSubtype.getRawSubtype()); mLanguageOnSpacebarHelper.onSubtypeChanged( richSubtype, implicitlyEnabledSubtype, mResources.getConfiguration().locale); - mRichImm.updateShortcutIME(); } public int getLanguageOnSpacebarFormatType(final RichInputMethodSubtype subtype) { diff --git a/java/src/com/android/inputmethod/latin/personalization/DictionaryDecayBroadcastReciever.java b/java/src/com/android/inputmethod/latin/personalization/DictionaryDecayBroadcastReciever.java index 221bb9a8f..e974f3320 100644 --- a/java/src/com/android/inputmethod/latin/personalization/DictionaryDecayBroadcastReciever.java +++ b/java/src/com/android/inputmethod/latin/personalization/DictionaryDecayBroadcastReciever.java @@ -43,17 +43,40 @@ public class DictionaryDecayBroadcastReciever extends BroadcastReceiver { /** * Interval to update for decaying dictionaries. */ - /* package */ static final long DICTIONARY_DECAY_INTERVAL = TimeUnit.MINUTES.toMillis(60); + static final long DICTIONARY_DECAY_INTERVAL_IN_MILLIS = TimeUnit.MINUTES.toMillis(60); - public static void setUpIntervalAlarmForDictionaryDecaying(Context context) { - AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); + private static PendingIntent getPendingIntentForDictionaryDecay(final Context context) { final Intent updateIntent = new Intent(DICTIONARY_DECAY_INTENT_ACTION); updateIntent.setClass(context, DictionaryDecayBroadcastReciever.class); - final long alarmTime = System.currentTimeMillis() + DICTIONARY_DECAY_INTERVAL; - final PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0 /* requestCode */, + return PendingIntent.getBroadcast(context, 0 /* requestCode */, updateIntent, PendingIntent.FLAG_CANCEL_CURRENT); - if (null != alarmManager) alarmManager.setInexactRepeating(AlarmManager.RTC, - alarmTime, DICTIONARY_DECAY_INTERVAL, pendingIntent); + } + + /** + * 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 diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java index 8c5eb0aa7..b595f3974 100644 --- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java +++ b/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java @@ -58,8 +58,7 @@ public class PersonalizationHelper { final UserHistoryDictionary dict = ref == null ? null : ref.get(); if (dict != null) { if (DEBUG) { - Log.d(TAG, "Use cached UserHistoryDictionary for " + locale + - " & account" + accountName); + Log.d(TAG, "Use cached UserHistoryDictionary with lookup: " + lookupStr); } dict.reloadDictionaryIfRequired(); return dict; @@ -74,7 +73,7 @@ public class PersonalizationHelper { private static int sCurrentTimestampForTesting = 0; public static void currentTimeChangedForTesting(final int currentTimestamp) { if (TimeUnit.MILLISECONDS.toSeconds( - DictionaryDecayBroadcastReciever.DICTIONARY_DECAY_INTERVAL) + DictionaryDecayBroadcastReciever.DICTIONARY_DECAY_INTERVAL_IN_MILLIS) < currentTimestamp - sCurrentTimestampForTesting) { runGCOnAllOpenedUserHistoryDictionaries(); runGCOnAllOpenedPersonalizationDictionaries(); diff --git a/java/src/com/android/inputmethod/latin/settings/PreferencesSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/PreferencesSettingsFragment.java index c0ceb8857..975396d2d 100644 --- a/java/src/com/android/inputmethod/latin/settings/PreferencesSettingsFragment.java +++ b/java/src/com/android/inputmethod/latin/settings/PreferencesSettingsFragment.java @@ -71,6 +71,7 @@ public final class PreferencesSettingsFragment extends SubScreenFragment { super.onResume(); final Preference voiceInputKeyOption = findPreference(Settings.PREF_VOICE_INPUT_KEY); if (voiceInputKeyOption != null) { + RichInputMethodManager.getInstance().refreshSubtypeCaches(); final boolean isShortcutImeEnabled = RichInputMethodManager.getInstance() .isShortcutImeEnabled(); voiceInputKeyOption.setEnabled(isShortcutImeEnabled); |