aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dictionaries/es_wordlist.combined.gzbin1164600 -> 1164608 bytes
-rw-r--r--java/res/layout/dictionary_line.xml12
-rw-r--r--java/res/layout/key_preview.xml27
-rw-r--r--java/res/raw/main_es.dictbin1376670 -> 1376678 bytes
-rw-r--r--java/res/values-km-rKH/strings-emoji-descriptions.xml72
-rw-r--r--java/res/values-km-rKH/strings.xml18
-rw-r--r--java/res/values-lo-rLA/strings-emoji-descriptions.xml4
-rw-r--r--java/res/values/attrs.xml6
-rw-r--r--java/res/values/themes-common.xml2
-rw-r--r--java/res/values/themes-ics.xml8
-rw-r--r--java/res/values/themes-klp.xml8
-rw-r--r--java/res/values/themes-lxx-dark.xml8
-rw-r--r--java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityDelegate.java4
-rw-r--r--java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityNodeProvider.java58
-rw-r--r--java/src/com/android/inputmethod/keyboard/MainKeyboardView.java54
-rw-r--r--java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java57
-rw-r--r--java/src/com/android/inputmethod/keyboard/emoji/EmojiPageKeyboardView.java7
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/AbstractDrawingPreview.java11
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/DrawingPreviewPlacerView.java4
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/GestureFloatingTextDrawingPreview.java15
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/GestureTrailsDrawingPreview.java56
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyPreviewChoreographer.java157
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyPreviewDrawParams.java9
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyPreviewView.java90
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/SlidingKeyInputDrawingPreview.java14
-rw-r--r--java/src/com/android/inputmethod/latin/BinaryDictionary.java74
-rw-r--r--java/src/com/android/inputmethod/latin/DicTraverseSession.java15
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryFacilitator.java16
-rw-r--r--java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java22
-rw-r--r--java/src/com/android/inputmethod/latin/InputAttributes.java10
-rw-r--r--java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java10
-rw-r--r--java/src/com/android/inputmethod/latin/settings/SettingsValues.java3
-rw-r--r--java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java7
-rw-r--r--native/jni/Android.mk3
-rw-r--r--native/jni/TargetUnitTests.mk55
-rw-r--r--native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp36
-rwxr-xr-xnative/jni/run-tests.sh53
-rw-r--r--native/jni/src/suggest/core/dictionary/dictionary.cpp5
-rw-r--r--native/jni/src/suggest/core/dictionary/dictionary.h3
-rw-r--r--native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h3
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_reader.h2
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.cpp22
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.h3
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_writing_helper.cpp2
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_gc_event_listeners.cpp2
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_helper.h2
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_updating_helper.cpp18
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_reader.h3
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp18
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h3
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v2/ver2_patricia_trie_node_reader.cpp2
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v2/ver2_patricia_trie_node_reader.h2
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.h2
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.cpp34
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.h5
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp42
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h3
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.cpp5
-rw-r--r--tools/dicttool/src/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtils.java109
-rw-r--r--tools/dicttool/src/com/android/inputmethod/latin/dicttool/CombinedInputOutput.java34
-rw-r--r--tools/dicttool/src/com/android/inputmethod/latin/dicttool/Compress.java34
-rw-r--r--tools/dicttool/src/com/android/inputmethod/latin/dicttool/DictionaryMaker.java56
-rw-r--r--tools/dicttool/src/com/android/inputmethod/latin/dicttool/Dicttool.java46
-rw-r--r--tools/dicttool/src/com/android/inputmethod/latin/dicttool/Package.java13
-rw-r--r--tools/dicttool/src/com/android/inputmethod/latin/dicttool/XmlDictInputOutput.java58
-rw-r--r--tools/dicttool/tests/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtilsTests.java28
66 files changed, 866 insertions, 698 deletions
diff --git a/dictionaries/es_wordlist.combined.gz b/dictionaries/es_wordlist.combined.gz
index 181a958c0..c0a5264fc 100644
--- a/dictionaries/es_wordlist.combined.gz
+++ b/dictionaries/es_wordlist.combined.gz
Binary files differ
diff --git a/java/res/layout/dictionary_line.xml b/java/res/layout/dictionary_line.xml
index 7268cd468..bb1843d6c 100644
--- a/java/res/layout/dictionary_line.xml
+++ b/java/res/layout/dictionary_line.xml
@@ -42,7 +42,7 @@
android:orientation="vertical">
<TextView
- android:id="@+android:id/title"
+ android:id="@android:id/title"
android:layout_marginLeft="5dip"
android:layout_marginStart="5dip"
android:layout_width="wrap_content"
@@ -59,7 +59,7 @@
android:layout_marginLeft="5dip">
<TextView
- android:id="@+android:id/summary"
+ android:id="@android:id/summary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
@@ -77,14 +77,14 @@
</LinearLayout>
<com.android.inputmethod.dictionarypack.ButtonSwitcher
- android:id="@+android:id/wordlist_button_switcher"
+ android:id="@+id/wordlist_button_switcher"
android:layout_weight="0"
android:layout_marginStart="13dip"
android:layout_marginLeft="13dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button
- android:id="@+android:id/dict_install_button"
+ android:id="@+id/dict_install_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right|center_vertical"
@@ -92,7 +92,7 @@
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="@string/install_dict" />
<Button
- android:id="@+android:id/dict_cancel_button"
+ android:id="@+id/dict_cancel_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right|center_vertical"
@@ -100,7 +100,7 @@
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="@string/cancel_download_dict" />
<Button
- android:id="@+android:id/dict_delete_button"
+ android:id="@+id/dict_delete_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right|center_vertical"
diff --git a/java/res/layout/key_preview.xml b/java/res/layout/key_preview.xml
deleted file mode 100644
index 16d4c72c3..000000000
--- a/java/res/layout/key_preview.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2013, 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.
-*/
--->
-
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:minWidth="32dp"
- android:gravity="center"
- style="?attr/keyPreviewTextViewStyle"
-/>
diff --git a/java/res/raw/main_es.dict b/java/res/raw/main_es.dict
index 83eefe4f6..0911b70f1 100644
--- a/java/res/raw/main_es.dict
+++ b/java/res/raw/main_es.dict
Binary files differ
diff --git a/java/res/values-km-rKH/strings-emoji-descriptions.xml b/java/res/values-km-rKH/strings-emoji-descriptions.xml
index 757df50e7..9f1d9973e 100644
--- a/java/res/values-km-rKH/strings-emoji-descriptions.xml
+++ b/java/res/values-km-rKH/strings-emoji-descriptions.xml
@@ -25,16 +25,16 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="spoken_emoji_00A9" msgid="2859822817116803638">"សញ្ញា​រក្សា​សិទ្ធ​"</string>
+ <string name="spoken_emoji_00A9" msgid="2859822817116803638">"សញ្ញា​រក្សា​សិទ្ធ"</string>
<string name="spoken_emoji_00AE" msgid="7708335454134589027">"សញ្ញា​​​ចុះ​បញ្ជី"</string>
<string name="spoken_emoji_203C" msgid="153340916701508663">"សញ្ញា​ឧទាន​​ពីរ"</string>
- <string name="spoken_emoji_2049" msgid="4877256448299555371">"សញ្ញា​​ឧទាន​សញ្ញា​សួរ​​"</string>
+ <string name="spoken_emoji_2049" msgid="4877256448299555371">"សញ្ញា​​ឧទាន​សញ្ញា​សួរ"</string>
<string name="spoken_emoji_2122" msgid="9188440722954720429">"សញ្ញា​​​និក្ខិត្តសញ្ញា"</string>
<string name="spoken_emoji_2139" msgid="9114342638917304327">"ប្រភព​ព័ត៌មាន"</string>
<string name="spoken_emoji_2194" msgid="8055202727034946680">"ព្រួញ​ឆ្វេងស្ដាំ"</string>
<string name="spoken_emoji_2195" msgid="8028122253301087407">"ព្រួញ​ឡើង​លើ​ចុះក្រោម"</string>
<string name="spoken_emoji_2196" msgid="4019164898967854363">"ព្រួញ​ទិសពាយព្យ"</string>
- <string name="spoken_emoji_2197" msgid="4255723717709017801">"ព្រួញ​​ទិស​ឥសាន្ត​ឦសាន្ត​"</string>
+ <string name="spoken_emoji_2197" msgid="4255723717709017801">"ព្រួញ​​ទិស​ឥសាន្ត​ឦសាន្ត"</string>
<string name="spoken_emoji_2198" msgid="1452063451313622090">"ព្រួញ​​ទិស​អាគ្នេយ៍"</string>
<string name="spoken_emoji_2199" msgid="6942722693368807849">"ព្រួញ​​ទិស​និរតី"</string>
<string name="spoken_emoji_21A9" msgid="5204750172335111188">"ព្រួញ​ទៅ​ឆ្វេង​មាន​ទំពក់"</string>
@@ -45,7 +45,7 @@
<string name="spoken_emoji_23EA" msgid="2251396938087774944">"ត្រីកោណ​ខ្មៅ​ពីរ​ចង្អុល​ទៅ​ឆ្វេង"</string>
<string name="spoken_emoji_23EB" msgid="3746885195641491865">"ត្រីកោណ​ខ្មៅ​ពីរ​ចង្អុល​​ឡើង​លើ"</string>
<string name="spoken_emoji_23EC" msgid="7852372752901163416">"ត្រីកោណ​ខ្មៅ​ពីរ​ចង្អុល​​ចុះក្រោម"</string>
- <string name="spoken_emoji_23F0" msgid="8474219588750627870">"នាឡិកា​រោទ៍​"</string>
+ <string name="spoken_emoji_23F0" msgid="8474219588750627870">"នាឡិកា​រោទ៍"</string>
<string name="spoken_emoji_23F3" msgid="166900119581024371">"កែវ​ពិសោធន៍​មាន​ខ្សាច់ហូរ"</string>
<string name="spoken_emoji_24C2" msgid="3948348737566038470">"អក្សរ​អឹម​ធំ​ក្នុង​រង្វង់"</string>
<string name="spoken_emoji_25AA" msgid="7865181015100227349">"ការ៉េ​តូច​​ពណ៌ខ្មៅ"</string>
@@ -195,7 +195,7 @@
<string name="spoken_emoji_1F312" msgid="4458575672576125401">"ព្រះ​ចន្ទ​មួយ​ចំណិត​ស្ដាំ"</string>
<string name="spoken_emoji_1F313" msgid="7599181787989497294">"ព្រះ​ចន្ទ​ពាក់​កណ្ដាល"</string>
<string name="spoken_emoji_1F314" msgid="4898293184964365413">"ព្រះ​ចន្ទ​មួយ​ចំណិត​ឆ្វេង"</string>
- <string name="spoken_emoji_1F315" msgid="3218117051779496309">"ព្រះចន្ទ​ពេញ​វង់​"</string>
+ <string name="spoken_emoji_1F315" msgid="3218117051779496309">"ព្រះចន្ទ​ពេញ​វង់"</string>
<string name="spoken_emoji_1F316" msgid="2061317145777689569">"ព្រះ​ចន្ទ​ភ្លឺ​មួយ​ចំហៀង"</string>
<string name="spoken_emoji_1F317" msgid="2721090687319539049">"ព្រះ​ចន្ទ​ភ្លឺ​ពាក់​កណ្ដាល"</string>
<string name="spoken_emoji_1F318" msgid="3814091755648887570">"ព្រះ​ចន្ទ​ភ្លឺ​មួយ​ចំណិត​ឆ្វេង"</string>
@@ -262,7 +262,7 @@
<string name="spoken_emoji_1F365" msgid="4963815540953316307">"នំ​ត្រី​រាង​មូល"</string>
<string name="spoken_emoji_1F366" msgid="7862401745277049404">"ការ៉េម​​បំពង់"</string>
<string name="spoken_emoji_1F367" msgid="7447972978281980414">"ការ៉េម​កែវ"</string>
- <string name="spoken_emoji_1F368" msgid="7790003146142724913">"ការ៉េម​"</string>
+ <string name="spoken_emoji_1F368" msgid="7790003146142724913">"ការ៉េម"</string>
<string name="spoken_emoji_1F369" msgid="7383712944084857350">"ដូណាត់"</string>
<string name="spoken_emoji_1F36A" msgid="2726271795913042295">"ខូគី"</string>
<string name="spoken_emoji_1F36B" msgid="6342163604299875931">"​​សូកូឡា"</string>
@@ -280,7 +280,7 @@
<string name="spoken_emoji_1F377" msgid="1762398562314172075">"កែវ​ស្រា"</string>
<string name="spoken_emoji_1F378" msgid="5528234560590117516">"កែវ​ស្រា​ក្រឡុក"</string>
<string name="spoken_emoji_1F379" msgid="790581290787943325">"ភេសជ្ជៈ​​​ត្រូពិក"</string>
- <string name="spoken_emoji_1F37A" msgid="391966822450619516">"កែវ​​ស្រាបៀ​"</string>
+ <string name="spoken_emoji_1F37A" msgid="391966822450619516">"កែវ​​ស្រាបៀ"</string>
<string name="spoken_emoji_1F37B" msgid="9015043286465670662">"ជល់​កែវ​ស្រាបៀ"</string>
<string name="spoken_emoji_1F37C" msgid="2532113819464508894">"ដប​ទឹកដោះ​គោ"</string>
<string name="spoken_emoji_1F380" msgid="3487363857092458827">"ខ្សែ​បូ"</string>
@@ -313,7 +313,7 @@
<string name="spoken_emoji_1F3A7" msgid="837856608794094105">"កាស"</string>
<string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"ក្ដារ​លាយ​ពណ៌​វិចិត្រករ"</string>
<string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"មួក​​​សម្ដែង​សិល្បៈ"</string>
- <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"តង់​សៀក​"</string>
+ <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"តង់​សៀក"</string>
<string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"សំបុត្រ"</string>
<string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"បន្ទះកណ្ដឹង"</string>
<string name="spoken_emoji_1F3AD" msgid="607157286336130470">"សម្ដែង​សិល្បៈ"</string>
@@ -334,10 +334,10 @@
<string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"និមិត្តសញ្ញា​តន្ត្រី"</string>
<string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"អាវ​កីឡា​​មាន​ខ្សែ​ឆៀង"</string>
<string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"រ៉ាកែត និង​បាល់"</string>
- <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"ជិះ​ស្គី ​និង​ក្ដារ​​ស្គី​"</string>
+ <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"ជិះ​ស្គី ​និង​ក្ដារ​​ស្គី"</string>
<string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"បាល់​បោះ​ និង​វណ្ណ​មូល"</string>
<string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"ទង់ជាតិ​ប្រណាំង​ម៉ូតូ"</string>
- <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"អ្នក​ជិះ​​ក្ដារ​រំអិល​លើ​ព្រិល​"</string>
+ <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"អ្នក​ជិះ​​ក្ដារ​រំអិល​លើ​ព្រិល"</string>
<string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"អ្នក​រត់"</string>
<string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"អ្នក​ជិះ​ទូក​រអិល​លើ​ទឹក"</string>
<string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"ពាន​រង្វាន់"</string>
@@ -354,7 +354,7 @@
<string name="spoken_emoji_1F3E6" msgid="342132788513806214">"ធនាគារ"</string>
<string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"ម៉ាស៊ីន​​អេធីអឹម"</string>
<string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"សណ្ឋាគារ"</string>
- <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"សណ្ឋាគារ​ក្ដី​ស្រឡាញ់​"</string>
+ <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"សណ្ឋាគារ​ក្ដី​ស្រឡាញ់"</string>
<string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"ហាង​​ទំនិញ ២៤​ម៉ោង"</string>
<string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"សាលារៀន"</string>
<string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"ហាង​​ទំនិញធំៗ"</string>
@@ -439,12 +439,12 @@
<string name="spoken_emoji_1F44D" msgid="6182553970602667815">"​មេដៃ​ឡើង​លើ"</string>
<string name="spoken_emoji_1F44E" msgid="8030851867365111809">"​មេដៃ​ចុះ​ក្រោម"</string>
<string name="spoken_emoji_1F44F" msgid="5148753662268213389">"ទះ​ដៃ"</string>
- <string name="spoken_emoji_1F450" msgid="1012021072085157054">"លា​ដៃ​"</string>
+ <string name="spoken_emoji_1F450" msgid="1012021072085157054">"លា​ដៃ"</string>
<string name="spoken_emoji_1F451" msgid="8257466714629051320">"មកុដ"</string>
<string name="spoken_emoji_1F452" msgid="4567394011149905466">"មួក​​ស្ត្រី"</string>
<string name="spoken_emoji_1F453" msgid="5978410551173163010">"វ៉ែនតា"</string>
- <string name="spoken_emoji_1F454" msgid="348469036193323252">"ក្រ​វ៉ាត់​ករ​"</string>
- <string name="spoken_emoji_1F455" msgid="5665118831861433578">"អាវ​យឺត​​"</string>
+ <string name="spoken_emoji_1F454" msgid="348469036193323252">"ក្រ​វ៉ាត់​ករ"</string>
+ <string name="spoken_emoji_1F455" msgid="5665118831861433578">"អាវ​យឺត"</string>
<string name="spoken_emoji_1F456" msgid="1890991330923356408">"ខោ​ខោវប៊យ"</string>
<string name="spoken_emoji_1F457" msgid="3904310482655702620">"សំលៀក​បំពាក់"</string>
<string name="spoken_emoji_1F458" msgid="5704243858031107692">"គី​ម៉ូណូ"</string>
@@ -463,8 +463,8 @@
<string name="spoken_emoji_1F465" msgid="4461307702499679879">"គណនី"</string>
<string name="spoken_emoji_1F466" msgid="1938873085514108889">"ក្មេង​​ប្រុស"</string>
<string name="spoken_emoji_1F467" msgid="8237080594860144998">"ក្មេង​ស្រី"</string>
- <string name="spoken_emoji_1F468" msgid="6081300722526675382">"បុរស​"</string>
- <string name="spoken_emoji_1F469" msgid="1090140923076108158">"ស្ត្រី​"</string>
+ <string name="spoken_emoji_1F468" msgid="6081300722526675382">"បុរស"</string>
+ <string name="spoken_emoji_1F469" msgid="1090140923076108158">"ស្ត្រី"</string>
<string name="spoken_emoji_1F46A" msgid="5063570981942606595">"គ្រួសារ"</string>
<string name="spoken_emoji_1F46B" msgid="6795882374287327952">"បុរស​​ និង​ស្ត្រី​កាន់ដៃ​គ្នា"</string>
<string name="spoken_emoji_1F46C" msgid="6844464165783964495">"បុរស​ពីរ​នាក់​កាន់​ដៃ​គ្នា"</string>
@@ -490,16 +490,16 @@
<string name="spoken_emoji_1F480" msgid="3696253485164878739">"លលាដ៍​ក្បាល"</string>
<string name="spoken_emoji_1F481" msgid="320408708521966893">"អ្នក​ផ្ដល់​ព័ត៌មាន"</string>
<string name="spoken_emoji_1F482" msgid="3424354860245608949">"អ្នក​យាម"</string>
- <string name="spoken_emoji_1F483" msgid="3221113594843849083">"អ្នក​រាំ​"</string>
+ <string name="spoken_emoji_1F483" msgid="3221113594843849083">"អ្នក​រាំ"</string>
<string name="spoken_emoji_1F484" msgid="7348014979080444885">"ក្រេម​លាប​បបូរ​មាត់"</string>
<string name="spoken_emoji_1F485" msgid="6133507975565116339">"ថ្នាំ​លាប​​​ក្រចក"</string>
<string name="spoken_emoji_1F486" msgid="9085459968247394155">"ម៉ាស្សា​មុខ"</string>
<string name="spoken_emoji_1F487" msgid="1479113637259592150">"កាត់សក់"</string>
<string name="spoken_emoji_1F488" msgid="6922559285234100252">"ស្លាក​សញ្ញា​កាត់សក់"</string>
<string name="spoken_emoji_1F489" msgid="8114863680950147305">"ស៊ីរ៉ាំង"</string>
- <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"ថ្នាំ​គ្រាប់​"</string>
+ <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"ថ្នាំ​គ្រាប់"</string>
<string name="spoken_emoji_1F48B" msgid="2538528967897640292">"ស្នាម​ថើប"</string>
- <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"លិខិត​ស្នេហា​"</string>
+ <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"លិខិត​ស្នេហា"</string>
<string name="spoken_emoji_1F48D" msgid="8259886164999042373">"រោទ៍"</string>
<string name="spoken_emoji_1F48E" msgid="8777981696011111101">"ត្បូង​ថ្ម"</string>
<string name="spoken_emoji_1F48F" msgid="741593675183677907">"ថើប"</string>
@@ -525,7 +525,7 @@
<string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"គ្រាប់បែក"</string>
<string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"និមិត្ត​សញ្ញា​​ដេក"</string>
<string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"និមិត្ត​សញ្ញា​​ប៉ះ​ទង្គិច​គ្នា"</string>
- <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"និមិត្ត​សញ្ញា​​ស្រក់​ញើស​"</string>
+ <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"និមិត្ត​សញ្ញា​​ស្រក់​ញើស"</string>
<string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"ដំណក់​ទឹក"</string>
<string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"និមិត្ត​សញ្ញា​​ដកឃ្លា"</string>
<string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"គំនរ​ធូលី"</string>
@@ -539,7 +539,7 @@
<string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"ប្ដូរ​​រូបិយប័ណ្ណ"</string>
<string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"សញ្ញា​ដុល្លារ"</string>
<string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"កាត​​ឥណទាន"</string>
- <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"ក្រដាស​ប្រាក់​​ធនាគារ​មាន​សញ្ញា​​យ៉េន​​"</string>
+ <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"ក្រដាស​ប្រាក់​​ធនាគារ​មាន​សញ្ញា​​យ៉េន"</string>
<string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"លុយដុល្លារ"</string>
<string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"ក្រដាស​ប្រាក់​​ធនាគារ​មាន​សញ្ញា​អឺរ៉ូ"</string>
<string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"ក្រដាស​ប្រាក់​​ធនាគារ​មាន​សញ្ញា​​​ផោន"</string>
@@ -547,7 +547,7 @@
<string name="spoken_emoji_1F4B9" msgid="647509393536679903">"ក្រាហ្វិក​និន្នាការ​ឡើង​​មាន​​សញ្ញា​យ៉េន"</string>
<string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"កៅអី"</string>
<string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"កុំព្យូទ័រ​ផ្ទាល់ខ្លួន"</string>
- <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"វ៉ា​លី​"</string>
+ <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"វ៉ា​លី"</string>
<string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"ឌីស​​តូច"</string>
<string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"ថា​ស​​ទន់"</string>
<string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"ថាស"</string>
@@ -557,7 +557,7 @@
<string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"ទំព័រ​​កោង"</string>
<string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"ទំព័រ​បញ្ឈរ"</string>
<string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"ប្រតិទិន"</string>
- <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"ហែក​ប្រតិទិន​"</string>
+ <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"ហែក​ប្រតិទិន"</string>
<string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"​កាត​រៀប​តាម​អក្សរ"</string>
<string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"ក្រាហ្វិក​មាន​និន្នាការ​ឡើង"</string>
<string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"ក្រាហ្វិក​មាន​និន្នាការ​ចុះ"</string>
@@ -573,11 +573,11 @@
<string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"សៀវភៅ"</string>
<string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"សៀវភៅ​មាន​ក្រប​ពណ៌"</string>
<string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"សៀវភៅ​​បិទ"</string>
- <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"សៀវភៅ​បើក​​"</string>
+ <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"សៀវភៅ​បើក"</string>
<string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"សៀវភៅ​​ពណ៌​បៃតង"</string>
<string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"សៀវភៅ​​ពណ៌​ខៀវ"</string>
<string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"សៀវភៅ​​ពណ៌​ទឹកក្រូច"</string>
- <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"សៀវភៅ​"</string>
+ <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"សៀវភៅ"</string>
<string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"ស្លាកឈ្មោះ"</string>
<string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"ក្រដាស​រមូរ"</string>
<string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"កំណត់ចំណាំ"</string>
@@ -589,7 +589,7 @@
<string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"ឧបករណ៍​បំពង​សំឡេង"</string>
<string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"ថា​ស​​​ចេញ"</string>
<string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"ថា​ស​ចូល"</string>
- <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"កញ្ចប់​"</string>
+ <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"កញ្ចប់"</string>
<string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"និមិត្ត​សញ្ញា​អ៊ីមែល"</string>
<string name="spoken_emoji_1F4E8" msgid="30698793974124123">"ស្រោម​​សំបុត្រ​ចូល"</string>
<string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"ស្រោម​សំបុត្រ​​មាន​សញ្ញា​ព្រួញ​ពី​លើ"</string>
@@ -626,7 +626,7 @@
<string name="spoken_emoji_1F50C" msgid="7793219132036431680">"ដុយ​អគ្គិសនី"</string>
<string name="spoken_emoji_1F50D" msgid="8140244710637926780">"កែវ​ពង្រីក​ចង្អុល​ខាង​ឆ្វេង"</string>
<string name="spoken_emoji_1F50E" msgid="4751821352839693365">"កែវ​ពង្រីក​ចង្អុល​ខាង​ស្ដាំ"</string>
- <string name="spoken_emoji_1F50F" msgid="915079280472199605">"ចាក់សោ​​​ដោយ​ប្រើ​​ប៊ិច​"</string>
+ <string name="spoken_emoji_1F50F" msgid="915079280472199605">"ចាក់សោ​​​ដោយ​ប្រើ​​ប៊ិច"</string>
<string name="spoken_emoji_1F510" msgid="7658381761691758318">"បិទ​​សោ​ដោយ​ប្រើ​​​​កូនសោ"</string>
<string name="spoken_emoji_1F511" msgid="262319867774655688">"សោ"</string>
<string name="spoken_emoji_1F512" msgid="5628688337255115175">"ចាក់សោ"</string>
@@ -645,15 +645,15 @@
<string name="spoken_emoji_1F51F" msgid="8673370823728653973">"គ្រាប់​ចុច​ ១០"</string>
<string name="spoken_emoji_1F520" msgid="7335109890337048900">"និមិត្ត​សញ្ញា​បញ្ចូល​សម្រាប់​អក្សរ​ឡាតាំង​ធំ"</string>
<string name="spoken_emoji_1F521" msgid="2693185864450925778">"និមិត្ត​សញ្ញា​បញ្ចូល​សម្រាប់​អក្សរ​ឡាតាំង​តូច"</string>
- <string name="spoken_emoji_1F522" msgid="8419130286280673347">"និមិត្ត​សញ្ញា​បញ្ចូល​សម្រាប់​​លេខ​"</string>
+ <string name="spoken_emoji_1F522" msgid="8419130286280673347">"និមិត្ត​សញ្ញា​បញ្ចូល​សម្រាប់​​លេខ"</string>
<string name="spoken_emoji_1F523" msgid="3318053476401719421">"ការ​បញ្ចូល​និមិត្តសញ្ញា"</string>
<string name="spoken_emoji_1F524" msgid="1625073997522316331">"និមិត្ត​សញ្ញា​បញ្ចូល​សម្រាប់​អក្សរ​ឡាតាំង"</string>
<string name="spoken_emoji_1F525" msgid="4083884189172963790">"ភ្លើង"</string>
<string name="spoken_emoji_1F526" msgid="2035494936742643580">"ពិល​​អគ្គិសនី"</string>
<string name="spoken_emoji_1F527" msgid="134257142354034271">"ម៉ាឡេត"</string>
<string name="spoken_emoji_1F528" msgid="700627429570609375">"ញញួរ"</string>
- <string name="spoken_emoji_1F529" msgid="7480548235904988573">"ឡោ​ស៊ី​​"</string>
- <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"កាំបិត​​"</string>
+ <string name="spoken_emoji_1F529" msgid="7480548235904988573">"ឡោ​ស៊ី"</string>
+ <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"កាំបិត"</string>
<string name="spoken_emoji_1F52B" msgid="4554906608328118613">"កាំភ្លើង​ខ្លី"</string>
<string name="spoken_emoji_1F52C" msgid="1330294501371770790">"មីក្រូទស្សន៍"</string>
<string name="spoken_emoji_1F52D" msgid="7549551775445177140">"កែវ​យឹត"</string>
@@ -662,7 +662,7 @@
<string name="spoken_emoji_1F530" msgid="3572898444281774023">"និមិត្តសញ្ញា​ជប៉ុន​សម្រាប់​អ្នក​ចាប់ផ្ដើម"</string>
<string name="spoken_emoji_1F531" msgid="5225633376450025396">"លំពែង​មុខ​បី"</string>
<string name="spoken_emoji_1F532" msgid="9169568490485180779">"ប៊ូតុង​ការេ​ពណ៌​ខ្មៅ"</string>
- <string name="spoken_emoji_1F533" msgid="6554193837201918598">"ប៊ូតុង​ការ៉េ​ពណ៌​ស​"</string>
+ <string name="spoken_emoji_1F533" msgid="6554193837201918598">"ប៊ូតុង​ការ៉េ​ពណ៌​ស"</string>
<string name="spoken_emoji_1F534" msgid="8339298801331865340">"រង្វង់​ពណ៌​ក្រហម​​​ធំ"</string>
<string name="spoken_emoji_1F535" msgid="1227403104835533512">"រង្វង់​ពណ៌​ខៀវ​ធំ"</string>
<string name="spoken_emoji_1F536" msgid="5477372445510469331">"ពេជ្រ​ពណ៌​ទឹកក្រូច​ធំ"</string>
@@ -745,8 +745,8 @@
<string name="spoken_emoji_1F628" msgid="8875777401624904224">"មុខ​ភ័យ​ខ្លាច"</string>
<string name="spoken_emoji_1F629" msgid="1411538490319190118">"មុខ​​នឿយហត់"</string>
<string name="spoken_emoji_1F62A" msgid="4726686726690289969">"មុខ​​ងងុយ​គេង"</string>
- <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"មុខ​អស់កម្លាំង​​"</string>
- <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"មុខ​ក្រញេវក្រញូវ​"</string>
+ <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"មុខ​អស់កម្លាំង"</string>
+ <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"មុខ​ក្រញេវក្រញូវ"</string>
<string name="spoken_emoji_1F62D" msgid="4283677508698812232">"មុខ​យំ​លឺៗ"</string>
<string name="spoken_emoji_1F62E" msgid="726083405284353894">"មុខ​បើក​មាត់"</string>
<string name="spoken_emoji_1F62F" msgid="7746620088234710962">"មុខ​ស្ងៀមស្ងាត់"</string>
@@ -784,7 +784,7 @@
<string name="spoken_emoji_1F683" msgid="8772750354339223092">"ទូរ​​រថភ្លើង"</string>
<string name="spoken_emoji_1F684" msgid="346396777356203608">"រថភ្លើង​ល្បឿន​លឿន"</string>
<string name="spoken_emoji_1F685" msgid="1237059817190832730">"រថភ្លើង​ល្បឿន​លឿន​​មាន​ច្រមុះ"</string>
- <string name="spoken_emoji_1F686" msgid="3525197227223620343">"រថភ្លើង​"</string>
+ <string name="spoken_emoji_1F686" msgid="3525197227223620343">"រថភ្លើង"</string>
<string name="spoken_emoji_1F687" msgid="5110143437960392837">"មេត្រូ"</string>
<string name="spoken_emoji_1F688" msgid="4702085029871797965">"រថភ្លើង​ប្រើ​​​ពន្លឺ"</string>
<string name="spoken_emoji_1F689" msgid="2375851019798817094">"ស្ថានីយ"</string>
@@ -803,7 +803,7 @@
<string name="spoken_emoji_1F696" msgid="6391604457418285404">"តាក់ស៊ី​ខាង​មុខ"</string>
<string name="spoken_emoji_1F697" msgid="7978399334396733790">"រថយន្ត"</string>
<string name="spoken_emoji_1F698" msgid="7006050861129732018">"រថយន្ត​ខាង​មុខ"</string>
- <string name="spoken_emoji_1F699" msgid="630317052666590607">"រថយន្ត​​​សម្រាប់​កម្សាន្ត​"</string>
+ <string name="spoken_emoji_1F699" msgid="630317052666590607">"រថយន្ត​​​សម្រាប់​កម្សាន្ត"</string>
<string name="spoken_emoji_1F69A" msgid="4739797891735823577">"រថយន្ត​​ចែក​ចាយ"</string>
<string name="spoken_emoji_1F69B" msgid="4715997280786620649">"ឡាន​កាមីយ៉ុង"</string>
<string name="spoken_emoji_1F69C" msgid="5557395610750818161">"ត្រាក់ទ័រ"</string>
@@ -819,7 +819,7 @@
<string name="spoken_emoji_1F6A6" msgid="485575967773793454">"ភ្លើង​ចរាចរណ៍​បញ្ឈរ"</string>
<string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"សញ្ញា​​សំណង់"</string>
<string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"រថយន្ត​​ប៉ូលិស​បើក​សារ៉ែន​វិល"</string>
- <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"បង្គោល​ទង់ជាតិ​រាង​ត្រីកោណ​"</string>
+ <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"បង្គោល​ទង់ជាតិ​រាង​ត្រីកោណ"</string>
<string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"ទ្វារ"</string>
<string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"សញ្ញា​ហាម​ចូល"</string>
<string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"​សញ្ញា​ជក់​បារី"</string>
diff --git a/java/res/values-km-rKH/strings.xml b/java/res/values-km-rKH/strings.xml
index 91ba5b96f..2cf51d875 100644
--- a/java/res/values-km-rKH/strings.xml
+++ b/java/res/values-km-rKH/strings.xml
@@ -28,7 +28,7 @@
<string name="popup_on_keypress" msgid="123894815723512944">"លេច​ឡើង​នៅ​​ពេល​ចុច​គ្រាប់​ចុច"</string>
<string name="general_category" msgid="1859088467017573195">"ទូទៅ"</string>
<string name="correction_category" msgid="2236750915056607613">"ការ​កែ​អត្ថបទ"</string>
- <string name="gesture_typing_category" msgid="497263612130532630">"បញ្ចូល​ដោយ​ប្រើ​កាយវិការ​"</string>
+ <string name="gesture_typing_category" msgid="497263612130532630">"បញ្ចូល​ដោយ​ប្រើ​កាយវិការ"</string>
<string name="misc_category" msgid="6894192814868233453">"ជម្រើស​ផ្សេងទៀត"</string>
<string name="advanced_settings" msgid="362895144495591463">"ការ​កំណត់​កម្រិត​ខ្ពស់"</string>
<string name="advanced_settings_summary" msgid="4487980456152830271">"ជម្រើស​សម្រាប់​អ្នក​ជំនាញ"</string>
@@ -38,7 +38,7 @@
<string name="show_language_switch_key_summary" msgid="7343403647474265713">"បង្ហាញ​នៅ​ពេល​ដែល​បើក​ភាសា​បញ្ចូល​ច្រើន"</string>
<string name="sliding_key_input_preview" msgid="6604262359510068370">"បង្ហាញ​ទ្រនិច​បង្ហាញ​ស្លាយ"</string>
<string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"បង្ហាញ​​សញ្ញា​មើល​​ឃើញ​ខណៈ​ពេល​ដែល​រុញ​ពី​ឆ្វេង ឬ​​គ្រាប់​ចុច​​និមិត្ត​សញ្ញា"</string>
- <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"​សោ​លេចឡើង​បោះបង់​ការ​​ពន្យារពេល​"</string>
+ <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"​សោ​លេចឡើង​បោះបង់​ការ​​ពន្យារពេល"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"គ្មាន​ការ​ពន្យារពេល"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"លំនាំដើម"</string>
<string name="abbreviation_unit_milliseconds" msgid="8700286094028323363">"<xliff:g id="MILLISECONDS">%s</xliff:g> មិល្លី​វិនាទី"</string>
@@ -50,7 +50,7 @@
<skip />
<string name="use_double_space_period" msgid="8781529969425082860">"រយៈ​ពេល​ចុច​ដកឃ្លា​ពីរដង"</string>
<string name="use_double_space_period_summary" msgid="6532892187247952799">"ប៉ះ​ដកឃ្លា​ពីរ​​ដង​បញ្ចូល​​​រយៈ​ពេល​ដែល​អនុវត្ត​តាម​ដកឃ្លា"</string>
- <string name="auto_cap" msgid="1719746674854628252">"ការ​សរសេរ​ជា​អក្សរ​ធំ​​ស្វ័យប្រវត្តិ​"</string>
+ <string name="auto_cap" msgid="1719746674854628252">"ការ​សរសេរ​ជា​អក្សរ​ធំ​​ស្វ័យប្រវត្តិ"</string>
<string name="auto_cap_summary" msgid="7934452761022946874">"សរសេរ​ពាក្យ​ដំបូង​​​ជា​អក្សរ​ធំ​​នៃ​ប្រយោគ​នីមួយ​ៗ"</string>
<string name="edit_personal_dictionary" msgid="3996910038952940420">"វចនានុក្រម​ផ្ទាល់ខ្លួន"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"ផ្នែក​បន្ថែម​វចនានុក្រម"</string>
@@ -61,7 +61,7 @@
<string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"បង្ហាញ​នៅ​ក្នុង​របៀប​បញ្ឈរ"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"លាក់​ជានិច្ច"</string>
<string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"ទប់ស្កាត់​​ពាក្យ​​បំពាន"</string>
- <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"កុំ​ស្នើ​ឲ្យ​ពាក្យ​បំពាន​មាន​សក្ដានុពល​"</string>
+ <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"កុំ​ស្នើ​ឲ្យ​ពាក្យ​បំពាន​មាន​សក្ដានុពល"</string>
<string name="auto_correction" msgid="7630720885194996950">"ការ​កែ​​​ស្វ័យប្រវត្តិ"</string>
<string name="auto_correction_summary" msgid="5625751551134658006">"ចន្លោះ​មិន​ឃើញ ​និង​សញ្ញា​​វណ្ណយុត្ត​កែ​ពាក្យ​ដែល​បាន​វាយ​ខុស​ស្វ័យប្រវត្តិ"</string>
<string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"បិទ"</string>
@@ -121,7 +121,7 @@
<string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"ថិរវេលា​​ញ័រ​​ពេល​ចុច​គ្រាប់ចុច"</string>
<string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"កម្រិត​សំឡេង​ពេល​ចុច​គ្រាប់​ចុច"</string>
<string name="prefs_read_external_dictionary" msgid="2588931418575013067">"អាន​ឯកសារ​វចនានុក្រម​ខាង​ក្រៅ"</string>
- <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"គ្មាន​ឯកសារ​វចនានុក្រម​នៅ​ក្នុង​ថត​ទាញ​យក​​"</string>
+ <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"គ្មាន​ឯកសារ​វចនានុក្រម​នៅ​ក្នុង​ថត​ទាញ​យក"</string>
<string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"ជ្រើស​ឯកសារ​វចនានុក្រម​ ដើម្បី​ដំឡើង"</string>
<string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"ពិត​ជា​ដំឡើង​ឯកសារ​នេះ​សម្រាប់ <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string>
<string name="error" msgid="8940763624668513648">"មាន​កំហុស"</string>
@@ -148,7 +148,7 @@
<string name="dictionary_provider_name" msgid="3027315045397363079">"កម្មវិធី​ផ្ដល់​វចនានុក្រម"</string>
<string name="dictionary_service_name" msgid="6237472350693511448">"សេវាកម្ម​​វចនានុក្រម"</string>
<string name="download_description" msgid="6014835283119198591">"ព័ត៌មាន​បច្ចុប្បន្នភាព​វចនានុក្រម"</string>
- <string name="dictionary_settings_title" msgid="8091417676045693313">"ផ្នែក​បន្ថែម​វចនានុក្រម​​"</string>
+ <string name="dictionary_settings_title" msgid="8091417676045693313">"ផ្នែក​បន្ថែម​វចនានុក្រម"</string>
<string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"វចនានុក្រម​​​​​អាច​ប្រើ​បាន"</string>
<string name="dictionary_settings_summary" msgid="5305694987799824349">"ការ​កំណត់​សម្រាប់​វចនានុក្រម"</string>
<string name="user_dictionaries" msgid="3582332055892252845">"វចនានុក្រម​​​អ្នក​ប្រើ"</string>
@@ -164,10 +164,10 @@
<string name="message_updating" msgid="4457761393932375219">"ពិនិត្យមើល​បច្ចុប្បន្នភាព"</string>
<string name="message_loading" msgid="5638680861387748936">"កំពុង​ផ្ទុក..."</string>
<string name="main_dict_description" msgid="3072821352793492143">"វចនានុក្រម​ចម្បង"</string>
- <string name="cancel" msgid="6830980399865683324">"បោះ​បង់​"</string>
+ <string name="cancel" msgid="6830980399865683324">"បោះ​បង់"</string>
<string name="go_to_settings" msgid="3876892339342569259">"ការ​កំណត់"</string>
<string name="install_dict" msgid="180852772562189365">"ដំឡើង"</string>
- <string name="cancel_download_dict" msgid="7843340278507019303">"បោះ​បង់​"</string>
+ <string name="cancel_download_dict" msgid="7843340278507019303">"បោះ​បង់"</string>
<string name="delete_dict" msgid="756853268088330054">"លុប"</string>
<string name="should_download_over_metered_prompt" msgid="1583881200688185508">"ភាសា​ដែល​បាន​ជ្រើស​នៅ​លើ​ឧបករណ៍​ចល័ត​មាន​វចនានុក្រម​អាច​ប្រើ​បាន។&lt;br/&gt; យើង​ផ្ដល់​អនុសាសន៍​ឲ្យ &lt;b&gt;ទាញ​យក&lt;/b&gt; វចនានុក្រម​ភាសា <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g> ដើម្បី​បង្កើន​បទពិសោធន៍​វាយ​បញ្ចូល​របស់​អ្នក។&lt;br/&gt; &lt;br/&gt; ការ​ទាញ​យក​អាច​ចំណាយ​ពេល​ប្រហែល​ពីរ​នាទី​នៅ​តាម 3G។ ការ​គិត​ថ្លៃ​អាច​អនុវត្ត​ប្រសិន​បើ​អ្នក​មិន​ប្រើ &lt;b&gt;ផែនការ​ទិន្នន័យ​គ្មាន​ដែន​កំណត់&lt;/b&gt;.&lt;br/&gt; បើ​អ្នក​មិន​ប្រាកដ​​ថា​ផែនការ​ណា​មួយ​ដែល​អ្នក​មាន យើង​ផ្ដល់​អនុសាសន៍​ឲ្យ​​ភ្ជាប់​វ៉ាយហ្វាយ ដើម្បី​ចាប់ផ្ដើម​ទាញ​យក​ដោយ​ស្វ័យ​ប្រវត្តិ។&lt;br/&gt; &lt;br/&gt; ជំនួយ៖ អ្នក​អាច​ទាញ​យក និង​លុប​វចនានុក្រម​ដោយ​ចូល​ទៅ​ &lt;b&gt;ភាសា &amp; ការ​បញ្ចូល&lt;/b&gt; នៅ​ក្នុង​ម៉ឺនុយ &lt;b&gt;ការ​កំណត់&lt;/b&gt; សម្រាប់​ឧបករណ៍​ចល័ត។"</string>
<string name="download_over_metered" msgid="1643065851159409546">"ទាញ​យក​ឥឡូវ​នេះ (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> មេកាបៃ)"</string>
@@ -185,7 +185,7 @@
<string name="user_dict_settings_add_word_option_name" msgid="6665558053408962865">"ពាក្យ៖"</string>
<string name="user_dict_settings_add_shortcut_option_name" msgid="3094731590655523777">"ផ្លូវកាត់​៖"</string>
<string name="user_dict_settings_add_locale_option_name" msgid="4738643440987277705">"ភាសា៖"</string>
- <string name="user_dict_settings_add_word_hint" msgid="4902434148985906707">"វាយ​បញ្ចូល​ពាក្យ​"</string>
+ <string name="user_dict_settings_add_word_hint" msgid="4902434148985906707">"វាយ​បញ្ចូល​ពាក្យ"</string>
<string name="user_dict_settings_add_shortcut_hint" msgid="2265453012555060178">"ផ្លូវកាត់​ជា​ជម្រើស"</string>
<string name="user_dict_settings_edit_dialog_title" msgid="3765774633869590352">"កែ​ពាក្យ"</string>
<string name="user_dict_settings_context_menu_edit_title" msgid="6812255903472456302">"កែ"</string>
diff --git a/java/res/values-lo-rLA/strings-emoji-descriptions.xml b/java/res/values-lo-rLA/strings-emoji-descriptions.xml
index 0747fa629..83a702e95 100644
--- a/java/res/values-lo-rLA/strings-emoji-descriptions.xml
+++ b/java/res/values-lo-rLA/strings-emoji-descriptions.xml
@@ -210,7 +210,7 @@
<string name="spoken_emoji_1F330" msgid="3115760035618051575">"​ລູກ​ເກົາ​ລັດ"</string>
<string name="spoken_emoji_1F331" msgid="5658888205290008691">"​ກ້າ​ໄມ້"</string>
<string name="spoken_emoji_1F332" msgid="2935650450421165938">"ຕົ້ນ​ໄມ້​ບໍ່​ຜັດ​ໃບ"</string>
- <string name="spoken_emoji_1F333" msgid="5898847427062482675">"​ຕົ້ນ​ໄມ້​ຜັດໃບ​"</string>
+ <string name="spoken_emoji_1F333" msgid="5898847427062482675">"​ຕົ້ນ​ໄມ້​ຜັດໃບ"</string>
<string name="spoken_emoji_1F334" msgid="6183375224678417894">"​ຕົ້ນ​ປາມ"</string>
<string name="spoken_emoji_1F335" msgid="5352418412103584941">"​ກະ​ບອງ​ເພັດ"</string>
<string name="spoken_emoji_1F337" msgid="3839107352363566289">"​ທິວ​ລິບ"</string>
@@ -450,7 +450,7 @@
<string name="spoken_emoji_1F458" msgid="5704243858031107692">"​ກິ​ໂມ​ໂນ"</string>
<string name="spoken_emoji_1F459" msgid="3553148747050035251">"​ບິ​ກີ​ນີ"</string>
<string name="spoken_emoji_1F45A" msgid="1389654639484716101">"​ເສື້ອ​ຜ້າ​ຜູ່​ຍິງ"</string>
- <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"ກະ​ເປົາ​"</string>
+ <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"ກະ​ເປົາ"</string>
<string name="spoken_emoji_1F45C" msgid="3410257778598006936">"ກະ​ເປົາ"</string>
<string name="spoken_emoji_1F45D" msgid="812176504300064819">"​ກະ​ເປົາ"</string>
<string name="spoken_emoji_1F45E" msgid="2901741399934723562">"​ເກີບ​ຜູ່​ຊາຍ"</string>
diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml
index a1f478bd5..fcb919d0b 100644
--- a/java/res/values/attrs.xml
+++ b/java/res/values/attrs.xml
@@ -26,8 +26,6 @@
<attr name="keyboardViewStyle" format="reference" />
<!-- MainKeyboardView style -->
<attr name="mainKeyboardViewStyle" format="reference" />
- <!-- Key preview text view style -->
- <attr name="keyPreviewTextViewStyle" format="reference"/>
<!-- EmojiPalettesView style -->
<attr name="emojiPalettesViewStyle" format="reference" />
<!-- MoreKeysKeyboard style -->
@@ -106,8 +104,8 @@
<attr name="longPressShiftLockTimeout" format="integer" />
<!-- Ignore special key timeout while typing in millisecond. -->
<attr name="ignoreAltCodeKeyTimeout" format="integer" />
- <!-- Layout resource for key press feedback.-->
- <attr name="keyPreviewLayout" format="reference" />
+ <!-- Background resource for key press feedback.-->
+ <attr name="keyPreviewBackground" format="reference" />
<!-- Vertical offset of the key press feedback from the key. -->
<attr name="keyPreviewOffset" format="dimension" />
<!-- Height of the key press feedback popup. -->
diff --git a/java/res/values/themes-common.xml b/java/res/values/themes-common.xml
index 02a93ca82..2b2a80aed 100644
--- a/java/res/values/themes-common.xml
+++ b/java/res/values/themes-common.xml
@@ -75,7 +75,6 @@
<item name="keyRepeatInterval">@integer/config_key_repeat_interval</item>
<item name="longPressShiftLockTimeout">@integer/config_longpress_shift_lock_timeout</item>
<item name="ignoreAltCodeKeyTimeout">@integer/config_ignore_alt_code_key_timeout</item>
- <item name="keyPreviewLayout">@layout/key_preview</item>
<item name="keyPreviewHeight">@dimen/config_key_preview_height</item>
<!-- TODO: consolidate key preview linger timeout with the key preview animation parameters. -->
<item name="keyPreviewLingerTimeout">@integer/config_key_preview_linger_timeout</item>
@@ -106,7 +105,6 @@
<style
name="MainKeyboardView"
parent="KeyboardView" />
- <style name="KeyPreviewTextView" />
<!-- Though {@link EmojiPalettesView} doesn't extend {@link KeyboardView}, some views inside it,
for instance delete button, need themed {@link KeyboardView} attributes. -->
<style name="EmojiPalettesView" />
diff --git a/java/res/values/themes-ics.xml b/java/res/values/themes-ics.xml
index 319b4aeed..073ae90b9 100644
--- a/java/res/values/themes-ics.xml
+++ b/java/res/values/themes-ics.xml
@@ -23,7 +23,6 @@
<item name="keyboardStyle">@style/Keyboard.ICS</item>
<item name="keyboardViewStyle">@style/KeyboardView.ICS</item>
<item name="mainKeyboardViewStyle">@style/MainKeyboardView.ICS</item>
- <item name="keyPreviewTextViewStyle">@style/KeyPreviewTextView.ICS</item>
<item name="emojiPalettesViewStyle">@style/EmojiPalettesView.ICS</item>
<item name="moreKeysKeyboardStyle">@style/MoreKeysKeyboard.ICS</item>
<item name="moreKeysKeyboardViewStyle">@style/MoreKeysKeyboardView.ICS</item>
@@ -66,6 +65,7 @@
name="MainKeyboardView.ICS"
parent="KeyboardView.ICS"
>
+ <item name="keyPreviewBackground">@drawable/keyboard_key_feedback_ics</item>
<item name="keyPreviewOffset">@dimen/config_key_preview_offset_holo</item>
<item name="gestureFloatingPreviewTextColor">@color/highlight_color_ics</item>
<item name="gestureFloatingPreviewColor">@color/gesture_floating_preview_color_holo</item>
@@ -75,12 +75,6 @@
<item name="languageOnSpacebarTextShadowRadius">1.0</item>
<item name="languageOnSpacebarTextShadowColor">@color/spacebar_text_shadow_color_holo</item>
</style>
- <style
- name="KeyPreviewTextView.ICS"
- parent="KeyPreviewTextView"
- >
- <item name="android:background">@drawable/keyboard_key_feedback_ics</item>
- </style>
<!-- Though {@link EmojiPalettesView} doesn't extend {@link KeyboardView}, some views inside it,
for instance delete button, need themed {@link KeyboardView} attributes. -->
<style
diff --git a/java/res/values/themes-klp.xml b/java/res/values/themes-klp.xml
index 208723dd3..f895de572 100644
--- a/java/res/values/themes-klp.xml
+++ b/java/res/values/themes-klp.xml
@@ -23,7 +23,6 @@
<item name="keyboardStyle">@style/Keyboard.KLP</item>
<item name="keyboardViewStyle">@style/KeyboardView.KLP</item>
<item name="mainKeyboardViewStyle">@style/MainKeyboardView.KLP</item>
- <item name="keyPreviewTextViewStyle">@style/KeyPreviewTextView.KLP</item>
<item name="emojiPalettesViewStyle">@style/EmojiPalettesView.KLP</item>
<item name="moreKeysKeyboardStyle">@style/MoreKeysKeyboard.KLP</item>
<item name="moreKeysKeyboardViewStyle">@style/MoreKeysKeyboardView.KLP</item>
@@ -66,6 +65,7 @@
name="MainKeyboardView.KLP"
parent="KeyboardView.KLP"
>
+ <item name="keyPreviewBackground">@drawable/keyboard_key_feedback_klp</item>
<item name="keyPreviewOffset">@dimen/config_key_preview_offset_holo</item>
<item name="gestureFloatingPreviewTextColor">@color/highlight_color_klp</item>
<item name="gestureFloatingPreviewColor">@color/gesture_floating_preview_color_holo</item>
@@ -75,12 +75,6 @@
<item name="languageOnSpacebarTextShadowRadius">1.0</item>
<item name="languageOnSpacebarTextShadowColor">@color/spacebar_text_shadow_color_holo</item>
</style>
- <style
- name="KeyPreviewTextView.KLP"
- parent="KeyPreviewTextView"
- >
- <item name="android:background">@drawable/keyboard_key_feedback_klp</item>
- </style>
<!-- Though {@link EmojiPalettesView} doesn't extend {@link KeyboardView}, some views inside it,
for instance delete button, need themed {@link KeyboardView} attributes. -->
<style
diff --git a/java/res/values/themes-lxx-dark.xml b/java/res/values/themes-lxx-dark.xml
index e9a295c67..1db8f428e 100644
--- a/java/res/values/themes-lxx-dark.xml
+++ b/java/res/values/themes-lxx-dark.xml
@@ -23,7 +23,6 @@
<item name="keyboardStyle">@style/Keyboard.LXX_Dark</item>
<item name="keyboardViewStyle">@style/KeyboardView.LXX_Dark</item>
<item name="mainKeyboardViewStyle">@style/MainKeyboardView.LXX_Dark</item>
- <item name="keyPreviewTextViewStyle">@style/KeyPreviewTextView.LXX_Dark</item>
<item name="emojiPalettesViewStyle">@style/EmojiPalettesView.LXX_Dark</item>
<item name="moreKeysKeyboardStyle">@style/MoreKeysKeyboard.LXX_Dark</item>
<item name="moreKeysKeyboardViewStyle">@style/MoreKeysKeyboardView.LXX_Dark</item>
@@ -67,6 +66,7 @@
name="MainKeyboardView.LXX_Dark"
parent="KeyboardView.LXX_Dark"
>
+ <item name="keyPreviewBackground">@drawable/keyboard_key_feedback_lxx_dark</item>
<item name="keyPreviewOffset">@dimen/config_key_preview_offset_holo</item>
<item name="gestureFloatingPreviewTextColor">@color/highlight_color_lxx_dark</item>
<item name="gestureFloatingPreviewColor">@color/gesture_floating_preview_color_lxx_dark</item>
@@ -76,12 +76,6 @@
<!-- A negative value to disable text shadow layer. -->
<item name="languageOnSpacebarTextShadowRadius">-1.0</item>
</style>
- <style
- name="KeyPreviewTextView.LXX_Dark"
- parent="KeyPreviewTextView"
- >
- <item name="android:background">@drawable/keyboard_key_feedback_lxx_dark</item>
- </style>
<!-- Though {@link EmojiPalettesView} doesn't extend {@link KeyboardView}, some views inside it,
for instance delete button, need themed {@link KeyboardView} attributes. -->
<style
diff --git a/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityDelegate.java b/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityDelegate.java
index d67d9dc4b..3925fc652 100644
--- a/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityDelegate.java
+++ b/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityDelegate.java
@@ -305,7 +305,7 @@ public class KeyboardAccessibilityDelegate<KV extends KeyboardView>
key.onPressed();
mKeyboardView.invalidateKey(key);
final KeyboardAccessibilityNodeProvider provider = getAccessibilityNodeProvider();
- provider.sendAccessibilityEventForKey(key, AccessibilityEventCompat.TYPE_VIEW_HOVER_ENTER);
+ provider.onHoverEnterTo(key);
provider.performActionForKey(key, AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS);
}
@@ -328,6 +328,6 @@ public class KeyboardAccessibilityDelegate<KV extends KeyboardView>
key.onReleased();
mKeyboardView.invalidateKey(key);
final KeyboardAccessibilityNodeProvider provider = getAccessibilityNodeProvider();
- provider.sendAccessibilityEventForKey(key, AccessibilityEventCompat.TYPE_VIEW_HOVER_EXIT);
+ provider.onHoverExitFrom(key);
}
}
diff --git a/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityNodeProvider.java b/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityNodeProvider.java
index cb13483f2..61d066af5 100644
--- a/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityNodeProvider.java
+++ b/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityNodeProvider.java
@@ -65,6 +65,9 @@ final class KeyboardAccessibilityNodeProvider extends AccessibilityNodeProviderC
/** The virtual view identifier for the focused node. */
private int mAccessibilityFocusedView = UNDEFINED;
+ /** The virtual view identifier for the hovering node. */
+ private int mHoveringNodeId = UNDEFINED;
+
/** The current keyboard view. */
private final KeyboardView mKeyboardView;
@@ -76,7 +79,6 @@ final class KeyboardAccessibilityNodeProvider extends AccessibilityNodeProviderC
mKeyCodeDescriptionMapper = KeyCodeDescriptionMapper.getInstance();
mAccessibilityUtils = AccessibilityUtils.getInstance();
mKeyboardView = keyboardView;
- updateParentLocation();
// Since this class is constructed lazily, we might not get a subsequent
// call to setKeyboard() and therefore need to call it now.
@@ -141,6 +143,28 @@ final class KeyboardAccessibilityNodeProvider extends AccessibilityNodeProviderC
return event;
}
+ public void onHoverEnterTo(final Key key) {
+ final int id = getVirtualViewIdOf(key);
+ if (id == View.NO_ID) {
+ return;
+ }
+ // Start hovering on the key. Because our accessibility model is lift-to-type, we should
+ // report the node info without click and long click actions to avoid unnecessary
+ // announcements.
+ mHoveringNodeId = id;
+ // Invalidate the node info of the key.
+ sendAccessibilityEventForKey(key, AccessibilityEventCompat.TYPE_WINDOW_CONTENT_CHANGED);
+ sendAccessibilityEventForKey(key, AccessibilityEventCompat.TYPE_VIEW_HOVER_ENTER);
+ }
+
+ public void onHoverExitFrom(final Key key) {
+ mHoveringNodeId = UNDEFINED;
+ // Invalidate the node info of the key to be able to revert the change we have done
+ // in {@link #onHoverEnterTo(Key)}.
+ sendAccessibilityEventForKey(key, AccessibilityEventCompat.TYPE_WINDOW_CONTENT_CHANGED);
+ sendAccessibilityEventForKey(key, AccessibilityEventCompat.TYPE_VIEW_HOVER_EXIT);
+ }
+
/**
* Returns an {@link AccessibilityNodeInfoCompat} representing a virtual
* view, i.e. a descendant of the host View, with the given <code>virtualViewId</code> or
@@ -169,10 +193,23 @@ final class KeyboardAccessibilityNodeProvider extends AccessibilityNodeProviderC
}
if (virtualViewId == View.NO_ID) {
// We are requested to create an AccessibilityNodeInfo describing
- // this View. Returning an empty info is sufficient for a keyboard.
+ // this View, i.e. the root of the virtual sub-tree.
final AccessibilityNodeInfoCompat rootInfo =
AccessibilityNodeInfoCompat.obtain(mKeyboardView);
ViewCompat.onInitializeAccessibilityNodeInfo(mKeyboardView, rootInfo);
+ updateParentLocation();
+
+ // Add the virtual children of the root View.
+ final List<Key> sortedKeys = mKeyboard.getSortedKeys();
+ final int size = sortedKeys.size();
+ for (int index = 0; index < size; index++) {
+ final Key key = sortedKeys.get(index);
+ if (key.isSpacer()) {
+ continue;
+ }
+ // Use an index of the sorted keys list as a virtual view id.
+ rootInfo.addChild(mKeyboardView, index);
+ }
return rootInfo;
}
@@ -200,9 +237,16 @@ final class KeyboardAccessibilityNodeProvider extends AccessibilityNodeProviderC
info.setBoundsInScreen(boundsInScreen);
info.setParent(mKeyboardView);
info.setSource(mKeyboardView, virtualViewId);
- info.setBoundsInScreen(boundsInScreen);
- info.setEnabled(true);
+ info.setEnabled(key.isEnabled());
info.setVisibleToUser(true);
+ // Don't add ACTION_CLICK and ACTION_LONG_CLOCK actions while hovering on the key.
+ // See {@link #onHoverEnterTo(Key)} and {@link #onHoverExitFrom(Key)}.
+ if (virtualViewId != mHoveringNodeId) {
+ info.addAction(AccessibilityNodeInfoCompat.ACTION_CLICK);
+ if (key.isLongPressEnabled()) {
+ info.addAction(AccessibilityNodeInfoCompat.ACTION_LONG_CLICK);
+ }
+ }
if (mAccessibilityFocusedView == virtualViewId) {
info.addAction(AccessibilityNodeInfoCompat.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
@@ -241,6 +285,12 @@ final class KeyboardAccessibilityNodeProvider extends AccessibilityNodeProviderC
sendAccessibilityEventForKey(
key, AccessibilityEventCompat.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
return true;
+ case AccessibilityNodeInfoCompat.ACTION_CLICK:
+ sendAccessibilityEventForKey(key, AccessibilityEvent.TYPE_VIEW_CLICKED);
+ return true;
+ case AccessibilityNodeInfoCompat.ACTION_LONG_CLICK:
+ sendAccessibilityEventForKey(key, AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
+ return true;
default:
return false;
}
diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
index 9a859bfdb..81825934f 100644
--- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
@@ -35,7 +35,6 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodSubtype;
-import android.widget.TextView;
import com.android.inputmethod.accessibility.AccessibilityUtils;
import com.android.inputmethod.accessibility.MainKeyboardAccessibilityDelegate;
@@ -48,6 +47,7 @@ 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.LanguageOnSpacebarHelper;
+import com.android.inputmethod.keyboard.internal.MoreKeySpec;
import com.android.inputmethod.keyboard.internal.NonDistinctMultitouchHelper;
import com.android.inputmethod.keyboard.internal.SlidingKeyInputDrawingPreview;
import com.android.inputmethod.keyboard.internal.TimerHandler;
@@ -236,16 +236,14 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
R.styleable.MainKeyboardView_gestureFloatingPreviewTextLingerTimeout, 0);
mGestureFloatingTextDrawingPreview = new GestureFloatingTextDrawingPreview(
- mDrawingPreviewPlacerView, mainKeyboardViewAttr);
- mDrawingPreviewPlacerView.addPreview(mGestureFloatingTextDrawingPreview);
+ mainKeyboardViewAttr);
+ mGestureFloatingTextDrawingPreview.setDrawingView(mDrawingPreviewPlacerView);
- mGestureTrailsDrawingPreview = new GestureTrailsDrawingPreview(
- mDrawingPreviewPlacerView, mainKeyboardViewAttr);
- mDrawingPreviewPlacerView.addPreview(mGestureTrailsDrawingPreview);
+ mGestureTrailsDrawingPreview = new GestureTrailsDrawingPreview(mainKeyboardViewAttr);
+ mGestureTrailsDrawingPreview.setDrawingView(mDrawingPreviewPlacerView);
- mSlidingKeyInputDrawingPreview = new SlidingKeyInputDrawingPreview(
- mDrawingPreviewPlacerView, mainKeyboardViewAttr);
- mDrawingPreviewPlacerView.addPreview(mSlidingKeyInputDrawingPreview);
+ mSlidingKeyInputDrawingPreview = new SlidingKeyInputDrawingPreview(mainKeyboardViewAttr);
+ mSlidingKeyInputDrawingPreview.setDrawingView(mDrawingPreviewPlacerView);
mainKeyboardViewAttr.recycle();
mMoreKeysKeyboardContainer = LayoutInflater.from(getContext())
@@ -428,15 +426,6 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
windowContentView.addView(mDrawingPreviewPlacerView);
}
- /**
- * Returns the enabled state of the key feedback preview
- * @return whether or not the key feedback preview is enabled
- * @see #setKeyPreviewPopupEnabled(boolean, int)
- */
- public boolean isKeyPreviewPopupEnabled() {
- return mKeyPreviewDrawParams.isPopupEnabled();
- }
-
// Implements {@link DrawingHandler.Callbacks} method.
@Override
public void dismissAllKeyPreviews() {
@@ -461,12 +450,9 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
}
locatePreviewPlacerView();
- final TextView previewTextView = mKeyPreviewChoreographer.getKeyPreviewTextView(
- key, mDrawingPreviewPlacerView);
getLocationInWindow(mOriginCoords);
- mKeyPreviewChoreographer.placeKeyPreview(key, previewTextView, keyboard.mIconsSet,
- mKeyDrawParams, getWidth(), mOriginCoords);
- mKeyPreviewChoreographer.showKeyPreview(key, previewTextView, isHardwareAccelerated());
+ mKeyPreviewChoreographer.placeKeyPreviewAndShow(key, keyboard.mIconsSet, mKeyDrawParams,
+ getWidth(), mOriginCoords, mDrawingPreviewPlacerView, isHardwareAccelerated());
}
// Implements {@link TimerHandler.Callbacks} method.
@@ -557,13 +543,25 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
}
private MoreKeysPanel onCreateMoreKeysPanel(final Key key, final Context context) {
- if (key.getMoreKeys() == null) {
+ final MoreKeySpec[] moreKeys = key.getMoreKeys();
+ if (moreKeys == null) {
return null;
}
Keyboard moreKeysKeyboard = mMoreKeysKeyboardCache.get(key);
if (moreKeysKeyboard == null) {
- moreKeysKeyboard = new MoreKeysKeyboard.Builder(
- context, key, this, mKeyPreviewDrawParams).build();
+ // {@link KeyPreviewDrawParams#mPreviewVisibleWidth} should have been set at
+ // {@link KeyPreviewChoreographer#placeKeyPreview(Key,TextView,KeyboardIconsSet,KeyDrawParams,int,int[]},
+ // though there may be some chances that the value is zero. <code>width == 0</code>
+ // will cause zero-division error at
+ // {@link MoreKeysKeyboardParams#setParameters(int,int,int,int,int,int,boolean,int)}.
+ final boolean singleMoreKeyWithPreview = mKeyPreviewDrawParams.isPopupEnabled()
+ && !key.noKeyPreview() && moreKeys.length == 1
+ && mKeyPreviewDrawParams.getVisibleWidth() > 0;
+ final MoreKeysKeyboard.Builder builder = new MoreKeysKeyboard.Builder(
+ context, key, getKeyboard(), singleMoreKeyWithPreview,
+ mKeyPreviewDrawParams.getVisibleWidth(),
+ mKeyPreviewDrawParams.getVisibleHeight(), newLabelPaint(key));
+ moreKeysKeyboard = builder.build();
mMoreKeysKeyboardCache.put(key, moreKeysKeyboard);
}
@@ -619,7 +617,8 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
final int[] lastCoords = CoordinateUtils.newInstance();
tracker.getLastCoordinates(lastCoords);
- final boolean keyPreviewEnabled = isKeyPreviewPopupEnabled() && !key.noKeyPreview();
+ final boolean keyPreviewEnabled = mKeyPreviewDrawParams.isPopupEnabled()
+ && !key.noKeyPreview();
// The more keys keyboard is usually horizontally aligned with the center of the parent key.
// If showMoreKeysKeyboardAtTouchedPoint is true and the key preview is disabled, the more
// keys keyboard is placed at the touch point of the parent key.
@@ -730,6 +729,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
}
public void onHideWindow() {
+ onDismissMoreKeysPanel();
final MainKeyboardAccessibilityDelegate accessibilityDelegate = mAccessibilityDelegate;
if (accessibilityDelegate != null) {
accessibilityDelegate.onHideWindow();
diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java
index a72f79137..353e07cf7 100644
--- a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java
@@ -21,7 +21,6 @@ import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import com.android.inputmethod.annotations.UsedForTesting;
-import com.android.inputmethod.keyboard.internal.KeyPreviewDrawParams;
import com.android.inputmethod.keyboard.internal.KeyboardBuilder;
import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
import com.android.inputmethod.keyboard.internal.KeyboardParams;
@@ -260,32 +259,25 @@ public final class MoreKeysKeyboard extends Keyboard {
/**
* The builder of MoreKeysKeyboard.
* @param context the context of {@link MoreKeysKeyboardView}.
- * @param parentKey the {@link Key} that invokes more keys keyboard.
- * @param parentKeyboardView the {@link KeyboardView} that contains the parentKey.
+ * @param key the {@link Key} that invokes more keys keyboard.
+ * @param keyboard the {@link Keyboard} that contains the parentKey.
+ * @param singleMoreKeyWithPreview true if the <code>key</code> has only one more key
+ * and key popup preview is enabled.
* @param keyPreviewDrawParams the parameter to place key preview.
+ * @param paintToMeasure the {@link Paint} object to measure a more key width
*/
- public Builder(final Context context, final Key parentKey,
- final MainKeyboardView parentKeyboardView,
- final KeyPreviewDrawParams keyPreviewDrawParams) {
+ public Builder(final Context context, final Key key, final Keyboard keyboard,
+ final boolean singleMoreKeyWithPreview, final int keyPreviewVisibleWidth,
+ final int keyPreviewVisibleHeight, final Paint paintToMeasure) {
super(context, new MoreKeysKeyboardParams());
- final Keyboard parentKeyboard = parentKeyboardView.getKeyboard();
- load(parentKeyboard.mMoreKeysTemplate, parentKeyboard.mId);
+ load(keyboard.mMoreKeysTemplate, keyboard.mId);
// TODO: More keys keyboard's vertical gap is currently calculated heuristically.
// Should revise the algorithm.
- mParams.mVerticalGap = parentKeyboard.mVerticalGap / 2;
- mParentKey = parentKey;
-
- final MoreKeySpec[] moreKeys = parentKey.getMoreKeys();
- final int width, height;
- // {@link KeyPreviewDrawParams#mPreviewVisibleWidth} should have been set at
- // {@link MainKeyboardView#showKeyPreview(PointerTracker}, though there may be
- // some chances that the value is zero. <code>width == 0</code> will cause
- // zero-division error at
- // {@link MoreKeysKeyboardParams#setParameters(int,int,int,int,int,int,boolean,int)}.
- final boolean singleMoreKeyWithPreview = parentKeyboardView.isKeyPreviewPopupEnabled()
- && !parentKey.noKeyPreview() && moreKeys.length == 1
- && keyPreviewDrawParams.getVisibleWidth() > 0;
+ mParams.mVerticalGap = keyboard.mVerticalGap / 2;
+ mParentKey = key;
+
+ final int keyWidth, rowHeight;
if (singleMoreKeyWithPreview) {
// Use pre-computed width and height if this more keys keyboard has only one key to
// mitigate visual flicker between key preview and more keys keyboard.
@@ -294,29 +286,28 @@ public final class MoreKeysKeyboard extends Keyboard {
// left/right/top paddings. The bottom paddings of both backgrounds don't need to
// be considered because the vertical positions of both backgrounds were already
// adjusted with their bottom paddings deducted.
- width = keyPreviewDrawParams.getVisibleWidth();
- height = keyPreviewDrawParams.getVisibleHeight() + mParams.mVerticalGap;
+ keyWidth = keyPreviewVisibleWidth;
+ rowHeight = keyPreviewVisibleHeight + mParams.mVerticalGap;
} else {
final float padding = context.getResources().getDimension(
R.dimen.config_more_keys_keyboard_key_horizontal_padding)
- + (parentKey.hasLabelsInMoreKeys()
+ + (key.hasLabelsInMoreKeys()
? mParams.mDefaultKeyWidth * LABEL_PADDING_RATIO : 0.0f);
- width = getMaxKeyWidth(parentKey, mParams.mDefaultKeyWidth, padding,
- parentKeyboardView.newLabelPaint(parentKey));
- height = parentKeyboard.mMostCommonKeyHeight;
+ keyWidth = getMaxKeyWidth(key, mParams.mDefaultKeyWidth, padding, paintToMeasure);
+ rowHeight = keyboard.mMostCommonKeyHeight;
}
final int dividerWidth;
- if (parentKey.needsDividersInMoreKeys()) {
+ if (key.needsDividersInMoreKeys()) {
mDivider = mResources.getDrawable(R.drawable.more_keys_divider);
- dividerWidth = (int)(width * DIVIDER_RATIO);
+ dividerWidth = (int)(keyWidth * DIVIDER_RATIO);
} else {
mDivider = null;
dividerWidth = 0;
}
- mParams.setParameters(moreKeys.length, parentKey.getMoreKeysColumn(),
- width, height, parentKey.getX() + parentKey.getWidth() / 2,
- parentKeyboard.mId.mWidth, parentKey.isFixedColumnOrderMoreKeys(),
- dividerWidth);
+ final MoreKeySpec[] moreKeys = key.getMoreKeys();
+ mParams.setParameters(moreKeys.length, key.getMoreKeysColumn(), keyWidth, rowHeight,
+ key.getX() + key.getWidth() / 2, keyboard.mId.mWidth,
+ key.isFixedColumnOrderMoreKeys(), dividerWidth);
}
private static int getMaxKeyWidth(final Key parentKey, final int minKeyWidth,
diff --git a/java/src/com/android/inputmethod/keyboard/emoji/EmojiPageKeyboardView.java b/java/src/com/android/inputmethod/keyboard/emoji/EmojiPageKeyboardView.java
index a34dbef4b..8010a3e7e 100644
--- a/java/src/com/android/inputmethod/keyboard/emoji/EmojiPageKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/emoji/EmojiPageKeyboardView.java
@@ -21,6 +21,7 @@ import android.os.Handler;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
+import android.view.accessibility.AccessibilityEvent;
import com.android.inputmethod.accessibility.AccessibilityUtils;
import com.android.inputmethod.accessibility.KeyboardAccessibilityDelegate;
@@ -106,6 +107,12 @@ final class EmojiPageKeyboardView extends KeyboardView implements
}
}
+ @Override
+ public boolean dispatchPopulateAccessibilityEvent(final AccessibilityEvent event) {
+ // Don't populate accessibility event with all Emoji keys.
+ return true;
+ }
+
/**
* {@inheritDoc}
*/
diff --git a/java/src/com/android/inputmethod/keyboard/internal/AbstractDrawingPreview.java b/java/src/com/android/inputmethod/keyboard/internal/AbstractDrawingPreview.java
index 3a72aed0d..a194f3dfd 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/AbstractDrawingPreview.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/AbstractDrawingPreview.java
@@ -27,16 +27,19 @@ import com.android.inputmethod.keyboard.PointerTracker;
* SlidingKeyInputDrawingPreview.
*/
public abstract class AbstractDrawingPreview {
- private final View mDrawingView;
+ private View mDrawingView;
private boolean mPreviewEnabled;
private boolean mHasValidGeometry;
- protected AbstractDrawingPreview(final View drawingView) {
+ public void setDrawingView(final DrawingPreviewPlacerView drawingView) {
mDrawingView = drawingView;
+ drawingView.addPreview(this);
}
- protected final View getDrawingView() {
- return mDrawingView;
+ protected void invalidateDrawingView() {
+ if (mDrawingView != null) {
+ mDrawingView.invalidate();
+ }
}
protected final boolean isPreviewEnabled() {
diff --git a/java/src/com/android/inputmethod/keyboard/internal/DrawingPreviewPlacerView.java b/java/src/com/android/inputmethod/keyboard/internal/DrawingPreviewPlacerView.java
index 3b4c43418..a5d47adb3 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/DrawingPreviewPlacerView.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/DrawingPreviewPlacerView.java
@@ -46,7 +46,9 @@ public final class DrawingPreviewPlacerView extends RelativeLayout {
}
public void addPreview(final AbstractDrawingPreview preview) {
- mPreviews.add(preview);
+ if (mPreviews.indexOf(preview) < 0) {
+ mPreviews.add(preview);
+ }
}
public void setKeyboardViewGeometry(final int[] originCoords, final int width,
diff --git a/java/src/com/android/inputmethod/keyboard/internal/GestureFloatingTextDrawingPreview.java b/java/src/com/android/inputmethod/keyboard/internal/GestureFloatingTextDrawingPreview.java
index 2fa703083..fd84856b7 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/GestureFloatingTextDrawingPreview.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/GestureFloatingTextDrawingPreview.java
@@ -23,7 +23,6 @@ import android.graphics.Paint.Align;
import android.graphics.Rect;
import android.graphics.RectF;
import android.text.TextUtils;
-import android.view.View;
import com.android.inputmethod.keyboard.PointerTracker;
import com.android.inputmethod.latin.R;
@@ -49,6 +48,7 @@ public class GestureFloatingTextDrawingPreview extends AbstractDrawingPreview {
public final float mGesturePreviewHorizontalPadding;
public final float mGesturePreviewVerticalPadding;
public final float mGesturePreviewRoundRadius;
+ public final int mDisplayWidth;
private final int mGesturePreviewTextSize;
private final int mGesturePreviewTextColor;
@@ -72,6 +72,7 @@ public class GestureFloatingTextDrawingPreview extends AbstractDrawingPreview {
R.styleable.MainKeyboardView_gestureFloatingPreviewVerticalPadding, 0.0f);
mGesturePreviewRoundRadius = mainKeyboardViewAttr.getDimension(
R.styleable.MainKeyboardView_gestureFloatingPreviewRoundRadius, 0.0f);
+ mDisplayWidth = mainKeyboardViewAttr.getResources().getDisplayMetrics().widthPixels;
final Paint textPaint = getTextPaint();
final Rect textRect = new Rect();
@@ -100,9 +101,8 @@ public class GestureFloatingTextDrawingPreview extends AbstractDrawingPreview {
private SuggestedWords mSuggestedWords = SuggestedWords.EMPTY;
private final int[] mLastPointerCoords = CoordinateUtils.newInstance();
- public GestureFloatingTextDrawingPreview(final View drawingView, final TypedArray typedArray) {
- super(drawingView);
- mParams = new GesturePreviewTextParams(typedArray);
+ public GestureFloatingTextDrawingPreview(final TypedArray mainKeyboardViewAttr) {
+ mParams = new GesturePreviewTextParams(mainKeyboardViewAttr);
}
@Override
@@ -149,7 +149,7 @@ public class GestureFloatingTextDrawingPreview extends AbstractDrawingPreview {
*/
protected void updatePreviewPosition() {
if (mSuggestedWords.isEmpty() || TextUtils.isEmpty(mSuggestedWords.getWord(0))) {
- getDrawingView().invalidate();
+ invalidateDrawingView();
return;
}
final String text = mSuggestedWords.getWord(0);
@@ -163,10 +163,9 @@ public class GestureFloatingTextDrawingPreview extends AbstractDrawingPreview {
final float rectWidth = textWidth + hPad * 2.0f;
final float rectHeight = textHeight + vPad * 2.0f;
- final int displayWidth = getDrawingView().getResources().getDisplayMetrics().widthPixels;
final float rectX = Math.min(
Math.max(CoordinateUtils.x(mLastPointerCoords) - rectWidth / 2.0f, 0.0f),
- displayWidth - rectWidth);
+ mParams.mDisplayWidth - rectWidth);
final float rectY = CoordinateUtils.y(mLastPointerCoords)
- mParams.mGesturePreviewTextOffset - rectHeight;
rectangle.set(rectX, rectY, rectX + rectWidth, rectY + rectHeight);
@@ -174,6 +173,6 @@ public class GestureFloatingTextDrawingPreview extends AbstractDrawingPreview {
mPreviewTextX = (int)(rectX + hPad + textWidth / 2.0f);
mPreviewTextY = (int)(rectY + vPad) + textHeight;
// TODO: Should narrow the invalidate region.
- getDrawingView().invalidate();
+ invalidateDrawingView();
}
}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/GestureTrailsDrawingPreview.java b/java/src/com/android/inputmethod/keyboard/internal/GestureTrailsDrawingPreview.java
index 72628e38a..f7bd7efe0 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/GestureTrailsDrawingPreview.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/GestureTrailsDrawingPreview.java
@@ -24,17 +24,15 @@ import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
-import android.os.Message;
+import android.os.Handler;
import android.util.SparseArray;
-import android.view.View;
import com.android.inputmethod.keyboard.PointerTracker;
-import com.android.inputmethod.latin.utils.LeakGuardHandlerWrapper;
/**
* Draw preview graphics of multiple gesture trails during gesture input.
*/
-public final class GestureTrailsDrawingPreview extends AbstractDrawingPreview {
+public final class GestureTrailsDrawingPreview extends AbstractDrawingPreview implements Runnable {
private final SparseArray<GestureTrailDrawingPoints> mGestureTrails = new SparseArray<>();
private final GestureTrailDrawingParams mDrawingParams;
private final Paint mGesturePaint;
@@ -47,45 +45,10 @@ public final class GestureTrailsDrawingPreview extends AbstractDrawingPreview {
private final Rect mDirtyRect = new Rect();
private final Rect mGestureTrailBoundsRect = new Rect(); // per trail
- private final DrawingHandler mDrawingHandler;
+ private final Handler mDrawingHandler = new Handler();
- private static final class DrawingHandler
- extends LeakGuardHandlerWrapper<GestureTrailsDrawingPreview> {
- private static final int MSG_UPDATE_GESTURE_TRAIL = 0;
-
- private final GestureTrailDrawingParams mDrawingParams;
-
- public DrawingHandler(final GestureTrailsDrawingPreview ownerInstance,
- final GestureTrailDrawingParams drawingParams) {
- super(ownerInstance);
- mDrawingParams = drawingParams;
- }
-
- @Override
- public void handleMessage(final Message msg) {
- final GestureTrailsDrawingPreview preview = getOwnerInstance();
- if (preview == null) {
- return;
- }
- switch (msg.what) {
- case MSG_UPDATE_GESTURE_TRAIL:
- preview.getDrawingView().invalidate();
- break;
- }
- }
-
- public void postUpdateGestureTrailPreview() {
- removeMessages(MSG_UPDATE_GESTURE_TRAIL);
- sendMessageDelayed(obtainMessage(MSG_UPDATE_GESTURE_TRAIL),
- mDrawingParams.mUpdateInterval);
- }
- }
-
- public GestureTrailsDrawingPreview(final View drawingView,
- final TypedArray mainKeyboardViewAttr) {
- super(drawingView);
+ public GestureTrailsDrawingPreview(final TypedArray mainKeyboardViewAttr) {
mDrawingParams = new GestureTrailDrawingParams(mainKeyboardViewAttr);
- mDrawingHandler = new DrawingHandler(this, mDrawingParams);
final Paint gesturePaint = new Paint();
gesturePaint.setAntiAlias(true);
gesturePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
@@ -153,6 +116,12 @@ public final class GestureTrailsDrawingPreview extends AbstractDrawingPreview {
return needsUpdatingGestureTrail;
}
+ @Override
+ public void run() {
+ // Update preview.
+ invalidateDrawingView();
+ }
+
/**
* Draws the preview
* @param canvas The canvas where the preview is drawn.
@@ -167,7 +136,8 @@ public final class GestureTrailsDrawingPreview extends AbstractDrawingPreview {
final boolean needsUpdatingGestureTrail = drawGestureTrails(
mOffscreenCanvas, mGesturePaint, mDirtyRect);
if (needsUpdatingGestureTrail) {
- mDrawingHandler.postUpdateGestureTrailPreview();
+ mDrawingHandler.removeCallbacks(this);
+ mDrawingHandler.postDelayed(this, mDrawingParams.mUpdateInterval);
}
// Transfer offscreen buffer to screen.
if (!mDirtyRect.isEmpty()) {
@@ -199,6 +169,6 @@ public final class GestureTrailsDrawingPreview extends AbstractDrawingPreview {
trail.addStroke(tracker.getGestureStrokeDrawingPoints(), tracker.getDownTime());
// TODO: Should narrow the invalidate region.
- getDrawingView().invalidate();
+ invalidateDrawingView();
}
}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewChoreographer.java b/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewChoreographer.java
index 605519b02..6fc300beb 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewChoreographer.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewChoreographer.java
@@ -21,17 +21,12 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.util.TypedValue;
-import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
-import android.widget.TextView;
import com.android.inputmethod.keyboard.Key;
-import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.utils.CoordinateUtils;
import com.android.inputmethod.latin.utils.ViewLayoutUtils;
@@ -46,10 +41,11 @@ import java.util.HashSet;
* - how key previews should be shown and dismissed.
*/
public final class KeyPreviewChoreographer {
- // Free {@link TextView} pool that can be used for key preview.
- private final ArrayDeque<TextView> mFreeKeyPreviewTextViews = new ArrayDeque<>();
- // Map from {@link Key} to {@link TextView} that is currently being displayed as key preview.
- private final HashMap<Key,TextView> mShowingKeyPreviewTextViews = new HashMap<>();
+ // Free {@link KeyPreviewView} pool that can be used for key preview.
+ private final ArrayDeque<KeyPreviewView> mFreeKeyPreviewViews = new ArrayDeque<>();
+ // Map from {@link Key} to {@link KeyPreviewView} that is currently being displayed as key
+ // preview.
+ private final HashMap<Key,KeyPreviewView> mShowingKeyPreviewViews = new HashMap<>();
private final KeyPreviewDrawParams mParams;
@@ -57,32 +53,28 @@ public final class KeyPreviewChoreographer {
mParams = params;
}
- public TextView getKeyPreviewTextView(final Key key, final ViewGroup placerView) {
- TextView previewTextView = mShowingKeyPreviewTextViews.remove(key);
- if (previewTextView != null) {
- return previewTextView;
+ public KeyPreviewView getKeyPreviewView(final Key key, final ViewGroup placerView) {
+ KeyPreviewView keyPreviewView = mShowingKeyPreviewViews.remove(key);
+ if (keyPreviewView != null) {
+ return keyPreviewView;
}
- previewTextView = mFreeKeyPreviewTextViews.poll();
- if (previewTextView != null) {
- return previewTextView;
+ keyPreviewView = mFreeKeyPreviewViews.poll();
+ if (keyPreviewView != null) {
+ return keyPreviewView;
}
final Context context = placerView.getContext();
- if (mParams.mLayoutId != 0) {
- previewTextView = (TextView)LayoutInflater.from(context)
- .inflate(mParams.mLayoutId, null);
- } else {
- previewTextView = new TextView(context);
- }
- placerView.addView(previewTextView, ViewLayoutUtils.newLayoutParam(placerView, 0, 0));
- return previewTextView;
+ keyPreviewView = new KeyPreviewView(context, null /* attrs */);
+ keyPreviewView.setBackgroundResource(mParams.mPreviewBackgroundResId);
+ placerView.addView(keyPreviewView, ViewLayoutUtils.newLayoutParam(placerView, 0, 0));
+ return keyPreviewView;
}
public boolean isShowingKeyPreview(final Key key) {
- return mShowingKeyPreviewTextViews.containsKey(key);
+ return mShowingKeyPreviewViews.containsKey(key);
}
public void dismissAllKeyPreviews() {
- for (final Key key : new HashSet<>(mShowingKeyPreviewTextViews.keySet())) {
+ for (final Key key : new HashSet<>(mShowingKeyPreviewViews.keySet())) {
dismissKeyPreview(key, false /* withAnimation */);
}
}
@@ -91,11 +83,11 @@ public final class KeyPreviewChoreographer {
if (key == null) {
return;
}
- final TextView previewTextView = mShowingKeyPreviewTextViews.get(key);
- if (previewTextView == null) {
+ final KeyPreviewView keyPreviewView = mShowingKeyPreviewViews.get(key);
+ if (keyPreviewView == null) {
return;
}
- final Object tag = previewTextView.getTag();
+ final Object tag = keyPreviewView.getTag();
if (withAnimation) {
if (tag instanceof KeyPreviewAnimations) {
final KeyPreviewAnimations animation = (KeyPreviewAnimations)tag;
@@ -104,105 +96,76 @@ public final class KeyPreviewChoreographer {
}
}
// Dismiss preview without animation.
- mShowingKeyPreviewTextViews.remove(key);
+ mShowingKeyPreviewViews.remove(key);
if (tag instanceof Animator) {
((Animator)tag).cancel();
}
- previewTextView.setTag(null);
- previewTextView.setVisibility(View.INVISIBLE);
- mFreeKeyPreviewTextViews.add(previewTextView);
+ keyPreviewView.setTag(null);
+ keyPreviewView.setVisibility(View.INVISIBLE);
+ mFreeKeyPreviewViews.add(keyPreviewView);
}
- // Background state set
- private static final int[][][] KEY_PREVIEW_BACKGROUND_STATE_TABLE = {
- { // STATE_MIDDLE
- {},
- { R.attr.state_has_morekeys }
- },
- { // STATE_LEFT
- { R.attr.state_left_edge },
- { R.attr.state_left_edge, R.attr.state_has_morekeys }
- },
- { // STATE_RIGHT
- { R.attr.state_right_edge },
- { R.attr.state_right_edge, R.attr.state_has_morekeys }
- }
- };
- private static final int STATE_MIDDLE = 0;
- private static final int STATE_LEFT = 1;
- private static final int STATE_RIGHT = 2;
- private static final int STATE_NORMAL = 0;
- private static final int STATE_HAS_MOREKEYS = 1;
+ public void placeKeyPreviewAndShow(final Key key, final KeyboardIconsSet iconsSet,
+ final KeyDrawParams drawParams, final int keyboardViewWidth, final int[] keyboardOrigin,
+ final ViewGroup placerView, final boolean withAnimation) {
+ final KeyPreviewView keyPreviewView = getKeyPreviewView(key, placerView);
+ placeKeyPreview(
+ key, keyPreviewView, iconsSet, drawParams, keyboardViewWidth, keyboardOrigin);
+ showKeyPreview(key, keyPreviewView, withAnimation);
+ }
- public void placeKeyPreview(final Key key, final TextView previewTextView,
+ private void placeKeyPreview(final Key key, final KeyPreviewView keyPreviewView,
final KeyboardIconsSet iconsSet, final KeyDrawParams drawParams,
final int keyboardViewWidth, final int[] originCoords) {
- previewTextView.setTextColor(drawParams.mPreviewTextColor);
- final Drawable background = previewTextView.getBackground();
- final String label = key.getPreviewLabel();
- // What we show as preview should match what we show on a key top in onDraw().
- if (label != null) {
- // TODO Should take care of temporaryShiftLabel here.
- previewTextView.setCompoundDrawables(null, null, null, null);
- previewTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX,
- key.selectPreviewTextSize(drawParams));
- previewTextView.setTypeface(key.selectPreviewTypeface(drawParams));
- previewTextView.setText(label);
- } else {
- previewTextView.setCompoundDrawables(null, null, null, key.getPreviewIcon(iconsSet));
- previewTextView.setText(null);
- }
-
- previewTextView.measure(
+ keyPreviewView.setPreviewVisual(key, iconsSet, drawParams);
+ keyPreviewView.measure(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
- mParams.setGeometry(previewTextView);
- final int previewWidth = previewTextView.getMeasuredWidth();
+ mParams.setGeometry(keyPreviewView);
+ final int previewWidth = keyPreviewView.getMeasuredWidth();
final int previewHeight = mParams.mPreviewHeight;
final int keyDrawWidth = key.getDrawWidth();
// The key preview is horizontally aligned with the center of the visible part of the
// parent key. If it doesn't fit in this {@link KeyboardView}, it is moved inward to fit and
// the left/right background is used if such background is specified.
- final int statePosition;
+ final int keyPreviewPosition;
int previewX = key.getDrawX() - (previewWidth - keyDrawWidth) / 2
+ CoordinateUtils.x(originCoords);
if (previewX < 0) {
previewX = 0;
- statePosition = STATE_LEFT;
+ keyPreviewPosition = KeyPreviewView.POSITION_LEFT;
} else if (previewX > keyboardViewWidth - previewWidth) {
previewX = keyboardViewWidth - previewWidth;
- statePosition = STATE_RIGHT;
+ keyPreviewPosition = KeyPreviewView.POSITION_RIGHT;
} else {
- statePosition = STATE_MIDDLE;
+ keyPreviewPosition = KeyPreviewView.POSITION_MIDDLE;
}
+ final boolean hasMoreKeys = (key.getMoreKeys() != null);
+ keyPreviewView.setPreviewBackground(hasMoreKeys, keyPreviewPosition);
// The key preview is placed vertically above the top edge of the parent key with an
// arbitrary offset.
final int previewY = key.getY() - previewHeight + mParams.mPreviewOffset
+ CoordinateUtils.y(originCoords);
- if (background != null) {
- final int hasMoreKeys = (key.getMoreKeys() != null) ? STATE_HAS_MOREKEYS : STATE_NORMAL;
- background.setState(KEY_PREVIEW_BACKGROUND_STATE_TABLE[statePosition][hasMoreKeys]);
- }
ViewLayoutUtils.placeViewAt(
- previewTextView, previewX, previewY, previewWidth, previewHeight);
- previewTextView.setPivotX(previewWidth / 2.0f);
- previewTextView.setPivotY(previewHeight);
+ keyPreviewView, previewX, previewY, previewWidth, previewHeight);
+ keyPreviewView.setPivotX(previewWidth / 2.0f);
+ keyPreviewView.setPivotY(previewHeight);
}
- public void showKeyPreview(final Key key, final TextView previewTextView,
+ private void showKeyPreview(final Key key, final KeyPreviewView keyPreviewView,
final boolean withAnimation) {
if (!withAnimation) {
- previewTextView.setVisibility(View.VISIBLE);
- mShowingKeyPreviewTextViews.put(key, previewTextView);
+ keyPreviewView.setVisibility(View.VISIBLE);
+ mShowingKeyPreviewViews.put(key, keyPreviewView);
return;
}
// Show preview with animation.
- final Animator showUpAnimation = createShowUpAniation(key, previewTextView);
- final Animator dismissAnimation = createDismissAnimation(key, previewTextView);
+ final Animator showUpAnimation = createShowUpAniation(key, keyPreviewView);
+ final Animator dismissAnimation = createDismissAnimation(key, keyPreviewView);
final KeyPreviewAnimations animation = new KeyPreviewAnimations(
showUpAnimation, dismissAnimation);
- previewTextView.setTag(animation);
+ keyPreviewView.setTag(animation);
animation.startShowUp();
}
@@ -212,13 +175,13 @@ public final class KeyPreviewChoreographer {
private static final DecelerateInterpolator DECELERATE_INTERPOLATOR =
new DecelerateInterpolator();
- private Animator createShowUpAniation(final Key key, final TextView previewTextView) {
+ private Animator createShowUpAniation(final Key key, final KeyPreviewView keyPreviewView) {
// TODO: Optimization for no scale animation and no duration.
final ObjectAnimator scaleXAnimation = ObjectAnimator.ofFloat(
- previewTextView, View.SCALE_X, mParams.getShowUpStartScale(),
+ keyPreviewView, View.SCALE_X, mParams.getShowUpStartScale(),
KEY_PREVIEW_SHOW_UP_END_SCALE);
final ObjectAnimator scaleYAnimation = ObjectAnimator.ofFloat(
- previewTextView, View.SCALE_Y, mParams.getShowUpStartScale(),
+ keyPreviewView, View.SCALE_Y, mParams.getShowUpStartScale(),
KEY_PREVIEW_SHOW_UP_END_SCALE);
final AnimatorSet showUpAnimation = new AnimatorSet();
showUpAnimation.play(scaleXAnimation).with(scaleYAnimation);
@@ -227,18 +190,18 @@ public final class KeyPreviewChoreographer {
showUpAnimation.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(final Animator animation) {
- showKeyPreview(key, previewTextView, false /* withAnimation */);
+ showKeyPreview(key, keyPreviewView, false /* withAnimation */);
}
});
return showUpAnimation;
}
- private Animator createDismissAnimation(final Key key, final TextView previewTextView) {
+ private Animator createDismissAnimation(final Key key, final KeyPreviewView keyPreviewView) {
// TODO: Optimization for no scale animation and no duration.
final ObjectAnimator scaleXAnimation = ObjectAnimator.ofFloat(
- previewTextView, View.SCALE_X, mParams.getDismissEndScale());
+ keyPreviewView, View.SCALE_X, mParams.getDismissEndScale());
final ObjectAnimator scaleYAnimation = ObjectAnimator.ofFloat(
- previewTextView, View.SCALE_Y, mParams.getDismissEndScale());
+ keyPreviewView, View.SCALE_Y, mParams.getDismissEndScale());
final AnimatorSet dismissAnimation = new AnimatorSet();
dismissAnimation.play(scaleXAnimation).with(scaleYAnimation);
final int dismissDuration = Math.min(
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewDrawParams.java b/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewDrawParams.java
index 37e5c889d..68c9831fa 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewDrawParams.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewDrawParams.java
@@ -23,9 +23,9 @@ import com.android.inputmethod.latin.R;
public final class KeyPreviewDrawParams {
// XML attributes of {@link MainKeyboardView}.
- public final int mLayoutId;
public final int mPreviewOffset;
public final int mPreviewHeight;
+ public final int mPreviewBackgroundResId;
private int mShowUpDuration;
private int mDismissDuration;
private float mShowUpStartScale;
@@ -63,13 +63,10 @@ public final class KeyPreviewDrawParams {
R.styleable.MainKeyboardView_keyPreviewOffset, 0);
mPreviewHeight = mainKeyboardViewAttr.getDimensionPixelSize(
R.styleable.MainKeyboardView_keyPreviewHeight, 0);
+ mPreviewBackgroundResId = mainKeyboardViewAttr.getResourceId(
+ R.styleable.MainKeyboardView_keyPreviewBackground, 0);
mLingerTimeout = mainKeyboardViewAttr.getInt(
R.styleable.MainKeyboardView_keyPreviewLingerTimeout, 0);
- mLayoutId = mainKeyboardViewAttr.getResourceId(
- R.styleable.MainKeyboardView_keyPreviewLayout, 0);
- if (mLayoutId == 0) {
- mShowPopup = false;
- }
}
public void setVisibleOffset(final int previewVisibleOffset) {
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewView.java b/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewView.java
new file mode 100644
index 000000000..360faf829
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewView.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.keyboard.internal;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.widget.TextView;
+
+import com.android.inputmethod.keyboard.Key;
+import com.android.inputmethod.latin.R;
+
+/**
+ * The pop up key preview view.
+ */
+public class KeyPreviewView extends TextView {
+ public static final int POSITION_MIDDLE = 0;
+ public static final int POSITION_LEFT = 1;
+ public static final int POSITION_RIGHT = 2;
+
+ public KeyPreviewView(final Context context, final AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public KeyPreviewView(final Context context, final AttributeSet attrs, final int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ setGravity(Gravity.CENTER);
+ }
+
+ public void setPreviewVisual(final Key key, final KeyboardIconsSet iconsSet,
+ final KeyDrawParams drawParams) {
+ // What we show as preview should match what we show on a key top in onDraw().
+ final int iconId = key.getIconId();
+ if (iconId != KeyboardIconsSet.ICON_UNDEFINED) {
+ setCompoundDrawables(null, null, null, key.getPreviewIcon(iconsSet));
+ setText(null);
+ return;
+ }
+
+ setCompoundDrawables(null, null, null, null);
+ setTextColor(drawParams.mPreviewTextColor);
+ setTextSize(TypedValue.COMPLEX_UNIT_PX, key.selectPreviewTextSize(drawParams));
+ setTypeface(key.selectPreviewTypeface(drawParams));
+ // TODO Should take care of temporaryShiftLabel here.
+ setText(key.getPreviewLabel());
+ }
+
+ // Background state set
+ private static final int[][][] KEY_PREVIEW_BACKGROUND_STATE_TABLE = {
+ { // POSITION_MIDDLE
+ {},
+ { R.attr.state_has_morekeys }
+ },
+ { // POSITION_LEFT
+ { R.attr.state_left_edge },
+ { R.attr.state_left_edge, R.attr.state_has_morekeys }
+ },
+ { // POSITION_RIGHT
+ { R.attr.state_right_edge },
+ { R.attr.state_right_edge, R.attr.state_has_morekeys }
+ }
+ };
+ private static final int STATE_NORMAL = 0;
+ private static final int STATE_HAS_MOREKEYS = 1;
+
+ public void setPreviewBackground(final boolean hasMoreKeys, final int position) {
+ final Drawable background = getBackground();
+ if (background == null) {
+ return;
+ }
+ final int hasMoreKeysState = hasMoreKeys ? STATE_HAS_MOREKEYS : STATE_NORMAL;
+ background.setState(KEY_PREVIEW_BACKGROUND_STATE_TABLE[position][hasMoreKeysState]);
+ }
+}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/SlidingKeyInputDrawingPreview.java b/java/src/com/android/inputmethod/keyboard/internal/SlidingKeyInputDrawingPreview.java
index 76cb89160..ef4c74d61 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/SlidingKeyInputDrawingPreview.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/SlidingKeyInputDrawingPreview.java
@@ -20,7 +20,6 @@ import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
-import android.view.View;
import com.android.inputmethod.keyboard.PointerTracker;
import com.android.inputmethod.latin.R;
@@ -28,6 +27,11 @@ import com.android.inputmethod.latin.utils.CoordinateUtils;
/**
* Draw rubber band preview graphics during sliding key input.
+ *
+ * @attr ref R.styleable#MainKeyboardView_slidingKeyInputPreviewColor
+ * @attr ref R.styleable#MainKeyboardView_slidingKeyInputPreviewWidth
+ * @attr ref R.styleable#MainKeyboardView_slidingKeyInputPreviewBodyRatio
+ * @attr ref R.styleable#MainKeyboardView_slidingKeyInputPreviewShadowRatio
*/
public final class SlidingKeyInputDrawingPreview extends AbstractDrawingPreview {
private final float mPreviewBodyRadius;
@@ -40,9 +44,7 @@ public final class SlidingKeyInputDrawingPreview extends AbstractDrawingPreview
private final RoundedLine mRoundedLine = new RoundedLine();
private final Paint mPaint = new Paint();
- public SlidingKeyInputDrawingPreview(final View drawingView,
- final TypedArray mainKeyboardViewAttr) {
- super(drawingView);
+ public SlidingKeyInputDrawingPreview(final TypedArray mainKeyboardViewAttr) {
final int previewColor = mainKeyboardViewAttr.getColor(
R.styleable.MainKeyboardView_slidingKeyInputPreviewColor, 0);
final float previewRadius = mainKeyboardViewAttr.getDimension(
@@ -69,7 +71,7 @@ public final class SlidingKeyInputDrawingPreview extends AbstractDrawingPreview
public void dismissSlidingKeyInputPreview() {
mShowsSlidingKeyInputPreview = false;
- getDrawingView().invalidate();
+ invalidateDrawingView();
}
/**
@@ -99,6 +101,6 @@ public final class SlidingKeyInputDrawingPreview extends AbstractDrawingPreview
tracker.getDownCoordinates(mPreviewFrom);
tracker.getLastCoordinates(mPreviewTo);
mShowsSlidingKeyInputPreview = true;
- getDrawingView().invalidate();
+ invalidateDrawingView();
}
}
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index 543f74fc4..42105e2c3 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -28,7 +28,6 @@ import com.android.inputmethod.latin.makedict.FormatSpec;
import com.android.inputmethod.latin.makedict.FormatSpec.DictionaryOptions;
import com.android.inputmethod.latin.makedict.UnsupportedFormatException;
import com.android.inputmethod.latin.makedict.WordProperty;
-import com.android.inputmethod.latin.settings.NativeSuggestOptions;
import com.android.inputmethod.latin.utils.BinaryDictionaryUtils;
import com.android.inputmethod.latin.utils.FileUtils;
import com.android.inputmethod.latin.utils.JniUtils;
@@ -49,10 +48,6 @@ import java.util.Map;
public final class BinaryDictionary extends Dictionary {
private static final String TAG = BinaryDictionary.class.getSimpleName();
- // Must be equal to MAX_WORD_LENGTH in native/jni/src/defines.h
- private static final int MAX_WORD_LENGTH = Constants.DICTIONARY_MAX_WORD_LENGTH;
- // Must be equal to MAX_RESULTS in native/jni/src/defines.h
- private static final int MAX_RESULTS = 18;
// The cutoff returned by native for auto-commit confidence.
// Must be equal to CONFIDENCE_TO_AUTO_COMMIT in native/jni/src/defines.h
private static final int CONFIDENCE_TO_AUTO_COMMIT = 1000000;
@@ -88,21 +83,10 @@ public final class BinaryDictionary extends Dictionary {
private final Locale mLocale;
private final long mDictSize;
private final String mDictFilePath;
+ private final boolean mUseFullEditDistance;
private final boolean mIsUpdatable;
private boolean mHasUpdated;
- private final int[] mInputCodePoints = new int[MAX_WORD_LENGTH];
- private final int[] mOutputSuggestionCount = new int[1];
- private final int[] mOutputCodePoints = new int[MAX_WORD_LENGTH * MAX_RESULTS];
- private final int[] mSpaceIndices = new int[MAX_RESULTS];
- private final int[] mOutputScores = new int[MAX_RESULTS];
- private final int[] mOutputTypes = new int[MAX_RESULTS];
- // Only one result is ever used
- private final int[] mOutputAutoCommitFirstWordConfidence = new int[1];
- private final float[] mInputOutputLanguageWeight = new float[1];
-
- private final NativeSuggestOptions mNativeSuggestOptions = new NativeSuggestOptions();
-
private final SparseArray<DicTraverseSession> mDicTraverseSessions = new SparseArray<>();
// TODO: There should be a way to remove used DicTraverseSession objects from
@@ -136,7 +120,7 @@ public final class BinaryDictionary extends Dictionary {
mDictFilePath = filename;
mIsUpdatable = isUpdatable;
mHasUpdated = false;
- mNativeSuggestOptions.setUseFullEditDistance(useFullEditDistance);
+ mUseFullEditDistance = useFullEditDistance;
loadDictionary(filename, offset, length, isUpdatable);
}
@@ -148,7 +132,6 @@ public final class BinaryDictionary extends Dictionary {
* @param formatVersion the format version of the dictionary
* @param attributeMap the attributes of the dictionary
*/
- @UsedForTesting
public BinaryDictionary(final String filename, final boolean useFullEditDistance,
final Locale locale, final String dictType, final long formatVersion,
final Map<String, String> attributeMap) {
@@ -159,7 +142,7 @@ public final class BinaryDictionary extends Dictionary {
// On memory dictionary is always updatable.
mIsUpdatable = true;
mHasUpdated = false;
- mNativeSuggestOptions.setUseFullEditDistance(useFullEditDistance);
+ mUseFullEditDistance = useFullEditDistance;
final String[] keyArray = new String[attributeMap.size()];
final String[] valueArray = new String[attributeMap.size()];
int index = 0;
@@ -274,8 +257,8 @@ public final class BinaryDictionary extends Dictionary {
if (!isValidDictionary()) {
return null;
}
-
- Arrays.fill(mInputCodePoints, Constants.NOT_A_CODE);
+ final DicTraverseSession session = getTraverseSession(sessionId);
+ Arrays.fill(session.mInputCodePoints, Constants.NOT_A_CODE);
// TODO: toLowerCase in the native code
final int[] prevWordCodePointArray = (null == prevWordsInfo.mPrevWord)
? null : StringUtils.toCodePointArray(prevWordsInfo.mPrevWord);
@@ -284,47 +267,50 @@ public final class BinaryDictionary extends Dictionary {
final int inputSize;
if (!isGesture) {
inputSize = composer.copyCodePointsExceptTrailingSingleQuotesAndReturnCodePointCount(
- mInputCodePoints);
+ session.mInputCodePoints);
if (inputSize < 0) {
return null;
}
} else {
inputSize = inputPointers.getPointerSize();
}
-
- mNativeSuggestOptions.setIsGesture(isGesture);
- mNativeSuggestOptions.setBlockOffensiveWords(blockOffensiveWords);
- mNativeSuggestOptions.setAdditionalFeaturesOptions(additionalFeaturesOptions);
+ session.mNativeSuggestOptions.setUseFullEditDistance(mUseFullEditDistance);
+ session.mNativeSuggestOptions.setIsGesture(isGesture);
+ session.mNativeSuggestOptions.setBlockOffensiveWords(blockOffensiveWords);
+ session.mNativeSuggestOptions.setAdditionalFeaturesOptions(additionalFeaturesOptions);
if (inOutLanguageWeight != null) {
- mInputOutputLanguageWeight[0] = inOutLanguageWeight[0];
+ session.mInputOutputLanguageWeight[0] = inOutLanguageWeight[0];
} else {
- mInputOutputLanguageWeight[0] = Dictionary.NOT_A_LANGUAGE_WEIGHT;
+ session.mInputOutputLanguageWeight[0] = Dictionary.NOT_A_LANGUAGE_WEIGHT;
}
// proximityInfo and/or prevWordForBigrams may not be null.
getSuggestionsNative(mNativeDict, proximityInfo.getNativeProximityInfo(),
getTraverseSession(sessionId).getSession(), inputPointers.getXCoordinates(),
inputPointers.getYCoordinates(), inputPointers.getTimes(),
- inputPointers.getPointerIds(), mInputCodePoints, inputSize,
- mNativeSuggestOptions.getOptions(), prevWordCodePointArray,
- prevWordsInfo.mIsBeginningOfSentence, mOutputSuggestionCount,
- mOutputCodePoints, mOutputScores, mSpaceIndices, mOutputTypes,
- mOutputAutoCommitFirstWordConfidence, mInputOutputLanguageWeight);
+ inputPointers.getPointerIds(), session.mInputCodePoints, inputSize,
+ session.mNativeSuggestOptions.getOptions(), prevWordCodePointArray,
+ prevWordsInfo.mIsBeginningOfSentence, session.mOutputSuggestionCount,
+ session.mOutputCodePoints, session.mOutputScores, session.mSpaceIndices,
+ session.mOutputTypes, session.mOutputAutoCommitFirstWordConfidence,
+ session.mInputOutputLanguageWeight);
if (inOutLanguageWeight != null) {
- inOutLanguageWeight[0] = mInputOutputLanguageWeight[0];
+ inOutLanguageWeight[0] = session.mInputOutputLanguageWeight[0];
}
- final int count = mOutputSuggestionCount[0];
+ final int count = session.mOutputSuggestionCount[0];
final ArrayList<SuggestedWordInfo> suggestions = new ArrayList<>();
for (int j = 0; j < count; ++j) {
- final int start = j * MAX_WORD_LENGTH;
+ final int start = j * Constants.DICTIONARY_MAX_WORD_LENGTH;
int len = 0;
- while (len < MAX_WORD_LENGTH && mOutputCodePoints[start + len] != 0) {
+ while (len < Constants.DICTIONARY_MAX_WORD_LENGTH
+ && session.mOutputCodePoints[start + len] != 0) {
++len;
}
if (len > 0) {
- suggestions.add(new SuggestedWordInfo(new String(mOutputCodePoints, start, len),
- mOutputScores[j], mOutputTypes[j], this /* sourceDict */,
- mSpaceIndices[j] /* indexOfTouchPointOfSecondWord */,
- mOutputAutoCommitFirstWordConfidence[0]));
+ suggestions.add(new SuggestedWordInfo(
+ new String(session.mOutputCodePoints, start, len),
+ session.mOutputScores[j], session.mOutputTypes[j], this /* sourceDict */,
+ session.mSpaceIndices[j] /* indexOfTouchPointOfSecondWord */,
+ session.mOutputAutoCommitFirstWordConfidence[0]));
}
}
return suggestions;
@@ -377,7 +363,7 @@ public final class BinaryDictionary extends Dictionary {
return null;
}
final int[] codePoints = StringUtils.toCodePointArray(word);
- final int[] outCodePoints = new int[MAX_WORD_LENGTH];
+ final int[] outCodePoints = new int[Constants.DICTIONARY_MAX_WORD_LENGTH];
final boolean[] outFlags = new boolean[FORMAT_WORD_PROPERTY_OUTPUT_FLAG_COUNT];
final int[] outProbabilityInfo =
new int[FORMAT_WORD_PROPERTY_OUTPUT_PROBABILITY_INFO_COUNT];
@@ -412,7 +398,7 @@ public final class BinaryDictionary extends Dictionary {
* If token is 0, this method newly starts iterating the dictionary.
*/
public GetNextWordPropertyResult getNextWordProperty(final int token) {
- final int[] codePoints = new int[MAX_WORD_LENGTH];
+ final int[] codePoints = new int[Constants.DICTIONARY_MAX_WORD_LENGTH];
final int nextToken = getNextWordNative(mNativeDict, token, codePoints);
final String word = StringUtils.getStringFromNullTerminatedCodePointArray(codePoints);
return new GetNextWordPropertyResult(getWordProperty(word), nextToken);
diff --git a/java/src/com/android/inputmethod/latin/DicTraverseSession.java b/java/src/com/android/inputmethod/latin/DicTraverseSession.java
index 8d295adee..8bbf426e5 100644
--- a/java/src/com/android/inputmethod/latin/DicTraverseSession.java
+++ b/java/src/com/android/inputmethod/latin/DicTraverseSession.java
@@ -16,6 +16,7 @@
package com.android.inputmethod.latin;
+import com.android.inputmethod.latin.settings.NativeSuggestOptions;
import com.android.inputmethod.latin.utils.JniUtils;
import java.util.Locale;
@@ -24,6 +25,20 @@ public final class DicTraverseSession {
static {
JniUtils.loadNativeLibrary();
}
+ // Must be equal to MAX_RESULTS in native/jni/src/defines.h
+ private static final int MAX_RESULTS = 18;
+ public final int[] mInputCodePoints = new int[Constants.DICTIONARY_MAX_WORD_LENGTH];
+ public final int[] mOutputSuggestionCount = new int[1];
+ public final int[] mOutputCodePoints =
+ new int[Constants.DICTIONARY_MAX_WORD_LENGTH * MAX_RESULTS];
+ public final int[] mSpaceIndices = new int[MAX_RESULTS];
+ public final int[] mOutputScores = new int[MAX_RESULTS];
+ public final int[] mOutputTypes = new int[MAX_RESULTS];
+ // Only one result is ever used
+ public final int[] mOutputAutoCommitFirstWordConfidence = new int[1];
+ public final float[] mInputOutputLanguageWeight = new float[1];
+
+ public final NativeSuggestOptions mNativeSuggestOptions = new NativeSuggestOptions();
private static native long setDicTraverseSessionNative(String locale, long dictSize);
private static native void initDicTraverseSessionNative(long nativeDicTraverseSession,
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java
index 4a28a242a..8c4870d08 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java
@@ -468,15 +468,19 @@ public class DictionaryFacilitator {
isValid, timeStampInSeconds, mDistracterFilter);
}
- public void cancelAddingUserHistory(final PrevWordsInfo prevWordsInfo,
- final String committedWord) {
- final ExpandableBinaryDictionary userHistoryDictionary =
- mDictionaries.getSubDict(Dictionary.TYPE_USER_HISTORY);
- if (userHistoryDictionary != null) {
- userHistoryDictionary.removeNgramDynamically(prevWordsInfo, committedWord);
+ private void removeWord(final String dictName, final String word) {
+ final ExpandableBinaryDictionary dictionary = mDictionaries.getSubDict(dictName);
+ if (dictionary != null) {
+ dictionary.removeUnigramEntryDynamically(word);
}
}
+ public void removeWordFromPersonalizedDicts(final String word) {
+ removeWord(Dictionary.TYPE_USER_HISTORY, word);
+ removeWord(Dictionary.TYPE_PERSONALIZATION, word);
+ removeWord(Dictionary.TYPE_CONTEXTUAL, word);
+ }
+
// TODO: Revise the way to fusion suggestion results.
public SuggestionResults getSuggestionResults(final WordComposer composer,
final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo,
diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
index b1966bffc..6199c7dfe 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
@@ -311,6 +311,27 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
}
/**
+ * Dynamically remove the unigram entry from the dictionary.
+ */
+ public void removeUnigramEntryDynamically(final String word) {
+ reloadDictionaryIfRequired();
+ asyncExecuteTaskWithWriteLock(new Runnable() {
+ @Override
+ public void run() {
+ if (mBinaryDictionary == null) {
+ return;
+ }
+ runGCIfRequiredLocked(true /* mindsBlockByGC */);
+ if (!mBinaryDictionary.removeUnigramEntry(word)) {
+ if (DEBUG) {
+ Log.i(TAG, "Cannot remove unigram entry: " + word);
+ }
+ }
+ }
+ });
+ }
+
+ /**
* Adds n-gram information of a word to the dictionary. May overwrite an existing entry.
*/
public void addNgramEntry(final PrevWordsInfo prevWordsInfo, final String word,
@@ -341,6 +362,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
/**
* Dynamically remove the n-gram entry in the dictionary.
*/
+ @UsedForTesting
public void removeNgramDynamically(final PrevWordsInfo prevWordsInfo, final String word) {
reloadDictionaryIfRequired();
asyncExecuteTaskWithWriteLock(new Runnable() {
diff --git a/java/src/com/android/inputmethod/latin/InputAttributes.java b/java/src/com/android/inputmethod/latin/InputAttributes.java
index e1ae3dfe3..ebe436128 100644
--- a/java/src/com/android/inputmethod/latin/InputAttributes.java
+++ b/java/src/com/android/inputmethod/latin/InputAttributes.java
@@ -41,6 +41,7 @@ public final class InputAttributes {
final public boolean mShouldShowSuggestions;
final public boolean mApplicationSpecifiedCompletionOn;
final public boolean mShouldInsertSpacesAutomatically;
+ final public boolean mShouldShowVoiceInputKey;
final private int mInputType;
final private EditorInfo mEditorInfo;
final private String mPackageNameForPrivateImeOptions;
@@ -74,6 +75,7 @@ public final class InputAttributes {
mInputTypeNoAutoCorrect = false;
mApplicationSpecifiedCompletionOn = false;
mShouldInsertSpacesAutomatically = false;
+ mShouldShowVoiceInputKey = false;
return;
}
// inputClass == InputType.TYPE_CLASS_TEXT
@@ -99,6 +101,12 @@ public final class InputAttributes {
mShouldInsertSpacesAutomatically = InputTypeUtils.isAutoSpaceFriendlyType(inputType);
+ final boolean noMicrophone = mIsPasswordField
+ || InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS == variation
+ || InputType.TYPE_TEXT_VARIATION_URI == variation
+ || hasNoMicrophoneKeyOption();
+ mShouldShowVoiceInputKey = !noMicrophone;
+
// If it's a browser edit field and auto correct is not ON explicitly, then
// disable auto correction, but keep suggestions on.
// If NO_SUGGESTIONS is set, don't do prediction.
@@ -119,7 +127,7 @@ public final class InputAttributes {
return editorInfo.inputType == mInputType;
}
- public boolean hasNoMicrophoneKeyOption() {
+ private boolean hasNoMicrophoneKeyOption() {
@SuppressWarnings("deprecation")
final boolean deprecatedNoMicrophone = InputAttributes.inPrivateImeOptions(
null, NO_MICROPHONE_COMPAT, mEditorInfo);
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index de95b9787..9462c385d 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -884,6 +884,9 @@ public final class InputLogic {
final String rejectedSuggestion = mWordComposer.getTypedWord();
mWordComposer.reset();
mWordComposer.setRejectedBatchModeSuggestion(rejectedSuggestion);
+ if (!TextUtils.isEmpty(rejectedSuggestion)) {
+ mDictionaryFacilitator.removeWordFromPersonalizedDicts(rejectedSuggestion);
+ }
} else {
mWordComposer.processEvent(inputTransaction.mEvent);
}
@@ -1187,6 +1190,8 @@ public final class InputLogic {
Log.w(TAG, "Called updateSuggestionsOrPredictions but suggestions were not "
+ "requested!");
}
+ // Clear the suggestions strip.
+ mSuggestionStripViewAccessor.showSuggestionStrip(SuggestedWords.EMPTY);
return;
}
@@ -1363,7 +1368,6 @@ public final class InputLogic {
* @param inputTransaction The transaction in progress.
*/
private void revertCommit(final InputTransaction inputTransaction) {
- final PrevWordsInfo prevWordsInfo = mLastComposedWord.mPrevWordsInfo;
final CharSequence originallyTypedWord = mLastComposedWord.mTypedWord;
final CharSequence committedWord = mLastComposedWord.mCommittedWord;
final String committedWordString = committedWord.toString();
@@ -1385,8 +1389,8 @@ public final class InputLogic {
}
}
mConnection.deleteSurroundingText(deleteLength, 0);
- if (!TextUtils.isEmpty(prevWordsInfo.mPrevWord) && !TextUtils.isEmpty(committedWord)) {
- mDictionaryFacilitator.cancelAddingUserHistory(prevWordsInfo, committedWordString);
+ if (!TextUtils.isEmpty(committedWord)) {
+ mDictionaryFacilitator.removeWordFromPersonalizedDicts(committedWordString);
}
final String stringToCommit = originallyTypedWord + mLastComposedWord.mSeparatorString;
final SpannableString textToCommit = new SpannableString(stringToCommit);
diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
index 44104019b..8de5fed07 100644
--- a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
+++ b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
@@ -125,8 +125,7 @@ public final class SettingsValues {
mSlidingKeyInputPreviewEnabled = prefs.getBoolean(
DebugSettings.PREF_SLIDING_KEY_INPUT_PREVIEW, true);
mShowsVoiceInputKey = needsToShowVoiceInputKey(prefs, res)
- && !mInputAttributes.mIsPasswordField
- && !mInputAttributes.hasNoMicrophoneKeyOption()
+ && mInputAttributes.mShouldShowVoiceInputKey
&& SubtypeSwitcher.getInstance().isShortcutImeEnabled();
final String autoCorrectionThresholdRawValue = prefs.getString(
Settings.PREF_AUTO_CORRECTION_THRESHOLD,
diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
index 19b48f081..46f5cdee0 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
@@ -44,6 +44,7 @@ import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
+import com.android.inputmethod.accessibility.AccessibilityUtils;
import com.android.inputmethod.latin.LatinImeLogger;
import com.android.inputmethod.latin.PunctuationSuggestions;
import com.android.inputmethod.latin.R;
@@ -386,6 +387,12 @@ final class SuggestionStripLayoutHelper {
final float scaleX = getTextScaleX(word, width, wordView.getPaint());
wordView.setText(text); // TextView.setText() resets text scale x to 1.0.
wordView.setTextScaleX(Math.max(scaleX, MIN_TEXT_XSCALE));
+ // A <code>wordView</code> should be disabled when <code>word</code> is empty in order to
+ // make it unclickable.
+ // With accessibility touch exploration on, <code>wordView</code> should be enabled even
+ // when it is empty to avoid announcing as "disabled".
+ wordView.setEnabled(!TextUtils.isEmpty(word)
+ || AccessibilityUtils.getInstance().isTouchExplorationEnabled());
return wordView;
}
diff --git a/native/jni/Android.mk b/native/jni/Android.mk
index 47b5c3344..72f8f87e4 100644
--- a/native/jni/Android.mk
+++ b/native/jni/Android.mk
@@ -92,3 +92,6 @@ include $(LOCAL_PATH)/CleanupNativeFileList.mk
#################### Unit test on host environment
include $(LOCAL_PATH)/HostUnitTests.mk
+
+#################### Unit test on target environment
+include $(LOCAL_PATH)/TargetUnitTests.mk
diff --git a/native/jni/TargetUnitTests.mk b/native/jni/TargetUnitTests.mk
new file mode 100644
index 000000000..12aae44ea
--- /dev/null
+++ b/native/jni/TargetUnitTests.mk
@@ -0,0 +1,55 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+######################################
+include $(CLEAR_VARS)
+
+include $(LOCAL_PATH)/NativeFileList.mk
+
+#################### Target library for unit test
+LATIN_IME_SRC_DIR := src
+LOCAL_CFLAGS += -std=c++11 -Wno-unused-parameter -Wno-unused-function
+LOCAL_CLANG := true
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(LATIN_IME_SRC_DIR)
+LOCAL_MODULE := liblatinime_target_static_for_unittests
+LOCAL_MODULE_TAGS := optional
+LOCAL_SRC_FILES := $(addprefix $(LATIN_IME_SRC_DIR)/, $(LATIN_IME_CORE_SRC_FILES))
+# Here intentionally use libc++_shared rather than libc++_static because
+# $(BUILD_NATIVE_TEST) has not yet supported libc++_static.
+LOCAL_SDK_VERSION := 14
+LOCAL_NDK_STL_VARIANT := c++_shared
+include $(BUILD_STATIC_LIBRARY)
+
+#################### Target native tests
+include $(CLEAR_VARS)
+LATIN_IME_TEST_SRC_DIR := tests
+LOCAL_CFLAGS += -std=c++11 -Wno-unused-parameter -Wno-unused-function
+LOCAL_CLANG := true
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(LATIN_IME_SRC_DIR)
+LOCAL_MODULE := liblatinime_target_unittests
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := \
+ $(addprefix $(LATIN_IME_TEST_SRC_DIR)/, $(LATIN_IME_CORE_TEST_FILES))
+LOCAL_STATIC_LIBRARIES += liblatinime_target_static_for_unittests
+# Here intentionally include external/libcxx/libcxx.mk rather because
+# $(BUILD_NATIVE_TEST) fails when LOCAL_NDK_STL_VARIANT is specified.
+include external/libcxx/libcxx.mk
+include $(BUILD_NATIVE_TEST)
+
+#################### Clean up the tmp vars
+LATIN_IME_SRC_DIR :=
+LATIN_IME_TEST_SRC_DIR :=
+include $(LOCAL_PATH)/CleanupNativeFileList.mk
diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
index 6e2219d87..c2cd2addd 100644
--- a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
+++ b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
@@ -304,17 +304,18 @@ static jint latinime_BinaryDictionary_getNextWord(JNIEnv *env, jclass clazz,
jlong dict, jint token, jintArray outCodePoints) {
Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
if (!dictionary) return 0;
- const jsize outCodePointsLength = env->GetArrayLength(outCodePoints);
- if (outCodePointsLength != MAX_WORD_LENGTH) {
- AKLOGE("Invalid outCodePointsLength: %d", outCodePointsLength);
+ const jsize codePointBufSize = env->GetArrayLength(outCodePoints);
+ if (codePointBufSize != MAX_WORD_LENGTH) {
+ AKLOGE("Invalid outCodePointsLength: %d", codePointBufSize);
ASSERT(false);
return 0;
}
- int wordCodePoints[outCodePointsLength];
- memset(wordCodePoints, 0, sizeof(wordCodePoints));
- const int nextToken = dictionary->getNextWordAndNextToken(token, wordCodePoints);
+ int wordCodePoints[codePointBufSize];
+ int wordCodePointCount = 0;
+ const int nextToken = dictionary->getNextWordAndNextToken(token, wordCodePoints,
+ &wordCodePointCount);
JniDataUtils::outputCodePoints(env, outCodePoints, 0 /* start */,
- MAX_WORD_LENGTH /* maxLength */, wordCodePoints, outCodePointsLength,
+ MAX_WORD_LENGTH /* maxLength */, wordCodePoints, wordCodePointCount,
false /* needsNullTermination */);
return nextToken;
}
@@ -555,12 +556,13 @@ static bool latinime_BinaryDictionary_migrateNative(JNIEnv *env, jclass clazz, j
// TODO: Migrate historical information.
int wordCodePoints[MAX_WORD_LENGTH];
+ int wordCodePointCount = 0;
int token = 0;
// Add unigrams.
do {
- token = dictionary->getNextWordAndNextToken(token, wordCodePoints);
- const int wordLength = CharUtils::getCodePointCount(MAX_WORD_LENGTH, wordCodePoints);
- const WordProperty wordProperty = dictionary->getWordProperty(wordCodePoints, wordLength);
+ token = dictionary->getNextWordAndNextToken(token, wordCodePoints, &wordCodePointCount);
+ const WordProperty wordProperty = dictionary->getWordProperty(wordCodePoints,
+ wordCodePointCount);
if (dictionaryStructureWithBufferPolicy->needsToRunGC(true /* mindsBlockByGC */)) {
dictionaryStructureWithBufferPolicy = runGCAndGetNewStructurePolicy(
std::move(dictionaryStructureWithBufferPolicy), dictFilePathChars);
@@ -569,8 +571,8 @@ static bool latinime_BinaryDictionary_migrateNative(JNIEnv *env, jclass clazz, j
return false;
}
}
- if (!dictionaryStructureWithBufferPolicy->addUnigramEntry(wordCodePoints, wordLength,
- wordProperty.getUnigramProperty())) {
+ if (!dictionaryStructureWithBufferPolicy->addUnigramEntry(wordCodePoints,
+ wordCodePointCount, wordProperty.getUnigramProperty())) {
LogUtils::logToJava(env, "Cannot add unigram to the new dict.");
return false;
}
@@ -578,9 +580,9 @@ static bool latinime_BinaryDictionary_migrateNative(JNIEnv *env, jclass clazz, j
// Add bigrams.
do {
- token = dictionary->getNextWordAndNextToken(token, wordCodePoints);
- const int wordLength = CharUtils::getCodePointCount(MAX_WORD_LENGTH, wordCodePoints);
- const WordProperty wordProperty = dictionary->getWordProperty(wordCodePoints, wordLength);
+ token = dictionary->getNextWordAndNextToken(token, wordCodePoints, &wordCodePointCount);
+ const WordProperty wordProperty = dictionary->getWordProperty(wordCodePoints,
+ wordCodePointCount);
if (dictionaryStructureWithBufferPolicy->needsToRunGC(true /* mindsBlockByGC */)) {
dictionaryStructureWithBufferPolicy = runGCAndGetNewStructurePolicy(
std::move(dictionaryStructureWithBufferPolicy), dictFilePathChars);
@@ -589,8 +591,8 @@ static bool latinime_BinaryDictionary_migrateNative(JNIEnv *env, jclass clazz, j
return false;
}
}
- const PrevWordsInfo prevWordsInfo(wordCodePoints, wordLength,
- false /* isStartOfSentence */);
+ const PrevWordsInfo prevWordsInfo(wordCodePoints, wordCodePointCount,
+ false /* isBeginningOfSentence */);
for (const BigramProperty &bigramProperty : *wordProperty.getBigramProperties()) {
if (!dictionaryStructureWithBufferPolicy->addNgramEntry(&prevWordsInfo,
&bigramProperty)) {
diff --git a/native/jni/run-tests.sh b/native/jni/run-tests.sh
index 5b60e0d65..3da45270d 100755
--- a/native/jni/run-tests.sh
+++ b/native/jni/run-tests.sh
@@ -13,17 +13,56 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+function usage() {
+ echo "usage: source run-tests.sh [--host] [--target] [-h] [--help]" 1>&2
+ echo " --host: run test on the host environment" 1>&2
+ echo " --no-host: skip host test" 1>&2
+ echo " --target: run test on the target environment" 1>&2
+ echo " --no-target: skip target device test" 1>&2
+}
+
+# check script arguments
if [[ $(type -t mmm) != function ]]; then
-echo "Usage:" 1>&2
-echo " source $0" 1>&2
-echo " or" 1>&2
-echo " . $0" 1>&2
+usage
if [[ ${BASH_SOURCE[0]} != $0 ]]; then return; else exit 1; fi
fi
+show_usage=no
+enable_host_test=yes
+enable_target_device_test=no
+while [ "$1" != "" ]
+ do
+ case "$1" in
+ "-h") show_usage=yes;;
+ "--help") show_usage=yes;;
+ "--target") enable_target_device_test=yes;;
+ "--no-target") enable_target_device_test=no;;
+ "--host") enable_host_test=yes;;
+ "--no-host") enable_host_test=no;;
+ esac
+ shift
+done
+
+if [[ $show_usage == yes ]]; then
+ usage
+ if [[ ${BASH_SOURCE[0]} != $0 ]]; then return; else exit 1; fi
+fi
+
+target_test_name=liblatinime_target_unittests
+host_test_name=liblatinime_host_unittests
+
pushd $PWD > /dev/null
cd $(gettop)
mmm -j16 packages/inputmethods/LatinIME/native/jni || \
- make -j16 liblatinime_host_unittests
-${ANDROID_HOST_OUT}/bin/liblatinime_host_unittests
-popd > /dev/null \ No newline at end of file
+ make -j16 adb $target_test_name $host_test_name
+if [[ $enable_host_test == yes ]]; then
+ $ANDROID_HOST_OUT/bin/$host_test_name
+fi
+if [[ $enable_target_device_test == yes ]]; then
+ target_test_local=$ANDROID_PRODUCT_OUT/data/nativetest/$target_test_name/$target_test_name
+ target_test_device=/data/nativetest/$target_test_name/$target_test_name
+ adb push $target_test_local $target_test_device
+ adb shell $target_test_device
+ adb shell rm -rf $target_test_device
+fi
+popd > /dev/null
diff --git a/native/jni/src/suggest/core/dictionary/dictionary.cpp b/native/jni/src/suggest/core/dictionary/dictionary.cpp
index 0bcde2294..228260216 100644
--- a/native/jni/src/suggest/core/dictionary/dictionary.cpp
+++ b/native/jni/src/suggest/core/dictionary/dictionary.cpp
@@ -145,10 +145,11 @@ const WordProperty Dictionary::getWordProperty(const int *const codePoints,
codePoints, codePointCount);
}
-int Dictionary::getNextWordAndNextToken(const int token, int *const outCodePoints) {
+int Dictionary::getNextWordAndNextToken(const int token, int *const outCodePoints,
+ int *const outCodePointCount) {
TimeKeeper::setCurrentTime();
return mDictionaryStructureWithBufferPolicy->getNextWordAndNextToken(
- token, outCodePoints);
+ token, outCodePoints, outCodePointCount);
}
void Dictionary::logDictionaryInfo(JNIEnv *const env) const {
diff --git a/native/jni/src/suggest/core/dictionary/dictionary.h b/native/jni/src/suggest/core/dictionary/dictionary.h
index 542ba7291..247ee2421 100644
--- a/native/jni/src/suggest/core/dictionary/dictionary.h
+++ b/native/jni/src/suggest/core/dictionary/dictionary.h
@@ -103,7 +103,8 @@ class Dictionary {
// Method to iterate all words in the dictionary.
// The returned token has to be used to get the next word. If token is 0, this method newly
// starts iterating the dictionary.
- int getNextWordAndNextToken(const int token, int *const outCodePoints);
+ int getNextWordAndNextToken(const int token, int *const outCodePoints,
+ int *const outCodePointCount);
const DictionaryStructureWithBufferPolicy *getDictionaryStructurePolicy() const {
return mDictionaryStructureWithBufferPolicy.get();
diff --git a/native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h b/native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h
index e2771f97c..b72601109 100644
--- a/native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h
+++ b/native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h
@@ -104,7 +104,8 @@ class DictionaryStructureWithBufferPolicy {
// Method to iterate all words in the dictionary.
// The returned token has to be used to get the next word. If token is 0, this method newly
// starts iterating the dictionary.
- virtual int getNextWordAndNextToken(const int token, int *const outCodePoints) = 0;
+ virtual int getNextWordAndNextToken(const int token, int *const outCodePoints,
+ int *const outCodePointCount) = 0;
virtual bool isCorrupted() const = 0;
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_reader.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_reader.h
index 4032a67fa..1999a51a6 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_reader.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_reader.h
@@ -58,7 +58,7 @@ class Ver4PatriciaTrieNodeReader : public PtNodeReader {
~Ver4PatriciaTrieNodeReader() {}
- virtual const PtNodeParams fetchNodeInfoInBufferFromPtNodePos(const int ptNodePos) const {
+ virtual const PtNodeParams fetchPtNodeParamsInBufferFromPtNodePos(const int ptNodePos) const {
return fetchPtNodeInfoFromBufferAndProcessMovedPtNode(ptNodePos,
NOT_A_DICT_POS /* siblingNodePos */);
}
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 805820b05..9780ae048 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
@@ -135,7 +135,7 @@ int Ver4PatriciaTriePolicy::getUnigramProbabilityOfPtNode(const int ptNodePos) c
if (ptNodePos == NOT_A_DICT_POS) {
return NOT_A_PROBABILITY;
}
- const PtNodeParams ptNodeParams(mNodeReader.fetchNodeInfoInBufferFromPtNodePos(ptNodePos));
+ const PtNodeParams ptNodeParams(mNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos));
if (ptNodeParams.isDeleted() || ptNodeParams.isBlacklisted() || ptNodeParams.isNotAWord()) {
return NOT_A_PROBABILITY;
}
@@ -146,7 +146,7 @@ int Ver4PatriciaTriePolicy::getShortcutPositionOfPtNode(const int ptNodePos) con
if (ptNodePos == NOT_A_DICT_POS) {
return NOT_A_DICT_POS;
}
- const PtNodeParams ptNodeParams(mNodeReader.fetchNodeInfoInBufferFromPtNodePos(ptNodePos));
+ const PtNodeParams ptNodeParams(mNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos));
if (ptNodeParams.isDeleted()) {
return NOT_A_DICT_POS;
}
@@ -158,7 +158,7 @@ int Ver4PatriciaTriePolicy::getBigramsPositionOfPtNode(const int ptNodePos) cons
if (ptNodePos == NOT_A_DICT_POS) {
return NOT_A_DICT_POS;
}
- const PtNodeParams ptNodeParams(mNodeReader.fetchNodeInfoInBufferFromPtNodePos(ptNodePos));
+ const PtNodeParams ptNodeParams(mNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos));
if (ptNodeParams.isDeleted()) {
return NOT_A_DICT_POS;
}
@@ -410,7 +410,7 @@ const WordProperty Ver4PatriciaTriePolicy::getWordProperty(const int *const code
AKLOGE("getWordProperty is called for invalid word.");
return WordProperty();
}
- const PtNodeParams ptNodeParams = mNodeReader.fetchNodeInfoInBufferFromPtNodePos(ptNodePos);
+ const PtNodeParams ptNodeParams = mNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos);
std::vector<int> codePointVector(ptNodeParams.getCodePoints(),
ptNodeParams.getCodePoints() + ptNodeParams.getCodePointCount());
const ProbabilityEntry probabilityEntry =
@@ -478,10 +478,9 @@ const WordProperty Ver4PatriciaTriePolicy::getWordProperty(const int *const code
return WordProperty(&codePointVector, &unigramProperty, &bigrams);
}
-int Ver4PatriciaTriePolicy::getNextWordAndNextToken(const int token, int *const outCodePoints) {
- // TODO: Return code point count like other methods.
- // Null termination.
- outCodePoints[0] = 0;
+int Ver4PatriciaTriePolicy::getNextWordAndNextToken(const int token, int *const outCodePoints,
+ int *const outCodePointCount) {
+ *outCodePointCount = 0;
if (token == 0) {
mTerminalPtNodePositionsForIteratingWords.clear();
DynamicPtReadingHelper::TraversePolicyToGetAllTerminalPtNodePositions traversePolicy(
@@ -498,13 +497,8 @@ int Ver4PatriciaTriePolicy::getNextWordAndNextToken(const int token, int *const
}
const int terminalPtNodePos = mTerminalPtNodePositionsForIteratingWords[token];
int unigramProbability = NOT_A_PROBABILITY;
- const int codePointCount = getCodePointsAndProbabilityAndReturnCodePointCount(
+ *outCodePointCount = getCodePointsAndProbabilityAndReturnCodePointCount(
terminalPtNodePos, MAX_WORD_LENGTH, outCodePoints, &unigramProbability);
- if (codePointCount < MAX_WORD_LENGTH) {
- // Null termination. outCodePoints have to be null terminated or contain MAX_WORD_LENGTH
- // code points.
- outCodePoints[codePointCount] = 0;
- }
const int nextToken = token + 1;
if (nextToken >= terminalPtNodePositionsVectorSize) {
// All words have been iterated.
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 2e948ac4a..16b1bd2c1 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
@@ -134,7 +134,8 @@ class Ver4PatriciaTriePolicy : public DictionaryStructureWithBufferPolicy {
const WordProperty getWordProperty(const int *const codePoints,
const int codePointCount) const;
- int getNextWordAndNextToken(const int token, int *const outCodePoints);
+ int getNextWordAndNextToken(const int token, int *const outCodePoints,
+ int *const outCodePointCount);
bool isCorrupted() const {
return mIsCorrupted;
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_writing_helper.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_writing_helper.cpp
index 99eed0f67..3fb4caa08 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_writing_helper.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_writing_helper.cpp
@@ -224,7 +224,7 @@ bool Ver4PatriciaTrieWritingHelper::truncateUnigrams(
const int ptNodePos = priorityQueue.top().getDictPos();
priorityQueue.pop();
const PtNodeParams ptNodeParams =
- ptNodeReader->fetchNodeInfoInBufferFromPtNodePos(ptNodePos);
+ ptNodeReader->fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos);
if (ptNodeParams.representsNonWordInfo()) {
continue;
}
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_gc_event_listeners.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_gc_event_listeners.cpp
index 1f00fc6ab..db1a802d0 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_gc_event_listeners.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_gc_event_listeners.cpp
@@ -65,7 +65,7 @@ bool DynamicPtGcEventListeners
bool DynamicPtGcEventListeners::TraversePolicyToUpdateBigramProbability
::onVisitingPtNode(const PtNodeParams *const ptNodeParams) {
- if (!ptNodeParams->isDeleted() && ptNodeParams->hasBigrams()) {
+ if (!ptNodeParams->isDeleted()) {
int bigramEntryCount = 0;
if (!mPtNodeWriter->updateAllBigramEntriesAndDeleteUselessEntries(ptNodeParams,
&bigramEntryCount)) {
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_helper.h b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_helper.h
index cc7b5ff70..2e05bf397 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_helper.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_helper.h
@@ -126,7 +126,7 @@ class DynamicPtReadingHelper {
if (isEnd()) {
return PtNodeParams();
}
- return mPtNodeReader->fetchNodeInfoInBufferFromPtNodePos(mReadingState.mPos);
+ return mPtNodeReader->fetchPtNodeParamsInBufferFromPtNodePos(mReadingState.mPos);
}
AK_FORCE_INLINE bool isValidTerminalNode(const PtNodeParams &ptNodeParams) const {
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_updating_helper.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_updating_helper.cpp
index 9e575858a..f31c914d2 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_updating_helper.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_updating_helper.cpp
@@ -87,9 +87,9 @@ bool DynamicPtUpdatingHelper::addUnigramWord(
bool DynamicPtUpdatingHelper::addBigramWords(const int word0Pos, const int word1Pos,
const BigramProperty *const bigramProperty, bool *const outAddedNewBigram) {
const PtNodeParams sourcePtNodeParams(
- mPtNodeReader->fetchNodeInfoInBufferFromPtNodePos(word0Pos));
+ mPtNodeReader->fetchPtNodeParamsInBufferFromPtNodePos(word0Pos));
const PtNodeParams targetPtNodeParams(
- mPtNodeReader->fetchNodeInfoInBufferFromPtNodePos(word1Pos));
+ mPtNodeReader->fetchPtNodeParamsInBufferFromPtNodePos(word1Pos));
return mPtNodeWriter->addNewBigramEntry(&sourcePtNodeParams, &targetPtNodeParams,
bigramProperty, outAddedNewBigram);
}
@@ -97,16 +97,16 @@ bool DynamicPtUpdatingHelper::addBigramWords(const int word0Pos, const int word1
// Remove a bigram relation from word0Pos to word1Pos.
bool DynamicPtUpdatingHelper::removeBigramWords(const int word0Pos, const int word1Pos) {
const PtNodeParams sourcePtNodeParams(
- mPtNodeReader->fetchNodeInfoInBufferFromPtNodePos(word0Pos));
+ mPtNodeReader->fetchPtNodeParamsInBufferFromPtNodePos(word0Pos));
const PtNodeParams targetPtNodeParams(
- mPtNodeReader->fetchNodeInfoInBufferFromPtNodePos(word1Pos));
+ mPtNodeReader->fetchPtNodeParamsInBufferFromPtNodePos(word1Pos));
return mPtNodeWriter->removeBigramEntry(&sourcePtNodeParams, &targetPtNodeParams);
}
bool DynamicPtUpdatingHelper::addShortcutTarget(const int wordPos,
const int *const targetCodePoints, const int targetCodePointCount,
const int shortcutProbability) {
- const PtNodeParams ptNodeParams(mPtNodeReader->fetchNodeInfoInBufferFromPtNodePos(wordPos));
+ const PtNodeParams ptNodeParams(mPtNodeReader->fetchPtNodeParamsInBufferFromPtNodePos(wordPos));
return mPtNodeWriter->addShortcutTarget(&ptNodeParams, targetCodePoints, targetCodePointCount,
shortcutProbability);
}
@@ -125,7 +125,7 @@ bool DynamicPtUpdatingHelper::createAndInsertNodeIntoPtNodeArray(const int paren
bool DynamicPtUpdatingHelper::setPtNodeProbability(const PtNodeParams *const originalPtNodeParams,
const UnigramProperty *const unigramProperty, bool *const outAddedNewUnigram) {
- if (originalPtNodeParams->isTerminal()) {
+ if (originalPtNodeParams->isTerminal() && !originalPtNodeParams->isDeleted()) {
// Overwrites the probability.
*outAddedNewUnigram = false;
return mPtNodeWriter->updatePtNodeUnigramProperty(originalPtNodeParams, unigramProperty);
@@ -260,7 +260,7 @@ bool DynamicPtUpdatingHelper::reallocatePtNodeAndAddNewPtNodes(
}
// Load node info. Information of the 1st part will be fetched.
const PtNodeParams ptNodeParams(
- mPtNodeReader->fetchNodeInfoInBufferFromPtNodePos(firstPartOfReallocatedPtNodePos));
+ mPtNodeReader->fetchPtNodeParamsInBufferFromPtNodePos(firstPartOfReallocatedPtNodePos));
// Update children position.
return mPtNodeWriter->updateChildrenPosition(&ptNodeParams, actualChildrenPos);
}
@@ -270,8 +270,8 @@ const PtNodeParams DynamicPtUpdatingHelper::getUpdatedPtNodeParams(
const bool isNotAWord, const bool isBlacklisted, const bool isTerminal, const int parentPos,
const int codePointCount, const int *const codePoints, const int probability) const {
const PatriciaTrieReadingUtils::NodeFlags flags = PatriciaTrieReadingUtils::createAndGetFlags(
- isBlacklisted, isNotAWord, isTerminal, originalPtNodeParams->hasShortcutTargets(),
- originalPtNodeParams->hasBigrams(), codePointCount > 1 /* hasMultipleChars */,
+ isBlacklisted, isNotAWord, isTerminal, false /* hasShortcutTargets */,
+ false /* hasBigrams */, codePointCount > 1 /* hasMultipleChars */,
CHILDREN_POSITION_FIELD_SIZE);
return PtNodeParams(originalPtNodeParams, flags, parentPos, codePointCount, codePoints,
probability);
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_reader.h b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_reader.h
index c6b2a8bed..31299a707 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_reader.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_reader.h
@@ -27,7 +27,8 @@ namespace latinime {
class PtNodeReader {
public:
virtual ~PtNodeReader() {}
- virtual const PtNodeParams fetchNodeInfoInBufferFromPtNodePos(const int ptNodePos) const = 0;
+ virtual const PtNodeParams fetchPtNodeParamsInBufferFromPtNodePos(
+ const int ptNodePos) const = 0;
protected:
PtNodeReader() {};
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp
index a6a470c4e..5c62b9caf 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp
@@ -282,7 +282,8 @@ int PatriciaTriePolicy::getUnigramProbabilityOfPtNode(const int ptNodePos) const
if (ptNodePos == NOT_A_DICT_POS) {
return NOT_A_PROBABILITY;
}
- const PtNodeParams ptNodeParams = mPtNodeReader.fetchNodeInfoInBufferFromPtNodePos(ptNodePos);
+ const PtNodeParams ptNodeParams =
+ mPtNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos);
if (ptNodeParams.isNotAWord() || ptNodeParams.isBlacklisted()) {
// If this is not a word, or if it's a blacklisted entry, it should behave as
// having no probability outside of the suggestion process (where it should be used
@@ -296,14 +297,14 @@ int PatriciaTriePolicy::getShortcutPositionOfPtNode(const int ptNodePos) const {
if (ptNodePos == NOT_A_DICT_POS) {
return NOT_A_DICT_POS;
}
- return mPtNodeReader.fetchNodeInfoInBufferFromPtNodePos(ptNodePos).getShortcutPos();
+ return mPtNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos).getShortcutPos();
}
int PatriciaTriePolicy::getBigramsPositionOfPtNode(const int ptNodePos) const {
if (ptNodePos == NOT_A_DICT_POS) {
return NOT_A_DICT_POS;
}
- return mPtNodeReader.fetchNodeInfoInBufferFromPtNodePos(ptNodePos).getBigramsPos();
+ return mPtNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos).getBigramsPos();
}
int PatriciaTriePolicy::createAndGetLeavingChildNode(const DicNode *const dicNode,
@@ -339,7 +340,8 @@ const WordProperty PatriciaTriePolicy::getWordProperty(const int *const codePoin
AKLOGE("getWordProperty was called for invalid word.");
return WordProperty();
}
- const PtNodeParams ptNodeParams = mPtNodeReader.fetchNodeInfoInBufferFromPtNodePos(ptNodePos);
+ const PtNodeParams ptNodeParams =
+ mPtNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos);
std::vector<int> codePointVector(ptNodeParams.getCodePoints(),
ptNodeParams.getCodePoints() + ptNodeParams.getCodePointCount());
// Fetch bigram information.
@@ -389,7 +391,9 @@ const WordProperty PatriciaTriePolicy::getWordProperty(const int *const codePoin
return WordProperty(&codePointVector, &unigramProperty, &bigrams);
}
-int PatriciaTriePolicy::getNextWordAndNextToken(const int token, int *const outCodePoints) {
+int PatriciaTriePolicy::getNextWordAndNextToken(const int token, int *const outCodePoints,
+ int *const outCodePointCount) {
+ *outCodePointCount = 0;
if (token == 0) {
// Start iterating the dictionary.
mTerminalPtNodePositionsForIteratingWords.clear();
@@ -407,8 +411,8 @@ int PatriciaTriePolicy::getNextWordAndNextToken(const int token, int *const outC
}
const int terminalPtNodePos = mTerminalPtNodePositionsForIteratingWords[token];
int unigramProbability = NOT_A_PROBABILITY;
- getCodePointsAndProbabilityAndReturnCodePointCount(terminalPtNodePos, MAX_WORD_LENGTH,
- outCodePoints, &unigramProbability);
+ *outCodePointCount = getCodePointsAndProbabilityAndReturnCodePointCount(terminalPtNodePos,
+ MAX_WORD_LENGTH, outCodePoints, &unigramProbability);
const int nextToken = token + 1;
if (nextToken >= terminalPtNodePositionsVectorSize) {
// All words have been iterated.
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h
index dce94363a..ec8407408 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h
@@ -137,7 +137,8 @@ class PatriciaTriePolicy : public DictionaryStructureWithBufferPolicy {
const WordProperty getWordProperty(const int *const codePoints,
const int codePointCount) const;
- int getNextWordAndNextToken(const int token, int *const outCodePoints);
+ int getNextWordAndNextToken(const int token, int *const outCodePoints,
+ int *const outCodePointCount);
bool isCorrupted() const {
return mIsCorrupted;
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/ver2_patricia_trie_node_reader.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/ver2_patricia_trie_node_reader.cpp
index 0c8de0df2..c1e938710 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/ver2_patricia_trie_node_reader.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/ver2_patricia_trie_node_reader.cpp
@@ -20,7 +20,7 @@
namespace latinime {
-const PtNodeParams Ver2ParticiaTrieNodeReader::fetchNodeInfoInBufferFromPtNodePos(
+const PtNodeParams Ver2ParticiaTrieNodeReader::fetchPtNodeParamsInBufferFromPtNodePos(
const int ptNodePos) const {
if (ptNodePos < 0 || ptNodePos >= mDictSize) {
// Reading invalid position because of bug or broken dictionary.
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/ver2_patricia_trie_node_reader.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/ver2_patricia_trie_node_reader.h
index 86fc89c5e..f0725b66d 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/ver2_patricia_trie_node_reader.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/ver2_patricia_trie_node_reader.h
@@ -36,7 +36,7 @@ class Ver2ParticiaTrieNodeReader : public PtNodeReader {
: mDictBuffer(dictBuffer), mDictSize(dictSize), mBigramPolicy(bigramPolicy),
mShortuctPolicy(shortcutPolicy) {}
- virtual const PtNodeParams fetchNodeInfoInBufferFromPtNodePos(const int ptNodePos) const;
+ virtual const PtNodeParams fetchPtNodeParamsInBufferFromPtNodePos(const int ptNodePos) const;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Ver2ParticiaTrieNodeReader);
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.h
index f24307e7b..22ed4a6c0 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.h
@@ -41,7 +41,7 @@ class Ver4PatriciaTrieNodeReader : public PtNodeReader {
~Ver4PatriciaTrieNodeReader() {}
- virtual const PtNodeParams fetchNodeInfoInBufferFromPtNodePos(const int ptNodePos) const {
+ virtual const PtNodeParams fetchPtNodeParamsInBufferFromPtNodePos(const int ptNodePos) const {
return fetchPtNodeInfoFromBufferAndProcessMovedPtNode(ptNodePos,
NOT_A_DICT_POS /* siblingNodePos */);
}
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 f89d3d7a0..3d8da9173 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
@@ -231,14 +231,6 @@ bool Ver4PatriciaTrieNodeWriter::addNewBigramEntry(
sourcePtNodeParams->getTerminalId(), targetPtNodeParam->getTerminalId());
return false;
}
- if (!sourcePtNodeParams->hasBigrams()) {
- // Update has bigrams flag.
- return updatePtNodeFlags(sourcePtNodeParams->getHeadPos(),
- sourcePtNodeParams->isBlacklisted(), sourcePtNodeParams->isNotAWord(),
- sourcePtNodeParams->isTerminal(), sourcePtNodeParams->hasShortcutTargets(),
- true /* hasBigrams */,
- sourcePtNodeParams->getCodePointCount() > 1 /* hasMultipleChars */);
- }
return true;
}
@@ -303,28 +295,9 @@ bool Ver4PatriciaTrieNodeWriter::addShortcutTarget(const PtNodeParams *const ptN
AKLOGE("Cannot add new shortuct entry. terminalId: %d", ptNodeParams->getTerminalId());
return false;
}
- if (!ptNodeParams->hasShortcutTargets()) {
- // Update has shortcut targets flag.
- return updatePtNodeFlags(ptNodeParams->getHeadPos(),
- ptNodeParams->isBlacklisted(), ptNodeParams->isNotAWord(),
- ptNodeParams->isTerminal(), true /* hasShortcutTargets */,
- ptNodeParams->hasBigrams(),
- ptNodeParams->getCodePointCount() > 1 /* hasMultipleChars */);
- }
return true;
}
-bool Ver4PatriciaTrieNodeWriter::updatePtNodeHasBigramsAndShortcutTargetsFlags(
- const PtNodeParams *const ptNodeParams) {
- const bool hasBigrams = mBuffers->getBigramDictContent()->getBigramListHeadPos(
- ptNodeParams->getTerminalId()) != NOT_A_DICT_POS;
- const bool hasShortcutTargets = mBuffers->getShortcutDictContent()->getShortcutListHeadPos(
- ptNodeParams->getTerminalId()) != NOT_A_DICT_POS;
- return updatePtNodeFlags(ptNodeParams->getHeadPos(), ptNodeParams->isBlacklisted(),
- ptNodeParams->isNotAWord(), ptNodeParams->isTerminal(), hasShortcutTargets,
- hasBigrams, ptNodeParams->getCodePointCount() > 1 /* hasMultipleChars */);
-}
-
bool Ver4PatriciaTrieNodeWriter::writePtNodeAndGetTerminalIdAndAdvancePosition(
const PtNodeParams *const ptNodeParams, int *const outTerminalId,
int *const ptNodeWritingPos) {
@@ -377,8 +350,7 @@ bool Ver4PatriciaTrieNodeWriter::writePtNodeAndGetTerminalIdAndAdvancePosition(
return false;
}
return updatePtNodeFlags(nodePos, ptNodeParams->isBlacklisted(), ptNodeParams->isNotAWord(),
- isTerminal, ptNodeParams->hasShortcutTargets(), ptNodeParams->hasBigrams(),
- ptNodeParams->getCodePointCount() > 1 /* hasMultipleChars */);
+ isTerminal, ptNodeParams->getCodePointCount() > 1 /* hasMultipleChars */);
}
const ProbabilityEntry Ver4PatriciaTrieNodeWriter::createUpdatedEntryFrom(
@@ -402,11 +374,11 @@ const ProbabilityEntry Ver4PatriciaTrieNodeWriter::createUpdatedEntryFrom(
bool Ver4PatriciaTrieNodeWriter::updatePtNodeFlags(const int ptNodePos,
const bool isBlacklisted, const bool isNotAWord, const bool isTerminal,
- const bool hasShortcutTargets, const bool hasBigrams, const bool hasMultipleChars) {
+ const bool hasMultipleChars) {
// Create node flags and write them.
PatriciaTrieReadingUtils::NodeFlags nodeFlags =
PatriciaTrieReadingUtils::createAndGetFlags(isBlacklisted, isNotAWord, isTerminal,
- hasShortcutTargets, hasBigrams, hasMultipleChars,
+ false /* hasShortcutTargets */, false /* hasBigrams */, hasMultipleChars,
CHILDREN_POSITION_FIELD_SIZE);
if (!DynamicPtWritingUtils::writeFlags(mTrieBuffer, nodeFlags, ptNodePos)) {
AKLOGE("Cannot write PtNode flags. flags: %x, pos: %d", nodeFlags, ptNodePos);
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 e90bc44c0..162dc9b1d 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
@@ -93,8 +93,6 @@ class Ver4PatriciaTrieNodeWriter : public PtNodeWriter {
const int *const targetCodePoints, const int targetCodePointCount,
const int shortcutProbability);
- bool updatePtNodeHasBigramsAndShortcutTargetsFlags(const PtNodeParams *const ptNodeParams);
-
private:
DISALLOW_COPY_AND_ASSIGN(Ver4PatriciaTrieNodeWriter);
@@ -110,8 +108,7 @@ class Ver4PatriciaTrieNodeWriter : public PtNodeWriter {
const UnigramProperty *const unigramProperty) const;
bool updatePtNodeFlags(const int ptNodePos, const bool isBlacklisted, const bool isNotAWord,
- const bool isTerminal, const bool hasShortcutTargets, const bool hasBigrams,
- const bool hasMultipleChars);
+ const bool isTerminal, const bool hasMultipleChars);
static const int CHILDREN_POSITION_FIELD_SIZE;
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 aec3b8ea3..46107d92a 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
@@ -125,7 +125,7 @@ int Ver4PatriciaTriePolicy::getUnigramProbabilityOfPtNode(const int ptNodePos) c
if (ptNodePos == NOT_A_DICT_POS) {
return NOT_A_PROBABILITY;
}
- const PtNodeParams ptNodeParams(mNodeReader.fetchNodeInfoInBufferFromPtNodePos(ptNodePos));
+ const PtNodeParams ptNodeParams(mNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos));
if (ptNodeParams.isDeleted() || ptNodeParams.isBlacklisted() || ptNodeParams.isNotAWord()) {
return NOT_A_PROBABILITY;
}
@@ -136,7 +136,7 @@ int Ver4PatriciaTriePolicy::getShortcutPositionOfPtNode(const int ptNodePos) con
if (ptNodePos == NOT_A_DICT_POS) {
return NOT_A_DICT_POS;
}
- const PtNodeParams ptNodeParams(mNodeReader.fetchNodeInfoInBufferFromPtNodePos(ptNodePos));
+ const PtNodeParams ptNodeParams(mNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos));
if (ptNodeParams.isDeleted()) {
return NOT_A_DICT_POS;
}
@@ -148,7 +148,7 @@ int Ver4PatriciaTriePolicy::getBigramsPositionOfPtNode(const int ptNodePos) cons
if (ptNodePos == NOT_A_DICT_POS) {
return NOT_A_DICT_POS;
}
- const PtNodeParams ptNodeParams(mNodeReader.fetchNodeInfoInBufferFromPtNodePos(ptNodePos));
+ const PtNodeParams ptNodeParams(mNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos));
if (ptNodeParams.isDeleted()) {
return NOT_A_DICT_POS;
}
@@ -222,8 +222,24 @@ bool Ver4PatriciaTriePolicy::addUnigramEntry(const int *const word, const int le
}
bool Ver4PatriciaTriePolicy::removeUnigramEntry(const int *const word, const int length) {
- // TODO: Implement.
- return false;
+ 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);
+ if (!mNodeWriter.markPtNodeAsDeleted(&ptNodeParams)) {
+ AKLOGE("Cannot remove unigram. ptNodePos: %d", ptNodePos);
+ return false;
+ }
+ if (!ptNodeParams.representsNonWordInfo()) {
+ mUnigramCount--;
+ }
+ return true;
}
bool Ver4PatriciaTriePolicy::addNgramEntry(const PrevWordsInfo *const prevWordsInfo,
@@ -405,7 +421,7 @@ const WordProperty Ver4PatriciaTriePolicy::getWordProperty(const int *const code
AKLOGE("getWordProperty is called for invalid word.");
return WordProperty();
}
- const PtNodeParams ptNodeParams = mNodeReader.fetchNodeInfoInBufferFromPtNodePos(ptNodePos);
+ const PtNodeParams ptNodeParams = mNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos);
std::vector<int> codePointVector(ptNodeParams.getCodePoints(),
ptNodeParams.getCodePoints() + ptNodeParams.getCodePointCount());
const ProbabilityEntry probabilityEntry =
@@ -473,10 +489,9 @@ const WordProperty Ver4PatriciaTriePolicy::getWordProperty(const int *const code
return WordProperty(&codePointVector, &unigramProperty, &bigrams);
}
-int Ver4PatriciaTriePolicy::getNextWordAndNextToken(const int token, int *const outCodePoints) {
- // TODO: Return code point count like other methods.
- // Null termination.
- outCodePoints[0] = 0;
+int Ver4PatriciaTriePolicy::getNextWordAndNextToken(const int token, int *const outCodePoints,
+ int *const outCodePointCount) {
+ *outCodePointCount = 0;
if (token == 0) {
mTerminalPtNodePositionsForIteratingWords.clear();
DynamicPtReadingHelper::TraversePolicyToGetAllTerminalPtNodePositions traversePolicy(
@@ -493,13 +508,8 @@ int Ver4PatriciaTriePolicy::getNextWordAndNextToken(const int token, int *const
}
const int terminalPtNodePos = mTerminalPtNodePositionsForIteratingWords[token];
int unigramProbability = NOT_A_PROBABILITY;
- const int codePointCount = getCodePointsAndProbabilityAndReturnCodePointCount(
+ *outCodePointCount = getCodePointsAndProbabilityAndReturnCodePointCount(
terminalPtNodePos, MAX_WORD_LENGTH, outCodePoints, &unigramProbability);
- if (codePointCount < MAX_WORD_LENGTH) {
- // Null termination. outCodePoints have to be null terminated or contain MAX_WORD_LENGTH
- // code points.
- outCodePoints[codePointCount] = 0;
- }
const int nextToken = token + 1;
if (nextToken >= terminalPtNodePositionsVectorSize) {
// All words have been iterated.
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h
index 0a20965f3..5d66a2cce 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h
@@ -113,7 +113,8 @@ class Ver4PatriciaTriePolicy : public DictionaryStructureWithBufferPolicy {
const WordProperty getWordProperty(const int *const codePoints,
const int codePointCount) const;
- int getNextWordAndNextToken(const int token, int *const outCodePoints);
+ int getNextWordAndNextToken(const int token, int *const outCodePoints,
+ int *const outCodePointCount);
bool isCorrupted() const {
return mIsCorrupted;
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.cpp
index e868ddf6f..40fdfa068 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.cpp
@@ -215,7 +215,7 @@ bool Ver4PatriciaTrieWritingHelper::truncateUnigrams(
const int ptNodePos = priorityQueue.top().getDictPos();
priorityQueue.pop();
const PtNodeParams ptNodeParams =
- ptNodeReader->fetchNodeInfoInBufferFromPtNodePos(ptNodePos);
+ ptNodeReader->fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos);
if (ptNodeParams.representsNonWordInfo()) {
continue;
}
@@ -286,8 +286,9 @@ bool Ver4PatriciaTrieWritingHelper::TraversePolicyToUpdateAllPtNodeFlagsAndTermi
}
if (!mPtNodeWriter->updateTerminalId(ptNodeParams, it->second)) {
AKLOGE("Cannot update terminal id. %d -> %d", it->first, it->second);
+ return false;
}
- return mPtNodeWriter->updatePtNodeHasBigramsAndShortcutTargetsFlags(ptNodeParams);
+ return true;
}
} // namespace latinime
diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtils.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtils.java
index 2cbc04154..3ef03f4bd 100644
--- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtils.java
+++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtils.java
@@ -26,11 +26,13 @@ import org.xml.sax.SAXException;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.ArrayList;
@@ -51,14 +53,17 @@ public final class BinaryDictOffdeviceUtils {
public final static String ENCRYPTION = "encrypted";
private final static int MAX_DECODE_DEPTH = 8;
+ private final static int COPY_BUFFER_SIZE = 8192;
public static class DecoderChainSpec {
ArrayList<String> mDecoderSpec = new ArrayList<>();
File mFile;
+
public DecoderChainSpec addStep(final String stepDescription) {
mDecoderSpec.add(stepDescription);
return this;
}
+
public String describeChain() {
final StringBuilder s = new StringBuilder("raw");
for (final String step : mDecoderSpec) {
@@ -70,13 +75,10 @@ public final class BinaryDictOffdeviceUtils {
}
public static void copy(final InputStream input, final OutputStream output) throws IOException {
- final byte[] buffer = new byte[1000];
- final BufferedInputStream in = new BufferedInputStream(input);
- final BufferedOutputStream out = new BufferedOutputStream(output);
- for (int readBytes = in.read(buffer); readBytes >= 0; readBytes = in.read(buffer))
+ final byte[] buffer = new byte[COPY_BUFFER_SIZE];
+ for (int readBytes = input.read(buffer); readBytes >= 0; readBytes = input.read(buffer)) {
output.write(buffer, 0, readBytes);
- in.close();
- out.close();
+ }
}
/**
@@ -131,11 +133,15 @@ public final class BinaryDictOffdeviceUtils {
try {
final File dst = File.createTempFile(PREFIX, SUFFIX);
dst.deleteOnExit();
- final FileOutputStream dstStream = new FileOutputStream(dst);
- copy(Compress.getUncompressedStream(new BufferedInputStream(new FileInputStream(src))),
- new BufferedOutputStream(dstStream)); // #copy() closes the streams
- return dst;
- } catch (IOException e) {
+ try (
+ final InputStream input = Compress.getUncompressedStream(
+ new BufferedInputStream(new FileInputStream(src)));
+ final OutputStream output = new BufferedOutputStream(new FileOutputStream(dst))
+ ) {
+ copy(input, output);
+ return dst;
+ }
+ } catch (final IOException e) {
// Could not uncompress the file: presumably the file is simply not a compressed file
return null;
}
@@ -150,20 +156,20 @@ public final class BinaryDictOffdeviceUtils {
try {
final File dst = File.createTempFile(PREFIX, SUFFIX);
dst.deleteOnExit();
- final FileOutputStream dstStream = new FileOutputStream(dst);
- copy(Crypt.getDecryptedStream(new BufferedInputStream(new FileInputStream(src))),
- dstStream); // #copy() closes the streams
- return dst;
- } catch (IOException e) {
+ try (
+ final InputStream input = Crypt.getDecryptedStream(
+ new BufferedInputStream(new FileInputStream(src)));
+ final OutputStream output = new BufferedOutputStream(new FileOutputStream(dst))
+ ) {
+ copy(input, output);
+ return dst;
+ }
+ } catch (final IOException e) {
// Could not decrypt the file: presumably the file is simply not a crypted file
return null;
}
}
- static void crash(final String filename, final Exception e) {
- throw new RuntimeException("Can't read file " + filename, e);
- }
-
static FusionDictionary getDictionary(final String filename, final boolean report) {
final File file = new File(filename);
if (report) {
@@ -172,45 +178,40 @@ public final class BinaryDictOffdeviceUtils {
}
try {
if (XmlDictInputOutput.isXmlUnigramDictionary(filename)) {
- if (report) System.out.println("Format : XML unigram list");
+ if (report) {
+ System.out.println("Format : XML unigram list");
+ }
return XmlDictInputOutput.readDictionaryXml(
new BufferedInputStream(new FileInputStream(file)),
null /* shortcuts */, null /* bigrams */);
- } else {
- final DecoderChainSpec decodedSpec = getRawDictionaryOrNull(file);
- if (null == decodedSpec) {
- crash(filename, new RuntimeException(
- filename + " does not seem to be a dictionary file"));
- } else if (CombinedInputOutput.isCombinedDictionary(
- decodedSpec.mFile.getAbsolutePath())){
- if (report) {
- System.out.println("Format : Combined format");
- System.out.println("Packaging : " + decodedSpec.describeChain());
- System.out.println("Uncompressed size : " + decodedSpec.mFile.length());
- }
- return CombinedInputOutput.readDictionaryCombined(
- new BufferedInputStream(new FileInputStream(decodedSpec.mFile)));
- } else {
- final DictDecoder dictDecoder = BinaryDictIOUtils.getDictDecoder(
- decodedSpec.mFile, 0, decodedSpec.mFile.length(),
- DictDecoder.USE_BYTEARRAY);
- if (report) {
- System.out.println("Format : Binary dictionary format");
- System.out.println("Packaging : " + decodedSpec.describeChain());
- System.out.println("Uncompressed size : " + decodedSpec.mFile.length());
- }
- return dictDecoder.readDictionaryBinary(false /* deleteDictIfBroken */);
+ }
+ final DecoderChainSpec decodedSpec = getRawDictionaryOrNull(file);
+ if (null == decodedSpec) {
+ throw new RuntimeException("Does not seem to be a dictionary file " + filename);
+ }
+ if (CombinedInputOutput.isCombinedDictionary(decodedSpec.mFile.getAbsolutePath())) {
+ if (report) {
+ System.out.println("Format : Combined format");
+ System.out.println("Packaging : " + decodedSpec.describeChain());
+ System.out.println("Uncompressed size : " + decodedSpec.mFile.length());
}
+ try (final BufferedReader reader = new BufferedReader(
+ new InputStreamReader(new FileInputStream(decodedSpec.mFile), "UTF-8"))) {
+ return CombinedInputOutput.readDictionaryCombined(reader);
+ }
+ }
+ final DictDecoder dictDecoder = BinaryDictIOUtils.getDictDecoder(
+ decodedSpec.mFile, 0, decodedSpec.mFile.length(),
+ DictDecoder.USE_BYTEARRAY);
+ if (report) {
+ System.out.println("Format : Binary dictionary format");
+ System.out.println("Packaging : " + decodedSpec.describeChain());
+ System.out.println("Uncompressed size : " + decodedSpec.mFile.length());
}
- } catch (IOException e) {
- crash(filename, e);
- } catch (SAXException e) {
- crash(filename, e);
- } catch (ParserConfigurationException e) {
- crash(filename, e);
- } catch (UnsupportedFormatException e) {
- crash(filename, e);
+ return dictDecoder.readDictionaryBinary(false /* deleteDictIfBroken */);
+ } catch (final IOException | SAXException | ParserConfigurationException |
+ UnsupportedFormatException e) {
+ throw new RuntimeException("Can't read file " + filename, e);
}
- return null;
}
}
diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/CombinedInputOutput.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/CombinedInputOutput.java
index 6a0e1b7f0..23cbee81c 100644
--- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/CombinedInputOutput.java
+++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/CombinedInputOutput.java
@@ -26,13 +26,9 @@ import com.android.inputmethod.latin.makedict.WordProperty;
import com.android.inputmethod.latin.utils.CombinedFormatUtils;
import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileNotFoundException;
+import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.TreeSet;
@@ -57,27 +53,15 @@ public class CombinedInputOutput {
* @return true if the file is in the combined format, false otherwise
*/
public static boolean isCombinedDictionary(final String filename) {
- BufferedReader reader = null;
- try {
- reader = new BufferedReader(new FileReader(new File(filename)));
+ try (final BufferedReader reader = new BufferedReader(new FileReader(filename))) {
String firstLine = reader.readLine();
while (firstLine.startsWith(COMMENT_LINE_STARTER)) {
firstLine = reader.readLine();
}
return firstLine.matches(
"^" + CombinedFormatUtils.DICTIONARY_TAG + "=[^:]+(:[^=]+=[^:]+)*");
- } catch (FileNotFoundException e) {
+ } catch (final IOException e) {
return false;
- } catch (IOException e) {
- return false;
- } finally {
- if (reader != null) {
- try {
- reader.close();
- } catch (IOException e) {
- // do nothing
- }
- }
}
}
@@ -87,12 +71,11 @@ public class CombinedInputOutput {
* This is the public method that will read a combined file and return the corresponding memory
* representation.
*
- * @param source the file to read the data from.
+ * @param reader the buffered reader to read the data from.
* @return the in-memory representation of the dictionary.
*/
- public static FusionDictionary readDictionaryCombined(final InputStream source)
+ public static FusionDictionary readDictionaryCombined(final BufferedReader reader)
throws IOException {
- final BufferedReader reader = new BufferedReader(new InputStreamReader(source, "UTF-8"));
String headerLine = reader.readLine();
while (headerLine.startsWith(COMMENT_LINE_STARTER)) {
headerLine = reader.readLine();
@@ -218,11 +201,11 @@ public class CombinedInputOutput {
/**
* Writes a dictionary to a combined file.
*
- * @param destination a destination stream to write to.
+ * @param destination a destination writer.
* @param dict the dictionary to write.
*/
- public static void writeDictionaryCombined(
- final Writer destination, final FusionDictionary dict) throws IOException {
+ public static void writeDictionaryCombined(final BufferedWriter destination,
+ final FusionDictionary dict) throws IOException {
final TreeSet<WordProperty> wordPropertiesInDict = new TreeSet<>();
for (final WordProperty wordProperty : dict) {
// This for ordering by frequency, then by asciibetic order
@@ -232,6 +215,5 @@ public class CombinedInputOutput {
for (final WordProperty wordProperty : wordPropertiesInDict) {
destination.write(CombinedFormatUtils.formatWordProperty(wordProperty));
}
- destination.close();
}
}
diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Compress.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Compress.java
index b7f48b522..728a159a0 100644
--- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Compress.java
+++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Compress.java
@@ -16,11 +16,6 @@
package com.android.inputmethod.latin.dicttool;
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -32,8 +27,7 @@ public class Compress {
// This container class is not publicly instantiable.
}
- public static OutputStream getCompressedStream(final OutputStream out)
- throws java.io.IOException {
+ public static OutputStream getCompressedStream(final OutputStream out) throws IOException {
return new GZIPOutputStream(out);
}
@@ -43,7 +37,6 @@ public class Compress {
static public class Compressor extends Dicttool.Command {
public static final String COMMAND = "compress";
- public static final String STDIN_OR_STDOUT = "-";
public Compressor() {
}
@@ -61,17 +54,18 @@ public class Compress {
}
final String inFilename = mArgs.length >= 1 ? mArgs[0] : STDIN_OR_STDOUT;
final String outFilename = mArgs.length >= 2 ? mArgs[1] : STDIN_OR_STDOUT;
- final InputStream input = inFilename.equals(STDIN_OR_STDOUT) ? System.in
- : new BufferedInputStream(new FileInputStream(new File(inFilename)));
- final OutputStream output = outFilename.equals(STDIN_OR_STDOUT) ? System.out
- : new BufferedOutputStream(new FileOutputStream(new File(outFilename)));
- BinaryDictOffdeviceUtils.copy(input, new GZIPOutputStream(output));
+ try (
+ final InputStream input = getFileInputStreamOrStdIn(inFilename);
+ final OutputStream compressedOutput = getCompressedStream(
+ getFileOutputStreamOrStdOut(outFilename))
+ ) {
+ BinaryDictOffdeviceUtils.copy(input, compressedOutput);
+ }
}
}
static public class Uncompressor extends Dicttool.Command {
public static final String COMMAND = "uncompress";
- public static final String STDIN_OR_STDOUT = "-";
public Uncompressor() {
}
@@ -89,11 +83,13 @@ public class Compress {
}
final String inFilename = mArgs.length >= 1 ? mArgs[0] : STDIN_OR_STDOUT;
final String outFilename = mArgs.length >= 2 ? mArgs[1] : STDIN_OR_STDOUT;
- final InputStream input = inFilename.equals(STDIN_OR_STDOUT) ? System.in
- : new BufferedInputStream(new FileInputStream(new File(inFilename)));
- final OutputStream output = outFilename.equals(STDIN_OR_STDOUT) ? System.out
- : new BufferedOutputStream(new FileOutputStream(new File(outFilename)));
- BinaryDictOffdeviceUtils.copy(new GZIPInputStream(input), output);
+ try (
+ final InputStream uncompressedInput = getUncompressedStream(
+ getFileInputStreamOrStdIn(inFilename));
+ final OutputStream output = getFileOutputStreamOrStdOut(outFilename)
+ ) {
+ BinaryDictOffdeviceUtils.copy(uncompressedInput, output);
+ }
}
}
}
diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/DictionaryMaker.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/DictionaryMaker.java
index 37c8d4184..3d0557b5c 100644
--- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/DictionaryMaker.java
+++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/DictionaryMaker.java
@@ -27,19 +27,23 @@ import com.android.inputmethod.latin.makedict.UnsupportedFormatException;
import com.android.inputmethod.latin.makedict.Ver2DictEncoder;
import com.android.inputmethod.latin.makedict.Ver4DictEncoder;
+import org.xml.sax.SAXException;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.LinkedList;
import javax.xml.parsers.ParserConfigurationException;
-import org.xml.sax.SAXException;
-
/**
* Main class/method for DictionaryMaker.
*/
@@ -279,22 +283,21 @@ public class DictionaryMaker {
*/
private static FusionDictionary readCombinedFile(final String combinedFilename)
throws FileNotFoundException, IOException {
- FileInputStream inStream = null;
- try {
- final File file = new File(combinedFilename);
- inStream = new FileInputStream(file);
- return CombinedInputOutput.readDictionaryCombined(inStream);
- } finally {
- if (null != inStream) {
- try {
- inStream.close();
- } catch (IOException e) {
- // do nothing
- }
- }
+ try (final BufferedReader reader = new BufferedReader(new InputStreamReader(
+ new FileInputStream(combinedFilename), "UTF-8"))
+ ) {
+ return CombinedInputOutput.readDictionaryCombined(reader);
}
}
+ private static BufferedInputStream getBufferedFileInputStream(final String filename)
+ throws FileNotFoundException {
+ if (filename == null) {
+ return null;
+ }
+ return new BufferedInputStream(new FileInputStream(filename));
+ }
+
/**
* Read a dictionary from a unigram XML file, and optionally a bigram XML file.
*
@@ -310,12 +313,13 @@ public class DictionaryMaker {
private static FusionDictionary readXmlFile(final String unigramXmlFilename,
final String shortcutXmlFilename, final String bigramXmlFilename)
throws FileNotFoundException, SAXException, IOException, ParserConfigurationException {
- final FileInputStream unigrams = new FileInputStream(new File(unigramXmlFilename));
- final FileInputStream shortcuts = null == shortcutXmlFilename ? null :
- new FileInputStream(new File(shortcutXmlFilename));
- final FileInputStream bigrams = null == bigramXmlFilename ? null :
- new FileInputStream(new File(bigramXmlFilename));
- return XmlDictInputOutput.readDictionaryXml(unigrams, shortcuts, bigrams);
+ try (
+ final BufferedInputStream unigrams = getBufferedFileInputStream(unigramXmlFilename);
+ final BufferedInputStream shortcuts = getBufferedFileInputStream(shortcutXmlFilename);
+ final BufferedInputStream bigrams = getBufferedFileInputStream(bigramXmlFilename);
+ ) {
+ return XmlDictInputOutput.readDictionaryXml(unigrams, shortcuts, bigrams);
+ }
}
/**
@@ -374,8 +378,9 @@ public class DictionaryMaker {
*/
private static void writeXmlDictionary(final String outputFilename,
final FusionDictionary dict) throws FileNotFoundException, IOException {
- XmlDictInputOutput.writeDictionaryXml(new BufferedWriter(new FileWriter(outputFilename)),
- dict);
+ try (final BufferedWriter writer = new BufferedWriter(new FileWriter(outputFilename))) {
+ XmlDictInputOutput.writeDictionaryXml(writer, dict);
+ }
}
/**
@@ -388,7 +393,8 @@ public class DictionaryMaker {
*/
private static void writeCombinedDictionary(final String outputFilename,
final FusionDictionary dict) throws FileNotFoundException, IOException {
- CombinedInputOutput.writeDictionaryCombined(
- new BufferedWriter(new FileWriter(outputFilename)), dict);
+ try (final BufferedWriter writer = new BufferedWriter(new FileWriter(outputFilename))) {
+ CombinedInputOutput.writeDictionaryCombined(writer, dict);
+ }
}
}
diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Dicttool.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Dicttool.java
index 8ae035f64..e49b35084 100644
--- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Dicttool.java
+++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Dicttool.java
@@ -16,23 +16,63 @@
package com.android.inputmethod.latin.dicttool;
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.util.Arrays;
import java.util.HashMap;
public class Dicttool {
public static abstract class Command {
+ public static final String STDIN_OR_STDOUT = "-";
protected String[] mArgs;
+
public void setArgs(String[] args) throws IllegalArgumentException {
mArgs = args;
}
+
+ protected static InputStream getFileInputStreamOrStdIn(final String inFilename)
+ throws FileNotFoundException {
+ if (STDIN_OR_STDOUT.equals(inFilename)) {
+ return System.in;
+ }
+ return getFileInputStream(new File(inFilename));
+ }
+
+ protected static InputStream getFileInputStream(final File inFile)
+ throws FileNotFoundException {
+ return new BufferedInputStream(new FileInputStream(inFile));
+ }
+
+ protected static OutputStream getFileOutputStreamOrStdOut(final String outFilename)
+ throws FileNotFoundException {
+ if (STDIN_OR_STDOUT.equals(outFilename)) {
+ return System.out;
+ }
+ return getFileOutputStream(new File(outFilename));
+ }
+
+ protected static OutputStream getFileOutputStream(final File outFile)
+ throws FileNotFoundException {
+ return new BufferedOutputStream(new FileOutputStream(outFile));
+ }
+
abstract public String getHelp();
abstract public void run() throws Exception;
}
+
static HashMap<String, Class<? extends Command>> sCommands = new HashMap<>();
+
static {
CommandList.populate();
}
+
public static void addCommand(final String commandName, final Class<? extends Command> cls) {
sCommands.put(commandName, cls);
}
@@ -60,7 +100,7 @@ public class Dicttool {
return sCommands.containsKey(commandName);
}
- private Command getCommand(final String[] arguments) {
+ private static Command getCommand(final String[] arguments) {
final String commandName = arguments[0];
if (!isCommand(commandName)) {
throw new RuntimeException("Unknown command : " + commandName);
@@ -76,7 +116,7 @@ public class Dicttool {
* @param arguments the arguments passed to dicttool.
* @return 0 for success, an error code otherwise (always 1 at the moment)
*/
- private int execute(final String[] arguments) {
+ private static int execute(final String[] arguments) {
final Command command = getCommand(arguments);
try {
command.run();
@@ -95,6 +135,6 @@ public class Dicttool {
return;
}
// Exit with the success/error code from #execute() as status.
- System.exit(new Dicttool().execute(arguments));
+ System.exit(execute(arguments));
}
}
diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Package.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Package.java
index dff3387be..1f6798269 100644
--- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Package.java
+++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Package.java
@@ -21,8 +21,9 @@ import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
public class Package {
private Package() {
@@ -86,9 +87,13 @@ public class Package {
}
System.out.println("Packaging : " + decodedSpec.describeChain());
System.out.println("Uncompressed size : " + decodedSpec.mFile.length());
- final FileOutputStream dstStream = new FileOutputStream(new File(mArgs[1]));
- BinaryDictOffdeviceUtils.copy(new BufferedInputStream(
- new FileInputStream(decodedSpec.mFile)), new BufferedOutputStream(dstStream));
+ try (
+ final InputStream input = getFileInputStream(decodedSpec.mFile);
+ final OutputStream output = new BufferedOutputStream(
+ getFileOutputStreamOrStdOut(mArgs[1]))
+ ) {
+ BinaryDictOffdeviceUtils.copy(input, output);
+ }
}
}
}
diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/XmlDictInputOutput.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/XmlDictInputOutput.java
index 7435fa7d6..bdec44761 100644
--- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/XmlDictInputOutput.java
+++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/XmlDictInputOutput.java
@@ -23,13 +23,16 @@ import com.android.inputmethod.latin.makedict.ProbabilityInfo;
import com.android.inputmethod.latin.makedict.WeightedString;
import com.android.inputmethod.latin.makedict.WordProperty;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import java.io.BufferedInputStream;
import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileReader;
+import java.io.BufferedWriter;
+import java.io.FileInputStream;
import java.io.IOException;
-import java.io.InputStream;
-import java.io.Writer;
+import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.TreeSet;
@@ -38,10 +41,6 @@ import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
-import org.xml.sax.Attributes;
-import org.xml.sax.SAXException;
-import org.xml.sax.helpers.DefaultHandler;
-
/**
* Reads and writes XML files for a FusionDictionary.
*
@@ -57,8 +56,6 @@ public class XmlDictInputOutput {
private static final String WORD_ATTR = "word";
private static final String NOT_A_WORD_ATTR = "not_a_word";
- private static final String OPTIONS_KEY = "options";
-
/**
* SAX handler for a unigram XML file.
*/
@@ -120,7 +117,6 @@ public class XmlDictInputOutput {
final String attrName = attrs.getLocalName(attrIndex);
attributes.put(attrName, attrs.getValue(attrIndex));
}
- final String optionsString = attributes.get(OPTIONS_KEY);
mDictionary = new FusionDictionary(new PtNodeArray(),
new DictionaryOptions(attributes));
} else {
@@ -244,14 +240,13 @@ public class XmlDictInputOutput {
protected int getValueFromFreqString(final String freqString) {
if (WHITELIST_MARKER.equals(freqString)) {
return WHITELIST_FREQ_VALUE;
- } else {
- final int intValue = super.getValueFromFreqString(freqString);
- if (intValue < MIN_FREQ || intValue > MAX_FREQ) {
- throw new RuntimeException("Shortcut freq out of range. Accepted range is "
- + MIN_FREQ + ".." + MAX_FREQ);
- }
- return intValue;
}
+ final int intValue = super.getValueFromFreqString(freqString);
+ if (intValue < MIN_FREQ || intValue > MAX_FREQ) {
+ throw new RuntimeException("Shortcut freq out of range. Accepted range is "
+ + MIN_FREQ + ".." + MAX_FREQ);
+ }
+ return intValue;
}
// As per getAssocMap(), this never returns null.
@@ -269,23 +264,12 @@ public class XmlDictInputOutput {
* @return true if the file is in the unigram XML format, false otherwise
*/
public static boolean isXmlUnigramDictionary(final String filename) {
- BufferedReader reader = null;
- try {
- reader = new BufferedReader(new FileReader(new File(filename)));
+ try (final BufferedReader reader = new BufferedReader(
+ new InputStreamReader(new FileInputStream(filename), "UTF-8"))) {
final String firstLine = reader.readLine();
return firstLine.matches("^\\s*<wordlist .*>\\s*$");
- } catch (FileNotFoundException e) {
+ } catch (final IOException e) {
return false;
- } catch (IOException e) {
- return false;
- } finally {
- if (reader != null) {
- try {
- reader.close();
- } catch (IOException e) {
- // do nothing
- }
- }
}
}
@@ -300,8 +284,8 @@ public class XmlDictInputOutput {
* @param bigrams the file to read the bigrams from, or null.
* @return the in-memory representation of the dictionary.
*/
- public static FusionDictionary readDictionaryXml(final InputStream unigrams,
- final InputStream shortcuts, final InputStream bigrams)
+ public static FusionDictionary readDictionaryXml(final BufferedInputStream unigrams,
+ final BufferedInputStream shortcuts, final BufferedInputStream bigrams)
throws SAXException, IOException, ParserConfigurationException {
final SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true);
@@ -350,8 +334,8 @@ public class XmlDictInputOutput {
* @param destination a destination stream to write to.
* @param dict the dictionary to write.
*/
- public static void writeDictionaryXml(Writer destination, FusionDictionary dict)
- throws IOException {
+ public static void writeDictionaryXml(final BufferedWriter destination,
+ final FusionDictionary dict) throws IOException {
final TreeSet<WordProperty> wordPropertiesInDict = new TreeSet<>();
for (WordProperty wordProperty : dict) {
wordPropertiesInDict.add(wordProperty);
diff --git a/tools/dicttool/tests/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtilsTests.java b/tools/dicttool/tests/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtilsTests.java
index fccb654b0..0236a446d 100644
--- a/tools/dicttool/tests/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtilsTests.java
+++ b/tools/dicttool/tests/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtilsTests.java
@@ -62,13 +62,13 @@ public class BinaryDictOffdeviceUtilsTests extends TestCase {
final File dst = File.createTempFile("testGetRawDict", ".tmp");
dst.deleteOnExit();
-
- final OutputStream out = Compress.getCompressedStream(
+ try (final OutputStream out = Compress.getCompressedStream(
Compress.getCompressedStream(
Compress.getCompressedStream(
- new BufferedOutputStream(new FileOutputStream(dst)))));
- final DictEncoder dictEncoder = new Ver2DictEncoder(out);
- dictEncoder.writeDictionary(dict, new FormatOptions(2, false));
+ new BufferedOutputStream(new FileOutputStream(dst)))))) {
+ final DictEncoder dictEncoder = new Ver2DictEncoder(out);
+ dictEncoder.writeDictionary(dict, new FormatOptions(2, false));
+ }
// Test for an actually compressed dictionary and its contents
final BinaryDictOffdeviceUtils.DecoderChainSpec decodeSpec =
@@ -96,11 +96,11 @@ public class BinaryDictOffdeviceUtilsTests extends TestCase {
// Randomly create some 4k file containing garbage
final File dst = File.createTempFile("testGetRawDict", ".tmp");
dst.deleteOnExit();
- final OutputStream out = new BufferedOutputStream(new FileOutputStream(dst));
- for (int i = 0; i < 1024; ++i) {
- out.write(0x12345678);
+ try (final OutputStream out = new BufferedOutputStream(new FileOutputStream(dst))) {
+ for (int i = 0; i < 1024; ++i) {
+ out.write(0x12345678);
+ }
}
- out.close();
// Test that a random data file actually fails
assertNull("Wrongly identified data file",
@@ -108,12 +108,12 @@ public class BinaryDictOffdeviceUtilsTests extends TestCase {
final File gzDst = File.createTempFile("testGetRawDict", ".tmp");
gzDst.deleteOnExit();
- final OutputStream gzOut =
- Compress.getCompressedStream(new BufferedOutputStream(new FileOutputStream(gzDst)));
- for (int i = 0; i < 1024; ++i) {
- gzOut.write(0x12345678);
+ try (final OutputStream gzOut = Compress.getCompressedStream(
+ new BufferedOutputStream(new FileOutputStream(gzDst)))) {
+ for (int i = 0; i < 1024; ++i) {
+ gzOut.write(0x12345678);
+ }
}
- gzOut.close();
// Test that a compressed random data file actually fails
assertNull("Wrongly identified data file",