merge in jb-mr1-release history after reset to jb-mr1-dev
diff --git a/java/res/values-in/strings.xml b/java/res/values-in/strings.xml
index 8273d54..9229910 100644
--- a/java/res/values-in/strings.xml
+++ b/java/res/values-in/strings.xml
@@ -140,7 +140,7 @@
     <string name="enable" msgid="5031294444630523247">"Aktifkan"</string>
     <string name="not_now" msgid="6172462888202790482">"Nanti saja"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Sudah ada gaya masukan yang sama: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
-    <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modus studi daya guna"</string>
+    <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Mode studi daya guna"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Setelan durasi getaran saat tombol ditekan"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Setelan volume suara saat tombol ditekan"</string>
 </resources>
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java
index 0171dc0..06f5db7 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java
@@ -193,7 +193,7 @@
             if (shouldFilterOut(inText, mScript)) {
                 DictAndProximity dictInfo = null;
                 try {
-                    dictInfo = mDictionaryPool.takeOrGetNull();
+                    dictInfo = mDictionaryPool.pollWithDefaultTimeout();
                     if (null == dictInfo) {
                         return AndroidSpellCheckerService.getNotInDictEmptySuggestions();
                     }
@@ -236,7 +236,7 @@
             boolean isInDict = true;
             DictAndProximity dictInfo = null;
             try {
-                dictInfo = mDictionaryPool.takeOrGetNull();
+                dictInfo = mDictionaryPool.pollWithDefaultTimeout();
                 if (null == dictInfo) {
                     return AndroidSpellCheckerService.getNotInDictEmptySuggestions();
                 }
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java b/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java
index 8fc632e..83f82fa 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java
@@ -16,14 +16,24 @@
 
 package com.android.inputmethod.latin.spellcheck;
 
+import android.util.Log;
+
 import java.util.Locale;
 import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
 
 /**
  * A blocking queue that creates dictionaries up to a certain limit as necessary.
+ * As a deadlock-detecting device, if waiting for more than TIMEOUT = 3 seconds, we
+ * will clear the queue and generate its contents again. This is transparent for
+ * the client code, but may help with sloppy clients.
  */
 @SuppressWarnings("serial")
 public class DictionaryPool extends LinkedBlockingQueue<DictAndProximity> {
+    private final static String TAG = DictionaryPool.class.getSimpleName();
+    // How many seconds we wait for a dictionary to become available. Past this delay, we give up in
+    // fear some bug caused a deadlock, and reset the whole pool.
+    private final static int TIMEOUT = 3;
     private final AndroidSpellCheckerService mService;
     private final int mMaxSize;
     private final Locale mLocale;
@@ -41,13 +51,23 @@
     }
 
     @Override
-    public DictAndProximity take() throws InterruptedException {
+    public DictAndProximity poll(final long timeout, final TimeUnit unit)
+            throws InterruptedException {
         final DictAndProximity dict = poll();
         if (null != dict) return dict;
         synchronized(this) {
             if (mSize >= mMaxSize) {
-                // Our pool is already full. Wait until some dictionary is ready.
-                return super.take();
+                // Our pool is already full. Wait until some dictionary is ready, or TIMEOUT
+                // expires to avoid a deadlock.
+                final DictAndProximity result = super.poll(timeout, unit);
+                if (null == result) {
+                    Log.e(TAG, "Deadlock detected ! Resetting dictionary pool");
+                    clear();
+                    mSize = 1;
+                    return mService.createDictAndProximity(mLocale);
+                } else {
+                    return result;
+                }
             } else {
                 ++mSize;
                 return mService.createDictAndProximity(mLocale);
@@ -56,9 +76,9 @@
     }
 
     // Convenience method
-    public DictAndProximity takeOrGetNull() {
+    public DictAndProximity pollWithDefaultTimeout() {
         try {
-            return take();
+            return poll(TIMEOUT, TimeUnit.SECONDS);
         } catch (InterruptedException e) {
             return null;
         }
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerProximityInfo.java b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerProximityInfo.java
index 0103e84..bd92d88 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerProximityInfo.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerProximityInfo.java
@@ -111,6 +111,7 @@
             NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
             NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
             NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+            NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
         };
         static {
             buildProximityIndices(PROXIMITY, INDICES);
diff --git a/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp b/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp
index 545d91a..560b3a5 100644
--- a/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp
+++ b/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp
@@ -37,7 +37,7 @@
 }
 
 static void latinime_Keyboard_release(JNIEnv *env, jobject object, jlong proximityInfo) {
-    ProximityInfo *pi = reinterpret_cast<ProximityInfo*>(proximityInfo);
+    ProximityInfo *pi = reinterpret_cast<ProximityInfo *>(proximityInfo);
     delete pi;
 }
 
diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
index 5a287a1..2add7c9 100644
--- a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
+++ b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
@@ -27,6 +27,7 @@
 #include <sys/mman.h>
 #else // USE_MMAP_FOR_DICTIONARY
 #include <cstdlib>
+#include <cstdio> // for fopen() etc.
 #endif // USE_MMAP_FOR_DICTIONARY
 
 #include "binary_format.h"
@@ -40,7 +41,7 @@
 
 class ProximityInfo;
 
-static void releaseDictBuf(void *dictBuf, const size_t length, int fd);
+static void releaseDictBuf(const void *dictBuf, const size_t length, const int fd);
 
 static jlong latinime_BinaryDictionary_open(JNIEnv *env, jobject object,
         jstring sourceDir, jlong dictOffset, jlong dictSize,
@@ -75,7 +76,7 @@
         AKLOGE("DICT: Can't mmap dictionary. errno=%d", errno);
         return 0;
     }
-    dictBuf = reinterpret_cast<void *>(reinterpret_cast<char *>(dictBuf) + adjust);
+    dictBuf = static_cast<char *>(dictBuf) + adjust;
 #else // USE_MMAP_FOR_DICTIONARY
     /* malloc version */
     FILE *file = 0;
@@ -111,10 +112,10 @@
     }
     Dictionary *dictionary = 0;
     if (BinaryFormat::UNKNOWN_FORMAT
-            == BinaryFormat::detectFormat(reinterpret_cast<uint8_t *>(dictBuf))) {
+            == BinaryFormat::detectFormat(static_cast<uint8_t *>(dictBuf))) {
         AKLOGE("DICT: dictionary format is unknown, bad magic number");
 #ifdef USE_MMAP_FOR_DICTIONARY
-        releaseDictBuf(reinterpret_cast<char *>(dictBuf) - adjust, adjDictSize, fd);
+        releaseDictBuf(static_cast<const char *>(dictBuf) - adjust, adjDictSize, fd);
 #else // USE_MMAP_FOR_DICTIONARY
         releaseDictBuf(dictBuf, 0, 0);
 #endif // USE_MMAP_FOR_DICTIONARY
@@ -134,10 +135,10 @@
         jintArray prevWordCodePointsForBigrams, jboolean useFullEditDistance,
         jcharArray outputCharsArray, jintArray scoresArray, jintArray spaceIndicesArray,
         jintArray outputTypesArray) {
-    Dictionary *dictionary = reinterpret_cast<Dictionary*>(dict);
+    Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
     if (!dictionary) return 0;
-    ProximityInfo *pInfo = reinterpret_cast<ProximityInfo*>(proximityInfo);
-    void *traverseSession = reinterpret_cast<void*>(dicTraverseSession);
+    ProximityInfo *pInfo = reinterpret_cast<ProximityInfo *>(proximityInfo);
+    void *traverseSession = reinterpret_cast<void *>(dicTraverseSession);
 
     // Input values
     int xCoordinates[arraySize];
@@ -199,7 +200,7 @@
 
 static jint latinime_BinaryDictionary_getFrequency(JNIEnv *env, jobject object, jlong dict,
         jintArray wordArray) {
-    Dictionary *dictionary = reinterpret_cast<Dictionary*>(dict);
+    Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
     if (!dictionary) return 0;
     const jsize codePointLength = env->GetArrayLength(wordArray);
     int codePoints[codePointLength];
@@ -209,7 +210,7 @@
 
 static jboolean latinime_BinaryDictionary_isValidBigram(JNIEnv *env, jobject object, jlong dict,
         jintArray wordArray1, jintArray wordArray2) {
-    Dictionary *dictionary = reinterpret_cast<Dictionary*>(dict);
+    Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
     if (!dictionary) return (jboolean) false;
     const jsize codePointLength1 = env->GetArrayLength(wordArray1);
     const jsize codePointLength2 = env->GetArrayLength(wordArray2);
@@ -229,8 +230,8 @@
     env->GetCharArrayRegion(before, 0, beforeLength, beforeChars);
     env->GetCharArrayRegion(after, 0, afterLength, afterChars);
     return Correction::RankingAlgorithm::calcNormalizedScore(
-            reinterpret_cast<unsigned short *>(beforeChars), beforeLength,
-            reinterpret_cast<unsigned short *>(afterChars), afterLength, score);
+            static_cast<unsigned short *>(beforeChars), beforeLength,
+            static_cast<unsigned short *>(afterChars), afterLength, score);
 }
 
 static jint latinime_BinaryDictionary_editDistance(JNIEnv *env, jobject object,
@@ -242,19 +243,17 @@
     env->GetCharArrayRegion(before, 0, beforeLength, beforeChars);
     env->GetCharArrayRegion(after, 0, afterLength, afterChars);
     return Correction::RankingAlgorithm::editDistance(
-            reinterpret_cast<unsigned short *>(beforeChars), beforeLength,
-            reinterpret_cast<unsigned short *>(afterChars), afterLength);
+            static_cast<unsigned short *>(beforeChars), beforeLength,
+            static_cast<unsigned short *>(afterChars), afterLength);
 }
 
 static void latinime_BinaryDictionary_close(JNIEnv *env, jobject object, jlong dict) {
-    Dictionary *dictionary = reinterpret_cast<Dictionary*>(dict);
+    Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
     if (!dictionary) return;
-    void *dictBuf = dictionary->getDict();
+    const void *dictBuf = dictionary->getDict();
     if (!dictBuf) return;
 #ifdef USE_MMAP_FOR_DICTIONARY
-    releaseDictBuf(
-            reinterpret_cast<void *>(
-                    reinterpret_cast<char *>(dictBuf) - dictionary->getDictBufAdjust()),
+    releaseDictBuf(static_cast<const char *>(dictBuf) - dictionary->getDictBufAdjust(),
             dictionary->getDictSize() + dictionary->getDictBufAdjust(), dictionary->getMmapFd());
 #else // USE_MMAP_FOR_DICTIONARY
     releaseDictBuf(dictBuf, 0, 0);
@@ -262,9 +261,9 @@
     delete dictionary;
 }
 
-static void releaseDictBuf(void *dictBuf, const size_t length, int fd) {
+static void releaseDictBuf(const void *dictBuf, const size_t length, const int fd) {
 #ifdef USE_MMAP_FOR_DICTIONARY
-    int ret = munmap(dictBuf, length);
+    int ret = munmap(const_cast<void *>(dictBuf), length);
     if (ret != 0) {
         AKLOGE("DICT: Failure in munmap. ret=%d errno=%d", ret, errno);
     }
@@ -273,7 +272,7 @@
         AKLOGE("DICT: Failure in close. ret=%d errno=%d", ret, errno);
     }
 #else // USE_MMAP_FOR_DICTIONARY
-    free(dictBuf);
+    free(const_cast<void *>(dictBuf));
 #endif // USE_MMAP_FOR_DICTIONARY
 }
 
diff --git a/native/jni/com_android_inputmethod_latin_DicTraverseSession.cpp b/native/jni/com_android_inputmethod_latin_DicTraverseSession.cpp
index 947360e..5d405f1 100644
--- a/native/jni/com_android_inputmethod_latin_DicTraverseSession.cpp
+++ b/native/jni/com_android_inputmethod_latin_DicTraverseSession.cpp
@@ -30,8 +30,8 @@
 
 static void latinime_initDicTraverseSession(JNIEnv *env, jobject object, jlong traverseSession,
         jlong dictionary, jintArray previousWord, jint previousWordLength) {
-    void *ts = reinterpret_cast<void*>(traverseSession);
-    Dictionary *dict = reinterpret_cast<Dictionary*>(dictionary);
+    void *ts = reinterpret_cast<void *>(traverseSession);
+    Dictionary *dict = reinterpret_cast<Dictionary *>(dictionary);
     if (!previousWord) {
         DicTraverseWrapper::initDicTraverseSession(ts, dict, 0, 0);
         return;
@@ -42,7 +42,7 @@
 }
 
 static void latinime_releaseDicTraverseSession(JNIEnv *env, jobject object, jlong traverseSession) {
-    void *ts = reinterpret_cast<void*>(traverseSession);
+    void *ts = reinterpret_cast<void *>(traverseSession);
     DicTraverseWrapper::releaseDicTraverseSession(ts);
 }
 
diff --git a/native/jni/jni_common.cpp b/native/jni/jni_common.cpp
index 1586f25..0da1669 100644
--- a/native/jni/jni_common.cpp
+++ b/native/jni/jni_common.cpp
@@ -34,7 +34,7 @@
     JNIEnv *env = 0;
     jint result = -1;
 
-    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+    if (vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6) != JNI_OK) {
         AKLOGE("ERROR: GetEnv failed");
         goto bail;
     }
diff --git a/native/jni/src/bigram_dictionary.cpp b/native/jni/src/bigram_dictionary.cpp
index df1ebc0..f1d5380 100644
--- a/native/jni/src/bigram_dictionary.cpp
+++ b/native/jni/src/bigram_dictionary.cpp
@@ -60,16 +60,15 @@
         AKLOGI("Bigram: InsertAt -> %d MAX_PREDICTIONS: %d", insertAt, MAX_PREDICTIONS);
     }
     if (insertAt < MAX_PREDICTIONS) {
-        memmove(reinterpret_cast<char *>(bigramFreq) + (insertAt + 1) * sizeof(bigramFreq[0]),
-                reinterpret_cast<char *>(bigramFreq) + insertAt * sizeof(bigramFreq[0]),
+        memmove(bigramFreq + (insertAt + 1),
+                bigramFreq + insertAt,
                 (MAX_PREDICTIONS - insertAt - 1) * sizeof(bigramFreq[0]));
         bigramFreq[insertAt] = frequency;
         outputTypes[insertAt] = Dictionary::KIND_PREDICTION;
-        memmove(reinterpret_cast<char *>(bigramChars)
-                + (insertAt + 1) * MAX_WORD_LENGTH * sizeof(short),
-                reinterpret_cast<char *>(bigramChars) + insertAt * MAX_WORD_LENGTH * sizeof(short),
-                (MAX_PREDICTIONS - insertAt - 1) * sizeof(short) * MAX_WORD_LENGTH);
-        unsigned short *dest = bigramChars + (insertAt    ) * MAX_WORD_LENGTH;
+        memmove(bigramChars + (insertAt + 1) * MAX_WORD_LENGTH,
+                bigramChars + insertAt * MAX_WORD_LENGTH,
+                (MAX_PREDICTIONS - insertAt - 1) * sizeof(bigramChars[0]) * MAX_WORD_LENGTH);
+        unsigned short *dest = bigramChars + insertAt * MAX_WORD_LENGTH;
         while (length--) {
             *dest++ = *word++;
         }
diff --git a/native/jni/src/char_utils.cpp b/native/jni/src/char_utils.cpp
index fc0a059..223291f 100644
--- a/native/jni/src/char_utils.cpp
+++ b/native/jni/src/char_utils.cpp
@@ -885,14 +885,13 @@
 };
 
 static int compare_pair_capital(const void *a, const void *b) {
-    return static_cast<int>(*reinterpret_cast<const unsigned short *>(a))
-            - static_cast<int>(
-                    (reinterpret_cast<const struct LatinCapitalSmallPair *>(b))->capital);
+    return static_cast<int>(*static_cast<const unsigned short *>(a))
+            - static_cast<int>((static_cast<const struct LatinCapitalSmallPair *>(b))->capital);
 }
 
 unsigned short latin_tolower(unsigned short c) {
     struct LatinCapitalSmallPair *p =
-            reinterpret_cast<struct LatinCapitalSmallPair *>(bsearch(&c, SORTED_CHAR_MAP,
+            static_cast<struct LatinCapitalSmallPair *>(bsearch(&c, SORTED_CHAR_MAP,
                     sizeof(SORTED_CHAR_MAP) / sizeof(SORTED_CHAR_MAP[0]),
                     sizeof(SORTED_CHAR_MAP[0]),
                     compare_pair_capital));
diff --git a/native/jni/src/debug.h b/native/jni/src/debug.h
index 2432b1f..4e21640 100644
--- a/native/jni/src/debug.h
+++ b/native/jni/src/debug.h
@@ -58,7 +58,7 @@
 }
 
 static inline void printDebug(const char *tag, int *codes, int codesSize, int MAX_PROXIMITY_CHARS) {
-    unsigned char *buf = reinterpret_cast<unsigned char *>(malloc((1 + codesSize) * sizeof(*buf)));
+    unsigned char *buf = static_cast<unsigned char *>(malloc((1 + codesSize) * sizeof(*buf)));
 
     buf[codesSize] = 0;
     while (--codesSize >= 0) {
diff --git a/native/jni/src/dictionary.cpp b/native/jni/src/dictionary.cpp
index 9e4bd15..158c3fb 100644
--- a/native/jni/src/dictionary.cpp
+++ b/native/jni/src/dictionary.cpp
@@ -32,8 +32,8 @@
 Dictionary::Dictionary(void *dict, int dictSize, int mmapFd, int dictBufAdjust,
         int typedLetterMultiplier, int fullWordMultiplier,
         int maxWordLength, int maxWords, int maxPredictions)
-    : mDict(reinterpret_cast<unsigned char *>(dict)),
-      mOffsetDict((reinterpret_cast<unsigned char *>(dict)) + BinaryFormat::getHeaderSize(mDict)),
+    : mDict(static_cast<unsigned char *>(dict)),
+      mOffsetDict((static_cast<unsigned char *>(dict)) + BinaryFormat::getHeaderSize(mDict)),
       mDictSize(dictSize), mMmapFd(mmapFd), mDictBufAdjust(dictBufAdjust) {
     if (DEBUG_DICT) {
         if (MAX_WORD_LENGTH_INTERNAL < maxWordLength) {
diff --git a/native/jni/src/dictionary.h b/native/jni/src/dictionary.h
index 3b55e5d..fd9e770 100644
--- a/native/jni/src/dictionary.h
+++ b/native/jni/src/dictionary.h
@@ -55,11 +55,11 @@
 
     int getFrequency(const int32_t *word, int length) const;
     bool isValidBigram(const int32_t *word1, int length1, const int32_t *word2, int length2) const;
-    void *getDict() const { // required to release dictionary buffer
-        return reinterpret_cast<void *>(const_cast<unsigned char *>(mDict));
+    const uint8_t *getDict() const { // required to release dictionary buffer
+        return mDict;
     }
-    void *getOffsetDict() const {
-        return reinterpret_cast<void *>(const_cast<unsigned char *>(mOffsetDict));
+    const uint8_t *getOffsetDict() const {
+        return mOffsetDict;
     }
     int getDictSize() const { return mDictSize; }
     int getMmapFd() const { return mMmapFd; }
@@ -72,8 +72,8 @@
 
  private:
     DISALLOW_IMPLICIT_CONSTRUCTORS(Dictionary);
-    const unsigned char *mDict;
-    const unsigned char *mOffsetDict;
+    const uint8_t *mDict;
+    const uint8_t *mOffsetDict;
 
     // Used only for the mmap version of dictionary loading, but we use these as dummy variables
     // also for the malloc version.
diff --git a/native/jni/src/geometry_utils.h b/native/jni/src/geometry_utils.h
index deb0425..146eb80 100644
--- a/native/jni/src/geometry_utils.h
+++ b/native/jni/src/geometry_utils.h
@@ -32,11 +32,6 @@
     return x * x;
 }
 
-static inline float getNormalizedSquaredDistanceFloat(float x1, float y1, float x2, float y2,
-        float scale) {
-    return squareFloat((x1 - x2) / scale) + squareFloat((y1 - y2) / scale);
-}
-
 static inline float getSquaredDistanceFloat(float x1, float y1, float x2, float y2) {
     return squareFloat(x1 - x2) + squareFloat(y1 - y2);
 }
diff --git a/native/jni/src/proximity_info.cpp b/native/jni/src/proximity_info.cpp
index ade78a1..1b9bac0 100644
--- a/native/jni/src/proximity_info.cpp
+++ b/native/jni/src/proximity_info.cpp
@@ -135,6 +135,21 @@
     return false;
 }
 
+static inline float getNormalizedSquaredDistanceFloat(float x1, float y1, float x2, float y2,
+        float scale) {
+    return squareFloat((x1 - x2) / scale) + squareFloat((y1 - y2) / scale);
+}
+
+float ProximityInfo::getNormalizedSquaredDistanceFromCenterFloat(
+        const int keyId, const int x, const int y) const {
+    const float centerX = static_cast<float>(getKeyCenterXOfIdG(keyId));
+    const float centerY = static_cast<float>(getKeyCenterYOfIdG(keyId));
+    const float touchX = static_cast<float>(x);
+    const float touchY = static_cast<float>(y);
+    const float keyWidth = static_cast<float>(getMostCommonKeyWidth());
+    return getNormalizedSquaredDistanceFloat(centerX, centerY, touchX, touchY, keyWidth);
+}
+
 int ProximityInfo::squaredDistanceToEdge(const int keyId, const int x, const int y) const {
     if (keyId < 0) return true; // NOT_A_ID is -1, but return whenever < 0 just in case
     const int left = mKeyXCoordinates[keyId];
@@ -233,6 +248,7 @@
 }
 
 void ProximityInfo::initializeG() {
+    // TODO: Optimize
     for (int i = 0; i < KEY_COUNT; ++i) {
         const int code = mKeyCharCodes[i];
         const int lowerCode = toBaseLowerCase(code);
@@ -285,25 +301,4 @@
     }
     return 0;
 }
-
-// TODO: [Staging] Optimize
-void ProximityInfo::getCenters(int *centerXs, int *centerYs, int *codeToKeyIndex,
-        int *keyToCodeIndex, int *keyCount, int *keyWidth) const {
-    *keyCount = KEY_COUNT;
-    *keyWidth = sqrtf(static_cast<float>(MOST_COMMON_KEY_WIDTH_SQUARE));
-
-    for (int i = 0; i < KEY_COUNT; ++i) {
-        const int code = mKeyCharCodes[i];
-        const int lowerCode = toBaseLowerCase(code);
-        centerXs[i] = mKeyXCoordinates[i] + mKeyWidths[i] / 2;
-        centerYs[i] = mKeyYCoordinates[i] + mKeyHeights[i] / 2;
-        codeToKeyIndex[code] = i;
-        if (code != lowerCode && lowerCode >= 0 && lowerCode <= MAX_CHAR_CODE) {
-            codeToKeyIndex[lowerCode] = i;
-            keyToCodeIndex[i] = lowerCode;
-        } else {
-            keyToCodeIndex[i] = code;
-        }
-    }
-}
 } // namespace latinime
diff --git a/native/jni/src/proximity_info.h b/native/jni/src/proximity_info.h
index 58f2d75..8a407e7 100644
--- a/native/jni/src/proximity_info.h
+++ b/native/jni/src/proximity_info.h
@@ -38,6 +38,8 @@
     ~ProximityInfo();
     bool hasSpaceProximity(const int x, const int y) const;
     int getNormalizedSquaredDistance(const int inputIndex, const int proximityIndex) const;
+    float getNormalizedSquaredDistanceFromCenterFloat(
+            const int keyId, const int x, const int y) const;
     bool sameAsTyped(const unsigned short *word, int length) const;
     int squaredDistanceToEdge(const int keyId, const int x, const int y) const;
     bool isOnKey(const int keyId, const int x, const int y) const {
diff --git a/native/jni/src/words_priority_queue.h b/native/jni/src/words_priority_queue.h
index e97e16a..1e4e00a 100644
--- a/native/jni/src/words_priority_queue.h
+++ b/native/jni/src/words_priority_queue.h
@@ -140,13 +140,12 @@
                 continue;
             }
             const unsigned int wordLength = sw->mWordLength;
-            char *targetAddress = reinterpret_cast<char *>(outputChars)
-                    + i * MAX_WORD_LENGTH * sizeof(short);
+            unsigned short *targetAddress = outputChars + i * MAX_WORD_LENGTH;
             frequencies[i] = sw->mScore;
             outputTypes[i] = sw->mType;
-            memcpy(targetAddress, sw->mWord, (wordLength) * sizeof(short));
+            memcpy(targetAddress, sw->mWord, wordLength * sizeof(unsigned short));
             if (wordLength < MAX_WORD_LENGTH) {
-                reinterpret_cast<unsigned short *>(targetAddress)[wordLength] = 0;
+                targetAddress[wordLength] = 0;
             }
             sw->mUsed = false;
         }
@@ -223,7 +222,7 @@
                 before, beforeLength, word, wordLength, score);
     }
 
-    typedef std::priority_queue<SuggestedWord*, std::vector<SuggestedWord*>,
+    typedef std::priority_queue<SuggestedWord *, std::vector<SuggestedWord *>,
             wordComparator> Suggestions;
     Suggestions mSuggestions;
     const unsigned int MAX_WORDS;