Merge "Separate SuggestionStripLayoutHelper for readablity"
diff --git a/java/src/com/android/inputmethod/dictionarypack/ButtonSwitcher.java b/java/src/com/android/inputmethod/dictionarypack/ButtonSwitcher.java
index 5ab94a4..c5aca17 100644
--- a/java/src/com/android/inputmethod/dictionarypack/ButtonSwitcher.java
+++ b/java/src/com/android/inputmethod/dictionarypack/ButtonSwitcher.java
@@ -57,6 +57,11 @@
         super(context, attrs, defStyle);
     }
 
+    public void reset() {
+        mStatus = NOT_INITIALIZED;
+        mAnimateToStatus = NOT_INITIALIZED;
+    }
+
     @Override
     protected void onLayout(final boolean changed, final int left, final int top, final int right,
             final int bottom) {
@@ -64,9 +69,7 @@
         mInstallButton = (Button)findViewById(R.id.dict_install_button);
         mCancelButton = (Button)findViewById(R.id.dict_cancel_button);
         mDeleteButton = (Button)findViewById(R.id.dict_delete_button);
-        mInstallButton.setOnClickListener(mOnClickListener);
-        mCancelButton.setOnClickListener(mOnClickListener);
-        mDeleteButton.setOnClickListener(mOnClickListener);
+        setInternalOnClickListener(mOnClickListener);
         setButtonPositionWithoutAnimation(mStatus);
         if (mAnimateToStatus != NOT_INITIALIZED) {
             // We have been asked to animate before we were ready, so we took a note of it.
@@ -139,6 +142,12 @@
 
     public void setInternalOnClickListener(final OnClickListener listener) {
         mOnClickListener = listener;
+        if (null != mInstallButton) {
+            // Already laid out : do it now
+            mInstallButton.setOnClickListener(mOnClickListener);
+            mCancelButton.setOnClickListener(mOnClickListener);
+            mDeleteButton.setOnClickListener(mOnClickListener);
+        }
     }
 
     private ViewPropertyAnimator animateButton(final View button, final int direction) {
diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionaryListInterfaceState.java b/java/src/com/android/inputmethod/dictionarypack/DictionaryListInterfaceState.java
index de3711c..5ad5900 100644
--- a/java/src/com/android/inputmethod/dictionarypack/DictionaryListInterfaceState.java
+++ b/java/src/com/android/inputmethod/dictionarypack/DictionaryListInterfaceState.java
@@ -16,8 +16,11 @@
 
 package com.android.inputmethod.dictionarypack;
 
+import android.view.View;
+
 import com.android.inputmethod.latin.CollectionUtils;
 
+import java.util.ArrayList;
 import java.util.HashMap;
 
 /**
@@ -37,6 +40,7 @@
     }
 
     private HashMap<String, State> mWordlistToState = CollectionUtils.newHashMap();
+    private ArrayList<View> mViewCache = CollectionUtils.newArrayList();
 
     public boolean isOpen(final String wordlistId) {
         final State state = mWordlistToState.get(wordlistId);
@@ -64,4 +68,16 @@
             state.mOpen = false;
         }
     }
+
+    public View findFirstOrphanedView() {
+        for (final View v : mViewCache) {
+            if (null == v.getParent()) return v;
+        }
+        return null;
+    }
+
+    public View addToCacheAndReturnView(final View view) {
+        mViewCache.add(view);
+        return view;
+    }
 }
diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java b/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java
index 6183223..1e93e7e 100644
--- a/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java
+++ b/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java
@@ -222,7 +222,9 @@
                     refreshNetworkState();
 
                     removeAnyDictSettings(prefScreen);
+                    int i = 0;
                     for (Preference preference : prefList) {
+                        preference.setOrder(i++);
                         prefScreen.addPreference(preference);
                     }
                 }
diff --git a/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java b/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java
index 03ed267..1511dbc 100644
--- a/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java
+++ b/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java
@@ -572,7 +572,8 @@
      * If several clients use the same metadata URL, we know to only download it once, and
      * dispatch the update process across all relevant clients when the download ends. This means
      * several clients may share a single download ID if they share a metadata URI.
-     * The dispatching is done in {@link UpdateHandler#downloadFinished(Context, Intent)}, which
+     * The dispatching is done in
+     * {@link UpdateHandler#downloadFinished(Context, android.content.Intent)}, which
      * finds out about the list of relevant clients by calling this method.
      *
      * @param context a context instance to open the databases
@@ -863,17 +864,20 @@
                                 r.getAsString(WORDLISTID_COLUMN),
                                 Integer.toString(STATUS_INSTALLED) },
                         null, null, null);
-                if (c.moveToFirst()) {
-                    // There should never be more than one file, but if there are, it's a bug
-                    // and we should remove them all. I think it might happen if the power of the
-                    // phone is suddenly cut during an update.
-                    final int filenameIndex = c.getColumnIndex(LOCAL_FILENAME_COLUMN);
-                    do {
-                        Utils.l("Setting for removal", c.getString(filenameIndex));
-                        filenames.add(c.getString(filenameIndex));
-                    } while (c.moveToNext());
+                try {
+                    if (c.moveToFirst()) {
+                        // There should never be more than one file, but if there are, it's a bug
+                        // and we should remove them all. I think it might happen if the power of
+                        // the phone is suddenly cut during an update.
+                        final int filenameIndex = c.getColumnIndex(LOCAL_FILENAME_COLUMN);
+                        do {
+                            Utils.l("Setting for removal", c.getString(filenameIndex));
+                            filenames.add(c.getString(filenameIndex));
+                        } while (c.moveToNext());
+                    }
+                } finally {
+                    c.close();
                 }
-
                 r.put(STATUS_COLUMN, STATUS_INSTALLED);
                 db.beginTransactionNonExclusive();
                 // Delete all old entries. There should never be any stalled entries, but if
diff --git a/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java b/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java
index 451a0fb..a1031c2 100644
--- a/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java
+++ b/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java
@@ -98,6 +98,14 @@
         setSummary(getSummary(status));
     }
 
+    @Override
+    public View onCreateView(final ViewGroup parent) {
+        final View orphanedView = mInterfaceState.findFirstOrphanedView();
+        if (null != orphanedView) return orphanedView; // Will be sent to onBindView
+        final View newView = super.onCreateView(parent);
+        return mInterfaceState.addToCacheAndReturnView(newView);
+    }
+
     private String getSummary(final int status) {
         switch (status) {
             // If we are deleting the word list, for the user it's like it's already deleted.
@@ -209,6 +217,9 @@
 
         final ButtonSwitcher buttonSwitcher =
                 (ButtonSwitcher)view.findViewById(R.id.wordlist_button_switcher);
+        // We need to clear the state of the button switcher, because we reuse views; if we didn't
+        // reset it would animate from whatever its old state was.
+        buttonSwitcher.reset();
         if (mInterfaceState.isOpen(mWordlistId)) {
             // The button is open.
             final int previousStatus = mInterfaceState.getStatus(mWordlistId);
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
index a9b58de..603e8d3 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
@@ -32,6 +32,7 @@
 
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
+import java.io.Closeable;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
@@ -319,20 +320,12 @@
                 // Try the next method.
             } finally {
                 // Ignore exceptions while closing files.
-                try {
-                    if (null != afd) afd.close();
-                    if (null != inputStream) inputStream.close();
-                    if (null != uncompressedStream) uncompressedStream.close();
-                    if (null != decryptedStream) decryptedStream.close();
-                    if (null != bufferedInputStream) bufferedInputStream.close();
-                } catch (Exception e) {
-                    Log.e(TAG, "Exception while closing a file descriptor", e);
-                }
-                try {
-                    if (null != bufferedOutputStream) bufferedOutputStream.close();
-                } catch (Exception e) {
-                    Log.e(TAG, "Exception while closing a file", e);
-                }
+                closeAssetFileDescriptorAndReportAnyException(afd);
+                closeCloseableAndReportAnyException(inputStream);
+                closeCloseableAndReportAnyException(uncompressedStream);
+                closeCloseableAndReportAnyException(decryptedStream);
+                closeCloseableAndReportAnyException(bufferedInputStream);
+                closeCloseableAndReportAnyException(bufferedOutputStream);
             }
         }
 
@@ -352,6 +345,26 @@
         }
     }
 
+    // Ideally the two following methods should be merged, but AssetFileDescriptor does not
+    // implement Closeable although it does implement #close(), and Java does not have
+    // structural typing.
+    private static void closeAssetFileDescriptorAndReportAnyException(
+            final AssetFileDescriptor file) {
+        try {
+            if (null != file) file.close();
+        } catch (Exception e) {
+            Log.e(TAG, "Exception while closing a file", e);
+        }
+    }
+
+    private static void closeCloseableAndReportAnyException(final Closeable file) {
+        try {
+            if (null != file) file.close();
+        } catch (Exception e) {
+            Log.e(TAG, "Exception while closing a file", e);
+        }
+    }
+
     /**
      * Queries a content provider for word list data for some locale and cache the returned files
      *
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index cebc93c..c9a42a3 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -855,6 +855,7 @@
         }
         // Remove pending messages related to update suggestions
         mHandler.cancelUpdateSuggestionStrip();
+        if (mWordComposer.isComposingWord()) mConnection.finishComposingText();
         resetComposingState(true /* alsoResetLastComposedWord */);
         // Notify ResearchLogger
         if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
diff --git a/native/jni/Android.mk b/native/jni/Android.mk
index cbe9515..ea35dab 100644
--- a/native/jni/Android.mk
+++ b/native/jni/Android.mk
@@ -46,17 +46,12 @@
     jni_common.cpp
 
 LATIN_IME_CORE_SRC_FILES := \
-    additional_proximity_chars.cpp \
     bigram_dictionary.cpp \
     char_utils.cpp \
     correction.cpp \
     dictionary.cpp \
     dic_traverse_wrapper.cpp \
     digraph_utils.cpp \
-    proximity_info.cpp \
-    proximity_info_params.cpp \
-    proximity_info_state.cpp \
-    proximity_info_state_utils.cpp \
     unigram_dictionary.cpp \
     words_priority_queue.cpp \
     suggest/core/suggest.cpp \
@@ -64,6 +59,12 @@
         dic_node.cpp \
         dic_node_utils.cpp \
         dic_nodes_cache.cpp) \
+    $(addprefix suggest/core/layout/, \
+        additional_proximity_chars.cpp \
+        proximity_info.cpp \
+        proximity_info_params.cpp \
+        proximity_info_state.cpp \
+        proximity_info_state_utils.cpp) \
     suggest/core/policy/weighting.cpp \
     suggest/core/session/dic_traverse_session.cpp \
     suggest/policyimpl/gesture/gesture_suggest_policy_factory.cpp \
diff --git a/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp b/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp
index dedb02a..e312aea 100644
--- a/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp
+++ b/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp
@@ -17,10 +17,11 @@
 #define LOG_TAG "LatinIME: jni: ProximityInfo"
 
 #include "com_android_inputmethod_keyboard_ProximityInfo.h"
+
 #include "defines.h"
 #include "jni.h"
 #include "jni_common.h"
-#include "proximity_info.h"
+#include "suggest/core/layout/proximity_info.h"
 
 namespace latinime {
 
diff --git a/native/jni/src/correction.cpp b/native/jni/src/correction.cpp
index 61bf3f6..e2ad557 100644
--- a/native/jni/src/correction.cpp
+++ b/native/jni/src/correction.cpp
@@ -21,8 +21,8 @@
 #include "char_utils.h"
 #include "correction.h"
 #include "defines.h"
-#include "proximity_info_state.h"
-#include "suggest_utils.h"
+#include "suggest/core/layout/proximity_info_state.h"
+#include "suggest/core/layout/touch_position_correction_utils.h"
 #include "suggest/policyimpl/utils/edit_distance.h"
 #include "suggest/policyimpl/utils/damerau_levenshtein_edit_distance_policy.h"
 
@@ -676,8 +676,8 @@
             if (i < adjustedProximityMatchedCount) {
                 multiplyIntCapped(typedLetterMultiplier, &finalFreq);
             }
-            const float factor =
-                    SuggestUtils::getLengthScalingFactor(static_cast<float>(squaredDistance));
+            const float factor = TouchPositionCorrectionUtils::getLengthScalingFactor(
+                    static_cast<float>(squaredDistance));
             if (factor > 0.0f) {
                 multiplyRate(static_cast<int>(factor * 100.0f), &finalFreq);
             } else if (squaredDistance == PROXIMITY_CHAR_WITHOUT_DISTANCE_INFO) {
diff --git a/native/jni/src/correction.h b/native/jni/src/correction.h
index a9e9b48..75b4995 100644
--- a/native/jni/src/correction.h
+++ b/native/jni/src/correction.h
@@ -21,7 +21,7 @@
 
 #include "correction_state.h"
 #include "defines.h"
-#include "proximity_info_state.h"
+#include "suggest/core/layout/proximity_info_state.h"
 
 namespace latinime {
 
diff --git a/native/jni/src/geometry_utils.h b/native/jni/src/geometry_utils.h
deleted file mode 100644
index 4cbb127..0000000
--- a/native/jni/src/geometry_utils.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-#ifndef LATINIME_GEOMETRY_UTILS_H
-#define LATINIME_GEOMETRY_UTILS_H
-
-#include <cmath>
-
-#include "defines.h"
-
-#define ROUND_FLOAT_10000(f) ((f) < 1000.0f && (f) > 0.001f) \
-        ? (floorf((f) * 10000.0f) / 10000.0f) : (f)
-
-namespace latinime {
-
-static inline float SQUARE_FLOAT(const float x) { return x * x; }
-
-static AK_FORCE_INLINE float getAngle(const int x1, const int y1, const int x2, const int y2) {
-    const int dx = x1 - x2;
-    const int dy = y1 - y2;
-    if (dx == 0 && dy == 0) return 0.0f;
-    return atan2f(static_cast<float>(dy), static_cast<float>(dx));
-}
-
-static AK_FORCE_INLINE float getAngleDiff(const float a1, const float a2) {
-    const float deltaA = fabsf(a1 - a2);
-    const float diff = ROUND_FLOAT_10000(deltaA);
-    if (diff > M_PI_F) {
-        const float normalizedDiff = 2.0f * M_PI_F - diff;
-        return ROUND_FLOAT_10000(normalizedDiff);
-    }
-    return diff;
-}
-
-static AK_FORCE_INLINE int getDistanceInt(const int x1, const int y1, const int x2,
-        const int y2) {
-    return static_cast<int>(hypotf(static_cast<float>(x1 - x2), static_cast<float>(y1 - y2)));
-}
-} // namespace latinime
-#endif // LATINIME_GEOMETRY_UTILS_H
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp b/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp
index 5357c37..4fe4bad 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp
+++ b/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp
@@ -22,8 +22,8 @@
 #include "dic_node_utils.h"
 #include "dic_node_vector.h"
 #include "multi_bigram_map.h"
-#include "proximity_info.h"
-#include "proximity_info_state.h"
+#include "suggest/core/layout/proximity_info.h"
+#include "suggest/core/layout/proximity_info_state.h"
 
 namespace latinime {
 
diff --git a/native/jni/src/additional_proximity_chars.cpp b/native/jni/src/suggest/core/layout/additional_proximity_chars.cpp
similarity index 95%
rename from native/jni/src/additional_proximity_chars.cpp
rename to native/jni/src/suggest/core/layout/additional_proximity_chars.cpp
index 661c50e..34b8b37 100644
--- a/native/jni/src/additional_proximity_chars.cpp
+++ b/native/jni/src/suggest/core/layout/additional_proximity_chars.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "additional_proximity_chars.h"
+#include "suggest/core/layout/additional_proximity_chars.h"
 
 namespace latinime {
 // TODO: Stop using hardcoded additional proximity characters.
diff --git a/native/jni/src/additional_proximity_chars.h b/native/jni/src/suggest/core/layout/additional_proximity_chars.h
similarity index 100%
rename from native/jni/src/additional_proximity_chars.h
rename to native/jni/src/suggest/core/layout/additional_proximity_chars.h
diff --git a/native/jni/src/suggest/core/layout/geometry_utils.h b/native/jni/src/suggest/core/layout/geometry_utils.h
new file mode 100644
index 0000000..b667df6
--- /dev/null
+++ b/native/jni/src/suggest/core/layout/geometry_utils.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#ifndef LATINIME_GEOMETRY_UTILS_H
+#define LATINIME_GEOMETRY_UTILS_H
+
+#include <cmath>
+
+#include "defines.h"
+
+#define ROUND_FLOAT_10000(f) ((f) < 1000.0f && (f) > 0.001f) \
+        ? (floorf((f) * 10000.0f) / 10000.0f) : (f)
+
+namespace latinime {
+
+class GeometryUtils {
+ public:
+    static inline float SQUARE_FLOAT(const float x) { return x * x; }
+
+    static AK_FORCE_INLINE float getAngle(const int x1, const int y1, const int x2, const int y2) {
+        const int dx = x1 - x2;
+        const int dy = y1 - y2;
+        if (dx == 0 && dy == 0) return 0.0f;
+        return atan2f(static_cast<float>(dy), static_cast<float>(dx));
+    }
+
+    static AK_FORCE_INLINE float getAngleDiff(const float a1, const float a2) {
+        const float deltaA = fabsf(a1 - a2);
+        const float diff = ROUND_FLOAT_10000(deltaA);
+        if (diff > M_PI_F) {
+            const float normalizedDiff = 2.0f * M_PI_F - diff;
+            return ROUND_FLOAT_10000(normalizedDiff);
+        }
+        return diff;
+    }
+
+    static AK_FORCE_INLINE int getDistanceInt(const int x1, const int y1, const int x2,
+            const int y2) {
+        return static_cast<int>(hypotf(static_cast<float>(x1 - x2), static_cast<float>(y1 - y2)));
+    }
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(GeometryUtils);
+};
+} // namespace latinime
+#endif // LATINIME_GEOMETRY_UTILS_H
diff --git a/native/jni/src/proximity_info.cpp b/native/jni/src/suggest/core/layout/proximity_info.cpp
similarity index 94%
rename from native/jni/src/proximity_info.cpp
rename to native/jni/src/suggest/core/layout/proximity_info.cpp
index 88d670d..995e104 100644
--- a/native/jni/src/proximity_info.cpp
+++ b/native/jni/src/suggest/core/layout/proximity_info.cpp
@@ -14,18 +14,19 @@
  * limitations under the License.
  */
 
+#include "suggest/core/layout/proximity_info.h"
+
 #include <cstring>
 #include <cmath>
 
 #define LOG_TAG "LatinIME: proximity_info.cpp"
 
-#include "additional_proximity_chars.h"
 #include "char_utils.h"
 #include "defines.h"
-#include "geometry_utils.h"
 #include "jni.h"
-#include "proximity_info.h"
-#include "proximity_info_params.h"
+#include "suggest/core/layout/additional_proximity_chars.h"
+#include "suggest/core/layout/geometry_utils.h"
+#include "suggest/core/layout/proximity_info_params.h"
 
 namespace latinime {
 
@@ -58,7 +59,7 @@
           MOST_COMMON_KEY_WIDTH_SQUARE(mostCommonKeyWidth * mostCommonKeyWidth),
           MOST_COMMON_KEY_HEIGHT(mostCommonKeyHeight),
           NORMALIZED_SQUARED_MOST_COMMON_KEY_HYPOTENUSE(1.0f +
-                  SQUARE_FLOAT(static_cast<float>(mostCommonKeyHeight) /
+                  GeometryUtils::SQUARE_FLOAT(static_cast<float>(mostCommonKeyHeight) /
                           static_cast<float>(mostCommonKeyWidth))),
           CELL_WIDTH((keyboardWidth + gridWidth - 1) / gridWidth),
           CELL_HEIGHT((keyboardHeight + gridHeight - 1) / gridHeight),
@@ -150,7 +151,7 @@
     const float touchY = static_cast<float>(y);
     const float keyWidth = static_cast<float>(getMostCommonKeyWidth());
     return ProximityInfoUtils::getSquaredDistanceFloat(centerX, centerY, touchX, touchY)
-            / SQUARE_FLOAT(keyWidth);
+            / GeometryUtils::SQUARE_FLOAT(keyWidth);
 }
 
 int ProximityInfo::getCodePointOf(const int keyIndex) const {
@@ -173,7 +174,7 @@
     for (int i = 0; i < KEY_COUNT; i++) {
         mKeyKeyDistancesG[i][i] = 0;
         for (int j = i + 1; j < KEY_COUNT; j++) {
-            mKeyKeyDistancesG[i][j] = getDistanceInt(
+            mKeyKeyDistancesG[i][j] = GeometryUtils::getDistanceInt(
                     mCenterXsG[i], mCenterYsG[i], mCenterXsG[j], mCenterYsG[j]);
             mKeyKeyDistancesG[j][i] = mKeyKeyDistancesG[i][j];
         }
diff --git a/native/jni/src/proximity_info.h b/native/jni/src/suggest/core/layout/proximity_info.h
similarity index 98%
rename from native/jni/src/proximity_info.h
rename to native/jni/src/suggest/core/layout/proximity_info.h
index deb9ae0..6d2ddd4 100644
--- a/native/jni/src/proximity_info.h
+++ b/native/jni/src/suggest/core/layout/proximity_info.h
@@ -20,7 +20,7 @@
 #include "defines.h"
 #include "hash_map_compat.h"
 #include "jni.h"
-#include "proximity_info_utils.h"
+#include "suggest/core/layout/proximity_info_utils.h"
 
 namespace latinime {
 
diff --git a/native/jni/src/proximity_info_params.cpp b/native/jni/src/suggest/core/layout/proximity_info_params.cpp
similarity index 98%
rename from native/jni/src/proximity_info_params.cpp
rename to native/jni/src/suggest/core/layout/proximity_info_params.cpp
index 2675d9e..0e887f7 100644
--- a/native/jni/src/proximity_info_params.cpp
+++ b/native/jni/src/suggest/core/layout/proximity_info_params.cpp
@@ -15,7 +15,7 @@
  */
 
 #include "defines.h"
-#include "proximity_info_params.h"
+#include "suggest/core/layout/proximity_info_params.h"
 
 namespace latinime {
 const float ProximityInfoParams::NOT_A_DISTANCE_FLOAT = -1.0f;
diff --git a/native/jni/src/proximity_info_params.h b/native/jni/src/suggest/core/layout/proximity_info_params.h
similarity index 100%
rename from native/jni/src/proximity_info_params.h
rename to native/jni/src/suggest/core/layout/proximity_info_params.h
diff --git a/native/jni/src/proximity_info_state.cpp b/native/jni/src/suggest/core/layout/proximity_info_state.cpp
similarity index 98%
rename from native/jni/src/proximity_info_state.cpp
rename to native/jni/src/suggest/core/layout/proximity_info_state.cpp
index cc5b736..fb57174 100644
--- a/native/jni/src/proximity_info_state.cpp
+++ b/native/jni/src/suggest/core/layout/proximity_info_state.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include "suggest/core/layout/proximity_info_state.h"
+
 #include <cstring> // for memset() and memcpy()
 #include <sstream> // for debug prints
 #include <vector>
@@ -21,10 +23,9 @@
 #define LOG_TAG "LatinIME: proximity_info_state.cpp"
 
 #include "defines.h"
-#include "geometry_utils.h"
-#include "proximity_info.h"
-#include "proximity_info_state.h"
-#include "proximity_info_state_utils.h"
+#include "suggest/core/layout/geometry_utils.h"
+#include "suggest/core/layout/proximity_info.h"
+#include "suggest/core/layout/proximity_info_state_utils.h"
 
 namespace latinime {
 
diff --git a/native/jni/src/proximity_info_state.h b/native/jni/src/suggest/core/layout/proximity_info_state.h
similarity index 98%
rename from native/jni/src/proximity_info_state.h
rename to native/jni/src/suggest/core/layout/proximity_info_state.h
index bbe8af2..fd09307 100644
--- a/native/jni/src/proximity_info_state.h
+++ b/native/jni/src/suggest/core/layout/proximity_info_state.h
@@ -23,8 +23,8 @@
 #include "char_utils.h"
 #include "defines.h"
 #include "hash_map_compat.h"
-#include "proximity_info_params.h"
-#include "proximity_info_state_utils.h"
+#include "suggest/core/layout/proximity_info_params.h"
+#include "suggest/core/layout/proximity_info_state_utils.h"
 
 namespace latinime {
 
diff --git a/native/jni/src/proximity_info_state_utils.cpp b/native/jni/src/suggest/core/layout/proximity_info_state_utils.cpp
similarity index 95%
rename from native/jni/src/proximity_info_state_utils.cpp
rename to native/jni/src/suggest/core/layout/proximity_info_state_utils.cpp
index 359673c..6f88833 100644
--- a/native/jni/src/proximity_info_state_utils.cpp
+++ b/native/jni/src/suggest/core/layout/proximity_info_state_utils.cpp
@@ -14,16 +14,17 @@
  * limitations under the License.
  */
 
+#include "suggest/core/layout/proximity_info_state_utils.h"
+
 #include <cmath>
 #include <cstring> // for memset()
 #include <sstream> // for debug prints
 #include <vector>
 
 #include "defines.h"
-#include "geometry_utils.h"
-#include "proximity_info.h"
-#include "proximity_info_params.h"
-#include "proximity_info_state_utils.h"
+#include "suggest/core/layout/geometry_utils.h"
+#include "suggest/core/layout/proximity_info.h"
+#include "suggest/core/layout/proximity_info_params.h"
 
 namespace latinime {
 
@@ -103,12 +104,12 @@
             const int time = times ? times[i] : -1;
 
             if (i > 1) {
-                const float prevAngle = getAngle(
+                const float prevAngle = GeometryUtils::getAngle(
                         inputXCoordinates[i - 2], inputYCoordinates[i - 2],
                         inputXCoordinates[i - 1], inputYCoordinates[i - 1]);
-                const float currentAngle = getAngle(
+                const float currentAngle = GeometryUtils::getAngle(
                         inputXCoordinates[i - 1], inputYCoordinates[i - 1], x, y);
-                sumAngle += getAngleDiff(prevAngle, currentAngle);
+                sumAngle += GeometryUtils::getAngleDiff(prevAngle, currentAngle);
             }
 
             if (pushTouchPoint(proximityInfo, maxPointToKeyLength, i, c, x, y, time,
@@ -157,7 +158,8 @@
     const float sweetSpotCenterY = proximityInfo->getSweetSpotCenterYAt(keyIndex);
     const float inputX = static_cast<float>((*sampledInputXs)[inputIndex]);
     const float inputY = static_cast<float>((*sampledInputYs)[inputIndex]);
-    return SQUARE_FLOAT(inputX - sweetSpotCenterX) + SQUARE_FLOAT(inputY - sweetSpotCenterY);
+    return GeometryUtils::SQUARE_FLOAT(inputX - sweetSpotCenterX)
+            + GeometryUtils::SQUARE_FLOAT(inputY - sweetSpotCenterY);
 }
 
 /* static */ float ProximityInfoStateUtils::calculateNormalizedSquaredDistance(
@@ -174,7 +176,8 @@
     }
     const float squaredDistance = calculateSquaredDistanceFromSweetSpotCenter(proximityInfo,
             sampledInputXs, sampledInputYs, keyIndex, inputIndex);
-    const float squaredRadius = SQUARE_FLOAT(proximityInfo->getSweetSpotRadiiAt(keyIndex));
+    const float squaredRadius = GeometryUtils::SQUARE_FLOAT(
+            proximityInfo->getSweetSpotRadiiAt(keyIndex));
     return squaredDistance / squaredRadius;
 }
 
@@ -285,7 +288,7 @@
             if (i < sampledInputSize - 1 && j >= (*sampledInputIndice)[i + 1]) {
                 break;
             }
-            length += getDistanceInt(xCoordinates[j], yCoordinates[j],
+            length += GeometryUtils::getDistanceInt(xCoordinates[j], yCoordinates[j],
                     xCoordinates[j + 1], yCoordinates[j + 1]);
             duration += times[j + 1] - times[j];
         }
@@ -296,7 +299,7 @@
                 break;
             }
             // TODO: use mSampledLengthCache instead?
-            length += getDistanceInt(xCoordinates[j], yCoordinates[j],
+            length += GeometryUtils::getDistanceInt(xCoordinates[j], yCoordinates[j],
                     xCoordinates[j + 1], yCoordinates[j + 1]);
             duration += times[j + 1] - times[j];
         }
@@ -349,7 +352,7 @@
     const int y1 = (*sampledInputYs)[index0];
     const int x2 = (*sampledInputXs)[index1];
     const int y2 = (*sampledInputYs)[index1];
-    return getAngle(x1, y1, x2, y2);
+    return GeometryUtils::getAngle(x1, y1, x2, y2);
 }
 
 // Calculating point to key distance for all near keys and returning the distance between
@@ -411,9 +414,9 @@
     }
 
     const int baseSampleRate = mostCommonKeyWidth;
-    const int distPrev = getDistanceInt(sampledInputXs->back(), sampledInputYs->back(),
-            (*sampledInputXs)[size - 2], (*sampledInputYs)[size - 2])
-                    * ProximityInfoParams::DISTANCE_BASE_SCALE;
+    const int distPrev = GeometryUtils::getDistanceInt(sampledInputXs->back(),
+            sampledInputYs->back(), (*sampledInputXs)[size - 2],
+            (*sampledInputYs)[size - 2]) * ProximityInfoParams::DISTANCE_BASE_SCALE;
     float score = 0.0f;
 
     // Location
@@ -425,10 +428,11 @@
         score += ProximityInfoParams::LOCALMIN_DISTANCE_AND_NEAR_TO_KEY_SCORE;
     }
     // Angle
-    const float angle1 = getAngle(x, y, sampledInputXs->back(), sampledInputYs->back());
-    const float angle2 = getAngle(sampledInputXs->back(), sampledInputYs->back(),
+    const float angle1 = GeometryUtils::getAngle(x, y, sampledInputXs->back(),
+            sampledInputYs->back());
+    const float angle2 = GeometryUtils::getAngle(sampledInputXs->back(), sampledInputYs->back(),
             (*sampledInputXs)[size - 2], (*sampledInputYs)[size - 2]);
-    const float angleDiff = getAngleDiff(angle1, angle2);
+    const float angleDiff = GeometryUtils::getAngleDiff(angle1, angle2);
 
     // Save corner
     if (distPrev > baseSampleRate * ProximityInfoParams::CORNER_CHECK_DISTANCE_THRESHOLD_SCALE
@@ -472,13 +476,13 @@
         }
         // Check if the last point should be skipped.
         if (isLastPoint && size > 0) {
-            if (getDistanceInt(x, y, sampledInputXs->back(), sampledInputYs->back())
+            if (GeometryUtils::getDistanceInt(x, y, sampledInputXs->back(), sampledInputYs->back())
                     * ProximityInfoParams::LAST_POINT_SKIP_DISTANCE_SCALE < mostCommonKeyWidth) {
                 // This point is not used because it's too close to the previous point.
                 if (DEBUG_GEO_FULL) {
                     AKLOGI("p0: size = %zd, x = %d, y = %d, lx = %d, ly = %d, dist = %d, "
                            "width = %d", size, x, y, sampledInputXs->back(),
-                           sampledInputYs->back(), getDistanceInt(
+                           sampledInputYs->back(), GeometryUtils::getDistanceInt(
                                    x, y, sampledInputXs->back(), sampledInputYs->back()),
                            mostCommonKeyWidth
                                    / ProximityInfoParams::LAST_POINT_SKIP_DISTANCE_SCALE);
@@ -499,7 +503,7 @@
     // Pushing point information.
     if (size > 0) {
         sampledLengthCache->push_back(
-                sampledLengthCache->back() + getDistanceInt(
+                sampledLengthCache->back() + GeometryUtils::getDistanceInt(
                         x, y, sampledInputXs->back(), sampledInputYs->back()));
     } else {
         sampledLengthCache->push_back(0);
@@ -540,7 +544,8 @@
     while (start > 0 && tempBeelineDistance < lookupRadius) {
         tempTime += times[start] - times[start - 1];
         --start;
-        tempBeelineDistance = getDistanceInt(x0, y0, xCoordinates[start], yCoordinates[start]);
+        tempBeelineDistance = GeometryUtils::getDistanceInt(x0, y0, xCoordinates[start],
+                yCoordinates[start]);
     }
     // Exclusive unless this is an edge point
     if (start > 0 && start < actualInputIndex) {
@@ -553,7 +558,8 @@
     while (end < (inputSize - 1) && tempBeelineDistance < lookupRadius) {
         tempTime += times[end + 1] - times[end];
         ++end;
-        tempBeelineDistance = getDistanceInt(x0, y0, xCoordinates[end], yCoordinates[end]);
+        tempBeelineDistance = GeometryUtils::getDistanceInt(x0, y0, xCoordinates[end],
+                yCoordinates[end]);
     }
     // Exclusive unless this is an edge point
     if (end > actualInputIndex && end < (inputSize - 1)) {
@@ -571,7 +577,7 @@
     const int y2 = yCoordinates[start];
     const int x3 = xCoordinates[end];
     const int y3 = yCoordinates[end];
-    const int beelineDistance = getDistanceInt(x2, y2, x3, y3);
+    const int beelineDistance = GeometryUtils::getDistanceInt(x2, y2, x3, y3);
     int adjustedStartTime = times[start];
     if (start == 0 && actualInputIndex == 0 && inputSize > 1) {
         adjustedStartTime += ProximityInfoParams::FIRST_POINT_TIME_OFFSET_MILLIS;
@@ -613,7 +619,7 @@
     }
     const float previousDirection = getDirection(sampledInputXs, sampledInputYs, index - 1, index);
     const float nextDirection = getDirection(sampledInputXs, sampledInputYs, index, index + 1);
-    const float directionDiff = getAngleDiff(previousDirection, nextDirection);
+    const float directionDiff = GeometryUtils::getAngleDiff(previousDirection, nextDirection);
     return directionDiff;
 }
 
@@ -636,7 +642,7 @@
     }
     const float previousDirection = getDirection(sampledInputXs, sampledInputYs, index0, index1);
     const float nextDirection = getDirection(sampledInputXs, sampledInputYs, index1, index2);
-    return getAngleDiff(previousDirection, nextDirection);
+    return GeometryUtils::getAngleDiff(previousDirection, nextDirection);
 }
 
 // This function basically converts from a length to an edit distance. Accordingly, it's obviously
diff --git a/native/jni/src/proximity_info_state_utils.h b/native/jni/src/suggest/core/layout/proximity_info_state_utils.h
similarity index 100%
rename from native/jni/src/proximity_info_state_utils.h
rename to native/jni/src/suggest/core/layout/proximity_info_state_utils.h
diff --git a/native/jni/src/proximity_info_utils.h b/native/jni/src/suggest/core/layout/proximity_info_utils.h
similarity index 93%
rename from native/jni/src/proximity_info_utils.h
rename to native/jni/src/suggest/core/layout/proximity_info_utils.h
index 71c97e3..c3a275b 100644
--- a/native/jni/src/proximity_info_utils.h
+++ b/native/jni/src/suggest/core/layout/proximity_info_utils.h
@@ -19,11 +19,11 @@
 
 #include <cmath>
 
-#include "additional_proximity_chars.h"
 #include "char_utils.h"
 #include "defines.h"
-#include "geometry_utils.h"
 #include "hash_map_compat.h"
+#include "suggest/core/layout/additional_proximity_chars.h"
+#include "suggest/core/layout/geometry_utils.h"
 
 namespace latinime {
 class ProximityInfoUtils {
@@ -87,7 +87,7 @@
 
     static inline float getSquaredDistanceFloat(const float x1, const float y1, const float x2,
             const float y2) {
-        return SQUARE_FLOAT(x1 - x2) + SQUARE_FLOAT(y1 - y2);
+        return GeometryUtils::SQUARE_FLOAT(x1 - x2) + GeometryUtils::SQUARE_FLOAT(y1 - y2);
     }
 
     static inline float pointToLineSegSquaredDistanceFloat(const float x, const float y,
@@ -98,7 +98,8 @@
         const float ray2y = y2 - y1;
 
         const float dotProduct = ray1x * ray2x + ray1y * ray2y;
-        const float lineLengthSqr = SQUARE_FLOAT(ray2x) + SQUARE_FLOAT(ray2y);
+        const float lineLengthSqr = GeometryUtils::SQUARE_FLOAT(ray2x)
+                + GeometryUtils::SQUARE_FLOAT(ray2y);
         const float projectionLengthSqr = dotProduct / lineLengthSqr;
 
         float projectionX;
@@ -121,12 +122,14 @@
      public:
         NormalDistribution(const float u, const float sigma)
                 : mU(u), mSigma(sigma),
-                  mPreComputedNonExpPart(1.0f / sqrtf(2.0f * M_PI_F * SQUARE_FLOAT(sigma))),
-                  mPreComputedExponentPart(-1.0f / (2.0f * SQUARE_FLOAT(sigma))) {}
+                  mPreComputedNonExpPart(1.0f / sqrtf(2.0f * M_PI_F
+                          * GeometryUtils::SQUARE_FLOAT(sigma))),
+                  mPreComputedExponentPart(-1.0f / (2.0f * GeometryUtils::SQUARE_FLOAT(sigma))) {}
 
         float getProbabilityDensity(const float x) const {
             const float shiftedX = x - mU;
-            return mPreComputedNonExpPart * expf(mPreComputedExponentPart * SQUARE_FLOAT(shiftedX));
+            return mPreComputedNonExpPart
+                    * expf(mPreComputedExponentPart * GeometryUtils::SQUARE_FLOAT(shiftedX));
         }
 
      private:
diff --git a/native/jni/src/suggest_utils.h b/native/jni/src/suggest/core/layout/touch_position_correction_utils.h
similarity index 91%
rename from native/jni/src/suggest_utils.h
rename to native/jni/src/suggest/core/layout/touch_position_correction_utils.h
index e053dd6..e7a8cae 100644
--- a/native/jni/src/suggest_utils.h
+++ b/native/jni/src/suggest/core/layout/touch_position_correction_utils.h
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-#ifndef LATINIME_SUGGEST_UTILS_H
-#define LATINIME_SUGGEST_UTILS_H
+#ifndef LATINIME_TOUCH_POSITION_CORRECTION_UTILS_H
+#define LATINIME_TOUCH_POSITION_CORRECTION_UTILS_H
 
 #include "defines.h"
 #include "proximity_info_params.h"
 
 namespace latinime {
-class SuggestUtils {
+class TouchPositionCorrectionUtils {
  public:
     // TODO: (OLD) Remove
     static float getLengthScalingFactor(const float normalizedSquaredDistance) {
@@ -82,7 +82,7 @@
         }
     }
  private:
-    DISALLOW_IMPLICIT_CONSTRUCTORS(SuggestUtils);
+    DISALLOW_IMPLICIT_CONSTRUCTORS(TouchPositionCorrectionUtils);
 };
 } // namespace latinime
-#endif // LATINIME_SUGGEST_UTILS_H
+#endif // LATINIME_TOUCH_POSITION_CORRECTION_UTILS_H
diff --git a/native/jni/src/suggest/core/session/dic_traverse_session.h b/native/jni/src/suggest/core/session/dic_traverse_session.h
index 5aaad03..c774eae 100644
--- a/native/jni/src/suggest/core/session/dic_traverse_session.h
+++ b/native/jni/src/suggest/core/session/dic_traverse_session.h
@@ -23,8 +23,8 @@
 #include "defines.h"
 #include "jni.h"
 #include "multi_bigram_map.h"
-#include "proximity_info_state.h"
 #include "suggest/core/dicnode/dic_nodes_cache.h"
+#include "suggest/core/layout/proximity_info_state.h"
 
 namespace latinime {
 
diff --git a/native/jni/src/suggest/core/suggest.cpp b/native/jni/src/suggest/core/suggest.cpp
index a187948..8fe8fbc 100644
--- a/native/jni/src/suggest/core/suggest.cpp
+++ b/native/jni/src/suggest/core/suggest.cpp
@@ -19,11 +19,11 @@
 #include "char_utils.h"
 #include "dictionary.h"
 #include "digraph_utils.h"
-#include "proximity_info.h"
 #include "suggest/core/dicnode/dic_node.h"
 #include "suggest/core/dicnode/dic_node_priority_queue.h"
 #include "suggest/core/dicnode/dic_node_vector.h"
 #include "suggest/core/dictionary/shortcut_utils.h"
+#include "suggest/core/layout/proximity_info.h"
 #include "suggest/core/policy/scoring.h"
 #include "suggest/core/policy/traversal.h"
 #include "suggest/core/policy/weighting.h"
diff --git a/native/jni/src/suggest/policyimpl/typing/typing_traversal.h b/native/jni/src/suggest/policyimpl/typing/typing_traversal.h
index 12110d5..b212fe1 100644
--- a/native/jni/src/suggest/policyimpl/typing/typing_traversal.h
+++ b/native/jni/src/suggest/policyimpl/typing/typing_traversal.h
@@ -21,9 +21,9 @@
 
 #include "char_utils.h"
 #include "defines.h"
-#include "proximity_info_state.h"
 #include "suggest/core/dicnode/dic_node.h"
 #include "suggest/core/dicnode/dic_node_vector.h"
+#include "suggest/core/layout/proximity_info_state.h"
 #include "suggest/core/policy/traversal.h"
 #include "suggest/core/session/dic_traverse_session.h"
 #include "suggest/policyimpl/typing/scoring_params.h"
diff --git a/native/jni/src/suggest/policyimpl/typing/typing_weighting.h b/native/jni/src/suggest/policyimpl/typing/typing_weighting.h
index 3938c0e..cb6abd5 100644
--- a/native/jni/src/suggest/policyimpl/typing/typing_weighting.h
+++ b/native/jni/src/suggest/policyimpl/typing/typing_weighting.h
@@ -18,8 +18,8 @@
 #define LATINIME_TYPING_WEIGHTING_H
 
 #include "defines.h"
-#include "suggest_utils.h"
 #include "suggest/core/dicnode/dic_node_utils.h"
+#include "suggest/core/layout/touch_position_correction_utils.h"
 #include "suggest/core/policy/weighting.h"
 #include "suggest/core/session/dic_traverse_session.h"
 #include "suggest/policyimpl/typing/scoring_params.h"
@@ -74,7 +74,7 @@
         // the keyboard (like accented letters)
         const float normalizedSquaredLength = traverseSession->getProximityInfoState(0)
                 ->getPointToKeyLength(pointIndex, dicNode->getNodeCodePoint());
-        const float normalizedDistance = SuggestUtils::getSweetSpotFactor(
+        const float normalizedDistance = TouchPositionCorrectionUtils::getSweetSpotFactor(
                 traverseSession->isTouchPositionCorrectionEnabled(), normalizedSquaredLength);
         const float weightedDistance = ScoringParams::DISTANCE_WEIGHT_LENGTH * normalizedDistance;
 
diff --git a/native/jni/src/suggest_options.h b/native/jni/src/suggest_options.h
index e9d7bc8..1b21aaf 100644
--- a/native/jni/src/suggest_options.h
+++ b/native/jni/src/suggest_options.h
@@ -39,6 +39,8 @@
     }
 
  private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(SuggestOptions);
+
     // Need to update com.android.inputmethod.latin.NativeSuggestOptions when you add, remove or
     // reorder options.
     static const int IS_GESTURE = 0;
diff --git a/native/jni/src/unigram_dictionary.cpp b/native/jni/src/unigram_dictionary.cpp
index a672294..08cd7b7 100644
--- a/native/jni/src/unigram_dictionary.cpp
+++ b/native/jni/src/unigram_dictionary.cpp
@@ -23,7 +23,7 @@
 #include "defines.h"
 #include "dictionary.h"
 #include "digraph_utils.h"
-#include "proximity_info.h"
+#include "suggest/core/layout/proximity_info.h"
 #include "terminal_attributes.h"
 #include "unigram_dictionary.h"
 #include "words_priority_queue.h"