diff options
64 files changed, 881 insertions, 465 deletions
diff --git a/java/src/com/android/inputmethod/compat/AppWorkaroundsHelper.java b/java-overridable/src/com/android/inputmethod/compat/AppWorkaroundsHelper.java index 21535e421..21535e421 100644 --- a/java/src/com/android/inputmethod/compat/AppWorkaroundsHelper.java +++ b/java-overridable/src/com/android/inputmethod/compat/AppWorkaroundsHelper.java diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionaryPackConstants.java b/java-overridable/src/com/android/inputmethod/dictionarypack/DictionaryPackConstants.java index df0e3f0e1..df0e3f0e1 100644 --- a/java/src/com/android/inputmethod/dictionarypack/DictionaryPackConstants.java +++ b/java-overridable/src/com/android/inputmethod/dictionarypack/DictionaryPackConstants.java diff --git a/java/src/com/android/inputmethod/dictionarypack/MetadataUriGetter.java b/java-overridable/src/com/android/inputmethod/dictionarypack/MetadataUriGetter.java index ed817658e..ed817658e 100644 --- a/java/src/com/android/inputmethod/dictionarypack/MetadataUriGetter.java +++ b/java-overridable/src/com/android/inputmethod/dictionarypack/MetadataUriGetter.java diff --git a/java/src/com/android/inputmethod/latin/SpecialKeyDetector.java b/java-overridable/src/com/android/inputmethod/latin/SpecialKeyDetector.java index 27b2f5012..27b2f5012 100644 --- a/java/src/com/android/inputmethod/latin/SpecialKeyDetector.java +++ b/java-overridable/src/com/android/inputmethod/latin/SpecialKeyDetector.java diff --git a/java/src/com/android/inputmethod/latin/about/AboutPreferences.java b/java-overridable/src/com/android/inputmethod/latin/about/AboutPreferences.java index f60b189f1..f60b189f1 100644 --- a/java/src/com/android/inputmethod/latin/about/AboutPreferences.java +++ b/java-overridable/src/com/android/inputmethod/latin/about/AboutPreferences.java diff --git a/java/src/com/android/inputmethod/latin/define/DebugFlags.java b/java-overridable/src/com/android/inputmethod/latin/define/DebugFlags.java index c509e8322..c509e8322 100644 --- a/java/src/com/android/inputmethod/latin/define/DebugFlags.java +++ b/java-overridable/src/com/android/inputmethod/latin/define/DebugFlags.java diff --git a/java/src/com/android/inputmethod/latin/define/JniLibName.java b/java-overridable/src/com/android/inputmethod/latin/define/JniLibName.java index abfc36d39..abfc36d39 100644 --- a/java/src/com/android/inputmethod/latin/define/JniLibName.java +++ b/java-overridable/src/com/android/inputmethod/latin/define/JniLibName.java diff --git a/java/src/com/android/inputmethod/latin/define/ProductionFlags.java b/java-overridable/src/com/android/inputmethod/latin/define/ProductionFlags.java index 461c226a1..5ab126486 100644 --- a/java/src/com/android/inputmethod/latin/define/ProductionFlags.java +++ b/java-overridable/src/com/android/inputmethod/latin/define/ProductionFlags.java @@ -24,23 +24,14 @@ public final class ProductionFlags { public static final boolean IS_HARDWARE_KEYBOARD_SUPPORTED = false; /** - * When true, enable {@link InputMethodService#onUpdateCursorAnchorInfo} callback via - * {@link InputConnection#requestCursorAnchorInfo}. This flag has no effect in API Level 20 - * and prior. In general, this callback provides more detailed positional information, - * even though an explicit support is required by the editor. + * When true, enable {@link InputMethodService#onUpdateCursorAnchorInfo} callback via + * {@link InputConnection#requestUpdateCursorAnchorInfo}. This flag has no effect in API + * Level 20 and prior. In general, this callback provides detailed positional information, + * even though an explicit support is required by the editor. */ public static final boolean ENABLE_CURSOR_ANCHOR_INFO_CALLBACK = true; /** - * When true, enable {@link InputMethodService#onUpdateCursor} callback via - * {@link InputConnection#requestCursorAnchorInfo}. Although this callback has been available - * since API Level 3, the callback has never been used until API Level 20. Thus it may or may - * not work well as expected. Should rely on {@link InputMethodService#onUpdateCursorAnchorInfo} - * whenever possible since it is supposed to be more reliable and accurate. - */ - public static final boolean ENABLE_CURSOR_RECT_CALLBACK = false; - - /** * Include all suggestions from all dictionaries in {@link SuggestedWords#mRawSuggestions}. */ public static final boolean INCLUDE_RAW_SUGGESTIONS = false; diff --git a/java/src/com/android/inputmethod/latin/personalization/ContextualDictionaryUpdater.java b/java-overridable/src/com/android/inputmethod/latin/personalization/ContextualDictionaryUpdater.java index 7dc120e06..7dc120e06 100644 --- a/java/src/com/android/inputmethod/latin/personalization/ContextualDictionaryUpdater.java +++ b/java-overridable/src/com/android/inputmethod/latin/personalization/ContextualDictionaryUpdater.java diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryUpdater.java b/java-overridable/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryUpdater.java index c97a0d232..c97a0d232 100644 --- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryUpdater.java +++ b/java-overridable/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryUpdater.java diff --git a/java/src/com/android/inputmethod/latin/settings/AdditionalFeaturesSettingUtils.java b/java-overridable/src/com/android/inputmethod/latin/settings/AdditionalFeaturesSettingUtils.java index 6543003e8..6543003e8 100644 --- a/java/src/com/android/inputmethod/latin/settings/AdditionalFeaturesSettingUtils.java +++ b/java-overridable/src/com/android/inputmethod/latin/settings/AdditionalFeaturesSettingUtils.java diff --git a/java/src/com/android/inputmethod/latin/utils/FeedbackUtils.java b/java-overridable/src/com/android/inputmethod/latin/utils/FeedbackUtils.java index 0aed41ee4..0aed41ee4 100644 --- a/java/src/com/android/inputmethod/latin/utils/FeedbackUtils.java +++ b/java-overridable/src/com/android/inputmethod/latin/utils/FeedbackUtils.java diff --git a/java/src/com/android/inputmethod/latin/utils/FileTransforms.java b/java-overridable/src/com/android/inputmethod/latin/utils/FileTransforms.java index 9f4584ec9..9f4584ec9 100644 --- a/java/src/com/android/inputmethod/latin/utils/FileTransforms.java +++ b/java-overridable/src/com/android/inputmethod/latin/utils/FileTransforms.java diff --git a/java/src/com/android/inputmethod/latin/utils/MetadataFileUriGetter.java b/java-overridable/src/com/android/inputmethod/latin/utils/MetadataFileUriGetter.java index 9ad319da6..9ad319da6 100644 --- a/java/src/com/android/inputmethod/latin/utils/MetadataFileUriGetter.java +++ b/java-overridable/src/com/android/inputmethod/latin/utils/MetadataFileUriGetter.java diff --git a/java/src/com/android/inputmethod/latin/utils/StatsUtils.java b/java-overridable/src/com/android/inputmethod/latin/utils/StatsUtils.java index 79c19d077..95df202db 100644 --- a/java/src/com/android/inputmethod/latin/utils/StatsUtils.java +++ b/java-overridable/src/com/android/inputmethod/latin/utils/StatsUtils.java @@ -17,13 +17,16 @@ package com.android.inputmethod.latin.utils; import android.content.Context; + +import com.android.inputmethod.latin.RichInputMethodManager; import com.android.inputmethod.latin.settings.SettingsValues; public final class StatsUtils { public static void init(final Context context) { } - public static void onCreate(final SettingsValues settingsValues) { + public static void onCreate(final SettingsValues settingsValues, + RichInputMethodManager richImm) { } public static void onLoadSettings(final SettingsValues settingsValues) { diff --git a/java/Android.mk b/java/Android.mk index 9b8b2b448..0d12c45fe 100644 --- a/java/Android.mk +++ b/java/Android.mk @@ -17,7 +17,7 @@ include $(CLEAR_VARS) LOCAL_MODULE_TAGS := optional -LOCAL_SRC_FILES := $(call all-java-files-under, src) +LOCAL_SRC_FILES := $(call all-java-files-under, src ../java-overridable/src) LOCAL_PACKAGE_NAME := LatinIME diff --git a/java/res/layout/input_view.xml b/java/res/layout/input_view.xml index 7bfda3ae2..a4bcdcc8a 100644 --- a/java/res/layout/input_view.xml +++ b/java/res/layout/input_view.xml @@ -25,7 +25,7 @@ android:gravity="bottom|center_horizontal" android:orientation="vertical" > <!-- The height of key_preview_backing view will automatically be determined by code. --> - <RelativeLayout + <FrameLayout android:id="@+id/key_preview_backing" android:layout_width="match_parent" android:layout_height="0dp" /> diff --git a/java/res/layout/suggestions_strip.xml b/java/res/layout/suggestions_strip.xml index 489477990..aefdb8cad 100644 --- a/java/res/layout/suggestions_strip.xml +++ b/java/res/layout/suggestions_strip.xml @@ -48,12 +48,13 @@ android:layout_height="match_parent" style="?attr/suggestionWordStyle" /> <include + android:id="@+id/word_to_save_divider" layout="@layout/suggestion_divider" /> <TextView android:id="@+id/hint_add_to_dictionary" android:layout_width="match_parent" android:layout_height="match_parent" - android:textAlignment="viewStart" + android:gravity="center_vertical|start" style="?attr/suggestionWordStyle" /> </LinearLayout> <!-- Provide audio and haptic feedback by ourselves based on the keyboard settings. diff --git a/java/res/values/donottranslate.xml b/java/res/values/donottranslate.xml index b25a20803..d4d638542 100644 --- a/java/res/values/donottranslate.xml +++ b/java/res/values/donottranslate.xml @@ -37,6 +37,12 @@ <item>en_US</item> <item>en_GB</item> <item>es_US</item> + <item>hi_ZZ</item> + </string-array> + + <!-- Subtype locale whose name should be displayed in Locale.ROOT. --> + <string-array name="subtype_locale_displayed_in_root_locale"> + <item>hi_ZZ</item> </string-array> <!-- Generic subtype label --> diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml index cb03260ed..2a6495a57 100644 --- a/java/res/values/strings.xml +++ b/java/res/values/strings.xml @@ -168,6 +168,8 @@ <!-- Add to dictionary hint --> <string name="hint_add_to_dictionary">Touch again to save</string> + <!-- Add to dictionary hint --> + <string name="hint_add_to_dictionary_without_word">Touch here to save</string> <!-- Inform the user that a particular language has an available dictionary --> <string name="has_dictionary">Dictionary available</string> @@ -184,6 +186,8 @@ <!-- Description for Spanish (US) keyboard subtype [CHAR LIMIT=25] (US) should be an abbreviation of United States to fit in the CHAR LIMIT. --> <string name="subtype_es_US">Spanish (US)</string> + <!-- Description for Hinglish (https://en.wikipedia.org/wiki/Hinglish) keyboard subtype [CHAR LIMIT=25] --> + <string name="subtype_hi_ZZ">Hinglish</string> <!-- Description for English (UK) keyboard subtype with explicit keyboard layout [CHAR LIMIT=25] (UK) should be an abbreviation of United Kingdom to fit in the CHAR LIMIT. This should be identical to subtype_en_GB aside from the trailing (%s). --> @@ -196,6 +200,9 @@ (US) should be an abbreviation of United Statesn to fit in the CHAR LIMIT. This should be identical to subtype_es_US aside from the trailing (%s). --> <string name="subtype_with_layout_es_US">Spanish (US) (<xliff:g id="KEYBOARD_LAYOUT" example="QWERTY">%s</xliff:g>)</string> + <!-- Description for Hinglish (https://en.wikipedia.org/wiki/Hinglish) keyboard subtype with explicit keyboard layout [CHAR LIMIT=25] + This should be identical to subtype_hi_ZZ aside from the trailing (%s). --> + <string name="subtype_with_layout_hi_ZZ">Hinglish (<xliff:g id="KEYBOARD_LAYOUT" example="QWERTY">%s</xliff:g>)</string> <!-- Description for "LANGUAGE_NAME" (Traditional) keyboard subtype [CHAR LIMIT=25] (Traditional) can be an abbreviation to fit in the CHAR LIMIT. --> <string name="subtype_generic_traditional"><xliff:g id="LANGUAGE_NAME" example="Nepali">%s</xliff:g> (Traditional)</string> diff --git a/java/res/xml/key_styles_currency.xml b/java/res/xml/key_styles_currency.xml index cfe9a90a1..2ce6318f3 100644 --- a/java/res/xml/key_styles_currency.xml +++ b/java/res/xml/key_styles_currency.xml @@ -80,6 +80,7 @@ </case> <!-- fa: Persian (Rial and Afgahni) hi: Hindi (Indian Rupee) + hi_ZZ: Hinglish (Indian Rupee) iw: Hebrew (New Sheqel) lo: Lao (Kip) mn: Mongolian (Tugrik) diff --git a/java/res/xml/method.xml b/java/res/xml/method.xml index d71e88b8f..74ac79f59 100644 --- a/java/res/xml/method.xml +++ b/java/res/xml/method.xml @@ -52,6 +52,7 @@ gl_ES: Galician (Spain)/spanish hi: Hindi/hindi hi: Hindi/hindi_compact + (hi_ZZ: Hinglish/qwerty) # This is a preliminary keyboard layout. hr: Croatian/qwertz hu: Hungarian/qwertz hy_AM: Armenian (Armenia) Phonetic/armenian_phonetic @@ -354,6 +355,16 @@ android:imeSubtypeExtraValue="KeyboardLayoutSet=hindi_compact,EmojiCapable" android:isAsciiCapable="false" /> + <!-- TODO: This Hinglish keyboard is a preliminary layout. + This isn't based on the final specification. --> + <subtype android:icon="@drawable/ic_ime_switcher_dark" + android:label="@string/subtype_hi_ZZ" + android:subtypeId="0x352eb37c" + android:imeSubtypeLocale="hi_ZZ" + android:imeSubtypeMode="keyboard" + android:imeSubtypeExtraValue="AsciiCapable,KeyboardLayoutSet=qwerty,EmojiCapable" + android:isAsciiCapable="true" + /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" android:subtypeId="0x35b7526a" diff --git a/java/src/com/android/inputmethod/compat/CompatUtils.java b/java/src/com/android/inputmethod/compat/CompatUtils.java index 4fd2a6936..6aa2736c1 100644 --- a/java/src/com/android/inputmethod/compat/CompatUtils.java +++ b/java/src/com/android/inputmethod/compat/CompatUtils.java @@ -127,4 +127,92 @@ public final class CompatUtils { Log.e(TAG, "Exception in setFieldValue", e); } } + + public static ClassWrapper getClassWrapper(final String className) { + return new ClassWrapper(getClass(className)); + } + + public static final class ClassWrapper { + private final Class<?> mClass; + public ClassWrapper(final Class<?> targetClass) { + mClass = targetClass; + } + + public boolean exists() { + return mClass != null; + } + + public <T> ToObjectMethodWrapper<T> getMethod(final String name, + final T defaultValue, final Class<?>... parameterTypes) { + return new ToObjectMethodWrapper<T>(CompatUtils.getMethod(mClass, name, parameterTypes), + defaultValue); + } + + public ToIntMethodWrapper getPrimitiveMethod(final String name, final int defaultValue, + final Class<?>... parameterTypes) { + return new ToIntMethodWrapper(CompatUtils.getMethod(mClass, name, parameterTypes), + defaultValue); + } + + public ToFloatMethodWrapper getPrimitiveMethod(final String name, final float defaultValue, + final Class<?>... parameterTypes) { + return new ToFloatMethodWrapper(CompatUtils.getMethod(mClass, name, parameterTypes), + defaultValue); + } + + public ToBooleanMethodWrapper getPrimitiveMethod(final String name, + final boolean defaultValue, final Class<?>... parameterTypes) { + return new ToBooleanMethodWrapper(CompatUtils.getMethod(mClass, name, parameterTypes), + defaultValue); + } + } + + public static final class ToObjectMethodWrapper<T> { + private final Method mMethod; + private final T mDefaultValue; + public ToObjectMethodWrapper(final Method method, final T defaultValue) { + mMethod = method; + mDefaultValue = defaultValue; + } + @SuppressWarnings("unchecked") + public T invoke(final Object receiver, final Object... args) { + return (T) CompatUtils.invoke(receiver, mDefaultValue, mMethod, args); + } + } + + public static final class ToIntMethodWrapper { + private final Method mMethod; + private final int mDefaultValue; + public ToIntMethodWrapper(final Method method, final int defaultValue) { + mMethod = method; + mDefaultValue = defaultValue; + } + public int invoke(final Object receiver, final Object... args) { + return (int) CompatUtils.invoke(receiver, mDefaultValue, mMethod, args); + } + } + + public static final class ToFloatMethodWrapper { + private final Method mMethod; + private final float mDefaultValue; + public ToFloatMethodWrapper(final Method method, final float defaultValue) { + mMethod = method; + mDefaultValue = defaultValue; + } + public float invoke(final Object receiver, final Object... args) { + return (float) CompatUtils.invoke(receiver, mDefaultValue, mMethod, args); + } + } + + public static final class ToBooleanMethodWrapper { + private final Method mMethod; + private final boolean mDefaultValue; + public ToBooleanMethodWrapper(final Method method, final boolean defaultValue) { + mMethod = method; + mDefaultValue = defaultValue; + } + public boolean invoke(final Object receiver, final Object... args) { + return (boolean) CompatUtils.invoke(receiver, mDefaultValue, mMethod, args); + } + } } diff --git a/java/src/com/android/inputmethod/compat/CursorAnchorInfoCompatWrapper.java b/java/src/com/android/inputmethod/compat/CursorAnchorInfoCompatWrapper.java index 2cec14240..24eaec85c 100644 --- a/java/src/com/android/inputmethod/compat/CursorAnchorInfoCompatWrapper.java +++ b/java/src/com/android/inputmethod/compat/CursorAnchorInfoCompatWrapper.java @@ -21,39 +21,8 @@ import android.graphics.RectF; import com.android.inputmethod.annotations.UsedForTesting; -import java.lang.reflect.Method; - @UsedForTesting public final class CursorAnchorInfoCompatWrapper { - // Note that CursorAnchorInfo has been introduced in API level XX (Build.VERSION_CODE.LXX). - private static Class<?> getCursorAnchorInfoClass() { - try { - return Class.forName("android.view.inputmethod.CursorAnchorInfo"); - } catch (ClassNotFoundException e) { - return null; - } - } - private static final Class<?> CLASS; - private static final Method METHOD_GET_CHARACTER_RECT; - private static final Method METHOD_GET_CHARACTER_RECT_FLAGS; - private static final Method METHOD_GET_COMPOSING_TEXT; - private static final Method METHOD_GET_COMPOSING_TEXT_START; - private static final Method METHOD_GET_MATRIX; - static { - CLASS = getCursorAnchorInfoClass(); - METHOD_GET_CHARACTER_RECT = CompatUtils.getMethod(CLASS, "getCharacterRect", int.class); - METHOD_GET_CHARACTER_RECT_FLAGS = CompatUtils.getMethod(CLASS, "getCharacterRectFlags", - int.class); - METHOD_GET_COMPOSING_TEXT = CompatUtils.getMethod(CLASS, "getComposingText"); - METHOD_GET_COMPOSING_TEXT_START = CompatUtils.getMethod(CLASS, "getComposingTextStart"); - METHOD_GET_MATRIX = CompatUtils.getMethod(CLASS, "getMatrix"); - } - - @UsedForTesting - public static boolean isAvailable() { - return CLASS != null; - } - public static final int CHARACTER_RECT_TYPE_MASK = 0x0f; /** @@ -83,6 +52,49 @@ public final class CursorAnchorInfoCompatWrapper { */ public static final int CHARACTER_RECT_TYPE_NOT_FEASIBLE = 4; + // Note that CursorAnchorInfo has been introduced in API level XX (Build.VERSION_CODE.LXX). + private static final CompatUtils.ClassWrapper sCursorAnchorInfoClass; + private static final CompatUtils.ToObjectMethodWrapper<RectF> sGetCharacterRectMethod; + private static final CompatUtils.ToIntMethodWrapper sGetCharacterRectFlagsMethod; + private static final CompatUtils.ToObjectMethodWrapper<CharSequence> sGetComposingTextMethod; + private static final CompatUtils.ToIntMethodWrapper sGetComposingTextStartMethod; + private static final CompatUtils.ToFloatMethodWrapper sGetInsertionMarkerBaselineMethod; + private static final CompatUtils.ToFloatMethodWrapper sGetInsertionMarkerBottomMethod; + private static final CompatUtils.ToFloatMethodWrapper sGetInsertionMarkerHorizontalMethod; + private static final CompatUtils.ToFloatMethodWrapper sGetInsertionMarkerTopMethod; + private static final CompatUtils.ToObjectMethodWrapper<Matrix> sGetMatrixMethod; + private static final CompatUtils.ToBooleanMethodWrapper sIsInsertionMarkerClippedMethod; + + private static int COMPOSING_TEXT_START_DEFAULT = -1; + static { + sCursorAnchorInfoClass = CompatUtils.getClassWrapper( + "android.view.inputmethod.CursorAnchorInfo"); + sGetCharacterRectMethod = sCursorAnchorInfoClass.getMethod( + "getCharacterRect", (RectF)null, int.class); + sGetCharacterRectFlagsMethod = sCursorAnchorInfoClass.getPrimitiveMethod( + "getCharacterRectFlags", CHARACTER_RECT_TYPE_UNSPECIFIED, int.class); + sGetComposingTextMethod = sCursorAnchorInfoClass.getMethod( + "getComposingText", (CharSequence)null); + sGetComposingTextStartMethod = sCursorAnchorInfoClass.getPrimitiveMethod( + "getComposingTextStart", COMPOSING_TEXT_START_DEFAULT); + sGetInsertionMarkerBaselineMethod = sCursorAnchorInfoClass.getPrimitiveMethod( + "getInsertionMarkerBaseline", 0.0f); + sGetInsertionMarkerBottomMethod = sCursorAnchorInfoClass.getPrimitiveMethod( + "getInsertionMarkerBottom", 0.0f); + sGetInsertionMarkerHorizontalMethod = sCursorAnchorInfoClass.getPrimitiveMethod( + "getInsertionMarkerHorizontal", 0.0f); + sGetInsertionMarkerTopMethod = sCursorAnchorInfoClass.getPrimitiveMethod( + "getInsertionMarkerTop", 0.0f); + sGetMatrixMethod = sCursorAnchorInfoClass.getMethod("getMatrix", (Matrix)null); + sIsInsertionMarkerClippedMethod = sCursorAnchorInfoClass.getPrimitiveMethod( + "isInsertionMarkerClipped", false); + } + + @UsedForTesting + public static boolean isAvailable() { + return sCursorAnchorInfoClass.exists(); + } + private Object mInstance; private CursorAnchorInfoCompatWrapper(final Object instance) { @@ -107,29 +119,42 @@ public final class CursorAnchorInfoCompatWrapper { } public CharSequence getComposingText() { - return (CharSequence) CompatUtils.invoke(mInstance, null, METHOD_GET_COMPOSING_TEXT); + return sGetComposingTextMethod.invoke(mInstance); } - private static int COMPOSING_TEXT_START_DEFAULT = -1; public int getComposingTextStart() { - if (mInstance == null || METHOD_GET_COMPOSING_TEXT_START == null) { - return COMPOSING_TEXT_START_DEFAULT; - } - return (int) CompatUtils.invoke(mInstance, null, METHOD_GET_COMPOSING_TEXT_START); + return sGetComposingTextStartMethod.invoke(mInstance); } public Matrix getMatrix() { - return (Matrix) CompatUtils.invoke(mInstance, null, METHOD_GET_MATRIX); + return sGetMatrixMethod.invoke(mInstance); } public RectF getCharacterRect(final int index) { - return (RectF) CompatUtils.invoke(mInstance, null, METHOD_GET_CHARACTER_RECT, index); + return sGetCharacterRectMethod.invoke(mInstance, index); } public int getCharacterRectFlags(final int index) { - if (mInstance == null || METHOD_GET_CHARACTER_RECT_FLAGS == null) { - return CHARACTER_RECT_TYPE_UNSPECIFIED; - } - return (int) CompatUtils.invoke(mInstance, null, METHOD_GET_CHARACTER_RECT_FLAGS, index); + return sGetCharacterRectFlagsMethod.invoke(mInstance, index); + } + + public float getInsertionMarkerBaseline() { + return sGetInsertionMarkerBaselineMethod.invoke(mInstance); + } + + public float getInsertionMarkerBottom() { + return sGetInsertionMarkerBottomMethod.invoke(mInstance); + } + + public float getInsertionMarkerHorizontal() { + return sGetInsertionMarkerHorizontalMethod.invoke(mInstance); + } + + public float getInsertionMarkerTop() { + return sGetInsertionMarkerTopMethod.invoke(mInstance); + } + + public boolean isInsertionMarkerClipped() { + return sIsInsertionMarkerClippedMethod.invoke(mInstance); } } diff --git a/java/src/com/android/inputmethod/compat/InputConnectionCompatUtils.java b/java/src/com/android/inputmethod/compat/InputConnectionCompatUtils.java index be7bf402d..862ec8a58 100644 --- a/java/src/com/android/inputmethod/compat/InputConnectionCompatUtils.java +++ b/java/src/com/android/inputmethod/compat/InputConnectionCompatUtils.java @@ -16,67 +16,35 @@ package com.android.inputmethod.compat; -import android.util.Log; import android.view.inputmethod.InputConnection; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; +import android.view.inputmethod.InputMethodManager; public final class InputConnectionCompatUtils { - private static final String TAG = InputConnectionCompatUtils.class.getSimpleName(); - - // Note that CursorAnchorInfoRequest is supposed to be available in API level 21 and later. - private static Class<?> getCursorAnchorInfoRequestClass() { - try { - return Class.forName("android.view.inputmethod.CursorAnchorInfoRequest"); - } catch (ClassNotFoundException e) { - return null; - } - } - - private static final Class<?> TYPE_CursorAnchorInfoRequest; - private static final Constructor<?> CONSTRUCTOR_CursorAnchorInfoRequest; - private static final Method METHOD_requestCursorAnchorInfo; + private static final CompatUtils.ClassWrapper sInputConnectionType; + private static final CompatUtils.ToBooleanMethodWrapper sRequestUpdateCursorAnchorInfoMethod; static { - TYPE_CursorAnchorInfoRequest = getCursorAnchorInfoRequestClass(); - CONSTRUCTOR_CursorAnchorInfoRequest = CompatUtils.getConstructor( - TYPE_CursorAnchorInfoRequest, int.class, int.class); - METHOD_requestCursorAnchorInfo = CompatUtils.getMethod(InputConnection.class, - "requestCursorAnchorInfo", TYPE_CursorAnchorInfoRequest); + sInputConnectionType = new CompatUtils.ClassWrapper(InputConnection.class); + sRequestUpdateCursorAnchorInfoMethod = sInputConnectionType.getPrimitiveMethod( + "requestUpdateCursorAnchorInfo", false, int.class); } - public static boolean isRequestCursorAnchorInfoAvailable() { - return METHOD_requestCursorAnchorInfo != null && - CONSTRUCTOR_CursorAnchorInfoRequest != null; + public static boolean isRequestUpdateCursorAnchorInfoAvailable() { + return sRequestUpdateCursorAnchorInfoMethod != null; } /** * Local copies of some constants in CursorAnchorInfoRequest until the SDK becomes publicly * available. */ - private final static int RESULT_NOT_HANDLED = 0; - private final static int RESULT_SCHEDULED = 1; - private final static int TYPE_CURSOR_ANCHOR_INFO = 1; - private final static int FLAG_CURSOR_ANCHOR_INFO_MONITOR = 1; - private final static int FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE = 2; - private final static int TYPE_CURSOR_RECT = 2; - private final static int FLAG_CURSOR_RECT_MONITOR = 1; - private final static int FLAG_CURSOR_RECT_IN_SCREEN_COORDINATES = 2; - private final static int FLAG_CURSOR_RECT_WITH_VIEW_MATRIX = 4; + private static int REQUEST_UPDATE_CURSOR_UPDATE_IMMEDIATE = 1 << 0; + private static int REQUEST_UPDATE_CURSOR_UPDATE_MONITOR = 1 << 1; - private static int requestCursorAnchorInfoImpl(final InputConnection inputConnection, - final int type, final int flags) { - if (!isRequestCursorAnchorInfoAvailable()) { - return RESULT_NOT_HANDLED; - } - final Object requestObject = CompatUtils.newInstance( - CONSTRUCTOR_CursorAnchorInfoRequest, type, flags); - if (requestObject == null) { - return RESULT_NOT_HANDLED; + private static boolean requestUpdateCursorAnchorInfoImpl(final InputConnection inputConnection, + final int cursorUpdateMode) { + if (!isRequestUpdateCursorAnchorInfoAvailable()) { + return false; } - return (Integer) CompatUtils.invoke(inputConnection, - RESULT_NOT_HANDLED /* defaultValue */, - METHOD_requestCursorAnchorInfo, requestObject); + return sRequestUpdateCursorAnchorInfoMethod.invoke(inputConnection, cursorUpdateMode); } /** @@ -88,47 +56,11 @@ public final class InputConnectionCompatUtils { * as soon as possible to notify the current cursor/anchor position to the input method. * @return {@code false} if the request is not handled. Otherwise returns {@code true}. */ - public static boolean requestCursorAnchorInfo(final InputConnection inputConnection, + public static boolean requestUpdateCursorAnchorInfo(final InputConnection inputConnection, final boolean enableMonitor, final boolean requestImmediateCallback) { - final int requestFlags = (enableMonitor ? FLAG_CURSOR_ANCHOR_INFO_MONITOR : 0) - | (requestImmediateCallback ? FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE : 0); - final int requestResult = requestCursorAnchorInfoImpl(inputConnection, - TYPE_CURSOR_ANCHOR_INFO, requestFlags); - switch (requestResult) { - case RESULT_NOT_HANDLED: - return false; - case RESULT_SCHEDULED: - return true; - default: - Log.w(TAG, "requestCursorAnchorInfo returned unknown result=" + requestResult - + " for type=TYPE_CURSOR_ANCHOR_INFO flags=" + requestFlags); - return true; - } + final int cursorUpdateMode = (enableMonitor ? REQUEST_UPDATE_CURSOR_UPDATE_MONITOR : 0) + | (requestImmediateCallback ? REQUEST_UPDATE_CURSOR_UPDATE_IMMEDIATE : 0); + return requestUpdateCursorAnchorInfoImpl(inputConnection, cursorUpdateMode); } - /** - * Requests the editor to call back {@link InputMethodManager#updateCursor}. - * @param inputConnection the input connection to which the request is to be sent. - * @param enableMonitor {@code true} to request the editor to call back the method whenever the - * cursor position is changed. - * @return {@code false} if the request is not handled. Otherwise returns {@code true}. - */ - public static boolean requestCursorRect(final InputConnection inputConnection, - final boolean enableMonitor) { - final int requestFlags = enableMonitor ? - FLAG_CURSOR_RECT_MONITOR | FLAG_CURSOR_RECT_IN_SCREEN_COORDINATES | - FLAG_CURSOR_RECT_WITH_VIEW_MATRIX : 0; - final int requestResult = requestCursorAnchorInfoImpl(inputConnection, TYPE_CURSOR_RECT, - requestFlags); - switch (requestResult) { - case RESULT_NOT_HANDLED: - return false; - case RESULT_SCHEDULED: - return true; - default: - Log.w(TAG, "requestCursorAnchorInfo returned unknown result=" + requestResult - + " for type=TYPE_CURSOR_RECT flags=" + requestFlags); - return true; - } - } } diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java index 31bc549ca..0e3acff84 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java @@ -94,7 +94,7 @@ public final class KeyboardTextsTable { /* 8:22 */ "morekeys_n", /* 9:22 */ "single_quotes", /* 10:20 */ "morekeys_s", - /* 11:17 */ "keyspec_currency", + /* 11:18 */ "keyspec_currency", /* 12:14 */ "morekeys_y", /* 13:13 */ "morekeys_d", /* 14:12 */ "morekeys_z", @@ -1874,6 +1874,15 @@ public final class KeyboardTextsTable { /* additional_morekeys_symbols_0 */ "0", }; + /* Locale hi_ZZ: Hindi (ZZ) */ + private static final String[] TEXTS_hi_ZZ = { + /* morekeys_a ~ */ + null, null, null, null, null, null, null, null, null, null, null, + /* ~ morekeys_s */ + // U+20B9: "₹" INDIAN RUPEE SIGN + /* keyspec_currency */ "\u20B9", + }; + /* Locale hr: Croatian */ private static final String[] TEXTS_hr = { /* morekeys_a ~ */ @@ -3957,6 +3966,7 @@ public final class KeyboardTextsTable { "fr" , TEXTS_fr, /* 13/ 62 French */ "gl_ES" , TEXTS_gl_ES, /* 7/ 9 Gallegan (Spain) */ "hi" , TEXTS_hi, /* 23/ 53 Hindi */ + "hi_ZZ" , TEXTS_hi_ZZ, /* 1/ 12 Hindi (ZZ) */ "hr" , TEXTS_hr, /* 9/ 20 Croatian */ "hu" , TEXTS_hu, /* 9/ 20 Hungarian */ "hy_AM" , TEXTS_hy_AM, /* 9/126 Armenian (Armenia) */ diff --git a/java/src/com/android/inputmethod/latin/DictionaryStats.java b/java/src/com/android/inputmethod/latin/DictionaryStats.java new file mode 100644 index 000000000..75aa2411d --- /dev/null +++ b/java/src/com/android/inputmethod/latin/DictionaryStats.java @@ -0,0 +1,35 @@ +/* + * 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 java.io.File; +import java.util.Locale; + +public class DictionaryStats { + public final Locale mLocale; + public final String mDictName; + public final String mDictFilePath; + public final long mDictFileSize; + // TODO: Add more members. + + public DictionaryStats(final Locale locale, final String dictName, final File dictFile) { + mLocale = locale; + mDictName = dictName; + mDictFilePath = dictFile.getAbsolutePath(); + mDictFileSize = dictFile.length(); + } +} diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java index 22b91700c..de384037f 100644 --- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java @@ -644,6 +644,17 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { }); } + public DictionaryStats getDictionaryStats() { + reloadDictionaryIfRequired(); + mLock.readLock().lock(); + try { + // TODO: Get stats form the dictionary. + return new DictionaryStats(mLocale, mDictName, mDictFile); + } finally { + mLock.readLock().unlock(); + } + } + @UsedForTesting public void waitAllTasksForTests() { final CountDownLatch countDownLatch = new CountDownLatch(1); diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 8768e126e..e1d809907 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -420,18 +420,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (latinIme != null) { executePendingImsCallback(latinIme, editorInfo, restarting); latinIme.onStartInputInternal(editorInfo, restarting); - if (ProductionFlags.ENABLE_CURSOR_RECT_CALLBACK) { - InputConnectionCompatUtils.requestCursorRect( - latinIme.getCurrentInputConnection(), true /* enableMonitor */); - } - if (ProductionFlags.ENABLE_CURSOR_ANCHOR_INFO_CALLBACK) { - // AcceptTypedWord feature relies on CursorAnchorInfo. - if (latinIme.mSettings.getCurrent().mShouldShowUiToAcceptTypedWord) { - InputConnectionCompatUtils.requestCursorAnchorInfo( - latinIme.getCurrentInputConnection(), true /* enableMonitor */, - true /* requestImmediateCallback */); - } - } } } } @@ -573,7 +561,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen DictionaryDecayBroadcastReciever.setUpIntervalAlarmForDictionaryDecaying(this); - StatsUtils.onCreate(mSettings.getCurrent()); + StatsUtils.onCreate(mSettings.getCurrent(), mRichImm); } // Has to be package-visible for unit tests @@ -766,6 +754,14 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen private void onStartInputInternal(final EditorInfo editorInfo, final boolean restarting) { super.onStartInput(editorInfo, restarting); + if (ProductionFlags.ENABLE_CURSOR_ANCHOR_INFO_CALLBACK) { + // AcceptTypedWord feature relies on CursorAnchorInfo. + if (mSettings.getCurrent().mShouldShowUiToAcceptTypedWord) { + InputConnectionCompatUtils.requestUpdateCursorAnchorInfo( + getCurrentInputConnection(), true /* enableMonitor */, + true /* requestImmediateCallback */); + } + } } @SuppressWarnings("deprecation") @@ -970,14 +966,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } } - @Override - public void onUpdateCursor(final Rect rect) { - if (DEBUG) { - Log.i(TAG, "onUpdateCursor:" + rect.toShortString()); - } - super.onUpdateCursor(rect); - } - // We cannot mark this method as @Override until new SDK becomes publicly available. // @Override public void onUpdateCursorAnchorInfo(final CursorAnchorInfo info) { diff --git a/java/src/com/android/inputmethod/latin/RichInputMethodManager.java b/java/src/com/android/inputmethod/latin/RichInputMethodManager.java index 7cf4eff92..e43c18255 100644 --- a/java/src/com/android/inputmethod/latin/RichInputMethodManager.java +++ b/java/src/com/android/inputmethod/latin/RichInputMethodManager.java @@ -40,7 +40,8 @@ import java.util.List; /** * Enrichment class for InputMethodManager to simplify interaction and add functionality. */ -public final class RichInputMethodManager { +// non final for easy mocking. +public class RichInputMethodManager { private static final String TAG = RichInputMethodManager.class.getSimpleName(); private RichInputMethodManager() { diff --git a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java index a2ae74b20..ec3c6e291 100644 --- a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java +++ b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java @@ -36,9 +36,7 @@ public final class FormatSpec { * sion * * o | - * p | not used 3 bits - * t | each unigram and bigram entry has a time stamp? - * i | 1 bit, 1 = yes, 0 = no : CONTAINS_TIMESTAMP_FLAG + * p | not used, 2 bytes. * o | * nflags * @@ -48,7 +46,7 @@ public final class FormatSpec { * d | * ersize * - * | attributes list + * attributes list * * attributes list is: * <key> = | string of characters at the char format described below, with the terminator used @@ -86,11 +84,10 @@ public final class FormatSpec { */ /* Node (FusionDictionary.PtNode) layout is as follows: - * | is moved ? 2 bits, 11 = no : FLAG_IS_NOT_MOVED - * | This must be the same as FLAG_CHILDREN_ADDRESS_TYPE_THREEBYTES - * | 01 = yes : FLAG_IS_MOVED - * f | the new address is stored in the same place as the parent address - * l | is deleted? 10 = yes : FLAG_IS_DELETED + * | CHILDREN_ADDRESS_TYPE 2 bits, 11 : FLAG_CHILDREN_ADDRESS_TYPE_THREEBYTES + * | 10 : FLAG_CHILDREN_ADDRESS_TYPE_TWOBYTES + * f | 01 : FLAG_CHILDREN_ADDRESS_TYPE_ONEBYTE + * l | 00 : FLAG_CHILDREN_ADDRESS_TYPE_NOADDRESS * a | has several chars ? 1 bit, 1 = yes, 0 = no : FLAG_HAS_MULTIPLE_CHARS * g | has a terminal ? 1 bit, 1 = yes, 0 = no : FLAG_IS_TERMINAL * s | has shortcut targets ? 1 bit, 1 = yes, 0 = no : FLAG_HAS_SHORTCUT_TARGETS @@ -98,16 +95,6 @@ public final class FormatSpec { * | 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 * - * p | - * a | parent address, 3byte - * r | 1 byte = bbbbbbbb match - * e | case 1xxxxxxx => -((0xxxxxxx << 16) + (next byte << 8) + next byte) - * n | otherwise => (bbbbbbbb << 16) + (next byte << 8) + next byte - * t | This address is relative to the head of the PtNode. - * a | If the node doesn't have a parent, this field is set to 0. - * d | - * dress - * * c | IF FLAG_HAS_MULTIPLE_CHARS * h | char, char, char, char n * (1 or 3 bytes) : use PtNodeInfo for i/o helpers * a | end 1 byte, = 0 @@ -121,15 +108,10 @@ public final class FormatSpec { * q | * * c | - * h | children address, 3 bytes - * i | 1 byte = bbbbbbbb match - * l | case 1xxxxxxx => -((0xxxxxxx << 16) + (next byte << 8) + next byte) - * d | otherwise => (bbbbbbbb<<16) + (next byte << 8) + next byte - * r | if this node doesn't have children, this field is set to 0. - * e | (see BinaryDictEncoderUtils#writeVariableSignedAddress) - * n | This address is relative to the position of this field. - * a | - * ddress + * h | children address, CHILDREN_ADDRESS_TYPE bytes + * i | This address is relative to the position of this field. + * l | + * drenaddress * * | IF FLAG_IS_TERMINAL && FLAG_HAS_SHORTCUT_TARGETS * | shortcut string list @@ -179,8 +161,6 @@ public final class FormatSpec { public static final int MAGIC_NUMBER = 0x9BC13AFE; static final int NOT_A_VERSION_NUMBER = -1; - static final int FIRST_VERSION_WITH_DYNAMIC_UPDATE = 3; - static final int FIRST_VERSION_WITH_TERMINAL_ID = 4; // These MUST have the same values as the relevant constants in format_utils.h. // From version 4 on, we use version * 100 + revision as a version number. That allows @@ -202,9 +182,6 @@ public final class FormatSpec { // use it in the reading code. static final int MAX_WORD_LENGTH = Constants.DICTIONARY_MAX_WORD_LENGTH; - static final int PARENT_ADDRESS_SIZE = 3; - static final int FORWARD_LINK_ADDRESS_SIZE = 3; - // These flags are used only in the static dictionary. static final int MASK_CHILDREN_ADDRESS_TYPE = 0xC0; static final int FLAG_CHILDREN_ADDRESS_TYPE_NOADDRESS = 0x00; @@ -220,13 +197,6 @@ public final class FormatSpec { static final int FLAG_IS_NOT_A_WORD = 0x02; static final int FLAG_IS_BLACKLISTED = 0x01; - // These flags are used only in the dynamic dictionary. - static final int MASK_MOVE_AND_DELETE_FLAG = 0xC0; - static final int FIXED_BIT_OF_DYNAMIC_UPDATE_MOVE = 0x40; - static final int FLAG_IS_MOVED = 0x00 | FIXED_BIT_OF_DYNAMIC_UPDATE_MOVE; - static final int FLAG_IS_NOT_MOVED = 0x80 | FIXED_BIT_OF_DYNAMIC_UPDATE_MOVE; - static final int FLAG_IS_DELETED = 0x80; - static final int FLAG_BIGRAM_SHORTCUT_ATTR_HAS_NEXT = 0x80; static final int FLAG_BIGRAM_ATTR_OFFSET_NEGATIVE = 0x40; static final int MASK_BIGRAM_ATTR_ADDRESS_TYPE = 0x30; @@ -240,52 +210,12 @@ public final class FormatSpec { static final int PTNODE_TERMINATOR_SIZE = 1; static final int PTNODE_FLAGS_SIZE = 1; static final int PTNODE_FREQUENCY_SIZE = 1; - static final int PTNODE_TERMINAL_ID_SIZE = 4; static final int PTNODE_MAX_ADDRESS_SIZE = 3; static final int PTNODE_ATTRIBUTE_FLAGS_SIZE = 1; static final int PTNODE_ATTRIBUTE_MAX_ADDRESS_SIZE = 3; static final int PTNODE_SHORTCUT_LIST_SIZE_SIZE = 2; - // These values are used only by version 4 or later. They MUST match the definitions in - // ver4_dict_constants.cpp. - static final String TRIE_FILE_EXTENSION = ".trie"; - public static final String HEADER_FILE_EXTENSION = ".header"; - static final String FREQ_FILE_EXTENSION = ".freq"; - // tat = Terminal Address Table - static final String TERMINAL_ADDRESS_TABLE_FILE_EXTENSION = ".tat"; - static final String BIGRAM_FILE_EXTENSION = ".bigram"; - static final String SHORTCUT_FILE_EXTENSION = ".shortcut"; - static final String LOOKUP_TABLE_FILE_SUFFIX = "_lookup"; - static final String CONTENT_TABLE_FILE_SUFFIX = "_index"; - static final int FLAGS_IN_FREQ_FILE_SIZE = 1; - static final int FREQUENCY_AND_FLAGS_SIZE = 2; - static final int TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE = 3; - static final int UNIGRAM_TIMESTAMP_SIZE = 4; - static final int UNIGRAM_COUNTER_SIZE = 1; - static final int UNIGRAM_LEVEL_SIZE = 1; - - // With the English main dictionary as of October 2013, the size of bigram address table is - // is 345KB with the block size being 16. - // This is 54% of that of full address table. - static final int BIGRAM_ADDRESS_TABLE_BLOCK_SIZE = 16; - static final int BIGRAM_CONTENT_COUNT = 1; - static final int BIGRAM_FREQ_CONTENT_INDEX = 0; - static final String BIGRAM_FREQ_CONTENT_ID = "_freq"; - static final int BIGRAM_TIMESTAMP_SIZE = 4; - static final int BIGRAM_COUNTER_SIZE = 1; - static final int BIGRAM_LEVEL_SIZE = 1; - - static final int SHORTCUT_CONTENT_COUNT = 1; - static final int SHORTCUT_CONTENT_INDEX = 0; - // With the English main dictionary as of October 2013, the size of shortcut address table is - // 26KB with the block size being 64. - // This is only 4.4% of that of full address table. - static final int SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE = 64; - static final String SHORTCUT_CONTENT_ID = "_shortcut"; - static final int NO_CHILDREN_ADDRESS = Integer.MIN_VALUE; - static final int NO_PARENT_ADDRESS = 0; - static final int NO_FORWARD_LINK_ADDRESS = 0; static final int INVALID_CHARACTER = -1; static final int MAX_PTNODES_FOR_ONE_BYTE_PTNODE_COUNT = 0x7F; // 127 @@ -302,14 +232,11 @@ public final class FormatSpec { // This option needs to be the same numeric value as the one in binary_format.h. static final int NOT_VALID_WORD = -99; - static final int SIGNED_CHILDREN_ADDRESS_SIZE = 3; static final int UINT8_MAX = 0xFF; static final int UINT16_MAX = 0xFFFF; static final int UINT24_MAX = 0xFFFFFF; - static final int SINT24_MAX = 0x7FFFFF; static final int MSB8 = 0x80; - static final int MSB24 = 0x800000; /** * Options about file format. diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDataChunk.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDataChunk.java index 9d72de8c5..6f4b09741 100644 --- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDataChunk.java +++ b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDataChunk.java @@ -18,20 +18,20 @@ package com.android.inputmethod.latin.personalization; import java.util.Collections; import java.util.List; -import java.util.Locale; public class PersonalizationDataChunk { public final boolean mInputByUser; public final List<String> mTokens; public final int mTimestampInSeconds; public final String mPackageName; - public final Locale mlocale = null; + public final String mDetectedLanguage; public PersonalizationDataChunk(boolean inputByUser, final List<String> tokens, - final int timestampInSeconds, final String packageName) { + final int timestampInSeconds, final String packageName, final String detectedLanguage) { mInputByUser = inputByUser; mTokens = Collections.unmodifiableList(tokens); mTimestampInSeconds = timestampInSeconds; mPackageName = packageName; + mDetectedLanguage = detectedLanguage; } } diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java index 346aea34a..9d186d44d 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java +++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java @@ -125,9 +125,9 @@ public final class MoreSuggestions extends Keyboard { } private static final int[][] COLUMN_ORDER_TO_NUMBER = { - { 0, }, - { 1, 0, }, - { 2, 0, 1}, + { 0 }, // center + { 1, 0 }, // right-left + { 1, 0, 2 }, // center-left-right }; public int getNumColumnInRow(final int index) { diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java index 7307ca1ba..1e8df8986 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java +++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java @@ -45,11 +45,14 @@ import android.widget.LinearLayout; import android.widget.TextView; import com.android.inputmethod.accessibility.AccessibilityUtils; +import com.android.inputmethod.annotations.UsedForTesting; 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; @@ -72,7 +75,7 @@ final class SuggestionStripLayoutHelper { private int mMaxMoreSuggestionsRow; public final float mMinMoreSuggestionsWidth; public final int mMoreSuggestionsBottomGap; - public boolean mMoreSuggestionsAvailable; + private boolean mMoreSuggestionsAvailable; // The index of these {@link ArrayList} is the position in the suggestion strip. The indices // increase towards the right for LTR scripts and the left for RTL scripts, starting with 0. @@ -223,11 +226,59 @@ final class SuggestionStripLayoutHelper { return spannedWord; } + /** + * Convert an index of {@link SuggestedWords} to position in the suggestion strip. + * @param indexInSuggestedWords the index of {@link SuggestedWords}. + * @param suggestedWords the suggested words list + * @return Non-negative integer of the position in the suggestion strip. + * Negative integer if the word of the index shouldn't be shown on the suggestion strip. + */ private int getPositionInSuggestionStrip(final int indexInSuggestedWords, final SuggestedWords suggestedWords) { + final SettingsValues settingsValues = Settings.getInstance().getCurrent(); + final boolean shouldOmitTypedWord = shouldOmitTypedWord(suggestedWords.mInputStyle, + settingsValues.mGestureFloatingPreviewTextEnabled, + settingsValues.mShouldShowUiToAcceptTypedWord); + return getPositionInSuggestionStrip(indexInSuggestedWords, suggestedWords.mWillAutoCorrect, + settingsValues.mShouldShowUiToAcceptTypedWord && shouldOmitTypedWord, + mCenterPositionInStrip, mTypedWordPositionWhenAutocorrect); + } + + @UsedForTesting + static boolean shouldOmitTypedWord(final int inputStyle, + final boolean gestureFloatingPreviewTextEnabled, + final boolean shouldShowUiToAcceptTypedWord) { + final boolean omitTypedWord = (inputStyle == SuggestedWords.INPUT_STYLE_TYPING) + || (inputStyle == SuggestedWords.INPUT_STYLE_TAIL_BATCH) + || (inputStyle == SuggestedWords.INPUT_STYLE_UPDATE_BATCH + && gestureFloatingPreviewTextEnabled); + return shouldShowUiToAcceptTypedWord && omitTypedWord; + } + + @UsedForTesting + static int getPositionInSuggestionStrip(final int indexInSuggestedWords, + final boolean willAutoCorrect, final boolean omitTypedWord, + final int centerPositionInStrip, final int typedWordPositionWhenAutoCorrect) { + if (omitTypedWord) { + if (indexInSuggestedWords == SuggestedWords.INDEX_OF_TYPED_WORD) { + // Ignore. + return -1; + } + if (indexInSuggestedWords == SuggestedWords.INDEX_OF_AUTO_CORRECTION) { + // Center in the suggestion strip. + return centerPositionInStrip; + } + // If neither of those, the order in the suggestion strip is left of the center first + // then right of the center, to both edges of the suggestion strip. + // For example, center-1, center+1, center-2, center+2, and so on. + final int n = indexInSuggestedWords; + final int offsetFromCenter = (n % 2) == 0 ? -(n / 2) : (n / 2); + final int positionInSuggestionStrip = centerPositionInStrip + offsetFromCenter; + return positionInSuggestionStrip; + } final int indexToDisplayMostImportantSuggestion; final int indexToDisplaySecondMostImportantSuggestion; - if (suggestedWords.mWillAutoCorrect) { + if (willAutoCorrect) { indexToDisplayMostImportantSuggestion = SuggestedWords.INDEX_OF_AUTO_CORRECTION; indexToDisplaySecondMostImportantSuggestion = SuggestedWords.INDEX_OF_TYPED_WORD; } else { @@ -235,25 +286,31 @@ final class SuggestionStripLayoutHelper { indexToDisplaySecondMostImportantSuggestion = SuggestedWords.INDEX_OF_AUTO_CORRECTION; } if (indexInSuggestedWords == indexToDisplayMostImportantSuggestion) { - return mCenterPositionInStrip; + // Center in the suggestion strip. + return centerPositionInStrip; } if (indexInSuggestedWords == indexToDisplaySecondMostImportantSuggestion) { - return mTypedWordPositionWhenAutocorrect; + // Center-1. + return typedWordPositionWhenAutoCorrect; } - // If neither of those, the order in the suggestion strip is the same as in SuggestedWords. - return indexInSuggestedWords; + // If neither of those, the order in the suggestion strip is right of the center first + // then left of the center, to both edges of the suggestion strip. + // For example, Center+1, center-2, center+2, center-3, and so on. + final int n = indexInSuggestedWords + 1; + final int offsetFromCenter = (n % 2) == 0 ? -(n / 2) : (n / 2); + final int positionInSuggestionStrip = centerPositionInStrip + offsetFromCenter; + return positionInSuggestionStrip; } private int getSuggestionTextColor(final SuggestedWords suggestedWords, final int indexInSuggestedWords) { - final int positionInStrip = - getPositionInSuggestionStrip(indexInSuggestedWords, suggestedWords); // Use identity for strings, not #equals : it's the typed word if it's the same object final boolean isTypedWord = suggestedWords.getInfo(indexInSuggestedWords).isKindOf( SuggestedWordInfo.KIND_TYPED); final int color; - if (positionInStrip == mCenterPositionInStrip && suggestedWords.mWillAutoCorrect) { + if (indexInSuggestedWords == SuggestedWords.INDEX_OF_AUTO_CORRECTION + && suggestedWords.mWillAutoCorrect) { color = mColorAutoCorrect; } else if (isTypedWord && suggestedWords.mTypedWordValid) { color = mColorValidTypedWord; @@ -265,7 +322,8 @@ final class SuggestionStripLayoutHelper { if (DebugFlags.DEBUG_ENABLED && suggestedWords.size() > 1) { // If we auto-correct, then the autocorrection is in slot 0 and the typed word // is in slot 1. - if (positionInStrip == mCenterPositionInStrip + if (indexInSuggestedWords == SuggestedWords.INDEX_OF_AUTO_CORRECTION + && suggestedWords.mWillAutoCorrect && AutoCorrectionUtils.shouldBlockAutoCorrectionBySafetyNet( suggestedWords.getLabel(SuggestedWords.INDEX_OF_AUTO_CORRECTION), suggestedWords.getLabel(SuggestedWords.INDEX_OF_TYPED_WORD))) { @@ -292,31 +350,31 @@ final class SuggestionStripLayoutHelper { } /** - * Layout suggestions to the suggestions strip. And returns the number of suggestions displayed - * in the suggestions strip. + * Layout suggestions to the suggestions strip. And returns the start index of more + * suggestions. * * @param suggestedWords suggestions to be shown in the suggestions strip. * @param stripView the suggestions strip view. * @param placerView the view where the debug info will be placed. - * @return the number of suggestions displayed in the suggestions strip + * @return the start index of more suggestions. */ - public int layoutAndReturnSuggestionCountInStrip(final SuggestedWords suggestedWords, + public int layoutAndReturnStartIndexOfMoreSuggestions(final SuggestedWords suggestedWords, final ViewGroup stripView, final ViewGroup placerView) { if (suggestedWords.isPunctuationSuggestions()) { - return layoutPunctuationSuggestionsAndReturnSuggestionCountInStrip( + return layoutPunctuationsAndReturnStartIndexOfMoreSuggestions( (PunctuationSuggestions)suggestedWords, stripView); } - setupWordViewsTextAndColor(suggestedWords, mSuggestionsCountInStrip); + final int startIndexOfMoreSuggestions = setupWordViewsAndReturnStartIndexOfMoreSuggestions( + suggestedWords, mSuggestionsCountInStrip); final TextView centerWordView = mWordViews.get(mCenterPositionInStrip); final int stripWidth = stripView.getWidth(); final int centerWidth = getSuggestionWidth(mCenterPositionInStrip, stripWidth); - final int countInStrip; if (suggestedWords.size() == 1 || getTextScaleX(centerWordView.getText(), centerWidth, centerWordView.getPaint()) < MIN_TEXT_XSCALE) { // Layout only the most relevant suggested word at the center of the suggestion strip // by consolidating all slots in the strip. - countInStrip = 1; + final int countInStrip = 1; mMoreSuggestionsAvailable = (suggestedWords.size() > countInStrip); layoutWord(mCenterPositionInStrip, stripWidth - mPadding); stripView.addView(centerWordView); @@ -324,31 +382,33 @@ final class SuggestionStripLayoutHelper { if (SuggestionStripView.DBG) { layoutDebugInfo(mCenterPositionInStrip, placerView, stripWidth); } - } else { - countInStrip = mSuggestionsCountInStrip; - mMoreSuggestionsAvailable = (suggestedWords.size() > countInStrip); - int x = 0; - for (int positionInStrip = 0; positionInStrip < countInStrip; positionInStrip++) { - if (positionInStrip != 0) { - final View divider = mDividerViews.get(positionInStrip); - // Add divider if this isn't the left most suggestion in suggestions strip. - addDivider(stripView, divider); - x += divider.getMeasuredWidth(); - } - - final int width = getSuggestionWidth(positionInStrip, stripWidth); - final TextView wordView = layoutWord(positionInStrip, width); - stripView.addView(wordView); - setLayoutWeight(wordView, getSuggestionWeight(positionInStrip), - ViewGroup.LayoutParams.MATCH_PARENT); - x += wordView.getMeasuredWidth(); - - if (SuggestionStripView.DBG) { - layoutDebugInfo(positionInStrip, placerView, x); - } + final Integer lastIndex = (Integer)centerWordView.getTag(); + return (lastIndex == null ? 0 : lastIndex) + 1; + } + + final int countInStrip = mSuggestionsCountInStrip; + mMoreSuggestionsAvailable = (suggestedWords.size() > countInStrip); + int x = 0; + for (int positionInStrip = 0; positionInStrip < countInStrip; positionInStrip++) { + if (positionInStrip != 0) { + final View divider = mDividerViews.get(positionInStrip); + // Add divider if this isn't the left most suggestion in suggestions strip. + addDivider(stripView, divider); + x += divider.getMeasuredWidth(); + } + + final int width = getSuggestionWidth(positionInStrip, stripWidth); + final TextView wordView = layoutWord(positionInStrip, width); + stripView.addView(wordView); + setLayoutWeight(wordView, getSuggestionWeight(positionInStrip), + ViewGroup.LayoutParams.MATCH_PARENT); + x += wordView.getMeasuredWidth(); + + if (SuggestionStripView.DBG) { + layoutDebugInfo(positionInStrip, placerView, x); } } - return countInStrip; + return startIndexOfMoreSuggestions; } /** @@ -426,10 +486,10 @@ final class SuggestionStripLayoutHelper { return (1.0f - mCenterSuggestionWeight) / (mSuggestionsCountInStrip - 1); } - private void setupWordViewsTextAndColor(final SuggestedWords suggestedWords, - final int countInStrip) { + private int setupWordViewsAndReturnStartIndexOfMoreSuggestions( + final SuggestedWords suggestedWords, final int maxSuggestionInStrip) { // Clear all suggestions first - for (int positionInStrip = 0; positionInStrip < countInStrip; ++positionInStrip) { + for (int positionInStrip = 0; positionInStrip < maxSuggestionInStrip; ++positionInStrip) { final TextView wordView = mWordViews.get(positionInStrip); wordView.setText(null); wordView.setTag(null); @@ -438,11 +498,15 @@ final class SuggestionStripLayoutHelper { mDebugInfoViews.get(positionInStrip).setText(null); } } - final int count = Math.min(suggestedWords.size(), countInStrip); - for (int indexInSuggestedWords = 0; indexInSuggestedWords < count; - indexInSuggestedWords++) { + int count = 0; + int indexInSuggestedWords; + for (indexInSuggestedWords = 0; indexInSuggestedWords < suggestedWords.size() + && count < maxSuggestionInStrip; indexInSuggestedWords++) { final int positionInStrip = getPositionInSuggestionStrip(indexInSuggestedWords, suggestedWords); + if (positionInStrip < 0) { + continue; + } final TextView wordView = mWordViews.get(positionInStrip); // {@link TextView#getTag()} is used to get the index in suggestedWords at // {@link SuggestionStripView#onClick(View)}. @@ -453,10 +517,12 @@ final class SuggestionStripLayoutHelper { mDebugInfoViews.get(positionInStrip).setText( suggestedWords.getDebugString(indexInSuggestedWords)); } + count++; } + return indexInSuggestedWords; } - private int layoutPunctuationSuggestionsAndReturnSuggestionCountInStrip( + private int layoutPunctuationsAndReturnStartIndexOfMoreSuggestions( final PunctuationSuggestions punctuationSuggestions, final ViewGroup stripView) { final int countInStrip = Math.min(punctuationSuggestions.size(), PUNCTUATIONS_IN_STRIP); for (int positionInStrip = 0; positionInStrip < countInStrip; positionInStrip++) { @@ -483,8 +549,11 @@ final class SuggestionStripLayoutHelper { } public void layoutAddToDictionaryHint(final String word, final ViewGroup addToDictionaryStrip) { + final boolean shouldShowUiToAcceptTypedWord = Settings.getInstance().getCurrent() + .mShouldShowUiToAcceptTypedWord; final int stripWidth = addToDictionaryStrip.getWidth(); - final int width = stripWidth - mDividerWidth - mPadding * 2; + final int width = shouldShowUiToAcceptTypedWord ? stripWidth + : stripWidth - mDividerWidth - mPadding * 2; final TextView wordView = (TextView)addToDictionaryStrip.findViewById(R.id.word_to_save); wordView.setTextColor(mColorTypedWord); @@ -494,25 +563,38 @@ final class SuggestionStripLayoutHelper { wordView.setText(wordToSave); wordView.setTextScaleX(wordScaleX); setLayoutWeight(wordView, mCenterSuggestionWeight, ViewGroup.LayoutParams.MATCH_PARENT); + final int wordVisibility = shouldShowUiToAcceptTypedWord ? View.GONE : View.VISIBLE; + wordView.setVisibility(wordVisibility); + addToDictionaryStrip.findViewById(R.id.word_to_save_divider).setVisibility(wordVisibility); + final Resources res = addToDictionaryStrip.getResources(); + final CharSequence hintText; + final int hintWidth; + final float hintWeight; final TextView hintView = (TextView)addToDictionaryStrip.findViewById( R.id.hint_add_to_dictionary); + if (shouldShowUiToAcceptTypedWord) { + hintText = res.getText(R.string.hint_add_to_dictionary_without_word); + hintWidth = width; + hintWeight = 1.0f; + hintView.setGravity(Gravity.CENTER); + } else { + final boolean isRtlLanguage = (ViewCompat.getLayoutDirection(addToDictionaryStrip) + == ViewCompat.LAYOUT_DIRECTION_RTL); + final String arrow = isRtlLanguage ? RIGHTWARDS_ARROW : LEFTWARDS_ARROW; + final boolean isRtlSystem = SubtypeLocaleUtils.isRtlLanguage( + res.getConfiguration().locale); + final CharSequence hint = res.getText(R.string.hint_add_to_dictionary); + hintText = (isRtlLanguage == isRtlSystem) ? (arrow + hint) : (hint + arrow); + hintWidth = width - wordWidth; + hintWeight = 1.0f - mCenterSuggestionWeight; + hintView.setGravity(Gravity.CENTER_VERTICAL | Gravity.START); + } hintView.setTextColor(mColorAutoCorrect); - final boolean isRtlLanguage = (ViewCompat.getLayoutDirection(addToDictionaryStrip) - == ViewCompat.LAYOUT_DIRECTION_RTL); - final String arrow = isRtlLanguage ? RIGHTWARDS_ARROW : LEFTWARDS_ARROW; - final Resources res = addToDictionaryStrip.getResources(); - final boolean isRtlSystem = SubtypeLocaleUtils.isRtlLanguage(res.getConfiguration().locale); - final CharSequence hintText = res.getText(R.string.hint_add_to_dictionary); - final String hintWithArrow = (isRtlLanguage == isRtlSystem) - ? (arrow + hintText) : (hintText + arrow); - final int hintWidth = width - wordWidth; - hintView.setTextScaleX(1.0f); // Reset textScaleX. - final float hintScaleX = getTextScaleX(hintWithArrow, hintWidth, hintView.getPaint()); - hintView.setText(hintWithArrow); + final float hintScaleX = getTextScaleX(hintText, hintWidth, hintView.getPaint()); + hintView.setText(hintText); hintView.setTextScaleX(hintScaleX); - setLayoutWeight( - hintView, 1.0f - mCenterSuggestionWeight, ViewGroup.LayoutParams.MATCH_PARENT); + setLayoutWeight(hintView, hintWeight, ViewGroup.LayoutParams.MATCH_PARENT); } public void layoutImportantNotice(final View importantNoticeStrip, diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java index 9b8c38a2d..33745a846 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java +++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java @@ -83,7 +83,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick Listener mListener; private SuggestedWords mSuggestedWords = SuggestedWords.EMPTY; - private int mSuggestionsCountInStrip; + private int mStartIndexOfMoreSuggestions; private final SuggestionStripLayoutHelper mLayoutHelper; private final StripVisibilityGroup mStripVisibilityGroup; @@ -214,7 +214,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick clear(); mStripVisibilityGroup.setLayoutDirection(isRtlLanguage); mSuggestedWords = suggestedWords; - mSuggestionsCountInStrip = mLayoutHelper.layoutAndReturnSuggestionCountInStrip( + mStartIndexOfMoreSuggestions = mLayoutHelper.layoutAndReturnStartIndexOfMoreSuggestions( mSuggestedWords, mSuggestionsStrip, this); mStripVisibilityGroup.showSuggestionsStrip(); } @@ -337,7 +337,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick return false; } final SuggestionStripLayoutHelper layoutHelper = mLayoutHelper; - if (!layoutHelper.mMoreSuggestionsAvailable) { + if (mSuggestedWords.size() <= mStartIndexOfMoreSuggestions) { return false; } // Dismiss another {@link MoreKeysPanel} that may be being showed, for example @@ -350,7 +350,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick final View container = mMoreSuggestionsContainer; final int maxWidth = stripWidth - container.getPaddingLeft() - container.getPaddingRight(); final MoreSuggestions.Builder builder = mMoreSuggestionsBuilder; - builder.layout(mSuggestedWords, mSuggestionsCountInStrip, maxWidth, + builder.layout(mSuggestedWords, mStartIndexOfMoreSuggestions, maxWidth, (int)(maxWidth * layoutHelper.mMinMoreSuggestionsWidth), layoutHelper.getMaxMoreSuggestionsRow(), parentKeyboard); mMoreSuggestionsView.setKeyboard(builder.build()); @@ -363,7 +363,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick mMoreSuggestionsListener); mOriginX = mLastX; mOriginY = mLastY; - for (int i = 0; i < mSuggestionsCountInStrip; i++) { + for (int i = 0; i < mStartIndexOfMoreSuggestions; i++) { mWordViews.get(i).setPressed(false); } return true; diff --git a/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java b/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java index 351d01400..0db4106c5 100644 --- a/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java @@ -30,6 +30,7 @@ import com.android.inputmethod.latin.R; import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.Locale; public final class SubtypeLocaleUtils { @@ -52,6 +53,8 @@ public final class SubtypeLocaleUtils { private static final HashMap<String, String> sKeyboardLayoutToDisplayNameMap = new HashMap<>(); // Keyboard layout to subtype name resource id map. private static final HashMap<String, Integer> sKeyboardLayoutToNameIdsMap = new HashMap<>(); + // Exceptional locale whose name should be displayed in Locale.ROOT. + static final HashSet<String> sExceptionalLocaleDisplayedInRootLocale = new HashSet<>(); // Exceptional locale to subtype name resource id map. private static final HashMap<String, Integer> sExceptionalLocaleToNameIdsMap = new HashMap<>(); // Exceptional locale to subtype name with layout resource id map. @@ -106,6 +109,12 @@ public final class SubtypeLocaleUtils { sKeyboardLayoutToNameIdsMap.put(key, noLanguageResId); } + final String[] excetionalLocaleInRootLocale = res.getStringArray( + R.array.subtype_locale_displayed_in_root_locale); + for (int i = 0; i < excetionalLocaleInRootLocale.length; i++) { + sExceptionalLocaleDisplayedInRootLocale.add(excetionalLocaleInRootLocale[i]); + } + final String[] exceptionalLocales = res.getStringArray( R.array.subtype_locale_exception_keys); for (int i = 0; i < exceptionalLocales.length; i++) { @@ -157,6 +166,9 @@ public final class SubtypeLocaleUtils { if (NO_LANGUAGE.equals(localeString)) { return sResources.getConfiguration().locale; } + if (sExceptionalLocaleDisplayedInRootLocale.contains(localeString)) { + return Locale.ROOT; + } return LocaleUtils.constructLocaleFromString(localeString); } @@ -171,9 +183,15 @@ public final class SubtypeLocaleUtils { } public static String getSubtypeLanguageDisplayName(final String localeString) { - final Locale locale = LocaleUtils.constructLocaleFromString(localeString); final Locale displayLocale = getDisplayLocaleOfSubtypeLocale(localeString); - return getSubtypeLocaleDisplayNameInternal(locale.getLanguage(), displayLocale); + final String languageString; + if (sExceptionalLocaleDisplayedInRootLocale.contains(localeString)) { + languageString = localeString; + } else { + final Locale locale = LocaleUtils.constructLocaleFromString(localeString); + languageString = locale.getLanguage(); + } + return getSubtypeLocaleDisplayNameInternal(languageString, displayLocale); } private static String getSubtypeLocaleDisplayNameInternal(final String localeString, diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.h index 361dd2c74..20bae5943 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.h +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.h @@ -17,7 +17,6 @@ #ifndef LATINIME_BIGRAM_DICT_CONTENT_H #define LATINIME_BIGRAM_DICT_CONTENT_H -#include <cstdint> #include <cstdio> #include "defines.h" @@ -28,11 +27,12 @@ namespace latinime { +class ReadWriteByteArrayView; + class BigramDictContent : public SparseTableDictContent { public: - BigramDictContent(uint8_t *const *buffers, const int *bufferSizes, const bool hasHistoricalInfo) - : SparseTableDictContent(buffers, bufferSizes, - Ver4DictConstants::BIGRAM_ADDRESS_TABLE_BLOCK_SIZE, + BigramDictContent(const ReadWriteByteArrayView *const buffers, const bool hasHistoricalInfo) + : SparseTableDictContent(buffers, Ver4DictConstants::BIGRAM_ADDRESS_TABLE_BLOCK_SIZE, Ver4DictConstants::BIGRAM_ADDRESS_TABLE_DATA_SIZE), mHasHistoricalInfo(hasHistoricalInfo) {} diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/probability_entry.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/probability_entry.h index ed77bd20e..3dfaba755 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/probability_entry.h +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/probability_entry.h @@ -43,14 +43,13 @@ class ProbabilityEntry { : mFlags(flags), mProbability(probability), mHistoricalInfo() {} // Entry with historical information. - ProbabilityEntry(const int flags, const int probability, - const HistoricalInfo *const historicalInfo) - : mFlags(flags), mProbability(probability), mHistoricalInfo(*historicalInfo) {} + ProbabilityEntry(const int flags, const HistoricalInfo *const historicalInfo) + : mFlags(flags), mProbability(NOT_A_PROBABILITY), mHistoricalInfo(*historicalInfo) {} // Create from unigram property. - // TODO: Set flags. ProbabilityEntry(const UnigramProperty *const unigramProperty) - : mFlags(0), mProbability(unigramProperty->getProbability()), + : mFlags(createFlags(unigramProperty->representsBeginningOfSentence())), + mProbability(unigramProperty->getProbability()), mHistoricalInfo(unigramProperty->getTimestamp(), unigramProperty->getLevel(), unigramProperty->getCount()) {} @@ -61,15 +60,6 @@ class ProbabilityEntry { mHistoricalInfo(bigramProperty->getTimestamp(), bigramProperty->getLevel(), bigramProperty->getCount()) {} - const ProbabilityEntry createEntryWithUpdatedProbability(const int probability) const { - return ProbabilityEntry(mFlags, probability, &mHistoricalInfo); - } - - const ProbabilityEntry createEntryWithUpdatedHistoricalInfo( - const HistoricalInfo *const historicalInfo) const { - return ProbabilityEntry(mFlags, mProbability, historicalInfo); - } - bool isValid() const { return (mProbability != NOT_A_PROBABILITY) || hasHistoricalInfo(); } @@ -78,7 +68,7 @@ class ProbabilityEntry { return mHistoricalInfo.isValid(); } - int getFlags() const { + uint8_t getFlags() const { return mFlags; } @@ -90,6 +80,10 @@ class ProbabilityEntry { return &mHistoricalInfo; } + bool representsBeginningOfSentence() const { + return (mFlags & Ver4DictConstants::FLAG_REPRESENTS_BEGINNING_OF_SENTENCE) != 0; + } + uint64_t encode(const bool hasHistoricalInfo) const { uint64_t encodedEntry = static_cast<uint64_t>(mFlags); if (hasHistoricalInfo) { @@ -123,7 +117,7 @@ class ProbabilityEntry { const int count = readFromEncodedEntry(encodedEntry, Ver4DictConstants::WORD_COUNT_FIELD_SIZE, 0 /* pos */); const HistoricalInfo historicalInfo(timestamp, level, count); - return ProbabilityEntry(flags, NOT_A_PROBABILITY, &historicalInfo); + return ProbabilityEntry(flags, &historicalInfo); } else { const int flags = readFromEncodedEntry(encodedEntry, Ver4DictConstants::FLAGS_IN_LANGUAGE_MODEL_SIZE, @@ -138,7 +132,7 @@ class ProbabilityEntry { // Copy constructor is public to use this class as a type of return value. DISALLOW_ASSIGNMENT_OPERATOR(ProbabilityEntry); - const int mFlags; + const uint8_t mFlags; const int mProbability; const HistoricalInfo mHistoricalInfo; @@ -146,6 +140,14 @@ class ProbabilityEntry { return static_cast<int>( (encodedEntry >> (pos * CHAR_BIT)) & ((1ull << (size * CHAR_BIT)) - 1)); } + + static uint8_t createFlags(const bool representsBeginningOfSentence) { + uint8_t flags = 0; + if (representsBeginningOfSentence) { + flags ^= Ver4DictConstants::FLAG_REPRESENTS_BEGINNING_OF_SENTENCE; + } + return flags; + } }; } // namespace latinime #endif /* LATINIME_PROBABILITY_ENTRY_H */ diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/shortcut_dict_content.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/shortcut_dict_content.h index 7b12aff16..85c9ce8d8 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/shortcut_dict_content.h +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/shortcut_dict_content.h @@ -17,7 +17,6 @@ #ifndef LATINIME_SHORTCUT_DICT_CONTENT_H #define LATINIME_SHORTCUT_DICT_CONTENT_H -#include <cstdint> #include <cstdio> #include "defines.h" @@ -27,11 +26,12 @@ namespace latinime { +class ReadWriteByteArrayView; + class ShortcutDictContent : public SparseTableDictContent { public: - ShortcutDictContent(uint8_t *const *buffers, const int *bufferSizes) - : SparseTableDictContent(buffers, bufferSizes, - Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE, + ShortcutDictContent(const ReadWriteByteArrayView *const buffers) + : SparseTableDictContent(buffers, Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE, Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_DATA_SIZE) {} ShortcutDictContent() diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/single_dict_content.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/single_dict_content.h index 921774181..309c434cf 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/single_dict_content.h +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/single_dict_content.h @@ -17,7 +17,6 @@ #ifndef LATINIME_SINGLE_DICT_CONTENT_H #define LATINIME_SINGLE_DICT_CONTENT_H -#include <cstdint> #include <cstdio> #include "defines.h" @@ -30,9 +29,9 @@ namespace latinime { class SingleDictContent { public: - SingleDictContent(uint8_t *const buffer, const int bufferSize) - : mExpandableContentBuffer(ReadWriteByteArrayView(buffer, bufferSize), - BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE) {} + SingleDictContent(const ReadWriteByteArrayView buffer) + : mExpandableContentBuffer(buffer, + BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE) {} SingleDictContent() : mExpandableContentBuffer(Ver4DictConstants::MAX_DICTIONARY_SIZE) {} diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/sparse_table_dict_content.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/sparse_table_dict_content.h index c98dd11fd..0ce2da7bf 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/sparse_table_dict_content.h +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/sparse_table_dict_content.h @@ -17,7 +17,6 @@ #ifndef LATINIME_SPARSE_TABLE_DICT_CONTENT_H #define LATINIME_SPARSE_TABLE_DICT_CONTENT_H -#include <cstdint> #include <cstdio> #include "defines.h" @@ -31,19 +30,13 @@ namespace latinime { // TODO: Support multiple contents. class SparseTableDictContent { public: - AK_FORCE_INLINE SparseTableDictContent(uint8_t *const *buffers, const int *bufferSizes, + AK_FORCE_INLINE SparseTableDictContent(const ReadWriteByteArrayView *const buffers, const int sparseTableBlockSize, const int sparseTableDataSize) - : mExpandableLookupTableBuffer( - ReadWriteByteArrayView(buffers[LOOKUP_TABLE_BUFFER_INDEX], - bufferSizes[LOOKUP_TABLE_BUFFER_INDEX]), + : mExpandableLookupTableBuffer(buffers[LOOKUP_TABLE_BUFFER_INDEX], BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE), - mExpandableAddressTableBuffer( - ReadWriteByteArrayView(buffers[ADDRESS_TABLE_BUFFER_INDEX], - bufferSizes[ADDRESS_TABLE_BUFFER_INDEX]), + mExpandableAddressTableBuffer(buffers[ADDRESS_TABLE_BUFFER_INDEX], BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE), - mExpandableContentBuffer( - ReadWriteByteArrayView(buffers[CONTENT_BUFFER_INDEX], - bufferSizes[CONTENT_BUFFER_INDEX]), + mExpandableContentBuffer(buffers[CONTENT_BUFFER_INDEX], BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE), mAddressLookupTable(&mExpandableLookupTableBuffer, &mExpandableAddressTableBuffer, sparseTableBlockSize, sparseTableDataSize) {} diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.h index b2262bf1e..febcbe5b4 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.h +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.h @@ -17,13 +17,13 @@ #ifndef LATINIME_TERMINAL_POSITION_LOOKUP_TABLE_H #define LATINIME_TERMINAL_POSITION_LOOKUP_TABLE_H -#include <cstdint> #include <cstdio> #include <unordered_map> #include "defines.h" #include "suggest/policyimpl/dictionary/structure/v4/content/single_dict_content.h" #include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h" +#include "utils/byte_array_view.h" namespace latinime { @@ -31,8 +31,8 @@ class TerminalPositionLookupTable : public SingleDictContent { public: typedef std::unordered_map<int, int> TerminalIdMap; - TerminalPositionLookupTable(uint8_t *const buffer, const int bufferSize) - : SingleDictContent(buffer, bufferSize), + TerminalPositionLookupTable(const ReadWriteByteArrayView buffer) + : SingleDictContent(buffer), mSize(getBuffer()->getTailPosition() / Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE) {} diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.cpp index 3c8008dc4..1f40e3dd2 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.cpp +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.cpp @@ -45,16 +45,13 @@ namespace latinime { if (!bodyBuffer) { return Ver4DictBuffersPtr(nullptr); } - std::vector<uint8_t *> buffers; - std::vector<int> bufferSizes; + std::vector<ReadWriteByteArrayView> buffers; const ReadWriteByteArrayView buffer = bodyBuffer->getReadWriteByteArrayView(); int position = 0; while (position < static_cast<int>(buffer.size())) { const int bufferSize = ByteArrayUtils::readUint32AndAdvancePosition( buffer.data(), &position); - const ReadWriteByteArrayView subBuffer = buffer.subView(position, bufferSize); - buffers.push_back(subBuffer.data()); - bufferSizes.push_back(subBuffer.size()); + buffers.push_back(buffer.subView(position, bufferSize)); position += bufferSize; if (bufferSize < 0 || position < 0 || position > static_cast<int>(buffer.size())) { AKLOGE("The dict body file is corrupted."); @@ -66,7 +63,7 @@ namespace latinime { return Ver4DictBuffersPtr(nullptr); } return Ver4DictBuffersPtr(new Ver4DictBuffers(std::move(headerBuffer), std::move(bodyBuffer), - formatVersion, buffers, bufferSizes)); + formatVersion, buffers)); } bool Ver4DictBuffers::flushHeaderAndDictBuffers(const char *const dictDirPath, @@ -178,29 +175,20 @@ bool Ver4DictBuffers::flushDictBuffers(FILE *const file) const { Ver4DictBuffers::Ver4DictBuffers(MmappedBuffer::MmappedBufferPtr &&headerBuffer, MmappedBuffer::MmappedBufferPtr &&bodyBuffer, const FormatUtils::FORMAT_VERSION formatVersion, - const std::vector<uint8_t *> &contentBuffers, const std::vector<int> &contentBufferSizes) + const std::vector<ReadWriteByteArrayView> &contentBuffers) : mHeaderBuffer(std::move(headerBuffer)), mDictBuffer(std::move(bodyBuffer)), mHeaderPolicy(mHeaderBuffer->getReadOnlyByteArrayView().data(), formatVersion), mExpandableHeaderBuffer(mHeaderBuffer->getReadWriteByteArrayView(), BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE), - mExpandableTrieBuffer( - ReadWriteByteArrayView(contentBuffers[Ver4DictConstants::TRIE_BUFFER_INDEX], - contentBufferSizes[Ver4DictConstants::TRIE_BUFFER_INDEX]), + mExpandableTrieBuffer(contentBuffers[Ver4DictConstants::TRIE_BUFFER_INDEX], BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE), mTerminalPositionLookupTable( - contentBuffers[Ver4DictConstants::TERMINAL_ADDRESS_LOOKUP_TABLE_BUFFER_INDEX], - contentBufferSizes[ - Ver4DictConstants::TERMINAL_ADDRESS_LOOKUP_TABLE_BUFFER_INDEX]), - mLanguageModelDictContent( - ReadWriteByteArrayView( - contentBuffers[Ver4DictConstants::LANGUAGE_MODEL_BUFFER_INDEX], - contentBufferSizes[Ver4DictConstants::LANGUAGE_MODEL_BUFFER_INDEX]), + contentBuffers[Ver4DictConstants::TERMINAL_ADDRESS_LOOKUP_TABLE_BUFFER_INDEX]), + mLanguageModelDictContent(contentBuffers[Ver4DictConstants::LANGUAGE_MODEL_BUFFER_INDEX], mHeaderPolicy.hasHistoricalInfoOfWords()), mBigramDictContent(&contentBuffers[Ver4DictConstants::BIGRAM_BUFFERS_INDEX], - &contentBufferSizes[Ver4DictConstants::BIGRAM_BUFFERS_INDEX], mHeaderPolicy.hasHistoricalInfoOfWords()), - mShortcutDictContent(&contentBuffers[Ver4DictConstants::SHORTCUT_BUFFERS_INDEX], - &contentBufferSizes[Ver4DictConstants::SHORTCUT_BUFFERS_INDEX]), + mShortcutDictContent(&contentBuffers[Ver4DictConstants::SHORTCUT_BUFFERS_INDEX]), mIsUpdatable(mDictBuffer->isUpdatable()) {} Ver4DictBuffers::Ver4DictBuffers(const HeaderPolicy *const headerPolicy, const int maxTrieSize) diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.h index 68027dcb8..70a7983f1 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.h +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.h @@ -122,8 +122,7 @@ class Ver4DictBuffers { Ver4DictBuffers(MmappedBuffer::MmappedBufferPtr &&headerBuffer, MmappedBuffer::MmappedBufferPtr &&bodyBuffer, const FormatUtils::FORMAT_VERSION formatVersion, - const std::vector<uint8_t *> &contentBuffers, - const std::vector<int> &contentBufferSizes); + const std::vector<ReadWriteByteArrayView> &contentBuffers); Ver4DictBuffers(const HeaderPolicy *const headerPolicy, const int maxTrieSize); diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.cpp index e622442ba..b085a6661 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.cpp +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.cpp @@ -54,6 +54,8 @@ const int Ver4DictConstants::TIME_STAMP_FIELD_SIZE = 4; const int Ver4DictConstants::WORD_LEVEL_FIELD_SIZE = 1; const int Ver4DictConstants::WORD_COUNT_FIELD_SIZE = 1; +const uint8_t Ver4DictConstants::FLAG_REPRESENTS_BEGINNING_OF_SENTENCE = 0x1; + const int Ver4DictConstants::BIGRAM_ADDRESS_TABLE_BLOCK_SIZE = 16; const int Ver4DictConstants::BIGRAM_ADDRESS_TABLE_DATA_SIZE = 4; const int Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE = 64; diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h index 8d29f60d4..230b3052d 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h @@ -20,6 +20,7 @@ #include "defines.h" #include <cstddef> +#include <cstdint> namespace latinime { @@ -48,6 +49,8 @@ class Ver4DictConstants { static const int TIME_STAMP_FIELD_SIZE; static const int WORD_LEVEL_FIELD_SIZE; static const int WORD_COUNT_FIELD_SIZE; + // Flags in probability entry. + static const uint8_t FLAG_REPRESENTS_BEGINNING_OF_SENTENCE; static const int BIGRAM_ADDRESS_TABLE_BLOCK_SIZE; static const int BIGRAM_ADDRESS_TABLE_DATA_SIZE; diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.cpp index 62e008b94..fb6840ba6 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.cpp +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.cpp @@ -164,8 +164,8 @@ bool Ver4PatriciaTrieNodeWriter::updatePtNodeProbabilityAndGetNeedsToKeepPtNodeA if (originalProbabilityEntry.hasHistoricalInfo()) { const HistoricalInfo historicalInfo = ForgettingCurveUtils::createHistoricalInfoToSave( originalProbabilityEntry.getHistoricalInfo(), mHeaderPolicy); - const ProbabilityEntry probabilityEntry = - originalProbabilityEntry.createEntryWithUpdatedHistoricalInfo(&historicalInfo); + const ProbabilityEntry probabilityEntry(originalProbabilityEntry.getFlags(), + &historicalInfo); if (!mBuffers->getMutableLanguageModelDictContent()->setProbabilityEntry( toBeUpdatedPtNodeParams->getTerminalId(), &probabilityEntry)) { AKLOGE("Cannot write updated probability entry. terminalId: %d", @@ -383,18 +383,15 @@ bool Ver4PatriciaTrieNodeWriter::writePtNodeAndGetTerminalIdAndAdvancePosition( const ProbabilityEntry Ver4PatriciaTrieNodeWriter::createUpdatedEntryFrom( const ProbabilityEntry *const originalProbabilityEntry, const ProbabilityEntry *const probabilityEntry) const { - // TODO: Consolidate historical info and probability. if (mHeaderPolicy->hasHistoricalInfoOfWords()) { const HistoricalInfo updatedHistoricalInfo = ForgettingCurveUtils::createUpdatedHistoricalInfo( originalProbabilityEntry->getHistoricalInfo(), probabilityEntry->getProbability(), probabilityEntry->getHistoricalInfo(), mHeaderPolicy); - return originalProbabilityEntry->createEntryWithUpdatedHistoricalInfo( - &updatedHistoricalInfo); + return ProbabilityEntry(probabilityEntry->getFlags(), &updatedHistoricalInfo); } else { - return originalProbabilityEntry->createEntryWithUpdatedProbability( - probabilityEntry->getProbability()); + return *probabilityEntry; } } diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/trie_map.cpp b/native/jni/src/suggest/policyimpl/dictionary/utils/trie_map.cpp index 944a59c52..39f417ebb 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/utils/trie_map.cpp +++ b/native/jni/src/suggest/policyimpl/dictionary/utils/trie_map.cpp @@ -85,7 +85,7 @@ int TrieMap::getNextLevelBitmapEntryIndex(const int key, const int bitmapEntryIn if (!writeEntry(EMPTY_BITMAP_ENTRY, valueEntryIndex + 1)) { return INVALID_INDEX; } - if (!writeField1(valueEntryIndex | TERMINAL_LINK_FLAG, valueEntryIndex)) { + if (!writeField1(valueEntryIndex | TERMINAL_LINK_FLAG, terminalEntryIndex)) { return INVALID_INDEX; } return valueEntryIndex + 1; diff --git a/native/jni/src/utils/byte_array_view.h b/native/jni/src/utils/byte_array_view.h index 2c97c6d58..10d7ae278 100644 --- a/native/jni/src/utils/byte_array_view.h +++ b/native/jni/src/utils/byte_array_view.h @@ -77,10 +77,12 @@ class ReadWriteByteArrayView { } private: - DISALLOW_ASSIGNMENT_OPERATOR(ReadWriteByteArrayView); + // Default copy constructor and assignment operator are used for using this class with STL + // containers. - uint8_t *const mPtr; - const size_t mSize; + // These members cannot be const to have the assignment operator. + uint8_t *mPtr; + size_t mSize; }; } // namespace latinime diff --git a/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content_test.cpp b/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content_test.cpp index a1a3b1a75..3cacba1c3 100644 --- a/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content_test.cpp +++ b/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content_test.cpp @@ -53,7 +53,7 @@ TEST(LanguageModelDictContentTest, TestUnigramProbabilityWithHistoricalInfo) { const int count = 10; const int wordId = 100; const HistoricalInfo historicalInfo(timestamp, level, count); - const ProbabilityEntry probabilityEntry(flag, NOT_A_PROBABILITY, &historicalInfo); + const ProbabilityEntry probabilityEntry(flag, &historicalInfo); LanguageModelDictContent.setProbabilityEntry(wordId, &probabilityEntry); const ProbabilityEntry entry = LanguageModelDictContent.getProbabilityEntry(wordId); EXPECT_EQ(flag, entry.getFlags()); diff --git a/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/probability_entry_test.cpp b/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/probability_entry_test.cpp index db94550ef..f0494f355 100644 --- a/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/probability_entry_test.cpp +++ b/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/probability_entry_test.cpp @@ -43,7 +43,7 @@ TEST(ProbabilityEntryTest, TestEncodeDecodeWithHistoricalInfo) { const int count = 10; const HistoricalInfo historicalInfo(timestamp, level, count); - const ProbabilityEntry entry(flag, NOT_A_PROBABILITY, &historicalInfo); + const ProbabilityEntry entry(flag, &historicalInfo); const uint64_t encodedEntry = entry.encode(true /* hasHistoricalInfo */); EXPECT_EQ(0xF03FFFFFFF030Aull, encodedEntry); diff --git a/native/jni/tests/suggest/policyimpl/dictionary/utils/trie_map_test.cpp b/native/jni/tests/suggest/policyimpl/dictionary/utils/trie_map_test.cpp index 9904a3aa8..56b5aa985 100644 --- a/native/jni/tests/suggest/policyimpl/dictionary/utils/trie_map_test.cpp +++ b/native/jni/tests/suggest/policyimpl/dictionary/utils/trie_map_test.cpp @@ -40,6 +40,7 @@ TEST(TrieMapTest, TestSetAndGet) { trieMap.putRoot(11, 1000); EXPECT_EQ(1000ull, trieMap.getRoot(11).mValue); const int next = trieMap.getNextLevelBitmapEntryIndex(10); + EXPECT_EQ(1000ull, trieMap.getRoot(10).mValue); trieMap.put(9, 9, next); EXPECT_EQ(9ull, trieMap.get(9, next).mValue); EXPECT_FALSE(trieMap.get(11, next).mIsValid); diff --git a/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetSubtypesCountTests.java b/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetSubtypesCountTests.java index eb67bc134..302f3b9fe 100644 --- a/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetSubtypesCountTests.java +++ b/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetSubtypesCountTests.java @@ -25,8 +25,8 @@ import java.util.ArrayList; @SmallTest public class KeyboardLayoutSetSubtypesCountTests extends KeyboardLayoutSetTestsBase { - private static final int NUMBER_OF_SUBTYPES = 77; - private static final int NUMBER_OF_ASCII_CAPABLE_SUBTYPES = 45; + private static final int NUMBER_OF_SUBTYPES = 78; + private static final int NUMBER_OF_ASCII_CAPABLE_SUBTYPES = 46; private static final int NUMBER_OF_PREDEFINED_ADDITIONAL_SUBTYPES = 2; @Override diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsHinglish.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsHinglish.java new file mode 100644 index 000000000..2a6e46f96 --- /dev/null +++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsHinglish.java @@ -0,0 +1,56 @@ +/* + * 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.keyboard.layout.tests; + +import android.test.suitebuilder.annotation.SmallTest; + +import com.android.inputmethod.keyboard.layout.LayoutBase; +import com.android.inputmethod.keyboard.layout.LayoutBase.LayoutCustomizer; +import com.android.inputmethod.keyboard.layout.Qwerty; +import com.android.inputmethod.keyboard.layout.Symbols; +import com.android.inputmethod.keyboard.layout.SymbolsShifted; +import com.android.inputmethod.keyboard.layout.expected.ExpectedKey; + +import java.util.Locale; + +/* + * hi_ZZ: Hinglish/qwerty + */ +@SmallTest +public final class TestsHinglish extends LayoutTestsBase { + private static final Locale LOCALE = new Locale("hi", "ZZ"); + private static final LayoutBase LAYOUT = new Qwerty(new HinglishCustomizer(LOCALE)); + + @Override + LayoutBase getLayout() { return LAYOUT; } + + private static class HinglishCustomizer extends LayoutCustomizer { + public HinglishCustomizer(final Locale locale) { super(locale); } + + @Override + public ExpectedKey getCurrencyKey() { return CURRENCY_RUPEE; } + + @Override + public ExpectedKey[] getOtherCurrencyKeys() { + return SymbolsShifted.CURRENCIES_OTHER_GENERIC; + } + + // U+20B9: "₹" INDIAN RUPEE SIGN + private static final ExpectedKey CURRENCY_RUPEE = key("\u20B9", + Symbols.CURRENCY_GENERIC_MORE_KEYS); + } +} diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java index eabd8d722..2b3fd892a 100644 --- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java +++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java @@ -548,28 +548,6 @@ public class BinaryDictEncoderUtils { } /** - * Helper method to write a signed children position to a file. - * - * @param buffer the buffer to write to. - * @param index the index in the buffer to write the address to. - * @param position the position to write. - * @return the size in bytes the address actually took. - */ - /* package */ static int writeSignedChildrenPosition(final byte[] buffer, int index, - final int position) { - if (!BinaryDictIOUtils.hasChildrenAddress(position)) { - buffer[index] = buffer[index + 1] = buffer[index + 2] = 0; - } else { - final int absPosition = Math.abs(position); - buffer[index++] = - (byte)((position < 0 ? FormatSpec.MSB8 : 0) | (0xFF & (absPosition >> 16))); - buffer[index++] = (byte)(0xFF & (absPosition >> 8)); - buffer[index++] = (byte)(0xFF & absPosition); - } - return 3; - } - - /** * Makes the flag value for a PtNode. * * @param hasMultipleChars whether the PtNode has multiple chars. @@ -734,10 +712,6 @@ public class BinaryDictEncoderUtils { final int ptNodeCount = ptNodeArray.mData.size(); dictEncoder.writePtNodeCount(ptNodeCount); - final int parentPosition = - (ptNodeArray.mCachedParentAddress == FormatSpec.NO_PARENT_ADDRESS) - ? FormatSpec.NO_PARENT_ADDRESS - : ptNodeArray.mCachedParentAddress + ptNodeArray.mCachedAddressAfterUpdate; for (int i = 0; i < ptNodeCount; ++i) { final PtNode ptNode = ptNodeArray.mData.get(i); if (dictEncoder.getPosition() != ptNode.mCachedAddressAfterUpdate) { diff --git a/tests/src/com/android/inputmethod/latin/makedict/DictEncoder.java b/tests/src/com/android/inputmethod/latin/makedict/DictEncoder.java index 678c5ca6b..645fd5c02 100644 --- a/tests/src/com/android/inputmethod/latin/makedict/DictEncoder.java +++ b/tests/src/com/android/inputmethod/latin/makedict/DictEncoder.java @@ -33,6 +33,5 @@ public interface DictEncoder { public void setPosition(final int position); public int getPosition(); public void writePtNodeCount(final int ptNodeCount); - public void writeForwardLinkAddress(final int forwardLinkAddress); public void writePtNode(final PtNode ptNode, final FusionDictionary dict); } diff --git a/tests/src/com/android/inputmethod/latin/makedict/Ver2DictEncoder.java b/tests/src/com/android/inputmethod/latin/makedict/Ver2DictEncoder.java index a286190cb..a7693d5ab 100644 --- a/tests/src/com/android/inputmethod/latin/makedict/Ver2DictEncoder.java +++ b/tests/src/com/android/inputmethod/latin/makedict/Ver2DictEncoder.java @@ -223,12 +223,6 @@ public class Ver2DictEncoder implements DictEncoder { } @Override - public void writeForwardLinkAddress(final int forwardLinkAddress) { - mPosition = BinaryDictEncoderUtils.writeUIntToBuffer(mBuffer, mPosition, forwardLinkAddress, - FormatSpec.FORWARD_LINK_ADDRESS_SIZE); - } - - @Override public void writePtNode(final PtNode ptNode, final FusionDictionary dict) { writePtNodeFlags(ptNode); writeCharacters(ptNode.mChars, ptNode.hasSeveralChars()); diff --git a/tests/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java b/tests/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java index 76eaef431..2e5435159 100644 --- a/tests/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java +++ b/tests/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java @@ -141,10 +141,6 @@ public class Ver4DictEncoder implements DictEncoder { } @Override - public void writeForwardLinkAddress(int forwardLinkAddress) { - } - - @Override public void writePtNode(PtNode ptNode, FusionDictionary dict) { } } diff --git a/tests/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryTests.java b/tests/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryTests.java index 0f2f9814b..b6562921e 100644 --- a/tests/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryTests.java +++ b/tests/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryTests.java @@ -78,7 +78,8 @@ public class PersonalizationDictionaryTests extends AndroidTestCase { tokens.add(CodePointUtils.generateWord(random, codePointSet)); } final PersonalizationDataChunk personalizationDataChunk = new PersonalizationDataChunk( - true /* inputByUser */, tokens, timeStampInSeconds, DUMMY_PACKAGE_NAME); + true /* inputByUser */, tokens, timeStampInSeconds, DUMMY_PACKAGE_NAME, + LOCALE_EN_US.getLanguage()); final CountDownLatch countDownLatch = new CountDownLatch(1); final AddMultipleDictionaryEntriesCallback callback = new AddMultipleDictionaryEntriesCallback() { diff --git a/tests/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelperTests.java b/tests/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelperTests.java new file mode 100644 index 000000000..f3273a2d1 --- /dev/null +++ b/tests/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelperTests.java @@ -0,0 +1,221 @@ +/* + * 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.suggestions; + +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.SmallTest; + +import com.android.inputmethod.latin.SuggestedWords; + +@SmallTest +public class SuggestionStripLayoutHelperTests extends AndroidTestCase { + private static void confirmShowTypedWord(final String message, final int inputType) { + assertFalse(message, SuggestionStripLayoutHelper.shouldOmitTypedWord( + inputType, + false /* gestureFloatingPreviewTextEnabled */, + false /* shouldShowUiToAcceptTypedWord */)); + assertFalse(message, SuggestionStripLayoutHelper.shouldOmitTypedWord( + inputType, + true /* gestureFloatingPreviewTextEnabled */, + false /* shouldShowUiToAcceptTypedWord */)); + assertFalse(message, SuggestionStripLayoutHelper.shouldOmitTypedWord( + inputType, + false /* gestureFloatingPreviewTextEnabled */, + true /* shouldShowUiToAcceptTypedWord */)); + assertFalse(message, SuggestionStripLayoutHelper.shouldOmitTypedWord( + inputType, + true /* gestureFloatingPreviewTextEnabled */, + true /* shouldShowUiToAcceptTypedWord */)); + } + + public void testShouldShowTypedWord() { + confirmShowTypedWord("no input style", + SuggestedWords.INPUT_STYLE_NONE); + confirmShowTypedWord("application specifed", + SuggestedWords.INPUT_STYLE_APPLICATION_SPECIFIED); + confirmShowTypedWord("recorrection", + SuggestedWords.INPUT_STYLE_RECORRECTION); + } + + public void testshouldOmitTypedWordWhileTyping() { + assertFalse("typing", SuggestionStripLayoutHelper.shouldOmitTypedWord( + SuggestedWords.INPUT_STYLE_TYPING, + false /* gestureFloatingPreviewTextEnabled */, + false /* shouldShowUiToAcceptTypedWord */)); + assertFalse("typing", SuggestionStripLayoutHelper.shouldOmitTypedWord( + SuggestedWords.INPUT_STYLE_TYPING, + true /* gestureFloatingPreviewTextEnabled */, + false /* shouldShowUiToAcceptTypedWord */)); + assertTrue("typing", SuggestionStripLayoutHelper.shouldOmitTypedWord( + SuggestedWords.INPUT_STYLE_TYPING, + false /* gestureFloatingPreviewTextEnabled */, + true /* shouldShowUiToAcceptTypedWord */)); + assertTrue("typing", SuggestionStripLayoutHelper.shouldOmitTypedWord( + SuggestedWords.INPUT_STYLE_TYPING, + true /* gestureFloatingPreviewTextEnabled */, + true /* shouldShowUiToAcceptTypedWord */)); + } + + public void testshouldOmitTypedWordWhileGesturing() { + assertFalse("gesturing", SuggestionStripLayoutHelper.shouldOmitTypedWord( + SuggestedWords.INPUT_STYLE_UPDATE_BATCH, + false /* gestureFloatingPreviewTextEnabled */, + false /* shouldShowUiToAcceptTypedWord */)); + assertFalse("gesturing", SuggestionStripLayoutHelper.shouldOmitTypedWord( + SuggestedWords.INPUT_STYLE_UPDATE_BATCH, + true /* gestureFloatingPreviewTextEnabled */, + false /* shouldShowUiToAcceptTypedWord */)); + assertFalse("gesturing", SuggestionStripLayoutHelper.shouldOmitTypedWord( + SuggestedWords.INPUT_STYLE_UPDATE_BATCH, + false /* gestureFloatingPreviewTextEnabled */, + true /* shouldShowUiToAcceptTypedWord */)); + assertTrue("gesturing", SuggestionStripLayoutHelper.shouldOmitTypedWord( + SuggestedWords.INPUT_STYLE_UPDATE_BATCH, + true /* gestureFloatingPreviewTextEnabled */, + true /* shouldShowUiToAcceptTypedWord */)); + } + + public void testshouldOmitTypedWordWhenGestured() { + assertFalse("gestured", SuggestionStripLayoutHelper.shouldOmitTypedWord( + SuggestedWords.INPUT_STYLE_TAIL_BATCH, + false /* gestureFloatingPreviewTextEnabled */, + false /* shouldShowUiToAcceptTypedWord */)); + assertFalse("gestured", SuggestionStripLayoutHelper.shouldOmitTypedWord( + SuggestedWords.INPUT_STYLE_TAIL_BATCH, + true /* gestureFloatingPreviewTextEnabled */, + false /* shouldShowUiToAcceptTypedWord */)); + assertTrue("gestured", SuggestionStripLayoutHelper.shouldOmitTypedWord( + SuggestedWords.INPUT_STYLE_TAIL_BATCH, + false /* gestureFloatingPreviewTextEnabled */, + true /* shouldShowUiToAcceptTypedWord */)); + assertTrue("gestured", SuggestionStripLayoutHelper.shouldOmitTypedWord( + SuggestedWords.INPUT_STYLE_TAIL_BATCH, + true /* gestureFloatingPreviewTextEnabled */, + true /* shouldShowUiToAcceptTypedWord */)); + } + + // Note that this unit test assumes that the number of suggested words in the suggestion strip + // is 3. + private static final int POSITION_OMIT = -1; + private static final int POSITION_LEFT = 0; + private static final int POSITION_CENTER = 1; + private static final int POSITION_RIGHT = 2; + + public void testGetPositionInSuggestionStrip() { + assertEquals("1st word without auto correction", POSITION_CENTER, + SuggestionStripLayoutHelper.getPositionInSuggestionStrip( + SuggestedWords.INDEX_OF_TYPED_WORD /* indexInSuggestedWords */, + false /* willAutoCorrect */, + false /* omitTypedWord */, + POSITION_CENTER /* centerPositionInStrip */, + POSITION_LEFT /* typedWordPositionWhenAutoCorrect */)); + assertEquals("2nd word without auto correction", POSITION_LEFT, + SuggestionStripLayoutHelper.getPositionInSuggestionStrip( + SuggestedWords.INDEX_OF_AUTO_CORRECTION /* indexInSuggestedWords */, + false /* willAutoCorrect */, + false /* omitTypedWord */, + POSITION_CENTER /* centerPositionInStrip */, + POSITION_LEFT /* typedWordPositionWhenAutoCorrect */)); + assertEquals("3rd word without auto correction", POSITION_RIGHT, + SuggestionStripLayoutHelper.getPositionInSuggestionStrip( + 2 /* indexInSuggestedWords */, + false /* willAutoCorrect */, + false /* omitTypedWord */, + POSITION_CENTER /* centerPositionInStrip */, + POSITION_LEFT /* typedWordPositionWhenAutoCorrect */)); + + assertEquals("typed word with auto correction", POSITION_LEFT, + SuggestionStripLayoutHelper.getPositionInSuggestionStrip( + SuggestedWords.INDEX_OF_TYPED_WORD /* indexInSuggestedWords */, + true /* willAutoCorrect */, + false /* omitTypedWord */, + POSITION_CENTER /* centerPositionInStrip */, + POSITION_LEFT /* typedWordPositionWhenAutoCorrect */)); + assertEquals("2nd word with auto correction", POSITION_CENTER, + SuggestionStripLayoutHelper.getPositionInSuggestionStrip( + SuggestedWords.INDEX_OF_AUTO_CORRECTION /* indexInSuggestedWords */, + true /* willAutoCorrect */, + false /* omitTypedWord */, + POSITION_CENTER /* centerPositionInStrip */, + POSITION_LEFT /* typedWordPositionWhenAutoCorrect */)); + assertEquals("3rd word with auto correction", POSITION_RIGHT, + SuggestionStripLayoutHelper.getPositionInSuggestionStrip( + 2 /* indexInSuggestedWords */, + true /* willAutoCorrect */, + false /* omitTypedWord */, + POSITION_CENTER /* centerPositionInStrip */, + POSITION_LEFT /* typedWordPositionWhenAutoCorrect */)); + + assertEquals("1st word without auto correction", POSITION_OMIT, + SuggestionStripLayoutHelper.getPositionInSuggestionStrip( + SuggestedWords.INDEX_OF_TYPED_WORD /* indexInSuggestedWords */, + false /* willAutoCorrect */, + true /* omitTypedWord */, + POSITION_CENTER /* centerPositionInStrip */, + POSITION_LEFT /* typedWordPositionWhenAutoCorrect */)); + assertEquals("2nd word without auto correction", POSITION_CENTER, + SuggestionStripLayoutHelper.getPositionInSuggestionStrip( + SuggestedWords.INDEX_OF_AUTO_CORRECTION /* indexInSuggestedWords */, + false /* willAutoCorrect */, + true /* omitTypedWord */, + POSITION_CENTER /* centerPositionInStrip */, + POSITION_LEFT /* typedWordPositionWhenAutoCorrect */)); + assertEquals("3rd word without auto correction", POSITION_LEFT, + SuggestionStripLayoutHelper.getPositionInSuggestionStrip( + 2 /* indexInSuggestedWords */, + false /* willAutoCorrect */, + true /* omitTypedWord */, + POSITION_CENTER /* centerPositionInStrip */, + POSITION_LEFT /* typedWordPositionWhenAutoCorrect */)); + assertEquals("4th word without auto correction", POSITION_RIGHT, + SuggestionStripLayoutHelper.getPositionInSuggestionStrip( + 3 /* indexInSuggestedWords */, + false /* willAutoCorrect */, + true /* omitTypedWord */, + POSITION_CENTER /* centerPositionInStrip */, + POSITION_LEFT /* typedWordPositionWhenAutoCorrect */)); + + assertEquals("typed word with auto correction", POSITION_OMIT, + SuggestionStripLayoutHelper.getPositionInSuggestionStrip( + SuggestedWords.INDEX_OF_TYPED_WORD /* indexInSuggestedWords */, + true /* willAutoCorrect */, + true /* omitTypedWord */, + POSITION_CENTER /* centerPositionInStrip */, + POSITION_LEFT /* typedWordPositionWhenAutoCorrect */)); + assertEquals("2nd word with auto correction", POSITION_CENTER, + SuggestionStripLayoutHelper.getPositionInSuggestionStrip( + SuggestedWords.INDEX_OF_AUTO_CORRECTION /* indexInSuggestedWords */, + true /* willAutoCorrect */, + true /* omitTypedWord */, + POSITION_CENTER /* centerPositionInStrip */, + POSITION_LEFT /* typedWordPositionWhenAutoCorrect */)); + assertEquals("3rd word with auto correction", POSITION_LEFT, + SuggestionStripLayoutHelper.getPositionInSuggestionStrip( + 2 /* indexInSuggestedWords */, + true /* willAutoCorrect */, + true /* omitTypedWord */, + POSITION_CENTER /* centerPositionInStrip */, + POSITION_LEFT /* typedWordPositionWhenAutoCorrect */)); + assertEquals("4th word with auto correction", POSITION_RIGHT, + SuggestionStripLayoutHelper.getPositionInSuggestionStrip( + 3 /* indexInSuggestedWords */, + true /* willAutoCorrect */, + true /* omitTypedWord */, + POSITION_CENTER /* centerPositionInStrip */, + POSITION_LEFT /* typedWordPositionWhenAutoCorrect */)); + } +} diff --git a/tests/src/com/android/inputmethod/latin/utils/SpacebarLanguagetUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/SpacebarLanguageUtilsTests.java index fdde34251..aef517ca8 100644 --- a/tests/src/com/android/inputmethod/latin/utils/SpacebarLanguagetUtilsTests.java +++ b/tests/src/com/android/inputmethod/latin/utils/SpacebarLanguageUtilsTests.java @@ -29,7 +29,7 @@ import java.util.ArrayList; import java.util.Locale; @SmallTest -public class SpacebarLanguagetUtilsTests extends AndroidTestCase { +public class SpacebarLanguageUtilsTests extends AndroidTestCase { // All input method subtypes of LatinIME. private final ArrayList<InputMethodSubtype> mSubtypesList = new ArrayList<>(); @@ -44,6 +44,7 @@ public class SpacebarLanguagetUtilsTests extends AndroidTestCase { InputMethodSubtype FR_CH; InputMethodSubtype DE; InputMethodSubtype DE_CH; + InputMethodSubtype HI_ZZ; InputMethodSubtype ZZ; InputMethodSubtype DE_QWERTY; InputMethodSubtype FR_QWERTZ; @@ -85,6 +86,8 @@ public class SpacebarLanguagetUtilsTests extends AndroidTestCase { Locale.GERMAN.toString(), "qwertz"); DE_CH = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet( "de_CH", "swiss"); + HI_ZZ = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet( + "hi_ZZ", "qwerty"); ZZ = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet( SubtypeLocaleUtils.NO_LANGUAGE, "qwerty"); DE_QWERTY = AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype( @@ -122,6 +125,12 @@ public class SpacebarLanguagetUtilsTests extends AndroidTestCase { for (final InputMethodSubtype subtype : mSubtypesList) { final String subtypeName = SubtypeLocaleUtils .getSubtypeDisplayNameInSystemLocale(subtype); + if (SubtypeLocaleUtils.sExceptionalLocaleDisplayedInRootLocale.contains( + subtype.getLocale())) { + // Skip test because the language part of this locale string doesn't represent + // the locale to be displayed on the spacebar (for example hi_ZZ and Hinglish). + continue; + } final String spacebarText = SpacebarLanguageUtils.getMiddleDisplayName(subtype); if (SubtypeLocaleUtils.isNoLanguage(subtype)) { assertEquals(subtypeName, @@ -147,6 +156,7 @@ public class SpacebarLanguagetUtilsTests extends AndroidTestCase { // fr_CH swiss F Français Français (Suisse) // de qwertz F Deutsch Deutsch // de_CH swiss F Deutsch Deutsch (Schweiz) + // hi_ZZ qwerty F Hinglish Hinglish // zz qwerty F QWERTY QWERTY // fr qwertz T Français Français // de qwerty T Deutsch Deutsch @@ -172,6 +182,8 @@ public class SpacebarLanguagetUtilsTests extends AndroidTestCase { SpacebarLanguageUtils.getFullDisplayName(DE)); assertEquals("de_CH", "Deutsch (Schweiz)", SpacebarLanguageUtils.getFullDisplayName(DE_CH)); + assertEquals("hi_ZZ", "Hinglish", + SpacebarLanguageUtils.getFullDisplayName(HI_ZZ)); assertEquals("zz", "QWERTY", SpacebarLanguageUtils.getFullDisplayName(ZZ)); @@ -191,6 +203,8 @@ public class SpacebarLanguagetUtilsTests extends AndroidTestCase { SpacebarLanguageUtils.getMiddleDisplayName(DE)); assertEquals("de_CH", "Deutsch", SpacebarLanguageUtils.getMiddleDisplayName(DE_CH)); + assertEquals("hi_ZZ", "Hinglish", + SpacebarLanguageUtils.getMiddleDisplayName(HI_ZZ)); assertEquals("zz", "QWERTY", SpacebarLanguageUtils.getMiddleDisplayName(ZZ)); return null; diff --git a/tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java index ce3df7dd6..4f0b3ccdc 100644 --- a/tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java +++ b/tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java @@ -44,6 +44,7 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase { InputMethodSubtype FR_CH; InputMethodSubtype DE; InputMethodSubtype DE_CH; + InputMethodSubtype HI_ZZ; InputMethodSubtype ZZ; InputMethodSubtype DE_QWERTY; InputMethodSubtype FR_QWERTZ; @@ -85,6 +86,8 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase { Locale.GERMAN.toString(), "qwertz"); DE_CH = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet( "de_CH", "swiss"); + HI_ZZ = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet( + "hi_ZZ", "qwerty"); ZZ = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet( SubtypeLocaleUtils.NO_LANGUAGE, "qwerty"); DE_QWERTY = AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype( @@ -128,6 +131,7 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase { assertEquals("fr_CH", "swiss", SubtypeLocaleUtils.getKeyboardLayoutSetName(FR_CH)); assertEquals("de", "qwertz", SubtypeLocaleUtils.getKeyboardLayoutSetName(DE)); assertEquals("de_CH", "swiss", SubtypeLocaleUtils.getKeyboardLayoutSetName(DE_CH)); + assertEquals("hi_ZZ", "qwerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(HI_ZZ)); assertEquals("zz", "qwerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(ZZ)); assertEquals("de qwerty", "qwerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(DE_QWERTY)); @@ -154,6 +158,7 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase { // fr_CH swiss F French (Switzerland) // de qwertz F German // de_CH swiss F German (Switzerland) + // hi_ZZ qwerty F Hinglish // zz qwerty F Alphabet (QWERTY) // fr qwertz T French (QWERTZ) // de qwerty T German (QWERTY) @@ -182,6 +187,8 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase { SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(DE)); assertEquals("de_CH", "German (Switzerland)", SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(DE_CH)); + assertEquals("hi_ZZ", "Hinglish", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(HI_ZZ)); assertEquals("zz", "Alphabet (QWERTY)", SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ZZ)); return null; @@ -226,6 +233,7 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase { // fr_CH swiss F Français (Suisse) // de qwertz F Allemand // de_CH swiss F Allemand (Suisse) + // hi_ZZ qwerty F Hinglish // zz qwerty F Alphabet latin (QWERTY) // fr qwertz T Français (QWERTZ) // de qwerty T Allemand (QWERTY) @@ -254,6 +262,8 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase { SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(DE)); assertEquals("de_CH", "Allemand (Suisse)", SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(DE_CH)); + assertEquals("hi_ZZ", "Hinglish", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(HI_ZZ)); assertEquals("zz", "Alphabet latin (QWERTY)", SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ZZ)); return null; diff --git a/tools/dicttool/Android.mk b/tools/dicttool/Android.mk index 0f1f34418..3e3d419e6 100644 --- a/tools/dicttool/Android.mk +++ b/tools/dicttool/Android.mk @@ -32,10 +32,12 @@ LOCAL_PATH := $(LATINIME_DICTTOOL_AOSP_LOCAL_PATH) include $(CLEAR_VARS) LATINIME_LOCAL_DIR := ../.. -LATINIME_BASE_SOURCE_DIRECTORY := $(LATINIME_LOCAL_DIR)/java/src/com/android/inputmethod -LATINIME_ANNOTATIONS_SOURCE_DIRECTORY := $(LATINIME_BASE_SOURCE_DIRECTORY)/annotations -MAKEDICT_CORE_SOURCE_DIRECTORY := $(LATINIME_BASE_SOURCE_DIRECTORY)/latin/makedict -LATINIME_TESTS_SOURCE_DIRECTORY := $(LATINIME_LOCAL_DIR)/tests/src/com/android/inputmethod/latin +LATINIME_BASE_SRC_DIR := $(LATINIME_LOCAL_DIR)/java/src/com/android/inputmethod +LATINIME_BASE_OVERRIDABLE_SRC_DIR := \ + $(LATINIME_LOCAL_DIR)/java-overridable/src/com/android/inputmethod +LATINIME_ANNOTATIONS_SRC_DIR := $(LATINIME_BASE_SRC_DIR)/annotations +MAKEDICT_CORE_SRC_DIR := $(LATINIME_BASE_SRC_DIR)/latin/makedict +LATINIME_TESTS_SRC_DIR := $(LATINIME_LOCAL_DIR)/tests/src/com/android/inputmethod/latin # Dependencies for Dicttool. Most of these files are needed by BinaryDictionary.java. Note that # a significant part of the dependencies are mocked in the compat/ directory, with empty or @@ -51,7 +53,6 @@ LATINIME_SRC_FILES_FOR_DICTTOOL := \ latin/PrevWordsInfo.java \ latin/SuggestedWords.java \ latin/WordComposer.java \ - latin/define/DebugFlags.java \ latin/settings/NativeSuggestOptions.java \ latin/settings/SettingsValuesForSuggestion.java \ latin/utils/BinaryDictionaryUtils.java \ @@ -63,29 +64,33 @@ LATINIME_SRC_FILES_FOR_DICTTOOL := \ latin/utils/ResizableIntArray.java \ latin/utils/StringUtils.java +LATINIME_OVERRIDABLE_SRC_FILES_FOR_DICTTOOL := \ + latin/define/DebugFlags.java + LATINIME_TEST_SRC_FILES_FOR_DICTTOOL := \ utils/ByteArrayDictBuffer.java -USED_TARGETED_SRCS := \ - $(addprefix $(LATINIME_BASE_SOURCE_DIRECTORY)/, $(LATINIME_SRC_FILES_FOR_DICTTOOL)) \ - $(addprefix $(LATINIME_TESTS_SOURCE_DIRECTORY)/, $(LATINIME_TEST_SRC_FILES_FOR_DICTTOOL)) +USED_TARGETED_SRC_FILES := \ + $(addprefix $(LATINIME_BASE_SRC_DIR)/, $(LATINIME_SRC_FILES_FOR_DICTTOOL)) \ + $(addprefix $(LATINIME_BASE_OVERRIDABLE_SRC_DIR)/, \ + $(LATINIME_OVERRIDABLE_SRC_FILES_FOR_DICTTOOL)) \ + $(addprefix $(LATINIME_TESTS_SRC_DIR)/, $(LATINIME_TEST_SRC_FILES_FOR_DICTTOOL)) -DICTTOOL_ONDEVICE_TESTS_DIRECTORY := \ +DICTTOOL_ONDEVICE_TESTS_DIR := \ $(LATINIME_LOCAL_DIR)/tests/src/com/android/inputmethod/latin/makedict/ -DICTTOOL_COMPAT_TESTS_DIRECTORY := compat +DICTTOOL_COMPAT_TESTS_DIR := compat -LOCAL_MAIN_SRC_FILES := $(call all-java-files-under, $(MAKEDICT_CORE_SOURCE_DIRECTORY)) +LOCAL_MAIN_SRC_FILES := $(call all-java-files-under, $(MAKEDICT_CORE_SRC_DIR)) LOCAL_TOOL_SRC_FILES := $(call all-java-files-under, src) -LOCAL_ANNOTATIONS_SRC_FILES := \ - $(call all-java-files-under, $(LATINIME_ANNOTATIONS_SOURCE_DIRECTORY)) +LOCAL_ANNOTATIONS_SRC_FILES := $(call all-java-files-under, $(LATINIME_ANNOTATIONS_SRC_DIR)) LOCAL_SRC_FILES := $(LOCAL_TOOL_SRC_FILES) \ $(filter-out $(addprefix %/, $(notdir $(LOCAL_TOOL_SRC_FILES))), $(LOCAL_MAIN_SRC_FILES)) \ - $(call all-java-files-under, $(DICTTOOL_COMPAT_TESTS_DIRECTORY)) \ - $(LOCAL_ANNOTATIONS_SRC_FILES) $(USED_TARGETED_SRCS) \ - $(LATINIME_BASE_SOURCE_DIRECTORY)/latin/Constants.java \ + $(call all-java-files-under, $(DICTTOOL_COMPAT_TESTS_DIR)) \ + $(LOCAL_ANNOTATIONS_SRC_FILES) $(USED_TARGETED_SRC_FILES) \ + $(LATINIME_BASE_SRC_DIR)/latin/Constants.java \ $(call all-java-files-under, tests) \ - $(call all-java-files-under, $(DICTTOOL_ONDEVICE_TESTS_DIRECTORY)) + $(call all-java-files-under, $(DICTTOOL_ONDEVICE_TESTS_DIR)) LOCAL_JAVA_LIBRARIES := junit LOCAL_STATIC_JAVA_LIBRARIES := jsr305lib diff --git a/tools/make-keyboard-text/res/values-hi-rZZ/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-hi-rZZ/donottranslate-more-keys.xml new file mode 100644 index 000000000..068639d77 --- /dev/null +++ b/tools/make-keyboard-text/res/values-hi-rZZ/donottranslate-more-keys.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 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. +*/ +--> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <!-- U+20B9: "₹" INDIAN RUPEE SIGN --> + <string name="keyspec_currency">₹</string> +</resources> |