aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--java/res/drawable-hdpi/sym_keyboard_smiley_lxx_light.pngbin1134 -> 1619 bytes
-rw-r--r--java/res/drawable-mdpi/sym_keyboard_smiley_lxx_light.pngbin777 -> 996 bytes
-rw-r--r--java/res/drawable-xhdpi/sym_keyboard_smiley_lxx_light.pngbin1344 -> 2089 bytes
-rw-r--r--java/res/drawable-xxhdpi/sym_keyboard_smiley_lxx_light.pngbin1967 -> 3338 bytes
-rw-r--r--java/res/values/attrs.xml3
-rw-r--r--java/res/values/donottranslate.xml6
-rw-r--r--java/res/values/keyboard-icons-holo.xml3
-rw-r--r--java/res/values/keyboard-icons-lxx-dark.xml3
-rw-r--r--java/res/values/keyboard-icons-lxx-light.xml5
-rw-r--r--java/res/xml-sw600dp/key_styles_common.xml2
-rw-r--r--java/res/xml-sw600dp/key_styles_enter.xml1
-rw-r--r--java/res/xml/key_styles_common.xml2
-rw-r--r--java/res/xml/key_styles_enter.xml18
-rw-r--r--java/res/xml/prefs_screen_debug.xml10
-rw-r--r--java/src/com/android/inputmethod/compat/BuildCompatUtils.java43
-rw-r--r--java/src/com/android/inputmethod/compat/CursorAnchorInfoCompatWrapper.java135
-rw-r--r--java/src/com/android/inputmethod/event/Event.java2
-rw-r--r--java/src/com/android/inputmethod/event/InputTransaction.java2
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java21
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardTheme.java18
-rw-r--r--java/src/com/android/inputmethod/keyboard/MainKeyboardView.java4
-rw-r--r--java/src/com/android/inputmethod/keyboard/emoji/EmojiCategory.java5
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyPreviewView.java51
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java6
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java4
-rw-r--r--java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java2
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java82
-rw-r--r--java/src/com/android/inputmethod/latin/PunctuationSuggestions.java3
-rw-r--r--java/src/com/android/inputmethod/latin/SpecialKeyDetector.java43
-rw-r--r--java/src/com/android/inputmethod/latin/Suggest.java37
-rw-r--r--java/src/com/android/inputmethod/latin/SuggestedWords.java30
-rw-r--r--java/src/com/android/inputmethod/latin/define/ProductionFlags.java2
-rw-r--r--java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java40
-rw-r--r--java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java9
-rw-r--r--java/src/com/android/inputmethod/latin/settings/DebugSettings.java4
-rw-r--r--java/src/com/android/inputmethod/latin/settings/DebugSettingsFragment.java7
-rw-r--r--java/src/com/android/inputmethod/latin/settings/Settings.java7
-rw-r--r--java/src/com/android/inputmethod/latin/settings/SettingsValues.java10
-rw-r--r--native/jni/src/suggest/core/dictionary/error_type_utils.cpp19
-rw-r--r--native/jni/src/suggest/core/dictionary/error_type_utils.h5
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_writer.cpp16
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_writer.h5
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.cpp20
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.h5
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.cpp6
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.cpp15
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.h2
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/probability_entry.h24
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.cpp2
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h2
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.cpp41
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.h6
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp6
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.cpp10
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.h5
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/utils/trie_map.cpp71
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/utils/trie_map.h11
-rw-r--r--native/jni/src/suggest/policyimpl/typing/typing_scoring.h4
-rw-r--r--native/jni/src/suggest/policyimpl/typing/typing_weighting.cpp29
-rw-r--r--native/jni/src/utils/int_array_view.h5
-rw-r--r--native/jni/tests/suggest/policyimpl/dictionary/utils/trie_map_test.cpp25
-rw-r--r--native/jni/tests/utils/int_array_view_test.cpp17
-rw-r--r--tests/src/com/android/inputmethod/keyboard/KeyboardThemeTests.java4
-rw-r--r--tests/src/com/android/inputmethod/keyboard/layout/ArmenianPhonetic.java26
-rw-r--r--tests/src/com/android/inputmethod/keyboard/layout/Khmer.java26
-rw-r--r--tests/src/com/android/inputmethod/keyboard/layout/Lao.java26
-rw-r--r--tests/src/com/android/inputmethod/keyboard/layout/LayoutBase.java33
-rw-r--r--tests/src/com/android/inputmethod/keyboard/layout/Myanmar.java26
-rw-r--r--tests/src/com/android/inputmethod/keyboard/layout/PcQwerty.java7
-rw-r--r--tests/src/com/android/inputmethod/keyboard/layout/Symbols.java4
-rw-r--r--tests/src/com/android/inputmethod/keyboard/layout/SymbolsShifted.java4
-rw-r--r--tests/src/com/android/inputmethod/keyboard/layout/Thai.java26
-rw-r--r--tests/src/com/android/inputmethod/keyboard/layout/expected/AbstractLayoutBase.java9
-rw-r--r--tests/src/com/android/inputmethod/keyboard/layout/tests/TestsMalayalamIN.java2
-rw-r--r--tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java32
-rw-r--r--tests/src/com/android/inputmethod/latin/SuggestedWordsTests.java6
-rw-r--r--tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java72
-rw-r--r--tools/make-keyboard-text/res/values/donottranslate-more-keys.xml2
78 files changed, 937 insertions, 339 deletions
diff --git a/java/res/drawable-hdpi/sym_keyboard_smiley_lxx_light.png b/java/res/drawable-hdpi/sym_keyboard_smiley_lxx_light.png
index 2cfe1d406..b1fe2c0b1 100644
--- a/java/res/drawable-hdpi/sym_keyboard_smiley_lxx_light.png
+++ b/java/res/drawable-hdpi/sym_keyboard_smiley_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_smiley_lxx_light.png b/java/res/drawable-mdpi/sym_keyboard_smiley_lxx_light.png
index ff49d58e1..e639416cd 100644
--- a/java/res/drawable-mdpi/sym_keyboard_smiley_lxx_light.png
+++ b/java/res/drawable-mdpi/sym_keyboard_smiley_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_smiley_lxx_light.png b/java/res/drawable-xhdpi/sym_keyboard_smiley_lxx_light.png
index df3eba750..0d8c33bcd 100644
--- a/java/res/drawable-xhdpi/sym_keyboard_smiley_lxx_light.png
+++ b/java/res/drawable-xhdpi/sym_keyboard_smiley_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/sym_keyboard_smiley_lxx_light.png b/java/res/drawable-xxhdpi/sym_keyboard_smiley_lxx_light.png
index 08d4f8adc..ef5bf5a6f 100644
--- a/java/res/drawable-xxhdpi/sym_keyboard_smiley_lxx_light.png
+++ b/java/res/drawable-xxhdpi/sym_keyboard_smiley_lxx_light.png
Binary files differ
diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml
index bfe385698..e89912a9d 100644
--- a/java/res/values/attrs.xml
+++ b/java/res/values/attrs.xml
@@ -242,7 +242,8 @@
<attr name="iconZwnjKey" format="reference" />
<attr name="iconZwjKey" format="reference" />
<attr name="iconImeKey" format="reference" />
- <attr name="iconEmojiKey" format="reference" />
+ <attr name="iconEmojiActionKey" format="reference" />
+ <attr name="iconEmojiNormalKey" format="reference" />
</declare-styleable>
<declare-styleable name="Keyboard_GridRows">
diff --git a/java/res/values/donottranslate.xml b/java/res/values/donottranslate.xml
index e3f0aeade..b25a20803 100644
--- a/java/res/values/donottranslate.xml
+++ b/java/res/values/donottranslate.xml
@@ -22,10 +22,12 @@
See {@link SettingsValues#needsToShowVoiceInputKey(SharedPreferences,Resources)} -->
<string name="voice_mode_main">0</string>
- <!-- Title for Latin keyboard debug settings activity / dialog -->
- <string name="english_ime_debug_settings">Android keyboard Debug settings</string>
+ <!-- Title for Android keyboard debug settings activity / dialog -->
+ <string name="english_ime_debug_settings">Android Keyboard Debug settings</string>
<string name="prefs_debug_mode">Debug Mode</string>
<string name="prefs_force_non_distinct_multitouch">Force non-distinct multitouch</string>
+ <string name="prefs_force_physical_keyboard_special_key">Force physical keyboard special key</string>
+ <string name="prefs_show_ui_to_accept_typed_word">Show UI to accept typed word</string>
<!-- Subtype locale display name exceptions.
For each exception, there should be related string resources for display name that may have
diff --git a/java/res/values/keyboard-icons-holo.xml b/java/res/values/keyboard-icons-holo.xml
index d95ff8201..f5484bf4e 100644
--- a/java/res/values/keyboard-icons-holo.xml
+++ b/java/res/values/keyboard-icons-holo.xml
@@ -35,6 +35,7 @@
<item name="iconLanguageSwitchKey">@drawable/sym_keyboard_language_switch_dark</item>
<item name="iconZwnjKey">@drawable/sym_keyboard_zwnj_holo_dark</item>
<item name="iconZwjKey">@drawable/sym_keyboard_zwj_holo_dark</item>
- <item name="iconEmojiKey">@drawable/sym_keyboard_smiley_holo_dark</item>
+ <item name="iconEmojiActionKey">@drawable/sym_keyboard_smiley_holo_dark</item>
+ <item name="iconEmojiNormalKey">@drawable/sym_keyboard_smiley_holo_dark</item>
</style>
</resources>
diff --git a/java/res/values/keyboard-icons-lxx-dark.xml b/java/res/values/keyboard-icons-lxx-dark.xml
index dfa585c16..305df02cd 100644
--- a/java/res/values/keyboard-icons-lxx-dark.xml
+++ b/java/res/values/keyboard-icons-lxx-dark.xml
@@ -40,6 +40,7 @@
<item name="iconLanguageSwitchKey">@drawable/sym_keyboard_language_switch_lxx_dark</item>
<item name="iconZwnjKey">@drawable/sym_keyboard_zwnj_lxx_dark</item>
<item name="iconZwjKey">@drawable/sym_keyboard_zwj_lxx_dark</item>
- <item name="iconEmojiKey">@drawable/sym_keyboard_smiley_lxx_dark</item>
+ <item name="iconEmojiActionKey">@drawable/sym_keyboard_smiley_lxx_dark</item>
+ <item name="iconEmojiNormalKey">@drawable/sym_keyboard_smiley_lxx_dark</item>
</style>
</resources>
diff --git a/java/res/values/keyboard-icons-lxx-light.xml b/java/res/values/keyboard-icons-lxx-light.xml
index e8a3c56cd..866dc682f 100644
--- a/java/res/values/keyboard-icons-lxx-light.xml
+++ b/java/res/values/keyboard-icons-lxx-light.xml
@@ -40,6 +40,9 @@
<item name="iconLanguageSwitchKey">@drawable/sym_keyboard_language_switch_lxx_light</item>
<item name="iconZwnjKey">@drawable/sym_keyboard_zwnj_lxx_light</item>
<item name="iconZwjKey">@drawable/sym_keyboard_zwj_lxx_light</item>
- <item name="iconEmojiKey">@drawable/sym_keyboard_smiley_lxx_light</item>
+ <!-- Use white emoji icon (for lxx_dark) because an action key has green/dark color background. -->
+ <item name="iconEmojiActionKey">@drawable/sym_keyboard_smiley_lxx_dark</item>
+ <!-- Use dark green emoji icon (for lxx_light) because a normal key has white color background. -->
+ <item name="iconEmojiNormalKey">@drawable/sym_keyboard_smiley_lxx_light</item>
</style>
</resources>
diff --git a/java/res/xml-sw600dp/key_styles_common.xml b/java/res/xml-sw600dp/key_styles_common.xml
index 877c796c7..1b52b1efd 100644
--- a/java/res/xml-sw600dp/key_styles_common.xml
+++ b/java/res/xml-sw600dp/key_styles_common.xml
@@ -105,7 +105,7 @@
latin:altCode="!code/key_space" />
<key-style
latin:styleName="emojiKeyStyle"
- latin:keySpec="!icon/emoji_key|!code/key_emoji"
+ latin:keySpec="!icon/emoji_normal_key|!code/key_emoji"
latin:keyActionFlags="noKeyPreview"
latin:backgroundType="functional" />
<key-style
diff --git a/java/res/xml-sw600dp/key_styles_enter.xml b/java/res/xml-sw600dp/key_styles_enter.xml
index d0167d336..c20523b2a 100644
--- a/java/res/xml-sw600dp/key_styles_enter.xml
+++ b/java/res/xml-sw600dp/key_styles_enter.xml
@@ -21,7 +21,6 @@
<merge
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
>
- <!-- TODO: Stop using many conditional cases for keyspec_emoji_key. There are way too many to maintain. -->
<!-- Navigate more keys style -->
<switch>
<!-- latin:passwordInput="true" -->
diff --git a/java/res/xml/key_styles_common.xml b/java/res/xml/key_styles_common.xml
index bc739f7d0..2d006c992 100644
--- a/java/res/xml/key_styles_common.xml
+++ b/java/res/xml/key_styles_common.xml
@@ -80,7 +80,7 @@
<!-- emojiKeyStyle must be defined before including @xml/key_syles_enter. -->
<key-style
latin:styleName="emojiKeyStyle"
- latin:keySpec="!icon/emoji_key|!code/key_emoji"
+ latin:keySpec="!icon/emoji_action_key|!code/key_emoji"
latin:keyActionFlags="noKeyPreview"
latin:backgroundType="action" />
<include
diff --git a/java/res/xml/key_styles_enter.xml b/java/res/xml/key_styles_enter.xml
index 960c79c18..55dab78c3 100644
--- a/java/res/xml/key_styles_enter.xml
+++ b/java/res/xml/key_styles_enter.xml
@@ -21,7 +21,7 @@
<merge
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
>
- <!-- TODO: Stop using many conditional cases for keyspec_emoji_key. There are way too many to maintain. -->
+ <!-- TODO: Stop using many conditional cases for keyspec_emoji_action_key. There are way too many to maintain. -->
<!-- Navigate more keys style -->
<switch>
<!-- latin:passwordInput="true" -->
@@ -182,7 +182,7 @@
<key-style
latin:styleName="navigateMoreKeysStyle"
latin:keyLabelFlags="hasPopupHint|preserveCase"
- latin:moreKeys="!fixedColumnOrder!2,!needsDividers!,!text/keyspec_emoji_key,!text/keyspec_action_previous" />
+ latin:moreKeys="!fixedColumnOrder!2,!needsDividers!,!text/keyspec_emoji_action_key,!text/keyspec_action_previous" />
</case>
<case
latin:imeAction="actionNext"
@@ -191,7 +191,7 @@
<key-style
latin:styleName="navigateMoreKeysStyle"
latin:keyLabelFlags="hasPopupHint|preserveCase"
- latin:moreKeys="!text/keyspec_emoji_key" />
+ latin:moreKeys="!text/keyspec_emoji_action_key" />
</case>
<case
latin:imeAction="actionPrevious"
@@ -200,7 +200,7 @@
<key-style
latin:styleName="navigateMoreKeysStyle"
latin:keyLabelFlags="hasPopupHint|preserveCase"
- latin:moreKeys="!fixedColumnOrder!2,!needsDividers!,!text/keyspec_emoji_key,!text/keyspec_action_next" />
+ latin:moreKeys="!fixedColumnOrder!2,!needsDividers!,!text/keyspec_emoji_action_key,!text/keyspec_action_next" />
</case>
<case
latin:imeAction="actionPrevious"
@@ -209,7 +209,7 @@
<key-style
latin:styleName="navigateMoreKeysStyle"
latin:keyLabelFlags="hasPopupHint|preserveCase"
- latin:moreKeys="!text/keyspec_emoji_key" />
+ latin:moreKeys="!text/keyspec_emoji_action_key" />
</case>
<case
latin:navigateNext="true"
@@ -218,7 +218,7 @@
<key-style
latin:styleName="navigateMoreKeysStyle"
latin:keyLabelFlags="hasPopupHint|preserveCase"
- latin:moreKeys="!fixedColumnOrder!3,!needsDividers!,!text/keyspec_emoji_key,!text/keyspec_action_previous,!text/keyspec_action_next" />
+ latin:moreKeys="!fixedColumnOrder!3,!needsDividers!,!text/keyspec_emoji_action_key,!text/keyspec_action_previous,!text/keyspec_action_next" />
</case>
<case
latin:navigateNext="true"
@@ -227,7 +227,7 @@
<key-style
latin:styleName="navigateMoreKeysStyle"
latin:keyLabelFlags="hasPopupHint|preserveCase"
- latin:moreKeys="!fixedColumnOrder!2,!needsDividers!,!text/keyspec_emoji_key,!text/keyspec_action_next" />
+ latin:moreKeys="!fixedColumnOrder!2,!needsDividers!,!text/keyspec_emoji_action_key,!text/keyspec_action_next" />
</case>
<case
latin:navigateNext="false"
@@ -236,7 +236,7 @@
<key-style
latin:styleName="navigateMoreKeysStyle"
latin:keyLabelFlags="hasPopupHint|preserveCase"
- latin:moreKeys="!fixedColumnOrder!2,!needsDividers!,!text/keyspec_emoji_key,!text/keyspec_action_previous" />
+ latin:moreKeys="!fixedColumnOrder!2,!needsDividers!,!text/keyspec_emoji_action_key,!text/keyspec_action_previous" />
</case>
<case
latin:navigateNext="false"
@@ -245,7 +245,7 @@
<key-style
latin:styleName="navigateMoreKeysStyle"
latin:keyLabelFlags="hasPopupHint|preserveCase"
- latin:moreKeys="!text/keyspec_emoji_key" />
+ latin:moreKeys="!text/keyspec_emoji_action_key" />
</case>
<default>
<key-style
diff --git a/java/res/xml/prefs_screen_debug.xml b/java/res/xml/prefs_screen_debug.xml
index ae29a8a82..965369a90 100644
--- a/java/res/xml/prefs_screen_debug.xml
+++ b/java/res/xml/prefs_screen_debug.xml
@@ -31,6 +31,16 @@
android:defaultValue="false"
android:persistent="true" />
<CheckBoxPreference
+ android:key="force_physical_keyboard_special_key"
+ android:title="@string/prefs_force_physical_keyboard_special_key"
+ android:defaultValue="false"
+ android:persistent="true" />
+ <CheckBoxPreference
+ android:key="pref_show_ui_to_accept_typed_word"
+ android:title="@string/prefs_show_ui_to_accept_typed_word"
+ android:defaultValue="true"
+ android:persistent="true" />
+ <CheckBoxPreference
android:key="pref_sliding_key_input_preview"
android:title="@string/sliding_key_input_preview"
android:summary="@string/sliding_key_input_preview_summary"
diff --git a/java/src/com/android/inputmethod/compat/BuildCompatUtils.java b/java/src/com/android/inputmethod/compat/BuildCompatUtils.java
new file mode 100644
index 000000000..7d1717bd1
--- /dev/null
+++ b/java/src/com/android/inputmethod/compat/BuildCompatUtils.java
@@ -0,0 +1,43 @@
+/*
+ * 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.compat;
+
+import android.os.Build;
+
+public final class BuildCompatUtils {
+ private BuildCompatUtils() {
+ // This utility class is not publicly instantiable.
+ }
+
+ private static final boolean IS_RELEASE_BUILD = Build.VERSION.CODENAME.equals("REL");
+
+ /**
+ * The "effective" API version.
+ * {@link android.os.Build.VERSION#SDK_INT} if the platform is a release build.
+ * {@link android.os.Build.VERSION#SDK_INT} plus 1 if the platform is a development build.
+ */
+ public static final int EFFECTIVE_SDK_INT = IS_RELEASE_BUILD
+ ? Build.VERSION.SDK_INT
+ : Build.VERSION.SDK_INT + 1;
+
+ /**
+ * API version for L-release.
+ */
+ // TODO: Substitute this constant reference with Build.VERSION_CODES.L* once the *next* version
+ // becomes available.
+ public static final int VERSION_CODES_LXX = 21;
+}
diff --git a/java/src/com/android/inputmethod/compat/CursorAnchorInfoCompatWrapper.java b/java/src/com/android/inputmethod/compat/CursorAnchorInfoCompatWrapper.java
new file mode 100644
index 000000000..2cec14240
--- /dev/null
+++ b/java/src/com/android/inputmethod/compat/CursorAnchorInfoCompatWrapper.java
@@ -0,0 +1,135 @@
+/*
+ * 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.compat;
+
+import android.graphics.Matrix;
+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;
+
+ /**
+ * Type for {@link #CHARACTER_RECT_TYPE_MASK}: the editor did not specify any type of this
+ * character. Editor authors should not use this flag.
+ */
+ public static final int CHARACTER_RECT_TYPE_UNSPECIFIED = 0;
+
+ /**
+ * Type for {@link #CHARACTER_RECT_TYPE_MASK}: the character is entirely visible.
+ */
+ public static final int CHARACTER_RECT_TYPE_FULLY_VISIBLE = 1;
+
+ /**
+ * Type for {@link #CHARACTER_RECT_TYPE_MASK}: some area of the character is invisible.
+ */
+ public static final int CHARACTER_RECT_TYPE_PARTIALLY_VISIBLE = 2;
+
+ /**
+ * Type for {@link #CHARACTER_RECT_TYPE_MASK}: the character is entirely invisible.
+ */
+ public static final int CHARACTER_RECT_TYPE_INVISIBLE = 3;
+
+ /**
+ * Type for {@link #CHARACTER_RECT_TYPE_MASK}: the editor gave up to calculate the rectangle
+ * for this character. Input method authors should ignore the returned rectangle.
+ */
+ public static final int CHARACTER_RECT_TYPE_NOT_FEASIBLE = 4;
+
+ private Object mInstance;
+
+ private CursorAnchorInfoCompatWrapper(final Object instance) {
+ mInstance = instance;
+ }
+
+ @UsedForTesting
+ public static CursorAnchorInfoCompatWrapper fromObject(final Object instance) {
+ if (!isAvailable()) {
+ return new CursorAnchorInfoCompatWrapper(null);
+ }
+ return new CursorAnchorInfoCompatWrapper(instance);
+ }
+
+ private static final class FakeHolder {
+ static CursorAnchorInfoCompatWrapper sInstance = new CursorAnchorInfoCompatWrapper(null);
+ }
+
+ @UsedForTesting
+ public static CursorAnchorInfoCompatWrapper getFake() {
+ return FakeHolder.sInstance;
+ }
+
+ public CharSequence getComposingText() {
+ return (CharSequence) CompatUtils.invoke(mInstance, null, METHOD_GET_COMPOSING_TEXT);
+ }
+
+ 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);
+ }
+
+ public Matrix getMatrix() {
+ return (Matrix) CompatUtils.invoke(mInstance, null, METHOD_GET_MATRIX);
+ }
+
+ public RectF getCharacterRect(final int index) {
+ return (RectF) CompatUtils.invoke(mInstance, null, METHOD_GET_CHARACTER_RECT, 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);
+ }
+}
diff --git a/java/src/com/android/inputmethod/event/Event.java b/java/src/com/android/inputmethod/event/Event.java
index f02f7885a..ef5b04747 100644
--- a/java/src/com/android/inputmethod/event/Event.java
+++ b/java/src/com/android/inputmethod/event/Event.java
@@ -257,6 +257,8 @@ public class Event {
public boolean isConsumed() { return 0 != (FLAG_CONSUMED & mFlags); }
+ public boolean isGesture() { return EVENT_TYPE_GESTURE == mEventType; }
+
// Returns whether this is a fake key press from the suggestion strip. This happens with
// punctuation signs selected from the suggestion strip.
public boolean isSuggestionStripPress() {
diff --git a/java/src/com/android/inputmethod/event/InputTransaction.java b/java/src/com/android/inputmethod/event/InputTransaction.java
index b18bf5638..5bc9111de 100644
--- a/java/src/com/android/inputmethod/event/InputTransaction.java
+++ b/java/src/com/android/inputmethod/event/InputTransaction.java
@@ -33,7 +33,7 @@ public class InputTransaction {
// Initial conditions
public final SettingsValues mSettingsValues;
- private final Event mEvent;
+ public final Event mEvent;
public final long mTimestamp;
public final int mSpaceState;
public final int mShiftState;
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index f35126750..140e76879 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -18,6 +18,7 @@ package com.android.inputmethod.keyboard;
import android.content.Context;
import android.content.SharedPreferences;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.preference.PreferenceManager;
import android.util.Log;
@@ -233,11 +234,21 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
}
private void setMainKeyboardFrame() {
- mMainKeyboardFrame.setVisibility(View.VISIBLE);
+ mMainKeyboardFrame.setVisibility(hasHardwareKeyboard() ? View.GONE : View.VISIBLE);
mEmojiPalettesView.setVisibility(View.GONE);
mEmojiPalettesView.stopEmojiPalettes();
}
+ // TODO: Move this boolean to a member of {@link SettingsValues} and reset it
+ // at {@link LatinIME#onConfigurationChanged(Configuration)}.
+ public boolean hasHardwareKeyboard() {
+ // Copied from {@link InputMethodServce#onEvaluateInputViewShown()}.
+ final Configuration config = mLatinIME.getResources().getConfiguration();
+ final boolean noHardwareKeyboard = config.keyboard == Configuration.KEYBOARD_NOKEYS
+ || config.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES;
+ return !noHardwareKeyboard;
+ }
+
// Implements {@link KeyboardState.SwitchActions}.
@Override
public void setEmojiKeyboard() {
@@ -249,6 +260,14 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
mEmojiPalettesView.setVisibility(View.VISIBLE);
}
+ public void onToggleEmojiKeyboard() {
+ if (isShowingEmojiPalettes()) {
+ setAlphabetKeyboard();
+ } else {
+ setEmojiKeyboard();
+ }
+ }
+
// Implements {@link KeyboardState.SwitchActions}.
@Override
public void setSymbolsShiftedKeyboard() {
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardTheme.java b/java/src/com/android/inputmethod/keyboard/KeyboardTheme.java
index 4c2e0dd1d..0cd606d19 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardTheme.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardTheme.java
@@ -17,11 +17,11 @@
package com.android.inputmethod.keyboard;
import android.content.SharedPreferences;
-import android.os.Build;
import android.os.Build.VERSION_CODES;
import android.util.Log;
import com.android.inputmethod.annotations.UsedForTesting;
+import com.android.inputmethod.compat.BuildCompatUtils;
import com.android.inputmethod.latin.R;
import java.util.Arrays;
@@ -47,8 +47,7 @@ public final class KeyboardTheme implements Comparable<KeyboardTheme> {
VERSION_CODES.ICE_CREAM_SANDWICH),
new KeyboardTheme(THEME_ID_LXX_LIGHT, R.style.KeyboardTheme_LXX_Light,
// Default theme for LXX.
- // TODO: Update this constant once the *next* version becomes available.
- VERSION_CODES.CUR_DEVELOPMENT),
+ BuildCompatUtils.VERSION_CODES_LXX),
new KeyboardTheme(THEME_ID_LXX_DARK, R.style.KeyboardTheme_LXX_Dark,
VERSION_CODES.BASE),
};
@@ -99,15 +98,6 @@ public final class KeyboardTheme implements Comparable<KeyboardTheme> {
return null;
}
- private static int getSdkVersion() {
- final int sdkVersion = Build.VERSION.SDK_INT;
- // TODO: Consider to remove this check once the *next* version becomes available.
- if (sdkVersion > VERSION_CODES.KITKAT) {
- return VERSION_CODES.CUR_DEVELOPMENT;
- }
- return sdkVersion;
- }
-
@UsedForTesting
static KeyboardTheme getDefaultKeyboardTheme(final SharedPreferences prefs,
final int sdkVersion) {
@@ -140,7 +130,7 @@ public final class KeyboardTheme implements Comparable<KeyboardTheme> {
public static void saveKeyboardThemeId(final String themeIdString,
final SharedPreferences prefs) {
- saveKeyboardThemeId(themeIdString, prefs, getSdkVersion());
+ saveKeyboardThemeId(themeIdString, prefs, BuildCompatUtils.EFFECTIVE_SDK_INT);
}
@UsedForTesting
@@ -159,7 +149,7 @@ public final class KeyboardTheme implements Comparable<KeyboardTheme> {
}
public static KeyboardTheme getKeyboardTheme(final SharedPreferences prefs) {
- return getKeyboardTheme(prefs, getSdkVersion());
+ return getKeyboardTheme(prefs, BuildCompatUtils.EFFECTIVE_SDK_INT);
}
@UsedForTesting
diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
index 702efb3d7..1ef53a65d 100644
--- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
@@ -46,6 +46,7 @@ import com.android.inputmethod.keyboard.internal.GestureTrailsDrawingPreview;
import com.android.inputmethod.keyboard.internal.KeyDrawParams;
import com.android.inputmethod.keyboard.internal.KeyPreviewChoreographer;
import com.android.inputmethod.keyboard.internal.KeyPreviewDrawParams;
+import com.android.inputmethod.keyboard.internal.KeyPreviewView;
import com.android.inputmethod.keyboard.internal.LanguageOnSpacebarHelper;
import com.android.inputmethod.keyboard.internal.MoreKeySpec;
import com.android.inputmethod.keyboard.internal.NonDistinctMultitouchHelper;
@@ -764,6 +765,9 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
public void startDisplayLanguageOnSpacebar(final boolean subtypeChanged,
final int languageOnSpacebarFormatType,
final boolean hasMultipleEnabledIMEsOrSubtypes) {
+ if (subtypeChanged) {
+ KeyPreviewView.clearTextCache();
+ }
mLanguageOnSpacebarFormatType = languageOnSpacebarFormatType;
mHasMultipleEnabledIMEsOrSubtypes = hasMultipleEnabledIMEsOrSubtypes;
final ObjectAnimator animator = mLanguageOnSpacebarFadeoutAnimator;
diff --git a/java/src/com/android/inputmethod/keyboard/emoji/EmojiCategory.java b/java/src/com/android/inputmethod/keyboard/emoji/EmojiCategory.java
index 512d4615d..0f9dc855b 100644
--- a/java/src/com/android/inputmethod/keyboard/emoji/EmojiCategory.java
+++ b/java/src/com/android/inputmethod/keyboard/emoji/EmojiCategory.java
@@ -24,6 +24,7 @@ import android.os.Build;
import android.util.Log;
import android.util.Pair;
+import com.android.inputmethod.compat.BuildCompatUtils;
import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.keyboard.KeyboardId;
@@ -121,9 +122,7 @@ final class EmojiCategory {
sCategoryTabIconAttr[i], 0);
}
addShownCategoryId(EmojiCategory.ID_RECENTS);
- if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR2
- || android.os.Build.VERSION.CODENAME.equalsIgnoreCase("KeyLimePie")
- || android.os.Build.VERSION.CODENAME.equalsIgnoreCase("KitKat")) {
+ if (BuildCompatUtils.EFFECTIVE_SDK_INT >= Build.VERSION_CODES.KITKAT) {
addShownCategoryId(EmojiCategory.ID_PEOPLE);
addShownCategoryId(EmojiCategory.ID_OBJECTS);
addShownCategoryId(EmojiCategory.ID_NATURE);
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewView.java b/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewView.java
index 360faf829..24538605a 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewView.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewView.java
@@ -17,7 +17,10 @@
package com.android.inputmethod.keyboard.internal;
import android.content.Context;
+import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import android.text.TextPaint;
+import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
@@ -26,6 +29,8 @@ import android.widget.TextView;
import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.latin.R;
+import java.util.HashSet;
+
/**
* The pop up key preview view.
*/
@@ -34,6 +39,9 @@ public class KeyPreviewView extends TextView {
public static final int POSITION_LEFT = 1;
public static final int POSITION_RIGHT = 2;
+ private final Rect mBackgroundPadding = new Rect();
+ private static final HashSet<String> sNoScaleXTextSet = new HashSet<>();
+
public KeyPreviewView(final Context context, final AttributeSet attrs) {
this(context, attrs, 0);
}
@@ -58,7 +66,48 @@ public class KeyPreviewView extends TextView {
setTextSize(TypedValue.COMPLEX_UNIT_PX, key.selectPreviewTextSize(drawParams));
setTypeface(key.selectPreviewTypeface(drawParams));
// TODO Should take care of temporaryShiftLabel here.
- setText(key.getPreviewLabel());
+ setTextAndScaleX(key.getPreviewLabel());
+ }
+
+ private void setTextAndScaleX(final String text) {
+ setTextScaleX(1.0f);
+ setText(text);
+ if (sNoScaleXTextSet.contains(text)) {
+ return;
+ }
+ // TODO: Override {@link #setBackground(Drawable)} that is supported from API 16 and
+ // calculate maximum text width.
+ final Drawable background = getBackground();
+ if (background == null) {
+ return;
+ }
+ background.getPadding(mBackgroundPadding);
+ final int maxWidth = background.getIntrinsicWidth() - mBackgroundPadding.left
+ - mBackgroundPadding.right;
+ final float width = getTextWidth(text, getPaint());
+ if (width <= maxWidth) {
+ sNoScaleXTextSet.add(text);
+ return;
+ }
+ setTextScaleX(maxWidth / width);
+ }
+
+ public static void clearTextCache() {
+ sNoScaleXTextSet.clear();
+ }
+
+ private static float getTextWidth(final String text, final TextPaint paint) {
+ if (TextUtils.isEmpty(text)) {
+ return 0.0f;
+ }
+ final int len = text.length();
+ final float[] widths = new float[len];
+ final int count = paint.getTextWidths(text, 0, len, widths);
+ float width = 0;
+ for (int i = 0; i < count; i++) {
+ width += widths[i];
+ }
+ return width;
}
// Background state set
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
index 09550c4cb..e1f302c1e 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
@@ -53,7 +53,8 @@ public final class KeyboardIconsSet {
public static final String NAME_LANGUAGE_SWITCH_KEY = "language_switch_key";
public static final String NAME_ZWNJ_KEY = "zwnj_key";
public static final String NAME_ZWJ_KEY = "zwj_key";
- public static final String NAME_EMOJI_KEY = "emoji_key";
+ public static final String NAME_EMOJI_ACTION_KEY = "emoji_action_key";
+ public static final String NAME_EMOJI_NORMAL_KEY = "emoji_normal_key";
private static final SparseIntArray ATTR_ID_TO_ICON_ID = new SparseIntArray();
@@ -81,7 +82,8 @@ public final class KeyboardIconsSet {
NAME_LANGUAGE_SWITCH_KEY, R.styleable.Keyboard_iconLanguageSwitchKey,
NAME_ZWNJ_KEY, R.styleable.Keyboard_iconZwnjKey,
NAME_ZWJ_KEY, R.styleable.Keyboard_iconZwjKey,
- NAME_EMOJI_KEY, R.styleable.Keyboard_iconEmojiKey,
+ NAME_EMOJI_ACTION_KEY, R.styleable.Keyboard_iconEmojiActionKey,
+ NAME_EMOJI_NORMAL_KEY, R.styleable.Keyboard_iconEmojiNormalKey,
};
private static int NUM_ICONS = NAMES_AND_ATTR_IDS.length / 2;
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java
index e6897bf1d..31bc549ca 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java
@@ -250,7 +250,7 @@ public final class KeyboardTextsTable {
/* 164: 0 */ "morekeys_single_quote",
/* 165: 0 */ "morekeys_double_quote",
/* 166: 0 */ "morekeys_tablet_double_quote",
- /* 167: 0 */ "keyspec_emoji_key",
+ /* 167: 0 */ "keyspec_emoji_action_key",
};
private static final String EMPTY = "";
@@ -464,7 +464,7 @@ public final class KeyboardTextsTable {
/* morekeys_single_quote */ "!fixedColumnOrder!5,!text/single_quotes,!text/single_angle_quotes",
/* morekeys_double_quote */ "!fixedColumnOrder!5,!text/double_quotes,!text/double_angle_quotes",
/* morekeys_tablet_double_quote */ "!fixedColumnOrder!6,!text/double_quotes,!text/single_quotes,!text/double_angle_quotes,!text/single_angle_quotes",
- /* keyspec_emoji_key */ "!icon/emoji_key|!code/key_emoji",
+ /* keyspec_emoji_action_key */ "!icon/emoji_action_key|!code/key_emoji",
};
/* Locale af: Afrikaans */
diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
index c11a220a4..22b91700c 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
@@ -647,7 +647,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
@UsedForTesting
public void waitAllTasksForTests() {
final CountDownLatch countDownLatch = new CountDownLatch(1);
- ExecutorUtils.getExecutor(mDictName).execute(new Runnable() {
+ asyncExecuteTaskWithWriteLock(new Runnable() {
@Override
public void run() {
countDownLatch.countDown();
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 2e3cd6b6f..71fd10e83 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -49,11 +49,13 @@ import android.view.ViewGroup.LayoutParams;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.CompletionInfo;
+import android.view.inputmethod.CursorAnchorInfo;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodSubtype;
import com.android.inputmethod.accessibility.AccessibilityUtils;
import com.android.inputmethod.annotations.UsedForTesting;
+import com.android.inputmethod.compat.CursorAnchorInfoCompatWrapper;
import com.android.inputmethod.compat.InputConnectionCompatUtils;
import com.android.inputmethod.compat.InputMethodServiceCompatUtils;
import com.android.inputmethod.dictionarypack.DictionaryPackConstants;
@@ -136,7 +138,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
new Runnable() {
@Override
public void run() {
- mHandler.postUpdateSuggestionStrip();
+ mHandler.postUpdateSuggestionStrip(SuggestedWords.INPUT_STYLE_NONE);
}
});
private final InputLogic mInputLogic = new InputLogic(this /* LatinIME */,
@@ -145,6 +147,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// If it turns out we need several, it will get grown seamlessly.
final SparseArray<HardwareEventDecoder> mHardwareEventDecoders = new SparseArray<>(1);
+ // TODO: Move these {@link View}s to {@link KeyboardSwitcher}.
+ private View mInputView;
private View mExtractArea;
private View mKeyPreviewBackingView;
private SuggestionStripView mSuggestionStripView;
@@ -153,6 +157,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
@UsedForTesting final KeyboardSwitcher mKeyboardSwitcher;
private final SubtypeSwitcher mSubtypeSwitcher;
private final SubtypeState mSubtypeState = new SubtypeState();
+ private final SpecialKeyDetector mSpecialKeyDetector;
// Object for reacting to adding/removing a dictionary pack.
private final BroadcastReceiver mDictionaryPackInstallReceiver =
@@ -215,7 +220,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
case MSG_UPDATE_SUGGESTION_STRIP:
cancelUpdateSuggestionStrip();
latinIme.mInputLogic.performUpdateSuggestionStripSync(
- latinIme.mSettings.getCurrent());
+ latinIme.mSettings.getCurrent(), msg.arg1 /* inputStyle */);
break;
case MSG_UPDATE_SHIFT_STATE:
switcher.requestUpdatingShiftState(latinIme.getCurrentAutoCapsState(),
@@ -265,8 +270,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
}
- public void postUpdateSuggestionStrip() {
- sendMessageDelayed(obtainMessage(MSG_UPDATE_SUGGESTION_STRIP), mDelayUpdateSuggestions);
+ public void postUpdateSuggestionStrip(final int inputStyle) {
+ sendMessageDelayed(obtainMessage(MSG_UPDATE_SUGGESTION_STRIP, inputStyle,
+ 0 /* ignored */), mDelayUpdateSuggestions);
}
public void postReopenDictionaries() {
@@ -419,9 +425,12 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
latinIme.getCurrentInputConnection(), true /* enableMonitor */);
}
if (ProductionFlags.ENABLE_CURSOR_ANCHOR_INFO_CALLBACK) {
- InputConnectionCompatUtils.requestCursorAnchorInfo(
- latinIme.getCurrentInputConnection(), true /* enableMonitor */,
- true /* requestImmediateCallback */);
+ // AcceptTypedWord feature relies on CursorAnchorInfo.
+ if (latinIme.mSettings.getCurrent().mShouldShowUiToAcceptTypedWord) {
+ InputConnectionCompatUtils.requestCursorAnchorInfo(
+ latinIme.getCurrentInputConnection(), true /* enableMonitor */,
+ true /* requestImmediateCallback */);
+ }
}
}
}
@@ -514,6 +523,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mSettings = Settings.getInstance();
mSubtypeSwitcher = SubtypeSwitcher.getInstance();
mKeyboardSwitcher = KeyboardSwitcher.getInstance();
+ mSpecialKeyDetector = new SpecialKeyDetector(this);
mIsHardwareAcceleratedDrawingEnabled =
InputMethodServiceCompatUtils.enableHardwareAcceleration(this);
Log.i(TAG, "Hardware accelerated drawing: " + mIsHardwareAcceleratedDrawingEnabled);
@@ -709,6 +719,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
@Override
public void setInputView(final View view) {
super.setInputView(view);
+ mInputView = view;
mExtractArea = getWindow().getWindow().getDecorView()
.findViewById(android.R.id.extractArea);
mKeyPreviewBackingView = view.findViewById(R.id.key_preview_backing);
@@ -967,6 +978,16 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
super.onUpdateCursor(rect);
}
+ // We cannot mark this method as @Override until new SDK becomes publicly available.
+ // @Override
+ public void onUpdateCursorAnchorInfo(final CursorAnchorInfo info) {
+ if (ProductionFlags.ENABLE_CURSOR_ANCHOR_INFO_CALLBACK) {
+ final CursorAnchorInfoCompatWrapper wrapper =
+ CursorAnchorInfoCompatWrapper.fromObject(info);
+ // TODO: Implement here
+ }
+ }
+
/**
* This is called when the user has clicked on the extracted text view,
* when running in fullscreen mode. The default implementation hides
@@ -1040,7 +1061,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
applicationSpecifiedCompletions);
final SuggestedWords suggestedWords = new SuggestedWords(applicationSuggestedWords,
null /* rawSuggestions */, false /* typedWordValid */, false /* willAutoCorrect */,
- false /* isObsoleteSuggestions */, false /* isPrediction */);
+ false /* isObsoleteSuggestions */, false /* isPrediction */,
+ SuggestedWords.INPUT_STYLE_APPLICATION_SPECIFIED /* inputStyle */);
// When in fullscreen mode, show completions generated by the application forcibly
setSuggestedWords(suggestedWords);
}
@@ -1079,6 +1101,14 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (visibleKeyboardView == null || !hasSuggestionStripView()) {
return;
}
+ final boolean hasHardwareKeyboard = mKeyboardSwitcher.hasHardwareKeyboard();
+ if (hasHardwareKeyboard && visibleKeyboardView.getVisibility() == View.GONE) {
+ // If there is a hardware keyboard and a visible software keyboard view has been hidden,
+ // no visual element will be shown on the screen.
+ outInsets.touchableInsets = mInputView.getHeight();
+ outInsets.visibleTopInsets = mInputView.getHeight();
+ return;
+ }
final int adjustedBackingHeight = getAdjustedBackingViewHeight();
final boolean backingGone = (mKeyPreviewBackingView.getVisibility() == View.GONE);
final int backingHeight = backingGone ? 0 : adjustedBackingHeight;
@@ -1111,7 +1141,17 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
@Override
+ public boolean onEvaluateInputViewShown() {
+ // Always show {@link InputView}.
+ return true;
+ }
+
+ @Override
public boolean onEvaluateFullscreenMode() {
+ if (mKeyboardSwitcher.hasHardwareKeyboard()) {
+ // If there is a hardware keyboard, disable full screen mode.
+ return false;
+ }
// Reread resource value here, because this method is called by the framework as needed.
final boolean isFullscreenModeAllowed = Settings.readUseFullscreenMode(getResources());
if (super.onEvaluateFullscreenMode() && isFullscreenModeAllowed) {
@@ -1413,7 +1453,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
// TODO[IL]: Move this out of LatinIME.
- public void getSuggestedWords(final int sessionId, final int sequenceNumber,
+ public void getSuggestedWords(final int inputStyle, final int sequenceNumber,
final OnGetSuggestedWordsCallback callback) {
final Keyboard keyboard = mKeyboardSwitcher.getKeyboard();
if (keyboard == null) {
@@ -1421,7 +1461,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
return;
}
mInputLogic.getSuggestedWords(mSettings.getCurrent(), keyboard.getProximityInfo(),
- mKeyboardSwitcher.getKeyboardShiftMode(), sessionId, sequenceNumber, callback);
+ mKeyboardSwitcher.getKeyboardShiftMode(), inputStyle, sequenceNumber, callback);
}
@Override
@@ -1505,7 +1545,16 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
default: // SHIFT_NO_UPDATE
}
if (inputTransaction.requiresUpdateSuggestions()) {
- mHandler.postUpdateSuggestionStrip();
+ final int inputStyle;
+ if (inputTransaction.mEvent.isSuggestionStripPress()) {
+ // Suggestion strip press: no input.
+ inputStyle = SuggestedWords.INPUT_STYLE_NONE;
+ } else if (inputTransaction.mEvent.isGesture()) {
+ inputStyle = SuggestedWords.INPUT_STYLE_TAIL_BATCH;
+ } else {
+ inputStyle = SuggestedWords.INPUT_STYLE_TYPING;
+ }
+ mHandler.postUpdateSuggestionStrip(inputStyle);
}
if (inputTransaction.didAffectContents()) {
mSubtypeState.setCurrentSubtypeHasBeenUsed();
@@ -1568,6 +1617,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// Hooks for hardware keyboard
@Override
public boolean onKeyDown(final int keyCode, final KeyEvent keyEvent) {
+ mSpecialKeyDetector.onKeyDown(keyEvent);
if (!ProductionFlags.IS_HARDWARE_KEYBOARD_SUPPORTED) {
return super.onKeyDown(keyCode, keyEvent);
}
@@ -1587,12 +1637,16 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
@Override
- public boolean onKeyUp(final int keyCode, final KeyEvent event) {
- final long keyIdentifier = event.getDeviceId() << 32 + event.getKeyCode();
+ public boolean onKeyUp(final int keyCode, final KeyEvent keyEvent) {
+ mSpecialKeyDetector.onKeyUp(keyEvent);
+ if (!ProductionFlags.IS_HARDWARE_KEYBOARD_SUPPORTED) {
+ return super.onKeyUp(keyCode, keyEvent);
+ }
+ final long keyIdentifier = keyEvent.getDeviceId() << 32 + keyEvent.getKeyCode();
if (mInputLogic.mCurrentlyPressedHardwareKeys.remove(keyIdentifier)) {
return true;
}
- return super.onKeyUp(keyCode, event);
+ return super.onKeyUp(keyCode, keyEvent);
}
// onKeyDown and onKeyUp are the main events we are interested in. There are two more events
diff --git a/java/src/com/android/inputmethod/latin/PunctuationSuggestions.java b/java/src/com/android/inputmethod/latin/PunctuationSuggestions.java
index 0fba37c8a..6b0205c0f 100644
--- a/java/src/com/android/inputmethod/latin/PunctuationSuggestions.java
+++ b/java/src/com/android/inputmethod/latin/PunctuationSuggestions.java
@@ -35,7 +35,8 @@ public final class PunctuationSuggestions extends SuggestedWords {
false /* typedWordValid */,
false /* hasAutoCorrectionCandidate */,
false /* isObsoleteSuggestions */,
- false /* isPrediction */);
+ false /* isPrediction */,
+ INPUT_STYLE_NONE /* inputStyle */);
}
/**
diff --git a/java/src/com/android/inputmethod/latin/SpecialKeyDetector.java b/java/src/com/android/inputmethod/latin/SpecialKeyDetector.java
new file mode 100644
index 000000000..27b2f5012
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/SpecialKeyDetector.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.content.Context;
+import android.view.KeyEvent;
+
+final class SpecialKeyDetector {
+ /**
+ * Special physical key detector
+ * @param context a context of this detector.
+ */
+ public SpecialKeyDetector(final Context context) {
+ }
+
+ /**
+ * Record a down key event.
+ * @param keyEvent a down key event.
+ */
+ public void onKeyDown(final KeyEvent keyEvent) {
+ }
+
+ /**
+ * Record an up key event.
+ * @param keyEvent an up key event.
+ */
+ public void onKeyUp(final KeyEvent keyEvent) {
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index b8b6d6471..ab852f8dd 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -40,13 +40,8 @@ public final class Suggest {
// Session id for
// {@link #getSuggestedWords(WordComposer,String,ProximityInfo,boolean,int)}.
// We are sharing the same ID between typing and gesture to save RAM footprint.
- public static final int SESSION_TYPING = 0;
- public static final int SESSION_GESTURE = 0;
-
- // TODO: rename this to CORRECTION_OFF
- public static final int CORRECTION_NONE = 0;
- // TODO: rename this to CORRECTION_ON
- public static final int CORRECTION_FULL = 1;
+ public static final int SESSION_ID_TYPING = 0;
+ public static final int SESSION_ID_GESTURE = 0;
// Close to -2**31
private static final int SUPPRESS_SUGGEST_THRESHOLD = -2000000000;
@@ -75,14 +70,15 @@ public final class Suggest {
public void getSuggestedWords(final WordComposer wordComposer,
final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo,
final SettingsValuesForSuggestion settingsValuesForSuggestion,
- final boolean isCorrectionEnabled, final int sessionId, final int sequenceNumber,
+ final boolean isCorrectionEnabled, final int inputStyle, final int sequenceNumber,
final OnGetSuggestedWordsCallback callback) {
if (wordComposer.isBatchMode()) {
getSuggestedWordsForBatchInput(wordComposer, prevWordsInfo, proximityInfo,
- settingsValuesForSuggestion, sessionId, sequenceNumber, callback);
+ settingsValuesForSuggestion, inputStyle, sequenceNumber, callback);
} else {
- getSuggestedWordsForTypingInput(wordComposer, prevWordsInfo, proximityInfo,
- settingsValuesForSuggestion, isCorrectionEnabled, sequenceNumber, callback);
+ getSuggestedWordsForNonBatchInput(wordComposer, prevWordsInfo, proximityInfo,
+ settingsValuesForSuggestion, inputStyle, isCorrectionEnabled,
+ sequenceNumber, callback);
}
}
@@ -120,11 +116,11 @@ public final class Suggest {
return firstSuggestedWordInfo.mWord;
}
- // Retrieves suggestions for the typing input
+ // Retrieves suggestions for non-batch input (typing, recorrection, predictions...)
// and calls the callback function with the suggestions.
- private void getSuggestedWordsForTypingInput(final WordComposer wordComposer,
+ private void getSuggestedWordsForNonBatchInput(final WordComposer wordComposer,
final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo,
- final SettingsValuesForSuggestion settingsValuesForSuggestion,
+ final SettingsValuesForSuggestion settingsValuesForSuggestion, final int inputStyle,
final boolean isCorrectionEnabled, final int sequenceNumber,
final OnGetSuggestedWordsCallback callback) {
final String typedWord = wordComposer.getTypedWord();
@@ -135,7 +131,7 @@ public final class Suggest {
final SuggestionResults suggestionResults = mDictionaryFacilitator.getSuggestionResults(
wordComposer, prevWordsInfo, proximityInfo, settingsValuesForSuggestion,
- SESSION_TYPING);
+ SESSION_ID_TYPING);
final ArrayList<SuggestedWordInfo> suggestionsContainer =
getTransformedSuggestedWordInfoList(wordComposer, suggestionResults,
trailingSingleQuotesCount);
@@ -197,7 +193,8 @@ public final class Suggest {
// rename the attribute or change the value.
!resultsArePredictions && !allowsToBeAutoCorrected /* typedWordValid */,
hasAutoCorrection /* willAutoCorrect */,
- false /* isObsoleteSuggestions */, resultsArePredictions, sequenceNumber));
+ false /* isObsoleteSuggestions */, resultsArePredictions,
+ inputStyle, sequenceNumber));
}
// Retrieves suggestions for the batch input
@@ -205,10 +202,11 @@ public final class Suggest {
private void getSuggestedWordsForBatchInput(final WordComposer wordComposer,
final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo,
final SettingsValuesForSuggestion settingsValuesForSuggestion,
- final int sessionId, final int sequenceNumber,
+ final int inputStyle, final int sequenceNumber,
final OnGetSuggestedWordsCallback callback) {
final SuggestionResults suggestionResults = mDictionaryFacilitator.getSuggestionResults(
- wordComposer, prevWordsInfo, proximityInfo, settingsValuesForSuggestion, sessionId);
+ wordComposer, prevWordsInfo, proximityInfo, settingsValuesForSuggestion,
+ SESSION_ID_GESTURE);
final ArrayList<SuggestedWordInfo> suggestionsContainer =
new ArrayList<>(suggestionResults);
final int suggestionsCount = suggestionsContainer.size();
@@ -246,7 +244,8 @@ public final class Suggest {
true /* typedWordValid */,
false /* willAutoCorrect */,
false /* isObsoleteSuggestions */,
- false /* isPrediction */, sequenceNumber));
+ false /* isPrediction */,
+ inputStyle, sequenceNumber));
}
private static ArrayList<SuggestedWordInfo> getSuggestionsInfoListWithDebugInfo(
diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java
index 5231cc893..d7693af41 100644
--- a/java/src/com/android/inputmethod/latin/SuggestedWords.java
+++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java
@@ -31,12 +31,20 @@ public class SuggestedWords {
public static final int INDEX_OF_AUTO_CORRECTION = 1;
public static final int NOT_A_SEQUENCE_NUMBER = -1;
+ public static final int INPUT_STYLE_NONE = 0;
+ public static final int INPUT_STYLE_TYPING = 1;
+ public static final int INPUT_STYLE_UPDATE_BATCH = 2;
+ public static final int INPUT_STYLE_TAIL_BATCH = 3;
+ public static final int INPUT_STYLE_APPLICATION_SPECIFIED = 4;
+ public static final int INPUT_STYLE_RECORRECTION = 5;
+
// The maximum number of suggestions available.
public static final int MAX_SUGGESTIONS = 18;
private static final ArrayList<SuggestedWordInfo> EMPTY_WORD_INFO_LIST = new ArrayList<>(0);
public static final SuggestedWords EMPTY = new SuggestedWords(
- EMPTY_WORD_INFO_LIST, null /* rawSuggestions */, false, false, false, false);
+ EMPTY_WORD_INFO_LIST, null /* rawSuggestions */, false, false, false, false,
+ INPUT_STYLE_NONE);
public final String mTypedWord;
public final boolean mTypedWordValid;
@@ -46,6 +54,9 @@ public class SuggestedWords {
public final boolean mWillAutoCorrect;
public final boolean mIsObsoleteSuggestions;
public final boolean mIsPrediction;
+ // How the input for these suggested words was done by the user. Must be one of the
+ // INPUT_STYLE_* constants above.
+ public final int mInputStyle;
public final int mSequenceNumber; // Sequence number for auto-commit.
protected final ArrayList<SuggestedWordInfo> mSuggestedWordInfoList;
public final ArrayList<SuggestedWordInfo> mRawSuggestions;
@@ -55,9 +66,10 @@ public class SuggestedWords {
final boolean typedWordValid,
final boolean willAutoCorrect,
final boolean isObsoleteSuggestions,
- final boolean isPrediction) {
+ final boolean isPrediction,
+ final int inputStyle) {
this(suggestedWordInfoList, rawSuggestions, typedWordValid, willAutoCorrect,
- isObsoleteSuggestions, isPrediction, NOT_A_SEQUENCE_NUMBER);
+ isObsoleteSuggestions, isPrediction, inputStyle, NOT_A_SEQUENCE_NUMBER);
}
public SuggestedWords(final ArrayList<SuggestedWordInfo> suggestedWordInfoList,
@@ -66,11 +78,12 @@ public class SuggestedWords {
final boolean willAutoCorrect,
final boolean isObsoleteSuggestions,
final boolean isPrediction,
+ final int inputStyle,
final int sequenceNumber) {
this(suggestedWordInfoList, rawSuggestions,
(suggestedWordInfoList.isEmpty() || isPrediction) ? null
: suggestedWordInfoList.get(INDEX_OF_TYPED_WORD).mWord,
- typedWordValid, willAutoCorrect, isObsoleteSuggestions, isPrediction,
+ typedWordValid, willAutoCorrect, isObsoleteSuggestions, isPrediction, inputStyle,
sequenceNumber);
}
@@ -81,6 +94,7 @@ public class SuggestedWords {
final boolean willAutoCorrect,
final boolean isObsoleteSuggestions,
final boolean isPrediction,
+ final int inputStyle,
final int sequenceNumber) {
mSuggestedWordInfoList = suggestedWordInfoList;
mRawSuggestions = rawSuggestions;
@@ -88,6 +102,7 @@ public class SuggestedWords {
mWillAutoCorrect = willAutoCorrect;
mIsObsoleteSuggestions = isObsoleteSuggestions;
mIsPrediction = isPrediction;
+ mInputStyle = inputStyle;
mSequenceNumber = sequenceNumber;
mTypedWord = typedWord;
}
@@ -367,7 +382,7 @@ public class SuggestedWords {
// SuggestedWords is an immutable object, as much as possible. We must not just remove
// words from the member ArrayList as some other parties may expect the object to never change.
- public SuggestedWords getSuggestedWordsExcludingTypedWord() {
+ public SuggestedWords getSuggestedWordsExcludingTypedWord(final int inputStyle) {
final ArrayList<SuggestedWordInfo> newSuggestions = new ArrayList<>();
String typedWord = null;
for (int i = 0; i < mSuggestedWordInfoList.size(); ++i) {
@@ -383,7 +398,7 @@ public class SuggestedWords {
// no auto-correction should take place hence willAutoCorrect = false.
return new SuggestedWords(newSuggestions, null /* rawSuggestions */, typedWord,
true /* typedWordValid */, false /* willAutoCorrect */, mIsObsoleteSuggestions,
- mIsPrediction, NOT_A_SEQUENCE_NUMBER);
+ mIsPrediction, inputStyle, NOT_A_SEQUENCE_NUMBER);
}
// Creates a new SuggestedWordInfo from the currently suggested words that removes all but the
@@ -402,6 +417,7 @@ public class SuggestedWords {
SuggestedWordInfo.NOT_A_CONFIDENCE));
}
return new SuggestedWords(newSuggestions, null /* rawSuggestions */, mTypedWordValid,
- mWillAutoCorrect, mIsObsoleteSuggestions, mIsPrediction);
+ mWillAutoCorrect, mIsObsoleteSuggestions, mIsPrediction,
+ INPUT_STYLE_TAIL_BATCH);
}
}
diff --git a/java/src/com/android/inputmethod/latin/define/ProductionFlags.java b/java/src/com/android/inputmethod/latin/define/ProductionFlags.java
index d385cf840..461c226a1 100644
--- a/java/src/com/android/inputmethod/latin/define/ProductionFlags.java
+++ b/java/src/com/android/inputmethod/latin/define/ProductionFlags.java
@@ -29,7 +29,7 @@ public final class ProductionFlags {
* and prior. In general, this callback provides more detailed positional information,
* even though an explicit support is required by the editor.
*/
- public static final boolean ENABLE_CURSOR_ANCHOR_INFO_CALLBACK = false;
+ public static final boolean ENABLE_CURSOR_ANCHOR_INFO_CALLBACK = true;
/**
* When true, enable {@link InputMethodService#onUpdateCursor} callback via
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index 418866ae1..348bae63a 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -216,7 +216,7 @@ public final class InputLogic {
} else {
resetComposingState(true /* alsoResetLastComposedWord */);
}
- handler.postUpdateSuggestionStrip();
+ handler.postUpdateSuggestionStrip(SuggestedWords.INPUT_STYLE_TYPING);
final String text = performSpecificTldProcessingOnTextInput(rawText);
if (SpaceState.PHANTOM == mSpaceState) {
promotePhantomSpace(settingsValues);
@@ -288,9 +288,6 @@ public final class InputLogic {
return inputTransaction;
}
- // We need to log before we commit, because the word composer will store away the user
- // typed word.
- final String replacedWord = mWordComposer.getTypedWord();
commitChosenWord(settingsValues, suggestion,
LastComposedWord.COMMIT_TYPE_MANUAL_PICK, LastComposedWord.NOT_A_SEPARATOR);
mConnection.endBatchEdit();
@@ -311,7 +308,8 @@ public final class InputLogic {
mSuggestionStripViewAccessor.showAddToDictionaryHint(suggestion);
} else {
// If we're not showing the "Touch again to save", then update the suggestion strip.
- handler.postUpdateSuggestionStrip();
+ // That's going to be predictions (or punctuation suggestions), so INPUT_STYLE_NONE.
+ handler.postUpdateSuggestionStrip(SuggestedWords.INPUT_STYLE_NONE);
}
return inputTransaction;
}
@@ -1299,7 +1297,8 @@ public final class InputLogic {
prevWordsInfo, timeStampInSeconds, settingsValues.mBlockPotentiallyOffensive);
}
- public void performUpdateSuggestionStripSync(final SettingsValues settingsValues) {
+ public void performUpdateSuggestionStripSync(final SettingsValues settingsValues,
+ final int inputStyle) {
// Check if we have a suggestion engine attached.
if (!settingsValues.needsToLookupSuggestions()) {
if (mWordComposer.isComposingWord()) {
@@ -1317,8 +1316,8 @@ public final class InputLogic {
}
final AsyncResultHolder<SuggestedWords> holder = new AsyncResultHolder<>();
- mInputLogicHandler.getSuggestedWords(Suggest.SESSION_TYPING,
- SuggestedWords.NOT_A_SEQUENCE_NUMBER, new OnGetSuggestedWordsCallback() {
+ mInputLogicHandler.getSuggestedWords(inputStyle, SuggestedWords.NOT_A_SEQUENCE_NUMBER,
+ new OnGetSuggestedWordsCallback() {
@Override
public void onGetSuggestedWords(final SuggestedWords suggestedWords) {
final String typedWord = mWordComposer.getTypedWord();
@@ -1379,7 +1378,7 @@ public final class InputLogic {
if (!mConnection.isCursorTouchingWord(settingsValues.mSpacingAndPunctuations)) {
// Show predictions.
mWordComposer.setCapitalizedModeAtStartComposingTime(WordComposer.CAPS_MODE_OFF);
- mLatinIME.mHandler.postUpdateSuggestionStrip();
+ mLatinIME.mHandler.postUpdateSuggestionStrip(SuggestedWords.INPUT_STYLE_RECORRECTION);
return;
}
final TextRange range = mConnection.getWordRangeAtCursor(
@@ -1444,7 +1443,7 @@ public final class InputLogic {
// If there weren't any suggestion spans on this word, suggestions#size() will be 1
// if shouldIncludeResumedWordInSuggestions is true, 0 otherwise. In this case, we
// have no useful suggestions, so we will try to compute some for it instead.
- mInputLogicHandler.getSuggestedWords(Suggest.SESSION_TYPING,
+ mInputLogicHandler.getSuggestedWords(Suggest.SESSION_ID_TYPING,
SuggestedWords.NOT_A_SEQUENCE_NUMBER, new OnGetSuggestedWordsCallback() {
@Override
public void onGetSuggestedWords(
@@ -1457,7 +1456,8 @@ public final class InputLogic {
// case. The #getSuggestedWordsExcludingTypedWord() method sets
// willAutoCorrect to false.
suggestedWords = suggestedWordsIncludingTypedWord
- .getSuggestedWordsExcludingTypedWord();
+ .getSuggestedWordsExcludingTypedWord(SuggestedWords
+ .INPUT_STYLE_RECORRECTION);
} else {
// No saved suggestions, and we were unable to compute any good one
// either. Rather than displaying an empty suggestion strip, we'll
@@ -1477,6 +1477,7 @@ public final class InputLogic {
null /* rawSuggestions */, typedWord,
false /* typedWordValid */, false /* willAutoCorrect */,
false /* isObsoleteSuggestions */, false /* isPrediction */,
+ SuggestedWords.INPUT_STYLE_RECORRECTION,
SuggestedWords.NOT_A_SEQUENCE_NUMBER);
mIsAutoCorrectionIndicatorOn = false;
mLatinIME.mHandler.showSuggestionStrip(suggestedWords);
@@ -1773,7 +1774,8 @@ public final class InputLogic {
SuggestedWords.getTypedWordAndPreviousSuggestions(typedWord, oldSuggestedWords);
return new SuggestedWords(typedWordAndPreviousSuggestions, null /* rawSuggestions */,
false /* typedWordValid */, false /* hasAutoCorrectionCandidate */,
- true /* isObsoleteSuggestions */, false /* isPrediction */);
+ true /* isObsoleteSuggestions */, false /* isPrediction */,
+ oldSuggestedWords.mInputStyle);
}
/**
@@ -1956,7 +1958,15 @@ public final class InputLogic {
// Complete any pending suggestions query first
if (handler.hasPendingUpdateSuggestions()) {
handler.cancelUpdateSuggestionStrip();
- performUpdateSuggestionStripSync(settingsValues);
+ // To know the input style here, we should retrieve the in-flight "update suggestions"
+ // message and read its arg1 member here. However, the Handler class does not let
+ // us retrieve this message, so we can't do that. But in fact, we notice that
+ // we only ever come here when the input style was typing. In the case of batch
+ // input, we update the suggestions synchronously when the tail batch comes. Likewise
+ // for application-specified completions. As for recorrections, we never auto-correct,
+ // so we don't come here either. Hence, the input style is necessarily
+ // INPUT_STYLE_TYPING.
+ performUpdateSuggestionStripSync(settingsValues, SuggestedWords.INPUT_STYLE_TYPING);
}
final String typedAutoCorrection = mWordComposer.getAutoCorrectionOrNull();
final String typedWord = mWordComposer.getTypedWord();
@@ -2052,7 +2062,7 @@ public final class InputLogic {
}
public void getSuggestedWords(final SettingsValues settingsValues,
- final ProximityInfo proximityInfo, final int keyboardShiftMode, final int sessionId,
+ final ProximityInfo proximityInfo, final int keyboardShiftMode, final int inputStyle,
final int sequenceNumber, final OnGetSuggestedWordsCallback callback) {
mWordComposer.adviseCapitalizedModeBeforeFetchingSuggestions(
getActualCapsMode(settingsValues, keyboardShiftMode));
@@ -2068,6 +2078,6 @@ public final class InputLogic {
settingsValues.mPhraseGestureEnabled,
settingsValues.mAdditionalFeaturesSettingValues),
settingsValues.mAutoCorrectionEnabledPerUserSettings,
- sessionId, sequenceNumber, callback);
+ inputStyle, sequenceNumber, callback);
}
}
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java
index 9dbe2c38b..c6f83d0b9 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java
@@ -96,7 +96,7 @@ class InputLogicHandler implements Handler.Callback {
public boolean handleMessage(final Message msg) {
switch (msg.what) {
case MSG_GET_SUGGESTED_WORDS:
- mLatinIME.getSuggestedWords(msg.arg1 /* sessionId */,
+ mLatinIME.getSuggestedWords(msg.arg1 /* inputStyle */,
msg.arg2 /* sequenceNumber */, (OnGetSuggestedWordsCallback) msg.obj);
break;
}
@@ -134,7 +134,8 @@ class InputLogicHandler implements Handler.Callback {
return;
}
mInputLogic.mWordComposer.setBatchInputPointers(batchPointers);
- getSuggestedWords(Suggest.SESSION_GESTURE, sequenceNumber,
+ getSuggestedWords(isTailBatchInput ? SuggestedWords.INPUT_STYLE_TAIL_BATCH
+ : SuggestedWords.INPUT_STYLE_UPDATE_BATCH, sequenceNumber,
new OnGetSuggestedWordsCallback() {
@Override
public void onGetSuggestedWords(SuggestedWords suggestedWords) {
@@ -205,9 +206,9 @@ class InputLogicHandler implements Handler.Callback {
updateBatchInput(batchPointers, sequenceNumber, true /* isTailBatchInput */);
}
- public void getSuggestedWords(final int sessionId, final int sequenceNumber,
+ public void getSuggestedWords(final int inputStyle, final int sequenceNumber,
final OnGetSuggestedWordsCallback callback) {
mNonUIThreadHandler.obtainMessage(
- MSG_GET_SUGGESTED_WORDS, sessionId, sequenceNumber, callback).sendToTarget();
+ MSG_GET_SUGGESTED_WORDS, inputStyle, sequenceNumber, callback).sendToTarget();
}
}
diff --git a/java/src/com/android/inputmethod/latin/settings/DebugSettings.java b/java/src/com/android/inputmethod/latin/settings/DebugSettings.java
index dce11b434..63d848e2d 100644
--- a/java/src/com/android/inputmethod/latin/settings/DebugSettings.java
+++ b/java/src/com/android/inputmethod/latin/settings/DebugSettings.java
@@ -19,6 +19,10 @@ package com.android.inputmethod.latin.settings;
public final class DebugSettings {
public static final String PREF_DEBUG_MODE = "debug_mode";
public static final String PREF_FORCE_NON_DISTINCT_MULTITOUCH = "force_non_distinct_multitouch";
+ public static final String PREF_FORCE_PHYSICAL_KEYBOARD_SPECIAL_KEY =
+ "force_physical_keyboard_special_key";
+ public static final String PREF_SHOW_UI_TO_ACCEPT_TYPED_WORD =
+ "pref_show_ui_to_accept_typed_word";
public static final String PREF_KEY_PREVIEW_SHOW_UP_START_SCALE =
"pref_key_preview_show_up_start_scale";
public static final String PREF_KEY_PREVIEW_DISMISS_END_SCALE =
diff --git a/java/src/com/android/inputmethod/latin/settings/DebugSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/DebugSettingsFragment.java
index 4e41d52a3..dc2f88aa8 100644
--- a/java/src/com/android/inputmethod/latin/settings/DebugSettingsFragment.java
+++ b/java/src/com/android/inputmethod/latin/settings/DebugSettingsFragment.java
@@ -56,6 +56,10 @@ public final class DebugSettingsFragment extends SubScreenFragment
super.onCreate(icicle);
addPreferencesFromResource(R.xml.prefs_screen_debug);
+ if (!Settings.HAS_UI_TO_ACCEPT_TYPED_WORD) {
+ removePreference(DebugSettings.PREF_SHOW_UI_TO_ACCEPT_TYPED_WORD);
+ }
+
mReadExternalDictionaryPref = findPreference(PREF_READ_EXTERNAL_DICTIONARY);
if (mReadExternalDictionaryPref != null) {
mReadExternalDictionaryPref.setOnPreferenceClickListener(this);
@@ -133,7 +137,8 @@ public final class DebugSettingsFragment extends SubScreenFragment
mServiceNeedsRestart = true;
return;
}
- if (key.equals(DebugSettings.PREF_FORCE_NON_DISTINCT_MULTITOUCH)) {
+ if (key.equals(DebugSettings.PREF_FORCE_NON_DISTINCT_MULTITOUCH)
+ || key.equals(DebugSettings.PREF_FORCE_PHYSICAL_KEYBOARD_SPECIAL_KEY)) {
mServiceNeedsRestart = true;
return;
}
diff --git a/java/src/com/android/inputmethod/latin/settings/Settings.java b/java/src/com/android/inputmethod/latin/settings/Settings.java
index 90174e490..9d3c27bbe 100644
--- a/java/src/com/android/inputmethod/latin/settings/Settings.java
+++ b/java/src/com/android/inputmethod/latin/settings/Settings.java
@@ -24,6 +24,7 @@ import android.os.Build;
import android.preference.PreferenceManager;
import android.util.Log;
+import com.android.inputmethod.compat.BuildCompatUtils;
import com.android.inputmethod.latin.AudioAndHapticFeedbackManager;
import com.android.inputmethod.latin.InputAttributes;
import com.android.inputmethod.latin.R;
@@ -68,9 +69,9 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
public static final String PREF_BLOCK_POTENTIALLY_OFFENSIVE =
"pref_key_block_potentially_offensive";
public static final boolean ENABLE_SHOW_LANGUAGE_SWITCH_KEY_SETTINGS =
- (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
- || (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT
- && Build.VERSION.CODENAME.equals("REL"));
+ BuildCompatUtils.EFFECTIVE_SDK_INT <= Build.VERSION_CODES.KITKAT;
+ public static final boolean HAS_UI_TO_ACCEPT_TYPED_WORD =
+ BuildCompatUtils.EFFECTIVE_SDK_INT >= BuildCompatUtils.VERSION_CODES_LXX;
public static final String PREF_SHOW_LANGUAGE_SWITCH_KEY =
"pref_show_language_switch_key";
public static final String PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST =
diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
index 39e834f84..c12474b3d 100644
--- a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
+++ b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
@@ -40,7 +40,8 @@ import java.util.Locale;
* When you call the constructor of this class, you may want to change the current system locale by
* using {@link com.android.inputmethod.latin.utils.RunInLocale}.
*/
-public final class SettingsValues {
+// Non-final for testing via mock library.
+public class SettingsValues {
private static final String TAG = SettingsValues.class.getSimpleName();
// "floatMaxValue" and "floatNegativeInfinity" are special marker strings for
// Float.NEGATIVE_INFINITE and Float.MAX_VALUE. Currently used for auto-correction settings.
@@ -75,6 +76,7 @@ public final class SettingsValues {
public final int mKeyLongpressTimeout;
public final Locale mLocale;
public final boolean mEnableMetricsLogging;
+ public final boolean mShouldShowUiToAcceptTypedWord;
// From the input box
public final InputAttributes mInputAttributes;
@@ -142,6 +144,8 @@ public final class SettingsValues {
mBigramPredictionEnabled = readBigramPredictionEnabled(prefs, res);
mDoubleSpacePeriodTimeout = res.getInteger(R.integer.config_double_space_period_timeout);
mEnableMetricsLogging = prefs.getBoolean(Settings.PREF_ENABLE_METRICS_LOGGING, true);
+ mShouldShowUiToAcceptTypedWord = Settings.HAS_UI_TO_ACCEPT_TYPED_WORD
+ && prefs.getBoolean(DebugSettings.PREF_SHOW_UI_TO_ACCEPT_TYPED_WORD, true);
// Compute other readable settings
mKeyLongpressTimeout = Settings.readKeyLongpressTimeout(prefs, res);
mKeypressVibrationDuration = Settings.readKeypressVibrationDuration(prefs, res);
@@ -186,6 +190,10 @@ public final class SettingsValues {
}
}
+ public boolean isMetricsLoggingEnabled() {
+ return mEnableMetricsLogging;
+ }
+
public boolean isApplicationSpecifiedCompletionsOn() {
return mInputAttributes.mApplicationSpecifiedCompletionOn;
}
diff --git a/native/jni/src/suggest/core/dictionary/error_type_utils.cpp b/native/jni/src/suggest/core/dictionary/error_type_utils.cpp
index b6bf7a98c..1e2494e92 100644
--- a/native/jni/src/suggest/core/dictionary/error_type_utils.cpp
+++ b/native/jni/src/suggest/core/dictionary/error_type_utils.cpp
@@ -19,17 +19,18 @@
namespace latinime {
const ErrorTypeUtils::ErrorType ErrorTypeUtils::NOT_AN_ERROR = 0x0;
-const ErrorTypeUtils::ErrorType ErrorTypeUtils::MATCH_WITH_CASE_ERROR = 0x1;
-const ErrorTypeUtils::ErrorType ErrorTypeUtils::MATCH_WITH_ACCENT_ERROR = 0x2;
-const ErrorTypeUtils::ErrorType ErrorTypeUtils::MATCH_WITH_DIGRAPH = 0x4;
-const ErrorTypeUtils::ErrorType ErrorTypeUtils::INTENTIONAL_OMISSION = 0x8;
-const ErrorTypeUtils::ErrorType ErrorTypeUtils::EDIT_CORRECTION = 0x10;
-const ErrorTypeUtils::ErrorType ErrorTypeUtils::PROXIMITY_CORRECTION = 0x20;
-const ErrorTypeUtils::ErrorType ErrorTypeUtils::COMPLETION = 0x40;
-const ErrorTypeUtils::ErrorType ErrorTypeUtils::NEW_WORD = 0x80;
+const ErrorTypeUtils::ErrorType ErrorTypeUtils::MATCH_WITH_WRONG_CASE = 0x1;
+const ErrorTypeUtils::ErrorType ErrorTypeUtils::MATCH_WITH_MISSING_ACCENT = 0x2;
+const ErrorTypeUtils::ErrorType ErrorTypeUtils::MATCH_WITH_WRONG_ACCENT = 0x4;
+const ErrorTypeUtils::ErrorType ErrorTypeUtils::MATCH_WITH_DIGRAPH = 0x8;
+const ErrorTypeUtils::ErrorType ErrorTypeUtils::INTENTIONAL_OMISSION = 0x10;
+const ErrorTypeUtils::ErrorType ErrorTypeUtils::EDIT_CORRECTION = 0x20;
+const ErrorTypeUtils::ErrorType ErrorTypeUtils::PROXIMITY_CORRECTION = 0x40;
+const ErrorTypeUtils::ErrorType ErrorTypeUtils::COMPLETION = 0x80;
+const ErrorTypeUtils::ErrorType ErrorTypeUtils::NEW_WORD = 0x100;
const ErrorTypeUtils::ErrorType ErrorTypeUtils::ERRORS_TREATED_AS_AN_EXACT_MATCH =
- NOT_AN_ERROR | MATCH_WITH_CASE_ERROR | MATCH_WITH_ACCENT_ERROR | MATCH_WITH_DIGRAPH;
+ NOT_AN_ERROR | MATCH_WITH_WRONG_CASE | MATCH_WITH_MISSING_ACCENT | MATCH_WITH_DIGRAPH;
const ErrorTypeUtils::ErrorType
ErrorTypeUtils::ERRORS_TREATED_AS_AN_EXACT_MATCH_WITH_INTENTIONAL_OMISSION =
diff --git a/native/jni/src/suggest/core/dictionary/error_type_utils.h b/native/jni/src/suggest/core/dictionary/error_type_utils.h
index e3e76b238..fd1d5fcff 100644
--- a/native/jni/src/suggest/core/dictionary/error_type_utils.h
+++ b/native/jni/src/suggest/core/dictionary/error_type_utils.h
@@ -30,8 +30,9 @@ class ErrorTypeUtils {
typedef uint32_t ErrorType;
static const ErrorType NOT_AN_ERROR;
- static const ErrorType MATCH_WITH_CASE_ERROR;
- static const ErrorType MATCH_WITH_ACCENT_ERROR;
+ static const ErrorType MATCH_WITH_WRONG_CASE;
+ static const ErrorType MATCH_WITH_MISSING_ACCENT;
+ static const ErrorType MATCH_WITH_WRONG_ACCENT;
static const ErrorType MATCH_WITH_DIGRAPH;
// Treat error as an intentional omission when the CorrectionType is omission and the node can
// be intentional omission.
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_writer.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_writer.cpp
index 278f2b199..97a8bcc98 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_writer.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_writer.cpp
@@ -234,8 +234,8 @@ bool Ver4PatriciaTrieNodeWriter::writeNewTerminalPtNodeAndAdvancePosition(
bool Ver4PatriciaTrieNodeWriter::addNgramEntry(const WordIdArrayView prevWordIds, const int wordId,
const BigramProperty *const bigramProperty, bool *const outAddedNewEntry) {
if (!mBigramPolicy->addNewEntry(prevWordIds[0], wordId, bigramProperty, outAddedNewEntry)) {
- AKLOGE("Cannot add new bigram entry. terminalId: %d, targetTerminalId: %d",
- sourcePtNodeParams->getTerminalId(), targetPtNodeParam->getTerminalId());
+ AKLOGE("Cannot add new bigram entry. prevWordId: %d, wordId: %d",
+ prevWordIds[0], wordId);
return false;
}
const int ptNodePos =
@@ -425,6 +425,18 @@ bool Ver4PatriciaTrieNodeWriter::updatePtNodeFlags(const int ptNodePos,
return true;
}
+bool Ver4PatriciaTrieNodeWriter::suppressUnigramEntry(const PtNodeParams *const ptNodeParams) {
+ if (!mHeaderPolicy->hasHistoricalInfoOfWords()) {
+ // Require historical info to suppress unigram entry.
+ return false;
+ }
+ const HistoricalInfo suppressedHistorycalInfo(0 /* timestamp */, 0 /* level */, 0 /* count */);
+ const ProbabilityEntry probabilityEntryToWrite =
+ ProbabilityEntry().createEntryWithUpdatedHistoricalInfo(&suppressedHistorycalInfo);
+ return mBuffers->getMutableProbabilityDictContent()->setProbabilityEntry(
+ ptNodeParams->getTerminalId(), &probabilityEntryToWrite);
+}
+
} // namespace v402
} // namespace backward
} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_writer.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_writer.h
index d49d9a666..9d8a55bff 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_writer.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_writer.h
@@ -111,6 +111,11 @@ class Ver4PatriciaTrieNodeWriter : public PtNodeWriter {
bool updatePtNodeHasBigramsAndShortcutTargetsFlags(const PtNodeParams *const ptNodeParams);
+ // Suppress unigram not to use the word for generating suggestions. So, this method can be used
+ // only for dictionaries with historical info. Also, suppressed entries are included in unigram
+ // count. They will be removed from the dictionary during GC.
+ bool suppressUnigramEntry(const PtNodeParams *const ptNodeParams);
+
private:
DISALLOW_COPY_AND_ASSIGN(Ver4PatriciaTrieNodeWriter);
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.cpp
index 1296b8acd..9c6452e40 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.cpp
@@ -210,7 +210,7 @@ bool Ver4PatriciaTriePolicy::addUnigramEntry(const int *const word, const int le
}
for (const auto &shortcut : unigramProperty->getShortcuts()) {
if (shortcut.getTargetCodePoints()->size() > MAX_WORD_LENGTH) {
- AKLOGE("One of shortcut targets is too long to insert to the dictionary, length: %d",
+ AKLOGE("One of shortcut targets is too long to insert to the dictionary, length: %zd",
shortcut.getTargetCodePoints()->size());
return false;
}
@@ -245,7 +245,7 @@ bool Ver4PatriciaTriePolicy::addUnigramEntry(const int *const word, const int le
if (!mUpdatingHelper.addShortcutTarget(wordPos,
shortcut.getTargetCodePoints()->data(),
shortcut.getTargetCodePoints()->size(), shortcut.getProbability())) {
- AKLOGE("Cannot add new shortcut target. PtNodePos: %d, length: %d, "
+ AKLOGE("Cannot add new shortcut target. PtNodePos: %d, length: %zd, "
"probability: %d", wordPos, shortcut.getTargetCodePoints()->size(),
shortcut.getProbability());
return false;
@@ -258,6 +258,20 @@ bool Ver4PatriciaTriePolicy::addUnigramEntry(const int *const word, const int le
}
}
+bool Ver4PatriciaTriePolicy::removeUnigramEntry(const int *const word, const int length) {
+ if (!mBuffers->isUpdatable()) {
+ AKLOGI("Warning: removeUnigramEntry() is called for non-updatable dictionary.");
+ return false;
+ }
+ const int ptNodePos = getTerminalPtNodePositionOfWord(word, length,
+ false /* forceLowerCaseSearch */);
+ if (ptNodePos == NOT_A_DICT_POS) {
+ return false;
+ }
+ const PtNodeParams ptNodeParams = mNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos);
+ return mNodeWriter.suppressUnigramEntry(&ptNodeParams);
+}
+
bool Ver4PatriciaTriePolicy::addNgramEntry(const PrevWordsInfo *const prevWordsInfo,
const BigramProperty *const bigramProperty) {
if (!mBuffers->isUpdatable()) {
@@ -275,7 +289,7 @@ bool Ver4PatriciaTriePolicy::addNgramEntry(const PrevWordsInfo *const prevWordsI
}
if (bigramProperty->getTargetCodePoints()->size() > MAX_WORD_LENGTH) {
AKLOGE("The word is too long to insert the ngram to the dictionary. "
- "length: %d", bigramProperty->getTargetCodePoints()->size());
+ "length: %zd", bigramProperty->getTargetCodePoints()->size());
return false;
}
int prevWordsPtNodePos[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.h
index 9e989b268..d77499636 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.h
@@ -108,10 +108,7 @@ class Ver4PatriciaTriePolicy : public DictionaryStructureWithBufferPolicy {
bool addUnigramEntry(const int *const word, const int length,
const UnigramProperty *const unigramProperty);
- bool removeUnigramEntry(const int *const word, const int length) {
- // Removing unigram entry is not supported.
- return false;
- }
+ bool removeUnigramEntry(const int *const word, const int length);
bool addNgramEntry(const PrevWordsInfo *const prevWordsInfo,
const BigramProperty *const bigramProperty);
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.cpp
index e4ea3da16..9fa93efc9 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.cpp
@@ -111,8 +111,7 @@ template<class DictConstants, class DictBuffers, class DictBuffersPtr, class Str
return nullptr;
}
const FormatUtils::FORMAT_VERSION formatVersion = FormatUtils::detectFormatVersion(
- mmappedBuffer->getReadOnlyByteArrayView().data(),
- mmappedBuffer->getReadOnlyByteArrayView().size());
+ mmappedBuffer->getReadOnlyByteArrayView());
switch (formatVersion) {
case FormatUtils::VERSION_2:
AKLOGE("Given path is a directory but the format is version 2. path: %s", path);
@@ -174,8 +173,7 @@ template<class DictConstants, class DictBuffers, class DictBuffersPtr, class Str
if (!mmappedBuffer) {
return nullptr;
}
- switch (FormatUtils::detectFormatVersion(mmappedBuffer->getReadOnlyByteArrayView().data(),
- mmappedBuffer->getReadOnlyByteArrayView().size())) {
+ switch (FormatUtils::detectFormatVersion(mmappedBuffer->getReadOnlyByteArrayView())) {
case FormatUtils::VERSION_2:
return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(
new PatriciaTriePolicy(std::move(mmappedBuffer)));
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.cpp
index 5dc91ba10..f3bc4a0cb 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.cpp
@@ -46,7 +46,7 @@ ProbabilityEntry LanguageModelDictContent::getNgramProbabilityEntry(
bool LanguageModelDictContent::setNgramProbabilityEntry(const WordIdArrayView prevWordIds,
const int terminalId, const ProbabilityEntry *const probabilityEntry) {
- const int bitmapEntryIndex = getBitmapEntryIndex(prevWordIds);
+ const int bitmapEntryIndex = createAndGetBitmapEntryIndex(prevWordIds);
if (bitmapEntryIndex == TrieMap::INVALID_INDEX) {
return false;
}
@@ -80,6 +80,19 @@ bool LanguageModelDictContent::runGCInner(
return true;
}
+int LanguageModelDictContent::createAndGetBitmapEntryIndex(const WordIdArrayView prevWordIds) {
+ if (prevWordIds.empty()) {
+ return mTrieMap.getRootBitmapEntryIndex();
+ }
+ const int lastBitmapEntryIndex =
+ getBitmapEntryIndex(prevWordIds.limit(prevWordIds.size() - 1));
+ if (lastBitmapEntryIndex == TrieMap::INVALID_INDEX) {
+ return TrieMap::INVALID_INDEX;
+ }
+ return mTrieMap.getNextLevelBitmapEntryIndex(prevWordIds[prevWordIds.size() - 1],
+ lastBitmapEntryIndex);
+}
+
int LanguageModelDictContent::getBitmapEntryIndex(const WordIdArrayView prevWordIds) const {
int bitmapEntryIndex = mTrieMap.getRootBitmapEntryIndex();
for (const int wordId : prevWordIds) {
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.h
index 18f2e0170..104ee2520 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.h
@@ -76,7 +76,7 @@ class LanguageModelDictContent {
bool runGCInner(const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
const TrieMap::TrieMapRange trieMapRange, const int nextLevelBitmapEntryIndex,
int *const outNgramCount);
-
+ int createAndGetBitmapEntryIndex(const WordIdArrayView prevWordIds);
int getBitmapEntryIndex(const WordIdArrayView prevWordIds) const;
};
} // namespace latinime
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 feff6b57f..ed77bd20e 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
@@ -21,6 +21,8 @@
#include <cstdint>
#include "defines.h"
+#include "suggest/core/dictionary/property/bigram_property.h"
+#include "suggest/core/dictionary/property/unigram_property.h"
#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h"
#include "suggest/policyimpl/dictionary/utils/historical_info.h"
@@ -45,6 +47,20 @@ class ProbabilityEntry {
const HistoricalInfo *const historicalInfo)
: mFlags(flags), mProbability(probability), mHistoricalInfo(*historicalInfo) {}
+ // Create from unigram property.
+ // TODO: Set flags.
+ ProbabilityEntry(const UnigramProperty *const unigramProperty)
+ : mFlags(0), mProbability(unigramProperty->getProbability()),
+ mHistoricalInfo(unigramProperty->getTimestamp(), unigramProperty->getLevel(),
+ unigramProperty->getCount()) {}
+
+ // Create from bigram property.
+ // TODO: Set flags.
+ ProbabilityEntry(const BigramProperty *const bigramProperty)
+ : mFlags(0), mProbability(bigramProperty->getProbability()),
+ mHistoricalInfo(bigramProperty->getTimestamp(), bigramProperty->getLevel(),
+ bigramProperty->getCount()) {}
+
const ProbabilityEntry createEntryWithUpdatedProbability(const int probability) const {
return ProbabilityEntry(mFlags, probability, &mHistoricalInfo);
}
@@ -54,6 +70,10 @@ class ProbabilityEntry {
return ProbabilityEntry(mFlags, mProbability, historicalInfo);
}
+ bool isValid() const {
+ return (mProbability != NOT_A_PROBABILITY) || hasHistoricalInfo();
+ }
+
bool hasHistoricalInfo() const {
return mHistoricalInfo.isValid();
}
@@ -89,7 +109,7 @@ class ProbabilityEntry {
static ProbabilityEntry decode(const uint64_t encodedEntry, const bool hasHistoricalInfo) {
if (hasHistoricalInfo) {
const int flags = readFromEncodedEntry(encodedEntry,
- Ver4DictConstants::FLAGS_IN_PROBABILITY_FILE_SIZE,
+ Ver4DictConstants::FLAGS_IN_LANGUAGE_MODEL_SIZE,
Ver4DictConstants::TIME_STAMP_FIELD_SIZE
+ Ver4DictConstants::WORD_LEVEL_FIELD_SIZE
+ Ver4DictConstants::WORD_COUNT_FIELD_SIZE);
@@ -106,7 +126,7 @@ class ProbabilityEntry {
return ProbabilityEntry(flags, NOT_A_PROBABILITY, &historicalInfo);
} else {
const int flags = readFromEncodedEntry(encodedEntry,
- Ver4DictConstants::FLAGS_IN_PROBABILITY_FILE_SIZE,
+ Ver4DictConstants::FLAGS_IN_LANGUAGE_MODEL_SIZE,
Ver4DictConstants::PROBABILITY_SIZE);
const int probability = readFromEncodedEntry(encodedEntry,
Ver4DictConstants::PROBABILITY_SIZE, 0 /* pos */);
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 93d4e562d..e622442ba 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
@@ -46,7 +46,7 @@ const int Ver4DictConstants::SHORTCUT_BUFFERS_INDEX =
const int Ver4DictConstants::NOT_A_TERMINAL_ID = -1;
const int Ver4DictConstants::PROBABILITY_SIZE = 1;
-const int Ver4DictConstants::FLAGS_IN_PROBABILITY_FILE_SIZE = 1;
+const int Ver4DictConstants::FLAGS_IN_LANGUAGE_MODEL_SIZE = 1;
const int Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE = 3;
const int Ver4DictConstants::NOT_A_TERMINAL_ADDRESS = 0;
const int Ver4DictConstants::TERMINAL_ID_FIELD_SIZE = 4;
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 6950ca70f..8d29f60d4 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
@@ -41,7 +41,7 @@ class Ver4DictConstants {
static const int NOT_A_TERMINAL_ID;
static const int PROBABILITY_SIZE;
- static const int FLAGS_IN_PROBABILITY_FILE_SIZE;
+ static const int FLAGS_IN_LANGUAGE_MODEL_SIZE;
static const int TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE;
static const int NOT_A_TERMINAL_ADDRESS;
static const int TERMINAL_ID_FIELD_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 857222f5d..2c848cb29 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
@@ -145,10 +145,11 @@ bool Ver4PatriciaTrieNodeWriter::updatePtNodeUnigramProperty(
const ProbabilityEntry originalProbabilityEntry =
mBuffers->getLanguageModelDictContent()->getProbabilityEntry(
toBeUpdatedPtNodeParams->getTerminalId());
- const ProbabilityEntry probabilityEntry = createUpdatedEntryFrom(&originalProbabilityEntry,
- unigramProperty);
+ const ProbabilityEntry probabilityEntryOfUnigramProperty = ProbabilityEntry(unigramProperty);
+ const ProbabilityEntry updatedProbabilityEntry =
+ createUpdatedEntryFrom(&originalProbabilityEntry, &probabilityEntryOfUnigramProperty);
return mBuffers->getMutableLanguageModelDictContent()->setProbabilityEntry(
- toBeUpdatedPtNodeParams->getTerminalId(), &probabilityEntry);
+ toBeUpdatedPtNodeParams->getTerminalId(), &updatedProbabilityEntry);
}
bool Ver4PatriciaTrieNodeWriter::updatePtNodeProbabilityAndGetNeedsToKeepPtNodeAfterGC(
@@ -216,16 +217,36 @@ bool Ver4PatriciaTrieNodeWriter::writeNewTerminalPtNodeAndAdvancePosition(
}
// Write probability.
ProbabilityEntry newProbabilityEntry;
+ const ProbabilityEntry probabilityEntryOfUnigramProperty = ProbabilityEntry(unigramProperty);
const ProbabilityEntry probabilityEntryToWrite = createUpdatedEntryFrom(
- &newProbabilityEntry, unigramProperty);
+ &newProbabilityEntry, &probabilityEntryOfUnigramProperty);
return mBuffers->getMutableLanguageModelDictContent()->setProbabilityEntry(
terminalId, &probabilityEntryToWrite);
}
bool Ver4PatriciaTrieNodeWriter::addNgramEntry(const WordIdArrayView prevWordIds, const int wordId,
const BigramProperty *const bigramProperty, bool *const outAddedNewBigram) {
+ // TODO: Support n-gram.
+ LanguageModelDictContent *const languageModelDictContent =
+ mBuffers->getMutableLanguageModelDictContent();
+ const ProbabilityEntry probabilityEntry =
+ languageModelDictContent->getNgramProbabilityEntry(
+ prevWordIds.limit(1 /* maxSize */), wordId);
+ const ProbabilityEntry probabilityEntryOfBigramProperty(bigramProperty);
+ const ProbabilityEntry updatedProbabilityEntry = createUpdatedEntryFrom(
+ &probabilityEntry, &probabilityEntryOfBigramProperty);
+ if (!languageModelDictContent->setNgramProbabilityEntry(
+ prevWordIds.limit(1 /* maxSize */), wordId, &updatedProbabilityEntry)) {
+ AKLOGE("Cannot add new ngram entry. prevWordId: %d, wordId: %d",
+ prevWordIds[0], wordId);
+ return false;
+ }
+ if (!probabilityEntry.isValid() && outAddedNewBigram) {
+ *outAddedNewBigram = true;
+ }
+ // TODO: Remove.
if (!mBigramPolicy->addNewEntry(prevWordIds[0], wordId, bigramProperty, outAddedNewBigram)) {
- AKLOGE("Cannot add new bigram entry. terminalId: %d, targetTerminalId: %d",
+ AKLOGE("Cannot add new bigram entry. prevWordId: %d, wordId: %d",
prevWordIds[0], wordId);
return false;
}
@@ -234,6 +255,7 @@ bool Ver4PatriciaTrieNodeWriter::addNgramEntry(const WordIdArrayView prevWordIds
bool Ver4PatriciaTrieNodeWriter::removeNgramEntry(const WordIdArrayView prevWordIds,
const int wordId) {
+ // TODO: Remove.
return mBigramPolicy->removeEntry(prevWordIds[0], wordId);
}
@@ -352,20 +374,19 @@ bool Ver4PatriciaTrieNodeWriter::writePtNodeAndGetTerminalIdAndAdvancePosition(
const ProbabilityEntry Ver4PatriciaTrieNodeWriter::createUpdatedEntryFrom(
const ProbabilityEntry *const originalProbabilityEntry,
- const UnigramProperty *const unigramProperty) const {
+ const ProbabilityEntry *const probabilityEntry) const {
// TODO: Consolidate historical info and probability.
if (mHeaderPolicy->hasHistoricalInfoOfWords()) {
- const HistoricalInfo historicalInfoForUpdate(unigramProperty->getTimestamp(),
- unigramProperty->getLevel(), unigramProperty->getCount());
const HistoricalInfo updatedHistoricalInfo =
ForgettingCurveUtils::createUpdatedHistoricalInfo(
originalProbabilityEntry->getHistoricalInfo(),
- unigramProperty->getProbability(), &historicalInfoForUpdate, mHeaderPolicy);
+ probabilityEntry->getProbability(), probabilityEntry->getHistoricalInfo(),
+ mHeaderPolicy);
return originalProbabilityEntry->createEntryWithUpdatedHistoricalInfo(
&updatedHistoricalInfo);
} else {
return originalProbabilityEntry->createEntryWithUpdatedProbability(
- unigramProperty->getProbability());
+ probabilityEntry->getProbability());
}
}
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.h
index 6703dba04..5d73b6ea3 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.h
@@ -98,12 +98,12 @@ class Ver4PatriciaTrieNodeWriter : public PtNodeWriter {
const PtNodeParams *const ptNodeParams, int *const outTerminalId,
int *const ptNodeWritingPos);
- // Create updated probability entry using given unigram property. In addition to the
+ // Create updated probability entry using given probability property. In addition to the
// probability, this method updates historical information if needed.
- // TODO: Update flags belonging to the unigram property.
+ // TODO: Update flags.
const ProbabilityEntry createUpdatedEntryFrom(
const ProbabilityEntry *const originalProbabilityEntry,
- const UnigramProperty *const unigramProperty) const;
+ const ProbabilityEntry *const probabilityEntry) const;
bool updatePtNodeFlags(const int ptNodePos, const bool isBlacklisted, const bool isNotAWord,
const bool isTerminal, const bool hasMultipleChars);
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp
index 723808399..d8f4595ff 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp
@@ -200,7 +200,7 @@ bool Ver4PatriciaTriePolicy::addUnigramEntry(const int *const word, const int le
}
for (const auto &shortcut : unigramProperty->getShortcuts()) {
if (shortcut.getTargetCodePoints()->size() > MAX_WORD_LENGTH) {
- AKLOGE("One of shortcut targets is too long to insert to the dictionary, length: %d",
+ AKLOGE("One of shortcut targets is too long to insert to the dictionary, length: %zd",
shortcut.getTargetCodePoints()->size());
return false;
}
@@ -235,7 +235,7 @@ bool Ver4PatriciaTriePolicy::addUnigramEntry(const int *const word, const int le
if (!mUpdatingHelper.addShortcutTarget(wordPos,
shortcut.getTargetCodePoints()->data(),
shortcut.getTargetCodePoints()->size(), shortcut.getProbability())) {
- AKLOGE("Cannot add new shortcut target. PtNodePos: %d, length: %d, "
+ AKLOGE("Cannot add new shortcut target. PtNodePos: %d, length: %zd, "
"probability: %d", wordPos, shortcut.getTargetCodePoints()->size(),
shortcut.getProbability());
return false;
@@ -286,7 +286,7 @@ bool Ver4PatriciaTriePolicy::addNgramEntry(const PrevWordsInfo *const prevWordsI
}
if (bigramProperty->getTargetCodePoints()->size() > MAX_WORD_LENGTH) {
AKLOGE("The word is too long to insert the ngram to the dictionary. "
- "length: %d", bigramProperty->getTargetCodePoints()->size());
+ "length: %zd", bigramProperty->getTargetCodePoints()->size());
return false;
}
int prevWordsPtNodePos[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.cpp
index 1916ea560..e6e7167c2 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.cpp
@@ -23,7 +23,7 @@ namespace latinime {
const uint32_t FormatUtils::MAGIC_NUMBER = 0x9BC13AFE;
// Magic number (4 bytes), version (2 bytes), flags (2 bytes), header size (4 bytes) = 12
-const int FormatUtils::DICTIONARY_MINIMUM_SIZE = 12;
+const size_t FormatUtils::DICTIONARY_MINIMUM_SIZE = 12;
/* static */ FormatUtils::FORMAT_VERSION FormatUtils::getFormatVersion(const int formatVersion) {
switch (formatVersion) {
@@ -40,14 +40,14 @@ const int FormatUtils::DICTIONARY_MINIMUM_SIZE = 12;
}
}
/* static */ FormatUtils::FORMAT_VERSION FormatUtils::detectFormatVersion(
- const uint8_t *const dict, const int dictSize) {
+ const ReadOnlyByteArrayView dictBuffer) {
// The magic number is stored big-endian.
// If the dictionary is less than 4 bytes, we can't even read the magic number, so we don't
// understand this format.
- if (dictSize < DICTIONARY_MINIMUM_SIZE) {
+ if (dictBuffer.size() < DICTIONARY_MINIMUM_SIZE) {
return UNKNOWN_VERSION;
}
- const uint32_t magicNumber = ByteArrayUtils::readUint32(dict, 0);
+ const uint32_t magicNumber = ByteArrayUtils::readUint32(dictBuffer.data(), 0);
switch (magicNumber) {
case MAGIC_NUMBER:
// The layout of the header is as follows:
@@ -58,7 +58,7 @@ const int FormatUtils::DICTIONARY_MINIMUM_SIZE = 12;
// Conceptually this converts the hardcoded value of the bytes in the file into
// the symbolic value we use in the code. But we want the constants to be the
// same so we use them for both here.
- return getFormatVersion(ByteArrayUtils::readUint16(dict, 4));
+ return getFormatVersion(ByteArrayUtils::readUint16(dictBuffer.data(), 4));
default:
return UNKNOWN_VERSION;
}
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.h b/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.h
index 55ad5799f..51ad9877c 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.h
@@ -20,6 +20,7 @@
#include <cstdint>
#include "defines.h"
+#include "utils/byte_array_view.h"
namespace latinime {
@@ -42,12 +43,12 @@ class FormatUtils {
static const uint32_t MAGIC_NUMBER;
static FORMAT_VERSION getFormatVersion(const int formatVersion);
- static FORMAT_VERSION detectFormatVersion(const uint8_t *const dict, const int dictSize);
+ static FORMAT_VERSION detectFormatVersion(const ReadOnlyByteArrayView dictBuffer);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(FormatUtils);
- static const int DICTIONARY_MINIMUM_SIZE;
+ static const size_t DICTIONARY_MINIMUM_SIZE;
};
} // namespace latinime
#endif /* LATINIME_FORMAT_UTILS_H */
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 407b8efd0..e630aba9a 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/trie_map.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/trie_map.cpp
@@ -26,6 +26,7 @@ const int TrieMap::FIELD1_SIZE = 3;
const int TrieMap::ENTRY_SIZE = FIELD0_SIZE + FIELD1_SIZE;
const uint32_t TrieMap::VALUE_FLAG = 0x400000;
const uint32_t TrieMap::VALUE_MASK = 0x3FFFFF;
+const uint32_t TrieMap::INVALID_VALUE_IN_KEY_VALUE_ENTRY = VALUE_MASK;
const uint32_t TrieMap::TERMINAL_LINK_FLAG = 0x800000;
const uint32_t TrieMap::TERMINAL_LINK_MASK = 0x7FFFFF;
const int TrieMap::NUM_OF_BITS_USED_FOR_ONE_LEVEL = 5;
@@ -34,6 +35,7 @@ const int TrieMap::MAX_NUM_OF_ENTRIES_IN_ONE_LEVEL = 1 << NUM_OF_BITS_USED_FOR_O
const int TrieMap::ROOT_BITMAP_ENTRY_INDEX = 0;
const int TrieMap::ROOT_BITMAP_ENTRY_POS = MAX_NUM_OF_ENTRIES_IN_ONE_LEVEL * FIELD0_SIZE;
const TrieMap::Entry TrieMap::EMPTY_BITMAP_ENTRY = TrieMap::Entry(0, 0);
+const int TrieMap::TERMINAL_LINKED_ENTRY_COUNT = 2; // Value entry and bitmap entry.
const uint64_t TrieMap::MAX_VALUE =
(static_cast<uint64_t>(1) << ((FIELD0_SIZE + FIELD1_SIZE) * CHAR_BIT)) - 1;
const int TrieMap::MAX_BUFFER_SIZE = TERMINAL_LINK_MASK * ENTRY_SIZE;
@@ -76,7 +78,7 @@ int TrieMap::getNextLevelBitmapEntryIndex(const int key, const int bitmapEntryIn
return terminalEntry.getValueEntryIndex() + 1;
}
// Create a value entry and a bitmap entry.
- const int valueEntryIndex = allocateTable(2 /* entryCount */);
+ const int valueEntryIndex = allocateTable(TERMINAL_LINKED_ENTRY_COUNT);
if (!writeEntry(Entry(0, terminalEntry.getValue()), valueEntryIndex)) {
return INVALID_INDEX;
}
@@ -108,6 +110,31 @@ bool TrieMap::save(FILE *const file) const {
return DictFileWritingUtils::writeBufferToFileTail(file, &mBuffer);
}
+bool TrieMap::remove(const int key, const int bitmapEntryIndex) {
+ const Entry bitmapEntry = readEntry(bitmapEntryIndex);
+ const uint32_t unsignedKey = static_cast<uint32_t>(key);
+ const int terminalEntryIndex = getTerminalEntryIndex(
+ unsignedKey, getBitShuffledKey(unsignedKey), bitmapEntry, 0 /* level */);
+ if (terminalEntryIndex == INVALID_INDEX) {
+ // Not found.
+ return false;
+ }
+ const Entry terminalEntry = readEntry(terminalEntryIndex);
+ if (!writeField1(VALUE_FLAG ^ INVALID_VALUE_IN_KEY_VALUE_ENTRY , terminalEntryIndex)) {
+ return false;
+ }
+ if (terminalEntry.hasTerminalLink()) {
+ const Entry nextLevelBitmapEntry = readEntry(terminalEntry.getValueEntryIndex() + 1);
+ if (!freeTable(terminalEntry.getValueEntryIndex(), TERMINAL_LINKED_ENTRY_COUNT)) {
+ return false;
+ }
+ if (!removeInner(nextLevelBitmapEntry)){
+ return false;
+ }
+ }
+ return true;
+}
+
/**
* Iterate next entry in a certain level.
*
@@ -129,7 +156,7 @@ const TrieMap::Result TrieMap::iterateNext(std::vector<TableIterationState> *con
if (entry.isBitmapEntry()) {
// Move to child.
iterationState->emplace_back(popCount(entry.getBitmap()), entry.getTableIndex());
- } else {
+ } else if (entry.isValidTerminalEntry()) {
if (outKey) {
*outKey = entry.getKey();
}
@@ -162,12 +189,12 @@ uint32_t TrieMap::getBitShuffledKey(const uint32_t key) const {
}
bool TrieMap::writeValue(const uint64_t value, const int terminalEntryIndex) {
- if (value <= VALUE_MASK) {
+ if (value < VALUE_MASK) {
// Write value into the terminal entry.
return writeField1(value | VALUE_FLAG, terminalEntryIndex);
}
// Create value entry and write value.
- const int valueEntryIndex = allocateTable(2 /* entryCount */);
+ const int valueEntryIndex = allocateTable(TERMINAL_LINKED_ENTRY_COUNT);
if (!writeEntry(Entry(value >> (FIELD1_SIZE * CHAR_BIT), value), valueEntryIndex)) {
return false;
}
@@ -227,6 +254,9 @@ int TrieMap::getTerminalEntryIndex(const uint32_t key, const uint32_t hashedKey,
// Move to the next level.
return getTerminalEntryIndex(key, hashedKey, entry, level + 1);
}
+ if (!entry.isValidTerminalEntry()) {
+ return INVALID_INDEX;
+ }
if (entry.getKey() == key) {
// Terminal entry is found.
return entryIndex;
@@ -287,6 +317,10 @@ bool TrieMap::putInternal(const uint32_t key, const uint64_t value, const uint32
// Bitmap entry is found. Go to the next level.
return putInternal(key, value, hashedKey, entryIndex, entry, level + 1);
}
+ if (!entry.isValidTerminalEntry()) {
+ // Overwrite invalid terminal entry.
+ return writeTerminalEntry(key, value, entryIndex);
+ }
if (entry.getKey() == key) {
// Terminal entry for the key is found. Update the value.
return updateValue(entry, value, entryIndex);
@@ -384,4 +418,33 @@ bool TrieMap::addNewEntryByExpandingTable(const uint32_t key, const uint64_t val
return true;
}
+bool TrieMap::removeInner(const Entry &bitmapEntry) {
+ const int tableSize = popCount(bitmapEntry.getBitmap());
+ for (int i = 0; i < tableSize; ++i) {
+ const int entryIndex = bitmapEntry.getTableIndex() + i;
+ const Entry entry = readEntry(entryIndex);
+ if (entry.isBitmapEntry()) {
+ // Delete next bitmap entry recursively.
+ if (!removeInner(entry)) {
+ return false;
+ }
+ } else {
+ // Invalidate terminal entry just in case.
+ if (!writeField1(VALUE_FLAG ^ INVALID_VALUE_IN_KEY_VALUE_ENTRY , entryIndex)) {
+ return false;
+ }
+ if (entry.hasTerminalLink()) {
+ const Entry nextLevelBitmapEntry = readEntry(entry.getValueEntryIndex() + 1);
+ if (!freeTable(entry.getValueEntryIndex(), TERMINAL_LINKED_ENTRY_COUNT)) {
+ return false;
+ }
+ if (!removeInner(nextLevelBitmapEntry)) {
+ return false;
+ }
+ }
+ }
+ }
+ return freeTable(bitmapEntry.getTableIndex(), tableSize);
+}
+
} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/trie_map.h b/native/jni/src/suggest/policyimpl/dictionary/utils/trie_map.h
index 3e5c4010c..6d91790b2 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/trie_map.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/trie_map.h
@@ -202,6 +202,8 @@ class TrieMap {
bool save(FILE *const file) const;
+ bool remove(const int key, const int bitmapEntryIndex);
+
private:
DISALLOW_COPY_AND_ASSIGN(TrieMap);
@@ -245,6 +247,11 @@ class TrieMap {
}
// For terminal entry.
+ AK_FORCE_INLINE bool isValidTerminalEntry() const {
+ return hasTerminalLink() || ((mData1 & VALUE_MASK) != INVALID_VALUE_IN_KEY_VALUE_ENTRY);
+ }
+
+ // For terminal entry.
AK_FORCE_INLINE uint32_t getValueEntryIndex() const {
return mData1 & TERMINAL_LINK_MASK;
}
@@ -272,6 +279,7 @@ class TrieMap {
static const int ENTRY_SIZE;
static const uint32_t VALUE_FLAG;
static const uint32_t VALUE_MASK;
+ static const uint32_t INVALID_VALUE_IN_KEY_VALUE_ENTRY;
static const uint32_t TERMINAL_LINK_FLAG;
static const uint32_t TERMINAL_LINK_MASK;
static const int NUM_OF_BITS_USED_FOR_ONE_LEVEL;
@@ -280,6 +288,7 @@ class TrieMap {
static const int ROOT_BITMAP_ENTRY_INDEX;
static const int ROOT_BITMAP_ENTRY_POS;
static const Entry EMPTY_BITMAP_ENTRY;
+ static const int TERMINAL_LINKED_ENTRY_COUNT;
static const int MAX_BUFFER_SIZE;
uint32_t getBitShuffledKey(const uint32_t key) const;
@@ -378,6 +387,8 @@ class TrieMap {
AK_FORCE_INLINE int getTailEntryIndex() const {
return (mBuffer.getTailPosition() - ROOT_BITMAP_ENTRY_POS) / ENTRY_SIZE;
}
+
+ bool removeInner(const Entry &bitmapEntry);
};
} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/typing/typing_scoring.h b/native/jni/src/suggest/policyimpl/typing/typing_scoring.h
index 04cb6603a..52c4251f0 100644
--- a/native/jni/src/suggest/policyimpl/typing/typing_scoring.h
+++ b/native/jni/src/suggest/policyimpl/typing/typing_scoring.h
@@ -51,10 +51,10 @@ class TypingScoring : public Scoring {
}
if (boostExactMatches && ErrorTypeUtils::isExactMatch(containedErrorTypes)) {
score += ScoringParams::EXACT_MATCH_PROMOTION;
- if ((ErrorTypeUtils::MATCH_WITH_CASE_ERROR & containedErrorTypes) != 0) {
+ if ((ErrorTypeUtils::MATCH_WITH_WRONG_CASE & containedErrorTypes) != 0) {
score -= ScoringParams::CASE_ERROR_PENALTY_FOR_EXACT_MATCH;
}
- if ((ErrorTypeUtils::MATCH_WITH_ACCENT_ERROR & containedErrorTypes) != 0) {
+ if ((ErrorTypeUtils::MATCH_WITH_MISSING_ACCENT & containedErrorTypes) != 0) {
score -= ScoringParams::ACCENT_ERROR_PENALTY_FOR_EXACT_MATCH;
}
if ((ErrorTypeUtils::MATCH_WITH_DIGRAPH & containedErrorTypes) != 0) {
diff --git a/native/jni/src/suggest/policyimpl/typing/typing_weighting.cpp b/native/jni/src/suggest/policyimpl/typing/typing_weighting.cpp
index 54f65c786..1d590c353 100644
--- a/native/jni/src/suggest/policyimpl/typing/typing_weighting.cpp
+++ b/native/jni/src/suggest/policyimpl/typing/typing_weighting.cpp
@@ -36,25 +36,34 @@ ErrorTypeUtils::ErrorType TypingWeighting::getErrorType(const CorrectionType cor
// Compare the node code point with original primary code point on the keyboard.
const ProximityInfoState *const pInfoState =
traverseSession->getProximityInfoState(0);
- const int primaryOriginalCodePoint = pInfoState->getPrimaryOriginalCodePointAt(
+ const int primaryCodePoint = pInfoState->getPrimaryCodePointAt(
dicNode->getInputIndex(0));
const int nodeCodePoint = dicNode->getNodeCodePoint();
- if (primaryOriginalCodePoint == nodeCodePoint) {
+ // TODO: Check whether the input code point is on the keyboard.
+ if (primaryCodePoint == nodeCodePoint) {
// Node code point is same as original code point on the keyboard.
return ErrorTypeUtils::NOT_AN_ERROR;
- } else if (CharUtils::toLowerCase(primaryOriginalCodePoint) ==
+ } else if (CharUtils::toLowerCase(primaryCodePoint) ==
CharUtils::toLowerCase(nodeCodePoint)) {
// Only cases of the code points are different.
- return ErrorTypeUtils::MATCH_WITH_CASE_ERROR;
- } else if (CharUtils::toBaseCodePoint(primaryOriginalCodePoint) ==
- CharUtils::toBaseCodePoint(nodeCodePoint)) {
+ return ErrorTypeUtils::MATCH_WITH_WRONG_CASE;
+ } else if (primaryCodePoint == CharUtils::toBaseCodePoint(nodeCodePoint)) {
// Node code point is a variant of original code point.
- return ErrorTypeUtils::MATCH_WITH_ACCENT_ERROR;
- } else {
+ return ErrorTypeUtils::MATCH_WITH_MISSING_ACCENT;
+ } else if (CharUtils::toBaseCodePoint(primaryCodePoint)
+ == CharUtils::toBaseCodePoint(nodeCodePoint)) {
+ // Base code points are the same but the code point is intentionally input.
+ return ErrorTypeUtils::MATCH_WITH_WRONG_ACCENT;
+ } else if (CharUtils::toLowerCase(primaryCodePoint)
+ == CharUtils::toBaseLowerCase(nodeCodePoint)) {
// Node code point is a variant of original code point and the cases are also
// different.
- return ErrorTypeUtils::MATCH_WITH_ACCENT_ERROR
- | ErrorTypeUtils::MATCH_WITH_CASE_ERROR;
+ return ErrorTypeUtils::MATCH_WITH_MISSING_ACCENT
+ | ErrorTypeUtils::MATCH_WITH_WRONG_CASE;
+ } else {
+ // Base code points are the same and the cases are different.
+ return ErrorTypeUtils::MATCH_WITH_WRONG_ACCENT
+ | ErrorTypeUtils::MATCH_WITH_WRONG_CASE;
}
}
break;
diff --git a/native/jni/src/utils/int_array_view.h b/native/jni/src/utils/int_array_view.h
index c1ddc9812..53f2d2971 100644
--- a/native/jni/src/utils/int_array_view.h
+++ b/native/jni/src/utils/int_array_view.h
@@ -91,6 +91,11 @@ class IntArrayView {
return mPtr + mSize;
}
+ // Returns the view whose size is smaller than or equal to the given count.
+ const IntArrayView limit(const size_t maxSize) const {
+ return IntArrayView(mPtr, std::min(maxSize, mSize));
+ }
+
private:
DISALLOW_ASSIGNMENT_OPERATOR(IntArrayView);
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 df778b6cf..8c8e8838a 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
@@ -47,6 +47,31 @@ TEST(TrieMapTest, TestSetAndGet) {
EXPECT_EQ(0xFFFFFFFFFull, trieMap.getRoot(0).mValue);
}
+TEST(TrieMapTest, TestRemove) {
+ TrieMap trieMap;
+ trieMap.putRoot(10, 10);
+ EXPECT_EQ(10ull, trieMap.getRoot(10).mValue);
+ EXPECT_TRUE(trieMap.remove(10, trieMap.getRootBitmapEntryIndex()));
+ EXPECT_FALSE(trieMap.getRoot(10).mIsValid);
+ for (const auto &element : trieMap.getEntriesInRootLevel()) {
+ EXPECT_TRUE(false);
+ }
+ EXPECT_TRUE(trieMap.putRoot(10, 0x3FFFFF));
+ EXPECT_FALSE(trieMap.remove(11, trieMap.getRootBitmapEntryIndex()))
+ << "Should fail if the key does not exist.";
+ EXPECT_EQ(0x3FFFFFull, trieMap.getRoot(10).mValue);
+ trieMap.putRoot(12, 11);
+ const int nextLevel = trieMap.getNextLevelBitmapEntryIndex(10);
+ trieMap.put(10, 10, nextLevel);
+ EXPECT_EQ(0x3FFFFFull, trieMap.getRoot(10).mValue);
+ EXPECT_EQ(10ull, trieMap.get(10, nextLevel).mValue);
+ EXPECT_TRUE(trieMap.remove(10, trieMap.getRootBitmapEntryIndex()));
+ const TrieMap::Result result = trieMap.getRoot(10);
+ EXPECT_FALSE(result.mIsValid);
+ EXPECT_EQ(TrieMap::INVALID_INDEX, result.mNextLevelBitmapEntryIndex);
+ EXPECT_EQ(11ull, trieMap.getRoot(12).mValue);
+}
+
TEST(TrieMapTest, TestSetAndGetLarge) {
static const int ELEMENT_COUNT = 200000;
TrieMap trieMap;
diff --git a/native/jni/tests/utils/int_array_view_test.cpp b/native/jni/tests/utils/int_array_view_test.cpp
index bd843ab02..ecc451af0 100644
--- a/native/jni/tests/utils/int_array_view_test.cpp
+++ b/native/jni/tests/utils/int_array_view_test.cpp
@@ -53,9 +53,24 @@ TEST(IntArrayViewTest, TestConstructFromArray) {
TEST(IntArrayViewTest, TestConstructFromObject) {
const int object = 10;
const auto intArrayView = IntArrayView::fromObject(&object);
- EXPECT_EQ(1, intArrayView.size());
+ EXPECT_EQ(1u, intArrayView.size());
EXPECT_EQ(object, intArrayView[0]);
}
+TEST(IntArrayViewTest, TestLimit) {
+ const std::vector<int> intVector = {3, 2, 1, 0, -1, -2};
+ IntArrayView intArrayView(intVector);
+
+ EXPECT_TRUE(intArrayView.limit(0).empty());
+ EXPECT_EQ(intArrayView.size(), intArrayView.limit(intArrayView.size()).size());
+ EXPECT_EQ(intArrayView.size(), intArrayView.limit(1000).size());
+
+ IntArrayView subView = intArrayView.limit(4);
+ EXPECT_EQ(4u, subView.size());
+ for (size_t i = 0; i < subView.size(); ++i) {
+ EXPECT_EQ(intVector[i], subView[i]);
+ }
+}
+
} // namespace
} // namespace latinime
diff --git a/tests/src/com/android/inputmethod/keyboard/KeyboardThemeTests.java b/tests/src/com/android/inputmethod/keyboard/KeyboardThemeTests.java
index 0c7e4000e..c20954f81 100644
--- a/tests/src/com/android/inputmethod/keyboard/KeyboardThemeTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/KeyboardThemeTests.java
@@ -16,6 +16,7 @@
package com.android.inputmethod.keyboard;
+import static com.android.inputmethod.compat.BuildCompatUtils.VERSION_CODES_LXX;
import static com.android.inputmethod.keyboard.KeyboardTheme.THEME_ID_ICS;
import static com.android.inputmethod.keyboard.KeyboardTheme.THEME_ID_KLP;
import static com.android.inputmethod.keyboard.KeyboardTheme.THEME_ID_LXX_DARK;
@@ -31,9 +32,6 @@ import android.test.suitebuilder.annotation.SmallTest;
public class KeyboardThemeTests extends AndroidTestCase {
private SharedPreferences mPrefs;
- // TODO: Remove this constant once the *next* version becomes available.
- private static final int VERSION_CODES_LXX = VERSION_CODES.CUR_DEVELOPMENT;
-
private static final int THEME_ID_NULL = -1;
private static final int THEME_ID_UNKNOWN = -2;
private static final int THEME_ID_ILLEGAL = -3;
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/ArmenianPhonetic.java b/tests/src/com/android/inputmethod/keyboard/layout/ArmenianPhonetic.java
index 42ce0c1ea..dba91b4da 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/ArmenianPhonetic.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/ArmenianPhonetic.java
@@ -39,6 +39,9 @@ public final class ArmenianPhonetic extends LayoutBase {
public ArmenianPhoneticCustomizer(final Locale locale) { super(locale); }
@Override
+ public int getNumberOfRows() { return 5; }
+
+ @Override
public ExpectedKey getAlphabetKey() { return ARMENIAN_ALPHABET_KEY; }
@Override
@@ -112,29 +115,6 @@ public final class ArmenianPhonetic extends LayoutBase {
return builder.build();
}
- // Helper method to create alphabet layout by adding special function keys.
- @Override
- ExpectedKeyboardBuilder convertCommonLayoutToKeyboard(final ExpectedKeyboardBuilder builder,
- final boolean isPhone) {
- final LayoutCustomizer customizer = getCustomizer();
- builder.setKeysOfRow(5, (Object[])customizer.getSpaceKeys(isPhone));
- builder.addKeysOnTheLeftOfRow(5, (Object[])customizer.getKeysLeftToSpacebar(isPhone));
- builder.addKeysOnTheRightOfRow(5, (Object[])customizer.getKeysRightToSpacebar(isPhone));
- if (isPhone) {
- builder.addKeysOnTheRightOfRow(4, DELETE_KEY)
- .addKeysOnTheLeftOfRow(5, customizer.getSymbolsKey())
- .addKeysOnTheRightOfRow(5, key(ENTER_KEY, EMOJI_KEY));
- } else {
- builder.addKeysOnTheRightOfRow(1, DELETE_KEY)
- .addKeysOnTheRightOfRow(3, ENTER_KEY)
- .addKeysOnTheLeftOfRow(5, customizer.getSymbolsKey())
- .addKeysOnTheRightOfRow(5, EMOJI_KEY);
- }
- builder.addKeysOnTheLeftOfRow(4, (Object[])customizer.getLeftShiftKeys(isPhone))
- .addKeysOnTheRightOfRow(4, (Object[])customizer.getRightShiftKeys(isPhone));
- return builder;
- }
-
private static final ExpectedKey[][] ALPHABET_COMMON = new ExpectedKeyboardBuilder()
.setKeysOfRow(1,
// U+0567: "է" ARMENIAN SMALL LETTER EH
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Khmer.java b/tests/src/com/android/inputmethod/keyboard/layout/Khmer.java
index 143ccf6eb..7e4f159ab 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Khmer.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Khmer.java
@@ -40,6 +40,9 @@ public final class Khmer extends LayoutBase {
public KhmerCustomizer(final Locale locale) { super(locale); }
@Override
+ public int getNumberOfRows() { return 5; }
+
+ @Override
public ExpectedKey getAlphabetKey() { return KHMER_ALPHABET_KEY; }
@Override
@@ -79,29 +82,6 @@ public final class Khmer extends LayoutBase {
return ALPHABET_SHIFTED_COMMON;
}
- // Helper method to create alphabet layout by adding special function keys.
- @Override
- ExpectedKeyboardBuilder convertCommonLayoutToKeyboard(final ExpectedKeyboardBuilder builder,
- final boolean isPhone) {
- final LayoutCustomizer customizer = getCustomizer();
- builder.setKeysOfRow(5, (Object[])customizer.getSpaceKeys(isPhone));
- builder.addKeysOnTheLeftOfRow(5, (Object[])customizer.getKeysLeftToSpacebar(isPhone));
- builder.addKeysOnTheRightOfRow(5, (Object[])customizer.getKeysRightToSpacebar(isPhone));
- if (isPhone) {
- builder.addKeysOnTheRightOfRow(4, DELETE_KEY)
- .addKeysOnTheLeftOfRow(5, customizer.getSymbolsKey())
- .addKeysOnTheRightOfRow(5, key(ENTER_KEY, EMOJI_KEY));
- } else {
- builder.addKeysOnTheRightOfRow(1, DELETE_KEY)
- .addKeysOnTheRightOfRow(3, ENTER_KEY)
- .addKeysOnTheLeftOfRow(5, customizer.getSymbolsKey())
- .addKeysOnTheRightOfRow(5, EMOJI_KEY);
- }
- builder.addKeysOnTheLeftOfRow(4, (Object[])customizer.getLeftShiftKeys(isPhone))
- .addKeysOnTheRightOfRow(4, (Object[])customizer.getRightShiftKeys(isPhone));
- return builder;
- }
-
private static final ExpectedKey[][] ALPHABET_COMMON = new ExpectedKeyboardBuilder()
.setKeysOfRow(1,
// U+17E1: "១" KHMER DIGIT ONE
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Lao.java b/tests/src/com/android/inputmethod/keyboard/layout/Lao.java
index e7be9982a..aaa1c8a8a 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Lao.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Lao.java
@@ -40,6 +40,9 @@ public final class Lao extends LayoutBase {
public LaoCustomizer(final Locale locale) { super(locale); }
@Override
+ public int getNumberOfRows() { return 5; }
+
+ @Override
public ExpectedKey getAlphabetKey() { return LAO_ALPHABET_KEY; }
@Override
@@ -83,29 +86,6 @@ public final class Lao extends LayoutBase {
return ALPHABET_SHIFTED_COMMON;
}
- // Helper method to create alphabet layout by adding special function keys.
- @Override
- ExpectedKeyboardBuilder convertCommonLayoutToKeyboard(final ExpectedKeyboardBuilder builder,
- final boolean isPhone) {
- final LayoutCustomizer customizer = getCustomizer();
- builder.setKeysOfRow(5, (Object[])customizer.getSpaceKeys(isPhone));
- builder.addKeysOnTheLeftOfRow(5, (Object[])customizer.getKeysLeftToSpacebar(isPhone));
- builder.addKeysOnTheRightOfRow(5, (Object[])customizer.getKeysRightToSpacebar(isPhone));
- if (isPhone) {
- builder.addKeysOnTheRightOfRow(4, DELETE_KEY)
- .addKeysOnTheLeftOfRow(5, customizer.getSymbolsKey())
- .addKeysOnTheRightOfRow(5, key(ENTER_KEY, EMOJI_KEY));
- } else {
- builder.addKeysOnTheRightOfRow(1, DELETE_KEY)
- .addKeysOnTheRightOfRow(3, ENTER_KEY)
- .addKeysOnTheLeftOfRow(5, customizer.getSymbolsKey())
- .addKeysOnTheRightOfRow(5, EMOJI_KEY);
- }
- builder.addKeysOnTheLeftOfRow(4, (Object[])customizer.getLeftShiftKeys(isPhone))
- .addKeysOnTheRightOfRow(4, (Object[])customizer.getRightShiftKeys(isPhone));
- return builder;
- }
-
private static final ExpectedKey[][] ALPHABET_COMMON = new ExpectedKeyboardBuilder()
.setKeysOfRow(1,
// U+0EA2: "ຢ" LAO LETTER YO
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/LayoutBase.java b/tests/src/com/android/inputmethod/keyboard/layout/LayoutBase.java
index c5223720c..0548a010d 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/LayoutBase.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/LayoutBase.java
@@ -46,6 +46,10 @@ public abstract class LayoutBase extends AbstractLayoutBase {
return mLocale;
}
+ public int getNumberOfRows() {
+ return 4;
+ }
+
/**
* Set accented letters to common layout.
* @param builder the {@link ExpectedKeyboardBuilder} object that contains common keyboard
@@ -277,7 +281,7 @@ public abstract class LayoutBase extends AbstractLayoutBase {
",", "'", "#", ")", "(", "/", ";",
"@", ":", "-", "\"", "+", "%", "&");
- /**
+ /**
* Helper method to create alphabet layout adding special function keys.
* @param builder the {@link ExpectedKeyboardBuilder} object that contains common keyboard
* layout
@@ -287,21 +291,26 @@ public abstract class LayoutBase extends AbstractLayoutBase {
ExpectedKeyboardBuilder convertCommonLayoutToKeyboard(final ExpectedKeyboardBuilder builder,
final boolean isPhone) {
final LayoutCustomizer customizer = getCustomizer();
- builder.setKeysOfRow(4, (Object[])customizer.getSpaceKeys(isPhone));
- builder.addKeysOnTheLeftOfRow(4, (Object[])customizer.getKeysLeftToSpacebar(isPhone));
- builder.addKeysOnTheRightOfRow(4, (Object[])customizer.getKeysRightToSpacebar(isPhone));
+ final int numberOfRows = customizer.getNumberOfRows();
+ builder.setKeysOfRow(numberOfRows, (Object[])customizer.getSpaceKeys(isPhone));
+ builder.addKeysOnTheLeftOfRow(
+ numberOfRows, (Object[])customizer.getKeysLeftToSpacebar(isPhone));
+ builder.addKeysOnTheRightOfRow(
+ numberOfRows, (Object[])customizer.getKeysRightToSpacebar(isPhone));
if (isPhone) {
- builder.addKeysOnTheRightOfRow(3, DELETE_KEY)
- .addKeysOnTheLeftOfRow(4, customizer.getSymbolsKey())
- .addKeysOnTheRightOfRow(4, key(ENTER_KEY, EMOJI_KEY));
+ builder.addKeysOnTheRightOfRow(numberOfRows - 1, DELETE_KEY)
+ .addKeysOnTheLeftOfRow(numberOfRows, customizer.getSymbolsKey())
+ .addKeysOnTheRightOfRow(numberOfRows, key(ENTER_KEY, EMOJI_ACTION_KEY));
} else {
builder.addKeysOnTheRightOfRow(1, DELETE_KEY)
- .addKeysOnTheRightOfRow(2, ENTER_KEY)
- .addKeysOnTheLeftOfRow(4, customizer.getSymbolsKey())
- .addKeysOnTheRightOfRow(4, EMOJI_KEY);
+ .addKeysOnTheRightOfRow(numberOfRows - 2, ENTER_KEY)
+ .addKeysOnTheLeftOfRow(numberOfRows, customizer.getSymbolsKey())
+ .addKeysOnTheRightOfRow(numberOfRows, EMOJI_NORMAL_KEY);
}
- builder.addKeysOnTheLeftOfRow(3, (Object[])customizer.getLeftShiftKeys(isPhone))
- .addKeysOnTheRightOfRow(3, (Object[])customizer.getRightShiftKeys(isPhone));
+ builder.addKeysOnTheLeftOfRow(
+ numberOfRows - 1, (Object[])customizer.getLeftShiftKeys(isPhone));
+ builder.addKeysOnTheRightOfRow(
+ numberOfRows - 1, (Object[])customizer.getRightShiftKeys(isPhone));
return builder;
}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Myanmar.java b/tests/src/com/android/inputmethod/keyboard/layout/Myanmar.java
index f2a2dfdd8..15c74ed8c 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Myanmar.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Myanmar.java
@@ -40,6 +40,9 @@ public final class Myanmar extends LayoutBase {
public MyanmarCustomizer(final Locale locale) { super(locale); }
@Override
+ public int getNumberOfRows() { return 5; }
+
+ @Override
public ExpectedKey getAlphabetKey() { return MYANMAR_ALPHABET_KEY; }
@Override
@@ -97,29 +100,6 @@ public final class Myanmar extends LayoutBase {
return ALPHABET_SHIFTED_COMMON;
}
- // Helper method to create alphabet layout by adding special function keys.
- @Override
- ExpectedKeyboardBuilder convertCommonLayoutToKeyboard(final ExpectedKeyboardBuilder builder,
- final boolean isPhone) {
- final LayoutCustomizer customizer = getCustomizer();
- builder.setKeysOfRow(5, (Object[])customizer.getSpaceKeys(isPhone));
- builder.addKeysOnTheLeftOfRow(5, (Object[])customizer.getKeysLeftToSpacebar(isPhone));
- builder.addKeysOnTheRightOfRow(5, (Object[])customizer.getKeysRightToSpacebar(isPhone));
- if (isPhone) {
- builder.addKeysOnTheRightOfRow(4, DELETE_KEY)
- .addKeysOnTheLeftOfRow(5, customizer.getSymbolsKey())
- .addKeysOnTheRightOfRow(5, key(ENTER_KEY, EMOJI_KEY));
- } else {
- builder.addKeysOnTheRightOfRow(1, DELETE_KEY)
- .addKeysOnTheRightOfRow(3, ENTER_KEY)
- .addKeysOnTheLeftOfRow(5, customizer.getSymbolsKey())
- .addKeysOnTheRightOfRow(5, EMOJI_KEY);
- }
- builder.addKeysOnTheLeftOfRow(4, (Object[])customizer.getLeftShiftKeys(isPhone))
- .addKeysOnTheRightOfRow(4, (Object[])customizer.getRightShiftKeys(isPhone));
- return builder;
- }
-
private static final ExpectedKey[][] ALPHABET_COMMON = new ExpectedKeyboardBuilder()
.setKeysOfRow(1,
// U+1041: "၁" MYANMAR DIGIT ONE
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/PcQwerty.java b/tests/src/com/android/inputmethod/keyboard/layout/PcQwerty.java
index 9da6dcc44..3f7340fd0 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/PcQwerty.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/PcQwerty.java
@@ -39,6 +39,9 @@ public final class PcQwerty extends LayoutBase {
public PcQwertyCustomizer(final Locale locale) { super(locale); }
@Override
+ public int getNumberOfRows() { return 5; }
+
+ @Override
public ExpectedKey[] getLeftShiftKeys(final boolean isPhone) {
return joinKeys(SHIFT_KEY);
}
@@ -55,7 +58,9 @@ public final class PcQwerty extends LayoutBase {
@Override
public ExpectedKey[] getKeysRightToSpacebar(final boolean isPhone) {
- return isPhone ? joinKeys(key(ENTER_KEY, EMOJI_KEY)) : joinKeys(EMOJI_KEY);
+ return isPhone
+ ? joinKeys(key(ENTER_KEY, EMOJI_ACTION_KEY))
+ : joinKeys(EMOJI_NORMAL_KEY);
}
}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Symbols.java b/tests/src/com/android/inputmethod/keyboard/layout/Symbols.java
index 5f3e4b196..2cee2d909 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Symbols.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Symbols.java
@@ -43,7 +43,7 @@ public class Symbols extends AbstractLayoutBase {
builder.addKeysOnTheLeftOfRow(3, customizer.getSymbolsShiftKey(isPhone))
.addKeysOnTheRightOfRow(3, DELETE_KEY)
.addKeysOnTheLeftOfRow(4, customizer.getAlphabetKey())
- .addKeysOnTheRightOfRow(4, key(ENTER_KEY, EMOJI_KEY));
+ .addKeysOnTheRightOfRow(4, key(ENTER_KEY, EMOJI_ACTION_KEY));
} else {
// Tablet symbols keyboard has extra two keys at the left edge of the 3rd row.
builder.addKeysOnTheLeftOfRow(3, (Object[])joinKeys("\\", "="));
@@ -52,7 +52,7 @@ public class Symbols extends AbstractLayoutBase {
.addKeysOnTheLeftOfRow(3, customizer.getSymbolsShiftKey(isPhone))
.addKeysOnTheRightOfRow(3, customizer.getSymbolsShiftKey(isPhone))
.addKeysOnTheLeftOfRow(4, customizer.getAlphabetKey())
- .addKeysOnTheRightOfRow(4, EMOJI_KEY);
+ .addKeysOnTheRightOfRow(4, EMOJI_NORMAL_KEY);
}
return builder.build();
}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/SymbolsShifted.java b/tests/src/com/android/inputmethod/keyboard/layout/SymbolsShifted.java
index 3265e10e1..7ed103ba0 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/SymbolsShifted.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/SymbolsShifted.java
@@ -39,7 +39,7 @@ public class SymbolsShifted extends AbstractLayoutBase {
builder.addKeysOnTheLeftOfRow(3, customizer.getBackToSymbolsKey())
.addKeysOnTheRightOfRow(3, DELETE_KEY)
.addKeysOnTheLeftOfRow(4, customizer.getAlphabetKey())
- .addKeysOnTheRightOfRow(4, key(ENTER_KEY, EMOJI_KEY));
+ .addKeysOnTheRightOfRow(4, key(ENTER_KEY, EMOJI_ACTION_KEY));
} else {
// Tablet symbols shifted keyboard has extra two keys at the right edge of the 3rd row.
// U+00BF: "¿" INVERTED QUESTION MARK
@@ -50,7 +50,7 @@ public class SymbolsShifted extends AbstractLayoutBase {
.addKeysOnTheLeftOfRow(3, customizer.getBackToSymbolsKey())
.addKeysOnTheRightOfRow(3, customizer.getBackToSymbolsKey())
.addKeysOnTheLeftOfRow(4, customizer.getAlphabetKey())
- .addKeysOnTheRightOfRow(4, EMOJI_KEY);
+ .addKeysOnTheRightOfRow(4, EMOJI_NORMAL_KEY);
}
return builder.build();
}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Thai.java b/tests/src/com/android/inputmethod/keyboard/layout/Thai.java
index af4abea93..cfda2947c 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Thai.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Thai.java
@@ -40,6 +40,9 @@ public final class Thai extends LayoutBase {
public ThaiCustomizer(final Locale locale) { super(locale); }
@Override
+ public int getNumberOfRows() { return 5; }
+
+ @Override
public ExpectedKey getAlphabetKey() { return THAI_ALPHABET_KEY; }
@Override
@@ -96,29 +99,6 @@ public final class Thai extends LayoutBase {
return builder.build();
}
- // Helper method to create alphabet layout by adding special function keys.
- @Override
- ExpectedKeyboardBuilder convertCommonLayoutToKeyboard(final ExpectedKeyboardBuilder builder,
- final boolean isPhone) {
- final LayoutCustomizer customizer = getCustomizer();
- builder.setKeysOfRow(5, (Object[])customizer.getSpaceKeys(isPhone));
- builder.addKeysOnTheLeftOfRow(5, (Object[])customizer.getKeysLeftToSpacebar(isPhone));
- builder.addKeysOnTheRightOfRow(5, (Object[])customizer.getKeysRightToSpacebar(isPhone));
- if (isPhone) {
- builder.addKeysOnTheRightOfRow(4, DELETE_KEY)
- .addKeysOnTheLeftOfRow(5, customizer.getSymbolsKey())
- .addKeysOnTheRightOfRow(5, key(ENTER_KEY, EMOJI_KEY));
- } else {
- builder.addKeysOnTheRightOfRow(1, DELETE_KEY)
- .addKeysOnTheRightOfRow(3, ENTER_KEY)
- .addKeysOnTheLeftOfRow(5, customizer.getSymbolsKey())
- .addKeysOnTheRightOfRow(5, EMOJI_KEY);
- }
- builder.addKeysOnTheLeftOfRow(4, (Object[])customizer.getLeftShiftKeys(isPhone))
- .addKeysOnTheRightOfRow(4, (Object[])customizer.getRightShiftKeys(isPhone));
- return builder;
- }
-
private static final ExpectedKey[][] ALPHABET_COMMON = new ExpectedKeyboardBuilder()
.setKeysOfRow(1,
// U+0E45: "ๅ" THAI CHARACTER LAKKHANGYAO
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/expected/AbstractLayoutBase.java b/tests/src/com/android/inputmethod/keyboard/layout/expected/AbstractLayoutBase.java
index 9e0039d84..0f7bef2a3 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/expected/AbstractLayoutBase.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/expected/AbstractLayoutBase.java
@@ -120,8 +120,10 @@ public abstract class AbstractLayoutBase {
KeyboardIconsSet.NAME_LANGUAGE_SWITCH_KEY);
private static final int ICON_ENTER = KeyboardIconsSet.getIconId(
KeyboardIconsSet.NAME_ENTER_KEY);
- private static final int ICON_EMOJI = KeyboardIconsSet.getIconId(
- KeyboardIconsSet.NAME_EMOJI_KEY);
+ private static final int ICON_EMOJI_ACTION = KeyboardIconsSet.getIconId(
+ KeyboardIconsSet.NAME_EMOJI_ACTION_KEY);
+ private static final int ICON_EMOJI_NORMAL = KeyboardIconsSet.getIconId(
+ KeyboardIconsSet.NAME_EMOJI_NORMAL_KEY);
// Functional keys.
public static final ExpectedKey DELETE_KEY = key(ICON_DELETE, Constants.CODE_DELETE);
@@ -131,6 +133,7 @@ public abstract class AbstractLayoutBase {
public static final ExpectedKey LANGUAGE_SWITCH_KEY = key(
ICON_LANGUAGE_SWITCH, Constants.CODE_LANGUAGE_SWITCH);
public static final ExpectedKey ENTER_KEY = key(ICON_ENTER, Constants.CODE_ENTER);
- public static final ExpectedKey EMOJI_KEY = key(ICON_EMOJI, Constants.CODE_EMOJI);
+ public static final ExpectedKey EMOJI_ACTION_KEY = key(ICON_EMOJI_ACTION, Constants.CODE_EMOJI);
+ public static final ExpectedKey EMOJI_NORMAL_KEY = key(ICON_EMOJI_NORMAL, Constants.CODE_EMOJI);
public static final ExpectedKey SPACE_KEY = key(ICON_SPACE, Constants.CODE_SPACE);
}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsMalayalamIN.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsMalayalamIN.java
index f937de89a..b494ad37b 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsMalayalamIN.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsMalayalamIN.java
@@ -25,7 +25,7 @@ import com.android.inputmethod.keyboard.layout.Malayalam.MalayalamCustomizer;
import java.util.Locale;
/**
- * ta_IN: Malayalam (India)/malayalam
+ * ml_IN: Malayalam (India)/malayalam
*/
@SmallTest
public final class TestsMalayalamIN extends LayoutTestsBase {
diff --git a/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java b/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java
index ae184268c..342eb2978 100644
--- a/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java
+++ b/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java
@@ -689,4 +689,36 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase {
binaryDictionary.close();
dictFile.delete();
}
+
+ public void testRemoveUnigrams() {
+ for (final int formatVersion : DICT_FORMAT_VERSIONS) {
+ testRemoveUnigrams(formatVersion);
+ }
+ }
+
+ private void testRemoveUnigrams(final int formatVersion) {
+ final int unigramInputCount = 20;
+ setCurrentTimeForTestMode(mCurrentTime);
+ File dictFile = null;
+ try {
+ dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
+ } catch (IOException e) {
+ fail("IOException while writing an initial dictionary : " + e);
+ }
+ final BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
+ 0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
+ Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+
+ addUnigramWord(binaryDictionary, "aaa", Dictionary.NOT_A_PROBABILITY);
+ assertFalse(binaryDictionary.isValidWord("aaa"));
+ for (int i = 0; i < unigramInputCount; i++) {
+ addUnigramWord(binaryDictionary, "aaa", Dictionary.NOT_A_PROBABILITY);
+ }
+ assertTrue(binaryDictionary.isValidWord("aaa"));
+ assertTrue(binaryDictionary.removeUnigramEntry("aaa"));
+ assertFalse(binaryDictionary.isValidWord("aaa"));
+
+ binaryDictionary.close();
+ dictFile.delete();
+ }
}
diff --git a/tests/src/com/android/inputmethod/latin/SuggestedWordsTests.java b/tests/src/com/android/inputmethod/latin/SuggestedWordsTests.java
index 66b4a9c71..a5f20b565 100644
--- a/tests/src/com/android/inputmethod/latin/SuggestedWordsTests.java
+++ b/tests/src/com/android/inputmethod/latin/SuggestedWordsTests.java
@@ -48,7 +48,8 @@ public class SuggestedWordsTests extends AndroidTestCase {
false /* typedWordValid */,
false /* willAutoCorrect */,
false /* isObsoleteSuggestions */,
- false /* isPrediction*/);
+ false /* isPrediction*/,
+ SuggestedWords.INPUT_STYLE_NONE);
assertEquals(NUMBER_OF_ADDED_SUGGESTIONS + 1, words.size());
assertEquals("typed", words.getWord(0));
assertTrue(words.getInfo(0).isKindOf(SuggestedWordInfo.KIND_TYPED));
@@ -57,7 +58,8 @@ public class SuggestedWordsTests extends AndroidTestCase {
assertEquals("4", words.getWord(5));
assertTrue(words.getInfo(5).isKindOf(SuggestedWordInfo.KIND_CORRECTION));
- final SuggestedWords wordsWithoutTyped = words.getSuggestedWordsExcludingTypedWord();
+ final SuggestedWords wordsWithoutTyped = words.getSuggestedWordsExcludingTypedWord(
+ SuggestedWords.INPUT_STYLE_NONE);
assertEquals(words.size() - 1, wordsWithoutTyped.size());
assertEquals("0", wordsWithoutTyped.getWord(0));
assertTrue(wordsWithoutTyped.getInfo(0).isKindOf(SuggestedWordInfo.KIND_CORRECTION));
diff --git a/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java b/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java
index f87f3b494..abb468fda 100644
--- a/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java
+++ b/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java
@@ -28,6 +28,7 @@ import com.android.inputmethod.latin.utils.DistracterFilter;
import com.android.inputmethod.latin.utils.FileUtils;
import java.io.File;
+import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
@@ -41,6 +42,8 @@ import java.util.concurrent.TimeUnit;
@LargeTest
public class UserHistoryDictionaryTests extends AndroidTestCase {
private static final String TAG = UserHistoryDictionaryTests.class.getSimpleName();
+ private static final int WAIT_FOR_WRITING_FILE_IN_MILLISECONDS = 3000;
+ private static final String TEST_LOCALE_PREFIX = "test_";
private static final String[] CHARACTERS = {
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
@@ -49,14 +52,55 @@ public class UserHistoryDictionaryTests extends AndroidTestCase {
private int mCurrentTime = 0;
+ private void removeAllTestDictFiles() {
+ final Locale dummyLocale = new Locale(TEST_LOCALE_PREFIX);
+ final String dictName = ExpandableBinaryDictionary.getDictName(
+ UserHistoryDictionary.NAME, dummyLocale, null /* dictFile */);
+ final File dictFile = ExpandableBinaryDictionary.getDictFile(
+ mContext, dictName, null /* dictFile */);
+ final FilenameFilter filenameFilter = new FilenameFilter() {
+ @Override
+ public boolean accept(File dir, String filename) {
+ return filename.startsWith(UserHistoryDictionary.NAME + "." + TEST_LOCALE_PREFIX);
+ }
+ };
+ FileUtils.deleteFilteredFiles(dictFile.getParentFile(), filenameFilter);
+ }
+
+ private void printAllFiles(final File dir) {
+ Log.d(TAG, dir.getAbsolutePath());
+ for (final File file : dir.listFiles()) {
+ Log.d(TAG, " " + file.getName());
+ }
+ }
+
+ private void checkExistenceAndRemoveDictFile(final Locale locale, final File dictFile) {
+ Log.d(TAG, "waiting for writing ...");
+ waitForWriting(locale);
+ if (!dictFile.exists()) {
+ try {
+ Log.d(TAG, dictFile + " is not existing. Wait "
+ + WAIT_FOR_WRITING_FILE_IN_MILLISECONDS + " ms for writing.");
+ printAllFiles(dictFile.getParentFile());
+ Thread.sleep(WAIT_FOR_WRITING_FILE_IN_MILLISECONDS);
+ } catch (final InterruptedException e) {
+ Log.e(TAG, "Interrupted during waiting for writing the dict file.");
+ }
+ }
+ assertTrue("check exisiting of " + dictFile, dictFile.exists());
+ FileUtils.deleteRecursively(dictFile);
+ }
+
@Override
protected void setUp() throws Exception {
super.setUp();
resetCurrentTimeForTestMode();
+ removeAllTestDictFiles();
}
@Override
protected void tearDown() throws Exception {
+ removeAllTestDictFiles();
stopTestModeInNativeCode();
super.tearDown();
}
@@ -168,7 +212,8 @@ public class UserHistoryDictionaryTests extends AndroidTestCase {
public void testRandomWords() {
Log.d(TAG, "This test can be used for profiling.");
Log.d(TAG, "Usage: please set UserHistoryDictionary.PROFILE_SAVE_RESTORE to true.");
- final Locale dummyLocale = new Locale("test_random_words" + System.currentTimeMillis());
+ final Locale dummyLocale =
+ new Locale(TEST_LOCALE_PREFIX + "random_words" + System.currentTimeMillis());
final String dictName = ExpandableBinaryDictionary.getDictName(
UserHistoryDictionary.NAME, dummyLocale, null /* dictFile */);
final File dictFile = ExpandableBinaryDictionary.getDictFile(
@@ -182,10 +227,7 @@ public class UserHistoryDictionaryTests extends AndroidTestCase {
addAndWriteRandomWords(dummyLocale, numberOfWords, random,
true /* checksContents */);
} finally {
- Log.d(TAG, "waiting for writing ...");
- waitForWriting(dummyLocale);
- assertTrue("check exisiting of " + dictFile, dictFile.exists());
- FileUtils.deleteRecursively(dictFile);
+ checkExistenceAndRemoveDictFile(dummyLocale, dictFile);
}
}
@@ -201,7 +243,7 @@ public class UserHistoryDictionaryTests extends AndroidTestCase {
// Create filename suffixes for this test.
for (int i = 0; i < numberOfLanguages; i++) {
- dummyLocales[i] = new Locale("test_switching_languages" + i);
+ dummyLocales[i] = new Locale(TEST_LOCALE_PREFIX + "switching_languages" + i);
final String dictName = ExpandableBinaryDictionary.getDictName(
UserHistoryDictionary.NAME, dummyLocales[i], null /* dictFile */);
dictFiles[i] = ExpandableBinaryDictionary.getDictFile(
@@ -223,19 +265,15 @@ public class UserHistoryDictionaryTests extends AndroidTestCase {
Log.d(TAG, "testStressTestForSwitchingLanguageAndAddingWords took "
+ (end - start) + " ms");
} finally {
- Log.d(TAG, "waiting for writing ...");
for (int i = 0; i < numberOfLanguages; i++) {
- waitForWriting(dummyLocales[i]);
- }
- for (final File dictFile : dictFiles) {
- assertTrue("check exisiting of " + dictFile, dictFile.exists());
- FileUtils.deleteRecursively(dictFile);
+ checkExistenceAndRemoveDictFile(dummyLocales[i], dictFiles[i]);
}
}
}
public void testAddManyWords() {
- final Locale dummyLocale = new Locale("test_random_words" + System.currentTimeMillis());
+ final Locale dummyLocale =
+ new Locale(TEST_LOCALE_PREFIX + "many_random_words" + System.currentTimeMillis());
final String dictName = ExpandableBinaryDictionary.getDictName(
UserHistoryDictionary.NAME, dummyLocale, null /* dictFile */);
final File dictFile = ExpandableBinaryDictionary.getDictFile(
@@ -246,15 +284,13 @@ public class UserHistoryDictionaryTests extends AndroidTestCase {
try {
addAndWriteRandomWords(dummyLocale, numberOfWords, random, true /* checksContents */);
} finally {
- Log.d(TAG, "waiting for writing ...");
- waitForWriting(dummyLocale);
- assertTrue("check exisiting of " + dictFile, dictFile.exists());
- FileUtils.deleteRecursively(dictFile);
+ checkExistenceAndRemoveDictFile(dummyLocale, dictFile);
}
}
public void testDecaying() {
- final Locale dummyLocale = new Locale("test_decaying" + System.currentTimeMillis());
+ final Locale dummyLocale =
+ new Locale(TEST_LOCALE_PREFIX + "decaying" + System.currentTimeMillis());
final int numberOfWords = 5000;
final Random random = new Random(123456);
resetCurrentTimeForTestMode();
diff --git a/tools/make-keyboard-text/res/values/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values/donottranslate-more-keys.xml
index bf97e73f4..c4a1b889e 100644
--- a/tools/make-keyboard-text/res/values/donottranslate-more-keys.xml
+++ b/tools/make-keyboard-text/res/values/donottranslate-more-keys.xml
@@ -258,5 +258,5 @@
<string name="morekeys_single_quote">!fixedColumnOrder!5,!text/single_quotes,!text/single_angle_quotes</string>
<string name="morekeys_double_quote">!fixedColumnOrder!5,!text/double_quotes,!text/double_angle_quotes</string>
<string name="morekeys_tablet_double_quote">!fixedColumnOrder!6,!text/double_quotes,!text/single_quotes,!text/double_angle_quotes,!text/single_angle_quotes</string>
- <string name="keyspec_emoji_key">!icon/emoji_key|!code/key_emoji</string>
+ <string name="keyspec_emoji_action_key">!icon/emoji_action_key|!code/key_emoji</string>
</resources>