diff options
Diffstat (limited to 'java/src/com')
141 files changed, 1359 insertions, 1528 deletions
diff --git a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java index edcdd4c4c..9f7caa47e 100644 --- a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java +++ b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java @@ -26,8 +26,8 @@ import android.view.inputmethod.EditorInfo; import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.KeyboardId; -import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.utils.StringUtils; import java.util.Locale; @@ -346,7 +346,8 @@ final class KeyCodeDescriptionMapper { } // TODO: Remove this method once TTS supports emoticon verbalization. - private String getSpokenEmoticonDescription(final Context context, final String outputText) { + private static String getSpokenEmoticonDescription(final Context context, + final String outputText) { final StringBuilder sb = new StringBuilder(SPOKEN_EMOTICON_RESOURCE_NAME_PREFIX); final int textLength = outputText.length(); for (int index = 0; index < textLength; index = outputText.offsetByCodePoints(index, 1)) { diff --git a/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityNodeProvider.java b/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityNodeProvider.java index 66b0acb2f..7fc1e9d8a 100644 --- a/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityNodeProvider.java +++ b/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityNodeProvider.java @@ -329,9 +329,8 @@ final class KeyboardAccessibilityNodeProvider<KV extends KeyboardView> if (currentSettings.isWordSeparator(key.getCode())) { return mAccessibilityUtils.getAutoCorrectionDescription( keyCodeDescription, shouldObscure); - } else { - return keyCodeDescription; } + return keyCodeDescription; } /** diff --git a/java/src/com/android/inputmethod/annotations/ExternallyReferenced.java b/java/src/com/android/inputmethod/annotations/ExternallyReferenced.java deleted file mode 100644 index ea5f12ce2..000000000 --- a/java/src/com/android/inputmethod/annotations/ExternallyReferenced.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.inputmethod.annotations; - -/** - * Denotes that the class, method or field should not be eliminated by ProGuard, - * because it is externally referenced. (See proguard.flags) - */ -public @interface ExternallyReferenced { -} diff --git a/java/src/com/android/inputmethod/annotations/UsedForTesting.java b/java/src/com/android/inputmethod/annotations/UsedForTesting.java deleted file mode 100644 index 2ada091e4..000000000 --- a/java/src/com/android/inputmethod/annotations/UsedForTesting.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.inputmethod.annotations; - -/** - * Denotes that the class, method or field should not be eliminated by ProGuard, - * so that unit tests can access it. (See proguard.flags) - */ -public @interface UsedForTesting { -} diff --git a/java/src/com/android/inputmethod/compat/BuildCompatUtils.java b/java/src/com/android/inputmethod/compat/BuildCompatUtils.java index 7d1717bd1..5d56f12ae 100644 --- a/java/src/com/android/inputmethod/compat/BuildCompatUtils.java +++ b/java/src/com/android/inputmethod/compat/BuildCompatUtils.java @@ -33,11 +33,4 @@ public final class BuildCompatUtils { public static final int EFFECTIVE_SDK_INT = IS_RELEASE_BUILD ? Build.VERSION.SDK_INT : Build.VERSION.SDK_INT + 1; - - /** - * API version for L-release. - */ - // TODO: Substitute this constant reference with Build.VERSION_CODES.L* once the *next* version - // becomes available. - public static final int VERSION_CODES_LXX = 21; } diff --git a/java/src/com/android/inputmethod/compat/CompatUtils.java b/java/src/com/android/inputmethod/compat/CompatUtils.java index 6aa2736c1..5db80190c 100644 --- a/java/src/com/android/inputmethod/compat/CompatUtils.java +++ b/java/src/com/android/inputmethod/compat/CompatUtils.java @@ -144,7 +144,7 @@ public final class CompatUtils { public <T> ToObjectMethodWrapper<T> getMethod(final String name, final T defaultValue, final Class<?>... parameterTypes) { - return new ToObjectMethodWrapper<T>(CompatUtils.getMethod(mClass, name, parameterTypes), + return new ToObjectMethodWrapper<>(CompatUtils.getMethod(mClass, name, parameterTypes), defaultValue); } diff --git a/java/src/com/android/inputmethod/compat/CursorAnchorInfoCompatWrapper.java b/java/src/com/android/inputmethod/compat/CursorAnchorInfoCompatWrapper.java index f4f54b624..01a9e6712 100644 --- a/java/src/com/android/inputmethod/compat/CursorAnchorInfoCompatWrapper.java +++ b/java/src/com/android/inputmethod/compat/CursorAnchorInfoCompatWrapper.java @@ -46,14 +46,14 @@ public class CursorAnchorInfoCompatWrapper { */ public static final int FLAG_IS_RTL = 0x04; - private CursorAnchorInfoCompatWrapper() { + CursorAnchorInfoCompatWrapper() { // This class is not publicly instantiable. } - @TargetApi(BuildCompatUtils.VERSION_CODES_LXX) + @TargetApi(Build.VERSION_CODES.LOLLIPOP) @Nullable public static CursorAnchorInfoCompatWrapper wrap(@Nullable final CursorAnchorInfo instance) { - if (Build.VERSION.SDK_INT < BuildCompatUtils.VERSION_CODES_LXX) { + if (BuildCompatUtils.EFFECTIVE_SDK_INT < Build.VERSION_CODES.LOLLIPOP) { return null; } if (instance == null) { @@ -82,10 +82,12 @@ public class CursorAnchorInfoCompatWrapper { throw new UnsupportedOperationException("not supported."); } + @SuppressWarnings("unused") public RectF getCharacterBounds(final int index) { throw new UnsupportedOperationException("not supported."); } + @SuppressWarnings("unused") public int getCharacterBoundsFlags(final int index) { throw new UnsupportedOperationException("not supported."); } @@ -110,7 +112,7 @@ public class CursorAnchorInfoCompatWrapper { throw new UnsupportedOperationException("not supported."); } - @TargetApi(BuildCompatUtils.VERSION_CODES_LXX) + @TargetApi(Build.VERSION_CODES.LOLLIPOP) private static final class RealWrapper extends CursorAnchorInfoCompatWrapper { @Nonnull diff --git a/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatUtils.java b/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatUtils.java index b9a536721..3a27c5739 100644 --- a/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatUtils.java +++ b/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatUtils.java @@ -20,8 +20,8 @@ import android.os.Build; import android.view.inputmethod.InputMethodSubtype; import com.android.inputmethod.annotations.UsedForTesting; -import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.RichInputMethodSubtype; +import com.android.inputmethod.latin.common.Constants; import java.lang.reflect.Constructor; import java.lang.reflect.Method; @@ -52,6 +52,7 @@ public final class InputMethodSubtypeCompatUtils { // This utility class is not publicly instantiable. } + @SuppressWarnings("deprecation") public static InputMethodSubtype newInputMethodSubtype(int nameId, int iconId, String locale, String mode, String extraValue, boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype, int id) { diff --git a/java/src/com/android/inputmethod/compat/LocaleSpanCompatUtils.java b/java/src/com/android/inputmethod/compat/LocaleSpanCompatUtils.java index f411f181b..58e5a36b6 100644 --- a/java/src/com/android/inputmethod/compat/LocaleSpanCompatUtils.java +++ b/java/src/com/android/inputmethod/compat/LocaleSpanCompatUtils.java @@ -17,6 +17,7 @@ package com.android.inputmethod.compat; import android.text.Spannable; +import android.text.Spanned; import android.text.style.LocaleSpan; import android.util.Log; @@ -127,13 +128,13 @@ public final class LocaleSpanCompatUtils { final int spanFlag = spannable.getSpanFlags(existingLocaleSpan); if (spanStart < newStart) { newStart = spanStart; - isStartExclusive = ((spanFlag & Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) == - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + isStartExclusive = ((spanFlag & Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) == + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } if (newEnd < spanEnd) { newEnd = spanEnd; - isEndExclusive = ((spanFlag & Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) == - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + isEndExclusive = ((spanFlag & Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) == + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } existingLocaleSpansToBeMerged.add(existingLocaleSpan); } @@ -201,24 +202,17 @@ public final class LocaleSpanCompatUtils { private static int getSpanFlag(final int originalFlag, final boolean isStartExclusive, final boolean isEndExclusive) { - return (originalFlag & ~Spannable.SPAN_POINT_MARK_MASK) | + return (originalFlag & ~Spanned.SPAN_POINT_MARK_MASK) | getSpanPointMarkFlag(isStartExclusive, isEndExclusive); } private static int getSpanPointMarkFlag(final boolean isStartExclusive, final boolean isEndExclusive) { if (isStartExclusive) { - if (isEndExclusive) { - return Spannable.SPAN_EXCLUSIVE_EXCLUSIVE; - } else { - return Spannable.SPAN_EXCLUSIVE_INCLUSIVE; - } - } else { - if (isEndExclusive) { - return Spannable.SPAN_INCLUSIVE_EXCLUSIVE; - } else { - return Spannable.SPAN_INCLUSIVE_INCLUSIVE; - } + return isEndExclusive ? Spanned.SPAN_EXCLUSIVE_EXCLUSIVE + : Spanned.SPAN_EXCLUSIVE_INCLUSIVE; } + return isEndExclusive ? Spanned.SPAN_INCLUSIVE_EXCLUSIVE + : Spanned.SPAN_INCLUSIVE_INCLUSIVE; } } diff --git a/java/src/com/android/inputmethod/compat/NotificationCompatUtils.java b/java/src/com/android/inputmethod/compat/NotificationCompatUtils.java index eb180071e..70ab972c5 100644 --- a/java/src/com/android/inputmethod/compat/NotificationCompatUtils.java +++ b/java/src/com/android/inputmethod/compat/NotificationCompatUtils.java @@ -71,13 +71,13 @@ public class NotificationCompatUtils { CompatUtils.invoke(builder, null, METHOD_setPriority, PRIORITY_LOW); } + @SuppressWarnings("deprecation") public static Notification build(final Notification.Builder builder) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { // #build was added in API level 16, JELLY_BEAN return (Notification) CompatUtils.invoke(builder, null, METHOD_build); - } else { - // #getNotification was deprecated in API level 16, JELLY_BEAN - return builder.getNotification(); } + // #getNotification was deprecated in API level 16, JELLY_BEAN + return builder.getNotification(); } } diff --git a/java/src/com/android/inputmethod/compat/ViewOutlineProviderCompatUtils.java b/java/src/com/android/inputmethod/compat/ViewOutlineProviderCompatUtils.java index 52b8b74e8..0c8e5b77d 100644 --- a/java/src/com/android/inputmethod/compat/ViewOutlineProviderCompatUtils.java +++ b/java/src/com/android/inputmethod/compat/ViewOutlineProviderCompatUtils.java @@ -17,6 +17,7 @@ package com.android.inputmethod.compat; import android.inputmethodservice.InputMethodService; +import android.os.Build; import android.view.View; public class ViewOutlineProviderCompatUtils { @@ -34,7 +35,7 @@ public class ViewOutlineProviderCompatUtils { }; public static InsetsUpdater setInsetsOutlineProvider(final View view) { - if (BuildCompatUtils.EFFECTIVE_SDK_INT < BuildCompatUtils.VERSION_CODES_LXX) { + if (BuildCompatUtils.EFFECTIVE_SDK_INT < Build.VERSION_CODES.LOLLIPOP) { return EMPTY_INSETS_UPDATER; } return ViewOutlineProviderCompatUtilsLXX.setInsetsOutlineProvider(view); diff --git a/java/src/com/android/inputmethod/dictionarypack/ButtonSwitcher.java b/java/src/com/android/inputmethod/dictionarypack/ButtonSwitcher.java index 6d6c8f5c6..0fa72c3fd 100644 --- a/java/src/com/android/inputmethod/dictionarypack/ButtonSwitcher.java +++ b/java/src/com/android/inputmethod/dictionarypack/ButtonSwitcher.java @@ -122,19 +122,23 @@ public class ButtonSwitcher extends FrameLayout { mDeleteButton.setTranslationX(STATUS_DELETE == status ? 0 : width); } + // The helper method for {@link AnimatorListenerAdapter}. + void animateButtonIfStatusIsEqual(final View newButton, final int newStatus) { + if (newStatus != mStatus) return; + animateButton(newButton, ANIMATION_IN); + } + private void animateButtonPosition(final int oldStatus, final int newStatus) { final View oldButton = getButton(oldStatus); final View newButton = getButton(newStatus); if (null != oldButton && null != newButton) { // Transition between two buttons : animate out, then in - animateButton(oldButton, ANIMATION_OUT).setListener( - new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(final Animator animation) { - if (newStatus != mStatus) return; - animateButton(newButton, ANIMATION_IN); - } - }); + animateButton(oldButton, ANIMATION_OUT).setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(final Animator animation) { + animateButtonIfStatusIsEqual(newButton, newStatus); + } + }); } else if (null != oldButton) { animateButton(oldButton, ANIMATION_OUT); } else if (null != newButton) { @@ -159,9 +163,8 @@ public class ButtonSwitcher extends FrameLayout { if (ANIMATION_IN == direction) { button.setClickable(true); return button.animate().translationX(0); - } else { - button.setClickable(false); - return button.animate().translationX(outerX - innerX); } + button.setClickable(false); + return button.animate().translationX(outerX - innerX); } } diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionaryDownloadProgressBar.java b/java/src/com/android/inputmethod/dictionarypack/DictionaryDownloadProgressBar.java index 1d84e5888..759852025 100644 --- a/java/src/com/android/inputmethod/dictionarypack/DictionaryDownloadProgressBar.java +++ b/java/src/com/android/inputmethod/dictionarypack/DictionaryDownloadProgressBar.java @@ -148,7 +148,7 @@ public class DictionaryDownloadProgressBar extends ProgressBar { } } - private class UpdateHelper implements Runnable { + class UpdateHelper implements Runnable { private int mProgress; @Override public void run() { diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionaryListInterfaceState.java b/java/src/com/android/inputmethod/dictionarypack/DictionaryListInterfaceState.java index 8e026171d..836340a75 100644 --- a/java/src/com/android/inputmethod/dictionarypack/DictionaryListInterfaceState.java +++ b/java/src/com/android/inputmethod/dictionarypack/DictionaryListInterfaceState.java @@ -32,7 +32,7 @@ import java.util.HashMap; * in case some dictionaries appeared, disappeared, changed states etc. */ public class DictionaryListInterfaceState { - private static class State { + static class State { public boolean mOpen = false; public int mStatus = MetadataDbHelper.STATUS_UNKNOWN; } diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionaryProvider.java b/java/src/com/android/inputmethod/dictionarypack/DictionaryProvider.java index e748321e2..37fa76be7 100644 --- a/java/src/com/android/inputmethod/dictionarypack/DictionaryProvider.java +++ b/java/src/com/android/inputmethod/dictionarypack/DictionaryProvider.java @@ -255,10 +255,9 @@ public final class DictionaryProvider extends ContentProvider { if (null != dictFiles && dictFiles.size() > 0) { PrivateLog.log("Returned " + dictFiles.size() + " files"); return new ResourcePathCursor(dictFiles); - } else { - PrivateLog.log("No dictionary files for this URL"); - return new ResourcePathCursor(Collections.<WordListInfo>emptyList()); } + PrivateLog.log("No dictionary files for this URL"); + return new ResourcePathCursor(Collections.<WordListInfo>emptyList()); // V2_METADATA and V2_DATAFILE are not supported for query() default: return null; @@ -319,14 +318,13 @@ public final class DictionaryProvider extends ContentProvider { final AssetFileDescriptor afd = getContext().getResources().openRawResourceFd( R.raw.empty); return afd; - } else { - final String localFilename = - wordList.getAsString(MetadataDbHelper.LOCAL_FILENAME_COLUMN); - final File f = getContext().getFileStreamPath(localFilename); - final ParcelFileDescriptor pfd = - ParcelFileDescriptor.open(f, ParcelFileDescriptor.MODE_READ_ONLY); - return new AssetFileDescriptor(pfd, 0, pfd.getStatSize()); } + final String localFilename = + wordList.getAsString(MetadataDbHelper.LOCAL_FILENAME_COLUMN); + final File f = getContext().getFileStreamPath(localFilename); + final ParcelFileDescriptor pfd = + ParcelFileDescriptor.open(f, ParcelFileDescriptor.MODE_READ_ONLY); + return new AssetFileDescriptor(pfd, 0, pfd.getStatSize()); } catch (FileNotFoundException e) { // No file : fall through and return null } @@ -461,13 +459,16 @@ public final class DictionaryProvider extends ContentProvider { final String wordlistId = uri.getLastPathSegment(); final String clientId = getClientId(uri); final ContentValues wordList = getWordlistMetadataForWordlistId(clientId, wordlistId); - if (null == wordList) return 0; + if (null == wordList) { + return 0; + } final int status = wordList.getAsInteger(MetadataDbHelper.STATUS_COLUMN); final int version = wordList.getAsInteger(MetadataDbHelper.VERSION_COLUMN); if (MetadataDbHelper.STATUS_DELETING == status) { UpdateHandler.markAsDeleted(getContext(), clientId, wordlistId, version, status); return 1; - } else if (MetadataDbHelper.STATUS_INSTALLED == status) { + } + if (MetadataDbHelper.STATUS_INSTALLED == status) { final String result = uri.getQueryParameter(QUERY_PARAMETER_DELETE_RESULT); if (QUERY_PARAMETER_FAILURE.equals(result)) { if (DEBUG) { @@ -480,15 +481,10 @@ public final class DictionaryProvider extends ContentProvider { wordList.getAsString(MetadataDbHelper.LOCAL_FILENAME_COLUMN); final File f = getContext().getFileStreamPath(localFilename); // f.delete() returns true if the file was successfully deleted, false otherwise - if (f.delete()) { - return 1; - } else { - return 0; - } - } else { - Log.e(TAG, "Attempt to delete a file whose status is " + status); - return 0; + return f.delete() ? 1 : 0; } + Log.e(TAG, "Attempt to delete a file whose status is " + status); + return 0; } /** diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionaryService.java b/java/src/com/android/inputmethod/dictionarypack/DictionaryService.java index 568c80abd..e9b634eec 100644 --- a/java/src/com/android/inputmethod/dictionarypack/DictionaryService.java +++ b/java/src/com/android/inputmethod/dictionarypack/DictionaryService.java @@ -179,7 +179,7 @@ public final class DictionaryService extends Service { return Service.START_REDELIVER_INTENT; } - private static void dispatchBroadcast(final Context context, final Intent intent) { + static void dispatchBroadcast(final Context context, final Intent intent) { if (DATE_CHANGED_INTENT_ACTION.equals(intent.getAction())) { // This happens when the date of the device changes. This normally happens // at midnight local time, but it may happen if the user changes the date diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsActivity.java b/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsActivity.java index 4366348d5..284032beb 100644 --- a/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsActivity.java +++ b/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsActivity.java @@ -18,7 +18,9 @@ package com.android.inputmethod.dictionarypack; import com.android.inputmethod.latin.utils.FragmentUtils; +import android.annotation.TargetApi; import android.content.Intent; +import android.os.Build; import android.os.Bundle; import android.preference.PreferenceActivity; @@ -44,8 +46,8 @@ public final class DictionarySettingsActivity extends PreferenceActivity { return modIntent; } - // TODO: Uncomment the override annotation once we start using SDK version 19. - // @Override + @TargetApi(Build.VERSION_CODES.KITKAT) + @Override public boolean isValidFragment(String fragmentName) { return FragmentUtils.isValidFragment(fragmentName); } diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java b/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java index 11982fa65..c2dc87900 100644 --- a/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java +++ b/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java @@ -31,7 +31,6 @@ import android.preference.Preference; import android.preference.PreferenceFragment; import android.preference.PreferenceGroup; import android.text.TextUtils; -import android.text.format.DateUtils; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; @@ -203,25 +202,19 @@ public final class DictionarySettingsFragment extends PreferenceFragment @Override public void updateCycleCompleted() {} - private void refreshNetworkState() { + void refreshNetworkState() { NetworkInfo info = mConnectivityManager.getActiveNetworkInfo(); boolean isConnected = null == info ? false : info.isConnected(); if (null != mUpdateNowMenu) mUpdateNowMenu.setEnabled(isConnected); } - private void refreshInterface() { + void refreshInterface() { final Activity activity = getActivity(); if (null == activity) return; - final long lastUpdateDate = - MetadataDbHelper.getLastUpdateDateForClient(getActivity(), mClientId); final PreferenceGroup prefScreen = getPreferenceScreen(); final Collection<? extends Preference> prefList = createInstalledDictSettingsCollection(mClientId); - final String updateNowSummary = getString(R.string.last_update) + " " - + DateUtils.formatDateTime(activity, lastUpdateDate, - DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_TIME); - activity.runOnUiThread(new Runnable() { @Override public void run() { @@ -239,14 +232,14 @@ public final class DictionarySettingsFragment extends PreferenceFragment }); } - private Preference createErrorMessage(final Activity activity, final int messageResource) { + private static Preference createErrorMessage(final Activity activity, final int messageResource) { final Preference message = new Preference(activity); message.setTitle(messageResource); message.setEnabled(false); return message; } - private void removeAnyDictSettings(final PreferenceGroup prefGroup) { + static void removeAnyDictSettings(final PreferenceGroup prefGroup) { for (int i = prefGroup.getPreferenceCount() - 1; i >= 0; --i) { prefGroup.removePreference(prefGroup.getPreference(i)); } @@ -276,7 +269,7 @@ public final class DictionarySettingsFragment extends PreferenceFragment .appendQueryParameter(DictionaryProvider.QUERY_PARAMETER_PROTOCOL_VERSION, "2") .build(); final Activity activity = getActivity(); - final Cursor cursor = null == activity ? null + final Cursor cursor = (null == activity) ? null : activity.getContentResolver().query(contentUri, null, null, null, null); if (null == cursor) { @@ -289,61 +282,57 @@ public final class DictionarySettingsFragment extends PreferenceFragment final ArrayList<Preference> result = new ArrayList<>(); result.add(createErrorMessage(activity, R.string.no_dictionaries_available)); return result; - } else { - final String systemLocaleString = Locale.getDefault().toString(); - final TreeMap<String, WordListPreference> prefMap = new TreeMap<>(); - final int idIndex = cursor.getColumnIndex(MetadataDbHelper.WORDLISTID_COLUMN); - final int versionIndex = cursor.getColumnIndex(MetadataDbHelper.VERSION_COLUMN); - final int localeIndex = cursor.getColumnIndex(MetadataDbHelper.LOCALE_COLUMN); - final int descriptionIndex = - cursor.getColumnIndex(MetadataDbHelper.DESCRIPTION_COLUMN); - final int statusIndex = cursor.getColumnIndex(MetadataDbHelper.STATUS_COLUMN); - final int filesizeIndex = cursor.getColumnIndex(MetadataDbHelper.FILESIZE_COLUMN); - do { - final String wordlistId = cursor.getString(idIndex); - final int version = cursor.getInt(versionIndex); - final String localeString = cursor.getString(localeIndex); - final Locale locale = new Locale(localeString); - final String description = cursor.getString(descriptionIndex); - final int status = cursor.getInt(statusIndex); - final int matchLevel = - LocaleUtils.getMatchLevel(systemLocaleString, localeString); - final String matchLevelString = - LocaleUtils.getMatchLevelSortedString(matchLevel); - final int filesize = cursor.getInt(filesizeIndex); - // The key is sorted in lexicographic order, according to the match level, then - // the description. - final String key = matchLevelString + "." + description + "." + wordlistId; - final WordListPreference existingPref = prefMap.get(key); - if (null == existingPref || existingPref.hasPriorityOver(status)) { - final WordListPreference oldPreference = mCurrentPreferenceMap.get(key); - final WordListPreference pref; - if (null != oldPreference - && oldPreference.mVersion == version - && oldPreference.hasStatus(status) - && oldPreference.mLocale.equals(locale)) { - // If the old preference has all the new attributes, reuse it. Ideally, - // we should reuse the old pref even if its status is different and call - // setStatus here, but setStatus calls Preference#setSummary() which - // needs to be done on the UI thread and we're not on the UI thread - // here. We could do all this work on the UI thread, but in this case - // it's probably lighter to stay on a background thread and throw this - // old preference out. - pref = oldPreference; - } else { - // Otherwise, discard it and create a new one instead. - // TODO: when the status is different from the old one, we need to - // animate the old one out before animating the new one in. - pref = new WordListPreference(activity, mDictionaryListInterfaceState, - mClientId, wordlistId, version, locale, description, status, - filesize); - } - prefMap.put(key, pref); - } - } while (cursor.moveToNext()); - mCurrentPreferenceMap = prefMap; - return prefMap.values(); } + final String systemLocaleString = Locale.getDefault().toString(); + final TreeMap<String, WordListPreference> prefMap = new TreeMap<>(); + final int idIndex = cursor.getColumnIndex(MetadataDbHelper.WORDLISTID_COLUMN); + final int versionIndex = cursor.getColumnIndex(MetadataDbHelper.VERSION_COLUMN); + final int localeIndex = cursor.getColumnIndex(MetadataDbHelper.LOCALE_COLUMN); + final int descriptionIndex = cursor.getColumnIndex(MetadataDbHelper.DESCRIPTION_COLUMN); + final int statusIndex = cursor.getColumnIndex(MetadataDbHelper.STATUS_COLUMN); + final int filesizeIndex = cursor.getColumnIndex(MetadataDbHelper.FILESIZE_COLUMN); + do { + final String wordlistId = cursor.getString(idIndex); + final int version = cursor.getInt(versionIndex); + final String localeString = cursor.getString(localeIndex); + final Locale locale = new Locale(localeString); + final String description = cursor.getString(descriptionIndex); + final int status = cursor.getInt(statusIndex); + final int matchLevel = LocaleUtils.getMatchLevel(systemLocaleString, localeString); + final String matchLevelString = LocaleUtils.getMatchLevelSortedString(matchLevel); + final int filesize = cursor.getInt(filesizeIndex); + // The key is sorted in lexicographic order, according to the match level, then + // the description. + final String key = matchLevelString + "." + description + "." + wordlistId; + final WordListPreference existingPref = prefMap.get(key); + if (null == existingPref || existingPref.hasPriorityOver(status)) { + final WordListPreference oldPreference = mCurrentPreferenceMap.get(key); + final WordListPreference pref; + if (null != oldPreference + && oldPreference.mVersion == version + && oldPreference.hasStatus(status) + && oldPreference.mLocale.equals(locale)) { + // If the old preference has all the new attributes, reuse it. Ideally, + // we should reuse the old pref even if its status is different and call + // setStatus here, but setStatus calls Preference#setSummary() which + // needs to be done on the UI thread and we're not on the UI thread + // here. We could do all this work on the UI thread, but in this case + // it's probably lighter to stay on a background thread and throw this + // old preference out. + pref = oldPreference; + } else { + // Otherwise, discard it and create a new one instead. + // TODO: when the status is different from the old one, we need to + // animate the old one out before animating the new one in. + pref = new WordListPreference(activity, mDictionaryListInterfaceState, + mClientId, wordlistId, version, locale, description, status, + filesize); + } + prefMap.put(key, pref); + } + } while (cursor.moveToNext()); + mCurrentPreferenceMap = prefMap; + return prefMap.values(); } finally { cursor.close(); } @@ -396,26 +385,28 @@ public final class DictionarySettingsFragment extends PreferenceFragment if (null != mUpdateNowMenu) mUpdateNowMenu.setTitle(R.string.cancel); } - private void stopLoadingAnimation() { + void stopLoadingAnimation() { final View preferenceView = getView(); final Activity activity = getActivity(); if (null == activity) return; + final View loadingView = mLoadingView; + final MenuItem updateNowMenu = mUpdateNowMenu; activity.runOnUiThread(new Runnable() { - @Override - public void run() { - mLoadingView.setVisibility(View.GONE); - preferenceView.setVisibility(View.VISIBLE); - mLoadingView.startAnimation(AnimationUtils.loadAnimation( - getActivity(), android.R.anim.fade_out)); - preferenceView.startAnimation(AnimationUtils.loadAnimation( - getActivity(), android.R.anim.fade_in)); - // The menu is created by the framework asynchronously after the activity, - // which means it's possible to have the activity running but the menu not - // created yet - hence the necessity for a null check here. - if (null != mUpdateNowMenu) { - mUpdateNowMenu.setTitle(R.string.check_for_updates_now); - } + @Override + public void run() { + loadingView.setVisibility(View.GONE); + preferenceView.setVisibility(View.VISIBLE); + loadingView.startAnimation(AnimationUtils.loadAnimation( + activity, android.R.anim.fade_out)); + preferenceView.startAnimation(AnimationUtils.loadAnimation( + activity, android.R.anim.fade_in)); + // The menu is created by the framework asynchronously after the activity, + // which means it's possible to have the activity running but the menu not + // created yet - hence the necessity for a null check here. + if (null != updateNowMenu) { + updateNowMenu.setTitle(R.string.check_for_updates_now); } - }); + } + }); } } diff --git a/java/src/com/android/inputmethod/dictionarypack/DownloadOverMeteredDialog.java b/java/src/com/android/inputmethod/dictionarypack/DownloadOverMeteredDialog.java index d3c0a910f..f1633ff28 100644 --- a/java/src/com/android/inputmethod/dictionarypack/DownloadOverMeteredDialog.java +++ b/java/src/com/android/inputmethod/dictionarypack/DownloadOverMeteredDialog.java @@ -24,6 +24,7 @@ import android.view.View; import android.widget.Button; import android.widget.TextView; +import com.android.inputmethod.annotations.ExternallyReferenced; import com.android.inputmethod.latin.R; import java.util.Locale; @@ -63,11 +64,19 @@ public final class DownloadOverMeteredDialog extends Activity { allowButton.setText(String.format(allowButtonFormat, ((float)size)/(1024*1024))); } + // This method is externally referenced from layout/download_over_metered.xml using onClick + // attribute of Button. + @ExternallyReferenced + @SuppressWarnings("unused") public void onClickDeny(final View v) { UpdateHandler.setDownloadOverMeteredSetting(this, false); finish(); } + // This method is externally referenced from layout/download_over_metered.xml using onClick + // attribute of Button. + @ExternallyReferenced + @SuppressWarnings("unused") public void onClickAllow(final View v) { UpdateHandler.setDownloadOverMeteredSetting(this, true); UpdateHandler.installIfNeverRequested(this, mClientId, mWordListToDownload, diff --git a/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java b/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java index c9e8f9118..db4315f8f 100644 --- a/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java +++ b/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java @@ -226,7 +226,7 @@ public class MetadataDbHelper extends SQLiteOpenHelper { createClientTable(db); } - private void addRawChecksumColumnUnlessPresent(final SQLiteDatabase db) { + private static void addRawChecksumColumnUnlessPresent(final SQLiteDatabase db) { try { db.execSQL("SELECT " + RAW_CHECKSUM_COLUMN + " FROM " + METADATA_TABLE_NAME + " LIMIT 0;"); @@ -237,7 +237,7 @@ public class MetadataDbHelper extends SQLiteOpenHelper { } } - private void addRetryCountColumnUnlessPresent(final SQLiteDatabase db) { + private static void addRetryCountColumnUnlessPresent(final SQLiteDatabase db) { try { db.execSQL("SELECT " + RETRY_COUNT_COLUMN + " FROM " + METADATA_TABLE_NAME + " LIMIT 0;"); diff --git a/java/src/com/android/inputmethod/dictionarypack/MetadataHandler.java b/java/src/com/android/inputmethod/dictionarypack/MetadataHandler.java index 639d904a0..329b9f62e 100644 --- a/java/src/com/android/inputmethod/dictionarypack/MetadataHandler.java +++ b/java/src/com/android/inputmethod/dictionarypack/MetadataHandler.java @@ -30,9 +30,6 @@ import java.util.List; * Helper class to easy up manipulation of dictionary pack metadata. */ public class MetadataHandler { - @SuppressWarnings("unused") - private static final String TAG = "DictionaryProvider:" + MetadataHandler.class.getSimpleName(); - // The canonical file name for metadata. This is not the name of a real file on the // device, but a symbolic name used in the database and in metadata handling. It is never // tested against, only used for human-readability as the file name for the metadata. diff --git a/java/src/com/android/inputmethod/dictionarypack/PrivateLog.java b/java/src/com/android/inputmethod/dictionarypack/PrivateLog.java index 67dd7b9b7..bb64721d5 100644 --- a/java/src/com/android/inputmethod/dictionarypack/PrivateLog.java +++ b/java/src/com/android/inputmethod/dictionarypack/PrivateLog.java @@ -43,8 +43,8 @@ public class PrivateLog { + COLUMN_DATE + " TEXT," + COLUMN_EVENT + " TEXT);"; - private static final SimpleDateFormat sDateFormat = - new SimpleDateFormat("yyyy/MM/dd HH:mm:ss", Locale.US); + static final SimpleDateFormat sDateFormat = new SimpleDateFormat( + "yyyy/MM/dd HH:mm:ss", Locale.ROOT); private static PrivateLog sInstance = new PrivateLog(); private static DebugHelper sDebugHelper = null; @@ -62,9 +62,9 @@ public class PrivateLog { } } - private static class DebugHelper extends SQLiteOpenHelper { + static class DebugHelper extends SQLiteOpenHelper { - private DebugHelper(final Context context) { + DebugHelper(final Context context) { super(context, LOG_DATABASE_NAME, null, LOG_DATABASE_VERSION); } @@ -84,7 +84,7 @@ public class PrivateLog { insert(db, "Upgrade finished"); } - private static void insert(SQLiteDatabase db, String event) { + static void insert(SQLiteDatabase db, String event) { if (!DEBUG) return; final ContentValues c = new ContentValues(2); c.put(COLUMN_DATE, sDateFormat.format(new Date(System.currentTimeMillis()))); diff --git a/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java b/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java index 90a750493..d59b7a545 100644 --- a/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java +++ b/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java @@ -59,6 +59,8 @@ import java.util.Locale; import java.util.Set; import java.util.TreeSet; +import javax.annotation.Nullable; + /** * Handler for the update process. * @@ -750,19 +752,22 @@ public final class UpdateHandler { * @return an ordered list of runnables to be called to upgrade. */ private static ActionBatch compareMetadataForUpgrade(final Context context, - final String clientId, List<WordListMetadata> from, List<WordListMetadata> to) { + final String clientId, @Nullable final List<WordListMetadata> from, + @Nullable final List<WordListMetadata> to) { final ActionBatch actions = new ActionBatch(); // Upgrade existing word lists DebugLogUtils.l("Comparing dictionaries"); final Set<String> wordListIds = new TreeSet<>(); // TODO: Can these be null? - if (null == from) from = new ArrayList<>(); - if (null == to) to = new ArrayList<>(); - for (WordListMetadata wlData : from) wordListIds.add(wlData.mId); - for (WordListMetadata wlData : to) wordListIds.add(wlData.mId); + final List<WordListMetadata> fromList = (from == null) ? new ArrayList<WordListMetadata>() + : from; + final List<WordListMetadata> toList = (to == null) ? new ArrayList<WordListMetadata>() + : to; + for (WordListMetadata wlData : fromList) wordListIds.add(wlData.mId); + for (WordListMetadata wlData : toList) wordListIds.add(wlData.mId); for (String id : wordListIds) { - final WordListMetadata currentInfo = MetadataHandler.findWordListById(from, id); - final WordListMetadata metadataInfo = MetadataHandler.findWordListById(to, id); + final WordListMetadata currentInfo = MetadataHandler.findWordListById(fromList, id); + final WordListMetadata metadataInfo = MetadataHandler.findWordListById(toList, id); // TODO: Remove the following unnecessary check, since we are now doing the filtering // inside findWordListById. final WordListMetadata newInfo = null == metadataInfo diff --git a/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java b/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java index aea16af0d..500e39e0e 100644 --- a/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java +++ b/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java @@ -38,45 +38,39 @@ import java.util.Locale; * enable or delete it as appropriate for the current state of the word list. */ public final class WordListPreference extends Preference { - static final private String TAG = WordListPreference.class.getSimpleName(); + private static final String TAG = WordListPreference.class.getSimpleName(); // What to display in the "status" field when we receive unknown data as a status from // the content provider. Empty string sounds sensible. - static final private String NO_STATUS_MESSAGE = ""; + private static final String NO_STATUS_MESSAGE = ""; /// Actions - static final private int ACTION_UNKNOWN = 0; - static final private int ACTION_ENABLE_DICT = 1; - static final private int ACTION_DISABLE_DICT = 2; - static final private int ACTION_DELETE_DICT = 3; + private static final int ACTION_UNKNOWN = 0; + private static final int ACTION_ENABLE_DICT = 1; + private static final int ACTION_DISABLE_DICT = 2; + private static final int ACTION_DELETE_DICT = 3; // Members - // The context to get resources - final Context mContext; - // The id of the client for which this preference is. - final String mClientId; // The metadata word list id and version of this word list. public final String mWordlistId; public final int mVersion; public final Locale mLocale; public final String mDescription; + + // The id of the client for which this preference is. + private final String mClientId; // The status private int mStatus; // The size of the dictionary file private final int mFilesize; private final DictionaryListInterfaceState mInterfaceState; - private final OnWordListPreferenceClick mPreferenceClickHandler = - new OnWordListPreferenceClick(); - private final OnActionButtonClick mActionButtonClickHandler = - new OnActionButtonClick(); public WordListPreference(final Context context, final DictionaryListInterfaceState dictionaryListInterfaceState, final String clientId, final String wordlistId, final int version, final Locale locale, final String description, final int status, final int filesize) { super(context, null); - mContext = context; mInterfaceState = dictionaryListInterfaceState; mClientId = clientId; mVersion = version; @@ -116,22 +110,23 @@ public final class WordListPreference extends Preference { } private String getSummary(final int status) { + final Context context = getContext(); switch (status) { - // If we are deleting the word list, for the user it's like it's already deleted. - // It should be reinstallable. Exposing to the user the whole complexity of - // the delayed deletion process between the dictionary pack and Android Keyboard - // would only be confusing. - case MetadataDbHelper.STATUS_DELETING: - case MetadataDbHelper.STATUS_AVAILABLE: - return mContext.getString(R.string.dictionary_available); - case MetadataDbHelper.STATUS_DOWNLOADING: - return mContext.getString(R.string.dictionary_downloading); - case MetadataDbHelper.STATUS_INSTALLED: - return mContext.getString(R.string.dictionary_installed); - case MetadataDbHelper.STATUS_DISABLED: - return mContext.getString(R.string.dictionary_disabled); - default: - return NO_STATUS_MESSAGE; + // If we are deleting the word list, for the user it's like it's already deleted. + // It should be reinstallable. Exposing to the user the whole complexity of + // the delayed deletion process between the dictionary pack and Android Keyboard + // would only be confusing. + case MetadataDbHelper.STATUS_DELETING: + case MetadataDbHelper.STATUS_AVAILABLE: + return context.getString(R.string.dictionary_available); + case MetadataDbHelper.STATUS_DOWNLOADING: + return context.getString(R.string.dictionary_downloading); + case MetadataDbHelper.STATUS_INSTALLED: + return context.getString(R.string.dictionary_installed); + case MetadataDbHelper.STATUS_DISABLED: + return context.getString(R.string.dictionary_disabled); + default: + return NO_STATUS_MESSAGE; } } @@ -154,7 +149,7 @@ public final class WordListPreference extends Preference { { ButtonSwitcher.STATUS_INSTALL, ACTION_ENABLE_DICT } }; - private int getButtonSwitcherStatus(final int status) { + static int getButtonSwitcherStatus(final int status) { if (status >= sStatusActionList.length) { Log.e(TAG, "Unknown status " + status); return ButtonSwitcher.STATUS_NO_BUTTON; @@ -162,7 +157,7 @@ public final class WordListPreference extends Preference { return sStatusActionList[status][0]; } - private static int getActionIdFromStatusAndMenuEntry(final int status) { + static int getActionIdFromStatusAndMenuEntry(final int status) { if (status >= sStatusActionList.length) { Log.e(TAG, "Unknown status " + status); return ACTION_UNKNOWN; @@ -171,9 +166,10 @@ public final class WordListPreference extends Preference { } private void disableDict() { - SharedPreferences prefs = CommonPreferences.getCommonPreferences(mContext); + final Context context = getContext(); + final SharedPreferences prefs = CommonPreferences.getCommonPreferences(context); CommonPreferences.disable(prefs, mWordlistId); - UpdateHandler.markAsUnused(mContext, mClientId, mWordlistId, mVersion, mStatus); + UpdateHandler.markAsUnused(context, mClientId, mWordlistId, mVersion, mStatus); if (MetadataDbHelper.STATUS_DOWNLOADING == mStatus) { setStatus(MetadataDbHelper.STATUS_AVAILABLE); } else if (MetadataDbHelper.STATUS_INSTALLED == mStatus) { @@ -184,11 +180,13 @@ public final class WordListPreference extends Preference { Log.e(TAG, "Unexpected state of the word list for disabling " + mStatus); } } + private void enableDict() { - SharedPreferences prefs = CommonPreferences.getCommonPreferences(mContext); + final Context context = getContext(); + final SharedPreferences prefs = CommonPreferences.getCommonPreferences(context); CommonPreferences.enable(prefs, mWordlistId); // Explicit enabling by the user : allow downloading on metered data connection. - UpdateHandler.markAsUsed(mContext, mClientId, mWordlistId, mVersion, mStatus, true); + UpdateHandler.markAsUsed(context, mClientId, mWordlistId, mVersion, mStatus, true); if (MetadataDbHelper.STATUS_AVAILABLE == mStatus) { setStatus(MetadataDbHelper.STATUS_DOWNLOADING); } else if (MetadataDbHelper.STATUS_DISABLED == mStatus @@ -203,11 +201,13 @@ public final class WordListPreference extends Preference { Log.e(TAG, "Unexpected state of the word list for enabling " + mStatus); } } + private void deleteDict() { - SharedPreferences prefs = CommonPreferences.getCommonPreferences(mContext); + final Context context = getContext(); + final SharedPreferences prefs = CommonPreferences.getCommonPreferences(context); CommonPreferences.disable(prefs, mWordlistId); setStatus(MetadataDbHelper.STATUS_DELETING); - UpdateHandler.markAsDeleting(mContext, mClientId, mWordlistId, mVersion, mStatus); + UpdateHandler.markAsDeleting(context, mClientId, mWordlistId, mVersion, mStatus); } @Override @@ -225,8 +225,8 @@ public final class WordListPreference extends Preference { status.setVisibility(showProgressBar ? View.INVISIBLE : View.VISIBLE); progressBar.setVisibility(showProgressBar ? View.VISIBLE : View.INVISIBLE); - final ButtonSwitcher buttonSwitcher = - (ButtonSwitcher)view.findViewById(R.id.wordlist_button_switcher); + final ButtonSwitcher buttonSwitcher = (ButtonSwitcher)view.findViewById( + R.id.wordlist_button_switcher); // We need to clear the state of the button switcher, because we reuse views; if we didn't // reset it would animate from whatever its old state was. buttonSwitcher.reset(mInterfaceState); @@ -244,63 +244,67 @@ public final class WordListPreference extends Preference { // The button is closed. buttonSwitcher.setStatusAndUpdateVisuals(ButtonSwitcher.STATUS_NO_BUTTON); } - buttonSwitcher.setInternalOnClickListener(mActionButtonClickHandler); - view.setOnClickListener(mPreferenceClickHandler); + buttonSwitcher.setInternalOnClickListener(new View.OnClickListener() { + @Override + public void onClick(final View v) { + onActionButtonClicked(); + } + }); + view.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(final View v) { + onWordListClicked(v); + } + }); } - private class OnWordListPreferenceClick implements View.OnClickListener { - @Override - public void onClick(final View v) { - // Note : v is the preference view - final ViewParent parent = v.getParent(); - // Just in case something changed in the framework, test for the concrete class - if (!(parent instanceof ListView)) return; - final ListView listView = (ListView)parent; - final int indexToOpen; - // Close all first, we'll open back any item that needs to be open. - final boolean wasOpen = mInterfaceState.isOpen(mWordlistId); - mInterfaceState.closeAll(); - if (wasOpen) { - // This button being shown. Take note that we don't want to open any button in the - // loop below. - indexToOpen = -1; + void onWordListClicked(final View v) { + // Note : v is the preference view + final ViewParent parent = v.getParent(); + // Just in case something changed in the framework, test for the concrete class + if (!(parent instanceof ListView)) return; + final ListView listView = (ListView)parent; + final int indexToOpen; + // Close all first, we'll open back any item that needs to be open. + final boolean wasOpen = mInterfaceState.isOpen(mWordlistId); + mInterfaceState.closeAll(); + if (wasOpen) { + // This button being shown. Take note that we don't want to open any button in the + // loop below. + indexToOpen = -1; + } else { + // This button was not being shown. Open it, and remember the index of this + // child as the one to open in the following loop. + mInterfaceState.setOpen(mWordlistId, mStatus); + indexToOpen = listView.indexOfChild(v); + } + final int lastDisplayedIndex = + listView.getLastVisiblePosition() - listView.getFirstVisiblePosition(); + // The "lastDisplayedIndex" is actually displayed, hence the <= + for (int i = 0; i <= lastDisplayedIndex; ++i) { + final ButtonSwitcher buttonSwitcher = (ButtonSwitcher)listView.getChildAt(i) + .findViewById(R.id.wordlist_button_switcher); + if (i == indexToOpen) { + buttonSwitcher.setStatusAndUpdateVisuals(getButtonSwitcherStatus(mStatus)); } else { - // This button was not being shown. Open it, and remember the index of this - // child as the one to open in the following loop. - mInterfaceState.setOpen(mWordlistId, mStatus); - indexToOpen = listView.indexOfChild(v); - } - final int lastDisplayedIndex = - listView.getLastVisiblePosition() - listView.getFirstVisiblePosition(); - // The "lastDisplayedIndex" is actually displayed, hence the <= - for (int i = 0; i <= lastDisplayedIndex; ++i) { - final ButtonSwitcher buttonSwitcher = (ButtonSwitcher)listView.getChildAt(i) - .findViewById(R.id.wordlist_button_switcher); - if (i == indexToOpen) { - buttonSwitcher.setStatusAndUpdateVisuals(getButtonSwitcherStatus(mStatus)); - } else { - buttonSwitcher.setStatusAndUpdateVisuals(ButtonSwitcher.STATUS_NO_BUTTON); - } + buttonSwitcher.setStatusAndUpdateVisuals(ButtonSwitcher.STATUS_NO_BUTTON); } } } - private class OnActionButtonClick implements View.OnClickListener { - @Override - public void onClick(final View v) { - switch (getActionIdFromStatusAndMenuEntry(mStatus)) { - case ACTION_ENABLE_DICT: - enableDict(); - break; - case ACTION_DISABLE_DICT: - disableDict(); - break; - case ACTION_DELETE_DICT: - deleteDict(); - break; - default: - Log.e(TAG, "Unknown menu item pressed"); - } + void onActionButtonClicked() { + switch (getActionIdFromStatusAndMenuEntry(mStatus)) { + case ACTION_ENABLE_DICT: + enableDict(); + break; + case ACTION_DISABLE_DICT: + disableDict(); + break; + case ACTION_DELETE_DICT: + deleteDict(); + break; + default: + Log.e(TAG, "Unknown menu item pressed"); } } } diff --git a/java/src/com/android/inputmethod/event/CombinerChain.java b/java/src/com/android/inputmethod/event/CombinerChain.java index 2d2731f21..5858faa09 100644 --- a/java/src/com/android/inputmethod/event/CombinerChain.java +++ b/java/src/com/android/inputmethod/event/CombinerChain.java @@ -19,7 +19,7 @@ package com.android.inputmethod.event; import android.text.SpannableStringBuilder; import android.text.TextUtils; -import com.android.inputmethod.latin.Constants; +import com.android.inputmethod.latin.common.Constants; import java.util.ArrayList; import java.util.HashMap; @@ -97,7 +97,8 @@ public class CombinerChain { * new event. However it may never be null. */ @Nonnull - public Event processEvent(final ArrayList<Event> previousEvents, final Event newEvent) { + public Event processEvent(final ArrayList<Event> previousEvents, + @Nonnull final Event newEvent) { final ArrayList<Event> modifiablePreviousEvents = new ArrayList<>(previousEvents); Event event = newEvent; for (final Combiner combiner : mCombiners) { diff --git a/java/src/com/android/inputmethod/event/DeadKeyCombiner.java b/java/src/com/android/inputmethod/event/DeadKeyCombiner.java index 88c70630d..1a28bb1d5 100644 --- a/java/src/com/android/inputmethod/event/DeadKeyCombiner.java +++ b/java/src/com/android/inputmethod/event/DeadKeyCombiner.java @@ -18,9 +18,8 @@ package com.android.inputmethod.event; import android.text.TextUtils; import android.util.SparseIntArray; -import android.view.KeyCharacterMap; -import com.android.inputmethod.latin.Constants; +import com.android.inputmethod.latin.common.Constants; import java.text.Normalizer; import java.util.ArrayList; @@ -70,8 +69,8 @@ public class DeadKeyCombiner implements Combiner { /** * Maps Unicode combining diacritical to display-form dead key. */ - private static final SparseIntArray sCombiningToAccent = new SparseIntArray(); - private static final SparseIntArray sAccentToCombining = new SparseIntArray(); + static final SparseIntArray sCombiningToAccent = new SparseIntArray(); + static final SparseIntArray sAccentToCombining = new SparseIntArray(); static { // U+0300: COMBINING GRAVE ACCENT addCombining('\u0300', ACCENT_GRAVE); @@ -217,21 +216,20 @@ public class DeadKeyCombiner implements Combiner { final StringBuilder mDeadSequence = new StringBuilder(); @Nonnull - private Event createEventChainFromSequence(final @Nonnull CharSequence text, - final Event originalEvent) { - if (text.length() <= 0) { + private static Event createEventChainFromSequence(final @Nonnull CharSequence text, + @Nonnull final Event originalEvent) { + int index = text.length(); + if (index <= 0) { return originalEvent; - } else { - Event lastEvent = null; - int codePoint = 0; - for (int i = text.length(); i > 0; i -= Character.charCount(codePoint)) { - codePoint = Character.codePointBefore(text, i); - final Event thisEvent = Event.createHardwareKeypressEvent(codePoint, - originalEvent.mKeyCode, lastEvent, false /* isKeyRepeat */); - lastEvent = thisEvent; - } - return lastEvent; } + Event lastEvent = null; + do { + final int codePoint = Character.codePointBefore(text, index); + lastEvent = Event.createHardwareKeypressEvent(codePoint, + originalEvent.mKeyCode, lastEvent, false /* isKeyRepeat */); + index -= Character.charCount(codePoint); + } while (index > 0); + return lastEvent; } @Override @@ -248,51 +246,49 @@ public class DeadKeyCombiner implements Combiner { // no dead keys at all in the current input, so this combiner has nothing to do and // simply returns the event as is. The majority of events will go through this path. return event; - } else { - if (Character.isWhitespace(event.mCodePoint) - || event.mCodePoint == mDeadSequence.codePointBefore(mDeadSequence.length())) { - // When whitespace or twice the same dead key, we should output the dead sequence - // as is. - final Event resultEvent = createEventChainFromSequence(mDeadSequence.toString(), - event); - mDeadSequence.setLength(0); - return resultEvent; - } else if (event.isFunctionalKeyEvent()) { - if (Constants.CODE_DELETE == event.mKeyCode) { - // Remove the last code point - final int trimIndex = mDeadSequence.length() - Character.charCount( - mDeadSequence.codePointBefore(mDeadSequence.length())); - mDeadSequence.setLength(trimIndex); - return Event.createConsumedEvent(event); - } else { - return event; - } - } else if (event.isDead()) { - mDeadSequence.appendCodePoint(event.mCodePoint); + } + if (Character.isWhitespace(event.mCodePoint) + || event.mCodePoint == mDeadSequence.codePointBefore(mDeadSequence.length())) { + // When whitespace or twice the same dead key, we should output the dead sequence as is. + final Event resultEvent = createEventChainFromSequence(mDeadSequence.toString(), + event); + mDeadSequence.setLength(0); + return resultEvent; + } + if (event.isFunctionalKeyEvent()) { + if (Constants.CODE_DELETE == event.mKeyCode) { + // Remove the last code point + final int trimIndex = mDeadSequence.length() - Character.charCount( + mDeadSequence.codePointBefore(mDeadSequence.length())); + mDeadSequence.setLength(trimIndex); return Event.createConsumedEvent(event); + } + return event; + } + if (event.isDead()) { + mDeadSequence.appendCodePoint(event.mCodePoint); + return Event.createConsumedEvent(event); + } + // Combine normally. + final StringBuilder sb = new StringBuilder(); + sb.appendCodePoint(event.mCodePoint); + int codePointIndex = 0; + while (codePointIndex < mDeadSequence.length()) { + final int deadCodePoint = mDeadSequence.codePointAt(codePointIndex); + final char replacementSpacingChar = + Data.getNonstandardCombination(deadCodePoint, event.mCodePoint); + if (Data.NOT_A_CHAR != replacementSpacingChar) { + sb.setCharAt(0, replacementSpacingChar); } else { - // Combine normally. - final StringBuilder sb = new StringBuilder(); - sb.appendCodePoint(event.mCodePoint); - int codePointIndex = 0; - while (codePointIndex < mDeadSequence.length()) { - final int deadCodePoint = mDeadSequence.codePointAt(codePointIndex); - final char replacementSpacingChar = - Data.getNonstandardCombination(deadCodePoint, event.mCodePoint); - if (Data.NOT_A_CHAR != replacementSpacingChar) { - sb.setCharAt(0, replacementSpacingChar); - } else { - final int combining = Data.sAccentToCombining.get(deadCodePoint); - sb.appendCodePoint(0 == combining ? deadCodePoint : combining); - } - codePointIndex += Character.isSupplementaryCodePoint(deadCodePoint) ? 2 : 1; - } - final String normalizedString = Normalizer.normalize(sb, Normalizer.Form.NFC); - final Event resultEvent = createEventChainFromSequence(normalizedString, event); - mDeadSequence.setLength(0); - return resultEvent; + final int combining = Data.sAccentToCombining.get(deadCodePoint); + sb.appendCodePoint(0 == combining ? deadCodePoint : combining); } + codePointIndex += Character.isSupplementaryCodePoint(deadCodePoint) ? 2 : 1; } + final String normalizedString = Normalizer.normalize(sb, Normalizer.Form.NFC); + final Event resultEvent = createEventChainFromSequence(normalizedString, event); + mDeadSequence.setLength(0); + return resultEvent; } @Override diff --git a/java/src/com/android/inputmethod/event/Event.java b/java/src/com/android/inputmethod/event/Event.java index ff6f88066..92bcda455 100644 --- a/java/src/com/android/inputmethod/event/Event.java +++ b/java/src/com/android/inputmethod/event/Event.java @@ -17,10 +17,12 @@ package com.android.inputmethod.event; import com.android.inputmethod.annotations.ExternallyReferenced; -import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.utils.StringUtils; +import javax.annotation.Nonnull; + /** * Class representing a generic input event as handled by Latin IME. * @@ -134,12 +136,14 @@ public class Event { } } + @Nonnull public static Event createSoftwareKeypressEvent(final int codePoint, final int keyCode, final int x, final int y, final boolean isKeyRepeat) { return new Event(EVENT_TYPE_INPUT_KEYPRESS, null /* text */, codePoint, keyCode, x, y, null /* suggestedWordInfo */, isKeyRepeat ? FLAG_REPEAT : FLAG_NONE, null); } + @Nonnull public static Event createHardwareKeypressEvent(final int codePoint, final int keyCode, final Event next, final boolean isKeyRepeat) { return new Event(EVENT_TYPE_INPUT_KEYPRESS, null /* text */, codePoint, keyCode, @@ -149,6 +153,7 @@ public class Event { // This creates an input event for a dead character. @see {@link #FLAG_DEAD} @ExternallyReferenced + @Nonnull public static Event createDeadEvent(final int codePoint, final int keyCode, final Event next) { // TODO: add an argument or something if we ever create a software layout with dead keys. return new Event(EVENT_TYPE_INPUT_KEYPRESS, null /* text */, codePoint, keyCode, @@ -163,6 +168,7 @@ public class Event { * @param codePoint the code point. * @return an event for this code point. */ + @Nonnull public static Event createEventForCodePointFromUnknownSource(final int codePoint) { // TODO: should we have a different type of event for this? After all, it's not a key press. return new Event(EVENT_TYPE_INPUT_KEYPRESS, null /* text */, codePoint, NOT_A_KEY_CODE, @@ -178,6 +184,7 @@ public class Event { * @param y the Y coordinate. * @return an event for this code point and coordinates. */ + @Nonnull public static Event createEventForCodePointFromAlreadyTypedText(final int codePoint, final int x, final int y) { // TODO: should we have a different type of event for this? After all, it's not a key press. @@ -189,6 +196,7 @@ public class Event { * Creates an input event representing the manual pick of a suggestion. * @return an event for this suggestion pick. */ + @Nonnull public static Event createSuggestionPickedEvent(final SuggestedWordInfo suggestedWordInfo) { return new Event(EVENT_TYPE_SUGGESTION_PICKED, suggestedWordInfo.mWord, NOT_A_CODE_POINT, NOT_A_KEY_CODE, @@ -204,6 +212,7 @@ public class Event { * @param keyCode the key code, or NOT_A_KEYCODE if not applicable. * @return an event for this text. */ + @Nonnull public static Event createSoftwareTextEvent(final CharSequence text, final int keyCode) { return new Event(EVENT_TYPE_SOFTWARE_GENERATED_STRING, text, NOT_A_CODE_POINT, keyCode, Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE, @@ -214,6 +223,7 @@ public class Event { * Creates an input event representing the manual pick of a punctuation suggestion. * @return an event for this suggestion pick. */ + @Nonnull public static Event createPunctuationSuggestionPickedEvent( final SuggestedWordInfo suggestedWordInfo) { final int primaryCode = suggestedWordInfo.mWord.charAt(0); @@ -228,6 +238,7 @@ public class Event { * @param source the event to copy the properties of. * @return an identical event marked as consumed. */ + @Nonnull public static Event createConsumedEvent(final Event source) { // A consumed event should not input any text at all, so we pass the empty string as text. return new Event(source.mEventType, source.mText, source.mCodePoint, source.mKeyCode, @@ -235,6 +246,7 @@ public class Event { source.mNextEvent); } + @Nonnull public static Event createNotHandledEvent() { return new Event(EVENT_TYPE_NOT_HANDLED, null /* text */, NOT_A_CODE_POINT, NOT_A_KEY_CODE, Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE, diff --git a/java/src/com/android/inputmethod/event/HardwareKeyboardEventDecoder.java b/java/src/com/android/inputmethod/event/HardwareKeyboardEventDecoder.java index c61f45efa..3a4097d7f 100644 --- a/java/src/com/android/inputmethod/event/HardwareKeyboardEventDecoder.java +++ b/java/src/com/android/inputmethod/event/HardwareKeyboardEventDecoder.java @@ -19,7 +19,7 @@ package com.android.inputmethod.event; import android.view.KeyCharacterMap; import android.view.KeyEvent; -import com.android.inputmethod.latin.Constants; +import com.android.inputmethod.latin.common.Constants; /** * A hardware event decoder for a hardware qwerty-ish keyboard. @@ -67,10 +67,9 @@ public class HardwareKeyboardEventDecoder implements HardwareEventDecoder { if (keyEvent.isShiftPressed()) { return Event.createHardwareKeypressEvent(Event.NOT_A_CODE_POINT, Constants.CODE_SHIFT_ENTER, null /* next */, isKeyRepeat); - } else { - return Event.createHardwareKeypressEvent(Constants.CODE_ENTER, keyCode, - null /* next */, isKeyRepeat); } + return Event.createHardwareKeypressEvent(Constants.CODE_ENTER, keyCode, + null /* next */, isKeyRepeat); } // If not Enter, then this is just a regular keypress event for a normal character // that can be committed right away, taking into account the current state. diff --git a/java/src/com/android/inputmethod/event/MyanmarReordering.java b/java/src/com/android/inputmethod/event/MyanmarReordering.java index dcd06c899..7bc1630f5 100644 --- a/java/src/com/android/inputmethod/event/MyanmarReordering.java +++ b/java/src/com/android/inputmethod/event/MyanmarReordering.java @@ -16,7 +16,7 @@ package com.android.inputmethod.event; -import com.android.inputmethod.latin.Constants; +import com.android.inputmethod.latin.common.Constants; import java.util.ArrayList; import java.util.Arrays; @@ -115,6 +115,7 @@ public class MyanmarReordering implements Combiner { * @param newEvent the new event to add to the stream. null if none. * @return the resulting software text event. Never null. */ + @Nonnull private Event clearAndGetResultingEvent(final Event newEvent) { final CharSequence combinedText; if (mCurrentEvents.size() > 0) { @@ -139,7 +140,8 @@ public class MyanmarReordering implements Combiner { if (null == lastEvent) { mCurrentEvents.add(newEvent); return Event.createConsumedEvent(newEvent); - } else if (isConsonantOrMedial(lastEvent.mCodePoint)) { + } + if (isConsonantOrMedial(lastEvent.mCodePoint)) { final Event resultingEvent = clearAndGetResultingEvent(null); mCurrentEvents.add(Event.createSoftwareKeypressEvent(ZERO_WIDTH_NON_JOINER, Event.NOT_A_KEY_CODE, @@ -147,15 +149,17 @@ public class MyanmarReordering implements Combiner { false /* isKeyRepeat */)); mCurrentEvents.add(newEvent); return resultingEvent; - } else { // VOWEL_E == lastCodePoint. But if that was anything else this is correct too. - return clearAndGetResultingEvent(newEvent); } - } if (isConsonant(codePoint)) { + // VOWEL_E == lastCodePoint. But if that was anything else this is correct too. + return clearAndGetResultingEvent(newEvent); + } + if (isConsonant(codePoint)) { final Event lastEvent = getLastEvent(); if (null == lastEvent) { mCurrentEvents.add(newEvent); return Event.createConsumedEvent(newEvent); - } else if (VOWEL_E == lastEvent.mCodePoint) { + } + if (VOWEL_E == lastEvent.mCodePoint) { final int eventSize = mCurrentEvents.size(); if (eventSize >= 2 && mCurrentEvents.get(eventSize - 2).mCodePoint == ZERO_WIDTH_NON_JOINER) { @@ -178,15 +182,17 @@ public class MyanmarReordering implements Combiner { mCurrentEvents.add(newEvent); mCurrentEvents.add(lastEvent); return Event.createConsumedEvent(newEvent); - } else { // lastCodePoint is a consonant/medial. But if it's something else it's fine - return clearAndGetResultingEvent(newEvent); } - } else if (isMedial(codePoint)) { + // lastCodePoint is a consonant/medial. But if it's something else it's fine + return clearAndGetResultingEvent(newEvent); + } + if (isMedial(codePoint)) { final Event lastEvent = getLastEvent(); if (null == lastEvent) { mCurrentEvents.add(newEvent); return Event.createConsumedEvent(newEvent); - } else if (VOWEL_E == lastEvent.mCodePoint) { + } + if (VOWEL_E == lastEvent.mCodePoint) { final int eventSize = mCurrentEvents.size(); // If there is already a consonant, then we are in the middle of a syllable, and we // need to reorder. @@ -205,37 +211,36 @@ public class MyanmarReordering implements Combiner { } // Otherwise, we just commit everything. return clearAndGetResultingEvent(null); - } else { // lastCodePoint is a consonant/medial. But if it's something else it's fine - return clearAndGetResultingEvent(newEvent); } - } else if (Constants.CODE_DELETE == newEvent.mKeyCode) { - final Event lastEvent = getLastEvent(); + // lastCodePoint is a consonant/medial. But if it's something else it's fine + return clearAndGetResultingEvent(newEvent); + } + final Event lastEvent = getLastEvent(); + if (Constants.CODE_DELETE == newEvent.mKeyCode && null != lastEvent) { final int eventSize = mCurrentEvents.size(); - if (null != lastEvent) { - if (VOWEL_E == lastEvent.mCodePoint) { - // We have a VOWEL_E at the end. There are four cases. - // - The vowel is the only code point in the buffer. Remove it. - // - The vowel is preceded by a ZWNJ. Remove both vowel E and ZWNJ. - // - The vowel is preceded by a consonant/medial, remove the consonant/medial. - // - In all other cases, it's strange, so just remove the last code point. - if (eventSize <= 1) { - mCurrentEvents.clear(); - } else { // eventSize >= 2 - final int previousCodePoint = mCurrentEvents.get(eventSize - 2).mCodePoint; - if (previousCodePoint == ZERO_WIDTH_NON_JOINER) { - mCurrentEvents.remove(eventSize - 1); - mCurrentEvents.remove(eventSize - 2); - } else if (isConsonantOrMedial(previousCodePoint)) { - mCurrentEvents.remove(eventSize - 2); - } else { - mCurrentEvents.remove(eventSize - 1); - } + if (VOWEL_E == lastEvent.mCodePoint) { + // We have a VOWEL_E at the end. There are four cases. + // - The vowel is the only code point in the buffer. Remove it. + // - The vowel is preceded by a ZWNJ. Remove both vowel E and ZWNJ. + // - The vowel is preceded by a consonant/medial, remove the consonant/medial. + // - In all other cases, it's strange, so just remove the last code point. + if (eventSize <= 1) { + mCurrentEvents.clear(); + } else { // eventSize >= 2 + final int previousCodePoint = mCurrentEvents.get(eventSize - 2).mCodePoint; + if (previousCodePoint == ZERO_WIDTH_NON_JOINER) { + mCurrentEvents.remove(eventSize - 1); + mCurrentEvents.remove(eventSize - 2); + } else if (isConsonantOrMedial(previousCodePoint)) { + mCurrentEvents.remove(eventSize - 2); + } else { + mCurrentEvents.remove(eventSize - 1); } - return Event.createConsumedEvent(newEvent); - } else if (eventSize > 0) { - mCurrentEvents.remove(eventSize - 1); - return Event.createConsumedEvent(newEvent); } + return Event.createConsumedEvent(newEvent); + } else if (eventSize > 0) { + mCurrentEvents.remove(eventSize - 1); + return Event.createConsumedEvent(newEvent); } } // This character is not part of the combining scheme, so we should reset everything. @@ -243,10 +248,9 @@ public class MyanmarReordering implements Combiner { // If we have events in flight, then add the new event and return the resulting event. mCurrentEvents.add(newEvent); return clearAndGetResultingEvent(null); - } else { - // If we don't have any events in flight, then just pass this one through. - return newEvent; } + // If we don't have any events in flight, then just pass this one through. + return newEvent; } @Override diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java index 45ce6a85f..04a0f1e13 100644 --- a/java/src/com/android/inputmethod/keyboard/Key.java +++ b/java/src/com/android/inputmethod/keyboard/Key.java @@ -17,10 +17,10 @@ package com.android.inputmethod.keyboard; import static com.android.inputmethod.keyboard.internal.KeyboardIconsSet.ICON_UNDEFINED; -import static com.android.inputmethod.latin.Constants.CODE_OUTPUT_TEXT; -import static com.android.inputmethod.latin.Constants.CODE_SHIFT; -import static com.android.inputmethod.latin.Constants.CODE_SWITCH_ALPHA_SYMBOL; -import static com.android.inputmethod.latin.Constants.CODE_UNSPECIFIED; +import static com.android.inputmethod.latin.common.Constants.CODE_OUTPUT_TEXT; +import static com.android.inputmethod.latin.common.Constants.CODE_SHIFT; +import static com.android.inputmethod.latin.common.Constants.CODE_SWITCH_ALPHA_SYMBOL; +import static com.android.inputmethod.latin.common.Constants.CODE_UNSPECIFIED; import android.content.res.TypedArray; import android.graphics.Rect; @@ -36,8 +36,8 @@ import com.android.inputmethod.keyboard.internal.KeyboardIconsSet; import com.android.inputmethod.keyboard.internal.KeyboardParams; import com.android.inputmethod.keyboard.internal.KeyboardRow; import com.android.inputmethod.keyboard.internal.MoreKeySpec; -import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.utils.StringUtils; import java.util.Arrays; diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java index d35c8fae1..3c90a04db 100644 --- a/java/src/com/android/inputmethod/keyboard/Keyboard.java +++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java @@ -21,7 +21,7 @@ import android.util.SparseArray; import com.android.inputmethod.keyboard.internal.KeyVisualAttributes; import com.android.inputmethod.keyboard.internal.KeyboardIconsSet; import com.android.inputmethod.keyboard.internal.KeyboardParams; -import com.android.inputmethod.latin.Constants; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.utils.CoordinateUtils; import java.util.ArrayList; diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java b/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java index c565866b7..ac66f7c6a 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java @@ -16,8 +16,8 @@ package com.android.inputmethod.keyboard; -import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.InputPointers; +import com.android.inputmethod.latin.common.Constants; public interface KeyboardActionListener { /** diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardId.java b/java/src/com/android/inputmethod/keyboard/KeyboardId.java index ab0d63306..d43bf37cb 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardId.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardId.java @@ -16,7 +16,7 @@ package com.android.inputmethod.keyboard; -import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET; +import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET; import android.text.InputType; import android.text.TextUtils; @@ -25,7 +25,6 @@ import android.view.inputmethod.EditorInfo; import com.android.inputmethod.compat.EditorInfoCompatUtils; import com.android.inputmethod.latin.RichInputMethodSubtype; import com.android.inputmethod.latin.utils.InputTypeUtils; -import com.android.inputmethod.latin.utils.SubtypeLocaleUtils; import java.util.Arrays; import java.util.Locale; diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java index 1c66c37d3..b674359e6 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java @@ -16,8 +16,8 @@ package com.android.inputmethod.keyboard; -import static com.android.inputmethod.latin.Constants.ImeOption.FORCE_ASCII; -import static com.android.inputmethod.latin.Constants.ImeOption.NO_SETTINGS_KEY; +import static com.android.inputmethod.latin.common.Constants.ImeOption.FORCE_ASCII; +import static com.android.inputmethod.latin.common.Constants.ImeOption.NO_SETTINGS_KEY; import android.content.Context; import android.content.res.Resources; @@ -40,7 +40,6 @@ import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.RichInputMethodSubtype; import com.android.inputmethod.latin.SubtypeSwitcher; import com.android.inputmethod.latin.define.DebugFlags; -import com.android.inputmethod.latin.utils.DebugLogUtils; import com.android.inputmethod.latin.utils.InputTypeUtils; import com.android.inputmethod.latin.utils.ScriptUtils; import com.android.inputmethod.latin.utils.SubtypeLocaleUtils; @@ -424,9 +423,8 @@ public final class KeyboardLayoutSet { final String tag = parser.getName(); if (TAG_KEYBOARD_SET.equals(tag)) { break; - } else { - throw new XmlParseUtils.IllegalEndTag(parser, tag, TAG_KEYBOARD_SET); } + throw new XmlParseUtils.IllegalEndTag(parser, tag, TAG_KEYBOARD_SET); } } } diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java index 93123d1ec..3bcce4f69 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java @@ -273,6 +273,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { } // Future method for requesting an updating to the shift state. + @Override public void requestUpdatingShiftState(final int currentAutoCapsState, final int currentRecapitalizeState) { mState.onUpdateShiftState(currentAutoCapsState, currentRecapitalizeState); diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardTheme.java b/java/src/com/android/inputmethod/keyboard/KeyboardTheme.java index 8a9688ac4..006d08696 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardTheme.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardTheme.java @@ -18,6 +18,7 @@ package com.android.inputmethod.keyboard; import android.content.Context; import android.content.SharedPreferences; +import android.os.Build; import android.os.Build.VERSION_CODES; import android.preference.PreferenceManager; import android.util.Log; @@ -54,7 +55,7 @@ public final class KeyboardTheme implements Comparable<KeyboardTheme> { VERSION_CODES.ICE_CREAM_SANDWICH), new KeyboardTheme(THEME_ID_LXX_LIGHT, "LXXLight", R.style.KeyboardTheme_LXX_Light, // Default theme for LXX. - BuildCompatUtils.VERSION_CODES_LXX), + Build.VERSION_CODES.LOLLIPOP), new KeyboardTheme(THEME_ID_LXX_DARK, "LXXDark", R.style.KeyboardTheme_LXX_Dark, // This has never been selected as default theme. VERSION_CODES.BASE), diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java index 98cd1da54..6feb1e7ad 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java @@ -35,8 +35,8 @@ import android.view.View; import com.android.inputmethod.keyboard.internal.KeyDrawParams; import com.android.inputmethod.keyboard.internal.KeyVisualAttributes; -import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.utils.TypefaceUtils; import java.util.HashSet; diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java index 06f9ced92..e66523be0 100644 --- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java @@ -52,10 +52,10 @@ import com.android.inputmethod.keyboard.internal.MoreKeySpec; import com.android.inputmethod.keyboard.internal.NonDistinctMultitouchHelper; import com.android.inputmethod.keyboard.internal.SlidingKeyInputDrawingPreview; import com.android.inputmethod.keyboard.internal.TimerHandler; -import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.RichInputMethodSubtype; import com.android.inputmethod.latin.SuggestedWords; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.settings.DebugSettings; import com.android.inputmethod.latin.utils.CoordinateUtils; import com.android.inputmethod.latin.utils.StringUtils; diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java index 841283b7f..01522536f 100644 --- a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java @@ -29,8 +29,8 @@ import android.view.ViewGroup; import com.android.inputmethod.accessibility.AccessibilityUtils; import com.android.inputmethod.accessibility.MoreKeysKeyboardAccessibilityDelegate; import com.android.inputmethod.keyboard.internal.KeyDrawParams; -import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.utils.CoordinateUtils; /** diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index 49288ade4..fe6270fb5 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -31,9 +31,9 @@ import com.android.inputmethod.keyboard.internal.GestureStrokeDrawingPoints; import com.android.inputmethod.keyboard.internal.GestureStrokeRecognitionParams; import com.android.inputmethod.keyboard.internal.PointerTrackerQueue; import com.android.inputmethod.keyboard.internal.TypingTimeRecorder; -import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.InputPointers; import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.define.DebugFlags; import com.android.inputmethod.latin.settings.Settings; import com.android.inputmethod.latin.utils.CoordinateUtils; diff --git a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java index 9c5abcd71..ab2323b06 100644 --- a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java +++ b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java @@ -17,11 +17,10 @@ package com.android.inputmethod.keyboard; import android.graphics.Rect; -import android.text.TextUtils; import android.util.Log; import com.android.inputmethod.keyboard.internal.TouchPositionCorrection; -import com.android.inputmethod.latin.Constants; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.utils.JniUtils; import java.util.ArrayList; diff --git a/java/src/com/android/inputmethod/keyboard/TextDecorator.java b/java/src/com/android/inputmethod/keyboard/TextDecorator.java index 2b7d2ce3c..892d36752 100644 --- a/java/src/com/android/inputmethod/keyboard/TextDecorator.java +++ b/java/src/com/android/inputmethod/keyboard/TextDecorator.java @@ -74,7 +74,7 @@ public class TextDecorator { void onClickComposingTextToAddToDictionary(final String word); } - public TextDecorator(final Listener listener) { + public TextDecorator(@Nullable final Listener listener) { mListener = (listener != null) ? listener : EMPTY_LISTENER; } @@ -83,7 +83,7 @@ public class TextDecorator { * delegated to the associated UI operator. * @param uiOperator the UI operator to be associated. */ - public void setUiOperator(final TextDecoratorUiOperator uiOperator) { + public void setUiOperator(@Nonnull final TextDecoratorUiOperator uiOperator) { mUiOperator.disposeUi(); mUiOperator = uiOperator; mUiOperator.setOnClickListener(getOnClickHandler()); @@ -181,7 +181,7 @@ public class TextDecorator { layoutMain(); } - private void layoutMain() { + void layoutMain() { final CursorAnchorInfoCompatWrapper info = mCursorAnchorInfoWrapper; if (info == null) { @@ -289,7 +289,7 @@ public class TextDecorator { mHasRtlCharsInLastComposingText); } - private void onClickIndicator() { + void onClickIndicator() { if (mMode != MODE_SHOWING_INDICATOR) { return; } @@ -347,12 +347,14 @@ public class TextDecorator { } } + @Nonnull private final static Listener EMPTY_LISTENER = new Listener() { @Override public void onClickComposingTextToAddToDictionary(final String word) { } }; + @Nonnull private final static TextDecoratorUiOperator EMPTY_UI_OPERATOR = new TextDecoratorUiOperator() { @Override public void disposeUi() { diff --git a/java/src/com/android/inputmethod/keyboard/emoji/EmojiCategory.java b/java/src/com/android/inputmethod/keyboard/emoji/EmojiCategory.java index 0f9dc855b..a9711aed2 100644 --- a/java/src/com/android/inputmethod/keyboard/emoji/EmojiCategory.java +++ b/java/src/com/android/inputmethod/keyboard/emoji/EmojiCategory.java @@ -29,7 +29,6 @@ import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.KeyboardId; import com.android.inputmethod.keyboard.KeyboardLayoutSet; -import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.settings.Settings; @@ -147,7 +146,7 @@ final class EmojiCategory { mShownCategories.add(properties); } - public String getCategoryName(final int categoryId, final int categoryPageId) { + public static String getCategoryName(final int categoryId, final int categoryPageId) { return sCategoryName[categoryId] + "-" + categoryPageId; } @@ -271,7 +270,7 @@ final class EmojiCategory { } private static final Long getCategoryKeyboardMapKey(final int categoryId, final int id) { - return (((long) categoryId) << Constants.MAX_INT_BIT_COUNT) | id; + return (((long) categoryId) << Integer.SIZE) | id; } public DynamicGridKeyboard getKeyboard(final int categoryId, final int id) { diff --git a/java/src/com/android/inputmethod/keyboard/emoji/EmojiPageKeyboardView.java b/java/src/com/android/inputmethod/keyboard/emoji/EmojiPageKeyboardView.java index 925ec6bfb..54d3e3b88 100644 --- a/java/src/com/android/inputmethod/keyboard/emoji/EmojiPageKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/emoji/EmojiPageKeyboardView.java @@ -138,6 +138,21 @@ final class EmojiPageKeyboardView extends KeyboardView implements return mKeyDetector.detectHitKey(x, y); } + void callListenerOnReleaseKey(final Key releasedKey, final boolean withKeyRegistering) { + releasedKey.onReleased(); + invalidateKey(releasedKey); + if (withKeyRegistering) { + mListener.onReleaseKey(releasedKey); + } + } + + void callListenerOnPressKey(final Key pressedKey) { + mPendingKeyDown = null; + pressedKey.onReleased(); + invalidateKey(pressedKey); + mListener.onPressKey(pressedKey); + } + public void releaseCurrentKey(final boolean withKeyRegistering) { mHandler.removeCallbacks(mPendingKeyDown); mPendingKeyDown = null; @@ -145,11 +160,7 @@ final class EmojiPageKeyboardView extends KeyboardView implements if (currentKey == null) { return; } - currentKey.onReleased(); - invalidateKey(currentKey); - if (withKeyRegistering) { - mListener.onReleaseKey(currentKey); - } + callListenerOnReleaseKey(currentKey, withKeyRegistering); mCurrentKey = null; } @@ -165,10 +176,7 @@ final class EmojiPageKeyboardView extends KeyboardView implements mPendingKeyDown = new Runnable() { @Override public void run() { - mPendingKeyDown = null; - key.onPressed(); - invalidateKey(key); - mListener.onPressKey(key); + callListenerOnPressKey(key); } }; mHandler.postDelayed(mPendingKeyDown, KEY_PRESS_DELAY_TIME); @@ -195,15 +203,11 @@ final class EmojiPageKeyboardView extends KeyboardView implements mHandler.postDelayed(new Runnable() { @Override public void run() { - key.onReleased(); - invalidateKey(key); - mListener.onReleaseKey(key); + callListenerOnReleaseKey(key, true /* withRegistering */); } }, KEY_RELEASE_DELAY_TIME); } else { - key.onReleased(); - invalidateKey(key); - mListener.onReleaseKey(key); + callListenerOnReleaseKey(key, true /* withRegistering */); } return true; } diff --git a/java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesView.java b/java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesView.java index e37cd2369..06184f8d2 100644 --- a/java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesView.java +++ b/java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesView.java @@ -16,7 +16,7 @@ package com.android.inputmethod.keyboard.emoji; -import static com.android.inputmethod.latin.Constants.NOT_A_COORDINATE; +import static com.android.inputmethod.latin.common.Constants.NOT_A_COORDINATE; import android.content.Context; import android.content.res.Resources; @@ -47,9 +47,9 @@ import com.android.inputmethod.keyboard.internal.KeyDrawParams; import com.android.inputmethod.keyboard.internal.KeyVisualAttributes; import com.android.inputmethod.keyboard.internal.KeyboardIconsSet; import com.android.inputmethod.latin.AudioAndHapticFeedbackManager; -import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.SubtypeSwitcher; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.utils.ResourceUtils; import java.util.concurrent.TimeUnit; @@ -149,7 +149,7 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange } private void addTab(final TabHost host, final int categoryId) { - final String tabId = mEmojiCategory.getCategoryName(categoryId, 0 /* categoryPageId */); + final String tabId = EmojiCategory.getCategoryName(categoryId, 0 /* categoryPageId */); final TabHost.TabSpec tspec = host.newTabSpec(tabId); tspec.setContent(R.id.emoji_keyboard_dummy); final ImageView iconView = (ImageView)LayoutInflater.from(getContext()).inflate( diff --git a/java/src/com/android/inputmethod/keyboard/internal/AbstractDrawingPreview.java b/java/src/com/android/inputmethod/keyboard/internal/AbstractDrawingPreview.java index a194f3dfd..755a99a2c 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/AbstractDrawingPreview.java +++ b/java/src/com/android/inputmethod/keyboard/internal/AbstractDrawingPreview.java @@ -19,6 +19,7 @@ package com.android.inputmethod.keyboard.internal; import android.graphics.Canvas; import android.view.View; +import com.android.inputmethod.keyboard.MainKeyboardView; import com.android.inputmethod.keyboard.PointerTracker; /** @@ -51,11 +52,11 @@ public abstract class AbstractDrawingPreview { } /** - * Set {@link MainKeyboardView} geometry and position in the {@link SoftInputWindow}. + * Set {@link MainKeyboardView} geometry and position in the window of input method. * The class that is overriding this method must call this super implementation. * * @param originCoords the top-left coordinates of the {@link MainKeyboardView} in - * {@link SoftInputWindow} coordinate-system. This is unused but has a point in an + * the input method window coordinate-system. This is unused but has a point in an * extended class, such as {@link GestureTrailsDrawingPreview}. * @param width the width of {@link MainKeyboardView}. * @param height the height of {@link MainKeyboardView}. diff --git a/java/src/com/android/inputmethod/keyboard/internal/BatchInputArbiter.java b/java/src/com/android/inputmethod/keyboard/internal/BatchInputArbiter.java index cd9875955..efb365e42 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/BatchInputArbiter.java +++ b/java/src/com/android/inputmethod/keyboard/internal/BatchInputArbiter.java @@ -16,8 +16,8 @@ package com.android.inputmethod.keyboard.internal; -import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.InputPointers; +import com.android.inputmethod.latin.common.Constants; /** * This class arbitrates batch input. diff --git a/java/src/com/android/inputmethod/keyboard/internal/BogusMoveEventDetector.java b/java/src/com/android/inputmethod/keyboard/internal/BogusMoveEventDetector.java index 6420edd7a..4b355a4ab 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/BogusMoveEventDetector.java +++ b/java/src/com/android/inputmethod/keyboard/internal/BogusMoveEventDetector.java @@ -20,8 +20,8 @@ import android.content.res.Resources; import android.util.DisplayMetrics; import android.util.Log; -import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.define.DebugFlags; // This hack is applied to certain classes of tablets. diff --git a/java/src/com/android/inputmethod/keyboard/internal/CodesArrayParser.java b/java/src/com/android/inputmethod/keyboard/internal/CodesArrayParser.java index dce7fc57e..5797b7efd 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/CodesArrayParser.java +++ b/java/src/com/android/inputmethod/keyboard/internal/CodesArrayParser.java @@ -16,7 +16,7 @@ package com.android.inputmethod.keyboard.internal; -import com.android.inputmethod.latin.Constants; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.utils.StringUtils; import android.text.TextUtils; diff --git a/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeRecognitionPoints.java b/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeRecognitionPoints.java index e49e538aa..99ec18f4d 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeRecognitionPoints.java +++ b/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeRecognitionPoints.java @@ -18,8 +18,8 @@ package com.android.inputmethod.keyboard.internal; import android.util.Log; -import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.InputPointers; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.utils.ResizableIntArray; /** diff --git a/java/src/com/android/inputmethod/keyboard/internal/GestureTrailDrawingPoints.java b/java/src/com/android/inputmethod/keyboard/internal/GestureTrailDrawingPoints.java index bf4c4da10..67683e247 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/GestureTrailDrawingPoints.java +++ b/java/src/com/android/inputmethod/keyboard/internal/GestureTrailDrawingPoints.java @@ -23,7 +23,7 @@ import android.graphics.Path; import android.graphics.Rect; import android.os.SystemClock; -import com.android.inputmethod.latin.Constants; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.utils.ResizableIntArray; /** diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewChoreographer.java b/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewChoreographer.java index 5005b7d7d..ddb193ead 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewChoreographer.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewChoreographer.java @@ -148,7 +148,7 @@ public final class KeyPreviewChoreographer { keyPreviewView.setPivotY(previewHeight); } - private void showKeyPreview(final Key key, final KeyPreviewView keyPreviewView, + void showKeyPreview(final Key key, final KeyPreviewView keyPreviewView, final boolean withAnimation) { if (!withAnimation) { keyPreviewView.setVisibility(View.VISIBLE); @@ -166,25 +166,25 @@ public final class KeyPreviewChoreographer { } public Animator createShowUpAnimator(final Key key, final KeyPreviewView keyPreviewView) { - final Animator animator = mParams.createShowUpAnimator(keyPreviewView); - animator.addListener(new AnimatorListenerAdapter() { + final Animator showUpAnimator = mParams.createShowUpAnimator(keyPreviewView); + showUpAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(final Animator animator) { showKeyPreview(key, keyPreviewView, false /* withAnimation */); } }); - return animator; + return showUpAnimator; } private Animator createDismissAnimator(final Key key, final KeyPreviewView keyPreviewView) { - final Animator animator = mParams.createDismissAnimator(keyPreviewView); - animator.addListener(new AnimatorListenerAdapter() { + final Animator dismissAnimator = mParams.createDismissAnimator(keyPreviewView); + dismissAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(final Animator animator) { dismissKeyPreview(key, false /* withAnimation */); } }); - return animator; + return dismissAnimator; } private static class KeyPreviewAnimators extends AnimatorListenerAdapter { diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java index 48ba8e051..d33e53a61 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java @@ -16,10 +16,10 @@ package com.android.inputmethod.keyboard.internal; -import static com.android.inputmethod.latin.Constants.CODE_OUTPUT_TEXT; -import static com.android.inputmethod.latin.Constants.CODE_UNSPECIFIED; +import static com.android.inputmethod.latin.common.Constants.CODE_OUTPUT_TEXT; +import static com.android.inputmethod.latin.common.Constants.CODE_UNSPECIFIED; -import com.android.inputmethod.latin.Constants; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.utils.StringUtils; /** diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java index f4e010c4d..6c75fb6c1 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java @@ -32,8 +32,8 @@ import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.KeyboardId; import com.android.inputmethod.keyboard.KeyboardTheme; -import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.utils.ResourceUtils; import com.android.inputmethod.latin.utils.StringUtils; import com.android.inputmethod.latin.utils.SubtypeLocaleUtils; @@ -47,6 +47,8 @@ import java.io.IOException; import java.util.Arrays; import java.util.Locale; +import javax.annotation.Nonnull; + /** * Keyboard Building helper. * @@ -733,18 +735,18 @@ public class KeyboardBuilder<KP extends KeyboardParams> { } } - private boolean matchLocaleCodes(TypedArray caseAttr, final Locale[] locales) { + private static boolean matchLocaleCodes(TypedArray caseAttr, final Locale[] locales) { // TODO: adujst this for multilingual input return matchString(caseAttr, R.styleable.Keyboard_Case_localeCode, locales[0].toString()); } - private boolean matchLanguageCodes(TypedArray caseAttr, Locale[] locales) { + private static boolean matchLanguageCodes(TypedArray caseAttr, Locale[] locales) { // TODO: adujst this for multilingual input return matchString(caseAttr, R.styleable.Keyboard_Case_languageCode, locales[0].getLanguage()); } - private boolean matchCountryCodes(TypedArray caseAttr, Locale[] locales) { + private static boolean matchCountryCodes(TypedArray caseAttr, Locale[] locales) { // TODO: adujst this for multilingual input return matchString(caseAttr, R.styleable.Keyboard_Case_countryCode, locales[0].getCountry()); @@ -859,7 +861,7 @@ public class KeyboardBuilder<KP extends KeyboardParams> { mTopEdge = false; } - private void endKey(final Key key) { + private void endKey(@Nonnull final Key key) { mParams.onAddKey(key); if (mLeftEdge) { key.markAsLeftEdge(mParams); diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java index 62b69dcc9..05b4c7473 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java @@ -16,7 +16,7 @@ package com.android.inputmethod.keyboard.internal; -import com.android.inputmethod.latin.Constants; +import com.android.inputmethod.latin.common.Constants; import java.util.HashMap; diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java index 71ce768a9..fb5e97757 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java @@ -20,7 +20,7 @@ import android.util.SparseIntArray; import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.keyboard.KeyboardId; -import com.android.inputmethod.latin.Constants; +import com.android.inputmethod.latin.common.Constants; import java.util.ArrayList; import java.util.Comparator; diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java index 5f4d55bdb..cc28e7ac8 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java @@ -20,7 +20,7 @@ import android.text.TextUtils; import android.util.Log; import com.android.inputmethod.event.Event; -import com.android.inputmethod.latin.Constants; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.utils.RecapitalizeStatus; /** diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java index f9297ac27..0aaf6b401 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java @@ -21,7 +21,7 @@ import android.content.res.Resources; import android.text.TextUtils; import com.android.inputmethod.annotations.UsedForTesting; -import com.android.inputmethod.latin.Constants; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.utils.RunInLocale; import com.android.inputmethod.latin.utils.SubtypeLocaleUtils; diff --git a/java/src/com/android/inputmethod/keyboard/internal/MatrixUtils.java b/java/src/com/android/inputmethod/keyboard/internal/MatrixUtils.java index c1f374964..d927cc362 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/MatrixUtils.java +++ b/java/src/com/android/inputmethod/keyboard/internal/MatrixUtils.java @@ -28,7 +28,8 @@ import java.util.Arrays; */ @UsedForTesting public class MatrixUtils { - private static final String TAG = MatrixUtils.class.getSimpleName(); + static final String TAG = MatrixUtils.class.getSimpleName(); + public static class MatrixOperationFailedException extends Exception { private static final long serialVersionUID = 4384485606788583829L; diff --git a/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpec.java b/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpec.java index 0cd031e5f..4392dbcbd 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpec.java +++ b/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpec.java @@ -21,7 +21,7 @@ import android.util.SparseIntArray; import com.android.inputmethod.compat.CharacterCompat; import com.android.inputmethod.keyboard.Key; -import com.android.inputmethod.latin.Constants; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.define.DebugFlags; import com.android.inputmethod.latin.utils.CollectionUtils; import com.android.inputmethod.latin.utils.StringUtils; @@ -31,6 +31,8 @@ import java.util.Arrays; import java.util.HashSet; import java.util.Locale; +import javax.annotation.Nonnull; + /** * The more key specification object. The more keys are an array of {@link MoreKeySpec}. * @@ -70,6 +72,7 @@ public final class MoreKeySpec { mIconId = KeySpecParser.getIconId(moreKeySpec); } + @Nonnull public Key buildKey(final int x, final int y, final int labelFlags, final KeyboardParams params) { return new Key(mLabel, mIconId, mCode, mOutputText, null /* hintLabel */, labelFlags, @@ -108,9 +111,8 @@ public final class MoreKeySpec { : Constants.printableCode(mCode)); if (StringUtils.codePointCount(label) == 1 && label.codePointAt(0) == mCode) { return output; - } else { - return label + "|" + output; } + return label + "|" + output; } public static class LettersOnBaseLayout { diff --git a/java/src/com/android/inputmethod/keyboard/internal/TimerHandler.java b/java/src/com/android/inputmethod/keyboard/internal/TimerHandler.java index 80b299bf5..076abbf4d 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/TimerHandler.java +++ b/java/src/com/android/inputmethod/keyboard/internal/TimerHandler.java @@ -24,7 +24,7 @@ import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.keyboard.PointerTracker; import com.android.inputmethod.keyboard.PointerTracker.TimerProxy; import com.android.inputmethod.keyboard.internal.TimerHandler.Callbacks; -import com.android.inputmethod.latin.Constants; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.utils.LeakGuardHandlerWrapper; import javax.annotation.Nonnull; diff --git a/java/src/com/android/inputmethod/keyboard/internal/TouchPositionCorrection.java b/java/src/com/android/inputmethod/keyboard/internal/TouchPositionCorrection.java index fef97cc11..d8f0114e1 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/TouchPositionCorrection.java +++ b/java/src/com/android/inputmethod/keyboard/internal/TouchPositionCorrection.java @@ -80,6 +80,7 @@ public final class TouchPositionCorrection { return mRadii.length; } + @SuppressWarnings({ "static-method", "unused" }) public float getX(final int row) { return 0.0f; // Touch position correction data for X coordinate is obsolete. diff --git a/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java b/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java index eb8b34ccd..60d257362 100644 --- a/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java +++ b/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java @@ -22,6 +22,7 @@ import android.os.Vibrator; import android.view.HapticFeedbackConstants; import android.view.View; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.settings.SettingsValues; /** diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java index 2fece7c85..76459f817 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java @@ -23,6 +23,7 @@ import android.util.SparseArray; import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.keyboard.ProximityInfo; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.makedict.DictionaryHeader; import com.android.inputmethod.latin.makedict.FormatSpec; import com.android.inputmethod.latin.makedict.FormatSpec.DictionaryOptions; @@ -32,8 +33,8 @@ import com.android.inputmethod.latin.settings.SettingsValuesForSuggestion; import com.android.inputmethod.latin.utils.BinaryDictionaryUtils; import com.android.inputmethod.latin.utils.FileUtils; import com.android.inputmethod.latin.utils.JniUtils; -import com.android.inputmethod.latin.utils.LanguageModelParam; import com.android.inputmethod.latin.utils.StringUtils; +import com.android.inputmethod.latin.utils.WordInputEventForPersonalization; import java.io.File; import java.util.ArrayList; @@ -69,7 +70,7 @@ public final class BinaryDictionary extends Dictionary { // Format to get unigram flags from native side via getWordPropertyNative(). private static final int FORMAT_WORD_PROPERTY_OUTPUT_FLAG_COUNT = 5; private static final int FORMAT_WORD_PROPERTY_IS_NOT_A_WORD_INDEX = 0; - private static final int FORMAT_WORD_PROPERTY_IS_BLACKLISTED_INDEX = 1; + private static final int FORMAT_WORD_PROPERTY_IS_POSSIBLY_OFFENSIVE_INDEX = 1; private static final int FORMAT_WORD_PROPERTY_HAS_NGRAMS_INDEX = 2; private static final int FORMAT_WORD_PROPERTY_HAS_SHORTCUTS_INDEX = 3; private static final int FORMAT_WORD_PROPERTY_IS_BEGINNING_OF_SENTENCE_INDEX = 4; @@ -195,7 +196,7 @@ public final class BinaryDictionary extends Dictionary { float[] inOutWeightOfLangModelVsSpatialModel); private static native boolean addUnigramEntryNative(long dict, int[] word, int probability, int[] shortcutTarget, int shortcutProbability, boolean isBeginningOfSentence, - boolean isNotAWord, boolean isBlacklisted, int timestamp); + boolean isNotAWord, boolean isPossiblyOffensive, int timestamp); private static native boolean removeUnigramEntryNative(long dict, int[] word); private static native boolean addNgramEntryNative(long dict, int[][] prevWordCodePointArrays, boolean[] isBeginningOfSentenceArray, @@ -205,8 +206,8 @@ public final class BinaryDictionary extends Dictionary { private static native boolean updateEntriesForWordWithNgramContextNative(long dict, int[][] prevWordCodePointArrays, boolean[] isBeginningOfSentenceArray, int[] word, boolean isValidWord, int count, int timestamp); - private static native int addMultipleDictionaryEntriesNative(long dict, - LanguageModelParam[] languageModelParams, int startIndex); + private static native int updateEntriesForInputEventsNative(long dict, + WordInputEventForPersonalization[] inputEvents, int startIndex); private static native String getPropertyNative(long dict, String query); private static native boolean isCorruptedNative(long dict); private static native boolean migrateNative(long dict, String dictFilePath, @@ -351,15 +352,19 @@ public final class BinaryDictionary extends Dictionary { @Override public int getFrequency(final String word) { - if (TextUtils.isEmpty(word)) return NOT_A_PROBABILITY; - int[] codePoints = StringUtils.toCodePointArray(word); + if (TextUtils.isEmpty(word)) { + return NOT_A_PROBABILITY; + } + final int[] codePoints = StringUtils.toCodePointArray(word); return getProbabilityNative(mNativeDict, codePoints); } @Override public int getMaxFrequencyOfExactMatches(final String word) { - if (TextUtils.isEmpty(word)) return NOT_A_PROBABILITY; - int[] codePoints = StringUtils.toCodePointArray(word); + if (TextUtils.isEmpty(word)) { + return NOT_A_PROBABILITY; + } + final int[] codePoints = StringUtils.toCodePointArray(word); return getMaxProbabilityOfExactMatchesNative(mNativeDict, codePoints); } @@ -402,7 +407,7 @@ public final class BinaryDictionary extends Dictionary { outNgramProbabilityInfo, outShortcutTargets, outShortcutProbabilities); return new WordProperty(codePoints, outFlags[FORMAT_WORD_PROPERTY_IS_NOT_A_WORD_INDEX], - outFlags[FORMAT_WORD_PROPERTY_IS_BLACKLISTED_INDEX], + outFlags[FORMAT_WORD_PROPERTY_IS_POSSIBLY_OFFENSIVE_INDEX], outFlags[FORMAT_WORD_PROPERTY_HAS_NGRAMS_INDEX], outFlags[FORMAT_WORD_PROPERTY_HAS_SHORTCUTS_INDEX], outFlags[FORMAT_WORD_PROPERTY_IS_BEGINNING_OF_SENTENCE_INDEX], outProbabilityInfo, @@ -439,7 +444,7 @@ public final class BinaryDictionary extends Dictionary { public boolean addUnigramEntry(final String word, final int probability, final String shortcutTarget, final int shortcutProbability, final boolean isBeginningOfSentence, final boolean isNotAWord, - final boolean isBlacklisted, final int timestamp) { + final boolean isPossiblyOffensive, final int timestamp) { if (word == null || (word.isEmpty() && !isBeginningOfSentence)) { return false; } @@ -447,7 +452,8 @@ public final class BinaryDictionary extends Dictionary { final int[] shortcutTargetCodePoints = (shortcutTarget != null) ? StringUtils.toCodePointArray(shortcutTarget) : null; if (!addUnigramEntryNative(mNativeDict, codePoints, probability, shortcutTargetCodePoints, - shortcutProbability, isBeginningOfSentence, isNotAWord, isBlacklisted, timestamp)) { + shortcutProbability, isBeginningOfSentence, isNotAWord, isPossiblyOffensive, + timestamp)) { return false; } mHasUpdated = true; @@ -521,17 +527,19 @@ public final class BinaryDictionary extends Dictionary { } @UsedForTesting - public void addMultipleDictionaryEntries(final LanguageModelParam[] languageModelParams) { - if (!isValidDictionary()) return; - int processedParamCount = 0; - while (processedParamCount < languageModelParams.length) { + public void updateEntriesForInputEvents(final WordInputEventForPersonalization[] inputEvents) { + if (!isValidDictionary()) { + return; + } + int processedEventCount = 0; + while (processedEventCount < inputEvents.length) { if (needsToRunGC(true /* mindsBlockByGC */)) { flushWithGC(); } - processedParamCount = addMultipleDictionaryEntriesNative(mNativeDict, - languageModelParams, processedParamCount); + processedEventCount = updateEntriesForInputEventsNative(mNativeDict, inputEvents, + processedEventCount); mHasUpdated = true; - if (processedParamCount <= 0) { + if (processedEventCount <= 0) { return; } } @@ -549,7 +557,9 @@ public final class BinaryDictionary extends Dictionary { // Flush to dict file if the dictionary has been updated. public boolean flush() { - if (!isValidDictionary()) return false; + if (!isValidDictionary()) { + return false; + } if (mHasUpdated) { if (!flushNative(mNativeDict, mDictFilePath)) { return false; @@ -569,7 +579,9 @@ public final class BinaryDictionary extends Dictionary { // Run GC and flush to dict file. public boolean flushWithGC() { - if (!isValidDictionary()) return false; + if (!isValidDictionary()) { + return false; + } if (!flushWithGCNative(mNativeDict, mDictFilePath)) { return false; } @@ -584,7 +596,9 @@ public final class BinaryDictionary extends Dictionary { * @return whether GC is needed to run or not. */ public boolean needsToRunGC(final boolean mindsBlockByGC) { - if (!isValidDictionary()) return false; + if (!isValidDictionary()) { + return false; + } return needsToRunGCNative(mNativeDict, mindsBlockByGC); } @@ -629,7 +643,9 @@ public final class BinaryDictionary extends Dictionary { @UsedForTesting public String getPropertyForGettingStats(final String query) { - if (!isValidDictionary()) return ""; + if (!isValidDictionary()) { + return ""; + } return getPropertyNative(mNativeDict, query); } diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java index 867c18686..1570bdae0 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java @@ -121,12 +121,11 @@ final public class BinaryDictionaryGetter { // reason some dictionaries have been installed BUT the dictionary pack can't be // found anymore it's safer to actually supply installed dictionaries. return true; - } else { - // The default is true here for the same reasons as above. We got the dictionary - // pack but if we don't have any settings for it it means the user has never been - // to the settings yet. So by default, the main dictionaries should be on. - return mDictPreferences.getBoolean(dictId, true); } + // The default is true here for the same reasons as above. We got the dictionary + // pack but if we don't have any settings for it it means the user has never been + // to the settings yet. So by default, the main dictionaries should be on. + return mDictPreferences.getBoolean(dictId, true); } } @@ -224,7 +223,7 @@ final public class BinaryDictionaryGetter { // ## HACK ## we prevent usage of a dictionary before version 18. The reason for this is, since // those do not include whitelist entries, the new code with an old version of the dictionary // would lose whitelist functionality. - private static boolean hackCanUseDictionaryFile(final Locale locale, final File file) { + private static boolean hackCanUseDictionaryFile(final File file) { try { // Read the version of the file final DictionaryHeader header = BinaryDictionaryUtils.getHeader(file); @@ -276,7 +275,7 @@ final public class BinaryDictionaryGetter { // cachedWordLists may not be null, see doc for getCachedDictionaryList for (final File f : cachedWordLists) { final String wordListId = DictionaryInfoUtils.getWordListIdFromFileName(f.getName()); - final boolean canUse = f.canRead() && hackCanUseDictionaryFile(locale, f); + final boolean canUse = f.canRead() && hackCanUseDictionaryFile(f); if (canUse && DictionaryInfoUtils.isMainWordListId(wordListId)) { foundMainDict = true; } diff --git a/java/src/com/android/inputmethod/latin/Constants.java b/java/src/com/android/inputmethod/latin/Constants.java deleted file mode 100644 index fc7f95c7b..000000000 --- a/java/src/com/android/inputmethod/latin/Constants.java +++ /dev/null @@ -1,320 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.inputmethod.latin; - -public final class Constants { - public static final class Color { - /** - * The alpha value for fully opaque. - */ - public final static int ALPHA_OPAQUE = 255; - } - - public static final class ImeOption { - /** - * The private IME option used to indicate that no microphone should be shown for a given - * text field. For instance, this is specified by the search dialog when the dialog is - * already showing a voice search button. - * - * @deprecated Use {@link ImeOption#NO_MICROPHONE} with package name prefixed. - */ - @SuppressWarnings("dep-ann") - public static final String NO_MICROPHONE_COMPAT = "nm"; - - /** - * The private IME option used to indicate that no microphone should be shown for a given - * text field. For instance, this is specified by the search dialog when the dialog is - * already showing a voice search button. - */ - public static final String NO_MICROPHONE = "noMicrophoneKey"; - - /** - * The private IME option used to indicate that no settings key should be shown for a given - * text field. - */ - public static final String NO_SETTINGS_KEY = "noSettingsKey"; - - /** - * The private IME option used to indicate that the given text field needs ASCII code points - * input. - * - * @deprecated Use EditorInfo#IME_FLAG_FORCE_ASCII. - */ - @SuppressWarnings("dep-ann") - public static final String FORCE_ASCII = "forceAscii"; - - /** - * The private IME option used to suppress the floating gesture preview for a given text - * field. This overrides the corresponding keyboard settings preference. - * {@link com.android.inputmethod.latin.settings.SettingsValues#mGestureFloatingPreviewTextEnabled} - */ - public static final String NO_FLOATING_GESTURE_PREVIEW = "noGestureFloatingPreview"; - - private ImeOption() { - // This utility class is not publicly instantiable. - } - } - - public static final class Subtype { - /** - * The subtype mode used to indicate that the subtype is a keyboard. - */ - public static final String KEYBOARD_MODE = "keyboard"; - - public static final class ExtraValue { - /** - * The subtype extra value used to indicate that this subtype is capable of - * entering ASCII characters. - */ - public static final String ASCII_CAPABLE = "AsciiCapable"; - - /** - * The subtype extra value used to indicate that this subtype is enabled - * when the default subtype is not marked as ascii capable. - */ - public static final String ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE = - "EnabledWhenDefaultIsNotAsciiCapable"; - - /** - * The subtype extra value used to indicate that this subtype is capable of - * entering emoji characters. - */ - public static final String EMOJI_CAPABLE = "EmojiCapable"; - - /** - * The subtype extra value used to indicate that this subtype requires a network - * connection to work. - */ - public static final String REQ_NETWORK_CONNECTIVITY = "requireNetworkConnectivity"; - - /** - * The subtype extra value used to indicate that the display name of this subtype - * contains a "%s" for printf-like replacement and it should be replaced by - * this extra value. - * This extra value is supported on JellyBean and later. - */ - public static final String UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME = - "UntranslatableReplacementStringInSubtypeName"; - - /** - * The subtype extra value used to indicate this subtype keyboard layout set name. - * This extra value is private to LatinIME. - */ - public static final String KEYBOARD_LAYOUT_SET = "KeyboardLayoutSet"; - - /** - * The subtype extra value used to indicate that this subtype is an additional subtype - * that the user defined. This extra value is private to LatinIME. - */ - public static final String IS_ADDITIONAL_SUBTYPE = "isAdditionalSubtype"; - - /** - * The subtype extra value used to specify the combining rules. - */ - public static final String COMBINING_RULES = "CombiningRules"; - - private ExtraValue() { - // This utility class is not publicly instantiable. - } - } - - private Subtype() { - // This utility class is not publicly instantiable. - } - } - - public static final class TextUtils { - /** - * Capitalization mode for {@link android.text.TextUtils#getCapsMode}: don't capitalize - * characters. This value may be used with - * {@link android.text.TextUtils#CAP_MODE_CHARACTERS}, - * {@link android.text.TextUtils#CAP_MODE_WORDS}, and - * {@link android.text.TextUtils#CAP_MODE_SENTENCES}. - */ - // TODO: Straighten this out. It's bizarre to have to use android.text.TextUtils.CAP_MODE_* - // except for OFF that is in Constants.TextUtils. - public static final int CAP_MODE_OFF = 0; - - private TextUtils() { - // This utility class is not publicly instantiable. - } - } - - public static final int NOT_A_CODE = -1; - public static final int NOT_A_CURSOR_POSITION = -1; - // TODO: replace the following constants with state in InputTransaction? - public static final int NOT_A_COORDINATE = -1; - public static final int SUGGESTION_STRIP_COORDINATE = -2; - public static final int SPELL_CHECKER_COORDINATE = -3; - public static final int EXTERNAL_KEYBOARD_COORDINATE = -4; - - // A hint on how many characters to cache from the TextView. A good value of this is given by - // how many characters we need to be able to almost always find the caps mode. - public static final int EDITOR_CONTENTS_CACHE_SIZE = 1024; - // How many characters we accept for the recapitalization functionality. This needs to be - // large enough for all reasonable purposes, but avoid purposeful attacks. 100k sounds about - // right for this. - public static final int MAX_CHARACTERS_FOR_RECAPITALIZATION = 1024 * 100; - - // Must be equal to MAX_WORD_LENGTH in native/jni/src/defines.h - public static final int DICTIONARY_MAX_WORD_LENGTH = 48; - - // (MAX_PREV_WORD_COUNT_FOR_N_GRAM + 1)-gram is supported in Java side. Needs to modify - // MAX_PREV_WORD_COUNT_FOR_N_GRAM in native/jni/src/defines.h for suggestions. - public static final int MAX_PREV_WORD_COUNT_FOR_N_GRAM = 2; - - // Key events coming any faster than this are long-presses. - public static final int LONG_PRESS_MILLISECONDS = 200; - // TODO: Set this value appropriately. - public static final int GET_SUGGESTED_WORDS_TIMEOUT = 200; - // How many continuous deletes at which to start deleting at a higher speed. - public static final int DELETE_ACCELERATE_AT = 20; - - public static final String WORD_SEPARATOR = " "; - - public static boolean isValidCoordinate(final int coordinate) { - // Detect {@link NOT_A_COORDINATE}, {@link SUGGESTION_STRIP_COORDINATE}, - // and {@link SPELL_CHECKER_COORDINATE}. - return coordinate >= 0; - } - - /** - * Custom request code used in - * {@link com.android.inputmethod.keyboard.KeyboardActionListener#onCustomRequest(int)}. - */ - // The code to show input method picker. - public static final int CUSTOM_CODE_SHOW_INPUT_METHOD_PICKER = 1; - - /** - * Some common keys code. Must be positive. - */ - public static final int CODE_ENTER = '\n'; - public static final int CODE_TAB = '\t'; - public static final int CODE_SPACE = ' '; - public static final int CODE_PERIOD = '.'; - public static final int CODE_COMMA = ','; - public static final int CODE_DASH = '-'; - public static final int CODE_SINGLE_QUOTE = '\''; - public static final int CODE_DOUBLE_QUOTE = '"'; - public static final int CODE_QUESTION_MARK = '?'; - public static final int CODE_EXCLAMATION_MARK = '!'; - public static final int CODE_SLASH = '/'; - public static final int CODE_BACKSLASH = '\\'; - public static final int CODE_VERTICAL_BAR = '|'; - public static final int CODE_COMMERCIAL_AT = '@'; - public static final int CODE_PLUS = '+'; - public static final int CODE_PERCENT = '%'; - public static final int CODE_CLOSING_PARENTHESIS = ')'; - public static final int CODE_CLOSING_SQUARE_BRACKET = ']'; - public static final int CODE_CLOSING_CURLY_BRACKET = '}'; - public static final int CODE_CLOSING_ANGLE_BRACKET = '>'; - public static final int CODE_INVERTED_QUESTION_MARK = 0xBF; // ¿ - public static final int CODE_INVERTED_EXCLAMATION_MARK = 0xA1; // ¡ - public static final int CODE_GRAVE_ACCENT = '`'; - public static final int CODE_CIRCUMFLEX_ACCENT = '^'; - public static final int CODE_TILDE = '~'; - - public static final String REGEXP_PERIOD = "\\."; - public static final String STRING_SPACE = " "; - - /** - * Special keys code. Must be negative. - * These should be aligned with {@link KeyboardCodesSet#ID_TO_NAME}, - * {@link KeyboardCodesSet#DEFAULT}, and {@link KeyboardCodesSet#RTL}. - */ - public static final int CODE_SHIFT = -1; - public static final int CODE_CAPSLOCK = -2; - public static final int CODE_SWITCH_ALPHA_SYMBOL = -3; - public static final int CODE_OUTPUT_TEXT = -4; - public static final int CODE_DELETE = -5; - public static final int CODE_SETTINGS = -6; - public static final int CODE_SHORTCUT = -7; - public static final int CODE_ACTION_NEXT = -8; - public static final int CODE_ACTION_PREVIOUS = -9; - public static final int CODE_LANGUAGE_SWITCH = -10; - public static final int CODE_EMOJI = -11; - public static final int CODE_SHIFT_ENTER = -12; - public static final int CODE_SYMBOL_SHIFT = -13; - public static final int CODE_ALPHA_FROM_EMOJI = -14; - // Code value representing the code is not specified. - public static final int CODE_UNSPECIFIED = -15; - - public static boolean isLetterCode(final int code) { - return code >= CODE_SPACE; - } - - public static String printableCode(final int code) { - switch (code) { - case CODE_SHIFT: return "shift"; - case CODE_CAPSLOCK: return "capslock"; - case CODE_SWITCH_ALPHA_SYMBOL: return "symbol"; - case CODE_OUTPUT_TEXT: return "text"; - case CODE_DELETE: return "delete"; - case CODE_SETTINGS: return "settings"; - case CODE_SHORTCUT: return "shortcut"; - case CODE_ACTION_NEXT: return "actionNext"; - case CODE_ACTION_PREVIOUS: return "actionPrevious"; - case CODE_LANGUAGE_SWITCH: return "languageSwitch"; - case CODE_EMOJI: return "emoji"; - case CODE_SHIFT_ENTER: return "shiftEnter"; - case CODE_ALPHA_FROM_EMOJI: return "alpha"; - case CODE_UNSPECIFIED: return "unspec"; - case CODE_TAB: return "tab"; - case CODE_ENTER: return "enter"; - case CODE_SPACE: return "space"; - default: - if (code < CODE_SPACE) return String.format("\\u%02X", code); - if (code < 0x100) return String.format("%c", code); - if (code < 0x10000) return String.format("\\u%04X", code); - return String.format("\\U%05X", code); - } - } - - public static String printableCodes(final int[] codes) { - final StringBuilder sb = new StringBuilder(); - boolean addDelimiter = false; - for (final int code : codes) { - if (code == NOT_A_CODE) break; - if (addDelimiter) sb.append(", "); - sb.append(printableCode(code)); - addDelimiter = true; - } - return "[" + sb + "]"; - } - - public static final int MAX_INT_BIT_COUNT = 32; - - /** - * Screen metrics (a.k.a. Device form factor) constants of - * {@link R.integer#config_screen_metrics}. - */ - public static final int SCREEN_METRICS_SMALL_PHONE = 0; - public static final int SCREEN_METRICS_LARGE_PHONE = 1; - public static final int SCREEN_METRICS_LARGE_TABLET = 2; - public static final int SCREEN_METRICS_SMALL_TABLET = 3; - - /** - * Default capacity of gesture points container. - * This constant is used by {@link BatchInputArbiter} and etc. to preallocate regions that - * contain gesture event points. - */ - public static final int DEFAULT_GESTURE_POINTS_CAPACITY = 128; - - private Constants() { - // This utility class is not publicly instantiable. - } -} diff --git a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java index 78c6cbd24..08e1983d4 100644 --- a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java @@ -26,10 +26,10 @@ import android.os.SystemClock; import android.provider.BaseColumns; import android.provider.ContactsContract; import android.provider.ContactsContract.Contacts; -import android.text.TextUtils; import android.util.Log; -import com.android.inputmethod.annotations.UsedForTesting; +import com.android.inputmethod.annotations.ExternallyReferenced; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.personalization.AccountUtils; import com.android.inputmethod.latin.utils.ExecutorUtils; import com.android.inputmethod.latin.utils.StringUtils; @@ -83,7 +83,8 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary { reloadDictionaryIfRequired(); } - @UsedForTesting + // Note: This method is called by {@link DictionaryFacilitator} using Java reflection. + @ExternallyReferenced public static ContactsBinaryDictionary getDictionary(final Context context, final Locale locale, final File dictFile, final String dictNamePrefix) { return new ContactsBinaryDictionary(context, locale, dictFile, dictNamePrefix + NAME); @@ -137,7 +138,7 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary { } runGCIfRequiredLocked(true /* mindsBlockByGC */); addUnigramLocked(word, FREQUENCY_FOR_CONTACTS, null /* shortcut */, - 0 /* shortcutFreq */, false /* isNotAWord */, false /* isBlacklisted */, + 0 /* shortcutFreq */, false /* isNotAWord */, false /* isPossiblyOffensive */, BinaryDictionary.NOT_A_VALID_TIMESTAMP); } } @@ -164,7 +165,7 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary { } } - private boolean useFirstLastBigramsForLocale(final Locale locale) { + private static boolean useFirstLastBigramsForLocale(final Locale locale) { // TODO: Add firstname/lastname bigram rules for other languages. if (locale != null && locale.getLanguage().equals(Locale.ENGLISH.getLanguage())) { return true; @@ -238,7 +239,8 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary { runGCIfRequiredLocked(true /* mindsBlockByGC */); addUnigramLocked(word, FREQUENCY_FOR_CONTACTS, null /* shortcut */, 0 /* shortcutFreq */, false /* isNotAWord */, - false /* isBlacklisted */, BinaryDictionary.NOT_A_VALID_TIMESTAMP); + false /* isPossiblyOffensive */, + BinaryDictionary.NOT_A_VALID_TIMESTAMP); if (!ngramContext.isValid() && mUseFirstLastBigrams) { runGCIfRequiredLocked(true /* mindsBlockByGC */); addNgramEntryLocked(ngramContext, word, FREQUENCY_FOR_CONTACTS_BIGRAM, @@ -268,7 +270,7 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary { return end; } - private boolean haveContentsChanged() { + boolean haveContentsChanged() { final long startTime = SystemClock.uptimeMillis(); final int contactCount = getContactCount(); if (contactCount > MAX_CONTACT_COUNT) { diff --git a/java/src/com/android/inputmethod/latin/DicTraverseSession.java b/java/src/com/android/inputmethod/latin/DicTraverseSession.java index 2751c1250..95390aa9f 100644 --- a/java/src/com/android/inputmethod/latin/DicTraverseSession.java +++ b/java/src/com/android/inputmethod/latin/DicTraverseSession.java @@ -16,6 +16,7 @@ package com.android.inputmethod.latin; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.settings.NativeSuggestOptions; import com.android.inputmethod.latin.utils.JniUtils; @@ -70,7 +71,7 @@ public final class DicTraverseSession { mNativeDicTraverseSession, dictionary, previousWord, previousWordLength); } - private final long createNativeDicTraverseSession(String locale, long dictSize) { + private static long createNativeDicTraverseSession(String locale, long dictSize) { return setDicTraverseSessionNative(locale, dictSize); } diff --git a/java/src/com/android/inputmethod/latin/Dictionary.java b/java/src/com/android/inputmethod/latin/Dictionary.java index e66847b56..28a62b283 100644 --- a/java/src/com/android/inputmethod/latin/Dictionary.java +++ b/java/src/com/android/inputmethod/latin/Dictionary.java @@ -72,9 +72,13 @@ public abstract class Dictionary { * Set out of the dictionary types listed above that are based on data specific to the user, * e.g., the user's contacts. */ - private static final HashSet<String> sUserSpecificDictionaryTypes = - new HashSet(Arrays.asList(new String[] { TYPE_USER_TYPED, TYPE_USER, TYPE_CONTACTS, - TYPE_USER_HISTORY, TYPE_PERSONALIZATION, TYPE_CONTEXTUAL })); + private static final HashSet<String> sUserSpecificDictionaryTypes = new HashSet<>(Arrays.asList( + TYPE_USER_TYPED, + TYPE_USER, + TYPE_CONTACTS, + TYPE_USER_HISTORY, + TYPE_PERSONALIZATION, + TYPE_CONTEXTUAL)); public Dictionary(final String dictType, final Locale locale) { mDictType = dictType; @@ -116,10 +120,18 @@ public abstract class Dictionary { */ abstract public boolean isInDictionary(final String word); + /** + * Get the frequency of the word. + * @param word the word to get the frequency of. + */ public int getFrequency(final String word) { return NOT_A_PROBABILITY; } + /** + * Get the maximum frequency of the word. + * @param word the word to get the maximum frequency of. + */ public int getMaxFrequencyOfExactMatches(final String word) { return NOT_A_PROBABILITY; } diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java index 08035dfd6..4a22cde7b 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java @@ -24,9 +24,10 @@ import android.view.inputmethod.InputMethodSubtype; import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.keyboard.ProximityInfo; -import com.android.inputmethod.latin.ExpandableBinaryDictionary.AddMultipleDictionaryEntriesCallback; +import com.android.inputmethod.latin.ExpandableBinaryDictionary.UpdateEntriesForInputEventsCallback; import com.android.inputmethod.latin.NgramContext.WordInfo; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.personalization.ContextualDictionary; import com.android.inputmethod.latin.personalization.PersonalizationDataChunk; import com.android.inputmethod.latin.personalization.PersonalizationDictionary; @@ -53,6 +54,9 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + // TODO: Consolidate dictionaries in native code. public class DictionaryFacilitator { public static final String TAG = DictionaryFacilitator.class.getSimpleName(); @@ -172,9 +176,8 @@ public class DictionaryFacilitator { public Dictionary getDict(final String dictType) { if (Dictionary.TYPE_MAIN.equals(dictType)) { return mMainDict; - } else { - return getSubDict(dictType); } + return getSubDict(dictType); } public ExpandableBinaryDictionary getSubDict(final String dictType) { @@ -184,9 +187,8 @@ public class DictionaryFacilitator { public boolean hasDict(final String dictType) { if (Dictionary.TYPE_MAIN.equals(dictType)) { return mMainDict != null; - } else { - return mSubDictMap.containsKey(dictType); } + return mSubDictMap.containsKey(dictType); } public void closeDict(final String dictType) { @@ -276,6 +278,7 @@ public class DictionaryFacilitator { mMostProbableDictionaryGroup = newMostProbableDictionaryGroup; } + @Nullable private static ExpandableBinaryDictionary getSubDict(final String dictType, final Context context, final Locale locale, final File dictFile, final String dictNamePrefix) { @@ -305,7 +308,8 @@ public class DictionaryFacilitator { usePersonalizedDicts, forceReloadMainDictionary, listener, "" /* dictNamePrefix */); } - private DictionaryGroup findDictionaryGroupWithLocale(final DictionaryGroup[] dictionaryGroups, + @Nullable + static DictionaryGroup findDictionaryGroupWithLocale(final DictionaryGroup[] dictionaryGroups, final Locale locale) { for (int i = 0; i < dictionaryGroups.length; ++i) { if (locale.equals(dictionaryGroups[i].mLocale)) { @@ -319,7 +323,7 @@ public class DictionaryFacilitator { final Locale[] newLocales, final boolean useContactsDict, final boolean usePersonalizedDicts, final boolean forceReloadMainDictionary, - final DictionaryInitializationListener listener, + @Nullable final DictionaryInitializationListener listener, final String dictNamePrefix) { final HashMap<Locale, ArrayList<String>> existingDictsToCleanup = new HashMap<>(); // TODO: Make subDictTypesToUse configurable by resource or a static final list. @@ -422,34 +426,41 @@ public class DictionaryFacilitator { ExecutorUtils.getExecutor("InitializeBinaryDictionary").execute(new Runnable() { @Override public void run() { - for (final Locale locale : locales) { - final DictionaryGroup dictionaryGroup = - findDictionaryGroupWithLocale(mDictionaryGroups, locale); - if (null == dictionaryGroup) { - // This should never happen, but better safe than crashy - Log.w(TAG, "Expected a dictionary group for " + locale + " but none found"); - continue; - } - final Dictionary mainDict = - DictionaryFactory.createMainDictionaryFromManager(context, locale); - synchronized (mLock) { - if (locale.equals(dictionaryGroup.mLocale)) { - dictionaryGroup.setMainDict(mainDict); - } else { - // Dictionary facilitator has been reset for another locale. - mainDict.close(); - } - } - } - if (listener != null) { - listener.onUpdateMainDictionaryAvailability( - hasAtLeastOneInitializedMainDictionary()); - } - latchForWaitingLoadingMainDictionary.countDown(); + doReloadUninitializedMainDictionaries( + context, locales, listener, latchForWaitingLoadingMainDictionary); } }); } + void doReloadUninitializedMainDictionaries(final Context context, final Locale[] locales, + final DictionaryInitializationListener listener, + final CountDownLatch latchForWaitingLoadingMainDictionary) { + for (final Locale locale : locales) { + final DictionaryGroup dictionaryGroup = + findDictionaryGroupWithLocale(mDictionaryGroups, locale); + if (null == dictionaryGroup) { + // This should never happen, but better safe than crashy + Log.w(TAG, "Expected a dictionary group for " + locale + " but none found"); + continue; + } + final Dictionary mainDict = + DictionaryFactory.createMainDictionaryFromManager(context, locale); + synchronized (mLock) { + if (locale.equals(dictionaryGroup.mLocale)) { + dictionaryGroup.setMainDict(mainDict); + } else { + // Dictionary facilitator has been reset for another locale. + mainDict.close(); + } + } + } + if (listener != null) { + listener.onUpdateMainDictionaryAvailability( + hasAtLeastOneInitializedMainDictionary()); + } + latchForWaitingLoadingMainDictionary.countDown(); + } + @UsedForTesting public void resetDictionariesForTesting(final Context context, final Locale[] locales, final ArrayList<String> dictionaryTypes, final HashMap<String, File> dictionaryFiles, @@ -588,7 +599,7 @@ public class DictionaryFacilitator { } public void addToUserHistory(final String suggestion, final boolean wasAutoCapitalized, - final NgramContext ngramContext, final int timeStampInSeconds, + @Nonnull final NgramContext ngramContext, final int timeStampInSeconds, final boolean blockPotentiallyOffensive) { final DictionaryGroup dictionaryGroup = getDictionaryGroupForMostProbableLanguage(); final String[] words = suggestion.split(Constants.WORD_SEPARATOR); @@ -786,8 +797,8 @@ public class DictionaryFacilitator { public void addEntriesToPersonalizationDictionary( final PersonalizationDataChunk personalizationDataChunk, final SpacingAndPunctuations spacingAndPunctuations, - final AddMultipleDictionaryEntriesCallback callback) { - mPersonalizationHelper.addEntriesToPersonalizationDictionariesToUpdate( + final UpdateEntriesForInputEventsCallback callback) { + mPersonalizationHelper.updateEntriesOfPersonalizationDictionaries( getMostProbableLocale(), personalizationDataChunk, spacingAndPunctuations, callback); } @@ -809,7 +820,7 @@ public class DictionaryFacilitator { contextualDict.addUnigramEntryWithCheckingDistracter( subPhraseStr, probability, null /* shortcutTarget */, Dictionary.NOT_A_PROBABILITY /* shortcutFreq */, - false /* isNotAWord */, false /* isBlacklisted */, + false /* isNotAWord */, false /* isPossiblyOffensive */, BinaryDictionary.NOT_A_VALID_TIMESTAMP, DistracterFilter.EMPTY_DISTRACTER_FILTER); contextualDict.addNgramEntry(ngramContext, subPhraseStr, @@ -819,7 +830,7 @@ public class DictionaryFacilitator { contextualDict.addUnigramEntryWithCheckingDistracter( phrase[i], probability, null /* shortcutTarget */, Dictionary.NOT_A_PROBABILITY /* shortcutFreq */, - false /* isNotAWord */, false /* isBlacklisted */, + false /* isNotAWord */, false /* isPossiblyOffensive */, BinaryDictionary.NOT_A_VALID_TIMESTAMP, DistracterFilter.EMPTY_DISTRACTER_FILTER); contextualDict.addNgramEntry(ngramContext, phrase[i], diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorLruCache.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorLruCache.java index 1b33d9129..b578159eb 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorLruCache.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorLruCache.java @@ -31,7 +31,7 @@ import android.util.LruCache; * This class automatically creates and releases facilitator instances using LRU policy. */ public class DictionaryFacilitatorLruCache { - private static final String TAG = DictionaryFacilitatorLruCache.class.getSimpleName(); + static final String TAG = DictionaryFacilitatorLruCache.class.getSimpleName(); private static final int WAIT_FOR_LOADING_MAIN_DICT_IN_MILLISECONDS = 1000; private static final int MAX_RETRY_COUNT_FOR_WAITING_FOR_LOADING_DICT = 5; @@ -81,7 +81,8 @@ public class DictionaryFacilitatorLruCache { mDictionaryNamePrefix = dictionaryNamePrefix; } - private void waitForLoadingMainDictionary(final DictionaryFacilitator dictionaryFacilitator) { + private static void waitForLoadingMainDictionary( + final DictionaryFacilitator dictionaryFacilitator) { for (int i = 0; i < MAX_RETRY_COUNT_FOR_WAITING_FOR_LOADING_DICT; i++) { try { dictionaryFacilitator.waitForLoadingMainDictionaries( diff --git a/java/src/com/android/inputmethod/latin/EmojiAltPhysicalKeyDetector.java b/java/src/com/android/inputmethod/latin/EmojiAltPhysicalKeyDetector.java new file mode 100644 index 000000000..8116a4983 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/EmojiAltPhysicalKeyDetector.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2014, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.inputmethod.latin; + +import android.view.KeyEvent; + +import com.android.inputmethod.keyboard.KeyboardSwitcher; +import com.android.inputmethod.latin.settings.Settings; + +/** + * A class for detecting Emoji-Alt physical key. + */ +final class EmojiAltPhysicalKeyDetector { + // True if the Alt key has been used as a modifier. In this case the Alt key up isn't + // recognized as an emoji key. + private boolean mAltHasBeenUsedAsAModifier; + + /** + * Record a down key event. + * @param keyEvent a down key event. + */ + public void onKeyDown(final KeyEvent keyEvent) { + if (isAltKey(keyEvent)) { + mAltHasBeenUsedAsAModifier = false; + } + if (containsAltModifier(keyEvent)) { + mAltHasBeenUsedAsAModifier = true; + } + } + + /** + * Determine whether an up key event is a special key up or not. + * @param keyEvent an up key event. + */ + public void onKeyUp(final KeyEvent keyEvent) { + if (keyEvent.isCanceled()) { + // This key up event was a part of key combinations and should be ignored. + return; + } + if (!isAltKey(keyEvent)) { + mAltHasBeenUsedAsAModifier |= containsAltModifier(keyEvent); + return; + } + if (containsAltModifier(keyEvent)) { + mAltHasBeenUsedAsAModifier = true; + return; + } + if (!Settings.getInstance().getCurrent().mEnableEmojiAltPhysicalKey) { + return; + } + if (!mAltHasBeenUsedAsAModifier) { + onEmojiAltKeyDetected(); + } + } + + private static void onEmojiAltKeyDetected() { + KeyboardSwitcher.getInstance().onToggleEmojiKeyboard(); + } + + private static boolean isAltKey(final KeyEvent keyEvent) { + final int keyCode = keyEvent.getKeyCode(); + return keyCode == KeyEvent.KEYCODE_ALT_LEFT || keyCode == KeyEvent.KEYCODE_ALT_RIGHT; + } + + private static boolean containsAltModifier(final KeyEvent keyEvent) { + final int metaState = keyEvent.getMetaState(); + // TODO: Support multiple keyboards. Take device id into account. + switch (keyEvent.getKeyCode()) { + case KeyEvent.KEYCODE_ALT_LEFT: + // Return true if Left-Alt is pressed with Right-Alt pressed. + return (metaState & KeyEvent.META_ALT_RIGHT_ON) != 0; + case KeyEvent.KEYCODE_ALT_RIGHT: + // Return true if Right-Alt is pressed with Left-Alt pressed. + return (metaState & KeyEvent.META_ALT_LEFT_ON) != 0; + default: + return (metaState & (KeyEvent.META_ALT_LEFT_ON | KeyEvent.META_ALT_RIGHT_ON)) != 0; + } + } +} diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java index d58373ff6..702d1536a 100644 --- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java @@ -21,18 +21,19 @@ import android.util.Log; import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.keyboard.ProximityInfo; +import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.makedict.DictionaryHeader; import com.android.inputmethod.latin.makedict.FormatSpec; import com.android.inputmethod.latin.makedict.UnsupportedFormatException; import com.android.inputmethod.latin.makedict.WordProperty; -import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import com.android.inputmethod.latin.settings.SettingsValuesForSuggestion; import com.android.inputmethod.latin.utils.AsyncResultHolder; import com.android.inputmethod.latin.utils.CombinedFormatUtils; import com.android.inputmethod.latin.utils.DistracterFilter; import com.android.inputmethod.latin.utils.ExecutorUtils; import com.android.inputmethod.latin.utils.FileUtils; -import com.android.inputmethod.latin.utils.LanguageModelParam; +import com.android.inputmethod.latin.utils.WordInputEventForPersonalization; import java.io.File; import java.util.ArrayList; @@ -47,11 +48,16 @@ import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantReadWriteLock; import javax.annotation.Nonnull; +import javax.annotation.Nullable; /** * Abstract base class for an expandable dictionary that can be created and updated dynamically * during runtime. When updated it automatically generates a new binary dictionary to handle future * queries in native code. This binary dictionary is written to internal storage. + * + * A class that extends this abstract class must have a static factory method named + * getDictionary(Context context, Locale locale, File dictFile, String dictNamePrefix) + * @see DictionaryFacilitator#getSubDict(String,Context,Locale,File,String) */ abstract public class ExpandableBinaryDictionary extends Dictionary { private static final boolean DEBUG = false; @@ -107,11 +113,11 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { */ protected abstract void loadInitialContentsLocked(); - private boolean matchesExpectedBinaryDictFormatVersionForThisType(final int formatVersion) { + static boolean matchesExpectedBinaryDictFormatVersionForThisType(final int formatVersion) { return formatVersion == FormatSpec.VERSION4; } - private boolean needsToMigrateDictionary(final int formatVersion) { + private static boolean needsToMigrateDictionary(final int formatVersion) { // When we bump up the dictionary format version, the old version should be added to here // for supporting migration. Note that native code has to support reading such formats. return formatVersion == FormatSpec.VERSION4_ONLY_FOR_TESTING; @@ -159,7 +165,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { asyncExecuteTaskWithLock(mLock.writeLock(), mDictName /* executorName */, task); } - private void asyncExecuteTaskWithLock(final Lock lock, final String executorName, + private static void asyncExecuteTaskWithLock(final Lock lock, final String executorName, final Runnable task) { asyncPreCheckAndExecuteTaskWithLock(lock, null /* preCheckTask */, executorName, task); } @@ -172,8 +178,9 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { } // Execute task with lock when the result of preCheckTask is true or preCheckTask is null. - private void asyncPreCheckAndExecuteTaskWithLock(final Lock lock, + private static void asyncPreCheckAndExecuteTaskWithLock(final Lock lock, final Callable<Boolean> preCheckTask, final String executorName, final Runnable task) { + final String tag = TAG; ExecutorUtils.getExecutor(executorName).execute(new Runnable() { @Override public void run() { @@ -183,7 +190,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { return; } } catch (final Exception e) { - Log.e(TAG, "The pre check task throws an exception.", e); + Log.e(tag, "The pre check task throws an exception.", e); return; } } @@ -197,6 +204,18 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { }); } + @Nullable + BinaryDictionary getBinaryDictionary() { + return mBinaryDictionary; + } + + void closeBinaryDictionary() { + if (mBinaryDictionary != null) { + mBinaryDictionary.close(); + mBinaryDictionary = null; + } + } + /** * Closes and cleans up the binary dictionary. */ @@ -205,10 +224,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { asyncExecuteTaskWithWriteLock(new Runnable() { @Override public void run() { - if (mBinaryDictionary != null) { - mBinaryDictionary.close(); - mBinaryDictionary = null; - } + closeBinaryDictionary(); } }); } @@ -234,14 +250,11 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { }); } - private void removeBinaryDictionaryLocked() { - if (mBinaryDictionary != null) { - mBinaryDictionary.close(); - } + void removeBinaryDictionaryLocked() { + closeBinaryDictionary(); if (mDictFile.exists() && !FileUtils.deleteRecursively(mDictFile)) { Log.e(TAG, "Can't remove a file: " + mDictFile.getName()); } - mBinaryDictionary = null; } private void openBinaryDictionaryLocked() { @@ -250,7 +263,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { true /* useFullEditDistance */, mLocale, mDictType, true /* isUpdatable */); } - private void createOnMemoryBinaryDictionaryLocked() { + void createOnMemoryBinaryDictionaryLocked() { mBinaryDictionary = new BinaryDictionary( mDictFile.getAbsolutePath(), true /* useFullEditDistance */, mLocale, mDictType, DICTIONARY_FORMAT_VERSION, getHeaderAttributeMap()); @@ -273,7 +286,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { asyncExecuteTaskWithWriteLock(new Runnable() { @Override public void run() { - if (mBinaryDictionary == null) { + if (getBinaryDictionary() == null) { return; } runGCIfRequiredLocked(mindsBlockByGC); @@ -291,24 +304,24 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { @Nonnull final Runnable updateTask, @Nonnull final String word, @Nonnull final DistracterFilter distracterFilter) { reloadDictionaryIfRequired(); - asyncPreCheckAndExecuteTaskWithWriteLock( - new Callable<Boolean>() { - @Override - public Boolean call() throws Exception { - return !distracterFilter.isDistracterToWordsInDictionaries( - NgramContext.EMPTY_PREV_WORDS_INFO, word, mLocale); - } - }, - new Runnable() { - @Override - public void run() { - if (mBinaryDictionary == null) { - return; - } - runGCIfRequiredLocked(true /* mindsBlockByGC */); - updateTask.run(); - } - }); + final Callable<Boolean> preCheckTask = new Callable<Boolean>() { + @Override + public Boolean call() throws Exception { + return !distracterFilter.isDistracterToWordsInDictionaries( + NgramContext.EMPTY_PREV_WORDS_INFO, word, mLocale); + } + }; + final Runnable task = new Runnable() { + @Override + public void run() { + if (getBinaryDictionary() == null) { + return; + } + runGCIfRequiredLocked(true /* mindsBlockByGC */); + updateTask.run(); + } + }; + asyncPreCheckAndExecuteTaskWithWriteLock(preCheckTask, task); } /** @@ -316,22 +329,22 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { */ public void addUnigramEntryWithCheckingDistracter(final String word, final int frequency, final String shortcutTarget, final int shortcutFreq, final boolean isNotAWord, - final boolean isBlacklisted, final int timestamp, + final boolean isPossiblyOffensive, final int timestamp, @Nonnull final DistracterFilter distracterFilter) { updateDictionaryWithWriteLockIfWordIsNotADistracter(new Runnable() { @Override public void run() { addUnigramLocked(word, frequency, shortcutTarget, shortcutFreq, - isNotAWord, isBlacklisted, timestamp); + isNotAWord, isPossiblyOffensive, timestamp); } }, word, distracterFilter); } protected void addUnigramLocked(final String word, final int frequency, final String shortcutTarget, final int shortcutFreq, final boolean isNotAWord, - final boolean isBlacklisted, final int timestamp) { + final boolean isPossiblyOffensive, final int timestamp) { if (!mBinaryDictionary.addUnigramEntry(word, frequency, shortcutTarget, shortcutFreq, - false /* isBeginningOfSentence */, isNotAWord, isBlacklisted, timestamp)) { + false /* isBeginningOfSentence */, isNotAWord, isPossiblyOffensive, timestamp)) { Log.e(TAG, "Cannot add unigram entry. word: " + word); } } @@ -344,11 +357,12 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { asyncExecuteTaskWithWriteLock(new Runnable() { @Override public void run() { - if (mBinaryDictionary == null) { + final BinaryDictionary binaryDictionary = getBinaryDictionary(); + if (binaryDictionary == null) { return; } runGCIfRequiredLocked(true /* mindsBlockByGC */); - if (!mBinaryDictionary.removeUnigramEntry(word)) { + if (!binaryDictionary.removeUnigramEntry(word)) { if (DEBUG) { Log.i(TAG, "Cannot remove unigram entry: " + word); } @@ -366,7 +380,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { asyncExecuteTaskWithWriteLock(new Runnable() { @Override public void run() { - if (mBinaryDictionary == null) { + if (getBinaryDictionary() == null) { return; } runGCIfRequiredLocked(true /* mindsBlockByGC */); @@ -395,11 +409,12 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { asyncExecuteTaskWithWriteLock(new Runnable() { @Override public void run() { - if (mBinaryDictionary == null) { + final BinaryDictionary binaryDictionary = getBinaryDictionary(); + if (binaryDictionary == null) { return; } runGCIfRequiredLocked(true /* mindsBlockByGC */); - if (!mBinaryDictionary.removeNgramEntry(ngramContext, word)) { + if (!binaryDictionary.removeNgramEntry(ngramContext, word)) { if (DEBUG) { Log.i(TAG, "Cannot remove n-gram entry."); Log.i(TAG, " NgramContext: " + ngramContext + ", word: " + word); @@ -418,7 +433,11 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { updateDictionaryWithWriteLockIfWordIsNotADistracter(new Runnable() { @Override public void run() { - if (!mBinaryDictionary.updateEntriesForWordWithNgramContext(ngramContext, word, + final BinaryDictionary binaryDictionary = getBinaryDictionary(); + if (binaryDictionary == null) { + return; + } + if (!binaryDictionary.updateEntriesForWordWithNgramContext(ngramContext, word, isValidWord, count, timestamp)) { if (DEBUG) { Log.e(TAG, "Cannot update counter. word: " + word @@ -429,27 +448,28 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { }, word, distracterFilter); } - public interface AddMultipleDictionaryEntriesCallback { + public interface UpdateEntriesForInputEventsCallback { public void onFinished(); } /** - * Dynamically add multiple entries to the dictionary. + * Dynamically update entries according to input events. */ - public void addMultipleDictionaryEntriesDynamically( - @Nonnull final ArrayList<LanguageModelParam> languageModelParams, - final AddMultipleDictionaryEntriesCallback callback) { + public void updateEntriesForInputEvents( + @Nonnull final ArrayList<WordInputEventForPersonalization> inputEvents, + final UpdateEntriesForInputEventsCallback callback) { reloadDictionaryIfRequired(); asyncExecuteTaskWithWriteLock(new Runnable() { @Override public void run() { try { - if (mBinaryDictionary == null) { + final BinaryDictionary binaryDictionary = getBinaryDictionary(); + if (binaryDictionary == null) { return; } - mBinaryDictionary.addMultipleDictionaryEntries( - languageModelParams.toArray( - new LanguageModelParam[languageModelParams.size()])); + binaryDictionary.updateEntriesForInputEvents( + inputEvents.toArray( + new WordInputEventForPersonalization[inputEvents.size()])); } finally { if (callback != null) { callback.onFinished(); @@ -555,7 +575,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { * Loads the current binary dictionary from internal storage. Assumes the dictionary file * exists. */ - private void loadBinaryDictionaryLocked() { + void loadBinaryDictionaryLocked() { if (DBG_STRESS_TEST) { // Test if this class does not cause problems when it takes long time to load binary // dictionary. @@ -583,7 +603,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { /** * Create a new binary dictionary and load initial contents. */ - private void createNewDictionaryLocked() { + void createNewDictionaryLocked() { removeBinaryDictionaryLocked(); createOnMemoryBinaryDictionaryLocked(); loadInitialContentsLocked(); @@ -599,6 +619,14 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { mNeedsToRecreate = true; } + void clearNeedsToRecreate() { + mNeedsToRecreate = false; + } + + boolean isNeededToRecreate() { + return mNeedsToRecreate; + } + /** * Load the current binary dictionary from internal storage. If the dictionary file doesn't * exists or needs to be regenerated, the new dictionary file will be asynchronously generated. @@ -621,35 +649,39 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { * Reloads the dictionary. Access is controlled on a per dictionary file basis. */ private final void asyncReloadDictionary() { - if (mIsReloading.compareAndSet(false, true)) { - asyncExecuteTaskWithWriteLock(new Runnable() { - @Override - public void run() { - try { - if (!mDictFile.exists() || mNeedsToRecreate) { - // If the dictionary file does not exist or contents have been updated, - // generate a new one. + final AtomicBoolean isReloading = mIsReloading; + if (!isReloading.compareAndSet(false, true)) { + return; + } + final File dictFile = mDictFile; + asyncExecuteTaskWithWriteLock(new Runnable() { + @Override + public void run() { + try { + if (!dictFile.exists() || isNeededToRecreate()) { + // If the dictionary file does not exist or contents have been updated, + // generate a new one. + createNewDictionaryLocked(); + } else if (getBinaryDictionary() == null) { + // Otherwise, load the existing dictionary. + loadBinaryDictionaryLocked(); + final BinaryDictionary binaryDictionary = getBinaryDictionary(); + if (binaryDictionary != null && !(isValidDictionaryLocked() + // TODO: remove the check below + && matchesExpectedBinaryDictFormatVersionForThisType( + binaryDictionary.getFormatVersion()))) { + // Binary dictionary or its format version is not valid. Regenerate + // the dictionary file. createNewDictionaryLocked will remove the + // existing files if appropriate. createNewDictionaryLocked(); - } else if (mBinaryDictionary == null) { - // Otherwise, load the existing dictionary. - loadBinaryDictionaryLocked(); - if (mBinaryDictionary != null && !(isValidDictionaryLocked() - // TODO: remove the check below - && matchesExpectedBinaryDictFormatVersionForThisType( - mBinaryDictionary.getFormatVersion()))) { - // Binary dictionary or its format version is not valid. Regenerate - // the dictionary file. createNewDictionaryLocked will remove the - // existing files if appropriate. - createNewDictionaryLocked(); - } } - mNeedsToRecreate = false; - } finally { - mIsReloading.set(false); } + clearNeedsToRecreate(); + } finally { + isReloading.set(false); } - }); - } + } + }); } /** @@ -659,19 +691,20 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { asyncExecuteTaskWithWriteLock(new Runnable() { @Override public void run() { - if (mBinaryDictionary == null) { + final BinaryDictionary binaryDictionary = getBinaryDictionary(); + if (binaryDictionary == null) { return; } - if (mBinaryDictionary.needsToRunGC(false /* mindsBlockByGC */)) { - mBinaryDictionary.flushWithGC(); + if (binaryDictionary.needsToRunGC(false /* mindsBlockByGC */)) { + binaryDictionary.flushWithGC(); } else { - mBinaryDictionary.flush(); + binaryDictionary.flush(); } } }); } - private static int parseEntryCount(final String entryCountStr) { + static int parseEntryCount(final String entryCountStr) { int entryCount; try { entryCount = Integer.parseInt(entryCountStr); @@ -683,23 +716,27 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { public DictionaryStats getDictionaryStats() { reloadDictionaryIfRequired(); + final String dictName = mDictName; + final File dictFile = mDictFile; final AsyncResultHolder<DictionaryStats> result = new AsyncResultHolder<>(); - asyncExecuteTaskWithLock(mLock.readLock(), mDictName /* executorName */, new Runnable() { + asyncExecuteTaskWithLock(mLock.readLock(), dictName /* executorName */, new Runnable() { @Override public void run() { - if (mBinaryDictionary == null) { - result.set(new DictionaryStats(mLocale, mDictName, mDictFile, + final BinaryDictionary binaryDictionary = getBinaryDictionary(); + if (binaryDictionary == null) { + result.set(new DictionaryStats(mLocale, dictName, dictFile, DictionaryStats.NOT_AN_ENTRY_COUNT, DictionaryStats.NOT_AN_ENTRY_COUNT)); + return; } final int unigramCount = parseEntryCount( - mBinaryDictionary.getPropertyForGettingStats( + binaryDictionary.getPropertyForGettingStats( BinaryDictionary.MAX_UNIGRAM_COUNT_QUERY)); // TODO: Get dedicated entry counts for bigram, trigram, and so on. - final int ngramCount = parseEntryCount(mBinaryDictionary.getPropertyForGettingStats( + final int ngramCount = parseEntryCount(binaryDictionary.getPropertyForGettingStats( BinaryDictionary.MAX_BIGRAM_COUNT_QUERY)); // TODO: Get more information from dictionary. - result.set(new DictionaryStats(mLocale, mDictName, mDictFile, unigramCount, + result.set(new DictionaryStats(mLocale, dictName, dictFile, unigramCount, ngramCount)); } }); @@ -731,28 +768,34 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { public void dumpAllWordsForDebug() { reloadDictionaryIfRequired(); + final String tag = TAG; + final String dictName = mDictName; asyncExecuteTaskWithLock(mLock.readLock(), "dumpAllWordsForDebug", new Runnable() { @Override public void run() { - Log.d(TAG, "Dump dictionary: " + mDictName + " for " + mLocale); + Log.d(tag, "Dump dictionary: " + dictName + " for " + mLocale); + final BinaryDictionary binaryDictionary = getBinaryDictionary(); + if (binaryDictionary == null) { + return; + } try { - final DictionaryHeader header = mBinaryDictionary.getHeader(); - Log.d(TAG, "Format version: " + mBinaryDictionary.getFormatVersion()); - Log.d(TAG, CombinedFormatUtils.formatAttributeMap( + final DictionaryHeader header = binaryDictionary.getHeader(); + Log.d(tag, "Format version: " + binaryDictionary.getFormatVersion()); + Log.d(tag, CombinedFormatUtils.formatAttributeMap( header.mDictionaryOptions.mAttributes)); } catch (final UnsupportedFormatException e) { - Log.d(TAG, "Cannot fetch header information.", e); + Log.d(tag, "Cannot fetch header information.", e); } int token = 0; do { final BinaryDictionary.GetNextWordPropertyResult result = - mBinaryDictionary.getNextWordProperty(token); + binaryDictionary.getNextWordProperty(token); final WordProperty wordProperty = result.mWordProperty; if (wordProperty == null) { - Log.d(TAG, " dictionary is empty."); + Log.d(tag, " dictionary is empty."); break; } - Log.d(TAG, wordProperty.toString()); + Log.d(tag, wordProperty.toString()); token = result.mNextToken; } while (token != 0); } diff --git a/java/src/com/android/inputmethod/latin/InputAttributes.java b/java/src/com/android/inputmethod/latin/InputAttributes.java index ffd363b5d..002222080 100644 --- a/java/src/com/android/inputmethod/latin/InputAttributes.java +++ b/java/src/com/android/inputmethod/latin/InputAttributes.java @@ -16,9 +16,9 @@ package com.android.inputmethod.latin; -import static com.android.inputmethod.latin.Constants.ImeOption.NO_FLOATING_GESTURE_PREVIEW; -import static com.android.inputmethod.latin.Constants.ImeOption.NO_MICROPHONE; -import static com.android.inputmethod.latin.Constants.ImeOption.NO_MICROPHONE_COMPAT; +import static com.android.inputmethod.latin.common.Constants.ImeOption.NO_FLOATING_GESTURE_PREVIEW; +import static com.android.inputmethod.latin.common.Constants.ImeOption.NO_MICROPHONE; +import static com.android.inputmethod.latin.common.Constants.ImeOption.NO_MICROPHONE_COMPAT; import android.text.InputType; import android.util.Log; diff --git a/java/src/com/android/inputmethod/latin/InputView.java b/java/src/com/android/inputmethod/latin/InputView.java index 7fa935413..f3a8ca169 100644 --- a/java/src/com/android/inputmethod/latin/InputView.java +++ b/java/src/com/android/inputmethod/latin/InputView.java @@ -139,7 +139,10 @@ public final class InputView extends FrameLayout { return y - mEventReceivingRect.top; } - // Callback when a {@link MotionEvent} is forwarded. + /** + * Callback when a {@link MotionEvent} is forwarded. + * @param me the motion event to be forwarded. + */ protected void onForwardingEvent(final MotionEvent me) {} // Returns true if a {@link MotionEvent} is needed to be forwarded to diff --git a/java/src/com/android/inputmethod/latin/LastComposedWord.java b/java/src/com/android/inputmethod/latin/LastComposedWord.java index f3f736fbc..c4c389411 100644 --- a/java/src/com/android/inputmethod/latin/LastComposedWord.java +++ b/java/src/com/android/inputmethod/latin/LastComposedWord.java @@ -19,6 +19,7 @@ package com.android.inputmethod.latin; import android.text.TextUtils; import com.android.inputmethod.event.Event; +import com.android.inputmethod.latin.common.Constants; import java.util.ArrayList; diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 91a4ec84c..ff82087ae 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -16,10 +16,11 @@ package com.android.inputmethod.latin; -import static com.android.inputmethod.latin.Constants.ImeOption.FORCE_ASCII; -import static com.android.inputmethod.latin.Constants.ImeOption.NO_MICROPHONE; -import static com.android.inputmethod.latin.Constants.ImeOption.NO_MICROPHONE_COMPAT; +import static com.android.inputmethod.latin.common.Constants.ImeOption.FORCE_ASCII; +import static com.android.inputmethod.latin.common.Constants.ImeOption.NO_MICROPHONE; +import static com.android.inputmethod.latin.common.Constants.ImeOption.NO_MICROPHONE_COMPAT; +import android.annotation.TargetApi; import android.app.AlertDialog; import android.content.BroadcastReceiver; import android.content.Context; @@ -75,6 +76,7 @@ import com.android.inputmethod.keyboard.MainKeyboardView; import com.android.inputmethod.keyboard.TextDecoratorUi; import com.android.inputmethod.latin.Suggest.OnGetSuggestedWordsCallback; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.define.DebugFlags; import com.android.inputmethod.latin.define.ProductionFlags; import com.android.inputmethod.latin.inputlogic.InputLogic; @@ -119,15 +121,15 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen SuggestionStripView.Listener, SuggestionStripViewAccessor, DictionaryFacilitator.DictionaryInitializationListener, ImportantNoticeDialog.ImportantNoticeDialogListener { - private static final String TAG = LatinIME.class.getSimpleName(); + static final String TAG = LatinIME.class.getSimpleName(); private static final boolean TRACE = false; private static boolean DEBUG = false; private static final int EXTENDED_TOUCHABLE_REGION_HEIGHT = 100; private static final int PERIOD_FOR_AUDIO_AND_HAPTIC_FEEDBACK_IN_KEY_REPEAT = 2; private static final int PENDING_IMS_CALLBACK_DURATION_MILLIS = 800; - private static final long DELAY_WAIT_FOR_DICTIONARY_LOAD_MILLIS = TimeUnit.SECONDS.toMillis(2); - private static final long DELAY_DEALLOCATE_MEMORY_MILLIS = TimeUnit.SECONDS.toMillis(10); + static final long DELAY_WAIT_FOR_DICTIONARY_LOAD_MILLIS = TimeUnit.SECONDS.toMillis(2); + static final long DELAY_DEALLOCATE_MEMORY_MILLIS = TimeUnit.SECONDS.toMillis(10); /** * The name of the scheme used by the Package Manager to warn of a new package installation, @@ -135,7 +137,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen */ private static final String SCHEME_PACKAGE = "package"; - private final Settings mSettings; + final Settings mSettings; private final DictionaryFacilitator mDictionaryFacilitator = new DictionaryFacilitator(this /* context */); // TODO: Move from LatinIME. @@ -149,7 +151,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mHandler.postUpdateSuggestionStrip(SuggestedWords.INPUT_STYLE_NONE); } }); - private final InputLogic mInputLogic = new InputLogic(this /* LatinIME */, + final InputLogic mInputLogic = new InputLogic(this /* LatinIME */, this /* SuggestionStripViewAccessor */, mDictionaryFacilitator); // We expect to have only one decoder in almost all cases, hence the default capacity of 1. // If it turns out we need several, it will get grown seamlessly. @@ -163,9 +165,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen private RichInputMethodManager mRichImm; @UsedForTesting final KeyboardSwitcher mKeyboardSwitcher; - private final SubtypeSwitcher mSubtypeSwitcher; + final SubtypeSwitcher mSubtypeSwitcher; private final SubtypeState mSubtypeState = new SubtypeState(); - private final SpecialKeyDetector mSpecialKeyDetector; + private final EmojiAltPhysicalKeyDetector mEmojiAltPhysicalKeyDetector = + new EmojiAltPhysicalKeyDetector(); private StatsUtilsManager mStatsUtilsManager; // Working variable for {@link #startShowingInputView()} and // {@link #onEvaluateInputViewShown()}. @@ -204,7 +207,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen private static final int ARG1_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT = 1; private static final int ARG1_SHOW_GESTURE_FLOATING_PREVIEW_TEXT = 2; private static final int ARG2_UNUSED = 0; - private static final int ARG1_FALSE = 0; private static final int ARG1_TRUE = 1; private int mDelayInMillisecondsToUpdateSuggestions; @@ -544,7 +546,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mSettings = Settings.getInstance(); mSubtypeSwitcher = SubtypeSwitcher.getInstance(); mKeyboardSwitcher = KeyboardSwitcher.getInstance(); - mSpecialKeyDetector = new SpecialKeyDetector(this); mStatsUtilsManager = StatsUtilsManager.getInstance(); mIsHardwareAcceleratedDrawingEnabled = InputMethodServiceCompatUtils.enableHardwareAcceleration(this); @@ -654,7 +655,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } } - private void resetDictionaryFacilitatorIfNecessary() { + void resetDictionaryFacilitatorIfNecessary() { final Locale[] subtypeSwitcherLocales = mSubtypeSwitcher.getCurrentSubtypeLocales(); if (mDictionaryFacilitator.isForLocales(subtypeSwitcherLocales)) { return; @@ -791,17 +792,21 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } } + void updateCursorAnchorInfo() { + // CursorAnchorInfo is used on L and later. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + if (isFullscreenMode() && mExtractEditText != null) { + mInputLogic.onUpdateCursorAnchorInfo( + CursorAnchorInfoUtils.extractFromTextView(mExtractEditText)); + } + } + } + private final ViewTreeObserver.OnPreDrawListener mExtractTextViewPreDrawListener = new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { - // CursorAnchorInfo is used on L and later. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - if (isFullscreenMode() && mExtractEditText != null) { - mInputLogic.onUpdateCursorAnchorInfo( - CursorAnchorInfoUtils.extractFromTextView(mExtractEditText)); - } - } + updateCursorAnchorInfo(); return true; } }; @@ -846,12 +851,12 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen loadKeyboard(); } - private void onStartInputInternal(final EditorInfo editorInfo, final boolean restarting) { + void onStartInputInternal(final EditorInfo editorInfo, final boolean restarting) { super.onStartInput(editorInfo, restarting); } @SuppressWarnings("deprecation") - private void onStartInputViewInternal(final EditorInfo editorInfo, final boolean restarting) { + void onStartInputViewInternal(final EditorInfo editorInfo, final boolean restarting) { super.onStartInputView(editorInfo, restarting); // Switch to the null consumer to handle cases leading to early exit below, for which we // also wouldn't be consuming gesture data. @@ -1034,7 +1039,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } } - private void onFinishInputInternal() { + void onFinishInputInternal() { super.onFinishInput(); final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView(); @@ -1043,7 +1048,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } } - private void onFinishInputViewInternal(final boolean finishingInput) { + void onFinishInputViewInternal(final boolean finishingInput) { super.onFinishInputView(finishingInput); cleanupInternalStateForFinishInput(); } @@ -1083,8 +1088,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } } - // We cannot mark this method as @Override until new SDK becomes publicly available. - // @Override + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + @Override public void onUpdateCursorAnchorInfo(final CursorAnchorInfo info) { if (isFullscreenMode()) { return; @@ -1295,11 +1300,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } } - private int getCurrentAutoCapsState() { + int getCurrentAutoCapsState() { return mInputLogic.getCurrentAutoCapsState(mSettings.getCurrent()); } - private int getCurrentRecapitalizeState() { + int getCurrentRecapitalizeState() { return mInputLogic.getCurrentRecapitalizeState(); } @@ -1389,12 +1394,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen final Keyboard currentKeyboard = mKeyboardSwitcher.getKeyboard(); if (null != currentKeyboard && currentKeyboard.mId.isAlphabetKeyboard()) { return codePoint; - } else { - return Constants.CODE_SYMBOL_SHIFT; } - } else { - return codePoint; + return Constants.CODE_SYMBOL_SHIFT; } + return codePoint; } // Implementation of {@link KeyboardActionListener}. @@ -1417,7 +1420,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // This method is public for testability of LatinIME, but also in the future it should // completely replace #onCodeInput. - public void onEvent(final Event event) { + public void onEvent(@Nonnull final Event event) { if (Constants.CODE_SHORTCUT == event.mKeyCode) { mSubtypeSwitcher.switchToShortcutIME(this); } @@ -1432,6 +1435,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // A helper method to split the code point and the key code. Ultimately, they should not be // squashed into the same variable, and this method should be removed. // public for testing, as we don't want to copy the same logic into test code + @Nonnull public static Event createSoftwareKeypressEvent(final int keyCodeOrCodePoint, final int keyX, final int keyY, final boolean isKeyRepeat) { final int keyCode; @@ -1496,7 +1500,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } // This method must run on the UI Thread. - private void showGesturePreviewAndSuggestionStrip(final SuggestedWords suggestedWords, + void showGesturePreviewAndSuggestionStrip(final SuggestedWords suggestedWords, final boolean dismissGestureFloatingPreviewText) { showSuggestionStrip(suggestedWords); final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView(); @@ -1761,7 +1765,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // Hooks for hardware keyboard @Override public boolean onKeyDown(final int keyCode, final KeyEvent keyEvent) { - mSpecialKeyDetector.onKeyDown(keyEvent); + // TODO: This should be processed in {@link InputLogic}. + mEmojiAltPhysicalKeyDetector.onKeyDown(keyEvent); if (!ProductionFlags.IS_HARDWARE_KEYBOARD_SUPPORTED) { return super.onKeyDown(keyCode, keyEvent); } @@ -1782,7 +1787,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen @Override public boolean onKeyUp(final int keyCode, final KeyEvent keyEvent) { - mSpecialKeyDetector.onKeyUp(keyEvent); + // TODO: This should be processed in {@link InputLogic}. + mEmojiAltPhysicalKeyDetector.onKeyUp(keyEvent); if (!ProductionFlags.IS_HARDWARE_KEYBOARD_SUPPORTED) { return super.onKeyUp(keyCode, keyEvent); } @@ -1812,7 +1818,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } }; - private void launchSettings() { + void launchSettings() { mInputLogic.commitTyped(mSettings.getCurrent(), LastComposedWord.NOT_A_SEPARATOR); requestHideSelf(0); final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView(); @@ -1836,6 +1842,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen languageSelectionTitle, getString(ApplicationUtils.getActivityTitleResId(this, SettingsActivity.class)) }; + final String imeId = mRichImm.getInputMethodIdOfThisIme(); final OnClickListener listener = new OnClickListener() { @Override public void onClick(DialogInterface di, int position) { @@ -1843,7 +1850,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen switch (position) { case 0: final Intent intent = IntentUtils.getInputLanguageSelectionIntent( - mRichImm.getInputMethodIdOfThisIme(), + imeId, Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED | Intent.FLAG_ACTIVITY_CLEAR_TOP); diff --git a/java/src/com/android/inputmethod/latin/NgramContext.java b/java/src/com/android/inputmethod/latin/NgramContext.java index a02531cc4..0ccea4732 100644 --- a/java/src/com/android/inputmethod/latin/NgramContext.java +++ b/java/src/com/android/inputmethod/latin/NgramContext.java @@ -19,26 +19,33 @@ package com.android.inputmethod.latin; import android.text.TextUtils; import com.android.inputmethod.annotations.UsedForTesting; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.utils.StringUtils; import java.util.Arrays; +import javax.annotation.Nonnull; + /** * Class to represent information of previous words. This class is used to add n-gram entries * into binary dictionaries, to get predictions, and to get suggestions. */ public class NgramContext { + @Nonnull public static final NgramContext EMPTY_PREV_WORDS_INFO = new NgramContext(WordInfo.EMPTY_WORD_INFO); + @Nonnull public static final NgramContext BEGINNING_OF_SENTENCE = - new NgramContext(WordInfo.BEGINNING_OF_SENTENCE); + new NgramContext(WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO); /** * Word information used to represent previous words information. */ public static class WordInfo { + @Nonnull public static final WordInfo EMPTY_WORD_INFO = new WordInfo(null); - public static final WordInfo BEGINNING_OF_SENTENCE = new WordInfo(); + @Nonnull + public static final WordInfo BEGINNING_OF_SENTENCE_WORD_INFO = new WordInfo(); // This is an empty char sequence when mIsBeginningOfSentence is true. public final CharSequence mWord; @@ -48,7 +55,7 @@ public class NgramContext { public final boolean mIsBeginningOfSentence; // Beginning of sentence. - public WordInfo() { + private WordInfo() { mWord = ""; mIsBeginningOfSentence = true; } @@ -96,19 +103,8 @@ public class NgramContext { mPrevWordsCount = prevWordsInfo.length; } - // Construct from WordInfo array and size. The caller shouldn't change prevWordsInfo after - // calling this method. - private NgramContext(final NgramContext ngramContext, final int prevWordsCount) { - if (ngramContext.mPrevWordsCount < prevWordsCount) { - throw new IndexOutOfBoundsException("ngramContext.mPrevWordsCount (" - + ngramContext.mPrevWordsCount + ") is smaller than prevWordsCount (" - + prevWordsCount + ")"); - } - mPrevWordsInfo = ngramContext.mPrevWordsInfo; - mPrevWordsCount = prevWordsCount; - } - // Create next prevWordsInfo using current prevWordsInfo. + @Nonnull public NgramContext getNextNgramContext(final WordInfo wordInfo) { final int nextPrevWordCount = Math.min(Constants.MAX_PREV_WORD_COUNT_FOR_N_GRAM, mPrevWordsCount + 1); diff --git a/java/src/com/android/inputmethod/latin/PersonalizationHelperForDictionaryFacilitator.java b/java/src/com/android/inputmethod/latin/PersonalizationHelperForDictionaryFacilitator.java index 396d062f8..2dbab0a3f 100644 --- a/java/src/com/android/inputmethod/latin/PersonalizationHelperForDictionaryFacilitator.java +++ b/java/src/com/android/inputmethod/latin/PersonalizationHelperForDictionaryFacilitator.java @@ -26,14 +26,14 @@ import java.util.concurrent.atomic.AtomicInteger; import android.content.Context; import android.view.inputmethod.InputMethodSubtype; -import com.android.inputmethod.latin.ExpandableBinaryDictionary.AddMultipleDictionaryEntriesCallback; +import com.android.inputmethod.latin.ExpandableBinaryDictionary.UpdateEntriesForInputEventsCallback; import com.android.inputmethod.latin.personalization.PersonalizationDataChunk; import com.android.inputmethod.latin.personalization.PersonalizationDictionary; import com.android.inputmethod.latin.settings.SpacingAndPunctuations; import com.android.inputmethod.latin.utils.DistracterFilter; import com.android.inputmethod.latin.utils.DistracterFilterCheckingIsInDictionary; -import com.android.inputmethod.latin.utils.LanguageModelParam; import com.android.inputmethod.latin.utils.SubtypeLocaleUtils; +import com.android.inputmethod.latin.utils.WordInputEventForPersonalization; /** * Class for managing and updating personalization dictionaries. @@ -119,10 +119,10 @@ public class PersonalizationHelperForDictionaryFacilitator { return personalizationDict; } - private void addEntriesToPersonalizationDictionariesForLocale(final Locale locale, + private void updateEntriesOfPersonalizationDictionariesForLocale(final Locale locale, final PersonalizationDataChunk personalizationDataChunk, final SpacingAndPunctuations spacingAndPunctuations, - final AddMultipleDictionaryEntriesCallback callback) { + final UpdateEntriesForInputEventsCallback callback) { final ExpandableBinaryDictionary personalizationDict = getPersonalizationDictToUpdate(mContext, locale); if (personalizationDict == null) { @@ -131,25 +131,25 @@ public class PersonalizationHelperForDictionaryFacilitator { } return; } - final ArrayList<LanguageModelParam> languageModelParams = - LanguageModelParam.createLanguageModelParamsFrom( + final ArrayList<WordInputEventForPersonalization> inputEvents = + WordInputEventForPersonalization.createInputEventFrom( personalizationDataChunk.mTokens, personalizationDataChunk.mTimestampInSeconds, spacingAndPunctuations, locale, new DistracterFilterCheckingIsInDictionary( mDistracterFilter, personalizationDict)); - if (languageModelParams == null || languageModelParams.isEmpty()) { + if (inputEvents == null || inputEvents.isEmpty()) { if (callback != null) { callback.onFinished(); } return; } - personalizationDict.addMultipleDictionaryEntriesDynamically(languageModelParams, callback); + personalizationDict.updateEntriesForInputEvents(inputEvents, callback); } - public void addEntriesToPersonalizationDictionariesToUpdate(final Locale defaultLocale, + public void updateEntriesOfPersonalizationDictionaries(final Locale defaultLocale, final PersonalizationDataChunk personalizationDataChunk, final SpacingAndPunctuations spacingAndPunctuations, - final AddMultipleDictionaryEntriesCallback callback) { + final UpdateEntriesForInputEventsCallback callback) { final String language = personalizationDataChunk.mDetectedLanguage; final HashSet<Locale> locales; if (mIsMonolingualUser && PersonalizationDataChunk.LANGUAGE_UNKNOWN.equals(language) @@ -165,8 +165,8 @@ public class PersonalizationHelperForDictionaryFacilitator { return; } final AtomicInteger remainingTaskCount = new AtomicInteger(locales.size()); - final AddMultipleDictionaryEntriesCallback callbackForLocales = - new AddMultipleDictionaryEntriesCallback() { + final UpdateEntriesForInputEventsCallback callbackForLocales = + new UpdateEntriesForInputEventsCallback() { @Override public void onFinished() { if (remainingTaskCount.decrementAndGet() == 0) { @@ -178,7 +178,7 @@ public class PersonalizationHelperForDictionaryFacilitator { } }; for (final Locale locale : locales) { - addEntriesToPersonalizationDictionariesForLocale(locale, personalizationDataChunk, + updateEntriesOfPersonalizationDictionariesForLocale(locale, personalizationDataChunk, spacingAndPunctuations, callbackForLocales); } } diff --git a/java/src/com/android/inputmethod/latin/PunctuationSuggestions.java b/java/src/com/android/inputmethod/latin/PunctuationSuggestions.java index 56014cbad..93598d2fb 100644 --- a/java/src/com/android/inputmethod/latin/PunctuationSuggestions.java +++ b/java/src/com/android/inputmethod/latin/PunctuationSuggestions.java @@ -17,6 +17,7 @@ package com.android.inputmethod.latin; import com.android.inputmethod.keyboard.internal.KeySpecParser; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.utils.StringUtils; import java.util.ArrayList; @@ -56,7 +57,7 @@ public final class PunctuationSuggestions extends SuggestedWords { /** * {@inheritDoc} - * Note that {@link super#getWord(int)} returns a punctuation key specification text. + * Note that {@link SuggestedWords#getWord(int)} returns a punctuation key specification text. * The suggested punctuation should be gotten by parsing the key specification. */ @Override @@ -70,7 +71,7 @@ public final class PunctuationSuggestions extends SuggestedWords { /** * {@inheritDoc} - * Note that {@link super#getWord(int)} returns a punctuation key specification text. + * Note that {@link SuggestedWords#getWord(int)} returns a punctuation key specification text. * The displayed text should be gotten by parsing the key specification. */ @Override @@ -82,7 +83,7 @@ public final class PunctuationSuggestions extends SuggestedWords { /** * {@inheritDoc} * Note that {@link #getWord(int)} returns a suggested punctuation. We should create a - * {@link SuggestedWordInfo} object that represents a hard coded word. + * {@link SuggestedWords.SuggestedWordInfo} object that represents a hard coded word. */ @Override public SuggestedWordInfo getInfo(final int index) { diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java index a3f7bb4d6..0763ef807 100644 --- a/java/src/com/android/inputmethod/latin/RichInputConnection.java +++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java @@ -34,6 +34,7 @@ import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; import com.android.inputmethod.compat.InputConnectionCompatUtils; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.inputlogic.PrivateCommandPerformer; import com.android.inputmethod.latin.settings.SpacingAndPunctuations; import com.android.inputmethod.latin.utils.CapsModeUtils; @@ -44,7 +45,7 @@ import com.android.inputmethod.latin.utils.SpannableStringUtils; import com.android.inputmethod.latin.utils.StringUtils; import com.android.inputmethod.latin.utils.TextRange; -import java.util.Arrays; +import javax.annotation.Nonnull; /** * Enrichment class for InputConnection to simplify interaction and add functionality. @@ -91,7 +92,7 @@ public final class RichInputConnection implements PrivateCommandPerformer { /** * This variable is a temporary object used in - * {@link #commitTextWithBackgroundColor(CharSequence, int, int)} to avoid object creation. + * {@link #commitTextWithBackgroundColor(CharSequence,int,int,int)} to avoid object creation. */ private SpannableStringBuilder mTempObjectForCommitText = new SpannableStringBuilder(); /** @@ -151,9 +152,8 @@ public final class RichInputConnection implements PrivateCommandPerformer { } else { if (DBG) { throw new RuntimeException("Nest level too deep"); - } else { - Log.e(TAG, "Nest level too deep : " + mNestLevel); } + Log.e(TAG, "Nest level too deep : " + mNestLevel); } if (DEBUG_BATCH_NESTING) checkBatchEdit(); if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug(); @@ -351,10 +351,9 @@ public final class RichInputConnection implements PrivateCommandPerformer { // If we have some composing text and a space before, then we should have // MODE_CHARACTERS and MODE_WORDS on. return (TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_WORDS) & inputType; - } else { - // We have some composing text - we should be in MODE_CHARACTERS only. - return TextUtils.CAP_MODE_CHARACTERS & inputType; } + // We have some composing text - we should be in MODE_CHARACTERS only. + return TextUtils.CAP_MODE_CHARACTERS & inputType; } // TODO: this will generally work, but there may be cases where the buffer contains SOME // information but not enough to determine the caps mode accurately. This may happen after @@ -369,7 +368,9 @@ public final class RichInputConnection implements PrivateCommandPerformer { } // This never calls InputConnection#getCapsMode - in fact, it's a static method that // never blocks or initiates IPC. - return CapsModeUtils.getCapsMode(mCommittedTextBeforeComposingText, inputType, + // TODO: don't call #toString() here. Instead, all accesses to + // mCommittedTextBeforeComposingText should be done on the main thread. + return CapsModeUtils.getCapsMode(mCommittedTextBeforeComposingText.toString(), inputType, spacingAndPunctuations, hasSpaceBefore); } @@ -595,6 +596,7 @@ public final class RichInputConnection implements PrivateCommandPerformer { } @SuppressWarnings("unused") + @Nonnull public NgramContext getNgramContextFromNthPreviousWord( final SpacingAndPunctuations spacingAndPunctuations, final int n) { mIC = mParent.getCurrentInputConnection(); @@ -624,10 +626,6 @@ public final class RichInputConnection implements PrivateCommandPerformer { prev, spacingAndPunctuations, n); } - private static boolean isSeparator(final int code, final int[] sortedSeparators) { - return Arrays.binarySearch(sortedSeparators, code) >= 0; - } - private static boolean isPartOfCompositionForScript(final int codePoint, final SpacingAndPunctuations spacingAndPunctuations, final int scriptId) { // We always consider word connectors part of compositions. @@ -977,7 +975,8 @@ public final class RichInputConnection implements PrivateCommandPerformer { /** * @return {@code true} if the application reported that the monitor mode of - * {@link InputMethodService#onUpdateCursorAnchorInfo(CursorAnchorInfo)} is currently enabled. + * {@link InputMethodService#onUpdateCursorAnchorInfo(android.view.inputmethod.CursorAnchorInfo)} + * is currently enabled. */ public boolean isCursorAnchorInfoMonitorEnabled() { return mCursorAnchorInfoMonitorEnabled; diff --git a/java/src/com/android/inputmethod/latin/RichInputMethodManager.java b/java/src/com/android/inputmethod/latin/RichInputMethodManager.java index e6df35bea..8d8e7ac38 100644 --- a/java/src/com/android/inputmethod/latin/RichInputMethodManager.java +++ b/java/src/com/android/inputmethod/latin/RichInputMethodManager.java @@ -16,11 +16,10 @@ package com.android.inputmethod.latin; -import static com.android.inputmethod.latin.Constants.Subtype.KEYBOARD_MODE; +import static com.android.inputmethod.latin.common.Constants.Subtype.KEYBOARD_MODE; import android.content.Context; import android.content.SharedPreferences; -import android.content.res.Resources; import android.os.Build; import android.os.IBinder; import android.preference.PreferenceManager; @@ -39,6 +38,8 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; +import javax.annotation.Nonnull; + /** * Enrichment class for InputMethodManager to simplify interaction and add functionality. */ @@ -302,12 +303,13 @@ public class RichInputMethodManager { return INDEX_NOT_FOUND; } + @Nonnull public InputMethodSubtype getCurrentRawSubtype() { return mImmWrapper.mImm.getCurrentInputMethodSubtype(); } public RichInputMethodSubtype createCurrentRichInputMethodSubtype( - final InputMethodSubtype rawSubtype) { + @Nonnull final InputMethodSubtype rawSubtype) { return AdditionalFeaturesSettingUtils.createRichInputMethodSubtype(this, rawSubtype, mContext); } diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java index 6fc549549..98bce95bd 100644 --- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java +++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java @@ -16,8 +16,7 @@ package com.android.inputmethod.latin; -import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.REQ_NETWORK_CONNECTIVITY; - +import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.REQ_NETWORK_CONNECTIVITY; import android.content.Context; import android.content.Intent; import android.content.res.Resources; @@ -35,6 +34,7 @@ import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.compat.InputMethodSubtypeCompatUtils; import com.android.inputmethod.keyboard.KeyboardSwitcher; import com.android.inputmethod.keyboard.internal.LanguageOnSpacebarHelper; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.define.DebugFlags; import com.android.inputmethod.latin.utils.SubtypeLocaleUtils; @@ -44,6 +44,8 @@ import java.util.Locale; import java.util.Map; import java.util.Set; +import javax.annotation.Nonnull; + public final class SubtypeSwitcher { private static boolean DBG = DebugFlags.DEBUG_ENABLED; private static final String TAG = SubtypeSwitcher.class.getSimpleName(); @@ -169,7 +171,7 @@ public final class SubtypeSwitcher { } // Update the current subtype. LatinIME.onCurrentInputMethodSubtypeChanged calls this function. - public void onSubtypeChanged(final InputMethodSubtype newSubtype) { + public void onSubtypeChanged(@Nonnull final InputMethodSubtype newSubtype) { final RichInputMethodSubtype richSubtype = mRichImm.createCurrentRichInputMethodSubtype(newSubtype); if (DBG) { @@ -291,8 +293,9 @@ public final class SubtypeSwitcher { } private static RichInputMethodSubtype sForcedSubtypeForTesting = null; + @UsedForTesting - void forceSubtype(final InputMethodSubtype subtype) { + static void forceSubtype(final InputMethodSubtype subtype) { sForcedSubtypeForTesting = new RichInputMethodSubtype(subtype); } diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index e6c138407..17df1eab4 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -20,6 +20,7 @@ import android.text.TextUtils; import com.android.inputmethod.keyboard.ProximityInfo; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.define.DebugFlags; import com.android.inputmethod.latin.settings.SettingsValuesForSuggestion; import com.android.inputmethod.latin.utils.AutoCorrectionUtils; @@ -328,7 +329,7 @@ public final class Suggest { * @param info the suggestion info * @return whether it's fine to auto-correct to this. */ - private boolean isAllowedByAutoCorrectionWithSpaceFilter(final SuggestedWordInfo info) { + private static boolean isAllowedByAutoCorrectionWithSpaceFilter(final SuggestedWordInfo info) { final Locale locale = info.mSourceDict.mLocale; if (null == locale) { return true; diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java index e5bf25d5f..a6428896e 100644 --- a/java/src/com/android/inputmethod/latin/SuggestedWords.java +++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java @@ -20,6 +20,7 @@ import android.text.TextUtils; import android.view.inputmethod.CompletionInfo; import com.android.inputmethod.annotations.UsedForTesting; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.define.DebugFlags; import com.android.inputmethod.latin.utils.StringUtils; @@ -365,9 +366,8 @@ public class SuggestedWords { public String toString() { if (TextUtils.isEmpty(mDebugString)) { return mWord; - } else { - return mWord + " (" + mDebugString + ")"; } + return mWord + " (" + mDebugString + ")"; } // This will always remove the higher index if a duplicate is found. diff --git a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java index 21014b378..2b7fb1748 100644 --- a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java @@ -28,7 +28,7 @@ import android.provider.UserDictionary.Words; import android.text.TextUtils; import android.util.Log; -import com.android.inputmethod.annotations.UsedForTesting; +import com.android.inputmethod.annotations.ExternallyReferenced; import com.android.inputmethod.compat.UserDictionaryCompatUtils; import com.android.inputmethod.latin.utils.SubtypeLocaleUtils; @@ -64,7 +64,7 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary { private static final String NAME = "userunigram"; private ContentObserver mObserver; - final private String mLocale; + final private String mLocaleString; final private boolean mAlsoUseMoreRestrictiveLocales; protected UserBinaryDictionary(final Context context, final Locale locale, @@ -74,9 +74,9 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary { final String localeStr = locale.toString(); if (SubtypeLocaleUtils.NO_LANGUAGE.equals(localeStr)) { // If we don't have a locale, insert into the "all locales" user dictionary. - mLocale = USER_DICTIONARY_ALL_LANGUAGES; + mLocaleString = USER_DICTIONARY_ALL_LANGUAGES; } else { - mLocale = localeStr; + mLocaleString = localeStr; } mAlsoUseMoreRestrictiveLocales = alsoUseMoreRestrictiveLocales; ContentResolver cres = context.getContentResolver(); @@ -101,7 +101,8 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary { reloadDictionaryIfRequired(); } - @UsedForTesting + // Note: This method is called by {@link DictionaryFacilitator} using Java reflection. + @ExternallyReferenced public static UserBinaryDictionary getDictionary(final Context context, final Locale locale, final File dictFile, final String dictNamePrefix) { return new UserBinaryDictionary(context, locale, false /* alsoUseMoreRestrictiveLocales */, @@ -124,7 +125,7 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary { // This is correct for locale processing. // For this example, we'll look at the "en_US_POSIX" case. final String[] localeElements = - TextUtils.isEmpty(mLocale) ? new String[] {} : mLocale.split("_", 3); + TextUtils.isEmpty(mLocaleString) ? new String[] {} : mLocaleString.split("_", 3); final int length = localeElements.length; final StringBuilder request = new StringBuilder("(locale is NULL)"); @@ -207,9 +208,8 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary { if (client != null) { client.release(); return true; - } else { - return false; } + return false; } /** @@ -227,17 +227,16 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary { HISTORICAL_DEFAULT_USER_DICTIONARY_FREQUENCY, null, locale); } - private int scaleFrequencyFromDefaultToLatinIme(final int defaultFrequency) { + private static int scaleFrequencyFromDefaultToLatinIme(final int defaultFrequency) { // The default frequency for the user dictionary is 250 for historical reasons. // Latin IME considers a good value for the default user dictionary frequency // is about 160 considering the scale we use. So we are scaling down the values. if (defaultFrequency > Integer.MAX_VALUE / LATINIME_DEFAULT_USER_DICTIONARY_FREQUENCY) { return (defaultFrequency / HISTORICAL_DEFAULT_USER_DICTIONARY_FREQUENCY) * LATINIME_DEFAULT_USER_DICTIONARY_FREQUENCY; - } else { - return (defaultFrequency * LATINIME_DEFAULT_USER_DICTIONARY_FREQUENCY) - / HISTORICAL_DEFAULT_USER_DICTIONARY_FREQUENCY; } + return (defaultFrequency * LATINIME_DEFAULT_USER_DICTIONARY_FREQUENCY) + / HISTORICAL_DEFAULT_USER_DICTIONARY_FREQUENCY; } private void addWordsLocked(final Cursor cursor) { @@ -257,12 +256,14 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary { runGCIfRequiredLocked(true /* mindsBlockByGC */); addUnigramLocked(word, adjustedFrequency, null /* shortcutTarget */, 0 /* shortcutFreq */, false /* isNotAWord */, - false /* isBlacklisted */, BinaryDictionary.NOT_A_VALID_TIMESTAMP); + false /* isPossiblyOffensive */, + BinaryDictionary.NOT_A_VALID_TIMESTAMP); if (null != shortcut && shortcut.length() <= MAX_WORD_LENGTH) { runGCIfRequiredLocked(true /* mindsBlockByGC */); addUnigramLocked(shortcut, adjustedFrequency, word, USER_DICT_SHORTCUT_FREQUENCY, true /* isNotAWord */, - false /* isBlacklisted */, BinaryDictionary.NOT_A_VALID_TIMESTAMP); + false /* isPossiblyOffensive */, + BinaryDictionary.NOT_A_VALID_TIMESTAMP); } } cursor.moveToNext(); diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java index 5eb338eb3..8830521c7 100644 --- a/java/src/com/android/inputmethod/latin/WordComposer.java +++ b/java/src/com/android/inputmethod/latin/WordComposer.java @@ -19,6 +19,7 @@ package com.android.inputmethod.latin; import com.android.inputmethod.event.CombinerChain; import com.android.inputmethod.event.Event; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.define.DebugFlags; import com.android.inputmethod.latin.utils.CoordinateUtils; import com.android.inputmethod.latin.utils.StringUtils; @@ -182,7 +183,7 @@ public final class WordComposer { * @return the processed event. Never null, but may be marked as consumed. */ @Nonnull - public Event processEvent(final Event event) { + public Event processEvent(@Nonnull final Event event) { final Event processedEvent = mCombinerChain.processEvent(mEvents, event); // The retained state of the combiner chain may have changed while processing the event, // so we need to update our cache. @@ -353,9 +354,8 @@ public final class WordComposer { if (size() <= 1) { return mCapitalizedMode == CAPS_MODE_AUTO_SHIFT_LOCKED || mCapitalizedMode == CAPS_MODE_MANUAL_SHIFT_LOCKED; - } else { - return mCapsCount == size(); } + return mCapsCount == size(); } public boolean wasShiftedNoLock() { diff --git a/java/src/com/android/inputmethod/latin/debug/ExternalDictionaryGetterForDebug.java b/java/src/com/android/inputmethod/latin/debug/ExternalDictionaryGetterForDebug.java index a87785b1a..d4be0e397 100644 --- a/java/src/com/android/inputmethod/latin/debug/ExternalDictionaryGetterForDebug.java +++ b/java/src/com/android/inputmethod/latin/debug/ExternalDictionaryGetterForDebug.java @@ -44,7 +44,7 @@ import java.util.Locale; * A class to read a local file as a dictionary for debugging purposes. */ public class ExternalDictionaryGetterForDebug { - private static final String SOURCE_FOLDER = Environment.getExternalStorageDirectory().getPath() + static final String SOURCE_FOLDER = Environment.getExternalStorageDirectory().getPath() + "/Download"; private static String[] findDictionariesInTheDownloadedFolder() { @@ -142,8 +142,7 @@ public class ExternalDictionaryGetterForDebug { }).create().show(); } - private static void installFile(final Context context, final File file, - final DictionaryHeader header) { + static void installFile(final Context context, final File file, final DictionaryHeader header) { BufferedOutputStream outputStream = null; File tempFile = null; try { diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java index 5cc61db79..a67f46108 100644 --- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java +++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java @@ -39,7 +39,6 @@ import com.android.inputmethod.keyboard.KeyboardSwitcher; import com.android.inputmethod.keyboard.ProximityInfo; import com.android.inputmethod.keyboard.TextDecorator; import com.android.inputmethod.keyboard.TextDecoratorUiOperator; -import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.Dictionary; import com.android.inputmethod.latin.DictionaryFacilitator; import com.android.inputmethod.latin.InputPointers; @@ -52,6 +51,7 @@ import com.android.inputmethod.latin.Suggest.OnGetSuggestedWordsCallback; 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.Constants; import com.android.inputmethod.latin.define.DebugFlags; import com.android.inputmethod.latin.settings.SettingsValues; import com.android.inputmethod.latin.settings.SettingsValuesForSuggestion; @@ -68,6 +68,8 @@ import java.util.ArrayList; import java.util.TreeSet; import java.util.concurrent.TimeUnit; +import javax.annotation.Nonnull; + /** * This class manages the input logic. */ @@ -75,7 +77,7 @@ public final class InputLogic { private static final String TAG = InputLogic.class.getSimpleName(); // TODO : Remove this member when we can. - private final LatinIME mLatinIME; + final LatinIME mLatinIME; private final SuggestionStripViewAccessor mSuggestionStripViewAccessor; // Never null. @@ -454,8 +456,8 @@ public final class InputLogic { * {@link com.android.inputmethod.keyboard.KeyboardSwitcher#getKeyboardShiftMode()} * @return the complete transaction object */ - public InputTransaction onCodeInput(final SettingsValues settingsValues, final Event event, - final int keyboardShiftMode, + public InputTransaction onCodeInput(final SettingsValues settingsValues, + @Nonnull final Event event, final int keyboardShiftMode, // TODO: remove these arguments final int currentKeyboardScriptId, final LatinIME.UIHandler handler) { final Event processedEvent = mWordComposer.processEvent(event); @@ -1373,7 +1375,7 @@ public final class InputLogic { } private void performAdditionToUserHistoryDictionary(final SettingsValues settingsValues, - final String suggestion, final NgramContext ngramContext) { + final String suggestion, @Nonnull final NgramContext ngramContext) { // If correction is not enabled, we don't add words to the user history dictionary. // That's to avoid unintended additions in some sensitive fields, or fields that // expect to receive non-words. @@ -1512,12 +1514,6 @@ public final class InputLogic { } } final int[] codePoints = StringUtils.toCodePointArray(typedWord); - // We want the context of preceding words for suggestion. If we have chars in the word - // before the cursor, then we want the word before that, hence 2; otherwise, - // we want the word immediately before the cursor, hence 1. - final NgramContext ngramContext = getNgramContextFromNthPreviousWordForSuggestion( - settingsValues.mSpacingAndPunctuations, - 0 == numberOfCharsInWordBeforeCursor ? 1 : 2); mWordComposer.setComposingWord(codePoints, mLatinIME.getCoordinatesForCurrentKeyboard(codePoints)); mWordComposer.setCursorPositionWithinWord( @@ -1533,8 +1529,7 @@ public final class InputLogic { SuggestedWords.NOT_A_SEQUENCE_NUMBER, new OnGetSuggestedWordsCallback() { @Override public void onGetSuggestedWords(final SuggestedWords suggestedWords) { - mIsAutoCorrectionIndicatorOn = false; - mLatinIME.mHandler.showSuggestionStrip(suggestedWords); + doShowSuggestionsAndClearAutoCorrectionIndicator(suggestedWords); }}); } else { // We found suggestion spans in the word. We'll create the SuggestedWords out of @@ -1545,11 +1540,15 @@ public final class InputLogic { null /* rawSuggestions */, typedWord, false /* typedWordValid */, false /* willAutoCorrect */, false /* isObsoleteSuggestions */, SuggestedWords.INPUT_STYLE_RECORRECTION, SuggestedWords.NOT_A_SEQUENCE_NUMBER); - mIsAutoCorrectionIndicatorOn = false; - mLatinIME.mHandler.showSuggestionStrip(suggestedWords); + doShowSuggestionsAndClearAutoCorrectionIndicator(suggestedWords); } } + void doShowSuggestionsAndClearAutoCorrectionIndicator(final SuggestedWords suggestedWords) { + mIsAutoCorrectionIndicatorOn = false; + mLatinIME.mHandler.showSuggestionStrip(suggestedWords); + } + /** * Reverts a previous commit with auto-correction. * @@ -1761,12 +1760,12 @@ public final class InputLogic { // word information from textview. return mConnection.getNgramContextFromNthPreviousWord( spacingAndPunctuations, nthPreviousWord); - } else { - return LastComposedWord.NOT_A_COMPOSED_WORD == mLastComposedWord ? - NgramContext.BEGINNING_OF_SENTENCE : - new NgramContext(new NgramContext.WordInfo( - mLastComposedWord.mCommittedWord.toString())); } + if (LastComposedWord.NOT_A_COMPOSED_WORD == mLastComposedWord) { + return NgramContext.BEGINNING_OF_SENTENCE; + } + return new NgramContext(new NgramContext.WordInfo( + mLastComposedWord.mCommittedWord.toString())); } /** @@ -1819,9 +1818,8 @@ public final class InputLogic { // If no code point, #getCodePointBeforeCursor returns NOT_A_CODE_POINT. if (Constants.CODE_PERIOD == codePointBeforeCursor) { return text.substring(1); - } else { - return text; } + return text; } /** @@ -1877,7 +1875,7 @@ public final class InputLogic { * @param previousSuggestedWords The previously suggested words. * @return Obsolete suggestions with the newly typed word. */ - private SuggestedWords retrieveOlderSuggestions(final String typedWord, + static SuggestedWords retrieveOlderSuggestions(final String typedWord, final SuggestedWords previousSuggestedWords) { final SuggestedWords oldSuggestedWords = previousSuggestedWords.isPunctuationSuggestions() ? SuggestedWords.getEmptyInstance() : previousSuggestedWords; @@ -2305,7 +2303,7 @@ public final class InputLogic { * Sets the UI operator for {@link TextDecorator}. * @param uiOperator the UI operator which should be associated with {@link TextDecorator}. */ - public void setTextDecoratorUi(final TextDecoratorUiOperator uiOperator) { + public void setTextDecoratorUi(@Nonnull final TextDecoratorUiOperator uiOperator) { mTextDecorator.setUiOperator(uiOperator); } diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java index c6f83d0b9..5f391dd9b 100644 --- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java +++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java @@ -23,7 +23,6 @@ import android.os.Message; import com.android.inputmethod.compat.LooperCompatUtils; import com.android.inputmethod.latin.InputPointers; import com.android.inputmethod.latin.LatinIME; -import com.android.inputmethod.latin.Suggest; import com.android.inputmethod.latin.SuggestedWords; import com.android.inputmethod.latin.Suggest.OnGetSuggestedWordsCallback; @@ -62,7 +61,7 @@ class InputLogicHandler implements Handler.Callback { final OnGetSuggestedWordsCallback callback) {} }; - private InputLogicHandler() { + InputLogicHandler() { mNonUIThreadHandler = null; mLatinIME = null; mInputLogic = null; @@ -134,30 +133,38 @@ class InputLogicHandler implements Handler.Callback { return; } mInputLogic.mWordComposer.setBatchInputPointers(batchPointers); + final OnGetSuggestedWordsCallback callback = new OnGetSuggestedWordsCallback() { + @Override + public void onGetSuggestedWords(final SuggestedWords suggestedWords) { + showGestureSuggestionsWithPreviewVisuals(suggestedWords, isTailBatchInput); + } + }; getSuggestedWords(isTailBatchInput ? SuggestedWords.INPUT_STYLE_TAIL_BATCH - : SuggestedWords.INPUT_STYLE_UPDATE_BATCH, sequenceNumber, - new OnGetSuggestedWordsCallback() { - @Override - public void onGetSuggestedWords(SuggestedWords suggestedWords) { - // We're now inside the callback. This always runs on the Non-UI thread, - // no matter what thread updateBatchInput was originally called on. - if (suggestedWords.isEmpty()) { - // Use old suggestions if we don't have any new ones. - // Previous suggestions are found in InputLogic#mSuggestedWords. - // Since these are the most recent ones and we just recomputed - // new ones to update them, then the previous ones are there. - suggestedWords = mInputLogic.mSuggestedWords; - } - mLatinIME.mHandler.showGesturePreviewAndSuggestionStrip(suggestedWords, - isTailBatchInput /* dismissGestureFloatingPreviewText */); - if (isTailBatchInput) { - mInBatchInput = false; - // The following call schedules onEndBatchInputInternal - // to be called on the UI thread. - mLatinIME.mHandler.showTailBatchInputResult(suggestedWords); - } - } - }); + : SuggestedWords.INPUT_STYLE_UPDATE_BATCH, sequenceNumber, callback); + } + } + + void showGestureSuggestionsWithPreviewVisuals(final SuggestedWords suggestedWordsForBatchInput, + final boolean isTailBatchInput) { + final SuggestedWords suggestedWordsToShowSuggestions; + // We're now inside the callback. This always runs on the Non-UI thread, + // no matter what thread updateBatchInput was originally called on. + if (suggestedWordsForBatchInput.isEmpty()) { + // Use old suggestions if we don't have any new ones. + // Previous suggestions are found in InputLogic#mSuggestedWords. + // Since these are the most recent ones and we just recomputed + // new ones to update them, then the previous ones are there. + suggestedWordsToShowSuggestions = mInputLogic.mSuggestedWords; + } else { + suggestedWordsToShowSuggestions = suggestedWordsForBatchInput; + } + mLatinIME.mHandler.showGesturePreviewAndSuggestionStrip(suggestedWordsToShowSuggestions, + isTailBatchInput /* dismissGestureFloatingPreviewText */); + if (isTailBatchInput) { + mInBatchInput = false; + // The following call schedules onEndBatchInputInternal + // to be called on the UI thread. + mLatinIME.mHandler.showTailBatchInputResult(suggestedWordsToShowSuggestions); } } diff --git a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java index 34edfa0da..78d79ae50 100644 --- a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java +++ b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java @@ -17,7 +17,7 @@ package com.android.inputmethod.latin.makedict; import com.android.inputmethod.annotations.UsedForTesting; -import com.android.inputmethod.latin.Constants; +import com.android.inputmethod.latin.common.Constants; import java.util.Date; import java.util.HashMap; @@ -93,7 +93,7 @@ public final class FormatSpec { * s | has shortcut targets ? 1 bit, 1 = yes, 0 = no : FLAG_HAS_SHORTCUT_TARGETS * | has bigrams ? 1 bit, 1 = yes, 0 = no : FLAG_HAS_BIGRAMS * | is not a word ? 1 bit, 1 = yes, 0 = no : FLAG_IS_NOT_A_WORD - * | is blacklisted ? 1 bit, 1 = yes, 0 = no : FLAG_IS_BLACKLISTED + * | is possibly offensive ? 1 bit, 1 = yes, 0 = no : FLAG_IS_POSSIBLY_OFFENSIVE * * c | IF FLAG_HAS_MULTIPLE_CHARS * h | char, char, char, char n * (1 or 3 bytes) : use PtNodeInfo for i/o helpers @@ -197,7 +197,7 @@ public final class FormatSpec { static final int FLAG_HAS_SHORTCUT_TARGETS = 0x08; static final int FLAG_HAS_BIGRAMS = 0x04; static final int FLAG_IS_NOT_A_WORD = 0x02; - static final int FLAG_IS_BLACKLISTED = 0x01; + static final int FLAG_IS_POSSIBLY_OFFENSIVE = 0x01; static final int FLAG_BIGRAM_SHORTCUT_ATTR_HAS_NEXT = 0x80; static final int FLAG_BIGRAM_ATTR_OFFSET_NEGATIVE = 0x40; diff --git a/java/src/com/android/inputmethod/latin/makedict/NgramProperty.java b/java/src/com/android/inputmethod/latin/makedict/NgramProperty.java index 99e0e273f..b1d19dc3c 100644 --- a/java/src/com/android/inputmethod/latin/makedict/NgramProperty.java +++ b/java/src/com/android/inputmethod/latin/makedict/NgramProperty.java @@ -1,3 +1,19 @@ +/* + * Copyright (C) 2014 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.makedict; import com.android.inputmethod.latin.NgramContext; diff --git a/java/src/com/android/inputmethod/latin/makedict/ProbabilityInfo.java b/java/src/com/android/inputmethod/latin/makedict/ProbabilityInfo.java index 5fcbb6357..03c2ece1d 100644 --- a/java/src/com/android/inputmethod/latin/makedict/ProbabilityInfo.java +++ b/java/src/com/android/inputmethod/latin/makedict/ProbabilityInfo.java @@ -40,11 +40,8 @@ public final class ProbabilityInfo { if (probabilityInfo2 == null) { return probabilityInfo1; } - if (probabilityInfo1.mProbability > probabilityInfo2.mProbability) { - return probabilityInfo1; - } else { - return probabilityInfo2; - } + return (probabilityInfo1.mProbability > probabilityInfo2.mProbability) ? probabilityInfo1 + : probabilityInfo2; } public ProbabilityInfo(final int probability) { @@ -67,9 +64,8 @@ public final class ProbabilityInfo { public int hashCode() { if (hasHistoricalInfo()) { return Arrays.hashCode(new Object[] { mProbability, mTimestamp, mLevel, mCount }); - } else { - return Arrays.hashCode(new Object[] { mProbability }); } + return Arrays.hashCode(new Object[] { mProbability }); } @Override diff --git a/java/src/com/android/inputmethod/latin/makedict/WordProperty.java b/java/src/com/android/inputmethod/latin/makedict/WordProperty.java index 1e6cadf03..e7808e46e 100644 --- a/java/src/com/android/inputmethod/latin/makedict/WordProperty.java +++ b/java/src/com/android/inputmethod/latin/makedict/WordProperty.java @@ -18,6 +18,7 @@ package com.android.inputmethod.latin.makedict; import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.latin.BinaryDictionary; +import com.android.inputmethod.latin.Dictionary; import com.android.inputmethod.latin.NgramContext; import com.android.inputmethod.latin.NgramContext.WordInfo; import com.android.inputmethod.latin.utils.CombinedFormatUtils; @@ -41,7 +42,7 @@ public final class WordProperty implements Comparable<WordProperty> { // TODO: Support mIsBeginningOfSentence. public final boolean mIsBeginningOfSentence; public final boolean mIsNotAWord; - public final boolean mIsBlacklistEntry; + public final boolean mIsPossiblyOffensive; public final boolean mHasShortcuts; public final boolean mHasNgrams; @@ -52,7 +53,7 @@ public final class WordProperty implements Comparable<WordProperty> { public WordProperty(final String word, final ProbabilityInfo probabilityInfo, final ArrayList<WeightedString> shortcutTargets, @Nullable final ArrayList<WeightedString> bigrams, - final boolean isNotAWord, final boolean isBlacklistEntry) { + final boolean isNotAWord, final boolean isPossiblyOffensive) { mWord = word; mProbabilityInfo = probabilityInfo; mShortcutTargets = shortcutTargets; @@ -61,15 +62,13 @@ public final class WordProperty implements Comparable<WordProperty> { } else { mNgrams = new ArrayList<>(); final NgramContext ngramContext = new NgramContext(new WordInfo(mWord)); - if (bigrams != null) { - for (final WeightedString bigramTarget : bigrams) { - mNgrams.add(new NgramProperty(bigramTarget, ngramContext)); - } + for (final WeightedString bigramTarget : bigrams) { + mNgrams.add(new NgramProperty(bigramTarget, ngramContext)); } } mIsBeginningOfSentence = false; mIsNotAWord = isNotAWord; - mIsBlacklistEntry = isBlacklistEntry; + mIsPossiblyOffensive = isPossiblyOffensive; mHasNgrams = bigrams != null && !bigrams.isEmpty(); mHasShortcuts = shortcutTargets != null && !shortcutTargets.isEmpty(); } @@ -85,10 +84,10 @@ public final class WordProperty implements Comparable<WordProperty> { // Construct word property using information from native code. // This represents invalid word when the probability is BinaryDictionary.NOT_A_PROBABILITY. public WordProperty(final int[] codePoints, final boolean isNotAWord, - final boolean isBlacklisted, final boolean hasBigram, final boolean hasShortcuts, + final boolean isPossiblyOffensive, final boolean hasBigram, final boolean hasShortcuts, final boolean isBeginningOfSentence, final int[] probabilityInfo, final ArrayList<int[][]> ngramPrevWordsArray, - final ArrayList<boolean[]> outNgramPrevWordIsBeginningOfSentenceArray, + final ArrayList<boolean[]> ngramPrevWordIsBeginningOfSentenceArray, final ArrayList<int[]> ngramTargets, final ArrayList<int[]> ngramProbabilityInfo, final ArrayList<int[]> shortcutTargets, final ArrayList<Integer> shortcutProbabilities) { @@ -98,20 +97,27 @@ public final class WordProperty implements Comparable<WordProperty> { final ArrayList<NgramProperty> ngrams = new ArrayList<>(); mIsBeginningOfSentence = isBeginningOfSentence; mIsNotAWord = isNotAWord; - mIsBlacklistEntry = isBlacklisted; + mIsPossiblyOffensive = isPossiblyOffensive; mHasShortcuts = hasShortcuts; mHasNgrams = hasBigram; final int relatedNgramCount = ngramTargets.size(); - final WordInfo currentWordInfo = - mIsBeginningOfSentence ? WordInfo.BEGINNING_OF_SENTENCE : new WordInfo(mWord); - final NgramContext ngramContext = new NgramContext(currentWordInfo); for (int i = 0; i < relatedNgramCount; i++) { final String ngramTargetString = StringUtils.getStringFromNullTerminatedCodePointArray(ngramTargets.get(i)); final WeightedString ngramTarget = new WeightedString(ngramTargetString, createProbabilityInfoFromArray(ngramProbabilityInfo.get(i))); - // TODO: Support n-gram. + final int[][] prevWords = ngramPrevWordsArray.get(i); + final boolean[] isBeginningOfSentenceArray = + ngramPrevWordIsBeginningOfSentenceArray.get(i); + final WordInfo[] wordInfoArray = new WordInfo[prevWords.length]; + for (int j = 0; j < prevWords.length; j++) { + wordInfoArray[j] = isBeginningOfSentenceArray[j] + ? WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO + : new WordInfo(StringUtils.getStringFromNullTerminatedCodePointArray( + prevWords[j])); + } + final NgramContext ngramContext = new NgramContext(wordInfoArray); ngrams.add(new NgramProperty(ngramTarget, ngramContext)); } mNgrams = ngrams.isEmpty() ? null : ngrams; @@ -126,6 +132,7 @@ public final class WordProperty implements Comparable<WordProperty> { } // TODO: Remove + @UsedForTesting public ArrayList<WeightedString> getBigrams() { if (null == mNgrams) { return null; @@ -150,7 +157,7 @@ public final class WordProperty implements Comparable<WordProperty> { word.mShortcutTargets, word.mNgrams, word.mIsNotAWord, - word.mIsBlacklistEntry + word.mIsPossiblyOffensive }); } @@ -180,7 +187,7 @@ public final class WordProperty implements Comparable<WordProperty> { WordProperty w = (WordProperty)o; return mProbabilityInfo.equals(w.mProbabilityInfo) && mWord.equals(w.mWord) && mShortcutTargets.equals(w.mShortcutTargets) && equals(mNgrams, w.mNgrams) - && mIsNotAWord == w.mIsNotAWord && mIsBlacklistEntry == w.mIsBlacklistEntry + && mIsNotAWord == w.mIsNotAWord && mIsPossiblyOffensive == w.mIsPossiblyOffensive && mHasNgrams == w.mHasNgrams && mHasShortcuts && w.mHasNgrams; } @@ -202,7 +209,7 @@ public final class WordProperty implements Comparable<WordProperty> { @UsedForTesting public boolean isValid() { - return getProbability() != BinaryDictionary.NOT_A_PROBABILITY; + return getProbability() != Dictionary.NOT_A_PROBABILITY; } @Override diff --git a/java/src/com/android/inputmethod/latin/network/BlockingHttpClient.java b/java/src/com/android/inputmethod/latin/network/BlockingHttpClient.java index e2d24fd0a..079d07eac 100644 --- a/java/src/com/android/inputmethod/latin/network/BlockingHttpClient.java +++ b/java/src/com/android/inputmethod/latin/network/BlockingHttpClient.java @@ -85,12 +85,11 @@ public class BlockingHttpClient { throw new AuthException(mConnection.getResponseMessage()); } throw new HttpException(responseCode); - } else { - if (DEBUG) { - Log.d(TAG, "request executed successfully"); - } - return responseProcessor.onSuccess(mConnection.getInputStream()); } + if (DEBUG) { + Log.d(TAG, "request executed successfully"); + } + return responseProcessor.onSuccess(mConnection.getInputStream()); } finally { mConnection.disconnect(); } diff --git a/java/src/com/android/inputmethod/latin/network/HttpUrlConnectionBuilder.java b/java/src/com/android/inputmethod/latin/network/HttpUrlConnectionBuilder.java index 502f72f17..df54bf464 100644 --- a/java/src/com/android/inputmethod/latin/network/HttpUrlConnectionBuilder.java +++ b/java/src/com/android/inputmethod/latin/network/HttpUrlConnectionBuilder.java @@ -95,7 +95,7 @@ public class HttpUrlConnectionBuilder { } /** - * Sets the connect timeout. Defaults to {@value #DEFAULT_TIMEOUT} milliseconds. + * Sets the connect timeout. Defaults to {@value #DEFAULT_TIMEOUT_MILLIS} milliseconds. * * TODO: Remove @UsedForTesting after this method is actually used. */ @@ -110,7 +110,7 @@ public class HttpUrlConnectionBuilder { } /** - * Sets the read timeout. Defaults to {@value #DEFAULT_TIMEOUT} milliseconds. + * Sets the read timeout. Defaults to {@value #DEFAULT_TIMEOUT_MILLIS} milliseconds. * * TODO: Remove @UsedForTesting after this method is actually used. */ diff --git a/java/src/com/android/inputmethod/latin/personalization/ContextualDictionary.java b/java/src/com/android/inputmethod/latin/personalization/ContextualDictionary.java index ac55b9333..39d9596ef 100644 --- a/java/src/com/android/inputmethod/latin/personalization/ContextualDictionary.java +++ b/java/src/com/android/inputmethod/latin/personalization/ContextualDictionary.java @@ -18,7 +18,7 @@ package com.android.inputmethod.latin.personalization; import android.content.Context; -import com.android.inputmethod.annotations.UsedForTesting; +import com.android.inputmethod.annotations.ExternallyReferenced; import com.android.inputmethod.latin.Dictionary; import com.android.inputmethod.latin.ExpandableBinaryDictionary; @@ -36,7 +36,9 @@ public class ContextualDictionary extends ExpandableBinaryDictionary { clear(); } - @UsedForTesting + // Note: This method is called by {@link DictionaryFacilitator} using Java reflection. + @SuppressWarnings("unused") + @ExternallyReferenced public static ContextualDictionary getDictionary(final Context context, final Locale locale, final File dictFile, final String dictNamePrefix) { return new ContextualDictionary(context, locale, dictFile); diff --git a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java index 1ba7b366f..78b51d9f4 100644 --- a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java +++ b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java @@ -39,14 +39,10 @@ public abstract class DecayingExpandableBinaryDictionaryBase extends ExpandableB 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; - /** The locale for this dictionary. */ - public final Locale mLocale; - protected DecayingExpandableBinaryDictionaryBase(final Context context, final String dictName, final Locale locale, final String dictionaryType, final File dictFile) { super(context, dictName, locale, dictionaryType, dictFile); - mLocale = locale; if (mLocale != null && mLocale.toString().length() > 1) { reloadDictionaryIfRequired(); } diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java index f2ad22ac7..33d1273f7 100644 --- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java +++ b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java @@ -18,7 +18,7 @@ package com.android.inputmethod.latin.personalization; import android.content.Context; -import com.android.inputmethod.annotations.UsedForTesting; +import com.android.inputmethod.annotations.ExternallyReferenced; import com.android.inputmethod.latin.Dictionary; import java.io.File; @@ -33,7 +33,9 @@ public class PersonalizationDictionary extends DecayingExpandableBinaryDictionar Dictionary.TYPE_PERSONALIZATION, null /* dictFile */); } - @UsedForTesting + // Note: This method is called by {@link DictionaryFacilitator} using Java reflection. + @SuppressWarnings("unused") + @ExternallyReferenced public static PersonalizationDictionary getDictionary(final Context context, final Locale locale, final File dictFile, final String dictNamePrefix) { return PersonalizationHelper.getPersonalizationDictionary(context, locale); diff --git a/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java b/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java index 59761547d..58782c646 100644 --- a/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java +++ b/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java @@ -17,25 +17,25 @@ package com.android.inputmethod.latin.personalization; import android.content.Context; -import android.text.TextUtils; -import com.android.inputmethod.annotations.UsedForTesting; -import com.android.inputmethod.latin.Constants; +import com.android.inputmethod.annotations.ExternallyReferenced; import com.android.inputmethod.latin.Dictionary; import com.android.inputmethod.latin.ExpandableBinaryDictionary; import com.android.inputmethod.latin.NgramContext; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.utils.DistracterFilter; import java.io.File; import java.util.Locale; +import javax.annotation.Nonnull; + /** * Locally gathers stats about the words user types and various other signals like auto-correction * cancellation or manual picks. This allows the keyboard to adapt to the typist over time. */ public class UserHistoryDictionary extends DecayingExpandableBinaryDictionaryBase { /* package */ static final String NAME = UserHistoryDictionary.class.getSimpleName(); - private final static int SUPPORTED_NGRAM = 2; // TODO: 3 // TODO: Make this constructor private /* package */ UserHistoryDictionary(final Context context, final Locale locale) { @@ -43,7 +43,9 @@ public class UserHistoryDictionary extends DecayingExpandableBinaryDictionaryBas Dictionary.TYPE_USER_HISTORY, null /* dictFile */); } - @UsedForTesting + // Note: This method is called by {@link DictionaryFacilitator} using Java reflection. + @SuppressWarnings("unused") + @ExternallyReferenced public static UserHistoryDictionary getDictionary(final Context context, final Locale locale, final File dictFile, final String dictNamePrefix) { return PersonalizationHelper.getUserHistoryDictionary(context, locale); @@ -60,8 +62,8 @@ public class UserHistoryDictionary extends DecayingExpandableBinaryDictionaryBas * @param distracterFilter the filter to check whether the word is a distracter */ public static void addToDictionary(final ExpandableBinaryDictionary userHistoryDictionary, - final NgramContext ngramContext, final String word, final boolean isValid, - final int timestamp, final DistracterFilter distracterFilter) { + @Nonnull final NgramContext ngramContext, final String word, final boolean isValid, + final int timestamp, @Nonnull final DistracterFilter distracterFilter) { if (word.length() > Constants.DICTIONARY_MAX_WORD_LENGTH) { return; } diff --git a/java/src/com/android/inputmethod/latin/settings/CustomInputStylePreference.java b/java/src/com/android/inputmethod/latin/settings/CustomInputStylePreference.java index c07b60a0b..01398f467 100644 --- a/java/src/com/android/inputmethod/latin/settings/CustomInputStylePreference.java +++ b/java/src/com/android/inputmethod/latin/settings/CustomInputStylePreference.java @@ -259,6 +259,7 @@ final class CustomInputStylePreference extends DialogPreference mSubtype = (InputMethodSubtype)source.readParcelable(null); } + @SuppressWarnings("hiding") public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() { @Override diff --git a/java/src/com/android/inputmethod/latin/settings/DebugSettings.java b/java/src/com/android/inputmethod/latin/settings/DebugSettings.java index 768cba9b2..4985c2f08 100644 --- a/java/src/com/android/inputmethod/latin/settings/DebugSettings.java +++ b/java/src/com/android/inputmethod/latin/settings/DebugSettings.java @@ -27,8 +27,6 @@ package com.android.inputmethod.latin.settings; public final class DebugSettings { public static final String PREF_DEBUG_MODE = "debug_mode"; public static final String PREF_FORCE_NON_DISTINCT_MULTITOUCH = "force_non_distinct_multitouch"; - public static final String PREF_FORCE_PHYSICAL_KEYBOARD_SPECIAL_KEY = - "force_physical_keyboard_special_key"; public static final String PREF_HAS_CUSTOM_KEY_PREVIEW_ANIMATION_PARAMS = "pref_has_custom_key_preview_animation_params"; public static final String PREF_KEY_PREVIEW_DISMISS_DURATION = diff --git a/java/src/com/android/inputmethod/latin/settings/DebugSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/DebugSettingsFragment.java index 475f1def7..2e5c3c479 100644 --- a/java/src/com/android/inputmethod/latin/settings/DebugSettingsFragment.java +++ b/java/src/com/android/inputmethod/latin/settings/DebugSettingsFragment.java @@ -142,8 +142,7 @@ public final class DebugSettingsFragment extends SubScreenFragment mServiceNeedsRestart = true; return; } - if (key.equals(DebugSettings.PREF_FORCE_NON_DISTINCT_MULTITOUCH) - || key.equals(DebugSettings.PREF_FORCE_PHYSICAL_KEYBOARD_SPECIAL_KEY)) { + if (key.equals(DebugSettings.PREF_FORCE_NON_DISTINCT_MULTITOUCH)) { mServiceNeedsRestart = true; return; } diff --git a/java/src/com/android/inputmethod/latin/settings/GestureSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/GestureSettingsFragment.java index 832fbf65a..22b0655b4 100644 --- a/java/src/com/android/inputmethod/latin/settings/GestureSettingsFragment.java +++ b/java/src/com/android/inputmethod/latin/settings/GestureSettingsFragment.java @@ -16,7 +16,6 @@ package com.android.inputmethod.latin.settings; -import android.content.SharedPreferences; import android.os.Bundle; import com.android.inputmethod.latin.R; diff --git a/java/src/com/android/inputmethod/latin/settings/LocalSettingsConstants.java b/java/src/com/android/inputmethod/latin/settings/LocalSettingsConstants.java index c9e9dc8d9..0fd94b0f8 100644 --- a/java/src/com/android/inputmethod/latin/settings/LocalSettingsConstants.java +++ b/java/src/com/android/inputmethod/latin/settings/LocalSettingsConstants.java @@ -46,7 +46,6 @@ public class LocalSettingsConstants { // correctly set for it to work on a new device. DebugSettings.PREF_DEBUG_MODE, DebugSettings.PREF_FORCE_NON_DISTINCT_MULTITOUCH, - DebugSettings.PREF_FORCE_PHYSICAL_KEYBOARD_SPECIAL_KEY, DebugSettings.PREF_HAS_CUSTOM_KEY_PREVIEW_ANIMATION_PARAMS, DebugSettings.PREF_KEY_PREVIEW_DISMISS_DURATION, DebugSettings.PREF_KEY_PREVIEW_DISMISS_END_X_SCALE, diff --git a/java/src/com/android/inputmethod/latin/settings/MultiLingualSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/MultiLingualSettingsFragment.java index b71f8829b..c5930db1e 100644 --- a/java/src/com/android/inputmethod/latin/settings/MultiLingualSettingsFragment.java +++ b/java/src/com/android/inputmethod/latin/settings/MultiLingualSettingsFragment.java @@ -20,8 +20,6 @@ import android.os.Bundle; import com.android.inputmethod.latin.R; -import java.util.ArrayList; - /** * "Multilingual options" settings sub screen. * diff --git a/java/src/com/android/inputmethod/latin/settings/RadioButtonPreference.java b/java/src/com/android/inputmethod/latin/settings/RadioButtonPreference.java index c173d4706..91444604d 100644 --- a/java/src/com/android/inputmethod/latin/settings/RadioButtonPreference.java +++ b/java/src/com/android/inputmethod/latin/settings/RadioButtonPreference.java @@ -43,9 +43,7 @@ public class RadioButtonPreference extends Preference { private final View.OnClickListener mClickListener = new View.OnClickListener() { @Override public void onClick(final View v) { - if (mListener != null) { - mListener.onRadioButtonClicked(RadioButtonPreference.this); - } + callListenerOnRadioButtonClicked(); } }; @@ -67,6 +65,12 @@ public class RadioButtonPreference extends Preference { mListener = listener; } + void callListenerOnRadioButtonClicked() { + if (mListener != null) { + mListener.onRadioButtonClicked(this); + } + } + @Override protected void onBindView(final View view) { super.onBindView(view); diff --git a/java/src/com/android/inputmethod/latin/settings/Settings.java b/java/src/com/android/inputmethod/latin/settings/Settings.java index 391fc1982..2ac6e8576 100644 --- a/java/src/com/android/inputmethod/latin/settings/Settings.java +++ b/java/src/com/android/inputmethod/latin/settings/Settings.java @@ -40,6 +40,8 @@ import java.util.Locale; import java.util.Set; import java.util.concurrent.locks.ReentrantLock; +import javax.annotation.Nonnull; + public final class Settings implements SharedPreferences.OnSharedPreferenceChangeListener { private static final String TAG = Settings.class.getSimpleName(); // Settings screens @@ -78,7 +80,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang public static final boolean ENABLE_SHOW_LANGUAGE_SWITCH_KEY_SETTINGS = BuildCompatUtils.EFFECTIVE_SDK_INT <= Build.VERSION_CODES.KITKAT; public static final boolean SHOULD_SHOW_LXX_SUGGESTION_UI = - BuildCompatUtils.EFFECTIVE_SDK_INT >= BuildCompatUtils.VERSION_CODES_LXX; + BuildCompatUtils.EFFECTIVE_SDK_INT >= Build.VERSION_CODES.LOLLIPOP; public static final String PREF_SHOW_LANGUAGE_SWITCH_KEY = "pref_show_language_switch_key"; public static final String PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST = @@ -95,6 +97,8 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang "pref_vibration_duration_settings"; public static final String PREF_KEYPRESS_SOUND_VOLUME = "pref_keypress_sound_volume"; public static final String PREF_KEY_LONGPRESS_TIMEOUT = "pref_key_longpress_timeout"; + public static final String PREF_ENABLE_EMOJI_ALT_PHYSICAL_KEY = + "pref_enable_emoji_alt_physical_key"; public static final String PREF_GESTURE_PREVIEW_TRAIL = "pref_gesture_preview_trail"; public static final String PREF_GESTURE_FLOATING_PREVIEW_TEXT = "pref_gesture_floating_preview_text"; @@ -175,7 +179,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang } public void loadSettings(final Context context, final Locale locale, - final InputAttributes inputAttributes) { + @Nonnull final InputAttributes inputAttributes) { mSettingsValuesLock.lock(); mContext = context; try { diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java index 660b4e095..e488cb10c 100644 --- a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java +++ b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java @@ -25,11 +25,11 @@ import android.util.Log; import android.view.inputmethod.EditorInfo; import com.android.inputmethod.compat.AppWorkaroundsUtils; -import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.InputAttributes; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.RichInputMethodManager; import com.android.inputmethod.latin.SubtypeSwitcher; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.utils.AsyncResultHolder; import com.android.inputmethod.latin.utils.ResourceUtils; import com.android.inputmethod.latin.utils.TargetPackageInfoGetterTask; @@ -37,6 +37,8 @@ import com.android.inputmethod.latin.utils.TargetPackageInfoGetterTask; import java.util.Arrays; import java.util.Locale; +import javax.annotation.Nonnull; + /** * When you call the constructor of this class, you may want to change the current system locale by * using {@link com.android.inputmethod.latin.utils.RunInLocale}. @@ -78,6 +80,7 @@ public class SettingsValues { public final boolean mSlidingKeyInputPreviewEnabled; public final boolean mPhraseGestureEnabled; public final int mKeyLongpressTimeout; + public final boolean mEnableEmojiAltPhysicalKey; public final boolean mEnableMetricsLogging; public final boolean mShouldShowLxxSuggestionUi; // Use split layout for keyboard. @@ -85,6 +88,7 @@ public class SettingsValues { public final int mScreenMetrics; // From the input box + @Nonnull public final InputAttributes mInputAttributes; // Deduced settings @@ -115,7 +119,7 @@ public class SettingsValues { public final float mKeyPreviewDismissEndYScale; public SettingsValues(final Context context, final SharedPreferences prefs, final Resources res, - final InputAttributes inputAttributes) { + @Nonnull final InputAttributes inputAttributes) { mLocale = res.getConfiguration().locale; // Get the resources mDelayInMillisecondsToUpdateOldSuggestions = @@ -123,12 +127,7 @@ public class SettingsValues { mSpacingAndPunctuations = new SpacingAndPunctuations(res); // Store the input attributes - if (null == inputAttributes) { - mInputAttributes = new InputAttributes( - null, false /* isFullscreenMode */, context.getPackageName()); - } else { - mInputAttributes = inputAttributes; - } + mInputAttributes = inputAttributes; // Get the settings preferences mAutoCap = prefs.getBoolean(Settings.PREF_AUTO_CAP, true); @@ -168,6 +167,8 @@ public class SettingsValues { mKeypressVibrationDuration = Settings.readKeypressVibrationDuration(prefs, res); mKeypressSoundVolume = Settings.readKeypressSoundVolume(prefs, res); mKeyPreviewPopupDismissDelay = Settings.readKeyPreviewPopupDismissDelay(prefs, res); + mEnableEmojiAltPhysicalKey = prefs.getBoolean( + Settings.PREF_ENABLE_EMOJI_ALT_PHYSICAL_KEY, true); mAutoCorrectionThreshold = readAutoCorrectionThreshold(res, autoCorrectionThresholdRawValue); mGestureInputEnabled = Settings.readGestureInputEnabled(prefs, res); @@ -273,9 +274,8 @@ public class SettingsValues { final RichInputMethodManager imm = RichInputMethodManager.getInstance(); if (mIncludesOtherImesInLanguageSwitchList) { return imm.hasMultipleEnabledIMEsOrSubtypes(false /* include aux subtypes */); - } else { - return imm.hasMultipleEnabledSubtypesInThisIme(false /* include aux subtypes */); } + return imm.hasMultipleEnabledSubtypesInThisIme(false /* include aux subtypes */); } public boolean isSameInputType(final EditorInfo editorInfo) { diff --git a/java/src/com/android/inputmethod/latin/settings/SpacingAndPunctuations.java b/java/src/com/android/inputmethod/latin/settings/SpacingAndPunctuations.java index 97aad3b6d..46aef89c4 100644 --- a/java/src/com/android/inputmethod/latin/settings/SpacingAndPunctuations.java +++ b/java/src/com/android/inputmethod/latin/settings/SpacingAndPunctuations.java @@ -20,9 +20,9 @@ import android.content.res.Resources; import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.keyboard.internal.MoreKeySpec; -import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.PunctuationSuggestions; import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.utils.StringUtils; import java.util.Arrays; diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java index 2a4e14ca7..315e3696b 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java @@ -50,13 +50,10 @@ import java.util.concurrent.Semaphore; */ public final class AndroidSpellCheckerService extends SpellCheckerService implements SharedPreferences.OnSharedPreferenceChangeListener { - private static final String TAG = AndroidSpellCheckerService.class.getSimpleName(); - private static final boolean DBG = false; - public static final String PREF_USE_CONTACTS_KEY = "pref_spellcheck_use_contacts"; private static final int SPELLCHECKER_DUMMY_KEYBOARD_WIDTH = 480; - private static final int SPELLCHECKER_DUMMY_KEYBOARD_HEIGHT = 368; + private static final int SPELLCHECKER_DUMMY_KEYBOARD_HEIGHT = 301; private static final String DICTIONARY_NAME_PREFIX = "spellcheck_"; diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerSession.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerSession.java index 8393b306c..ac395bf02 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerSession.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerSession.java @@ -16,8 +16,10 @@ package com.android.inputmethod.latin.spellcheck; +import android.annotation.TargetApi; import android.content.res.Resources; import android.os.Binder; +import android.os.Build; import android.text.TextUtils; import android.util.Log; import android.view.textservice.SentenceSuggestionsInfo; @@ -42,6 +44,7 @@ public final class AndroidSpellCheckerSession extends AndroidWordLevelSpellCheck mResources = service.getResources(); } + @TargetApi(Build.VERSION_CODES.JELLY_BEAN) private SentenceSuggestionsInfo fixWronglyInvalidatedWordWithSingleQuote(TextInfo ti, SentenceSuggestionsInfo ssi) { final CharSequence typedText = TextInfoCompatUtils.getCharSequenceOrString(ti); @@ -149,7 +152,7 @@ public final class AndroidSpellCheckerSession extends AndroidWordLevelSpellCheck * @param textInfos an array of the text metadata * @param suggestionsLimit the maximum number of suggestions to be returned * @return an array of {@link SentenceSuggestionsInfo} returned by - * {@link SpellCheckerService.Session#onGetSuggestions(TextInfo, int)} + * {@link android.service.textservice.SpellCheckerService.Session#onGetSuggestions(TextInfo, int)} */ private SentenceSuggestionsInfo[] splitAndSuggest(TextInfo[] textInfos, int suggestionsLimit) { if (textInfos == null || textInfos.length == 0) { diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java index 7b6aacd15..514bfca85 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java @@ -30,10 +30,10 @@ import android.view.textservice.TextInfo; import com.android.inputmethod.compat.SuggestionsInfoCompatUtils; import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.ProximityInfo; -import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.NgramContext; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import com.android.inputmethod.latin.WordComposer; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.utils.BinaryDictionaryUtils; import com.android.inputmethod.latin.utils.CoordinateUtils; import com.android.inputmethod.latin.utils.LocaleUtils; @@ -312,11 +312,10 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session { // Don't kill the keyboard if there is a bug in the spell checker if (DBG) { throw e; - } else { - Log.e(TAG, "Exception while spellcheking", e); - return AndroidSpellCheckerService.getNotInDictEmptySuggestions( - false /* reportAsTypo */); } + Log.e(TAG, "Exception while spellcheking", e); + return AndroidSpellCheckerService.getNotInDictEmptySuggestions( + false /* reportAsTypo */); } } diff --git a/java/src/com/android/inputmethod/latin/spellcheck/SentenceLevelAdapter.java b/java/src/com/android/inputmethod/latin/spellcheck/SentenceLevelAdapter.java index 9ddee8629..10c458c7d 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/SentenceLevelAdapter.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/SentenceLevelAdapter.java @@ -16,13 +16,15 @@ package com.android.inputmethod.latin.spellcheck; +import android.annotation.TargetApi; import android.content.res.Resources; +import android.os.Build; import android.view.textservice.SentenceSuggestionsInfo; import android.view.textservice.SuggestionsInfo; import android.view.textservice.TextInfo; import com.android.inputmethod.compat.TextInfoCompatUtils; -import com.android.inputmethod.latin.Constants; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.settings.SpacingAndPunctuations; import com.android.inputmethod.latin.utils.RunInLocale; @@ -76,19 +78,19 @@ public class SentenceLevelAdapter { private static class WordIterator { private final SpacingAndPunctuations mSpacingAndPunctuations; public WordIterator(final Resources res, final Locale locale) { - final RunInLocale<SpacingAndPunctuations> job - = new RunInLocale<SpacingAndPunctuations>() { + final RunInLocale<SpacingAndPunctuations> job = + new RunInLocale<SpacingAndPunctuations>() { @Override - protected SpacingAndPunctuations job(final Resources res) { - return new SpacingAndPunctuations(res); + protected SpacingAndPunctuations job(final Resources r) { + return new SpacingAndPunctuations(r); } }; mSpacingAndPunctuations = job.runInLocale(res, locale); } - public int getEndOfWord(final CharSequence sequence, int index) { + public int getEndOfWord(final CharSequence sequence, final int fromIndex) { final int length = sequence.length(); - index = index < 0 ? 0 : Character.offsetByCodePoints(sequence, index, 1); + int index = fromIndex < 0 ? 0 : Character.offsetByCodePoints(sequence, fromIndex, 1); while (index < length) { final int codePoint = Character.codePointAt(sequence, index); if (mSpacingAndPunctuations.isWordSeparator(codePoint)) { @@ -111,12 +113,12 @@ public class SentenceLevelAdapter { return index; } - public int getBeginningOfNextWord(final CharSequence sequence, int index) { + public int getBeginningOfNextWord(final CharSequence sequence, final int fromIndex) { final int length = sequence.length(); - if (index >= length) { + if (fromIndex >= length) { return -1; } - index = index < 0 ? 0 : Character.offsetByCodePoints(sequence, index, 1); + int index = fromIndex < 0 ? 0 : Character.offsetByCodePoints(sequence, fromIndex, 1); while (index < length) { final int codePoint = Character.codePointAt(sequence, index); if (!mSpacingAndPunctuations.isWordSeparator(codePoint)) { @@ -140,7 +142,7 @@ public class SentenceLevelAdapter { final int cookie = originalTextInfo.getCookie(); final int start = -1; final int end = originalText.length(); - final ArrayList<SentenceWordItem> wordItems = new ArrayList<SentenceWordItem>(); + final ArrayList<SentenceWordItem> wordItems = new ArrayList<>(); int wordStart = wordIterator.getBeginningOfNextWord(originalText, start); int wordEnd = wordIterator.getEndOfWord(originalText, wordStart); while (wordStart <= end && wordEnd != -1 && wordStart != -1) { @@ -158,6 +160,7 @@ public class SentenceLevelAdapter { return new SentenceTextInfoParams(originalTextInfo, wordItems); } + @TargetApi(Build.VERSION_CODES.JELLY_BEAN) public static SentenceSuggestionsInfo reconstructSuggestions( SentenceTextInfoParams originalTextInfoParams, SuggestionsInfo[] results) { if (results == null || results.length == 0) { diff --git a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsActivity.java b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsActivity.java index df9a76119..294666b8b 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsActivity.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsActivity.java @@ -18,7 +18,9 @@ package com.android.inputmethod.latin.spellcheck; import com.android.inputmethod.latin.utils.FragmentUtils; +import android.annotation.TargetApi; import android.content.Intent; +import android.os.Build; import android.os.Bundle; import android.preference.PreferenceActivity; @@ -41,8 +43,8 @@ public final class SpellCheckerSettingsActivity extends PreferenceActivity { return modIntent; } - // TODO: Uncomment the override annotation once we start using SDK version 19. - // @Override + @TargetApi(Build.VERSION_CODES.KITKAT) + @Override public boolean isValidFragment(String fragmentName) { return FragmentUtils.isValidFragment(fragmentName); } diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java index 9d186d44d..37ab2669b 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java +++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java @@ -26,9 +26,9 @@ import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.internal.KeyboardBuilder; import com.android.inputmethod.keyboard.internal.KeyboardIconsSet; import com.android.inputmethod.keyboard.internal.KeyboardParams; -import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.SuggestedWords; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.utils.TypefaceUtils; public final class MoreSuggestions extends Keyboard { diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java index 7b66bbb75..27a0f62ff 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java +++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java @@ -50,10 +50,8 @@ import com.android.inputmethod.latin.PunctuationSuggestions; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.SuggestedWords; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; -import com.android.inputmethod.latin.define.DebugFlags; import com.android.inputmethod.latin.settings.Settings; import com.android.inputmethod.latin.settings.SettingsValues; -import com.android.inputmethod.latin.utils.AutoCorrectionUtils; import com.android.inputmethod.latin.utils.ResourceUtils; import com.android.inputmethod.latin.utils.SubtypeLocaleUtils; import com.android.inputmethod.latin.utils.ViewLayoutUtils; @@ -380,6 +378,7 @@ final class SuggestionStripLayoutHelper { final int countInStrip = mSuggestionsCountInStrip; mMoreSuggestionsAvailable = (wordCountToShow > countInStrip); + @SuppressWarnings("unused") int x = 0; for (int positionInStrip = 0; positionInStrip < countInStrip; positionInStrip++) { if (positionInStrip != 0) { diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java index 789d549d7..b18fcc744 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java +++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java @@ -43,10 +43,10 @@ import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.MainKeyboardView; import com.android.inputmethod.keyboard.MoreKeysPanel; import com.android.inputmethod.latin.AudioAndHapticFeedbackManager; -import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.SuggestedWords; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.define.DebugFlags; import com.android.inputmethod.latin.settings.Settings; import com.android.inputmethod.latin.settings.SettingsValues; diff --git a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryList.java b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryList.java index 624783a70..90e4faafd 100644 --- a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryList.java +++ b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryList.java @@ -47,12 +47,12 @@ public class UserDictionaryList extends PreferenceFragment { "android.settings.USER_DICTIONARY_SETTINGS"; @Override - public void onCreate(Bundle icicle) { + public void onCreate(final Bundle icicle) { super.onCreate(icicle); setPreferenceScreen(getPreferenceManager().createPreferenceScreen(getActivity())); } - public static TreeSet<String> getUserDictionaryLocalesSet(Activity activity) { + public static TreeSet<String> getUserDictionaryLocalesSet(final Activity activity) { final Cursor cursor = activity.getContentResolver().query(UserDictionary.Words.CONTENT_URI, new String[] { UserDictionary.Words.LOCALE }, null, null, null); @@ -108,7 +108,7 @@ public class UserDictionaryList extends PreferenceFragment { * Creates the entries that allow the user to go into the user dictionary for each locale. * @param userDictGroup The group to put the settings in. */ - protected void createUserDictSettings(PreferenceGroup userDictGroup) { + protected void createUserDictSettings(final PreferenceGroup userDictGroup) { final Activity activity = getActivity(); userDictGroup.removeAll(); final TreeSet<String> localeSet = @@ -121,10 +121,10 @@ public class UserDictionaryList extends PreferenceFragment { } if (localeSet.isEmpty()) { - userDictGroup.addPreference(createUserDictionaryPreference(null, activity)); + userDictGroup.addPreference(createUserDictionaryPreference(null)); } else { for (String locale : localeSet) { - userDictGroup.addPreference(createUserDictionaryPreference(locale, activity)); + userDictGroup.addPreference(createUserDictionaryPreference(locale)); } } } @@ -134,7 +134,7 @@ public class UserDictionaryList extends PreferenceFragment { * @param locale The locale for which this user dictionary is for. * @return The corresponding preference. */ - protected Preference createUserDictionaryPreference(String locale, Activity activity) { + protected Preference createUserDictionaryPreference(final String locale) { final Preference newPref = new Preference(getActivity()); final Intent intent = new Intent(USER_DICTIONARY_SETTINGS_INTENT_ACTION); if (null == locale) { diff --git a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettings.java b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettings.java index cf2014a1a..727485724 100644 --- a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettings.java +++ b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettings.java @@ -177,17 +177,16 @@ public class UserDictionarySettings extends ListFragment { return getActivity().managedQuery(UserDictionary.Words.CONTENT_URI, QUERY_PROJECTION, QUERY_SELECTION_ALL_LOCALES, null, "UPPER(" + UserDictionary.Words.WORD + ")"); - } else { - final String queryLocale = null != locale ? locale : Locale.getDefault().toString(); - return getActivity().managedQuery(UserDictionary.Words.CONTENT_URI, QUERY_PROJECTION, - QUERY_SELECTION, new String[] { queryLocale }, - "UPPER(" + UserDictionary.Words.WORD + ")"); } + final String queryLocale = null != locale ? locale : Locale.getDefault().toString(); + return getActivity().managedQuery(UserDictionary.Words.CONTENT_URI, QUERY_PROJECTION, + QUERY_SELECTION, new String[] { queryLocale }, + "UPPER(" + UserDictionary.Words.WORD + ")"); } private ListAdapter createAdapter() { return new MyAdapter(getActivity(), R.layout.user_dictionary_item, mCursor, - ADAPTER_FROM, ADAPTER_TO, this); + ADAPTER_FROM, ADAPTER_TO); } @Override @@ -289,7 +288,7 @@ public class UserDictionarySettings extends ListFragment { private ViewBinder mViewBinder = new ViewBinder() { @Override - public boolean setViewValue(View v, Cursor c, int columnIndex) { + public boolean setViewValue(final View v, final Cursor c, final int columnIndex) { if (!IS_SHORTCUT_API_SUPPORTED) { // just let SimpleCursorAdapter set the view values return false; @@ -310,10 +309,9 @@ public class UserDictionarySettings extends ListFragment { } }; - @SuppressWarnings("deprecation") - public MyAdapter(Context context, int layout, Cursor c, String[] from, int[] to, - UserDictionarySettings settings) { - super(context, layout, c, from, to); + public MyAdapter(final Context context, final int layout, final Cursor c, + final String[] from, final int[] to) { + super(context, layout, c, from, to, 0 /* flags */); if (null != c) { final String alphabet = context.getString(R.string.user_dict_fast_scroll_alphabet); @@ -324,12 +322,12 @@ public class UserDictionarySettings extends ListFragment { } @Override - public int getPositionForSection(int section) { + public int getPositionForSection(final int section) { return null == mIndexer ? 0 : mIndexer.getPositionForSection(section); } @Override - public int getSectionForPosition(int position) { + public int getSectionForPosition(final int position) { return null == mIndexer ? 0 : mIndexer.getSectionForPosition(position); } diff --git a/java/src/com/android/inputmethod/latin/utils/AdditionalSubtypeUtils.java b/java/src/com/android/inputmethod/latin/utils/AdditionalSubtypeUtils.java index db7f2a56c..02ace6a1e 100644 --- a/java/src/com/android/inputmethod/latin/utils/AdditionalSubtypeUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/AdditionalSubtypeUtils.java @@ -16,12 +16,12 @@ package com.android.inputmethod.latin.utils; -import static com.android.inputmethod.latin.Constants.Subtype.KEYBOARD_MODE; -import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.ASCII_CAPABLE; -import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.EMOJI_CAPABLE; -import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.IS_ADDITIONAL_SUBTYPE; -import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET; -import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME; +import static com.android.inputmethod.latin.common.Constants.Subtype.KEYBOARD_MODE; +import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.ASCII_CAPABLE; +import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.EMOJI_CAPABLE; +import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.IS_ADDITIONAL_SUBTYPE; +import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET; +import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME; import android.os.Build; import android.text.TextUtils; diff --git a/java/src/com/android/inputmethod/latin/utils/AsyncResultHolder.java b/java/src/com/android/inputmethod/latin/utils/AsyncResultHolder.java index d12aad639..952ac2a62 100644 --- a/java/src/com/android/inputmethod/latin/utils/AsyncResultHolder.java +++ b/java/src/com/android/inputmethod/latin/utils/AsyncResultHolder.java @@ -59,11 +59,7 @@ public class AsyncResultHolder<E> { */ public E get(final E defaultValue, final long timeOut) { try { - if (mLatch.await(timeOut, TimeUnit.MILLISECONDS)) { - return mResult; - } else { - return defaultValue; - } + return mLatch.await(timeOut, TimeUnit.MILLISECONDS) ? mResult : defaultValue; } catch (InterruptedException e) { return defaultValue; } diff --git a/java/src/com/android/inputmethod/latin/utils/AutoCorrectionUtils.java b/java/src/com/android/inputmethod/latin/utils/AutoCorrectionUtils.java index cba769521..120cffbde 100644 --- a/java/src/com/android/inputmethod/latin/utils/AutoCorrectionUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/AutoCorrectionUtils.java @@ -24,7 +24,6 @@ import com.android.inputmethod.latin.define.DebugFlags; public final class AutoCorrectionUtils { private static final boolean DBG = DebugFlags.DEBUG_ENABLED; private static final String TAG = AutoCorrectionUtils.class.getSimpleName(); - private static final int MINIMUM_SAFETY_NET_CHAR_LENGTH = 4; private AutoCorrectionUtils() { // Purely static class: can't instantiate. diff --git a/java/src/com/android/inputmethod/latin/utils/CapsModeUtils.java b/java/src/com/android/inputmethod/latin/utils/CapsModeUtils.java index 02f1c5f00..b087e9ee8 100644 --- a/java/src/com/android/inputmethod/latin/utils/CapsModeUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/CapsModeUtils.java @@ -19,8 +19,8 @@ package com.android.inputmethod.latin.utils; import android.text.InputType; import android.text.TextUtils; -import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.WordComposer; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.settings.SpacingAndPunctuations; import java.util.Locale; diff --git a/java/src/com/android/inputmethod/latin/utils/CollectionUtils.java b/java/src/com/android/inputmethod/latin/utils/CollectionUtils.java index fb36b7c50..f9839eb91 100644 --- a/java/src/com/android/inputmethod/latin/utils/CollectionUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/CollectionUtils.java @@ -18,19 +18,18 @@ package com.android.inputmethod.latin.utils; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; -import java.util.Map; -import java.util.TreeMap; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; public final class CollectionUtils { private CollectionUtils() { // This utility class is not publicly instantiable. } - public static <E> ArrayList<E> arrayAsList(final E[] array, final int start, final int end) { - if (array == null) { - throw new NullPointerException(); - } + @Nonnull + public static <E> ArrayList<E> arrayAsList(@Nonnull final E[] array, final int start, + final int end) { if (start < 0 || start > end || end > array.length) { throw new IllegalArgumentException(); } @@ -47,7 +46,7 @@ public final class CollectionUtils { * @param c Collection to test. * @return Whether c contains no elements. */ - public static boolean isNullOrEmpty(final Collection c) { + public static boolean isNullOrEmpty(@Nullable final Collection<?> c) { return c == null || c.isEmpty(); } } diff --git a/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java b/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java index 7e8e55990..4e0f5f583 100644 --- a/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java @@ -17,6 +17,7 @@ package com.android.inputmethod.latin.utils; import com.android.inputmethod.latin.makedict.DictionaryHeader; +import com.android.inputmethod.latin.makedict.NgramProperty; import com.android.inputmethod.latin.makedict.ProbabilityInfo; import com.android.inputmethod.latin.makedict.WeightedString; import com.android.inputmethod.latin.makedict.WordProperty; @@ -26,6 +27,8 @@ import java.util.HashMap; public class CombinedFormatUtils { public static final String DICTIONARY_TAG = "dictionary"; public static final String BIGRAM_TAG = "bigram"; + public static final String NGRAM_TAG = "ngram"; + public static final String NGRAM_PREV_WORD_TAG = "prev_word"; public static final String SHORTCUT_TAG = "shortcut"; public static final String PROBABILITY_TAG = "f"; public static final String HISTORICAL_INFO_TAG = "historicalInfo"; @@ -63,7 +66,7 @@ public class CombinedFormatUtils { if (wordProperty.mIsNotAWord) { builder.append("," + NOT_A_WORD_TAG + "=true"); } - if (wordProperty.mIsBlacklistEntry) { + if (wordProperty.mIsPossiblyOffensive) { builder.append("," + BLACKLISTED_TAG + "=true"); } builder.append("\n"); @@ -76,12 +79,19 @@ public class CombinedFormatUtils { } } if (wordProperty.mHasNgrams) { - // TODO: Support ngram. - for (final WeightedString bigram : wordProperty.getBigrams()) { - builder.append(" " + BIGRAM_TAG + "=" + bigram.mWord); + for (final NgramProperty ngramProperty : wordProperty.mNgrams) { + builder.append(" " + NGRAM_TAG + "=" + ngramProperty.mTargetWord.mWord); builder.append(","); - builder.append(formatProbabilityInfo(bigram.mProbabilityInfo)); + builder.append(formatProbabilityInfo(ngramProperty.mTargetWord.mProbabilityInfo)); builder.append("\n"); + 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)) { + builder.append("," + BEGINNING_OF_SENTENCE_TAG + "=true"); + } + builder.append("\n"); + } } } return builder.toString(); diff --git a/java/src/com/android/inputmethod/latin/utils/CoordinateUtils.java b/java/src/com/android/inputmethod/latin/utils/CoordinateUtils.java index 87df013a6..3a9705904 100644 --- a/java/src/com/android/inputmethod/latin/utils/CoordinateUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/CoordinateUtils.java @@ -16,7 +16,7 @@ package com.android.inputmethod.latin.utils; -import java.util.Arrays; +import javax.annotation.Nonnull; public final class CoordinateUtils { private static final int INDEX_X = 0; @@ -27,32 +27,35 @@ public final class CoordinateUtils { // This utility class is not publicly instantiable. } + @Nonnull public static int[] newInstance() { return new int[ELEMENT_SIZE]; } - public static int x(final int[] coords) { + public static int x(@Nonnull final int[] coords) { return coords[INDEX_X]; } - public static int y(final int[] coords) { + public static int y(@Nonnull final int[] coords) { return coords[INDEX_Y]; } - public static void set(final int[] coords, final int x, final int y) { + public static void set(@Nonnull final int[] coords, final int x, final int y) { coords[INDEX_X] = x; coords[INDEX_Y] = y; } - public static void copy(final int[] destination, final int[] source) { + public static void copy(@Nonnull final int[] destination, @Nonnull final int[] source) { destination[INDEX_X] = source[INDEX_X]; destination[INDEX_Y] = source[INDEX_Y]; } + @Nonnull public static int[] newCoordinateArray(final int arraySize) { return new int[ELEMENT_SIZE * arraySize]; } + @Nonnull public static int[] newCoordinateArray(final int arraySize, final int defaultX, final int defaultY) { final int[] result = new int[ELEMENT_SIZE * arraySize]; @@ -62,30 +65,30 @@ public final class CoordinateUtils { return result; } - public static int xFromArray(final int[] coordsArray, final int index) { + public static int xFromArray(@Nonnull final int[] coordsArray, final int index) { return coordsArray[ELEMENT_SIZE * index + INDEX_X]; } - public static int yFromArray(final int[] coordsArray, final int index) { + public static int yFromArray(@Nonnull final int[] coordsArray, final int index) { return coordsArray[ELEMENT_SIZE * index + INDEX_Y]; } - public static int[] coordinateFromArray(final int[] coordsArray, final int index) { - final int baseIndex = ELEMENT_SIZE * index; - return Arrays.copyOfRange(coordsArray, baseIndex, baseIndex + ELEMENT_SIZE); + @Nonnull + public static int[] coordinateFromArray(@Nonnull final int[] coordsArray, final int index) { + final int[] coords = newInstance(); + set(coords, xFromArray(coordsArray, index), yFromArray(coordsArray, index)); + return coords; } - public static void setXYInArray(final int[] coordsArray, final int index, + public static void setXYInArray(@Nonnull final int[] coordsArray, final int index, final int x, final int y) { final int baseIndex = ELEMENT_SIZE * index; coordsArray[baseIndex + INDEX_X] = x; coordsArray[baseIndex + INDEX_Y] = y; } - public static void setCoordinateInArray(final int[] coordsArray, final int index, - final int[] coords) { - final int baseIndex = ELEMENT_SIZE * index; - coordsArray[baseIndex + INDEX_X] = coords[INDEX_X]; - coordsArray[baseIndex + INDEX_Y] = coords[INDEX_Y]; + public static void setCoordinateInArray(@Nonnull final int[] coordsArray, final int index, + @Nonnull final int[] coords) { + setXYInArray(coordsArray, index, x(coords), y(coords)); } } diff --git a/java/src/com/android/inputmethod/latin/utils/CursorAnchorInfoUtils.java b/java/src/com/android/inputmethod/latin/utils/CursorAnchorInfoUtils.java index e05618901..c90d30c42 100644 --- a/java/src/com/android/inputmethod/latin/utils/CursorAnchorInfoUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/CursorAnchorInfoUtils.java @@ -24,6 +24,7 @@ import android.inputmethodservice.InputMethodService; import android.os.Build; import android.text.Layout; import android.text.Spannable; +import android.text.Spanned; import android.view.View; import android.view.ViewParent; import android.view.inputmethod.CursorAnchorInfo; @@ -95,7 +96,7 @@ public final class CursorAnchorInfoUtils { @Nullable public static CursorAnchorInfoCompatWrapper extractFromTextView( @Nonnull final TextView textView) { - if (Build.VERSION.SDK_INT < BuildCompatUtils.VERSION_CODES_LXX) { + if (BuildCompatUtils.EFFECTIVE_SDK_INT < Build.VERSION_CODES.LOLLIPOP) { return null; } return CursorAnchorInfoCompatWrapper.wrap(extractFromTextViewInternal(textView)); @@ -107,7 +108,7 @@ public final class CursorAnchorInfoUtils { * @return the {@link CursorAnchorInfo} object based on the current layout. {@code null} if it * is not feasible. */ - @TargetApi(BuildCompatUtils.VERSION_CODES_LXX) + @TargetApi(Build.VERSION_CODES.LOLLIPOP) @Nullable private static CursorAnchorInfo extractFromTextViewInternal(@Nonnull final TextView textView) { final Layout layout = textView.getLayout(); @@ -149,7 +150,7 @@ public final class CursorAnchorInfoUtils { final Object[] spans = spannable.getSpans(0, text.length(), Object.class); for (Object span : spans) { final int spanFlag = spannable.getSpanFlags(span); - if ((spanFlag & Spannable.SPAN_COMPOSING) != 0) { + if ((spanFlag & Spanned.SPAN_COMPOSING) != 0) { composingTextStart = Math.min(composingTextStart, spannable.getSpanStart(span)); composingTextEnd = Math.max(composingTextEnd, spannable.getSpanEnd(span)); diff --git a/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java b/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java index e29aabacd..24025b272 100644 --- a/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java @@ -26,8 +26,8 @@ import android.util.Log; import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.latin.AssetFileAddress; import com.android.inputmethod.latin.BinaryDictionaryGetter; -import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.makedict.DictionaryHeader; import com.android.inputmethod.latin.makedict.UnsupportedFormatException; import com.android.inputmethod.latin.settings.SpacingAndPunctuations; diff --git a/java/src/com/android/inputmethod/latin/utils/DistracterFilter.java b/java/src/com/android/inputmethod/latin/utils/DistracterFilter.java index 355d00dac..525212c96 100644 --- a/java/src/com/android/inputmethod/latin/utils/DistracterFilter.java +++ b/java/src/com/android/inputmethod/latin/utils/DistracterFilter.java @@ -16,14 +16,16 @@ package com.android.inputmethod.latin.utils; -import java.util.List; -import java.util.Locale; - import android.view.inputmethod.InputMethodSubtype; import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.latin.NgramContext; +import java.util.List; +import java.util.Locale; + +import javax.annotation.Nonnull; + public interface DistracterFilter { /** * Determine whether a word is a distracter to words in dictionaries. @@ -68,8 +70,9 @@ public interface DistracterFilter { public static boolean shouldBeHandledAsOov(final int handlingType) { return (handlingType & SHOULD_BE_HANDLED_AS_OOV) != 0; } - }; + } + @Nonnull public static final DistracterFilter EMPTY_DISTRACTER_FILTER = new DistracterFilter() { @Override public boolean isDistracterToWordsInDictionaries(NgramContext ngramContext, diff --git a/java/src/com/android/inputmethod/latin/utils/DistracterFilterCheckingIsInDictionary.java b/java/src/com/android/inputmethod/latin/utils/DistracterFilterCheckingIsInDictionary.java index df6e97028..4c99fed9f 100644 --- a/java/src/com/android/inputmethod/latin/utils/DistracterFilterCheckingIsInDictionary.java +++ b/java/src/com/android/inputmethod/latin/utils/DistracterFilterCheckingIsInDictionary.java @@ -41,10 +41,9 @@ public class DistracterFilterCheckingIsInDictionary implements DistracterFilter // This filter treats entries that are already in the dictionary as non-distracters // because they have passed the filtering in the past. return false; - } else { - return mDistracterFilter.isDistracterToWordsInDictionaries( - ngramContext, testedWord, locale); } + return mDistracterFilter.isDistracterToWordsInDictionaries( + ngramContext, testedWord, locale); } @Override diff --git a/java/src/com/android/inputmethod/latin/utils/ExecutorUtils.java b/java/src/com/android/inputmethod/latin/utils/ExecutorUtils.java index 61da1b789..e77f6fd40 100644 --- a/java/src/com/android/inputmethod/latin/utils/ExecutorUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/ExecutorUtils.java @@ -27,7 +27,7 @@ import java.util.concurrent.ThreadFactory; * Utilities to manage executors. */ public class ExecutorUtils { - private static final ConcurrentHashMap<String, ExecutorService> sExecutorMap = + static final ConcurrentHashMap<String, ExecutorService> sExecutorMap = new ConcurrentHashMap<>(); private static class ThreadFactoryWithId implements ThreadFactory { @@ -49,7 +49,7 @@ public class ExecutorUtils { public static ExecutorService getExecutor(final String id) { ExecutorService executor = sExecutorMap.get(id); if (executor == null) { - synchronized(sExecutorMap) { + synchronized (sExecutorMap) { executor = sExecutorMap.get(id); if (executor == null) { executor = Executors.newSingleThreadExecutor(new ThreadFactoryWithId(id)); @@ -65,7 +65,7 @@ public class ExecutorUtils { */ @UsedForTesting public static void shutdownAllExecutors() { - synchronized(sExecutorMap) { + synchronized (sExecutorMap) { for (final ExecutorService executor : sExecutorMap.values()) { executor.execute(new Runnable() { @Override diff --git a/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java b/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java deleted file mode 100644 index 73aefb821..000000000 --- a/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (C) 2014 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.utils; - -import android.util.Log; - -import com.android.inputmethod.annotations.UsedForTesting; -import com.android.inputmethod.latin.Dictionary; -import com.android.inputmethod.latin.DictionaryFacilitator; -import com.android.inputmethod.latin.NgramContext; -import com.android.inputmethod.latin.settings.SpacingAndPunctuations; -import com.android.inputmethod.latin.utils.DistracterFilter.HandlingType; - -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; - -// Note: this class is used as a parameter type of a native method. You should be careful when you -// rename this class or field name. See BinaryDictionary#addMultipleDictionaryEntriesNative(). -public final class LanguageModelParam { - private static final String TAG = LanguageModelParam.class.getSimpleName(); - private static final boolean DEBUG = false; - private static final boolean DEBUG_TOKEN = false; - - // For now, these probability values are being referred to only when we add new entries to - // decaying dynamic binary dictionaries. When these are referred to, what matters is 0 or - // non-0. Thus, it's not meaningful to compare 10, 100, and so on. - // TODO: Revise the logic in ForgettingCurveUtils in native code. - private static final int UNIGRAM_PROBABILITY_FOR_VALID_WORD = 100; - private static final int UNIGRAM_PROBABILITY_FOR_OOV_WORD = Dictionary.NOT_A_PROBABILITY; - private static final int BIGRAM_PROBABILITY_FOR_VALID_WORD = 10; - private static final int BIGRAM_PROBABILITY_FOR_OOV_WORD = Dictionary.NOT_A_PROBABILITY; - - public final CharSequence mTargetWord; - public final int[] mWord0; - public final int[] mWord1; - // TODO: this needs to be a list of shortcuts - public final int[] mShortcutTarget; - public final int mUnigramProbability; - public final int mBigramProbability; - public final int mShortcutProbability; - public final boolean mIsNotAWord; - public final boolean mIsBlacklisted; - // Time stamp in seconds. - public final int mTimestamp; - - // Constructor for unigram. TODO: support shortcuts - @UsedForTesting - public LanguageModelParam(final CharSequence word, final int unigramProbability, - final int timestamp) { - this(null /* word0 */, word, unigramProbability, Dictionary.NOT_A_PROBABILITY, timestamp); - } - - // Constructor for unigram and bigram. - @UsedForTesting - public LanguageModelParam(final CharSequence word0, final CharSequence word1, - final int unigramProbability, final int bigramProbability, - final int timestamp) { - mTargetWord = word1; - mWord0 = (word0 == null) ? null : StringUtils.toCodePointArray(word0); - mWord1 = StringUtils.toCodePointArray(word1); - mShortcutTarget = null; - mUnigramProbability = unigramProbability; - mBigramProbability = bigramProbability; - mShortcutProbability = Dictionary.NOT_A_PROBABILITY; - mIsNotAWord = false; - mIsBlacklisted = false; - mTimestamp = timestamp; - } - - // Process a list of words and return a list of {@link LanguageModelParam} objects. - public static ArrayList<LanguageModelParam> createLanguageModelParamsFrom( - final List<String> tokens, final int timestamp, - final SpacingAndPunctuations spacingAndPunctuations, final Locale locale, - final DistracterFilter distracterFilter) { - final ArrayList<LanguageModelParam> languageModelParams = new ArrayList<>(); - final int N = tokens.size(); - NgramContext ngramContext = NgramContext.EMPTY_PREV_WORDS_INFO; - for (int i = 0; i < N; ++i) { - final String tempWord = tokens.get(i); - if (StringUtils.isEmptyStringOrWhiteSpaces(tempWord)) { - // just skip this token - if (DEBUG_TOKEN) { - Log.d(TAG, "--- isEmptyStringOrWhiteSpaces: \"" + tempWord + "\""); - } - continue; - } - if (!DictionaryInfoUtils.looksValidForDictionaryInsertion( - tempWord, spacingAndPunctuations)) { - if (DEBUG_TOKEN) { - Log.d(TAG, "--- not looksValidForDictionaryInsertion: \"" - + tempWord + "\""); - } - // Sentence terminator found. Split. - ngramContext = NgramContext.EMPTY_PREV_WORDS_INFO; - continue; - } - if (DEBUG_TOKEN) { - Log.d(TAG, "--- word: \"" + tempWord + "\""); - } - final LanguageModelParam languageModelParam = - detectWhetherVaildWordOrNotAndGetLanguageModelParam( - ngramContext, tempWord, timestamp, locale, distracterFilter); - if (languageModelParam == null) { - continue; - } - languageModelParams.add(languageModelParam); - ngramContext = ngramContext.getNextNgramContext( - new NgramContext.WordInfo(tempWord)); - } - return languageModelParams; - } - - private static LanguageModelParam detectWhetherVaildWordOrNotAndGetLanguageModelParam( - final NgramContext ngramContext, final String targetWord, final int timestamp, - final Locale locale, final DistracterFilter distracterFilter) { - if (locale == null) { - return null; - } - final int wordHandlingType = distracterFilter.getWordHandlingType(ngramContext, - targetWord, locale); - final String word = HandlingType.shouldBeLowerCased(wordHandlingType) ? - targetWord.toLowerCase(locale) : targetWord; - if (distracterFilter.isDistracterToWordsInDictionaries(ngramContext, targetWord, locale)) { - // The word is a distracter. - return null; - } - return createAndGetLanguageModelParamOfWord(ngramContext, word, timestamp, - !HandlingType.shouldBeHandledAsOov(wordHandlingType)); - } - - private static LanguageModelParam createAndGetLanguageModelParamOfWord( - final NgramContext ngramContext, final String word, final int timestamp, - final boolean isValidWord) { - final int unigramProbability = isValidWord ? - UNIGRAM_PROBABILITY_FOR_VALID_WORD : UNIGRAM_PROBABILITY_FOR_OOV_WORD; - if (!ngramContext.isValid()) { - if (DEBUG) { - Log.d(TAG, "--- add unigram: current(" - + (isValidWord ? "Valid" : "OOV") + ") = " + word); - } - return new LanguageModelParam(word, unigramProbability, timestamp); - } - if (DEBUG) { - Log.d(TAG, "--- add bigram: prev = " + ngramContext + ", current(" - + (isValidWord ? "Valid" : "OOV") + ") = " + word); - } - final int bigramProbability = isValidWord ? - BIGRAM_PROBABILITY_FOR_VALID_WORD : BIGRAM_PROBABILITY_FOR_OOV_WORD; - return new LanguageModelParam(ngramContext.getNthPrevWord(1 /* n */), word, - unigramProbability, bigramProbability, timestamp); - } -} diff --git a/java/src/com/android/inputmethod/latin/utils/NgramContextUtils.java b/java/src/com/android/inputmethod/latin/utils/NgramContextUtils.java index 34eeac2c2..7d2ddd268 100644 --- a/java/src/com/android/inputmethod/latin/utils/NgramContextUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/NgramContextUtils.java @@ -16,14 +16,16 @@ package com.android.inputmethod.latin.utils; -import java.util.Arrays; -import java.util.regex.Pattern; - -import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.NgramContext; import com.android.inputmethod.latin.NgramContext.WordInfo; +import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.settings.SpacingAndPunctuations; +import java.util.Arrays; +import java.util.regex.Pattern; + +import javax.annotation.Nonnull; + public final class NgramContextUtils { private NgramContextUtils() { // Intentional empty constructor for utility class. @@ -52,6 +54,7 @@ public final class NgramContextUtils { // (n = 2) "abc|" -> beginning-of-sentence // (n = 2) "abc |" -> beginning-of-sentence // (n = 2) "abc. def|" -> beginning-of-sentence + @Nonnull public static NgramContext getNgramContextFromNthPreviousWord(final CharSequence prev, final SpacingAndPunctuations spacingAndPunctuations, final int n) { if (prev == null) return NgramContext.EMPTY_PREV_WORDS_INFO; @@ -74,20 +77,20 @@ public final class NgramContextUtils { } // If we can't find (n + i) words, the context is beginning-of-sentence. if (focusedWordIndex < 0) { - prevWordsInfo[i] = WordInfo.BEGINNING_OF_SENTENCE; + prevWordsInfo[i] = WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO; break; } final String focusedWord = w[focusedWordIndex]; // If the word is, the context is beginning-of-sentence. final int length = focusedWord.length(); if (length <= 0) { - prevWordsInfo[i] = WordInfo.BEGINNING_OF_SENTENCE; + prevWordsInfo[i] = WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO; break; } // If ends in a sentence separator, the context is beginning-of-sentence. final char lastChar = focusedWord.charAt(length - 1); if (spacingAndPunctuations.isSentenceSeparator(lastChar)) { - prevWordsInfo[i] = WordInfo.BEGINNING_OF_SENTENCE; + prevWordsInfo[i] = WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO; break; } // If ends in a word separator or connector, the context is unclear. diff --git a/java/src/com/android/inputmethod/latin/utils/ResourceUtils.java b/java/src/com/android/inputmethod/latin/utils/ResourceUtils.java index 093c5a6c1..d1fc642f3 100644 --- a/java/src/com/android/inputmethod/latin/utils/ResourceUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/ResourceUtils.java @@ -110,7 +110,6 @@ public final class ResourceUtils { * are true for the specified key value pairs. * * For example, "condition,constant" has the following format. - * (See {@link ResourceUtilsTests#testFindConstantForKeyValuePairsRegexp()}) * - HARDWARE=mako,constantForNexus4 * - MODEL=Nexus 4:MANUFACTURER=LGE,constantForNexus4 * - ,defaultConstant @@ -119,6 +118,7 @@ public final class ResourceUtils { * @param conditionConstantArray an array of "condition,constant" elements to be searched. * @return the constant part of the matched "condition,constant" element. Returns null if no * condition matches. + * @see com.android.inputmethod.latin.utils.ResourceUtilsTests#testFindConstantForKeyValuePairsRegexp() */ @UsedForTesting static String findConstantForKeyValuePairs(final HashMap<String, String> keyValuePairs, diff --git a/java/src/com/android/inputmethod/latin/utils/SpannableStringUtils.java b/java/src/com/android/inputmethod/latin/utils/SpannableStringUtils.java index 38164cb36..cea1d1d58 100644 --- a/java/src/com/android/inputmethod/latin/utils/SpannableStringUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/SpannableStringUtils.java @@ -51,7 +51,7 @@ public final class SpannableStringUtils { // of a word. But the spans have been split into two by the getText{Before,After}Cursor // methods, so after concatenation they may end in the middle of a word. // Since we don't use them, we can just remove them and avoid crashing. - fl &= ~Spannable.SPAN_PARAGRAPH; + fl &= ~Spanned.SPAN_PARAGRAPH; int st = source.getSpanStart(spans[i]); int en = source.getSpanEnd(spans[i]); diff --git a/java/src/com/android/inputmethod/latin/utils/StringUtils.java b/java/src/com/android/inputmethod/latin/utils/StringUtils.java index bbcef990d..f96ed0468 100644 --- a/java/src/com/android/inputmethod/latin/utils/StringUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/StringUtils.java @@ -16,13 +16,11 @@ package com.android.inputmethod.latin.utils; -import static com.android.inputmethod.latin.Constants.CODE_UNSPECIFIED; - import android.text.Spanned; import android.text.TextUtils; import com.android.inputmethod.annotations.UsedForTesting; -import com.android.inputmethod.latin.Constants; +import com.android.inputmethod.latin.common.Constants; import java.util.ArrayList; import java.util.Arrays; @@ -502,7 +500,7 @@ public final class StringUtils { final String casedText = toUpperCaseOfStringForLocale( text, needsToUpperCase, locale); return codePointCount(casedText) == 1 - ? casedText.codePointAt(0) : CODE_UNSPECIFIED; + ? casedText.codePointAt(0) : Constants.CODE_UNSPECIFIED; } public static int getTrailingSingleQuotesCount(final CharSequence charSequence) { @@ -521,12 +519,12 @@ public final class StringUtils { * {@code charSequence.toString().split(regex, preserveTrailingEmptySegments ? -1 : 0)} * except that the spans are preserved in the result array. * </p> - * @param input the character sequence to be split. + * @param charSequence the character sequence to be split. * @param regex the regex pattern to be used as the separator. * @param preserveTrailingEmptySegments {@code true} to preserve the trailing empty * segments. Otherwise, trailing empty segments will be removed before being returned. - * @return the array which contains the result. All the spans in the {@param input} is - * preserved. + * @return the array which contains the result. All the spans in the <code>charSequence</code> + * is preserved. */ @UsedForTesting public static CharSequence[] split(final CharSequence charSequence, final String regex, diff --git a/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java b/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java index 61661cd52..eb85c1baf 100644 --- a/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java @@ -16,8 +16,9 @@ package com.android.inputmethod.latin.utils; -import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET; -import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME; +import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.COMBINING_RULES; +import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET; +import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME; import android.content.Context; import android.content.res.Resources; @@ -25,7 +26,6 @@ import android.os.Build; import android.util.Log; import android.view.inputmethod.InputMethodSubtype; -import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.RichInputMethodSubtype; @@ -39,10 +39,10 @@ import java.util.Locale; */ // TODO: consolidate this into RichInputMethodSubtype public final class SubtypeLocaleUtils { - private static final String TAG = SubtypeLocaleUtils.class.getSimpleName(); + static final String TAG = SubtypeLocaleUtils.class.getSimpleName(); - // This reference class {@link Constants} must be located in the same package as LatinIME.java. - private static final String RESOURCE_PACKAGE_NAME = Constants.class.getPackage().getName(); + // This reference class {@link R} must be located in the same package as LatinIME.java. + private static final String RESOURCE_PACKAGE_NAME = R.class.getPackage().getName(); // Special language code to represent "no language". public static final String NO_LANGUAGE = "zz"; @@ -245,9 +245,8 @@ public final class SubtypeLocaleUtils { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && subtype.containsExtraValueKey(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME)) { return subtype.getExtraValueOf(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME); - } else { - return getSubtypeLocaleDisplayNameInternal(subtype.getLocale(), displayLocale); } + return getSubtypeLocaleDisplayNameInternal(subtype.getLocale(), displayLocale); } public static String getSubtypeDisplayNameInSystemLocale(final InputMethodSubtype subtype) { @@ -342,6 +341,6 @@ public final class SubtypeLocaleUtils { } public static String getCombiningRulesExtraValue(final InputMethodSubtype subtype) { - return subtype.getExtraValueOf(Constants.Subtype.ExtraValue.COMBINING_RULES); + return subtype.getExtraValueOf(COMBINING_RULES); } } diff --git a/java/src/com/android/inputmethod/latin/utils/SuggestionResults.java b/java/src/com/android/inputmethod/latin/utils/SuggestionResults.java index 4e2e396c2..b319aeb8a 100644 --- a/java/src/com/android/inputmethod/latin/utils/SuggestionResults.java +++ b/java/src/com/android/inputmethod/latin/utils/SuggestionResults.java @@ -66,8 +66,7 @@ public final class SuggestionResults extends TreeSet<SuggestedWordInfo> { return super.addAll(e); } - private static final class SuggestedWordInfoComparator - implements Comparator<SuggestedWordInfo> { + static final class SuggestedWordInfoComparator implements Comparator<SuggestedWordInfo> { // This comparator ranks the word info with the higher frequency first. That's because // that's the order we want our elements in. @Override diff --git a/java/src/com/android/inputmethod/latin/utils/ViewLayoutUtils.java b/java/src/com/android/inputmethod/latin/utils/ViewLayoutUtils.java index dd122b634..0bcba2754 100644 --- a/java/src/com/android/inputmethod/latin/utils/ViewLayoutUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/ViewLayoutUtils.java @@ -57,7 +57,7 @@ public final class ViewLayoutUtils { public static void updateLayoutHeightOf(final Window window, final int layoutHeight) { final WindowManager.LayoutParams params = window.getAttributes(); - if (params.height != layoutHeight) { + if (params != null && params.height != layoutHeight) { params.height = layoutHeight; window.setAttributes(params); } @@ -65,7 +65,7 @@ public final class ViewLayoutUtils { public static void updateLayoutHeightOf(final View view, final int layoutHeight) { final ViewGroup.LayoutParams params = view.getLayoutParams(); - if (params.height != layoutHeight) { + if (params != null && params.height != layoutHeight) { params.height = layoutHeight; view.setLayoutParams(params); } diff --git a/java/src/com/android/inputmethod/latin/utils/WordInputEventForPersonalization.java b/java/src/com/android/inputmethod/latin/utils/WordInputEventForPersonalization.java new file mode 100644 index 000000000..d3fa0c748 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/utils/WordInputEventForPersonalization.java @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2014 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.utils; + +import android.util.Log; + +import com.android.inputmethod.annotations.UsedForTesting; +import com.android.inputmethod.latin.NgramContext; +import com.android.inputmethod.latin.common.Constants; +import com.android.inputmethod.latin.settings.SpacingAndPunctuations; +import com.android.inputmethod.latin.utils.DistracterFilter.HandlingType; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +// Note: this class is used as a parameter type of a native method. You should be careful when you +// rename this class or field name. See BinaryDictionary#addMultipleDictionaryEntriesNative(). +public final class WordInputEventForPersonalization { + private static final String TAG = WordInputEventForPersonalization.class.getSimpleName(); + private static final boolean DEBUG_TOKEN = false; + + public final int[] mTargetWord; + public final int mPrevWordsCount; + public final int[][] mPrevWordArray = new int[Constants.MAX_PREV_WORD_COUNT_FOR_N_GRAM][]; + public final boolean[] mIsPrevWordBeginningOfSentenceArray = + new boolean[Constants.MAX_PREV_WORD_COUNT_FOR_N_GRAM]; + public final boolean mIsValid; + // Time stamp in seconds. + public final int mTimestamp; + + @UsedForTesting + public WordInputEventForPersonalization(final CharSequence targetWord, + final NgramContext ngramContext, final boolean isValid, final int timestamp) { + mTargetWord = StringUtils.toCodePointArray(targetWord); + mPrevWordsCount = ngramContext.getPrevWordCount(); + ngramContext.outputToArray(mPrevWordArray, mIsPrevWordBeginningOfSentenceArray); + mIsValid = isValid; + mTimestamp = timestamp; + } + + // Process a list of words and return a list of {@link WordInputEventForPersonalization} + // objects. + public static ArrayList<WordInputEventForPersonalization> createInputEventFrom( + final List<String> tokens, final int timestamp, + final SpacingAndPunctuations spacingAndPunctuations, final Locale locale, + final DistracterFilter distracterFilter) { + final ArrayList<WordInputEventForPersonalization> inputEvents = new ArrayList<>(); + final int N = tokens.size(); + NgramContext ngramContext = NgramContext.EMPTY_PREV_WORDS_INFO; + for (int i = 0; i < N; ++i) { + final String tempWord = tokens.get(i); + if (StringUtils.isEmptyStringOrWhiteSpaces(tempWord)) { + // just skip this token + if (DEBUG_TOKEN) { + Log.d(TAG, "--- isEmptyStringOrWhiteSpaces: \"" + tempWord + "\""); + } + continue; + } + if (!DictionaryInfoUtils.looksValidForDictionaryInsertion( + tempWord, spacingAndPunctuations)) { + if (DEBUG_TOKEN) { + Log.d(TAG, "--- not looksValidForDictionaryInsertion: \"" + + tempWord + "\""); + } + // Sentence terminator found. Split. + // TODO: Detect whether the context is beginning-of-sentence. + ngramContext = NgramContext.EMPTY_PREV_WORDS_INFO; + continue; + } + if (DEBUG_TOKEN) { + Log.d(TAG, "--- word: \"" + tempWord + "\""); + } + final WordInputEventForPersonalization inputEvent = + detectWhetherVaildWordOrNotAndGetInputEvent( + ngramContext, tempWord, timestamp, locale, distracterFilter); + if (inputEvent == null) { + continue; + } + inputEvents.add(inputEvent); + ngramContext = ngramContext.getNextNgramContext(new NgramContext.WordInfo(tempWord)); + } + return inputEvents; + } + + private static WordInputEventForPersonalization detectWhetherVaildWordOrNotAndGetInputEvent( + final NgramContext ngramContext, final String targetWord, final int timestamp, + final Locale locale, final DistracterFilter distracterFilter) { + if (locale == null) { + return null; + } + final int wordHandlingType = distracterFilter.getWordHandlingType(ngramContext, + targetWord, locale); + final String word = HandlingType.shouldBeLowerCased(wordHandlingType) ? + targetWord.toLowerCase(locale) : targetWord; + if (distracterFilter.isDistracterToWordsInDictionaries(ngramContext, targetWord, locale)) { + // The word is a distracter. + return null; + } + return new WordInputEventForPersonalization(word, ngramContext, + !HandlingType.shouldBeHandledAsOov(wordHandlingType), timestamp); + } +} |