Merge "Remove processMotionEvent from MoreKeysKeyboardView"
diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index 1eff2f9..aae5b0b 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -388,7 +388,7 @@
 be a QWERTY, or AZERTY, or any other disposition that only offers Latin characters, so
 you wouldn't be able to type, say, Arabic on it. Please translate it in a way that "alphabet"
 would be understood to mean specifically the Latin alphabet, rather than any other
-alphabet. [CHAR LIMIT=25] -->
+alphabet. [CHAR LIMIT=29] -->
     <string name="subtype_no_language">No language (Alphabet)</string>
     <!-- This string is displayed in the description for a keyboard type. It refers specifically to
 the Latin alphabet, as opposed to Cyrillic, Arabic, Hebrew or other scripts.
diff --git a/java/src/com/android/inputmethod/latin/DictionaryWriter.java b/java/src/com/android/inputmethod/latin/DictionaryWriter.java
index 8be04c1..47151bf 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryWriter.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryWriter.java
@@ -37,10 +37,9 @@
  * An in memory dictionary for memorizing entries and writing a binary dictionary.
  */
 public class DictionaryWriter extends AbstractDictionaryWriter {
-    // TODO: Regenerate version 3 binary dictionary.
-    private static final int BINARY_DICT_VERSION = 2;
+    private static final int BINARY_DICT_VERSION = 3;
     private static final FormatSpec.FormatOptions FORMAT_OPTIONS =
-            new FormatSpec.FormatOptions(BINARY_DICT_VERSION);
+            new FormatSpec.FormatOptions(BINARY_DICT_VERSION, true /* supportsDynamicUpdate */);
 
     private FusionDictionary mFusionDictionary;
 
diff --git a/java/src/com/android/inputmethod/latin/personalization/DynamicPredictionDictionaryBase.java b/java/src/com/android/inputmethod/latin/personalization/DynamicPredictionDictionaryBase.java
index 6498bf9..bb6ec6b 100644
--- a/java/src/com/android/inputmethod/latin/personalization/DynamicPredictionDictionaryBase.java
+++ b/java/src/com/android/inputmethod/latin/personalization/DynamicPredictionDictionaryBase.java
@@ -77,7 +77,7 @@
             CollectionUtils.newArrayList();
 
     // Should always be false except when we use this class for test
-    @UsedForTesting boolean isTest = false;
+    @UsedForTesting boolean mIsTest = false;
 
     /* package */ DynamicPredictionDictionaryBase(final Context context, final String locale,
             final SharedPreferences sp, final String dictionaryType) {
@@ -298,8 +298,8 @@
 
         @Override
         protected Void doInBackground(final Void... v) {
-            if (mDynamicPredictionDictionary.isTest) {
-                // If isTest == true, wait until the lock is released.
+            if (mDynamicPredictionDictionary.mIsTest) {
+                // If mIsTest == true, wait until the lock is released.
                 mDynamicPredictionDictionary.mBigramListLock.lock();
                 try {
                     doWriteTaskLocked();
diff --git a/native/jni/src/suggest/core/dictionary/binary_dictionary_format_utils.cpp b/native/jni/src/suggest/core/dictionary/binary_dictionary_format_utils.cpp
index 5d14a05..0e8d72f 100644
--- a/native/jni/src/suggest/core/dictionary/binary_dictionary_format_utils.cpp
+++ b/native/jni/src/suggest/core/dictionary/binary_dictionary_format_utils.cpp
@@ -61,8 +61,7 @@
             if (ByteArrayUtils::readUint16(dict, 4) == 2) {
                 return VERSION_2;
             } else if (ByteArrayUtils::readUint16(dict, 4) == 3) {
-                // TODO: Support version 3 dictionary.
-                return UNKNOWN_VERSION;
+                return VERSION_3;
             } else {
                 return UNKNOWN_VERSION;
             }
diff --git a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_node_reader.cpp b/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_node_reader.cpp
index 20cda91..7ac635a 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_node_reader.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_node_reader.cpp
@@ -27,7 +27,9 @@
     const uint8_t *const dictRoot = mBinaryDictionaryInfo->getDictRoot();
     int pos = nodePos;
     mFlags = PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(dictRoot, &pos);
-    mParentPos = DynamicPatriciaTrieReadingUtils::getParentPosAndAdvancePosition(dictRoot, &pos);
+    const int parentPos =
+            DynamicPatriciaTrieReadingUtils::getParentPosAndAdvancePosition(dictRoot, &pos);
+    mParentPos = (parentPos != 0) ? mNodePos + parentPos : NOT_A_DICT_POS;
     if (outCodePoints != 0) {
         mCodePointCount = PatriciaTrieReadingUtils::getCharsAndAdvancePosition(
                 dictRoot, mFlags, maxCodePointCount, outCodePoints, &pos);
diff --git a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_policy.cpp
index 0b73efa..3df5056 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_policy.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_policy.cpp
@@ -94,7 +94,7 @@
         reverseCodePoints[codePointCount++] = mergedNodeCodePoints[i];
     }
     // Then, follow parent pos toward the root node.
-    while (nodeReader.getParentPos() != getRootPosition()) {
+    while (nodeReader.getParentPos() != NOT_A_DICT_POS) {
         // codePointCount must be incremented at least once in each iteration to ensure preventing
         // infinite loop.
         if (nodeReader.isDeleted() || codePointCount > maxCodePointCount
diff --git a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_reading_utils.h b/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_reading_utils.h
index f44c265..5398d7e 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_reading_utils.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_reading_utils.h
@@ -39,8 +39,7 @@
 
     static AK_FORCE_INLINE int getParentPosAndAdvancePosition(const uint8_t *const buffer,
             int *const pos) {
-        const int base = *pos;
-        return base + ByteArrayUtils::readSint24AndAdvancePosition(buffer, pos);
+        return ByteArrayUtils::readSint24AndAdvancePosition(buffer, pos);
     }
 
     static int readChildrenPositionAndAdvancePosition(const uint8_t *const buffer,
diff --git a/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java b/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java
index 8f9ef1d..b3e2ee0 100644
--- a/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java
+++ b/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java
@@ -93,7 +93,7 @@
             final UserHistoryPredictionDictionary dict =
                     PersonalizationDictionaryHelper.getUserHistoryPredictionDictionary(
                             getContext(), locale, mPrefs);
-            dict.isTest = true;
+            dict.mIsTest = true;
 
             addToDict(dict, words);