Fix keyboard row height calculation

The keyboard height will be distrubuted as:
  top_padding + (key_height + vertical_gap) * row_count - vertical_gap + bottom_padding

Change-Id: I841f356b9dbf8cfaf3756178bc9e4e6b2aa61364
diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java
index 7ae3467..997c4c9 100644
--- a/java/src/com/android/inputmethod/keyboard/Key.java
+++ b/java/src/com/android/inputmethod/keyboard/Key.java
@@ -219,16 +219,17 @@
         final TypedArray keyboardAttr = res.obtainAttributes(Xml.asAttributeSet(parser),
                 R.styleable.Keyboard);
         mHeight = (int)KeyboardBuilder.getDimensionOrFraction(keyboardAttr,
-                R.styleable.Keyboard_rowHeight, params.mHeight, row.mRowHeight)
+                R.styleable.Keyboard_rowHeight, params.mBaseHeight, row.mRowHeight)
                 - params.mVerticalGap;
         final float horizontalGap = isSpacer() ? 0
                 : KeyboardBuilder.getDimensionOrFraction(keyboardAttr,
-                        R.styleable.Keyboard_horizontalGap, params.mWidth, params.mHorizontalGap);
+                        R.styleable.Keyboard_horizontalGap, params.mBaseWidth,
+                        params.mHorizontalGap);
         mVerticalGap = params.mVerticalGap;
         final int widthType = KeyboardBuilder.getEnumValue(keyboardAttr,
                 R.styleable.Keyboard_keyWidth, KEYWIDTH_NOT_ENUM);
         float keyWidth = KeyboardBuilder.getDimensionOrFraction(keyboardAttr,
-                R.styleable.Keyboard_keyWidth, params.mWidth, row.mDefaultKeyWidth);
+                R.styleable.Keyboard_keyWidth, params.mBaseWidth, row.mDefaultKeyWidth);
         keyboardAttr.recycle();
 
         final TypedArray keyAttr = res.obtainAttributes(Xml.asAttributeSet(parser),
diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java
index 3a8a1d4..2f11164 100644
--- a/java/src/com/android/inputmethod/keyboard/Keyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java
@@ -90,15 +90,12 @@
     /** Total width of the keyboard, including the padding and keys */
     public final int mOccupiedWidth;
 
-    public final int mHeight;
-    public final int mWidth;
-
-    /** Default row height */
-    public final int mDefaultRowHeight;
-
+    /** The padding above the keyboard */
+    public final int mTopPadding;
     /** Default gap between rows */
     public final int mVerticalGap;
 
+    public final int mMostCommonKeyHeight;
     public final int mMostCommonKeyWidth;
 
     /** More keys keyboard template */
@@ -126,14 +123,13 @@
         mId = params.mId;
         mOccupiedHeight = params.mOccupiedHeight;
         mOccupiedWidth = params.mOccupiedWidth;
-        mHeight = params.mHeight;
-        mWidth = params.mWidth;
+        mMostCommonKeyHeight = params.mMostCommonKeyHeight;
         mMostCommonKeyWidth = params.mMostCommonKeyWidth;
         mIsRtlKeyboard = params.mIsRtlKeyboard;
         mMoreKeysTemplate = params.mMoreKeysTemplate;
         mMaxMiniKeyboardColumn = params.mMaxMiniKeyboardColumn;
 
-        mDefaultRowHeight = params.mDefaultRowHeight;
+        mTopPadding = params.mTopPadding;
         mVerticalGap = params.mVerticalGap;
 
         mKeys = Collections.unmodifiableList(params.mKeys);
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index 8d34b7e..2a68459 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -391,7 +391,7 @@
         mDirtyRect.set(0, 0, getWidth(), getHeight());
         mBufferNeedsUpdate = true;
         invalidateAllKeys();
-        final int keyHeight = keyboard.mDefaultRowHeight - keyboard.mVerticalGap;
+        final int keyHeight = keyboard.mMostCommonKeyHeight - keyboard.mVerticalGap;
         mKeyDrawParams.updateKeyHeight(keyHeight);
         mKeyPreviewDrawParams.updateKeyHeight(keyHeight);
     }
diff --git a/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java b/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java
index ad8056c..c904394 100644
--- a/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java
@@ -122,9 +122,9 @@
                     mTopRowAdjustment = -1;
                 }
 
-                mWidth = mOccupiedWidth = mNumColumns * mDefaultKeyWidth;
+                mBaseWidth = mOccupiedWidth = mNumColumns * mDefaultKeyWidth;
                 // Need to subtract the bottom row's gutter only.
-                mHeight = mOccupiedHeight = mNumRows * mDefaultRowHeight - mVerticalGap
+                mBaseHeight = mOccupiedHeight = mNumRows * mDefaultRowHeight - mVerticalGap
                         + mTopPadding + mBottomPadding;
             }
 
@@ -219,7 +219,7 @@
 
             final int keyWidth = getMaxKeyWidth(view, mMoreKeys, mParams.mDefaultKeyWidth);
             mParams.setParameters(mMoreKeys.length, parentKey.mMaxMoreKeysColumn,
-                    keyWidth, parentKeyboard.mDefaultRowHeight, parentKey.mX
+                    keyWidth, parentKeyboard.mMostCommonKeyHeight, parentKey.mX
                             + (mParams.mDefaultKeyWidth - keyWidth) / 2, view.getMeasuredWidth());
         }
 
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
index e39548e..8d246c4 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
@@ -123,6 +123,9 @@
     private static final String TAG_DEFAULT = "default";
     public static final String TAG_KEY_STYLE = "key-style";
 
+    private static final int DEFAULT_KEYBOARD_COLUMNS = 10;
+    private static final int DEFAULT_KEYBOARD_ROWS = 4;
+
     protected final KP mParams;
     protected final Context mContext;
     protected final Resources mResources;
@@ -151,14 +154,12 @@
         public float mCurrentX;
 
         public Row(Resources res, KeyboardParams params, XmlResourceParser parser, int y) {
-            final int keyboardWidth = params.mWidth;
-            final int keyboardHeight = params.mHeight;
             TypedArray a = res.obtainAttributes(Xml.asAttributeSet(parser),
                     R.styleable.Keyboard);
             mDefaultKeyWidth = KeyboardBuilder.getDimensionOrFraction(a,
-                    R.styleable.Keyboard_keyWidth, keyboardWidth, params.mDefaultKeyWidth);
+                    R.styleable.Keyboard_keyWidth, params.mBaseWidth, params.mDefaultKeyWidth);
             mRowHeight = (int)KeyboardBuilder.getDimensionOrFraction(a,
-                    R.styleable.Keyboard_rowHeight, keyboardHeight, params.mDefaultRowHeight);
+                    R.styleable.Keyboard_rowHeight, params.mBaseHeight, params.mDefaultRowHeight);
             a.recycle();
 
             mCurrentY = y;
@@ -259,38 +260,40 @@
                 minKeyboardHeight = -(int)getDimensionOrFraction(keyboardAttr,
                         R.styleable.Keyboard_minKeyboardHeight, displayWidth, displayWidth / 2);
             }
+            final KeyboardParams params = mParams;
             // Keyboard height will not exceed maxKeyboardHeight and will not be less than
             // minKeyboardHeight.
-            mParams.mOccupiedHeight = Math.max(
+            params.mOccupiedHeight = Math.max(
                     Math.min(keyboardHeight, maxKeyboardHeight), minKeyboardHeight);
-            mParams.mOccupiedWidth = mParams.mId.mWidth;
-            mParams.mTopPadding = (int)getDimensionOrFraction(keyboardAttr,
-                    R.styleable.Keyboard_keyboardTopPadding, mParams.mOccupiedHeight, 0);
-            mParams.mBottomPadding = (int)getDimensionOrFraction(keyboardAttr,
-                    R.styleable.Keyboard_keyboardBottomPadding, mParams.mOccupiedHeight, 0);
+            params.mOccupiedWidth = params.mId.mWidth;
+            params.mTopPadding = (int)getDimensionOrFraction(keyboardAttr,
+                    R.styleable.Keyboard_keyboardTopPadding, params.mOccupiedHeight, 0);
+            params.mBottomPadding = (int)getDimensionOrFraction(keyboardAttr,
+                    R.styleable.Keyboard_keyboardBottomPadding, params.mOccupiedHeight, 0);
 
-            final int height = mParams.mOccupiedHeight;
-            final int width = mParams.mOccupiedWidth - mParams.mHorizontalEdgesPadding * 2
-                    - mParams.mHorizontalCenterPadding;
-            mParams.mHeight = height;
-            mParams.mWidth = width;
-            mParams.mDefaultKeyWidth = (int)getDimensionOrFraction(keyboardAttr,
-                    R.styleable.Keyboard_keyWidth, width, width / 10);
-            mParams.mDefaultRowHeight = (int)getDimensionOrFraction(keyboardAttr,
-                    R.styleable.Keyboard_rowHeight, height, height / 4);
-            mParams.mHorizontalGap = (int)getDimensionOrFraction(keyboardAttr,
-                    R.styleable.Keyboard_horizontalGap, width, 0);
-            mParams.mVerticalGap = (int)getDimensionOrFraction(keyboardAttr,
-                    R.styleable.Keyboard_verticalGap, height, 0);
+            params.mBaseWidth = params.mOccupiedWidth - params.mHorizontalEdgesPadding * 2
+                    - params.mHorizontalCenterPadding;
+            params.mDefaultKeyWidth = (int)getDimensionOrFraction(keyboardAttr,
+                    R.styleable.Keyboard_keyWidth, params.mBaseWidth,
+                    params.mBaseWidth / DEFAULT_KEYBOARD_COLUMNS);
+            params.mHorizontalGap = (int)getDimensionOrFraction(keyboardAttr,
+                    R.styleable.Keyboard_horizontalGap, params.mBaseWidth, 0);
+            params.mVerticalGap = (int)getDimensionOrFraction(keyboardAttr,
+                    R.styleable.Keyboard_verticalGap, params.mOccupiedHeight, 0);
+            params.mBaseHeight = params.mOccupiedHeight - params.mTopPadding
+                    - params.mBottomPadding + params.mVerticalGap;
+            params.mDefaultRowHeight = (int)getDimensionOrFraction(keyboardAttr,
+                    R.styleable.Keyboard_rowHeight, params.mBaseHeight,
+                    params.mBaseHeight / DEFAULT_KEYBOARD_ROWS);
 
-            mParams.mIsRtlKeyboard = keyboardAttr.getBoolean(
+            params.mIsRtlKeyboard = keyboardAttr.getBoolean(
                     R.styleable.Keyboard_isRtlKeyboard, false);
-            mParams.mMoreKeysTemplate = keyboardAttr.getResourceId(
+            params.mMoreKeysTemplate = keyboardAttr.getResourceId(
                     R.styleable.Keyboard_moreKeysTemplate, 0);
-            mParams.mMaxMiniKeyboardColumn = keyAttr.getInt(
+            params.mMaxMiniKeyboardColumn = keyAttr.getInt(
                     R.styleable.Keyboard_Key_maxMoreKeysColumn, 5);
 
-            mParams.mIconsSet.loadIcons(keyboardAttr);
+            params.mIconsSet.loadIcons(keyboardAttr);
         } finally {
             keyAttr.recycle();
             keyboardAttr.recycle();
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java
index 593c3dc..01f9d3b 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java
@@ -32,11 +32,13 @@
 public class KeyboardParams {
     public KeyboardId mId;
 
+    /** Total height and width of the keyboard, including the paddings and keys */
     public int mOccupiedHeight;
     public int mOccupiedWidth;
 
-    public int mHeight;
-    public int mWidth;
+    /** Base height and width of the keyboard used to calculate rows' or keys' heights and widths */
+    public int mBaseHeight;
+    public int mBaseWidth;
 
     public int mTopPadding;
     public int mBottomPadding;
@@ -62,6 +64,7 @@
     public final Map<Key, Drawable> mUnshiftedIcons = new HashMap<Key, Drawable>();
     public final KeyboardIconsSet mIconsSet = new KeyboardIconsSet();
 
+    public int mMostCommonKeyHeight = 0;
     public int mMostCommonKeyWidth = 0;
 
     protected void clearKeys() {
@@ -89,21 +92,39 @@
         mShiftedIcons.put(key, icon);
     }
 
-    private int mMaxCount = 0;
-    private final Map<Integer, Integer> mHistogram = new HashMap<Integer, Integer>();
+    private int mMaxHeightCount = 0;
+    private int mMaxWidthCount = 0;
+    private final Map<Integer, Integer> mHeightHistogram = new HashMap<Integer, Integer>();
+    private final Map<Integer, Integer> mWidthHistogram = new HashMap<Integer, Integer>();
 
     private void clearHistogram() {
+        mMostCommonKeyHeight = 0;
+        mMaxHeightCount = 0;
+        mHeightHistogram.clear();
+
+        mMaxWidthCount = 0;
         mMostCommonKeyWidth = 0;
-        mMaxCount = 0;
-        mHistogram.clear();
+        mWidthHistogram.clear();
+    }
+
+    private static int updateHistogramCounter(Map<Integer, Integer> histogram, Integer key) {
+        final int count = (histogram.containsKey(key) ? histogram.get(key) : 0) + 1;
+        histogram.put(key, count);
+        return count;
     }
 
     private void updateHistogram(Key key) {
+        final Integer height = key.mHeight + key.mVerticalGap;
+        final int heightCount = updateHistogramCounter(mHeightHistogram, height);
+        if (heightCount > mMaxHeightCount) {
+            mMaxHeightCount = heightCount;
+            mMostCommonKeyHeight = height;
+        }
+
         final Integer width = key.mWidth + key.mHorizontalGap;
-        final int count = (mHistogram.containsKey(width) ? mHistogram.get(width) : 0) + 1;
-        mHistogram.put(width, count);
-        if (count > mMaxCount) {
-            mMaxCount = count;
+        final int widthCount = updateHistogramCounter(mWidthHistogram, width);
+        if (widthCount > mMaxWidthCount) {
+            mMaxWidthCount = widthCount;
             mMostCommonKeyWidth = width;
         }
     }
diff --git a/java/src/com/android/inputmethod/latin/MoreSuggestions.java b/java/src/com/android/inputmethod/latin/MoreSuggestions.java
index 24011c4..1afa072 100644
--- a/java/src/com/android/inputmethod/latin/MoreSuggestions.java
+++ b/java/src/com/android/inputmethod/latin/MoreSuggestions.java
@@ -92,8 +92,9 @@
                 }
                 mNumColumnsInRow[row] = pos - rowStartPos;
                 mNumRows = row + 1;
-                mWidth = mOccupiedWidth = Math.max(minWidth, calcurateMaxRowWidth(fromPos, pos));
-                mHeight = mOccupiedHeight = mNumRows * mDefaultRowHeight + mVerticalGap;
+                mBaseWidth = mOccupiedWidth = Math.max(
+                        minWidth, calcurateMaxRowWidth(fromPos, pos));
+                mBaseHeight = mOccupiedHeight = mNumRows * mDefaultRowHeight + mVerticalGap;
                 return pos - fromPos;
             }
 
@@ -149,7 +150,7 @@
 
             public int getWidth(int pos) {
                 final int numColumnInRow = getNumColumnInRow(pos);
-                return (mWidth - mDividerWidth * (numColumnInRow - 1)) / numColumnInRow;
+                return (mOccupiedWidth - mDividerWidth * (numColumnInRow - 1)) / numColumnInRow;
             }
 
             public int getFlags(int pos) {