diff --git a/java/res/values-land/dimens.xml b/java/res/values-land/dimens.xml
index 6cdcf891c25222fe908fc481e1dab4cfd9d13a1d..550d29f7677799ccc164d18aba9a844f8b9feece 100644
--- a/java/res/values-land/dimens.xml
+++ b/java/res/values-land/dimens.xml
@@ -19,8 +19,9 @@
 -->
 
 <resources>
-    <!-- keyboardHeight = key_height*4 + key_bottom_gap*3, key_height=0.260in -->
-    <dimen name="keyboardHeight">1.100in</dimen>
+    <!-- Preferable keyboard height in absolute scale: 1.100in -->
+    <!-- This keyboardHeight value should match with keyboard-heights.xml -->
+    <dimen name="keyboardHeight">176.0dp</dimen>
     <fraction name="minKeyboardHeight">45%p</fraction>
     <!-- key_height + key_bottom_gap = popup_key_height -->
 <!--    <dimen name="key_height">0.260in</dimen>-->
@@ -31,7 +32,6 @@
     <fraction name="key_bottom_gap">4.330%p</fraction>
     <fraction name="key_horizontal_gap">0.405%p</fraction>
 
-    <dimen name="keyboardHeight_stone">0.984in</dimen>
     <fraction name="key_bottom_gap_stone">5.010%p</fraction>
     <fraction name="key_horizontal_gap_stone">1.159%p</fraction>
 
diff --git a/java/res/values-land/keyboard-heights.xml b/java/res/values-land/keyboard-heights.xml
new file mode 100644
index 0000000000000000000000000000000000000000..12c3e3951137d4084de71cae1a2d427fe27bbf2d
--- /dev/null
+++ b/java/res/values-land/keyboard-heights.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+
+<!-- Preferable keyboard height in absolute scale: 1.100in -->
+<resources>
+    <!-- Build.HARDWARE,keyboard_height_in_dp -->
+    <string-array name="keyboard_heights" translatable="false">
+        <!-- Droid -->
+        <item>sholes,194.3333</item>
+        <!-- Nexus One -->
+        <item>mahimahi,186.2667</item>
+        <!-- Nexus S -->
+        <item>herring,171.9385</item>
+        <!-- Galaxy Nexus -->
+        <item>tuna,173.4207</item>
+    </string-array>
+</resources>
diff --git a/java/res/values-sw600dp-land/dimens.xml b/java/res/values-sw600dp-land/dimens.xml
index 5dce47ee3505787afd9411ead06768a8758badc5..d84f843c12f99fe3066c53ea328aa9f01016afa3 100644
--- a/java/res/values-sw600dp-land/dimens.xml
+++ b/java/res/values-sw600dp-land/dimens.xml
@@ -19,8 +19,9 @@
 -->
 
 <resources>
-    <!-- keyboardHeight = key_height*4 + key_bottom_gap*3 -->
-    <dimen name="keyboardHeight">45.0mm</dimen>
+    <!-- Preferable keyboard height in absolute scale: 45.0mm -->
+    <!-- This keyboardHeight value should match with keyboard-heights.xml -->
+    <dimen name="keyboardHeight">283.5dp</dimen>
     <fraction name="minKeyboardHeight">45%p</fraction>
 
     <fraction name="keyboard_top_padding">2.444%p</fraction>
@@ -28,7 +29,6 @@
     <fraction name="key_bottom_gap">4.911%p</fraction>
     <fraction name="key_horizontal_gap">1.284%p</fraction>
 
-    <dimen name="keyboardHeight_stone">45.0mm</dimen>
     <fraction name="key_bottom_gap_stone">4.355%p</fraction>
     <fraction name="key_horizontal_gap_stone">1.505%p</fraction>
 
diff --git a/java/res/values-sw600dp-land/keyboard-heights.xml b/java/res/values-sw600dp-land/keyboard-heights.xml
new file mode 100644
index 0000000000000000000000000000000000000000..93f9824d164763d981fef28dc2b3d4d5dd05b374
--- /dev/null
+++ b/java/res/values-sw600dp-land/keyboard-heights.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+
+<!-- Preferable keyboard height in absolute scale: 45.0mm -->
+<resources>
+    <!-- Build.HARDWARE,keyboard_height_in_dp -->
+    <string-array name="keyboard_heights" translatable="false">
+        <!-- Xoom -->
+        <item>stingray,265.4378</item>
+    </string-array>
+</resources>
diff --git a/java/res/values-sw600dp/dimens.xml b/java/res/values-sw600dp/dimens.xml
index 0f256a302f85f5341b25346390dce01b7cd6a52a..1b24b6ba8cf4789943b165eae498d7ff7266ae49 100644
--- a/java/res/values-sw600dp/dimens.xml
+++ b/java/res/values-sw600dp/dimens.xml
@@ -19,8 +19,9 @@
 -->
 
 <resources>
-    <!-- keyboardHeight = key_height*4 + key_bottom_gap*3 -->
-    <dimen name="keyboardHeight">48.0mm</dimen>
+    <!-- Preferable keyboard height in absolute scale: 48.0mm -->
+    <!-- This keyboardHeight value should match with keyboard-heights.xml -->
+    <dimen name="keyboardHeight">302.4dp</dimen>
     <fraction name="maxKeyboardHeight">50%p</fraction>
     <fraction name="minKeyboardHeight">-35.0%p</fraction>
 
@@ -31,7 +32,6 @@
     <fraction name="key_bottom_gap">3.750%p</fraction>
     <fraction name="key_horizontal_gap">1.857%p</fraction>
 
-    <dimen name="keyboardHeight_stone">48.0mm</dimen>
     <fraction name="key_bottom_gap_stone">3.75%p</fraction>
     <fraction name="key_horizontal_gap_stone">1.602%p</fraction>
 
diff --git a/java/res/values-sw600dp/keyboard-heights.xml b/java/res/values-sw600dp/keyboard-heights.xml
new file mode 100644
index 0000000000000000000000000000000000000000..77e52be2f07815bdab711add7c4944d21f0fe9dd
--- /dev/null
+++ b/java/res/values-sw600dp/keyboard-heights.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+
+<!-- Preferable keyboard height in absolute scale: 48.0mm -->
+<resources>
+    <!-- Build.HARDWARE,keyboard_height_in_dp -->
+    <string-array name="keyboard_heights" translatable="false">
+        <!-- Xoom -->
+        <item>stingray,283.1337</item>
+    </string-array>
+</resources>
diff --git a/java/res/values-sw768dp-land/dimens.xml b/java/res/values-sw768dp-land/dimens.xml
index 535c62308a6b5041cd9e7ae0503ed0b9de6a6449..597ed5102d22b41455fb74bf93f5b449f5847f21 100644
--- a/java/res/values-sw768dp-land/dimens.xml
+++ b/java/res/values-sw768dp-land/dimens.xml
@@ -19,8 +19,9 @@
 -->
 
 <resources>
-    <!-- keyboardHeight = key_height*4 + key_bottom_gap*3, key_height=14.5mm -->
-    <dimen name="keyboardHeight">58.0mm</dimen>
+    <!-- Preferable keyboard height in absolute scale: 58.0mm -->
+    <!-- This keyboardHeight value should match with keyboard-heights.xml -->
+    <dimen name="keyboardHeight">365.4dp</dimen>
     <fraction name="minKeyboardHeight">45%p</fraction>
 
     <fraction name="keyboard_top_padding">1.896%p</fraction>
@@ -29,7 +30,6 @@
     <fraction name="key_bottom_gap">4.103%p</fraction>
     <fraction name="key_horizontal_gap">1.034%p</fraction>
 
-    <dimen name="keyboardHeight_stone">58.0mm</dimen>
     <fraction name="key_bottom_gap_stone">3.379%p</fraction>
     <fraction name="key_horizontal_gap_stone">1.062%p</fraction>
 
diff --git a/java/res/values-sw768dp-land/keyboard-heights.xml b/java/res/values-sw768dp-land/keyboard-heights.xml
new file mode 100644
index 0000000000000000000000000000000000000000..692c5a0fb3f5276f8ab87ca6854781806d621364
--- /dev/null
+++ b/java/res/values-sw768dp-land/keyboard-heights.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+
+<!-- Preferable keyboard height in absolute scale: 58.0mm -->
+<resources>
+    <!-- Build.HARDWARE,keyboard_height_in_dp -->
+    <string-array name="keyboard_heights" translatable="false">
+        <!-- Xoom -->
+        <item>stingray,342.1198</item>
+    </string-array>
+</resources>
diff --git a/java/res/values-sw768dp/dimens.xml b/java/res/values-sw768dp/dimens.xml
index 7aefa26afb830e67309f54555882bd95b739c1ac..a9f0c00aad568730a65bfee38249cf64982a8994 100644
--- a/java/res/values-sw768dp/dimens.xml
+++ b/java/res/values-sw768dp/dimens.xml
@@ -19,8 +19,9 @@
 -->
 
 <resources>
-    <!-- keyboardHeight = key_height*4 + key_bottom_gap*3, key_height=12mm -->
-    <dimen name="keyboardHeight">48.0mm</dimen>
+    <!-- Preferable keyboard height in absolute scale: 48.0mm -->
+    <!-- This keyboardHeight value should match with keyboard-heights.xml -->
+    <dimen name="keyboardHeight">302.4dp</dimen>
     <fraction name="maxKeyboardHeight">50%p</fraction>
     <fraction name="minKeyboardHeight">-35.0%p</fraction>
 
@@ -30,7 +31,6 @@
     <fraction name="key_bottom_gap">4.270%p</fraction>
     <fraction name="key_horizontal_gap">1.551%p</fraction>
 
-    <dimen name="keyboardHeight_stone">48.0mm</dimen>
     <fraction name="key_bottom_gap_stone">3.75%p</fraction>
     <fraction name="key_horizontal_gap_stone">1.059%p</fraction>
 
diff --git a/java/res/values-sw768dp/keyboard-heights.xml b/java/res/values-sw768dp/keyboard-heights.xml
new file mode 100644
index 0000000000000000000000000000000000000000..77e52be2f07815bdab711add7c4944d21f0fe9dd
--- /dev/null
+++ b/java/res/values-sw768dp/keyboard-heights.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+
+<!-- Preferable keyboard height in absolute scale: 48.0mm -->
+<resources>
+    <!-- Build.HARDWARE,keyboard_height_in_dp -->
+    <string-array name="keyboard_heights" translatable="false">
+        <!-- Xoom -->
+        <item>stingray,283.1337</item>
+    </string-array>
+</resources>
diff --git a/java/res/values/dimens.xml b/java/res/values/dimens.xml
index 5f74fa746cd08f4f14abee025ee51daaffb52dd2..9d64a618a5d5ffef3cc2a3702620a429093611b1 100644
--- a/java/res/values/dimens.xml
+++ b/java/res/values/dimens.xml
@@ -19,8 +19,9 @@
 -->
 
 <resources>
-    <!-- keyboardHeight = row_height*4 + key_bottom_gap*3 -->
-    <dimen name="keyboardHeight">1.285in</dimen>
+    <!-- Preferable keyboard height in absolute scale: 1.285in -->
+    <!-- This keyboardHeight value should match with keyboard-heights.xml -->
+    <dimen name="keyboardHeight">205.6dp</dimen>
     <fraction name="maxKeyboardHeight">50%p</fraction>
     <fraction name="minKeyboardHeight">-61.8%p</fraction>
 
@@ -35,7 +36,6 @@
     <fraction name="key_bottom_gap">6.250%p</fraction>
     <fraction name="key_horizontal_gap">1.352%p</fraction>
 
-    <dimen name="keyboardHeight_stone">1.317in</dimen>
     <fraction name="keyboard_top_padding_stone">1.556%p</fraction>
     <fraction name="keyboard_bottom_padding_stone">0.778%p</fraction>
     <fraction name="key_bottom_gap_stone">7.506%p</fraction>
diff --git a/java/res/values/keyboard-heights.xml b/java/res/values/keyboard-heights.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7d5b583723e894e97b560dd24ca03eba29395049
--- /dev/null
+++ b/java/res/values/keyboard-heights.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+
+<!-- Preferable keyboard height in absolute scale: 1.285in -->
+<resources>
+    <!-- Build.HARDWARE,keyboard_height_in_dp -->
+    <string-array name="keyboard_heights" translatable="false">
+        <!-- Droid -->
+        <item>sholes,227.0167</item>
+        <!-- Nexus One -->
+        <item>mahimahi,217.5932</item>
+        <!-- Nexus S -->
+        <item>herring,200.8554</item>
+        <!-- Galaxy Nexus -->
+        <item>tuna,202.5869</item>
+    </string-array>
+</resources>
diff --git a/java/res/values/styles.xml b/java/res/values/styles.xml
index 691f98ae22c0e6613ab9c171148b0523a46f6076..b08ff3b908966a389c6f454d7f7d46eaa66daf59 100644
--- a/java/res/values/styles.xml
+++ b/java/res/values/styles.xml
@@ -173,7 +173,6 @@
     >
         <!-- This should be aligned with KeyboardSwitcher.KEYBOARD_THEMES[] -->
         <item name="themeId">6</item>
-        <item name="keyboardHeight">@dimen/keyboardHeight_stone</item>
         <item name="keyboardTopPadding">@fraction/keyboard_top_padding_stone</item>
         <item name="keyboardBottomPadding">@fraction/keyboard_bottom_padding_stone</item>
         <item name="horizontalGap">@fraction/key_horizontal_gap_stone</item>
diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java
index 2b1cc43cd18f978308b5383f49def2335ec800dd..07b9c1e8c1064e24d4e35431118db671efd113af 100644
--- a/java/src/com/android/inputmethod/keyboard/Keyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java
@@ -31,6 +31,7 @@ import com.android.inputmethod.keyboard.internal.KeyStyles;
 import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
 import com.android.inputmethod.latin.LatinImeLogger;
 import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.Utils;
 import com.android.inputmethod.latin.XmlParseUtils;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -715,22 +716,30 @@ public class Keyboard {
                     R.styleable.Keyboard_Key);
             try {
                 final int displayHeight = mDisplayMetrics.heightPixels;
-                final int keyboardHeight = (int)keyboardAttr.getDimension(
-                        R.styleable.Keyboard_keyboardHeight, displayHeight / 2);
-                final int maxKeyboardHeight = (int)getDimensionOrFraction(keyboardAttr,
+                final String keyboardHeightString = Utils.getDeviceOverrideValue(
+                        mResources, R.array.keyboard_heights, null);
+                final float keyboardHeight;
+                if (keyboardHeightString != null) {
+                    keyboardHeight = Float.parseFloat(keyboardHeightString)
+                            * mDisplayMetrics.density;
+                } else {
+                    keyboardHeight = keyboardAttr.getDimension(
+                            R.styleable.Keyboard_keyboardHeight, displayHeight / 2);
+                }
+                final float maxKeyboardHeight = getDimensionOrFraction(keyboardAttr,
                         R.styleable.Keyboard_maxKeyboardHeight, displayHeight, displayHeight / 2);
-                int minKeyboardHeight = (int)getDimensionOrFraction(keyboardAttr,
+                float minKeyboardHeight = getDimensionOrFraction(keyboardAttr,
                         R.styleable.Keyboard_minKeyboardHeight, displayHeight, displayHeight / 2);
                 if (minKeyboardHeight < 0) {
                     // Specified fraction was negative, so it should be calculated against display
                     // width.
-                    minKeyboardHeight = -(int)getDimensionOrFraction(keyboardAttr,
+                    minKeyboardHeight = -getDimensionOrFraction(keyboardAttr,
                             R.styleable.Keyboard_minKeyboardHeight, displayWidth, displayWidth / 2);
                 }
                 final Params params = mParams;
                 // Keyboard height will not exceed maxKeyboardHeight and will not be less than
                 // minKeyboardHeight.
-                params.mOccupiedHeight = Math.max(
+                params.mOccupiedHeight = (int)Math.max(
                         Math.min(keyboardHeight, maxKeyboardHeight), minKeyboardHeight);
                 params.mOccupiedWidth = params.mId.mWidth;
                 params.mTopPadding = (int)getDimensionOrFraction(keyboardAttr,