diff options
Diffstat (limited to 'java/src')
32 files changed, 313 insertions, 184 deletions
diff --git a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java index be0744393..c38ea0037 100644 --- a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java +++ b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java @@ -118,11 +118,7 @@ public final class SuggestionSpanUtils { if (TextUtils.isEmpty(localeString)) { continue; } - final Locale locale = LocaleUtils.constructLocaleFromString(localeString); - if (locale == null) { - continue; - } - return locale; + return LocaleUtils.constructLocaleFromString(localeString); } return null; } diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionaryService.java b/java/src/com/android/inputmethod/dictionarypack/DictionaryService.java index e6acb8f36..c678f081d 100644 --- a/java/src/com/android/inputmethod/dictionarypack/DictionaryService.java +++ b/java/src/com/android/inputmethod/dictionarypack/DictionaryService.java @@ -22,6 +22,7 @@ import android.app.Service; import android.content.Context; import android.content.Intent; import android.os.IBinder; +import android.util.Log; import android.widget.Toast; import com.android.inputmethod.latin.R; @@ -33,6 +34,8 @@ import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import javax.annotation.Nonnull; + /** * Service that handles background tasks for the dictionary provider. * @@ -51,6 +54,8 @@ import java.util.concurrent.TimeUnit; * to access, and mark the current state as such. */ public final class DictionaryService extends Service { + private static final String TAG = DictionaryService.class.getSimpleName(); + /** * The package name, to use in the intent actions. */ @@ -156,9 +161,14 @@ public final class DictionaryService extends Service { final int startId) { final DictionaryService self = this; if (SHOW_DOWNLOAD_TOAST_INTENT_ACTION.equals(intent.getAction())) { - // This is a UI action, it can't be run in another thread - showStartDownloadingToast(this, LocaleUtils.constructLocaleFromString( - intent.getStringExtra(LOCALE_INTENT_ARGUMENT))); + final String localeString = intent.getStringExtra(LOCALE_INTENT_ARGUMENT); + if (localeString == null) { + Log.e(TAG, "Received " + intent.getAction() + " without locale; skipped"); + } else { + // This is a UI action, it can't be run in another thread + showStartDownloadingToast( + this, LocaleUtils.constructLocaleFromString(localeString)); + } } else { // If it's a command that does not require UI, arrange for the work to be done on a // separate thread, so that we can return right away. The executor will spawn a thread @@ -245,7 +255,8 @@ public final class DictionaryService extends Service { /** * Shows a toast informing the user that an automatic dictionary download is starting. */ - private static void showStartDownloadingToast(final Context context, final Locale locale) { + private static void showStartDownloadingToast(final Context context, + @Nonnull final Locale locale) { final String toastText = String.format( context.getString(R.string.toast_downloading_suggestions), locale.getDisplayName()); diff --git a/java/src/com/android/inputmethod/dictionarypack/DownloadOverMeteredDialog.java b/java/src/com/android/inputmethod/dictionarypack/DownloadOverMeteredDialog.java index 50b3c72f3..91ed673ae 100644 --- a/java/src/com/android/inputmethod/dictionarypack/DownloadOverMeteredDialog.java +++ b/java/src/com/android/inputmethod/dictionarypack/DownloadOverMeteredDialog.java @@ -28,7 +28,7 @@ import com.android.inputmethod.annotations.ExternallyReferenced; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.common.LocaleUtils; -import java.util.Locale; +import javax.annotation.Nullable; /** * This implements the dialog for asking the user whether it's okay to download dictionaries over @@ -54,11 +54,11 @@ public final class DownloadOverMeteredDialog extends Activity { setTexts(localeString, size); } - private void setTexts(final String localeString, final long size) { + private void setTexts(@Nullable final String localeString, final long size) { final String promptFormat = getString(R.string.should_download_over_metered_prompt); final String allowButtonFormat = getString(R.string.download_over_metered); - final Locale locale = LocaleUtils.constructLocaleFromString(localeString); - final String language = (null == locale ? "" : locale.getDisplayLanguage()); + final String language = (null == localeString) ? "" + : LocaleUtils.constructLocaleFromString(localeString).getDisplayLanguage(); final TextView prompt = (TextView)findViewById(R.id.download_over_metered_prompt); prompt.setText(Html.fromHtml(String.format(promptFormat, language))); final Button allowButton = (Button)findViewById(R.id.allow_button); diff --git a/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java b/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java index aeb666704..f05db9dab 100644 --- a/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java +++ b/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java @@ -57,7 +57,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; import java.util.List; -import java.util.Locale; import java.util.Set; import java.util.TreeSet; @@ -880,8 +879,8 @@ public final class UpdateHandler { // None of those are expected to happen, but just in case... if (null == notificationIntent || null == notificationManager) return; - final Locale locale = LocaleUtils.constructLocaleFromString(localeString); - final String language = (null == locale ? "" : locale.getDisplayLanguage()); + final String language = (null == localeString) ? "" + : LocaleUtils.constructLocaleFromString(localeString).getDisplayLanguage(); final String titleFormat = context.getString(R.string.dict_available_notification_title); final String notificationTitle = String.format(titleFormat, language); final Notification.Builder builder = new Notification.Builder(context) diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java index 5e3a5f17c..d19f506ab 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java @@ -22,7 +22,9 @@ import android.util.Log; import android.view.ContextThemeWrapper; import android.view.LayoutInflater; import android.view.View; +import android.view.ViewGroup; import android.view.inputmethod.EditorInfo; +import android.widget.LinearLayout; import com.android.inputmethod.compat.InputMethodServiceCompatUtils; import com.android.inputmethod.event.Event; @@ -64,7 +66,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { private KeyboardTheme mKeyboardTheme; private Context mThemeContext; - + private View mHorizontalKeyboardFrame; private static final KeyboardSwitcher sInstance = new KeyboardSwitcher(); public static KeyboardSwitcher getInstance() { @@ -111,8 +113,16 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { final KeyboardLayoutSet.Builder builder = new KeyboardLayoutSet.Builder( mThemeContext, editorInfo); final Resources res = mThemeContext.getResources(); - final int keyboardWidth = ResourceUtils.getDefaultKeyboardWidth(res); + final ViewGroup.MarginLayoutParams p = + (ViewGroup.MarginLayoutParams) mHorizontalKeyboardFrame.getLayoutParams(); + + final int keyboardLeftMargin = ResourceUtils.getKeyboardLeftMargin(res, settingsValues); + final int keyboardRightMargin = ResourceUtils.getKeyboardRightMargin(res, settingsValues); + final int keyboardBottomMargin = ResourceUtils.getKeyboardBottomMargin(res, settingsValues); + p.setMargins(keyboardLeftMargin, 0, keyboardRightMargin, keyboardBottomMargin); + final int keyboardHeight = ResourceUtils.getKeyboardHeight(res, settingsValues); + final int keyboardWidth = ResourceUtils.getKeyboardWidth(res, settingsValues); builder.setKeyboardGeometry(keyboardWidth, keyboardHeight); builder.setSubtype(RichInputMethodManager.getInstance().getCurrentSubtype()); builder.setVoiceInputKeyEnabled(settingsValues.mShowsVoiceInputKey); @@ -411,6 +421,8 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { mEmojiPalettesView.setHardwareAcceleratedDrawingEnabled( isHardwareAcceleratedDrawingEnabled); mEmojiPalettesView.setKeyboardActionListener(mLatinIME); + mHorizontalKeyboardFrame = (LinearLayout)mCurrentInputView.findViewById( + R.id.horizontal_keyboard_frame); return mCurrentInputView; } diff --git a/java/src/com/android/inputmethod/keyboard/emoji/EmojiLayoutParams.java b/java/src/com/android/inputmethod/keyboard/emoji/EmojiLayoutParams.java index 582e09124..2ac79975d 100644 --- a/java/src/com/android/inputmethod/keyboard/emoji/EmojiLayoutParams.java +++ b/java/src/com/android/inputmethod/keyboard/emoji/EmojiLayoutParams.java @@ -39,7 +39,7 @@ final class EmojiLayoutParams { public EmojiLayoutParams(final Resources res) { final int defaultKeyboardHeight = ResourceUtils.getDefaultKeyboardHeight(res); - final int defaultKeyboardWidth = ResourceUtils.getDefaultKeyboardWidth(res); + final int defaultKeyboardWidth = ResourceUtils.getKeyboardFrameWidth(res); mKeyVerticalGap = (int) res.getFraction(R.fraction.config_key_vertical_gap_holo, defaultKeyboardHeight, defaultKeyboardHeight); mBottomPadding = (int) res.getFraction(R.fraction.config_keyboard_bottom_padding_holo, diff --git a/java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesView.java b/java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesView.java index cf4dd3db3..223947e38 100644 --- a/java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesView.java +++ b/java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesView.java @@ -50,6 +50,8 @@ import com.android.inputmethod.latin.AudioAndHapticFeedbackManager; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.RichInputMethodSubtype; import com.android.inputmethod.latin.common.Constants; +import com.android.inputmethod.latin.settings.Settings; +import com.android.inputmethod.latin.settings.SettingsValues; import com.android.inputmethod.latin.utils.ResourceUtils; import java.util.concurrent.TimeUnit; @@ -113,9 +115,10 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange context, null /* editorInfo */); final Resources res = context.getResources(); mEmojiLayoutParams = new EmojiLayoutParams(res); + final SettingsValues s = Settings.getInstance().getCurrent(); builder.setSubtype(RichInputMethodSubtype.getEmojiSubtype()); - builder.setKeyboardGeometry(ResourceUtils.getDefaultKeyboardWidth(res), - mEmojiLayoutParams.mEmojiKeyboardHeight); + builder.setKeyboardGeometry(ResourceUtils.getKeyboardWidth(res, s), + ResourceUtils.getKeyboardHeight(res, s)); final KeyboardLayoutSet layoutSet = builder.build(); final TypedArray emojiPalettesViewAttr = context.obtainStyledAttributes(attrs, R.styleable.EmojiPalettesView, defStyle, R.style.EmojiPalettesView); @@ -140,7 +143,7 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange super.onMeasure(widthMeasureSpec, heightMeasureSpec); final Resources res = getContext().getResources(); // The main keyboard expands to the entire this {@link KeyboardView}. - final int width = ResourceUtils.getDefaultKeyboardWidth(res) + final int width = ResourceUtils.getKeyboardFrameWidth(res) + getPaddingLeft() + getPaddingRight(); final int height = ResourceUtils.getDefaultKeyboardHeight(res) + res.getDimensionPixelSize(R.dimen.config_suggestions_strip_height) diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java index f2d7a8c3c..acf9cf10c 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java @@ -264,7 +264,7 @@ public class DictionaryFacilitator { return mMostProbableDictionaryGroup; } - public void switchMostProbableLanguage(final Locale locale) { + public void switchMostProbableLanguage(@Nullable final Locale locale) { if (null == locale) { // In many cases, there is no locale to a committed word. For example, a typed word // that is in none of the currently active dictionaries but still does not @@ -301,6 +301,9 @@ public class DictionaryFacilitator { if (!mostProbableDictionaryGroup.mLocale.equals(mLocale)) { return false; } + if (mDictionaryGroups.length <= 1) { + return true; + } return mostProbableDictionaryGroup.mConfidence >= CONFIDENCE_THRESHOLD; } diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java index 4de1f99af..781ab06c5 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java @@ -98,25 +98,23 @@ public final class DictionaryFactory { } final String wordlistId = DictionaryInfoUtils.getWordListIdFromFileName(new File(f.mFilename).getName()); - if (null != wordlistId) { - // TODO: this is a reasonable last resort, but it is suboptimal. - // The following will remove the entry for this dictionary with the dictionary - // provider. When the metadata is downloaded again, we will try downloading it - // again. - // However, in the practice that will mean the user will find themselves without - // the new dictionary. That's fine for languages where it's included in the APK, - // but for other languages it will leave the user without a dictionary at all until - // the next update, which may be a few days away. - // Ideally, we would trigger a new download right away, and use increasing retry - // delays for this particular id/version combination. - // Then again, this is expected to only ever happen in case of human mistake. If - // the wrong file is on the server, the following is still doing the right thing. - // If it's a file left over from the last version however, it's not great. - BinaryDictionaryFileDumper.reportBrokenFileToDictionaryProvider( - providerClient, - context.getString(R.string.dictionary_pack_client_id), - wordlistId); - } + // TODO: this is a reasonable last resort, but it is suboptimal. + // The following will remove the entry for this dictionary with the dictionary + // provider. When the metadata is downloaded again, we will try downloading it + // again. + // However, in the practice that will mean the user will find themselves without + // the new dictionary. That's fine for languages where it's included in the APK, + // but for other languages it will leave the user without a dictionary at all until + // the next update, which may be a few days away. + // Ideally, we would trigger a new download right away, and use increasing retry + // delays for this particular id/version combination. + // Then again, this is expected to only ever happen in case of human mistake. If + // the wrong file is on the server, the following is still doing the right thing. + // If it's a file left over from the last version however, it's not great. + BinaryDictionaryFileDumper.reportBrokenFileToDictionaryProvider( + providerClient, + context.getString(R.string.dictionary_pack_client_id), + wordlistId); } } diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 66746cb6a..bd660c5f3 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -100,6 +100,7 @@ import com.android.inputmethod.latin.utils.ImportantNoticeUtils; import com.android.inputmethod.latin.utils.IntentUtils; import com.android.inputmethod.latin.utils.JniUtils; import com.android.inputmethod.latin.utils.LeakGuardHandlerWrapper; +import com.android.inputmethod.latin.utils.ResourceUtils; import com.android.inputmethod.latin.utils.StatsUtils; import com.android.inputmethod.latin.utils.StatsUtilsManager; import com.android.inputmethod.latin.utils.SubtypeLocaleUtils; @@ -590,7 +591,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 +731,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen unregisterReceiver(mDictionaryPackInstallReceiver); unregisterReceiver(mDictionaryDumpBroadcastReceiver); mStatsUtilsManager.onDestroy(); + DictionaryDecayBroadcastReciever.cancelIntervalAlarmForDictionaryDecaying(this); super.onDestroy(); } @@ -865,7 +866,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 +883,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(); @@ -1210,6 +1212,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen return; } final SettingsValues settingsValues = mSettings.getCurrent(); + final Resources res = getResources(); final View visibleKeyboardView = mKeyboardSwitcher.getVisibleKeyboardView(); if (visibleKeyboardView == null || !hasSuggestionStripView()) { return; @@ -1227,13 +1230,15 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen final int suggestionsHeight = (!mKeyboardSwitcher.isShowingEmojiPalettes() && mSuggestionStripView.getVisibility() == View.VISIBLE) ? mSuggestionStripView.getHeight() : 0; - final int visibleTopY = inputHeight - visibleKeyboardView.getHeight() - suggestionsHeight; + final int visibleTopY = inputHeight + - ResourceUtils.getKeyboardFrameHeight(res, settingsValues) + - suggestionsHeight; mSuggestionStripView.setMoreSuggestionsHeight(visibleTopY); // Need to set expanded touchable region only if a keyboard view is being shown. if (visibleKeyboardView.isShown()) { final int touchLeft = 0; final int touchTop = mKeyboardSwitcher.isShowingMoreKeysPanel() ? 0 : visibleTopY; - final int touchRight = visibleKeyboardView.getWidth(); + final int touchRight = ResourceUtils.getKeyboardFrameWidth(res); final int touchBottom = inputHeight // Extend touchable region below the keyboard. + EXTENDED_TOUCHABLE_REGION_HEIGHT; @@ -1448,7 +1453,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/NgramContext.java b/java/src/com/android/inputmethod/latin/NgramContext.java index 82a13274d..b47731229 100644 --- a/java/src/com/android/inputmethod/latin/NgramContext.java +++ b/java/src/com/android/inputmethod/latin/NgramContext.java @@ -133,7 +133,7 @@ public class NgramContext { // n is 1-indexed. @UsedForTesting - public boolean isNthPrevWordBeginningOfSontence(final int n) { + public boolean isNthPrevWordBeginningOfSentence(final int n) { if (n <= 0 || n > mPrevWordsCount) { return false; } 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/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java index 390b311e2..30dd51aed 100644 --- a/java/src/com/android/inputmethod/latin/SuggestedWords.java +++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java @@ -27,7 +27,6 @@ import com.android.inputmethod.latin.define.DebugFlags; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; -import java.util.Locale; import javax.annotation.Nonnull; import javax.annotation.Nullable; diff --git a/java/src/com/android/inputmethod/latin/debug/ExternalDictionaryGetterForDebug.java b/java/src/com/android/inputmethod/latin/debug/ExternalDictionaryGetterForDebug.java index 78bfd2b52..8cc3552ed 100644 --- a/java/src/com/android/inputmethod/latin/debug/ExternalDictionaryGetterForDebug.java +++ b/java/src/com/android/inputmethod/latin/debug/ExternalDictionaryGetterForDebug.java @@ -101,12 +101,12 @@ public class ExternalDictionaryGetterForDebug { final File file = new File(dirPath, fileName.toString()); final DictionaryHeader header = DictionaryInfoUtils.getDictionaryFileHeaderOrNull(file); final StringBuilder message = new StringBuilder(); - final String locale = header.getLocaleString(); - for (String key : header.mDictionaryOptions.mAttributes.keySet()) { + final String localeString = header.mLocaleString; + for (final String key : header.mDictionaryOptions.mAttributes.keySet()) { message.append(key + " = " + header.mDictionaryOptions.mAttributes.get(key)); message.append("\n"); } - final String languageName = LocaleUtils.constructLocaleFromString(locale) + final String languageName = LocaleUtils.constructLocaleFromString(localeString) .getDisplayName(Locale.getDefault()); final String title = String.format( context.getString(R.string.read_external_dictionary_confirm_install_message), @@ -146,11 +146,12 @@ public class ExternalDictionaryGetterForDebug { BufferedOutputStream outputStream = null; File tempFile = null; try { - final String locale = header.getLocaleString(); + final String localeString = header.mLocaleString; // Create the id for a main dictionary for this locale final String id = BinaryDictionaryGetter.MAIN_DICTIONARY_CATEGORY - + BinaryDictionaryGetter.ID_CATEGORY_SEPARATOR + locale; - final String finalFileName = DictionaryInfoUtils.getCacheFileName(id, locale, context); + + BinaryDictionaryGetter.ID_CATEGORY_SEPARATOR + localeString; + final String finalFileName = DictionaryInfoUtils.getCacheFileName( + id, localeString, context); final String tempFileName = BinaryDictionaryGetter.getTempFileName(id, context); tempFile = new File(tempFileName); tempFile.delete(); diff --git a/java/src/com/android/inputmethod/latin/makedict/DictionaryHeader.java b/java/src/com/android/inputmethod/latin/makedict/DictionaryHeader.java index 644818ba6..4d253b0cb 100644 --- a/java/src/com/android/inputmethod/latin/makedict/DictionaryHeader.java +++ b/java/src/com/android/inputmethod/latin/makedict/DictionaryHeader.java @@ -19,13 +19,24 @@ package com.android.inputmethod.latin.makedict; import com.android.inputmethod.latin.makedict.FormatSpec.DictionaryOptions; import com.android.inputmethod.latin.makedict.FormatSpec.FormatOptions; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * Class representing dictionary header. */ public final class DictionaryHeader { public final int mBodyOffset; + @Nonnull public final DictionaryOptions mDictionaryOptions; + @Nonnull public final FormatOptions mFormatOptions; + @Nonnull + public final String mLocaleString; + @Nonnull + public final String mVersionString; + @Nonnull + public final String mIdString; // Note that these are corresponding definitions in native code in latinime::HeaderPolicy // and latinime::HeaderReadWriteUtils. @@ -46,39 +57,32 @@ public final class DictionaryHeader { public static final String ATTRIBUTE_VALUE_TRUE = "1"; public static final String CODE_POINT_TABLE_KEY = "codePointTable"; - public DictionaryHeader(final int headerSize, final DictionaryOptions dictionaryOptions, - final FormatOptions formatOptions) throws UnsupportedFormatException { + public DictionaryHeader(final int headerSize, + @Nonnull final DictionaryOptions dictionaryOptions, + @Nonnull final FormatOptions formatOptions) throws UnsupportedFormatException { mDictionaryOptions = dictionaryOptions; mFormatOptions = formatOptions; mBodyOffset = formatOptions.mVersion < FormatSpec.VERSION4 ? headerSize : 0; - if (null == getLocaleString()) { + final String localeString = dictionaryOptions.mAttributes.get(DICTIONARY_LOCALE_KEY); + if (null == localeString) { throw new UnsupportedFormatException("Cannot create a FileHeader without a locale"); } - if (null == getVersion()) { + final String versionString = dictionaryOptions.mAttributes.get(DICTIONARY_VERSION_KEY); + if (null == versionString) { throw new UnsupportedFormatException( "Cannot create a FileHeader without a version"); } - if (null == getId()) { + final String idString = dictionaryOptions.mAttributes.get(DICTIONARY_ID_KEY); + if (null == idString) { throw new UnsupportedFormatException("Cannot create a FileHeader without an ID"); } - } - - // Helper method to get the locale as a String - public String getLocaleString() { - return mDictionaryOptions.mAttributes.get(DICTIONARY_LOCALE_KEY); - } - - // Helper method to get the version String - public String getVersion() { - return mDictionaryOptions.mAttributes.get(DICTIONARY_VERSION_KEY); - } - - // Helper method to get the dictionary ID as a String - public String getId() { - return mDictionaryOptions.mAttributes.get(DICTIONARY_ID_KEY); + mLocaleString = localeString; + mVersionString = versionString; + mIdString = idString; } // Helper method to get the description + @Nullable public String getDescription() { // TODO: Right now each dictionary file comes with a description in its own language. // It will display as is no matter the device's locale. It should be internationalized. 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..74196dd6d 100644 --- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java +++ b/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java @@ -74,7 +74,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/CustomInputStylePreference.java b/java/src/com/android/inputmethod/latin/settings/CustomInputStylePreference.java index b749aa51a..21ea8f859 100644 --- a/java/src/com/android/inputmethod/latin/settings/CustomInputStylePreference.java +++ b/java/src/com/android/inputmethod/latin/settings/CustomInputStylePreference.java @@ -196,16 +196,6 @@ final class CustomInputStylePreference extends DialogPreference } } - private static int getSpinnerPosition(final Spinner spinner) { - if (spinner == null) return -1; - return spinner.getSelectedItemPosition(); - } - - private static void setSpinnerPosition(final Spinner spinner, final int position) { - if (spinner == null || position < 0) return; - spinner.setSelection(position); - } - @Override protected Parcelable onSaveInstanceState() { final Parcelable superState = super.onSaveInstanceState(); @@ -216,8 +206,6 @@ final class CustomInputStylePreference extends DialogPreference final SavedState myState = new SavedState(superState); myState.mSubtype = mSubtype; - myState.mSubtypeLocaleSelectedPos = getSpinnerPosition(mSubtypeLocaleSpinner); - myState.mKeyboardLayoutSetSelectedPos = getSpinnerPosition(mKeyboardLayoutSetSpinner); return myState; } @@ -230,15 +218,11 @@ final class CustomInputStylePreference extends DialogPreference final SavedState myState = (SavedState) state; super.onRestoreInstanceState(myState.getSuperState()); - setSpinnerPosition(mSubtypeLocaleSpinner, myState.mSubtypeLocaleSelectedPos); - setSpinnerPosition(mKeyboardLayoutSetSpinner, myState.mKeyboardLayoutSetSelectedPos); setSubtype(myState.mSubtype); } static final class SavedState extends Preference.BaseSavedState { InputMethodSubtype mSubtype; - int mSubtypeLocaleSelectedPos; - int mKeyboardLayoutSetSelectedPos; public SavedState(final Parcelable superState) { super(superState); @@ -247,15 +231,11 @@ final class CustomInputStylePreference extends DialogPreference @Override public void writeToParcel(final Parcel dest, final int flags) { super.writeToParcel(dest, flags); - dest.writeInt(mSubtypeLocaleSelectedPos); - dest.writeInt(mKeyboardLayoutSetSelectedPos); dest.writeParcelable(mSubtype, 0); } public SavedState(final Parcel source) { super(source); - mSubtypeLocaleSelectedPos = source.readInt(); - mKeyboardLayoutSetSelectedPos = source.readInt(); mSubtype = (InputMethodSubtype)source.readParcelable(null); } diff --git a/java/src/com/android/inputmethod/latin/settings/DebugSettings.java b/java/src/com/android/inputmethod/latin/settings/DebugSettings.java index 6fffb8e9d..eff7bde5d 100644 --- a/java/src/com/android/inputmethod/latin/settings/DebugSettings.java +++ b/java/src/com/android/inputmethod/latin/settings/DebugSettings.java @@ -31,6 +31,9 @@ public final class DebugSettings { "pref_has_custom_key_preview_animation_params"; public static final String PREF_RESIZE_KEYBOARD = "pref_resize_keyboard"; public static final String PREF_KEYBOARD_HEIGHT_SCALE = "pref_keyboard_height_scale"; + public static final String PREF_KEYBOARD_BOTTOM_MARGIN = "pref_keyboard_bottom_margin"; + public static final String PREF_KEYBOARD_LEFT_MARGIN = "pref_keyboard_left_margin"; + public static final String PREF_KEYBOARD_RIGHT_MARGIN = "pref_keyboard_right_margin"; public static final String PREF_KEY_PREVIEW_DISMISS_DURATION = "pref_key_preview_dismiss_duration"; public static final String PREF_KEY_PREVIEW_DISMISS_END_X_SCALE = diff --git a/java/src/com/android/inputmethod/latin/settings/DebugSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/DebugSettingsFragment.java index 068f56df1..779bf47c9 100644 --- a/java/src/com/android/inputmethod/latin/settings/DebugSettingsFragment.java +++ b/java/src/com/android/inputmethod/latin/settings/DebugSettingsFragment.java @@ -89,8 +89,14 @@ public final class DebugSettingsFragment extends SubScreenFragment defaultKeyPreviewDismissEndScale); setupKeyPreviewAnimationScale(DebugSettings.PREF_KEY_PREVIEW_DISMISS_END_Y_SCALE, defaultKeyPreviewDismissEndScale); - setupKeyboardHeight( + setupKeyboardScale( DebugSettings.PREF_KEYBOARD_HEIGHT_SCALE, SettingsValues.DEFAULT_SIZE_SCALE); + setupKeyboardScale( + DebugSettings.PREF_KEYBOARD_BOTTOM_MARGIN, SettingsValues.DEFAULT_MARGIN_SCALE); + setupKeyboardScale( + DebugSettings.PREF_KEYBOARD_LEFT_MARGIN, SettingsValues.DEFAULT_MARGIN_SCALE); + setupKeyboardScale( + DebugSettings.PREF_KEYBOARD_RIGHT_MARGIN, SettingsValues.DEFAULT_MARGIN_SCALE); mServiceNeedsRestart = false; mDebugMode = (TwoStatePreference) findPreference(DebugSettings.PREF_DEBUG_MODE); @@ -253,7 +259,7 @@ public final class DebugSettingsFragment extends SubScreenFragment }); } - private void setupKeyboardHeight(final String prefKey, final float defaultValue) { + private void setupKeyboardScale(final String prefKey, final float defaultValue) { final SharedPreferences prefs = getSharedPreferences(); final SeekBarDialogPreference pref = (SeekBarDialogPreference)findPreference(prefKey); if (pref == null) { @@ -282,7 +288,7 @@ public final class DebugSettingsFragment extends SubScreenFragment @Override public int readValue(final String key) { return getPercentageFromValue( - Settings.readKeyboardHeight(prefs, key, defaultValue)); + Settings.readKeyboardScale(prefs, key, defaultValue)); } @Override 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); diff --git a/java/src/com/android/inputmethod/latin/settings/Settings.java b/java/src/com/android/inputmethod/latin/settings/Settings.java index 490fa827c..196fef4cd 100644 --- a/java/src/com/android/inputmethod/latin/settings/Settings.java +++ b/java/src/com/android/inputmethod/latin/settings/Settings.java @@ -367,7 +367,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang return (milliseconds != UNDEFINED_PREFERENCE_VALUE_INT) ? milliseconds : defaultValue; } - public static float readKeyboardHeight(final SharedPreferences prefs, + public static float readKeyboardScale(final SharedPreferences prefs, final String prefKey, final float defaultValue) { final float percentage = prefs.getFloat(prefKey, UNDEFINED_PREFERENCE_VALUE_FLOAT); return (percentage != UNDEFINED_PREFERENCE_VALUE_FLOAT) ? percentage : defaultValue; diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java index c3755792c..99e0565ca 100644 --- a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java +++ b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java @@ -50,6 +50,7 @@ public class SettingsValues { private static final String FLOAT_NEGATIVE_INFINITY_MARKER_STRING = "floatNegativeInfinity"; private static final int TIMEOUT_TO_GET_TARGET_PACKAGE = 5; // seconds public static final float DEFAULT_SIZE_SCALE = 1.0f; // 100% + public static final float DEFAULT_MARGIN_SCALE = 0.0f; // 0% // From resources: public final SpacingAndPunctuations mSpacingAndPunctuations; @@ -113,6 +114,9 @@ public class SettingsValues { public final boolean mHasCustomKeyPreviewAnimationParams; public final boolean mHasKeyboardResize; public final float mKeyboardHeightScale; + public final float mKeyboardBottomMarginScale; + public final float mKeyboardLeftMarginScale; + public final float mKeyboardRightMarginScale; public final int mKeyPreviewShowUpDuration; public final int mKeyPreviewDismissDuration; public final float mKeyPreviewShowUpStartXScale; @@ -190,8 +194,14 @@ public class SettingsValues { mHasCustomKeyPreviewAnimationParams = prefs.getBoolean( DebugSettings.PREF_HAS_CUSTOM_KEY_PREVIEW_ANIMATION_PARAMS, false); mHasKeyboardResize = prefs.getBoolean(DebugSettings.PREF_RESIZE_KEYBOARD, false); - mKeyboardHeightScale = Settings.readKeyboardHeight( + mKeyboardHeightScale = Settings.readKeyboardScale( prefs, DebugSettings.PREF_KEYBOARD_HEIGHT_SCALE, DEFAULT_SIZE_SCALE); + mKeyboardBottomMarginScale = Settings.readKeyboardScale( + prefs, DebugSettings.PREF_KEYBOARD_BOTTOM_MARGIN, DEFAULT_MARGIN_SCALE); + mKeyboardLeftMarginScale = Settings.readKeyboardScale( + prefs, DebugSettings.PREF_KEYBOARD_LEFT_MARGIN, DEFAULT_MARGIN_SCALE); + mKeyboardRightMarginScale = Settings.readKeyboardScale( + prefs, DebugSettings.PREF_KEYBOARD_RIGHT_MARGIN, DEFAULT_MARGIN_SCALE); mKeyPreviewShowUpDuration = Settings.readKeyPreviewAnimationDuration( prefs, DebugSettings.PREF_KEY_PREVIEW_SHOW_UP_DURATION, res.getInteger(R.integer.config_key_preview_show_up_duration)); diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java index c90e8a3cf..4b8d2a3f9 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java @@ -115,7 +115,8 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session { @Override public void onCreate() { final String localeString = getLocale(); - mLocale = LocaleUtils.constructLocaleFromString(localeString); + mLocale = (null == localeString) ? null + : LocaleUtils.constructLocaleFromString(localeString); mScript = ScriptUtils.getScriptFromSpellCheckerLocale(mLocale); } diff --git a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryAddWordContents.java b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryAddWordContents.java index 22fc35a42..69029c51e 100644 --- a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryAddWordContents.java +++ b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryAddWordContents.java @@ -34,6 +34,8 @@ import java.util.ArrayList; import java.util.Locale; import java.util.TreeSet; +import javax.annotation.Nullable; + // Caveat: This class is basically taken from // packages/apps/Settings/src/com/android/settings/inputmethod/UserDictionaryAddWordContents.java // in order to deal with some devices that have issues with the user dictionary handling @@ -218,8 +220,8 @@ public class UserDictionaryAddWordContents { public static class LocaleRenderer { private final String mLocaleString; private final String mDescription; - // LocaleString may NOT be null. - public LocaleRenderer(final Context context, final String localeString) { + + public LocaleRenderer(final Context context, @Nullable final String localeString) { mLocaleString = localeString; if (null == localeString) { mDescription = context.getString(R.string.user_dict_settings_more_languages); diff --git a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryList.java b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryList.java index b9ed35375..6254b54ff 100644 --- a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryList.java +++ b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryList.java @@ -37,6 +37,8 @@ import java.util.List; import java.util.Locale; import java.util.TreeSet; +import javax.annotation.Nullable; + // Caveat: This class is basically taken from // packages/apps/Settings/src/com/android/settings/inputmethod/UserDictionaryList.java // in order to deal with some devices that have issues with the user dictionary handling @@ -131,21 +133,23 @@ public class UserDictionaryList extends PreferenceFragment { /** * Create a single User Dictionary Preference object, with its parameters set. - * @param locale The locale for which this user dictionary is for. + * @param localeString The locale for which this user dictionary is for. * @return The corresponding preference. */ - protected Preference createUserDictionaryPreference(final String locale) { + protected Preference createUserDictionaryPreference(@Nullable final String localeString) { final Preference newPref = new Preference(getActivity()); final Intent intent = new Intent(USER_DICTIONARY_SETTINGS_INTENT_ACTION); - if (null == locale) { + if (null == localeString) { newPref.setTitle(Locale.getDefault().getDisplayName()); } else { - if ("".equals(locale)) + if (localeString.isEmpty()) { newPref.setTitle(getString(R.string.user_dict_settings_all_languages)); - else - newPref.setTitle(LocaleUtils.constructLocaleFromString(locale).getDisplayName()); - intent.putExtra("locale", locale); - newPref.getExtras().putString("locale", locale); + } else { + newPref.setTitle( + LocaleUtils.constructLocaleFromString(localeString).getDisplayName()); + } + intent.putExtra("locale", localeString); + newPref.getExtras().putString("locale", localeString); } newPref.setIntent(intent); newPref.setFragment(UserDictionarySettings.class.getName()); diff --git a/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java b/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java index 8699f2ce7..476c13406 100644 --- a/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java @@ -88,7 +88,7 @@ public class CombinedFormatUtils { for (int i = 0; i < ngramProperty.mNgramContext.getPrevWordCount(); i++) { builder.append(" " + NGRAM_PREV_WORD_TAG + "[" + i + "]=" + ngramProperty.mNgramContext.getNthPrevWord(i + 1)); - if (ngramProperty.mNgramContext.isNthPrevWordBeginningOfSontence(i + 1)) { + if (ngramProperty.mNgramContext.isNthPrevWordBeginningOfSentence(i + 1)) { builder.append("," + BEGINNING_OF_SENTENCE_TAG + "=true"); } builder.append("\n"); diff --git a/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java b/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java index 71d724d74..fcce1ecdd 100644 --- a/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java @@ -40,6 +40,9 @@ import java.util.Iterator; import java.util.Locale; import java.util.concurrent.TimeUnit; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * This class encapsulates the logic for the Latin-IME side of dictionary information management. */ @@ -59,19 +62,26 @@ public class DictionaryInfoUtils { private static final String DATE_COLUMN = "date"; private static final String FILESIZE_COLUMN = "filesize"; private static final String VERSION_COLUMN = "version"; + @Nonnull public final String mId; + @Nonnull public final Locale mLocale; + @Nullable public final String mDescription; + @Nonnull public final AssetFileAddress mFileAddress; public final int mVersion; - public DictionaryInfo(final String id, final Locale locale, final String description, - final AssetFileAddress fileAddress, final int version) { + + public DictionaryInfo(@Nonnull final String id, @Nonnull final Locale locale, + @Nullable final String description, @Nonnull final AssetFileAddress fileAddress, + final int version) { mId = id; mLocale = locale; mDescription = description; mFileAddress = fileAddress; mVersion = version; } + public ContentValues toContentValues() { final ContentValues values = new ContentValues(); values.put(WORDLISTID_COLUMN, mId); @@ -144,7 +154,8 @@ public class DictionaryInfoUtils { /** * Reverse escaping done by replaceFileNameDangerousCharacters. */ - public static String getWordListIdFromFileName(final String fname) { + @Nonnull + public static String getWordListIdFromFileName(@Nonnull final String fname) { final StringBuilder sb = new StringBuilder(); final int fnameLength = fname.length(); for (int i = 0; i < fnameLength; i = fname.offsetByCodePoints(i, 1)) { @@ -176,12 +187,15 @@ public class DictionaryInfoUtils { * {@link #getMainDictId(Locale)} and {@link #isMainWordListId(String)}. * @return The category as a string or null if it can't be found in the file name. */ - public static String getCategoryFromFileName(final String fileName) { + @Nullable + public static String getCategoryFromFileName(@Nonnull final String fileName) { final String id = getWordListIdFromFileName(fileName); final String[] idArray = id.split(BinaryDictionaryGetter.ID_CATEGORY_SEPARATOR); // An id is supposed to be in format category:locale, so splitting on the separator // should yield a 2-elements array - if (2 != idArray.length) return null; + if (2 != idArray.length) { + return null; + } return idArray[0]; } @@ -225,7 +239,9 @@ public class DictionaryInfoUtils { final String[] idArray = id.split(BinaryDictionaryGetter.ID_CATEGORY_SEPARATOR); // An id is supposed to be in format category:locale, so splitting on the separator // should yield a 2-elements array - if (2 != idArray.length) return false; + if (2 != idArray.length) { + return false; + } return BinaryDictionaryGetter.MAIN_DICTIONARY_CATEGORY.equals(idArray[0]); } @@ -277,7 +293,9 @@ public class DictionaryInfoUtils { */ public static int getMainDictionaryResourceId(final Resources res, final Locale locale) { int resourceId = getMainDictionaryResourceIdIfAvailableForLocale(res, locale); - if (0 != resourceId) return resourceId; + if (0 != resourceId) { + return resourceId; + } return res.getIdentifier(DEFAULT_MAIN_DICT, "raw", RESOURCE_PACKAGE_NAME); } @@ -346,10 +364,10 @@ public class DictionaryInfoUtils { if (header == null) { return null; } - final String id = header.getId(); - final Locale locale = LocaleUtils.constructLocaleFromString(header.getLocaleString()); + final String id = header.mIdString; + final Locale locale = LocaleUtils.constructLocaleFromString(header.mLocaleString); final String description = header.getDescription(); - final String version = header.getVersion(); + final String version = header.mVersionString; return new DictionaryInfo(id, locale, description, fileAddress, Integer.parseInt(version)); } @@ -377,10 +395,13 @@ public class DictionaryInfoUtils { if (null != directoryList) { for (final File directory : directoryList) { final String localeString = getWordListIdFromFileName(directory.getName()); - File[] dicts = BinaryDictionaryGetter.getCachedWordLists(localeString, context); + final File[] dicts = BinaryDictionaryGetter.getCachedWordLists( + localeString, context); for (final File dict : dicts) { final String wordListId = getWordListIdFromFileName(dict.getName()); - if (!DictionaryInfoUtils.isMainWordListId(wordListId)) continue; + if (!DictionaryInfoUtils.isMainWordListId(wordListId)) { + continue; + } final Locale locale = LocaleUtils.constructLocaleFromString(localeString); final AssetFileAddress fileAddress = AssetFileAddress.makeFromFile(dict); final DictionaryInfo dictionaryInfo = @@ -388,7 +409,9 @@ public class DictionaryInfoUtils { // Protect against cases of a less-specific dictionary being found, like an // en dictionary being used for an en_US locale. In this case, the en dictionary // should be used for en_US but discounted for listing purposes. - if (dictionaryInfo == null || !dictionaryInfo.mLocale.equals(locale)) continue; + if (dictionaryInfo == null || !dictionaryInfo.mLocale.equals(locale)) { + continue; + } addOrUpdateDictInfo(dictList, dictionaryInfo); } } @@ -402,14 +425,18 @@ public class DictionaryInfoUtils { final int resourceId = DictionaryInfoUtils.getMainDictionaryResourceIdIfAvailableForLocale( context.getResources(), locale); - if (0 == resourceId) continue; + if (0 == resourceId) { + continue; + } final AssetFileAddress fileAddress = BinaryDictionaryGetter.loadFallbackResource(context, resourceId); final DictionaryInfo dictionaryInfo = createDictionaryInfoFromFileAddress(fileAddress); // Protect against cases of a less-specific dictionary being found, like an // en dictionary being used for an en_US locale. In this case, the en dictionary // should be used for en_US but discounted for listing purposes. - if (!dictionaryInfo.mLocale.equals(locale)) continue; + if (!dictionaryInfo.mLocale.equals(locale)) { + continue; + } addOrUpdateDictInfo(dictList, dictionaryInfo); } @@ -419,7 +446,9 @@ public class DictionaryInfoUtils { @UsedForTesting public static boolean looksValidForDictionaryInsertion(final CharSequence text, final SpacingAndPunctuations spacingAndPunctuations) { - if (TextUtils.isEmpty(text)) return false; + if (TextUtils.isEmpty(text)) { + return false; + } final int length = text.length(); if (length > Constants.DICTIONARY_MAX_WORD_LENGTH) { return false; @@ -435,7 +464,9 @@ public class DictionaryInfoUtils { digitCount += charCount; continue; } - if (!spacingAndPunctuations.isWordCodePoint(codePoint)) return false; + if (!spacingAndPunctuations.isWordCodePoint(codePoint)) { + return false; + } } // We reject strings entirely comprised of digits to avoid using PIN codes or credit // card numbers. It would come in handy for word prediction though; a good example is diff --git a/java/src/com/android/inputmethod/latin/utils/DistracterFilterCheckingExactMatchesAndSuggestions.java b/java/src/com/android/inputmethod/latin/utils/DistracterFilterCheckingExactMatchesAndSuggestions.java index 9c6a94810..0c01a737c 100644 --- a/java/src/com/android/inputmethod/latin/utils/DistracterFilterCheckingExactMatchesAndSuggestions.java +++ b/java/src/com/android/inputmethod/latin/utils/DistracterFilterCheckingExactMatchesAndSuggestions.java @@ -143,7 +143,7 @@ public class DistracterFilterCheckingExactMatchesAndSuggestions implements Distr final KeyboardLayoutSet.Builder builder = new KeyboardLayoutSet.Builder( mContext, editorInfo); final Resources res = mContext.getResources(); - final int keyboardWidth = ResourceUtils.getDefaultKeyboardWidth(res); + final int keyboardWidth = ResourceUtils.getKeyboardFrameWidth(res); final int keyboardHeight = ResourceUtils.getDefaultKeyboardHeight(res); builder.setKeyboardGeometry(keyboardWidth, keyboardHeight); builder.setSubtype(new RichInputMethodSubtype(subtype)); diff --git a/java/src/com/android/inputmethod/latin/utils/ResourceUtils.java b/java/src/com/android/inputmethod/latin/utils/ResourceUtils.java index cc0d470df..0a757877a 100644 --- a/java/src/com/android/inputmethod/latin/utils/ResourceUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/ResourceUtils.java @@ -182,18 +182,63 @@ public final class ResourceUtils { return matchedAll; } - public static int getDefaultKeyboardWidth(final Resources res) { + public static int getKeyboardFrameWidth(final Resources res) { final DisplayMetrics dm = res.getDisplayMetrics(); return dm.widthPixels; } + public static int getKeyboardWidth(final Resources res, final SettingsValues settingsValues) { + final int frameWidth = getKeyboardFrameWidth(res); + if (settingsValues.mHasKeyboardResize) { + final float widthFraction = 1f - settingsValues.mKeyboardLeftMarginScale + - settingsValues.mKeyboardRightMarginScale; + return (int)(frameWidth * widthFraction); + } + return frameWidth; + } + + public static int getKeyboardFrameHeight(final Resources res, + final SettingsValues settingsValues) { + if (settingsValues.mHasKeyboardResize) { + return getKeyboardHeight(res, settingsValues) + + getKeyboardBottomMargin(res, settingsValues); + } + return getDefaultKeyboardHeight(res); + } + public static int getKeyboardHeight(final Resources res, final SettingsValues settingsValues) { - final int defaultKeyboardHeight = getDefaultKeyboardHeight(res); + final int keyboardHeight = getDefaultKeyboardHeight(res); + if (settingsValues.mHasKeyboardResize) { + return (int)(keyboardHeight * settingsValues.mKeyboardHeightScale); + } + return keyboardHeight; + } + + public static int getKeyboardLeftMargin( + final Resources res, final SettingsValues settingsValues) { + if (settingsValues.mHasKeyboardResize) { + final int frameWidth = getKeyboardFrameWidth(res); + return (int)(frameWidth * settingsValues.mKeyboardLeftMarginScale); + } + return 0; + } + + public static int getKeyboardRightMargin( + final Resources res, final SettingsValues settingsValues) { + if (settingsValues.mHasKeyboardResize) { + final int frameWidth = getKeyboardFrameWidth(res); + return (int)(frameWidth * settingsValues.mKeyboardRightMarginScale); + } + return 0; + } + + public static int getKeyboardBottomMargin( + final Resources res, final SettingsValues settingsValues) { if (settingsValues.mHasKeyboardResize) { - // mKeyboardHeightScale Ranges from [.5,1.2], from xml/prefs_screen_debug.xml - return (int)(defaultKeyboardHeight * settingsValues.mKeyboardHeightScale); + final int defaultHeight = getDefaultKeyboardHeight(res); + return (int)(defaultHeight * settingsValues.mKeyboardBottomMarginScale); } - return defaultKeyboardHeight; + return 0; } public static int getDefaultKeyboardHeight(final Resources res) { diff --git a/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java b/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java index 0e7f4717d..54a3fc39c 100644 --- a/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java @@ -199,8 +199,7 @@ public final class SubtypeLocaleUtils { if (sExceptionalLocaleDisplayedInRootLocale.containsKey(localeString)) { languageString = localeString; } else { - final Locale locale = LocaleUtils.constructLocaleFromString(localeString); - languageString = locale.getLanguage(); + languageString = LocaleUtils.constructLocaleFromString(localeString).getLanguage(); } return getSubtypeLocaleDisplayNameInternal(languageString, displayLocale); } @@ -232,8 +231,8 @@ public final class SubtypeLocaleUtils { }; displayName = getExceptionalName.runInLocale(sResources, displayLocale); } else { - final Locale locale = LocaleUtils.constructLocaleFromString(localeString); - displayName = locale.getDisplayName(displayLocale); + displayName = LocaleUtils.constructLocaleFromString(localeString) + .getDisplayName(displayLocale); } return StringUtils.capitalizeFirstCodePoint(displayName, displayLocale); } |