diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java
index 280c0c9d889474ff7a1957132e61b6e3c6e7026f..0b4fce417c6cc7ce35b5ab857b6dc00001935fe7 100644
--- a/java/src/com/android/inputmethod/keyboard/Keyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java
@@ -141,14 +141,6 @@ public class Keyboard {
     // TODO: Change GRID_WIDTH and GRID_HEIGHT to private.
     public final int GRID_WIDTH;
     public final int GRID_HEIGHT;
-    private final int GRID_SIZE;
-    private int mCellWidth;
-    private int mCellHeight;
-    private int[][] mGridNeighbors;
-    private int mProximityThreshold;
-    private static int[] EMPTY_INT_ARRAY = new int[0];
-    /** Number of key widths from current touch point to search for nearest keys. */
-    private static float SEARCH_DISTANCE = 1.2f;
 
     private final ProximityInfo mProximityInfo;
 
@@ -164,7 +156,6 @@ public class Keyboard {
         final Resources res = context.getResources();
         GRID_WIDTH = res.getInteger(R.integer.config_keyboard_grid_width);
         GRID_HEIGHT = res.getInteger(R.integer.config_keyboard_grid_height);
-        GRID_SIZE = GRID_WIDTH * GRID_HEIGHT;
 
         final int horizontalEdgesPadding = (int)res.getDimension(
                 R.dimen.keyboard_horizontal_edges_padding);
@@ -177,12 +168,13 @@ public class Keyboard {
         mDefaultVerticalGap = 0;
         mDefaultHeight = mDefaultWidth;
         mId = id;
-        mProximityInfo = new ProximityInfo(GRID_WIDTH, GRID_HEIGHT);
         loadKeyboard(context, xmlLayoutResId);
+        mProximityInfo = new ProximityInfo(
+                GRID_WIDTH, GRID_HEIGHT, getMinWidth(), getHeight(), getKeyWidth(), mKeys);
     }
 
     public int getProximityInfo() {
-        return mProximityInfo.getNativeProximityInfo(this);
+        return mProximityInfo.getNativeProximityInfo();
     }
 
     public List<Key> getKeys() {
@@ -219,8 +211,6 @@ public class Keyboard {
 
     public void setKeyWidth(int width) {
         mDefaultWidth = width;
-        final int threshold = (int) (width * SEARCH_DISTANCE);
-        mProximityThreshold = threshold * threshold;
     }
 
     /**
@@ -365,34 +355,6 @@ public class Keyboard {
         return label;
     }
 
-    // TODO: Move this function to ProximityInfo and make this private.
-    public void computeNearestNeighbors() {
-        // Round-up so we don't have any pixels outside the grid
-        mCellWidth = (getMinWidth() + GRID_WIDTH - 1) / GRID_WIDTH;
-        mCellHeight = (getHeight() + GRID_HEIGHT - 1) / GRID_HEIGHT;
-        mGridNeighbors = new int[GRID_SIZE][];
-        final int[] indices = new int[mKeys.size()];
-        final int gridWidth = GRID_WIDTH * mCellWidth;
-        final int gridHeight = GRID_HEIGHT * mCellHeight;
-        final int threshold = mProximityThreshold;
-        for (int x = 0; x < gridWidth; x += mCellWidth) {
-            for (int y = 0; y < gridHeight; y += mCellHeight) {
-                final int centerX = x + mCellWidth / 2;
-                final int centerY = y + mCellHeight / 2;
-                int count = 0;
-                for (int i = 0; i < mKeys.size(); i++) {
-                    final Key key = mKeys.get(i);
-                    if (key.squaredDistanceToEdge(centerX, centerY) < threshold)
-                        indices[count++] = i;
-                }
-                final int[] cell = new int[count];
-                System.arraycopy(indices, 0, cell, 0, count);
-                mGridNeighbors[(y / mCellHeight) * GRID_WIDTH + (x / mCellWidth)] = cell;
-            }
-        }
-        mProximityInfo.setProximityInfo(mGridNeighbors, getMinWidth(), getHeight(), mKeys);
-    }
-
     /**
      * Returns the indices of the keys that are closest to the given point.
      * @param x the x-coordinate of the point
@@ -401,14 +363,7 @@ public class Keyboard {
      * point is out of range, then an array of size zero is returned.
      */
     public int[] getNearestKeys(int x, int y) {
-        if (mGridNeighbors == null) computeNearestNeighbors();
-        if (x >= 0 && x < getMinWidth() && y >= 0 && y < getHeight()) {
-            int index = (y / mCellHeight) * GRID_WIDTH + (x / mCellWidth);
-            if (index < GRID_SIZE) {
-                return mGridNeighbors[index];
-            }
-        }
-        return EMPTY_INT_ARRAY;
+        return mProximityInfo.getNearestKeys(x, y);
     }
 
     /**
diff --git a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
index 33acc69075891830634bd502ad4baea7f1a461f4..aadedc69dd645535d69ea740546932a9f7e25514 100644
--- a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
+++ b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
@@ -23,15 +23,35 @@ import java.util.List;
 
 public class ProximityInfo {
     public static final int MAX_PROXIMITY_CHARS_SIZE = 16;
+    /** Number of key widths from current touch point to search for nearest keys. */
+    private static float SEARCH_DISTANCE = 1.2f;
+    private static final int[] EMPTY_INT_ARRAY = new int[0];
 
     private final int mGridWidth;
     private final int mGridHeight;
     private final int mGridSize;
+    private final int mCellWidth;
+    private final int mCellHeight;
+    // TODO: Find a proper name for mKeyboardMinWidth
+    private final int mKeyboardMinWidth;
+    private final int mKeyboardHeight;
+    private final int[][] mGridNeighbors;
 
-    ProximityInfo(int gridWidth, int gridHeight) {
+    ProximityInfo(
+            int gridWidth, int gridHeight, int minWidth, int height, int keyWidth, List<Key> keys) {
         mGridWidth = gridWidth;
         mGridHeight = gridHeight;
         mGridSize = mGridWidth * mGridHeight;
+        mCellWidth = (minWidth + mGridWidth - 1) / mGridWidth;
+        mCellHeight = (height + mGridHeight - 1) / mGridHeight;
+        mKeyboardMinWidth = minWidth;
+        mKeyboardHeight = height;
+        mGridNeighbors = new int[mGridSize][];
+        if (minWidth == 0 || height == 0) {
+            // No proximity required. Keyboard might be mini keyboard.
+            return;
+        }
+        computeNearestNeighbors(keyWidth, keys);
     }
 
     private int mNativeProximityInfo;
@@ -42,7 +62,7 @@ public class ProximityInfo {
             int displayHeight, int gridWidth, int gridHeight, int[] proximityCharsArray);
     private native void releaseProximityInfoNative(int nativeProximityInfo);
 
-    public final void setProximityInfo(int[][] gridNeighborKeyIndexes, int keyboardWidth,
+    private final void setProximityInfo(int[][] gridNeighborKeyIndexes, int keyboardWidth,
             int keyboardHeight, List<Key> keys) {
         int[] proximityCharsArray = new int[mGridSize * MAX_PROXIMITY_CHARS_SIZE];
         Arrays.fill(proximityCharsArray, KeyDetector.NOT_A_CODE);
@@ -57,12 +77,7 @@ public class ProximityInfo {
                 keyboardWidth, keyboardHeight, mGridWidth, mGridHeight, proximityCharsArray);
     }
 
-    // TODO: Get rid of this function's input (keyboard).
-    public int getNativeProximityInfo(Keyboard keyboard) {
-        if (mNativeProximityInfo == 0) {
-            // TODO: Move this function to ProximityInfo and make this private.
-            keyboard.computeNearestNeighbors();
-        }
+    public int getNativeProximityInfo() {
         return mNativeProximityInfo;
     }
 
@@ -77,4 +92,42 @@ public class ProximityInfo {
             super.finalize();
         }
     }
+
+    private void computeNearestNeighbors(int defaultWidth, List<Key> keys) {
+        final int thresholdBase = (int) (defaultWidth * SEARCH_DISTANCE);
+        final int threshold = thresholdBase * thresholdBase;
+        // Round-up so we don't have any pixels outside the grid
+        final int[] indices = new int[keys.size()];
+        final int gridWidth = mGridWidth * mCellWidth;
+        final int gridHeight = mGridHeight * mCellHeight;
+        for (int x = 0; x < gridWidth; x += mCellWidth) {
+            for (int y = 0; y < gridHeight; y += mCellHeight) {
+                final int centerX = x + mCellWidth / 2;
+                final int centerY = y + mCellHeight / 2;
+                int count = 0;
+                for (int i = 0; i < keys.size(); i++) {
+                    final Key key = keys.get(i);
+                    if (key.squaredDistanceToEdge(centerX, centerY) < threshold)
+                        indices[count++] = i;
+                }
+                final int[] cell = new int[count];
+                System.arraycopy(indices, 0, cell, 0, count);
+                mGridNeighbors[(y / mCellHeight) * mGridWidth + (x / mCellWidth)] = cell;
+            }
+        }
+        setProximityInfo(mGridNeighbors, mKeyboardMinWidth, mKeyboardHeight, keys);
+    }
+
+    public int[] getNearestKeys(int x, int y) {
+        if (mGridNeighbors == null) {
+            return EMPTY_INT_ARRAY;
+        }
+        if (x >= 0 && x < mKeyboardMinWidth && y >= 0 && y < mKeyboardHeight) {
+            int index = (y /  mCellHeight) * mGridWidth + (x / mCellWidth);
+            if (index < mGridSize) {
+                return mGridNeighbors[index];
+            }
+        }
+        return EMPTY_INT_ARRAY;
+    }
 }